1 /**
2 * @file unit-CellSlabIter.cc
3 *
4 * @section LICENSE
5 *
6 * The MIT License
7 *
8 * @copyright Copyright (c) 2017-2021 TileDB, Inc.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 *
28 * @section DESCRIPTION
29 *
30 * Tests the `CellSlabIter` class.
31 */
32
33 #include "test/src/helpers.h"
34 #include "test/src/vfs_helpers.h"
35 #include "tiledb/sm/c_api/tiledb_struct_def.h"
36 #include "tiledb/sm/subarray/cell_slab_iter.h"
37
38 #ifdef _WIN32
39 #include "tiledb/sm/filesystem/win.h"
40 #else
41 #include "tiledb/sm/filesystem/posix.h"
42 #endif
43
44 #include <catch.hpp>
45 #include <iostream>
46
47 using namespace tiledb::sm;
48 using namespace tiledb::test;
49
50 /* ********************************* */
51 /* STRUCT DEFINITION */
52 /* ********************************* */
53
54 struct CellSlabIterFx {
55 tiledb_ctx_t* ctx_;
56 tiledb_vfs_t* vfs_;
57
58 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
59
60 std::string temp_dir_;
61 std::string array_name_;
62 const char* ARRAY_NAME = "cell_slab_iter";
63 tiledb_array_t* array_ = nullptr;
64
65 CellSlabIterFx();
66 ~CellSlabIterFx();
67
68 template <class T>
69 void check_iter(
70 const Subarray& subarray, const std::vector<CellSlab<T>>& c_cell_slabs);
71 };
72
CellSlabIterFx()73 CellSlabIterFx::CellSlabIterFx()
74 : fs_vec_(vfs_test_get_fs_vec()) {
75 // Initialize vfs test
76 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
77
78 // Create temporary directory based on the supported filesystem
79 #ifdef _WIN32
80 SupportedFsLocal windows_fs;
81 temp_dir_ = windows_fs.file_prefix() + windows_fs.temp_dir();
82 #else
83 SupportedFsLocal posix_fs;
84 temp_dir_ = posix_fs.file_prefix() + posix_fs.temp_dir();
85 #endif
86
87 create_dir(temp_dir_, ctx_, vfs_);
88
89 array_name_ = temp_dir_ + ARRAY_NAME;
90 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_);
91 CHECK(rc == TILEDB_OK);
92 }
93
~CellSlabIterFx()94 CellSlabIterFx::~CellSlabIterFx() {
95 tiledb_array_free(&array_);
96 remove_dir(temp_dir_, ctx_, vfs_);
97 tiledb_ctx_free(&ctx_);
98 tiledb_vfs_free(&vfs_);
99 }
100
101 template <class T>
check_iter(const Subarray & subarray,const std::vector<CellSlab<T>> & c_cell_slabs)102 void CellSlabIterFx::check_iter(
103 const Subarray& subarray, const std::vector<CellSlab<T>>& c_cell_slabs) {
104 CellSlabIter<T> iter(&subarray);
105 CHECK(iter.end());
106 CHECK(iter.begin().ok());
107 auto cell_slab = iter.cell_slab();
108 CHECK(cell_slab == c_cell_slabs[0]);
109
110 for (size_t i = 1; i < c_cell_slabs.size(); ++i) {
111 ++iter;
112 cell_slab = iter.cell_slab();
113 CHECK(cell_slab == c_cell_slabs[i]);
114 CHECK(!iter.end());
115 }
116
117 ++iter;
118 CHECK(iter.end());
119 }
120
121 /* ********************************* */
122 /* TESTS */
123 /* ********************************* */
124
125 TEST_CASE_METHOD(
126 CellSlabIterFx, "CellSlabIter: Empty iterator", "[CellSlabIter][empty]") {
127 CellSlabIter<int32_t> iter;
128 CHECK(iter.end());
129 CHECK(iter.begin().ok());
130 CHECK(iter.end());
131 }
132
133 TEST_CASE_METHOD(
134 CellSlabIterFx, "CellSlabIter: Error checks", "[CellSlabIter][error]") {
135 // Create array
136 uint64_t domain[] = {1, 100};
137 uint64_t tile_extent = 10;
138 create_array(
139 ctx_,
140 array_name_,
141 TILEDB_DENSE,
142 {"d"},
143 {TILEDB_UINT64},
144 {domain},
145 {&tile_extent},
146 {"a", "b"},
147 {TILEDB_INT32, TILEDB_INT32},
148 {1, TILEDB_VAR_NUM},
149 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
150 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
151 TILEDB_ROW_MAJOR,
152 TILEDB_ROW_MAJOR,
153 2);
154
155 // Create subarray
156 open_array(ctx_, array_, TILEDB_READ);
157 Subarray subarray;
158 SubarrayRanges<uint64_t> ranges = {};
159 Layout subarray_layout = Layout::ROW_MAJOR;
160 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
161
162 // Datatype mismatch
163 CellSlabIter<int32_t> iter(&subarray);
164 CHECK(iter.end());
165 CHECK(!iter.begin().ok());
166
167 // Create subarray
168 Subarray subarray_2;
169 subarray_layout = Layout::GLOBAL_ORDER;
170 create_subarray(array_->array_, ranges, subarray_layout, &subarray_2);
171
172 // Invalid layout
173 CellSlabIter<uint64_t> iter2(&subarray_2);
174 CHECK(iter2.end());
175 CHECK(!iter2.begin().ok());
176
177 close_array(ctx_, array_);
178 }
179
180 TEST_CASE_METHOD(
181 CellSlabIterFx,
182 "CellSlabIter: Test 1D ranges",
183 "[CellSlabIter][ranges][1d]") {
184 // Create array
185 uint64_t domain[] = {1, 100};
186 uint64_t tile_extent = 10;
187 create_array(
188 ctx_,
189 array_name_,
190 TILEDB_DENSE,
191 {"d"},
192 {TILEDB_UINT64},
193 {domain},
194 {&tile_extent},
195 {"a", "b"},
196 {TILEDB_INT32, TILEDB_INT32},
197 {1, TILEDB_VAR_NUM},
198 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
199 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
200 TILEDB_ROW_MAJOR,
201 TILEDB_ROW_MAJOR,
202 2);
203
204 // Create subarray
205 open_array(ctx_, array_, TILEDB_READ);
206 Subarray subarray;
207 SubarrayRanges<uint64_t> ranges = {{5, 15, 3, 5, 10, 20, 6, 36}};
208 Layout subarray_layout = Layout::ROW_MAJOR;
209 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
210
211 CellSlabIter<uint64_t> iter(&subarray);
212 CHECK(iter.end());
213 CHECK(iter.begin().ok());
214 auto iter_ranges = iter.ranges();
215
216 std::vector<CellSlabIter<uint64_t>::Range> c_ranges = {{5, 10, 0},
217 {11, 15, 1},
218 {3, 5, 0},
219 {10, 10, 0},
220 {11, 20, 1},
221 {6, 10, 0},
222 {11, 20, 1},
223 {21, 30, 2},
224 {31, 36, 3}};
225 CHECK(iter_ranges.size() == 1);
226 CHECK(iter_ranges[0].size() == c_ranges.size());
227 CHECK(std::equal(
228 iter_ranges[0].begin(), iter_ranges[0].end(), c_ranges.begin()));
229
230 close_array(ctx_, array_);
231 }
232
233 TEST_CASE_METHOD(
234 CellSlabIterFx,
235 "CellSlabIter: Test 2D ranges",
236 "[CellSlabIter][ranges][2d]") {
237 // Create array
238 uint64_t domain[] = {1, 10};
239 uint64_t tile_extent_1 = 5;
240 uint64_t tile_extent_2 = 2;
241 create_array(
242 ctx_,
243 array_name_,
244 TILEDB_DENSE,
245 {"d1", "d2"},
246 {TILEDB_UINT64, TILEDB_UINT64},
247 {domain, domain},
248 {&tile_extent_1, &tile_extent_2},
249 {"a", "b"},
250 {TILEDB_INT32, TILEDB_INT32},
251 {1, TILEDB_VAR_NUM},
252 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
253 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
254 TILEDB_ROW_MAJOR,
255 TILEDB_ROW_MAJOR,
256 2);
257
258 // Create subarray
259 open_array(ctx_, array_, TILEDB_READ);
260 Subarray subarray;
261 SubarrayRanges<uint64_t> ranges = {{5, 8, 3, 5}, {5, 8, 3, 5}};
262 Layout subarray_layout = Layout::ROW_MAJOR;
263 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
264
265 CellSlabIter<uint64_t> iter(&subarray);
266 CHECK(iter.end());
267 CHECK(iter.begin().ok());
268 auto iter_ranges = iter.ranges();
269
270 CHECK(iter_ranges.size() == 2);
271 std::vector<CellSlabIter<uint64_t>::Range> c_ranges_1 = {
272 {5, 5, 0}, {6, 8, 1}, {3, 5, 0}};
273 CHECK(iter_ranges[0].size() == c_ranges_1.size());
274 CHECK(std::equal(
275 iter_ranges[0].begin(), iter_ranges[0].end(), c_ranges_1.begin()));
276
277 std::vector<CellSlabIter<uint64_t>::Range> c_ranges_2 = {
278 {5, 6, 2}, {7, 8, 3}, {3, 4, 1}, {5, 5, 2}};
279 CHECK(iter_ranges[1].size() == c_ranges_2.size());
280 CHECK(std::equal(
281 iter_ranges[1].begin(), iter_ranges[1].end(), c_ranges_2.begin()));
282
283 close_array(ctx_, array_);
284 }
285
286 TEST_CASE_METHOD(
287 CellSlabIterFx,
288 "CellSlabIter: Test 1D slabs",
289 "[CellSlabIter][slabs][1d]") {
290 // Create array
291 uint64_t domain[] = {1, 100};
292 uint64_t tile_extent = 10;
293 create_array(
294 ctx_,
295 array_name_,
296 TILEDB_DENSE,
297 {"d"},
298 {TILEDB_UINT64},
299 {domain},
300 {&tile_extent},
301 {"a", "b"},
302 {TILEDB_INT32, TILEDB_INT32},
303 {1, TILEDB_VAR_NUM},
304 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
305 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
306 TILEDB_ROW_MAJOR,
307 TILEDB_ROW_MAJOR,
308 2);
309
310 // Create subarray
311 open_array(ctx_, array_, TILEDB_READ);
312 Subarray subarray;
313 SubarrayRanges<uint64_t> ranges = {{5, 15, 3, 5, 11, 14}};
314 Layout subarray_layout = Layout::ROW_MAJOR;
315 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
316 subarray.compute_tile_coords<uint64_t>();
317
318 uint64_t tile_coords_0[] = {0};
319 uint64_t tile_coords_1[] = {1};
320
321 // Check iterator
322 std::vector<CellSlab<uint64_t>> c_cell_slabs = {
323 CellSlab<uint64_t>(tile_coords_0, {5}, 6),
324 CellSlab<uint64_t>(tile_coords_1, {11}, 5),
325 CellSlab<uint64_t>(tile_coords_0, {3}, 3),
326 CellSlab<uint64_t>(tile_coords_1, {11}, 4),
327 };
328 check_iter<uint64_t>(subarray, c_cell_slabs);
329
330 close_array(ctx_, array_);
331 }
332
333 TEST_CASE_METHOD(
334 CellSlabIterFx,
335 "CellSlabIter: Test 2D slabs",
336 "[CellSlabIter][slabs][2d]") {
337 // Create array
338 uint64_t domain_1[] = {1, 10};
339 uint64_t domain_2[] = {1, 9};
340 uint64_t tile_extent_1 = 5;
341 uint64_t tile_extent_2 = 3;
342 create_array(
343 ctx_,
344 array_name_,
345 TILEDB_DENSE,
346 {"d1", "d2"},
347 {TILEDB_UINT64, TILEDB_UINT64},
348 {domain_1, domain_2},
349 {&tile_extent_1, &tile_extent_2},
350 {"a", "b"},
351 {TILEDB_INT32, TILEDB_INT32},
352 {1, TILEDB_VAR_NUM},
353 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
354 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
355 TILEDB_ROW_MAJOR,
356 TILEDB_ROW_MAJOR,
357 2);
358
359 Layout subarray_layout = Layout::ROW_MAJOR;
360 std::vector<CellSlab<uint64_t>> c_cell_slabs;
361 uint64_t tile_coords_0_0[] = {0, 0};
362 uint64_t tile_coords_0_1[] = {0, 1};
363 uint64_t tile_coords_0_2[] = {0, 2};
364 uint64_t tile_coords_1_0[] = {1, 0};
365 uint64_t tile_coords_1_1[] = {1, 1};
366 uint64_t tile_coords_1_2[] = {1, 2};
367
368 SECTION("- row-major") {
369 subarray_layout = Layout::ROW_MAJOR;
370 c_cell_slabs = {
371 CellSlab<uint64_t>(tile_coords_0_0, {2, 1}, 2),
372 CellSlab<uint64_t>(tile_coords_0_1, {2, 5}, 2),
373 CellSlab<uint64_t>(tile_coords_0_2, {2, 7}, 2),
374 CellSlab<uint64_t>(tile_coords_0_0, {3, 1}, 2),
375 CellSlab<uint64_t>(tile_coords_0_1, {3, 5}, 2),
376 CellSlab<uint64_t>(tile_coords_0_2, {3, 7}, 2),
377 CellSlab<uint64_t>(tile_coords_0_0, {4, 1}, 2),
378 CellSlab<uint64_t>(tile_coords_0_1, {4, 5}, 2),
379 CellSlab<uint64_t>(tile_coords_0_2, {4, 7}, 2),
380 CellSlab<uint64_t>(tile_coords_0_0, {3, 1}, 2),
381 CellSlab<uint64_t>(tile_coords_0_1, {3, 5}, 2),
382 CellSlab<uint64_t>(tile_coords_0_2, {3, 7}, 2),
383 CellSlab<uint64_t>(tile_coords_0_0, {4, 1}, 2),
384 CellSlab<uint64_t>(tile_coords_0_1, {4, 5}, 2),
385 CellSlab<uint64_t>(tile_coords_0_2, {4, 7}, 2),
386 CellSlab<uint64_t>(tile_coords_0_0, {5, 1}, 2),
387 CellSlab<uint64_t>(tile_coords_0_1, {5, 5}, 2),
388 CellSlab<uint64_t>(tile_coords_0_2, {5, 7}, 2),
389 CellSlab<uint64_t>(tile_coords_1_0, {6, 1}, 2),
390 CellSlab<uint64_t>(tile_coords_1_1, {6, 5}, 2),
391 CellSlab<uint64_t>(tile_coords_1_2, {6, 7}, 2),
392 CellSlab<uint64_t>(tile_coords_1_0, {7, 1}, 2),
393 CellSlab<uint64_t>(tile_coords_1_1, {7, 5}, 2),
394 CellSlab<uint64_t>(tile_coords_1_2, {7, 7}, 2),
395 CellSlab<uint64_t>(tile_coords_1_0, {8, 1}, 2),
396 CellSlab<uint64_t>(tile_coords_1_1, {8, 5}, 2),
397 CellSlab<uint64_t>(tile_coords_1_2, {8, 7}, 2),
398 CellSlab<uint64_t>(tile_coords_1_0, {9, 1}, 2),
399 CellSlab<uint64_t>(tile_coords_1_1, {9, 5}, 2),
400 CellSlab<uint64_t>(tile_coords_1_2, {9, 7}, 2),
401 };
402 }
403
404 SECTION("- col-major") {
405 subarray_layout = Layout::COL_MAJOR;
406 c_cell_slabs = {
407 CellSlab<uint64_t>(tile_coords_0_0, {2, 1}, 3),
408 CellSlab<uint64_t>(tile_coords_0_0, {3, 1}, 3),
409 CellSlab<uint64_t>(tile_coords_1_0, {6, 1}, 4),
410 CellSlab<uint64_t>(tile_coords_0_0, {2, 2}, 3),
411 CellSlab<uint64_t>(tile_coords_0_0, {3, 2}, 3),
412 CellSlab<uint64_t>(tile_coords_1_0, {6, 2}, 4),
413 CellSlab<uint64_t>(tile_coords_0_1, {2, 5}, 3),
414 CellSlab<uint64_t>(tile_coords_0_1, {3, 5}, 3),
415 CellSlab<uint64_t>(tile_coords_1_1, {6, 5}, 4),
416 CellSlab<uint64_t>(tile_coords_0_1, {2, 6}, 3),
417 CellSlab<uint64_t>(tile_coords_0_1, {3, 6}, 3),
418 CellSlab<uint64_t>(tile_coords_1_1, {6, 6}, 4),
419 CellSlab<uint64_t>(tile_coords_0_2, {2, 7}, 3),
420 CellSlab<uint64_t>(tile_coords_0_2, {3, 7}, 3),
421 CellSlab<uint64_t>(tile_coords_1_2, {6, 7}, 4),
422 CellSlab<uint64_t>(tile_coords_0_2, {2, 8}, 3),
423 CellSlab<uint64_t>(tile_coords_0_2, {3, 8}, 3),
424 CellSlab<uint64_t>(tile_coords_1_2, {6, 8}, 4),
425 };
426 }
427
428 open_array(ctx_, array_, TILEDB_READ);
429
430 Subarray subarray;
431 SubarrayRanges<uint64_t> ranges = {
432 {2, 4, 3, 9},
433 {1, 2, 5, 8},
434 };
435 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
436 subarray.compute_tile_coords<uint64_t>();
437
438 check_iter<uint64_t>(subarray, c_cell_slabs);
439
440 close_array(ctx_, array_);
441 }
442