Select Git revision
test_clinkahead.cpp
-
Joscha Schmiedt authored
TODO: Add tests checking support for caosdb_client.json
Joscha Schmiedt authoredTODO: Add tests checking support for caosdb_client.json
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_clinkahead.cpp 38.27 KiB
/*
*
* This file is a part of the LinkAhead Project.
*
* Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2021-2024 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "linkahead/configuration.h"
#include "linkahead/status_code.h" // for StatusCode
#include "linkahead_test_utility.h" // for EXPECT_THROW_MESSAGE, TEST_DATA_DIR
#include "clinkahead.h" // for linkahead_utility_get_env_fallback
#include <cstdint> // for int64_t
#include <cstring> // for strcmp
#include <gtest/gtest.h>
#include <gtest/gtest-message.h> // for Message
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl
#include <gtest/gtest_pred_impl.h> // for Test, TestInfo, EXPECT_EQ, TEST
#include <string> // for allocator, operator+, string,...
class test_clinkahead : public ::testing::Test {
protected:
void SetUp() override {
linkahead::configuration::ConfigurationManager::Clear();
linkahead::configuration::ConfigurationManager::LoadSingleJSONConfiguration(
TEST_DATA_DIR + "/test_linkahead_client.json");
}
void TearDown() override { linkahead::configuration::ConfigurationManager::Clear(); }
};
TEST_F(test_clinkahead, test_get_env_fallback) {
const char *const some_var = linkahead_utility_get_env_fallback("SOME_ENV_VAR", "fall-back");
EXPECT_EQ("fall-back", some_var);
}
TEST_F(test_clinkahead, test_other_client_error) {
EXPECT_EQ(linkahead_status_code_OTHER_CLIENT_ERROR(), linkahead::StatusCode::OTHER_CLIENT_ERROR);
}
TEST_F(test_clinkahead, test_get_default_connection) {
linkahead_connection_connection out;
linkahead_connection_connection_manager_get_default_connection(&out);
EXPECT_TRUE(out.wrapped_connection);
}
TEST_F(test_clinkahead, test_get_connection) {
linkahead_connection_connection out;
linkahead_connection_connection_manager_get_connection(&out, "local-linkahead-admin");
EXPECT_TRUE(out.wrapped_connection);
}
TEST_F(test_clinkahead, test_execute_transaction) {
linkahead_connection_connection connection;
linkahead_connection_connection_manager_get_connection(&connection, "local-linkahead-admin");
linkahead_transaction_transaction transaction;
linkahead_connection_connection_create_transaction(&connection, &transaction);
EXPECT_TRUE(transaction.wrapped_transaction);
int return_code(linkahead_transaction_transaction_retrieve_by_id(&transaction, "some_id"));
EXPECT_EQ(return_code, linkahead::StatusCode::GO_ON);
return_code = linkahead_transaction_transaction_execute(&transaction);
EXPECT_EQ(return_code, linkahead::StatusCode::CONNECTION_ERROR);
return_code = linkahead_transaction_delete_transaction(&transaction);
EXPECT_EQ(return_code, 0);
linkahead_transaction_transaction multi_transaction;
linkahead_connection_connection_create_transaction(&connection, &multi_transaction);
// We explicitely want to define a C-style array here, so we disable
// linting
const char *ids[] = {"id1", "id2", "id3"}; // NOLINT
return_code = linkahead_transaction_transaction_retrieve_by_ids(&multi_transaction, ids, 3);
EXPECT_EQ(return_code, linkahead::StatusCode::GO_ON);
return_code = linkahead_transaction_delete_transaction(&multi_transaction);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_multi_retrieve) {
linkahead_connection_connection connection;
linkahead_connection_connection_manager_get_connection(&connection, "local-linkahead-admin");
linkahead_transaction_transaction multi_transaction;
linkahead_connection_connection_create_transaction(&connection, &multi_transaction);
// We explicitely want to define a C-style array here, so we disable
// linting
const char *ids[] = {"id1", "id2", "id3"}; // NOLINT
int return_code(linkahead_transaction_transaction_retrieve_by_ids(&multi_transaction, ids, 3));
EXPECT_EQ(return_code, linkahead::StatusCode::GO_ON);
return_code = linkahead_transaction_delete_transaction(&multi_transaction);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_query) {
linkahead_connection_connection connection;
linkahead_connection_connection_manager_get_connection(&connection, "local-linkahead-admin");
linkahead_transaction_transaction transaction;
linkahead_connection_connection_create_transaction(&connection, &transaction);
int return_code(linkahead_transaction_transaction_query(&transaction, "FIND ENTITY WITH id=123"));
EXPECT_EQ(return_code, linkahead::StatusCode::GO_ON);
return_code = linkahead_transaction_delete_transaction(&transaction);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_datatype) {
linkahead_entity_datatype atomic;
// check that this fails
int return_code(linkahead_entity_create_atomic_datatype(&atomic, "some type"));
EXPECT_EQ(return_code, linkahead::StatusCode::ENUM_MAPPING_ERROR);
return_code = linkahead_entity_create_atomic_datatype(&atomic, "INTEGER");
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype reference;
return_code = linkahead_entity_create_reference_datatype(&reference, "MyType");
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype list_of_atomics;
return_code = linkahead_entity_create_atomic_list_datatype(&list_of_atomics, "DATETIME");
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype list_of_references;
return_code = linkahead_entity_create_reference_list_datatype(&list_of_references, "MyType");
EXPECT_EQ(return_code, 0);
bool is_a(false);
return_code = linkahead_entity_datatype_is_undefined(&atomic, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_atomic(&atomic, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
return_code = linkahead_entity_datatype_is_reference(&atomic, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_atomic(&atomic, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_reference(&atomic, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_atomic(&reference, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_reference(&reference, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
return_code = linkahead_entity_datatype_is_list_of_atomic(&reference, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_reference(&reference, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_atomic(&list_of_atomics, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_reference(&list_of_atomics, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_atomic(&list_of_atomics, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
return_code = linkahead_entity_datatype_is_list_of_reference(&list_of_atomics, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_atomic(&list_of_references, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_reference(&list_of_references, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_atomic(&list_of_references, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_reference(&list_of_references, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
char *name = nullptr; // NOLINT
return_code = linkahead_entity_datatype_get_datatype_name(&atomic, &name);
EXPECT_EQ(return_code, 0);
EXPECT_STREQ(name, "INTEGER");
return_code = linkahead_entity_datatype_get_datatype_name(&reference, &name);
EXPECT_EQ(return_code, 0);
EXPECT_STREQ(name, "MyType");
return_code = linkahead_entity_datatype_get_datatype_name(&list_of_atomics, &name);
EXPECT_EQ(return_code, 0);
EXPECT_STREQ(name, "DATETIME");
return_code = linkahead_entity_datatype_get_datatype_name(&list_of_references, &name);
EXPECT_EQ(return_code, 0);
EXPECT_STREQ(name, "MyType");
return_code = linkahead_entity_delete_datatype(&atomic);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&reference);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&list_of_atomics);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&list_of_references);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_value) {
linkahead_entity_value string_value;
int return_code(linkahead_entity_create_string_value(&string_value, "value"));
EXPECT_EQ(return_code, 0);
linkahead_entity_value int_value;
return_code = linkahead_entity_create_int_value(&int_value, 27);
EXPECT_EQ(return_code, 0);
linkahead_entity_value bool_value;
return_code = linkahead_entity_create_bool_value(&bool_value, true);
EXPECT_EQ(return_code, 0);
linkahead_entity_value double_value;
return_code = linkahead_entity_create_double_value(&double_value, 2.7);
EXPECT_EQ(return_code, 0);
linkahead_entity_value string_vector_value;
const char *string_values[] = {"a", "b", "c"}; // NOLINT
return_code = linkahead_entity_create_string_vector_value(&string_vector_value, string_values, 3);
EXPECT_EQ(return_code, 0);
linkahead_entity_value int_vector_value;
const int64_t int_values[] = {1, 2, 3}; // NOLINT
return_code = linkahead_entity_create_int_vector_value(&int_vector_value, int_values, 3);
EXPECT_EQ(return_code, 0);
linkahead_entity_value double_vector_value;
const double double_values[] = {1.1, 2.2, 3.3}; // NOLINT
return_code = linkahead_entity_create_double_vector_value(&double_vector_value, double_values, 3);
EXPECT_EQ(return_code, 0);
linkahead_entity_value bool_vector_value;
const bool bool_values[] = {true, false, false}; // NOLINT
return_code = linkahead_entity_create_bool_vector_value(&bool_vector_value, bool_values, 3);
EXPECT_EQ(return_code, 0);
// One thorough check, afterwards only the ones that should be true
bool is_a(false);
return_code = linkahead_entity_value_is_null(&string_value, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_value_is_string(&string_value, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
return_code = linkahead_entity_value_is_double(&string_value, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_value_is_integer(&string_value, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_value_is_bool(&string_value, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_value_is_vector(&string_value, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
linkahead_entity_value_is_integer(&int_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_bool(&bool_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_double(&double_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_vector(&string_vector_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_vector(&int_vector_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_vector(&double_vector_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_vector(&bool_vector_value, &is_a);
EXPECT_TRUE(is_a);
char *out_string = nullptr; // NOLINT
return_code = linkahead_entity_value_get_as_string(&string_value, &out_string);
EXPECT_EQ(return_code, 0);
EXPECT_STREQ(out_string, "value");
int64_t out_int(0);
return_code = linkahead_entity_value_get_as_integer(&int_value, &out_int);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(out_int, 27);
bool out_bool(false);
return_code = linkahead_entity_value_get_as_bool(&bool_value, &out_bool);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(out_bool);
double out_double(0);
return_code = linkahead_entity_value_get_as_double(&double_value, &out_double);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(out_double, 2.7);
int list_length(0);
return_code = linkahead_entity_value_get_as_vector_size(&string_vector_value, &list_length);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(list_length, 3);
return_code = linkahead_entity_value_get_as_vector_size(&int_vector_value, &list_length);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(list_length, 3);
return_code = linkahead_entity_value_get_as_vector_size(&double_vector_value, &list_length);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(list_length, 3);
return_code = linkahead_entity_value_get_as_vector_size(&bool_vector_value, &list_length);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(list_length, 3);
// Only check for one, rest should be covered by this + scalar values
linkahead_entity_value out_val;
return_code = linkahead_entity_value_get_as_vector_at(&string_vector_value, &out_val, 0);
EXPECT_EQ(return_code, 0);
linkahead_entity_value_get_as_string(&out_val, &out_string);
EXPECT_STREQ(out_string, "a");
return_code = linkahead_entity_value_get_as_vector_at(&string_vector_value, &out_val, 1);
EXPECT_EQ(return_code, 0);
linkahead_entity_value_get_as_string(&out_val, &out_string);
EXPECT_STREQ(out_string, "b");
return_code = linkahead_entity_value_get_as_vector_at(&string_vector_value, &out_val, 2);
EXPECT_EQ(return_code, 0);
linkahead_entity_value_get_as_string(&out_val, &out_string);
EXPECT_STREQ(out_string, "c");
return_code = linkahead_entity_delete_value(&string_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&int_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&bool_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&double_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&string_vector_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&int_vector_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&double_vector_value);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&bool_vector_value);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_entity) {
linkahead_entity_entity entity;
int return_code(linkahead_entity_create_entity(&entity));
EXPECT_EQ(return_code, 0);
// cannot be created again without deletion
// return_code = linkahead_entity_create_entity(&entity);
// EXPECT_EQ(return_code, linkahead::StatusCode::EXTERN_C_ASSIGNMENT_ERROR);
// deletion and re-creation is ok
return_code = linkahead_entity_delete_entity(&entity);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_create_entity(&entity);
EXPECT_EQ(return_code, 0);
// In-depth check for one pair of setter and getter, just compare
// the strings for the rest
return_code = linkahead_entity_entity_set_name(&entity, "length");
EXPECT_EQ(return_code, 0);
char *out = nullptr; // NOLINT
return_code = linkahead_entity_entity_get_name(&entity, &out);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(strcmp(out, "length"), 0);
// test call without validation of result
return_code = linkahead_entity_entity_set_role(&entity, "FILE");
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_set_local_path(
&entity, (TEST_DATA_DIR + "/test_linkahead_client.json").c_str());
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_get_local_path(&entity, &out);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(strcmp(out, (TEST_DATA_DIR + "/test_linkahead_client.json").c_str()), 0);
// invalid role
return_code = linkahead_entity_entity_set_role(&entity, "Role does not exist");
EXPECT_EQ(return_code, linkahead::StatusCode::ENUM_MAPPING_ERROR);
linkahead_entity_entity_set_role(&entity, "PROPERTY");
linkahead_entity_entity_get_role(&entity, &out);
EXPECT_EQ(strcmp(out, "PROPERTY"), 0);
linkahead_entity_entity_set_description(&entity, "The length of an object");
linkahead_entity_entity_get_description(&entity, &out);
EXPECT_EQ(strcmp(out, "The length of an object"), 0);
linkahead_entity_datatype in_type;
linkahead_entity_create_atomic_datatype(&in_type, "DOUBLE");
linkahead_entity_entity_set_datatype(&entity, &in_type);
// verify that this doesn't work ...
// return_code = linkahead_entity_entity_get_datatype(&entity, &in_type);
// EXPECT_EQ(return_code, linkahead::StatusCode::EXTERN_C_ASSIGNMENT_ERROR);
linkahead_entity_datatype out_type;
// ... but does with a clean property
return_code = linkahead_entity_entity_get_datatype(&entity, &out_type);
EXPECT_EQ(return_code, 0);
bool is_a(false);
return_code = linkahead_entity_datatype_is_atomic(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
return_code = linkahead_entity_datatype_is_reference(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_atomic(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_reference(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(out, "DOUBLE");
linkahead_entity_value in_value;
return_code = linkahead_entity_create_double_value(&in_value, 5.0);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_set_value(&entity, &in_value);
EXPECT_EQ(return_code, 0);
linkahead_entity_value out_value;
return_code = linkahead_entity_entity_get_value(&entity, &out_value);
EXPECT_EQ(return_code, 0);
linkahead_entity_value_is_double(&out_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_is_null(&out_value, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_value_is_string(&out_value, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_value_is_bool(&out_value, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_value_is_integer(&out_value, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_value_is_vector(&out_value, &is_a);
EXPECT_FALSE(is_a);
double out_double(0);
linkahead_entity_value_get_as_double(&out_value, &out_double);
EXPECT_EQ(out_double, 5.0);
// clear to re-use
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
linkahead_entity_create_reference_list_datatype(&in_type, "Person");
linkahead_entity_entity_set_datatype(&entity, &in_type);
// works without clearing since datatype is managed by the owning entity
linkahead_entity_entity_get_datatype(&entity, &out_type);
return_code = linkahead_entity_datatype_is_atomic(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_reference(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_atomic(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_FALSE(is_a);
return_code = linkahead_entity_datatype_is_list_of_reference(&out_type, &is_a);
EXPECT_EQ(return_code, 0);
EXPECT_TRUE(is_a);
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(out, "Person");
linkahead_entity_entity_set_unit(&entity, "m");
linkahead_entity_entity_get_unit(&entity, &out);
EXPECT_EQ(strcmp(out, "m"), 0);
return_code = linkahead_entity_delete_entity(&entity);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&in_value);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_parent) {
linkahead_entity_parent parent;
int return_code(linkahead_entity_create_parent(&parent));
EXPECT_EQ(return_code, 0);
linkahead_entity_parent_set_id(&parent, "some_id");
linkahead_entity_parent_set_name(&parent, "some_name");
char *out = nullptr; // NOLINT
linkahead_entity_parent_get_id(&parent, &out);
EXPECT_EQ(strcmp(out, "some_id"), 0);
linkahead_entity_parent_get_name(&parent, &out);
EXPECT_EQ(strcmp(out, "some_name"), 0);
return_code = linkahead_entity_delete_parent(&parent);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_property) {
linkahead_entity_property property;
int return_code(linkahead_entity_create_property(&property));
EXPECT_EQ(return_code, 0);
linkahead_entity_property_set_id(&property, "some_id");
linkahead_entity_property_set_name(&property, "some_name");
linkahead_entity_datatype in_type;
linkahead_entity_create_atomic_datatype(&in_type, "TEXT");
linkahead_entity_property_set_datatype(&property, &in_type);
linkahead_entity_property_set_importance(&property, "FIX");
linkahead_entity_property_set_unit(&property, "some_unit");
linkahead_entity_value in_value;
linkahead_entity_create_string_value(&in_value, "some_value");
linkahead_entity_property_set_value(&property, &in_value);
char *out = nullptr; // NOLINT
linkahead_entity_property_get_id(&property, &out);
EXPECT_EQ(strcmp(out, "some_id"), 0);
linkahead_entity_property_get_name(&property, &out);
EXPECT_EQ(strcmp(out, "some_name"), 0);
linkahead_entity_datatype out_type;
return_code = linkahead_entity_property_get_datatype(&property, &out_type);
EXPECT_EQ(return_code, 0);
bool is_a(false);
linkahead_entity_datatype_is_atomic(&out_type, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_datatype_is_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_list_of_atomic(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_list_of_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(out, "TEXT");
linkahead_entity_property_get_importance(&property, &out);
EXPECT_EQ(strcmp(out, "FIX"), 0);
linkahead_entity_property_get_unit(&property, &out);
EXPECT_EQ(strcmp(out, "some_unit"), 0);
linkahead_entity_value out_value;
return_code = linkahead_entity_property_get_value(&property, &out_value);
EXPECT_EQ(return_code, 0);
linkahead_entity_value_is_string(&out_value, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_value_get_as_string(&out_value, &out);
EXPECT_STREQ(out, "some_value");
return_code = linkahead_entity_delete_property(&property);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&in_value);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_string_list_property) {
linkahead_entity_property property;
int return_code(linkahead_entity_create_property(&property));
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype in_type;
return_code = linkahead_entity_create_atomic_list_datatype(&in_type, "TEXT");
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_property_set_datatype(&property, &in_type);
EXPECT_EQ(return_code, 0);
linkahead_entity_value in_value;
const char *value_list[] = {"val0", "val1", "val2"}; // NOLINT
return_code = linkahead_entity_create_string_vector_value(&in_value, value_list, 3);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_property_set_value(&property, &in_value);
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype out_type;
return_code = linkahead_entity_property_get_datatype(&property, &out_type);
EXPECT_EQ(return_code, 0);
bool is_a(false);
linkahead_entity_datatype_is_atomic(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_list_of_atomic(&out_type, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_datatype_is_list_of_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
char *out = nullptr; // NOLINT
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(out, "TEXT");
linkahead_entity_value out_value;
linkahead_entity_property_get_value(&property, &out_value);
linkahead_entity_value_is_vector(&out_value, &is_a);
EXPECT_TRUE(is_a);
int length(-1);
linkahead_entity_value_get_as_vector_size(&out_value, &length);
EXPECT_EQ(length, 3);
linkahead_entity_value list_elt;
for (int i = 0; i < length; i++) {
return_code = linkahead_entity_value_get_as_vector_at(&out_value, &list_elt, i);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_value_get_as_string(&list_elt, &out);
EXPECT_EQ(return_code, 0);
EXPECT_STREQ(value_list[i], out); // NOLINT
}
return_code = linkahead_entity_delete_property(&property);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&in_value);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_int_list_property) {
linkahead_entity_property property;
int return_code(linkahead_entity_create_property(&property));
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype in_type;
linkahead_entity_create_atomic_list_datatype(&in_type, "INTEGER");
return_code = linkahead_entity_property_set_datatype(&property, &in_type);
EXPECT_EQ(return_code, 0);
const int64_t value_list[] = {1, 2, 3}; // NOLINT
linkahead_entity_value in_value;
linkahead_entity_create_int_vector_value(&in_value, value_list, 3);
return_code = linkahead_entity_property_set_value(&property, &in_value);
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype out_type;
return_code = linkahead_entity_property_get_datatype(&property, &out_type);
EXPECT_EQ(return_code, 0);
bool is_a(false);
linkahead_entity_datatype_is_atomic(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_list_of_atomic(&out_type, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_datatype_is_list_of_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
char *out = nullptr; // NOLINT
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(out, "INTEGER");
linkahead_entity_value out_value;
linkahead_entity_property_get_value(&property, &out_value);
linkahead_entity_value_is_vector(&out_value, &is_a);
EXPECT_TRUE(is_a);
int length(-1);
linkahead_entity_value_get_as_vector_size(&out_value, &length);
EXPECT_EQ(length, 3);
int64_t out_int = -1;
linkahead_entity_value list_elt;
for (int i = 0; i < length; i++) {
return_code = linkahead_entity_value_get_as_vector_at(&out_value, &list_elt, i);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_value_get_as_integer(&list_elt, &out_int);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(value_list[i], out_int); // NOLINT
}
return_code = linkahead_entity_delete_property(&property);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&in_value);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_bool_list_property) {
linkahead_entity_property property;
int return_code(linkahead_entity_create_property(&property));
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype in_type;
linkahead_entity_create_atomic_list_datatype(&in_type, "BOOLEAN");
return_code = linkahead_entity_property_set_datatype(&property, &in_type);
EXPECT_EQ(return_code, 0);
const bool value_list[] = {true, true, false}; // NOLINT
linkahead_entity_value in_value;
linkahead_entity_create_bool_vector_value(&in_value, value_list, 3);
return_code = linkahead_entity_property_set_value(&property, &in_value);
EXPECT_EQ(return_code, 0);
linkahead_entity_datatype out_type;
return_code = linkahead_entity_property_get_datatype(&property, &out_type);
EXPECT_EQ(return_code, 0);
bool is_a(false);
linkahead_entity_datatype_is_atomic(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
linkahead_entity_datatype_is_list_of_atomic(&out_type, &is_a);
EXPECT_TRUE(is_a);
linkahead_entity_datatype_is_list_of_reference(&out_type, &is_a);
EXPECT_FALSE(is_a);
char *out = nullptr; // NOLINT
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(out, "BOOLEAN");
linkahead_entity_value out_value;
linkahead_entity_property_get_value(&property, &out_value);
linkahead_entity_value_is_vector(&out_value, &is_a);
EXPECT_TRUE(is_a);
int length(-1);
linkahead_entity_value_get_as_vector_size(&out_value, &length);
EXPECT_EQ(length, 3);
bool out_bool(false);
linkahead_entity_value list_elt;
for (int i = 0; i < length; i++) {
return_code = linkahead_entity_value_get_as_vector_at(&out_value, &list_elt, i);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_value_get_as_bool(&list_elt, &out_bool);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(value_list[i], out_bool); // NOLINT
}
return_code = linkahead_entity_delete_property(&property);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&in_value);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_entity_with_parent_and_property) {
linkahead_entity_parent input_parent;
int return_code(linkahead_entity_create_parent(&input_parent));
EXPECT_EQ(return_code, 0);
linkahead_entity_parent_set_id(&input_parent, "parent_id");
linkahead_entity_parent_set_name(&input_parent, "parent_name");
linkahead_entity_property input_property;
return_code = linkahead_entity_create_property(&input_property);
EXPECT_EQ(return_code, 0);
linkahead_entity_property_set_id(&input_property, "property_id");
linkahead_entity_property_set_name(&input_property, "property_name");
linkahead_entity_datatype in_type;
linkahead_entity_create_atomic_datatype(&in_type, "TEXT");
linkahead_entity_value in_value;
linkahead_entity_create_string_value(&in_value, "property_value");
linkahead_entity_property_set_datatype(&input_property, &in_type);
linkahead_entity_property_set_value(&input_property, &in_value);
linkahead_entity_entity entity;
return_code = linkahead_entity_create_entity(&entity);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_append_parent(&entity, &input_parent);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_append_property(&entity, &input_property);
EXPECT_EQ(return_code, 0);
int count[] = {0}; // NOLINT
return_code = linkahead_entity_entity_get_parents_size(&entity, count);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(*count, 1);
return_code = linkahead_entity_entity_get_properties_size(&entity, count);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(*count, 1);
char *in = nullptr; // NOLINT
char *out = nullptr; // NOLINT
// cannot assign an already assigned property
// return_code = linkahead_entity_entity_get_property(&entity, &input_property, 0);
// EXPECT_EQ(return_code, linkahead::StatusCode::EXTERN_C_ASSIGNMENT_ERROR);
linkahead_entity_property output_property;
return_code = linkahead_entity_entity_get_property(&entity, &output_property, 0);
EXPECT_EQ(return_code, 0);
linkahead_entity_property_get_id(&input_property, &in);
linkahead_entity_property_get_id(&output_property, &out);
EXPECT_EQ(strcmp(in, out), 0);
linkahead_entity_property_get_name(&input_property, &in);
linkahead_entity_property_get_name(&output_property, &out);
EXPECT_EQ(strcmp(in, out), 0);
linkahead_entity_datatype out_type;
linkahead_entity_property_get_datatype(&output_property, &out_type);
bool in_is(false);
bool out_is(false);
linkahead_entity_datatype_is_atomic(&in_type, &in_is);
linkahead_entity_datatype_is_atomic(&out_type, &out_is);
EXPECT_EQ(in_is, out_is);
linkahead_entity_datatype_is_reference(&in_type, &in_is);
linkahead_entity_datatype_is_reference(&out_type, &out_is);
EXPECT_EQ(in_is, out_is);
linkahead_entity_datatype_is_list_of_atomic(&in_type, &in_is);
linkahead_entity_datatype_is_list_of_atomic(&out_type, &out_is);
EXPECT_EQ(in_is, out_is);
linkahead_entity_datatype_is_list_of_reference(&in_type, &in_is);
linkahead_entity_datatype_is_list_of_reference(&out_type, &out_is);
EXPECT_EQ(in_is, out_is);
linkahead_entity_datatype_get_datatype_name(&in_type, &in);
linkahead_entity_datatype_get_datatype_name(&out_type, &out);
EXPECT_STREQ(in, out);
linkahead_entity_value out_value;
linkahead_entity_property_get_value(&output_property, &out_value);
linkahead_entity_value_is_string(&in_value, &in_is);
EXPECT_TRUE(in_is);
linkahead_entity_value_is_string(&out_value, &out_is);
EXPECT_TRUE(out_is);
linkahead_entity_value_get_as_string(&in_value, &in);
linkahead_entity_value_get_as_string(&out_value, &out);
EXPECT_STREQ(in, out);
linkahead_entity_parent output_parent;
return_code = linkahead_entity_entity_get_parent(&entity, &output_parent, 0);
EXPECT_EQ(return_code, 0);
linkahead_entity_parent_get_id(&input_parent, &in);
linkahead_entity_parent_get_id(&output_parent, &out);
EXPECT_EQ(strcmp(in, out), 0);
linkahead_entity_parent_get_name(&input_parent, &in);
linkahead_entity_parent_get_name(&output_parent, &out);
EXPECT_EQ(strcmp(in, out), 0);
// Delete everything
return_code = linkahead_entity_delete_parent(&input_parent);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_property(&input_property);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_entity(&entity);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_datatype(&in_type);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_value(&in_value);
EXPECT_EQ(return_code, 0);
// This tests the `_deletable` flag. The wrapped cpp objects of
// `output_parent` and `output_property` are owned by the entity, so
// they have been deleted together with the entity. With a wrong
// `_deletable` flag, the following would cause segfaults.
//
return_code = linkahead_entity_delete_parent(&output_parent);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_property(&output_property);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_remove_property) {
linkahead_entity_entity entity;
int return_code(linkahead_entity_create_entity(&entity));
EXPECT_EQ(return_code, 0);
// Create two properties with names
linkahead_entity_property in_prop_1;
return_code = linkahead_entity_create_property(&in_prop_1);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_property_set_name(&in_prop_1, "Property 1");
EXPECT_EQ(return_code, 0);
linkahead_entity_property in_prop_2;
return_code = linkahead_entity_create_property(&in_prop_2);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_property_set_name(&in_prop_2, "Property 2");
EXPECT_EQ(return_code, 0);
// Append them
return_code = linkahead_entity_entity_append_property(&entity, &in_prop_1);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_append_property(&entity, &in_prop_2);
EXPECT_EQ(return_code, 0);
// Delete one and see that the number of properties decreases by one
int count[] = {0}; // NOLINT
return_code = linkahead_entity_entity_get_properties_size(&entity, count);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(*count, 2);
return_code = linkahead_entity_entity_remove_property(&entity, 0);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_entity_get_properties_size(&entity, count);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(*count, 1);
linkahead_entity_property out_prop;
return_code = linkahead_entity_entity_get_property(&entity, &out_prop, 0);
EXPECT_EQ(return_code, 0);
char *in = nullptr; // NOLINT
char *out = nullptr; // NOLINT
// Deleted the first property, so the second one should remain.
return_code = linkahead_entity_property_get_name(&in_prop_2, &in);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_property_get_name(&out_prop, &out);
EXPECT_EQ(return_code, 0);
EXPECT_EQ(strcmp(in, out), 0);
// Delete everything we have created
return_code = linkahead_entity_delete_property(&in_prop_2);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_property(&in_prop_1);
EXPECT_EQ(return_code, 0);
return_code = linkahead_entity_delete_entity(&entity);
EXPECT_EQ(return_code, 0);
}
TEST_F(test_clinkahead, test_insert_update_delete) {
// Only test adding to a transaction. Excution and results are
// tested in integration tests.
linkahead_connection_connection connection;
linkahead_connection_connection_manager_get_default_connection(&connection);
linkahead_transaction_transaction insert_transaction;
linkahead_connection_connection_create_transaction(&connection, &insert_transaction);
linkahead_entity_entity entity;
linkahead_entity_create_entity(&entity);
linkahead_entity_entity_set_name(&entity, "some_name");
linkahead_entity_entity_set_local_path(&entity, "some_name");
linkahead_entity_entity_set_file_path(&entity, "some_name");
auto return_code = linkahead_transaction_transaction_insert_entity(&insert_transaction, &entity);
EXPECT_EQ(return_code, linkahead::StatusCode::GO_ON);
linkahead_transaction_transaction update_transaction;
linkahead_connection_connection_create_transaction(&connection, &update_transaction);
return_code = linkahead_transaction_transaction_update_entity(&update_transaction, &entity);
// No ID, so this should be an error
EXPECT_EQ(return_code, linkahead::StatusCode::ORIGINAL_ENTITY_MISSING_ID);
linkahead_transaction_transaction delete_transaction;
linkahead_connection_connection_create_transaction(&connection, &delete_transaction);
return_code = linkahead_transaction_transaction_delete_by_id(&delete_transaction, "some_id");
// Could add further deletions
EXPECT_EQ(return_code, linkahead::StatusCode::GO_ON);
linkahead_entity_delete_entity(&entity);
linkahead_transaction_delete_transaction(&insert_transaction);
linkahead_transaction_delete_transaction(&update_transaction);
linkahead_transaction_delete_transaction(&delete_transaction);
}