blob: 5edeaca70927b98d076c7372f65b3aa73f2342c1 [file] [log] [blame]
// Copyright 2017 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 "chrome/profiling/json_exporter.h"
#include <sstream>
#include "base/json/json_reader.h"
#include "base/values.h"
#include "chrome/profiling/backtrace_storage.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace profiling {
namespace {
// Finds the first period_interval trace event in the given JSON trace.
// Returns null on failure.
const base::Value* FindFirstPeriodicInterval(const base::Value& root) {
auto found_trace_events =
root.FindKeyOfType("traceEvents", base::Value::Type::LIST);
if (found_trace_events == root.DictEnd())
return nullptr;
for (const base::Value& cur : found_trace_events->second.GetList()) {
auto found_name = cur.FindKeyOfType("name", base::Value::Type::STRING);
if (found_name == cur.DictEnd())
return nullptr;
if (found_name->second.GetString() == "periodic_interval")
return &cur;
}
return nullptr;
}
} // namespace
TEST(ProfilingJsonExporter, Simple) {
BacktraceStorage backtrace_storage;
std::vector<Address> stack1;
stack1.push_back(Address(1234));
stack1.push_back(Address(5678));
const Backtrace* bt1 = backtrace_storage.Insert(std::move(stack1));
std::vector<Address> stack2;
stack2.push_back(Address(9012));
const Backtrace* bt2 = backtrace_storage.Insert(std::move(stack2));
AllocationEventSet events;
events.insert(AllocationEvent(Address(0x1), 16, bt1));
events.insert(AllocationEvent(Address(0x2), 32, bt2));
events.insert(AllocationEvent(Address(0x3), 16, bt1));
std::ostringstream stream;
ExportAllocationEventSetToJSON(1234, &backtrace_storage, events, stream);
std::string json = stream.str();
// JSON should parse.
base::JSONReader reader(base::JSON_PARSE_RFC);
std::unique_ptr<base::Value> root = reader.ReadToValue(stream.str());
ASSERT_EQ(base::JSONReader::JSON_NO_ERROR, reader.error_code())
<< reader.GetErrorMessage();
ASSERT_TRUE(root.get());
// The trace array contains two items, a process_name one and a
// periodic_interval one. Find the latter.
const base::Value* periodic_interval = FindFirstPeriodicInterval(*root);
ASSERT_TRUE(periodic_interval) << "Array contains no periodic_interval";
const base::Value* heaps_v2 =
periodic_interval->GetPath({"args", "dumps", "heaps_v2"});
ASSERT_TRUE(heaps_v2);
// Counts should be a list of two items, a 1 and a 2 (in either order). The
// two matching 16-byte allocations should be coalesced to produce the 2.
const base::Value* counts =
heaps_v2->GetPath({"allocators", "malloc", "counts"});
ASSERT_TRUE(counts);
EXPECT_EQ(2u, counts->GetList().size());
EXPECT_TRUE((counts->GetList()[0].GetInt() == 1 &&
counts->GetList()[1].GetInt() == 2) ||
(counts->GetList()[0].GetInt() == 2 &&
counts->GetList()[1].GetInt() == 1));
}
} // namespace profiling