]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | #include "gtest/gtest.h" | |
4 | ||
5 | #include "os/memstore/PageSet.h" | |
6 | ||
7 | template <typename T> | |
8 | bool is_aligned(T* ptr) { | |
9 | const auto align_mask = alignof(T) - 1; | |
10 | return (reinterpret_cast<uintptr_t>(ptr) & align_mask) == 0; | |
11 | } | |
12 | ||
13 | TEST(PageSet, AllocAligned) | |
14 | { | |
15 | PageSet pages(1); | |
16 | PageSet::page_vector range; | |
17 | ||
18 | pages.alloc_range(0, 4, range); | |
19 | ASSERT_EQ(4u, range.size()); | |
20 | ASSERT_EQ(0u, range[0]->offset); | |
21 | ASSERT_EQ(1u, range[1]->offset); | |
22 | ASSERT_EQ(2u, range[2]->offset); | |
23 | ASSERT_EQ(3u, range[3]->offset); | |
24 | ||
25 | // verify that the Page pointers are properly aligned | |
26 | ASSERT_TRUE(is_aligned(range[0].get())); | |
27 | ASSERT_TRUE(is_aligned(range[1].get())); | |
28 | ASSERT_TRUE(is_aligned(range[2].get())); | |
29 | ASSERT_TRUE(is_aligned(range[3].get())); | |
30 | } | |
31 | ||
32 | TEST(PageSet, AllocUnaligned) | |
33 | { | |
34 | PageSet pages(2); | |
35 | PageSet::page_vector range; | |
36 | ||
37 | // front of first page | |
38 | pages.alloc_range(0, 1, range); | |
39 | ASSERT_EQ(1u, range.size()); | |
40 | ASSERT_EQ(0u, range[0]->offset); | |
41 | range.clear(); | |
42 | ||
43 | // back of first page | |
44 | pages.alloc_range(1, 1, range); | |
45 | ASSERT_EQ(1u, range.size()); | |
46 | ASSERT_EQ(0u, range[0]->offset); | |
47 | range.clear(); | |
48 | ||
49 | // back of first page and front of second | |
50 | pages.alloc_range(1, 2, range); | |
51 | ASSERT_EQ(2u, range.size()); | |
52 | ASSERT_EQ(0u, range[0]->offset); | |
53 | ASSERT_EQ(2u, range[1]->offset); | |
54 | range.clear(); | |
55 | ||
56 | // back of first page and all of second | |
57 | pages.alloc_range(1, 3, range); | |
58 | ASSERT_EQ(2u, range.size()); | |
59 | ASSERT_EQ(0u, range[0]->offset); | |
60 | ASSERT_EQ(2u, range[1]->offset); | |
61 | range.clear(); | |
62 | ||
63 | // back of first page, all of second, and front of third | |
64 | pages.alloc_range(1, 4, range); | |
65 | ASSERT_EQ(3u, range.size()); | |
66 | ASSERT_EQ(0u, range[0]->offset); | |
67 | ASSERT_EQ(2u, range[1]->offset); | |
68 | ASSERT_EQ(4u, range[2]->offset); | |
69 | } | |
70 | ||
71 | TEST(PageSet, GetAligned) | |
72 | { | |
73 | // allocate 4 pages | |
74 | PageSet pages(1); | |
75 | PageSet::page_vector range; | |
76 | pages.alloc_range(0, 4, range); | |
77 | range.clear(); | |
78 | ||
79 | // get first page | |
80 | pages.get_range(0, 1, range); | |
81 | ASSERT_EQ(1u, range.size()); | |
82 | ASSERT_EQ(0u, range[0]->offset); | |
83 | range.clear(); | |
84 | ||
85 | // get second and third pages | |
86 | pages.get_range(1, 2, range); | |
87 | ASSERT_EQ(2u, range.size()); | |
88 | ASSERT_EQ(1u, range[0]->offset); | |
89 | ASSERT_EQ(2u, range[1]->offset); | |
90 | range.clear(); | |
91 | ||
92 | // get all four pages | |
93 | pages.get_range(0, 4, range); | |
94 | ASSERT_EQ(4u, range.size()); | |
95 | ASSERT_EQ(0u, range[0]->offset); | |
96 | ASSERT_EQ(1u, range[1]->offset); | |
97 | ASSERT_EQ(2u, range[2]->offset); | |
98 | ASSERT_EQ(3u, range[3]->offset); | |
99 | range.clear(); | |
100 | } | |
101 | ||
102 | TEST(PageSet, GetUnaligned) | |
103 | { | |
104 | // allocate 3 pages | |
105 | PageSet pages(2); | |
106 | PageSet::page_vector range; | |
107 | pages.alloc_range(0, 6, range); | |
108 | range.clear(); | |
109 | ||
110 | // front of first page | |
111 | pages.get_range(0, 1, range); | |
112 | ASSERT_EQ(1u, range.size()); | |
113 | ASSERT_EQ(0u, range[0]->offset); | |
114 | range.clear(); | |
115 | ||
116 | // back of first page | |
117 | pages.get_range(1, 1, range); | |
118 | ASSERT_EQ(1u, range.size()); | |
119 | ASSERT_EQ(0u, range[0]->offset); | |
120 | range.clear(); | |
121 | ||
122 | // back of first page and front of second | |
123 | pages.get_range(1, 2, range); | |
124 | ASSERT_EQ(2u, range.size()); | |
125 | ASSERT_EQ(0u, range[0]->offset); | |
126 | ASSERT_EQ(2u, range[1]->offset); | |
127 | range.clear(); | |
128 | ||
129 | // back of first page and all of second | |
130 | pages.get_range(1, 3, range); | |
131 | ASSERT_EQ(2u, range.size()); | |
132 | ASSERT_EQ(0u, range[0]->offset); | |
133 | ASSERT_EQ(2u, range[1]->offset); | |
134 | range.clear(); | |
135 | ||
136 | // back of first page, all of second, and front of third | |
137 | pages.get_range(1, 4, range); | |
138 | ASSERT_EQ(3u, range.size()); | |
139 | ASSERT_EQ(0u, range[0]->offset); | |
140 | ASSERT_EQ(2u, range[1]->offset); | |
141 | ASSERT_EQ(4u, range[2]->offset); | |
142 | range.clear(); | |
143 | ||
144 | // back of third page with nothing beyond | |
145 | pages.get_range(5, 999, range); | |
146 | ASSERT_EQ(1u, range.size()); | |
147 | ASSERT_EQ(4u, range[0]->offset); | |
148 | range.clear(); | |
149 | } | |
150 | ||
151 | TEST(PageSet, GetHoles) | |
152 | { | |
153 | // allocate pages at offsets 1, 2, 5, and 7 | |
154 | PageSet pages(1); | |
155 | PageSet::page_vector range; | |
156 | for (uint64_t i : {1, 2, 5, 7}) | |
157 | pages.alloc_range(i, 1, range); | |
158 | range.clear(); | |
159 | ||
160 | // nothing at offset 0, page at offset 1 | |
161 | pages.get_range(0, 2, range); | |
162 | ASSERT_EQ(1u, range.size()); | |
163 | ASSERT_EQ(1u, range[0]->offset); | |
164 | range.clear(); | |
165 | ||
166 | // nothing at offset 0, pages at offset 1 and 2, nothing at offset 3 | |
167 | pages.get_range(0, 4, range); | |
168 | ASSERT_EQ(2u, range.size()); | |
169 | ASSERT_EQ(1u, range[0]->offset); | |
170 | ASSERT_EQ(2u, range[1]->offset); | |
171 | range.clear(); | |
172 | ||
173 | // page at offset 2, nothing at offset 3 or 4 | |
174 | pages.get_range(2, 3, range); | |
175 | ASSERT_EQ(1u, range.size()); | |
176 | ASSERT_EQ(2u, range[0]->offset); | |
177 | range.clear(); | |
178 | ||
179 | // get the full range | |
180 | pages.get_range(0, 999, range); | |
181 | ASSERT_EQ(4u, range.size()); | |
182 | ASSERT_EQ(1u, range[0]->offset); | |
183 | ASSERT_EQ(2u, range[1]->offset); | |
184 | ASSERT_EQ(5u, range[2]->offset); | |
185 | ASSERT_EQ(7u, range[3]->offset); | |
186 | range.clear(); | |
187 | } | |
188 | ||
189 | TEST(PageSet, FreeAligned) | |
190 | { | |
191 | // allocate 4 pages | |
192 | PageSet pages(1); | |
193 | PageSet::page_vector range; | |
194 | pages.alloc_range(0, 4, range); | |
195 | range.clear(); | |
196 | ||
197 | // get the full range | |
198 | pages.get_range(0, 4, range); | |
199 | ASSERT_EQ(4u, range.size()); | |
200 | range.clear(); | |
201 | ||
202 | // free after offset 4 has no effect | |
203 | pages.free_pages_after(4); | |
204 | pages.get_range(0, 4, range); | |
205 | ASSERT_EQ(4u, range.size()); | |
206 | range.clear(); | |
207 | ||
208 | // free page 4 | |
209 | pages.free_pages_after(3); | |
210 | pages.get_range(0, 4, range); | |
211 | ASSERT_EQ(3u, range.size()); | |
212 | range.clear(); | |
213 | ||
214 | // free pages 2 and 3 | |
215 | pages.free_pages_after(1); | |
216 | pages.get_range(0, 4, range); | |
217 | ASSERT_EQ(1u, range.size()); | |
218 | range.clear(); | |
219 | } | |
220 | ||
221 | TEST(PageSet, FreeUnaligned) | |
222 | { | |
223 | // allocate 4 pages | |
224 | PageSet pages(2); | |
225 | PageSet::page_vector range; | |
226 | pages.alloc_range(0, 8, range); | |
227 | range.clear(); | |
228 | ||
229 | // get the full range | |
230 | pages.get_range(0, 8, range); | |
231 | ASSERT_EQ(4u, range.size()); | |
232 | range.clear(); | |
233 | ||
234 | // free after offset 7 has no effect | |
235 | pages.free_pages_after(7); | |
236 | pages.get_range(0, 8, range); | |
237 | ASSERT_EQ(4u, range.size()); | |
238 | range.clear(); | |
239 | ||
240 | // free page 4 | |
241 | pages.free_pages_after(5); | |
242 | pages.get_range(0, 8, range); | |
243 | ASSERT_EQ(3u, range.size()); | |
244 | range.clear(); | |
245 | ||
246 | // free pages 2 and 3 | |
247 | pages.free_pages_after(1); | |
248 | pages.get_range(0, 8, range); | |
249 | ASSERT_EQ(1u, range.size()); | |
250 | range.clear(); | |
251 | } | |
252 | ||
253 | TEST(PageSet, FreeHoles) | |
254 | { | |
255 | // allocate pages at offsets 1, 2, 5, and 7 | |
256 | PageSet pages(1); | |
257 | PageSet::page_vector range; | |
258 | for (uint64_t i : {1, 2, 5, 7}) | |
259 | pages.alloc_range(i, 1, range); | |
260 | range.clear(); | |
261 | ||
262 | // get the full range | |
263 | pages.get_range(0, 8, range); | |
264 | ASSERT_EQ(4u, range.size()); | |
265 | range.clear(); | |
266 | ||
267 | // free page 7 | |
268 | pages.free_pages_after(6); | |
269 | pages.get_range(0, 8, range); | |
270 | ASSERT_EQ(3u, range.size()); | |
271 | range.clear(); | |
272 | ||
273 | // free page 5 | |
274 | pages.free_pages_after(3); | |
275 | pages.get_range(0, 8, range); | |
276 | ASSERT_EQ(2u, range.size()); | |
277 | range.clear(); | |
278 | ||
279 | // free pages 1 and 2 | |
280 | pages.free_pages_after(0); | |
281 | pages.get_range(0, 8, range); | |
282 | ASSERT_EQ(0u, range.size()); | |
283 | } |