diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h index 42d376698872e086c05a5905484e2f63c11dd346..771ca8c0859c3b462d5fbf6575e2e2569af2d61f 100644 --- a/include/caosdb/data_type.h +++ b/include/caosdb/data_type.h @@ -140,6 +140,21 @@ protected: class DataType : public ScalarProtoMessageWrapper<ProtoDataType> { public: + /** + * Copy constructor. + */ + inline DataType(const DataType &other) + : DataType(ProtoMessageWrapper<ProtoDataType>::CopyProtoMessage(other.wrapped)) {} + + /** + * Move constructor. + */ + inline DataType(DataType &&other) : DataType(other.wrapped) { + other.wrapped = nullptr; + other.list_data_type.reset(); + other.reference_data_type.reset(); + } + DataType(ProtoDataType *wrapped) : ScalarProtoMessageWrapper<ProtoDataType>(wrapped) {} DataType() : ScalarProtoMessageWrapper<ProtoDataType>(static_cast<ProtoDataType *>(nullptr)) {} /** @@ -166,6 +181,8 @@ public: } } + ~DataType() = default; + inline static auto ListOf(const AtomicDataType &atomic_data_type) -> DataType { return DataType(atomic_data_type, true); } @@ -227,6 +244,37 @@ public: return this->wrapped == other.wrapped; } + /** + * Copy assignment operator. + */ + inline auto operator=(const DataType &other) -> DataType & { + if (this != &other) { + this->reference_data_type.reset(); + this->list_data_type.reset(); + if (other.wrapped != nullptr) { + this->wrapped = ProtoMessageWrapper<ProtoDataType>::CopyProtoMessage(other.wrapped); + } else { + this->wrapped = nullptr; + } + } + return *this; + } + + /** + * Move assignment operator. + */ + inline auto operator=(DataType &&other) -> DataType & { + if (this != &other) { + this->wrapped = other.wrapped; + other.wrapped = nullptr; + other.reference_data_type.reset(); + this->reference_data_type.reset(); + other.list_data_type.reset(); + this->list_data_type.reset(); + } + return *this; + } + friend class Entity; friend class Property; diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h index 6de939c37f19d9419815dcb8b7001fd19050133f..0e34e43092652e05f495b3715dc337b9de6f6989 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -51,8 +51,8 @@ #include <random> // for mt19937, rand... #include <stdexcept> // for out_of_range #include <string> // for string, basic... -#include <vector> // for vector #include <utility> // for move +#include <vector> // for vector namespace caosdb::entity { using boost::filesystem::exists; @@ -187,6 +187,32 @@ public: return result.append(std::string("]\n")); } + /** + * Return true if the underlying Protobuf messages have the same + * serialization. + */ + inline auto operator==(const RepeatedPtrFieldWrapper<T, P> &other) const noexcept -> bool { + if (this->wrapped != nullptr && other.wrapped != nullptr && this->size() == other.size()) { + for (int i = 0; i < this->size(); i++) { + if (this->wrapped->Get(i).SerializeAsString() != + other.wrapped->Get(i).SerializeAsString()) { + return false; + } + } + return true; + } + // last chance for "true": both nullptr? + return this->wrapped == other.wrapped; + } + + /** + * Return true if the underlying Protobuf messages have a different + * serialization. + */ + inline auto operator!=(const RepeatedPtrFieldWrapper<T, P> &other) const noexcept -> bool { + return !(*this == other); + } + protected: RepeatedPtrFieldWrapper() : ProtoMessageWrapper<RepeatedPtrField<P>>(){}; explicit inline RepeatedPtrFieldWrapper(RepeatedPtrField<P> *wrapped) @@ -337,15 +363,13 @@ private: */ class Messages : public RepeatedPtrFieldWrapper<Message, ProtoMessage> { public: - ~Messages(); - friend class Entity; // TODO(fspreck) Same here. // friend class Parent; // friend class Property; private: - inline Messages() : RepeatedPtrFieldWrapper(){}; + inline Messages() : RepeatedPtrFieldWrapper<Message, ProtoMessage>(){}; }; /** @@ -359,6 +383,37 @@ class Parent : public ScalarProtoMessageWrapper<ProtoParent> { public: explicit inline Parent(ProtoParent *wrapped) : ScalarProtoMessageWrapper<ProtoParent>(wrapped){}; Parent() : ScalarProtoMessageWrapper<ProtoParent>(){}; + ~Parent() = default; + + /** + * Copy constructor. + */ + inline Parent(const Parent &other) + : Parent(ProtoMessageWrapper<ProtoParent>::CopyProtoMessage(other.wrapped)) {} + + /** + * Move constructor. + */ + inline Parent(Parent &&other) : Parent(other.wrapped) { other.wrapped = nullptr; } + + /** + * Copy assignment operator. + */ + inline auto operator=(const Parent &other) -> Parent & { + if (this != &other) { + this->wrapped->CopyFrom(*other.wrapped); + } + return *this; + } + + /** + * Move assignment operator. + */ + inline auto operator=(Parent &&other) -> Parent & { + this->wrapped = other.wrapped; + other.wrapped = nullptr; + return *this; + } /** * Return the id of the parent entity. @@ -426,14 +481,13 @@ private: */ class Parents : public RepeatedPtrFieldWrapper<Parent, ProtoParent> { public: - ~Parents() = default; friend class Entity; private: - inline Parents() : RepeatedPtrFieldWrapper(){}; + inline Parents() : RepeatedPtrFieldWrapper<Parent, ProtoParent>(){}; explicit inline Parents( ::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent> *wrapped) - : RepeatedPtrFieldWrapper(wrapped){}; + : RepeatedPtrFieldWrapper<Parent, ProtoParent>(wrapped){}; }; /** @@ -456,13 +510,10 @@ public: /** * Move constructor. */ - inline Property(Property &&other) : Property() { + inline Property(Property &&other) : Property(other.wrapped) { CAOSDB_LOG_TRACE(logger_name) << "Property::Property(Property &&) " << "- Move constructor"; - this->wrapped = std::move(other.wrapped); - this->value.wrapped = this->wrapped->mutable_value(); - this->data_type.wrapped = this->wrapped->mutable_data_type(); - + other.wrapped = nullptr; other.data_type.wrapped = nullptr; other.value.wrapped = nullptr; } @@ -477,6 +528,8 @@ public: : ScalarProtoMessageWrapper<ProtoProperty>(), value(static_cast<ProtoValue *>(nullptr)), data_type(static_cast<ProtoDataType *>(nullptr)){}; + ~Property() = default; + /** * Return the id of this property */ @@ -563,8 +616,12 @@ public: CAOSDB_LOG_TRACE(logger_name) << "Property::operator=(const Property &) " << "- Copy assignment operator"; this->wrapped->CopyFrom(*other.wrapped); - this->value = Value(this->wrapped->mutable_value()); - this->data_type = DataType(this->wrapped->mutable_data_type()); + + this->value.wrapped = (this->wrapped->has_value() ? this->wrapped->mutable_value() + : static_cast<ProtoValue *>(nullptr)); + this->data_type.wrapped = + (this->wrapped->has_data_type() ? this->wrapped->mutable_data_type() + : static_cast<ProtoDataType *>(nullptr)); return *this; } @@ -574,7 +631,8 @@ public: auto operator=(Property &&other) -> Property & { CAOSDB_LOG_TRACE(logger_name) << "Property::operator=(Property &&) " << "- Move assignment operator"; - this->wrapped = std::move(other.wrapped); + this->wrapped = other.wrapped; + other.wrapped = nullptr; this->value = std::move(other.value); this->data_type = std::move(other.data_type); return *this; @@ -606,7 +664,6 @@ private: */ class Properties : public RepeatedPtrFieldWrapper<Property, ProtoProperty> { public: - ~Properties() = default; friend class Entity; private: @@ -624,17 +681,23 @@ private: * Overview of the Constructors: * * <li> Entity() - Calls Entity(ProtoEntity *) with a fresh ProtoEntity - * <li> Entity(Entity) - Copy constructor, calls Entity(ProtoEntity *) after copying wrapped - * ProtoEntity of the original, then also copies all Messages. <li> Entity(ProtoEntity *) - The - * workhorse of the constructors. Initializes everything and does not call other Entity - * constructors. <li> Entity(EntityResponse *) - Constructor which is used by the Transaction class - * to create an Entity from the server's response, calls Entity(ProtoEntity). <li> Entity(IdResponse - * *) - Constructor which is used by the Transaction class to create an Entity from the servers's - * response. calls Entity(), then moves the data to the wrapped ProtoEntity. - * + * <li> Entity(const Entity&) - Copy constructor, calls Entity(ProtoEntity *) after + * copying wrapped ProtoEntity of the original, then also copies all Messages. + * <li> Entity(ProtoEntity *) - The workhorse of the constructors. Initializes + * everything and does not call other Entity constructors. + * <li> Entity(EntityResponse *) - Constructor which is used by the Transaction class + * to create an Entity from the server's response, calls Entity(ProtoEntity). + * <li> Entity(IdResponse *) - Constructor which is used by the Transaction + * class to create an Entity from the servers's response. calls Entity(), + * then moves the data to the wrapped ProtoEntity. + * <li> Entity(Entity&&) - Move constructor, calls Entity(ProtoEntity *), then + * moves the messages and resets the original, */ class Entity : public ScalarProtoMessageWrapper<ProtoEntity> { public: + /** + * Copy constructor. + */ inline Entity(const Entity &original) : Entity(ProtoMessageWrapper::CopyProtoMessage(original.wrapped)) { this->errors.wrapped->CopyFrom(*original.errors.wrapped); @@ -671,6 +734,58 @@ public: parents.wrapped = this->wrapped->mutable_parents(); }; + ~Entity() = default; + + /** + * Move constructor. + */ + explicit inline Entity(Entity &&original) : Entity(original.wrapped) { + original.wrapped = nullptr; + original.value.wrapped = nullptr; + original.data_type.wrapped = nullptr; + original.properties.wrapped = nullptr; + original.parents.wrapped = nullptr; + this->errors = std::move(original.errors); + this->warnings = std::move(original.warnings); + this->infos = std::move(original.infos); + }; + + /** + * Move assignment operator. + */ + auto operator=(Entity &&other) -> Entity & { + this->wrapped = other.wrapped; + other.wrapped = nullptr; + this->data_type = std::move(other.data_type); + this->value = std::move(other.value); + this->properties = std::move(other.properties); + this->parents = std::move(other.parents); + this->file_descriptor = std::move(other.file_descriptor); + this->errors = std::move(other.errors); + this->warnings = std::move(other.warnings); + this->infos = std::move(other.infos); + return *this; + } + + /** + * Copy assignment operator. + */ + auto operator=(const Entity &other) -> Entity & { + this->wrapped->CopyFrom(*other.wrapped); + this->data_type = other.data_type; + this->value = other.value; + this->properties = other.properties; + this->parents = other.parents; + this->file_descriptor.local_path = boost::filesystem::path(other.file_descriptor.local_path); + this->file_descriptor.file_transmission_id->CopyFrom( + *other.file_descriptor.file_transmission_id); + this->file_descriptor.wrapped->CopyFrom(*other.file_descriptor.wrapped); + this->errors = other.errors; + this->warnings = other.warnings; + this->infos = other.infos; + return *this; + } + [[nodiscard]] inline auto GetId() const noexcept -> const std::string & { return this->wrapped->id(); }; @@ -787,6 +902,15 @@ public: infos.Clear(); } + /** + * Return true if the other entity is equal to to this entity. + * + * This method ignores the errors, warnings and info messages. + */ + inline auto operator==(const Entity &other) const noexcept -> bool { + return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString(); + } + private: inline auto GetNextFileId() -> std::string { std::string str = "0123456789abcdef"; diff --git a/include/caosdb/file_transmission/file_reader.h b/include/caosdb/file_transmission/file_reader.h index 67c1247fa97cc43e28064b4e0da81812f41b231a..5820c1e9294c76f0f777a6e7cfae9cde7ebf490f 100644 --- a/include/caosdb/file_transmission/file_reader.h +++ b/include/caosdb/file_transmission/file_reader.h @@ -52,6 +52,7 @@ #include <boost/filesystem/fstream.hpp> // for ifstream #include <boost/filesystem/operations.hpp> // for exists #include <boost/filesystem/path.hpp> // for path +#include <cstddef> // for size_t #include <fstream> // for ifstream, size_t #include <string> // for string diff --git a/include/caosdb/protobuf_helper.h b/include/caosdb/protobuf_helper.h index 4dfc11c396ded34db6bb2cbed2c938a5402dd7c7..63b2c54cdfaae5eef33705ac7074e11c1caf3653 100644 --- a/include/caosdb/protobuf_helper.h +++ b/include/caosdb/protobuf_helper.h @@ -70,11 +70,7 @@ public: * serialization. */ inline auto operator!=(const ProtoMessageWrapper<P> &other) const noexcept -> bool { - if (this->wrapped != nullptr && other.wrapped != nullptr) { - return this->wrapped->SerializeAsString() != other.wrapped->SerializeAsString(); - } - // only one is nullptr? - return this->wrapped != other.wrapped; + return !(*this == other); } protected: diff --git a/requirements.txt b/requirements.txt index 4bf95a29fc3c9d28931a25664c2456f22041be3f..76372a8dce89684cb0c5490ff3d5afa916ea2f9c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,28 +1,29 @@ attrs==21.2.0 bottle==0.12.19 -certifi==2021.5.30 +certifi==2021.10.8 chardet==4.0.0 +charset-normalizer==2.0.7 colorama==0.4.4 -conan==1.40.3 -deprecation==2.0.7 -distro==1.5.0 +conan==1.41.0 +deprecation==2.1.0 +distro==1.6.0 fasteners==0.16.3 future==0.18.2 -idna==2.10 +idna==3.2 Jinja2==2.11.3 -jsonschema==3.2.0 +jsonschema==4.1.0 MarkupSafe==2.0.1 node-semver==0.6.1 -packaging==20.9 +packaging==21.0 patch-ng==1.17.4 pluginbase==1.0.1 -Pygments==2.9.0 +Pygments==2.10.0 PyJWT==1.7.1 pyparsing==2.4.7 pyrsistent==0.18.0 -python-dateutil==2.8.1 +python-dateutil==2.8.2 PyYAML==5.4.1 -requests==2.25.1 -six==1.15.0 -tqdm==4.61.1 -urllib3==1.25.11 +requests==2.26.0 +six==1.16.0 +tqdm==4.62.3 +urllib3==1.26.7 diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp index bb73431e4af00ed1db48b8f87fa883db6f4f9b31..a3872e4cb2be380adca644b7c7a109c0fec2b3c2 100644 --- a/src/caosdb/entity.cpp +++ b/src/caosdb/entity.cpp @@ -38,8 +38,6 @@ using ProtoFileDescriptor = caosdb::entity::v1alpha1::FileDescriptor; using caosdb::utility::get_arena; using google::protobuf::Arena; -Messages::~Messages() = default; - // Parent ///////////////////////////////////////////////////////////////////// auto Parent::SetName(const std::string &name) -> void { this->wrapped->set_name(name); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index aefe6846d23f2cc3a145cbf6158101e7e1bb3df4..9cacb63b0f6b74368508df6920e2dc03db81a929 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -41,7 +41,7 @@ set(test_cases # special linting for tests set(_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS - "${_CMAKE_CXX_CLANG_TIDY_CHECKS},-cert-err58-cpp,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-owning-memory,-modernize-use-trailing-return-type,-google-readability-avoid-underscore-in-googletest-name,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-readability-function-cognitive-complexity,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes" + "${_CMAKE_CXX_CLANG_TIDY_CHECKS},-cert-err58-cpp,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-owning-memory,-modernize-use-trailing-return-type,-google-readability-avoid-underscore-in-googletest-name,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto,-readability-function-cognitive-complexity,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-clang-analyzer-cplusplus.Move" ) # add special cmake functions for gtest diff --git a/test/test_data_type.cpp b/test/test_data_type.cpp index 78e5100f3ce984ece46918df4aca9ffb8f1d2522..b1e714d705b23dcaef6354e17cf94e411f1d8335 100644 --- a/test/test_data_type.cpp +++ b/test/test_data_type.cpp @@ -129,4 +129,54 @@ TEST(test_data_type, test_data_type_to_string) { EXPECT_EQ(data_type3.ToString(), "{\n \"atomicDataType\": \"ATOMIC_DATA_TYPE_INTEGER\"\n}\n"); } +TEST(test_data_type, data_type_copy_constructor) { + DataType data_type("person", true); + const auto dt_string = data_type.ToString(); + + // copy + const DataType copy_data_type(data_type); // NOLINT (explicit copy) + EXPECT_EQ(copy_data_type, data_type); + EXPECT_EQ(dt_string, copy_data_type.ToString()); +} + +TEST(test_data_type, data_type_move_constructor) { + DataType data_type("person", true); + const auto dt_string = data_type.ToString(); + + // copy for testing + const DataType copy_data_type(data_type); + // move + const DataType move_data_type(std::move(data_type)); // NOLINT + EXPECT_NE(data_type, copy_data_type); // NOLINT + EXPECT_NE(data_type.ToString(), dt_string); // NOLINT + + EXPECT_EQ(copy_data_type, move_data_type); + EXPECT_EQ(move_data_type.ToString(), dt_string); +} + +TEST(test_data_type, data_type_copy_assignment) { + DataType data_type("person", true); + const auto dt_string = data_type.ToString(); + + // copy + DataType copy_data_type = data_type; // NOLINT (explicit copy) + EXPECT_EQ(copy_data_type, data_type); + EXPECT_EQ(dt_string, copy_data_type.ToString()); +} + +TEST(test_data_type, data_type_move_assignment) { + DataType data_type("person", true); + const auto dt_string = data_type.ToString(); + + // copy for testing + const DataType copy_data_type(data_type); + // move + DataType move_data_type = std::move(data_type); // NOLINT + EXPECT_NE(data_type, copy_data_type); // NOLINT + EXPECT_NE(data_type.ToString(), dt_string); // NOLINT + + EXPECT_EQ(copy_data_type, move_data_type); + EXPECT_EQ(move_data_type.ToString(), dt_string); +} + } // namespace caosdb::entity diff --git a/test/test_entity.cpp b/test/test_entity.cpp index de0206f8b547884b7ae438b3bd4873230b9128d8..f66ee3f7185ee594f8465adde2e59fba2b62a328 100644 --- a/test/test_entity.cpp +++ b/test/test_entity.cpp @@ -44,7 +44,11 @@ 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(); @@ -138,7 +142,128 @@ TEST(test_entity, test_append_property) { EXPECT_EQ(prop.GetDataType(), same_prop.GetDataType()); } -TEST(test_entity, test_property_copy_constructor) { +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"); @@ -158,7 +283,7 @@ TEST(test_entity, test_property_copy_constructor) { EXPECT_EQ(prop.GetDataType(), other_prop.GetDataType()); } -TEST(test_entity, test_property_copy_assignment) { +TEST(test_entity, property_copy_assignment) { Property prop; prop.SetName("prop_name"); prop.SetId("prop_id"); @@ -183,7 +308,7 @@ TEST(test_entity, test_property_copy_assignment) { EXPECT_EQ(other_prop.GetName(), "other_prop_name"); } -TEST(test_entity, test_property_move_assignment) { +TEST(test_entity, property_move_assignment) { Property prop; prop.SetName("prop_name"); prop.SetId("prop_id"); @@ -191,15 +316,18 @@ TEST(test_entity, test_property_move_assignment) { 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_EQ(prop.ToString(), "{}"); NOLINT + 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()); @@ -215,6 +343,127 @@ TEST(test_entity, test_property_move_assignment) { 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); @@ -565,6 +814,35 @@ TEST(test_entity, test_add_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"); @@ -600,8 +878,8 @@ TEST(test_entity, test_property_to_string) { EXPECT_EQ(property.ToString(), "{}\n"); property.SetDataType(AtomicDataType::DOUBLE); - EXPECT_EQ(property.ToString(), - "{\n \"dataType\": {\n \"atomicDataType\": \"ATOMIC_DATA_TYPE_DOUBLE\"\n }\n}\n"); + EXPECT_EQ(property.ToString(), "{\n \"dataType\": {\n \"atomicDataType\": " + "\"ATOMIC_DATA_TYPE_DOUBLE\"\n }\n}\n"); } TEST(test_entity, test_parents_to_string) { diff --git a/test/test_value.cpp b/test/test_value.cpp index 241f2bd0ce2a7291184a79cdaa0612f2b99fa204..ecf87d01f816048ebce95a0f63262a38fe8c8244 100644 --- a/test/test_value.cpp +++ b/test/test_value.cpp @@ -188,9 +188,9 @@ TEST(test_value, test_value_to_string) { EXPECT_EQ(value3.ToString(), "{\n \"scalarValue\": {\n \"doubleValue\": 2.6\n }\n}\n"); Value value4(std::vector<bool>{true, false}); - EXPECT_EQ(value4.ToString(), - "{\n \"listValues\": {\n \"values\": [\n {\n \"booleanValue\": true\n },\n " - "{\n \"booleanValue\": false\n }\n ]\n }\n}\n"); + EXPECT_EQ(value4.ToString(), "{\n \"listValues\": {\n \"values\": [\n {\n " + "\"booleanValue\": true\n },\n " + "{\n \"booleanValue\": false\n }\n ]\n }\n}\n"); } } // namespace caosdb::entity