175 lines · python
1"""2Test the IR interpreter3"""4 5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class IRInterpreterTestCase(TestBase):13 NO_DEBUG_INFO_TESTCASE = True14 15 def time_expression(self, expr, options):16 start = time.time()17 res = self.target.EvaluateExpression(expr, options)18 return res, time.time() - start19 20 def test_interpreter_timeout(self):21 """Test the timeout logic in the IRInterpreter."""22 self.build()23 self.target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))24 self.assertTrue(self.target, VALID_TARGET)25 26 # A non-trivial infinite loop.27 inf_loop = "for (unsigned i = 0; i < 100; ++i) --i; 1"28 timeout_error = "Reached timeout while interpreting expression"29 options = lldb.SBExpressionOptions()30 31 # This is an IRInterpreter specific test, so disable the JIT.32 options.SetAllowJIT(False)33 34 # We use a 500ms timeout.35 options.SetTimeoutInMicroSeconds(500000)36 res, duration_sec = self.time_expression(inf_loop, options)37 self.assertIn(timeout_error, str(res.GetError()))38 39 # Depending on the machine load the expression might take quite some40 # time, so give the time a generous upper bound.41 self.assertLess(duration_sec, 15)42 43 # Try a simple one second timeout.44 options.SetTimeoutInMicroSeconds(1000000)45 res, duration_sec = self.time_expression(inf_loop, options)46 self.assertIn(timeout_error, str(res.GetError()))47 # Anything within 5% of 1s is fine, to account for machine differences.48 self.assertGreaterEqual(duration_sec, 0.95)49 self.assertLess(duration_sec, 30)50 51 def test_interpreter_interrupt(self):52 """Test interrupting the IRInterpreter."""53 self.build()54 self.target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))55 self.assertTrue(self.target, VALID_TARGET)56 57 # A non-trivial infinite loop.58 inf_loop = "for (unsigned i = 0; i < 100; ++i) --i; 1"59 60 options = lldb.SBExpressionOptions()61 62 # This is an IRInterpreter specific test, so disable the JIT.63 options.SetAllowJIT(False)64 65 # Make sure we have a pretty long (10s) timeout so we have a chance to66 # interrupt the interpreted expression.67 options.SetTimeoutInMicroSeconds(10000000)68 69 self.dbg.RequestInterrupt()70 71 self.dbg.SetAsync(True)72 res = self.target.EvaluateExpression(inf_loop, options)73 self.dbg.SetAsync(False)74 75 # Be sure to turn this off again:76 def cleanup():77 if self.dbg.InterruptRequested():78 self.dbg.CancelInterruptRequest()79 80 self.addTearDownHook(cleanup)81 82 interrupt_error = "Interrupted while interpreting expression"83 self.assertIn(interrupt_error, str(res.GetError()))84 85 def setUp(self):86 # Call super's setUp().87 TestBase.setUp(self)88 # Find the line number to break for main.c.89 self.line = line_number("main.c", "// Set breakpoint here")90 91 # Disable confirmation prompt to avoid infinite wait92 self.runCmd("settings set auto-confirm true")93 self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))94 95 def build_and_run(self):96 """Test the IR interpreter"""97 self.build()98 99 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)100 101 lldbutil.run_break_set_by_file_and_line(102 self, "main.c", self.line, num_expected_locations=1, loc_exact=False103 )104 105 self.runCmd("run", RUN_SUCCEEDED)106 107 @expectedFailureAll(108 oslist=["windows"],109 bugnumber="llvm.org/pr21765",110 )111 @add_test_categories(["pyapi"])112 def test_ir_interpreter(self):113 self.build_and_run()114 115 options = lldb.SBExpressionOptions()116 options.SetLanguage(lldb.eLanguageTypeC_plus_plus)117 118 set_up_expressions = [119 "int $i = 9",120 "int $j = 3",121 "int $k = 5",122 "unsigned long long $ull = -1",123 "unsigned $u = -1",124 ]125 126 expressions = [127 "$i + $j",128 "$i - $j",129 "$i * $j",130 "$i / $j",131 "$i % $k",132 "$i << $j",133 "$i & $j",134 "$i | $j",135 "$i ^ $j",136 "($ull & -1) == $u",137 ]138 139 for expression in set_up_expressions:140 self.frame().EvaluateExpression(expression, options)141 142 func_call = "(int)getpid()"143 if lldbplatformutil.getPlatform() == "windows":144 func_call = "(int)GetCurrentProcessId()"145 146 for expression in expressions:147 interp_expression = expression148 jit_expression = func_call + "; " + expression149 150 for expression in expressions:151 interp_expression = expression152 jit_expression = "(int)getpid(); " + expression153 154 interp_result = (155 self.frame()156 .EvaluateExpression(interp_expression, options)157 .GetValueAsSigned()158 )159 jit_result = (160 self.frame()161 .EvaluateExpression(jit_expression, options)162 .GetValueAsSigned()163 )164 165 self.assertEqual(166 interp_result, jit_result, "While evaluating " + expression167 )168 169 def test_type_conversions(self):170 target = self.dbg.GetDummyTarget()171 short_val = target.EvaluateExpression("(short)-1")172 self.assertEqual(short_val.GetValueAsSigned(), -1)173 long_val = target.EvaluateExpression("(long) " + short_val.GetName())174 self.assertEqual(long_val.GetValueAsSigned(), -1)175