annotation_list_test.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // Copyright 2017 The Crashpad Authors. 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. #include "client/annotation.h"
  15. #include <string>
  16. #include <vector>
  17. #include "base/rand_util.h"
  18. #include "client/crashpad_info.h"
  19. #include "gtest/gtest.h"
  20. #include "util/misc/clock.h"
  21. #include "util/thread/thread.h"
  22. namespace crashpad {
  23. namespace test {
  24. namespace {
  25. TEST(AnnotationListStatic, Register) {
  26. ASSERT_FALSE(AnnotationList::Get());
  27. EXPECT_TRUE(AnnotationList::Register());
  28. EXPECT_TRUE(AnnotationList::Get());
  29. EXPECT_EQ(AnnotationList::Get(), AnnotationList::Register());
  30. // This isn't expected usage of the AnnotationList API, but it is necessary
  31. // for testing.
  32. AnnotationList* list = AnnotationList::Get();
  33. CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
  34. delete list;
  35. EXPECT_FALSE(AnnotationList::Get());
  36. }
  37. class AnnotationList : public testing::Test {
  38. public:
  39. void SetUp() override {
  40. CrashpadInfo::GetCrashpadInfo()->set_annotations_list(&annotations_);
  41. }
  42. void TearDown() override {
  43. CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
  44. }
  45. // NOTE: Annotations should be declared at file-scope, but in order to test
  46. // them, they are declared as part of the test. These members are public so
  47. // they are accessible from global helpers.
  48. crashpad::StringAnnotation<8> one_{"First"};
  49. crashpad::StringAnnotation<256> two_{"Second"};
  50. crashpad::StringAnnotation<101> three_{"First"};
  51. protected:
  52. using AllAnnotations = std::vector<std::pair<std::string, std::string>>;
  53. AllAnnotations CollectAnnotations() {
  54. AllAnnotations annotations;
  55. for (Annotation* curr : annotations_) {
  56. if (!curr->is_set())
  57. continue;
  58. std::string value(static_cast<const char*>(curr->value()), curr->size());
  59. annotations.push_back(std::make_pair(curr->name(), value));
  60. }
  61. return annotations;
  62. }
  63. bool ContainsNameValue(const AllAnnotations& annotations,
  64. const std::string& name,
  65. const std::string& value) {
  66. return std::find(annotations.begin(),
  67. annotations.end(),
  68. std::make_pair(name, value)) != annotations.end();
  69. }
  70. crashpad::AnnotationList annotations_;
  71. };
  72. TEST_F(AnnotationList, SetAndClear) {
  73. one_.Set("this is a value longer than 8 bytes");
  74. AllAnnotations annotations = CollectAnnotations();
  75. EXPECT_EQ(1u, annotations.size());
  76. EXPECT_TRUE(ContainsNameValue(annotations, "First", "this is "));
  77. one_.Clear();
  78. EXPECT_EQ(0u, CollectAnnotations().size());
  79. one_.Set("short");
  80. two_.Set(std::string(500, 'A').data());
  81. annotations = CollectAnnotations();
  82. EXPECT_EQ(2u, annotations.size());
  83. EXPECT_EQ(5u, one_.size());
  84. EXPECT_EQ(256u, two_.size());
  85. EXPECT_TRUE(ContainsNameValue(annotations, "First", "short"));
  86. EXPECT_TRUE(ContainsNameValue(annotations, "Second", std::string(256, 'A')));
  87. }
  88. TEST_F(AnnotationList, DuplicateKeys) {
  89. ASSERT_EQ(0u, CollectAnnotations().size());
  90. one_.Set("1");
  91. three_.Set("2");
  92. AllAnnotations annotations = CollectAnnotations();
  93. EXPECT_EQ(2u, annotations.size());
  94. EXPECT_TRUE(ContainsNameValue(annotations, "First", "1"));
  95. EXPECT_TRUE(ContainsNameValue(annotations, "First", "2"));
  96. one_.Clear();
  97. annotations = CollectAnnotations();
  98. EXPECT_EQ(1u, annotations.size());
  99. }
  100. class RaceThread : public Thread {
  101. public:
  102. explicit RaceThread(test::AnnotationList* test) : Thread(), test_(test) {}
  103. private:
  104. void ThreadMain() override {
  105. for (int i = 0; i <= 50; ++i) {
  106. if (i % 2 == 0) {
  107. test_->three_.Set("three");
  108. test_->two_.Clear();
  109. } else {
  110. test_->three_.Clear();
  111. }
  112. SleepNanoseconds(base::RandInt(1, 1000));
  113. }
  114. }
  115. test::AnnotationList* test_;
  116. };
  117. TEST_F(AnnotationList, MultipleThreads) {
  118. ASSERT_EQ(0u, CollectAnnotations().size());
  119. RaceThread other_thread(this);
  120. other_thread.Start();
  121. for (int i = 0; i <= 50; ++i) {
  122. if (i % 2 == 0) {
  123. one_.Set("one");
  124. two_.Set("two");
  125. } else {
  126. one_.Clear();
  127. }
  128. SleepNanoseconds(base::RandInt(1, 1000));
  129. }
  130. other_thread.Join();
  131. AllAnnotations annotations = CollectAnnotations();
  132. EXPECT_GE(annotations.size(), 2u);
  133. EXPECT_LE(annotations.size(), 3u);
  134. EXPECT_TRUE(ContainsNameValue(annotations, "First", "one"));
  135. EXPECT_TRUE(ContainsNameValue(annotations, "First", "three"));
  136. if (annotations.size() == 3) {
  137. EXPECT_TRUE(ContainsNameValue(annotations, "Second", "two"));
  138. }
  139. }
  140. } // namespace
  141. } // namespace test
  142. } // namespace crashpad