Skip to content
Snippets Groups Projects
Select Git revision
  • 76b0562d96438623d958091bf98a0f3cec1022d7
  • main default protected
  • f-yaml-parser-enums
  • dev protected
  • f-fix-paths
  • f-fix-validate-to-dict
  • f-labfolder-converter
  • f-state-machine-script
  • f-xlsx-converter-warnings-errors
  • f-rename
  • f-extra-deps
  • f-more-jsonschema-export
  • f-henrik
  • f-fix-89
  • f-trigger-advanced-user-tools
  • f-real-rename-test
  • f-linkahead-rename
  • f-register-integrationtests
  • f-fix-id
  • f-h5-files
  • f-json-schema
  • v0.14.0
  • v0.13.0
  • v0.12.0
  • v0.11.0
  • v0.10.0-numpy2
  • v0.10.0
  • v0.9.0
  • v0.8.0
  • v0.7.0
  • v0.6.1
  • v0.6.0
  • v0.5.0
  • v0.4.1
  • v0.4.0
  • v0.3.1
  • v0.3.0
37 results

ref_to_commit.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    test_entity.cpp 29.29 KiB
    /*
     *
     * This file is a part of the CaosDB Project.
     *
     * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
     * Copyright (C) 2021 Florian Spreckelsen <f.spreckelsen@indiscale.com>
     * Copyright (C) 2021 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 "caosdb/data_type.h"                    // for DataType, AtomicDat...
    #include "caosdb/entity.h"                       // for Entity, Property
    #include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransactionSe...
    #include "caosdb/entity/v1alpha1/main.pb.h"      // for IdResponse, Message
    #include "caosdb/message_code.h"                 // for MessageCode, ENTITY...
    #include "caosdb/protobuf_helper.h"              // for get_arena
    #include "caosdb/status_code.h"                  // for StatusCode, FILE_DO...
    #include "caosdb/transaction.h"                  // for Transaction
    #include "caosdb/value.h"                        // for Value
    #include "caosdb_test_utility.h"                 // for TEST_DATA_DIR
    #include <google/protobuf/arena.h>               // for Arena
    #include <gtest/gtest-message.h>                 // for Message
    #include <gtest/gtest-test-part.h>               // for TestPartResult, Sui...
    #include <gtest/gtest_pred_impl.h>               // for Test, EXPECT_EQ
    #include <iostream>                              // for operator<<, basic_o...
    #include <memory>                                // for allocator, shared_ptr
    #include <stdexcept>                             // for out_of_range
    #include <string>                                // for operator+, to_string
    #include <utility>                               // for move
    
    namespace caosdb::entity {
    using caosdb::entity::v1alpha1::IdResponse;
    using ProtoEntity = caosdb::entity::v1alpha1::Entity;
    using ProtoParent = caosdb::entity::v1alpha1::Parent;
    using ProtoProperty = caosdb::entity::v1alpha1::Property;
    using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType;
    using caosdb::entity::v1alpha1::EntityResponse;
    using caosdb::utility::get_arena;
    using ProtoEntityRole = caosdb::entity::v1alpha1::EntityRole;
    
    TEST(test_entity, test_parent_setters) {
      auto parent = Parent();
      parent.SetName("RT1");
      parent.SetId("some-id");
    
      EXPECT_EQ(parent.GetName(), "RT1");
      EXPECT_EQ(parent.GetId(), "some-id");
    }
    
    TEST(test_entity, test_append_parent) {
      auto parent = Parent();
      parent.SetId("some-id");
    
      auto entity = Entity();
      EXPECT_EQ(entity.GetParents().size(), 0);
      entity.AppendParent(parent);
      EXPECT_EQ(entity.GetParents().size(), 1);
    
      auto same_parent = entity.GetParents().at(0);
      EXPECT_EQ(same_parent.GetId(), "some-id");
    }
    
    TEST(test_entity, test_property_setters) {
      auto prop = Property();
      prop.SetName("prop_name");
      prop.SetId("prop_id");
      prop.SetImportance(Importance::OBLIGATORY);
      prop.SetValue("prop_value");
      prop.SetUnit("prop_unit");
      prop.SetDataType("prop_dtype");
    
      EXPECT_EQ(prop.GetName(), "prop_name");
      EXPECT_EQ(prop.GetId(), "prop_id");
      EXPECT_EQ(prop.GetImportance(), Importance::OBLIGATORY);
      EXPECT_TRUE(prop.GetValue().IsString());
      EXPECT_EQ(prop.GetValue().GetAsString(), "prop_value");
      EXPECT_EQ(prop.GetUnit(), "prop_unit");
      EXPECT_TRUE(prop.GetDataType().IsReference());
      EXPECT_EQ(prop.GetDataType().GetAsReference().GetName(), "prop_dtype");
      EXPECT_FALSE(prop.GetDataType().IsList());
    
      prop.SetDataType(AtomicDataType::DATETIME);
      EXPECT_TRUE(prop.GetDataType().IsAtomic());
      EXPECT_EQ(prop.GetDataType().GetAsAtomic(), AtomicDataType::DATETIME);
      EXPECT_FALSE(prop.GetDataType().IsList());
    }
    
    TEST(test_entity, test_list_property_setters) {
      auto prop = Property();
    
      prop.SetDataType(AtomicDataType::DATETIME); // Set as atomic first.
      EXPECT_TRUE(prop.GetDataType().IsAtomic());
      EXPECT_EQ(prop.GetDataType().GetAsAtomic(), AtomicDataType::DATETIME);
    
      prop.SetDataType(AtomicDataType::DOUBLE, true);
      auto const &dtype = prop.GetDataType();
      EXPECT_FALSE(dtype.IsAtomic()); // Should not be true anymore.
      EXPECT_FALSE(dtype.IsReference());
      EXPECT_TRUE(dtype.IsList());
      EXPECT_NE(dtype.GetAsAtomic(), AtomicDataType::DATETIME); // Should be overwritten.
      EXPECT_TRUE(dtype.GetAsList().IsListOfAtomic());
      EXPECT_EQ(dtype.GetAsList().GetAtomicDataType(), AtomicDataType::DOUBLE);
    }
    
    TEST(test_entity, test_append_property) {
      auto entity = Entity();
    
      auto prop = Property();
      prop.SetName("prop_name");
      prop.SetId("prop_id");
      prop.SetImportance(Importance::RECOMMENDED);
      prop.SetValue("prop_value");
      prop.SetUnit("prop_unit");
      prop.SetDataType("prop_dtype");
    
      EXPECT_EQ(entity.GetProperties().size(), 0);
      entity.AppendProperty(prop);
      EXPECT_EQ(entity.GetProperties().size(), 1);
    
      // also test RepeatedPtrFieldWrapper.at()
      const auto &same_prop = entity.GetProperties().at(0);
      EXPECT_THROW((void)entity.GetProperties().at(2), std::out_of_range);
      EXPECT_THROW((void)entity.GetProperties().at(-1), std::out_of_range);
    
      EXPECT_EQ(prop.GetName(), same_prop.GetName());
      EXPECT_EQ(prop.GetId(), same_prop.GetId());
      EXPECT_EQ(prop.GetImportance(), same_prop.GetImportance());
      EXPECT_EQ(prop.GetValue().ToString(), same_prop.GetValue().ToString());
      EXPECT_EQ(prop.GetUnit(), same_prop.GetUnit());
      EXPECT_EQ(prop.GetDataType(), same_prop.GetDataType());
    }
    
    TEST(test_entity, test_copy_constructor) {
      ProtoParent parent;
      parent.set_description("the parent desc");
      parent.set_id("the parent id");
      parent.set_name("the parent name");
      ProtoProperty property;
      property.set_id("the-prop-id");
      property.set_description("the prop-desc");
      property.set_name("the-prop-name");
      property.mutable_value()->mutable_list_values()->mutable_values()->Add()->set_double_value(25.5);
      property.mutable_data_type()->mutable_list_data_type()->set_atomic_data_type(
        ProtoAtomicDataType::ATOMIC_DATA_TYPE_DOUBLE);
      EntityResponse entity_response;
      entity_response.mutable_entity()->set_id("the-id");
      entity_response.mutable_entity()->set_name("the-name");
      entity_response.mutable_entity()->set_role(ProtoEntityRole::ENTITY_ROLE_RECORD);
      entity_response.mutable_entity()->set_description("the description");
      entity_response.mutable_entity()->set_unit("the-unit");
      entity_response.mutable_entity()->mutable_value()->mutable_scalar_value()->set_string_value(
        "the-value");
      entity_response.mutable_entity()->mutable_version()->set_id("version-id");
      entity_response.mutable_entity()->mutable_data_type()->mutable_reference_data_type()->set_name(
        "refname");
      entity_response.mutable_entity()->mutable_file_descriptor();
      entity_response.mutable_entity()->mutable_properties()->Add()->CopyFrom(property);
      entity_response.mutable_entity()->mutable_parents()->Add()->CopyFrom(parent);
    
      Entity this_entity(&entity_response);
      Entity copy_entity(this_entity);
    
      EXPECT_EQ(this_entity, copy_entity);
      EXPECT_EQ(this_entity.GetVersionId(), copy_entity.GetVersionId());
      EXPECT_EQ(this_entity.GetValue(), copy_entity.GetValue());
      EXPECT_EQ(this_entity.GetDataType(), copy_entity.GetDataType());
      EXPECT_EQ(this_entity.GetId(), copy_entity.GetId());
      EXPECT_EQ(this_entity.GetName(), copy_entity.GetName());
      EXPECT_EQ(this_entity.GetDescription(), copy_entity.GetDescription());
      EXPECT_EQ(this_entity.ToString(), copy_entity.ToString());
      EXPECT_EQ(this_entity.GetErrors().ToString(), copy_entity.GetErrors().ToString());
      EXPECT_EQ(this_entity.GetWarnings().ToString(), copy_entity.GetWarnings().ToString());
      EXPECT_EQ(this_entity.GetInfos().ToString(), copy_entity.GetInfos().ToString());
      EXPECT_EQ(this_entity.GetProperties(), copy_entity.GetProperties());
    
      // change only description
      this_entity.SetDescription("new description");
      EXPECT_NE(this_entity, copy_entity);
      EXPECT_EQ(this_entity.GetVersionId(), copy_entity.GetVersionId());
      EXPECT_EQ(this_entity.GetValue(), copy_entity.GetValue());
      EXPECT_EQ(this_entity.GetDataType(), copy_entity.GetDataType());
      EXPECT_EQ(this_entity.GetId(), copy_entity.GetId());
      EXPECT_EQ(this_entity.GetName(), copy_entity.GetName());
      EXPECT_NE(this_entity.GetDescription(), copy_entity.GetDescription());
      EXPECT_NE(this_entity.ToString(), copy_entity.ToString());
    }
    
    TEST(test_entity, test_move_constructor) {
      ProtoParent parent;
      parent.set_description("the parent desc");
      parent.set_id("the parent id");
      parent.set_name("the parent name");
      ProtoProperty property;
      property.set_id("the-prop-id");
      property.set_description("the prop-desc");
      property.set_name("the-prop-name");
      property.mutable_value()->mutable_list_values()->mutable_values()->Add()->set_double_value(25.5);
      property.mutable_data_type()->mutable_list_data_type()->set_atomic_data_type(
        ProtoAtomicDataType::ATOMIC_DATA_TYPE_DOUBLE);
      EntityResponse entity_response;
      entity_response.mutable_errors()->Add()->set_code(25);
      entity_response.mutable_errors()->Mutable(0)->set_description("asdf");
      entity_response.mutable_warnings()->Add()->set_code(23);
      entity_response.mutable_warnings()->Mutable(0)->set_description("asdgsafdg");
      entity_response.mutable_infos()->Add()->set_code(235);
      entity_response.mutable_infos()->Mutable(0)->set_description("asdfsad");
      entity_response.mutable_entity()->set_id("the-id");
      entity_response.mutable_entity()->set_name("the-name");
      entity_response.mutable_entity()->set_role(ProtoEntityRole::ENTITY_ROLE_RECORD);
      entity_response.mutable_entity()->set_description("the description");
      entity_response.mutable_entity()->set_unit("the-unit");
      entity_response.mutable_entity()->mutable_value()->mutable_scalar_value()->set_string_value(
        "the-value");
      entity_response.mutable_entity()->mutable_version()->set_id("version-id");
      entity_response.mutable_entity()->mutable_data_type()->mutable_reference_data_type()->set_name(
        "refname");
      entity_response.mutable_entity()->mutable_file_descriptor();
      entity_response.mutable_entity()->mutable_properties()->Add()->CopyFrom(property);
      entity_response.mutable_entity()->mutable_parents()->Add()->CopyFrom(parent);
    
      Entity this_entity(&entity_response);
      std::string original_string = this_entity.ToString();
      Entity copy_entity(this_entity);
      EXPECT_EQ(this_entity, copy_entity);
    
      Entity move_entity(std::move(this_entity));
      EXPECT_NE(this_entity, copy_entity); // NOLINT
    
      EXPECT_EQ(move_entity, copy_entity);
      EXPECT_EQ(move_entity.GetVersionId(), copy_entity.GetVersionId());
      EXPECT_EQ(move_entity.GetValue(), copy_entity.GetValue());
      EXPECT_EQ(move_entity.GetDataType(), copy_entity.GetDataType());
      EXPECT_EQ(move_entity.GetId(), copy_entity.GetId());
      EXPECT_EQ(move_entity.GetName(), copy_entity.GetName());
      EXPECT_EQ(move_entity.GetDescription(), copy_entity.GetDescription());
      EXPECT_EQ(move_entity.ToString(), copy_entity.ToString());
      EXPECT_EQ(move_entity.GetErrors().ToString(), copy_entity.GetErrors().ToString());
      EXPECT_EQ(move_entity.GetWarnings().ToString(), copy_entity.GetWarnings().ToString());
      EXPECT_EQ(move_entity.GetInfos().ToString(), copy_entity.GetInfos().ToString());
      EXPECT_EQ(move_entity.GetProperties(), copy_entity.GetProperties());
    
      // change only description
      move_entity.SetDescription("new description");
      EXPECT_NE(move_entity, copy_entity);
      EXPECT_EQ(move_entity.GetVersionId(), copy_entity.GetVersionId());
      EXPECT_EQ(move_entity.GetValue(), copy_entity.GetValue());
      EXPECT_EQ(move_entity.GetDataType(), copy_entity.GetDataType());
      EXPECT_EQ(move_entity.GetId(), copy_entity.GetId());
      EXPECT_EQ(move_entity.GetName(), copy_entity.GetName());
      EXPECT_NE(move_entity.GetDescription(), copy_entity.GetDescription());
      EXPECT_NE(move_entity.ToString(), copy_entity.ToString());
    }
    
    TEST(test_entity, test_property_copy_constructor) {
      Property prop;
      prop.SetName("prop_name");
      prop.SetId("prop_id");
      prop.SetImportance(Importance::RECOMMENDED);
      prop.SetValue("prop_value");
      prop.SetUnit("prop_unit");
      prop.SetDataType("prop_dtype");
    
      Property other_prop(prop);
    
      EXPECT_EQ(prop, other_prop);
      EXPECT_EQ(prop.GetName(), other_prop.GetName());
      EXPECT_EQ(prop.GetId(), other_prop.GetId());
      EXPECT_EQ(prop.GetImportance(), other_prop.GetImportance());
      EXPECT_EQ(prop.GetValue().ToString(), other_prop.GetValue().ToString());
      EXPECT_EQ(prop.GetUnit(), other_prop.GetUnit());
      EXPECT_EQ(prop.GetDataType(), other_prop.GetDataType());
    }
    
    TEST(test_entity, test_property_copy_assignment) {
      Property prop;
      prop.SetName("prop_name");
      prop.SetId("prop_id");
      prop.SetImportance(Importance::RECOMMENDED);
      prop.SetValue("prop_value");
      prop.SetUnit("prop_unit");
      prop.SetDataType("prop_dtype");
    
      auto other_prop = prop;
      EXPECT_EQ(prop, other_prop);
      EXPECT_EQ(prop.GetName(), other_prop.GetName());
      EXPECT_EQ(prop.GetId(), other_prop.GetId());
      EXPECT_EQ(prop.GetImportance(), other_prop.GetImportance());
      EXPECT_EQ(prop.GetValue().ToString(), other_prop.GetValue().ToString());
      EXPECT_EQ(prop.GetUnit(), other_prop.GetUnit());
      EXPECT_EQ(prop.GetDataType(), other_prop.GetDataType());
    
      other_prop.SetName("other_prop_name");
      EXPECT_NE(prop, other_prop);
      EXPECT_NE(prop.GetName(), other_prop.GetName());
      EXPECT_EQ(prop.GetName(), "prop_name");
      EXPECT_EQ(other_prop.GetName(), "other_prop_name");
    }
    
    TEST(test_entity, test_property_move_assignment) {
      Property prop;
      prop.SetName("prop_name");
      prop.SetId("prop_id");
      prop.SetImportance(Importance::RECOMMENDED);
      prop.SetValue("prop_value");
      prop.SetUnit("prop_unit");
      prop.SetDataType("prop_dtype");
      const auto prop_string = prop.ToString();
    
      // we compare the moved one with this one
      const Property copy_prop(prop);
    
      Property other_prop = std::move(prop);
      EXPECT_NE(prop, copy_prop);              // NOLINT
      EXPECT_NE(prop, other_prop);             // NOLINT
      EXPECT_NE(prop.ToString(), prop_string); // NOLINT
    
      EXPECT_EQ(copy_prop.ToString(), prop_string);
      EXPECT_EQ(other_prop.ToString(), prop_string);
      EXPECT_EQ(copy_prop, other_prop);
      EXPECT_EQ(copy_prop.GetName(), other_prop.GetName());
      EXPECT_EQ(copy_prop.GetId(), other_prop.GetId());
      EXPECT_EQ(copy_prop.GetImportance(), other_prop.GetImportance());
      EXPECT_EQ(copy_prop.GetValue().ToString(), other_prop.GetValue().ToString());
      EXPECT_EQ(copy_prop.GetUnit(), other_prop.GetUnit());
      EXPECT_EQ(copy_prop.GetDataType(), other_prop.GetDataType());
    
      other_prop.SetName("other_prop_name");
      EXPECT_NE(copy_prop, other_prop);
      EXPECT_NE(copy_prop.GetName(), other_prop.GetName());
      EXPECT_EQ(copy_prop.GetName(), "prop_name");
      EXPECT_EQ(other_prop.GetName(), "other_prop_name");
    }
    
    TEST(test_entity, test_copy_to) {
      auto entity = Entity();
      entity.SetRole(Role::RECORD);
      entity.SetName("orignial_name");
    
      auto parent = Parent();
      parent.SetId("parent_id");
      parent.SetName("parent_name");
      entity.AppendParent(parent);
    
      auto prop = Property();
      prop.SetId("prop_id");
      prop.SetName("prop_name");
      entity.AppendProperty(prop);
    
      // create protobuf entity to which all fields ae copied and then a
      // CaoosDB entity from that protobuf entity.
      auto *proto_copy = google::protobuf::Arena::CreateMessage<ProtoEntity>(get_arena());
      entity.CopyTo(proto_copy);
      auto copied = Entity(proto_copy);
    
      EXPECT_EQ(entity.GetRole(), copied.GetRole());
      EXPECT_EQ(entity.GetName(), copied.GetName());
      EXPECT_EQ(copied.GetParents().at(0).GetId(), parent.GetId());
      EXPECT_EQ(copied.GetParents().at(0).GetName(), parent.GetName());
      EXPECT_EQ(copied.GetProperties().at(0).GetId(), prop.GetId());
      EXPECT_EQ(copied.GetProperties().at(0).GetName(), prop.GetName());
    }
    
    TEST(test_entity, test_insert_entity) {
      auto transaction = caosdb::transaction::Transaction(
        std::shared_ptr<transaction::EntityTransactionService::Stub>(nullptr),
        std::shared_ptr<transaction::FileTransmissionService::Stub>(nullptr));
    
      auto entity = Entity();
      entity.SetRole(Role::RECORD_TYPE);
      entity.SetName("entity_name");
    
      EXPECT_EQ(entity.GetRole(), Role::RECORD_TYPE);
      EXPECT_EQ(entity.GetName(), "entity_name");
    
      transaction.InsertEntity(&entity);
    
      EXPECT_EQ(entity.GetRole(), Role::RECORD_TYPE);
      EXPECT_EQ(entity.GetName(), "entity_name");
    }
    
    TEST(test_entity, test_insert_with_role) {
      auto transaction = caosdb::transaction::Transaction(
        std::shared_ptr<transaction::EntityTransactionService::Stub>(nullptr),
        std::shared_ptr<transaction::FileTransmissionService::Stub>(nullptr));
    
      auto entity = Entity();
      entity.SetRole(Role::PROPERTY);
      entity.SetDataType(AtomicDataType::DOUBLE);
      entity.SetName("Length");
      entity.SetUnit("m");
      entity.SetValue(5.5);
    
      transaction.InsertEntity(&entity);
    
      EXPECT_EQ(entity.GetRole(), Role::PROPERTY);
      EXPECT_TRUE(entity.GetDataType().IsAtomic());
      EXPECT_EQ(entity.GetDataType().GetAsAtomic(), AtomicDataType::DOUBLE);
      EXPECT_EQ(entity.GetName(), "Length");
      EXPECT_EQ(entity.GetUnit(), "m");
      EXPECT_TRUE(entity.GetValue().IsDouble());
      EXPECT_DOUBLE_EQ(entity.GetValue().GetAsDouble(), 5.5);
    }
    
    TEST(test_entity, test_insert_with_parent) {
      auto transaction = caosdb::transaction::Transaction(
        std::shared_ptr<transaction::EntityTransactionService::Stub>(nullptr),
        std::shared_ptr<transaction::FileTransmissionService::Stub>(nullptr));
    
      auto entity = Entity();
      entity.SetName("entity_name");
    
      auto parent = Parent();
      parent.SetId("parent_id");
      parent.SetName("parent_name");
      EXPECT_EQ(parent.GetId(), "parent_id");
      EXPECT_EQ(parent.GetName(), "parent_name");
    
      entity.AppendParent(parent);
    
      transaction.InsertEntity(&entity);
    
      EXPECT_EQ(entity.GetName(), "entity_name");
      EXPECT_EQ(entity.GetParents().size(), 1);
      auto inserted_parent = entity.GetParents().at(0);
      EXPECT_EQ(inserted_parent.GetId(), parent.GetId());
      EXPECT_EQ(inserted_parent.GetName(), parent.GetName());
    }
    
    TEST(test_entity, test_insert_with_property) {
      auto transaction = caosdb::transaction::Transaction(
        std::shared_ptr<transaction::EntityTransactionService::Stub>(nullptr),
        std::shared_ptr<transaction::FileTransmissionService::Stub>(nullptr));
    
      auto entity = Entity();
      entity.SetName("entity_name");
    
      auto prop = Property();
      prop.SetName("prop_name");
      prop.SetId("prop_id");
      prop.SetImportance(Importance::FIX);
      prop.SetValue(Value("prop_value"));
      prop.SetUnit("prop_unit");
      prop.SetDataType("prop_dtype");
    
      entity.AppendProperty(prop);
    
      transaction.InsertEntity(&entity);
    
      EXPECT_EQ(entity.GetProperties().size(), 1);
    
      const auto &inserted_prop = entity.GetProperties().at(0);
    
      EXPECT_EQ(prop.GetName(), inserted_prop.GetName());
      EXPECT_EQ(prop.GetId(), inserted_prop.GetId());
      EXPECT_EQ(prop.GetImportance(), inserted_prop.GetImportance());
      EXPECT_EQ(prop.GetValue().ToString(), inserted_prop.GetValue().ToString());
      EXPECT_EQ(prop.GetValue(), inserted_prop.GetValue());
      EXPECT_EQ(prop.GetUnit(), inserted_prop.GetUnit());
      EXPECT_EQ(prop.GetDataType(), inserted_prop.GetDataType());
    }
    
    TEST(test_entity, test_from_id_response) {
      IdResponse idResponse;
      idResponse.set_id("entity_id");
      auto *error = idResponse.add_errors();
      error->set_code(MessageCode::ENTITY_DOES_NOT_EXIST);
      error->set_description("error_desc");
    
      Entity entity(&idResponse);
    
      EXPECT_EQ(entity.GetId(), "entity_id");
      EXPECT_TRUE(entity.HasErrors());
      EXPECT_EQ(entity.GetErrors().size(), 1);
      EXPECT_EQ(entity.GetErrors().at(0).GetDescription(), "error_desc");
      EXPECT_EQ(entity.GetErrors().at(0).GetCode(), MessageCode::ENTITY_DOES_NOT_EXIST);
    
      IdResponse idr_warnings_and_infos;
      idr_warnings_and_infos.set_id("other_entity_id");
      auto *warning = idr_warnings_and_infos.add_warnings();
      warning->set_description("warning_desc");
      warning->set_code(MessageCode::ENTITY_HAS_NO_PROPERTIES);
      auto *info = idr_warnings_and_infos.add_infos();
      info->set_description("info_desc");
      info->set_code(MessageCode::UNSPECIFIED);
    
      Entity other_ent(&idr_warnings_and_infos);
    
      EXPECT_EQ(other_ent.GetId(), "other_entity_id");
      EXPECT_EQ(other_ent.GetWarnings().size(), 1);
      EXPECT_TRUE(other_ent.HasWarnings());
      EXPECT_EQ(other_ent.GetWarnings().at(0).GetDescription(), "warning_desc");
      EXPECT_EQ(other_ent.GetWarnings().at(0).GetCode(), MessageCode::ENTITY_HAS_NO_PROPERTIES);
      EXPECT_EQ(other_ent.GetInfos().size(), 1);
      EXPECT_EQ(other_ent.GetInfos().at(0).GetDescription(), "info_desc");
      EXPECT_EQ(other_ent.GetInfos().at(0).GetCode(), MessageCode::UNSPECIFIED);
    }
    
    TEST(test_entity, test_add_file_to_non_file_entity) {
      Entity entity;
      EXPECT_EQ(entity.SetLocalPath("local/path"), StatusCode::NOT_A_FILE_ENTITY);
    }
    
    TEST(test_entity, test_add_non_existing_file) {
      Entity entity;
      entity.SetRole(Role::FILE);
      EXPECT_EQ(entity.SetLocalPath("non-existing/path"), StatusCode::FILE_DOES_NOT_EXIST_LOCALLY);
    }
    
    TEST(test_entity, test_add_directory_path) {
      Entity entity;
      entity.SetRole(Role::FILE);
      EXPECT_EQ(entity.SetLocalPath("./"), StatusCode::PATH_IS_A_DIRECTORY);
    }
    
    TEST(test_entity, test_remove_property) {
      Entity entity;
      for (int i = 0; i < 5; i++) {
        auto name = "PROPERTY-" + std::to_string(i);
    
        Property property;
        property.SetName(name);
        EXPECT_EQ(property.GetName(), name);
    
        entity.AppendProperty(property);
        EXPECT_EQ(property.GetName(), name);
    
        // not initializing the cache
      }
      ASSERT_EQ(entity.GetProperties().size(), 5);
      for (int i = 5; i < 10; i++) {
        auto name = "PROPERTY-" + std::to_string(i);
    
        Property property;
        property.SetName(name);
        EXPECT_EQ(property.GetName(), name);
    
        entity.AppendProperty(property);
        EXPECT_EQ(property.GetName(), name);
    
        // initializing the cache
        const auto &property_2 = entity.GetProperties().at(i);
        EXPECT_EQ(property_2.GetName(), name);
      }
    
      ASSERT_EQ(entity.GetProperties().size(), 10);
    
      for (int i = 5; i < 10; i++) {
        // double checking the cache
        auto name = "PROPERTY-" + std::to_string(i);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
    
      // Remove at index 3
      // P0,P1,P2,P3,P4,P5,P6,P7,P8,P9
      //          ^
      // P0,P1,P2,   P4,P5,P6,P7,P8,P9
      entity.RemoveProperty(3);
    
      ASSERT_EQ(entity.GetProperties().size(), 9);
      for (int i = 0; i < 3; i++) {
        auto name = "PROPERTY-" + std::to_string(i);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
      for (int i = 3; i < 9; i++) {
        auto name = "PROPERTY-" + std::to_string(i + 1);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
    
      // Remove at index 6
      // P0,P1,P2,   P4,P5,P6,P7,P8,P9
      //                      ^
      // P0,P1,P2,   P4,P5,P6,   P8,P9
      entity.RemoveProperty(6);
      ASSERT_EQ(entity.GetProperties().size(), 8);
      for (int i = 0; i < 3; i++) {
        auto name = "PROPERTY-" + std::to_string(i);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
      for (int i = 3; i < 6; i++) {
        auto name = "PROPERTY-" + std::to_string(i + 1);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
      for (int i = 6; i < 8; i++) {
        auto name = "PROPERTY-" + std::to_string(i + 2);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
    
      // AppendProperty another property
      // P0,P1,P2,   P4,P5,P6,   P8,P9
      //                               ^
      // P0,P1,P2,   P4,P5,P6,   P8,P9,P10
      Property property10;
      property10.SetName("PROPERTY-10");
      entity.AppendProperty(property10);
      ASSERT_EQ(entity.GetProperties().size(), 9);
    
      std::cout << "[" << std::endl;
      for (int i = 0; i < 9; i++) {
        std::cout << "  " << entity.GetProperties().at(i).GetName() << ",\n";
      }
      std::cout << "]" << std::endl;
    
      for (int i = 0; i < 3; i++) {
        auto name = "PROPERTY-" + std::to_string(i);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
      for (int i = 3; i < 6; i++) {
        auto name = "PROPERTY-" + std::to_string(i + 1);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
      for (int i = 6; i < 9; i++) {
        auto name = "PROPERTY-" + std::to_string(i + 2);
        const auto &property = entity.GetProperties().at(i);
        EXPECT_EQ(property.GetName(), name);
      }
    }
    
    TEST(test_entity, test_property_iterator) {
      Entity entity;
      for (int i = 0; i < 5; i++) {
        auto name = "PROPERTY-" + std::to_string(i);
    
        Property property;
        property.SetName(name);
        EXPECT_EQ(property.GetName(), name);
    
        entity.AppendProperty(property);
      }
      ASSERT_EQ(entity.GetProperties().size(), 5);
      int counter = 0;
      for (auto &property : entity.GetProperties()) {
        // TODO(tf) Copy constructor was deleted
        // auto nonref_property = entity.GetProperties().at(counter);
        auto name = "PROPERTY-" + std::to_string(counter);
        EXPECT_EQ(property.GetName(), name);
        // EXPECT_EQ(nonref_property.GetName(), name);
        counter++;
      }
      EXPECT_EQ(counter, 5);
    }
    
    TEST(test_entity, test_description) {
      Entity entity;
      Property property;
      Parent parent;
    
      EXPECT_EQ(entity.GetDescription(), "");
      EXPECT_EQ(property.GetDescription(), "");
      EXPECT_EQ(parent.GetDescription(), "");
    
      entity.SetDescription("desc entity");
      property.SetDescription("desc property");
      // Parent has not setter
      ProtoParent protoParent;
      protoParent.set_description("desc parent");
      parent = Parent(&protoParent);
    
      EXPECT_EQ(entity.GetDescription(), "desc entity");
      EXPECT_EQ(property.GetDescription(), "desc property");
      EXPECT_EQ(parent.GetDescription(), "desc parent");
    }
    
    TEST(test_entity, test_role) {
      Entity entity;
      entity.SetRole(Role::RECORD_TYPE);
    
      EXPECT_EQ(entity.GetRole(), Role::RECORD_TYPE);
    }
    
    TEST(test_entity, test_add_file) {
      Entity entity;
      entity.SetRole(Role::FILE);
      EXPECT_EQ(entity.SetLocalPath(TEST_DATA_DIR + "/test.json"), StatusCode::SUCCESS);
    }
    
    TEST(test_entity, test_move_assign) {
      Entity entity1;
      entity1.SetRole(Role::RECORD_TYPE);
      entity1.SetName("E1");
      entity1.SetValue("some-string-1");
      entity1.SetDataType("some-other-string-1");
    
      Entity entity2;
      entity1.SetRole(Role::RECORD);
      entity1.SetName("E2");
      entity1.SetValue("some-string-2");
      entity1.SetDataType("some-other-string-2");
    
      const Entity copy1(entity1); // NOLINT
      const Entity copy2(entity2); // NOLINT
    
      EXPECT_EQ(copy1, entity1);
      EXPECT_EQ(copy2, entity2);
    
      // Swap
      Entity tmp;
      tmp = std::move(entity1);
      entity1 = std::move(entity2);
      entity2 = std::move(tmp);
    
      EXPECT_EQ(copy2, entity1);
      EXPECT_EQ(copy1, entity2);
    }
    
    TEST(test_entity, test_entity_to_string) {
      Entity entity;
      EXPECT_EQ(entity.ToString(), "{}\n");
    
      entity.SetRole(Role::PROPERTY);
      EXPECT_EQ(entity.ToString(), "{\n \"role\": \"ENTITY_ROLE_PROPERTY\"\n}\n");
    
      entity.SetValue(Value());
      EXPECT_EQ(entity.ToString(), "{\n \"role\": \"ENTITY_ROLE_PROPERTY\"\n}\n");
    
      entity.SetDataType(DataType());
      EXPECT_EQ(entity.ToString(), "{\n \"role\": \"ENTITY_ROLE_PROPERTY\"\n}\n");
    }
    
    TEST(test_entity, test_properties_to_string) {
      Entity entity;
      EXPECT_EQ(entity.GetProperties().ToString(), "[]\n");
    
      Property property;
      property.SetName("Prop1");
      entity.AppendProperty(property);
      EXPECT_EQ(entity.GetProperties().ToString(), "[\n{\n \"name\": \"Prop1\"\n}\n]\n");
    
      Property property2;
      property2.SetName("Prop2");
      entity.AppendProperty(property2);
      EXPECT_EQ(entity.GetProperties().ToString(),
                "[\n{\n \"name\": \"Prop1\"\n},\n{\n \"name\": \"Prop2\"\n}\n]\n");
    }
    
    TEST(test_entity, test_property_to_string) {
      Property property;
      EXPECT_EQ(property.ToString(), "{}\n");
    
      property.SetDataType(AtomicDataType::DOUBLE);
      EXPECT_EQ(property.ToString(),
                "{\n \"dataType\": {\n  \"atomicDataType\": \"ATOMIC_DATA_TYPE_DOUBLE\"\n }\n}\n");
    }
    
    TEST(test_entity, test_parents_to_string) {
      Parent parent;
      parent.SetName("the name");
    
      Entity entity;
      entity.AppendParent(parent);
    
      EXPECT_EQ(entity.GetParents().ToString(), "[\n{\n \"name\": \"the name\"\n}\n]\n");
    }
    
    TEST(test_entity, test_parent_to_string) {
      Parent parent;
      EXPECT_EQ(parent.ToString(), "{}\n");
    
      parent.SetName("the name");
      EXPECT_EQ(parent.ToString(), "{\n \"name\": \"the name\"\n}\n");
    }
    
    TEST(test_entity, test_messages_to_string) {
      IdResponse idResponse;
      idResponse.set_id("entity_id");
      auto *error = idResponse.add_errors();
      error->set_code(MessageCode::ENTITY_DOES_NOT_EXIST);
      error->set_description("error_desc");
    
      Entity entity(&idResponse);
    
      // Messages are not printed, currently.
      EXPECT_EQ(entity.ToString(), "{\n \"id\": \"entity_id\",\n \"version\": {}\n}\n");
      EXPECT_EQ(entity.GetErrors().ToString(),
                "[\n{\n \"code\": 2,\n \"description\": \"error_desc\"\n}\n]\n");
    }
    
    TEST(test_entity, test_message_to_string) {
      IdResponse idResponse;
      idResponse.set_id("entity_id");
      auto *error = idResponse.add_errors();
      error->set_code(MessageCode::ENTITY_DOES_NOT_EXIST);
      error->set_description("error_desc");
    
      Entity entity(&idResponse);
    
      // Messages are not printed, currently.
      EXPECT_EQ(entity.ToString(), "{\n \"id\": \"entity_id\",\n \"version\": {}\n}\n");
      EXPECT_EQ(entity.GetErrors().at(0).ToString(),
                "{\n \"code\": 2,\n \"description\": \"error_desc\"\n}\n");
    }
    
    } // namespace caosdb::entity