• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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