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/crashpad_reporter.h"
16 :
17 : #include "base/bind.h"
18 : #include "base/strings/stringprintf.h"
19 : #include "gtest/gtest.h"
20 :
21 : namespace agent {
22 : namespace asan {
23 : namespace reporters {
24 :
25 : class CrashpadReporterTest : public testing::Test {
26 : public:
27 E : CrashpadReporterTest() {}
28 E : virtual ~CrashpadReporterTest() {}
29 :
30 E : void CreateReporter() {
31 : // Create a reporter with a dummy CrashpadInfo, and that isn't actually
32 : // connected to a Crashpad server.
33 E : crashpad_info_.reset(new crashpad::CrashpadInfo());
34 E : reporter_.reset(new CrashpadReporter(crashpad_info_.get()));
35 E : }
36 :
37 : const crashpad::CrashpadInfo* crashpad_info() {
38 : return reporter_->crashpad_info_;
39 : }
40 :
41 E : const crashpad::SimpleAddressRangeBag* crash_ranges() {
42 E : return reporter_->crash_ranges_.get();
43 E : }
44 :
45 E : const crashpad::SimpleStringDictionary* crash_keys() {
46 E : return reporter_->crash_keys_.get();
47 E : }
48 :
49 : std::unique_ptr<crashpad::CrashpadInfo> crashpad_info_;
50 : std::unique_ptr<CrashpadReporter> reporter_;
51 : };
52 :
53 E : TEST_F(CrashpadReporterTest, CreateFails) {
54 : // This should fail because the unittest executable doesn't have crashpad
55 : // reporter integration.
56 E : reporter_ = CrashpadReporter::Create();
57 E : EXPECT_TRUE(reporter_.get() == nullptr);
58 E : }
59 :
60 E : TEST_F(CrashpadReporterTest, BasicProperties) {
61 E : CreateReporter();
62 :
63 E : EXPECT_TRUE(reporter_->GetName() != nullptr);
64 E : EXPECT_EQ(ReporterInterface::FEATURE_CRASH_KEYS |
65 : ReporterInterface::FEATURE_EARLY_CRASH_KEYS |
66 : ReporterInterface::FEATURE_MEMORY_RANGES |
67 : ReporterInterface::FEATURE_CUSTOM_STREAMS |
68 : ReporterInterface::FEATURE_DUMP_WITHOUT_CRASH,
69 E : reporter_->GetFeatures());
70 E : }
71 :
72 E : TEST_F(CrashpadReporterTest, SetCrashKey) {
73 E : CreateReporter();
74 E : EXPECT_EQ(0u, crash_keys()->GetCount());
75 :
76 : static const char kKey[] = "key";
77 : static const char kValue[] = "value";
78 E : reporter_->SetCrashKey(kKey, kValue);
79 E : EXPECT_EQ(1u, crash_keys()->GetCount());
80 E : EXPECT_STREQ(kValue, crash_keys()->GetValueForKey(kKey));
81 E : }
82 :
83 E : TEST_F(CrashpadReporterTest, SetCrashKeyFailsWhenFull) {
84 E : CreateReporter();
85 E : EXPECT_EQ(0u, crash_keys()->GetCount());
86 :
87 E : for (size_t i = 0; i < crashpad::SimpleAddressRangeBag::num_entries; ++i) {
88 E : std::string key = base::StringPrintf("key%d", i);
89 E : ASSERT_TRUE(reporter_->SetCrashKey(key.c_str(), key.c_str()));
90 E : ASSERT_EQ(i + 1, crash_keys()->GetCount());
91 E : ASSERT_STREQ(key.c_str(), crash_keys()->GetValueForKey(key.c_str()));
92 E : }
93 :
94 E : EXPECT_FALSE(reporter_->SetCrashKey("hey", "there"));
95 E : }
96 :
97 E : TEST_F(CrashpadReporterTest, SetMemoryRanges) {
98 E : CreateReporter();
99 E : EXPECT_TRUE(crash_ranges() == nullptr);
100 :
101 E : ReporterInterface::MemoryRanges ranges;
102 E : ranges.push_back(ReporterInterface::MemoryRange(
103 : reinterpret_cast<const char*>(0xDEADF00D), 10));
104 E : EXPECT_TRUE(reporter_->SetMemoryRanges(ranges));
105 E : ASSERT_TRUE(crash_ranges() != nullptr);
106 E : EXPECT_EQ(1u, crash_ranges()->GetCount());
107 :
108 E : ranges.push_back(ReporterInterface::MemoryRange(
109 : reinterpret_cast<const char*>(0xBAADBEEF), 20));
110 E : EXPECT_TRUE(reporter_->SetMemoryRanges(ranges));
111 E : ASSERT_TRUE(crash_ranges() != nullptr);
112 E : EXPECT_EQ(2u, crash_ranges()->GetCount());
113 E : }
114 :
115 E : TEST_F(CrashpadReporterTest, SetMemoryRangesFailsWhenTooMany) {
116 E : CreateReporter();
117 E : EXPECT_TRUE(crash_ranges() == nullptr);
118 :
119 E : ReporterInterface::MemoryRanges ranges;
120 E : for (size_t i = 0; i <= crashpad::SimpleAddressRangeBag::num_entries; ++i) {
121 E : const char* addr = reinterpret_cast<const char*>(0xDEADF00D) + 100 * i;
122 E : ranges.push_back(ReporterInterface::MemoryRange(addr, 10));
123 E : }
124 :
125 E : EXPECT_FALSE(reporter_->SetMemoryRanges(ranges));
126 E : ASSERT_TRUE(crash_ranges() != nullptr);
127 E : EXPECT_EQ(crashpad::SimpleAddressRangeBag::num_entries,
128 E : crash_ranges()->GetCount());
129 E : }
130 :
131 : } // namespace reporters
132 : } // namespace asan
133 : } // namespace agent
|