1 /**
2 * @file unit-cppapi-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/config/config.h"
38 #include "tiledb/sm/cpp_api/tiledb"
39 #include "tiledb/sm/enums/encryption_type.h"
40
41 #ifdef _WIN32
42 #include "tiledb/sm/filesystem/win.h"
43 #else
44 #include "tiledb/sm/filesystem/posix.h"
45 #endif
46
47 #include <catch.hpp>
48 #include <chrono>
49 #include <iostream>
50 #include <thread>
51
52 using namespace tiledb;
53 using namespace tiledb::test;
54
55 /* ********************************* */
56 /* STRUCT DEFINITION */
57 /* ********************************* */
58
59 struct CPPMetadataFx {
60 tiledb_ctx_t* ctx_;
61 tiledb_vfs_t* vfs_;
62 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
63 std::string temp_dir_;
64 std::string array_name_;
65 const char* ARRAY_NAME = "test_metadata";
66 tiledb_array_t* array_ = nullptr;
67 const char* key_ = "0123456789abcdeF0123456789abcdeF";
68 const uint32_t key_len_ =
69 (uint32_t)strlen("0123456789abcdeF0123456789abcdeF");
70 const tiledb_encryption_type_t enc_type_ = TILEDB_AES_256_GCM;
71
72 void create_default_array_1d();
73 void create_default_array_1d_with_key();
74
75 CPPMetadataFx();
76 ~CPPMetadataFx();
77 };
78
CPPMetadataFx()79 CPPMetadataFx::CPPMetadataFx()
80 : fs_vec_(vfs_test_get_fs_vec()) {
81 // Initialize vfs test
82 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
83
84 // Create temporary directory based on the supported filesystem
85 #ifdef _WIN32
86 SupportedFsLocal windows_fs;
87 temp_dir_ = windows_fs.file_prefix() + windows_fs.temp_dir();
88 #else
89 SupportedFsLocal posix_fs;
90 temp_dir_ = posix_fs.file_prefix() + posix_fs.temp_dir();
91 #endif
92
93 create_dir(temp_dir_, ctx_, vfs_);
94
95 array_name_ = temp_dir_ + ARRAY_NAME;
96 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_);
97 CHECK(rc == TILEDB_OK);
98 }
99
~CPPMetadataFx()100 CPPMetadataFx::~CPPMetadataFx() {
101 tiledb_array_free(&array_);
102 remove_dir(temp_dir_, ctx_, vfs_);
103 tiledb_ctx_free(&ctx_);
104 tiledb_vfs_free(&vfs_);
105 }
106
create_default_array_1d()107 void CPPMetadataFx::create_default_array_1d() {
108 uint64_t domain[] = {1, 10};
109 uint64_t tile_extent = 5;
110 create_array(
111 ctx_,
112 array_name_,
113 TILEDB_DENSE,
114 {"d"},
115 {TILEDB_UINT64},
116 {domain},
117 {&tile_extent},
118 {"a", "b", "c"},
119 {TILEDB_INT32, TILEDB_CHAR, TILEDB_FLOAT32},
120 {1, TILEDB_VAR_NUM, 2},
121 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1),
122 tiledb::test::Compressor(TILEDB_FILTER_ZSTD, -1),
123 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
124 TILEDB_ROW_MAJOR,
125 TILEDB_ROW_MAJOR,
126 2);
127 }
128
create_default_array_1d_with_key()129 void CPPMetadataFx::create_default_array_1d_with_key() {
130 uint64_t domain[] = {1, 10};
131 uint64_t tile_extent = 5;
132 create_array(
133 ctx_,
134 array_name_,
135 enc_type_,
136 key_,
137 key_len_,
138 TILEDB_DENSE,
139 {"d"},
140 {TILEDB_UINT64},
141 {domain},
142 {&tile_extent},
143 {"a", "b", "c"},
144 {TILEDB_INT32, TILEDB_CHAR, TILEDB_FLOAT32},
145 {1, TILEDB_VAR_NUM, 2},
146 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1),
147 tiledb::test::Compressor(TILEDB_FILTER_ZSTD, -1),
148 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
149 TILEDB_ROW_MAJOR,
150 TILEDB_ROW_MAJOR,
151 2);
152 }
153
154 /* ********************************* */
155 /* TESTS */
156 /* ********************************* */
157
158 TEST_CASE_METHOD(
159 CPPMetadataFx,
160 "C++ API: Metadata, basic errors",
161 "[cppapi][metadata][errors]") {
162 // Create default array
163 create_default_array_1d();
164
165 // Put metadata in an array opened for reads - error
166 Context ctx;
167 Array array(ctx, std::string(array_name_), TILEDB_READ);
168 int v = 5;
169 CHECK_THROWS(array.put_metadata("key", TILEDB_INT32, 1, &v));
170 array.close();
171
172 // Reopen array in WRITE mode
173 array.open(TILEDB_WRITE);
174
175 // Write value type ANY
176 CHECK_THROWS(array.put_metadata("key", TILEDB_ANY, 1, &v));
177
178 // Write a correct item
179 array.put_metadata("key", TILEDB_INT32, 1, &v);
180
181 // Close array
182 array.close();
183 }
184
185 TEST_CASE_METHOD(
186 CPPMetadataFx,
187 "C++ API: Metadata, write/read",
188 "[cppapi][metadata][read]") {
189 // Create default array
190 create_default_array_1d();
191
192 // Open array in write mode
193 Context ctx;
194 Array array(ctx, std::string(array_name_), TILEDB_WRITE);
195
196 // Write items
197 int32_t v = 5;
198 array.put_metadata("aaa", TILEDB_INT32, 1, &v);
199 float f[] = {1.1f, 1.2f};
200 array.put_metadata("bb", TILEDB_FLOAT32, 2, f);
201
202 // Write null value
203 array.put_metadata("zero_val", TILEDB_FLOAT32, 1, NULL);
204
205 // Close array
206 array.close();
207
208 // Open the array in read mode
209 array.open(TILEDB_READ);
210
211 // Read
212 const void* v_r;
213 tiledb_datatype_t v_type;
214 uint32_t v_num;
215 array.get_metadata("aaa", &v_type, &v_num, &v_r);
216 CHECK(v_type == TILEDB_INT32);
217 CHECK(v_num == 1);
218 CHECK(*((const int32_t*)v_r) == 5);
219
220 array.get_metadata("bb", &v_type, &v_num, &v_r);
221 CHECK(v_type == TILEDB_FLOAT32);
222 CHECK(v_num == 2);
223 CHECK(((const float*)v_r)[0] == 1.1f);
224 CHECK(((const float*)v_r)[1] == 1.2f);
225
226 array.get_metadata("zero_val", &v_type, &v_num, &v_r);
227 CHECK(v_type == TILEDB_FLOAT32);
228 CHECK(v_num == 1);
229 CHECK(v_r == nullptr);
230
231 array.get_metadata("foo", &v_type, &v_num, &v_r);
232 CHECK(v_r == nullptr);
233
234 uint64_t num = array.metadata_num();
235 CHECK(num == 3);
236
237 std::string key;
238 CHECK_THROWS(array.get_metadata_from_index(10, &key, &v_type, &v_num, &v_r));
239
240 array.get_metadata_from_index(1, &key, &v_type, &v_num, &v_r);
241 CHECK(v_type == TILEDB_FLOAT32);
242 CHECK(v_num == 2);
243 CHECK(((const float*)v_r)[0] == 1.1f);
244 CHECK(((const float*)v_r)[1] == 1.2f);
245 CHECK(key.size() == strlen("bb"));
246 CHECK(!strncmp(key.data(), "bb", strlen("bb")));
247
248 // idx 2 is 'zero_val'
249 array.get_metadata_from_index(2, &key, &v_type, &v_num, &v_r);
250 CHECK(v_type == TILEDB_FLOAT32);
251 CHECK(v_num == 1);
252 CHECK(v_r == nullptr);
253
254 // Check has_key
255 bool has_key;
256 v_type = (tiledb_datatype_t)std::numeric_limits<int32_t>::max();
257 has_key = array.has_metadata("bb", &v_type);
258 CHECK(has_key == true);
259 CHECK(v_type == TILEDB_FLOAT32);
260
261 // Check not has_key
262 v_type = (tiledb_datatype_t)std::numeric_limits<int32_t>::max();
263 has_key = array.has_metadata("non-existent-key", &v_type);
264 CHECK(has_key == false);
265 CHECK(v_type == (tiledb_datatype_t)std::numeric_limits<int32_t>::max());
266
267 // Close array
268 array.close();
269 }
270
271 TEST_CASE_METHOD(
272 CPPMetadataFx, "C++ API: Metadata, UTF-8", "[cppapi][metadata][utf-8]") {
273 // Create default array
274 create_default_array_1d();
275
276 // Open array in write mode
277 Context ctx;
278 Array array(ctx, std::string(array_name_), TILEDB_WRITE);
279
280 // Write UTF-8 (≥ holds 3 bytes)
281 int32_t v = 5;
282 array.put_metadata("≥", TILEDB_INT32, 1, &v);
283
284 // Close array
285 array.close();
286
287 // Open the array in read mode
288 array.open(TILEDB_READ);
289
290 // Read
291 const void* v_r;
292 tiledb_datatype_t v_type;
293 uint32_t v_num;
294 array.get_metadata("≥", &v_type, &v_num, &v_r);
295 CHECK(v_type == TILEDB_INT32);
296 CHECK(v_num == 1);
297 CHECK(*((const int32_t*)v_r) == 5);
298
299 std::string key;
300 array.get_metadata_from_index(0, &key, &v_type, &v_num, &v_r);
301 CHECK(v_type == TILEDB_INT32);
302 CHECK(v_num == 1);
303 CHECK(*((const int32_t*)v_r) == 5);
304 CHECK(key.size() == strlen("≥"));
305 CHECK(!strncmp(key.data(), "≥", strlen("≥")));
306
307 // Close array
308 array.close();
309 }
310
311 TEST_CASE_METHOD(
312 CPPMetadataFx, "C++ API: Metadata, delete", "[cppapi][metadata][delete]") {
313 // Create default array
314 create_default_array_1d();
315
316 // Create and open array in write mode
317 Context ctx;
318 Array array(ctx, std::string(array_name_), TILEDB_WRITE, 1);
319
320 // Write items
321 int32_t v = 5;
322 array.put_metadata("aaa", TILEDB_INT32, 1, &v);
323 float f[] = {1.1f, 1.2f};
324 array.put_metadata("bb", TILEDB_FLOAT32, 2, f);
325
326 // Close array
327 array.close();
328
329 // Delete an item that exists and one that does not exist
330 array.open(TILEDB_WRITE, 2);
331 array.delete_metadata("aaa");
332 array.delete_metadata("foo");
333 array.close();
334
335 // Open the array in read mode
336 array.open(TILEDB_READ);
337
338 // Read
339 const void* v_r;
340 tiledb_datatype_t v_type;
341 uint32_t v_num;
342 array.get_metadata("aaa", &v_type, &v_num, &v_r);
343 CHECK(v_r == nullptr);
344 array.get_metadata("bb", &v_type, &v_num, &v_r);
345 CHECK(v_type == TILEDB_FLOAT32);
346 CHECK(v_num == 2);
347 CHECK(((const float*)v_r)[0] == 1.1f);
348 CHECK(((const float*)v_r)[1] == 1.2f);
349
350 array.get_metadata("foo", &v_type, &v_num, &v_r);
351 CHECK(v_r == nullptr);
352
353 uint64_t num = array.metadata_num();
354 CHECK(num == 1);
355
356 std::string key;
357 array.get_metadata_from_index(0, &key, &v_type, &v_num, &v_r);
358 CHECK(v_type == TILEDB_FLOAT32);
359 CHECK(v_num == 2);
360 CHECK(((const float*)v_r)[0] == 1.1f);
361 CHECK(((const float*)v_r)[1] == 1.2f);
362 CHECK(key.size() == strlen("bb"));
363 CHECK(!strncmp(key.data(), "bb", strlen("bb")));
364
365 // Close array
366 array.close();
367 }
368
369 TEST_CASE_METHOD(
370 CPPMetadataFx,
371 "C++ API: Metadata, multiple metadata and consolidate",
372 "[cppapi][metadata][multiple][consolidation]") {
373 // Create default array
374 create_default_array_1d();
375
376 // Create and open array in write mode
377 Context ctx;
378 Array array(ctx, array_name_, TILEDB_WRITE);
379
380 // Write items
381 int32_t v = 5;
382 array.put_metadata("aaa", TILEDB_INT32, 1, &v);
383 float f[] = {1.1f, 1.2f};
384 array.put_metadata("bb", TILEDB_FLOAT32, 2, f);
385
386 // Close array
387 array.close();
388
389 // Prevent array metadata filename/timestamp conflicts
390 std::this_thread::sleep_for(std::chrono::milliseconds(1));
391
392 // Update
393 array.open(TILEDB_WRITE);
394 array.delete_metadata("aaa");
395 v = 10;
396 array.put_metadata("cccc", TILEDB_INT32, 1, &v);
397 array.close();
398
399 // Open the array in read mode
400 array.open(TILEDB_READ);
401
402 // Read
403 const void* v_r;
404 tiledb_datatype_t v_type;
405 uint32_t v_num;
406 array.get_metadata("aaa", &v_type, &v_num, &v_r);
407 CHECK(v_r == nullptr);
408
409 array.get_metadata("bb", &v_type, &v_num, &v_r);
410 CHECK(v_type == TILEDB_FLOAT32);
411 CHECK(v_num == 2);
412 CHECK(((const float*)v_r)[0] == 1.1f);
413 CHECK(((const float*)v_r)[1] == 1.2f);
414
415 array.get_metadata("cccc", &v_type, &v_num, &v_r);
416 CHECK(v_type == TILEDB_INT32);
417 CHECK(v_num == 1);
418 CHECK(*((const int32_t*)v_r) == 10);
419
420 uint64_t num = array.metadata_num();
421 CHECK(num == 2);
422
423 std::string key;
424 array.get_metadata_from_index(0, &key, &v_type, &v_num, &v_r);
425 CHECK(v_type == TILEDB_FLOAT32);
426 CHECK(v_num == 2);
427 CHECK(((const float*)v_r)[0] == 1.1f);
428 CHECK(((const float*)v_r)[1] == 1.2f);
429 CHECK(key.size() == strlen("bb"));
430 CHECK(!strncmp(key.data(), "bb", strlen("bb")));
431
432 // Close array
433 array.close();
434
435 // Consolidate
436 Config consolidation_cfg;
437 consolidation_cfg["sm.consolidation.mode"] = "array_meta";
438 Array::consolidate(ctx, array_name_, &consolidation_cfg);
439
440 // Open the array in read mode
441 array.open(TILEDB_READ);
442
443 num = array.metadata_num();
444 CHECK(num == 2);
445
446 // Close array
447 array.close();
448
449 // Write once more
450 array.open(TILEDB_WRITE);
451
452 // Write items
453 v = 50;
454 array.put_metadata("d", TILEDB_INT32, 1, &v);
455
456 // Close array
457 array.close();
458
459 // Consolidate again
460 Array::consolidate(ctx, array_name_, &consolidation_cfg);
461
462 // Open the array in read mode
463 array.open(TILEDB_READ);
464
465 num = array.metadata_num();
466 CHECK(num == 3);
467
468 array.get_metadata("cccc", &v_type, &v_num, &v_r);
469 CHECK(v_type == TILEDB_INT32);
470 CHECK(v_num == 1);
471 CHECK(*((const int32_t*)v_r) == 10);
472
473 array.get_metadata("d", &v_type, &v_num, &v_r);
474 CHECK(v_type == TILEDB_INT32);
475 CHECK(v_num == 1);
476 CHECK(*((const int32_t*)v_r) == 50);
477
478 // Close array
479 array.close();
480 }
481
482 TEST_CASE_METHOD(
483 CPPMetadataFx, "C++ Metadata, open at", "[cppapi][metadata][open-at]") {
484 // Create default array
485 create_default_array_1d();
486
487 // Create and open array in write mode
488 Context ctx;
489 Array array(ctx, array_name_, TILEDB_WRITE);
490
491 // Write items
492 int32_t v = 5;
493 array.put_metadata("aaa", TILEDB_INT32, 1, &v);
494 float f[] = {1.1f, 1.2f};
495 array.put_metadata("bb", TILEDB_FLOAT32, 2, f);
496
497 // Close array
498 array.close();
499
500 // Prevent array metadata filename/timestamp conflicts
501 auto timestamp = tiledb::sm::utils::time::timestamp_now_ms();
502 std::this_thread::sleep_for(std::chrono::milliseconds(1));
503
504 // Update
505 array.open(TILEDB_WRITE);
506 array.delete_metadata("aaa");
507 array.close();
508
509 // Open the array in read mode at a timestamp
510 array.set_open_timestamp_end(timestamp);
511 array.open(TILEDB_READ);
512
513 // Read
514 const void* v_r;
515 tiledb_datatype_t v_type;
516 uint32_t v_num;
517 array.get_metadata("aaa", &v_type, &v_num, &v_r);
518 CHECK(v_type == TILEDB_INT32);
519 CHECK(v_num == 1);
520 CHECK(*((const int32_t*)v_r) == 5);
521
522 uint64_t num = array.metadata_num();
523 CHECK(num == 2);
524
525 // Close array
526 array.close();
527 }
528
529 TEST_CASE_METHOD(
530 CPPMetadataFx, "C++ Metadata, reopen", "[cppapi][metadata][reopen]") {
531 // Create default array
532 create_default_array_1d();
533
534 // Open array in write mode
535 Context ctx;
536 Array array(ctx, array_name_, TILEDB_WRITE);
537
538 // Write items
539 int32_t v = 5;
540 array.put_metadata("aaa", TILEDB_INT32, 1, &v);
541 float f[] = {1.1f, 1.2f};
542 array.put_metadata("bb", TILEDB_FLOAT32, 2, f);
543
544 // Close array
545 array.close();
546
547 // Prevent array metadata filename/timestamp conflicts
548 auto timestamp = tiledb::sm::utils::time::timestamp_now_ms();
549 std::this_thread::sleep_for(std::chrono::milliseconds(1));
550
551 // Update
552 array.open(TILEDB_WRITE);
553 array.delete_metadata("aaa");
554 array.close();
555
556 // Open the array in read mode at a timestamp
557 array.set_open_timestamp_end(timestamp);
558 array.open(TILEDB_READ);
559
560 // Read
561 const void* v_r;
562 tiledb_datatype_t v_type;
563 uint32_t v_num;
564 array.get_metadata("aaa", &v_type, &v_num, &v_r);
565 CHECK(v_type == TILEDB_INT32);
566 CHECK(v_num == 1);
567 CHECK(*((const int32_t*)v_r) == 5);
568
569 uint64_t num = array.metadata_num();
570 CHECK(num == 2);
571
572 // Reopen
573 array.reopen();
574
575 // Read
576 array.get_metadata("aaa", &v_type, &v_num, &v_r);
577 CHECK(v_r == nullptr);
578
579 num = array.metadata_num();
580 CHECK(num == 1);
581
582 // Close array
583 array.close();
584 }
585
586 TEST_CASE_METHOD(
587 CPPMetadataFx,
588 "C++ Metadata, encryption",
589 "[cppapi][metadata][encryption]") {
590 // Create default array
591 create_default_array_1d_with_key();
592
593 // Create and open array in write mode
594 tiledb::Config cfg;
595 std::string enc_type_str =
596 encryption_type_str((tiledb::sm::EncryptionType)enc_type_);
597 cfg["sm.encryption_type"] = enc_type_str.c_str();
598 cfg["sm.encryption_key"] = key_;
599 Context ctx(cfg);
600 Array array(ctx, array_name_, TILEDB_WRITE);
601
602 // Write items
603 int32_t v = 5;
604 array.put_metadata("aaa", TILEDB_INT32, 1, &v);
605 float f[] = {1.1f, 1.2f};
606 array.put_metadata("bb", TILEDB_FLOAT32, 2, f);
607
608 // Close array
609 array.close();
610
611 // Prevent array metadata filename/timestamp conflicts
612 std::this_thread::sleep_for(std::chrono::milliseconds(1));
613
614 // Update
615 array.open(TILEDB_WRITE);
616 array.delete_metadata("aaa");
617 v = 10;
618 array.put_metadata("cccc", TILEDB_INT32, 1, &v);
619 array.close();
620
621 // Open the array in read mode
622 array.open(TILEDB_READ);
623
624 // Read
625 const void* v_r;
626 tiledb_datatype_t v_type;
627 uint32_t v_num;
628 array.get_metadata("aaa", &v_type, &v_num, &v_r);
629 CHECK(v_r == nullptr);
630
631 array.get_metadata("bb", &v_type, &v_num, &v_r);
632 CHECK(v_type == TILEDB_FLOAT32);
633 CHECK(v_num == 2);
634 CHECK(((const float*)v_r)[0] == 1.1f);
635 CHECK(((const float*)v_r)[1] == 1.2f);
636
637 array.get_metadata("cccc", &v_type, &v_num, &v_r);
638 CHECK(v_type == TILEDB_INT32);
639 CHECK(v_num == 1);
640 CHECK(*((const int32_t*)v_r) == 10);
641
642 uint64_t num = array.metadata_num();
643 CHECK(num == 2);
644
645 std::string key;
646 array.get_metadata_from_index(0, &key, &v_type, &v_num, &v_r);
647 CHECK(v_type == TILEDB_FLOAT32);
648 CHECK(v_num == 2);
649 CHECK(((const float*)v_r)[0] == 1.1f);
650 CHECK(((const float*)v_r)[1] == 1.2f);
651 CHECK(key.size() == strlen("bb"));
652 CHECK(!strncmp(key.data(), "bb", strlen("bb")));
653
654 // Close array
655 array.close();
656
657 // Consolidate without key - error
658 Config consolidate_without_key;
659 Context ctx_without_key(consolidate_without_key);
660 CHECK_THROWS(Array::consolidate(
661 ctx_without_key, array_name_, &consolidate_without_key));
662
663 // Consolidate with key - ok
664 Config consolidation_cfg;
665 consolidation_cfg["sm.consolidation.mode"] = "array_meta";
666 Array::consolidate(ctx, array_name_, &consolidation_cfg);
667
668 // Open the array in read mode
669 array.open(TILEDB_READ);
670
671 num = array.metadata_num();
672 CHECK(num == 2);
673
674 // Close array
675 array.close();
676
677 // Write once more
678 array.open(TILEDB_WRITE);
679
680 // Write items
681 v = 50;
682 array.put_metadata("d", TILEDB_INT32, 1, &v);
683
684 // Close array
685 array.close();
686
687 // Consolidate again
688 Array::consolidate_metadata(ctx, array_name_, &consolidation_cfg);
689
690 // Open the array in read mode
691 array.open(TILEDB_READ);
692
693 num = array.metadata_num();
694 CHECK(num == 3);
695
696 array.get_metadata("cccc", &v_type, &v_num, &v_r);
697 CHECK(v_type == TILEDB_INT32);
698 CHECK(v_num == 1);
699 CHECK(*((const int32_t*)v_r) == 10);
700
701 array.get_metadata("d", &v_type, &v_num, &v_r);
702 CHECK(v_type == TILEDB_INT32);
703 CHECK(v_num == 1);
704 CHECK(*((const int32_t*)v_r) == 50);
705
706 // Close array
707 array.close();
708 }
709