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.
5 #include "content/child/web_process_memory_dump_impl.h"
7 #include "base/trace_event/memory_allocator_dump.h"
8 #include "base/trace_event/process_memory_dump.h"
9 #include "base/trace_event/trace_event_argument.h"
10 #include "base/values.h"
11 #include "content/child/web_memory_allocator_dump_impl.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 // Tests that the Chromium<>Blink plumbing that exposes the MemoryInfra classes
17 // behaves correctly, performs the right transfers of memory ownerships and
18 // doesn't leak objects.
19 TEST(WebProcessMemoryDumpImplTest
, IntegrationTest
) {
20 scoped_refptr
<base::trace_event::TracedValue
> traced_value(
21 new base::trace_event::TracedValue());
23 scoped_ptr
<WebProcessMemoryDumpImpl
> wpmd1(new WebProcessMemoryDumpImpl());
24 auto wmad1
= wpmd1
->createMemoryAllocatorDump("1/1");
25 auto wmad2
= wpmd1
->createMemoryAllocatorDump("1/2");
26 ASSERT_EQ(wmad1
, wpmd1
->getMemoryAllocatorDump("1/1"));
27 ASSERT_EQ(wmad2
, wpmd1
->getMemoryAllocatorDump("1/2"));
29 scoped_ptr
<WebProcessMemoryDumpImpl
> wpmd2(new WebProcessMemoryDumpImpl());
30 wpmd2
->createMemoryAllocatorDump("2/1");
31 wpmd2
->createMemoryAllocatorDump("2/2");
33 wpmd1
->takeAllDumpsFrom(wpmd2
.get());
35 // Make sure that wpmd2 still owns its own PMD, even if empty.
36 ASSERT_NE(static_cast<base::trace_event::ProcessMemoryDump
*>(nullptr),
37 wpmd2
->process_memory_dump_
);
38 ASSERT_EQ(wpmd2
->owned_process_memory_dump_
.get(),
39 wpmd2
->process_memory_dump());
40 ASSERT_TRUE(wpmd2
->process_memory_dump()->allocator_dumps().empty());
42 // Make sure that wpmd2 is still usable after it has been emptied.
43 auto wmad
= wpmd2
->createMemoryAllocatorDump("2/new");
44 wmad
->AddScalar("attr_name", "bytes", 42);
45 wmad
->AddScalarF("attr_name_2", "rate", 42.0f
);
46 ASSERT_EQ(1u, wpmd2
->process_memory_dump()->allocator_dumps().size());
47 auto mad
= wpmd2
->process_memory_dump()->GetAllocatorDump("2/new");
48 ASSERT_NE(static_cast<base::trace_event::MemoryAllocatorDump
*>(nullptr), mad
);
49 ASSERT_EQ(wmad
, wpmd2
->getMemoryAllocatorDump("2/new"));
51 // Check that the attributes are propagated correctly.
52 auto raw_attrs
= mad
->attributes_for_testing()->ToBaseValue();
53 base::DictionaryValue
* attrs
= nullptr;
54 ASSERT_TRUE(raw_attrs
->GetAsDictionary(&attrs
));
55 base::DictionaryValue
* attr
= nullptr;
56 ASSERT_TRUE(attrs
->GetDictionary("attr_name", &attr
));
57 std::string attr_value
;
58 ASSERT_TRUE(attr
->GetString("type", &attr_value
));
59 ASSERT_EQ(base::trace_event::MemoryAllocatorDump::kTypeScalar
, attr_value
);
60 ASSERT_TRUE(attr
->GetString("units", &attr_value
));
61 ASSERT_EQ("bytes", attr_value
);
63 ASSERT_TRUE(attrs
->GetDictionary("attr_name_2", &attr
));
64 ASSERT_TRUE(attr
->GetString("type", &attr_value
));
65 ASSERT_EQ(base::trace_event::MemoryAllocatorDump::kTypeScalar
, attr_value
);
66 ASSERT_TRUE(attr
->GetString("units", &attr_value
));
67 ASSERT_EQ("rate", attr_value
);
68 ASSERT_TRUE(attr
->HasKey("value"));
70 // Check that AsValueInto() doesn't cause a crash.
71 wpmd2
->process_memory_dump()->AsValueInto(traced_value
.get());
73 // Free the |wpmd2| to check that the memory ownership of the two MAD(s)
74 // has been transferred to |wpmd1|.
77 // Now check that |wpmd1| has been effectively merged.
78 ASSERT_EQ(4u, wpmd1
->process_memory_dump()->allocator_dumps().size());
79 ASSERT_EQ(1u, wpmd1
->process_memory_dump()->allocator_dumps().count("1/1"));
80 ASSERT_EQ(1u, wpmd1
->process_memory_dump()->allocator_dumps().count("1/2"));
81 ASSERT_EQ(1u, wpmd1
->process_memory_dump()->allocator_dumps().count("2/1"));
82 ASSERT_EQ(1u, wpmd1
->process_memory_dump()->allocator_dumps().count("1/2"));
84 // Check that also the WMAD wrappers got merged.
85 blink::WebMemoryAllocatorDump
* null_wmad
= nullptr;
86 ASSERT_NE(null_wmad
, wpmd1
->getMemoryAllocatorDump("1/1"));
87 ASSERT_NE(null_wmad
, wpmd1
->getMemoryAllocatorDump("1/2"));
88 ASSERT_NE(null_wmad
, wpmd1
->getMemoryAllocatorDump("2/1"));
89 ASSERT_NE(null_wmad
, wpmd1
->getMemoryAllocatorDump("2/2"));
91 // Check that AsValueInto() doesn't cause a crash.
92 traced_value
= new base::trace_event::TracedValue();
93 wpmd1
->process_memory_dump()->AsValueInto(traced_value
.get());
95 // Check that clear() actually works.
97 ASSERT_TRUE(wpmd1
->process_memory_dump()->allocator_dumps().empty());
98 ASSERT_EQ(nullptr, wpmd1
->process_memory_dump()->GetAllocatorDump("1/1"));
99 ASSERT_EQ(nullptr, wpmd1
->process_memory_dump()->GetAllocatorDump("2/1"));
101 // Check that AsValueInto() doesn't cause a crash.
102 traced_value
= new base::trace_event::TracedValue();
103 wpmd1
->process_memory_dump()->AsValueInto(traced_value
.get());
105 // Check if a WebMemoryAllocatorDump created with guid, has correct guid.
106 blink::WebMemoryAllocatorDumpGuid guid
=
107 base::trace_event::MemoryAllocatorDumpGuid("id_1").ToUint64();
108 auto wmad3
= wpmd1
->createMemoryAllocatorDump("1/3", guid
);
109 ASSERT_EQ(wmad3
->guid(), guid
);
110 ASSERT_EQ(wmad3
, wpmd1
->getMemoryAllocatorDump("1/3"));
112 // Check that AddOwnershipEdge is propagated correctly.
113 auto wmad4
= wpmd1
->createMemoryAllocatorDump("1/4");
114 wpmd1
->AddOwnershipEdge(wmad4
->guid(), guid
);
115 auto allocator_dumps_edges
=
116 wpmd1
->process_memory_dump()->allocator_dumps_edges();
117 ASSERT_EQ(1u, allocator_dumps_edges
.size());
118 ASSERT_EQ(wmad4
->guid(), allocator_dumps_edges
[0].source
.ToUint64());
119 ASSERT_EQ(guid
, allocator_dumps_edges
[0].target
.ToUint64());
124 } // namespace content