1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/block_allocator.h"
16
17 #include "gtest/gtest.h"
18
19 namespace tint {
20 namespace {
21
22 struct LifetimeCounter {
LifetimeCountertint::__anonc6898c5b0111::LifetimeCounter23 explicit LifetimeCounter(size_t* count) : count_(count) { (*count)++; }
~LifetimeCountertint::__anonc6898c5b0111::LifetimeCounter24 ~LifetimeCounter() { (*count_)--; }
25
26 size_t* const count_;
27 };
28
29 using BlockAllocatorTest = testing::Test;
30
TEST_F(BlockAllocatorTest,Empty)31 TEST_F(BlockAllocatorTest, Empty) {
32 using Allocator = BlockAllocator<int>;
33
34 Allocator allocator;
35
36 for (int* i : allocator.Objects()) {
37 (void)i;
38 if ((true)) { // Workaround for "error: loop will run at most once"
39 FAIL() << "BlockAllocator should be empty";
40 }
41 }
42 for (int* i : static_cast<const Allocator&>(allocator).Objects()) {
43 (void)i;
44 if ((true)) { // Workaround for "error: loop will run at most once"
45 FAIL() << "BlockAllocator should be empty";
46 }
47 }
48 }
49
TEST_F(BlockAllocatorTest,ObjectLifetime)50 TEST_F(BlockAllocatorTest, ObjectLifetime) {
51 using Allocator = BlockAllocator<LifetimeCounter>;
52
53 size_t count = 0;
54 {
55 Allocator allocator;
56 EXPECT_EQ(count, 0u);
57 allocator.Create(&count);
58 EXPECT_EQ(count, 1u);
59 allocator.Create(&count);
60 EXPECT_EQ(count, 2u);
61 allocator.Create(&count);
62 EXPECT_EQ(count, 3u);
63 }
64 EXPECT_EQ(count, 0u);
65 }
66
TEST_F(BlockAllocatorTest,MoveConstruct)67 TEST_F(BlockAllocatorTest, MoveConstruct) {
68 using Allocator = BlockAllocator<LifetimeCounter>;
69
70 size_t count = 0;
71
72 {
73 Allocator allocator_a;
74 for (int i = 0; i < 10; i++) {
75 allocator_a.Create(&count);
76 }
77 EXPECT_EQ(count, 10u);
78
79 Allocator allocator_b{std::move(allocator_a)};
80 EXPECT_EQ(count, 10u);
81 }
82
83 EXPECT_EQ(count, 0u);
84 }
85
TEST_F(BlockAllocatorTest,MoveAssign)86 TEST_F(BlockAllocatorTest, MoveAssign) {
87 using Allocator = BlockAllocator<LifetimeCounter>;
88
89 size_t count_a = 0;
90 size_t count_b = 0;
91
92 {
93 Allocator allocator_a;
94 for (int i = 0; i < 10; i++) {
95 allocator_a.Create(&count_a);
96 }
97 EXPECT_EQ(count_a, 10u);
98
99 Allocator allocator_b;
100 for (int i = 0; i < 10; i++) {
101 allocator_b.Create(&count_b);
102 }
103 EXPECT_EQ(count_b, 10u);
104
105 allocator_b = std::move(allocator_a);
106 EXPECT_EQ(count_a, 10u);
107 EXPECT_EQ(count_b, 0u);
108 }
109
110 EXPECT_EQ(count_a, 0u);
111 EXPECT_EQ(count_b, 0u);
112 }
113
TEST_F(BlockAllocatorTest,ObjectOrder)114 TEST_F(BlockAllocatorTest, ObjectOrder) {
115 using Allocator = BlockAllocator<int>;
116
117 Allocator allocator;
118 constexpr int N = 10000;
119 for (int i = 0; i < N; i++) {
120 allocator.Create(i);
121 }
122
123 {
124 int i = 0;
125 for (int* p : allocator.Objects()) {
126 EXPECT_EQ(*p, i);
127 i++;
128 }
129 EXPECT_EQ(i, N);
130 }
131 {
132 int i = 0;
133 for (int* p : static_cast<const Allocator&>(allocator).Objects()) {
134 EXPECT_EQ(*p, i);
135 i++;
136 }
137 EXPECT_EQ(i, N);
138 }
139 }
140
141 } // namespace
142 } // namespace tint
143