xref: /llvm-project/lldb/test/API/functionalities/source-map/TestTargetSourceMap.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
1import lldb
2from lldbsuite.test.lldbtest import *
3from lldbsuite.test.decorators import *
4import json
5import os
6
7
8class TestTargetSourceMap(TestBase):
9    @no_debug_info_test
10    def test_source_map_via_setting_api(self):
11        """
12        Test that ensures SBDebugger::GetSetting("target.source-map") API
13        can correctly fetch source mapping entries.
14        """
15        # Set the target soure map to map "./" to the current test directory
16        src_dir = self.getSourceDir()
17
18        source_map_setting_path = "target.source-map"
19        initial_source_map = self.dbg.GetSetting(source_map_setting_path)
20        self.assertEqual(
21            initial_source_map.GetSize(), 0, "Initial source map should be empty"
22        )
23
24        src_dir = self.getSourceDir()
25        self.runCmd('settings set %s . "%s"' % (source_map_setting_path, src_dir))
26
27        source_map = self.dbg.GetSetting(source_map_setting_path)
28        self.assertEqual(
29            source_map.GetSize(), 1, "source map should be have one appended entry"
30        )
31
32        stream = lldb.SBStream()
33        source_map.GetAsJSON(stream)
34        serialized_source_map = json.loads(stream.GetData())
35
36        self.assertEqual(
37            len(serialized_source_map[0]), 2, "source map entry should have two parts"
38        )
39        self.assertEqual(
40            serialized_source_map[0][0],
41            ".",
42            "source map entry's first part does not match",
43        )
44        self.assertEqual(
45            serialized_source_map[0][1],
46            src_dir,
47            "source map entry's second part does not match",
48        )
49
50    @no_debug_info_test
51    def test_source_map(self):
52        """Test target.source-map' functionality."""
53
54        def assertBreakpointWithSourceMap(src_path):
55            # Set a breakpoint after we remap source and verify that it succeeds
56            bp = target.BreakpointCreateByLocation(src_path, 2)
57            self.assertEqual(
58                bp.GetNumLocations(), 1, "make sure breakpoint was resolved with map"
59            )
60
61            # Now make sure that we can actually FIND the source file using this
62            # remapping:
63            retval = lldb.SBCommandReturnObject()
64            self.dbg.GetCommandInterpreter().HandleCommand(
65                "source list -f main.c -l 2", retval
66            )
67            self.assertTrue(retval.Succeeded(), "source list didn't succeed.")
68            self.assertNotEqual(
69                retval.GetOutput(), None, "We got no ouput from source list"
70            )
71            self.assertIn(
72                "return", retval.GetOutput(), "We didn't find the source file..."
73            )
74
75        # Set the target soure map to map "./" to the current test directory
76        src_dir = self.getSourceDir()
77        src_path = os.path.join(src_dir, "main.c")
78        yaml_path = os.path.join(src_dir, "a.yaml")
79        yaml_base, ext = os.path.splitext(yaml_path)
80        obj_path = self.getBuildArtifact("main.o")
81        self.yaml2obj(yaml_path, obj_path)
82
83        # Create a target with the object file we just created from YAML
84        target = self.dbg.CreateTarget(obj_path)
85
86        # Set a breakpoint before we remap source and verify that it fails
87        bp = target.BreakpointCreateByLocation(src_path, 2)
88        self.assertEqual(
89            bp.GetNumLocations(),
90            0,
91            "make sure no breakpoints were resolved without map",
92        )
93
94        valid_path = os.path.dirname(src_dir)
95        valid_path2 = os.path.dirname(valid_path)
96        invalid_path = src_dir + "invalid_path"
97        invalid_path2 = src_dir + "invalid_path2"
98
99        # We make sure the error message contains all the invalid paths
100        self.expect(
101            'settings set target.source-map . "%s" . "%s" . "%s" . "%s'
102            % (invalid_path, src_dir, invalid_path2, valid_path),
103            substrs=[
104                'error: the replacement path doesn\'t exist: "%s"' % (invalid_path),
105                'the replacement path doesn\'t exist: "%s"' % (invalid_path2),
106            ],
107            error=True,
108        )
109        self.expect(
110            "settings show target.source-map",
111            substrs=[
112                '[0] "." -> "%s"' % (src_dir),
113                '[1] "." -> "%s"' % (valid_path),
114            ],
115        )
116        assertBreakpointWithSourceMap(src_path)
117
118        # Attempts to replace an index to an invalid mapping should have no effect.
119        # Modifications to valid mappings should work.
120        self.expect(
121            'settings replace target.source-map 0 . "%s" . "%s"'
122            % (invalid_path, valid_path2),
123            substrs=[
124                'error: the replacement path doesn\'t exist: "%s"' % (invalid_path),
125            ],
126            error=True,
127        )
128        self.expect(
129            "settings show target.source-map",
130            substrs=[
131                '[0] "." -> "%s"' % (src_dir),
132                '[1] "." -> "%s"' % (valid_path2),
133            ],
134        )
135        assertBreakpointWithSourceMap(src_path)
136
137        # Let's clear and add the mapping back with insert-after
138        self.runCmd("settings remove target.source-map 0")
139        self.expect(
140            "settings show target.source-map",
141            substrs=['[0] "." -> "%s"' % (valid_path2)],
142        )
143
144        self.expect(
145            'settings insert-after target.source-map 0 . "%s" . "%s" . "%s"'
146            % (invalid_path, invalid_path2, src_dir),
147            substrs=[
148                'error: the replacement path doesn\'t exist: "%s"' % (invalid_path),
149                'the replacement path doesn\'t exist: "%s"' % (invalid_path2),
150            ],
151            error=True,
152        )
153        self.expect(
154            "settings show target.source-map",
155            substrs=[
156                '[0] "." -> "%s"' % (valid_path2),
157                '[1] "." -> "%s"' % (src_dir),
158            ],
159        )
160
161        # Let's clear using remove and add the mapping in with append
162        self.runCmd("settings remove target.source-map 1")
163        self.expect(
164            "settings show target.source-map",
165            substrs=[
166                '[0] "." -> "%s"' % (valid_path2),
167            ],
168        )
169        self.runCmd("settings clear target.source-map")
170        self.expect(
171            'settings append target.source-map . "%s" . "%s" . "%s"'
172            % (invalid_path, src_dir, invalid_path2),
173            substrs=[
174                'error: the replacement path doesn\'t exist: "%s"' % (invalid_path),
175                'the replacement path doesn\'t exist: "%s"' % (invalid_path2),
176            ],
177            error=True,
178        )
179        self.expect(
180            "settings show target.source-map",
181            substrs=[
182                '[0] "." -> "%s"' % (src_dir),
183            ],
184        )
185        assertBreakpointWithSourceMap(src_path)
186