diff --git a/.circleci/config.yml b/.circleci/config.yml index 8919e00a26..2c757e9305 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -529,7 +529,7 @@ jobs: - deploy-maven-jni-snapshot-unix -# - deploy-clib-snapshot-unix + - deploy-clib-snapshot-unix # - test-clib-assembly-linux: # target-arch: arm64 @@ -551,7 +551,7 @@ jobs: - deploy-maven-jni-snapshot-unix -# - deploy-clib-snapshot-unix + - deploy-clib-snapshot-unix # - test-clib-assembly-linux: # target-arch: x86_64 @@ -575,7 +575,7 @@ jobs: # - run: brew install cmake -# - deploy-clib-snapshot-unix + - deploy-clib-snapshot-unix # - test-clib-assembly-mac: # target-arch: arm64 @@ -599,7 +599,7 @@ jobs: # - run: brew install cmake -# - deploy-clib-snapshot-unix + - deploy-clib-snapshot-unix # - test-clib-assembly-mac: # target-arch: x86_64 @@ -620,8 +620,8 @@ jobs: - run: .circleci\windows\java\deploy_snapshot.bat -# - run: .circleci\windows\clib\deploy_snapshot.bat -# - run: .circleci\windows\clib\test_assembly.bat + - run: .circleci\windows\clib\deploy_snapshot.bat + - run: .circleci\windows\clib\test_assembly.bat # - run: .circleci\windows\cpp\deploy_snapshot.bat # - run: .circleci\windows\cpp\test_assembly.bat @@ -728,7 +728,7 @@ jobs: bazel-arch: arm64 - deploy-pip-release-unix - deploy-maven-jni-release-unix -# - deploy-clib-release-unix + - deploy-clib-release-unix # - deploy-cpp-release-unix # - install-libicu-linux @@ -742,7 +742,7 @@ jobs: bazel-arch: amd64 - deploy-pip-release-unix - deploy-maven-jni-release-unix -# - deploy-clib-release-unix + - deploy-clib-release-unix # - deploy-cpp-release-unix # - install-libicu-linux @@ -756,7 +756,7 @@ jobs: bazel-arch: arm64 - deploy-pip-release-unix - deploy-maven-jni-release-unix -# - deploy-clib-release-unix + - deploy-clib-release-unix # - deploy-cpp-release-unix # - deploy-dotnet-runtime-release-unix @@ -769,7 +769,7 @@ jobs: bazel-arch: amd64 - deploy-pip-release-unix - deploy-maven-jni-release-unix -# - deploy-clib-release-unix + - deploy-clib-release-unix # - deploy-cpp-release-unix # - deploy-dotnet-runtime-release-unix @@ -781,7 +781,7 @@ jobs: - run: .circleci\windows\prepare.bat - run: .circleci\windows\python\deploy_release.bat - run: .circleci\windows\java\deploy_release.bat -# - run: .circleci\windows\clib\deploy_release.bat + - run: .circleci\windows\clib\deploy_release.bat # - run: .circleci\windows\cpp\deploy_release.bat # - run: .circleci\windows\csharp\deploy_release.bat diff --git a/.factory/automation.yml b/.factory/automation.yml index 4bc8525d54..3f11b883e0 100644 --- a/.factory/automation.yml +++ b/.factory/automation.yml @@ -145,20 +145,20 @@ build: # tool/test/stop-cluster-servers.sh # exit $TEST_SUCCESS -# test-c-integration: -# image: typedb-ubuntu-20.04 # Ubuntu 20.04 has GLIBC version 2.31 (2020) which we should verify to compile against -# dependencies: -# - build -# command: | -# export ARTIFACT_USERNAME=$REPO_TYPEDB_USERNAME -# export ARTIFACT_PASSWORD=$REPO_TYPEDB_PASSWORD -# bazel run @typedb_dependencies//tool/bazelinstall:remote_cache_setup.sh -# bazel run @typedb_dependencies//distribution/artifact:create-netrc -# tool/test/start-community-server.sh && -# bazel test //c/tests/integration:test-driver --test_output=errors && -# export TEST_SUCCESS=0 || export TEST_SUCCESS=1 -# tool/test/stop-community-server.sh -# exit $TEST_SUCCESS + test-c-integration: + image: typedb-ubuntu-20.04 # Ubuntu 20.04 has GLIBC version 2.31 (2020) which we should verify to compile against + dependencies: + - build + command: | + export ARTIFACT_USERNAME=$REPO_TYPEDB_USERNAME + export ARTIFACT_PASSWORD=$REPO_TYPEDB_PASSWORD + bazel run @typedb_dependencies//tool/bazelinstall:remote_cache_setup.sh + bazel run @typedb_dependencies//distribution/artifact:create-netrc + tool/test/start-community-server.sh && + bazel test //c/tests/integration:test-driver --test_output=errors && + export TEST_SUCCESS=0 || export TEST_SUCCESS=1 + tool/test/stop-community-server.sh + exit $TEST_SUCCESS test-java-integration: image: typedb-ubuntu-22.04 diff --git a/RELEASE_TEMPLATE.md b/RELEASE_TEMPLATE.md index a2aec9d5f7..ff53ad0965 100644 --- a/RELEASE_TEMPLATE.md +++ b/RELEASE_TEMPLATE.md @@ -57,4 +57,8 @@ Documentation: https://typedb.com/docs/drivers/ npm install typedb-driver-http@{version} ``` +### C driver + +Compiled distributions comprising headers and shared libraries available at: https://cloudsmith.io/~typedb/repos/public-release/packages/?q=name:^typedb-driver-clib+version:{version} + { release notes } diff --git a/c/README.md b/c/README.md index efe4d17554..465adba67c 100644 --- a/c/README.md +++ b/c/README.md @@ -1,6 +1,7 @@ # TypeDB C Driver The TypeDB C driver provides C bindings to the rust driver. It also serves as the base on which the other wrapper drivers are built. +It is not very ergonomic to be used directly as a C driver. That is future work. ## Usage The driver is distributed as an archive containing the headers & a shared library. @@ -22,16 +23,19 @@ Code examples can be found in the [integration tests](https://github.com/typedb/ Functions parameters & return values are either primitives or pointers to opaque structs, e.g.: ```c -Driver *driver_open_core(const char *address); +struct TypeDBDriver *driver_open(const char *address, + const struct Credentials *credentials, + const struct DriverOptions *driver_options); ``` These pointers are then used for further operations: ```c char* dbName = "hello"; - Driver *driver = driver_open_core("127.0.0.1:1729"); - DatabaseManager* databaseManager = database_manager_new(driver); - databases_create(databaseManager, dbName); - Database* database = databases_get(databaseManager, dbName); + DriverOptions* options = driver_options_new(false, NULL);;; + Credentials* creds = credentials_new(username, password); + TypeDBDriver* driver = driver_open(address, creds, options); + databases_create(driver, dbName); + Database* database = databases_get(driver, dbName); char* gotName = database_name(database); assert(0 == strcmp(gotName, dbName)); ... @@ -46,7 +50,6 @@ Types which have `*_close` methods will be freed on close. ... string_free(gotName); database_close(database); - database_manager_drop(databaseManager); driver_close(connection); ``` @@ -68,7 +71,7 @@ if (check_error()) { Iterators can be forwarded with the `*_iterator_next` method, which returns `NULL` when the end has been reached. ```c - DatabaseIterator* it = databases_all(databaseManager); + DatabaseIterator* it = databases_all(driver); Database* database = NULL; while (NULL != (database = database_iterator_next(it))) { ... diff --git a/c/tests/assembly/test.c b/c/tests/assembly/test.c index 09d74724d8..8468a7eba5 100644 --- a/c/tests/assembly/test.c +++ b/c/tests/assembly/test.c @@ -23,6 +23,8 @@ #include const char* TYPEDB_CORE_ADDRESS = "127.0.0.1:1729"; +const char* TYPEDB_CORE_USERNAME = "admin"; +const char* TYPEDB_CORE_PASSWORD = "password"; const char* DRIVER_LANG = "c"; @@ -40,25 +42,34 @@ bool check_error_may_print(const char* filename, int lineno) { } #define FAILED() check_error_may_print(__FILE__, __LINE__) +TypeDBDriver* driver_open_for_tests(const char* address, const char* username, const char* password) { + DriverOptions* options = NULL; + Credentials* creds = credentials_new(username, password); + if (check_error_may_print(__FILE__, __LINE__)) goto cleanup; + options = driver_options_new(false, NULL);; + if (check_error_may_print(__FILE__, __LINE__)) goto cleanup; + TypeDBDriver* driver = driver_open_with_description(address, creds, options, DRIVER_LANG); +cleanup: + driver_options_drop(options); + credentials_drop(creds); + + return driver; +} int main() { const char databaseName[] = "test_assembly_clib"; - Connection* connection = NULL; - DatabaseManager* databaseManager = NULL; + TypeDBDriver* driver = NULL; bool success = false; - connection = driver_open_core(TYPEDB_CORE_ADDRESS, DRIVER_LANG); - if (FAILED()) goto cleanup; - - databaseManager = database_manager_new(connection); + driver = driver_open_for_tests(TYPEDB_CORE_ADDRESS, TYPEDB_CORE_USERNAME, TYPEDB_CORE_PASSWORD); if (FAILED()) goto cleanup; - databases_create(databaseManager, databaseName); + databases_create(driver, databaseName); if (FAILED()) goto cleanup; - if (!databases_contains(databaseManager, databaseName)) { + if (!databases_contains(driver, databaseName)) { fprintf(stderr, "databases_contains(\'%s\') failed\n", databaseName); goto cleanup; } @@ -66,8 +77,7 @@ int main() { success = true; cleanup: check_error_may_print(__FILE__, __LINE__); - database_manager_drop(databaseManager); - driver_close(connection); + driver_close(driver); printf("Success: %s\n", success ? "true" : "false"); return success ? 0 : 1; diff --git a/c/tests/integration/common.c b/c/tests/integration/common.c index bb6d163200..785cd4f17b 100644 --- a/c/tests/integration/common.c +++ b/c/tests/integration/common.c @@ -23,6 +23,8 @@ #include "common.h" const char* TYPEDB_CORE_ADDRESS = "127.0.0.1:1729"; +const char* TYPEDB_CORE_USERNAME = "admin"; +const char* TYPEDB_CORE_PASSWORD = "password"; const char* DRIVER_LANG = "c"; bool check_error_may_print(const char* filename, int lineno) { @@ -38,9 +40,27 @@ bool check_error_may_print(const char* filename, int lineno) { } else return false; } -void delete_database_if_exists(DatabaseManager* databaseManager, const char* name) { - if (NULL != databaseManager && databases_contains(databaseManager, name)) { - Database* database = databases_get(databaseManager, name); - database_delete(database); +void delete_database_if_exists(TypeDBDriver* driver, const char* name) { + if (driver == NULL) return; + bool contains = databases_contains(driver, name); + if (check_error_may_print(__FILE__, __LINE__)) return; + if (contains) { + const Database* db = databases_get(driver, name); + if (check_error_may_print(__FILE__, __LINE__)) return; + database_delete(db); } } + +TypeDBDriver* driver_open_for_tests(const char* address, const char* username, const char* password) { + DriverOptions* options = NULL; + Credentials* creds = credentials_new(username, password); + if (check_error_may_print(__FILE__, __LINE__)) goto cleanup; + options = driver_options_new(false, NULL);; + if (check_error_may_print(__FILE__, __LINE__)) goto cleanup; + TypeDBDriver* driver = driver_open_with_description(address, creds, options, DRIVER_LANG); +cleanup: + driver_options_drop(options); + credentials_drop(creds); + + return driver; +} diff --git a/c/tests/integration/common.h b/c/tests/integration/common.h index 4d3b2159f7..135863cc70 100644 --- a/c/tests/integration/common.h +++ b/c/tests/integration/common.h @@ -18,7 +18,11 @@ */ extern const char* TYPEDB_CORE_ADDRESS; +extern const char* TYPEDB_CORE_USERNAME; +extern const char* TYPEDB_CORE_PASSWORD; bool check_error_may_print(const char* filename, int lineno); -void delete_database_if_exists(DatabaseManager* databaseManager, const char* name); +TypeDBDriver* driver_open_for_tests(const char* address, const char* username, const char* password); + +void delete_database_if_exists(TypeDBDriver* driver, const char* name); diff --git a/c/tests/integration/driver_test.c b/c/tests/integration/driver_test.c deleted file mode 100644 index 2efd963d02..0000000000 --- a/c/tests/integration/driver_test.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include - -#include "c/typedb_driver.h" -#include "common.h" - -#define FAILED() check_error_may_print(__FILE__, __LINE__) - -bool test_database_management() { - const char databaseName[] = "test_database_management"; - - Driver* driver = NULL; - DatabaseManager* databaseManager = NULL; - - bool success = false; - - driver = driver_open_core(TYPEDB_CORE_ADDRESS, DRIVER_LANG); - if (FAILED()) goto cleanup; - - databaseManager = database_manager_new(driver); - if (FAILED()) goto cleanup; - - delete_database_if_exists(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - databases_create(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - if (!databases_contains(databaseManager, databaseName)) { - fprintf(stderr, "databases_contains(\'%s\') failed\n", databaseName); - goto cleanup; - } - - bool foundDB = false; - DatabaseIterator* it = databases_all(databaseManager); - Database* database = NULL; - while (NULL != (database = database_iterator_next(it))) { - char* name = database_get_name(database); - foundDB = foundDB || (0 == strcmp(databaseName, name)); - string_free(name); - database_close(database); - } - database_iterator_drop(it); - - if (!foundDB) { - fprintf(stderr, "Did not find database \'%s\' in list of databases\n", databaseName); - goto cleanup; - } - - success = true; -cleanup: - delete_database_if_exists(databaseManager, databaseName); - check_error_may_print(__FILE__, __LINE__); - database_manager_drop(databaseManager); - driver_close(connection); - return success; -} - -bool test_query_schema() { - const char databaseName[] = "test_query_schema"; - - Connection* connection = NULL; - DatabaseManager* databaseManager = NULL; - Session* session = NULL; - Transaction* transaction = NULL; - Options* opts = NULL; - - bool success = false; - - // Set up connection & database - connection = driver_open_core(TYPEDB_CORE_ADDRESS, DRIVER_LANG); - if (FAILED()) goto cleanup; - - databaseManager = database_manager_new(connection); - if (FAILED()) goto cleanup; - - delete_database_if_exists(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - databases_create(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - opts = options_new(); - if (FAILED()) goto cleanup; - - // test schema queries - { - session = session_new(databaseManager, databaseName, Schema, opts); - if (FAILED()) goto cleanup; - - transaction = transaction_new(session, Write, opts); - if (FAILED()) goto cleanup; - - void_promise_resolve(query_define(transaction, "define name sub attribute, value string;", opts)); - if (FAILED()) goto cleanup; - - ConceptMapIterator* it = query_get(transaction, "match $t sub thing; get;", opts); - ConceptMap* conceptMap; - bool foundName = false; - while (NULL != (conceptMap = concept_map_iterator_next(it))) { - Concept* concept = concept_map_get(conceptMap, "t"); - char* label = thing_type_get_label(concept); - foundName = foundName || (0 == strcmp(label, "name")); - string_free(label); - concept_drop(concept); - concept_map_drop(conceptMap); - } - concept_map_iterator_drop(it); - - void_promise_resolve(transaction_commit(transaction)); - transaction = NULL; - - if (!foundName) { - fprintf(stderr, "Did not find type \'name\' in query result.\n"); - goto cleanup; - } - } - success = true; - -cleanup: - transaction_close(transaction); - session_close(session); - options_drop(opts); - - delete_database_if_exists(databaseManager, databaseName); - check_error_may_print(__FILE__, __LINE__); - database_manager_drop(databaseManager); - driver_close(connection); - return success; -} - -bool test_query_data() { - const char databaseName[] = "test_query_data"; - - Connection* connection = NULL; - DatabaseManager* databaseManager = NULL; - Session* session = NULL; - Transaction* transaction = NULL; - Options* opts = NULL; - - bool success = false; - - // Set up connection & database - connection = driver_open_core(TYPEDB_CORE_ADDRESS, DRIVER_LANG); - if (FAILED()) goto cleanup; - - databaseManager = database_manager_new(connection); - if (FAILED()) goto cleanup; - - delete_database_if_exists(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - databases_create(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - opts = options_new(); - if (FAILED()) goto cleanup; - - // Set up schema - { - session = session_new(databaseManager, databaseName, Schema, opts); - if (FAILED()) goto cleanup; - - transaction = transaction_new(session, Write, opts); - if (FAILED()) goto cleanup; - - void_promise_resolve(query_define(transaction, "define name sub attribute, value string;", opts)); - if (FAILED()) goto cleanup; - - void_promise_resolve(transaction_commit(transaction)); - transaction = NULL; - - session_close(session); - session = NULL; - } - - { - session = session_new(databaseManager, databaseName, Data, opts); - if (FAILED()) goto cleanup; - - transaction = transaction_new(session, Write, opts); - if (FAILED()) goto cleanup; - - ConceptMapIterator* insertResult = query_insert(transaction, "insert $n \"John\" isa name;", opts); - if (FAILED()) goto cleanup; - else concept_map_iterator_drop(insertResult); - - ConceptMapIterator* it = query_get(transaction, "match $n isa name; get;", opts); - ConceptMap* conceptMap; - bool foundJohn = false; - while (NULL != (conceptMap = concept_map_iterator_next(it))) { - Concept* concept = concept_map_get(conceptMap, "n"); - Concept* asValue = attribute_get_value(concept); - char* attr = value_get_string(asValue); - foundJohn = foundJohn || (0 == strcmp(attr, "John")); - string_free(attr); - concept_drop(asValue); - concept_drop(concept); - concept_map_drop(conceptMap); - } - concept_map_iterator_drop(it); - - void_promise_resolve(transaction_commit(transaction)); - transaction = NULL; - - if (!foundJohn) { - fprintf(stderr, "Did not find inserted name \'John\' in query result.\n"); - goto cleanup; - } - } - - success = true; - -cleanup: - transaction_close(transaction); - session_close(session); - options_drop(opts); - - delete_database_if_exists(databaseManager, databaseName); - check_error_may_print(__FILE__, __LINE__); - database_manager_drop(databaseManager); - driver_close(connection); - return success; -} - -bool test_concept_api_schema() { - const char databaseName[] = "test_concept_api"; - - Connection* connection = NULL; - DatabaseManager* databaseManager = NULL; - Session* session = NULL; - Transaction* transaction = NULL; - Options* opts = NULL; - - bool success = false; - - connection = driver_open_core(TYPEDB_CORE_ADDRESS, DRIVER_LANG); - if (FAILED()) goto cleanup; - - databaseManager = database_manager_new(connection); - if (FAILED()) goto cleanup; - - delete_database_if_exists(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - databases_create(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - opts = options_new(); - if (FAILED()) goto cleanup; - - // test schema api - { - session = session_new(databaseManager, databaseName, Schema, opts); - if (FAILED()) goto cleanup; - - transaction = transaction_new(session, Write, opts); - if (FAILED()) goto cleanup; - { - Concept* definedNameType = - concept_promise_resolve(concepts_put_attribute_type(transaction, "name", String)); - if (FAILED()) goto cleanup; - else concept_drop(definedNameType); - } - - { - ConceptIterator* it = NULL; - Concept* nameType = NULL; - Concept* rootAttributeType = NULL; - bool foundName = false; - if (NULL != (nameType = concept_promise_resolve(concepts_get_attribute_type(transaction, "name"))) && - NULL != (rootAttributeType = concepts_get_root_attribute_type()) && - NULL != (it = (attribute_type_get_subtypes(transaction, rootAttributeType, Transitive)))) { - Concept* concept; - while (NULL != (concept = concept_iterator_next(it))) { - char* label = thing_type_get_label(concept); - foundName = foundName || (0 == strcmp(label, "name")); - string_free(label); - concept_drop(concept); - } - } - concept_iterator_drop(it); - concept_drop(rootAttributeType); - concept_drop(nameType); - - void_promise_resolve(transaction_commit(transaction)); - transaction = NULL; - if (!foundName) { - fprintf(stderr, "Did not find type \'name\' in subtypes of attribute.\n"); - goto cleanup; - } - } - } - - success = true; - -cleanup: - transaction_close(transaction); - session_close(session); - options_drop(opts); - - delete_database_if_exists(databaseManager, databaseName); - check_error_may_print(__FILE__, __LINE__); - database_manager_drop(databaseManager); - driver_close(connection); - return success; -} - -bool test_concept_api_data() { - const char databaseName[] = "test_concept_api"; - - Connection* connection = NULL; - DatabaseManager* databaseManager = NULL; - Session* session = NULL; - Transaction* transaction = NULL; - Options* opts = NULL; - - Concept* nameType = NULL; - - bool success = false; - - connection = driver_open_core(TYPEDB_CORE_ADDRESS, DRIVER_LANG); - if (FAILED()) goto cleanup; - - databaseManager = database_manager_new(connection); - if (FAILED()) goto cleanup; - - delete_database_if_exists(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - databases_create(databaseManager, databaseName); - if (FAILED()) goto cleanup; - - opts = options_new(); - if (FAILED()) goto cleanup; - - // Set up schema - { - session = session_new(databaseManager, databaseName, Schema, opts); - if (FAILED()) goto cleanup; - - transaction = transaction_new(session, Write, opts); - if (FAILED()) goto cleanup; - - { - Concept* definedNameType = - concept_promise_resolve(concepts_put_attribute_type(transaction, "name", String)); - if (FAILED()) goto cleanup; - else concept_drop(definedNameType); - } - - void_promise_resolve(transaction_commit(transaction)); - transaction = NULL; - - session_close(session); - session = NULL; - } - - // Test data API - { - session = session_new(databaseManager, databaseName, Data, opts); - if (FAILED()) goto cleanup; - - transaction = transaction_new(session, Write, opts); - if (FAILED()) goto cleanup; - if (NULL == (nameType = concept_promise_resolve(concepts_get_attribute_type(transaction, "name")))) - goto cleanup; - { - Concept* valueOfJohn = NULL; - Concept* insertedJohn = NULL; - bool success = - NULL != (valueOfJohn = value_new_string("John")) && - NULL != - (insertedJohn = concept_promise_resolve(attribute_type_put(transaction, nameType, valueOfJohn))); - concept_drop(insertedJohn); - concept_drop(valueOfJohn); - if (!success) goto cleanup; - } - - bool foundJohn = false; - { - ConceptIterator* it = attribute_type_get_instances(transaction, nameType, Transitive); - if (FAILED()) goto cleanup; - - Concept* concept; - while (NULL != (concept = concept_iterator_next(it))) { - Concept* asValue = attribute_get_value(concept); - char* attr = value_get_string(asValue); - foundJohn = foundJohn || (0 == strcmp(attr, "John")); - string_free(attr); - concept_drop(asValue); - concept_drop(concept); - } - concept_iterator_drop(it); - } - - void_promise_resolve(transaction_commit(transaction)); - transaction = NULL; - - if (!foundJohn) { - fprintf(stderr, "Did not find inserted name \'John\' in query result.\n"); - goto cleanup; - } - } - - success = true; - -cleanup: - concept_drop(nameType); - - transaction_close(transaction); - session_close(session); - options_drop(opts); - - delete_database_if_exists(databaseManager, databaseName); - check_error_may_print(__FILE__, __LINE__); - database_manager_drop(databaseManager); - driver_close(connection); - return success; -} diff --git a/c/tests/integration/gtest_runner.cpp b/c/tests/integration/gtest_runner.cpp index 59f03ade71..2cf7fb96a3 100644 --- a/c/tests/integration/gtest_runner.cpp +++ b/c/tests/integration/gtest_runner.cpp @@ -20,7 +20,7 @@ #include "gtest/gtest.h" extern "C" { -#include "c/tests/integration/tests.h" +#include "c/tests/integration/test_driver.h" } TEST(TestDatabaseManagement, TestDatabaseManagement) { @@ -34,13 +34,6 @@ TEST(TestQuery, TestData) { EXPECT_TRUE(test_query_data()); } -TEST(TestConceptAPI, TestSchema) { - EXPECT_TRUE(test_concept_api_schema()); -} -TEST(TestConceptAPI, TestData) { - EXPECT_TRUE(test_concept_api_data()); -} - int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/c/tests/integration/test_driver.c b/c/tests/integration/test_driver.c new file mode 100644 index 0000000000..6e548f3d9c --- /dev/null +++ b/c/tests/integration/test_driver.c @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include "c/typedb_driver.h" +#include "common.h" + +#define FAILED() check_error_may_print(__FILE__, __LINE__) + +bool test_database_management() { + const char databaseName[] = "test_database_management"; + + TypeDBDriver* driver = NULL; + + bool success = false; + + driver = driver_open_for_tests(TYPEDB_CORE_ADDRESS, TYPEDB_CORE_USERNAME, TYPEDB_CORE_PASSWORD); + if (FAILED()) goto cleanup; + + delete_database_if_exists(driver, databaseName); + if (FAILED()) goto cleanup; + + databases_create(driver, databaseName); + if (FAILED()) goto cleanup; + + if (!databases_contains(driver, databaseName)) { + fprintf(stderr, "databases_contains(\'%s\') failed\n", databaseName); + goto cleanup; + } + + bool foundDB = false; + DatabaseIterator* it = databases_all(driver); + const Database* database = NULL; + while (NULL != (database = database_iterator_next(it))) { + char* name = database_get_name(database); + foundDB = foundDB || (0 == strcmp(databaseName, name)); + string_free(name); + database_close(database); + } + database_iterator_drop(it); + + if (!foundDB) { + fprintf(stderr, "Did not find database \'%s\' in list of databases\n", databaseName); + goto cleanup; + } + + success = true; +cleanup: + delete_database_if_exists(driver, databaseName); + check_error_may_print(__FILE__, __LINE__); + driver_close(driver); + return success; +} + +bool test_query_schema() { + const char databaseName[] = "test_query_schema"; + + TypeDBDriver* driver = NULL; + + TransactionOptions* tx_opts = NULL; + Transaction* transaction = NULL; + QueryOptions* query_opts = NULL; + + bool success = false; + + // Set up connection & database + driver = driver_open_for_tests(TYPEDB_CORE_ADDRESS, TYPEDB_CORE_USERNAME, TYPEDB_CORE_PASSWORD); + if (FAILED()) goto cleanup; + + delete_database_if_exists(driver, databaseName); + if (FAILED()) goto cleanup; + + databases_create(driver, databaseName); + if (FAILED()) goto cleanup; + + tx_opts = transaction_options_new(); + if (FAILED()) goto cleanup; + query_opts = query_options_new(); + if (FAILED()) goto cleanup; + + // test schema queries + { + transaction = transaction_new(driver, databaseName, Schema, tx_opts); + if (FAILED()) goto cleanup; + + { + QueryAnswerPromise* define_promise = transaction_query(transaction, "define attribute name, value string;", query_opts); + if (FAILED()) goto cleanup; + QueryAnswer* define_answer = query_answer_promise_resolve(define_promise); + if (FAILED()) goto cleanup; + success = query_answer_is_ok(define_answer); + query_answer_drop(define_answer); + if (!success) { + goto cleanup; + } + } + + { + QueryAnswerPromise* query_promise = transaction_query(transaction, "match $t sub $_;", query_opts); + if (FAILED()) goto cleanup; + QueryAnswer* query_answer = query_answer_promise_resolve(query_promise); + if (FAILED()) goto cleanup; + if (!query_answer_is_concept_row_stream(query_answer)) { + success = false; + query_answer_drop(query_answer); + goto cleanup; + } + + ConceptRowIterator* it = query_answer_into_rows(query_answer); + if (FAILED()) goto cleanup; + ConceptRow* conceptRow; + bool foundName = false; + while (NULL != (conceptRow = concept_row_iterator_next(it))) { + Concept* concept = concept_row_get(conceptRow, "t"); + char* label = concept_get_label(concept); + foundName = foundName || (0 == strcmp(label, "name")); + string_free(label); + concept_drop(concept); + concept_row_drop(conceptRow); + } + concept_row_iterator_drop(it); + + void_promise_resolve(transaction_commit(transaction)); + transaction = NULL; + + if (!foundName) { + fprintf(stderr, "Did not find type \'name\' in query result.\n"); + goto cleanup; + } + } + } + success = true; + +cleanup: + if (NULL != transaction) transaction_close(transaction); + transaction_options_drop(tx_opts); + query_options_drop(query_opts); + + delete_database_if_exists(driver, databaseName); + check_error_may_print(__FILE__, __LINE__); + driver_close(driver); + return success; +} + +bool test_query_data() { + const char databaseName[] = "test_query_data"; + + TypeDBDriver* driver = NULL; + TransactionOptions* tx_opts = NULL; + QueryOptions* query_opts = NULL; + Transaction* transaction = NULL; + + bool success = false; + + // Set up connection & database + driver = driver_open_for_tests(TYPEDB_CORE_ADDRESS, TYPEDB_CORE_USERNAME, TYPEDB_CORE_PASSWORD); + if (FAILED()) goto cleanup; + + delete_database_if_exists(driver, databaseName); + if (FAILED()) goto cleanup; + + databases_create(driver, databaseName); + if (FAILED()) goto cleanup; + + tx_opts = transaction_options_new(); + if (FAILED()) goto cleanup; + query_opts = query_options_new(); + if (FAILED()) goto cleanup; + + // Set up schema + { + + transaction = transaction_new(driver, databaseName, Schema, tx_opts); + if (FAILED()) goto cleanup; + + + QueryAnswerPromise* define_promise = transaction_query(transaction, "define attribute name, value string;", query_opts); + if (FAILED()) goto cleanup; + QueryAnswer* define_answer = query_answer_promise_resolve(define_promise); + if (FAILED()) goto cleanup; + success = query_answer_is_ok(define_answer); + query_answer_drop(define_answer); + if (!success) { + goto cleanup; + } + + void_promise_resolve(transaction_commit(transaction)); + transaction = NULL; + if (FAILED()) goto cleanup; + } + + { + transaction = transaction_new(driver, databaseName, Write, tx_opts); + if (FAILED()) goto cleanup; + QueryAnswerPromise* insert_promise = transaction_query(transaction, "insert $n isa name == \"John\";", query_opts); + if (FAILED()) goto cleanup; + QueryAnswer* insert_answer = query_answer_promise_resolve(insert_promise); + if (FAILED()) goto cleanup; + if (!query_answer_is_concept_row_stream(insert_answer)) { + success = false; + query_answer_drop(insert_answer); + goto cleanup; + } + ConceptRowIterator* insert_result = query_answer_into_rows(insert_answer); + if (FAILED()) goto cleanup; + else concept_row_iterator_drop(insert_result); + + + QueryAnswerPromise* match_promise = transaction_query(transaction, "match $n isa name;", query_opts); + QueryAnswer* match_answer = query_answer_promise_resolve(match_promise); + if (FAILED()) goto cleanup; + if (!query_answer_is_concept_row_stream(match_answer)) { + success = false; + query_answer_drop(match_answer); + goto cleanup; + } + ConceptRowIterator* it = query_answer_into_rows(match_answer); + ConceptRow* conceptRow; + bool foundJohn = false; + while (NULL != (conceptRow = concept_row_iterator_next(it))) { + Concept* concept = concept_row_get(conceptRow, "n"); + char* attr = concept_get_string(concept); + foundJohn = foundJohn || (0 == strcmp(attr, "John")); + string_free(attr); + concept_drop(concept); + concept_row_drop(conceptRow); + } + concept_row_iterator_drop(it); + + void_promise_resolve(transaction_commit(transaction)); + transaction = NULL; + + if (!foundJohn) { + fprintf(stderr, "Did not find inserted name \'John\' in query result.\n"); + goto cleanup; + } + } + + success = true; + +cleanup: + if (NULL != transaction) transaction_close(transaction); + transaction_options_drop(tx_opts); + query_options_drop(query_opts); + + delete_database_if_exists(driver, databaseName); + check_error_may_print(__FILE__, __LINE__); + + driver_close(driver); + return success; +} diff --git a/c/tests/integration/tests.h b/c/tests/integration/test_driver.h similarity index 100% rename from c/tests/integration/tests.h rename to c/tests/integration/test_driver.h