2 * Copyright (C) 2016 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "object_heap.h"
37 TEST(ObjectHeapTest, Init)
40 struct object_base base;
44 struct object_heap heap = {
55 EXPECT_EQ(0, object_heap_init(&heap, sizeof(test_object), 0xffffffff));
57 EXPECT_EQ(sizeof(test_object), (size_t)heap.object_size);
58 EXPECT_EQ(OBJECT_HEAP_OFFSET_MASK, heap.id_offset);
59 EXPECT_EQ(0, heap.next_free);
60 EXPECT_LE(1, heap.heap_increment);
61 EXPECT_EQ(heap.heap_increment, heap.heap_size);
62 EXPECT_PTR(heap.bucket);
63 EXPECT_LE(1, heap.num_buckets);
65 object_heap_destroy(&heap);
67 EXPECT_PTR_NULL(heap.bucket);
68 EXPECT_EQ(0, heap.heap_size);
69 EXPECT_GT(0, heap.next_free);
71 EXPECT_EQ(0, object_heap_init(&heap, sizeof(test_object), 0x0));
73 EXPECT_EQ(sizeof(test_object), (size_t)heap.object_size);
74 EXPECT_EQ(0, heap.id_offset);
75 EXPECT_EQ(0, heap.next_free);
76 EXPECT_LE(1, heap.heap_increment);
77 EXPECT_EQ(heap.heap_increment, heap.heap_size);
78 EXPECT_PTR(heap.bucket);
79 EXPECT_LE(1, heap.num_buckets);
81 object_heap_destroy(&heap);
83 EXPECT_PTR_NULL(heap.bucket);
84 EXPECT_EQ(0, heap.heap_size);
85 EXPECT_GT(0, heap.next_free);
88 TEST(ObjectHeapTest, AllocateAndLookup)
90 struct object_heap heap = {};
92 ASSERT_EQ(0, object_heap_init(&heap, sizeof(object_base), 0));
94 int nbuckets = heap.num_buckets;
96 for (int i(0); i < heap.heap_increment * nbuckets * 2; ++i)
98 int id = object_heap_allocate(&heap);
101 if (expect % heap.heap_increment == 0)
103 EXPECT_EQ(expect, heap.next_free);
106 EXPECT_EQ(nbuckets * 2, heap.num_buckets);
108 for (int i(0); i < heap.heap_increment * nbuckets * 2; ++i)
110 object_base_p obj = object_heap_lookup(&heap, i);
112 object_heap_free(&heap, obj);
113 obj = object_heap_lookup(&heap, i);
114 EXPECT_PTR_NULL(obj);
117 object_heap_destroy(&heap);
120 TEST(ObjectHeapTest, Iterate)
122 struct object_heap heap = {};
123 object_heap_iterator iter;
125 ASSERT_EQ(0, object_heap_init(&heap, sizeof(object_base), 0));
127 EXPECT_PTR_NULL(object_heap_first(&heap, &iter));
128 EXPECT_PTR_NULL(object_heap_next(&heap, &iter));
130 std::vector<object_base_p> objects(256, NULL);
131 std::generate(objects.begin(), objects.end(),
132 [&]{ return object_heap_lookup(&heap, object_heap_allocate(&heap)); });
134 // iterate all objects starting at first
135 object_base_p current = object_heap_first(&heap, &iter);
136 EXPECT_EQ(0, current->id);
137 EXPECT_TRUE(objects.front() == current);
139 while ((current = object_heap_next(&heap, &iter)) && i < objects.size())
141 EXPECT_EQ(i, (size_t)current->id);
142 EXPECT_TRUE(objects[i++] == current);
144 EXPECT_PTR_NULL(current);
145 EXPECT_EQ(i, objects.size());
146 EXPECT_PTR_NULL(object_heap_next(&heap, &iter));
148 // get "first" and free it
149 current = object_heap_first(&heap, &iter);
150 ASSERT_TRUE(objects[0] == current);
151 object_heap_free(&heap, current);
154 // get "first" again and ensure it's our second allocated object
155 current = object_heap_first(&heap, &iter);
156 EXPECT_TRUE(objects[1] == current);
158 // free the object after "current" and ensure "next"
159 // returns the one after it.
160 object_heap_free(&heap, objects[2]);
162 current = object_heap_next(&heap, &iter);
163 EXPECT_TRUE(objects[3] == current);
166 std::for_each(objects.begin(), objects.end(),
167 [&](object_base_p o){ object_heap_free(&heap, o); });
169 object_heap_destroy(&heap);
172 TEST(ObjectHeapTest, DataIntegrity)
175 struct object_base base;
179 typedef test_object *test_object_p;
180 struct object_heap heap = {};
182 ASSERT_EQ(0, object_heap_init(&heap, sizeof(test_object), 0));
184 std::time_t seed = std::time(0);
186 RecordProperty("seed", seed);
188 std::vector<int> values;
190 auto generator = [&]{
191 int id = object_heap_allocate(&heap);
192 object_base_p base = object_heap_lookup(&heap, id);
193 test_object_p object = (test_object_p)base;
194 object->i = std::rand();
195 values.push_back(object->i);
199 std::vector<test_object*> objects(71, NULL);
200 std::generate(objects.begin(), objects.end(), generator);
202 ASSERT_EQ(objects.size(), values.size());
204 auto validator = [&](test_object_p object) {
205 object_base_p base = object_heap_lookup(&heap, object->base.id);
206 EXPECT_TRUE(&object->base == base);
207 EXPECT_EQ(object->base.id, base->id);
208 test_object_p lo = (test_object_p)base;
209 ASSERT_GT(values.size(), (size_t)lo->base.id);
210 EXPECT_EQ(values[lo->base.id], lo->i);
213 std::for_each(objects.begin(), objects.end(), validator);
215 std::for_each(objects.begin(), objects.end(),
216 [&](test_object_p o){ object_heap_free(&heap, &o->base); });
217 object_heap_destroy(&heap);
220 TEST(ObjectHeapTest, OffsetID)
222 ASSERT_LT(0, (OBJECT_HEAP_OFFSET_MASK >> 24));
223 for (int i(0); i <= (OBJECT_HEAP_OFFSET_MASK >> 24); ++i)
225 struct object_heap heap = {};
226 int offset = i << 24;
230 << "offset=0x" << std::hex << std::setfill('0')
231 << std::setw(8) << offset << std::dec);
233 ASSERT_EQ(0, object_heap_init(&heap, sizeof(object_base), offset));
235 EXPECT_EQ(offset & OBJECT_HEAP_OFFSET_MASK, heap.id_offset);
237 std::vector<object_base_p> objects(1024, NULL);
238 std::generate(objects.begin(), objects.end(),
239 [&]{ return object_heap_lookup(&heap, object_heap_allocate(&heap)); });
241 for (int idx(0); (size_t)idx < objects.size(); ++idx)
242 EXPECT_EQ(offset + idx, objects[idx]->id);
244 std::for_each(objects.begin(), objects.end(),
245 [&](object_base_p o){ object_heap_free(&heap, o); });
246 object_heap_destroy(&heap);