1 /**
2  * @file   helpers.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  * This file defines some test suite helper functions.
31  */
32 
33 #include "helpers.h"
34 #include "catch.hpp"
35 #include "tiledb/common/logger.h"
36 #include "tiledb/sm/cpp_api/tiledb"
37 #include "tiledb/sm/enums/encryption_type.h"
38 #include "tiledb/sm/global_state/unit_test_config.h"
39 #include "tiledb/sm/misc/constants.h"
40 #include "tiledb/sm/misc/uri.h"
41 #include "tiledb/sm/subarray/subarray_partitioner.h"
42 
43 std::mutex catch2_macro_mutex;
44 
45 namespace tiledb {
46 namespace test {
47 
48 // Command line arguments.
49 extern std::string g_vfs;
50 
use_refactored_dense_reader()51 bool use_refactored_dense_reader() {
52   const char* value = nullptr;
53   tiledb_config_t* cfg;
54   tiledb_error_t* err = nullptr;
55   auto rc = tiledb_config_alloc(&cfg, &err);
56   REQUIRE(rc == TILEDB_OK);
57   REQUIRE(err == nullptr);
58 
59   rc = tiledb_config_get(cfg, "sm.query.dense.reader", &value, &err);
60   CHECK(rc == TILEDB_OK);
61   CHECK(err == nullptr);
62 
63   bool use_refactored_readers = strcmp(value, "refactored") == 0;
64 
65   tiledb_config_free(&cfg);
66 
67   return use_refactored_readers;
68 }
69 
use_refactored_sparse_global_order_reader()70 bool use_refactored_sparse_global_order_reader() {
71   const char* value = nullptr;
72   tiledb_config_t* cfg;
73   tiledb_error_t* err = nullptr;
74   auto rc = tiledb_config_alloc(&cfg, &err);
75   REQUIRE(rc == TILEDB_OK);
76   REQUIRE(err == nullptr);
77 
78   rc = tiledb_config_get(
79       cfg, "sm.query.sparse_global_order.reader", &value, &err);
80   CHECK(rc == TILEDB_OK);
81   CHECK(err == nullptr);
82 
83   bool use_refactored_readers = strcmp(value, "refactored") == 0;
84 
85   tiledb_config_free(&cfg);
86 
87   return use_refactored_readers;
88 }
89 
use_refactored_sparse_unordered_with_dups_reader()90 bool use_refactored_sparse_unordered_with_dups_reader() {
91   const char* value = nullptr;
92   tiledb_config_t* cfg;
93   tiledb_error_t* err = nullptr;
94   auto rc = tiledb_config_alloc(&cfg, &err);
95   REQUIRE(rc == TILEDB_OK);
96   REQUIRE(err == nullptr);
97 
98   rc = tiledb_config_get(
99       cfg, "sm.query.sparse_unordered_with_dups.reader", &value, &err);
100   CHECK(rc == TILEDB_OK);
101   CHECK(err == nullptr);
102 
103   bool use_refactored_readers = strcmp(value, "refactored") == 0;
104 
105   tiledb_config_free(&cfg);
106 
107   return use_refactored_readers;
108 }
109 
g_helper_logger(void)110 tdb_shared_ptr<Logger> g_helper_logger(void) {
111   static tdb_shared_ptr<Logger> g_helper_logger = tdb_make_shared(Logger, "");
112   return g_helper_logger;
113 }
114 
115 template <class T>
check_partitions(tiledb::sm::SubarrayPartitioner & partitioner,const std::vector<SubarrayRanges<T>> & partitions,bool last_unsplittable)116 void check_partitions(
117     tiledb::sm::SubarrayPartitioner& partitioner,
118     const std::vector<SubarrayRanges<T>>& partitions,
119     bool last_unsplittable) {
120   bool unsplittable = false;
121 
122   // Special case for empty partitions
123   if (partitions.empty()) {
124     CHECK(partitioner.next(&unsplittable).ok());
125     if (last_unsplittable) {
126       CHECK(unsplittable);
127     } else {
128       CHECK(!unsplittable);
129       CHECK(partitioner.done());
130     }
131     return;
132   }
133 
134   // Non-empty partitions
135   for (const auto& p : partitions) {
136     CHECK(!partitioner.done());
137     CHECK(!unsplittable);
138     CHECK(partitioner.next(&unsplittable).ok());
139     auto partition = partitioner.current();
140     check_subarray<T>(partition, p);
141   }
142 
143   // Check last unsplittable
144   if (last_unsplittable) {
145     CHECK(unsplittable);
146   } else {
147     CHECK(!unsplittable);
148     CHECK(partitioner.next(&unsplittable).ok());
149     CHECK(!unsplittable);
150     CHECK(partitioner.done());
151   }
152 }
153 
154 template <class T>
check_subarray(tiledb::sm::Subarray & subarray,const SubarrayRanges<T> & ranges)155 void check_subarray(
156     tiledb::sm::Subarray& subarray, const SubarrayRanges<T>& ranges) {
157   // Check empty subarray
158   auto subarray_range_num = subarray.range_num();
159   if (ranges.empty()) {
160     CHECK(subarray_range_num == 0);
161     return;
162   }
163   uint64_t range_num = 1;
164   for (const auto& dim_ranges : ranges)
165     range_num *= dim_ranges.size() / 2;
166   CHECK(subarray_range_num == range_num);
167 
168   // Check dim num
169   auto dim_num = subarray.dim_num();
170   CHECK(dim_num == ranges.size());
171 
172   // Check ranges
173   uint64_t dim_range_num = 0;
174   const sm::Range* range;
175   for (unsigned i = 0; i < dim_num; ++i) {
176     CHECK(subarray.get_range_num(i, &dim_range_num).ok());
177     CHECK(dim_range_num == ranges[i].size() / 2);
178     for (uint64_t j = 0; j < dim_range_num; ++j) {
179       subarray.get_range(i, j, &range);
180       auto r = (const T*)range->data();
181 
182       CHECK(r[0] == ranges[i][2 * j]);
183       CHECK(r[1] == ranges[i][2 * j + 1]);
184     }
185   }
186 }
187 
close_array(tiledb_ctx_t * ctx,tiledb_array_t * array)188 void close_array(tiledb_ctx_t* ctx, tiledb_array_t* array) {
189   int rc = tiledb_array_close(ctx, array);
190   CHECK(rc == TILEDB_OK);
191 }
192 
array_create_wrapper(tiledb_ctx_t * ctx,const std::string & path,tiledb_array_schema_t * array_schema,bool serialize_array_schema)193 int array_create_wrapper(
194     tiledb_ctx_t* ctx,
195     const std::string& path,
196     tiledb_array_schema_t* array_schema,
197     bool serialize_array_schema) {
198 #ifndef TILEDB_SERIALIZATION
199   return tiledb_array_create(ctx, path.c_str(), array_schema);
200 #endif
201 
202   if (!serialize_array_schema) {
203     return tiledb_array_create(ctx, path.c_str(), array_schema);
204   }
205 
206   // Serialize the array
207   tiledb_buffer_t* buff;
208   REQUIRE(
209       tiledb_serialize_array_schema(
210           ctx,
211           array_schema,
212           (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
213           1,
214           &buff) == TILEDB_OK);
215 
216   // Load array schema from the rest server
217   tiledb_array_schema_t* new_array_schema = nullptr;
218   REQUIRE(
219       tiledb_deserialize_array_schema(
220           ctx,
221           buff,
222           (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
223           0,
224           &new_array_schema) == TILEDB_OK);
225 
226   // Create array from new schema
227   int rc = tiledb_array_create(ctx, path.c_str(), new_array_schema);
228 
229   // Serialize the new array schema and deserialize into the original array
230   // schema.
231   tiledb_buffer_t* buff2;
232   REQUIRE(
233       tiledb_serialize_array_schema(
234           ctx,
235           new_array_schema,
236           (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
237           0,
238           &buff2) == TILEDB_OK);
239   REQUIRE(
240       tiledb_deserialize_array_schema(
241           ctx,
242           buff2,
243           (tiledb_serialization_type_t)tiledb::sm::SerializationType::CAPNP,
244           1,
245           &array_schema) == TILEDB_OK);
246 
247   // Clean up.
248   tiledb_array_schema_free(&array_schema);
249   tiledb_array_schema_free(&new_array_schema);
250   tiledb_buffer_free(&buff);
251   tiledb_buffer_free(&buff2);
252 
253   return rc;
254 }
255 
create_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_array_type_t array_type,const std::vector<std::string> & dim_names,const std::vector<tiledb_datatype_t> & dim_types,const std::vector<void * > & dim_domains,const std::vector<void * > & tile_extents,const std::vector<std::string> & attr_names,const std::vector<tiledb_datatype_t> & attr_types,const std::vector<uint32_t> & cell_val_num,const std::vector<std::pair<tiledb_filter_type_t,int>> & compressors,tiledb_layout_t tile_order,tiledb_layout_t cell_order,uint64_t capacity,bool allows_dups,bool serialize_array_schema)256 void create_array(
257     tiledb_ctx_t* ctx,
258     const std::string& array_name,
259     tiledb_array_type_t array_type,
260     const std::vector<std::string>& dim_names,
261     const std::vector<tiledb_datatype_t>& dim_types,
262     const std::vector<void*>& dim_domains,
263     const std::vector<void*>& tile_extents,
264     const std::vector<std::string>& attr_names,
265     const std::vector<tiledb_datatype_t>& attr_types,
266     const std::vector<uint32_t>& cell_val_num,
267     const std::vector<std::pair<tiledb_filter_type_t, int>>& compressors,
268     tiledb_layout_t tile_order,
269     tiledb_layout_t cell_order,
270     uint64_t capacity,
271     bool allows_dups,
272     bool serialize_array_schema) {
273   // For easy reference
274   auto dim_num = dim_names.size();
275   auto attr_num = attr_names.size();
276 
277   // Sanity checks
278   assert(dim_types.size() == dim_num);
279   assert(dim_domains.size() == dim_num);
280   assert(tile_extents.size() == dim_num);
281   assert(attr_types.size() == attr_num);
282   assert(cell_val_num.size() == attr_num);
283   assert(compressors.size() == attr_num);
284 
285   // Create array schema
286   tiledb_array_schema_t* array_schema;
287   int rc = tiledb_array_schema_alloc(ctx, array_type, &array_schema);
288   REQUIRE(rc == TILEDB_OK);
289   rc = tiledb_array_schema_set_cell_order(ctx, array_schema, cell_order);
290   REQUIRE(rc == TILEDB_OK);
291   rc = tiledb_array_schema_set_tile_order(ctx, array_schema, tile_order);
292   REQUIRE(rc == TILEDB_OK);
293   rc = tiledb_array_schema_set_capacity(ctx, array_schema, capacity);
294   REQUIRE(rc == TILEDB_OK);
295   rc = tiledb_array_schema_set_allows_dups(ctx, array_schema, (int)allows_dups);
296   REQUIRE(rc == TILEDB_OK);
297 
298   // Create dimensions and domain
299   tiledb_domain_t* domain;
300   rc = tiledb_domain_alloc(ctx, &domain);
301   REQUIRE(rc == TILEDB_OK);
302   for (size_t i = 0; i < dim_num; ++i) {
303     tiledb_dimension_t* d;
304     rc = tiledb_dimension_alloc(
305         ctx,
306         dim_names[i].c_str(),
307         dim_types[i],
308         dim_domains[i],
309         tile_extents[i],
310         &d);
311     REQUIRE(rc == TILEDB_OK);
312     rc = tiledb_domain_add_dimension(ctx, domain, d);
313     REQUIRE(rc == TILEDB_OK);
314     tiledb_dimension_free(&d);
315   }
316 
317   // Set domain to schema
318   rc = tiledb_array_schema_set_domain(ctx, array_schema, domain);
319   REQUIRE(rc == TILEDB_OK);
320   tiledb_domain_free(&domain);
321 
322   // Create attributes
323   for (size_t i = 0; i < attr_num; ++i) {
324     tiledb_attribute_t* a;
325     rc = tiledb_attribute_alloc(ctx, attr_names[i].c_str(), attr_types[i], &a);
326     REQUIRE(rc == TILEDB_OK);
327     rc = set_attribute_compression_filter(
328         ctx, a, compressors[i].first, compressors[i].second);
329     REQUIRE(rc == TILEDB_OK);
330     rc = tiledb_attribute_set_cell_val_num(ctx, a, cell_val_num[i]);
331     REQUIRE(rc == TILEDB_OK);
332     rc = tiledb_array_schema_add_attribute(ctx, array_schema, a);
333     REQUIRE(rc == TILEDB_OK);
334     tiledb_attribute_free(&a);
335   }
336 
337   // Check array schema
338   rc = tiledb_array_schema_check(ctx, array_schema);
339   REQUIRE(rc == TILEDB_OK);
340 
341   // Create array
342   rc = array_create_wrapper(
343       ctx, array_name, array_schema, serialize_array_schema);
344   REQUIRE(rc == TILEDB_OK);
345 
346   // Clean up
347   tiledb_array_schema_free(&array_schema);
348 }
349 
create_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_encryption_type_t enc_type,const char * key,uint32_t key_len,tiledb_array_type_t array_type,const std::vector<std::string> & dim_names,const std::vector<tiledb_datatype_t> & dim_types,const std::vector<void * > & dim_domains,const std::vector<void * > & tile_extents,const std::vector<std::string> & attr_names,const std::vector<tiledb_datatype_t> & attr_types,const std::vector<uint32_t> & cell_val_num,const std::vector<std::pair<tiledb_filter_type_t,int>> & compressors,tiledb_layout_t tile_order,tiledb_layout_t cell_order,uint64_t capacity)350 void create_array(
351     tiledb_ctx_t* ctx,
352     const std::string& array_name,
353     tiledb_encryption_type_t enc_type,
354     const char* key,
355     uint32_t key_len,
356     tiledb_array_type_t array_type,
357     const std::vector<std::string>& dim_names,
358     const std::vector<tiledb_datatype_t>& dim_types,
359     const std::vector<void*>& dim_domains,
360     const std::vector<void*>& tile_extents,
361     const std::vector<std::string>& attr_names,
362     const std::vector<tiledb_datatype_t>& attr_types,
363     const std::vector<uint32_t>& cell_val_num,
364     const std::vector<std::pair<tiledb_filter_type_t, int>>& compressors,
365     tiledb_layout_t tile_order,
366     tiledb_layout_t cell_order,
367     uint64_t capacity) {
368   // For easy reference
369   auto dim_num = dim_names.size();
370   auto attr_num = attr_names.size();
371 
372   // Sanity checks
373   assert(dim_types.size() == dim_num);
374   assert(dim_domains.size() == dim_num);
375   assert(tile_extents.size() == dim_num);
376   assert(attr_types.size() == attr_num);
377   assert(cell_val_num.size() == attr_num);
378   assert(compressors.size() == attr_num);
379 
380   // Create array schema
381   tiledb_array_schema_t* array_schema;
382   int rc = tiledb_array_schema_alloc(ctx, array_type, &array_schema);
383   REQUIRE(rc == TILEDB_OK);
384   rc = tiledb_array_schema_set_cell_order(ctx, array_schema, cell_order);
385   REQUIRE(rc == TILEDB_OK);
386   rc = tiledb_array_schema_set_tile_order(ctx, array_schema, tile_order);
387   REQUIRE(rc == TILEDB_OK);
388   rc = tiledb_array_schema_set_capacity(ctx, array_schema, capacity);
389   REQUIRE(rc == TILEDB_OK);
390 
391   // Create dimensions and domain
392   tiledb_domain_t* domain;
393   rc = tiledb_domain_alloc(ctx, &domain);
394   REQUIRE(rc == TILEDB_OK);
395   for (size_t i = 0; i < dim_num; ++i) {
396     tiledb_dimension_t* d;
397     rc = tiledb_dimension_alloc(
398         ctx,
399         dim_names[i].c_str(),
400         dim_types[i],
401         dim_domains[i],
402         tile_extents[i],
403         &d);
404     REQUIRE(rc == TILEDB_OK);
405     rc = tiledb_domain_add_dimension(ctx, domain, d);
406     REQUIRE(rc == TILEDB_OK);
407     tiledb_dimension_free(&d);
408   }
409 
410   // Set domain to schema
411   rc = tiledb_array_schema_set_domain(ctx, array_schema, domain);
412   REQUIRE(rc == TILEDB_OK);
413   tiledb_domain_free(&domain);
414 
415   // Create attributes
416   for (size_t i = 0; i < attr_num; ++i) {
417     tiledb_attribute_t* a;
418     rc = tiledb_attribute_alloc(ctx, attr_names[i].c_str(), attr_types[i], &a);
419     REQUIRE(rc == TILEDB_OK);
420     rc = set_attribute_compression_filter(
421         ctx, a, compressors[i].first, compressors[i].second);
422     REQUIRE(rc == TILEDB_OK);
423     rc = tiledb_attribute_set_cell_val_num(ctx, a, cell_val_num[i]);
424     REQUIRE(rc == TILEDB_OK);
425     rc = tiledb_array_schema_add_attribute(ctx, array_schema, a);
426     REQUIRE(rc == TILEDB_OK);
427     tiledb_attribute_free(&a);
428   }
429 
430   // Check array schema
431   rc = tiledb_array_schema_check(ctx, array_schema);
432   REQUIRE(rc == TILEDB_OK);
433 
434   // Create array
435   tiledb_config_t* config;
436   tiledb_error_t* error = nullptr;
437   rc = tiledb_config_alloc(&config, &error);
438   REQUIRE(rc == TILEDB_OK);
439   REQUIRE(error == nullptr);
440   std::string encryption_type_string =
441       encryption_type_str((tiledb::sm::EncryptionType)enc_type);
442   rc = tiledb_config_set(
443       config, "sm.encryption_type", encryption_type_string.c_str(), &error);
444   REQUIRE(error == nullptr);
445   rc = tiledb_config_set(config, "sm.encryption_key", key, &error);
446   REQUIRE(rc == TILEDB_OK);
447   REQUIRE(error == nullptr);
448   tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
449       key_len);
450   tiledb_ctx_t* ctx_array;
451   REQUIRE(tiledb_ctx_alloc(config, &ctx_array) == TILEDB_OK);
452   rc = tiledb_array_create(ctx_array, array_name.c_str(), array_schema);
453   REQUIRE(rc == TILEDB_OK);
454 
455   // Clean up
456   tiledb_array_schema_free(&array_schema);
457   tiledb_ctx_free(&ctx_array);
458 }
459 
create_s3_bucket(const std::string & bucket_name,bool s3_supported,tiledb_ctx_t * ctx,tiledb_vfs_t * vfs)460 void create_s3_bucket(
461     const std::string& bucket_name,
462     bool s3_supported,
463     tiledb_ctx_t* ctx,
464     tiledb_vfs_t* vfs) {
465   if (s3_supported) {
466     // Create bucket if it does not exist
467     int is_bucket = 0;
468     int rc = tiledb_vfs_is_bucket(ctx, vfs, bucket_name.c_str(), &is_bucket);
469     REQUIRE(rc == TILEDB_OK);
470     if (!is_bucket) {
471       rc = tiledb_vfs_create_bucket(ctx, vfs, bucket_name.c_str());
472       REQUIRE(rc == TILEDB_OK);
473     }
474   }
475 }
476 
create_azure_container(const std::string & container_name,bool azure_supported,tiledb_ctx_t * ctx,tiledb_vfs_t * vfs)477 void create_azure_container(
478     const std::string& container_name,
479     bool azure_supported,
480     tiledb_ctx_t* ctx,
481     tiledb_vfs_t* vfs) {
482   if (azure_supported) {
483     // Create container if it does not exist
484     int is_container = 0;
485     int rc =
486         tiledb_vfs_is_bucket(ctx, vfs, container_name.c_str(), &is_container);
487     REQUIRE(rc == TILEDB_OK);
488     if (!is_container) {
489       rc = tiledb_vfs_create_bucket(ctx, vfs, container_name.c_str());
490       REQUIRE(rc == TILEDB_OK);
491     }
492   }
493 }
494 
create_ctx_and_vfs(bool s3_supported,bool azure_supported,tiledb_ctx_t ** ctx,tiledb_vfs_t ** vfs)495 void create_ctx_and_vfs(
496     bool s3_supported,
497     bool azure_supported,
498     tiledb_ctx_t** ctx,
499     tiledb_vfs_t** vfs) {
500   // Create TileDB context
501   tiledb_config_t* config = nullptr;
502   tiledb_error_t* error = nullptr;
503   REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
504   REQUIRE(error == nullptr);
505   if (s3_supported) {
506 #ifndef TILEDB_TESTS_AWS_S3_CONFIG
507     REQUIRE(
508         tiledb_config_set(
509             config, "vfs.s3.endpoint_override", "localhost:9999", &error) ==
510         TILEDB_OK);
511     REQUIRE(
512         tiledb_config_set(config, "vfs.s3.scheme", "https", &error) ==
513         TILEDB_OK);
514     REQUIRE(
515         tiledb_config_set(
516             config, "vfs.s3.use_virtual_addressing", "false", &error) ==
517         TILEDB_OK);
518     REQUIRE(
519         tiledb_config_set(config, "vfs.s3.verify_ssl", "false", &error) ==
520         TILEDB_OK);
521     REQUIRE(error == nullptr);
522 #endif
523   }
524   if (azure_supported) {
525     REQUIRE(
526         tiledb_config_set(
527             config,
528             "vfs.azure.storage_account_name",
529             "devstoreaccount1",
530             &error) == TILEDB_OK);
531     REQUIRE(
532         tiledb_config_set(
533             config,
534             "vfs.azure.storage_account_key",
535             "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/"
536             "K1SZFPTOtr/KBHBeksoGMGw==",
537             &error) == TILEDB_OK);
538     REQUIRE(
539         tiledb_config_set(
540             config,
541             "vfs.azure.blob_endpoint",
542             "127.0.0.1:10000/devstoreaccount1",
543             &error) == TILEDB_OK);
544     REQUIRE(
545         tiledb_config_set(config, "vfs.azure.use_https", "false", &error) ==
546         TILEDB_OK);
547   }
548   REQUIRE(tiledb_ctx_alloc(config, ctx) == TILEDB_OK);
549   REQUIRE(error == nullptr);
550 
551   // Create VFS
552   *vfs = nullptr;
553   REQUIRE(tiledb_vfs_alloc(*ctx, config, vfs) == TILEDB_OK);
554   tiledb_config_free(&config);
555 }
556 
create_dir(const std::string & path,tiledb_ctx_t * ctx,tiledb_vfs_t * vfs)557 void create_dir(const std::string& path, tiledb_ctx_t* ctx, tiledb_vfs_t* vfs) {
558   remove_dir(path, ctx, vfs);
559   REQUIRE(tiledb_vfs_create_dir(ctx, vfs, path.c_str()) == TILEDB_OK);
560 }
561 
562 template <class T>
create_subarray(tiledb::sm::Array * array,const SubarrayRanges<T> & ranges,tiledb::sm::Layout layout,tiledb::sm::Subarray * subarray,bool coalesce_ranges)563 void create_subarray(
564     tiledb::sm::Array* array,
565     const SubarrayRanges<T>& ranges,
566     tiledb::sm::Layout layout,
567     tiledb::sm::Subarray* subarray,
568     bool coalesce_ranges) {
569   tiledb::sm::Subarray ret(
570       array, layout, &g_helper_stats, g_helper_logger(), coalesce_ranges);
571 
572   auto dim_num = (unsigned)ranges.size();
573   for (unsigned d = 0; d < dim_num; ++d) {
574     auto dim_range_num = ranges[d].size() / 2;
575     for (size_t j = 0; j < dim_range_num; ++j) {
576       sm::Range range(&ranges[d][2 * j], 2 * sizeof(T));
577       ret.add_range(d, std::move(range), true);
578     }
579   }
580 
581   *subarray = ret;
582 }
583 
get_supported_fs(bool * s3_supported,bool * hdfs_supported,bool * azure_supported,bool * gcs_supported)584 void get_supported_fs(
585     bool* s3_supported,
586     bool* hdfs_supported,
587     bool* azure_supported,
588     bool* gcs_supported) {
589   tiledb_ctx_t* ctx = nullptr;
590   REQUIRE(tiledb_ctx_alloc(nullptr, &ctx) == TILEDB_OK);
591 
592   int is_supported = 0;
593   int rc = tiledb_ctx_is_supported_fs(ctx, TILEDB_S3, &is_supported);
594   REQUIRE(rc == TILEDB_OK);
595   *s3_supported = (bool)is_supported;
596   rc = tiledb_ctx_is_supported_fs(ctx, TILEDB_HDFS, &is_supported);
597   REQUIRE(rc == TILEDB_OK);
598   *hdfs_supported = (bool)is_supported;
599   rc = tiledb_ctx_is_supported_fs(ctx, TILEDB_AZURE, &is_supported);
600   REQUIRE(rc == TILEDB_OK);
601   *azure_supported = (bool)is_supported;
602   rc = tiledb_ctx_is_supported_fs(ctx, TILEDB_GCS, &is_supported);
603   REQUIRE(rc == TILEDB_OK);
604   *gcs_supported = (bool)is_supported;
605 
606   // Override VFS support if the user used the '--vfs' command line argument.
607   if (!g_vfs.empty()) {
608     REQUIRE(
609         (g_vfs == "native" || g_vfs == "s3" || g_vfs == "hdfs" ||
610          g_vfs == "azure" || g_vfs == "gcs"));
611 
612     if (g_vfs == "native") {
613       *s3_supported = false;
614       *hdfs_supported = false;
615       *azure_supported = false;
616       *gcs_supported = false;
617     }
618 
619     if (g_vfs == "s3") {
620       *s3_supported = true;
621       *hdfs_supported = false;
622       *azure_supported = false;
623       *gcs_supported = false;
624     }
625 
626     if (g_vfs == "hdfs") {
627       *s3_supported = false;
628       *hdfs_supported = true;
629       *azure_supported = false;
630       *gcs_supported = false;
631     }
632 
633     if (g_vfs == "azure") {
634       *s3_supported = false;
635       *hdfs_supported = false;
636       *azure_supported = true;
637       *gcs_supported = false;
638     }
639 
640     if (g_vfs == "gcs") {
641       *s3_supported = false;
642       *hdfs_supported = false;
643       *azure_supported = false;
644       *gcs_supported = true;
645     }
646   }
647 
648   tiledb_ctx_free(&ctx);
649 }
650 
open_array(tiledb_ctx_t * ctx,tiledb_array_t * array,tiledb_query_type_t query_type)651 void open_array(
652     tiledb_ctx_t* ctx, tiledb_array_t* array, tiledb_query_type_t query_type) {
653   int rc = tiledb_array_open(ctx, array, query_type);
654   CHECK(rc == TILEDB_OK);
655 }
656 
random_name(const std::string & prefix)657 std::string random_name(const std::string& prefix) {
658   std::stringstream ss;
659   ss << prefix << "-" << std::this_thread::get_id() << "-"
660      << TILEDB_TIMESTAMP_NOW_MS;
661   return ss.str();
662 }
663 
remove_dir(const std::string & path,tiledb_ctx_t * ctx,tiledb_vfs_t * vfs)664 void remove_dir(const std::string& path, tiledb_ctx_t* ctx, tiledb_vfs_t* vfs) {
665   int is_dir = 0;
666   REQUIRE(tiledb_vfs_is_dir(ctx, vfs, path.c_str(), &is_dir) == TILEDB_OK);
667   if (is_dir)
668     REQUIRE(tiledb_vfs_remove_dir(ctx, vfs, path.c_str()) == TILEDB_OK);
669 }
670 
remove_s3_bucket(const std::string & bucket_name,bool s3_supported,tiledb_ctx_t * ctx,tiledb_vfs_t * vfs)671 void remove_s3_bucket(
672     const std::string& bucket_name,
673     bool s3_supported,
674     tiledb_ctx_t* ctx,
675     tiledb_vfs_t* vfs) {
676   if (s3_supported) {
677     int is_bucket = 0;
678     int rc = tiledb_vfs_is_bucket(ctx, vfs, bucket_name.c_str(), &is_bucket);
679     CHECK(rc == TILEDB_OK);
680     if (is_bucket) {
681       rc = tiledb_vfs_remove_bucket(ctx, vfs, bucket_name.c_str());
682       CHECK(rc == TILEDB_OK);
683     }
684   }
685 }
686 
set_attribute_compression_filter(tiledb_ctx_t * ctx,tiledb_attribute_t * attr,tiledb_filter_type_t compressor,int32_t level)687 int set_attribute_compression_filter(
688     tiledb_ctx_t* ctx,
689     tiledb_attribute_t* attr,
690     tiledb_filter_type_t compressor,
691     int32_t level) {
692   if (compressor == TILEDB_FILTER_NONE)
693     return TILEDB_OK;
694 
695   tiledb_filter_t* filter;
696   int rc = tiledb_filter_alloc(ctx, compressor, &filter);
697   REQUIRE(rc == TILEDB_OK);
698   rc = tiledb_filter_set_option(ctx, filter, TILEDB_COMPRESSION_LEVEL, &level);
699   REQUIRE(rc == TILEDB_OK);
700   tiledb_filter_list_t* list;
701   rc = tiledb_filter_list_alloc(ctx, &list);
702   REQUIRE(rc == TILEDB_OK);
703   rc = tiledb_filter_list_add_filter(ctx, list, filter);
704   REQUIRE(rc == TILEDB_OK);
705   rc = tiledb_attribute_set_filter_list(ctx, attr, list);
706   REQUIRE(rc == TILEDB_OK);
707 
708   tiledb_filter_free(&filter);
709   tiledb_filter_list_free(&list);
710 
711   return TILEDB_OK;
712 }
713 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_layout_t layout,const QueryBuffers & buffers)714 void write_array(
715     tiledb_ctx_t* ctx,
716     const std::string& array_name,
717     tiledb_layout_t layout,
718     const QueryBuffers& buffers) {
719   write_array(
720       ctx, array_name, TILEDB_TIMESTAMP_NOW_MS, nullptr, layout, buffers);
721 }
722 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,uint64_t timestamp,tiledb_layout_t layout,const QueryBuffers & buffers)723 void write_array(
724     tiledb_ctx_t* ctx,
725     const std::string& array_name,
726     uint64_t timestamp,
727     tiledb_layout_t layout,
728     const QueryBuffers& buffers) {
729   write_array(ctx, array_name, timestamp, nullptr, layout, buffers);
730 }
731 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_encryption_type_t encryption_type,const char * key,uint64_t key_len,uint64_t timestamp,tiledb_layout_t layout,const QueryBuffers & buffers)732 void write_array(
733     tiledb_ctx_t* ctx,
734     const std::string& array_name,
735     tiledb_encryption_type_t encryption_type,
736     const char* key,
737     uint64_t key_len,
738     uint64_t timestamp,
739     tiledb_layout_t layout,
740     const QueryBuffers& buffers) {
741   write_array(
742       ctx,
743       array_name,
744       encryption_type,
745       key,
746       key_len,
747       timestamp,
748       nullptr,
749       layout,
750       buffers);
751 }
752 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,const void * subarray,tiledb_layout_t layout,const QueryBuffers & buffers)753 void write_array(
754     tiledb_ctx_t* ctx,
755     const std::string& array_name,
756     const void* subarray,
757     tiledb_layout_t layout,
758     const QueryBuffers& buffers) {
759   write_array(
760       ctx, array_name, TILEDB_TIMESTAMP_NOW_MS, subarray, layout, buffers);
761 }
762 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,uint64_t timestamp,const void * subarray,tiledb_layout_t layout,const QueryBuffers & buffers)763 void write_array(
764     tiledb_ctx_t* ctx,
765     const std::string& array_name,
766     uint64_t timestamp,
767     const void* subarray,
768     tiledb_layout_t layout,
769     const QueryBuffers& buffers) {
770   std::string uri;
771   write_array(ctx, array_name, timestamp, subarray, layout, buffers, &uri);
772   (void)uri;
773 }
774 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_encryption_type_t encryption_type,const char * key,uint64_t key_len,uint64_t timestamp,const void * subarray,tiledb_layout_t layout,const QueryBuffers & buffers)775 void write_array(
776     tiledb_ctx_t* ctx,
777     const std::string& array_name,
778     tiledb_encryption_type_t encryption_type,
779     const char* key,
780     uint64_t key_len,
781     uint64_t timestamp,
782     const void* subarray,
783     tiledb_layout_t layout,
784     const QueryBuffers& buffers) {
785   std::string uri;
786   write_array(
787       ctx,
788       array_name,
789       encryption_type,
790       key,
791       key_len,
792       timestamp,
793       subarray,
794       layout,
795       buffers,
796       &uri);
797   (void)uri;
798 }
799 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,uint64_t timestamp,tiledb_layout_t layout,const QueryBuffers & buffers,std::string * uri)800 void write_array(
801     tiledb_ctx_t* ctx,
802     const std::string& array_name,
803     uint64_t timestamp,
804     tiledb_layout_t layout,
805     const QueryBuffers& buffers,
806     std::string* uri) {
807   write_array(ctx, array_name, timestamp, nullptr, layout, buffers, uri);
808 }
809 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_encryption_type_t encryption_type,const char * key,uint64_t key_len,uint64_t timestamp,tiledb_layout_t layout,const QueryBuffers & buffers,std::string * uri)810 void write_array(
811     tiledb_ctx_t* ctx,
812     const std::string& array_name,
813     tiledb_encryption_type_t encryption_type,
814     const char* key,
815     uint64_t key_len,
816     uint64_t timestamp,
817     tiledb_layout_t layout,
818     const QueryBuffers& buffers,
819     std::string* uri) {
820   write_array(
821       ctx,
822       array_name,
823       encryption_type,
824       key,
825       key_len,
826       timestamp,
827       nullptr,
828       layout,
829       buffers,
830       uri);
831 }
832 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,uint64_t timestamp,const void * subarray,tiledb_layout_t layout,const QueryBuffers & buffers,std::string * uri)833 void write_array(
834     tiledb_ctx_t* ctx,
835     const std::string& array_name,
836     uint64_t timestamp,
837     const void* subarray,
838     tiledb_layout_t layout,
839     const QueryBuffers& buffers,
840     std::string* uri) {
841   write_array(
842       ctx,
843       array_name,
844       TILEDB_NO_ENCRYPTION,
845       nullptr,
846       0,
847       timestamp,
848       subarray,
849       layout,
850       buffers,
851       uri);
852 }
853 
write_array(tiledb_ctx_t * ctx,const std::string & array_name,tiledb_encryption_type_t encryption_type,const char * key,uint64_t key_len,uint64_t timestamp,const void * subarray,tiledb_layout_t layout,const QueryBuffers & buffers,std::string * uri)854 void write_array(
855     tiledb_ctx_t* ctx,
856     const std::string& array_name,
857     tiledb_encryption_type_t encryption_type,
858     const char* key,
859     uint64_t key_len,
860     uint64_t timestamp,
861     const void* subarray,
862     tiledb_layout_t layout,
863     const QueryBuffers& buffers,
864     std::string* uri) {
865   // Set array configuration
866   tiledb_array_t* array;
867   int rc = tiledb_array_alloc(ctx, array_name.c_str(), &array);
868   CHECK(rc == TILEDB_OK);
869   tiledb_config_t* cfg;
870   tiledb_error_t* err = nullptr;
871   REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
872   REQUIRE(err == nullptr);
873 
874   rc = tiledb_array_set_open_timestamp_end(ctx, array, timestamp);
875   REQUIRE(rc == TILEDB_OK);
876 
877   // Open array
878   if (encryption_type != TILEDB_NO_ENCRYPTION) {
879     std::string encryption_type_string =
880         encryption_type_str((tiledb::sm::EncryptionType)encryption_type);
881     rc = tiledb_config_set(
882         cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
883     REQUIRE(rc == TILEDB_OK);
884     REQUIRE(err == nullptr);
885     rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
886     REQUIRE(rc == TILEDB_OK);
887     REQUIRE(err == nullptr);
888     rc = tiledb_array_set_config(ctx, array, cfg);
889     REQUIRE(rc == TILEDB_OK);
890     tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
891         key_len);
892   }
893   rc = tiledb_array_open(ctx, array, TILEDB_WRITE);
894   CHECK(rc == TILEDB_OK);
895 
896   // Create query
897   tiledb_query_t* query;
898   rc = tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query);
899   CHECK(rc == TILEDB_OK);
900   if (subarray != nullptr) {
901     rc = tiledb_query_set_subarray(ctx, query, subarray);
902     CHECK(rc == TILEDB_OK);
903   }
904   rc = tiledb_query_set_layout(ctx, query, layout);
905   CHECK(rc == TILEDB_OK);
906 
907   // Set buffers
908   for (const auto& b : buffers) {
909     if (b.second.var_ == nullptr) {  // Fixed-sized
910       rc = tiledb_query_set_data_buffer(
911           ctx,
912           query,
913           b.first.c_str(),
914           b.second.fixed_,
915           (uint64_t*)&(b.second.fixed_size_));
916       CHECK(rc == TILEDB_OK);
917     } else {  // Var-sized
918       rc = tiledb_query_set_data_buffer(
919           ctx,
920           query,
921           b.first.c_str(),
922           b.second.var_,
923           (uint64_t*)&(b.second.var_size_));
924       CHECK(rc == TILEDB_OK);
925       rc = tiledb_query_set_offsets_buffer(
926           ctx,
927           query,
928           b.first.c_str(),
929           (uint64_t*)b.second.fixed_,
930           (uint64_t*)&(b.second.fixed_size_));
931       CHECK(rc == TILEDB_OK);
932     }
933   }
934 
935   // Submit query
936   rc = tiledb_query_submit(ctx, query);
937   CHECK(rc == TILEDB_OK);
938 
939   // Finalize query
940   rc = tiledb_query_finalize(ctx, query);
941   CHECK(rc == TILEDB_OK);
942 
943   // Get fragment uri
944   const char* temp_uri;
945   rc = tiledb_query_get_fragment_uri(ctx, query, 0, &temp_uri);
946   REQUIRE(rc == TILEDB_OK);
947   *uri = std::string(temp_uri);
948 
949   // Close array
950   rc = tiledb_array_close(ctx, array);
951   CHECK(rc == TILEDB_OK);
952 
953   // Clean up
954   tiledb_array_free(&array);
955   tiledb_query_free(&query);
956   tiledb_config_free(&cfg);
957 }
958 
959 template <class T>
read_array(tiledb_ctx_t * ctx,tiledb_array_t * array,const SubarrayRanges<T> & ranges,tiledb_layout_t layout,const QueryBuffers & buffers)960 void read_array(
961     tiledb_ctx_t* ctx,
962     tiledb_array_t* array,
963     const SubarrayRanges<T>& ranges,
964     tiledb_layout_t layout,
965     const QueryBuffers& buffers) {
966   // Create query
967   tiledb_query_t* query;
968   int rc = tiledb_query_alloc(ctx, array, TILEDB_READ, &query);
969   CHECK(rc == TILEDB_OK);
970   rc = tiledb_query_set_layout(ctx, query, layout);
971   CHECK(rc == TILEDB_OK);
972 
973   auto dim_num = (unsigned)ranges.size();
974   for (unsigned i = 0; i < dim_num; ++i) {
975     auto dim_range_num = ranges[i].size() / 2;
976     for (size_t j = 0; j < dim_range_num; ++j) {
977       rc = tiledb_query_add_range(
978           ctx, query, i, &ranges[i][2 * j], &ranges[i][2 * j + 1], nullptr);
979       CHECK(rc == TILEDB_OK);
980     }
981   }
982 
983   // Set buffers
984   for (const auto& b : buffers) {
985     if (b.second.var_ == nullptr) {  // Fixed-sized
986       rc = tiledb_query_set_data_buffer(
987           ctx,
988           query,
989           b.first.c_str(),
990           b.second.fixed_,
991           (uint64_t*)&(b.second.fixed_size_));
992       CHECK(rc == TILEDB_OK);
993     } else {  // Var-sized
994       rc = tiledb_query_set_data_buffer(
995           ctx,
996           query,
997           b.first.c_str(),
998           b.second.var_,
999           (uint64_t*)&(b.second.var_size_));
1000       CHECK(rc == TILEDB_OK);
1001       rc = tiledb_query_set_offsets_buffer(
1002           ctx,
1003           query,
1004           b.first.c_str(),
1005           (uint64_t*)b.second.fixed_,
1006           (uint64_t*)&(b.second.fixed_size_));
1007       CHECK(rc == TILEDB_OK);
1008     }
1009   }
1010 
1011   // Submit query
1012   rc = tiledb_query_submit(ctx, query);
1013   CHECK(rc == TILEDB_OK);
1014 
1015   // Check status
1016   tiledb_query_status_t status;
1017   rc = tiledb_query_get_status(ctx, query, &status);
1018   CHECK(rc == TILEDB_OK);
1019   CHECK(status == TILEDB_COMPLETED);
1020 
1021   // Clean up
1022   tiledb_query_free(&query);
1023 }
1024 
num_fragments(const std::string & array_name)1025 int32_t num_fragments(const std::string& array_name) {
1026   Context ctx;
1027   VFS vfs(ctx);
1028 
1029   // Get all URIs in the array directory
1030   auto uris = vfs.ls(array_name);
1031 
1032   // Exclude '__meta' folder and any file with a suffix
1033   int ret = 0;
1034   for (const auto& uri : uris) {
1035     auto name = tiledb::sm::URI(uri).remove_trailing_slash().last_path_part();
1036     if (name != tiledb::sm::constants::array_metadata_folder_name &&
1037         name != tiledb::sm::constants::array_schema_folder_name &&
1038         name.find_first_of('.') == std::string::npos)
1039       ++ret;
1040   }
1041 
1042   return ret;
1043 }
1044 
1045 template void check_subarray<int8_t>(
1046     tiledb::sm::Subarray& subarray, const SubarrayRanges<int8_t>& ranges);
1047 template void check_subarray<uint8_t>(
1048     tiledb::sm::Subarray& subarray, const SubarrayRanges<uint8_t>& ranges);
1049 template void check_subarray<int16_t>(
1050     tiledb::sm::Subarray& subarray, const SubarrayRanges<int16_t>& ranges);
1051 template void check_subarray<uint16_t>(
1052     tiledb::sm::Subarray& subarray, const SubarrayRanges<uint16_t>& ranges);
1053 template void check_subarray<int32_t>(
1054     tiledb::sm::Subarray& subarray, const SubarrayRanges<int32_t>& ranges);
1055 template void check_subarray<uint32_t>(
1056     tiledb::sm::Subarray& subarray, const SubarrayRanges<uint32_t>& ranges);
1057 template void check_subarray<int64_t>(
1058     tiledb::sm::Subarray& subarray, const SubarrayRanges<int64_t>& ranges);
1059 template void check_subarray<uint64_t>(
1060     tiledb::sm::Subarray& subarray, const SubarrayRanges<uint64_t>& ranges);
1061 template void check_subarray<float>(
1062     tiledb::sm::Subarray& subarray, const SubarrayRanges<float>& ranges);
1063 template void check_subarray<double>(
1064     tiledb::sm::Subarray& subarray, const SubarrayRanges<double>& ranges);
1065 
1066 template void create_subarray<int8_t>(
1067     tiledb::sm::Array* array,
1068     const SubarrayRanges<int8_t>& ranges,
1069     tiledb::sm::Layout layout,
1070     tiledb::sm::Subarray* subarray,
1071     bool coalesce_ranges);
1072 template void create_subarray<uint8_t>(
1073     tiledb::sm::Array* array,
1074     const SubarrayRanges<uint8_t>& ranges,
1075     tiledb::sm::Layout layout,
1076     tiledb::sm::Subarray* subarray,
1077     bool coalesce_ranges);
1078 template void create_subarray<int16_t>(
1079     tiledb::sm::Array* array,
1080     const SubarrayRanges<int16_t>& ranges,
1081     tiledb::sm::Layout layout,
1082     tiledb::sm::Subarray* subarray,
1083     bool coalesce_ranges);
1084 template void create_subarray<uint16_t>(
1085     tiledb::sm::Array* array,
1086     const SubarrayRanges<uint16_t>& ranges,
1087     tiledb::sm::Layout layout,
1088     tiledb::sm::Subarray* subarray,
1089     bool coalesce_ranges);
1090 template void create_subarray<int32_t>(
1091     tiledb::sm::Array* array,
1092     const SubarrayRanges<int32_t>& ranges,
1093     tiledb::sm::Layout layout,
1094     tiledb::sm::Subarray* subarray,
1095     bool coalesce_ranges);
1096 template void create_subarray<uint32_t>(
1097     tiledb::sm::Array* array,
1098     const SubarrayRanges<uint32_t>& ranges,
1099     tiledb::sm::Layout layout,
1100     tiledb::sm::Subarray* subarray,
1101     bool coalesce_ranges);
1102 template void create_subarray<int64_t>(
1103     tiledb::sm::Array* array,
1104     const SubarrayRanges<int64_t>& ranges,
1105     tiledb::sm::Layout layout,
1106     tiledb::sm::Subarray* subarray,
1107     bool coalesce_ranges);
1108 template void create_subarray<uint64_t>(
1109     tiledb::sm::Array* array,
1110     const SubarrayRanges<uint64_t>& ranges,
1111     tiledb::sm::Layout layout,
1112     tiledb::sm::Subarray* subarray,
1113     bool coalesce_ranges);
1114 template void create_subarray<float>(
1115     tiledb::sm::Array* array,
1116     const SubarrayRanges<float>& ranges,
1117     tiledb::sm::Layout layout,
1118     tiledb::sm::Subarray* subarray,
1119     bool coalesce_ranges);
1120 template void create_subarray<double>(
1121     tiledb::sm::Array* array,
1122     const SubarrayRanges<double>& ranges,
1123     tiledb::sm::Layout layout,
1124     tiledb::sm::Subarray* subarray,
1125     bool coalesce_ranges);
1126 
1127 template void check_partitions<int8_t>(
1128     tiledb::sm::SubarrayPartitioner& partitioner,
1129     const std::vector<SubarrayRanges<int8_t>>& partitions,
1130     bool last_unsplittable);
1131 template void check_partitions<uint8_t>(
1132     tiledb::sm::SubarrayPartitioner& partitioner,
1133     const std::vector<SubarrayRanges<uint8_t>>& partitions,
1134     bool last_unsplittable);
1135 template void check_partitions<int16_t>(
1136     tiledb::sm::SubarrayPartitioner& partitioner,
1137     const std::vector<SubarrayRanges<int16_t>>& partitions,
1138     bool last_unsplittable);
1139 template void check_partitions<uint16_t>(
1140     tiledb::sm::SubarrayPartitioner& partitioner,
1141     const std::vector<SubarrayRanges<uint16_t>>& partitions,
1142     bool last_unsplittable);
1143 template void check_partitions<int32_t>(
1144     tiledb::sm::SubarrayPartitioner& partitioner,
1145     const std::vector<SubarrayRanges<int32_t>>& partitions,
1146     bool last_unsplittable);
1147 template void check_partitions<uint32_t>(
1148     tiledb::sm::SubarrayPartitioner& partitioner,
1149     const std::vector<SubarrayRanges<uint32_t>>& partitions,
1150     bool last_unsplittable);
1151 template void check_partitions<int64_t>(
1152     tiledb::sm::SubarrayPartitioner& partitioner,
1153     const std::vector<SubarrayRanges<int64_t>>& partitions,
1154     bool last_unsplittable);
1155 template void check_partitions<uint64_t>(
1156     tiledb::sm::SubarrayPartitioner& partitioner,
1157     const std::vector<SubarrayRanges<uint64_t>>& partitions,
1158     bool last_unsplittable);
1159 template void check_partitions<float>(
1160     tiledb::sm::SubarrayPartitioner& partitioner,
1161     const std::vector<SubarrayRanges<float>>& partitions,
1162     bool last_unsplittable);
1163 template void check_partitions<double>(
1164     tiledb::sm::SubarrayPartitioner& partitioner,
1165     const std::vector<SubarrayRanges<double>>& partitions,
1166     bool last_unsplittable);
1167 
1168 template void read_array<int8_t>(
1169     tiledb_ctx_t* ctx,
1170     tiledb_array_t* array,
1171     const SubarrayRanges<int8_t>& ranges,
1172     tiledb_layout_t layout,
1173     const QueryBuffers& buffers);
1174 template void read_array<uint8_t>(
1175     tiledb_ctx_t* ctx,
1176     tiledb_array_t* array,
1177     const SubarrayRanges<uint8_t>& ranges,
1178     tiledb_layout_t layout,
1179     const QueryBuffers& buffers);
1180 template void read_array<int16_t>(
1181     tiledb_ctx_t* ctx,
1182     tiledb_array_t* array,
1183     const SubarrayRanges<int16_t>& ranges,
1184     tiledb_layout_t layout,
1185     const QueryBuffers& buffers);
1186 template void read_array<uint16_t>(
1187     tiledb_ctx_t* ctx,
1188     tiledb_array_t* array,
1189     const SubarrayRanges<uint16_t>& ranges,
1190     tiledb_layout_t layout,
1191     const QueryBuffers& buffers);
1192 template void read_array<int32_t>(
1193     tiledb_ctx_t* ctx,
1194     tiledb_array_t* array,
1195     const SubarrayRanges<int32_t>& ranges,
1196     tiledb_layout_t layout,
1197     const QueryBuffers& buffers);
1198 template void read_array<uint32_t>(
1199     tiledb_ctx_t* ctx,
1200     tiledb_array_t* array,
1201     const SubarrayRanges<uint32_t>& ranges,
1202     tiledb_layout_t layout,
1203     const QueryBuffers& buffers);
1204 template void read_array<int64_t>(
1205     tiledb_ctx_t* ctx,
1206     tiledb_array_t* array,
1207     const SubarrayRanges<int64_t>& ranges,
1208     tiledb_layout_t layout,
1209     const QueryBuffers& buffers);
1210 template void read_array<uint64_t>(
1211     tiledb_ctx_t* ctx,
1212     tiledb_array_t* array,
1213     const SubarrayRanges<uint64_t>& ranges,
1214     tiledb_layout_t layout,
1215     const QueryBuffers& buffers);
1216 template void read_array<float>(
1217     tiledb_ctx_t* ctx,
1218     tiledb_array_t* array,
1219     const SubarrayRanges<float>& ranges,
1220     tiledb_layout_t layout,
1221     const QueryBuffers& buffers);
1222 template void read_array<double>(
1223     tiledb_ctx_t* ctx,
1224     tiledb_array_t* array,
1225     const SubarrayRanges<double>& ranges,
1226     tiledb_layout_t layout,
1227     const QueryBuffers& buffers);
1228 
1229 }  // End of namespace test
1230 
1231 }  // End of namespace tiledb
1232