1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/common/stack_capture.h"
16 :
17 : #include "base/memory/scoped_ptr.h"
18 : #include "gtest/gtest.h"
19 : #include "testing/gmock/include/gmock/gmock.h"
20 :
21 : namespace agent {
22 : namespace common {
23 :
24 : namespace {
25 :
26 : using ::testing::_;
27 :
28 : class TestStackCapture : public StackCapture {
29 : public:
30 E : TestStackCapture() {}
31 :
32 E : void set_relative_stack_id(StackId relative_stack_id) {
33 E : relative_stack_id_ = relative_stack_id;
34 E : }
35 :
36 : using StackCapture::ComputeAbsoluteStackId;
37 :
38 E : MOCK_CONST_METHOD0(ComputeRelativeStackId, void(void));
39 : };
40 :
41 : class StackCaptureTest : public testing::Test {
42 : public:
43 E : void SetUp() override {
44 : // Setup the "global" state.
45 E : StackCapture::Init();
46 E : }
47 : };
48 :
49 : } // namespace
50 :
51 E : TEST_F(StackCaptureTest, InitFromBuffer) {
52 E : StackCapture capture;
53 :
54 : // Validate the capture's initial state.
55 E : EXPECT_FALSE(capture.IsValid());
56 E : EXPECT_EQ(0u, capture.absolute_stack_id());
57 E : EXPECT_EQ(0, capture.num_frames());
58 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
59 E : EXPECT_TRUE(capture.frames() != NULL);
60 :
61 : // Create some fake stack trace data.
62 E : void* frames[StackCapture::kMaxNumFrames + 1] = { 0 };
63 E : for (size_t i = 0; i < arraysize(frames); ++i) {
64 E : frames[i] = reinterpret_cast<void*>(i);
65 E : }
66 :
67 : // Initialize the stack capture without using all of the frames.
68 E : capture.InitFromBuffer(frames, 7);
69 E : EXPECT_TRUE(capture.IsValid());
70 E : EXPECT_EQ(0xB986E1F8u, capture.absolute_stack_id());
71 E : EXPECT_EQ(7, capture.num_frames());
72 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
73 E : EXPECT_TRUE(capture.frames() != NULL);
74 :
75 : // Attempt to initialize the stack capture using too many frames; the
76 : // resulting capture should truncate to kMaxNumFrames.
77 E : capture.InitFromBuffer(frames, arraysize(frames));
78 E : EXPECT_TRUE(capture.IsValid());
79 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.num_frames());
80 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
81 E : EXPECT_TRUE(capture.frames() != NULL);
82 E : }
83 :
84 E : TEST_F(StackCaptureTest, InitFromStack) {
85 E : StackCapture capture;
86 :
87 E : EXPECT_FALSE(capture.IsValid());
88 E : EXPECT_EQ(0u, capture.absolute_stack_id());
89 E : EXPECT_EQ(0, capture.num_frames());
90 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
91 :
92 E : capture.InitFromStack();
93 E : EXPECT_TRUE(capture.IsValid());
94 E : EXPECT_LT(0u, capture.num_frames());
95 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
96 E : }
97 :
98 E : TEST_F(StackCaptureTest, InitFromExistingStack) {
99 E : StackCapture capture;
100 E : capture.InitFromStack();
101 E : StackCapture copy;
102 E : copy.InitFromExistingStack(capture);
103 E : EXPECT_TRUE(copy.IsValid());
104 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
105 E : EXPECT_EQ(capture.absolute_stack_id(), copy.absolute_stack_id());
106 E : EXPECT_EQ(capture.num_frames(), copy.num_frames());
107 E : for (size_t i = 0; i < capture.num_frames(); i++)
108 E : EXPECT_EQ(capture.frames()[i], copy.frames()[i]);
109 E : }
110 :
111 E : TEST_F(StackCaptureTest, RestrictedFrameCount) {
112 E : StackCapture::set_bottom_frames_to_skip(0);
113 : // Restrict this to a stack depth that is smaller than the stack depth of
114 : // this test.
115 E : StackCapture capture(5);
116 E : EXPECT_FALSE(capture.IsValid());
117 E : EXPECT_EQ(0u, capture.absolute_stack_id());
118 E : EXPECT_EQ(0, capture.num_frames());
119 E : EXPECT_EQ(5u, capture.max_num_frames());
120 :
121 E : capture.InitFromStack();
122 E : EXPECT_TRUE(capture.IsValid());
123 E : EXPECT_EQ(5u, capture.num_frames());
124 E : EXPECT_EQ(5u, capture.max_num_frames());
125 E : }
126 :
127 E : TEST_F(StackCaptureTest, AbsoluteStackId) {
128 E : TestStackCapture stack_capture;
129 E : stack_capture.InitFromStack();
130 E : auto stack_id = stack_capture.absolute_stack_id();
131 E : stack_capture.ComputeAbsoluteStackId();
132 E : EXPECT_EQ(stack_id, stack_capture.absolute_stack_id());
133 E : }
134 :
135 E : TEST_F(StackCaptureTest, RelativeStackId) {
136 E : TestStackCapture test_stack_capture;
137 :
138 : // Expect one callback when calling relative_stack_id the first time.
139 E : EXPECT_CALL(test_stack_capture, ComputeRelativeStackId());
140 E : EXPECT_EQ(0U, test_stack_capture.relative_stack_id());
141 :
142 : // Needed since ComputeRelativeStackId is mocked and makes sures that we don't
143 : // end up with a valid id that is 0 (which would trigger flakiness).
144 E : test_stack_capture.set_relative_stack_id(123456U);
145 :
146 : // Should not trigger call to ComputeRelativeStackId.
147 E : EXPECT_EQ(123456U, test_stack_capture.relative_stack_id());
148 E : }
149 :
150 : } // namespace common
151 : } // namespace agent
|