1 /**
2 * @file unit-capi-metadata.cc
3 *
4 * @section LICENSE
5 *
6 * The MIT License
7 *
8 * @copyright Copyright (c) 2017-2021 TileDB, Inc.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 *
28 * @section DESCRIPTION
29 *
30 * Tests the C API for array metadata.
31 */
32
33 #include "test/src/helpers.h"
34 #include "test/src/vfs_helpers.h"
35 #include "tiledb/sm/c_api/tiledb.h"
36 #include "tiledb/sm/c_api/tiledb_struct_def.h"
37 #include "tiledb/sm/enums/encryption_type.h"
38 #include "tiledb/sm/global_state/unit_test_config.h"
39
40 #ifdef _WIN32
41 #include "tiledb/sm/filesystem/win.h"
42 #else
43 #include "tiledb/sm/filesystem/posix.h"
44 #endif
45
46 #include <catch.hpp>
47 #include <chrono>
48 #include <iostream>
49 #include <thread>
50
51 using namespace tiledb::sm;
52 using namespace tiledb::test;
53
54 /* ********************************* */
55 /* STRUCT DEFINITION */
56 /* ********************************* */
57
58 struct CMetadataFx {
59 tiledb_ctx_t* ctx_;
60 tiledb_vfs_t* vfs_;
61 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
62 std::string temp_dir_;
63 std::string array_name_;
64 const char* ARRAY_NAME = "test_metadata";
65 tiledb_array_t* array_ = nullptr;
66 const char* key_ = "0123456789abcdeF0123456789abcdeF";
67 const uint32_t key_len_ =
68 (uint32_t)strlen("0123456789abcdeF0123456789abcdeF");
69 const tiledb_encryption_type_t enc_type_ = TILEDB_AES_256_GCM;
70
71 void create_default_array_1d();
72 void create_default_array_1d_with_key();
73
74 // Used to get the number of directories or files of another directory
75 struct get_num_struct {
76 int num;
77 };
78
79 static int get_meta_num(const char* path, void* data);
80
81 CMetadataFx();
82 ~CMetadataFx();
83 };
84
CMetadataFx()85 CMetadataFx::CMetadataFx()
86 : fs_vec_(vfs_test_get_fs_vec()) {
87 // Initialize vfs test
88 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
89
90 // Create temporary directory based on the supported filesystem
91 #ifdef _WIN32
92 SupportedFsLocal windows_fs;
93 temp_dir_ = windows_fs.file_prefix() + windows_fs.temp_dir();
94 #else
95 SupportedFsLocal posix_fs;
96 temp_dir_ = posix_fs.file_prefix() + posix_fs.temp_dir();
97 #endif
98
99 create_dir(temp_dir_, ctx_, vfs_);
100
101 array_name_ = temp_dir_ + ARRAY_NAME;
102 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_);
103 CHECK(rc == TILEDB_OK);
104 }
105
~CMetadataFx()106 CMetadataFx::~CMetadataFx() {
107 tiledb_array_free(&array_);
108 remove_dir(temp_dir_, ctx_, vfs_);
109 tiledb_ctx_free(&ctx_);
110 tiledb_vfs_free(&vfs_);
111 }
112
get_meta_num(const char * path,void * data)113 int CMetadataFx::get_meta_num(const char* path, void* data) {
114 (void)path;
115 auto data_struct = (CMetadataFx::get_num_struct*)data;
116 ++data_struct->num;
117
118 return 1;
119 }
120
create_default_array_1d()121 void CMetadataFx::create_default_array_1d() {
122 uint64_t domain[] = {1, 10};
123 uint64_t tile_extent = 5;
124 create_array(
125 ctx_,
126 array_name_,
127 TILEDB_DENSE,
128 {"d"},
129 {TILEDB_UINT64},
130 {domain},
131 {&tile_extent},
132 {"a", "b", "c"},
133 {TILEDB_INT32, TILEDB_CHAR, TILEDB_FLOAT32},
134 {1, TILEDB_VAR_NUM, 2},
135 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1),
136 tiledb::test::Compressor(TILEDB_FILTER_ZSTD, -1),
137 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
138 TILEDB_ROW_MAJOR,
139 TILEDB_ROW_MAJOR,
140 2);
141 }
142
create_default_array_1d_with_key()143 void CMetadataFx::create_default_array_1d_with_key() {
144 uint64_t domain[] = {1, 10};
145 uint64_t tile_extent = 5;
146 create_array(
147 ctx_,
148 array_name_,
149 enc_type_,
150 key_,
151 key_len_,
152 TILEDB_DENSE,
153 {"d"},
154 {TILEDB_UINT64},
155 {domain},
156 {&tile_extent},
157 {"a", "b", "c"},
158 {TILEDB_INT32, TILEDB_CHAR, TILEDB_FLOAT32},
159 {1, TILEDB_VAR_NUM, 2},
160 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1),
161 tiledb::test::Compressor(TILEDB_FILTER_ZSTD, -1),
162 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
163 TILEDB_ROW_MAJOR,
164 TILEDB_ROW_MAJOR,
165 2);
166 }
167
168 /* ********************************* */
169 /* TESTS */
170 /* ********************************* */
171
172 TEST_CASE_METHOD(
173 CMetadataFx, "C API: Metadata, basic errors", "[capi][metadata][errors]") {
174 // Create default array
175 create_default_array_1d();
176
177 // Create array
178 tiledb_array_t* array;
179 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
180 REQUIRE(rc == TILEDB_OK);
181
182 // Put metadata on an array that is not opened
183 int v = 5;
184 rc = tiledb_array_put_metadata(ctx_, array, "key", TILEDB_INT32, 1, &v);
185 CHECK(rc == TILEDB_ERR);
186
187 // Write metadata on an array opened in READ mode
188 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
189 REQUIRE(rc == TILEDB_OK);
190 rc = tiledb_array_put_metadata(ctx_, array, "key", TILEDB_INT32, 1, &v);
191 CHECK(rc == TILEDB_ERR);
192
193 // Close array
194 rc = tiledb_array_close(ctx_, array);
195 REQUIRE(rc == TILEDB_OK);
196
197 // Reopen array in WRITE mode
198 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
199 REQUIRE(rc == TILEDB_OK);
200
201 // Write null key
202 rc = tiledb_array_put_metadata(ctx_, array, NULL, TILEDB_INT32, 1, &v);
203 CHECK(rc == TILEDB_ERR);
204
205 // Write value type ANY
206 rc = tiledb_array_put_metadata(ctx_, array, "key", TILEDB_ANY, 1, &v);
207 CHECK(rc == TILEDB_ERR);
208
209 // Write a correct item
210 rc = tiledb_array_put_metadata(ctx_, array, "key", TILEDB_INT32, 1, &v);
211 CHECK(rc == TILEDB_OK);
212
213 // Close array
214 rc = tiledb_array_close(ctx_, array);
215 REQUIRE(rc == TILEDB_OK);
216
217 // Open with key
218 tiledb_config_t* config;
219 tiledb_error_t* error = nullptr;
220 rc = tiledb_config_alloc(&config, &error);
221 REQUIRE(rc == TILEDB_OK);
222 REQUIRE(error == nullptr);
223 std::string encryption_type_string =
224 encryption_type_str((tiledb::sm::EncryptionType)enc_type_);
225 rc = tiledb_config_set(
226 config, "sm.encryption_type", encryption_type_string.c_str(), &error);
227 REQUIRE(rc == TILEDB_OK);
228 REQUIRE(error == nullptr);
229 rc = tiledb_config_set(config, "sm.encryption_key", key_, &error);
230 REQUIRE(rc == TILEDB_OK);
231 REQUIRE(error == nullptr);
232 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
233 key_len_);
234 rc = tiledb_array_set_config(ctx_, array, config);
235 REQUIRE(rc == TILEDB_OK);
236 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
237 CHECK(rc == TILEDB_ERR);
238
239 // Clean up
240 tiledb_array_free(&array);
241 tiledb_config_free(&config);
242 }
243
244 TEST_CASE_METHOD(
245 CMetadataFx, "C API: Metadata, write/read", "[capi][metadata][read]") {
246 // Create default array
247 create_default_array_1d();
248
249 // Create and open array in write mode
250 tiledb_array_t* array;
251 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
252 REQUIRE(rc == TILEDB_OK);
253 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
254 REQUIRE(rc == TILEDB_OK);
255
256 // Write items
257 int32_t v = 5;
258 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
259 CHECK(rc == TILEDB_OK);
260 float f[] = {1.1f, 1.2f};
261 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f);
262 CHECK(rc == TILEDB_OK);
263
264 // Close array
265 rc = tiledb_array_close(ctx_, array);
266 REQUIRE(rc == TILEDB_OK);
267 tiledb_array_free(&array);
268
269 // Open the array in read mode
270 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
271 REQUIRE(rc == TILEDB_OK);
272 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
273 REQUIRE(rc == TILEDB_OK);
274
275 // Read
276 const void* v_r;
277 tiledb_datatype_t v_type;
278 uint32_t v_num;
279 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
280 CHECK(rc == TILEDB_OK);
281 CHECK(v_type == TILEDB_INT32);
282 CHECK(v_num == 1);
283 CHECK(*((const int32_t*)v_r) == 5);
284
285 rc = tiledb_array_get_metadata(ctx_, array, "bb", &v_type, &v_num, &v_r);
286 CHECK(rc == TILEDB_OK);
287 CHECK(v_type == TILEDB_FLOAT32);
288 CHECK(v_num == 2);
289 CHECK(((const float*)v_r)[0] == 1.1f);
290 CHECK(((const float*)v_r)[1] == 1.2f);
291
292 rc = tiledb_array_get_metadata(ctx_, array, "foo", &v_type, &v_num, &v_r);
293 CHECK(rc == TILEDB_OK);
294 CHECK(v_r == nullptr);
295
296 uint64_t num = 0;
297 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
298 CHECK(rc == TILEDB_OK);
299 CHECK(num == 2);
300
301 const char* key;
302 uint32_t key_len;
303 rc = tiledb_array_get_metadata_from_index(
304 ctx_, array, 10, &key, &key_len, &v_type, &v_num, &v_r);
305 CHECK(rc == TILEDB_ERR);
306
307 rc = tiledb_array_get_metadata_from_index(
308 ctx_, array, 1, &key, &key_len, &v_type, &v_num, &v_r);
309 CHECK(rc == TILEDB_OK);
310 CHECK(v_type == TILEDB_FLOAT32);
311 CHECK(v_num == 2);
312 CHECK(((const float*)v_r)[0] == 1.1f);
313 CHECK(((const float*)v_r)[1] == 1.2f);
314 CHECK(key_len == strlen("bb"));
315 CHECK(!strncmp(key, "bb", strlen("bb")));
316
317 // Check has_key
318 int32_t has_key = 0;
319 rc = tiledb_array_has_metadata_key(ctx_, array, "bb", &v_type, &has_key);
320 CHECK(rc == TILEDB_OK);
321 CHECK(v_type == TILEDB_FLOAT32);
322 CHECK(has_key == 1);
323
324 // Check not has_key
325 v_type = (tiledb_datatype_t)std::numeric_limits<int32_t>::max();
326 rc = tiledb_array_has_metadata_key(
327 ctx_, array, "non-existent-key", &v_type, &has_key);
328 CHECK(rc == TILEDB_OK);
329 // The API does not touch v_type when no key is found.
330 CHECK((int32_t)v_type == std::numeric_limits<int32_t>::max());
331 CHECK(has_key == 0);
332
333 // Close array
334 rc = tiledb_array_close(ctx_, array);
335 REQUIRE(rc == TILEDB_OK);
336 tiledb_array_free(&array);
337 }
338
339 TEST_CASE_METHOD(
340 CMetadataFx, "C API: Metadata, UTF-8", "[capi][metadata][utf-8]") {
341 // Create default array
342 create_default_array_1d();
343
344 // Create and open array in write mode
345 tiledb_array_t* array;
346 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
347 REQUIRE(rc == TILEDB_OK);
348 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
349 REQUIRE(rc == TILEDB_OK);
350
351 // Write UTF-8 (≥ holds 3 bytes)
352 int32_t v = 5;
353 rc = tiledb_array_put_metadata(ctx_, array, "≥", TILEDB_INT32, 1, &v);
354 CHECK(rc == TILEDB_OK);
355
356 // Close array
357 rc = tiledb_array_close(ctx_, array);
358 REQUIRE(rc == TILEDB_OK);
359 tiledb_array_free(&array);
360
361 // Open the array in read mode
362 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
363 REQUIRE(rc == TILEDB_OK);
364 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
365 REQUIRE(rc == TILEDB_OK);
366
367 // Read
368 const void* v_r;
369 tiledb_datatype_t v_type;
370 uint32_t v_num;
371 rc = tiledb_array_get_metadata(ctx_, array, "≥", &v_type, &v_num, &v_r);
372 CHECK(rc == TILEDB_OK);
373 CHECK(v_type == TILEDB_INT32);
374 CHECK(v_num == 1);
375 CHECK(*((const int32_t*)v_r) == 5);
376
377 const char* key;
378 uint32_t key_len;
379 rc = tiledb_array_get_metadata_from_index(
380 ctx_, array, 0, &key, &key_len, &v_type, &v_num, &v_r);
381 CHECK(rc == TILEDB_OK);
382 CHECK(v_type == TILEDB_INT32);
383 CHECK(v_num == 1);
384 CHECK(*((const int32_t*)v_r) == 5);
385 CHECK(key_len == strlen("≥"));
386 CHECK(!strncmp(key, "≥", strlen("≥")));
387
388 // Close array
389 rc = tiledb_array_close(ctx_, array);
390 REQUIRE(rc == TILEDB_OK);
391 tiledb_array_free(&array);
392 }
393
394 TEST_CASE_METHOD(
395 CMetadataFx, "C API: Metadata, delete", "[capi][metadata][delete]") {
396 // Create default array
397 create_default_array_1d();
398
399 // Create and open array in write mode
400 tiledb_array_t* array;
401 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
402 REQUIRE(rc == TILEDB_OK);
403 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
404 REQUIRE(rc == TILEDB_OK);
405
406 // Write items
407 int32_t v = 5;
408 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
409 CHECK(rc == TILEDB_OK);
410 float f[] = {1.1f, 1.2f};
411 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f);
412 CHECK(rc == TILEDB_OK);
413
414 // Close array
415 rc = tiledb_array_close(ctx_, array);
416 REQUIRE(rc == TILEDB_OK);
417 tiledb_array_free(&array);
418
419 // Prevent array metadata filename/timestamp conflicts
420 std::this_thread::sleep_for(std::chrono::milliseconds(1));
421
422 // Delete an item that exists and one that does not exist
423 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
424 REQUIRE(rc == TILEDB_OK);
425 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
426 REQUIRE(rc == TILEDB_OK);
427 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
428 CHECK(rc == TILEDB_OK);
429 rc = tiledb_array_delete_metadata(ctx_, array, "foo");
430 CHECK(rc == TILEDB_OK);
431 rc = tiledb_array_close(ctx_, array);
432 REQUIRE(rc == TILEDB_OK);
433 tiledb_array_free(&array);
434
435 // Open the array in read mode
436 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
437 REQUIRE(rc == TILEDB_OK);
438 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
439 REQUIRE(rc == TILEDB_OK);
440
441 // Read
442 const void* v_r;
443 tiledb_datatype_t v_type;
444 uint32_t v_num;
445 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
446 CHECK(rc == TILEDB_OK);
447 CHECK(v_r == nullptr);
448
449 rc = tiledb_array_get_metadata(ctx_, array, "bb", &v_type, &v_num, &v_r);
450 CHECK(rc == TILEDB_OK);
451 CHECK(v_type == TILEDB_FLOAT32);
452 CHECK(v_num == 2);
453 CHECK(((const float*)v_r)[0] == 1.1f);
454 CHECK(((const float*)v_r)[1] == 1.2f);
455
456 rc = tiledb_array_get_metadata(ctx_, array, "foo", &v_type, &v_num, &v_r);
457 CHECK(rc == TILEDB_OK);
458 CHECK(v_r == nullptr);
459
460 uint64_t num = 0;
461 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
462 CHECK(rc == TILEDB_OK);
463 CHECK(num == 1);
464
465 const char* key;
466 uint32_t key_len;
467 rc = tiledb_array_get_metadata_from_index(
468 ctx_, array, 0, &key, &key_len, &v_type, &v_num, &v_r);
469 CHECK(rc == TILEDB_OK);
470 CHECK(v_type == TILEDB_FLOAT32);
471 CHECK(v_num == 2);
472 CHECK(((const float*)v_r)[0] == 1.1f);
473 CHECK(((const float*)v_r)[1] == 1.2f);
474 CHECK(key_len == strlen("bb"));
475 CHECK(!strncmp(key, "bb", strlen("bb")));
476
477 // Close array
478 rc = tiledb_array_close(ctx_, array);
479 REQUIRE(rc == TILEDB_OK);
480 tiledb_array_free(&array);
481 }
482
483 TEST_CASE_METHOD(
484 CMetadataFx,
485 "C API: Metadata, multiple metadata and consolidate",
486 "[capi][metadata][multiple][consolidation]") {
487 // Create default array
488 create_default_array_1d();
489
490 // Create and open array in write mode
491 tiledb_array_t* array;
492 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
493 REQUIRE(rc == TILEDB_OK);
494 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
495 REQUIRE(rc == TILEDB_OK);
496 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
497 REQUIRE(rc == TILEDB_OK);
498
499 // Write items
500 int32_t v = 5;
501 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
502 CHECK(rc == TILEDB_OK);
503 float f[] = {1.1f, 1.2f};
504 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f);
505 CHECK(rc == TILEDB_OK);
506
507 // Close array
508 rc = tiledb_array_close(ctx_, array);
509 REQUIRE(rc == TILEDB_OK);
510 tiledb_array_free(&array);
511
512 // Update
513 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
514 REQUIRE(rc == TILEDB_OK);
515 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 2);
516 REQUIRE(rc == TILEDB_OK);
517 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
518 REQUIRE(rc == TILEDB_OK);
519 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
520 CHECK(rc == TILEDB_OK);
521 v = 10;
522 rc = tiledb_array_put_metadata(ctx_, array, "cccc", TILEDB_INT32, 1, &v);
523 CHECK(rc == TILEDB_OK);
524 rc = tiledb_array_close(ctx_, array);
525 REQUIRE(rc == TILEDB_OK);
526 tiledb_array_free(&array);
527
528 // Open the array in read mode
529 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
530 REQUIRE(rc == TILEDB_OK);
531 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
532 REQUIRE(rc == TILEDB_OK);
533
534 // Read
535 const void* v_r;
536 tiledb_datatype_t v_type;
537 uint32_t v_num;
538 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
539 CHECK(rc == TILEDB_OK);
540 CHECK(v_r == nullptr);
541
542 rc = tiledb_array_get_metadata(ctx_, array, "bb", &v_type, &v_num, &v_r);
543 CHECK(rc == TILEDB_OK);
544 CHECK(v_type == TILEDB_FLOAT32);
545 CHECK(v_num == 2);
546 CHECK(((const float*)v_r)[0] == 1.1f);
547 CHECK(((const float*)v_r)[1] == 1.2f);
548
549 rc = tiledb_array_get_metadata(ctx_, array, "cccc", &v_type, &v_num, &v_r);
550 CHECK(rc == TILEDB_OK);
551 CHECK(v_type == TILEDB_INT32);
552 CHECK(v_num == 1);
553 CHECK(*((const int32_t*)v_r) == 10);
554
555 uint64_t num = 0;
556 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
557 CHECK(rc == TILEDB_OK);
558 CHECK(num == 2);
559
560 const char* key;
561 uint32_t key_len;
562 rc = tiledb_array_get_metadata_from_index(
563 ctx_, array, 0, &key, &key_len, &v_type, &v_num, &v_r);
564 CHECK(rc == TILEDB_OK);
565 CHECK(v_type == TILEDB_FLOAT32);
566 CHECK(v_num == 2);
567 CHECK(((const float*)v_r)[0] == 1.1f);
568 CHECK(((const float*)v_r)[1] == 1.2f);
569 CHECK(key_len == strlen("bb"));
570 CHECK(!strncmp(key, "bb", strlen("bb")));
571
572 // Close array
573 rc = tiledb_array_close(ctx_, array);
574 REQUIRE(rc == TILEDB_OK);
575 tiledb_array_free(&array);
576
577 // Consolidate
578 SECTION("tiledb_array_consolidate") {
579 // Configuration for consolidating array metadata
580 tiledb_config_t* config = nullptr;
581 tiledb_error_t* error = nullptr;
582 REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
583 REQUIRE(error == nullptr);
584 int rc = tiledb_config_set(
585 config, "sm.consolidation.mode", "array_meta", &error);
586 REQUIRE(rc == TILEDB_OK);
587 REQUIRE(error == nullptr);
588 rc = tiledb_array_consolidate(ctx_, array_name_.c_str(), config);
589 CHECK(rc == TILEDB_OK);
590 tiledb_config_free(&config);
591 }
592
593 // Check number of metadata files
594 get_num_struct data = {0};
595 auto meta_folder =
596 array_name_ + "/" + tiledb::sm::constants::array_metadata_folder_name;
597 rc = tiledb_vfs_ls(ctx_, vfs_, meta_folder.c_str(), &get_meta_num, &data);
598 CHECK(rc == TILEDB_OK);
599 CHECK(data.num == 4);
600
601 // Read at timestamp 1
602 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
603 REQUIRE(rc == TILEDB_OK);
604 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
605 REQUIRE(rc == TILEDB_OK);
606 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
607 REQUIRE(rc == TILEDB_OK);
608 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
609 CHECK(rc == TILEDB_OK);
610 CHECK(v_type == TILEDB_INT32);
611 CHECK(*(const int32_t*)v_r == 5);
612 CHECK(v_num == 1);
613 rc = tiledb_array_close(ctx_, array);
614 REQUIRE(rc == TILEDB_OK);
615 tiledb_array_free(&array);
616
617 // Vacuum
618 tiledb_config_t* config_v = nullptr;
619 tiledb_error_t* error_v = nullptr;
620 REQUIRE(tiledb_config_alloc(&config_v, &error_v) == TILEDB_OK);
621 REQUIRE(error_v == nullptr);
622 rc = tiledb_config_set(config_v, "sm.vacuum.mode", "array_meta", &error_v);
623 REQUIRE(rc == TILEDB_OK);
624 REQUIRE(error_v == nullptr);
625 rc = tiledb_array_vacuum(ctx_, array_name_.c_str(), config_v);
626 CHECK(rc == TILEDB_OK);
627 tiledb_config_free(&config_v);
628
629 // Check number of metadata files
630 data = {0};
631 rc = tiledb_vfs_ls(ctx_, vfs_, meta_folder.c_str(), &get_meta_num, &data);
632 CHECK(rc == TILEDB_OK);
633 CHECK(data.num == 1);
634
635 // Open the array in read mode
636 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
637 REQUIRE(rc == TILEDB_OK);
638 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
639 REQUIRE(rc == TILEDB_OK);
640
641 num = 0;
642 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
643 CHECK(rc == TILEDB_OK);
644 CHECK(num == 2);
645
646 // Close array
647 rc = tiledb_array_close(ctx_, array);
648 REQUIRE(rc == TILEDB_OK);
649 tiledb_array_free(&array);
650
651 // Write once more
652 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
653 REQUIRE(rc == TILEDB_OK);
654 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
655 REQUIRE(rc == TILEDB_OK);
656
657 // Write items
658 v = 50;
659 rc = tiledb_array_put_metadata(ctx_, array, "d", TILEDB_INT32, 1, &v);
660 CHECK(rc == TILEDB_OK);
661
662 // Close array
663 rc = tiledb_array_close(ctx_, array);
664 REQUIRE(rc == TILEDB_OK);
665 tiledb_array_free(&array);
666
667 // Consolidate again
668 tiledb_config_t* config = nullptr;
669 tiledb_error_t* error = nullptr;
670 REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
671 REQUIRE(error == nullptr);
672 rc = tiledb_config_set(config, "sm.consolidation.mode", "array_meta", &error);
673 REQUIRE(rc == TILEDB_OK);
674 REQUIRE(error == nullptr);
675 rc = tiledb_array_consolidate(ctx_, array_name_.c_str(), config);
676 CHECK(rc == TILEDB_OK);
677 tiledb_config_free(&config);
678 tiledb_array_free(&array);
679
680 // Open the array in read mode
681 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
682 REQUIRE(rc == TILEDB_OK);
683 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
684 REQUIRE(rc == TILEDB_OK);
685
686 num = 0;
687 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
688 CHECK(rc == TILEDB_OK);
689 CHECK(num == 3);
690
691 rc = tiledb_array_get_metadata(ctx_, array, "cccc", &v_type, &v_num, &v_r);
692 CHECK(rc == TILEDB_OK);
693 CHECK(v_type == TILEDB_INT32);
694 CHECK(v_num == 1);
695 CHECK(*((const int32_t*)v_r) == 10);
696
697 rc = tiledb_array_get_metadata(ctx_, array, "d", &v_type, &v_num, &v_r);
698 CHECK(rc == TILEDB_OK);
699 CHECK(v_type == TILEDB_INT32);
700 CHECK(v_num == 1);
701 CHECK(*((const int32_t*)v_r) == 50);
702
703 // Close array
704 rc = tiledb_array_close(ctx_, array);
705 REQUIRE(rc == TILEDB_OK);
706 tiledb_array_free(&array);
707 }
708
709 TEST_CASE_METHOD(
710 CMetadataFx, "C API: Metadata, open at", "[capi][metadata][open-at]") {
711 // Create default array
712 create_default_array_1d();
713
714 // Create and open array in write mode
715 tiledb_array_t* array;
716 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
717 REQUIRE(rc == TILEDB_OK);
718 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
719 REQUIRE(rc == TILEDB_OK);
720 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
721 REQUIRE(rc == TILEDB_OK);
722
723 // Write items
724 int32_t v = 5;
725 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
726 CHECK(rc == TILEDB_OK);
727 float f[] = {1.1f, 1.2f};
728 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f);
729 CHECK(rc == TILEDB_OK);
730
731 // Close array
732 rc = tiledb_array_close(ctx_, array);
733 REQUIRE(rc == TILEDB_OK);
734 tiledb_array_free(&array);
735
736 // Update
737 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
738 REQUIRE(rc == TILEDB_OK);
739 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 2);
740 REQUIRE(rc == TILEDB_OK);
741 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
742 REQUIRE(rc == TILEDB_OK);
743 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
744 CHECK(rc == TILEDB_OK);
745 rc = tiledb_array_close(ctx_, array);
746 REQUIRE(rc == TILEDB_OK);
747 tiledb_array_free(&array);
748
749 // Open the array in read mode at a timestamp
750 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
751 REQUIRE(rc == TILEDB_OK);
752 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
753 REQUIRE(rc == TILEDB_OK);
754 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
755 REQUIRE(rc == TILEDB_OK);
756
757 // Read
758 const void* v_r;
759 tiledb_datatype_t v_type;
760 uint32_t v_num;
761 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
762 CHECK(rc == TILEDB_OK);
763 CHECK(v_type == TILEDB_INT32);
764 CHECK(v_num == 1);
765 CHECK(*((const int32_t*)v_r) == 5);
766
767 uint64_t num = 0;
768 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
769 CHECK(rc == TILEDB_OK);
770 CHECK(num == 2);
771
772 // Close array
773 rc = tiledb_array_close(ctx_, array);
774 REQUIRE(rc == TILEDB_OK);
775 tiledb_array_free(&array);
776 }
777
778 TEST_CASE_METHOD(
779 CMetadataFx, "C API: Metadata, reopen", "[capi][metadata][reopen]") {
780 // Create default array
781 create_default_array_1d();
782
783 // Create and open array in write mode
784 tiledb_array_t* array;
785 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
786 REQUIRE(rc == TILEDB_OK);
787 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
788 REQUIRE(rc == TILEDB_OK);
789 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
790 REQUIRE(rc == TILEDB_OK);
791
792 // Write items
793 int32_t v = 5;
794 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
795 CHECK(rc == TILEDB_OK);
796 float f[] = {1.1f, 1.2f};
797 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f);
798 CHECK(rc == TILEDB_OK);
799
800 // Close array
801 rc = tiledb_array_close(ctx_, array);
802 REQUIRE(rc == TILEDB_OK);
803 tiledb_array_free(&array);
804
805 // Update
806 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
807 REQUIRE(rc == TILEDB_OK);
808 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 2);
809 REQUIRE(rc == TILEDB_OK);
810 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
811 REQUIRE(rc == TILEDB_OK);
812 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
813 CHECK(rc == TILEDB_OK);
814 rc = tiledb_array_close(ctx_, array);
815 REQUIRE(rc == TILEDB_OK);
816 tiledb_array_free(&array);
817
818 // Open the array in read mode at a timestamp
819 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
820 REQUIRE(rc == TILEDB_OK);
821 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
822 REQUIRE(rc == TILEDB_OK);
823 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
824 REQUIRE(rc == TILEDB_OK);
825
826 // Read
827 const void* v_r;
828 tiledb_datatype_t v_type;
829 uint32_t v_num;
830 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
831 CHECK(rc == TILEDB_OK);
832 CHECK(v_type == TILEDB_INT32);
833 CHECK(v_num == 1);
834 CHECK(*((const int32_t*)v_r) == 5);
835
836 uint64_t num = 0;
837 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
838 CHECK(rc == TILEDB_OK);
839 CHECK(num == 2);
840
841 // Reopen
842 rc = tiledb_array_set_open_timestamp_end(
843 ctx_, array, tiledb::sm::utils::time::timestamp_now_ms());
844 REQUIRE(rc == TILEDB_OK);
845 rc = tiledb_array_reopen(ctx_, array);
846 CHECK(rc == TILEDB_OK);
847
848 // Read
849 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
850 CHECK(rc == TILEDB_OK);
851 CHECK(v_r == nullptr);
852
853 num = 0;
854 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
855 CHECK(rc == TILEDB_OK);
856 CHECK(num == 1);
857
858 // Close array
859 rc = tiledb_array_close(ctx_, array);
860 REQUIRE(rc == TILEDB_OK);
861 tiledb_array_free(&array);
862 }
863
864 TEST_CASE_METHOD(
865 CMetadataFx,
866 "C API: Metadata, timestamp_end",
867 "[capi][metadata][timestamp-end]") {
868 // Create default array
869 create_default_array_1d();
870
871 // Create and open array in write mode
872 tiledb_array_t* array;
873 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
874 REQUIRE(rc == TILEDB_OK);
875 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 1);
876 REQUIRE(rc == TILEDB_OK);
877 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
878 REQUIRE(rc == TILEDB_OK);
879
880 // Write items
881 int32_t v1 = 4;
882 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v1);
883 CHECK(rc == TILEDB_OK);
884 float f1[] = {1.0f, 1.2f};
885 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f1);
886 CHECK(rc == TILEDB_OK);
887
888 // Close array
889 rc = tiledb_array_close(ctx_, array);
890 REQUIRE(rc == TILEDB_OK);
891 tiledb_array_free(&array);
892
893 // Update
894 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
895 REQUIRE(rc == TILEDB_OK);
896 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 2);
897 REQUIRE(rc == TILEDB_OK);
898 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
899 REQUIRE(rc == TILEDB_OK);
900 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
901 CHECK(rc == TILEDB_OK);
902 rc = tiledb_array_close(ctx_, array);
903 REQUIRE(rc == TILEDB_OK);
904 tiledb_array_free(&array);
905
906 // Create and open array in write mode
907 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
908 REQUIRE(rc == TILEDB_OK);
909 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 3);
910 REQUIRE(rc == TILEDB_OK);
911 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
912 REQUIRE(rc == TILEDB_OK);
913
914 // Write items
915 int32_t v2 = 5;
916 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v2);
917 CHECK(rc == TILEDB_OK);
918 float f2[] = {1.1f, 1.2f};
919 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f2);
920 CHECK(rc == TILEDB_OK);
921
922 // Close array
923 rc = tiledb_array_close(ctx_, array);
924 REQUIRE(rc == TILEDB_OK);
925 tiledb_array_free(&array);
926
927 // Update
928 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
929 REQUIRE(rc == TILEDB_OK);
930 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 4);
931 REQUIRE(rc == TILEDB_OK);
932 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
933 REQUIRE(rc == TILEDB_OK);
934 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
935 CHECK(rc == TILEDB_OK);
936 rc = tiledb_array_close(ctx_, array);
937 REQUIRE(rc == TILEDB_OK);
938 tiledb_array_free(&array);
939
940 // Create and open array in write mode
941 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
942 REQUIRE(rc == TILEDB_OK);
943 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 5);
944 REQUIRE(rc == TILEDB_OK);
945 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
946 REQUIRE(rc == TILEDB_OK);
947
948 // Write items
949 int32_t v3 = 6;
950 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v3);
951 CHECK(rc == TILEDB_OK);
952 float f3[] = {1.2f, 1.3f};
953 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f3);
954 CHECK(rc == TILEDB_OK);
955
956 // Close array
957 rc = tiledb_array_close(ctx_, array);
958 REQUIRE(rc == TILEDB_OK);
959 tiledb_array_free(&array);
960
961 // Update
962 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
963 REQUIRE(rc == TILEDB_OK);
964 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 6);
965 REQUIRE(rc == TILEDB_OK);
966 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
967 REQUIRE(rc == TILEDB_OK);
968 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
969 CHECK(rc == TILEDB_OK);
970 rc = tiledb_array_close(ctx_, array);
971 REQUIRE(rc == TILEDB_OK);
972 tiledb_array_free(&array);
973
974 // Open the array in read mode between timestamp1 and timestamp2
975 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
976 rc = tiledb_array_set_open_timestamp_start(ctx_, array, 2);
977 REQUIRE(rc == TILEDB_OK);
978 rc = tiledb_array_set_open_timestamp_end(ctx_, array, 3);
979 REQUIRE(rc == TILEDB_OK);
980 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
981 REQUIRE(rc == TILEDB_OK);
982
983 // Read - ensure that the data is only that written between
984 // timestamp1 and timestamp2
985 const void* v_r;
986 tiledb_datatype_t v_type;
987 uint32_t v_num;
988 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
989 CHECK(rc == TILEDB_OK);
990 CHECK(v_type == TILEDB_INT32);
991 CHECK(v_num == 1);
992 CHECK(*((const int32_t*)v_r) == 5);
993
994 uint64_t num = 0;
995 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
996 CHECK(rc == TILEDB_OK);
997 CHECK(num == 2);
998
999 // Close array
1000 rc = tiledb_array_close(ctx_, array);
1001 REQUIRE(rc == TILEDB_OK);
1002 tiledb_array_free(&array);
1003 }
1004
1005 TEST_CASE_METHOD(
1006 CMetadataFx,
1007 "C API: Metadata, encryption",
1008 "[capi][metadata][encryption]") {
1009 // Create default array
1010 create_default_array_1d_with_key();
1011
1012 // Create and open array in write mode
1013 tiledb_array_t* array;
1014 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1015 REQUIRE(rc == TILEDB_OK);
1016 tiledb_config_t* config;
1017 tiledb_error_t* error = nullptr;
1018 rc = tiledb_config_alloc(&config, &error);
1019 REQUIRE(rc == TILEDB_OK);
1020 REQUIRE(error == nullptr);
1021 std::string encryption_type_string =
1022 encryption_type_str((tiledb::sm::EncryptionType)enc_type_);
1023 rc = tiledb_config_set(
1024 config, "sm.encryption_type", encryption_type_string.c_str(), &error);
1025 REQUIRE(rc == TILEDB_OK);
1026 REQUIRE(error == nullptr);
1027 rc = tiledb_config_set(config, "sm.encryption_key", key_, &error);
1028 REQUIRE(rc == TILEDB_OK);
1029 REQUIRE(error == nullptr);
1030 rc = tiledb_array_set_config(ctx_, array, config);
1031 REQUIRE(rc == TILEDB_OK);
1032 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
1033 key_len_);
1034 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1035 REQUIRE(rc == TILEDB_OK);
1036
1037 // Write items
1038 int32_t v = 5;
1039 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
1040 CHECK(rc == TILEDB_OK);
1041 float f[] = {1.1f, 1.2f};
1042 rc = tiledb_array_put_metadata(ctx_, array, "bb", TILEDB_FLOAT32, 2, f);
1043 CHECK(rc == TILEDB_OK);
1044
1045 // Close array
1046 rc = tiledb_array_close(ctx_, array);
1047 REQUIRE(rc == TILEDB_OK);
1048 tiledb_array_free(&array);
1049
1050 // Prevent array metadata filename/timestamp conflicts
1051 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1052
1053 // Update
1054 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1055 REQUIRE(rc == TILEDB_OK);
1056 rc = tiledb_array_set_config(ctx_, array, config);
1057 REQUIRE(rc == TILEDB_OK);
1058 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1059 REQUIRE(rc == TILEDB_OK);
1060 rc = tiledb_array_delete_metadata(ctx_, array, "aaa");
1061 CHECK(rc == TILEDB_OK);
1062 v = 10;
1063 rc = tiledb_array_put_metadata(ctx_, array, "cccc", TILEDB_INT32, 1, &v);
1064 CHECK(rc == TILEDB_OK);
1065 rc = tiledb_array_close(ctx_, array);
1066 REQUIRE(rc == TILEDB_OK);
1067 tiledb_array_free(&array);
1068
1069 // Open the array in read mode
1070 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1071 REQUIRE(rc == TILEDB_OK);
1072 rc = tiledb_array_set_config(ctx_, array, config);
1073 REQUIRE(rc == TILEDB_OK);
1074 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1075 REQUIRE(rc == TILEDB_OK);
1076
1077 // Read
1078 const void* v_r;
1079 tiledb_datatype_t v_type;
1080 uint32_t v_num;
1081 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
1082 CHECK(rc == TILEDB_OK);
1083 CHECK(v_r == nullptr);
1084
1085 rc = tiledb_array_get_metadata(ctx_, array, "bb", &v_type, &v_num, &v_r);
1086 CHECK(rc == TILEDB_OK);
1087 CHECK(v_type == TILEDB_FLOAT32);
1088 CHECK(v_num == 2);
1089 CHECK(((const float*)v_r)[0] == 1.1f);
1090 CHECK(((const float*)v_r)[1] == 1.2f);
1091
1092 rc = tiledb_array_get_metadata(ctx_, array, "cccc", &v_type, &v_num, &v_r);
1093 CHECK(rc == TILEDB_OK);
1094 CHECK(v_type == TILEDB_INT32);
1095 CHECK(v_num == 1);
1096 CHECK(*((const int32_t*)v_r) == 10);
1097
1098 uint64_t num = 0;
1099 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
1100 CHECK(rc == TILEDB_OK);
1101 CHECK(num == 2);
1102
1103 const char* key;
1104 uint32_t key_len;
1105 rc = tiledb_array_get_metadata_from_index(
1106 ctx_, array, 0, &key, &key_len, &v_type, &v_num, &v_r);
1107 CHECK(rc == TILEDB_OK);
1108 CHECK(v_type == TILEDB_FLOAT32);
1109 CHECK(v_num == 2);
1110 CHECK(((const float*)v_r)[0] == 1.1f);
1111 CHECK(((const float*)v_r)[1] == 1.2f);
1112 CHECK(key_len == strlen("bb"));
1113 CHECK(!strncmp(key, "bb", strlen("bb")));
1114
1115 // Close array
1116 rc = tiledb_array_close(ctx_, array);
1117 REQUIRE(rc == TILEDB_OK);
1118 tiledb_array_free(&array);
1119
1120 // Consolidate without key - error
1121 REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
1122 REQUIRE(error == nullptr);
1123 rc = tiledb_config_set(config, "sm.consolidation.mode", "array_meta", &error);
1124 REQUIRE(rc == TILEDB_OK);
1125 REQUIRE(error == nullptr);
1126 rc = tiledb_array_consolidate(ctx_, array_name_.c_str(), config);
1127 CHECK(rc == TILEDB_ERR);
1128 tiledb_config_free(&config);
1129
1130 // Consolidate with key - ok
1131 REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
1132 REQUIRE(error == nullptr);
1133 rc = tiledb_config_set(config, "sm.consolidation.mode", "array_meta", &error);
1134 REQUIRE(rc == TILEDB_OK);
1135 REQUIRE(error == nullptr);
1136 encryption_type_string =
1137 encryption_type_str((tiledb::sm::EncryptionType)enc_type_);
1138 rc = tiledb_config_set(
1139 config, "sm.encryption_type", encryption_type_string.c_str(), &error);
1140 REQUIRE(error == nullptr);
1141 rc = tiledb_config_set(config, "sm.encryption_key", key_, &error);
1142 REQUIRE(rc == TILEDB_OK);
1143 REQUIRE(error == nullptr);
1144 rc = tiledb_array_consolidate(ctx_, array_name_.c_str(), config);
1145 CHECK(rc == TILEDB_OK);
1146 tiledb_config_free(&config);
1147 tiledb_array_free(&array);
1148
1149 // Open the array in read mode
1150 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1151 REQUIRE(rc == TILEDB_OK);
1152 REQUIRE(tiledb_config_alloc(&config, &error) == TILEDB_OK);
1153 REQUIRE(error == nullptr);
1154 encryption_type_string =
1155 encryption_type_str((tiledb::sm::EncryptionType)enc_type_);
1156 rc = tiledb_config_set(
1157 config, "sm.encryption_type", encryption_type_string.c_str(), &error);
1158 REQUIRE(rc == TILEDB_OK);
1159 REQUIRE(error == nullptr);
1160 rc = tiledb_config_set(config, "sm.encryption_key", key_, &error);
1161 REQUIRE(rc == TILEDB_OK);
1162 REQUIRE(error == nullptr);
1163 rc = tiledb_array_set_config(ctx_, array, config);
1164 REQUIRE(rc == TILEDB_OK);
1165 tiledb::sm::UnitTestConfig::instance().array_encryption_key_length.set(
1166 key_len_);
1167 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1168 REQUIRE(rc == TILEDB_OK);
1169
1170 num = 0;
1171 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
1172 CHECK(rc == TILEDB_OK);
1173 CHECK(num == 2);
1174
1175 // Close array
1176 rc = tiledb_array_close(ctx_, array);
1177 REQUIRE(rc == TILEDB_OK);
1178 tiledb_array_free(&array);
1179
1180 // Write once more
1181 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1182 REQUIRE(rc == TILEDB_OK);
1183 rc = tiledb_array_set_config(ctx_, array, config);
1184 REQUIRE(rc == TILEDB_OK);
1185 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1186 REQUIRE(rc == TILEDB_OK);
1187
1188 // Write items
1189 v = 50;
1190 rc = tiledb_array_put_metadata(ctx_, array, "d", TILEDB_INT32, 1, &v);
1191 CHECK(rc == TILEDB_OK);
1192
1193 // Close array
1194 rc = tiledb_array_close(ctx_, array);
1195 REQUIRE(rc == TILEDB_OK);
1196 tiledb_array_free(&array);
1197
1198 // Consolidate again
1199 rc = tiledb_config_set(config, "sm.consolidation.mode", "array_meta", &error);
1200 REQUIRE(rc == TILEDB_OK);
1201 REQUIRE(error == nullptr);
1202 encryption_type_string =
1203 encryption_type_str((tiledb::sm::EncryptionType)enc_type_);
1204 rc = tiledb_config_set(
1205 config, "sm.encryption_type", encryption_type_string.c_str(), &error);
1206 REQUIRE(error == nullptr);
1207 rc = tiledb_config_set(config, "sm.encryption_key", key_, &error);
1208 REQUIRE(rc == TILEDB_OK);
1209 REQUIRE(error == nullptr);
1210
1211 rc = tiledb_array_consolidate(ctx_, array_name_.c_str(), config);
1212 CHECK(rc == TILEDB_OK);
1213 tiledb_array_free(&array);
1214
1215 // Open the array in read mode
1216 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1217 REQUIRE(rc == TILEDB_OK);
1218 rc = tiledb_array_set_config(ctx_, array, config);
1219 REQUIRE(rc == TILEDB_OK);
1220 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1221 REQUIRE(rc == TILEDB_OK);
1222
1223 num = 0;
1224 rc = tiledb_array_get_metadata_num(ctx_, array, &num);
1225 CHECK(rc == TILEDB_OK);
1226 CHECK(num == 3);
1227
1228 rc = tiledb_array_get_metadata(ctx_, array, "cccc", &v_type, &v_num, &v_r);
1229 CHECK(rc == TILEDB_OK);
1230 CHECK(v_type == TILEDB_INT32);
1231 CHECK(v_num == 1);
1232 CHECK(*((const int32_t*)v_r) == 10);
1233
1234 rc = tiledb_array_get_metadata(ctx_, array, "d", &v_type, &v_num, &v_r);
1235 CHECK(rc == TILEDB_OK);
1236 CHECK(v_type == TILEDB_INT32);
1237 CHECK(v_num == 1);
1238 CHECK(*((const int32_t*)v_r) == 50);
1239
1240 // Close array
1241 rc = tiledb_array_close(ctx_, array);
1242 REQUIRE(rc == TILEDB_OK);
1243 tiledb_array_free(&array);
1244 tiledb_config_free(&config);
1245 }
1246
1247 TEST_CASE_METHOD(
1248 CMetadataFx, "C API: Metadata, overwrite", "[capi][metadata][overwrite]") {
1249 // Create default array
1250 create_default_array_1d();
1251
1252 // Open array
1253 tiledb_array_t* array;
1254 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1255 CHECK(rc == TILEDB_OK);
1256 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1257 CHECK(rc == TILEDB_OK);
1258
1259 // Write and overwrite
1260 int32_t v = 5;
1261 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v);
1262 CHECK(rc == TILEDB_OK);
1263 int32_t v2 = 10;
1264 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v2);
1265 CHECK(rc == TILEDB_OK);
1266
1267 // Close array
1268 rc = tiledb_array_close(ctx_, array);
1269 CHECK(rc == TILEDB_OK);
1270
1271 // Read back
1272 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1273 CHECK(rc == TILEDB_OK);
1274 const void* vback_ptr = NULL;
1275 tiledb_datatype_t vtype;
1276 uint32_t vnum = 0;
1277 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &vtype, &vnum, &vback_ptr);
1278 CHECK(rc == TILEDB_OK);
1279 CHECK(vtype == TILEDB_INT32);
1280 CHECK(vnum == 1);
1281 CHECK(*((int32_t*)vback_ptr) == 10);
1282 rc = tiledb_array_close(ctx_, array);
1283 CHECK(rc == TILEDB_OK);
1284 tiledb_array_free(&array);
1285
1286 // Prevent array metadata filename/timestamp conflicts
1287 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1288
1289 // Overwrite again
1290 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1291 CHECK(rc == TILEDB_OK);
1292 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1293 CHECK(rc == TILEDB_OK);
1294 int32_t v3 = 20;
1295 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_INT32, 1, &v3);
1296 CHECK(rc == TILEDB_OK);
1297 rc = tiledb_array_close(ctx_, array);
1298 CHECK(rc == TILEDB_OK);
1299
1300 // Read back
1301 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1302 CHECK(rc == TILEDB_OK);
1303 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &vtype, &vnum, &vback_ptr);
1304 CHECK(rc == TILEDB_OK);
1305 CHECK(vtype == TILEDB_INT32);
1306 CHECK(vnum == 1);
1307 CHECK(*((int32_t*)vback_ptr) == 20);
1308 rc = tiledb_array_close(ctx_, array);
1309 CHECK(rc == TILEDB_OK);
1310
1311 tiledb_array_free(&array);
1312 }
1313
1314 TEST_CASE_METHOD(
1315 CMetadataFx,
1316 "C API: Metadata, write/read zero-valued",
1317 "[capi][metadata][read][zero-valued]") {
1318 // Create default array
1319 create_default_array_1d();
1320
1321 // Create and open array in write mode
1322 tiledb_array_t* array;
1323 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1324 REQUIRE(rc == TILEDB_OK);
1325 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
1326 REQUIRE(rc == TILEDB_OK);
1327
1328 // Write items
1329 rc = tiledb_array_put_metadata(ctx_, array, "aaa", TILEDB_CHAR, 0, nullptr);
1330 REQUIRE(rc == TILEDB_OK);
1331 rc = tiledb_array_put_metadata(ctx_, array, "b", TILEDB_INT32, 1, nullptr);
1332 REQUIRE(rc == TILEDB_OK);
1333
1334 // Close array
1335 rc = tiledb_array_close(ctx_, array);
1336 REQUIRE(rc == TILEDB_OK);
1337 tiledb_array_free(&array);
1338
1339 // Open the array in read mode
1340 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
1341 REQUIRE(rc == TILEDB_OK);
1342 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
1343 REQUIRE(rc == TILEDB_OK);
1344
1345 // Read
1346 const void* v_r;
1347 tiledb_datatype_t v_type;
1348 uint32_t v_num;
1349 rc = tiledb_array_get_metadata(ctx_, array, "aaa", &v_type, &v_num, &v_r);
1350 CHECK(rc == TILEDB_OK);
1351 CHECK(v_type == TILEDB_CHAR);
1352 CHECK(v_num == 1);
1353 CHECK(v_r == nullptr);
1354 rc = tiledb_array_get_metadata(ctx_, array, "b", &v_type, &v_num, &v_r);
1355 CHECK(rc == TILEDB_OK);
1356 CHECK(v_type == TILEDB_INT32);
1357 CHECK(v_num == 1);
1358 CHECK(v_r == nullptr);
1359
1360 // Close array
1361 rc = tiledb_array_close(ctx_, array);
1362 REQUIRE(rc == TILEDB_OK);
1363 tiledb_array_free(&array);
1364 }
1365