| /* | 
 |  * Copyright 2014 Google, Inc | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "SkSmallAllocator.h" | 
 | #include "SkTypes.h" | 
 | #include "Test.h" | 
 |  | 
 | class CountingClass { | 
 | public: | 
 |     CountingClass() { | 
 |         kCount++; | 
 |     } | 
 |  | 
 |     ~CountingClass() { | 
 |         kCount--; | 
 |     } | 
 |  | 
 |     static int GetCount() { return kCount; } | 
 |  | 
 | private: | 
 |     static int kCount; | 
 | }; | 
 |  | 
 | int CountingClass::kCount; | 
 |  | 
 | template<uint32_t kMaxObjects, size_t kBytes> void test_allocator(skiatest::Reporter* reporter) { | 
 |     { | 
 |         SkSmallAllocator<kMaxObjects, kBytes> alloc; | 
 |         for (uint32_t i = 0; i < kMaxObjects; ++i) { | 
 |             CountingClass* c = alloc.template createT<CountingClass>(); | 
 |             REPORTER_ASSERT(reporter, c != NULL); | 
 |             REPORTER_ASSERT(reporter, CountingClass::GetCount() == static_cast<int>(i+1)); | 
 |         } | 
 |     } | 
 |     REPORTER_ASSERT(reporter, CountingClass::GetCount() == 0); | 
 | } | 
 |  | 
 | // Tests that ensure that the destructor is called, whether the objects | 
 | // were created in fStorage or on the heap. | 
 | DEF_TEST(SmallAllocator_destructor, reporter) { | 
 |     // Four times as many bytes as objects will never require any heap | 
 |     // allocations (since SkAlign4(sizeof(CountingClass)) == 4 and the allocator | 
 |     // will stop once it reaches kMaxObjects). | 
 |     test_allocator<5, 20>(reporter); | 
 |     test_allocator<10, 40>(reporter); | 
 |     test_allocator<20, 80>(reporter); | 
 |  | 
 | #ifndef SK_DEBUG | 
 |     // Allowing less bytes than objects means some will be allocated on the | 
 |     // heap. Don't run these in debug where we assert. | 
 |     test_allocator<50, 20>(reporter); | 
 |     test_allocator<100, 20>(reporter); | 
 | #endif | 
 | } | 
 |  | 
 | class Dummy { | 
 | }; | 
 |  | 
 | class DummyContainer { | 
 | public: | 
 |     explicit DummyContainer(Dummy* d) | 
 |         :fDummy(d) | 
 |     {} | 
 |  | 
 |     Dummy* getDummy() const { return fDummy; } | 
 |  | 
 | private: | 
 |     Dummy* fDummy; | 
 | }; | 
 |  | 
 | // Test that using a createT with a constructor taking a pointer as a | 
 | // parameter works as expected. | 
 | DEF_TEST(SmallAllocator_pointer, reporter) { | 
 |     SkSmallAllocator<1, 8> alloc; | 
 |     Dummy d; | 
 |     DummyContainer* container = alloc.createT<DummyContainer>(&d); | 
 |     REPORTER_ASSERT(reporter, container != NULL); | 
 |     REPORTER_ASSERT(reporter, container->getDummy() == &d); | 
 | } |