1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
6#include <string>
7
8#include "base/json/json_reader.h"
9#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
10#include "base/values.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace base {
14namespace trace_event {
15
16namespace {
17
18// Define all strings once, because the deduplicator requires pointer equality,
19// and string interning is unreliable.
20const char kInt[] = "int";
21const char kBool[] = "bool";
22const char kString[] = "string";
23const char kNeedsEscape[] = "\"quotes\"";
24
25#if defined(OS_POSIX)
26const char kTaskFileName[] = "../../base/trace_event/trace_log.cc";
27const char kTaskPath[] = "base/trace_event";
28#else
29const char kTaskFileName[] = "..\\..\\base\\memory\\memory_win.cc";
30const char kTaskPath[] = "base\\memory";
31#endif
32
33std::unique_ptr<Value> DumpAndReadBack(
34    const TypeNameDeduplicator& deduplicator) {
35  std::string json;
36  deduplicator.AppendAsTraceFormat(&json);
37  return JSONReader::Read(json);
38}
39
40// Inserts a single type name into a new TypeNameDeduplicator instance and
41// checks if the value gets inserted and the exported value for |type_name| is
42// the same as |expected_value|.
43void TestInsertTypeAndReadback(const char* type_name,
44                               const char* expected_value) {
45  std::unique_ptr<TypeNameDeduplicator> dedup(new TypeNameDeduplicator);
46  ASSERT_EQ(1, dedup->Insert(type_name));
47
48  std::unique_ptr<Value> type_names = DumpAndReadBack(*dedup);
49  ASSERT_NE(nullptr, type_names);
50
51  const DictionaryValue* dictionary;
52  ASSERT_TRUE(type_names->GetAsDictionary(&dictionary));
53
54  // When the type name was inserted, it got ID 1. The exported key "1"
55  // should be equal to |expected_value|.
56  std::string value;
57  ASSERT_TRUE(dictionary->GetString("1", &value));
58  ASSERT_EQ(expected_value, value);
59}
60
61}  // namespace
62
63TEST(TypeNameDeduplicatorTest, Deduplication) {
64  // The type IDs should be like this:
65  // 0: [unknown]
66  // 1: int
67  // 2: bool
68  // 3: string
69
70  std::unique_ptr<TypeNameDeduplicator> dedup(new TypeNameDeduplicator);
71  ASSERT_EQ(1, dedup->Insert(kInt));
72  ASSERT_EQ(2, dedup->Insert(kBool));
73  ASSERT_EQ(3, dedup->Insert(kString));
74
75  // Inserting again should return the same IDs.
76  ASSERT_EQ(2, dedup->Insert(kBool));
77  ASSERT_EQ(1, dedup->Insert(kInt));
78  ASSERT_EQ(3, dedup->Insert(kString));
79
80  // A null pointer should yield type ID 0.
81  ASSERT_EQ(0, dedup->Insert(nullptr));
82}
83
84TEST(TypeNameDeduplicatorTest, EscapeTypeName) {
85  // Reading json should not fail, because the type name should have been
86  // escaped properly and exported value should contain quotes.
87  TestInsertTypeAndReadback(kNeedsEscape, kNeedsEscape);
88}
89
90TEST(TypeNameDeduplicatorTest, TestExtractFileName) {
91  // The exported value for passed file name should be the folders in the path.
92  TestInsertTypeAndReadback(kTaskFileName, kTaskPath);
93}
94
95}  // namespace trace_event
96}  // namespace base
97