Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(341)

Side by Side Diff: Source/wtf/tests/MemoryInstrumentationTest.cpp

Issue 13973026: remove memoryinstrumentation Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: remove the rest part of MemoryInstrumentation Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/wtf/MemoryObjectInfo.h ('k') | Source/wtf/text/AtomicString.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32
33 #include "wtf/ArrayBuffer.h"
34 #include "wtf/HashCountedSet.h"
35 #include "wtf/HashMap.h"
36 #include "wtf/HashSet.h"
37 #include "wtf/ListHashSet.h"
38 #include "wtf/MemoryInstrumentation.h"
39 #include "wtf/MemoryInstrumentationArrayBufferView.h"
40 #include "wtf/MemoryInstrumentationHashCountedSet.h"
41 #include "wtf/MemoryInstrumentationHashMap.h"
42 #include "wtf/MemoryInstrumentationHashSet.h"
43 #include "wtf/MemoryInstrumentationListHashSet.h"
44 #include "wtf/MemoryInstrumentationString.h"
45 #include "wtf/MemoryInstrumentationVector.h"
46 #include "wtf/MemoryObjectInfo.h"
47 #include "wtf/RefCounted.h"
48 #include "wtf/Vector.h"
49 #include "wtf/text/AtomicString.h"
50 #include "wtf/text/CString.h"
51 #include "wtf/text/StringBuffer.h"
52 #include "wtf/text/StringHash.h"
53 #include "wtf/text/StringImpl.h"
54 #include "wtf/text/WTFString.h"
55 #include <gtest/gtest.h>
56
57 namespace {
58 enum TestEnum { ONE = 1, TWO, THREE, MY_ENUM_MAX };
59 }
60
61 namespace WTF {
62
63 template<> struct DefaultHash<TestEnum> {
64 typedef IntHash<unsigned> Hash;
65 };
66
67 template<> struct HashTraits<TestEnum> : GenericHashTraits<TestEnum> {
68 static const bool emptyValueIsZero = true;
69 static const bool needsDestruction = false;
70 static void constructDeletedValue(TestEnum& slot) { slot = static_cast<TestE num>(MY_ENUM_MAX + 1); }
71 static bool isDeletedValue(TestEnum value) { return value == (MY_ENUM_MAX + 1); }
72 };
73
74 }
75
76 namespace {
77
78 using WTF::MemoryObjectInfo;
79 using WTF::MemoryClassInfo;
80 using WTF::MemoryObjectType;
81 using WTF::MemberType;
82
83 MemoryObjectType TestType = "TestType";
84
85 class MemoryInstrumentationTestClient : public WTF::MemoryInstrumentationClient {
86 public:
87 MemoryInstrumentationTestClient() : m_links(WTF::LastMemberTypeEntry)
88 {
89 m_links[WTF::PointerMember] = 0;
90 m_links[WTF::ReferenceMember] = 0;
91 m_links[WTF::RetainingPointer] = 0;
92 }
93
94 virtual void countObjectSize(const void*, MemoryObjectType objectType, size_ t size)
95 {
96 TypeToSizeMap::AddResult result = m_totalSizes.add(objectType, size);
97 if (!result.isNewEntry)
98 result.iterator->value += size;
99 }
100 virtual bool visited(const void* object) { return !m_visitedObjects.add(obje ct).isNewEntry; }
101 virtual bool checkCountedObject(const void*) { return true; }
102 virtual void reportNode(const MemoryObjectInfo&) OVERRIDE { }
103 virtual void reportEdge(const void*, const char*, MemberType memberType) OVE RRIDE
104 {
105 ++m_links[memberType];
106 }
107 virtual void reportLeaf(const MemoryObjectInfo&, const char*) OVERRIDE
108 {
109 ++m_links[WTF::RetainingPointer];
110 }
111 virtual void reportBaseAddress(const void*, const void*) OVERRIDE { }
112 virtual int registerString(const char*) OVERRIDE { return -1; }
113
114 size_t visitedObjects() const { return m_visitedObjects.size(); }
115 size_t totalSize(const MemoryObjectType objectType) const
116 {
117 TypeToSizeMap::const_iterator i = m_totalSizes.find(objectType);
118 return i == m_totalSizes.end() ? 0 : i->value;
119 }
120
121 size_t linksCount(const WTF::MemberType memberType) const
122 {
123 return m_links[memberType];
124 }
125
126 size_t reportedSizeForAllTypes() const
127 {
128 size_t size = 0;
129 for (TypeToSizeMap::const_iterator i = m_totalSizes.begin(); i != m_tota lSizes.end(); ++i)
130 size += i->value;
131 return size;
132 }
133
134 private:
135 typedef HashMap<MemoryObjectType, size_t> TypeToSizeMap;
136 TypeToSizeMap m_totalSizes;
137 WTF::HashSet<const void*> m_visitedObjects;
138 WTF::Vector<size_t, WTF::LastMemberTypeEntry> m_links;
139 };
140
141 class InstrumentationTestImpl : public WTF::MemoryInstrumentation {
142 public:
143 explicit InstrumentationTestImpl(MemoryInstrumentationTestClient* client)
144 : MemoryInstrumentation(client)
145 , m_client(client) { }
146
147 virtual void processDeferredObjects();
148 virtual void deferObject(PassOwnPtr<WrapperBase>);
149
150 size_t visitedObjects() const { return m_client->visitedObjects(); }
151 size_t reportedSizeForAllTypes() const { return m_client->reportedSizeForAll Types(); }
152 size_t totalSize(const MemoryObjectType objectType) const { return m_client- >totalSize(objectType); }
153 size_t linksCount(const WTF::MemberType memberType) const { return m_client ->linksCount(memberType); }
154
155 private:
156 MemoryInstrumentationTestClient* m_client;
157 Vector<OwnPtr<WrapperBase> > m_deferredObjects;
158 };
159
160 class InstrumentationTestHelper : public InstrumentationTestImpl {
161 public:
162 InstrumentationTestHelper() : InstrumentationTestImpl(&m_client) { }
163
164 private:
165 MemoryInstrumentationTestClient m_client;
166 };
167
168 void InstrumentationTestImpl::processDeferredObjects()
169 {
170 while (!m_deferredObjects.isEmpty()) {
171 OwnPtr<WrapperBase> pointer = m_deferredObjects.last().release();
172 m_deferredObjects.removeLast();
173 pointer->process(this);
174 }
175 }
176
177 void InstrumentationTestImpl::deferObject(PassOwnPtr<WrapperBase> pointer)
178 {
179 m_deferredObjects.append(pointer);
180 }
181
182 class NotInstrumented {
183 public:
184 NotInstrumented(const char* = 0) { }
185 char m_data[42];
186 };
187
188 class Instrumented {
189 public:
190 Instrumented() : m_notInstrumented(new NotInstrumented) { }
191 virtual ~Instrumented() { disposeOwnedObject(); }
192
193 virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
194 {
195 MemoryClassInfo info(memoryObjectInfo, this, TestType);
196 memoryObjectInfo->setClassName("Instrumented");
197 info.addMember(m_notInstrumented, "m_notInstrumented", WTF::RetainingPoi nter);
198 }
199
200 void disposeOwnedObject()
201 {
202 delete m_notInstrumented;
203 m_notInstrumented = 0;
204 }
205
206 NotInstrumented* m_notInstrumented;
207 };
208
209 TEST(MemoryInstrumentationTest, sizeOf)
210 {
211 InstrumentationTestHelper helper;
212 Instrumented instrumented;
213 helper.addRootObject(instrumented);
214 EXPECT_EQ(sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
215 EXPECT_EQ(1u, helper.visitedObjects());
216 EXPECT_EQ(1u, helper.linksCount(WTF::RetainingPointer));
217 }
218
219 TEST(MemoryInstrumentationTest, nullCheck)
220 {
221 InstrumentationTestHelper helper;
222 Instrumented* instrumented = 0;
223 helper.addRootObject(instrumented);
224 EXPECT_EQ(0u, helper.reportedSizeForAllTypes());
225 EXPECT_EQ(0u, helper.visitedObjects());
226 EXPECT_EQ(0u, helper.linksCount(WTF::RetainingPointer));
227 }
228
229 TEST(MemoryInstrumentationTest, ptrVsRef)
230 {
231 {
232 InstrumentationTestHelper helper;
233 Instrumented instrumented;
234 helper.addRootObject(&instrumented);
235 EXPECT_EQ(sizeof(Instrumented) + sizeof(NotInstrumented), helper.reporte dSizeForAllTypes());
236 EXPECT_EQ(2u, helper.visitedObjects());
237 EXPECT_EQ(1u, helper.linksCount(WTF::RetainingPointer));
238 }
239 {
240 InstrumentationTestHelper helper;
241 Instrumented instrumented;
242 helper.addRootObject(instrumented);
243 EXPECT_EQ(sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
244 EXPECT_EQ(1u, helper.visitedObjects());
245 EXPECT_EQ(1u, helper.linksCount(WTF::RetainingPointer));
246 }
247 }
248
249 class InstrumentedWithOwnPtr : public Instrumented {
250 public:
251 InstrumentedWithOwnPtr() : m_notInstrumentedOwnPtr(adoptPtr(new NotInstrumen ted)) { }
252
253 virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
254 {
255 MemoryClassInfo info(memoryObjectInfo, this, TestType);
256 Instrumented::reportMemoryUsage(memoryObjectInfo);
257 info.addMember(m_notInstrumentedOwnPtr);
258 }
259 OwnPtr<NotInstrumented> m_notInstrumentedOwnPtr;
260 };
261
262 TEST(MemoryInstrumentationTest, ownPtrNotInstrumented)
263 {
264 InstrumentationTestHelper helper;
265 InstrumentedWithOwnPtr instrumentedWithOwnPtr;
266 helper.addRootObject(instrumentedWithOwnPtr);
267 EXPECT_EQ(2u * sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
268 EXPECT_EQ(2u, helper.visitedObjects());
269 EXPECT_EQ(2u, helper.linksCount(WTF::RetainingPointer));
270 }
271
272 class InstrumentedUndefined {
273 public:
274 InstrumentedUndefined() : m_data(0) { }
275
276 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
277 {
278 MemoryClassInfo info(memoryObjectInfo, this);
279 }
280 int m_data;
281 };
282
283 class InstrumentedDOM {
284 public:
285 InstrumentedDOM() : m_instrumentedUndefined(adoptPtr(new InstrumentedUndefin ed)) { }
286
287 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
288 {
289 MemoryClassInfo info(memoryObjectInfo, this, TestType);
290 info.addMember(m_instrumentedUndefined);
291 }
292 OwnPtr<InstrumentedUndefined> m_instrumentedUndefined;
293 };
294
295 TEST(MemoryInstrumentationTest, ownerTypePropagation)
296 {
297 InstrumentationTestHelper helper;
298 OwnPtr<InstrumentedDOM> instrumentedDOM(adoptPtr(new InstrumentedDOM));
299 helper.addRootObject(instrumentedDOM.get());
300 EXPECT_EQ(sizeof(InstrumentedDOM) + sizeof(InstrumentedUndefined), helper.re portedSizeForAllTypes());
301 EXPECT_EQ(sizeof(InstrumentedDOM) + sizeof(InstrumentedUndefined), helper.to talSize(TestType));
302 EXPECT_EQ(2u, helper.visitedObjects());
303 }
304
305 class NonVirtualInstrumented {
306 public:
307 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
308 {
309 MemoryClassInfo info(memoryObjectInfo, this, TestType);
310 info.addMember(m_instrumented);
311 }
312
313 Instrumented m_instrumented;
314 };
315
316 TEST(MemoryInstrumentationTest, visitFirstMemberInNonVirtualClass)
317 {
318 InstrumentationTestHelper helper;
319 NonVirtualInstrumented nonVirtualInstrumented;
320 helper.addRootObject(&nonVirtualInstrumented);
321 EXPECT_EQ(sizeof(NonVirtualInstrumented) + sizeof(NotInstrumented), helper.r eportedSizeForAllTypes());
322 EXPECT_EQ(2u, helper.visitedObjects());
323 }
324
325 template<typename T>
326 class InstrumentedOwner {
327 public:
328 template<typename V>
329 InstrumentedOwner(const V& value) : m_value(value) { }
330 InstrumentedOwner() { }
331 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
332 {
333 MemoryClassInfo info(memoryObjectInfo, this, TestType);
334 info.addMember(m_value, "value", WTF::RetainingPointer);
335 }
336
337 T m_value;
338 };
339
340 TEST(MemoryInstrumentationTest, visitStrings)
341 {
342 { // 8-bit string.
343 InstrumentationTestHelper helper;
344 InstrumentedOwner<String> stringInstrumentedOwner("String");
345 helper.addRootObject(stringInstrumentedOwner);
346 EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length(), helper.reportedSizeForAllTypes());
347 EXPECT_EQ(1u, helper.visitedObjects());
348 }
349
350 { // 8-bit string with 16bit shadow.
351 InstrumentationTestHelper helper;
352 InstrumentedOwner<String> stringInstrumentedOwner("String");
353 stringInstrumentedOwner.m_value.characters();
354 helper.addRootObject(stringInstrumentedOwner);
355 EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length() * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes());
356 EXPECT_EQ(2u, helper.visitedObjects());
357 }
358
359 { // 16 bit string.
360 InstrumentationTestHelper helper;
361 String string("String");
362 InstrumentedOwner<String> stringInstrumentedOwner(String(string.characte rs(), string.length()));
363 helper.addRootObject(stringInstrumentedOwner);
364 EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length() * sizeof(UChar), helper.reportedSizeForAllTypes());
365 EXPECT_EQ(1u, helper.visitedObjects());
366 }
367
368 { // ASCIILiteral
369 InstrumentationTestHelper helper;
370 ASCIILiteral literal("String");
371 InstrumentedOwner<String> stringInstrumentedOwner(literal);
372 helper.addRootObject(stringInstrumentedOwner);
373 EXPECT_EQ(sizeof(StringImpl), helper.reportedSizeForAllTypes());
374 EXPECT_EQ(1u, helper.visitedObjects());
375 }
376
377 { // Zero terminated internal buffer.
378 InstrumentationTestHelper helper;
379 InstrumentedOwner<String> stringInstrumentedOwner("string");
380 stringInstrumentedOwner.m_value.charactersWithNullTermination();
381 helper.addRootObject(stringInstrumentedOwner);
382 EXPECT_EQ(sizeof(StringImpl) + (stringInstrumentedOwner.m_value.length() + 1) * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes());
383 EXPECT_EQ(2u, helper.visitedObjects());
384 }
385
386 { // Substring
387 InstrumentationTestHelper helper;
388 String baseString("String");
389 baseString.characters(); // Force 16 shadow creation.
390 InstrumentedOwner<String> stringInstrumentedOwner(baseString.substringSh aringImpl(1, 4));
391 helper.addRootObject(stringInstrumentedOwner);
392 EXPECT_EQ(sizeof(StringImpl) * 2 + baseString.length() * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes());
393 EXPECT_EQ(3u, helper.visitedObjects());
394 }
395
396 { // Owned buffer.
397 InstrumentationTestHelper helper;
398 StringBuffer<LChar> buffer(6);
399 InstrumentedOwner<String> stringInstrumentedOwner(String::adopt(buffer)) ;
400 helper.addRootObject(stringInstrumentedOwner);
401 EXPECT_EQ(sizeof(StringImpl) + stringInstrumentedOwner.m_value.length(), helper.reportedSizeForAllTypes());
402 EXPECT_EQ(2u, helper.visitedObjects());
403 }
404
405 {
406 InstrumentationTestHelper helper;
407 InstrumentedOwner<AtomicString> atomicStringInstrumentedOwner("AtomicStr ing");
408 atomicStringInstrumentedOwner.m_value.string().characters(); // Force 16 bit shadow creation.
409 helper.addRootObject(atomicStringInstrumentedOwner);
410 EXPECT_EQ(sizeof(StringImpl) + atomicStringInstrumentedOwner.m_value.len gth() * (sizeof(LChar) + sizeof(UChar)), helper.reportedSizeForAllTypes());
411 EXPECT_EQ(2u, helper.visitedObjects());
412 }
413
414 {
415 InstrumentationTestHelper helper;
416 InstrumentedOwner<CString> cStringInstrumentedOwner("CString");
417 helper.addRootObject(cStringInstrumentedOwner);
418 EXPECT_EQ(sizeof(WTF::CStringBuffer) + cStringInstrumentedOwner.m_value. length(), helper.reportedSizeForAllTypes());
419 EXPECT_EQ(1u, helper.visitedObjects());
420 }
421 }
422
423 class TwoPointersToRefPtr {
424 public:
425 TwoPointersToRefPtr(const RefPtr<StringImpl>& value) : m_ptr1(&value), m_ptr 2(&value) { }
426 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
427 {
428 MemoryClassInfo info(memoryObjectInfo, this, TestType);
429 info.addMember(m_ptr1);
430 info.addMember(m_ptr2);
431 }
432
433 const RefPtr<StringImpl>* m_ptr1;
434 const RefPtr<StringImpl>* m_ptr2;
435 };
436
437 TEST(MemoryInstrumentationTest, refPtrPtr)
438 {
439 InstrumentationTestHelper helper;
440 RefPtr<StringImpl> refPtr;
441 TwoPointersToRefPtr root(refPtr);
442 helper.addRootObject(root);
443 EXPECT_EQ(sizeof(RefPtr<StringImpl>), helper.reportedSizeForAllTypes());
444 EXPECT_EQ(1u, helper.visitedObjects());
445 }
446
447 class TwoPointersToOwnPtr {
448 public:
449 TwoPointersToOwnPtr(const OwnPtr<NotInstrumented>& value) : m_ptr1(&value), m_ptr2(&value) { }
450 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
451 {
452 MemoryClassInfo info(memoryObjectInfo, this, TestType);
453 info.addMember(m_ptr1);
454 info.addMember(m_ptr2);
455 }
456
457 const OwnPtr<NotInstrumented>* m_ptr1;
458 const OwnPtr<NotInstrumented>* m_ptr2;
459 };
460
461 TEST(MemoryInstrumentationTest, ownPtrPtr)
462 {
463 InstrumentationTestHelper helper;
464 OwnPtr<NotInstrumented> ownPtr;
465 TwoPointersToOwnPtr root(ownPtr);
466 helper.addRootObject(root);
467 EXPECT_EQ(sizeof(OwnPtr<NotInstrumented>), helper.reportedSizeForAllTypes()) ;
468 EXPECT_EQ(1u, helper.visitedObjects());
469 }
470
471 template<typename T>
472 class InstrumentedTemplate {
473 public:
474 template<typename V>
475 InstrumentedTemplate(const V& value) : m_value(value) { }
476
477 template<typename MemoryObjectInfo>
478 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
479 {
480 typename MemoryObjectInfo::ClassInfo info(memoryObjectInfo, this, TestTy pe);
481 info.addMember(m_value);
482 }
483
484 T m_value;
485 };
486
487 TEST(MemoryInstrumentationTest, detectReportMemoryUsageMethod)
488 {
489 {
490 InstrumentationTestHelper helper;
491
492 OwnPtr<InstrumentedTemplate<String> > value(adoptPtr(new InstrumentedTem plate<String>("")));
493 InstrumentedOwner<InstrumentedTemplate<String>* > root(value.get());
494 helper.addRootObject(root);
495 EXPECT_EQ(sizeof(InstrumentedTemplate<String>) + sizeof(StringImpl), hel per.reportedSizeForAllTypes());
496 // FIXME: it is failing on Chromium Canary bots but works fine locally.
497 // EXPECT_EQ(2, helper.visitedObjects());
498 }
499 {
500 InstrumentationTestHelper helper;
501
502 OwnPtr<InstrumentedTemplate<NotInstrumented> > value(adoptPtr(new Instru mentedTemplate<NotInstrumented>("")));
503 InstrumentedOwner<InstrumentedTemplate<NotInstrumented>* > root(value.ge t());
504 helper.addRootObject(root);
505 EXPECT_EQ(sizeof(InstrumentedTemplate<NotInstrumented>), helper.reported SizeForAllTypes());
506 EXPECT_EQ(1u, helper.visitedObjects());
507 }
508 }
509
510 TEST(MemoryInstrumentationTest, vectorZeroInlineCapacity)
511 {
512 InstrumentationTestHelper helper;
513 InstrumentedOwner<Vector<int> > vectorOwner(16);
514 helper.addRootObject(vectorOwner);
515 EXPECT_EQ(16 * sizeof(int), helper.reportedSizeForAllTypes());
516 EXPECT_EQ(1u, helper.visitedObjects());
517 }
518
519 TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacity)
520 {
521 InstrumentationTestHelper helper;
522 InstrumentedOwner<Vector<int, 4> > vectorOwner;
523 helper.addRootObject(vectorOwner);
524 EXPECT_EQ(static_cast<size_t>(0), helper.reportedSizeForAllTypes());
525 EXPECT_EQ(0u, helper.visitedObjects());
526 }
527
528 TEST(MemoryInstrumentationTest, vectorFieldWithInlineCapacityResized)
529 {
530 InstrumentationTestHelper helper;
531 InstrumentedOwner<Vector<int, 4> > vectorOwner;
532 vectorOwner.m_value.reserveCapacity(8);
533 helper.addRootObject(vectorOwner);
534 EXPECT_EQ(8u * sizeof(int), helper.reportedSizeForAllTypes());
535 EXPECT_EQ(1u, helper.visitedObjects());
536 }
537
538 TEST(MemoryInstrumentationTest, heapAllocatedVectorWithInlineCapacity)
539 {
540 InstrumentationTestHelper helper;
541 InstrumentedOwner<OwnPtr<Vector<int, 4> > > vectorOwner;
542 vectorOwner.m_value = adoptPtr(new Vector<int, 4>());
543 helper.addRootObject(vectorOwner);
544 EXPECT_EQ(sizeof(Vector<int, 4>), helper.reportedSizeForAllTypes());
545 EXPECT_EQ(1u, helper.visitedObjects());
546 }
547
548 TEST(MemoryInstrumentationTest, heapAllocatedVectorWithInlineCapacityResized)
549 {
550 InstrumentationTestHelper helper;
551 InstrumentedOwner<OwnPtr<Vector<int, 4> > > vectorOwner;
552 vectorOwner.m_value = adoptPtr(new Vector<int, 4>());
553 vectorOwner.m_value->reserveCapacity(8);
554 helper.addRootObject(vectorOwner);
555 EXPECT_EQ(8u * sizeof(int) + sizeof(Vector<int, 4>), helper.reportedSizeForA llTypes());
556 EXPECT_EQ(2u, helper.visitedObjects());
557 }
558
559 TEST(MemoryInstrumentationTest, vectorWithInstrumentedType)
560 {
561 InstrumentationTestHelper helper;
562
563 typedef Vector<String> StringVector;
564 OwnPtr<StringVector> value = adoptPtr(new StringVector());
565 size_t count = 10;
566 for (size_t i = 0; i < count; ++i)
567 value->append("string");
568 InstrumentedOwner<StringVector* > root(value.get());
569 helper.addRootObject(root);
570 EXPECT_EQ(sizeof(StringVector) + sizeof(String) * value->capacity() + (sizeo f(StringImpl) + 6) * value->size(), helper.reportedSizeForAllTypes());
571 EXPECT_EQ(count + 2, (size_t)helper.visitedObjects());
572 }
573
574 TEST(MemoryInstrumentationTest, hashSetWithInstrumentedType)
575 {
576 InstrumentationTestHelper helper;
577
578 typedef HashSet<String> ValueType;
579 OwnPtr<ValueType> value = adoptPtr(new ValueType());
580 size_t count = 10;
581 for (size_t i = 0; i < count; ++i)
582 value->add(String::number(i));
583 InstrumentedOwner<ValueType* > root(value.get());
584 helper.addRootObject(root);
585 EXPECT_EQ(sizeof(ValueType) + sizeof(String) * value->capacity() + (sizeof(S tringImpl) + 1) * value->size(), helper.reportedSizeForAllTypes());
586 EXPECT_EQ(count + 1, (size_t)helper.visitedObjects());
587 }
588
589 TEST(MemoryInstrumentationTest, hashMapWithNotInstrumentedKeysAndValues)
590 {
591 InstrumentationTestHelper helper;
592
593 typedef HashMap<int, int> IntToIntMap;
594 OwnPtr<IntToIntMap> value = adoptPtr(new IntToIntMap());
595 size_t count = 10;
596 for (size_t i = 1; i <= count; ++i)
597 value->set(i, i);
598 InstrumentedOwner<IntToIntMap* > root(value.get());
599 helper.addRootObject(root);
600 EXPECT_EQ(sizeof(IntToIntMap) + sizeof(IntToIntMap::ValueType) * value->capa city(), helper.reportedSizeForAllTypes());
601 EXPECT_EQ(1u, helper.visitedObjects());
602 }
603
604 TEST(MemoryInstrumentationTest, hashMapWithInstrumentedKeys)
605 {
606 InstrumentationTestHelper helper;
607
608 typedef HashMap<String, int> StringToIntMap;
609 OwnPtr<StringToIntMap> value = adoptPtr(new StringToIntMap());
610 size_t count = 10;
611 for (size_t i = 10; i < 10 + count; ++i)
612 value->set(String::number(i), i);
613 InstrumentedOwner<StringToIntMap* > root(value.get());
614 helper.addRootObject(root);
615 EXPECT_EQ(sizeof(StringToIntMap) + sizeof(StringToIntMap::ValueType) * value ->capacity() + (sizeof(StringImpl) + 2) * value->size(), helper.reportedSizeForA llTypes());
616 EXPECT_EQ(count + 1, helper.visitedObjects());
617 }
618
619 TEST(MemoryInstrumentationTest, hashMapWithInstrumentedValues)
620 {
621 InstrumentationTestHelper helper;
622
623 typedef HashMap<int, String> IntToStringMap;
624 OwnPtr<IntToStringMap> value = adoptPtr(new IntToStringMap());
625 size_t count = 10;
626 for (size_t i = 10; i < 10 + count; ++i)
627 value->set(i, String::number(i));
628 InstrumentedOwner<IntToStringMap* > root(value.get());
629 helper.addRootObject(root);
630 EXPECT_EQ(sizeof(IntToStringMap) + sizeof(IntToStringMap::ValueType) * value ->capacity() + (sizeof(StringImpl) + 2) * value->size(), helper.reportedSizeForA llTypes());
631 EXPECT_EQ(count + 1, helper.visitedObjects());
632 }
633
634 TEST(MemoryInstrumentationTest, hashMapWithInstrumentedKeysAndValues)
635 {
636 InstrumentationTestHelper helper;
637
638 typedef HashMap<String, String> StringToStringMap;
639 OwnPtr<StringToStringMap> value = adoptPtr(new StringToStringMap());
640 size_t count = 10;
641 for (size_t i = 10; i < 10 + count; ++i)
642 value->set(String::number(count + i), String::number(i));
643 InstrumentedOwner<StringToStringMap* > root(value.get());
644 helper.addRootObject(root);
645 EXPECT_EQ(sizeof(StringToStringMap) + sizeof(StringToStringMap::ValueType) * value->capacity() + 2 * (sizeof(StringImpl) + 2) * value->size(), helper.report edSizeForAllTypes());
646 EXPECT_EQ(2u * count + 1, helper.visitedObjects());
647 }
648
649 class InstrumentedRefCounted : public RefCounted<InstrumentedRefCounted> {
650 public:
651 InstrumentedRefCounted() : m_notInstrumented(new NotInstrumented) { }
652 ~InstrumentedRefCounted() { delete m_notInstrumented; }
653
654 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
655 {
656 MemoryClassInfo info(memoryObjectInfo, this, TestType);
657 info.addMember(m_notInstrumented, "m_notInstrumented", WTF::RetainingPoi nter);
658 }
659 private:
660 NotInstrumented* m_notInstrumented;
661 };
662
663 TEST(MemoryInstrumentationTest, hashMapWithInstrumentedPointerKeysAndPointerValu es)
664 {
665 InstrumentationTestHelper helper;
666
667 typedef HashMap<RefPtr<InstrumentedRefCounted>, RefPtr<InstrumentedRefCounte d> > InstrumentedToInstrumentedMap;
668 OwnPtr<InstrumentedToInstrumentedMap> value(adoptPtr(new InstrumentedToInstr umentedMap()));
669 size_t count = 10;
670 for (size_t i = 0; i < count; ++i)
671 value->set(adoptRef(new InstrumentedRefCounted()), adoptRef(new Instrume ntedRefCounted()));
672 InstrumentedOwner<InstrumentedToInstrumentedMap* > root(value.get());
673 helper.addRootObject(root);
674 EXPECT_EQ(sizeof(InstrumentedToInstrumentedMap)
675 + sizeof(InstrumentedToInstrumentedMap::ValueType) * value->capacity()
676 + 2 * (sizeof(InstrumentedRefCounted) + sizeof(NotInstrumented)) * value ->size(),
677 helper.reportedSizeForAllTypes());
678 EXPECT_EQ(2u * 2u * count + 1, helper.visitedObjects());
679 }
680
681 TEST(MemoryInstrumentationTest, listHashSetWithInstrumentedType)
682 {
683 InstrumentationTestHelper helper;
684
685 typedef ListHashSet<String, 8> TestSet;
686 OwnPtr<TestSet> value = adoptPtr(new TestSet());
687 size_t count = 10;
688 for (size_t i = 0; i < count; ++i)
689 value->add(String::number(i));
690 InstrumentedOwner<TestSet* > root(value.get());
691 helper.addRootObject(root);
692 EXPECT_EQ(sizeof(TestSet) + sizeof(String) * value->capacity() + (sizeof(Str ingImpl) + 1 * sizeof(LChar)) * count +
693 sizeof(WTF::ListHashSetNodeAllocator<String, 8>) + sizeof(WTF::ListHashS etNode<String, 8>) * (count - 8),
694 helper.reportedSizeForAllTypes());
695 EXPECT_EQ(1 + count, helper.visitedObjects());
696 }
697
698 TEST(MemoryInstrumentationTest, listHashSetWithInstrumentedTypeAfterValuesRemova l)
699 {
700 InstrumentationTestHelper helper;
701
702 typedef ListHashSet<String, 8> TestSet;
703 OwnPtr<TestSet> value = adoptPtr(new TestSet());
704 size_t count = 20;
705 for (size_t i = 0; i < count; ++i)
706 value->add(String::number(i));
707 // Remove 10 values, 8 of which were allocated in the internal buffer.
708 for (size_t i = 0; i < 10; ++i)
709 value->remove(String::number(i));
710 InstrumentedOwner<TestSet* > root(value.get());
711 helper.addRootObject(root);
712 EXPECT_EQ(sizeof(TestSet) + sizeof(String) * value->capacity() + (sizeof(Str ingImpl) + 2 * sizeof(LChar)) * (count - 10) +
713 sizeof(WTF::ListHashSetNodeAllocator<String, 8>) + sizeof(WTF::ListHashS etNode<String, 8>) * (count - 10),
714 helper.reportedSizeForAllTypes());
715 EXPECT_EQ(1 + (count - 10), helper.visitedObjects());
716 }
717
718 class InstrumentedConvertibleToInt : public RefCounted<InstrumentedConvertibleTo Int> {
719 public:
720 InstrumentedConvertibleToInt() : m_notInstrumented(new NotInstrumented) { }
721 virtual ~InstrumentedConvertibleToInt() { delete m_notInstrumented; }
722
723 virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
724 {
725 MemoryClassInfo info(memoryObjectInfo, this, TestType);
726 info.addMember(m_notInstrumented);
727 }
728
729 operator int() const { return 2012; }
730
731 NotInstrumented* m_notInstrumented;
732 };
733
734 // This test checks if reportMemoryUsage method will be called on a class
735 // that can be implicitly cast to int. Currently objects of such classes are
736 // treated as integers when they are stored in a HashMap by value and
737 // reportMemoryUsage will not be called on them. We may fix that later.
738 TEST(MemoryInstrumentationTest, hashMapWithValuesConvertibleToInt)
739 {
740 InstrumentationTestHelper helper;
741
742 typedef HashMap<RefPtr<InstrumentedConvertibleToInt>, int> TestMap;
743 OwnPtr<TestMap> value(adoptPtr(new TestMap()));
744 size_t count = 10;
745 for (size_t i = 0; i < count; ++i)
746 value->set(adoptRef(new InstrumentedConvertibleToInt()), 0);
747 InstrumentedOwner<TestMap* > root(value.get());
748 helper.addRootObject(root);
749 EXPECT_EQ(sizeof(TestMap) + sizeof(TestMap::ValueType) * value->capacity() +
750 sizeof(InstrumentedConvertibleToInt) * count /* + sizeof(NotInstrumented ) * count */, helper.reportedSizeForAllTypes());
751 EXPECT_EQ(count + 1, helper.visitedObjects());
752 }
753
754 TEST(MemoryInstrumentationTest, hashMapWithEnumKeysAndInstrumentedValues)
755 {
756 InstrumentationTestHelper helper;
757
758 typedef HashMap<TestEnum, String> EnumToStringMap;
759 OwnPtr<EnumToStringMap> value(adoptPtr(new EnumToStringMap()));
760 size_t count = MY_ENUM_MAX;
761 for (size_t i = ONE; i <= count; ++i)
762 value->set(static_cast<TestEnum>(i), String::number(i));
763 InstrumentedOwner<EnumToStringMap* > root(value.get());
764 helper.addRootObject(root);
765 EXPECT_EQ(sizeof(EnumToStringMap)
766 + sizeof(EnumToStringMap::ValueType) * value->capacity()
767 + (sizeof(StringImpl) + 1) * value->size(),
768 helper.reportedSizeForAllTypes());
769 EXPECT_EQ(count + 1, helper.visitedObjects());
770 }
771
772 TEST(MemoryInstrumentationTest, hashCountedSetWithInstrumentedValues)
773 {
774 InstrumentationTestHelper helper;
775
776 typedef HashCountedSet<RefPtr<InstrumentedRefCounted> > TestSet;
777 OwnPtr<TestSet> set(adoptPtr(new TestSet()));
778 size_t count = 10;
779 for (size_t i = 0; i < count; ++i) {
780 RefPtr<InstrumentedRefCounted> instrumentedRefCounted = adoptRef(new Ins trumentedRefCounted());
781 for (size_t j = 0; j <= i; j++)
782 set->add(instrumentedRefCounted);
783 }
784 InstrumentedOwner<TestSet* > root(set.get());
785 helper.addRootObject(root);
786 EXPECT_EQ(sizeof(TestSet)
787 + sizeof(HashMap<RefPtr<InstrumentedRefCounted>, unsigned>::ValueType) * set->capacity()
788 + (sizeof(InstrumentedRefCounted) + sizeof(NotInstrumented)) * set->siz e(),
789 helper.reportedSizeForAllTypes());
790 EXPECT_EQ(2u * count + 1, helper.visitedObjects());
791 }
792
793 TEST(MemoryInstrumentationTest, arrayBuffer)
794 {
795 InstrumentationTestHelper helper;
796
797 typedef InstrumentedTemplate<RefPtr<ArrayBuffer> > ValueType;
798 ValueType value(ArrayBuffer::create(1000, sizeof(int)));
799 helper.addRootObject(value);
800 EXPECT_EQ(sizeof(int) * 1000 + sizeof(ArrayBuffer), helper.reportedSizeForAl lTypes());
801 EXPECT_EQ(2u, helper.visitedObjects());
802 EXPECT_EQ(2u, helper.linksCount(WTF::RetainingPointer));
803 }
804
805 class AncestorWithVirtualMethod {
806 public:
807 virtual char* data() { return m_data; }
808
809 private:
810 char m_data[10];
811 };
812
813 class ClassWithTwoAncestors : public AncestorWithVirtualMethod, public Instrumen ted {
814 public:
815 virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
816 {
817 MemoryClassInfo info(memoryObjectInfo, this, TestType);
818 Instrumented::reportMemoryUsage(memoryObjectInfo);
819 }
820 };
821
822 TEST(MemoryInstrumentationTest, instrumentedWithMultipleAncestors)
823 {
824 InstrumentationTestHelper helper;
825 OwnPtr<ClassWithTwoAncestors> instance = adoptPtr(new ClassWithTwoAncestors( ));
826 ClassWithTwoAncestors* descendantPointer = instance.get();
827 InstrumentedOwner<ClassWithTwoAncestors*> descendantPointerOwner(descendantP ointer);
828 Instrumented* ancestorPointer = descendantPointer;
829 InstrumentedOwner<Instrumented*> ancestorPointerOwner(ancestorPointer);
830 EXPECT_NE(static_cast<void*>(ancestorPointer), static_cast<void*>(descendant Pointer));
831
832 helper.addRootObject(descendantPointerOwner);
833 helper.addRootObject(ancestorPointerOwner);
834 EXPECT_EQ(sizeof(ClassWithTwoAncestors) + sizeof(NotInstrumented), helper.re portedSizeForAllTypes());
835 EXPECT_EQ(3u, helper.visitedObjects());
836 }
837
838 class CheckCountedObjectsClient : public MemoryInstrumentationTestClient {
839 public:
840 CheckCountedObjectsClient(const void* expectedPointer) : m_expectedPointer(e xpectedPointer), m_expectedPointerFound(false) { }
841 virtual bool checkCountedObject(const void* pointer)
842 {
843 EXPECT_EQ(pointer, m_expectedPointer);
844 m_expectedPointerFound = true;
845 return true;
846 }
847 bool expectedPointerFound() { return m_expectedPointerFound; }
848
849 private:
850 const void* m_expectedPointer;
851 bool m_expectedPointerFound;
852 };
853
854 TEST(MemoryInstrumentationTest, checkCountedObjectWithMultipleAncestors)
855 {
856 OwnPtr<ClassWithTwoAncestors> instance = adoptPtr(new ClassWithTwoAncestors( ));
857 instance->disposeOwnedObject();
858 ClassWithTwoAncestors* descendantPointer = instance.get();
859 InstrumentedOwner<ClassWithTwoAncestors*> descendantPointerOwner(descendantP ointer);
860 Instrumented* ancestorPointer = descendantPointer;
861 InstrumentedOwner<Instrumented*> ancestorPointerOwner(ancestorPointer);
862 EXPECT_NE(static_cast<void*>(ancestorPointer), static_cast<void*>(descendant Pointer));
863
864 CheckCountedObjectsClient client(instance.get());
865 InstrumentationTestImpl instrumentation(&client);
866 instrumentation.addRootObject(descendantPointerOwner);
867 instrumentation.addRootObject(ancestorPointerOwner);
868 EXPECT_TRUE(client.expectedPointerFound());
869 }
870
871 class TwoPointersToSameInsrumented {
872 public:
873 TwoPointersToSameInsrumented()
874 : m_ownPtr(adoptPtr(new ClassWithTwoAncestors()))
875 , m_baseClassPtr(m_ownPtr.get())
876 {
877 EXPECT_NE(static_cast<void*>(m_ownPtr.get()), static_cast<void*>(m_baseC lassPtr));
878 }
879 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
880 {
881 MemoryClassInfo info(memoryObjectInfo, this, TestType);
882 info.addMember(m_ownPtr);
883 info.addMember(m_baseClassPtr);
884 }
885
886 private:
887 OwnPtr<ClassWithTwoAncestors> m_ownPtr;
888 Instrumented* m_baseClassPtr;
889 };
890
891 class CountLinksFromInstrumentedObject : public MemoryInstrumentationTestClient {
892 public:
893 CountLinksFromInstrumentedObject() : m_linkCount(0) { }
894 virtual void reportEdge(const void*, const char* name, MemberType) OVERRIDE
895 {
896 if (name && !strcmp("m_notInstrumented", name))
897 m_linkCount++;
898 }
899 int linkCount() const { return m_linkCount; }
900
901 private:
902 int m_linkCount;
903 };
904
905
906 TEST(MemoryInstrumentationTest, doNotReportEdgeTwice)
907 {
908 OwnPtr<TwoPointersToSameInsrumented> instance = adoptPtr(new TwoPointersToSa meInsrumented());
909
910 CountLinksFromInstrumentedObject client;
911 InstrumentationTestImpl instrumentation(&client);
912 instrumentation.addRootObject(instance.get());
913 EXPECT_EQ(1, client.linkCount());
914 }
915
916 class DerivedClass : public Instrumented {
917 public:
918 size_t m_member;
919 };
920
921 TEST(MemoryInstrumentationTest, detectBaseClassInstrumentation)
922 {
923 OwnPtr<DerivedClass> instance = adoptPtr(new DerivedClass());
924
925 InstrumentationTestHelper helper;
926 helper.addRootObject(instance.get(), TestType);
927 EXPECT_EQ(sizeof(Instrumented) + sizeof(NotInstrumented), helper.reportedSiz eForAllTypes());
928 EXPECT_EQ(2u, helper.visitedObjects());
929 }
930
931 } // namespace
OLDNEW
« no previous file with comments | « Source/wtf/MemoryObjectInfo.h ('k') | Source/wtf/text/AtomicString.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698