Index: base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc |
diff --git a/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc b/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc |
index b2e681ab26de025f0060e19ea4a2b16b2469c106..e027369d0768961f91db64e852f942a420a67529 100644 |
--- a/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc |
+++ b/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc |
@@ -2,11 +2,14 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
+ |
#include <memory> |
#include <string> |
-#include "base/json/json_reader.h" |
-#include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/trace_event/heap_profiler_string_deduplicator.h" |
+#include "base/trace_event/trace_event_argument.h" |
#include "base/values.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -15,13 +18,6 @@ namespace trace_event { |
namespace { |
-// Define all strings once, because the deduplicator requires pointer equality, |
-// and string interning is unreliable. |
-const char kInt[] = "int"; |
-const char kBool[] = "bool"; |
-const char kString[] = "string"; |
-const char kNeedsEscape[] = "\"quotes\""; |
- |
#if defined(OS_POSIX) |
const char kTaskFileName[] = "../../base/trace_event/trace_log.cc"; |
const char kTaskPath[] = "base/trace_event"; |
@@ -30,36 +26,72 @@ const char kTaskFileName[] = "..\\..\\base\\memory\\memory_win.cc"; |
const char kTaskPath[] = "base\\memory"; |
#endif |
-std::unique_ptr<Value> DumpAndReadBack( |
- const TypeNameDeduplicator& deduplicator) { |
- std::string json; |
- deduplicator.AppendAsTraceFormat(&json); |
- return JSONReader::Read(json); |
-} |
+// Calls TypeNameDeduplicator::ExportIncrementally() and returns ListValue |
+// with exported entries. |
+std::unique_ptr<ListValue> ExportEntriesIncrementally( |
+ TypeNameDeduplicator* dedup) { |
+ TracedValue traced_value; |
+ traced_value.BeginArray(""); |
+ dedup->ExportIncrementally(&traced_value); |
+ traced_value.EndArray(); |
+ |
+ auto base_value = traced_value.ToBaseValue(); |
+ const DictionaryValue* dictionary; |
+ const ListValue* entries; |
+ if (!base_value->GetAsDictionary(&dictionary) || |
+ !dictionary->GetList("", &entries)) { |
+ return nullptr; |
+ } |
-// Inserts a single type name into a new TypeNameDeduplicator instance and |
-// checks if the value gets inserted and the exported value for |type_name| is |
-// the same as |expected_value|. |
-void TestInsertTypeAndReadback(const char* type_name, |
- const char* expected_value) { |
- std::unique_ptr<TypeNameDeduplicator> dedup(new TypeNameDeduplicator); |
- ASSERT_EQ(1, dedup->Insert(type_name)); |
+ return WrapUnique(entries->DeepCopy()); |
+} |
- std::unique_ptr<Value> type_names = DumpAndReadBack(*dedup); |
- ASSERT_NE(nullptr, type_names); |
+struct TypeNameMapping { |
+ const int id; |
+ const char* const name; |
+}; |
+ |
+std::unique_ptr<ListValue> ConvertMappingsToExportedEntries( |
+ StringDeduplicator* string_dedup, |
+ std::initializer_list<TypeNameMapping> mappings) { |
+ auto entries = MakeUnique<ListValue>(); |
+ for (const auto& mapping : mappings) { |
+ auto entry = MakeUnique<DictionaryValue>(); |
+ entry->SetInteger("id", mapping.id); |
+ entry->SetInteger("name_sid", string_dedup->Insert(mapping.name)); |
+ entries->Append(std::move(entry)); |
+ } |
+ return entries; |
+} |
- const DictionaryValue* dictionary; |
- ASSERT_TRUE(type_names->GetAsDictionary(&dictionary)); |
+void ExpectIncrementalEntries(TypeNameDeduplicator* dedup, |
+ StringDeduplicator* string_dedup, |
+ std::initializer_list<TypeNameMapping> mappings) { |
+ auto entries = ExportEntriesIncrementally(dedup); |
+ ASSERT_TRUE(entries); |
- // When the type name was inserted, it got ID 1. The exported key "1" |
- // should be equal to |expected_value|. |
- std::string value; |
- ASSERT_TRUE(dictionary->GetString("1", &value)); |
- ASSERT_EQ(expected_value, value); |
+ auto expected_entries = |
+ ConvertMappingsToExportedEntries(string_dedup, mappings); |
+ ASSERT_TRUE(expected_entries->Equals(entries.get())) |
+ << "expected_entries = " << *expected_entries << "entries = " << *entries; |
} |
} // namespace |
+TEST(TypeNameDeduplicatorTest, ImplicitId0) { |
+ StringDeduplicator string_dedup; |
+ TypeNameDeduplicator dedup(&string_dedup); |
+ |
+ // NULL type name is mapped to an implicitly added ID #0. |
+ ExpectIncrementalEntries(&dedup, &string_dedup, {{0, "[unknown]"}}); |
+ ASSERT_EQ(0, dedup.Insert(nullptr)); |
+ |
+ // Even though ID #0 is exported as "[unknown]" string, it's distinct |
+ // from "[unknown]" type name. |
+ ASSERT_EQ(1, dedup.Insert("[unknown]")); |
+ ExpectIncrementalEntries(&dedup, &string_dedup, {{1, "[unknown]"}}); |
+} |
+ |
TEST(TypeNameDeduplicatorTest, Deduplication) { |
// The type IDs should be like this: |
// 0: [unknown] |
@@ -67,29 +99,44 @@ TEST(TypeNameDeduplicatorTest, Deduplication) { |
// 2: bool |
// 3: string |
- std::unique_ptr<TypeNameDeduplicator> dedup(new TypeNameDeduplicator); |
- ASSERT_EQ(1, dedup->Insert(kInt)); |
- ASSERT_EQ(2, dedup->Insert(kBool)); |
- ASSERT_EQ(3, dedup->Insert(kString)); |
+ StringDeduplicator string_dedup; |
+ TypeNameDeduplicator dedup(&string_dedup); |
+ ASSERT_EQ(1, dedup.Insert("int")); |
+ ASSERT_EQ(2, dedup.Insert("bool")); |
+ ASSERT_EQ(3, dedup.Insert("string")); |
// Inserting again should return the same IDs. |
- ASSERT_EQ(2, dedup->Insert(kBool)); |
- ASSERT_EQ(1, dedup->Insert(kInt)); |
- ASSERT_EQ(3, dedup->Insert(kString)); |
- |
- // A null pointer should yield type ID 0. |
- ASSERT_EQ(0, dedup->Insert(nullptr)); |
+ ASSERT_EQ(2, dedup.Insert("bool")); |
+ ASSERT_EQ(1, dedup.Insert("int")); |
+ ASSERT_EQ(3, dedup.Insert("string")); |
} |
-TEST(TypeNameDeduplicatorTest, EscapeTypeName) { |
- // Reading json should not fail, because the type name should have been |
- // escaped properly and exported value should contain quotes. |
- TestInsertTypeAndReadback(kNeedsEscape, kNeedsEscape); |
+TEST(TypeNameDeduplicatorTest, TestExtractFileName) { |
+ StringDeduplicator string_dedup; |
+ TypeNameDeduplicator dedup(&string_dedup); |
+ |
+ ASSERT_EQ(1, dedup.Insert(kTaskFileName)); |
+ |
+ ExpectIncrementalEntries(&dedup, &string_dedup, |
+ {{0, "[unknown]"}, {1, kTaskPath}}); |
} |
-TEST(TypeNameDeduplicatorTest, TestExtractFileName) { |
- // The exported value for passed file name should be the folders in the path. |
- TestInsertTypeAndReadback(kTaskFileName, kTaskPath); |
+TEST(TypeNameDeduplicatorTest, IncrementalExport) { |
+ StringDeduplicator string_dedup; |
+ TypeNameDeduplicator dedup(&string_dedup); |
+ |
+ ASSERT_EQ(1, dedup.Insert("int")); |
+ ASSERT_EQ(2, dedup.Insert("bool")); |
+ |
+ ExpectIncrementalEntries(&dedup, &string_dedup, |
+ {{0, "[unknown]"}, {1, "int"}, {2, "bool"}}); |
+ |
+ ASSERT_EQ(2, dedup.Insert("bool")); |
+ ASSERT_EQ(3, dedup.Insert("string")); |
+ |
+ ExpectIncrementalEntries(&dedup, &string_dedup, {{3, "string"}}); |
+ |
+ ExpectIncrementalEntries(&dedup, &string_dedup, {}); |
} |
} // namespace trace_event |