24
#include "precompiled.hpp"
25
#include "memory/resourceArea.hpp"
26
#include "utilities/growableArray.hpp"
27
#include "unittest.hpp"
29
struct WithEmbeddedArray {
31
GrowableArray<int> _a;
34
WithEmbeddedArray(int initial_max) : _a(initial_max) {}
36
WithEmbeddedArray(Arena* arena, int initial_max) : _a(arena, initial_max, 0, 0) {}
38
WithEmbeddedArray(int initial_max, MEMFLAGS memflags) : _a(initial_max, memflags) {
39
assert(memflags != mtNone, "test requirement");
41
WithEmbeddedArray(const GrowableArray<int>& other) : _a(other) {}
45
class GrowableArrayTest : public ::testing::Test {
49
static bool elements_on_C_heap(const GrowableArray<E>* array) {
50
return array->on_C_heap();
53
static bool elements_on_resource_area(const GrowableArray<E>* array) {
54
return array->on_resource_area();
57
static bool elements_on_arena(const GrowableArray<E>* array) {
58
return array->on_arena();
61
template <typename ArrayClass>
62
static void test_append(ArrayClass* a) {
64
for (int i = 0; i < 10; i++) {
69
ASSERT_EQ(a->length(), 10);
72
for (int i = 0; i < 10; i++) {
73
EXPECT_EQ(a->at(i), i);
77
template <typename ArrayClass>
78
static void test_clear(ArrayClass* a) {
80
for (int i = 0; i < 10; i++) {
85
ASSERT_EQ(a->length(), 10);
86
ASSERT_EQ(a->is_empty(), false);
92
ASSERT_EQ(a->length(), 0);
93
ASSERT_EQ(a->is_empty(), true);
99
ASSERT_EQ(a->length(), 1);
100
ASSERT_EQ(a->is_empty(), false);
106
ASSERT_EQ(a->length(), 0);
107
ASSERT_EQ(a->is_empty(), true);
110
template <typename ArrayClass>
111
static void test_iterator(ArrayClass* a) {
113
for (int i = 0; i < 10; i++) {
119
for (GrowableArrayIterator<int> i = a->begin(); i != a->end(); ++i) {
120
ASSERT_EQ(*i, counter++);
124
ASSERT_EQ(counter, 10);
127
template <typename ArrayClass>
128
static void test_capacity(ArrayClass* a) {
129
ASSERT_EQ(a->length(), 0);
131
ASSERT_EQ(a->length(), 0);
132
ASSERT_EQ(a->capacity(), 50);
133
for (int i = 0; i < 50; ++i) {
136
ASSERT_EQ(a->length(), 50);
137
ASSERT_EQ(a->capacity(), 50);
139
ASSERT_EQ(a->length(), 51);
140
int capacity = a->capacity();
141
ASSERT_GE(capacity, 51);
142
for (int i = 0; i < 30; ++i) {
145
ASSERT_EQ(a->length(), 21);
146
ASSERT_EQ(a->capacity(), capacity);
148
ASSERT_EQ(a->length(), 21);
149
ASSERT_EQ(a->capacity(), 21);
152
ASSERT_EQ(a->length(), 21);
153
ASSERT_EQ(a->capacity(), 50);
156
ASSERT_EQ(a->length(), 0);
157
ASSERT_EQ(a->capacity(), 50);
160
ASSERT_EQ(a->length(), 0);
161
ASSERT_EQ(a->capacity(), 0);
164
template <typename ArrayClass>
165
static void test_copy1(ArrayClass* a) {
166
ASSERT_EQ(a->length(), 1);
167
ASSERT_EQ(a->at(0), 1);
173
GrowableArray<int> c(*a);
175
ASSERT_EQ(c.length(), 1);
176
ASSERT_EQ(c.at(0), 1);
181
WithEmbeddedArray c(*a);
183
ASSERT_EQ(c._a.length(), 1);
184
ASSERT_EQ(c._a.at(0), 1);
188
template <typename ArrayClass>
189
static void test_assignment1(ArrayClass* a) {
190
ASSERT_EQ(a->length(), 1);
191
ASSERT_EQ(a->at(0), 1);
198
GrowableArray<int> c(1);
201
ASSERT_EQ(c.length(), 1);
202
ASSERT_EQ(c.at(0), 1);
208
GrowableArray<int> c(&arena, 1, 0, 0);
211
ASSERT_EQ(c.length(), 1);
212
ASSERT_EQ(c.at(0), 1);
218
WithEmbeddedArray c(1);
221
ASSERT_EQ(c._a.length(), 1);
222
ASSERT_EQ(c._a.at(0), 1);
228
WithEmbeddedArray c(&arena, 1);
231
ASSERT_EQ(c._a.length(), 1);
232
ASSERT_EQ(c._a.at(0), 1);
244
template <typename ArrayClass>
245
static void do_test(ArrayClass* a, TestEnum test) {
264
fatal("Missing dispatch");
270
enum TestNoCHeapEnum {
275
template <typename ArrayClass>
276
static void do_test(ArrayClass* a, TestNoCHeapEnum test) {
287
fatal("Missing dispatch");
295
Append1ClearAndDeallocate,
299
template <typename ArrayClass>
300
static void do_modify(ArrayClass* a, ModifyEnum modify) {
311
case Append1ClearAndDeallocate:
313
a->clear_and_deallocate();
321
fatal("Missing dispatch");
326
static const int Max0 = 0;
327
static const int Max1 = 1;
329
template <typename ArrayClass, typename T>
330
static void modify_and_test(ArrayClass* array, ModifyEnum modify, T test) {
331
do_modify(array, modify);
332
do_test(array, test);
335
template <typename T>
336
static void with_no_cheap_array(int max, ModifyEnum modify, T test) {
340
GrowableArray<int>* a = new GrowableArray<int>(max);
341
modify_and_test(a, modify, test);
356
GrowableArray<int> a(max);
357
modify_and_test(&a, modify, test);
363
GrowableArray<int> a(&arena, max, 0, 0);
364
modify_and_test(&a, modify, test);
370
WithEmbeddedArray w(max);
371
modify_and_test(&w._a, modify, test);
377
WithEmbeddedArray w(&arena, max);
378
modify_and_test(&w._a, modify, test);
382
static void with_cheap_array(int max, ModifyEnum modify, TestEnum test) {
388
GrowableArray<int>* a = new (mtTest) GrowableArray<int>(max, mtTest);
389
modify_and_test(a, modify, test);
395
GrowableArray<int> a(max, mtTest);
396
modify_and_test(&a, modify, test);
401
WithEmbeddedArray w(max, mtTest);
402
modify_and_test(&w._a, modify, test);
406
static void with_all_types(int max, ModifyEnum modify, TestEnum test) {
407
with_no_cheap_array(max, modify, test);
408
with_cheap_array(max, modify, test);
411
static void with_all_types_empty(TestEnum test) {
412
with_all_types(Max0, NoModify, test);
415
static void with_all_types_max_set(TestEnum test) {
416
with_all_types(Max1, NoModify, test);
419
static void with_all_types_cleared(TestEnum test) {
420
with_all_types(Max1, Append1Clear, test);
423
static void with_all_types_clear_and_deallocated(TestEnum test) {
424
with_all_types(Max1, Append1ClearAndDeallocate, test);
427
static void with_all_types_all_0(TestEnum test) {
428
with_all_types_empty(test);
429
with_all_types_max_set(test);
430
with_all_types_cleared(test);
431
with_all_types_clear_and_deallocated(test);
434
static void with_no_cheap_array_append1(TestNoCHeapEnum test) {
435
with_no_cheap_array(Max0, Append1, test);
439
TEST_VM_F(GrowableArrayTest, append) {
440
with_all_types_all_0(Append);
443
TEST_VM_F(GrowableArrayTest, clear) {
444
with_all_types_all_0(Clear);
447
TEST_VM_F(GrowableArrayTest, capacity) {
448
with_all_types_all_0(Capacity);
451
TEST_VM_F(GrowableArrayTest, iterator) {
452
with_all_types_all_0(Iterator);
455
TEST_VM_F(GrowableArrayTest, copy) {
456
with_no_cheap_array_append1(Copy1);
459
TEST_VM_F(GrowableArrayTest, assignment) {
460
with_no_cheap_array_append1(Assignment1);
464
TEST_VM_F(GrowableArrayTest, where) {
465
WithEmbeddedArray s(1, mtTest);
466
ASSERT_FALSE(s._a.allocated_on_C_heap());
467
ASSERT_TRUE(elements_on_C_heap(&s._a));
472
GrowableArray<int>* a = new GrowableArray<int>();
473
ASSERT_TRUE(a->allocated_on_res_area());
474
ASSERT_TRUE(elements_on_resource_area(a));
488
GrowableArray<int>* a = new (mtTest) GrowableArray<int>(0, mtTest);
489
ASSERT_TRUE(a->allocated_on_C_heap());
490
ASSERT_TRUE(elements_on_C_heap(a));
500
GrowableArray<int> a(0);
501
ASSERT_TRUE(a.allocated_on_stack_or_embedded());
502
ASSERT_TRUE(elements_on_resource_area(&a));
507
GrowableArray<int> a(0, mtTest);
508
ASSERT_TRUE(a.allocated_on_stack_or_embedded());
509
ASSERT_TRUE(elements_on_C_heap(&a));
515
GrowableArray<int> a(&arena, 0, 0, 0);
516
ASSERT_TRUE(a.allocated_on_stack_or_embedded());
517
ASSERT_TRUE(elements_on_arena(&a));
523
WithEmbeddedArray w(0);
524
ASSERT_TRUE(w._a.allocated_on_stack_or_embedded());
525
ASSERT_TRUE(elements_on_resource_area(&w._a));
530
WithEmbeddedArray w(0, mtTest);
531
ASSERT_TRUE(w._a.allocated_on_stack_or_embedded());
532
ASSERT_TRUE(elements_on_C_heap(&w._a));
538
WithEmbeddedArray w(&arena, 0);
539
ASSERT_TRUE(w._a.allocated_on_stack_or_embedded());
540
ASSERT_TRUE(elements_on_arena(&w._a));
544
TEST_VM_ASSERT_MSG(GrowableArrayAssertingTest, copy_with_embedded_cheap,
545
"assert.!on_C_heap... failed: Copying of CHeap arrays not supported") {
546
WithEmbeddedArray s(1, mtTest);
548
WithEmbeddedArray c(s);
551
TEST_VM_ASSERT_MSG(GrowableArrayAssertingTest, assignment_with_embedded_cheap,
552
"assert.!on_C_heap... failed: Assignment of CHeap arrays not supported") {
553
WithEmbeddedArray s(1, mtTest);
554
WithEmbeddedArray c(1, mtTest);
562
TEST(GrowableArrayCHeap, sanity) {
565
GrowableArrayCHeap<int, mtTest> a(0);
567
ASSERT_TRUE(a.allocated_on_stack_or_embedded());
569
ASSERT_TRUE(a.is_empty());
572
ASSERT_FALSE(a.is_empty());
573
ASSERT_EQ(a.at(0), 1);
578
GrowableArrayCHeap<int, mtTest>* a = new GrowableArrayCHeap<int, mtTest>(0);
580
ASSERT_TRUE(a->allocated_on_C_heap());
582
ASSERT_TRUE(a->is_empty());
585
ASSERT_FALSE(a->is_empty());
586
ASSERT_EQ(a->at(0), 1);
592
GrowableArrayCHeap<int, mtTest>* a = new (std::nothrow) GrowableArrayCHeap<int, mtTest>(0);
594
ASSERT_TRUE(a->allocated_on_C_heap());
596
ASSERT_TRUE(a->is_empty());
599
ASSERT_FALSE(a->is_empty());
600
ASSERT_EQ(a->at(0), 1);
605
TEST(GrowableArrayCHeap, find_if) {
609
GrowableArrayCHeap<Element, mtTest> array;
615
int index = array.find_if([&](const Element& elem) {
616
return elem.value == 1;
622
int index = array.find_if([&](const Element& elem) {
623
return elem.value > 1;
629
int index = array.find_if([&](const Element& elem) {
630
return elem.value == 4;
632
ASSERT_EQ(index, -1);
636
TEST(GrowableArrayCHeap, find_from_end_if) {
640
GrowableArrayCHeap<Element, mtTest> array;
646
int index = array.find_from_end_if([&](const Element& elem) {
647
return elem.value == 1;
653
int index = array.find_from_end_if([&](const Element& elem) {
654
return elem.value > 1;
660
int index = array.find_from_end_if([&](const Element& elem) {
661
return elem.value == 4;
663
ASSERT_EQ(index, -1);
667
TEST(GrowableArrayCHeap, returning_references_works_as_expected) {
668
GrowableArrayCHeap<int, mtTest> arr(8, 8, -1);
669
int& x = arr.at_grow(9, -1);
670
EXPECT_EQ(-1, arr.at(9));
673
EXPECT_EQ(2, arr.at(9));
675
EXPECT_EQ(2, arr.at(9));
677
EXPECT_EQ(5, arr.at(9));
679
int y = arr.at_grow(10, -1);
680
EXPECT_EQ(-1, arr.at(10));
682
EXPECT_EQ(-1, arr.at(10));
684
GrowableArrayCHeap<int, mtTest> arr2(1, 1, -1);
685
int& first = arr2.first();
686
int& last = arr2.last();
687
EXPECT_EQ(-1, first);