Select Git revision
test_clinkahead.cpp
-
Joscha Schmiedt authored
Something something string literals on Windows...
Joscha Schmiedt authoredSomething something string literals on Windows...
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_clinkahead.cpp 38.31 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) {
constexpr auto fall_back = "fall-back";
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);
}