Skip to content

Commit 03c73f4

Browse files
committed
Add unit test for realpath + source-map
1 parent 7f6f55f commit 03c73f4

File tree

11 files changed

+161
-0
lines changed

11 files changed

+161
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
C_SOURCES := main.c
2+
3+
include Makefile.rules
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
"""
2+
Test lldb breakpoint with symlinks/realpath and source-map.
3+
"""
4+
5+
6+
import lldb
7+
from lldbsuite.test.decorators import *
8+
from lldbsuite.test.lldbtest import *
9+
from lldbsuite.test import lldbutil, lldbplatformutil
10+
11+
12+
class BreakpointTestCase(TestBase):
13+
NO_DEBUG_INFO_TESTCASE = True
14+
15+
def setUp(self):
16+
# Call super's setUp().
17+
TestBase.setUp(self)
18+
# Find the line number to break inside main().
19+
self.line_in_main = line_number("main.c", "// Set break point at this line.")
20+
self.line_in_foo = line_number("real/foo.h", "// Set break point at this line.")
21+
self.line_in_bar = line_number("real/bar.h", "// Set break point at this line.")
22+
self.line_in_qux = line_number("real/qux.h", "// Set break point at this line.")
23+
# disable "There is a running process, kill it and restart?" prompt
24+
self.runCmd("settings set auto-confirm true")
25+
self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))
26+
27+
def buildAndCreateTarget(self):
28+
self.build()
29+
exe = self.getBuildArtifact("a.out")
30+
31+
# Create a target by the debugger.
32+
target = self.dbg.CreateTarget(exe)
33+
self.assertTrue(target, VALID_TARGET)
34+
35+
# Retrieve the associated command interpreter from our debugger.
36+
ci = self.dbg.GetCommandInterpreter()
37+
self.assertTrue(ci, VALID_COMMAND_INTERPRETER)
38+
return ci
39+
40+
@skipIf(oslist=["windows"])
41+
def test_file_line_breakpoint_realpath(self):
42+
"""Test file/line breakpoint where support files have symlinks."""
43+
ci = self.buildAndCreateTarget()
44+
45+
file_path = self.getBuildArtifact("a.out")
46+
print("DEBUG", file_path)
47+
48+
res = lldb.SBCommandReturnObject()
49+
# ci.HandleCommand(f"b main.c:{self.line_in_main}", res)
50+
# print("DEBUG OUT", res.GetOutput())
51+
# print("DEBUG ERR", res.GetError())
52+
53+
cwd = os.getcwd()
54+
print("DEBUG CWD", cwd)
55+
56+
######################################################################
57+
# Baseline
58+
#---------------------------------------------------------------------
59+
# Breakpoints should be resolved with paths which are in the line-table.
60+
lldbutil.run_break_set_by_file_and_line(
61+
self, "main.c", self.line_in_main, num_expected_locations=1, loc_exact=True
62+
)
63+
lldbutil.run_break_set_by_file_and_line(
64+
self, "symlink1/foo.h", self.line_in_foo, num_expected_locations=1, loc_exact=True
65+
)
66+
lldbutil.run_break_set_by_file_and_line(
67+
self, "symlink2/bar.h", self.line_in_bar, num_expected_locations=1, loc_exact=True
68+
)
69+
lldbutil.run_break_set_by_file_and_line(
70+
self, "symlink2/qux.h", self.line_in_qux, num_expected_locations=1, loc_exact=True
71+
)
72+
73+
######################################################################
74+
# Symlinked file
75+
#---------------------------------------------------------------------
76+
# - `symlink1/foo.h` is a symlink file, pointing at `real/foo.h`
77+
# - main.c includes `symlink1/foo.h`.
78+
# - As a result, the line-table contains a support file `(test_base_dir)/symlink1/foo.h`
79+
# - Setting a breakpoint for `real/foo.h` won't be resolved, because it doesn't match the above path.
80+
# - Setting a realpath prefix to the current working directory will cause the above support file to be realpath'ed to `(test_base_dir)/real/foo.h`
81+
# - Now setting a breakpoint for `real/foo.h` will be resolved.
82+
lldbutil.run_break_set_by_file_and_line(
83+
self, "real/foo.h", self.line_in_foo, num_expected_locations=0, loc_exact=True
84+
)
85+
self.runCmd(f'settings set target.source-realpath-prefixes "{cwd}"')
86+
lldbutil.run_break_set_by_file_and_line(
87+
self, "real/foo.h", self.line_in_foo, num_expected_locations=1, loc_exact=True
88+
)
89+
# Clear settings so that the test below won't be affected.
90+
self.runCmd("settings clear target.source-realpath-prefixes")
91+
92+
######################################################################
93+
# Symlinked directory
94+
#---------------------------------------------------------------------
95+
# - `symlink2` is a symlink directory, pointing at `real`.
96+
# - So, `symlink2/bar.h` will be realpath'ed to `real/bar.h`.
97+
# - main.c includes `symlink2/bar.h`.
98+
# - As a result, the line-table contains a support file `(test_base_dir)/symlink2/bar.h`
99+
# - Setting a breakpoint for `real/bar.h` won't be resolved, because it doesn't match the above path.
100+
# - Setting a realpath prefix to the current working directory will cause the above support file to be realpath'ed to `(test_base_dir)/real/bar.h`
101+
# - Now setting a breakpoint for `real/bar.h` will be resolved.
102+
lldbutil.run_break_set_by_file_and_line(
103+
self, "real/bar.h", self.line_in_foo, num_expected_locations=0, loc_exact=True
104+
)
105+
self.runCmd(f'settings set target.source-realpath-prefixes "{cwd}"')
106+
lldbutil.run_break_set_by_file_and_line(
107+
self, "real/bar.h", self.line_in_foo, num_expected_locations=1, loc_exact=True
108+
)
109+
# Clear settings so that the test below won't be affected.
110+
self.runCmd("settings clear target.source-realpath-prefixes")
111+
112+
######################################################################
113+
# Symlink + source-map
114+
#---------------------------------------------------------------------
115+
# - `symlink2` is a symlink directory, pointing at `real`.
116+
# - So, `symlink2/qux.h` will be realpath'ed to `real/qux.h`.
117+
# - main.c includes `symlink2/qux.h`.
118+
# - As a result, the line-table contains a support file `(test_base_dir)/symlink2/qux.h`
119+
# - Setting a realpath prefix to the current working directory will cause the above support file to be realpath'ed to `(test_base_dir)/real/qux.h`
120+
# - Setting a breakpoint for `to-be-mapped/qux.h` won't be resolved, because it doesn't match the above path.
121+
# - After setting a source-map, setting the same breakpoint will be resolved, because the input path `to-be-mapped/qux.h` is reverse-mapped to `real/qux.h`, which matches the realpath'ed support file.
122+
lldbutil.run_break_set_by_file_and_line(
123+
self, "real/qux.h", self.line_in_foo, num_expected_locations=0, loc_exact=True
124+
)
125+
self.runCmd(f'settings set target.source-realpath-prefixes "{cwd}"')
126+
lldbutil.run_break_set_by_file_and_line(
127+
self, "to-be-mapped/qux.h", self.line_in_foo, num_expected_locations=0, loc_exact=True
128+
)
129+
self.runCmd('settings set target.source-map "real" "to-be-mapped"')
130+
lldbutil.run_break_set_by_file_and_line(
131+
self, "to-be-mapped/qux.h", self.line_in_foo, num_expected_locations=1, loc_exact=True
132+
)
133+
# Clear settings so that the test below won't be affected.
134+
self.runCmd("settings clear target.source-realpath-prefixes")
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "symlink1/foo.h"
2+
#include "symlink2/bar.h"
3+
#include "symlink2/qux.h"
4+
5+
int main (int argc, char const *argv[]) {
6+
int a = foo(); // 1
7+
int b = bar(); // 2
8+
int c = qux(); // 3
9+
return a + b - c; // Set break point at this line.
10+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
int bar() {
2+
return 2; // Set break point at this line.
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
int foo() {
2+
return 1; // Set break point at this line.
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
int qux() {
2+
return 3; // Set break point at this line.
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../real/bar.c
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../real/bar.h
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../real/foo.h
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
real
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is an empty folder just so that `settings set target.source-map "real" "to-be-mapped"` can be run successfully - it requires tha the latter path is valid.

0 commit comments

Comments
 (0)