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