1""" 2Test C++ virtual function and virtual inheritance. 3""" 4 5import os, time 6import re 7import lldb 8from lldbtest import * 9import lldbutil 10 11def Msg(expr, val): 12 return "'expression %s' matches the output (from compiled code): %s" % (expr, val) 13 14class CppVirtualMadness(TestBase): 15 16 mydir = os.path.join("lang", "cpp", "virtual") 17 18 # This is the pattern by design to match the "my_expr = 'value'" output from 19 # printf() stmts (see main.cpp). 20 pattern = re.compile("^([^=]*) = '([^=]*)'$") 21 22 # Assert message. 23 PRINTF_OUTPUT_GROKKED = "The printf output from compiled code is parsed correctly" 24 25 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 26 def test_virtual_madness_dsym(self): 27 """Test that expression works correctly with virtual inheritance as well as virtual function.""" 28 self.buildDsym() 29 self.virtual_madness_test() 30 31 @expectedFailureFreeBSD('llvm.org/pr16697') # Expression fails with 'there is no JIT compiled function' 32 @expectedFailureIcc('llvm.org/pr16808') # lldb does not call the correct virtual function with icc 33 def test_virtual_madness_dwarf(self): 34 """Test that expression works correctly with virtual inheritance as well as virtual function.""" 35 self.buildDwarf() 36 self.virtual_madness_test() 37 38 def setUp(self): 39 # Call super's setUp(). 40 TestBase.setUp(self) 41 # Find the line number to break for main.cpp. 42 self.line = line_number('main.cpp', '// Set first breakpoint here.') 43 44 def virtual_madness_test(self): 45 """Test that variable expressions with basic types are evaluated correctly.""" 46 47 # First, capture the golden output emitted by the oracle, i.e., the 48 # series of printf statements. 49 go = system("./a.out", sender=self)[0] 50 # This golden list contains a list of "my_expr = 'value' pairs extracted 51 # from the golden output. 52 gl = [] 53 54 # Scan the golden output line by line, looking for the pattern: 55 # 56 # my_expr = 'value' 57 # 58 for line in go.split(os.linesep): 59 match = self.pattern.search(line) 60 if match: 61 my_expr, val = match.group(1), match.group(2) 62 gl.append((my_expr, val)) 63 #print "golden list:", gl 64 65 # Bring the program to the point where we can issue a series of 66 # 'expression' command to compare against the golden output. 67 self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) 68 lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) 69 self.runCmd("run", RUN_SUCCEEDED) 70 71 # Now iterate through the golden list, comparing against the output from 72 # 'expression var'. 73 for my_expr, val in gl: 74 # Don't overwhelm the expression mechanism. 75 # This slows down the test suite quite a bit, to enable it, define 76 # the environment variable LLDB_TYPES_EXPR_TIME_WAIT. For example: 77 # 78 # export LLDB_TYPES_EXPR_TIME_WAIT=0.5 79 # 80 # causes a 0.5 second delay between 'expression' commands. 81 if "LLDB_TYPES_EXPR_TIME_WAIT" in os.environ: 82 time.sleep(float(os.environ["LLDB_TYPES_EXPR_TIME_WAIT"])) 83 84 self.runCmd("expression %s" % my_expr) 85 output = self.res.GetOutput() 86 87 # The expression output must match the oracle. 88 self.expect(output, Msg(my_expr, val), exe=False, 89 substrs = [val]) 90