Index: base/trace_event/event_filter_registry_unittest.cc |
diff --git a/base/trace_event/event_filter_registry_unittest.cc b/base/trace_event/event_filter_registry_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6c01571a3f22806fc5ca43f6638cda209d087b96 |
--- /dev/null |
+++ b/base/trace_event/event_filter_registry_unittest.cc |
@@ -0,0 +1,102 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/trace_event/event_filter_registry.h" |
+ |
+#include <string> |
+ |
+#include "base/memory/ptr_util.h" |
+#include "base/trace_event/trace_event_filter.h" |
+#include "base/trace_event/trace_event_filter_test_utils.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace base { |
+namespace trace_event { |
+ |
+class TraceEventFilterRegistryTest : public testing::Test { |
+ public: |
+ void SetUp() override { EventFilterRegistry::ResetForTesting(); } |
+ void TearDown() override { EventFilterRegistry::ResetForTesting(); } |
+ |
+ uint32_t GetActiveFiltersCount() { |
+ uint32_t count = 0; |
+ for (auto it = EventFilterRegistry::GetActiveFilters(); it.IsValid(); |
+ it.MoveNext(), count++) { |
+ } |
+ return count; |
+ } |
+ |
+ EventFilterRegistry::Iterator GetLastActiveFilter() { |
+ EventFilterRegistry::Iterator it = EventFilterRegistry::GetActiveFilters(); |
+ uint32_t count = GetActiveFiltersCount(); |
+ for (uint32_t i = 1; i < count; i++) |
+ it.MoveNext(); |
+ return it; |
+ } |
+}; |
+ |
+TEST_F(TraceEventFilterRegistryTest, RegistrationAndUnregistration) { |
+ // Register one instance of TestEventFilter. |
+ TestEventFilter* filter_ptr = new TestEventFilter(nullptr); |
+ EventFilterRegistry::RegisterFilter(WrapUnique(filter_ptr)); |
+ ASSERT_EQ(1u, GetActiveFiltersCount()); |
+ ASSERT_EQ(0u, GetLastActiveFilter().GetIndex()); |
+ ASSERT_EQ(filter_ptr, &*GetLastActiveFilter()); |
+ |
+ // Register other 3 filters and check that the validity of the Iterator |
+ // chain. |
+ for (uint32_t i = 0; i < 3; i++) { |
+ filter_ptr = new TestEventFilter(nullptr); |
+ EventFilterRegistry::RegisterFilter(WrapUnique(filter_ptr)); |
+ ASSERT_EQ(i + 2, GetActiveFiltersCount()); |
+ ASSERT_EQ(i + 1, GetLastActiveFilter().GetIndex()); |
+ ASSERT_EQ(filter_ptr, &*GetLastActiveFilter()); |
+ } |
+ |
+ EventFilterRegistry::UnregisterAllFilters(); |
+ ASSERT_EQ(0u, GetActiveFiltersCount()); |
+ |
+ for (uint32_t i = 0; i < 3; i++) { |
+ filter_ptr = new TestEventFilter(nullptr); |
+ EventFilterRegistry::RegisterFilter(WrapUnique(filter_ptr)); |
+ ASSERT_EQ(i + 1, GetActiveFiltersCount()); |
+ ASSERT_EQ(i + 4, GetLastActiveFilter().GetIndex()); |
+ ASSERT_EQ(filter_ptr, &*GetLastActiveFilter()); |
+ } |
+} |
+ |
+// Tests that filters are destroyed at some point in the future (i.e. not leaked |
+// forever) but not immediately after unregistration (so that TRACE_EVENT macros |
+// that hit filters being unregistered from another thread don't race on UAF). |
+TEST_F(TraceEventFilterRegistryTest, DeferredDestruction) { |
+ TestEventFilter::HitsCounter hits; |
+ for (uint32_t i = 0; i < 3; i++) |
+ EventFilterRegistry::RegisterFilter(MakeUnique<TestEventFilter>(nullptr)); |
+ |
+ // Check that filters are not destroyed immediately after unregistration. |
+ EventFilterRegistry::UnregisterAllFilters(); |
+ ASSERT_EQ(0u, hits.dtor_hit_count); |
+ |
+ // Register and unregister enough filters to run out of the circular buffer. |
+ for (uint32_t i = 0; i < 256; i++) { |
+ EventFilterRegistry::RegisterFilter(MakeUnique<TestEventFilter>(nullptr)); |
+ EventFilterRegistry::UnregisterAllFilters(); |
+ } |
+ // A non-zero number of filters must have been desotryed at this point. The |
+ // exact number depends on internal implementation details (i.e. kMaxFilter). |
+ const uint32_t num_last_dtor_hits = hits.dtor_hit_count; |
+ ASSERT_GT(num_last_dtor_hits, 0u); |
+ |
+ // Register and unregister other 11 filters. Assuming that we exhausted the |
+ // circular buffer above, at least 11 of the previous filters should be |
+ // destroyed. |
+ for (uint32_t i = 0; i < 11; i++) { |
+ EventFilterRegistry::RegisterFilter(MakeUnique<TestEventFilter>(nullptr)); |
+ EventFilterRegistry::UnregisterAllFilters(); |
+ } |
+ ASSERT_GE(hits.dtor_hit_count - num_last_dtor_hits, 11u); |
+} |
+ |
+} // namespace trace_event |
+} // namespace base |