1 // Copyright 2021 gRPC 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/core/lib/gprpp/chunked_vector.h"
16
17 #include <algorithm>
18 #include <memory>
19
20 #include "gtest/gtest.h"
21
22 #include <grpc/event_engine/memory_allocator.h>
23
24 #include "src/core/lib/gprpp/ref_counted_ptr.h"
25 #include "src/core/lib/resource_quota/memory_quota.h"
26 #include "src/core/lib/resource_quota/resource_quota.h"
27
28 namespace grpc_core {
29 namespace testing {
30
31 static constexpr size_t kInitialArenaSize = 1024;
32 static constexpr size_t kChunkSize = 3;
33
34 class ChunkedVectorTest : public ::testing::Test {
35 protected:
36 MemoryAllocator memory_allocator_ = MemoryAllocator(
37 ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
38 };
39
TEST_F(ChunkedVectorTest,Noop)40 TEST_F(ChunkedVectorTest, Noop) {
41 auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
42 ChunkedVector<int, kChunkSize> v(arena.get());
43 EXPECT_EQ(0, v.size());
44 }
45
TEST_F(ChunkedVectorTest,Stack)46 TEST_F(ChunkedVectorTest, Stack) {
47 auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
48 ChunkedVector<int, kChunkSize> v(arena.get());
49
50 // Populate 2 chunks of memory, and 2/3 of a final chunk.
51 EXPECT_EQ(0, v.size());
52 v.EmplaceBack(1);
53 EXPECT_EQ(1, v.size());
54 v.EmplaceBack(2);
55 EXPECT_EQ(2, v.size());
56 v.EmplaceBack(3);
57 EXPECT_EQ(3, v.size());
58 v.EmplaceBack(4);
59 EXPECT_EQ(4, v.size());
60 v.EmplaceBack(5);
61 EXPECT_EQ(5, v.size());
62 v.EmplaceBack(6);
63 EXPECT_EQ(6, v.size());
64 v.EmplaceBack(7);
65 EXPECT_EQ(7, v.size());
66 v.EmplaceBack(8);
67 EXPECT_EQ(8, v.size());
68
69 // Now pop all of them out and check the expected ordering.
70 EXPECT_EQ(8, v.PopBack());
71 EXPECT_EQ(7, v.size());
72 EXPECT_EQ(7, v.PopBack());
73 EXPECT_EQ(6, v.size());
74 EXPECT_EQ(6, v.PopBack());
75 EXPECT_EQ(5, v.size());
76 EXPECT_EQ(5, v.PopBack());
77 EXPECT_EQ(4, v.size());
78 EXPECT_EQ(4, v.PopBack());
79 EXPECT_EQ(3, v.size());
80 EXPECT_EQ(3, v.PopBack());
81 EXPECT_EQ(2, v.size());
82 EXPECT_EQ(2, v.PopBack());
83 EXPECT_EQ(1, v.size());
84 EXPECT_EQ(1, v.PopBack());
85 EXPECT_EQ(0, v.size());
86 }
87
TEST_F(ChunkedVectorTest,Iterate)88 TEST_F(ChunkedVectorTest, Iterate) {
89 auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
90 ChunkedVector<int, kChunkSize> v(arena.get());
91 v.EmplaceBack(1);
92 v.EmplaceBack(2);
93 v.EmplaceBack(3);
94 v.EmplaceBack(4);
95 v.EmplaceBack(5);
96 v.EmplaceBack(6);
97 v.EmplaceBack(7);
98 v.EmplaceBack(8);
99
100 auto it = v.begin();
101 EXPECT_EQ(1, *it);
102 ++it;
103 EXPECT_EQ(2, *it);
104 ++it;
105 EXPECT_EQ(3, *it);
106 ++it;
107 EXPECT_EQ(4, *it);
108 ++it;
109 EXPECT_EQ(5, *it);
110 ++it;
111 EXPECT_EQ(6, *it);
112 ++it;
113 EXPECT_EQ(7, *it);
114 ++it;
115 EXPECT_EQ(8, *it);
116 ++it;
117 EXPECT_EQ(v.end(), it);
118 }
119
TEST_F(ChunkedVectorTest,ConstIterate)120 TEST_F(ChunkedVectorTest, ConstIterate) {
121 auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
122 ChunkedVector<int, kChunkSize> v(arena.get());
123 v.EmplaceBack(1);
124 v.EmplaceBack(2);
125 v.EmplaceBack(3);
126 v.EmplaceBack(4);
127 v.EmplaceBack(5);
128 v.EmplaceBack(6);
129 v.EmplaceBack(7);
130 v.EmplaceBack(8);
131
132 auto it = v.cbegin();
133 EXPECT_EQ(1, *it);
134 ++it;
135 EXPECT_EQ(2, *it);
136 ++it;
137 EXPECT_EQ(3, *it);
138 ++it;
139 EXPECT_EQ(4, *it);
140 ++it;
141 EXPECT_EQ(5, *it);
142 ++it;
143 EXPECT_EQ(6, *it);
144 ++it;
145 EXPECT_EQ(7, *it);
146 ++it;
147 EXPECT_EQ(8, *it);
148 ++it;
149 EXPECT_EQ(v.cend(), it);
150 }
151
TEST_F(ChunkedVectorTest,Clear)152 TEST_F(ChunkedVectorTest, Clear) {
153 auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
154 ChunkedVector<int, kChunkSize> v(arena.get());
155 v.EmplaceBack(1);
156 EXPECT_EQ(v.size(), 1);
157 v.Clear();
158 EXPECT_EQ(v.size(), 0);
159 EXPECT_EQ(v.begin(), v.end());
160 }
161
TEST_F(ChunkedVectorTest,RemoveIf)162 TEST_F(ChunkedVectorTest, RemoveIf) {
163 auto arena = MakeScopedArena(kInitialArenaSize, &memory_allocator_);
164 ChunkedVector<int, kChunkSize> v(arena.get());
165 v.EmplaceBack(1);
166 v.SetEnd(std::remove_if(v.begin(), v.end(), [](int i) { return i == 1; }));
167 EXPECT_EQ(v.size(), 0);
168 }
169
170 } // namespace testing
171
172 } // namespace grpc_core
173
main(int argc,char ** argv)174 int main(int argc, char** argv) {
175 ::testing::InitGoogleTest(&argc, argv);
176 return RUN_ALL_TESTS();
177 }
178