xref: /aosp_15_r20/external/cronet/base/debug/crash_logging_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/debug/crash_logging.h"
6 
7 #include <map>
8 #include <memory>
9 #include <sstream>
10 #include <string_view>
11 
12 #include "base/memory/raw_ref.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 using ::testing::ElementsAre;
17 using ::testing::IsEmpty;
18 using ::testing::Pair;
19 
20 namespace base {
21 namespace debug {
22 
23 namespace {
24 
25 class TestCrashKeyImplementation : public CrashKeyImplementation {
26  public:
TestCrashKeyImplementation(std::map<std::string,std::string> & data)27   explicit TestCrashKeyImplementation(std::map<std::string, std::string>& data)
28       : data_(data) {}
29 
30   TestCrashKeyImplementation(const TestCrashKeyImplementation&) = delete;
31   TestCrashKeyImplementation& operator=(const TestCrashKeyImplementation&) =
32       delete;
33 
Allocate(const char * name,CrashKeySize size)34   CrashKeyString* Allocate(const char* name, CrashKeySize size) override {
35     return new CrashKeyString(name, size);
36   }
37 
Set(CrashKeyString * crash_key,std::string_view value)38   void Set(CrashKeyString* crash_key, std::string_view value) override {
39     ASSERT_TRUE(data_->emplace(crash_key->name, value).second);
40   }
41 
Clear(CrashKeyString * crash_key)42   void Clear(CrashKeyString* crash_key) override {
43     ASSERT_EQ(1u, data_->erase(crash_key->name));
44   }
45 
OutputCrashKeysToStream(std::ostream & out)46   void OutputCrashKeysToStream(std::ostream& out) override {
47     out << "Got " << data_->size() << " crash keys.";
48   }
49 
50  private:
51   const raw_ref<std::map<std::string, std::string>> data_;
52 };
53 
54 }  // namespace
55 
56 class CrashLoggingTest : public ::testing::Test {
57  public:
CrashLoggingTest()58   CrashLoggingTest() {
59     SetCrashKeyImplementation(
60         std::make_unique<TestCrashKeyImplementation>(data_));
61   }
62 
~CrashLoggingTest()63   ~CrashLoggingTest() override { SetCrashKeyImplementation(nullptr); }
64 
data() const65   const std::map<std::string, std::string>& data() const { return data_; }
66 
67  private:
68   std::map<std::string, std::string> data_;
69 };
70 
71 // Should not crash.
TEST(UninitializedCrashLoggingTest,Basic)72 TEST(UninitializedCrashLoggingTest, Basic) {
73   static auto* crash_key = AllocateCrashKeyString("test", CrashKeySize::Size32);
74   EXPECT_FALSE(crash_key);
75 
76   SetCrashKeyString(crash_key, "value");
77 
78   ClearCrashKeyString(crash_key);
79 }
80 
TEST_F(CrashLoggingTest,Basic)81 TEST_F(CrashLoggingTest, Basic) {
82   static auto* crash_key = AllocateCrashKeyString("test", CrashKeySize::Size32);
83   EXPECT_TRUE(crash_key);
84   EXPECT_THAT(data(), IsEmpty());
85 
86   SetCrashKeyString(crash_key, "value");
87   EXPECT_THAT(data(), ElementsAre(Pair("test", "value")));
88   std::ostringstream stream;
89   OutputCrashKeysToStream(stream);
90   EXPECT_EQ("Got 1 crash keys.", stream.str());
91 
92   ClearCrashKeyString(crash_key);
93   EXPECT_THAT(data(), IsEmpty());
94   std::ostringstream stream2;
95   OutputCrashKeysToStream(stream2);
96   EXPECT_EQ("Got 0 crash keys.", stream2.str());
97 }
98 
99 // Verify that the macros are properly setting crash keys.
TEST_F(CrashLoggingTest,Macros)100 TEST_F(CrashLoggingTest, Macros) {
101   {
102     SCOPED_CRASH_KEY_BOOL("category", "bool-value", false);
103     EXPECT_THAT(data(), ElementsAre(Pair("category-bool-value", "false")));
104   }
105 
106   {
107     SCOPED_CRASH_KEY_BOOL("category", "bool-value", true);
108     EXPECT_THAT(data(), ElementsAre(Pair("category-bool-value", "true")));
109   }
110 
111   {
112     SCOPED_CRASH_KEY_NUMBER("category", "float-value", 0.5);
113     EXPECT_THAT(data(), ElementsAre(Pair("category-float-value", "0.5")));
114   }
115 
116   {
117     SCOPED_CRASH_KEY_NUMBER("category", "int-value", 1);
118     EXPECT_THAT(data(), ElementsAre(Pair("category-int-value", "1")));
119   }
120 
121   {
122     SCOPED_CRASH_KEY_STRING32("category", "string32-value", "餅");
123     EXPECT_THAT(data(), ElementsAre(Pair("category-string32-value", "餅")));
124   }
125 
126   {
127     SCOPED_CRASH_KEY_STRING64("category", "string64-value", "餅");
128     EXPECT_THAT(data(), ElementsAre(Pair("category-string64-value", "餅")));
129   }
130 
131   {
132     SCOPED_CRASH_KEY_STRING256("category", "string256-value", "餅");
133     EXPECT_THAT(data(), ElementsAre(Pair("category-string256-value", "餅")));
134   }
135 
136   {
137     SCOPED_CRASH_KEY_STRING1024("category", "string1024-value", "餅");
138     EXPECT_THAT(data(), ElementsAre(Pair("category-string1024-value", "餅")));
139   }
140 }
141 
142 // Test that the helper macros properly uniqify the internal variable used for
143 // the scoper.
TEST_F(CrashLoggingTest,MultipleCrashKeysInSameScope)144 TEST_F(CrashLoggingTest, MultipleCrashKeysInSameScope) {
145   SCOPED_CRASH_KEY_BOOL("category", "bool-value", false);
146   SCOPED_CRASH_KEY_NUMBER("category", "int-value", 1);
147 
148   EXPECT_THAT(data(), ElementsAre(Pair("category-bool-value", "false"),
149                                   Pair("category-int-value", "1")));
150 
151   std::ostringstream stream;
152   OutputCrashKeysToStream(stream);
153   EXPECT_EQ("Got 2 crash keys.", stream.str());
154 }
155 
156 }  // namespace debug
157 }  // namespace base
158