1"""Test that the 'add-dsym', aka 'target symbols add', command informs the user about success or failure."""
2
3
4
5import os
6import time
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13@skipUnlessDarwin
14class AddDsymCommandCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17
18    def setUp(self):
19        TestBase.setUp(self)
20        self.template = 'main.cpp.template'
21        self.source = 'main.cpp'
22        self.teardown_hook_added = False
23
24    @no_debug_info_test
25    def test_add_dsym_command_with_error(self):
26        """Test that the 'add-dsym' command informs the user about failures."""
27
28        # Call the program generator to produce main.cpp, version 1.
29        self.generate_main_cpp(version=1)
30        self.build(debug_info="dsym")
31
32        # Insert some delay and then call the program generator to produce
33        # main.cpp, version 2.
34        time.sleep(5)
35        self.generate_main_cpp(version=101)
36        # Now call make again, but this time don't generate the dSYM.
37        self.build(debug_info="dwarf")
38
39        self.exe_name = 'a.out'
40        self.do_add_dsym_with_error(self.exe_name)
41
42    @no_debug_info_test
43    def test_add_dsym_command_with_success(self):
44        """Test that the 'add-dsym' command informs the user about success."""
45
46        # Call the program generator to produce main.cpp, version 1.
47        self.generate_main_cpp(version=1)
48        self.build(debug_info="dsym")
49
50        self.exe_name = 'a.out'
51        self.do_add_dsym_with_success(self.exe_name)
52
53    @no_debug_info_test
54    def test_add_dsym_with_dSYM_bundle(self):
55        """Test that the 'add-dsym' command informs the user about success."""
56
57        # Call the program generator to produce main.cpp, version 1.
58        self.generate_main_cpp(version=1)
59        self.build(debug_info="dsym")
60
61        self.exe_name = 'a.out'
62        self.do_add_dsym_with_dSYM_bundle(self.exe_name)
63
64    def generate_main_cpp(self, version=0):
65        """Generate main.cpp from main.cpp.template."""
66        temp = os.path.join(self.getSourceDir(), self.template)
67        with open(temp, 'r') as f:
68            content = f.read()
69
70        new_content = content.replace(
71            '%ADD_EXTRA_CODE%',
72            'printf("This is version %d\\n");' %
73            version)
74        src = os.path.join(self.getBuildDir(), self.source)
75        with open(src, 'w') as f:
76            f.write(new_content)
77
78        # The main.cpp has been generated, add a teardown hook to remove it.
79        if not self.teardown_hook_added:
80            self.addTearDownHook(lambda: os.remove(src))
81            self.teardown_hook_added = True
82
83    def do_add_dsym_with_error(self, exe_name):
84        """Test that the 'add-dsym' command informs the user about failures."""
85        exe_path = self.getBuildArtifact(exe_name)
86        self.runCmd("file " + exe_path, CURRENT_EXECUTABLE_SET)
87
88        wrong_path = os.path.join(self.getBuildDir(),
89                                  "%s.dSYM" % exe_name, "Contents")
90        self.expect("add-dsym " + wrong_path, error=True,
91                    substrs=['invalid module path'])
92
93        right_path = os.path.join(
94            self.getBuildDir(),
95            "%s.dSYM" %
96            exe_path,
97            "Contents",
98            "Resources",
99            "DWARF",
100            exe_name)
101        self.expect("add-dsym " + right_path, error=True,
102                    substrs=['symbol file', 'does not match'])
103
104    def do_add_dsym_with_success(self, exe_name):
105        """Test that the 'add-dsym' command informs the user about success."""
106        exe_path = self.getBuildArtifact(exe_name)
107        self.runCmd("file " + exe_path, CURRENT_EXECUTABLE_SET)
108
109        # This time, the UUID should match and we expect some feedback from
110        # lldb.
111        right_path = os.path.join(
112            self.getBuildDir(),
113            "%s.dSYM" %
114            exe_path,
115            "Contents",
116            "Resources",
117            "DWARF",
118            exe_name)
119        self.expect("add-dsym " + right_path,
120                    substrs=['symbol file', 'has been added to'])
121
122    def do_add_dsym_with_dSYM_bundle(self, exe_name):
123        """Test that the 'add-dsym' command informs the user about success when loading files in bundles."""
124        exe_path = self.getBuildArtifact(exe_name)
125        self.runCmd("file " + exe_path, CURRENT_EXECUTABLE_SET)
126
127        # This time, the UUID should be found inside the bundle
128        right_path = "%s.dSYM" % exe_path
129        self.expect("add-dsym " + right_path,
130                    substrs=['symbol file', 'has been added to'])
131