1"""
2Test lldb-vscode logpoints feature.
3"""
4
5
6import unittest2
7import vscode
8import shutil
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12import lldbvscode_testcase
13import os
14
15
16class TestVSCode_logpoints(lldbvscode_testcase.VSCodeTestCaseBase):
17
18    def setUp(self):
19        lldbvscode_testcase.VSCodeTestCaseBase.setUp(self)
20
21        self.main_basename = 'main-copy.cpp'
22        self.main_path = os.path.realpath(self.getBuildArtifact(self.main_basename))
23
24    @skipIfWindows
25    @skipIfRemote
26    def test_logmessage_basic(self):
27        '''Tests breakpoint logmessage basic functionality.'''
28        before_loop_line = line_number('main.cpp', '// before loop')
29        loop_line = line_number('main.cpp', '// break loop')
30        after_loop_line = line_number('main.cpp', '// after loop')
31
32        program = self.getBuildArtifact("a.out")
33        self.build_and_launch(program)
34
35        # Set a breakpoint at a line before loop
36        before_loop_breakpoint_ids = self.set_source_breakpoints(
37            self.main_path,
38            [before_loop_line])
39        self.assertEquals(len(before_loop_breakpoint_ids), 1, "expect one breakpoint")
40
41        self.vscode.request_continue()
42
43        # Verify we hit the breakpoint before loop line
44        self.verify_breakpoint_hit(before_loop_breakpoint_ids)
45
46        # Swallow old console output
47        self.get_console()
48
49        # Set two breakpoints:
50        # 1. First at the loop line with logMessage
51        # 2. Second guard breakpoint at a line after loop
52        logMessage_prefix = "This is log message for { -- "
53        # Trailing newline is needed for splitlines()
54        logMessage = logMessage_prefix + "{i + 3}\n"
55        [loop_breakpoint_id, post_loop_breakpoint_id] = self.set_source_breakpoints(
56            self.main_path,
57            [loop_line, after_loop_line],
58            [{'logMessage': logMessage}, {}]
59        )
60
61        # Continue to trigger the breakpoint with log messages
62        self.vscode.request_continue()
63
64        # Verify we hit the breakpoint after loop line
65        self.verify_breakpoint_hit([post_loop_breakpoint_id])
66
67        output = self.get_console()
68        lines = output.splitlines()
69        logMessage_output = []
70        for line in lines:
71            if line.startswith(logMessage_prefix):
72                logMessage_output.append(line)
73
74        # Verify logMessage count
75        loop_count = 10
76        self.assertEqual(len(logMessage_output), loop_count)
77
78        # Verify log message match
79        for idx, logMessage_line in enumerate(logMessage_output):
80            result = idx + 3
81            self.assertEqual(logMessage_line, logMessage_prefix + str(result))
82
83
84    @skipIfWindows
85    @skipIfRemote
86    def test_logmessage_advanced(self):
87        '''Tests breakpoint logmessage functionality for complex expression.'''
88        before_loop_line = line_number('main.cpp', '// before loop')
89        loop_line = line_number('main.cpp', '// break loop')
90        after_loop_line = line_number('main.cpp', '// after loop')
91
92        program = self.getBuildArtifact("a.out")
93        self.build_and_launch(program)
94
95        # Set a breakpoint at a line before loop
96        before_loop_breakpoint_ids = self.set_source_breakpoints(
97            self.main_path,
98            [before_loop_line])
99        self.assertEquals(len(before_loop_breakpoint_ids), 1, "expect one breakpoint")
100
101        self.vscode.request_continue()
102
103        # Verify we hit the breakpoint before loop line
104        self.verify_breakpoint_hit(before_loop_breakpoint_ids)
105
106        # Swallow old console output
107        self.get_console()
108
109        # Set two breakpoints:
110        # 1. First at the loop line with logMessage
111        # 2. Second guard breakpoint at a line after loop
112        logMessage_prefix = "This is log message for { -- "
113        # Trailing newline is needed for splitlines()
114        logMessage = logMessage_prefix + "{int y = 0; if (i % 3 == 0) { y = i + 3;} else {y = i * 3;} y}\n"
115        [loop_breakpoint_id, post_loop_breakpoint_id] = self.set_source_breakpoints(
116            self.main_path,
117            [loop_line, after_loop_line],
118            [{'logMessage': logMessage}, {}]
119        )
120
121        # Continue to trigger the breakpoint with log messages
122        self.vscode.request_continue()
123
124        # Verify we hit the breakpoint after loop line
125        self.verify_breakpoint_hit([post_loop_breakpoint_id])
126
127        output = self.get_console()
128        lines = output.splitlines()
129        logMessage_output = []
130        for line in lines:
131            if line.startswith(logMessage_prefix):
132                logMessage_output.append(line)
133
134        # Verify logMessage count
135        loop_count = 10
136        self.assertEqual(len(logMessage_output), loop_count)
137
138        # Verify log message match
139        for idx, logMessage_line in enumerate(logMessage_output):
140            result = idx + 3 if idx % 3 == 0 else idx * 3
141            self.assertEqual(logMessage_line, logMessage_prefix + str(result))
142