| 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..cfc2aadd76c15dac58eccfab30a5c0a99fadaff5 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,66 +26,115 @@ 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::SerializeIncrementally() and returns ListValue
|
| +// with serialized entries.
|
| +std::unique_ptr<ListValue> SerializeEntriesIncrementally(
|
| + TypeNameDeduplicator* dedup) {
|
| + TracedValue traced_value;
|
| + traced_value.BeginArray("");
|
| + dedup->SerializeIncrementally(&traced_value);
|
| + traced_value.EndArray();
|
| +
|
| + auto base_value = traced_value.ToBaseValue();
|
| + DictionaryValue* dictionary;
|
| + std::unique_ptr<Value> entries;
|
| + if (!base_value->GetAsDictionary(&dictionary) ||
|
| + !dictionary->Remove("", &entries)) {
|
| + return nullptr;
|
| + }
|
| + return ListValue::From(std::move(entries));
|
| }
|
|
|
| -// 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));
|
| -
|
| - std::unique_ptr<Value> type_names = DumpAndReadBack(*dedup);
|
| - ASSERT_NE(nullptr, type_names);
|
| -
|
| - const DictionaryValue* dictionary;
|
| - ASSERT_TRUE(type_names->GetAsDictionary(&dictionary));
|
| -
|
| - // 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);
|
| +struct TypeNameMapping {
|
| + const int id;
|
| + const char* const name;
|
| +};
|
| +
|
| +std::unique_ptr<ListValue> SerializeMappingsAsEntries(
|
| + 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;
|
| +}
|
| +
|
| +void ExpectIncrementalEntries(TypeNameDeduplicator* dedup,
|
| + StringDeduplicator* string_dedup,
|
| + std::initializer_list<TypeNameMapping> mappings) {
|
| + auto entries = SerializeEntriesIncrementally(dedup);
|
| + ASSERT_TRUE(entries);
|
| +
|
| + auto expected_entries = SerializeMappingsAsEntries(string_dedup, mappings);
|
| + ASSERT_TRUE(expected_entries->Equals(entries.get()))
|
| + << "expected_entries = " << *expected_entries << "entries = " << *entries;
|
| }
|
|
|
| } // namespace
|
|
|
| -TEST(TypeNameDeduplicatorTest, Deduplication) {
|
| +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 serialized as "[unknown]" string, it's distinct
|
| + // from "[unknown]" type name.
|
| + ASSERT_EQ(1, dedup.Insert("[unknown]"));
|
| + ExpectIncrementalEntries(&dedup, &string_dedup, {{1, "[unknown]"}});
|
| +}
|
| +
|
| +TEST(TypeNameDeduplicatorTest, Deduplicate) {
|
| // The type IDs should be like this:
|
| // 0: [unknown]
|
| // 1: int
|
| // 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, SerializeIncrementally) {
|
| + 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
|
|
|