1 : // Copyright 2016 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/asan/reporters/breakpad_reporter.h"
16 :
17 : #include "base/bind.h"
18 : #include "gmock/gmock.h"
19 : #include "gtest/gtest.h"
20 :
21 : namespace agent {
22 : namespace asan {
23 : namespace reporters {
24 :
25 : namespace {
26 :
27 : using testing::_;
28 :
29 : class LenientMockBreakpadFunctions {
30 : public:
31 E : LenientMockBreakpadFunctions() {}
32 E : virtual ~LenientMockBreakpadFunctions() {}
33 :
34 E : MOCK_METHOD1(CrashForException, int(EXCEPTION_POINTERS* info));
35 E : MOCK_METHOD2(SetCrashKeyValuePair, void(const char* key,
36 E : const char* value));
37 E : MOCK_METHOD2(SetCrashKeyValueImpl, void(const wchar_t* key,
38 E : const wchar_t* value));
39 : private:
40 : DISALLOW_COPY_AND_ASSIGN(LenientMockBreakpadFunctions);
41 : };
42 : using MockBreakpadFunctions = testing::StrictMock<LenientMockBreakpadFunctions>;
43 :
44 : } // namespace
45 :
46 : class BreakpadReporterTest : public testing::Test {
47 : public:
48 E : BreakpadReporterTest() {}
49 E : virtual ~BreakpadReporterTest() {}
50 :
51 E : void BindCrashForException() {
52 E : breakpad_functions_.crash_for_exception.set_callback(
53 : base::Bind(&MockBreakpadFunctions::CrashForException,
54 : base::Unretained(&mock_)));
55 E : }
56 :
57 E : void BindSetCrashKeyValuePair() {
58 E : breakpad_functions_.set_crash_key_value_pair.set_callback(
59 : base::Bind(&MockBreakpadFunctions::SetCrashKeyValuePair,
60 : base::Unretained(&mock_)));
61 E : }
62 :
63 E : void BindSetCrashKeyValueImpl() {
64 E : breakpad_functions_.set_crash_key_value_impl.set_callback(
65 : base::Bind(&MockBreakpadFunctions::SetCrashKeyValueImpl,
66 : base::Unretained(&mock_)));
67 E : }
68 :
69 : // Binds the normal set of functions.
70 E : void BindNormal() {
71 E : BindCrashForException();
72 E : BindSetCrashKeyValueImpl();
73 E : }
74 :
75 E : void CreateReporter() {
76 E : reporter_.reset(new BreakpadReporter(breakpad_functions_));
77 E : }
78 :
79 : std::unique_ptr<BreakpadReporter> reporter_;
80 : BreakpadReporter::BreakpadFunctions breakpad_functions_;
81 : MockBreakpadFunctions mock_;
82 : };
83 :
84 E : TEST_F(BreakpadReporterTest, CreateFails) {
85 : // This should fail because the unittest executable doesn't satisfy the
86 : // expected exports.
87 E : reporter_ = BreakpadReporter::Create();
88 E : EXPECT_TRUE(reporter_.get() == nullptr);
89 E : }
90 :
91 E : TEST_F(BreakpadReporterTest, AreValid) {
92 : // No functions being set is invalid.
93 E : EXPECT_FALSE(BreakpadReporter::AreValid(breakpad_functions_));
94 :
95 : // Missing CrashForException.
96 E : BindSetCrashKeyValueImpl();
97 E : EXPECT_FALSE(BreakpadReporter::AreValid(breakpad_functions_));
98 :
99 : // One crash key function and CrashForException is valid.
100 E : BindCrashForException();
101 E : EXPECT_TRUE(BreakpadReporter::AreValid(breakpad_functions_));
102 :
103 : // Two crash key functions is invalid.
104 E : BindSetCrashKeyValuePair();
105 E : EXPECT_FALSE(BreakpadReporter::AreValid(breakpad_functions_));
106 :
107 : // One crash key function and CrashForException is valid.
108 E : breakpad_functions_.set_crash_key_value_impl.Reset();
109 E : EXPECT_TRUE(BreakpadReporter::AreValid(breakpad_functions_));
110 :
111 : // Missing CrashForException.
112 E : breakpad_functions_.crash_for_exception.Reset();
113 E : EXPECT_FALSE(BreakpadReporter::AreValid(breakpad_functions_));
114 E : }
115 :
116 E : TEST_F(BreakpadReporterTest, BasicProperties) {
117 E : BindNormal();
118 E : CreateReporter();
119 :
120 E : EXPECT_TRUE(reporter_->GetName() != nullptr);
121 E : EXPECT_EQ(ReporterInterface::FEATURE_CRASH_KEYS, reporter_->GetFeatures());
122 E : }
123 :
124 E : TEST_F(BreakpadReporterTest, SetCrashKeyValuePair) {
125 E : BindCrashForException();
126 E : BindSetCrashKeyValuePair();
127 E : CreateReporter();
128 :
129 E : EXPECT_CALL(mock_, SetCrashKeyValuePair(testing::StrEq("key"),
130 : testing::StrEq("value")));
131 E : EXPECT_TRUE(reporter_->SetCrashKey("key", "value"));
132 E : }
133 :
134 E : TEST_F(BreakpadReporterTest, SetCrashKeyValueImpl) {
135 E : BindCrashForException();
136 E : BindSetCrashKeyValueImpl();
137 E : CreateReporter();
138 :
139 E : EXPECT_CALL(mock_, SetCrashKeyValueImpl(testing::StrEq(L"key"),
140 : testing::StrEq(L"value")));
141 E : EXPECT_TRUE(reporter_->SetCrashKey("key", "value"));
142 E : }
143 :
144 E : TEST_F(BreakpadReporterTest, SetMemoryRangesFails) {
145 E : BindNormal();
146 E : CreateReporter();
147 :
148 E : ReporterInterface::MemoryRanges memory_ranges;
149 E : memory_ranges.push_back(ReporterInterface::MemoryRange(
150 : reinterpret_cast<const char*>(0xBAADCA57), 42));
151 E : EXPECT_FALSE(reporter_->SetMemoryRanges(memory_ranges));
152 E : }
153 :
154 E : TEST_F(BreakpadReporterTest, SetCustomStreamFails) {
155 E : BindNormal();
156 E : CreateReporter();
157 :
158 : // No streams are supported, not even the crashdata protobuf.
159 E : std::string s("hey");
160 E : EXPECT_FALSE(reporter_->SetCustomStream(
161 : ReporterInterface::kCrashdataProtobufStreamType + 1,
162 : reinterpret_cast<const uint8_t*>(s.data()),
163 E : s.size()));
164 E : EXPECT_FALSE(reporter_->SetCustomStream(
165 : ReporterInterface::kCrashdataProtobufStreamType,
166 : reinterpret_cast<const uint8_t*>(s.data()),
167 E : s.size()));
168 E : }
169 :
170 E : TEST_F(BreakpadReporterTest, DumpWithoutCrashFails) {
171 E : BindNormal();
172 E : CreateReporter();
173 :
174 E : CONTEXT dummy_context = {};
175 E : EXPECT_FALSE(reporter_->DumpWithoutCrash(dummy_context));
176 E : }
177 :
178 E : TEST_F(BreakpadReporterTest, DumpAndCrash) {
179 E : BindNormal();
180 E : CreateReporter();
181 :
182 : EXCEPTION_POINTERS* dummy_pointers = reinterpret_cast<EXCEPTION_POINTERS*>(
183 E : 0xBAADF00D);
184 E : EXPECT_CALL(mock_, CrashForException(testing::Eq(dummy_pointers)));
185 E : reporter_->DumpAndCrash(dummy_pointers);
186 E : }
187 :
188 : } // namespace reporters
189 : } // namespace asan
190 : } // namespace agent
|