-
Notifications
You must be signed in to change notification settings - Fork 344
[move-function] Add tests that show that the debugger displays variables correctly given usage of the move function. #3986
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
SWIFT_SOURCES := main.swift | ||
|
||
include Makefile.rules |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
# TestSwiftMoveFunction.py | ||
# | ||
# This source file is part of the Swift.org open source project | ||
# | ||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors | ||
# Licensed under Apache License v2.0 with Runtime Library Exception | ||
# | ||
# See https://swift.org/LICENSE.txt for license information | ||
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
# | ||
# ------------------------------------------------------------------------------ | ||
""" | ||
Check that we properly show variables at various points of the CFG while | ||
stepping with the move function. | ||
""" | ||
import lldb | ||
from lldbsuite.test.lldbtest import * | ||
from lldbsuite.test.decorators import * | ||
import lldbsuite.test.lldbutil as lldbutil | ||
import os | ||
import sys | ||
import unittest2 | ||
|
||
def stderr_print(line): | ||
sys.stderr.write(line + "\n") | ||
|
||
class TestSwiftMoveFunctionType(TestBase): | ||
|
||
mydir = TestBase.compute_mydir(__file__) | ||
|
||
@skipUnlessPlatform(["macosx"]) | ||
@swiftTest | ||
def test_swift_move_function(self): | ||
"""Check that we properly show variables at various points of the CFG while | ||
stepping with the move function. | ||
""" | ||
self.build() | ||
|
||
self.exec_artifact = self.getBuildArtifact(self.exec_name) | ||
self.target = self.dbg.CreateTarget(self.exec_artifact) | ||
self.assertTrue(self.target, VALID_TARGET) | ||
|
||
self.do_setup_breakpoints() | ||
|
||
self.process = self.target.LaunchSimple(None, None, os.getcwd()) | ||
threads = lldbutil.get_threads_stopped_at_breakpoint( | ||
self.process, self.breakpoints[0]) | ||
self.assertTrue(len(threads) == 1) | ||
self.thread = threads[0] | ||
|
||
self.do_check_copyable_value_test() | ||
self.do_check_copyable_var_test() | ||
self.do_check_addressonly_value_test() | ||
self.do_check_addressonly_var_test() | ||
# ccf is conditional control flow | ||
self.do_check_copyable_value_ccf_true() | ||
self.do_check_copyable_value_ccf_false() | ||
|
||
def setUp(self): | ||
TestBase.setUp(self) | ||
self.main_source = "main.swift" | ||
self.main_source_spec = lldb.SBFileSpec(self.main_source) | ||
self.exec_name = "a.out" | ||
|
||
def add_breakpoints(self, name, num_breakpoints): | ||
pattern = 'Set breakpoint {} here {}' | ||
for i in range(num_breakpoints): | ||
pat = pattern.format(name, i+1) | ||
brk = self.target.BreakpointCreateBySourceRegex( | ||
pat, self.main_source_spec) | ||
self.assertTrue(brk.GetNumLocations() > 0, VALID_BREAKPOINT) | ||
yield brk | ||
|
||
def do_setup_breakpoints(self): | ||
self.breakpoints = [] | ||
|
||
self.breakpoints.extend( | ||
self.add_breakpoints('copyableValueTest', 3)) | ||
self.breakpoints.extend( | ||
self.add_breakpoints('addressOnlyValueTest', 3)) | ||
self.breakpoints.extend( | ||
self.add_breakpoints('copyableVarTest', 4)) | ||
self.breakpoints.extend( | ||
self.add_breakpoints('addressOnlyVarTest', 4)) | ||
self.breakpoints.extend( | ||
self.add_breakpoints('copyableValueCCFTrueTest', | ||
5)) | ||
self.breakpoints.extend( | ||
self.add_breakpoints('copyableValueCCFFalseTest', | ||
3)) | ||
|
||
def do_check_copyable_value_test(self): | ||
frame = self.thread.frames[0] | ||
self.assertTrue(frame.IsValid(), "Couldn't get a frame.") | ||
|
||
# We haven't defined varK yet. | ||
varK = frame.FindVariable('k') | ||
|
||
self.assertTrue(varK.value == None, "varK initialized too early?!") | ||
|
||
# Go to break point 2. k should be valid. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.unsigned > 0, "varK not initialized?!") | ||
|
||
# Go to breakpoint 3. k should no longer be valid. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.value == None, "K is live but was moved?!") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
see |
||
|
||
# Run so we hit the next breakpoint to jump to the next test's | ||
# breakpoint. | ||
self.runCmd('continue') | ||
|
||
def do_check_copyable_var_test(self): | ||
frame = self.thread.frames[0] | ||
self.assertTrue(frame.IsValid(), "Couldn't get a frame.") | ||
|
||
# We haven't defined varK yet. | ||
varK = frame.FindVariable('k') | ||
self.assertTrue(varK.value == None, "varK initialized too early?!") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thank you for the tests! Note there are many specific assertion functions, including There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I'll send a follow on commit. I also noticed an fr v that snuck in there that is not necessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't want to create work, I mean only to mention it for future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kastiglione I had other things I needed to do and it inspired me to port some tests. |
||
|
||
# Go to break point 2. k should be valid. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.unsigned > 0, "varK not initialized?!") | ||
|
||
# Go to breakpoint 3. We invalidated k | ||
self.runCmd('continue') | ||
self.assertTrue(varK.value == None, "K is live but was moved?!") | ||
|
||
# Go to the last breakpoint and make sure that k is reinitialized | ||
# properly. | ||
self.runCmd('continue') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you store the process above, you could do |
||
self.assertTrue(varK.unsigned > 0, "varK not initialized") | ||
|
||
# Run so we hit the next breakpoint to go to the next test. | ||
self.runCmd('continue') | ||
|
||
def do_check_addressonly_value_test(self): | ||
frame = self.thread.frames[0] | ||
self.assertTrue(frame.IsValid(), "Couldn't get a frame.") | ||
|
||
# We haven't defined varK or varM yet... so we shouldn't have a summary. | ||
varK = frame.FindVariable('k') | ||
|
||
# Go to break point 2. k should be valid and m should not be. Since M is | ||
# a dbg.declare it is hard to test robustly that it is not initialized | ||
# so we don't do so. We have an additional llvm.dbg.addr test where we | ||
# move the other variable and show the correct behavior with | ||
# llvm.dbg.declare. | ||
self.runCmd('continue') | ||
|
||
self.assertTrue(varK.unsigned > 0, "var not initialized?!") | ||
|
||
# Go to breakpoint 3. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.unsigned == 0, | ||
"dbg thinks varK is live despite move?!") | ||
|
||
# Run so we hit the next breakpoint as part of the next test. | ||
self.runCmd('continue') | ||
|
||
def do_check_addressonly_var_test(self): | ||
frame = self.thread.frames[0] | ||
self.assertTrue(frame.IsValid(), "Couldn't get a frame.") | ||
|
||
varK = frame.FindVariable('k') | ||
|
||
# Go to break point 2. k should be valid. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.unsigned > 0, "varK not initialized?!") | ||
|
||
# Go to breakpoint 3. K was invalidated. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.value == None, "K is live but was moved?!") | ||
|
||
# Go to the last breakpoint and make sure that k is reinitialized | ||
# properly. | ||
self.runCmd('continue') | ||
self.assertTrue(varK.unsigned > 0, "varK not initialized") | ||
|
||
# Run so we hit the next breakpoint as part of the next test. | ||
self.runCmd('continue') | ||
|
||
def do_check_copyable_value_ccf_true(self): | ||
frame = self.thread.frames[0] | ||
self.assertTrue(frame.IsValid(), "Couldn't get a frame.") | ||
varK = frame.FindVariable('k') | ||
|
||
# Check at our start point that we do not have any state for varK and | ||
# then continue to our next breakpoint. | ||
self.assertTrue(varK.value == None, "varK should not have a value?!") | ||
self.runCmd('continue') | ||
|
||
# At this breakpoint, k should be defined since we are going to do | ||
# something with it. | ||
self.assertTrue(varK.value != None, "varK should have a value?!") | ||
self.runCmd('continue') | ||
|
||
# At this breakpoint, we are now in the conditional control flow part of | ||
# the loop. Make sure that we can see k still. | ||
self.assertTrue(varK.value != None, "varK should have a value?!") | ||
self.runCmd('continue') | ||
|
||
# Ok, we just performed the move. k should not be no longer initialized. | ||
self.runCmd('fr v') | ||
self.assertTrue(varK.value == None, "varK should not have a value?!") | ||
self.runCmd('continue') | ||
|
||
# Finally we left the conditional control flow part of the function. k | ||
# should still be None. | ||
self.assertTrue(varK.value == None, "varK should not have a value!") | ||
|
||
def do_check_copyable_value_ccf_false(self): | ||
pass |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// main.swift | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
// ----------------------------------------------------------------------------- | ||
|
||
public class Klass { | ||
public func doSomething() {} | ||
} | ||
|
||
public protocol P { | ||
static var value: P { get } | ||
func doSomething() | ||
} | ||
|
||
extension Klass : P { | ||
public static var value: P { Klass() } | ||
} | ||
|
||
var trueBoolValue : Bool { true } | ||
var falseBoolValue : Bool { false } | ||
|
||
////////////////// | ||
// Simple Tests // | ||
////////////////// | ||
|
||
public func copyableValueTest() { | ||
print("stop here") // Set breakpoint copyableValueTest here 1 | ||
let k = Klass() | ||
k.doSomething() | ||
let m = _move(k) // Set breakpoint copyableValueTest here 2 | ||
m.doSomething() // Set breakpoint copyableValueTest here 3 | ||
} | ||
|
||
public func copyableVarTest() { | ||
print("stop here") // Set breakpoint copyableVarTest here 1 | ||
var k = Klass() | ||
k.doSomething() | ||
let m = _move(k) // Set breakpoint copyableVarTest here 2 | ||
m.doSomething() | ||
k = Klass() // Set breakpoint copyableVarTest here 3 | ||
k.doSomething() // Set breakpoint copyableVarTest here 4 | ||
print("stop here") | ||
} | ||
|
||
public func addressOnlyValueTest<T : P>(_ x: T) { | ||
print("stop here") // Set breakpoint addressOnlyValueTest here 1 | ||
let k = x | ||
k.doSomething() | ||
let m = _move(k) // Set breakpoint addressOnlyValueTest here 2 | ||
m.doSomething() // Set breakpoint addressOnlyValueTest here 3 | ||
} | ||
|
||
public func addressOnlyVarTest<T : P>(_ x: T) { | ||
print("stop here") // Set breakpoint addressOnlyVarTest here 1 | ||
var k = x | ||
k.doSomething() | ||
let m = _move(k) // Set breakpoint addressOnlyVarTest here 2 | ||
m.doSomething() | ||
k = x // Set breakpoint addressOnlyVarTest here 3 | ||
k.doSomething() // Set breakpoint addressOnlyVarTest here 4 | ||
} | ||
|
||
//////////////////////////////////// | ||
// Conditional Control Flow Tests // | ||
//////////////////////////////////// | ||
|
||
public func copyableValueCCFTrueTest() { | ||
let k = Klass() // Set breakpoint copyableValueCCFTrueTest here 1 | ||
k.doSomething() // Set breakpoint copyableValueCCFTrueTest here 2 | ||
if trueBoolValue { | ||
let m = _move(k) // Set breakpoint copyableValueCCFTrueTest here 3 | ||
m.doSomething() // Set breakpoint copyableValueCCFTrueTest here 4 | ||
} | ||
// Set breakpoint copyableValueCCFTrueTest here 5 | ||
} | ||
|
||
public func copyableValueCCFFalseTest() { | ||
let k = Klass() // Set breakpoint copyableValueCCFFalseTest here 1 | ||
k.doSomething() | ||
if falseBoolValue { // Set breakpoint copyableValueCCFFalseTest here 2 | ||
let m = _move(k) | ||
m.doSomething() | ||
} | ||
// Set breakpoint copyableValueCCFFalseTest here 3 | ||
} | ||
|
||
////////////////////////// | ||
// Top Level Entrypoint // | ||
////////////////////////// | ||
|
||
func main() { | ||
copyableValueTest() | ||
copyableVarTest() | ||
addressOnlyValueTest(Klass()) | ||
addressOnlyVarTest(Klass()) | ||
copyableValueCCFTrueTest() | ||
copyableValueCCFFalseTest() | ||
} | ||
|
||
main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might be able to achieve the same with