2 Test that re-running a process from within the same target
3 after rebuilding the a dynamic library flushes the scratch
4 TypeSystems tied to that process.
8 from lldbsuite
.test
.lldbtest
import *
9 from lldbsuite
.test
import lldbutil
10 from lldbsuite
.test
.decorators
import *
15 Check if the host OS is Ubuntu 18.04.
16 Derived from `platform.freedesktop_os_release` in Python 3.10.
18 for path
in ("/etc/os-release", "/usr/lib/os-release"):
19 if os
.path
.exists(path
):
22 if "Ubuntu 18.04" in contents
:
28 class TestRerunExprDylib(TestBase
):
29 @skipTestIfFn(isUbuntu18_04
, bugnumber
="rdar://103831050")
33 Tests whether re-launching a process without destroying
34 the owning target keeps invalid ASTContexts in the
35 scratch AST's importer.
38 1. Evaluating an expression to import 'struct Foo' into
40 2. Change the definition of 'struct Foo' and rebuild the dylib
41 3. Re-launch the process
42 4. Evaluate the same expression in (1). We expect to have only
43 the latest definition of 'struct Foo' in the scratch AST.
47 FULL_DYLIB_NAME
= 'libfoo.dylib' if self
.platformIsDarwin() else 'libfoo.so'
50 self
.build(dictionary
={'DYLIB_CXX_SOURCES':'lib.cpp',
52 'DYLIB_NAME':DYLIB_NAME
,
57 self
.build(dictionary
={'EXE':'a.out',
58 'CXX_SOURCES':'main.cpp',
60 'CXXFLAGS_EXTRAS':f
'-DLIB_NAME=\\"{FULL_DYLIB_NAME}\\"',
63 exe
= self
.getBuildArtifact("a.out")
64 target
= self
.dbg
.CreateTarget(exe
)
65 target
.BreakpointCreateBySourceRegex('dlclose', lldb
.SBFileSpec('main.cpp'))
66 target
.BreakpointCreateBySourceRegex('return', lldb
.SBFileSpec('main.cpp'))
67 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
69 self
.expect_expr('*foo', result_type
='Foo', result_children
=[
70 ValueCheck(name
='m_val', value
='42')
73 # Delete the dylib to force make to rebuild it.
74 remove_file(self
.getBuildArtifact(FULL_DYLIB_NAME
))
76 # Re-build libfoo.dylib
77 self
.build(dictionary
={'DYLIB_CXX_SOURCES':'rebuild.cpp',
79 'DYLIB_NAME':DYLIB_NAME
,
83 # Rerun program within the same target
86 process
= target
.LaunchSimple(None, None, self
.get_process_working_directory())
88 self
.expect_expr('*foo', result_type
='Foo', result_children
=[
89 ValueCheck(name
='Base', children
=[
90 ValueCheck(name
='m_base_val', value
='42')
92 ValueCheck(name
='m_derived_val', value
='137')
95 self
.filecheck("target module dump ast", __file__
)
97 # The new definition 'struct Foo' is in the scratch AST
98 # CHECK: |-CXXRecordDecl {{.*}} struct Foo definition
99 # CHECK: | |-public 'Base'
100 # CHECK-NEXT: | `-FieldDecl {{.*}} m_derived_val 'int'
101 # CHECK-NEXT: `-CXXRecordDecl {{.*}} struct Base definition
102 # CHECK: `-FieldDecl {{.*}} m_base_val 'int'
104 # ...but the original definition of 'struct Foo' is not in the scratch AST anymore
105 # CHECK-NOT: FieldDecl {{.*}} m_val 'int'