Home | History | Annotate | Download | only in platform
      1 /*
      2  * Copyright (C) 2013 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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "platform/PODFreeListArena.h"
     28 
     29 #include "platform/testing/ArenaTestHelpers.h"
     30 #include "wtf/FastMalloc.h"
     31 #include "wtf/RefPtr.h"
     32 #include "wtf/Vector.h"
     33 
     34 #include <gtest/gtest.h>
     35 
     36 namespace WebCore {
     37 
     38 using ArenaTestHelpers::TrackedAllocator;
     39 
     40 namespace {
     41 
     42 // A couple of simple structs to allocate.
     43 struct TestClass1 {
     44     TestClass1()
     45         : x(0), y(0), z(0), w(1) { }
     46 
     47     float x, y, z, w;
     48 };
     49 
     50 struct TestClass2 {
     51     TestClass2()
     52         : padding(0)
     53     {
     54         static int TestIds = 0;
     55         id = TestIds++;
     56     }
     57     int id;
     58     int padding;
     59 };
     60 
     61 } // anonymous namespace
     62 
     63 class PODFreeListArenaTest : public testing::Test {
     64 protected:
     65     int getFreeListSize(const PassRefPtr<PODFreeListArena<TestClass1> > arena) const
     66     {
     67         return arena->getFreeListSizeForTesting();
     68     }
     69 };
     70 
     71 // Make sure the arena can successfully allocate from more than one
     72 // region.
     73 TEST_F(PODFreeListArenaTest, CanAllocateFromMoreThanOneRegion)
     74 {
     75     RefPtr<TrackedAllocator> allocator = TrackedAllocator::create();
     76     RefPtr<PODFreeListArena<TestClass1> > arena = PODFreeListArena<TestClass1>::create(allocator);
     77     int numIterations = 10 * PODArena::DefaultChunkSize / sizeof(TestClass1);
     78     for (int i = 0; i < numIterations; ++i)
     79         arena->allocateObject();
     80     EXPECT_GT(allocator->numRegions(), 1);
     81 }
     82 
     83 // Make sure the arena frees all allocated regions during destruction.
     84 TEST_F(PODFreeListArenaTest, FreesAllAllocatedRegions)
     85 {
     86     RefPtr<TrackedAllocator> allocator = TrackedAllocator::create();
     87     {
     88         RefPtr<PODFreeListArena<TestClass1> > arena = PODFreeListArena<TestClass1>::create(allocator);
     89         for (int i = 0; i < 3; i++)
     90             arena->allocateObject();
     91         EXPECT_GT(allocator->numRegions(), 0);
     92     }
     93     EXPECT_TRUE(allocator->isEmpty());
     94 }
     95 
     96 // Make sure the arena runs constructors of the objects allocated within.
     97 TEST_F(PODFreeListArenaTest, RunsConstructorsOnNewObjects)
     98 {
     99     RefPtr<PODFreeListArena<TestClass1> > arena = PODFreeListArena<TestClass1>::create();
    100     for (int i = 0; i < 10000; i++) {
    101         TestClass1* tc1 = arena->allocateObject();
    102         EXPECT_EQ(0, tc1->x);
    103         EXPECT_EQ(0, tc1->y);
    104         EXPECT_EQ(0, tc1->z);
    105         EXPECT_EQ(1, tc1->w);
    106     }
    107 }
    108 
    109 // Make sure the arena runs constructors of the objects allocated within.
    110 TEST_F(PODFreeListArenaTest, RunsConstructorsOnReusedObjects)
    111 {
    112     std::set<TestClass1*> objects;
    113     RefPtr<PODFreeListArena<TestClass1> > arena = PODFreeListArena<TestClass1>::create();
    114     for (int i = 0; i < 100; i++) {
    115         TestClass1* tc1 = arena->allocateObject();
    116         tc1->x = 100;
    117         tc1->y = 101;
    118         tc1->z = 102;
    119         tc1->w = 103;
    120 
    121         objects.insert(tc1);
    122     }
    123     for (std::set<TestClass1*>::iterator it = objects.begin(); it != objects.end(); ++it) {
    124         arena->freeObject(*it);
    125     }
    126     for (int i = 0; i < 100; i++) {
    127         TestClass1* cur = arena->allocateObject();
    128         EXPECT_TRUE(objects.find(cur) != objects.end());
    129         EXPECT_EQ(0, cur->x);
    130         EXPECT_EQ(0, cur->y);
    131         EXPECT_EQ(0, cur->z);
    132         EXPECT_EQ(1, cur->w);
    133 
    134         objects.erase(cur);
    135     }
    136 }
    137 
    138 // Make sure freeObject puts the object in the free list.
    139 TEST_F(PODFreeListArenaTest, AddsFreedObjectsToFreedList)
    140 {
    141     std::vector<TestClass1*> objects;
    142     RefPtr<PODFreeListArena<TestClass1> > arena = PODFreeListArena<TestClass1>::create();
    143     for (int i = 0; i < 100; i++) {
    144         objects.push_back(arena->allocateObject());
    145     }
    146     for (std::vector<TestClass1*>::iterator it = objects.begin(); it != objects.end(); ++it) {
    147         arena->freeObject(*it);
    148     }
    149     EXPECT_EQ(100, getFreeListSize(arena));
    150 }
    151 
    152 // Make sure allocations use previously freed memory.
    153 TEST_F(PODFreeListArenaTest, ReusesPreviouslyFreedObjects)
    154 {
    155     std::set<TestClass2*> objects;
    156     RefPtr<PODFreeListArena<TestClass2> > arena = PODFreeListArena<TestClass2>::create();
    157     for (int i = 0; i < 100; i++) {
    158         objects.insert(arena->allocateObject());
    159     }
    160     for (std::set<TestClass2*>::iterator it = objects.begin(); it != objects.end(); ++it) {
    161         arena->freeObject(*it);
    162     }
    163     for (int i = 0; i < 100; i++) {
    164         TestClass2* cur = arena->allocateObject();
    165         EXPECT_TRUE(objects.find(cur) != objects.end());
    166         EXPECT_TRUE(cur->id >= 100 && cur->id < 200);
    167         objects.erase(cur);
    168     }
    169 }
    170 
    171 } // namespace WebCore
    172