173 lines · python
1"""2Test lldb-dap stack trace when some of the source paths are missing3"""4 5from lldbsuite.test.lldbtest import line_number6import lldbdap_testcase7from contextlib import contextmanager8import os9 10 11OTHER_C_SOURCE_CODE = """12int no_source_func(int n) {13 return n + 1; // Break here14}15"""16 17 18@contextmanager19def delete_file_on_exit(path):20 try:21 yield path22 finally:23 if os.path.exists(path):24 os.remove(path)25 26 27class TestDAP_stackTraceMissingSourcePath(lldbdap_testcase.DAPTestCaseBase):28 def build_and_run_until_breakpoint(self):29 """30 Build the program and run until the breakpoint is hit, and return the stack frames.31 """32 other_source_file = self.getBuildArtifact("other.c")33 with delete_file_on_exit(other_source_file):34 with open(other_source_file, "w") as f:35 f.write(OTHER_C_SOURCE_CODE)36 37 breakpoint_line = line_number(other_source_file, "// Break here")38 39 program = self.getBuildArtifact("a.out")40 self.build_and_launch(program, commandEscapePrefix="")41 42 breakpoint_ids = self.set_source_breakpoints(43 other_source_file, [breakpoint_line]44 )45 self.assertEqual(46 len(breakpoint_ids), 1, "expect correct number of breakpoints"47 )48 49 self.continue_to_breakpoints(breakpoint_ids)50 51 frames = self.get_stackFrames()52 self.assertLessEqual(2, len(frames), "expect at least 2 frames")53 54 self.assertIn(55 "path",56 frames[0]["source"],57 "Expect source path to always be in frame (other.c)",58 )59 self.assertIn(60 "path",61 frames[1]["source"],62 "Expect source path in always be in frame (main.c)",63 )64 65 return frames66 67 def verify_frames_source(68 self, frames, main_frame_assembly: bool, other_frame_assembly: bool69 ):70 self.assertLessEqual(2, len(frames), "expect at least 2 frames")71 source_0 = frames[0].get("source")72 source_1 = frames[1].get("source")73 self.assertIsNotNone(source_0, "Expects a source object in frame 0")74 self.assertIsNotNone(source_1, "Expects a source object in frame 1")75 76 # it does not always have a path.77 source_0_path: str = source_0.get("path", "")78 source_1_path: str = source_1.get("path", "")79 80 if other_frame_assembly:81 self.assertFalse(82 source_0_path.endswith("other.c"),83 "Expect original source path to not be in unavailable source frame (other.c)",84 )85 self.assertIn(86 "sourceReference",87 source_0,88 "Expect sourceReference to be in unavailable source frame (other.c)",89 )90 else:91 self.assertTrue(92 source_0_path.endswith("other.c"),93 "Expect original source path to be in normal source frame (other.c)",94 )95 self.assertNotIn(96 "sourceReference",97 source_0,98 "Expect sourceReference to not be in normal source frame (other.c)",99 )100 101 if main_frame_assembly:102 self.assertFalse(103 source_1_path.endswith("main.c"),104 "Expect original source path to not be in unavailable source frame (main.c)",105 )106 self.assertIn(107 "sourceReference",108 source_1,109 "Expect sourceReference to be in unavailable source frame (main.c)",110 )111 else:112 self.assertTrue(113 source_1_path.endswith("main.c"),114 "Expect original source path to be in normal source frame (main.c)",115 )116 self.assertNotIn(117 "sourceReference",118 source_1,119 "Expect sourceReference to not be in normal source code frame (main.c)",120 )121 122 def test_stopDisassemblyDisplay(self):123 """124 Test that with with all stop-disassembly-display values you get correct assembly / no assembly source code.125 """126 self.build_and_run_until_breakpoint()127 frames = self.get_stackFrames()128 self.assertLessEqual(2, len(frames), "expect at least 2 frames")129 130 self.assertIn(131 "path",132 frames[0]["source"],133 "Expect source path to always be in frame (other.c)",134 )135 self.assertIn(136 "path",137 frames[1]["source"],138 "Expect source path in always be in frame (main.c)",139 )140 141 self.dap_server.request_evaluate(142 "settings set stop-disassembly-display never", context="repl"143 )144 frames = self.get_stackFrames()145 self.verify_frames_source(146 frames, main_frame_assembly=False, other_frame_assembly=False147 )148 149 self.dap_server.request_evaluate(150 "settings set stop-disassembly-display always", context="repl"151 )152 frames = self.get_stackFrames()153 self.verify_frames_source(154 frames, main_frame_assembly=True, other_frame_assembly=True155 )156 157 self.dap_server.request_evaluate(158 "settings set stop-disassembly-display no-source", context="repl"159 )160 frames = self.get_stackFrames()161 self.verify_frames_source(162 frames, main_frame_assembly=False, other_frame_assembly=True163 )164 165 self.dap_server.request_evaluate(166 "settings set stop-disassembly-display no-debuginfo", context="repl"167 )168 frames = self.get_stackFrames()169 self.verify_frames_source(170 frames, main_frame_assembly=False, other_frame_assembly=False171 )172 self.continue_to_exit()173