// 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 <string>

#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
namespace trace_event {

// 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\"";

scoped_ptr<Value> DumpAndReadBack(const ConvertableToTraceFormat& convertable) {
  std::string json;
  convertable.AppendAsTraceFormat(&json);
  return JSONReader::Read(json);
}

TEST(TypeNameDeduplicatorTest, Deduplication) {
  // The type IDs should be like this:
  // 0: [unknown]
  // 1: int
  // 2: bool
  // 3: string

  scoped_refptr<TypeNameDeduplicator> dedup = new TypeNameDeduplicator;
  ASSERT_EQ(1, dedup->Insert(kInt));
  ASSERT_EQ(2, dedup->Insert(kBool));
  ASSERT_EQ(3, dedup->Insert(kString));

  // 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));
}

TEST(TypeNameDeduplicatorTest, EscapeTypeName) {
  scoped_refptr<TypeNameDeduplicator> dedup = new TypeNameDeduplicator;
  ASSERT_EQ(1, dedup->Insert(kNeedsEscape));

  // Reading json should not fail, because the type name should have been
  // escaped properly.
  scoped_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 contain the name, with quotes.
  std::string type_name;
  ASSERT_TRUE(dictionary->GetString("1", &type_name));
  ASSERT_EQ("\"quotes\"", type_name);
}

}  // namespace trace_event
}  // namespace base
