From 0fd5f7d8fe4b8400a44e2b247a13a856fc28d500 Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Thu, 24 Aug 2023 12:05:37 -0500 Subject: [PATCH] Tests for tiledb_handle_load_enumerations_request Making these a separate PR that will be merged after the development branch of TileDB-Cloud-REST. If we included this in the same PR as adding the implementation we'd fail all the REST CI checks. I am open to suggestions on how to make this less terrible. --- test/CMakeLists.txt | 1 + test/src/unit-rest-enumerations.cc | 186 +++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 test/src/unit-rest-enumerations.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 92346d106e59..309b5b56aaee 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -261,6 +261,7 @@ endif() if (TILEDB_TESTS_ENABLE_REST) list(APPEND TILEDB_UNIT_TEST_SOURCES src/unit-capi-rest-dense_array.cc + src/unit-rest-enumerations.cc ) endif() diff --git a/test/src/unit-rest-enumerations.cc b/test/src/unit-rest-enumerations.cc new file mode 100644 index 000000000000..3f091cfb4f26 --- /dev/null +++ b/test/src/unit-rest-enumerations.cc @@ -0,0 +1,186 @@ +/** + * @file unit-rest-enumerations.cc + * + * @section LICENSE + * + * The MIT License + * + * @copyright Copyright (c) 2023 TileDB Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * Tests serialization of Enumerations via a REST server. + */ + +#include "test/support/tdb_catch.h" +#include "test/support/src/vfs_helpers.h" +#include "tiledb/sm/array_schema/array_schema.h" +#include "tiledb/sm/c_api/tiledb_struct_def.h" +#include "tiledb/sm/cpp_api/tiledb" +#include "tiledb/sm/cpp_api/tiledb_experimental" + +using namespace tiledb; + +struct RESTEnumerationFx { + RESTEnumerationFx(); + ~RESTEnumerationFx(); + + void create_array(const std::string& array_name); + void rm_array(); + + std::string bucket_; + std::string uri_; + Config cfg_; + Context ctx_; + VFS vfs_; +}; + +TEST_CASE_METHOD( + RESTEnumerationFx, + "Create array test", + "[rest][enumeration][create-array]") { + create_array("simple-array-create"); +} + +TEST_CASE_METHOD( + RESTEnumerationFx, + "Simple enumeration query", + "[rest][enumeration][simple-query]") { + create_array("simple-query"); + + Array array(ctx_, uri_, TILEDB_READ); + Subarray subarray(ctx_, array); + subarray.set_subarray({1, 5}); + + QueryCondition qc(ctx_); + qc.init("attr1", "wilma", 5, TILEDB_EQ); + + std::vector attr1_read(5); + std::vector attr2_read(5); + + Query query(ctx_, array); + query.set_subarray(subarray) + .set_condition(qc) + .set_data_buffer("attr1", attr1_read) + .set_data_buffer("attr2", attr2_read); + + REQUIRE(query.submit() == Query::Status::COMPLETE); + REQUIRE(attr1_read[1] == 1); + REQUIRE(attr1_read[3] == 1); +} + +TEST_CASE_METHOD( + RESTEnumerationFx, + "Get enumeration", + "[rest][enumeration][get-enumeration]") { + create_array("get-enumeration"); + + Array array(ctx_, uri_, TILEDB_READ); + auto enmr = ArrayExperimental::get_enumeration(ctx_, array, "an_enumeration"); + + std::vector expected = {"fred", "wilma", "barney", "pebbles"}; + REQUIRE(enmr.as_vector() == expected); +} + +Config& setup_config(Config& cfg) { + cfg["vfs.s3.endpoint_override"] = "localhost:9999"; + cfg["vfs.s3.scheme"] = "https"; + cfg["vfs.s3.use_virtual_addressing"] = "false"; + cfg["ssl.verify"] = "false"; + return cfg; +} + +RESTEnumerationFx::RESTEnumerationFx() + : bucket_("s3://enumeration-tests") + , ctx_(setup_config(cfg_)) + , vfs_(ctx_) { + if (!vfs_.is_bucket(bucket_)) { + vfs_.create_bucket(bucket_); + } +} + +RESTEnumerationFx::~RESTEnumerationFx() { + rm_array(); + if (vfs_.is_bucket(bucket_)) { + vfs_.remove_bucket(bucket_); + } +} + +void RESTEnumerationFx::create_array(const std::string& array_name) { + uri_ = "tiledb://unit/" + bucket_ + "/" + array_name; + + // Ensure that no array exists at uri_ + rm_array(); + + // Create a simple array for testing. This ends up with just five elements in + // the array. dim is an int32_t dimension, attr1 is an enumeration with string + // values and int32_t attribute values. attr2 is a float attribute. + // + // The array data is summarized as below, however, pay attention to the fact + // that attr1 is storing integral index values instead of the raw string data. + // + // dim = {1, 2, 3, 4, 5} + // attr1 = {"fred", "wilma", "barney", "wilma", "fred"} + // attr2 = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f} + ArraySchema schema(ctx_, TILEDB_DENSE); + + auto dim = Dimension::create(ctx_, "dim", {{-100, 100}}); + auto dom = Domain(ctx_); + dom.add_dimension(dim); + schema.set_domain(dom); + + // The list of string values in the attr1 enumeration + std::vector values = {"fred", "wilma", "barney", "pebbles"}; + auto enmr = Enumeration::create(ctx_, "an_enumeration", values); + ArraySchemaExperimental::add_enumeration(ctx_, schema, enmr); + + auto attr1 = Attribute::create(ctx_, "attr1"); + AttributeExperimental::set_enumeration_name(ctx_, attr1, "an_enumeration"); + schema.add_attribute(attr1); + + auto attr2 = Attribute::create(ctx_, "attr2"); + schema.add_attribute(attr2); + + Array::create(uri_, schema); + + // Attribute data + std::vector attr1_values = {0, 1, 2, 1, 0}; + std::vector attr2_values = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + + Array array(ctx_, uri_, TILEDB_WRITE); + Subarray subarray(ctx_, array); + subarray.set_subarray({1, 5}); + Query query(ctx_, array); + query.set_subarray(subarray) + .set_layout(TILEDB_ROW_MAJOR) + .set_data_buffer("attr1", attr1_values) + .set_data_buffer("attr2", attr2_values); + CHECK_NOTHROW(query.submit()); + query.finalize(); + array.close(); +} + +void RESTEnumerationFx::rm_array() { + auto obj = Object::object(ctx_, uri_); + if (obj.type() == Object::Type::Array) { + Array::delete_array(ctx_, uri_); + } +}