def test_cast_int_to_anonymous_enum(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) self.expect("expr (flow_e)0", substrs=['(flow_e) $0 = A'])
def test(self): """Test that std::forward_list is displayed correctly""" self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) forward_list = self.namespace + '::forward_list' self.expect("frame variable empty", substrs=[forward_list, 'size=0', '{}']) self.expect("frame variable one_elt", substrs=[forward_list, 'size=1', '{', '[0] = 47', '}']) self.expect("frame variable five_elts", substrs=[forward_list, 'size=5', '{', '[0] = 1', '[1] = 22', '[2] = 333', '[3] = 4444', '[4] = 55555', '}'])
def test(self): """Test that std::tuple is displayed correctly""" self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) tuple_name = self.namespace + '::tuple' self.expect("frame variable empty", substrs=[tuple_name, 'size=0', '{}']) self.expect("frame variable one_elt", substrs=[tuple_name, 'size=1', '{', '[0] = 47', '}']) self.expect("frame variable three_elts", substrs=[tuple_name, 'size=3', '{', '[0] = 1', '[1] = 47', '[2] = "foo"', '}'])
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") # Test std::queue functionality with a std::deque. self.expect("expr q_deque.pop()") self.expect("expr q_deque.push({4})") self.expect("expr (size_t)q_deque.size()", substrs=['(size_t) $0 = 1']) self.expect("expr (int)q_deque.front().i", substrs=['(int) $1 = 4']) self.expect("expr (int)q_deque.back().i", substrs=['(int) $2 = 4']) self.expect("expr q_deque.empty()", substrs=['(bool) $3 = false']) self.expect("expr q_deque.pop()") self.expect("expr q_deque.emplace(5)") self.expect("expr (int)q_deque.front().i", substrs=['(int) $4 = 5']) # Test std::queue functionality with a std::list. self.expect("expr q_list.pop()") self.expect("expr q_list.push({4})") self.expect("expr (size_t)q_list.size()", substrs=['(size_t) $5 = 1']) self.expect("expr (int)q_list.front().i", substrs=['(int) $6 = 4']) self.expect("expr (int)q_list.back().i", substrs=['(int) $7 = 4']) self.expect("expr q_list.empty()", substrs=['(bool) $8 = false']) self.expect("expr q_list.pop()") self.expect("expr q_list.emplace(5)") self.expect("expr (int)q_list.front().i", substrs=['(int) $9 = 5'])
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3']) self.expect("expr (int)a[1].a", substrs=['(int) $2 = 1']) self.expect("expr (int)a.back().a", substrs=['(int) $3 = 2']) self.expect("expr std::reverse(a.begin(), a.end())") self.expect("expr (int)a.front().a", substrs=['(int) $4 = 2']) self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2']) self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3']) self.expect("expr a.pop_back()") self.expect("expr (int)a.back().a", substrs=['(int) $7 = 1']) self.expect("expr (size_t)a.size()", substrs=['(size_t) $8 = 2']) self.expect("expr (int)a.at(0).a", substrs=['(int) $9 = 2']) self.expect("expr a.push_back({4})") self.expect("expr (int)a.back().a", substrs=['(int) $10 = 4']) self.expect("expr (size_t)a.size()", substrs=['(size_t) $11 = 3'])
def do_watchpoint_test(self, line): self.build() lldbutil.run_to_source_breakpoint(self, line, self.main_spec) # Now let's set a write-type watchpoint for variable 'g_val'. self.expect( "watchpoint set variable -w write g_val", WATCHPOINT_CREATED, substrs=[ 'Watchpoint created', 'size = 4', 'type = w']) # Use the '-v' option to do verbose listing of the watchpoint. # The hit count should be 0 initially. self.expect("watchpoint list -v", substrs=['hit_count = 0']) self.runCmd("process continue") self.runCmd("thread list") if "stop reason = watchpoint" in self.res.GetOutput(): # Good, we verified that the watchpoint works! self.runCmd("thread backtrace all") else: self.fail("The stop reason should be either break or watchpoint") # Use the '-v' option to do verbose listing of the watchpoint. # The hit count should now be 1. self.expect("watchpoint list -v", substrs=['hit_count = 1'])
def test_class_template_specialization(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) self.expect("expr -u 0 -- b.foo()", substrs=['$0 = 1'])
def test_import_builtin_fileid(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.m", False)) self.expect("expr int (*DBG_CGImageGetRenderingIntent)(void *) = ((int (*)(void *))CGImageGetRenderingIntent); DBG_CGImageGetRenderingIntent((void *)0x00000000000000);", substrs=['$0 = 0'])
def test(self): """Test that std::queue is displayed correctly""" self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) self.check_variable('q1') self.check_variable('q2')
def test_value(self): """Test that std::bitset is displayed correctly""" self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) self.check("empty", 0) self.check("small", 13) self.check("large", 200)
def test_argument_passing_restrictions(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp")) self.expect("expr returnPassByRef()", substrs=['(PassByRef)', '= 11223344']) self.expect("expr takePassByRef(p)", substrs=['(int)', '= 42'])
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 2']) self.expect("expr (int)a.front().front()", substrs=['(int) $1 = 1']) self.expect("expr (int)a[1][1]", substrs=['(int) $2 = 2']) self.expect("expr (int)a.back().at(0)", substrs=['(int) $3 = 3'])
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") self.expect("expr std::abs(-42)", substrs=['(int) $0 = 42']) self.expect("expr std::div(2, 1).quot", substrs=['(int) $1 = 2']) self.expect("expr (std::size_t)33U", substrs=['(size_t) $2 = 33']) self.expect("expr char char_a = 'b'; char char_b = 'a'; std::swap(char_a, char_b); char_a", substrs=["(char) $3 = 'a'"])
def test_vector_of_enums(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) self.expect("expr v", substrs=[ 'size=3', '[0] = a', '[1] = b', '[2] = c', '}' ])
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") self.expect("expr (int)*w.lock()", substrs=['(int) $0 = 3']) self.expect("expr (int)(*w.lock() = 5)", substrs=['(int) $1 = 5']) self.expect("expr (int)*w.lock()", substrs=['(int) $2 = 5']) self.expect("expr w.use_count()", substrs=['(long) $3 = 1']) self.expect("expr w.reset()") self.expect("expr w.use_count()", substrs=['(long) $4 = 0'])
def test_non_cpp_language(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) # Activate importing of std module. self.runCmd("settings set target.import-std-module true") # These languages don't support C++ modules, so they shouldn't # be able to evaluate the expression. self.expect("expr -l C -- std::abs(-42)", error=True) self.expect("expr -l C99 -- std::abs(-42)", error=True) self.expect("expr -l C11 -- std::abs(-42)", error=True) self.expect("expr -l ObjC -- std::abs(-42)", error=True)
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") self.expect("expr (int)s->a", substrs=['(int) $0 = 3']) self.expect("expr (int)(s->a = 5)", substrs=['(int) $1 = 5']) self.expect("expr (int)s->a", substrs=['(int) $2 = 5']) self.expect("expr (bool)s", substrs=['(bool) $3 = true']) self.expect("expr s.reset()") self.expect("expr (bool)s", substrs=['(bool) $4 = false'])
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) # Activate importing of std module. self.runCmd("settings set target.import-std-module true") # Run some commands that should all fail without our std module. self.expect("expr std::abs(-42)", error=True) self.expect("expr std::div(2, 1).quot", error=True) self.expect("expr (std::size_t)33U", error=True) self.expect("expr char a = 'b'; char b = 'a'; std::swap(a, b); a", error=True)
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") self.expect("expr (size_t)std::distance(a.begin(), a.end())", substrs=['(size_t) $0 = 3']) self.expect("expr (int)a.front()", substrs=['(int) $1 = 3']) self.expect("expr a.sort()") self.expect("expr (int)a.front()", substrs=['(int) $2 = 1']) self.expect("expr (int)(*a.begin())", substrs=['(int) $3 = 1'])
def test_watchpoint_multiple_threads_wp_set_and_then_delete(self): """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" self.build() self.setTearDownCleanup() lldbutil.run_to_source_breakpoint(self, "After running the thread", self.main_spec) # Now let's set a write-type watchpoint for variable 'g_val'. self.expect( "watchpoint set variable -w write g_val", WATCHPOINT_CREATED, substrs=[ 'Watchpoint created', 'size = 4', 'type = w']) # Use the '-v' option to do verbose listing of the watchpoint. # The hit count should be 0 initially. self.expect("watchpoint list -v", substrs=['hit_count = 0']) watchpoint_stops = 0 while True: self.runCmd("process continue") self.runCmd("process status") if re.search("Process .* exited", self.res.GetOutput()): # Great, we are done with this test! break self.runCmd("thread list") if "stop reason = watchpoint" in self.res.GetOutput(): self.runCmd("thread backtrace all") watchpoint_stops += 1 if watchpoint_stops > 1: self.fail( "Watchpoint hits not supposed to exceed 1 by design!") # Good, we verified that the watchpoint works! Now delete the # watchpoint. if self.TraceOn(): print( "watchpoint_stops=%d at the moment we delete the watchpoint" % watchpoint_stops) self.runCmd("watchpoint delete 1") self.expect("watchpoint list -v", substrs=['No watchpoints currently set.']) continue else: self.fail("The stop reason should be either break or watchpoint")
def test_hide_runtime_support_values(self): self.build() _, process, _, _ = lldbutil.run_to_source_breakpoint( self, 'break here', lldb.SBFileSpec('main.mm')) var_opts = lldb.SBVariablesOptions() var_opts.SetIncludeArguments(True) var_opts.SetIncludeLocals(True) var_opts.SetInScopeOnly(True) var_opts.SetIncludeStatics(False) var_opts.SetIncludeRuntimeSupportValues(False) var_opts.SetUseDynamic(lldb.eDynamicCanRunTarget) values = self.frame().GetVariables(var_opts) def shows_var(name): for value in values: if value.name == name: return True return False # ObjC method. values = self.frame().GetVariables(var_opts) self.assertFalse(shows_var("this")) self.assertTrue(shows_var("self")) self.assertTrue(shows_var("_cmd")) self.assertTrue(shows_var("c")) process.Continue() # C++ method. values = self.frame().GetVariables(var_opts) self.assertTrue(shows_var("this")) self.assertFalse(shows_var("self")) self.assertFalse(shows_var("_cmd"))
def test_expr_failing_import(self): self.build() shutil.rmtree(self.getBuildArtifact('include')) target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( self, 'break here', lldb.SBFileSpec('main.cpp')) self.expect("expr -l Objective-C++ -- @import Bar", error=True)
def do_test(self): (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "// Set a breakpoint here", lldb.SBFileSpec("main.cpp")) frame = thread.GetFrameAtIndex(0) v = frame.GetValueForVariablePath('no_such_variable') self.assertTrue(v.GetError().Fail(), "Make sure we don't find 'no_such_variable'") # Test an instance self.verify_point(frame, 'pt', 'Point', 1, 2) # Test a pointer self.verify_point(frame, 'pt_ptr', 'Point *', 3030, 4040) # Test using a pointer as an array self.verify_point(frame, 'pt_ptr[-1]', 'Point', 1010, 2020) self.verify_point(frame, 'pt_ptr[0]', 'Point', 3030, 4040) self.verify_point(frame, 'pt_ptr[1]', 'Point', 5050, 6060) # Test arrays v = frame.GetValueForVariablePath('points') self.assertTrue(v.GetError().Success(), "Make sure we find 'points'") self.verify_point(frame, 'points[0]', 'Point', 1010, 2020) self.verify_point(frame, 'points[1]', 'Point', 3030, 4040) self.verify_point(frame, 'points[2]', 'Point', 5050, 6060) # Test a reference self.verify_point(frame, 'pt_ref', 'Point &', 1, 2) v = frame.GetValueForVariablePath('pt_sp') self.assertTrue(v.GetError().Success(), "Make sure we find 'pt_sp'") # Make sure we don't crash when looking for non existant child # in type with synthetic children. This used to cause a crash. v = frame.GetValueForVariablePath('pt_sp->not_valid_child') self.assertTrue(v.GetError().Fail(), "Make sure we don't find 'pt_sp->not_valid_child'")
def test_expr_options(self): """These expression command options should work as expected.""" self.build() # Set debugger into synchronous mode self.dbg.SetAsync(False) (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, '// breakpoint_in_main', self.main_source_spec) frame = thread.GetFrameAtIndex(0) options = lldb.SBExpressionOptions() # test --language on C++ expression using the SB API's # Make sure we can evaluate a C++11 expression. val = frame.EvaluateExpression('foo != nullptr') self.assertTrue(val.IsValid()) self.assertTrue(val.GetError().Success()) self.DebugSBValue(val) # Make sure it still works if language is set to C++11: options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) val = frame.EvaluateExpression('foo != nullptr', options) self.assertTrue(val.IsValid()) self.assertTrue(val.GetError().Success()) self.DebugSBValue(val) # Make sure it fails if language is set to C: options.SetLanguage(lldb.eLanguageTypeC) val = frame.EvaluateExpression('foo != nullptr', options) self.assertTrue(val.IsValid()) self.assertFalse(val.GetError().Success())
def test_plain_objc_with_run_command(self): """Test basic ObjC formatting behavior.""" self.build() self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( self, '// Set break point at this line.', lldb.SBFileSpec('main.m', False)) # The stop reason of the thread should be breakpoint. self.expect( "thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) # This is the function to remove the custom formats in order to have a # clean slate for the next test case. def cleanup(): self.runCmd('type format clear', check=False) self.runCmd('type summary clear', check=False) self.runCmd('type synth clear', check=False) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) self.runCmd("type summary add --summary-string \"${var%@}\" MyClass") self.expect("frame variable object2", substrs=['MyOtherClass']) self.expect("frame variable *object2", substrs=['MyOtherClass']) # Now let's delete the 'MyClass' custom summary. self.runCmd("type summary delete MyClass") # The type format list should not show 'MyClass' at this point. self.expect("type summary list", matching=False, substrs=['MyClass']) self.runCmd("type summary add --summary-string \"a test\" MyClass") self.expect( "frame variable *object2", substrs=['*object2 =', 'MyClass = a test', 'backup = ']) self.expect( "frame variable object2", matching=False, substrs=['a test']) self.expect("frame variable object", substrs=['a test']) self.expect("frame variable *object", substrs=['a test']) self.expect( 'frame variable myclass', substrs=['(Class) myclass = NSValue']) self.expect( 'frame variable myclass2', substrs=['(Class) myclass2 = ', 'NS', 'String']) self.expect( 'frame variable myclass3', substrs=['(Class) myclass3 = Molecule']) self.expect( 'frame variable myclass4', substrs=['(Class) myclass4 = NSMutableArray']) self.expect( 'frame variable myclass5', substrs=['(Class) myclass5 = nil'])
def test_save_jit_objects(self): self.build() os.chdir(self.getBuildDir()) src_file = "main.c" src_file_spec = lldb.SBFileSpec(src_file) (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "break", src_file_spec) frame = thread.frames[0] self.cleanJITFiles() frame.EvaluateExpression("(void*)malloc(0x1)") self.assertTrue(self.countJITFiles() == 0, "No files emitted with save-jit-objects=false") self.runCmd("settings set target.save-jit-objects true") frame.EvaluateExpression("(void*)malloc(0x1)") jit_files_count = self.countJITFiles() self.cleanJITFiles() self.assertTrue(jit_files_count != 0, "At least one file emitted with save-jit-objects=true") process.Kill() os.chdir(self.getSourceDir())
def test_expr_options_lang(self): """These expression language options should work as expected.""" self.build() # Set debugger into synchronous mode self.dbg.SetAsync(False) (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, '// breakpoint_in_main', self.main_source_spec) frame = thread.GetFrameAtIndex(0) options = lldb.SBExpressionOptions() # Make sure we can retrieve `id` variable if language is set to C++11: options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) val = frame.EvaluateExpression('id == 0', options) self.assertTrue(val.IsValid()) self.assertTrue(val.GetError().Success()) self.DebugSBValue(val) # Make sure we can't retrieve `id` variable if language is set to ObjC: options.SetLanguage(lldb.eLanguageTypeObjC) val = frame.EvaluateExpression('id == 0', options) self.assertTrue(val.IsValid()) self.assertFalse(val.GetError().Success())
def try_expressions(self): """Test calling expressions with errors that can be fixed by the FixIts.""" (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, 'Stop here to evaluate expressions', self.main_source_spec) options = lldb.SBExpressionOptions() options.SetAutoApplyFixIts(True) frame = self.thread.GetFrameAtIndex(0) # Try with one error: value = frame.EvaluateExpression("my_pointer.first", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsUnsigned() == 10) # Try with two errors: two_error_expression = "my_pointer.second->a" value = frame.EvaluateExpression(two_error_expression, options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsUnsigned() == 20) # Now turn off the fixits, and the expression should fail: options.SetAutoApplyFixIts(False) value = frame.EvaluateExpression(two_error_expression, options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Fail()) error_string = value.GetError().GetCString() self.assertTrue( error_string.find("fixed expression suggested:") != -1, "Fix was suggested") self.assertTrue( error_string.find("my_pointer->second.a") != -1, "Fix was right")
def test(self): self.build() self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, '// Set break point at this line.', self.main_source_spec) frame = thread.GetFrameAtIndex(0) self.expect("expr f == Foo::FooBar", substrs=['(bool) $0 = true']) value = frame.EvaluateExpression("f == Foo::FooBar") self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsUnsigned(), 1) value = frame.EvaluateExpression("b == BarBar") self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsUnsigned(), 1) ## b is not a Foo value = frame.EvaluateExpression("b == Foo::FooBar") self.assertTrue(value.IsValid()) self.assertFalse(value.GetError().Success()) ## integral is not implicitly convertible to a scoped enum value = frame.EvaluateExpression("1 == Foo::FooBar") self.assertTrue(value.IsValid()) self.assertFalse(value.GetError().Success())
def expr_options_test(self): (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) frame = thread.GetFrameAtIndex(0) # First make sure we can call the function with the default option set. options = lldb.SBExpressionOptions() # Check that the default is to allow JIT: self.assertEqual(options.GetAllowJIT(), True, "Default is true") # Now use the options: result = frame.EvaluateExpression("call_me(10)", options) self.assertTrue(result.GetError().Success(), "expression succeeded") self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") # Now disallow JIT and make sure it fails: options.SetAllowJIT(False) # Check that we got the right value: self.assertEqual(options.GetAllowJIT(), False, "Got False after setting to False") # Again use it and ensure we fail: result = frame.EvaluateExpression("call_me(10)", options) self.assertTrue(result.GetError().Fail(), "expression failed with no JIT") self.assertTrue("Can't run the expression locally" in result.GetError().GetCString(), "Got right error") # Finally set the allow JIT value back to true and make sure that works: options.SetAllowJIT(True) self.assertEqual(options.GetAllowJIT(), True, "Set back to True correctly") # And again, make sure this works: result = frame.EvaluateExpression("call_me(10)", options) self.assertTrue(result.GetError().Success(), "expression succeeded") self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.")
def do_self_test(self, bkpt_pattern, needs_dynamic): lldbutil.run_to_source_breakpoint(self, bkpt_pattern, lldb.SBFileSpec('main.swift')) self.check_self(bkpt_pattern, needs_dynamic)
def test_namespace_only(self): """ Test that we fail to lookup a struct type that exists only in a namespace. """ self.build() self.main_source_file = lldb.SBFileSpec("main.cpp") (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) # Get frame for current thread frame = thread.GetSelectedFrame() # We are testing LLDB's type lookup machinery, but if we inject local # variables, the types for those will be found because they have been # imported through the variable, not because the type lookup worked. self.runCmd("settings set target.experimental.inject-local-vars false") # Make sure we don't accidentally accept structures that exist only # in namespaces when evaluating expressions with top level types. # Prior to the revision that added this test, we would accidentally # accept types from namespaces, so this will ensure we don't regress # to that behavior again expr_result = frame.EvaluateExpression("*((namespace_only *)&i)") self.assertTrue(expr_result.GetError().Fail(), "'namespace_only' exists in namespace only") # Make sure we can find the correct type in a namespace "nsp_a" expr_result = frame.EvaluateExpression( "*((nsp_a::namespace_only *)&i)") self.check_value(expr_result, "a", 123) # Make sure we can find the correct type in a namespace "nsp_b" expr_result = frame.EvaluateExpression( "*((nsp_b::namespace_only *)&i)") self.check_value(expr_result, "b", 123) # Make sure we can find the correct type in the root namespace expr_result = frame.EvaluateExpression("*((namespace_and_file *)&i)") self.check_value(expr_result, "ff", 123) # Make sure we can find the correct type in a namespace "nsp_a" expr_result = frame.EvaluateExpression( "*((nsp_a::namespace_and_file *)&i)") self.check_value(expr_result, "aa", 123) # Make sure we can find the correct type in a namespace "nsp_b" expr_result = frame.EvaluateExpression( "*((nsp_b::namespace_and_file *)&i)") self.check_value(expr_result, "bb", 123) # Make sure we don't accidentally accept structures that exist only # in namespaces when evaluating expressions with top level types. # Prior to the revision that added this test, we would accidentally # accept types from namespaces, so this will ensure we don't regress # to that behavior again expr_result = frame.EvaluateExpression("*((in_contains_type *)&i)") self.assertTrue(expr_result.GetError().Fail(), "'in_contains_type' exists in struct only") # Make sure we can find the correct type in the root namespace expr_result = frame.EvaluateExpression( "*((contains_type::in_contains_type *)&i)") self.check_value(expr_result, "fff", 123) # Make sure we can find the correct type in a namespace "nsp_a" expr_result = frame.EvaluateExpression( "*((nsp_a::contains_type::in_contains_type *)&i)") self.check_value(expr_result, "aaa", 123) # Make sure we can find the correct type in a namespace "nsp_b" expr_result = frame.EvaluateExpression( "*((nsp_b::contains_type::in_contains_type *)&i)") self.check_value(expr_result, "bbb", 123)
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c")) # Test several variables with C++ keyword names and make sure they # work as intended in the expression parser. self.expect_expr("alignas", result_type="int", result_value="1") self.expect_expr("alignof", result_type="int", result_value="1") self.expect_expr("and", result_type="int", result_value="1") self.expect_expr("and_eq", result_type="int", result_value="1") self.expect_expr("atomic_cancel", result_type="int", result_value="1") self.expect_expr("atomic_commit", result_type="int", result_value="1") self.expect_expr("atomic_noexcept", result_type="int", result_value="1") self.expect_expr("bitand", result_type="int", result_value="1") self.expect_expr("bitor", result_type="int", result_value="1") self.expect_expr("catch", result_type="int", result_value="1") self.expect_expr("char8_t", result_type="int", result_value="1") self.expect_expr("char16_t", result_type="int", result_value="1") self.expect_expr("char32_t", result_type="int", result_value="1") self.expect_expr("class", result_type="int", result_value="1") self.expect_expr("compl", result_type="int", result_value="1") self.expect_expr("concept", result_type="int", result_value="1") self.expect_expr("consteval", result_type="int", result_value="1") self.expect_expr("constexpr", result_type="int", result_value="1") self.expect_expr("constinit", result_type="int", result_value="1") self.expect_expr("const_cast", result_type="int", result_value="1") self.expect_expr("co_await", result_type="int", result_value="1") self.expect_expr("co_return", result_type="int", result_value="1") self.expect_expr("co_yield", result_type="int", result_value="1") self.expect_expr("decltype", result_type="int", result_value="1") self.expect_expr("delete", result_type="int", result_value="1") self.expect_expr("dynamic_cast", result_type="int", result_value="1") self.expect_expr("explicit", result_type="int", result_value="1") self.expect_expr("export", result_type="int", result_value="1") self.expect_expr("friend", result_type="int", result_value="1") self.expect_expr("mutable", result_type="int", result_value="1") self.expect_expr("namespace", result_type="int", result_value="1") self.expect_expr("new", result_type="int", result_value="1") self.expect_expr("noexcept", result_type="int", result_value="1") self.expect_expr("not", result_type="int", result_value="1") self.expect_expr("not_eq", result_type="int", result_value="1") self.expect_expr("operator", result_type="int", result_value="1") self.expect_expr("or", result_type="int", result_value="1") self.expect_expr("or_eq", result_type="int", result_value="1") self.expect_expr("private", result_type="int", result_value="1") self.expect_expr("protected", result_type="int", result_value="1") self.expect_expr("public", result_type="int", result_value="1") self.expect_expr("reflexpr", result_type="int", result_value="1") self.expect_expr("reinterpret_cast", result_type="int", result_value="1") self.expect_expr("requires", result_type="int", result_value="1") self.expect_expr("static_assert", result_type="int", result_value="1") self.expect_expr("static_cast", result_type="int", result_value="1") self.expect_expr("synchronized", result_type="int", result_value="1") self.expect_expr("template", result_type="int", result_value="1") self.expect_expr("this", result_type="int", result_value="1") self.expect_expr("thread_local", result_type="int", result_value="1") self.expect_expr("throw", result_type="int", result_value="1") self.expect_expr("try", result_type="int", result_value="1") self.expect_expr("typeid", result_type="int", result_value="1") self.expect_expr("typename", result_type="int", result_value="1") self.expect_expr("virtual", result_type="int", result_value="1") self.expect_expr("xor", result_type="int", result_value="1") self.expect_expr("xor_eq", result_type="int", result_value="1") # Some keywords are not available in LLDB as their language feature # is enabled by default. # 'using' is used by LLDB for local variables. self.expect("expr using", error=True, substrs=["expected unqualified-id"]) # 'wchar_t' supported is enabled in LLDB. self.expect("expr wchar_t", error=True, substrs=["expected unqualified-id"]) # LLDB enables 'bool' support by default. self.expect("expr bool", error=True, substrs=["expected unqualified-id"]) self.expect("expr false", error=True, substrs=["expected unqualified-id"]) self.expect("expr true", error=True, substrs=["expected unqualified-id"])
def test_stdcxx_disasm(self): """Do 'disassemble' on each and every 'Code' symbol entry from the std c++ lib.""" self.build() (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "// Set break point at this line", lldb.SBFileSpec("main.cpp")) # Disassemble the functions on the call stack. self.runCmd("thread backtrace") thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertIsNotNone(thread) depth = thread.GetNumFrames() for i in range(depth - 1): frame = thread.GetFrameAtIndex(i) function = frame.GetFunction() if function.GetName(): self.runCmd("disassemble -n '%s'" % function.GetName()) lib_stdcxx = "FAILHORRIBLYHERE" # Iterate through the available modules, looking for stdc++ library... for i in range(target.GetNumModules()): module = target.GetModuleAtIndex(i) fs = module.GetFileSpec() if (fs.GetFilename().startswith("libstdc++") or fs.GetFilename().startswith("libc++")): lib_stdcxx = str(fs) break # At this point, lib_stdcxx is the full path to the stdc++ library and # module is the corresponding SBModule. self.expect(lib_stdcxx, "Libraray StdC++ is located", exe=False, substrs=["lib"]) self.runCmd("image dump symtab '%s'" % lib_stdcxx) raw_output = self.res.GetOutput() # Now, look for every 'Code' symbol and feed its load address into the # command: 'disassemble -s load_address -e end_address', where the # end_address is taken from the next consecutive 'Code' symbol entry's # load address. # # The load address column comes after the file address column, with both # looks like '0xhhhhhhhh', i.e., 8 hexadecimal digits. codeRE = re.compile( r""" \ Code\ {9} # ' Code' followed by 9 SPCs, 0x[0-9a-f]{16} # the file address column, and \ # a SPC, and (0x[0-9a-f]{16}) # the load address column, and .* # the rest. """, re.VERBOSE) # Maintain a start address variable; if we arrive at a consecutive Code # entry, then the load address of the that entry is fed as the end # address to the 'disassemble -s SA -e LA' command. SA = None for line in raw_output.split(os.linesep): match = codeRE.search(line) if match: LA = match.group(1) if self.TraceOn(): print("line:", line) print("load address:", LA) print("SA:", SA) if SA and LA: if int(LA, 16) > int(SA, 16): self.runCmd("disassemble -s %s -e %s" % (SA, LA)) SA = LA else: # This entry is not a Code entry. Reset SA = None. SA = None
def test_expr_with_macros(self): self.build() # Get main source file src_file = "main.cpp" hdr_file = "macro1.h" src_file_spec = lldb.SBFileSpec(src_file) self.assertTrue(src_file_spec.IsValid(), "Main source file") (target, process, thread, bp1) = lldbutil.run_to_source_breakpoint(self, "Break here", src_file_spec) # Get frame for current thread frame = thread.GetSelectedFrame() result = frame.EvaluateExpression("MACRO_1") self.assertTrue(result.IsValid() and result.GetValue() == "100", "MACRO_1 = 100") result = frame.EvaluateExpression("MACRO_2") self.assertTrue(result.IsValid() and result.GetValue() == "200", "MACRO_2 = 200") result = frame.EvaluateExpression("ONE") self.assertTrue(result.IsValid() and result.GetValue() == "1", "ONE = 1") result = frame.EvaluateExpression("TWO") self.assertTrue(result.IsValid() and result.GetValue() == "2", "TWO = 2") result = frame.EvaluateExpression("THREE") self.assertTrue(result.IsValid() and result.GetValue() == "3", "THREE = 3") result = frame.EvaluateExpression("FOUR") self.assertTrue(result.IsValid() and result.GetValue() == "4", "FOUR = 4") result = frame.EvaluateExpression("HUNDRED") self.assertTrue(result.IsValid() and result.GetValue() == "100", "HUNDRED = 100") result = frame.EvaluateExpression("THOUSAND") self.assertTrue(result.IsValid() and result.GetValue() == "1000", "THOUSAND = 1000") result = frame.EvaluateExpression("MILLION") self.assertTrue(result.IsValid() and result.GetValue() == "1000000", "MILLION = 1000000") result = frame.EvaluateExpression("MAX(ONE, TWO)") self.assertTrue(result.IsValid() and result.GetValue() == "2", "MAX(ONE, TWO) = 2") result = frame.EvaluateExpression("MAX(THREE, TWO)") self.assertTrue(result.IsValid() and result.GetValue() == "3", "MAX(THREE, TWO) = 3") # Get the thread of the process thread.StepOver() # Get frame for current thread frame = thread.GetSelectedFrame() result = frame.EvaluateExpression("MACRO_2") self.assertTrue(result.GetError().Fail(), "Printing MACRO_2 fails in the mail file") result = frame.EvaluateExpression("FOUR") self.assertTrue(result.GetError().Fail(), "Printing FOUR fails in the main file") thread.StepInto() # Get frame for current thread frame = thread.GetSelectedFrame() result = frame.EvaluateExpression("ONE") self.assertTrue(result.IsValid() and result.GetValue() == "1", "ONE = 1") result = frame.EvaluateExpression("MAX(ONE, TWO)") self.assertTrue(result.IsValid() and result.GetValue() == "2", "MAX(ONE, TWO) = 2") # This time, MACRO_1 and MACRO_2 are not visible. result = frame.EvaluateExpression("MACRO_1") self.assertTrue(result.GetError().Fail(), "Printing MACRO_1 fails in the header file") result = frame.EvaluateExpression("MACRO_2") self.assertTrue(result.GetError().Fail(), "Printing MACRO_2 fails in the header file")
def test_swift_expression_access_control(self): """Make sure expressions ignore access control""" self.build() lldbutil.run_to_source_breakpoint(self, 'Set breakpoint here', lldb.SBFileSpec('main.swift')) self.check_expression("foo.m_a", "3", use_summary=False)
def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.cpp", False)) # This is the function to remove the custom formats in order to have a # clean slate for the next test case. def cleanup(): self.runCmd('type format clear', check=False) self.runCmd('type summary clear', check=False) self.runCmd('type filter clear', check=False) self.runCmd('type synth clear', check=False) self.runCmd( "settings set target.max-children-count 256", check=False) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) # empty vectors (and storage pointers SHOULD BOTH BE NULL..) self.expect("frame variable numbers", substrs=['numbers = size=0']) lldbutil.continue_to_breakpoint(process, bkpt) # first value added self.expect("frame variable numbers", substrs=['numbers = size=1', '[0] = 1', '}']) # add some more data lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable numbers", substrs=['numbers = size=4', '[0] = 1', '[1] = 12', '[2] = 123', '[3] = 1234', '}']) self.expect("p numbers", substrs=['$', 'size=4', '[0] = 1', '[1] = 12', '[2] = 123', '[3] = 1234', '}']) # check access to synthetic children self.runCmd( "type summary add --summary-string \"item 0 is ${var[0]}\" std::int_vect int_vect") self.expect('frame variable numbers', substrs=['item 0 is 1']) self.runCmd( "type summary add --summary-string \"item 0 is ${svar[0]}\" std::int_vect int_vect") self.expect('frame variable numbers', substrs=['item 0 is 1']) # move on with synths self.runCmd("type summary delete std::int_vect") self.runCmd("type summary delete int_vect") # add some more data lldbutil.continue_to_breakpoint(process, bkpt) self.check_numbers("numbers") # clear out the vector and see that we do the right thing once again lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable numbers", substrs=['numbers = size=0']) lldbutil.continue_to_breakpoint(process, bkpt) # first value added self.expect("frame variable numbers", substrs=['numbers = size=1', '[0] = 7', '}']) # check if we can display strings self.expect("frame variable strings", substrs=['goofy', 'is', 'smart']) self.expect("p strings", substrs=['goofy', 'is', 'smart']) # test summaries based on synthetic children self.runCmd( "type summary add std::string_vect string_vect --summary-string \"vector has ${svar%#} items\" -e") self.expect("frame variable strings", substrs=['vector has 3 items', 'goofy', 'is', 'smart']) self.expect("p strings", substrs=['vector has 3 items', 'goofy', 'is', 'smart']) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable strings", substrs=['vector has 4 items']) # check access-by-index self.expect("frame variable strings[0]", substrs=['goofy']) self.expect("frame variable strings[1]", substrs=['is']) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable strings", substrs=['vector has 0 items'])
def test_simple_swift_expressions(self): """Tests that we can run simple Swift expressions correctly""" self.build() lldbutil.run_to_source_breakpoint(self, 'Set breakpoint here', lldb.SBFileSpec('main.swift')) # Test that parse errors give a correct result: value_obj = self.frame().EvaluateExpression( "iff is_five === 5 { return is_five") error = value_obj.GetError() # Test simple math with constants self.check_expression("5 + 6", "11", use_summary=False) self.check_expression("is_five + is_six", "11", use_summary=False) self.check_expression("if (1 == 1) { return is_five + is_six }", "11", use_summary=False) # Test boolean operations with simple variables: # Bool's are currently enums, so their value is actually in the value. self.check_expression("is_eleven == is_five + is_six", "true") # Try a slightly more complex container for our expression: self.check_expression( "if is_five == 5 { return is_five + is_six } else { return is_five }", "11", use_summary=False) # Make sure we get an error if we don't give homogenous return types: bool_or_int = self.frame().EvaluateExpression( "if is_five == 5 { return is_five + is_six } else { return false }" ) self.assertTrue( bool_or_int.IsValid(), "if is_five == 5 { return is_five + is_six } else { return false } is invalid" ) # Make sure we get the correct branch of a complex result expression: self.check_expression( "if is_five == 6 {return is_five} else if is_six == 5 {return is_six} ; is_eleven", "11", use_summary=False) # Make sure we can access globals: # Commented out till we resolve <rdar://problem/15695494> Accessing global variables causes LLVM ERROR and exit... # self.check_expression ("my_global", "30") # Non-simple names: # Note: python 2 and python 3 have different default encodings. # This can be removed once python 2 is gone entirely. if sys.version_info.major == 2: self.check_expression(u"\u20ac_varname".encode("utf-8"), "5", use_summary=False) else: self.check_expression(u"\u20ac_varname", "5", use_summary=False) # See if we can do the same manipulations with tuples: # Commented out due to: <rdar://problem/15476525> Expressions with # tuple elements assert self.check_expression("a_tuple.0 + a_tuple.1", "11", use_summary=False) # See if we can do some manipulations with dicts: self.check_expression('str_int_dict["five"]! + str_int_dict["six"]!', "11", use_summary=False) self.check_expression('int_str_dict[Int(is_five + is_six)]!', '"eleven"') # Commented out, touching the dict twice causes it to die, probably the same problem # as <rdar://problem/15306399> self.check_expression( 'str_int_dict["five"] = 6; str_int_dict["five"]! + str_int_dict["six"]!', "12", use_summary=False) # See if we can use a switch statement in an expression: self.check_expression( "switch is_five { case 0..<6: return 1; case 7..<11: return 2; case _: return 4; }; 3;", "1", use_summary=False) # These ones are int-convertible and Equatable so we can do some things # with them anyway: self.check_expression("enum_eleven", "Eleven", False) self.check_expression("enum_eleven == SomeValues.Eleven", "true") self.check_expression( "SomeValues.Five.toInt() + SomeValues.Six.toInt()", "11", use_summary=False) self.check_expression( "enum_eleven = .Five; return enum_eleven == .Five", "true") # Test expressions with a simple object: self.check_expression("a_obj.x", "6", use_summary=False) # Should not have to make a second object here. This is another # side-effect of <rdar://problem/15306399> self.check_expression("a_nother_obj.y", "6.5", use_summary=False) # Test expressions with a struct: self.check_expression("b_struct.b_int", "5", use_summary=False) # Test expression with Chars and strings: # Commented out due to <rdar://problem/16856379> #self.check_expression ("a_char", "U+0061 U+0000 u'a'") # Interpolated strings and string addition: self.check_expression('"Five: \(is_five) " + "Six: \(is_six)"', '"Five: 5 Six: 6"') # Next let's try some simple array accesses: self.check_expression("an_int_array[0]", "5", use_summary=False) # Test expression with read-only variables: self.check_expression("b_struct.b_read_only == 5", "true") failed_value = self.frame().EvaluateExpression( "b_struct.b_read_only = 34") self.assertTrue(failed_value.IsValid(), "Get something back from the evaluation.") self.assertTrue(failed_value.GetError().Success() == False, "But it is an error.") # Check a simple value in a struct: self.check_expression("b_struct_2.b_int", "20", use_summary=False) # Make sure this works for properties in extensions as well: self.check_expression("b_struct_2.b_float", "20.5", use_summary=False) # Here are a few tests of making variables in expressions: self.check_expression( "var enum_six : SomeValues = SomeValues.Six; return enum_six == .Six", "true")
def test_c_unions(self): self.build() target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( self, 'break here', lldb.SBFileSpec('main.swift')) self.expect("target variable -- i", substrs=['42']) self.expect("target variable -- d", substrs=['23'])
def test_with_multiple_retries(self): """Test calling expressions with errors that can be fixed by the FixIts.""" self.build() (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint( self, 'Stop here to evaluate expressions', lldb.SBFileSpec("main.cpp")) # Test repeatedly applying Fix-Its to expressions and reparsing them. multiple_runs_options = lldb.SBExpressionOptions() multiple_runs_options.SetAutoApplyFixIts(True) multiple_runs_options.SetTopLevel(True) frame = self.thread.GetFrameAtIndex(0) # An expression that needs two parse attempts with one Fix-It each # to be successfully parsed. two_runs_expr = """ struct Data { int m; }; template<typename T> struct S1 : public T { using T::TypeDef; int f() { Data data; data.m = 123; // The first error as the using above requires a 'typename '. // Will trigger a Fix-It that puts 'typename' in the right place. typename S1<T>::TypeDef i = &data; // i has the type "Data *", so this should be i.m. // The second run will change the . to -> via the Fix-It. return i.m; } }; struct ClassWithTypeDef { typedef Data *TypeDef; }; int test_X(int i) { S1<ClassWithTypeDef> s1; return s1.f(); } """ # Disable retries which will fail. multiple_runs_options.SetRetriesWithFixIts(0) value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options) self.assertIn( "expression failed to parse, fixed expression suggested:", value.GetError().GetCString()) self.assertIn("using typename T::TypeDef", value.GetError().GetCString()) # The second Fix-It shouldn't be suggested here as Clang should have # aborted the parsing process. self.assertNotIn("i->m", value.GetError().GetCString()) # Retry once, but the expression needs two retries. multiple_runs_options.SetRetriesWithFixIts(1) value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options) self.assertIn( "expression failed to parse, fixed expression suggested:", value.GetError().GetCString()) # Both our fixed expressions should be in the suggested expression. self.assertIn("using typename T::TypeDef", value.GetError().GetCString()) self.assertIn("i->m", value.GetError().GetCString()) # Retry twice, which will get the expression working. multiple_runs_options.SetRetriesWithFixIts(2) value = frame.EvaluateExpression(two_runs_expr, multiple_runs_options) # This error signals success for top level expressions. self.assertEquals(value.GetError().GetCString(), "error: No value") # Test that the code above compiles to the right thing. self.expect_expr("test_X(1)", result_type="int", result_value="123")
def test_default_with_run(self): """Test "statistics dump" when running the target to a breakpoint. When we run the target, we expect to see 'launchOrAttachTime' and 'firstStopTime' top level keys. Output expected to be something like: (lldb) statistics dump { "memory" : {...}, "modules" : [...], "targets" : [ { "firstStopTime": 0.34164492800000001, "launchOrAttachTime": 0.31969605400000001, "moduleIdentifiers": [...], "targetCreateTime": 0.0040863039999999998 "expressionEvaluation": { "failures": 0, "successes": 0 }, "frameVariable": { "failures": 0, "successes": 0 }, } ], "totalDebugInfoByteSize": 182522234, "totalDebugInfoIndexTime": 2.33343, "totalDebugInfoParseTime": 8.2121400240000071, "totalSymbolTableParseTime": 0.123, "totalSymbolTableIndexTime": 0.234, } """ self.build() target = self.createTestTarget() lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c")) debug_stats = self.get_stats() debug_stat_keys = [ 'memory', 'modules', 'targets', 'totalSymbolTableParseTime', 'totalSymbolTableIndexTime', 'totalSymbolTablesLoadedFromCache', 'totalSymbolTablesSavedToCache', 'totalDebugInfoByteSize', 'totalDebugInfoIndexTime', 'totalDebugInfoIndexLoadedFromCache', 'totalDebugInfoIndexSavedToCache', 'totalDebugInfoParseTime', ] self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) stats = debug_stats['targets'][0] keys_exist = [ 'expressionEvaluation', 'firstStopTime', 'frameVariable', 'launchOrAttachTime', 'moduleIdentifiers', 'targetCreateTime', ] self.verify_keys(stats, '"stats"', keys_exist, None) self.assertGreater(stats['firstStopTime'], 0.0) self.assertGreater(stats['launchOrAttachTime'], 0.0) self.assertGreater(stats['targetCreateTime'], 0.0)
def do_test(self, bkpt_modifier=None): self.build() main_spec = lldb.SBFileSpec("main.cpp") # Launch and stop before the dlopen call. target, process, thread, _ = lldbutil.run_to_source_breakpoint( self, "// Set a breakpoint here", main_spec, extra_images=["load_a", "load_b"]) # Now turn on shared library events, continue and make sure we stop for the event. self.runCmd( "settings set target.process.stop-on-sharedlibrary-events 1") self.addTearDownHook(lambda: self.runCmd( "settings set target.process.stop-on-sharedlibrary-events 0")) # Since I don't know how to check that we are at the "right place" to stop for # shared library events, make an breakpoint after the load is done and # make sure we don't stop there: backstop_bkpt_1 = target.BreakpointCreateBySourceRegex( "Set another here - we should not hit this one", main_spec) self.assertGreater(backstop_bkpt_1.GetNumLocations(), 0, "Set our second breakpoint") process.Continue() self.assertState(process.GetState(), lldb.eStateStopped, "We didn't stop for the load") self.assertEqual(backstop_bkpt_1.GetHitCount(), 0, "Hit our backstop breakpoint") # We should be stopped after the library is loaded, check that: found_it = False for module in target.modules: if module.file.basename.find("load_a") > -1: found_it = True break self.assertTrue(found_it, "Found the loaded module.") # Now capture the place where we stopped so we can set a breakpoint and make # sure the breakpoint there works correctly: load_address = process.GetSelectedThread().frames[0].addr load_bkpt = target.BreakpointCreateBySBAddress(load_address) self.assertGreater(load_bkpt.GetNumLocations(), 0, "Set the load breakpoint") backstop_bkpt_1.SetEnabled(False) backstop_bkpt_2 = target.BreakpointCreateBySourceRegex( "Set a third here - we should not hit this one", main_spec) self.assertGreater(backstop_bkpt_2.GetNumLocations(), 0, "Set our third breakpoint") if bkpt_modifier == None: process.Continue() self.assertState(process.GetState(), lldb.eStateStopped, "We didn't stop for the load") self.assertEqual(backstop_bkpt_2.GetHitCount(), 0, "Hit our backstop breakpoint") self.assertStopReason(thread.stop_reason, lldb.eStopReasonBreakpoint, "We attributed the stop to the breakpoint") self.assertEqual(load_bkpt.GetHitCount(), 1, "We hit our breakpoint at the load address") else: bkpt_modifier(load_bkpt) process.Continue() self.assertState(process.GetState(), lldb.eStateStopped, "We didn't stop") self.assertTrue(thread.IsValid(), "Our thread was no longer valid.") self.assertStopReason(thread.stop_reason, lldb.eStopReasonBreakpoint, "We didn't hit some breakpoint") self.assertEqual(backstop_bkpt_2.GetHitCount(), 1, "We continued to the right breakpoint")
def build_run_stop(self): self.build() lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.c"))
def test_objc_exceptions_at_throw(self): self.build() target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) launch_info = lldb.SBLaunchInfo(["a.out", "0"]) lldbutil.run_to_name_breakpoint(self, "objc_exception_throw", launch_info=launch_info) self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) self.expect('thread exception', substrs=[ '(NSException *) exception = ', 'name: "ThrownException" - reason: "SomeReason"', ]) target = self.dbg.GetSelectedTarget() thread = target.GetProcess().GetSelectedThread() frame = thread.GetSelectedFrame() opts = lldb.SBVariablesOptions() opts.SetIncludeRecognizedArguments(True) variables = frame.GetVariables(opts) self.assertEqual(variables.GetSize(), 1) self.assertEqual(variables.GetValueAtIndex(0).name, "exception") self.assertEqual(variables.GetValueAtIndex(0).GetValueType(), lldb.eValueTypeVariableArgument) lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.mm"), launch_info=launch_info) self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) target = self.dbg.GetSelectedTarget() thread = target.GetProcess().GetSelectedThread() frame = thread.GetSelectedFrame() # No exception being currently thrown/caught at this point self.assertFalse(thread.GetCurrentException().IsValid()) self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid()) self.expect( 'frame variable e1', substrs=[ '(NSException *) e1 = ', 'name: "ExceptionName" - reason: "SomeReason"' ]) self.expect( 'frame variable --dynamic-type no-run-target *e1', substrs=[ '(NSException) *e1 = ', 'name = ', '"ExceptionName"', 'reason = ', '"SomeReason"', 'userInfo = ', '1 key/value pair', 'reserved = ', 'nil', ]) e1 = frame.FindVariable("e1") self.assertTrue(e1) self.assertEqual(e1.type.name, "NSException *") self.assertEqual(e1.GetSummary(), 'name: "ExceptionName" - reason: "SomeReason"') self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName") self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason") userInfo = e1.GetChildMemberWithName("userInfo").dynamic self.assertEqual(userInfo.summary, "1 key/value pair") self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") self.assertEqual(e1.GetChildMemberWithName("reserved").description, "<nil>") self.expect( 'frame variable e2', substrs=[ '(NSException *) e2 = ', 'name: "ThrownException" - reason: "SomeReason"' ]) self.expect( 'frame variable --dynamic-type no-run-target *e2', substrs=[ '(NSException) *e2 = ', 'name = ', '"ThrownException"', 'reason = ', '"SomeReason"', 'userInfo = ', '1 key/value pair', 'reserved = ', ]) e2 = frame.FindVariable("e2") self.assertTrue(e2) self.assertEqual(e2.type.name, "NSException *") self.assertEqual(e2.GetSummary(), 'name: "ThrownException" - reason: "SomeReason"') self.assertEqual(e2.GetChildMemberWithName("name").description, "ThrownException") self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason") userInfo = e2.GetChildMemberWithName("userInfo").dynamic self.assertEqual(userInfo.summary, "1 key/value pair") self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") reserved = e2.GetChildMemberWithName("reserved").dynamic self.assertGreater(reserved.num_children, 0) callStackReturnAddresses = [reserved.GetChildAtIndex(i).GetChildAtIndex(1) for i in range(0, reserved.GetNumChildren()) if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description == "callStackReturnAddresses"][0].dynamic children = [callStackReturnAddresses.GetChildAtIndex(i) for i in range(0, callStackReturnAddresses.num_children)] pcs = [i.unsigned for i in children] names = [target.ResolveSymbolContextForAddress(lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol).GetSymbol().name for pc in pcs] for n in ["objc_exception_throw", "foo(int)", "main"]: self.assertTrue(n in names, "%s is in the exception backtrace (%s)" % (n, names))
def do_test(self): # The custom swift module cache location swift_mod_cache = self.getBuildArtifact("MCP") # Clear the swift module cache (populated by the Makefile build) shutil.rmtree(swift_mod_cache) self.assertFalse(os.path.isdir(swift_mod_cache), "module cache should not exist") # Update the settings to use the custom module cache location self.runCmd('settings set symbols.clang-modules-cache-path "%s"' % swift_mod_cache) target = self.dbg.CreateTarget(self.getBuildArtifact("main")) self.assertTrue(target, VALID_TARGET) self.registerSharedLibrariesWithTarget(target, ['AA', 'BB', 'CC']) # Set a breakpoint in and launch the main executable lldbutil.run_to_source_breakpoint( self, "break here", lldb.SBFileSpec("main.swift"), exe_name=self.getBuildArtifact("main")) # Check we are able to access the public fields of variables whose # types are from the .swiftinterface-only dylibs var = self.frame().FindVariable("x") lldbutil.check_variable(self, var, False, typename="AA.MyPoint") child_y = var.GetChildMemberWithName("y") # MyPoint.y is public lldbutil.check_variable(self, child_y, False, value="0") child_x = var.GetChildMemberWithName("x") # MyPoint.x isn't public self.assertFalse(child_x.IsValid()) # Expression evaluation using types from the .swiftinterface only # dylibs should work too lldbutil.check_expression( self, self.frame(), "y.magnitudeSquared", "404", use_summary=False) lldbutil.check_expression( self, self.frame(), "MyPoint(x: 1, y: 2).magnitudeSquared", "5", use_summary=False) # Check the swift module cache was populated with the .swiftmodule # files of the loaded modules self.assertTrue(os.path.isdir(swift_mod_cache), "module cache exists") a_modules = glob.glob(os.path.join(swift_mod_cache, 'AA-*.swiftmodule')) b_modules = glob.glob(os.path.join(swift_mod_cache, 'BB-*.swiftmodule')) c_modules = glob.glob(os.path.join(swift_mod_cache, 'CC-*.swiftmodule')) self.assertEqual(len(a_modules), 1) self.assertEqual(len(b_modules), 1) self.assertEqual(len(c_modules), 0) # Update the timestamps of the modules to a time well in the past for file in a_modules + b_modules: make_old(file) # Re-import module A and B self.runCmd("expr import AA") self.runCmd("expr import BB") # Import C for the first time and check we can evaluate expressions # involving types from it self.runCmd("expr import CC") lldbutil.check_expression( self, self.frame(), "Baz.baz()", "23", use_summary=False) # Check we still have a single .swiftmodule in the cache for A and B # and that there is now one for C too a_modules = glob.glob(os.path.join(swift_mod_cache, 'AA-*.swiftmodule')) b_modules = glob.glob(os.path.join(swift_mod_cache, 'BB-*.swiftmodule')) c_modules = glob.glob(os.path.join(swift_mod_cache, 'CC-*.swiftmodule')) self.assertEqual(len(a_modules), 1, "unexpected number of swiftmodules for A.swift") self.assertEqual(len(b_modules), 1, "unexpected number of swiftmodules for B.swift") self.assertEqual(len(c_modules), 1, "unexpected number of swiftmodules for C.swift") # Make sure the .swiftmodule files of A and B were re-used rather than # re-generated when they were re-imported for file in a_modules + b_modules: self.assertTrue(is_old(file), "Swiftmodule file was regenerated rather than reused")
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.cpp")) # void self.assertEqual("", self.getFormatted("void", "1")) # boolean self.assertIn("= false\n", self.getFormatted("boolean", "0")) self.assertIn("= true\n", self.getFormatted("boolean", "1")) self.assertIn("= true\n", self.getFormatted("boolean", "2")) self.assertIn( "= error: unsupported byte size (16) for boolean format\n", self.getFormatted("boolean", "(__uint128_t)0")) # float self.assertIn("= 0\n", self.getFormatted("float", "0")) self.assertIn("= 2\n", self.getFormatted("float", "0x40000000")) self.assertIn("= NaN\n", self.getFormatted("float", "-1")) # Checks the float16 code. self.assertIn("= 2\n", self.getFormatted("float", "(__UINT16_TYPE__)0x4000")) self.assertIn("= error: unsupported byte size (1) for float format\n", self.getFormatted("float", "'a'")) # enumeration self.assertIn("= 0\n", self.getFormatted("enumeration", "0")) self.assertIn("= 1234567\n", self.getFormatted("enumeration", "1234567")) self.assertIn("= -1234567\n", self.getFormatted("enumeration", "-1234567")) # dec self.assertIn("= 1234567\n", self.getFormatted("dec", "1234567")) self.assertIn("= 123456789\n", self.getFormatted("dec", "(__uint128_t)123456789")) # unsigned decimal self.assertIn("= 1234567\n", self.getFormatted("unsigned decimal", "1234567")) self.assertIn("= 4293732729\n", self.getFormatted("unsigned decimal", "-1234567")) self.assertIn( "= 123456789\n", self.getFormatted("unsigned decimal", "(__uint128_t)123456789")) # octal self.assertIn("= 04553207\n", self.getFormatted("octal", "1234567")) self.assertIn( "= 0221505317046536757\n", self.getFormatted("octal", "(__uint128_t)0x123456789ABDEFull")) # complex float self.assertIn( "= error: unsupported byte size (1) for complex float format\n", self.getFormatted("complex float", "'a'")) # complex integer self.assertIn( "= error: unsupported byte size (1) for complex integer format\n", self.getFormatted("complex integer", "'a'")) # hex self.assertIn("= 0x00abc123\n", self.getFormatted("hex", "0xABC123")) self.assertIn( "= 0x000000000000000000123456789abdef\n", self.getFormatted("hex", "(__uint128_t)0x123456789ABDEFull")) # hex float self.assertIn("= 0x1p1\n", self.getFormatted("hex float", "2.0f")) self.assertIn("= 0x1p1\n", self.getFormatted("hex float", "2.0")) # FIXME: long double not supported. self.assertIn( "= error: unsupported byte size (16) for hex float format\n", self.getFormatted("hex float", "2.0l")) # uppercase hex self.assertIn("= 0x00ABC123\n", self.getFormatted("uppercase hex", "0xABC123")) # binary self.assertIn("= 0b00000000000000000000000000000010\n", self.getFormatted("binary", "2")) self.assertIn("= 0b01100001\n", self.getFormatted("binary", "'a'")) self.assertIn(" = 0b10010001101000101011001111000\n", self.getFormatted("binary", "(__uint128_t)0x12345678ll")) # Different character arrays. # FIXME: Passing a 'const char *' will ignore any given format, self.assertIn(r'= " \U0000001b\a\b\f\n\r\t\vaA09\0"', self.getFormatted("character array", "cstring")) self.assertIn(r'= " \U0000001b\a\b\f\n\r\t\vaA09\0"', self.getFormatted("c-string", "cstring")) self.assertIn( ' = " \\e\\a\\b\\f\\n\\r\\t\\vaA09" " \\U0000001b\\a\\b\\f\\n\\r\\t\\vaA09"\n', self.getFormatted("c-string", "(char *)cstring")) self.assertIn('=\n', self.getFormatted("c-string", "(__UINT64_TYPE__)0")) # Build a uint128_t that contains a series of characters in each byte. # First 8 byte of the uint128_t. cstring_chars1 = " \a\b\f\n\r\t\v" # Last 8 byte of the uint128_t. cstring_chars2 = "AZaz09\033\0" # Build a uint128_t value with the hex encoded characters. string_expr = "((__uint128_t)0x" for c in cstring_chars1: string_expr += format(ord(c), "x").zfill(2) string_expr += "ull << 64) | (__uint128_t)0x" for c in cstring_chars2: string_expr += format(ord(c), "x").zfill(2) string_expr += "ull" # Try to print that uint128_t with the different char formatters. self.assertIn('= \\0\\e90zaZA\\v\\t\\r\\n\\f\\b\\a \n', self.getFormatted("character array", string_expr)) self.assertIn('= \\0\\e90zaZA\\v\\t\\r\\n\\f\\b\\a \n', self.getFormatted("character", string_expr)) self.assertIn('= ..90zaZA....... \n', self.getFormatted("printable character", string_expr)) # FIXME: This should probably print the characters in the uint128_t. self.assertIn('= 0x2007080c0a0d090b415a617a30391b00\n', self.getFormatted("unicode8", string_expr)) # OSType ostype_expr = "(__UINT64_TYPE__)0x" for c in cstring_chars1: ostype_expr += format(ord(c), "x").zfill(2) self.assertIn("= ' \\a\\b\\f\\n\\r\\t\\v'\n", self.getFormatted("OSType", ostype_expr)) ostype_expr = "(__UINT64_TYPE__)0x" for c in cstring_chars2: ostype_expr += format(ord(c), "x").zfill(2) self.assertIn("= 'AZaz09\\e\\0'\n", self.getFormatted("OSType", ostype_expr)) self.assertIn('= 0x2007080c0a0d090b415a617a30391b00\n', self.getFormatted("OSType", string_expr)) # bytes self.assertIn(r'= " \U0000001b\a\b\f\n\r\t\vaA09\0"', self.getFormatted("bytes", "cstring")) # bytes with ASCII self.assertIn(r'= " \U0000001b\a\b\f\n\r\t\vaA09\0"', self.getFormatted("bytes with ASCII", "cstring")) # unicode16 self.assertIn('= U+5678 U+1234\n', self.getFormatted("unicode16", "0x12345678")) # unicode32 self.assertIn( '= U+0x89abcdef U+0x01234567\n', self.getFormatted("unicode32", "(__UINT64_TYPE__)0x123456789ABCDEFll")) # address self.assertIn("= 0x00000012\n", self.getFormatted("address", "0x12")) self.assertIn("= 0x00000000\n", self.getFormatted("address", "0")) # Different fixed-width integer type arrays (e.g. 'uint8_t[]'). self.assertIn("= {0xf8 0x56 0x34 0x12}\n", self.getFormatted("uint8_t[]", "0x123456f8")) self.assertIn("= {-8 86 52 18}\n", self.getFormatted("int8_t[]", "0x123456f8")) self.assertIn("= {0x56f8 0x1234}\n", self.getFormatted("uint16_t[]", "0x123456f8")) self.assertIn("= {-2312 4660}\n", self.getFormatted("int16_t[]", "0x1234F6f8")) self.assertIn( "= {0x89abcdef 0x01234567}\n", self.getFormatted("uint32_t[]", "(__UINT64_TYPE__)0x123456789ABCDEFll")) self.assertIn( "= {-1985229329 19088743}\n", self.getFormatted("int32_t[]", "(__UINT64_TYPE__)0x123456789ABCDEFll")) self.assertIn( "= {0x89abcdef 0x01234567 0x00000000 0x00000000}\n", self.getFormatted("uint32_t[]", "__uint128_t i = 0x123456789ABCDEF; i")) self.assertIn( "= {-1985229329 19088743 0 0}\n", self.getFormatted("int32_t[]", "__uint128_t i = 0x123456789ABCDEF; i")) self.assertIn( "= {0x0123456789abcdef 0x0000000000000000}\n", self.getFormatted("uint64_t[]", "__uint128_t i = 0x123456789ABCDEF; i")) self.assertIn( "= {-994074541749903617 0}\n", self.getFormatted("int64_t[]", "__uint128_t i = 0xF23456789ABCDEFFll; i")) # There is not int128_t[] style, so this only tests uint128_t[]. self.assertIn( "= {0x00000000000000000123456789abcdef}\n", self.getFormatted("uint128_t[]", "__uint128_t i = 0x123456789ABCDEF; i")) # Different fixed-width float type arrays. self.assertIn("{2 2}\n", self.getFormatted("float16[]", "0x40004000")) self.assertIn("{2 2}\n", self.getFormatted("float32[]", "0x4000000040000000ll")) self.assertIn( "{2 0}\n", self.getFormatted("float64[]", "__uint128_t i = 0x4000000000000000ll; i")) # Invalid format string self.expect( "expr --format invalid_format_string -- 1", error=True, substrs=[ "error: Invalid format character or name 'invalid_format_string'. Valid values are:" ])
def test_break_in_dlopen_dylib_using_lldbutils(self): self.common_setup() lldbutil.run_to_source_breakpoint(self, "Break here in dylib", self.b_spec, bkpt_module=self.lib_fullname, extra_images = [self.lib_shortname], has_locations_before_run = False)
def run_python_os_step_missing_thread(self, do_prune): """Test that the Python operating system plugin works correctly""" # Our OS plugin does NOT report all threads: result = self.dbg.HandleCommand( "settings set process.experimental.os-plugin-reports-all-threads false" ) python_os_plugin_path = os.path.join(self.getSourceDir(), "operating_system.py") (target, self.process, thread, thread_bkpt) = lldbutil.run_to_source_breakpoint( self, "first stop in thread - do a step out", self.main_file) main_bkpt = target.BreakpointCreateBySourceRegex( 'Stop here and do not make a memory thread for thread_1', self.main_file) self.assertEqual(main_bkpt.GetNumLocations(), 1, "Main breakpoint has one location") # There should not be an os thread before we load the plugin: self.assertFalse(self.get_os_thread().IsValid(), "No OS thread before loading plugin") # Now load the python OS plug-in which should update the thread list and we should have # an OS plug-in thread overlaying thread_1 with id 0x111111111 command = "settings set target.process.python-os-plugin-path '%s'" % python_os_plugin_path self.dbg.HandleCommand(command) # Verify our OS plug-in threads showed up os_thread = self.get_os_thread() self.assertTrue( os_thread.IsValid(), "Make sure we added the thread 0x111111111 after we load the python OS plug-in" ) # Now we are going to step-out. This should get interrupted by main_bkpt. We've # set up the OS plugin so at this stop, we have lost the OS thread 0x111111111. # Make sure both of these are true: os_thread.StepOut() stopped_threads = lldbutil.get_threads_stopped_at_breakpoint( self.process, main_bkpt) self.assertEqual(len(stopped_threads), 1, "Stopped at main_bkpt") thread = self.process.GetThreadByID(0x111111111) self.assertFalse(thread.IsValid(), "No thread 0x111111111 on second stop.") # Make sure we still have the thread plans for this thread: # First, don't show unreported threads, that should fail: command = "thread plan list -t 0x111111111" result = lldb.SBCommandReturnObject() interp = self.dbg.GetCommandInterpreter() interp.HandleCommand(command, result) self.assertFalse(result.Succeeded(), "We found no plans for the unreported thread.") # Now do it again but with the -u flag: command = "thread plan list -u -t 0x111111111" result = lldb.SBCommandReturnObject() interp.HandleCommand(command, result) self.assertTrue(result.Succeeded(), "We found plans for the unreported thread.") if do_prune: # Prune the thread plan and continue, and we will run to exit. interp.HandleCommand("thread plan prune 0x111111111", result) self.assertTrue(result.Succeeded(), "Found the plan for 0x111111111 and pruned it") # List again, make sure it doesn't work: command = "thread plan list -u -t 0x111111111" interp.HandleCommand(command, result) self.assertFalse( result.Succeeded(), "We still found plans for the unreported thread.") self.process.Continue() self.assertEqual(self.process.GetState(), lldb.eStateExited, "We exited.") else: # Now we are going to continue, and when we hit the step-out breakpoint, we will # put the OS plugin thread back, lldb will recover its ThreadPlanStack, and # we will stop with a "step-out" reason. self.process.Continue() os_thread = self.get_os_thread() self.assertTrue(os_thread.IsValid(), "The OS thread is back after continue") self.assertTrue("step out" in os_thread.GetStopDescription(100), "Completed step out plan")
def call_function(self): (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, 'Stop here in main.', self.main_source_spec) # Make sure the SIGCHLD behavior is pass/no-stop/no-notify: return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 0 -p 1 -n 0", return_obj) self.assertTrue(return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop") # The sigchld_no variable should be 0 at this point. self.sigchld_no = target.FindFirstGlobalVariable("sigchld_no") self.assertTrue(self.sigchld_no.IsValid(), "Got a value for sigchld_no") self.start_sigchld_no = self.sigchld_no.GetValueAsSigned(-1) self.assertTrue(self.start_sigchld_no != -1, "Got an actual value for sigchld_no") options = lldb.SBExpressionOptions() # processing 30 signals takes a while, increase the expression timeout # a bit options.SetTimeoutInMicroSeconds(3000000) # 3s options.SetUnwindOnError(True) frame = self.thread.GetFrameAtIndex(0) # Store away the PC to check that the functions unwind to the right # place after calls self.orig_frame_pc = frame.GetPC() num_sigchld = 30 value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Okay, now try with a breakpoint in the called code in the case where # we are ignoring breakpoint hits. handler_bkpt = target.BreakpointCreateBySourceRegex( "Got sigchld %d.", self.main_source_spec) self.assertTrue(handler_bkpt.GetNumLocations() > 0) options.SetIgnoreBreakpoints(True) options.SetUnwindOnError(True) value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Now set the signal to print but not stop and make sure that calling # still works: self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) self.assertTrue(return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop, notify") value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Now set this unwind on error to false, and make sure that we still # complete the call: options.SetUnwindOnError(False) value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Okay, now set UnwindOnError to true, and then make the signal behavior to stop # and see that now we do stop at the signal point: self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 1 -p 1 -n 1", return_obj) self.assertTrue(return_obj.Succeeded(), "Set SIGCHLD to pass, stop, notify") value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success() == False) # Set signal handling back to no-stop, and continue and we should end # up back in out starting frame: self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) self.assertTrue(return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop, notify") error = process.Continue() self.assertTrue(error.Success(), "Continuing after stopping for signal succeeds.") frame = self.thread.GetFrameAtIndex(0) self.assertTrue(frame.GetPC() == self.orig_frame_pc, "Continuing returned to the place we started.")
def test_command_line(self): """Test 'image lookup -t enum_test_days' and check for correct display and enum value printing.""" self.build() lldbutil.run_to_source_breakpoint( self, '// Breakpoint for bitfield', lldb.SBFileSpec("main.c")) self.expect("fr var a", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = A$']) self.expect("fr var b", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = B$']) self.expect("fr var c", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = C$']) self.expect("fr var ab", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = AB$']) self.expect("fr var ac", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = A | C$']) self.expect("fr var all", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = ALL$']) # Test that an enum that doesn't match the heuristic we use in # TypeSystemClang::DumpEnumValue, gets printed as a raw integer. self.expect("fr var omega", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = 7$']) # Test the behavior in case have a variable of a type considered # 'bitfield' by the heuristic, but the value isn't actually fully # covered by the enumerators. self.expect("p (enum bitfield)nonsense", DATA_TYPES_DISPLAYED_CORRECTLY, patterns=[' = B | C | 0x10$']) # Break inside the main. bkpt_id = lldbutil.run_break_set_by_file_and_line( self, "main.c", self.line, num_expected_locations=1, loc_exact=True) self.runCmd("c", RUN_SUCCEEDED) # The stop reason of the thread should be breakpoint. self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) # The breakpoint should have a hit count of 1. self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, substrs=[' resolved, hit count = 1']) # Look up information about the 'enum_test_days' enum type. # Check for correct display. self.expect("image lookup -t enum_test_days", DATA_TYPES_DISPLAYED_CORRECTLY, substrs=['enum enum_test_days {', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'kNumDays', '}']) enum_values = ['-4', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'kNumDays', '5'] # Make sure a pointer to an anonymous enum type does crash LLDB and displays correctly using # frame variable and expression commands self.expect( 'frame variable f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs=[ 'ops *', 'f.op'], patterns=['0x0+$']) self.expect( 'frame variable *f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs=[ 'ops', '*f.op', '<parent is NULL>']) self.expect( 'expr f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs=[ 'ops *', '$'], patterns=['0x0+$']) self.expect( 'expr *f.op', DATA_TYPES_DISPLAYED_CORRECTLY, substrs=['error:'], error=True) bkpt = self.target().FindBreakpointByID(bkpt_id) for enum_value in enum_values: self.expect( "frame variable day", 'check for valid enumeration value', substrs=[enum_value]) lldbutil.continue_to_breakpoint(self.process(), bkpt)
def test_swift_type_lookup(self): """Test the ability to look for type definitions at the command line""" self.build() lldbutil.run_to_source_breakpoint(self, 'break here', lldb.SBFileSpec('main.swift')) # for now, type lookup won't load the AST context, so force load it # before testing self.runCmd("expr 1") # check that basic cases work self.expect("type lookup String", substrs=[ '(struct Swift.String)', 'struct String {', 'extension Swift.String : ' ]) self.expect("type lookup Cla1", substrs=[ '(class a.Cla1)', 'class Cla1 {', 'func bat(_ x: Swift.Int, y: a.Str1) -> Swift.Int' ]) self.expect("type lookup Str1", substrs=[ '(struct a.Str1)', 'struct Str1 {', 'func bar()', 'var b' ]) # Regression test. Ensure "<could not resolve type>" is not output. self.expect("type lookup String", matching=False, substrs=["<could not resolve type>"]) # check that specifiers are honored # self.expect('type lookup class Cla1', substrs=['class Cla1 {']) # self.expect('type lookup struct Cla1', substrs=['class Cla1 {'], matching=False, error=True) # check that modules are honored self.expect("type lookup Swift.String", substrs=['(struct Swift.String)', 'struct String {']) self.expect("type lookup a.String", substrs=['(struct Swift.String)', 'struct String {'], matching=False) # check that a combination of module and specifier is honored # self.expect('type lookup class a.Cla1', substrs=['class Cla1 {']) # self.expect('type lookup class Swift.Cla1', substrs=['class Cla1 {'], matching=False, error=True) # self.expect('type lookup struct a.Cla1', substrs=['class Cla1 {'], matching=False, error=True) # self.expect('type lookup struct Swift.Cla1', substrs=['class Cla1 {'], matching=False, error=True) # check that nested types are looked up correctly self.expect('type lookup Toplevel.Nested.Deeper', substrs=[ 'class a.Toplevel.Nested.Deeper', 'struct a.Toplevel.Nested', 'class a.Toplevel', 'class Deeper', 'func foo' ]) # check that mangled name lookup works self.expect('type lookup _TtSi', substrs=['struct Int', 'extension Swift.Int']) # check that we can look for generic things self.expect('type lookup Generic', substrs=['class Generic', 'foo']) self.expect('type lookup Generic<String>', substrs=[ 'bound_generic_class a.Generic', 'struct Swift.String', 'class Generic', 'func foo' ]) # check that we print comment text (and let you get rid of it) self.expect('type lookup Int', substrs=['Creates a new instance'], matching=False) self.expect('type lookup --show-help -- Int', substrs=['Creates a new instance'], matching=True) self.expect('type lookup foo', substrs=['func foo', 'Int', 'Double'], matching=True, ordered=False) self.expect('type lookup --show-help -- print', substrs=['/// ', 'func print'], matching=True)
def test_sanity(self): self.build() lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec('main.swift')) self.expect("frame var foo", "sanity check", substrs=['(Foo)']) self.expect("expr FromOverlay(i: 23)", error=True)
def test_class_template_specialization(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) self.expect_expr("b.foo()", result_type="int", result_value="1")
def test_process_load(self): self.build() lldbutil.run_to_source_breakpoint(self, '// Break here', lldb.SBFileSpec("main.cpp")) self.complete_from_to('process load Makef', 'process load Makefile')
def test_dsym_swiftinterface(self): """Test that LLDB can import .swiftinterface files inside a .dSYM bundle.""" self.build() self.assertFalse(os.path.isdir(self.getBuildArtifact("AA.dylib.dSYM")), "dylib dsym exists") # The custom swift module cache location swift_mod_cache = self.getBuildArtifact("cache") self.assertTrue( os.path.isfile( self.getBuildArtifact( "a.out.dSYM/Contents/Resources/Swift/x86_64/AA.swiftinterface" )), "dsymutil doesn't support Swift interfaces") # Delete the .swiftinterface form the build dir. os.remove(self.getBuildArtifact("AA.swiftinterface")) # Clear the swift module cache (populated by the Makefile build) shutil.rmtree(swift_mod_cache) import glob self.assertFalse(os.path.isdir(swift_mod_cache), "module cache should not exist") # Update the settings to use the custom module cache location self.runCmd('settings set symbols.clang-modules-cache-path "%s"' % swift_mod_cache) # Set a breakpoint in and launch the main executable lldbutil.run_to_source_breakpoint(self, "break here", lldb.SBFileSpec("main.swift")) # Check we are able to access the public fields of variables whose # types are from the .swiftinterface-only dylibs var = self.frame().FindVariable("x") lldbutil.check_variable(self, var, False, typename="AA.MyPoint") child_y = var.GetChildMemberWithName("y") # MyPoint.y is public lldbutil.check_variable(self, child_y, False, value="0") # MyPoint.x isn't public, but LLDB can find it through type metadata. child_x = var.GetChildMemberWithName("x") self.assertTrue(child_x.IsValid()) # Expression evaluation using types from the .swiftinterface only # dylibs should work too lldbutil.check_expression(self, self.frame(), "y.magnitudeSquared", "404", use_summary=False) lldbutil.check_expression(self, self.frame(), "MyPoint(x: 1, y: 2).magnitudeSquared", "5", use_summary=False) # Check the swift module cache was populated with the .swiftmodule # files of the loaded modules self.assertTrue(os.path.isdir(swift_mod_cache), "module cache exists") a_modules = glob.glob(os.path.join(swift_mod_cache, 'AA-*.swiftmodule')) self.assertEqual(len(a_modules), 1)
def test_bitfields(self): self.build() lldbutil.run_to_source_breakpoint(self, '// break here', lldb.SBFileSpec("main.cpp", False)) # Accessing LargeBitsA. self.expect_expr("lba", result_children=[ ValueCheck(name="", type="int:32"), ValueCheck(name="a", type="unsigned int:20", value="2") ]) self.expect_expr("lba.a", result_type="unsigned int", result_value="2") # Accessing LargeBitsB. self.expect_expr("lbb", result_children=[ ValueCheck(name="a", type="unsigned int:1", value="1"), ValueCheck(name="", type="int:31"), ValueCheck(name="b", type="unsigned int:20", value="3") ]) self.expect_expr("lbb.b", result_type="unsigned int", result_value="3") # Accessing LargeBitsC. self.expect_expr("lbc", result_children=[ ValueCheck(name="", type="int:22"), ValueCheck(name="a", type="unsigned int:1", value="1"), ValueCheck(name="b", type="unsigned int:1", value="0"), ValueCheck(name="c", type="unsigned int:5", value="4"), ValueCheck(name="d", type="unsigned int:1", value="1"), ValueCheck(name="", type="int:2"), ValueCheck(name="e", type="unsigned int:20", value="20"), ]) self.expect_expr("lbc.c", result_type="unsigned int", result_value="4") # Accessing LargeBitsD. self.expect_expr("lbd", result_children=[ ValueCheck(name="arr", type="char[3]", summary='"ab"'), ValueCheck(name="", type="int:32"), ValueCheck(name="a", type="unsigned int:20", value="5") ]) self.expect_expr("lbd.a", result_type="unsigned int", result_value="5") # Test BitfieldsInStructInUnion. # FIXME: This needs some more explanation for what it's actually testing. nested_struct_children = [ ValueCheck(name="", type="int:22"), ValueCheck(name="a", type="uint64_t:1", value="1"), ValueCheck(name="b", type="uint64_t:1", value="0"), ValueCheck(name="c", type="uint64_t:1", value="1"), ValueCheck(name="d", type="uint64_t:1", value="0"), ValueCheck(name="e", type="uint64_t:1", value="1"), ValueCheck(name="f", type="uint64_t:1", value="0"), ValueCheck(name="g", type="uint64_t:1", value="1"), ValueCheck(name="h", type="uint64_t:1", value="0"), ValueCheck(name="i", type="uint64_t:1", value="1"), ValueCheck(name="j", type="uint64_t:1", value="0"), ValueCheck(name="k", type="uint64_t:1", value="1") ] self.expect_expr("bitfields_in_struct_in_union", result_type="BitfieldsInStructInUnion", result_children=[ValueCheck(name="", children=[ ValueCheck(name="f", children=nested_struct_children) ])] ) self.expect_expr("bitfields_in_struct_in_union.f.a", result_type="uint64_t", result_value="1") # Unions with bitfields. self.expect_expr("uwbf", result_type="UnionWithBitfields", result_children=[ ValueCheck(name="a", value="255"), ValueCheck(name="b", value="65535"), ValueCheck(name="c", value="4294967295"), ValueCheck(name="x", value="4294967295") ]) self.expect_expr("uwubf", result_type="UnionWithUnnamedBitfield", result_children=[ ValueCheck(name="a", value="16777215"), ValueCheck(name="x", value="4294967295") ] ) # Class with a base class and a bitfield. self.expect_expr("derived", result_type="Derived", result_children=[ ValueCheck(name="Base", children=[ ValueCheck(name="b_a", value="2", type="uint32_t") ]), ValueCheck(name="d_a", value="1", type="uint32_t:1") ]) # Struct with bool bitfields. self.expect_expr("bb", result_type="", result_children=[ ValueCheck(name="a", value="true", type="bool:1"), ValueCheck(name="b", value="false", type="bool:1"), ValueCheck(name="c", value="true", type="bool:2"), ValueCheck(name="d", value="true", type="bool:2") ]) bb = self.frame().FindVariable('bb') self.assertSuccess(bb.GetError()) bb_a = bb.GetChildAtIndex(0) self.assertSuccess(bb_a.GetError()) self.assertEqual(bb_a.GetValueAsUnsigned(), 1) self.assertEqual(bb_a.GetValueAsSigned(), 1) bb_b = bb.GetChildAtIndex(1) self.assertSuccess(bb_b.GetError()) self.assertEqual(bb_b.GetValueAsUnsigned(), 0) self.assertEqual(bb_b.GetValueAsSigned(), 0) bb_c = bb.GetChildAtIndex(2) self.assertSuccess(bb_c.GetError()) self.assertEqual(bb_c.GetValueAsUnsigned(), 1) self.assertEqual(bb_c.GetValueAsSigned(), 1) bb_d = bb.GetChildAtIndex(3) self.assertSuccess(bb_d.GetError()) self.assertEqual(bb_d.GetValueAsUnsigned(), 1) self.assertEqual(bb_d.GetValueAsSigned(), 1) # Test a class with a base class that has a vtable ptr. The derived # class has bitfields. base_with_vtable_children = [ ValueCheck(name="a", type="unsigned int:4", value="5"), ValueCheck(name="b", type="unsigned int:4", value="0"), ValueCheck(name="c", type="unsigned int:4", value="5") ] self.expect_expr("base_with_vtable", result_children=base_with_vtable_children) self.expect_var_path("base_with_vtable", children=base_with_vtable_children)
def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint( self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False)) # This is the function to remove the custom formats in order to have a # clean slate for the next test case. def cleanup(): self.runCmd('type format clear', check=False) self.runCmd('type summary clear', check=False) self.runCmd('type filter clear', check=False) self.runCmd('type synth clear', check=False) self.runCmd("settings set target.max-children-count 256", check=False) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) ii_type = self.getVariableType("ii") self.assertTrue(ii_type.startswith(self.namespace + "::multiset"), "Type: " + ii_type) self.expect("frame variable ii", substrs=["size=0", "{}"]) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ii", substrs=[ "size=6", "[0] = 0", "[1] = 1", "[2] = 2", "[3] = 3", "[4] = 4", "[5] = 5" ]) lldbutil.continue_to_breakpoint(process, bkpt) self.check_ii("ii") lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ii", substrs=["size=0", "{}"]) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ii", substrs=["size=0", "{}"]) ss_type = self.getVariableType("ss") self.assertTrue(ss_type.startswith(self.namespace + "::multiset"), "Type: " + ss_type) self.expect("frame variable ss", substrs=["size=0", "{}"]) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ss", substrs=[ "size=2", '[0] = "a"', '[1] = "a very long string is right here"' ]) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ss", substrs=[ "size=4", '[2] = "b"', '[3] = "c"', '[0] = "a"', '[1] = "a very long string is right here"' ]) self.expect("p ss", substrs=[ "size=4", '[2] = "b"', '[3] = "c"', '[0] = "a"', '[1] = "a very long string is right here"' ]) self.expect("frame variable ss[2]", substrs=[' = "b"']) lldbutil.continue_to_breakpoint(process, bkpt) self.expect("frame variable ss", substrs=[ "size=3", '[0] = "a"', '[1] = "a very long string is right here"', '[2] = "c"' ])
def test_array_typedef(self): self.build() lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.cpp", False)) self.expect("expr str", substrs=['"abcd"'])
def test_source_and_caret_printing(self): """Test that the source and caret positions LLDB prints are correct""" self.build() (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec) frame = thread.GetFrameAtIndex(0) # Test that source/caret are at the right position. value = frame.EvaluateExpression("unknown_identifier") self.assertFalse(value.GetError().Success()) # We should get a nice diagnostic with a caret pointing at the start of # the identifier. self.assertIn("\nunknown_identifier\n^\n", value.GetError().GetCString()) self.assertIn("<user expression 0>:1:1", value.GetError().GetCString()) # Same as above but with the identifier in the middle. value = frame.EvaluateExpression("1 + unknown_identifier ") self.assertFalse(value.GetError().Success()) self.assertIn("\n1 + unknown_identifier", value.GetError().GetCString()) self.assertIn("\n ^\n", value.GetError().GetCString()) # Multiline expressions. value = frame.EvaluateExpression("int a = 0;\nfoobar +=1;\na") self.assertFalse(value.GetError().Success()) # We should still get the right line information and caret position. self.assertIn("\nfoobar +=1;\n^\n", value.GetError().GetCString()) # It's the second line of the user expression. self.assertIn("<user expression 2>:2:1", value.GetError().GetCString()) # Top-level expressions. top_level_opts = lldb.SBExpressionOptions() top_level_opts.SetTopLevel(True) value = frame.EvaluateExpression("void foo(unknown_type x) {}", top_level_opts) self.assertFalse(value.GetError().Success()) self.assertIn("\nvoid foo(unknown_type x) {}\n ^\n", value.GetError().GetCString()) # Top-level expressions might use a different wrapper code, but the file name should still # be the same. self.assertIn("<user expression 3>:1:10", value.GetError().GetCString()) # Multiline top-level expressions. value = frame.EvaluateExpression("void x() {}\nvoid foo;", top_level_opts) self.assertFalse(value.GetError().Success()) self.assertIn("\nvoid foo;\n ^", value.GetError().GetCString()) self.assertIn("<user expression 4>:2:6", value.GetError().GetCString()) # Test that we render Clang's 'notes' correctly. value = frame.EvaluateExpression( "struct SFoo{}; struct SFoo { int x; };", top_level_opts) self.assertFalse(value.GetError().Success()) self.assertIn( "<user expression 5>:1:8: previous definition is here\nstruct SFoo{}; struct SFoo { int x; };\n ^\n", value.GetError().GetCString()) # Declarations from the debug information currently have no debug information. It's not clear what # we should do in this case, but we should at least not print anything that's wrong. # In the future our declarations should have valid source locations. value = frame.EvaluateExpression("struct FooBar { double x };", top_level_opts) self.assertFalse(value.GetError().Success()) self.assertEqual( "error: <user expression 6>:1:8: redefinition of 'FooBar'\nstruct FooBar { double x };\n ^\n", value.GetError().GetCString()) value = frame.EvaluateExpression("foo(1, 2)") self.assertFalse(value.GetError().Success()) self.assertEqual( "error: <user expression 7>:1:1: no matching function for call to 'foo'\nfoo(1, 2)\n^~~\nnote: candidate function not viable: requires single argument 'x', but 2 arguments were provided\n\n", value.GetError().GetCString()) # Redefine something that we defined in a user-expression. We should use the previous expression file name # for the original decl. value = frame.EvaluateExpression("struct Redef { double x; };", top_level_opts) value = frame.EvaluateExpression("struct Redef { float y; };", top_level_opts) self.assertFalse(value.GetError().Success()) self.assertIn( "error: <user expression 9>:1:8: redefinition of 'Redef'\nstruct Redef { float y; };\n ^\n<user expression 8>:1:8: previous definition is here\nstruct Redef { double x; };\n ^", value.GetError().GetCString())
def test(self): self.build() lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) self.runCmd("settings set target.import-std-module true") vector_type = "std::vector<int>" size_type = vector_type + "::size_type" iterator = vector_type + "::iterator" # LLDB's formatter provides us with a artificial 'item' member. iterator_children = [ValueCheck(name="item")] riterator = vector_type + "::reverse_iterator" riterator_children = [ ValueCheck(name="__t"), ValueCheck(name="current") ] self.expect_expr("a", result_type=vector_type, result_children=[ ValueCheck(value="3"), ValueCheck(value="1"), ValueCheck(value="2") ]) self.expect_expr("a.size()", result_type=size_type, result_value="3") front = self.expect_expr("a.front()", result_value="3") value_type = front.GetDisplayTypeName() self.assertIn( value_type, [ "std::vector<int>::value_type", # Pre-D112976 "std::__vector_base<int, std::allocator<int> >::value_type", # Post-D112976 ]) self.expect_expr("a[1]", result_type=value_type, result_value="1") self.expect_expr("a.back()", result_type=value_type, result_value="2") self.expect("expr std::sort(a.begin(), a.end())") self.expect_expr("a.front()", result_type=value_type, result_value="1") self.expect_expr("a[1]", result_type=value_type, result_value="2") self.expect_expr("a.back()", result_type=value_type, result_value="3") self.expect("expr std::reverse(a.begin(), a.end())") self.expect_expr("a.front()", result_type=value_type, result_value="3") self.expect_expr("a[1]", result_type=value_type, result_value="2") self.expect_expr("a.back()", result_type=value_type, result_value="1") self.expect_expr("a.begin()", result_type=iterator, result_children=iterator_children) self.expect_expr("a.rbegin()", result_type=riterator, result_children=riterator_children) self.expect_expr("*a.begin()", result_type="int", result_value="3") self.expect_expr("*a.rbegin()", result_type="int", result_value="1") self.expect("expr a.pop_back()") self.expect_expr("a.back()", result_type=value_type, result_value="2") self.expect_expr("a.size()", result_type=size_type, result_value="2") self.expect_expr("a.at(0)", result_type=value_type, result_value="3") self.expect("expr a.push_back(4)") self.expect_expr("a.back()", result_type=value_type, result_value="4") self.expect_expr("a.size()", result_type=size_type, result_value="3") self.expect("expr a.emplace_back(5)") self.expect_expr("a.back()", result_type=value_type, result_value="5") self.expect_expr("a.size()", result_type=size_type, result_value="4") self.expect_expr("a", result_children=[ ValueCheck(value="3"), ValueCheck(value="2"), ValueCheck(value="4"), ValueCheck(value="5") ]) # Test that the typedef'd vector type can be substituted. self.expect("expr b.emplace_back(6)") self.expect_expr("b", result_type="vector_long", result_children=[ ValueCheck(value="3"), ValueCheck(value="1"), ValueCheck(value="2"), ValueCheck(value="6"), ])