1"""
2Test lldb-vscode setBreakpoints request
3"""
4
5
6import unittest2
7import vscode
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11import lldbvscode_testcase
12import os
13
14
15class TestVSCode_stackTrace(lldbvscode_testcase.VSCodeTestCaseBase):
16    name_key_path = ['name']
17    source_key_path = ['source', 'path']
18    line_key_path = ['line']
19
20    def verify_stackFrames(self, start_idx, stackFrames):
21        frame_idx = start_idx
22        for stackFrame in stackFrames:
23            # Don't care about frame above main
24            if frame_idx > 20:
25                return
26            self.verify_stackFrame(frame_idx, stackFrame)
27            frame_idx += 1
28
29    def verify_stackFrame(self, frame_idx, stackFrame):
30        frame_name = self.get_dict_value(stackFrame, self.name_key_path)
31        frame_source = self.get_dict_value(stackFrame, self.source_key_path)
32        frame_line = self.get_dict_value(stackFrame, self.line_key_path)
33        if frame_idx == 0:
34            expected_line = self.recurse_end
35            expected_name = 'recurse'
36        elif frame_idx < 20:
37            expected_line = self.recurse_call
38            expected_name = 'recurse'
39        else:
40            expected_line = self.recurse_invocation
41            expected_name = 'main'
42        self.assertEquals(frame_name, expected_name,
43                        'frame #%i name "%s" == "%s"' % (
44                            frame_idx, frame_name, expected_name))
45        self.assertEquals(frame_source, self.source_path,
46                        'frame #%i source "%s" == "%s"' % (
47                            frame_idx, frame_source, self.source_path))
48        self.assertEquals(frame_line, expected_line,
49                        'frame #%i line %i == %i' % (frame_idx, frame_line,
50                                                     expected_line))
51
52    @skipIfWindows
53    @skipIfRemote
54    def test_stackTrace(self):
55        '''
56            Tests the 'stackTrace' packet and all its variants.
57        '''
58        program = self.getBuildArtifact("a.out")
59        self.build_and_launch(program)
60        source = 'main.c'
61        self.source_path = os.path.join(os.getcwd(), source)
62        self.recurse_end = line_number(source, 'recurse end')
63        self.recurse_call = line_number(source, 'recurse call')
64        self.recurse_invocation = line_number(source, 'recurse invocation')
65
66        lines = [self.recurse_end]
67
68        # Set breakpoint at a point of deepest recuusion
69        breakpoint_ids = self.set_source_breakpoints(source, lines)
70        self.assertEquals(len(breakpoint_ids), len(lines),
71                        "expect correct number of breakpoints")
72
73        self.continue_to_breakpoints(breakpoint_ids)
74        startFrame = 0
75        # Verify we get all stack frames with no arguments
76        (stackFrames, totalFrames) = self.get_stackFrames_and_totalFramesCount()
77        frameCount = len(stackFrames)
78        self.assertTrue(frameCount >= 20,
79                        'verify we get at least 20 frames for all frames')
80        self.assertEquals(totalFrames, frameCount,
81                        'verify we get correct value for totalFrames count')
82        self.verify_stackFrames(startFrame, stackFrames)
83
84        # Verify all stack frames by specifying startFrame = 0 and levels not
85        # specified
86        stackFrames = self.get_stackFrames(startFrame=startFrame)
87        self.assertEquals(frameCount, len(stackFrames),
88                        ('verify same number of frames with startFrame=%i') % (
89                            startFrame))
90        self.verify_stackFrames(startFrame, stackFrames)
91
92        # Verify all stack frames by specifying startFrame = 0 and levels = 0
93        levels = 0
94        stackFrames = self.get_stackFrames(startFrame=startFrame,
95                                           levels=levels)
96        self.assertEquals(frameCount, len(stackFrames),
97                        ('verify same number of frames with startFrame=%i and'
98                         ' levels=%i') % (startFrame, levels))
99        self.verify_stackFrames(startFrame, stackFrames)
100
101        # Get only the first stack frame by sepcifying startFrame = 0 and
102        # levels = 1
103        levels = 1
104        stackFrames = self.get_stackFrames(startFrame=startFrame,
105                                           levels=levels)
106        self.assertEquals(levels, len(stackFrames),
107                        ('verify one frame with startFrame=%i and'
108                         ' levels=%i') % (startFrame, levels))
109        self.verify_stackFrames(startFrame, stackFrames)
110
111        # Get only the first 3 stack frames by sepcifying startFrame = 0 and
112        # levels = 3
113        levels = 3
114        stackFrames = self.get_stackFrames(startFrame=startFrame,
115                                           levels=levels)
116        self.assertEquals(levels, len(stackFrames),
117                        ('verify %i frames with startFrame=%i and'
118                         ' levels=%i') % (levels, startFrame, levels))
119        self.verify_stackFrames(startFrame, stackFrames)
120
121        # Get only the first 15 stack frames by sepcifying startFrame = 5 and
122        # levels = 16
123        startFrame = 5
124        levels = 16
125        stackFrames = self.get_stackFrames(startFrame=startFrame,
126                                           levels=levels)
127        self.assertEquals(levels, len(stackFrames),
128                        ('verify %i frames with startFrame=%i and'
129                         ' levels=%i') % (levels, startFrame, levels))
130        self.verify_stackFrames(startFrame, stackFrames)
131
132        # Verify we cap things correctly when we ask for too many frames
133        startFrame = 5
134        levels = 1000
135        (stackFrames, totalFrames) = self.get_stackFrames_and_totalFramesCount(
136                                            startFrame=startFrame,
137                                            levels=levels)
138        self.assertEquals(len(stackFrames), frameCount - startFrame,
139                        ('verify less than 1000 frames with startFrame=%i and'
140                         ' levels=%i') % (startFrame, levels))
141        self.assertEquals(totalFrames, frameCount,
142                        'verify we get correct value for totalFrames count '
143                        'when requested frames not from 0 index')
144        self.verify_stackFrames(startFrame, stackFrames)
145
146        # Verify level=0 works with non-zerp start frame
147        startFrame = 5
148        levels = 0
149        stackFrames = self.get_stackFrames(startFrame=startFrame,
150                                           levels=levels)
151        self.assertEquals(len(stackFrames), frameCount - startFrame,
152                        ('verify less than 1000 frames with startFrame=%i and'
153                         ' levels=%i') % (startFrame, levels))
154        self.verify_stackFrames(startFrame, stackFrames)
155
156        # Verify we get not frames when startFrame is too high
157        startFrame = 1000
158        levels = 1
159        stackFrames = self.get_stackFrames(startFrame=startFrame,
160                                           levels=levels)
161        self.assertEquals(0, len(stackFrames),
162                        'verify zero frames with startFrame out of bounds')
163