blob: 71ee46dd28c0c62592585a5e814aba00dad7f8c6 [file] [log] [blame]
// 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 "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
#include "base/memory/discardable_memory.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/traced_value.h"
#include "base/values.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
namespace blink {
using testing::Contains;
using testing::Eq;
using testing::ByRef;
using base::trace_event::MemoryAllocatorDump;
// Tests that the Chromium<>Blink plumbing that exposes the MemoryInfra classes
// behaves correctly, performs the right transfers of memory ownerships and
// doesn't leak objects.
TEST(WebProcessMemoryDumpTest, IntegrationTest) {
std::unique_ptr<base::trace_event::TracedValue> traced_value(
new base::trace_event::TracedValue());
std::unique_ptr<WebProcessMemoryDump> wpmd1(new WebProcessMemoryDump());
auto* wmad1 = wpmd1->CreateMemoryAllocatorDump("1/1");
auto* wmad2 = wpmd1->CreateMemoryAllocatorDump("1/2");
ASSERT_EQ(wmad1, wpmd1->GetMemoryAllocatorDump("1/1"));
ASSERT_EQ(wmad2, wpmd1->GetMemoryAllocatorDump("1/2"));
std::unique_ptr<WebProcessMemoryDump> wpmd2(new WebProcessMemoryDump());
wpmd2->CreateMemoryAllocatorDump("2/1");
wpmd2->CreateMemoryAllocatorDump("2/2");
wpmd1->TakeAllDumpsFrom(wpmd2.get());
// Make sure that wpmd2 still owns its own PMD, even if empty.
ASSERT_NE(static_cast<base::trace_event::ProcessMemoryDump*>(nullptr),
wpmd2->process_memory_dump_);
ASSERT_EQ(wpmd2->owned_process_memory_dump_.get(),
wpmd2->process_memory_dump());
ASSERT_TRUE(wpmd2->process_memory_dump()->allocator_dumps().empty());
// Make sure that wpmd2 is still usable after it has been emptied.
auto* wmad = wpmd2->CreateMemoryAllocatorDump("2/new");
wmad->AddScalar("attr_name", "bytes", 42);
ASSERT_EQ(1u, wpmd2->process_memory_dump()->allocator_dumps().size());
auto* mad = wpmd2->process_memory_dump()->GetAllocatorDump("2/new");
ASSERT_NE(static_cast<MemoryAllocatorDump*>(nullptr), mad);
ASSERT_EQ(wmad, wpmd2->GetMemoryAllocatorDump("2/new"));
// Check that the attributes are propagated correctly.
MemoryAllocatorDump::Entry expected("attr_name", "bytes", 42);
ASSERT_THAT(mad->entries(), Contains(Eq(ByRef(expected))));
// Check that calling serialization routines doesn't cause a crash.
wpmd2->process_memory_dump()->SerializeAllocatorDumpsInto(traced_value.get());
// Free the |wpmd2| to check that the memory ownership of the two MAD(s)
// has been transferred to |wpmd1|.
wpmd2.reset();
// Now check that |wpmd1| has been effectively merged.
ASSERT_EQ(4u, wpmd1->process_memory_dump()->allocator_dumps().size());
ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("1/1"));
ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("1/2"));
ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("2/1"));
ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("1/2"));
// Check that also the WMAD wrappers got merged.
blink::WebMemoryAllocatorDump* null_wmad = nullptr;
ASSERT_NE(null_wmad, wpmd1->GetMemoryAllocatorDump("1/1"));
ASSERT_NE(null_wmad, wpmd1->GetMemoryAllocatorDump("1/2"));
ASSERT_NE(null_wmad, wpmd1->GetMemoryAllocatorDump("2/1"));
ASSERT_NE(null_wmad, wpmd1->GetMemoryAllocatorDump("2/2"));
// Check that calling serialization routines doesn't cause a crash.
traced_value.reset(new base::trace_event::TracedValue);
wpmd1->process_memory_dump()->SerializeAllocatorDumpsInto(traced_value.get());
// Check that clear() actually works.
wpmd1->Clear();
ASSERT_TRUE(wpmd1->process_memory_dump()->allocator_dumps().empty());
ASSERT_EQ(nullptr, wpmd1->process_memory_dump()->GetAllocatorDump("1/1"));
ASSERT_EQ(nullptr, wpmd1->process_memory_dump()->GetAllocatorDump("2/1"));
// Check that calling serialization routines doesn't cause a crash.
traced_value.reset(new base::trace_event::TracedValue);
wpmd1->process_memory_dump()->SerializeAllocatorDumpsInto(traced_value.get());
// Check if a WebMemoryAllocatorDump created with guid, has correct guid.
blink::WebMemoryAllocatorDumpGuid guid =
base::trace_event::MemoryAllocatorDumpGuid("id_1").ToUint64();
auto* wmad3 = wpmd1->CreateMemoryAllocatorDump("1/3", guid);
ASSERT_EQ(wmad3->Guid(), guid);
ASSERT_EQ(wmad3, wpmd1->GetMemoryAllocatorDump("1/3"));
// Check that AddOwnershipEdge is propagated correctly.
auto* wmad4 = wpmd1->CreateMemoryAllocatorDump("1/4");
wpmd1->AddOwnershipEdge(wmad4->Guid(), guid);
auto allocator_dumps_edges =
wpmd1->process_memory_dump()->allocator_dumps_edges();
ASSERT_EQ(1u, allocator_dumps_edges.size());
auto it = allocator_dumps_edges.begin();
ASSERT_NE(allocator_dumps_edges.end(), it);
ASSERT_EQ(wmad4->Guid(), it->first.ToUint64());
ASSERT_EQ(guid, it->second.target.ToUint64());
// Check that createDumpAdapterForSkia() works.
auto* skia_trace_memory_dump = wpmd1->CreateDumpAdapterForSkia("1/skia");
ASSERT_TRUE(skia_trace_memory_dump);
// Check that createDiscardableMemoryAllocatorDump() works.
base::TestDiscardableMemoryAllocator discardable_memory_allocator;
auto discardable_memory =
discardable_memory_allocator.AllocateLockedDiscardableMemory(1024);
wpmd1->CreateDiscardableMemoryAllocatorDump("1/discardable",
discardable_memory.get());
discardable_memory->Unlock();
wpmd1.reset();
}
} // namespace blink