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