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 <memory>
18 :
19 : #include "gtest/gtest.h"
20 : #include "testing/gmock/include/gmock/gmock.h"
21 :
22 : namespace agent {
23 : namespace common {
24 :
25 : namespace {
26 :
27 : using ::testing::_;
28 :
29 : class TestStackCapture : public StackCapture {
30 : public:
31 E : TestStackCapture() {}
32 :
33 E : void set_relative_stack_id(StackId relative_stack_id) {
34 E : relative_stack_id_ = relative_stack_id;
35 E : }
36 :
37 : using StackCapture::ComputeAbsoluteStackId;
38 :
39 E : MOCK_CONST_METHOD0(ComputeRelativeStackId, void(void));
40 : };
41 :
42 : class StackCaptureTest : public testing::Test {
43 : public:
44 E : void SetUp() override {
45 : // Setup the "global" state.
46 E : StackCapture::Init();
47 E : }
48 : };
49 :
50 : } // namespace
51 :
52 E : TEST_F(StackCaptureTest, InitFromBuffer) {
53 E : StackCapture capture;
54 :
55 : // Validate the capture's initial state.
56 E : EXPECT_FALSE(capture.IsValid());
57 E : EXPECT_EQ(0u, capture.absolute_stack_id());
58 E : EXPECT_EQ(0, capture.num_frames());
59 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
60 E : EXPECT_TRUE(capture.frames() != NULL);
61 :
62 : // Create some fake stack trace data.
63 E : void* frames[StackCapture::kMaxNumFrames + 1] = { 0 };
64 E : for (size_t i = 0; i < arraysize(frames); ++i) {
65 E : frames[i] = reinterpret_cast<void*>(i);
66 E : }
67 :
68 : // Initialize the stack capture without using all of the frames.
69 E : capture.InitFromBuffer(frames, 7);
70 E : EXPECT_TRUE(capture.IsValid());
71 E : EXPECT_EQ(0xB986E1F8u, capture.absolute_stack_id());
72 E : EXPECT_EQ(7, capture.num_frames());
73 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
74 E : EXPECT_TRUE(capture.frames() != NULL);
75 :
76 : // Attempt to initialize the stack capture using too many frames; the
77 : // resulting capture should truncate to kMaxNumFrames.
78 E : capture.InitFromBuffer(frames, arraysize(frames));
79 E : EXPECT_TRUE(capture.IsValid());
80 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.num_frames());
81 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
82 E : EXPECT_TRUE(capture.frames() != NULL);
83 E : }
84 :
85 E : TEST_F(StackCaptureTest, InitFromStack) {
86 E : StackCapture capture;
87 :
88 E : EXPECT_FALSE(capture.IsValid());
89 E : EXPECT_EQ(0u, capture.absolute_stack_id());
90 E : EXPECT_EQ(0, capture.num_frames());
91 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
92 :
93 E : capture.InitFromStack();
94 E : EXPECT_TRUE(capture.IsValid());
95 E : EXPECT_LT(0u, capture.num_frames());
96 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
97 E : }
98 :
99 E : TEST_F(StackCaptureTest, InitFromExistingStack) {
100 E : StackCapture capture;
101 E : capture.InitFromStack();
102 E : StackCapture copy;
103 E : copy.InitFromExistingStack(capture);
104 E : EXPECT_TRUE(copy.IsValid());
105 E : EXPECT_EQ(StackCapture::kMaxNumFrames, capture.max_num_frames());
106 E : EXPECT_EQ(capture.absolute_stack_id(), copy.absolute_stack_id());
107 E : EXPECT_EQ(capture.num_frames(), copy.num_frames());
108 E : for (size_t i = 0; i < capture.num_frames(); i++)
109 E : EXPECT_EQ(capture.frames()[i], copy.frames()[i]);
110 E : }
111 :
112 E : TEST_F(StackCaptureTest, RestrictedFrameCount) {
113 E : StackCapture::set_bottom_frames_to_skip(0);
114 : // Restrict this to a stack depth that is smaller than the stack depth of
115 : // this test.
116 E : StackCapture capture(5);
117 E : EXPECT_FALSE(capture.IsValid());
118 E : EXPECT_EQ(0u, capture.absolute_stack_id());
119 E : EXPECT_EQ(0, capture.num_frames());
120 E : EXPECT_EQ(5u, capture.max_num_frames());
121 :
122 E : capture.InitFromStack();
123 E : EXPECT_TRUE(capture.IsValid());
124 E : EXPECT_EQ(5u, capture.num_frames());
125 E : EXPECT_EQ(5u, capture.max_num_frames());
126 E : }
127 :
128 E : TEST_F(StackCaptureTest, AbsoluteStackId) {
129 E : TestStackCapture stack_capture;
130 E : stack_capture.InitFromStack();
131 E : auto stack_id = stack_capture.absolute_stack_id();
132 E : stack_capture.ComputeAbsoluteStackId();
133 E : EXPECT_EQ(stack_id, stack_capture.absolute_stack_id());
134 E : }
135 :
136 E : TEST_F(StackCaptureTest, RelativeStackId) {
137 E : TestStackCapture test_stack_capture;
138 :
139 : // Expect one callback when calling relative_stack_id the first time.
140 E : EXPECT_CALL(test_stack_capture, ComputeRelativeStackId());
141 E : EXPECT_EQ(0U, test_stack_capture.relative_stack_id());
142 :
143 : // Needed since ComputeRelativeStackId is mocked and makes sures that we don't
144 : // end up with a valid id that is 0 (which would trigger flakiness).
145 E : test_stack_capture.set_relative_stack_id(123456U);
146 :
147 : // Should not trigger call to ComputeRelativeStackId.
148 E : EXPECT_EQ(123456U, test_stack_capture.relative_stack_id());
149 E : }
150 :
151 : } // namespace common
152 : } // namespace agent
|