Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1030)

Side by Side Diff: base/trace_event/trace_category_unittest.cc

Issue 2495173002: tracing: fix races in CategoryRegistry (Closed)
Patch Set: . Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <string.h> 5 #include <string.h>
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/lazy_instance.h"
11 #include "base/synchronization/lock.h"
10 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h" 13 #include "base/threading/thread.h"
12 #include "base/trace_event/category_registry.h" 14 #include "base/trace_event/category_registry.h"
13 #include "base/trace_event/trace_category.h" 15 #include "base/trace_event/trace_category.h"
14 #include "testing/gtest/include/gtest/gtest.h" 16 #include "testing/gtest/include/gtest/gtest.h"
15 17
16 namespace base { 18 namespace base {
17 namespace trace_event { 19 namespace trace_event {
18 20
19 // Static initializers are generally forbidden. However, in the past we ran in 21 // Static initializers are generally forbidden. However, in the past we ran in
20 // the case of some test using tracing in a static initializer. This test checks 22 // the case of some test using tracing in a static initializer. This test checks
21 // That the category registry doesn't rely on static initializers itself and is 23 // That the category registry doesn't rely on static initializers itself and is
22 // functional even if called from another static initializer. 24 // functional even if called from another static initializer.
23 bool Initializer() { 25 bool Initializer() {
24 return CategoryRegistry::kCategoryMetadata && 26 return CategoryRegistry::kCategoryMetadata &&
25 CategoryRegistry::kCategoryMetadata->is_valid(); 27 CategoryRegistry::kCategoryMetadata->is_valid();
26 } 28 }
27 bool g_initializer_check = Initializer(); 29 bool g_initializer_check = Initializer();
28 30
29 class TraceCategoryTest : public testing::Test { 31 class TraceCategoryTest : public testing::Test {
30 public: 32 public:
31 void SetUp() override { CategoryRegistry::Initialize(); } 33 void SetUp() override { CategoryRegistry::Initialize(); }
32 34
33 void TearDown() override { CategoryRegistry::ResetForTesting(); } 35 void TearDown() override { CategoryRegistry::ResetForTesting(); }
34 36
35 static bool GetOrCreateCategoryByName(const char* name, TraceCategory** cat) { 37 static bool GetOrCreateCategoryByName(const char* name, TraceCategory** cat) {
36 return CategoryRegistry::GetOrCreateCategoryByName(name, cat); 38 static LazyInstance<Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
39 bool is_new_cat = false;
40 *cat = CategoryRegistry::GetCategoryByName(name);
41 if (!*cat) {
42 AutoLock lock(g_lock.Get());
43 is_new_cat = CategoryRegistry::GetOrCreateCategoryLocked(
44 name, [](TraceCategory*) {}, cat);
45 }
46 return is_new_cat;
37 }; 47 };
38 48
39 static CategoryRegistry::Range GetAllCategories() { 49 static CategoryRegistry::Range GetAllCategories() {
40 return CategoryRegistry::GetAllCategories(); 50 return CategoryRegistry::GetAllCategories();
41 } 51 }
42 52
43 static void TestRaceThreadMain(WaitableEvent* event) { 53 static void TestRaceThreadMain(WaitableEvent* event) {
44 TraceCategory* cat = nullptr; 54 TraceCategory* cat = nullptr;
45 event->Wait(); 55 event->Wait();
46 GetOrCreateCategoryByName("__test_race", &cat); 56 GetOrCreateCategoryByName("__test_race", &cat);
47 EXPECT_NE(nullptr, cat); 57 EXPECT_NE(nullptr, cat);
48 } 58 }
49 }; 59 };
50 60
51 TEST_F(TraceCategoryTest, Basic) { 61 TEST_F(TraceCategoryTest, Basic) {
52 ASSERT_NE(nullptr, CategoryRegistry::kCategoryMetadata); 62 ASSERT_NE(nullptr, CategoryRegistry::kCategoryMetadata);
53 ASSERT_TRUE(CategoryRegistry::kCategoryMetadata->is_valid()); 63 ASSERT_TRUE(CategoryRegistry::kCategoryMetadata->is_valid());
54 ASSERT_FALSE(CategoryRegistry::kCategoryMetadata->is_enabled()); 64 ASSERT_FALSE(CategoryRegistry::kCategoryMetadata->is_enabled());
55 65
56 // Metadata category is built-in and should create a new category. 66 // Metadata category is built-in and should create a new category.
57 TraceCategory* cat_meta = nullptr; 67 TraceCategory* cat_meta = nullptr;
58 const char* kMetadataName = CategoryRegistry::kCategoryMetadata->name(); 68 const char* kMetadataName = CategoryRegistry::kCategoryMetadata->name();
59 ASSERT_FALSE(GetOrCreateCategoryByName(kMetadataName, &cat_meta)); 69 ASSERT_FALSE(GetOrCreateCategoryByName(kMetadataName, &cat_meta));
60 ASSERT_EQ(CategoryRegistry::kCategoryMetadata, cat_meta); 70 ASSERT_EQ(CategoryRegistry::kCategoryMetadata, cat_meta);
61 71
62 TraceCategory* cat_1 = nullptr; 72 TraceCategory* cat_1 = nullptr;
63 ASSERT_TRUE(GetOrCreateCategoryByName("__test_ab", &cat_1)); 73 ASSERT_TRUE(GetOrCreateCategoryByName("__test_basic_ab", &cat_1));
64 ASSERT_FALSE(cat_1->is_enabled()); 74 ASSERT_FALSE(cat_1->is_enabled());
65 ASSERT_EQ(0u, cat_1->enabled_filters()); 75 ASSERT_EQ(0u, cat_1->enabled_filters());
66 cat_1->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING); 76 cat_1->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING);
67 cat_1->set_state_flag(TraceCategory::ENABLED_FOR_FILTERING); 77 cat_1->set_state_flag(TraceCategory::ENABLED_FOR_FILTERING);
68 ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING | 78 ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING |
69 TraceCategory::ENABLED_FOR_FILTERING, 79 TraceCategory::ENABLED_FOR_FILTERING,
70 cat_1->state()); 80 cat_1->state());
71 81
72 cat_1->set_enabled_filters(129); 82 cat_1->set_enabled_filters(129);
73 ASSERT_EQ(129u, cat_1->enabled_filters()); 83 ASSERT_EQ(129u, cat_1->enabled_filters());
74 ASSERT_EQ(cat_1, CategoryRegistry::GetCategoryByStatePtr(cat_1->state_ptr())); 84 ASSERT_EQ(cat_1, CategoryRegistry::GetCategoryByStatePtr(cat_1->state_ptr()));
75 85
76 cat_1->clear_state_flag(TraceCategory::ENABLED_FOR_FILTERING); 86 cat_1->clear_state_flag(TraceCategory::ENABLED_FOR_FILTERING);
77 ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, cat_1->state()); 87 ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, cat_1->state());
78 ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, *cat_1->state_ptr()); 88 ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, *cat_1->state_ptr());
79 ASSERT_TRUE(cat_1->is_enabled()); 89 ASSERT_TRUE(cat_1->is_enabled());
80 90
81 TraceCategory* cat_2 = nullptr; 91 TraceCategory* cat_2 = nullptr;
82 ASSERT_TRUE(GetOrCreateCategoryByName("__test_a", &cat_2)); 92 ASSERT_TRUE(GetOrCreateCategoryByName("__test_basic_a", &cat_2));
83 ASSERT_FALSE(cat_2->is_enabled()); 93 ASSERT_FALSE(cat_2->is_enabled());
84 cat_2->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING); 94 cat_2->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING);
85 95
86 TraceCategory* cat_2_copy = nullptr; 96 TraceCategory* cat_2_copy = nullptr;
87 ASSERT_FALSE(GetOrCreateCategoryByName("__test_a", &cat_2_copy)); 97 ASSERT_FALSE(GetOrCreateCategoryByName("__test_basic_a", &cat_2_copy));
88 ASSERT_EQ(cat_2, cat_2_copy); 98 ASSERT_EQ(cat_2, cat_2_copy);
89 99
90 TraceCategory* cat_3 = nullptr; 100 TraceCategory* cat_3 = nullptr;
91 ASSERT_TRUE(GetOrCreateCategoryByName("__test_ab,__test_a", &cat_3)); 101 ASSERT_TRUE(
102 GetOrCreateCategoryByName("__test_basic_ab,__test_basic_a", &cat_3));
92 ASSERT_FALSE(cat_3->is_enabled()); 103 ASSERT_FALSE(cat_3->is_enabled());
93 ASSERT_EQ(0u, cat_3->enabled_filters()); 104 ASSERT_EQ(0u, cat_3->enabled_filters());
94 105
95 int num_test_categories_seen = 0; 106 int num_test_categories_seen = 0;
96 for (const TraceCategory& cat : GetAllCategories()) { 107 for (const TraceCategory& cat : GetAllCategories()) {
97 if (strcmp(cat.name(), kMetadataName) == 0) 108 if (strcmp(cat.name(), kMetadataName) == 0)
98 ASSERT_TRUE(CategoryRegistry::IsBuiltinCategory(&cat)); 109 ASSERT_TRUE(CategoryRegistry::IsBuiltinCategory(&cat));
99 110
100 if (strncmp(cat.name(), "__test", 6) == 0) { 111 if (strncmp(cat.name(), "__test_basic_", 13) == 0) {
101 ASSERT_FALSE(CategoryRegistry::IsBuiltinCategory(&cat)); 112 ASSERT_FALSE(CategoryRegistry::IsBuiltinCategory(&cat));
102 num_test_categories_seen++; 113 num_test_categories_seen++;
103 } 114 }
104 } 115 }
105 ASSERT_EQ(3, num_test_categories_seen); 116 ASSERT_EQ(3, num_test_categories_seen);
106 ASSERT_TRUE(g_initializer_check); 117 ASSERT_TRUE(g_initializer_check);
107 } 118 }
108 119
109 // Tries to cover the case of multiple threads creating the same category 120 // Tries to cover the case of multiple threads creating the same category
110 // simultaeously. Should never end up with distinct entries with the same name. 121 // simultaeously. Should never end up with distinct entries with the same name.
(...skipping 17 matching lines...) Expand all
128 int num_times_seen = 0; 139 int num_times_seen = 0;
129 for (const TraceCategory& cat : GetAllCategories()) { 140 for (const TraceCategory& cat : GetAllCategories()) {
130 if (strcmp(cat.name(), "__test_race") == 0) 141 if (strcmp(cat.name(), "__test_race") == 0)
131 num_times_seen++; 142 num_times_seen++;
132 } 143 }
133 ASSERT_EQ(1, num_times_seen); 144 ASSERT_EQ(1, num_times_seen);
134 } 145 }
135 146
136 } // namespace trace_event 147 } // namespace trace_event
137 } // namespace base 148 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698