1 /**
2  * @file unit-ReadCellSlabIter.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 `ReadCellSlabIter` class.
31  */
32 
33 #include "test/src/helpers.h"
34 #include "test/src/vfs_helpers.h"
35 #include "tiledb/sm/array_schema/tile_domain.h"
36 #include "tiledb/sm/c_api/tiledb_struct_def.h"
37 #include "tiledb/sm/query/read_cell_slab_iter.h"
38 #include "tiledb/sm/query/reader.h"
39 
40 #ifdef _WIN32
41 #include "tiledb/sm/filesystem/win.h"
42 #else
43 #include "tiledb/sm/filesystem/posix.h"
44 #endif
45 
46 #include <catch.hpp>
47 #include <iostream>
48 
49 using namespace tiledb::sm;
50 using namespace tiledb::test;
51 
52 /* ********************************* */
53 /*         STRUCT DEFINITION         */
54 /* ********************************* */
55 
56 struct ReadCellSlabIterFx {
57   tiledb_ctx_t* ctx_;
58   tiledb_vfs_t* vfs_;
59   const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
60   std::string temp_dir_;
61   std::string array_name_;
62   const char* ARRAY_NAME = "read_cell_slab_iter";
63   tiledb_array_t* array_ = nullptr;
64 
65   ReadCellSlabIterFx();
66   ~ReadCellSlabIterFx();
67 
68   template <class T>
69   void check_iter(
70       ReadCellSlabIter<T>* iter,
71       const std::vector<std::vector<uint64_t>>& c_result_cell_slabs);
72   template <class T>
73   void create_result_space_tiles(
74       const Domain* dom,
75       const NDRange& dom_ndrange,
76       Layout layout,
77       const std::vector<NDRange>& domain_slices,
78       const std::vector<std::vector<uint8_t>>& tile_coords,
79       std::map<const T*, ResultSpaceTile<T>>* result_space_tiles);
80 };
81 
ReadCellSlabIterFx()82 ReadCellSlabIterFx::ReadCellSlabIterFx()
83     : fs_vec_(vfs_test_get_fs_vec()) {
84   // Initialize vfs test
85   REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
86 
87 // Create temporary directory based on the supported filesystem
88 #ifdef _WIN32
89   SupportedFsLocal windows_fs;
90   temp_dir_ = windows_fs.file_prefix() + windows_fs.temp_dir();
91 #else
92   SupportedFsLocal posix_fs;
93   temp_dir_ = posix_fs.file_prefix() + posix_fs.temp_dir();
94 #endif
95 
96   create_dir(temp_dir_, ctx_, vfs_);
97 
98   array_name_ = temp_dir_ + ARRAY_NAME;
99   int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_);
100   CHECK(rc == TILEDB_OK);
101 }
102 
~ReadCellSlabIterFx()103 ReadCellSlabIterFx::~ReadCellSlabIterFx() {
104   tiledb_array_free(&array_);
105   remove_dir(temp_dir_, ctx_, vfs_);
106   tiledb_ctx_free(&ctx_);
107   tiledb_vfs_free(&vfs_);
108 }
109 
110 template <class T>
check_iter(ReadCellSlabIter<T> * iter,const std::vector<std::vector<uint64_t>> & c_result_cell_slabs)111 void ReadCellSlabIterFx::check_iter(
112     ReadCellSlabIter<T>* iter,
113     const std::vector<std::vector<uint64_t>>& c_result_cell_slabs) {
114   CHECK(iter->end());
115   CHECK(iter->begin().ok());
116   for (const auto& rcs : c_result_cell_slabs) {
117     auto result_cell_slab = iter->result_cell_slab();
118     // result_cell_slab.print();
119 
120     if (rcs[0] == UINT64_MAX) {
121       CHECK(result_cell_slab.tile_ == nullptr);
122     } else {
123       CHECK(result_cell_slab.tile_ != nullptr);
124       CHECK(result_cell_slab.tile_->frag_idx() == rcs[0]);
125       CHECK(result_cell_slab.tile_->tile_idx() == rcs[1]);
126     }
127     CHECK(result_cell_slab.start_ == rcs[2]);
128     CHECK(result_cell_slab.length_ == rcs[3]);
129     CHECK(!iter->end());
130     ++(*iter);
131   }
132 
133   CHECK(iter->end());
134 }
135 
136 template <class T>
create_result_space_tiles(const Domain * dom,const NDRange & dom_ndrange,Layout layout,const std::vector<NDRange> & domain_slices,const std::vector<std::vector<uint8_t>> & tile_coords,std::map<const T *,ResultSpaceTile<T>> * result_space_tiles)137 void ReadCellSlabIterFx::create_result_space_tiles(
138     const Domain* dom,
139     const NDRange& dom_ndrange,
140     Layout layout,
141     const std::vector<NDRange>& domain_slices,
142     const std::vector<std::vector<uint8_t>>& tile_coords,
143     std::map<const T*, ResultSpaceTile<T>>* result_space_tiles) {
144   auto domain = dom->domain();
145   const auto& tile_extents = dom->tile_extents();
146   std::vector<TileDomain<T>> frag_tile_domains;
147   for (size_t i = 0; i < domain_slices.size(); ++i) {
148     frag_tile_domains.emplace_back(
149         (unsigned)(domain_slices.size() - i),
150         domain,
151         domain_slices[i],
152         tile_extents,
153         layout);
154   }
155   TileDomain<T> array_tile_domain(
156       UINT32_MAX, domain, dom_ndrange, tile_extents, layout);
157   Reader::compute_result_space_tiles<T>(
158       dom,
159       tile_coords,
160       array_tile_domain,
161       frag_tile_domains,
162       result_space_tiles);
163 }
164 
165 /* ********************************* */
166 /*                TESTS              */
167 /* ********************************* */
168 
169 TEST_CASE_METHOD(
170     ReadCellSlabIterFx,
171     "ReadCellSlabIter: Empty iterator",
172     "[ReadCellSlabIter][empty]") {
173   Subarray* subarray = nullptr;
174   std::map<const int32_t*, ResultSpaceTile<int32_t>> result_space_tiles;
175   std::vector<ResultCoords> result_coords;
176   ReadCellSlabIter<int32_t> iter(subarray, &result_space_tiles, &result_coords);
177   CHECK(iter.end());
178   CHECK(iter.begin().ok());
179   CHECK(iter.end());
180 }
181 
182 TEST_CASE_METHOD(
183     ReadCellSlabIterFx,
184     "ReadCellSlabIter: Test 1D slabs, 1 fragment, full overlap",
185     "[ReadCellSlabIter][slabs][1d][1f][full_overlap]") {
186   // Create array
187   uint64_t domain[] = {1, 100};
188   uint64_t tile_extent = 10;
189   create_array(
190       ctx_,
191       array_name_,
192       TILEDB_DENSE,
193       {"d"},
194       {TILEDB_UINT64},
195       {domain},
196       {&tile_extent},
197       {"a", "b"},
198       {TILEDB_INT32, TILEDB_INT32},
199       {1, TILEDB_VAR_NUM},
200       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
201        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
202       TILEDB_ROW_MAJOR,
203       TILEDB_ROW_MAJOR,
204       2);
205 
206   // Create subarray
207   open_array(ctx_, array_, TILEDB_READ);
208   Subarray subarray;
209   SubarrayRanges<uint64_t> ranges = {{5, 15}};
210   Layout subarray_layout = Layout::ROW_MAJOR;
211   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
212   subarray.compute_tile_coords<uint64_t>();
213 
214   // Create result space tiles
215   std::vector<uint64_t> slice = {1, 100};
216   NDRange ds = {Range(&slice[0], 2 * sizeof(uint64_t))};
217   std::vector<NDRange> domain_slices = {ds};
218   const auto& tile_coords = subarray.tile_coords();
219   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
220   auto dom = array_->array_->array_schema_latest()->domain();
221   create_result_space_tiles(
222       dom,
223       dom->domain(),
224       subarray_layout,
225       domain_slices,
226       tile_coords,
227       &result_space_tiles);
228 
229   // Check iterator
230   std::vector<ResultCoords> result_coords;
231   ReadCellSlabIter<uint64_t> iter(
232       &subarray, &result_space_tiles, &result_coords);
233   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {
234       {1, 0, 4, 6},
235       {1, 1, 0, 5},
236   };
237   check_iter<uint64_t>(&iter, c_result_cell_slabs);
238 
239   close_array(ctx_, array_);
240 }
241 
242 TEST_CASE_METHOD(
243     ReadCellSlabIterFx,
244     "ReadCellSlabIter: Test 1D slabs, 1 fragment, no overlap",
245     "[ReadCellSlabIter][slabs][1d][1f][no_overlap]") {
246   // Create array
247   uint64_t domain[] = {1, 100};
248   uint64_t tile_extent = 10;
249   create_array(
250       ctx_,
251       array_name_,
252       TILEDB_DENSE,
253       {"d"},
254       {TILEDB_UINT64},
255       {domain},
256       {&tile_extent},
257       {"a", "b"},
258       {TILEDB_INT32, TILEDB_INT32},
259       {1, TILEDB_VAR_NUM},
260       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
261        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
262       TILEDB_ROW_MAJOR,
263       TILEDB_ROW_MAJOR,
264       2);
265 
266   // Create subarray
267   open_array(ctx_, array_, TILEDB_READ);
268   Subarray subarray;
269   SubarrayRanges<uint64_t> ranges = {{5, 15}};
270   Layout subarray_layout = Layout::ROW_MAJOR;
271   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
272   subarray.compute_tile_coords<uint64_t>();
273 
274   // Create result space tiles
275   std::vector<uint64_t> slice = {20, 30};
276   NDRange ds = {Range(&slice[0], 2 * sizeof(uint64_t))};
277   std::vector<NDRange> domain_slices = {ds};
278   const auto& tile_coords = subarray.tile_coords();
279   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
280   auto dom = array_->array_->array_schema_latest()->domain();
281   create_result_space_tiles(
282       dom,
283       dom->domain(),
284       subarray_layout,
285       domain_slices,
286       tile_coords,
287       &result_space_tiles);
288 
289   // Check iterator
290   std::vector<ResultCoords> result_coords;
291   ReadCellSlabIter<uint64_t> iter(
292       &subarray, &result_space_tiles, &result_coords);
293   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {
294       {UINT64_MAX, 0, 4, 6},
295       {UINT64_MAX, 1, 0, 5},
296   };
297   check_iter<uint64_t>(&iter, c_result_cell_slabs);
298 
299   close_array(ctx_, array_);
300 }
301 
302 TEST_CASE_METHOD(
303     ReadCellSlabIterFx,
304     "ReadCellSlabIter: Test 1D slabs, 2 fragments",
305     "[ReadCellSlabIter][slabs][1d][2f]") {
306   // Create array
307   uint64_t domain[] = {1, 100};
308   uint64_t tile_extent = 10;
309   create_array(
310       ctx_,
311       array_name_,
312       TILEDB_DENSE,
313       {"d"},
314       {TILEDB_UINT64},
315       {domain},
316       {&tile_extent},
317       {"a", "b"},
318       {TILEDB_INT32, TILEDB_INT32},
319       {1, TILEDB_VAR_NUM},
320       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
321        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
322       TILEDB_ROW_MAJOR,
323       TILEDB_ROW_MAJOR,
324       2);
325 
326   // Create subarray
327   open_array(ctx_, array_, TILEDB_READ);
328   Subarray subarray;
329   SubarrayRanges<uint64_t> ranges = {{5, 15, 3, 5, 11, 14}};
330   Layout subarray_layout = Layout::ROW_MAJOR;
331   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
332   subarray.compute_tile_coords<uint64_t>();
333 
334   // Create result space tiles
335   std::vector<uint64_t> slice_1 = {5, 12};
336   std::vector<uint64_t> slice_2 = {4, 15};
337   auto size = 2 * sizeof(uint64_t);
338   NDRange ds1 = {Range(&slice_1[0], size)};
339   NDRange ds2 = {Range(&slice_2[0], size)};
340   std::vector<NDRange> domain_slices = {ds1, ds2};
341   const auto& tile_coords = subarray.tile_coords();
342   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
343   auto dom = array_->array_->array_schema_latest()->domain();
344   create_result_space_tiles(
345       dom,
346       dom->domain(),
347       subarray_layout,
348       domain_slices,
349       tile_coords,
350       &result_space_tiles);
351 
352   // Check iterator
353   std::vector<ResultCoords> result_coords;
354   ReadCellSlabIter<uint64_t> iter(
355       &subarray, &result_space_tiles, &result_coords);
356   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {
357       {2, 0, 4, 6},
358       {2, 1, 0, 2},
359       {1, 1, 2, 3},
360       {UINT64_MAX, 0, 2, 1},
361       {1, 0, 3, 1},
362       {2, 0, 4, 1},
363       {2, 1, 0, 2},
364       {1, 1, 2, 2},
365   };
366   check_iter<uint64_t>(&iter, c_result_cell_slabs);
367 
368   close_array(ctx_, array_);
369 }
370 
371 TEST_CASE_METHOD(
372     ReadCellSlabIterFx,
373     "ReadCellSlabIter: Test 1D slabs, 1 dense fragment, 2 sparse fragments",
374     "[ReadCellSlabIter][slabs][1d][1df][2sf]") {
375   // Create array
376   uint64_t domain[] = {1, 100};
377   uint64_t tile_extent = 10;
378   create_array(
379       ctx_,
380       array_name_,
381       TILEDB_DENSE,
382       {"d"},
383       {TILEDB_UINT64},
384       {domain},
385       {&tile_extent},
386       {"a", "b"},
387       {TILEDB_INT32, TILEDB_INT32},
388       {1, TILEDB_VAR_NUM},
389       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
390        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
391       TILEDB_ROW_MAJOR,
392       TILEDB_ROW_MAJOR,
393       2);
394 
395   // Create subarray
396   open_array(ctx_, array_, TILEDB_READ);
397   Subarray subarray;
398   SubarrayRanges<uint64_t> ranges = {{3, 15, 18, 20}};
399   Layout subarray_layout = Layout::ROW_MAJOR;
400   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
401   subarray.compute_tile_coords<uint64_t>();
402 
403   // Create result space tiles
404   std::vector<uint64_t> slice = {3, 12};
405   auto size = 2 * sizeof(uint64_t);
406   NDRange ds = {Range(&slice[0], size)};
407   std::vector<NDRange> domain_slices = {ds};
408   const auto& tile_coords = subarray.tile_coords();
409   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
410   auto dom = array_->array_->array_schema_latest()->domain();
411   create_result_space_tiles(
412       dom,
413       dom->domain(),
414       subarray_layout,
415       domain_slices,
416       tile_coords,
417       &result_space_tiles);
418 
419   // Create result coordinates
420   std::vector<ResultCoords> result_coords;
421   ResultTile result_tile_2_0(2, 0, dom);
422   ResultTile result_tile_3_0(3, 0, dom);
423   ResultTile result_tile_3_1(3, 1, dom);
424 
425   result_tile_2_0.init_coord_tile("d", 0);
426   result_tile_3_0.init_coord_tile("d", 0);
427   result_tile_3_1.init_coord_tile("d", 0);
428 
429   std::vector<uint64_t> vec_2_0 = {1000, 3, 1000, 5};
430   Buffer buff_2_0(&vec_2_0[0], vec_2_0.size() * sizeof(uint64_t));
431   Tile tile_2_0(Datatype::UINT64, sizeof(uint64_t), 0, &buff_2_0, false);
432   auto tile_tuple = result_tile_2_0.tile_tuple("d");
433   REQUIRE(tile_tuple != nullptr);
434   std::get<0>(*tile_tuple) = tile_2_0;
435 
436   std::vector<uint64_t> vec_3_0 = {1000, 1000, 8, 9};
437   Buffer buff_3_0(&vec_3_0[0], vec_3_0.size() * sizeof(uint64_t));
438   Tile tile_3_0(Datatype::UINT64, sizeof(uint64_t), 0, &buff_3_0, false);
439   tile_tuple = result_tile_3_0.tile_tuple("d");
440   REQUIRE(tile_tuple != nullptr);
441   std::get<0>(*tile_tuple) = tile_3_0;
442 
443   std::vector<uint64_t> vec_3_1 = {1000, 12, 19, 1000};
444   Buffer buff_3_1(&vec_3_1[0], vec_3_1.size() * sizeof(uint64_t));
445   Tile tile_3_1(Datatype::UINT64, sizeof(uint64_t), 0, &buff_3_1, false);
446   tile_tuple = result_tile_3_1.tile_tuple("d");
447   REQUIRE(tile_tuple != nullptr);
448   std::get<0>(*tile_tuple) = tile_3_1;
449 
450   result_coords.emplace_back(&result_tile_2_0, 1);
451   result_coords.emplace_back(&result_tile_2_0, 3);
452   result_coords.emplace_back(&result_tile_3_0, 2);
453   result_coords.emplace_back(&result_tile_3_0, 3);
454   result_coords.back().invalidate();
455   result_coords.emplace_back(&result_tile_3_1, 1);
456   result_coords.emplace_back(&result_tile_3_1, 2);
457 
458   // Check iterator
459   ReadCellSlabIter<uint64_t> iter(
460       &subarray, &result_space_tiles, &result_coords);
461   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {
462       {2, 0, 1, 1},
463       {1, 0, 3, 1},
464       {2, 0, 3, 1},
465       {1, 0, 5, 2},
466       {3, 0, 2, 1},
467       {1, 0, 8, 2},
468       {1, 1, 0, 1},
469       {3, 1, 1, 1},
470       {UINT64_MAX, 1, 2, 3},
471       {UINT64_MAX, 1, 7, 1},
472       {3, 1, 2, 1},
473       {UINT64_MAX, 1, 9, 1},
474   };
475   check_iter<uint64_t>(&iter, c_result_cell_slabs);
476 
477   close_array(ctx_, array_);
478 }
479 
480 TEST_CASE_METHOD(
481     ReadCellSlabIterFx,
482     "ReadCellSlabIter: Test 2D slabs, 1 range, 1 dense fragment, full "
483     "overlap",
484     "[ReadCellSlabIter][slabs][2d][1r][1f][full_overlap]") {
485   Layout subarray_layout = Layout::ROW_MAJOR;
486   Layout tile_domain_layout = Layout::ROW_MAJOR;
487   tiledb_layout_t tile_order = TILEDB_ROW_MAJOR;
488   tiledb_layout_t cell_order = TILEDB_ROW_MAJOR;
489   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {};
490 
491   SECTION("- tile: row, cell: row, subarray: row") {
492     tile_order = TILEDB_ROW_MAJOR;
493     cell_order = TILEDB_ROW_MAJOR;
494     subarray_layout = Layout::ROW_MAJOR;
495     tile_domain_layout = Layout::ROW_MAJOR;
496     c_result_cell_slabs = {
497         {1, 0, 4, 2},
498         {1, 1, 3, 3},
499         {1, 0, 7, 2},
500         {1, 1, 6, 3},
501     };
502   }
503 
504   SECTION("- tile: row, cell: col, subarray: row") {
505     tile_order = TILEDB_ROW_MAJOR;
506     cell_order = TILEDB_COL_MAJOR;
507     subarray_layout = Layout::ROW_MAJOR;
508     tile_domain_layout = Layout::ROW_MAJOR;
509     c_result_cell_slabs = {
510         {1, 0, 4, 2},
511         {1, 1, 1, 3},
512         {1, 0, 5, 2},
513         {1, 1, 2, 3},
514     };
515   }
516 
517   SECTION("- tile: col, cell: row, subarray: row") {
518     tile_order = TILEDB_COL_MAJOR;
519     cell_order = TILEDB_ROW_MAJOR;
520     subarray_layout = Layout::ROW_MAJOR;
521     tile_domain_layout = Layout::COL_MAJOR;
522     c_result_cell_slabs = {
523         {1, 0, 4, 2},
524         {1, 2, 3, 3},
525         {1, 0, 7, 2},
526         {1, 2, 6, 3},
527     };
528   }
529 
530   SECTION("- tile: col, cell: col, subarray: row") {
531     tile_order = TILEDB_COL_MAJOR;
532     cell_order = TILEDB_COL_MAJOR;
533     subarray_layout = Layout::ROW_MAJOR;
534     tile_domain_layout = Layout::COL_MAJOR;
535     c_result_cell_slabs = {
536         {1, 0, 4, 2},
537         {1, 2, 1, 3},
538         {1, 0, 5, 2},
539         {1, 2, 2, 3},
540     };
541   }
542 
543   SECTION("- tile: row, cell: row, subarray: col") {
544     tile_order = TILEDB_ROW_MAJOR;
545     cell_order = TILEDB_ROW_MAJOR;
546     subarray_layout = Layout::COL_MAJOR;
547     tile_domain_layout = Layout::ROW_MAJOR;
548     c_result_cell_slabs = {
549         {1, 0, 4, 2},
550         {1, 0, 5, 2},
551         {1, 1, 3, 2},
552         {1, 1, 4, 2},
553         {1, 1, 5, 2},
554     };
555   }
556 
557   SECTION("- tile: row, cell: col, subarray: col") {
558     tile_order = TILEDB_ROW_MAJOR;
559     cell_order = TILEDB_COL_MAJOR;
560     subarray_layout = Layout::COL_MAJOR;
561     tile_domain_layout = Layout::ROW_MAJOR;
562     c_result_cell_slabs = {
563         {1, 0, 4, 2},
564         {1, 0, 7, 2},
565         {1, 1, 1, 2},
566         {1, 1, 4, 2},
567         {1, 1, 7, 2},
568     };
569   }
570 
571   SECTION("- tile: col, cell: row, subarray: col") {
572     tile_order = TILEDB_COL_MAJOR;
573     cell_order = TILEDB_ROW_MAJOR;
574     subarray_layout = Layout::COL_MAJOR;
575     tile_domain_layout = Layout::COL_MAJOR;
576     c_result_cell_slabs = {
577         {1, 0, 4, 2},
578         {1, 0, 5, 2},
579         {1, 2, 3, 2},
580         {1, 2, 4, 2},
581         {1, 2, 5, 2},
582     };
583   }
584 
585   SECTION("- tile: col, cell: col, subarray: col") {
586     tile_order = TILEDB_COL_MAJOR;
587     cell_order = TILEDB_COL_MAJOR;
588     subarray_layout = Layout::COL_MAJOR;
589     tile_domain_layout = Layout::COL_MAJOR;
590     c_result_cell_slabs = {
591         {1, 0, 4, 2},
592         {1, 0, 7, 2},
593         {1, 2, 1, 2},
594         {1, 2, 4, 2},
595         {1, 2, 7, 2},
596     };
597   }
598 
599   // Create array
600   uint64_t domain[] = {1, 6, 1, 6};
601   uint64_t tile_extents[] = {3, 3};
602   create_array(
603       ctx_,
604       array_name_,
605       TILEDB_DENSE,
606       {"d1", "d2"},
607       {TILEDB_UINT64, TILEDB_UINT64},
608       {&domain[0], &domain[2]},
609       {&tile_extents[0], &tile_extents[1]},
610       {"a", "b"},
611       {TILEDB_INT32, TILEDB_INT32},
612       {1, TILEDB_VAR_NUM},
613       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
614        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
615       tile_order,
616       cell_order,
617       2);
618 
619   // Create subarray
620   open_array(ctx_, array_, TILEDB_READ);
621   Subarray subarray;
622   SubarrayRanges<uint64_t> ranges = {{2, 3}, {2, 6}};
623   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
624   subarray.compute_tile_coords<uint64_t>();
625 
626   // Create result space tiles
627   std::vector<uint64_t> slice = {1, 6, 1, 6};
628   auto size = 2 * sizeof(uint64_t);
629   NDRange ds = {Range(&slice[0], size), Range(&slice[2], size)};
630   std::vector<NDRange> domain_slices = {ds};
631   const auto& tile_coords = subarray.tile_coords();
632   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
633   auto dom = array_->array_->array_schema_latest()->domain();
634   create_result_space_tiles(
635       dom,
636       dom->domain(),
637       tile_domain_layout,
638       domain_slices,
639       tile_coords,
640       &result_space_tiles);
641 
642   // Create result coordinates
643   std::vector<ResultCoords> result_coords;
644 
645   // Check iterator
646   ReadCellSlabIter<uint64_t> iter(
647       &subarray, &result_space_tiles, &result_coords);
648   check_iter<uint64_t>(&iter, c_result_cell_slabs);
649 
650   close_array(ctx_, array_);
651 }
652 
653 TEST_CASE_METHOD(
654     ReadCellSlabIterFx,
655     "ReadCellSlabIter: Test 2D slabs, 1 range, 1 dense fragment, no overlap",
656     "[ReadCellSlabIter][slabs][2d][1r][1f][no_overlap]") {
657   Layout subarray_layout = Layout::ROW_MAJOR;
658   Layout tile_domain_layout = Layout::ROW_MAJOR;
659   tiledb_layout_t tile_order = TILEDB_ROW_MAJOR;
660   tiledb_layout_t cell_order = TILEDB_ROW_MAJOR;
661   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {};
662 
663   SECTION("- tile: row, cell: row, subarray: row") {
664     tile_order = TILEDB_ROW_MAJOR;
665     cell_order = TILEDB_ROW_MAJOR;
666     subarray_layout = Layout::ROW_MAJOR;
667     tile_domain_layout = Layout::ROW_MAJOR;
668     c_result_cell_slabs = {
669         {UINT64_MAX, 0, 4, 2},
670         {UINT64_MAX, 1, 3, 3},
671         {UINT64_MAX, 0, 7, 2},
672         {UINT64_MAX, 1, 6, 3},
673     };
674   }
675 
676   SECTION("- tile: row, cell: col, subarray: row") {
677     tile_order = TILEDB_ROW_MAJOR;
678     cell_order = TILEDB_COL_MAJOR;
679     subarray_layout = Layout::ROW_MAJOR;
680     tile_domain_layout = Layout::ROW_MAJOR;
681     c_result_cell_slabs = {
682         {UINT64_MAX, 0, 4, 2},
683         {UINT64_MAX, 1, 1, 3},
684         {UINT64_MAX, 0, 5, 2},
685         {UINT64_MAX, 1, 2, 3},
686     };
687   }
688 
689   SECTION("- tile: col, cell: row, subarray: row") {
690     tile_order = TILEDB_COL_MAJOR;
691     cell_order = TILEDB_ROW_MAJOR;
692     subarray_layout = Layout::ROW_MAJOR;
693     tile_domain_layout = Layout::COL_MAJOR;
694     c_result_cell_slabs = {
695         {UINT64_MAX, 0, 4, 2},
696         {UINT64_MAX, 2, 3, 3},
697         {UINT64_MAX, 0, 7, 2},
698         {UINT64_MAX, 2, 6, 3},
699     };
700   }
701 
702   SECTION("- tile: col, cell: col, subarray: row") {
703     tile_order = TILEDB_COL_MAJOR;
704     cell_order = TILEDB_COL_MAJOR;
705     subarray_layout = Layout::ROW_MAJOR;
706     tile_domain_layout = Layout::COL_MAJOR;
707     c_result_cell_slabs = {
708         {UINT64_MAX, 0, 4, 2},
709         {UINT64_MAX, 2, 1, 3},
710         {UINT64_MAX, 0, 5, 2},
711         {UINT64_MAX, 2, 2, 3},
712     };
713   }
714 
715   SECTION("- tile: row, cell: row, subarray: col") {
716     tile_order = TILEDB_ROW_MAJOR;
717     cell_order = TILEDB_ROW_MAJOR;
718     subarray_layout = Layout::COL_MAJOR;
719     tile_domain_layout = Layout::ROW_MAJOR;
720     c_result_cell_slabs = {
721         {UINT64_MAX, 0, 4, 2},
722         {UINT64_MAX, 0, 5, 2},
723         {UINT64_MAX, 1, 3, 2},
724         {UINT64_MAX, 1, 4, 2},
725         {UINT64_MAX, 1, 5, 2},
726     };
727   }
728 
729   SECTION("- tile: row, cell: col, subarray: col") {
730     tile_order = TILEDB_ROW_MAJOR;
731     cell_order = TILEDB_COL_MAJOR;
732     subarray_layout = Layout::COL_MAJOR;
733     tile_domain_layout = Layout::ROW_MAJOR;
734     c_result_cell_slabs = {
735         {UINT64_MAX, 0, 4, 2},
736         {UINT64_MAX, 0, 7, 2},
737         {UINT64_MAX, 1, 1, 2},
738         {UINT64_MAX, 1, 4, 2},
739         {UINT64_MAX, 1, 7, 2},
740     };
741   }
742 
743   SECTION("- tile: col, cell: row, subarray: col") {
744     tile_order = TILEDB_COL_MAJOR;
745     cell_order = TILEDB_ROW_MAJOR;
746     subarray_layout = Layout::COL_MAJOR;
747     tile_domain_layout = Layout::COL_MAJOR;
748     c_result_cell_slabs = {
749         {UINT64_MAX, 0, 4, 2},
750         {UINT64_MAX, 0, 5, 2},
751         {UINT64_MAX, 2, 3, 2},
752         {UINT64_MAX, 2, 4, 2},
753         {UINT64_MAX, 2, 5, 2},
754     };
755   }
756 
757   SECTION("- tile: col, cell: col, subarray: col") {
758     tile_order = TILEDB_COL_MAJOR;
759     cell_order = TILEDB_COL_MAJOR;
760     subarray_layout = Layout::COL_MAJOR;
761     tile_domain_layout = Layout::COL_MAJOR;
762     c_result_cell_slabs = {
763         {UINT64_MAX, 0, 4, 2},
764         {UINT64_MAX, 0, 7, 2},
765         {UINT64_MAX, 2, 1, 2},
766         {UINT64_MAX, 2, 4, 2},
767         {UINT64_MAX, 2, 7, 2},
768     };
769   }
770 
771   // Create array
772   uint64_t domain[] = {1, 6, 1, 6};
773   uint64_t tile_extents[] = {3, 3};
774   create_array(
775       ctx_,
776       array_name_,
777       TILEDB_DENSE,
778       {"d1", "d2"},
779       {TILEDB_UINT64, TILEDB_UINT64},
780       {&domain[0], &domain[2]},
781       {&tile_extents[0], &tile_extents[1]},
782       {"a", "b"},
783       {TILEDB_INT32, TILEDB_INT32},
784       {1, TILEDB_VAR_NUM},
785       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
786        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
787       tile_order,
788       cell_order,
789       2);
790 
791   // Create subarray
792   open_array(ctx_, array_, TILEDB_READ);
793   Subarray subarray;
794   SubarrayRanges<uint64_t> ranges = {{2, 3}, {2, 6}};
795   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
796   subarray.compute_tile_coords<uint64_t>();
797 
798   // Create result space tiles
799   std::vector<uint64_t> slice = {6, 6, 6, 6};
800   auto size = 2 * sizeof(uint64_t);
801   NDRange ds = {Range(&slice[0], size), Range(&slice[2], size)};
802   std::vector<NDRange> domain_slices = {ds};
803   const auto& tile_coords = subarray.tile_coords();
804   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
805   auto dom = array_->array_->array_schema_latest()->domain();
806   create_result_space_tiles(
807       dom,
808       dom->domain(),
809       tile_domain_layout,
810       domain_slices,
811       tile_coords,
812       &result_space_tiles);
813 
814   // Create result coordinates
815   std::vector<ResultCoords> result_coords;
816 
817   // Check iterator
818   ReadCellSlabIter<uint64_t> iter(
819       &subarray, &result_space_tiles, &result_coords);
820   check_iter<uint64_t>(&iter, c_result_cell_slabs);
821 
822   close_array(ctx_, array_);
823 }
824 
825 TEST_CASE_METHOD(
826     ReadCellSlabIterFx,
827     "ReadCellSlabIter: Test 2D slabs, 1 range, 1 dense fragment, partial "
828     "overlap",
829     "[ReadCellSlabIter][slabs][2d][1r][1f][partial_overlap]") {
830   Layout subarray_layout = Layout::ROW_MAJOR;
831   Layout tile_domain_layout = Layout::ROW_MAJOR;
832   tiledb_layout_t tile_order = TILEDB_ROW_MAJOR;
833   tiledb_layout_t cell_order = TILEDB_ROW_MAJOR;
834   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {};
835 
836   SECTION("- tile: row, cell: row, subarray: row") {
837     tile_order = TILEDB_ROW_MAJOR;
838     cell_order = TILEDB_ROW_MAJOR;
839     subarray_layout = Layout::ROW_MAJOR;
840     tile_domain_layout = Layout::ROW_MAJOR;
841     c_result_cell_slabs = {
842         {UINT64_MAX, 0, 4, 2},
843         {UINT64_MAX, 1, 3, 3},
844         {UINT64_MAX, 0, 7, 2},
845         {UINT64_MAX, 1, 6, 1},
846         {1, 0, 7, 2},
847     };
848   }
849 
850   SECTION("- tile: row, cell: col, subarray: row") {
851     tile_order = TILEDB_ROW_MAJOR;
852     cell_order = TILEDB_COL_MAJOR;
853     subarray_layout = Layout::ROW_MAJOR;
854     tile_domain_layout = Layout::ROW_MAJOR;
855     c_result_cell_slabs = {
856         {UINT64_MAX, 0, 4, 2},
857         {UINT64_MAX, 1, 1, 3},
858         {UINT64_MAX, 0, 5, 2},
859         {UINT64_MAX, 1, 2, 1},
860         {1, 0, 5, 2},
861     };
862   }
863 
864   SECTION("- tile: col, cell: row, subarray: row") {
865     tile_order = TILEDB_COL_MAJOR;
866     cell_order = TILEDB_ROW_MAJOR;
867     subarray_layout = Layout::ROW_MAJOR;
868     tile_domain_layout = Layout::COL_MAJOR;
869     c_result_cell_slabs = {
870         {UINT64_MAX, 0, 4, 2},
871         {UINT64_MAX, 2, 3, 3},
872         {UINT64_MAX, 0, 7, 2},
873         {UINT64_MAX, 2, 6, 1},
874         {1, 0, 7, 2},
875     };
876   }
877 
878   SECTION("- tile: col, cell: col, subarray: row") {
879     tile_order = TILEDB_COL_MAJOR;
880     cell_order = TILEDB_COL_MAJOR;
881     subarray_layout = Layout::ROW_MAJOR;
882     tile_domain_layout = Layout::COL_MAJOR;
883     c_result_cell_slabs = {
884         {UINT64_MAX, 0, 4, 2},
885         {UINT64_MAX, 2, 1, 3},
886         {UINT64_MAX, 0, 5, 2},
887         {UINT64_MAX, 2, 2, 1},
888         {1, 0, 5, 2},
889     };
890   }
891 
892   SECTION("- tile: row, cell: row, subarray: col") {
893     tile_order = TILEDB_ROW_MAJOR;
894     cell_order = TILEDB_ROW_MAJOR;
895     subarray_layout = Layout::COL_MAJOR;
896     tile_domain_layout = Layout::ROW_MAJOR;
897     c_result_cell_slabs = {
898         {UINT64_MAX, 0, 4, 2},
899         {UINT64_MAX, 0, 5, 2},
900         {UINT64_MAX, 1, 3, 2},
901         {UINT64_MAX, 1, 4, 1},
902         {1, 0, 7, 1},
903         {UINT64_MAX, 1, 5, 1},
904         {1, 0, 8, 1},
905     };
906   }
907 
908   SECTION("- tile: row, cell: col, subarray: col") {
909     tile_order = TILEDB_ROW_MAJOR;
910     cell_order = TILEDB_COL_MAJOR;
911     subarray_layout = Layout::COL_MAJOR;
912     tile_domain_layout = Layout::ROW_MAJOR;
913     c_result_cell_slabs = {
914         {UINT64_MAX, 0, 4, 2},
915         {UINT64_MAX, 0, 7, 2},
916         {UINT64_MAX, 1, 1, 2},
917         {UINT64_MAX, 1, 4, 1},
918         {1, 0, 5, 1},
919         {UINT64_MAX, 1, 7, 1},
920         {1, 0, 8, 1},
921     };
922   }
923 
924   SECTION("- tile: col, cell: row, subarray: col") {
925     tile_order = TILEDB_COL_MAJOR;
926     cell_order = TILEDB_ROW_MAJOR;
927     subarray_layout = Layout::COL_MAJOR;
928     tile_domain_layout = Layout::COL_MAJOR;
929     c_result_cell_slabs = {
930         {UINT64_MAX, 0, 4, 2},
931         {UINT64_MAX, 0, 5, 2},
932         {UINT64_MAX, 2, 3, 2},
933         {UINT64_MAX, 2, 4, 1},
934         {1, 0, 7, 1},
935         {UINT64_MAX, 2, 5, 1},
936         {1, 0, 8, 1},
937     };
938   }
939 
940   SECTION("- tile: col, cell: col, subarray: col") {
941     tile_order = TILEDB_COL_MAJOR;
942     cell_order = TILEDB_COL_MAJOR;
943     subarray_layout = Layout::COL_MAJOR;
944     tile_domain_layout = Layout::COL_MAJOR;
945     c_result_cell_slabs = {
946         {UINT64_MAX, 0, 4, 2},
947         {UINT64_MAX, 0, 7, 2},
948         {UINT64_MAX, 2, 1, 2},
949         {UINT64_MAX, 2, 4, 1},
950         {1, 0, 5, 1},
951         {UINT64_MAX, 2, 7, 1},
952         {1, 0, 8, 1},
953     };
954   }
955 
956   // Create array
957   uint64_t domain[] = {1, 6, 1, 6};
958   uint64_t tile_extents[] = {3, 3};
959   create_array(
960       ctx_,
961       array_name_,
962       TILEDB_DENSE,
963       {"d1", "d2"},
964       {TILEDB_UINT64, TILEDB_UINT64},
965       {&domain[0], &domain[2]},
966       {&tile_extents[0], &tile_extents[1]},
967       {"a", "b"},
968       {TILEDB_INT32, TILEDB_INT32},
969       {1, TILEDB_VAR_NUM},
970       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
971        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
972       tile_order,
973       cell_order,
974       2);
975 
976   // Create subarray
977   open_array(ctx_, array_, TILEDB_READ);
978   Subarray subarray;
979   SubarrayRanges<uint64_t> ranges = {{2, 3}, {2, 6}};
980   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
981   subarray.compute_tile_coords<uint64_t>();
982 
983   // Create result space tiles
984   std::vector<uint64_t> slice = {3, 6, 5, 6};
985   auto size = 2 * sizeof(uint64_t);
986   NDRange ds = {Range(&slice[0], size), Range(&slice[2], size)};
987   std::vector<NDRange> domain_slices = {ds};
988   const auto& tile_coords = subarray.tile_coords();
989   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
990   auto dom = array_->array_->array_schema_latest()->domain();
991   create_result_space_tiles(
992       dom,
993       dom->domain(),
994       tile_domain_layout,
995       domain_slices,
996       tile_coords,
997       &result_space_tiles);
998 
999   // Create result coordinates
1000   std::vector<ResultCoords> result_coords;
1001 
1002   // Check iterator
1003   ReadCellSlabIter<uint64_t> iter(
1004       &subarray, &result_space_tiles, &result_coords);
1005   check_iter<uint64_t>(&iter, c_result_cell_slabs);
1006 
1007   close_array(ctx_, array_);
1008 }
1009 
1010 TEST_CASE_METHOD(
1011     ReadCellSlabIterFx,
1012     "ReadCellSlabIter: Test 2D slabs, multiple ranges, 2 dense fragments, "
1013     "1 sparse, overlap",
1014     "[ReadCellSlabIter][slabs][2d][mr][2df1sf]") {
1015   Layout subarray_layout = Layout::ROW_MAJOR;
1016   Layout tile_domain_layout = Layout::ROW_MAJOR;
1017   tiledb_layout_t tile_order = TILEDB_ROW_MAJOR;
1018   tiledb_layout_t cell_order = TILEDB_ROW_MAJOR;
1019   std::vector<std::vector<uint64_t>> c_result_cell_slabs = {};
1020 
1021   SECTION("- tile: row, cell: row, subarray: row") {
1022     tile_order = TILEDB_ROW_MAJOR;
1023     cell_order = TILEDB_ROW_MAJOR;
1024     subarray_layout = Layout::ROW_MAJOR;
1025     tile_domain_layout = Layout::ROW_MAJOR;
1026     c_result_cell_slabs = {
1027         {2, 0, 7, 1},
1028         {3, 0, 1, 1},
1029         {2, 1, 6, 1},
1030         {1, 1, 7, 2},
1031         {2, 2, 1, 2},
1032         {2, 3, 0, 1},
1033         {UINT64_MAX, 3, 1, 2},
1034         {2, 2, 4, 2},
1035         {2, 3, 3, 1},
1036         {3, 1, 0, 1},
1037         {3, 1, 2, 1},
1038     };
1039   }
1040 
1041   SECTION("- tile: row, cell: col, subarray: row") {
1042     tile_order = TILEDB_ROW_MAJOR;
1043     cell_order = TILEDB_COL_MAJOR;
1044     subarray_layout = Layout::ROW_MAJOR;
1045     tile_domain_layout = Layout::ROW_MAJOR;
1046     c_result_cell_slabs = {
1047         {2, 0, 5, 1},
1048         {3, 0, 1, 1},
1049         {2, 1, 2, 1},
1050         {1, 1, 5, 2},
1051         {2, 2, 3, 2},
1052         {2, 3, 0, 1},
1053         {UINT64_MAX, 3, 3, 2},
1054         {2, 2, 4, 2},
1055         {2, 3, 1, 1},
1056         {3, 1, 0, 1},
1057         {3, 1, 2, 1},
1058     };
1059   }
1060 
1061   SECTION("- tile: col, cell: row, subarray: row") {
1062     tile_order = TILEDB_COL_MAJOR;
1063     cell_order = TILEDB_ROW_MAJOR;
1064     subarray_layout = Layout::ROW_MAJOR;
1065     tile_domain_layout = Layout::COL_MAJOR;
1066     c_result_cell_slabs = {
1067         {2, 0, 7, 1},
1068         {3, 0, 1, 1},
1069         {2, 2, 6, 1},
1070         {1, 1, 7, 2},
1071         {2, 1, 1, 2},
1072         {2, 3, 0, 1},
1073         {UINT64_MAX, 3, 1, 2},
1074         {2, 1, 4, 2},
1075         {2, 3, 3, 1},
1076         {3, 1, 0, 1},
1077         {3, 1, 2, 1},
1078     };
1079   }
1080 
1081   SECTION("- tile: col, cell: col, subarray: row") {
1082     tile_order = TILEDB_COL_MAJOR;
1083     cell_order = TILEDB_COL_MAJOR;
1084     subarray_layout = Layout::ROW_MAJOR;
1085     tile_domain_layout = Layout::COL_MAJOR;
1086     c_result_cell_slabs = {
1087         {2, 0, 5, 1},
1088         {3, 0, 1, 1},
1089         {2, 2, 2, 1},
1090         {1, 1, 5, 2},
1091         {2, 1, 3, 2},
1092         {2, 3, 0, 1},
1093         {UINT64_MAX, 3, 3, 2},
1094         {2, 1, 4, 2},
1095         {2, 3, 1, 1},
1096         {3, 1, 0, 1},
1097         {3, 1, 2, 1},
1098     };
1099   }
1100 
1101   SECTION("- tile: row, cell: row, subarray: col") {
1102     tile_order = TILEDB_ROW_MAJOR;
1103     cell_order = TILEDB_ROW_MAJOR;
1104     subarray_layout = Layout::COL_MAJOR;
1105     tile_domain_layout = Layout::ROW_MAJOR;
1106     c_result_cell_slabs = {
1107         {2, 0, 7, 1},
1108         {2, 2, 1, 2},
1109         {3, 0, 1, 1},
1110         {2, 2, 2, 2},
1111         {2, 1, 6, 1},
1112         {2, 3, 0, 2},
1113         {1, 1, 7, 1},
1114         {UINT64_MAX, 3, 1, 1},
1115         {3, 1, 0, 1},
1116         {1, 1, 8, 1},
1117         {UINT64_MAX, 3, 2, 1},
1118         {3, 1, 2, 1},
1119     };
1120   }
1121 
1122   SECTION("- tile: row, cell: col, subarray: col") {
1123     tile_order = TILEDB_ROW_MAJOR;
1124     cell_order = TILEDB_COL_MAJOR;
1125     subarray_layout = Layout::COL_MAJOR;
1126     tile_domain_layout = Layout::ROW_MAJOR;
1127     c_result_cell_slabs = {
1128         {2, 0, 5, 1},
1129         {2, 2, 3, 2},
1130         {3, 0, 1, 1},
1131         {2, 2, 6, 2},
1132         {2, 1, 2, 1},
1133         {2, 3, 0, 2},
1134         {1, 1, 5, 1},
1135         {UINT64_MAX, 3, 3, 1},
1136         {3, 1, 0, 1},
1137         {1, 1, 8, 1},
1138         {UINT64_MAX, 3, 6, 1},
1139         {3, 1, 2, 1},
1140     };
1141   }
1142 
1143   SECTION("- tile: col, cell: row, subarray: col") {
1144     tile_order = TILEDB_COL_MAJOR;
1145     cell_order = TILEDB_ROW_MAJOR;
1146     subarray_layout = Layout::COL_MAJOR;
1147     tile_domain_layout = Layout::COL_MAJOR;
1148     c_result_cell_slabs = {
1149         {2, 0, 7, 1},
1150         {2, 1, 1, 2},
1151         {3, 0, 1, 1},
1152         {2, 1, 2, 2},
1153         {2, 2, 6, 1},
1154         {2, 3, 0, 2},
1155         {1, 1, 7, 1},
1156         {UINT64_MAX, 3, 1, 1},
1157         {3, 1, 0, 1},
1158         {1, 1, 8, 1},
1159         {UINT64_MAX, 3, 2, 1},
1160         {3, 1, 2, 1},
1161     };
1162   }
1163 
1164   SECTION("- tile: col, cell: col, subarray: col") {
1165     tile_order = TILEDB_COL_MAJOR;
1166     cell_order = TILEDB_COL_MAJOR;
1167     subarray_layout = Layout::COL_MAJOR;
1168     tile_domain_layout = Layout::COL_MAJOR;
1169     c_result_cell_slabs = {
1170         {2, 0, 5, 1},
1171         {2, 1, 3, 2},
1172         {3, 0, 1, 1},
1173         {2, 1, 6, 2},
1174         {2, 2, 2, 1},
1175         {2, 3, 0, 2},
1176         {1, 1, 5, 1},
1177         {UINT64_MAX, 3, 3, 1},
1178         {3, 1, 0, 1},
1179         {1, 1, 8, 1},
1180         {UINT64_MAX, 3, 6, 1},
1181         {3, 1, 2, 1},
1182     };
1183   }
1184 
1185   // Create array
1186   uint64_t domain[] = {1, 6, 1, 6};
1187   uint64_t tile_extents[] = {3, 3};
1188   create_array(
1189       ctx_,
1190       array_name_,
1191       TILEDB_DENSE,
1192       {"d1", "d2"},
1193       {TILEDB_UINT64, TILEDB_UINT64},
1194       {&domain[0], &domain[2]},
1195       {&tile_extents[0], &tile_extents[1]},
1196       {"a", "b"},
1197       {TILEDB_INT32, TILEDB_INT32},
1198       {1, TILEDB_VAR_NUM},
1199       {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
1200        tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
1201       tile_order,
1202       cell_order,
1203       2);
1204 
1205   // Create subarray
1206   open_array(ctx_, array_, TILEDB_READ);
1207   Subarray subarray;
1208   SubarrayRanges<uint64_t> ranges = {{3, 5}, {2, 4, 5, 6}};
1209   create_subarray(array_->array_, ranges, subarray_layout, &subarray);
1210   subarray.compute_tile_coords<uint64_t>();
1211 
1212   // Create result space tiles
1213   std::vector<uint64_t> slice_1 = {3, 5, 2, 4};
1214   std::vector<uint64_t> slice_2 = {2, 3, 1, 6};
1215   auto size = 2 * sizeof(uint64_t);
1216   NDRange ds1 = {Range(&slice_1[0], size), Range(&slice_1[2], size)};
1217   NDRange ds2 = {Range(&slice_2[0], size), Range(&slice_2[2], size)};
1218   std::vector<NDRange> domain_slices = {ds1, ds2};
1219   const auto& tile_coords = subarray.tile_coords();
1220   std::map<const uint64_t*, ResultSpaceTile<uint64_t>> result_space_tiles;
1221   auto dom = array_->array_->array_schema_latest()->domain();
1222   create_result_space_tiles(
1223       dom,
1224       dom->domain(),
1225       tile_domain_layout,
1226       domain_slices,
1227       tile_coords,
1228       &result_space_tiles);
1229 
1230   // Create result coordinates
1231   std::vector<ResultCoords> result_coords;
1232   ResultTile result_tile_3_0(3, 0, dom);
1233   ResultTile result_tile_3_1(3, 1, dom);
1234 
1235   result_tile_3_0.init_coord_tile("d1", 0);
1236   result_tile_3_0.init_coord_tile("d2", 1);
1237   result_tile_3_1.init_coord_tile("d1", 0);
1238   result_tile_3_1.init_coord_tile("d2", 1);
1239 
1240   std::vector<uint64_t> vec_3_0_d1 = {1000, 3, 1000, 1000};
1241   Buffer buff_3_0_d1(&vec_3_0_d1[0], vec_3_0_d1.size() * sizeof(uint64_t));
1242   Tile tile_3_0_d1(Datatype::UINT64, sizeof(uint64_t), 0, &buff_3_0_d1, false);
1243   auto tile_tuple = result_tile_3_0.tile_tuple("d1");
1244   REQUIRE(tile_tuple != nullptr);
1245   std::get<0>(*tile_tuple) = tile_3_0_d1;
1246 
1247   std::vector<uint64_t> vec_3_0_d2 = {1000, 3, 1000, 1000};
1248   Buffer buff_3_0_d2(&vec_3_0_d2[0], vec_3_0_d2.size() * sizeof(uint64_t));
1249   Tile tile_3_0_d2(Datatype::UINT64, sizeof(uint64_t), 0, &buff_3_0_d2, false);
1250   tile_tuple = result_tile_3_0.tile_tuple("d2");
1251   REQUIRE(tile_tuple != nullptr);
1252   std::get<0>(*tile_tuple) = tile_3_0_d2;
1253 
1254   std::vector<uint64_t> vec_3_1_d1 = {5, 1000, 5, 1000};
1255   Buffer buff_3_1_d1(&vec_3_1_d1[0], vec_3_1_d1.size() * sizeof(uint64_t));
1256   Tile tile_3_1_d1(Datatype::UINT64, sizeof(uint64_t), 0, &buff_3_1_d1, false);
1257   tile_tuple = result_tile_3_1.tile_tuple("d1");
1258   REQUIRE(tile_tuple != nullptr);
1259   std::get<0>(*tile_tuple) = tile_3_1_d1;
1260 
1261   std::vector<uint64_t> vec_3_1_d2 = {5, 1000, 6, 1000};
1262   Buffer buff_3_1_d2(&vec_3_1_d2[0], vec_3_1_d2.size() * sizeof(uint64_t));
1263   Tile tile_3_1_d2(Datatype::UINT64, sizeof(uint64_t), 0, &buff_3_1_d2, false);
1264   tile_tuple = result_tile_3_1.tile_tuple("d2");
1265   REQUIRE(tile_tuple != nullptr);
1266   std::get<0>(*tile_tuple) = tile_3_1_d2;
1267 
1268   result_coords.emplace_back(&result_tile_3_0, 1);
1269   result_coords.emplace_back(&result_tile_3_1, 0);
1270   result_coords.emplace_back(&result_tile_3_1, 2);
1271 
1272   // Check iterator
1273   ReadCellSlabIter<uint64_t> iter(
1274       &subarray, &result_space_tiles, &result_coords);
1275   check_iter<uint64_t>(&iter, c_result_cell_slabs);
1276 
1277   close_array(ctx_, array_);
1278 }