/* * * 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, entity_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, entity_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, 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, 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, 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, property_move_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"); 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, parent_copy_constructor) { Parent parent; parent.SetId("par_id"); parent.SetName("par_name"); // copy const Parent copy_parent(parent); EXPECT_EQ(copy_parent, parent); EXPECT_EQ(copy_parent.GetId(), parent.GetId()); EXPECT_EQ(copy_parent.GetName(), parent.GetName()); // change something parent.SetName("new_name"); EXPECT_NE(copy_parent, parent); EXPECT_EQ(copy_parent.GetId(), parent.GetId()); EXPECT_NE(copy_parent.GetName(), parent.GetName()); } TEST(test_entity, parent_move_constructor) { Parent parent; parent.SetId("par_id"); parent.SetName("par_name"); const auto parent_string = parent.ToString(); // copy for testing const Parent copy_parent = parent; // move Parent move_parent(std::move(parent)); EXPECT_NE(parent, copy_parent); // NOLINT EXPECT_NE(parent, move_parent); // NOLINT EXPECT_NE(parent.ToString(), parent_string); // NOLINT EXPECT_EQ(copy_parent, move_parent); EXPECT_EQ(copy_parent.GetId(), move_parent.GetId()); EXPECT_EQ(copy_parent.GetName(), move_parent.GetName()); // change something move_parent.SetName("new_name"); EXPECT_NE(copy_parent, move_parent); EXPECT_EQ(copy_parent.GetId(), move_parent.GetId()); EXPECT_NE(copy_parent.GetName(), move_parent.GetName()); } TEST(test_entity, parent_copy_assignment) { Parent parent; parent.SetId("par_id"); parent.SetName("par_name"); // copy const Parent copy_parent = parent; EXPECT_EQ(copy_parent, parent); EXPECT_EQ(copy_parent.GetId(), parent.GetId()); EXPECT_EQ(copy_parent.GetName(), parent.GetName()); // change something parent.SetName("new_name"); EXPECT_NE(copy_parent, parent); EXPECT_EQ(copy_parent.GetId(), parent.GetId()); EXPECT_NE(copy_parent.GetName(), parent.GetName()); } TEST(test_entity, parent_move_assignment) { Parent parent; parent.SetId("par_id"); parent.SetName("par_name"); const auto parent_string = parent.ToString(); // copy for testing const Parent copy_parent = parent; // move Parent move_parent = std::move(parent); EXPECT_NE(parent, copy_parent); // NOLINT EXPECT_NE(parent, move_parent); // NOLINT EXPECT_NE(parent.ToString(), parent_string); // NOLINT EXPECT_EQ(copy_parent, move_parent); EXPECT_EQ(copy_parent.GetId(), move_parent.GetId()); EXPECT_EQ(copy_parent.GetName(), move_parent.GetName()); // change something move_parent.SetName("new_name"); EXPECT_NE(copy_parent, move_parent); EXPECT_EQ(copy_parent.GetId(), move_parent.GetId()); EXPECT_NE(copy_parent.GetName(), move_parent.GetName()); } 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, entity_move_assignment) { 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