| // 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 "content/child/web_process_memory_dump_impl.h" |
| |
| #include "base/trace_event/memory_allocator_dump.h" |
| #include "base/trace_event/process_memory_dump.h" |
| #include "base/trace_event/trace_event_argument.h" |
| #include "base/values.h" |
| #include "content/child/web_memory_allocator_dump_impl.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| |
| // 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(WebProcessMemoryDumpImplTest, IntegrationTest) { |
| scoped_refptr<base::trace_event::TracedValue> traced_value( |
| new base::trace_event::TracedValue()); |
| |
| scoped_ptr<WebProcessMemoryDumpImpl> wpmd1(new WebProcessMemoryDumpImpl()); |
| 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")); |
| |
| scoped_ptr<WebProcessMemoryDumpImpl> wpmd2(new WebProcessMemoryDumpImpl()); |
| 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); |
| wmad->addScalarF("attr_name_2", "rate", 42.0f); |
| ASSERT_EQ(1u, wpmd2->process_memory_dump()->allocator_dumps().size()); |
| auto mad = wpmd2->process_memory_dump()->GetAllocatorDump("2/new"); |
| ASSERT_NE(static_cast<base::trace_event::MemoryAllocatorDump*>(nullptr), mad); |
| ASSERT_EQ(wmad, wpmd2->getMemoryAllocatorDump("2/new")); |
| |
| // Check that the attributes are propagated correctly. |
| auto raw_attrs = mad->attributes_for_testing()->ToBaseValue(); |
| base::DictionaryValue* attrs = nullptr; |
| ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs)); |
| base::DictionaryValue* attr = nullptr; |
| ASSERT_TRUE(attrs->GetDictionary("attr_name", &attr)); |
| std::string attr_value; |
| ASSERT_TRUE(attr->GetString("type", &attr_value)); |
| ASSERT_EQ(base::trace_event::MemoryAllocatorDump::kTypeScalar, attr_value); |
| ASSERT_TRUE(attr->GetString("units", &attr_value)); |
| ASSERT_EQ("bytes", attr_value); |
| |
| ASSERT_TRUE(attrs->GetDictionary("attr_name_2", &attr)); |
| ASSERT_TRUE(attr->GetString("type", &attr_value)); |
| ASSERT_EQ(base::trace_event::MemoryAllocatorDump::kTypeScalar, attr_value); |
| ASSERT_TRUE(attr->GetString("units", &attr_value)); |
| ASSERT_EQ("rate", attr_value); |
| ASSERT_TRUE(attr->HasKey("value")); |
| |
| // Check that AsValueInto() doesn't cause a crash. |
| wpmd2->process_memory_dump()->AsValueInto(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 AsValueInto() doesn't cause a crash. |
| traced_value = new base::trace_event::TracedValue(); |
| wpmd1->process_memory_dump()->AsValueInto(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 AsValueInto() doesn't cause a crash. |
| traced_value = new base::trace_event::TracedValue(); |
| wpmd1->process_memory_dump()->AsValueInto(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()); |
| ASSERT_EQ(wmad4->guid(), allocator_dumps_edges[0].source.ToUint64()); |
| ASSERT_EQ(guid, allocator_dumps_edges[0].target.ToUint64()); |
| |
| wpmd1.reset(); |
| } |
| |
| } // namespace content |