1""" 2Test that re-running a process from within the same target 3after rebuilding the executable flushes the scratch TypeSystems 4tied to that process. 5""" 6 7import lldb 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10from lldbsuite.test.decorators import * 11 12 13class TestRerunExpr(TestBase): 14 # FIXME: on Windows rebuilding the binary isn't enough to unload it 15 # on progrem restart. One will have to try hard to evict 16 # the module from the ModuleList (possibly including a call to 17 # SBDebugger::MemoryPressureDetected. 18 @skipIfWindows 19 def test(self): 20 """ 21 Tests whether re-launching a process without destroying 22 the owning target keeps invalid ASTContexts in the 23 scratch AST's importer. 24 25 We test this by: 26 1. Evaluating an expression to import 'struct Foo' into 27 the scratch AST 28 2. Change the definition of 'struct Foo' and rebuild the executable 29 3. Re-launch the process 30 4. Evaluate the same expression in (1). We expect to have only 31 the latest definition of 'struct Foo' in the scratch AST. 32 """ 33 self.build(dictionary={"CXX_SOURCES": "main.cpp", "EXE": "a.out"}) 34 35 exe = self.getBuildArtifact("a.out") 36 target = self.dbg.CreateTarget(exe) 37 target.BreakpointCreateBySourceRegex("return", lldb.SBFileSpec("rebuild.cpp")) 38 target.BreakpointCreateBySourceRegex("return", lldb.SBFileSpec("main.cpp")) 39 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 40 41 self.expect_expr( 42 "foo", 43 result_type="Foo", 44 result_children=[ValueCheck(name="m_val", value="42")], 45 ) 46 47 # Delete the executable to force make to rebuild it. 48 remove_file(exe) 49 self.build(dictionary={"CXX_SOURCES": "rebuild.cpp", "EXE": "a.out"}) 50 51 # Rerun program within the same target 52 process.Destroy() 53 process = target.LaunchSimple(None, None, self.get_process_working_directory()) 54 55 self.expect_expr( 56 "foo", 57 result_type="Foo", 58 result_children=[ 59 ValueCheck( 60 name="Base", children=[ValueCheck(name="m_base_val", value="42")] 61 ), 62 ValueCheck(name="m_derived_val", value="137"), 63 ], 64 ) 65 66 self.filecheck("target module dump ast", __file__) 67 68 # The new definition 'struct Foo' is in the scratch AST 69 # CHECK: |-CXXRecordDecl {{.*}} struct Foo definition 70 # CHECK: | |-public 'Base' 71 # CHECK-NEXT: | `-FieldDecl {{.*}} m_derived_val 'int' 72 # CHECK-NEXT: `-CXXRecordDecl {{.*}} struct Base definition 73 # CHECK: `-FieldDecl {{.*}} m_base_val 'int' 74 75 # ...but the original definition of 'struct Foo' is not in the scratch AST anymore 76 # CHECK-NOT: FieldDecl {{.*}} m_val 'int' 77