1 /**
2 * @file unit-capi-array.cc
3 *
4 * @section LICENSE
5 *
6 * The MIT License
7 *
8 * @copyright Copyright (c) 2017-2021 TileDB Inc.
9 * @copyright Copyright (c) 2016 MIT and Intel Corporation
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @section DESCRIPTION
30 *
31 * Tests of C API for (dense or sparse) array operations.
32 */
33
34 #include "catch.hpp"
35 #include "tiledb/sm/c_api/tiledb.h"
36
37 #include <iostream>
38
39 #include "catch.hpp"
40 #include "test/src/helpers.h"
41 #include "test/src/vfs_helpers.h"
42 #ifdef _WIN32
43 #include <Windows.h>
44 #include "tiledb/sm/filesystem/win.h"
45 #else
46 #include "tiledb/sm/filesystem/posix.h"
47 #endif
48 #include "tiledb/sm/c_api/tiledb.h"
49 #include "tiledb/sm/enums/encryption_type.h"
50 #include "tiledb/sm/global_state/unit_test_config.h"
51 #include "tiledb/sm/misc/utils.h"
52
53 #include <chrono>
54 #include <climits>
55 #include <iostream>
56 #include <sstream>
57 #include <thread>
58
59 using namespace tiledb::test;
60
61 struct ArrayFx {
62 // TileDB context
63 tiledb_ctx_t* ctx_;
64 tiledb_vfs_t* vfs_;
65
66 // Vector of supported filesystems
67 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
68
69 // Encryption parameters
70 tiledb_encryption_type_t encryption_type_ = TILEDB_NO_ENCRYPTION;
71 const char* encryption_key_ = nullptr;
72
73 // Functions
74 ArrayFx();
75 ~ArrayFx();
76 void create_temp_dir(const std::string& path);
77 void remove_temp_dir(const std::string& path);
78 void create_sparse_vector(const std::string& path);
79 void create_sparse_array(const std::string& path);
80 void create_dense_vector(const std::string& path);
81 void create_dense_array(const std::string& path);
82 static std::string random_name(const std::string& prefix);
83 static int get_fragment_timestamps(const char* path, void* data);
84 };
85
86 static const std::string test_ca_path =
87 std::string(TILEDB_TEST_INPUTS_DIR) + "/test_certs";
88
89 static const std::string test_ca_file =
90 std::string(TILEDB_TEST_INPUTS_DIR) + "/test_certs/public.crt";
91
ArrayFx()92 ArrayFx::ArrayFx()
93 : fs_vec_(vfs_test_get_fs_vec()) {
94 // Initialize vfs test
95 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
96 }
97
~ArrayFx()98 ArrayFx::~ArrayFx() {
99 // Close vfs test
100 REQUIRE(vfs_test_close(fs_vec_, ctx_, vfs_).ok());
101 tiledb_vfs_free(&vfs_);
102 tiledb_ctx_free(&ctx_);
103 }
104
create_temp_dir(const std::string & path)105 void ArrayFx::create_temp_dir(const std::string& path) {
106 remove_temp_dir(path);
107 REQUIRE(tiledb_vfs_create_dir(ctx_, vfs_, path.c_str()) == TILEDB_OK);
108 }
109
remove_temp_dir(const std::string & path)110 void ArrayFx::remove_temp_dir(const std::string& path) {
111 int is_dir = 0;
112 REQUIRE(tiledb_vfs_is_dir(ctx_, vfs_, path.c_str(), &is_dir) == TILEDB_OK);
113 if (is_dir)
114 REQUIRE(tiledb_vfs_remove_dir(ctx_, vfs_, path.c_str()) == TILEDB_OK);
115 }
116
random_name(const std::string & prefix)117 std::string ArrayFx::random_name(const std::string& prefix) {
118 std::stringstream ss;
119 ss << prefix << "-" << std::this_thread::get_id() << "-"
120 << TILEDB_TIMESTAMP_NOW_MS;
121 return ss.str();
122 }
123
get_fragment_timestamps(const char * path,void * data)124 int ArrayFx::get_fragment_timestamps(const char* path, void* data) {
125 auto data_vec = (std::vector<uint64_t>*)data;
126 std::pair<uint64_t, uint64_t> timestamp_range;
127 if (tiledb::sm::utils::parse::ends_with(
128 path, tiledb::sm::constants::ok_file_suffix)) {
129 auto uri = tiledb::sm::URI(path);
130 if (tiledb::sm::utils::parse::get_timestamp_range(uri, ×tamp_range)
131 .ok())
132 data_vec->push_back(timestamp_range.first);
133 }
134
135 return 1;
136 }
137
create_sparse_vector(const std::string & path)138 void ArrayFx::create_sparse_vector(const std::string& path) {
139 int rc;
140 int64_t dim_domain[] = {-1, 2};
141 int64_t tile_extent = 2;
142
143 // Create domain
144 tiledb_domain_t* domain;
145 rc = tiledb_domain_alloc(ctx_, &domain);
146 REQUIRE(rc == TILEDB_OK);
147 tiledb_dimension_t* dim;
148 rc = tiledb_dimension_alloc(
149 ctx_, "d1", TILEDB_INT64, dim_domain, &tile_extent, &dim);
150 REQUIRE(rc == TILEDB_OK);
151 rc = tiledb_domain_add_dimension(ctx_, domain, dim);
152 REQUIRE(rc == TILEDB_OK);
153
154 // Create attribute
155 tiledb_attribute_t* attr;
156 rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &attr);
157 REQUIRE(rc == TILEDB_OK);
158
159 // Create array schema
160 tiledb_array_schema_t* array_schema;
161 rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema);
162 REQUIRE(rc == TILEDB_OK);
163 rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
164 REQUIRE(rc == TILEDB_OK);
165 rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
166 REQUIRE(rc == TILEDB_OK);
167 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
168 REQUIRE(rc == TILEDB_OK);
169 rc = tiledb_array_schema_add_attribute(ctx_, array_schema, attr);
170 REQUIRE(rc == TILEDB_OK);
171
172 rc = tiledb_array_schema_check(ctx_, array_schema);
173 REQUIRE(rc == TILEDB_OK);
174
175 // Create array
176 rc = tiledb_array_create(ctx_, path.c_str(), array_schema);
177 REQUIRE(rc == TILEDB_OK);
178 tiledb_attribute_free(&attr);
179 tiledb_dimension_free(&dim);
180 tiledb_domain_free(&domain);
181 tiledb_array_schema_free(&array_schema);
182 }
183
create_sparse_array(const std::string & path)184 void ArrayFx::create_sparse_array(const std::string& path) {
185 int rc;
186 int64_t dim_domain[] = {1, 10, 1, 10};
187 int64_t tile_extent = 2;
188
189 // Create domain
190 tiledb_domain_t* domain;
191 rc = tiledb_domain_alloc(ctx_, &domain);
192 REQUIRE(rc == TILEDB_OK);
193 tiledb_dimension_t* dim_1;
194 rc = tiledb_dimension_alloc(
195 ctx_, "d1", TILEDB_INT64, dim_domain, &tile_extent, &dim_1);
196 REQUIRE(rc == TILEDB_OK);
197 rc = tiledb_domain_add_dimension(ctx_, domain, dim_1);
198 REQUIRE(rc == TILEDB_OK);
199 tiledb_dimension_t* dim_2;
200 rc = tiledb_dimension_alloc(
201 ctx_, "d2", TILEDB_INT64, &dim_domain[2], &tile_extent, &dim_2);
202 REQUIRE(rc == TILEDB_OK);
203 rc = tiledb_domain_add_dimension(ctx_, domain, dim_2);
204 REQUIRE(rc == TILEDB_OK);
205
206 // Create attribute
207 tiledb_attribute_t* attr;
208 rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &attr);
209 REQUIRE(rc == TILEDB_OK);
210
211 // Create array schema
212 tiledb_array_schema_t* array_schema;
213 rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema);
214 REQUIRE(rc == TILEDB_OK);
215 rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
216 REQUIRE(rc == TILEDB_OK);
217 rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
218 REQUIRE(rc == TILEDB_OK);
219 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
220 REQUIRE(rc == TILEDB_OK);
221 rc = tiledb_array_schema_add_attribute(ctx_, array_schema, attr);
222 REQUIRE(rc == TILEDB_OK);
223
224 rc = tiledb_array_schema_check(ctx_, array_schema);
225 REQUIRE(rc == TILEDB_OK);
226
227 // Create array
228 rc = tiledb_array_create(ctx_, path.c_str(), array_schema);
229 REQUIRE(rc == TILEDB_OK);
230 tiledb_attribute_free(&attr);
231 tiledb_dimension_free(&dim_1);
232 tiledb_dimension_free(&dim_2);
233 tiledb_domain_free(&domain);
234 tiledb_array_schema_free(&array_schema);
235 }
236
create_dense_vector(const std::string & path)237 void ArrayFx::create_dense_vector(const std::string& path) {
238 int rc;
239 int64_t dim_domain[] = {1, 10};
240 int64_t tile_extent = 2;
241
242 // Create domain
243 tiledb_domain_t* domain;
244 rc = tiledb_domain_alloc(ctx_, &domain);
245 REQUIRE(rc == TILEDB_OK);
246 tiledb_dimension_t* dim;
247 rc = tiledb_dimension_alloc(
248 ctx_, "d1", TILEDB_INT64, dim_domain, &tile_extent, &dim);
249 REQUIRE(rc == TILEDB_OK);
250 rc = tiledb_domain_add_dimension(ctx_, domain, dim);
251 REQUIRE(rc == TILEDB_OK);
252
253 // Create attribute
254 tiledb_attribute_t* attr;
255 rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &attr);
256 REQUIRE(rc == TILEDB_OK);
257
258 // Create array schema
259 tiledb_array_schema_t* array_schema;
260 rc = tiledb_array_schema_alloc(ctx_, TILEDB_DENSE, &array_schema);
261 REQUIRE(rc == TILEDB_OK);
262 rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
263 REQUIRE(rc == TILEDB_OK);
264 rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
265 REQUIRE(rc == TILEDB_OK);
266 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
267 REQUIRE(rc == TILEDB_OK);
268 rc = tiledb_array_schema_add_attribute(ctx_, array_schema, attr);
269 REQUIRE(rc == TILEDB_OK);
270
271 rc = tiledb_array_schema_check(ctx_, array_schema);
272 REQUIRE(rc == TILEDB_OK);
273
274 // Create array
275 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
276 tiledb_ctx_free(&ctx_);
277 tiledb_vfs_free(&vfs_);
278 tiledb_config_t* cfg;
279 tiledb_error_t* err = nullptr;
280 rc = tiledb_config_alloc(&cfg, &err);
281 REQUIRE(rc == TILEDB_OK);
282 REQUIRE(err == nullptr);
283 std::string encryption_type_string =
284 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
285 rc = tiledb_config_set(
286 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
287 REQUIRE(err == nullptr);
288 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
289 REQUIRE(rc == TILEDB_OK);
290 REQUIRE(err == nullptr);
291 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.reset();
292 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_, cfg).ok());
293 tiledb_config_free(&cfg);
294 }
295 rc = tiledb_array_create(ctx_, path.c_str(), array_schema);
296 REQUIRE(rc == TILEDB_OK);
297 tiledb_attribute_free(&attr);
298 tiledb_dimension_free(&dim);
299 tiledb_domain_free(&domain);
300 tiledb_array_schema_free(&array_schema);
301 }
302
create_dense_array(const std::string & path)303 void ArrayFx::create_dense_array(const std::string& path) {
304 int rc;
305 int64_t dim_domain[] = {1, 10, 1, 10};
306 int64_t tile_extent = 2;
307
308 // Create domain
309 tiledb_domain_t* domain;
310 rc = tiledb_domain_alloc(ctx_, &domain);
311 REQUIRE(rc == TILEDB_OK);
312 tiledb_dimension_t* dim_1;
313 rc = tiledb_dimension_alloc(
314 ctx_, "d1", TILEDB_INT64, dim_domain, &tile_extent, &dim_1);
315 REQUIRE(rc == TILEDB_OK);
316 rc = tiledb_domain_add_dimension(ctx_, domain, dim_1);
317 REQUIRE(rc == TILEDB_OK);
318 tiledb_dimension_t* dim_2;
319 rc = tiledb_dimension_alloc(
320 ctx_, "d2", TILEDB_INT64, &dim_domain[2], &tile_extent, &dim_2);
321 REQUIRE(rc == TILEDB_OK);
322 rc = tiledb_domain_add_dimension(ctx_, domain, dim_2);
323 REQUIRE(rc == TILEDB_OK);
324
325 // Create attribute
326 tiledb_attribute_t* attr;
327 rc = tiledb_attribute_alloc(ctx_, "a", TILEDB_INT32, &attr);
328 REQUIRE(rc == TILEDB_OK);
329
330 // Create array schema
331 tiledb_array_schema_t* array_schema;
332 rc = tiledb_array_schema_alloc(ctx_, TILEDB_DENSE, &array_schema);
333 REQUIRE(rc == TILEDB_OK);
334 rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
335 REQUIRE(rc == TILEDB_OK);
336 rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
337 REQUIRE(rc == TILEDB_OK);
338 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
339 REQUIRE(rc == TILEDB_OK);
340 rc = tiledb_array_schema_add_attribute(ctx_, array_schema, attr);
341 REQUIRE(rc == TILEDB_OK);
342
343 rc = tiledb_array_schema_check(ctx_, array_schema);
344 REQUIRE(rc == TILEDB_OK);
345
346 // Create array
347 rc = tiledb_array_create(ctx_, path.c_str(), array_schema);
348 REQUIRE(rc == TILEDB_OK);
349 tiledb_attribute_free(&attr);
350 tiledb_dimension_free(&dim_1);
351 tiledb_dimension_free(&dim_2);
352 tiledb_domain_free(&domain);
353 tiledb_array_schema_free(&array_schema);
354 }
355
356 TEST_CASE_METHOD(
357 ArrayFx, "C API: Test getting array URI", "[capi][array][array-uri]") {
358 SupportedFsLocal local_fs;
359 std::string array_name =
360 local_fs.file_prefix() + local_fs.temp_dir() + "array_uri";
361 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
362
363 // Create array
364 tiledb_array_t* array;
365 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
366 REQUIRE(rc == TILEDB_OK);
367
368 // Get URI when array is not opened (should not error)
369 const char* uri = nullptr;
370 rc = tiledb_array_get_uri(ctx_, array, &uri);
371 CHECK(rc == TILEDB_OK);
372
373 // Get URI when array is opened
374 create_sparse_vector(array_name);
375 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
376 REQUIRE(rc == TILEDB_OK);
377 rc = tiledb_array_get_uri(ctx_, array, &uri);
378 CHECK(rc == TILEDB_OK);
379
380 #ifdef _WIN32
381 char path[MAX_PATH];
382 unsigned length = MAX_PATH;
383 rc = tiledb_uri_to_path(ctx_, uri, path, &length);
384 CHECK(rc == TILEDB_OK);
385 CHECK(!strcmp(path, array_name.c_str()));
386 #else
387 CHECK(!strcmp(uri, array_name.c_str()));
388 #endif
389
390 // Close array
391 rc = tiledb_array_close(ctx_, array);
392 CHECK(rc == TILEDB_OK);
393
394 // Clean up
395 tiledb_array_free(&array);
396
397 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
398 }
399
400 TEST_CASE_METHOD(
401 ArrayFx, "C API: Set null URI", "[capi][array][array-null-uri]") {
402 // Create context
403 tiledb_array_t* array;
404 int rc = tiledb_array_alloc(ctx_, nullptr, &array);
405 CHECK(rc == TILEDB_ERR);
406 }
407
408 TEST_CASE_METHOD(
409 ArrayFx, "C API: Set invalid URI", "[capi][array][array-invalid-uri]") {
410 std::string array_name = "this_is_not_a_valid_array_uri";
411 tiledb_array_t* array;
412 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
413 CHECK(rc == TILEDB_OK);
414 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
415 CHECK(rc == TILEDB_ERR);
416 int is_open;
417 rc = tiledb_array_is_open(ctx_, array, &is_open);
418 REQUIRE(rc == TILEDB_OK);
419 REQUIRE(is_open == 0);
420 tiledb_array_free(&array);
421 }
422
423 TEST_CASE_METHOD(
424 ArrayFx, "C API: Test array with encryption", "[capi][array][encryption]") {
425 // Create array schema
426 tiledb_array_schema_t* array_schema;
427 int rc = tiledb_array_schema_alloc(ctx_, TILEDB_SPARSE, &array_schema);
428 REQUIRE(rc == TILEDB_OK);
429
430 // Create dimensions
431 tiledb_dimension_t* d1;
432 const int64_t d1_domain[2] = {0, 99};
433 const int64_t tile_extent[1] = {10};
434 rc = tiledb_dimension_alloc(
435 ctx_, "", TILEDB_INT64, &d1_domain[0], &tile_extent[0], &d1);
436 REQUIRE(rc == TILEDB_OK);
437
438 // Set domain
439 tiledb_domain_t* domain;
440 rc = tiledb_domain_alloc(ctx_, &domain);
441 REQUIRE(rc == TILEDB_OK);
442 rc = tiledb_domain_add_dimension(ctx_, domain, d1);
443 REQUIRE(rc == TILEDB_OK);
444 rc = tiledb_array_schema_set_domain(ctx_, array_schema, domain);
445 REQUIRE(rc == TILEDB_OK);
446
447 // Set attribute
448 tiledb_attribute_t* attr1;
449 rc = tiledb_attribute_alloc(ctx_, "foo", TILEDB_INT32, &attr1);
450 REQUIRE(rc == TILEDB_OK);
451 rc = tiledb_attribute_set_cell_val_num(ctx_, attr1, TILEDB_VAR_NUM);
452 REQUIRE(rc == TILEDB_OK);
453 rc = tiledb_array_schema_add_attribute(ctx_, array_schema, attr1);
454 REQUIRE(rc == TILEDB_OK);
455
456 // Set schema members
457 rc = tiledb_array_schema_set_capacity(ctx_, array_schema, 500);
458 REQUIRE(rc == TILEDB_OK);
459 rc = tiledb_array_schema_set_cell_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
460 REQUIRE(rc == TILEDB_OK);
461 rc = tiledb_array_schema_set_tile_order(ctx_, array_schema, TILEDB_ROW_MAJOR);
462 REQUIRE(rc == TILEDB_OK);
463
464 // Instantiate local class
465 SupportedFsLocal local_fs;
466
467 // Check for invalid array schema
468 rc = tiledb_array_schema_check(ctx_, array_schema);
469 REQUIRE(rc == TILEDB_OK);
470
471 std::string array_name =
472 local_fs.file_prefix() + local_fs.temp_dir() + "encrypyted_array";
473 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
474
475 SECTION("- API calls with encrypted schema") {
476 const char key[] = "0123456789abcdeF0123456789abcdeF";
477 uint32_t key_len = (uint32_t)strlen(key);
478
479 // Check error with invalid key length
480 tiledb_config_t* cfg;
481 tiledb_error_t* err = nullptr;
482 rc = tiledb_config_alloc(&cfg, &err);
483 REQUIRE(rc == TILEDB_OK);
484 REQUIRE(err == nullptr);
485 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
486 REQUIRE(err == nullptr);
487 rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
488 REQUIRE(rc == TILEDB_OK);
489 REQUIRE(err == nullptr);
490 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(31);
491 tiledb_ctx_t* ctx_invalid_key_len_1;
492 tiledb_vfs_t* vfs_invalid_key_len_1;
493 REQUIRE(vfs_test_init(
494 fs_vec_, &ctx_invalid_key_len_1, &vfs_invalid_key_len_1, cfg)
495 .ok());
496 rc = tiledb_array_create(
497 ctx_invalid_key_len_1, array_name.c_str(), array_schema);
498 REQUIRE(rc == TILEDB_ERR);
499 tiledb_ctx_free(&ctx_invalid_key_len_1);
500 tiledb_vfs_free(&vfs_invalid_key_len_1);
501
502 rc = tiledb_config_set(
503 cfg, "sm.encryption_type", "TILEDB_NO_ENCRYPTION", &err);
504 REQUIRE(err == nullptr);
505 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
506 key_len);
507 tiledb_ctx_t* ctx_invalid_key_len_2;
508 tiledb_vfs_t* vfs_invalid_key_len_2;
509 REQUIRE(vfs_test_init(
510 fs_vec_, &ctx_invalid_key_len_2, &vfs_invalid_key_len_2, cfg)
511 .ok());
512 rc = tiledb_array_create(
513 ctx_invalid_key_len_2, array_name.c_str(), array_schema);
514 REQUIRE(rc == TILEDB_ERR);
515 tiledb_ctx_free(&ctx_invalid_key_len_2);
516 tiledb_vfs_free(&vfs_invalid_key_len_2);
517 // remove the empty array directory
518 remove_temp_dir(array_name);
519
520 // Create array with proper key
521 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
522 REQUIRE(err == nullptr);
523 tiledb_ctx_t* ctx_proper_key;
524 tiledb_vfs_t* vfs_proper_key;
525 REQUIRE(vfs_test_init(fs_vec_, &ctx_proper_key, &vfs_proper_key, cfg).ok());
526 rc = tiledb_array_create(ctx_proper_key, array_name.c_str(), array_schema);
527 REQUIRE(rc == TILEDB_OK);
528 tiledb_ctx_free(&ctx_proper_key);
529 tiledb_vfs_free(&vfs_proper_key);
530
531 // Clean up
532 tiledb_attribute_free(&attr1);
533 tiledb_dimension_free(&d1);
534 tiledb_domain_free(&domain);
535 tiledb_array_schema_free(&array_schema);
536
537 // Check getting encryption type
538 tiledb_encryption_type_t enc_type;
539 rc = tiledb_array_encryption_type(ctx_, array_name.c_str(), &enc_type);
540 REQUIRE(rc == TILEDB_OK);
541 REQUIRE(enc_type == TILEDB_AES_256_GCM);
542
543 // Open array
544 tiledb_array_t* array;
545 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
546 REQUIRE(rc == TILEDB_OK);
547 // Check error with no key
548 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
549 REQUIRE(rc == TILEDB_ERR);
550 int is_open;
551 rc = tiledb_array_is_open(ctx_, array, &is_open);
552 REQUIRE(rc == TILEDB_OK);
553 REQUIRE(is_open == 0);
554
555 // Check error with wrong algorithm
556 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
557 REQUIRE(err == nullptr);
558 rc = tiledb_config_set(cfg, "sm.encryption_type", "NO_ENCRYPTION", &err);
559 REQUIRE(rc == TILEDB_OK);
560 REQUIRE(err == nullptr);
561 rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
562 REQUIRE(rc == TILEDB_OK);
563 REQUIRE(err == nullptr);
564 rc = tiledb_array_set_config(ctx_, array, cfg);
565 REQUIRE(rc == TILEDB_OK);
566 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
567 REQUIRE(rc == TILEDB_ERR);
568 rc = tiledb_array_is_open(ctx_, array, &is_open);
569 REQUIRE(rc == TILEDB_OK);
570 REQUIRE(is_open == 0);
571
572 // Check error with bad key
573 char bad_key[32];
574 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
575 REQUIRE(rc == TILEDB_OK);
576 REQUIRE(err == nullptr);
577 rc = tiledb_config_set(cfg, "sm.encryption_key", bad_key, &err);
578 REQUIRE(rc == TILEDB_OK);
579 REQUIRE(err == nullptr);
580 rc = tiledb_array_set_config(ctx_, array, cfg);
581 REQUIRE(rc == TILEDB_OK);
582 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
583 REQUIRE(rc == TILEDB_ERR);
584 rc = tiledb_array_is_open(ctx_, array, &is_open);
585 REQUIRE(rc == TILEDB_OK);
586 REQUIRE(is_open == 0);
587
588 // Check error with bad key length
589 REQUIRE(
590 tiledb_config_set(cfg, "sm.encryption_key", key, &err) == TILEDB_OK);
591 REQUIRE(err == nullptr);
592 rc = tiledb_array_set_config(ctx_, array, cfg);
593 REQUIRE(rc == TILEDB_OK);
594 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
595 key_len - 1);
596 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
597 REQUIRE(rc == TILEDB_ERR);
598 rc = tiledb_array_is_open(ctx_, array, &is_open);
599 REQUIRE(rc == TILEDB_OK);
600 REQUIRE(is_open == 0);
601
602 // Use correct key
603 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
604 key_len);
605 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
606 REQUIRE(rc == TILEDB_OK);
607 rc = tiledb_array_is_open(ctx_, array, &is_open);
608 REQUIRE(rc == TILEDB_OK);
609 REQUIRE(is_open == 1);
610 tiledb_array_schema_t* read_schema;
611 rc = tiledb_array_get_schema(ctx_, array, &read_schema);
612 REQUIRE(rc == TILEDB_OK);
613 rc = tiledb_config_set(cfg, "sm.encryption_key", bad_key, &err);
614 REQUIRE(rc == TILEDB_OK);
615 REQUIRE(err == nullptr);
616 rc = tiledb_array_set_config(ctx_, array, cfg);
617 REQUIRE(rc == TILEDB_OK);
618
619 // Opening an already open array without a key should fail
620 tiledb_array_t* array2;
621 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array2);
622 REQUIRE(rc == TILEDB_OK);
623 rc = tiledb_array_open(ctx_, array2, TILEDB_READ);
624 REQUIRE(rc == TILEDB_ERR);
625
626 // Opening an array with a bad key should fail
627 rc = tiledb_array_set_config(ctx_, array2, cfg);
628 REQUIRE(rc == TILEDB_OK);
629 rc = tiledb_array_open(ctx_, array2, TILEDB_READ);
630 REQUIRE(rc == TILEDB_ERR);
631
632 // Check reopening works
633 rc = tiledb_array_reopen(ctx_, array);
634 REQUIRE(rc == TILEDB_OK);
635
636 // Close arrays
637 rc = tiledb_array_close(ctx_, array2);
638 REQUIRE(rc == TILEDB_OK);
639 rc = tiledb_array_close(ctx_, array);
640 REQUIRE(rc == TILEDB_OK);
641
642 // Check loading schema requires key
643 tiledb_array_schema_free(&read_schema);
644 rc = tiledb_array_schema_load(ctx_, array_name.c_str(), &read_schema);
645 REQUIRE(rc == TILEDB_ERR);
646 // Check with bad key
647 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
648 REQUIRE(err == nullptr);
649 rc = tiledb_config_set(cfg, "sm.encryption_key", bad_key, &err);
650 REQUIRE(rc == TILEDB_OK);
651 REQUIRE(err == nullptr);
652 tiledb_ctx_t* ctx_bad_key;
653 tiledb_vfs_t* vfs_bad_key;
654 REQUIRE(vfs_test_init(fs_vec_, &ctx_bad_key, &vfs_bad_key, cfg).ok());
655 rc =
656 tiledb_array_schema_load(ctx_bad_key, array_name.c_str(), &read_schema);
657 REQUIRE(rc == TILEDB_ERR);
658 tiledb_ctx_free(&ctx_bad_key);
659 tiledb_vfs_free(&vfs_bad_key);
660 // Check with correct key
661 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
662 REQUIRE(err == nullptr);
663 rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
664 REQUIRE(rc == TILEDB_OK);
665 REQUIRE(err == nullptr);
666 tiledb_ctx_t* ctx_correct_key;
667 tiledb_vfs_t* vfs_correct_key;
668 REQUIRE(
669 vfs_test_init(fs_vec_, &ctx_correct_key, &vfs_correct_key, cfg).ok());
670 rc = tiledb_array_schema_load(
671 ctx_correct_key, array_name.c_str(), &read_schema);
672 REQUIRE(rc == TILEDB_OK);
673 tiledb_ctx_free(&ctx_correct_key);
674 tiledb_vfs_free(&vfs_correct_key);
675
676 // Check opening after closing still requires a key.
677 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
678 REQUIRE(rc == TILEDB_ERR);
679 rc = tiledb_array_is_open(ctx_, array, &is_open);
680 REQUIRE(rc == TILEDB_OK);
681 REQUIRE(is_open == 0);
682 rc = tiledb_config_set(cfg, "sm.encryption_key", bad_key, &err);
683 REQUIRE(rc == TILEDB_OK);
684 REQUIRE(err == nullptr);
685 rc = tiledb_array_set_config(ctx_, array, cfg);
686 REQUIRE(rc == TILEDB_OK);
687 rc = tiledb_array_set_config(ctx_, array, cfg);
688 REQUIRE(rc == TILEDB_OK);
689 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
690 REQUIRE(rc == TILEDB_ERR);
691 rc = tiledb_array_is_open(ctx_, array, &is_open);
692 REQUIRE(rc == TILEDB_OK);
693 REQUIRE(is_open == 0);
694 rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
695 REQUIRE(rc == TILEDB_OK);
696 REQUIRE(err == nullptr);
697 rc = tiledb_array_set_config(ctx_, array, cfg);
698 REQUIRE(rc == TILEDB_OK);
699 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
700 REQUIRE(rc == TILEDB_OK);
701 rc = tiledb_array_is_open(ctx_, array, &is_open);
702 REQUIRE(rc == TILEDB_OK);
703 REQUIRE(is_open == 1);
704 rc = tiledb_array_close(ctx_, array);
705 REQUIRE(rc == TILEDB_OK);
706
707 // Clean up
708 tiledb_array_schema_free(&read_schema);
709 tiledb_array_free(&array);
710 tiledb_array_free(&array2);
711 tiledb_config_free(&cfg);
712 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
713 }
714
715 SECTION("- API calls with unencrypted schema") {
716 // Check for invalid array schema
717 rc = tiledb_array_schema_check(ctx_, array_schema);
718 REQUIRE(rc == TILEDB_OK);
719
720 // Check create ok with null key
721 tiledb_config_t* cfg;
722 tiledb_error_t* err = nullptr;
723 rc = tiledb_config_alloc(&cfg, &err);
724 REQUIRE(rc == TILEDB_OK);
725 REQUIRE(err == nullptr);
726 tiledb_ctx_t* ctx_null_key;
727 tiledb_vfs_t* vfs_null_key;
728 rc = tiledb_config_set(cfg, "sm.encryption_key", "", &err);
729 REQUIRE(rc == TILEDB_OK);
730 REQUIRE(err == nullptr);
731 REQUIRE(vfs_test_init(fs_vec_, &ctx_null_key, &vfs_null_key, cfg).ok());
732 rc = tiledb_array_create(ctx_, array_name.c_str(), array_schema);
733 REQUIRE(rc == TILEDB_OK);
734 tiledb_ctx_free(&ctx_null_key);
735 tiledb_vfs_free(&vfs_null_key);
736
737 // Clean up
738 tiledb_attribute_free(&attr1);
739 tiledb_dimension_free(&d1);
740 tiledb_domain_free(&domain);
741 tiledb_array_schema_free(&array_schema);
742
743 // Check getting encryption type
744 tiledb_encryption_type_t enc_type;
745 rc = tiledb_array_encryption_type(ctx_, array_name.c_str(), &enc_type);
746 REQUIRE(rc == TILEDB_OK);
747 REQUIRE(enc_type == TILEDB_NO_ENCRYPTION);
748
749 // Open array
750 tiledb_array_t* array;
751 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
752 REQUIRE(rc == TILEDB_OK);
753 // Check error with key
754 const char key[] = "0123456789abcdeF0123456789abcdeF";
755 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
756 REQUIRE(rc == TILEDB_OK);
757 REQUIRE(err == nullptr);
758 rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
759 REQUIRE(rc == TILEDB_OK);
760 REQUIRE(err == nullptr);
761 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.reset();
762 rc = tiledb_array_set_config(ctx_, array, cfg);
763 REQUIRE(rc == TILEDB_OK);
764 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
765 REQUIRE(rc == TILEDB_ERR);
766 int is_open;
767 rc = tiledb_array_is_open(ctx_, array, &is_open);
768 REQUIRE(rc == TILEDB_OK);
769 REQUIRE(is_open == 0);
770
771 // Check ok with null key
772 rc = tiledb_config_set(cfg, "sm.encryption_type", "NO_ENCRYPTION", &err);
773 REQUIRE(rc == TILEDB_OK);
774 REQUIRE(err == nullptr);
775 rc = tiledb_config_set(cfg, "sm.encryption_key", "0", &err);
776 REQUIRE(rc == TILEDB_OK);
777 REQUIRE(err == nullptr);
778 rc = tiledb_array_set_config(ctx_, array, cfg);
779 REQUIRE(rc == TILEDB_OK);
780 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(0);
781 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
782 REQUIRE(rc == TILEDB_OK);
783 rc = tiledb_array_is_open(ctx_, array, &is_open);
784 REQUIRE(rc == TILEDB_OK);
785 REQUIRE(is_open == 1);
786 tiledb_array_schema_t* read_schema;
787 rc = tiledb_array_get_schema(ctx_, array, &read_schema);
788 REQUIRE(rc == TILEDB_OK);
789
790 rc = tiledb_array_close(ctx_, array);
791 REQUIRE(rc == TILEDB_OK);
792
793 // Check loading schema with key is error
794 tiledb_array_schema_free(&read_schema);
795 rc = tiledb_config_set(cfg, "sm.encryption_type", "AES_256_GCM", &err);
796 REQUIRE(err == nullptr);
797 rc = tiledb_config_set(cfg, "sm.encryption_key", key, &err);
798 REQUIRE(rc == TILEDB_OK);
799 REQUIRE(err == nullptr);
800 tiledb_ctx_t* ctx_schema;
801 tiledb_vfs_t* vfs_schema;
802 REQUIRE(vfs_test_init(fs_vec_, &ctx_schema, &vfs_schema, cfg).ok());
803 rc = tiledb_array_schema_load(ctx_schema, array_name.c_str(), &read_schema);
804 REQUIRE(rc == TILEDB_ERR);
805 tiledb_ctx_free(&ctx_schema);
806 tiledb_vfs_free(&vfs_schema);
807
808 // Check ok with nullptr
809 rc = tiledb_config_set(cfg, "sm.encryption_key", "", &err);
810 REQUIRE(rc == TILEDB_OK);
811 REQUIRE(err == nullptr);
812 tiledb_ctx_t* ctx_nullptr;
813 tiledb_vfs_t* vfs_nullptr;
814 REQUIRE(vfs_test_init(fs_vec_, &ctx_nullptr, &vfs_nullptr, cfg).ok());
815 rc = tiledb_array_schema_load(ctx_, array_name.c_str(), &read_schema);
816 REQUIRE(rc == TILEDB_OK);
817 tiledb_ctx_free(&ctx_nullptr);
818 tiledb_vfs_free(&vfs_nullptr);
819
820 // Clean up
821 tiledb_array_schema_free(&read_schema);
822 tiledb_array_free(&array);
823 tiledb_config_free(&cfg);
824 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
825 }
826 }
827
828 TEST_CASE_METHOD(
829 ArrayFx,
830 "C API: Test opening array at timestamp, reads",
831 "[capi][array][open-at][reads]") {
832 // TODO: refactor for each supported FS.
833 std::string temp_dir = fs_vec_[0]->temp_dir();
834
835 std::string array_name = temp_dir + "array-open-at-reads";
836 SECTION("- without encryption") {
837 encryption_type_ = TILEDB_NO_ENCRYPTION;
838 encryption_key_ = nullptr;
839 }
840
841 SECTION("- with encryption") {
842 encryption_type_ = TILEDB_AES_256_GCM;
843 encryption_key_ = "0123456789abcdeF0123456789abcdeF";
844 }
845
846 create_temp_dir(temp_dir);
847
848 create_dense_vector(array_name);
849
850 // ---- FIRST WRITE ----
851 // Prepare cell buffers
852 int buffer_a1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
853 uint64_t buffer_a1_size = sizeof(buffer_a1);
854
855 // Open array
856 tiledb_array_t* array;
857 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
858 CHECK(rc == TILEDB_OK);
859 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
860 tiledb_config_t* cfg;
861 tiledb_error_t* err = nullptr;
862 rc = tiledb_config_alloc(&cfg, &err);
863 CHECK(rc == TILEDB_OK);
864 REQUIRE(err == nullptr);
865 std::string encryption_type_string =
866 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
867 rc = tiledb_config_set(
868 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
869 CHECK(rc == TILEDB_OK);
870 REQUIRE(err == nullptr);
871 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
872 CHECK(rc == TILEDB_OK);
873 REQUIRE(err == nullptr);
874 rc = tiledb_array_set_config(ctx_, array, cfg);
875 CHECK(rc == TILEDB_OK);
876 tiledb_config_free(&cfg);
877 uint32_t key_len = (uint32_t)strlen(encryption_key_);
878 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
879 key_len);
880 }
881 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
882 CHECK(rc == TILEDB_OK);
883
884 // Submit query
885 tiledb_query_t* query;
886 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
887 CHECK(rc == TILEDB_OK);
888 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
889 CHECK(rc == TILEDB_OK);
890 rc = tiledb_query_set_data_buffer(
891 ctx_, query, "a", buffer_a1, &buffer_a1_size);
892 CHECK(rc == TILEDB_OK);
893 rc = tiledb_query_submit(ctx_, query);
894 CHECK(rc == TILEDB_OK);
895 rc = tiledb_query_finalize(ctx_, query);
896 CHECK(rc == TILEDB_OK);
897
898 // Close array and clean up
899 rc = tiledb_array_close(ctx_, array);
900 CHECK(rc == TILEDB_OK);
901 tiledb_array_free(&array);
902 tiledb_query_free(&query);
903
904 // ---- UPDATE ----
905 int buffer_upd[] = {50, 60, 70};
906 uint64_t buffer_upd_size = sizeof(buffer_upd);
907 int64_t subarray[] = {5, 7};
908
909 // Open array
910 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
911 CHECK(rc == TILEDB_OK);
912 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
913 tiledb_config_t* cfg;
914 tiledb_error_t* err = nullptr;
915 rc = tiledb_config_alloc(&cfg, &err);
916 CHECK(rc == TILEDB_OK);
917 REQUIRE(err == nullptr);
918 std::string encryption_type_string =
919 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
920 rc = tiledb_config_set(
921 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
922 CHECK(rc == TILEDB_OK);
923 REQUIRE(err == nullptr);
924 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
925 CHECK(rc == TILEDB_OK);
926 REQUIRE(err == nullptr);
927 rc = tiledb_array_set_config(ctx_, array, cfg);
928 CHECK(rc == TILEDB_OK);
929 tiledb_config_free(&cfg);
930 }
931 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
932 CHECK(rc == TILEDB_OK);
933
934 // Submit query
935 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
936 CHECK(rc == TILEDB_OK);
937 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
938 CHECK(rc == TILEDB_OK);
939 rc = tiledb_query_set_subarray(ctx_, query, subarray);
940 CHECK(rc == TILEDB_OK);
941 rc = tiledb_query_set_data_buffer(
942 ctx_, query, "a", buffer_upd, &buffer_upd_size);
943 CHECK(rc == TILEDB_OK);
944 rc = tiledb_query_submit(ctx_, query);
945 CHECK(rc == TILEDB_OK);
946
947 // Close array and clean up
948 rc = tiledb_array_close(ctx_, array);
949 CHECK(rc == TILEDB_OK);
950 tiledb_array_free(&array);
951 tiledb_query_free(&query);
952
953 std::vector<uint64_t> fragment_timestamps;
954 rc = tiledb_vfs_ls(
955 ctx_,
956 vfs_,
957 array_name.c_str(),
958 &get_fragment_timestamps,
959 &fragment_timestamps);
960 CHECK(rc == TILEDB_OK);
961
962 // ---- NORMAL READ ----
963 int buffer_read[10];
964 uint64_t buffer_read_size = sizeof(buffer_read);
965
966 // Open array
967 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
968 CHECK(rc == TILEDB_OK);
969 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
970 tiledb_config_t* cfg;
971 tiledb_error_t* err = nullptr;
972 rc = tiledb_config_alloc(&cfg, &err);
973 CHECK(rc == TILEDB_OK);
974 REQUIRE(err == nullptr);
975 std::string encryption_type_string =
976 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
977 rc = tiledb_config_set(
978 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
979 CHECK(rc == TILEDB_OK);
980 REQUIRE(err == nullptr);
981 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
982 CHECK(rc == TILEDB_OK);
983 REQUIRE(err == nullptr);
984 rc = tiledb_array_set_config(ctx_, array, cfg);
985 CHECK(rc == TILEDB_OK);
986 tiledb_config_free(&cfg);
987 }
988 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
989 CHECK(rc == TILEDB_OK);
990
991 // Submit query
992 int64_t subarray_read[] = {1, 10};
993 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
994 CHECK(rc == TILEDB_OK);
995 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
996 CHECK(rc == TILEDB_OK);
997 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
998 CHECK(rc == TILEDB_OK);
999 rc = tiledb_query_set_data_buffer(
1000 ctx_, query, "a", buffer_read, &buffer_read_size);
1001 CHECK(rc == TILEDB_OK);
1002 rc = tiledb_query_submit(ctx_, query);
1003 CHECK(rc == TILEDB_OK);
1004
1005 // Close array and clean up
1006 rc = tiledb_array_close(ctx_, array);
1007 CHECK(rc == TILEDB_OK);
1008 tiledb_array_free(&array);
1009 tiledb_query_free(&query);
1010
1011 // Check correctness
1012 int32_t buffer_read_c[] = {1, 2, 3, 4, 50, 60, 70, 8, 9, 10};
1013 CHECK(!std::memcmp(buffer_read, buffer_read_c, sizeof(buffer_read_c)));
1014 CHECK(buffer_read_size == sizeof(buffer_read_c));
1015
1016 // ---- READ AT ZERO TIMESTAMP ----
1017
1018 tiledb_config_t* cfg;
1019 tiledb_error_t* err = nullptr;
1020 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1021 CHECK(rc == TILEDB_OK);
1022 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1023 REQUIRE(err == nullptr);
1024 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 0);
1025 REQUIRE(rc == TILEDB_OK);
1026
1027 // Open array
1028 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1029 std::string encryption_type_string =
1030 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1031 rc = tiledb_config_set(
1032 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1033 CHECK(rc == TILEDB_OK);
1034 REQUIRE(err == nullptr);
1035 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1036 CHECK(rc == TILEDB_OK);
1037 REQUIRE(err == nullptr);
1038 rc = tiledb_array_set_config(ctx_, array, cfg);
1039 CHECK(rc == TILEDB_OK);
1040 }
1041 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1042 CHECK(rc == TILEDB_OK);
1043
1044 // Check timestamp
1045 uint64_t timestamp_get;
1046 rc = tiledb_array_get_open_timestamp_end(ctx_, array, ×tamp_get);
1047 CHECK(rc == TILEDB_OK);
1048 CHECK(timestamp_get == 0);
1049
1050 // Submit query
1051 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1052 CHECK(rc == TILEDB_OK);
1053 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1054 CHECK(rc == TILEDB_OK);
1055 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1056 CHECK(rc == TILEDB_OK);
1057 rc = tiledb_query_set_data_buffer(
1058 ctx_, query, "a", buffer_read, &buffer_read_size);
1059 CHECK(rc == TILEDB_OK);
1060 rc = tiledb_query_submit(ctx_, query);
1061 CHECK(rc == TILEDB_OK);
1062
1063 // Close array and clean up
1064 rc = tiledb_array_close(ctx_, array);
1065 CHECK(rc == TILEDB_OK);
1066 tiledb_array_free(&array);
1067 tiledb_query_free(&query);
1068 tiledb_config_free(&cfg);
1069
1070 // Check correctness
1071 // Empty array still returns fill values
1072 CHECK(buffer_read_size == 10 * sizeof(int32_t));
1073
1074 // ---- READ AT TIMESTAMP BEFORE UPDATE ----
1075 buffer_read_size = sizeof(buffer_read);
1076
1077 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1078 CHECK(rc == TILEDB_OK);
1079 rc = tiledb_array_set_open_timestamp_end(ctx_, array, fragment_timestamps[0]);
1080 REQUIRE(rc == TILEDB_OK);
1081
1082 // Open array
1083 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1084 REQUIRE(err == nullptr);
1085 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1086 std::string encryption_type_string =
1087 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1088 rc = tiledb_config_set(
1089 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1090 CHECK(rc == TILEDB_OK);
1091 REQUIRE(err == nullptr);
1092 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1093 CHECK(rc == TILEDB_OK);
1094 REQUIRE(err == nullptr);
1095 rc = tiledb_array_set_config(ctx_, array, cfg);
1096 CHECK(rc == TILEDB_OK);
1097 }
1098 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1099 CHECK(rc == TILEDB_OK);
1100
1101 // Submit query
1102 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1103 CHECK(rc == TILEDB_OK);
1104 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1105 CHECK(rc == TILEDB_OK);
1106 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1107 CHECK(rc == TILEDB_OK);
1108 rc = tiledb_query_set_data_buffer(
1109 ctx_, query, "a", buffer_read, &buffer_read_size);
1110 CHECK(rc == TILEDB_OK);
1111 rc = tiledb_query_submit(ctx_, query);
1112 CHECK(rc == TILEDB_OK);
1113
1114 // Close array and clean up
1115 rc = tiledb_array_close(ctx_, array);
1116 CHECK(rc == TILEDB_OK);
1117 tiledb_array_free(&array);
1118 tiledb_query_free(&query);
1119 tiledb_config_free(&cfg);
1120
1121 // Check correctness
1122 int buffer_read_at_c[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1123 CHECK(!std::memcmp(buffer_read, buffer_read_at_c, sizeof(buffer_read_at_c)));
1124 CHECK(buffer_read_size == sizeof(buffer_read_at_c));
1125
1126 // ---- READ AT LATER TIMESTAMP ----
1127 // Open array
1128 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1129 CHECK(rc == TILEDB_OK);
1130
1131 rc = tiledb_array_set_open_timestamp_end(ctx_, array, fragment_timestamps[1]);
1132 REQUIRE(rc == TILEDB_OK);
1133
1134 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1135 REQUIRE(err == nullptr);
1136 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1137 std::string encryption_type_string =
1138 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1139 rc = tiledb_config_set(
1140 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1141 CHECK(rc == TILEDB_OK);
1142 REQUIRE(err == nullptr);
1143 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1144 CHECK(rc == TILEDB_OK);
1145 REQUIRE(err == nullptr);
1146 rc = tiledb_array_set_config(ctx_, array, cfg);
1147 CHECK(rc == TILEDB_OK);
1148 }
1149
1150 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1151 CHECK(rc == TILEDB_OK);
1152
1153 // Check timestamp
1154 rc = tiledb_array_get_open_timestamp_end(ctx_, array, ×tamp_get);
1155 CHECK(rc == TILEDB_OK);
1156 CHECK(timestamp_get == fragment_timestamps[1]);
1157
1158 // Submit query
1159 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1160 CHECK(rc == TILEDB_OK);
1161 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1162 CHECK(rc == TILEDB_OK);
1163 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1164 CHECK(rc == TILEDB_OK);
1165 rc = tiledb_query_set_data_buffer(
1166 ctx_, query, "a", buffer_read, &buffer_read_size);
1167 CHECK(rc == TILEDB_OK);
1168 rc = tiledb_query_submit(ctx_, query);
1169 CHECK(rc == TILEDB_OK);
1170
1171 // Clean up but don't close the array yet (we will reopen it).
1172 tiledb_query_free(&query);
1173 tiledb_config_free(&cfg);
1174
1175 // Check correctness
1176 CHECK(!std::memcmp(buffer_read, buffer_read_c, sizeof(buffer_read_c)));
1177 CHECK(buffer_read_size == sizeof(buffer_read_c));
1178
1179 // ---- REOPEN AT FIRST TIMESTAMP ----
1180 buffer_read_size = sizeof(buffer_read);
1181
1182 rc = tiledb_array_set_open_timestamp_end(
1183 ctx_, array, fragment_timestamps[1] - 1);
1184 REQUIRE(rc == TILEDB_OK);
1185
1186 rc = tiledb_array_reopen(ctx_, array);
1187 CHECK(rc == TILEDB_OK);
1188
1189 // Submit query
1190 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1191 CHECK(rc == TILEDB_OK);
1192 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1193 CHECK(rc == TILEDB_OK);
1194 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1195 CHECK(rc == TILEDB_OK);
1196 rc = tiledb_query_set_data_buffer(
1197 ctx_, query, "a", buffer_read, &buffer_read_size);
1198 CHECK(rc == TILEDB_OK);
1199 rc = tiledb_query_submit(ctx_, query);
1200 CHECK(rc == TILEDB_OK);
1201
1202 // Clean up but don't close the array yet (we will reopen it).
1203 tiledb_query_free(&query);
1204
1205 // Check correctness
1206 int buffer_read_reopen_c[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1207 CHECK(!std::memcmp(
1208 buffer_read, buffer_read_reopen_c, sizeof(buffer_read_reopen_c)));
1209 CHECK(buffer_read_size == sizeof(buffer_read_reopen_c));
1210
1211 // ---- REOPEN STARTING AT FIRST TIMESTAMP ----
1212 buffer_read_size = sizeof(buffer_read);
1213
1214 // Reopen array
1215 rc = tiledb_array_set_open_timestamp_start(
1216 ctx_, array, fragment_timestamps[0] + 1);
1217 REQUIRE(rc == TILEDB_OK);
1218 rc = tiledb_array_set_open_timestamp_end(ctx_, array, UINT64_MAX);
1219 REQUIRE(rc == TILEDB_OK);
1220 rc = tiledb_array_reopen(ctx_, array);
1221 CHECK(rc == TILEDB_OK);
1222
1223 // Submit query
1224 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1225 CHECK(rc == TILEDB_OK);
1226 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1227 CHECK(rc == TILEDB_OK);
1228 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1229 CHECK(rc == TILEDB_OK);
1230 rc = tiledb_query_set_data_buffer(
1231 ctx_, query, "a", buffer_read, &buffer_read_size);
1232 CHECK(rc == TILEDB_OK);
1233 rc = tiledb_query_submit(ctx_, query);
1234 CHECK(rc == TILEDB_OK);
1235
1236 // Close array and clean up
1237 rc = tiledb_array_close(ctx_, array);
1238 CHECK(rc == TILEDB_OK);
1239 tiledb_query_free(&query);
1240 tiledb_array_free(&array);
1241
1242 // Check correctness
1243 int buffer_read_reopen_start_c[] = {INT_MIN,
1244 INT_MIN,
1245 INT_MIN,
1246 INT_MIN,
1247 50,
1248 60,
1249 70,
1250 INT_MIN,
1251 INT_MIN,
1252 INT_MIN};
1253 CHECK(!std::memcmp(
1254 buffer_read,
1255 buffer_read_reopen_start_c,
1256 sizeof(buffer_read_reopen_start_c)));
1257 CHECK(buffer_read_size == sizeof(buffer_read_reopen_start_c));
1258
1259 // ---- OPEN STARTING AT FIRST TIMESTAMP ----
1260 buffer_read_size = sizeof(buffer_read);
1261
1262 // Open array
1263 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1264 CHECK(rc == TILEDB_OK);
1265 rc = tiledb_array_set_open_timestamp_start(
1266 ctx_, array, fragment_timestamps[1]);
1267 REQUIRE(rc == TILEDB_OK);
1268 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1269 REQUIRE(err == nullptr);
1270 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1271 std::string encryption_type_string =
1272 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1273 rc = tiledb_config_set(
1274 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1275 CHECK(rc == TILEDB_OK);
1276 REQUIRE(err == nullptr);
1277 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1278 CHECK(rc == TILEDB_OK);
1279 REQUIRE(err == nullptr);
1280 rc = tiledb_array_set_config(ctx_, array, cfg);
1281 CHECK(rc == TILEDB_OK);
1282 }
1283 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1284 CHECK(rc == TILEDB_OK);
1285
1286 // Submit query
1287 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1288 CHECK(rc == TILEDB_OK);
1289 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1290 CHECK(rc == TILEDB_OK);
1291 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1292 CHECK(rc == TILEDB_OK);
1293 rc = tiledb_query_set_data_buffer(
1294 ctx_, query, "a", buffer_read, &buffer_read_size);
1295 CHECK(rc == TILEDB_OK);
1296 rc = tiledb_query_submit(ctx_, query);
1297 CHECK(rc == TILEDB_OK);
1298
1299 // Close array and clean up
1300 rc = tiledb_array_close(ctx_, array);
1301 CHECK(rc == TILEDB_OK);
1302 tiledb_query_free(&query);
1303 tiledb_array_free(&array);
1304 tiledb_config_free(&cfg);
1305
1306 // Check correctness
1307 // Check correctness
1308 int buffer_read_open_start_c[] = {INT_MIN,
1309 INT_MIN,
1310 INT_MIN,
1311 INT_MIN,
1312 50,
1313 60,
1314 70,
1315 INT_MIN,
1316 INT_MIN,
1317 INT_MIN};
1318 CHECK(!std::memcmp(
1319 buffer_read, buffer_read_open_start_c, sizeof(buffer_read_open_start_c)));
1320 CHECK(buffer_read_size == sizeof(buffer_read_open_start_c));
1321
1322 // ---- OPEN STARTING AT PAST LAST TIMESTAMP ----
1323 buffer_read_size = sizeof(buffer_read);
1324
1325 // Open array
1326 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1327 CHECK(rc == TILEDB_OK);
1328 rc = tiledb_array_set_open_timestamp_start(
1329 ctx_, array, fragment_timestamps[1] + 1);
1330 REQUIRE(rc == TILEDB_OK);
1331 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1332 REQUIRE(err == nullptr);
1333 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1334 std::string encryption_type_string =
1335 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1336 rc = tiledb_config_set(
1337 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1338 CHECK(rc == TILEDB_OK);
1339 REQUIRE(err == nullptr);
1340 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1341 CHECK(rc == TILEDB_OK);
1342 REQUIRE(err == nullptr);
1343 rc = tiledb_array_set_config(ctx_, array, cfg);
1344 CHECK(rc == TILEDB_OK);
1345 }
1346 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1347 CHECK(rc == TILEDB_OK);
1348
1349 // Submit query
1350 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1351 CHECK(rc == TILEDB_OK);
1352 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1353 CHECK(rc == TILEDB_OK);
1354 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1355 CHECK(rc == TILEDB_OK);
1356 rc = tiledb_query_set_data_buffer(
1357 ctx_, query, "a", buffer_read, &buffer_read_size);
1358 CHECK(rc == TILEDB_OK);
1359 rc = tiledb_query_submit(ctx_, query);
1360 CHECK(rc == TILEDB_OK);
1361
1362 // Close array and clean up
1363 rc = tiledb_array_close(ctx_, array);
1364 CHECK(rc == TILEDB_OK);
1365 tiledb_query_free(&query);
1366 tiledb_array_free(&array);
1367 tiledb_config_free(&cfg);
1368
1369 // Check correctness
1370 int buffer_read_open_start_now_c[] = {INT_MIN,
1371 INT_MIN,
1372 INT_MIN,
1373 INT_MIN,
1374 INT_MIN,
1375 INT_MIN,
1376 INT_MIN,
1377 INT_MIN,
1378 INT_MIN,
1379 INT_MIN};
1380 CHECK(!std::memcmp(
1381 buffer_read,
1382 buffer_read_open_start_now_c,
1383 sizeof(buffer_read_open_start_now_c)));
1384 CHECK(buffer_read_size == sizeof(buffer_read_open_start_now_c));
1385
1386 remove_temp_dir(temp_dir);
1387 }
1388
1389 TEST_CASE_METHOD(
1390 ArrayFx,
1391 "C API: Test opening array at timestamp, writes",
1392 "[capi][array][open-at][writes]") {
1393 // TODO: refactor for each supported FS.
1394 std::string temp_dir = fs_vec_[0]->temp_dir();
1395
1396 std::string array_name = temp_dir + "array-open-at-writes";
1397 SECTION("- without encryption") {
1398 encryption_type_ = TILEDB_NO_ENCRYPTION;
1399 encryption_key_ = nullptr;
1400 }
1401
1402 SECTION("- with encryption") {
1403 encryption_type_ = TILEDB_AES_256_GCM;
1404 encryption_key_ = "0123456789abcdeF0123456789abcdeF";
1405 }
1406
1407 create_temp_dir(temp_dir);
1408
1409 create_dense_vector(array_name);
1410
1411 // ---- WRITE ----
1412 // Prepare cell buffers
1413 int buffer_a1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1414 uint64_t buffer_a1_size = sizeof(buffer_a1);
1415
1416 // Some timestamp, it could be anything
1417 uint64_t timestamp = 1000;
1418
1419 tiledb_array_t* array;
1420 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1421 CHECK(rc == TILEDB_OK);
1422 tiledb_config_t* cfg = nullptr;
1423 tiledb_error_t* err = nullptr;
1424 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1425 REQUIRE(err == nullptr);
1426
1427 rc = tiledb_array_set_open_timestamp_end(ctx_, array, timestamp);
1428 REQUIRE(rc == TILEDB_OK);
1429
1430 // Open array
1431 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1432 std::string encryption_type_string =
1433 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1434 rc = tiledb_config_set(
1435 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1436 CHECK(rc == TILEDB_OK);
1437 REQUIRE(err == nullptr);
1438 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1439 CHECK(rc == TILEDB_OK);
1440 REQUIRE(err == nullptr);
1441 rc = tiledb_array_set_config(ctx_, array, cfg);
1442 CHECK(rc == TILEDB_OK);
1443 }
1444 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1445 CHECK(rc == TILEDB_OK);
1446
1447 // Submit query
1448 tiledb_query_t* query;
1449 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1450 CHECK(rc == TILEDB_OK);
1451 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
1452 CHECK(rc == TILEDB_OK);
1453 rc = tiledb_query_set_data_buffer(
1454 ctx_, query, "a", buffer_a1, &buffer_a1_size);
1455 CHECK(rc == TILEDB_OK);
1456 rc = tiledb_query_submit(ctx_, query);
1457 CHECK(rc == TILEDB_OK);
1458 rc = tiledb_query_finalize(ctx_, query);
1459 CHECK(rc == TILEDB_OK);
1460
1461 // Get written timestamp
1462 uint64_t timestamp_get;
1463 rc = tiledb_array_get_open_timestamp_end(ctx_, array, ×tamp_get);
1464 CHECK(rc == TILEDB_OK);
1465
1466 uint64_t t1, t2;
1467 rc = tiledb_query_get_fragment_timestamp_range(ctx_, query, 0, &t1, &t2);
1468 CHECK(rc == TILEDB_OK);
1469 CHECK(timestamp_get == t1);
1470 CHECK(timestamp_get == t2);
1471
1472 // Close array and clean up
1473 rc = tiledb_array_close(ctx_, array);
1474 CHECK(rc == TILEDB_OK);
1475 tiledb_array_free(&array);
1476 tiledb_query_free(&query);
1477 tiledb_config_free(&cfg);
1478
1479 // ---- READ AT ZERO TIMESTAMP ----
1480
1481 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1482 CHECK(rc == TILEDB_OK);
1483 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 0);
1484 REQUIRE(rc == TILEDB_OK);
1485
1486 // Open array
1487 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1488 REQUIRE(err == nullptr);
1489 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1490 std::string encryption_type_string =
1491 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1492 rc = tiledb_config_set(
1493 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1494 CHECK(rc == TILEDB_OK);
1495 REQUIRE(err == nullptr);
1496 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1497 CHECK(rc == TILEDB_OK);
1498 REQUIRE(err == nullptr);
1499 rc = tiledb_array_set_config(ctx_, array, cfg);
1500 CHECK(rc == TILEDB_OK);
1501 }
1502 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1503 CHECK(rc == TILEDB_OK);
1504
1505 // Check timestamp
1506 rc = tiledb_array_get_open_timestamp_end(ctx_, array, ×tamp_get);
1507 CHECK(rc == TILEDB_OK);
1508 CHECK(timestamp_get == 0);
1509
1510 // Submit query
1511 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1512 CHECK(rc == TILEDB_OK);
1513 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1514 CHECK(rc == TILEDB_OK);
1515 int64_t subarray_read[] = {1, 10};
1516 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1517 CHECK(rc == TILEDB_OK);
1518 int buffer_read[10];
1519 uint64_t buffer_read_size = sizeof(buffer_read);
1520 rc = tiledb_query_set_data_buffer(
1521 ctx_, query, "a", buffer_read, &buffer_read_size);
1522 CHECK(rc == TILEDB_OK);
1523 rc = tiledb_query_submit(ctx_, query);
1524 CHECK(rc == TILEDB_OK);
1525
1526 // Close array and clean up
1527 rc = tiledb_array_close(ctx_, array);
1528 CHECK(rc == TILEDB_OK);
1529 tiledb_array_free(&array);
1530 tiledb_query_free(&query);
1531 tiledb_config_free(&cfg);
1532
1533 // Check correctness
1534 // Empty array still returns fill values
1535 CHECK(buffer_read_size == 10 * sizeof(int32_t));
1536
1537 // ---- READ AT THE WRITTEN TIMESTAMP ----
1538 buffer_read_size = sizeof(buffer_read);
1539
1540 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1541 CHECK(rc == TILEDB_OK);
1542 rc = tiledb_array_set_open_timestamp_end(ctx_, array, timestamp);
1543 REQUIRE(rc == TILEDB_OK);
1544
1545 // Open array
1546 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1547 REQUIRE(err == nullptr);
1548 if (encryption_type_ != TILEDB_NO_ENCRYPTION) {
1549 std::string encryption_type_string =
1550 encryption_type_str((tiledb::sm::EncryptionType)encryption_type_);
1551 rc = tiledb_config_set(
1552 cfg, "sm.encryption_type", encryption_type_string.c_str(), &err);
1553 CHECK(rc == TILEDB_OK);
1554 REQUIRE(err == nullptr);
1555 rc = tiledb_config_set(cfg, "sm.encryption_key", encryption_key_, &err);
1556 CHECK(rc == TILEDB_OK);
1557 REQUIRE(err == nullptr);
1558 rc = tiledb_array_set_config(ctx_, array, cfg);
1559 CHECK(rc == TILEDB_OK);
1560 }
1561 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1562 CHECK(rc == TILEDB_OK);
1563
1564 // Submit query
1565 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1566 CHECK(rc == TILEDB_OK);
1567 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1568 CHECK(rc == TILEDB_OK);
1569 rc = tiledb_query_set_subarray(ctx_, query, subarray_read);
1570 CHECK(rc == TILEDB_OK);
1571 rc = tiledb_query_set_data_buffer(
1572 ctx_, query, "a", buffer_read, &buffer_read_size);
1573 CHECK(rc == TILEDB_OK);
1574 rc = tiledb_query_submit(ctx_, query);
1575 CHECK(rc == TILEDB_OK);
1576
1577 // Close array and clean up
1578 rc = tiledb_array_close(ctx_, array);
1579 CHECK(rc == TILEDB_OK);
1580 tiledb_array_free(&array);
1581 tiledb_query_free(&query);
1582 tiledb_config_free(&cfg);
1583
1584 // Check correctness
1585 int buffer_read_at_c[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1586 CHECK(!std::memcmp(buffer_read, buffer_read_at_c, sizeof(buffer_read_at_c)));
1587 CHECK(buffer_read_size == sizeof(buffer_read_at_c));
1588
1589 remove_temp_dir(temp_dir);
1590 }
1591
1592 TEST_CASE_METHOD(
1593 ArrayFx,
1594 "C API: Check writing coordinates out of bounds",
1595 "[capi][array][array-write-coords-oob]") {
1596 SupportedFsLocal local_fs;
1597 std::string temp_dir = local_fs.file_prefix() + local_fs.temp_dir();
1598 std::string array_name = temp_dir + "array-write-coords-oob";
1599 create_temp_dir(temp_dir);
1600
1601 int dimension = 0;
1602 int64_t buffer_coords_dim1[3];
1603 int64_t buffer_coords_dim2[3];
1604 int buffer_a1[3];
1605 uint64_t buffer_a1_size, buffer_coords_size;
1606 int rc;
1607 bool check_coords_oob = true;
1608
1609 // Create TileDB context
1610 tiledb_config_t* cfg = nullptr;
1611 tiledb_error_t* err = nullptr;
1612 tiledb_ctx_t* ctx = nullptr;
1613
1614 SECTION("- Check out-of-bounds coordinates") {
1615 check_coords_oob = true;
1616 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1617 REQUIRE(err == nullptr);
1618 rc = tiledb_config_set(cfg, "sm.check_coord_oob", "true", &err);
1619 REQUIRE(rc == TILEDB_OK);
1620 REQUIRE(err == nullptr);
1621
1622 SECTION("** 1D") {
1623 dimension = 1;
1624 create_sparse_vector(array_name);
1625
1626 // Prepare cell buffers
1627 buffer_coords_dim1[0] = 1;
1628 buffer_coords_dim1[1] = 2;
1629 buffer_coords_dim1[2] = 30;
1630 buffer_a1[0] = 1;
1631 buffer_a1[1] = 2;
1632 buffer_a1[2] = 3;
1633 buffer_coords_size = 3 * sizeof(int64_t);
1634 buffer_a1_size = 3 * sizeof(int);
1635 }
1636
1637 SECTION("** 2D") {
1638 dimension = 2;
1639 create_sparse_array(array_name);
1640
1641 // Prepare cell buffers
1642 buffer_coords_dim1[0] = 1;
1643 buffer_coords_dim1[1] = 2;
1644 buffer_coords_dim1[2] = 3;
1645 buffer_coords_dim2[0] = 1;
1646 buffer_coords_dim2[1] = 30;
1647 buffer_coords_dim2[2] = 3;
1648 buffer_a1[0] = 1;
1649 buffer_a1[1] = 2;
1650 buffer_a1[2] = 3;
1651 buffer_coords_size = 3 * sizeof(int64_t);
1652 buffer_a1_size = 3 * sizeof(int);
1653 }
1654 }
1655
1656 SECTION("- Do not check out-of-bounds coordinates") {
1657 check_coords_oob = false;
1658 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1659 REQUIRE(err == nullptr);
1660 rc = tiledb_config_set(cfg, "sm.check_coord_oob", "false", &err);
1661 REQUIRE(rc == TILEDB_OK);
1662 REQUIRE(err == nullptr);
1663
1664 SECTION("** 1D") {
1665 dimension = 1;
1666 create_sparse_vector(array_name);
1667
1668 // Prepare cell buffers
1669 buffer_coords_dim1[0] = 1;
1670 buffer_coords_dim1[1] = 2;
1671 buffer_coords_dim1[2] = 30;
1672 buffer_a1[0] = 1;
1673 buffer_a1[1] = 2;
1674 buffer_a1[2] = 3;
1675 buffer_coords_size = 3 * sizeof(int64_t);
1676 buffer_a1_size = 3 * sizeof(int);
1677 }
1678
1679 SECTION("** 2D") {
1680 dimension = 2;
1681 create_sparse_array(array_name);
1682
1683 // Prepare cell buffers
1684 buffer_coords_dim1[0] = 1;
1685 buffer_coords_dim1[1] = 2;
1686 buffer_coords_dim1[2] = 3;
1687 buffer_coords_dim2[0] = 1;
1688 buffer_coords_dim2[1] = 30;
1689 buffer_coords_dim2[2] = 3;
1690 buffer_a1[0] = 1;
1691 buffer_a1[1] = 2;
1692 buffer_a1[2] = 3;
1693 buffer_coords_size = 3 * sizeof(int64_t);
1694 buffer_a1_size = 3 * sizeof(int);
1695 }
1696 }
1697
1698 REQUIRE(tiledb_ctx_alloc(cfg, &ctx) == TILEDB_OK);
1699 REQUIRE(err == nullptr);
1700 tiledb_config_free(&cfg);
1701
1702 // Open array
1703 tiledb_array_t* array;
1704 rc = tiledb_array_alloc(ctx, array_name.c_str(), &array);
1705 CHECK(rc == TILEDB_OK);
1706 rc = tiledb_array_open(ctx, array, TILEDB_WRITE);
1707 CHECK(rc == TILEDB_OK);
1708
1709 // Submit query
1710 tiledb_query_t* query;
1711 rc = tiledb_query_alloc(ctx, array, TILEDB_WRITE, &query);
1712 CHECK(rc == TILEDB_OK);
1713 rc = tiledb_query_set_layout(ctx, query, TILEDB_GLOBAL_ORDER);
1714 CHECK(rc == TILEDB_OK);
1715 rc =
1716 tiledb_query_set_data_buffer(ctx, query, "a", buffer_a1, &buffer_a1_size);
1717 CHECK(rc == TILEDB_OK);
1718 rc = tiledb_query_set_data_buffer(
1719 ctx, query, "d1", buffer_coords_dim1, &buffer_coords_size);
1720 CHECK(rc == TILEDB_OK);
1721 if (dimension == 2) {
1722 rc = tiledb_query_set_data_buffer(
1723 ctx, query, "d2", buffer_coords_dim2, &buffer_coords_size);
1724 CHECK(rc == TILEDB_OK);
1725 }
1726 rc = tiledb_query_submit(ctx, query);
1727 if (check_coords_oob)
1728 CHECK(rc == TILEDB_ERR);
1729 else
1730 CHECK(rc == TILEDB_OK);
1731 rc = tiledb_query_finalize(ctx, query);
1732 CHECK(rc == TILEDB_OK);
1733
1734 // Close array and clean up
1735 rc = tiledb_array_close(ctx, array);
1736 CHECK(rc == TILEDB_OK);
1737 tiledb_array_free(&array);
1738 tiledb_query_free(&query);
1739 tiledb_ctx_free(&ctx);
1740
1741 remove_temp_dir(temp_dir);
1742 }
1743
1744 TEST_CASE_METHOD(
1745 ArrayFx, "C API: Test empty array", "[capi][array][array-empty]") {
1746 SupportedFsLocal local_fs;
1747 std::string array_name =
1748 local_fs.file_prefix() + local_fs.temp_dir() + "array_empty";
1749 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1750
1751 create_sparse_vector(array_name);
1752
1753 // Open array
1754 tiledb_array_t* array;
1755 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1756 REQUIRE(rc == TILEDB_OK);
1757 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1758 REQUIRE(rc == TILEDB_OK);
1759
1760 // Buffers
1761 int buff_a[10];
1762 uint64_t buff_a_size = sizeof(buff_a);
1763
1764 // Submit query
1765 tiledb_query_t* query;
1766 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1767 CHECK(rc == TILEDB_OK);
1768 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
1769 CHECK(rc == TILEDB_OK);
1770 rc = tiledb_query_set_data_buffer(ctx_, query, "a", buff_a, &buff_a_size);
1771 CHECK(rc == TILEDB_OK);
1772 rc = tiledb_query_submit(ctx_, query);
1773 CHECK(rc == TILEDB_OK);
1774
1775 // Check status
1776 tiledb_query_status_t status;
1777 rc = tiledb_query_get_status(ctx_, query, &status);
1778 CHECK(rc == TILEDB_OK);
1779 CHECK(status == TILEDB_COMPLETED);
1780
1781 // Close array
1782 rc = tiledb_array_close(ctx_, array);
1783 CHECK(rc == TILEDB_OK);
1784
1785 // No results
1786 CHECK(buff_a_size == 0);
1787
1788 // Clean up
1789 tiledb_array_free(&array);
1790 tiledb_query_free(&query);
1791
1792 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1793 }
1794
1795 TEST_CASE_METHOD(
1796 ArrayFx,
1797 "C API: Test array with no filelocks",
1798 "[capi][array][array-no-filelocks]") {
1799 // TODO: refactor for each supported FS.
1800 std::string temp_dir = fs_vec_[0]->temp_dir();
1801
1802 std::string array_name = temp_dir + "array-no-filelocks";
1803
1804 // Create new TileDB context with file lock config disabled, rest the same.
1805 tiledb_ctx_free(&ctx_);
1806 tiledb_vfs_free(&vfs_);
1807
1808 tiledb_config_t* cfg = nullptr;
1809 tiledb_error_t* err = nullptr;
1810 REQUIRE(tiledb_config_alloc(&cfg, &err) == TILEDB_OK);
1811 REQUIRE(err == nullptr);
1812 REQUIRE(
1813 tiledb_config_set(cfg, "vfs.file.enable_filelocks", "false", &err) ==
1814 TILEDB_OK);
1815 REQUIRE(err == nullptr);
1816
1817 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_, cfg).ok());
1818
1819 tiledb_config_free(&cfg);
1820
1821 create_temp_dir(temp_dir);
1822
1823 create_dense_vector(array_name);
1824
1825 // Prepare cell buffers
1826 int buffer_a1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1827 uint64_t buffer_a1_size = sizeof(buffer_a1);
1828
1829 // Open array
1830 int64_t subarray[] = {1, 10};
1831 tiledb_array_t* array;
1832 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1833 CHECK(rc == TILEDB_OK);
1834 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1835 CHECK(rc == TILEDB_OK);
1836
1837 // Submit query
1838 tiledb_query_t* query;
1839 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1840 CHECK(rc == TILEDB_OK);
1841 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
1842 CHECK(rc == TILEDB_OK);
1843 rc = tiledb_query_set_subarray(ctx_, query, subarray);
1844 CHECK(rc == TILEDB_OK);
1845 rc = tiledb_query_set_data_buffer(
1846 ctx_, query, "a", buffer_a1, &buffer_a1_size);
1847 CHECK(rc == TILEDB_OK);
1848 rc = tiledb_query_submit(ctx_, query);
1849 CHECK(rc == TILEDB_OK);
1850 rc = tiledb_query_finalize(ctx_, query);
1851 CHECK(rc == TILEDB_OK);
1852
1853 // Close array and clean up
1854 rc = tiledb_array_close(ctx_, array);
1855 CHECK(rc == TILEDB_OK);
1856 tiledb_array_free(&array);
1857 tiledb_query_free(&query);
1858
1859 int buffer_read[10];
1860 uint64_t buffer_read_size = sizeof(buffer_read);
1861
1862 // Open array
1863 rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1864 CHECK(rc == TILEDB_OK);
1865 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1866 CHECK(rc == TILEDB_OK);
1867
1868 // Submit query
1869 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
1870 CHECK(rc == TILEDB_OK);
1871 rc = tiledb_query_set_layout(ctx_, query, TILEDB_ROW_MAJOR);
1872 CHECK(rc == TILEDB_OK);
1873 rc = tiledb_query_set_subarray(ctx_, query, subarray);
1874 CHECK(rc == TILEDB_OK);
1875 rc = tiledb_query_set_data_buffer(
1876 ctx_, query, "a", buffer_read, &buffer_read_size);
1877 CHECK(rc == TILEDB_OK);
1878 rc = tiledb_query_submit(ctx_, query);
1879 CHECK(rc == TILEDB_OK);
1880
1881 // Close array and clean up
1882 rc = tiledb_array_close(ctx_, array);
1883 CHECK(rc == TILEDB_OK);
1884 tiledb_array_free(&array);
1885 tiledb_query_free(&query);
1886
1887 // Check correctness
1888 int buffer_read_c[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1889 CHECK(!std::memcmp(buffer_read, buffer_read_c, sizeof(buffer_read_c)));
1890 CHECK(buffer_read_size == sizeof(buffer_read_c));
1891
1892 remove_temp_dir(temp_dir);
1893 }
1894
1895 TEST_CASE_METHOD(
1896 ArrayFx,
1897 "C API: Test query errors, getting subarray info from write queries in "
1898 "sparse arrays",
1899 "[capi][query][error][sparse]") {
1900 SupportedFsLocal local_fs;
1901 std::string array_name =
1902 local_fs.file_prefix() + local_fs.temp_dir() + "query_error_sparse";
1903 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1904
1905 create_sparse_vector(array_name);
1906
1907 // Open array
1908 tiledb_array_t* array;
1909 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1910 REQUIRE(rc == TILEDB_OK);
1911 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1912 REQUIRE(rc == TILEDB_OK);
1913
1914 // Prepare query
1915 tiledb_query_t* query;
1916 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1917 CHECK(rc == TILEDB_OK);
1918 uint64_t range_num;
1919 rc = tiledb_query_get_range_num(ctx_, query, 0, &range_num);
1920 CHECK(rc == TILEDB_ERR);
1921 const void *start, *end, *stride;
1922 rc = tiledb_query_get_range(ctx_, query, 0, 0, &start, &end, &stride);
1923 CHECK(rc == TILEDB_ERR);
1924 int64_t s = 10;
1925 int64_t e = 20;
1926 rc = tiledb_query_add_range(ctx_, query, 0, &s, &e, nullptr);
1927 CHECK(rc == TILEDB_ERR);
1928 int64_t subarray[] = {-1, 2};
1929 rc = tiledb_query_set_subarray(ctx_, query, subarray);
1930 CHECK(rc == TILEDB_ERR);
1931
1932 // Close array
1933 rc = tiledb_array_close(ctx_, array);
1934 CHECK(rc == TILEDB_OK);
1935
1936 // Clean up
1937 tiledb_array_free(&array);
1938 tiledb_query_free(&query);
1939
1940 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1941 }
1942
1943 TEST_CASE_METHOD(
1944 ArrayFx,
1945 "C API: Test query errors, dense writes",
1946 "[capi][query][error][dense]") {
1947 SupportedFsLocal local_fs;
1948 std::string array_name =
1949 local_fs.file_prefix() + local_fs.temp_dir() + "query_error_dense";
1950 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
1951
1952 create_dense_array(array_name);
1953
1954 // Open array
1955 tiledb_array_t* array;
1956 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
1957 REQUIRE(rc == TILEDB_OK);
1958 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1959 REQUIRE(rc == TILEDB_OK);
1960
1961 int32_t a[] = {1, 2, 3, 4};
1962 uint64_t a_size = sizeof(a);
1963
1964 // Prepare query
1965 tiledb_query_t* query;
1966 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
1967 CHECK(rc == TILEDB_OK);
1968 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
1969 CHECK(rc == TILEDB_OK);
1970 uint64_t range_num;
1971 rc = tiledb_query_get_range_num(ctx_, query, 0, &range_num);
1972 CHECK(rc == TILEDB_OK);
1973 CHECK(range_num == 1); // The default
1974 const void *start, *end, *stride;
1975 rc = tiledb_query_get_range(ctx_, query, 0, 0, &start, &end, &stride);
1976 CHECK(rc == TILEDB_OK);
1977 CHECK(*(const uint64_t*)start == 1);
1978 CHECK(*(const uint64_t*)end == 10);
1979 int64_t s = 1;
1980 int64_t e = 2;
1981 rc = tiledb_query_add_range(ctx_, query, 0, &s, &e, nullptr);
1982 CHECK(rc == TILEDB_OK);
1983
1984 int64_t subarray[] = {2, 3, 4, 5};
1985 rc = tiledb_query_set_subarray(ctx_, query, subarray);
1986 CHECK(rc == TILEDB_OK);
1987 rc = tiledb_query_add_range(ctx_, query, 0, &s, &e, nullptr);
1988 CHECK(rc == TILEDB_ERR);
1989
1990 rc = tiledb_query_get_range_num(ctx_, query, 0, &range_num);
1991 CHECK(rc == TILEDB_OK);
1992 CHECK(range_num == 1);
1993 rc = tiledb_query_get_range(ctx_, query, 0, 0, &start, &end, &stride);
1994 CHECK(rc == TILEDB_OK);
1995 CHECK(*(const uint64_t*)start == 2);
1996 CHECK(*(const uint64_t*)end == 3);
1997 rc = tiledb_query_get_range(ctx_, query, 1, 0, &start, &end, &stride);
1998 CHECK(rc == TILEDB_OK);
1999 CHECK(*(const uint64_t*)start == 4);
2000 CHECK(*(const uint64_t*)end == 5);
2001
2002 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
2003 CHECK(rc == TILEDB_OK);
2004 rc = tiledb_query_submit(ctx_, query);
2005 CHECK(rc == TILEDB_ERR);
2006
2007 // Close array
2008 rc = tiledb_array_close(ctx_, array);
2009 CHECK(rc == TILEDB_OK);
2010
2011 // Clean up
2012 tiledb_array_free(&array);
2013 tiledb_query_free(&query);
2014
2015 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2016 }
2017
2018 TEST_CASE_METHOD(
2019 ArrayFx,
2020 "C API: Test query errors, dense unordered writes",
2021 "[capi][query][error][dense]") {
2022 SupportedFsLocal local_fs;
2023 std::string array_name =
2024 local_fs.file_prefix() + local_fs.temp_dir() + "query_error_dense";
2025 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2026
2027 create_dense_array(array_name);
2028
2029 // Open array
2030 tiledb_array_t* array;
2031 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
2032 REQUIRE(rc == TILEDB_OK);
2033 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
2034 REQUIRE(rc == TILEDB_OK);
2035
2036 // Prepare query
2037 tiledb_query_t* query;
2038 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
2039 CHECK(rc == TILEDB_OK);
2040
2041 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
2042 CHECK(rc == TILEDB_ERR);
2043
2044 // Close array
2045 rc = tiledb_array_close(ctx_, array);
2046 CHECK(rc == TILEDB_OK);
2047
2048 // Clean up
2049 tiledb_array_free(&array);
2050 tiledb_query_free(&query);
2051
2052 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2053 }
2054
2055 TEST_CASE_METHOD(
2056 ArrayFx,
2057 "C API: Test query errors, dense reads in global order",
2058 "[capi][query][error][dense]") {
2059 SupportedFsLocal local_fs;
2060 std::string array_name =
2061 local_fs.file_prefix() + local_fs.temp_dir() + "query_error_dense";
2062 create_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2063
2064 create_dense_array(array_name);
2065
2066 // Open array
2067 tiledb_array_t* array;
2068 int rc = tiledb_array_alloc(ctx_, array_name.c_str(), &array);
2069 REQUIRE(rc == TILEDB_OK);
2070 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
2071 REQUIRE(rc == TILEDB_OK);
2072
2073 int32_t a[4];
2074 uint64_t a_size = sizeof(a);
2075
2076 // Prepare query
2077 tiledb_query_t* query;
2078 rc = tiledb_query_alloc(ctx_, array, TILEDB_READ, &query);
2079 CHECK(rc == TILEDB_OK);
2080 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a, &a_size);
2081 CHECK(rc == TILEDB_OK);
2082
2083 int64_t subarray[] = {2, 3, 4, 5};
2084 rc = tiledb_query_set_subarray(ctx_, query, subarray);
2085 CHECK(rc == TILEDB_OK);
2086 int64_t s = 1;
2087 int64_t e = 2;
2088 rc = tiledb_query_add_range(ctx_, query, 0, &s, &e, nullptr);
2089 CHECK(rc == TILEDB_OK);
2090
2091 rc = tiledb_query_set_layout(ctx_, query, TILEDB_GLOBAL_ORDER);
2092 CHECK(rc == TILEDB_OK);
2093 rc = tiledb_query_submit(ctx_, query);
2094 CHECK(rc == TILEDB_ERR);
2095
2096 // Close array
2097 rc = tiledb_array_close(ctx_, array);
2098 CHECK(rc == TILEDB_OK);
2099
2100 // Clean up
2101 tiledb_array_free(&array);
2102 tiledb_query_free(&query);
2103
2104 remove_temp_dir(local_fs.file_prefix() + local_fs.temp_dir());
2105 }