diff --git a/conanfile.py b/conanfile.py index 04d2b1f527b0c5936c0c9a5c7d6d20a98446f1bb..3495107311d4e0d467313dc4d8b088a508349d55 100644 --- a/conanfile.py +++ b/conanfile.py @@ -14,9 +14,9 @@ class CaosdbConan(ConanFile): default_options = {"shared": False, "fPIC": True} generators = "cmake" requires = [ - ("boost/1.76.0"), + ("boost/1.77.0"), ("gtest/1.11.0"), - ("grpc/1.38.0"), + ("grpc/1.39.1"), ] exports = "*.cpp", "*.h", "*.cmake", "*CMakeLists.txt", "*.in", "*.proto", "*.c" exports_sources = "src", "doc", "include", "test", "cmake", "proto" diff --git a/include/caosdb/authentication.h b/include/caosdb/authentication.h index 070346c9366d89e7476f125b74feaea4ceb40a32..8e98a17e6d94fe118cf2fc478efbbf77733be4a6 100644 --- a/include/caosdb/authentication.h +++ b/include/caosdb/authentication.h @@ -28,10 +28,10 @@ * @brief Configuration and setup of the client authentication. */ #include "caosdb/utility.h" // for base64_encode -#include "grpcpp/impl/codegen/interceptor.h" // for Status -#include "grpcpp/impl/codegen/security/auth_context.h" // for AuthContext -#include "grpcpp/impl/codegen/status.h" // for Status -#include "grpcpp/impl/codegen/string_ref.h" // for string_ref +#include <grpcpp/impl/codegen/interceptor.h> // for Status +#include <grpcpp/impl/codegen/security/auth_context.h> // for AuthContext +#include <grpcpp/impl/codegen/status.h> // for Status +#include <grpcpp/impl/codegen/string_ref.h> // for string_ref #include <grpcpp/security/credentials.h> // for CallCredentials #include <map> // for multimap #include <memory> // for shared_ptr diff --git a/include/caosdb/certificate_provider.h b/include/caosdb/certificate_provider.h index e7d7a156efeaf05435fd3ccb8029549a82e38442..197ab7277a8110063351718897b65c8db3289768 100644 --- a/include/caosdb/certificate_provider.h +++ b/include/caosdb/certificate_provider.h @@ -22,7 +22,8 @@ #ifndef CAOSDB_CERTIFICATE_PROVIDER_H #define CAOSDB_CERTIFICATE_PROVIDER_H -#include "boost/filesystem/path.hpp" // for path +#include <boost/filesystem/path.hpp> // for path + namespace caosdb::configuration { using boost::filesystem::path; diff --git a/include/caosdb/configuration.h b/include/caosdb/configuration.h index 2c521e7b0f36c351dabd6f7341ea3bb393fd402c..83b47810e7756555c201b57538b6f8ba738d1e43 100644 --- a/include/caosdb/configuration.h +++ b/include/caosdb/configuration.h @@ -21,21 +21,21 @@ #ifndef CAOSDB_CONFIGURATION_H #define CAOSDB_CONFIGURATION_H -#include "boost/filesystem/operations.hpp" // for exists -#include "boost/filesystem/path.hpp" // for path -#include "boost/json/object.hpp" // for object -#include "boost/json/value.hpp" // for value -#include "boost/json/value_ref.hpp" // IWYU pragma: keep -// IWYU pragma: no_include "boost/json/fwd.hpp" #include "caosdb/authentication.h" // for Authenticator, PlainPassw... #include "caosdb/certificate_provider.h" // for CertificateProvider, path #include "caosdb/exceptions.h" // for ConfigurationError -#include "caosdb/logging.h" +#include "caosdb/logging.h" // for CAOSDB_LOG_... #include "caosdb/utility.h" // for load_json_file -#include "grpcpp/security/credentials.h" // for ChannelCredentials -#include <iosfwd> // for ostream -#include <memory> // for unique_ptr, shared_ptr -#include <string> // for string +// IWYU pragma: no_include "boost/json/fwd.hpp" +#include <boost/filesystem/operations.hpp> // for exists +#include <boost/filesystem/path.hpp> // for path +#include <boost/json/object.hpp> // for object +#include <boost/json/value.hpp> // for value +#include <boost/json/value_ref.hpp> // IWYU pragma: keep +#include <grpcpp/security/credentials.h> // for ChannelCredentials +#include <iosfwd> // for ostream +#include <memory> // for unique_ptr, shared_ptr +#include <string> // for string namespace caosdb::configuration { using boost::filesystem::exists; diff --git a/include/caosdb/connection.h b/include/caosdb/connection.h index d3ed0945e0022f29e6097fb4ea2d9207c3258987..4eadde0ac281fb61bb5eca49b5b64cb8baedeccb 100644 --- a/include/caosdb/connection.h +++ b/include/caosdb/connection.h @@ -27,10 +27,6 @@ * @date 2021-05-18 * @brief Configuration and setup of the connection. */ -#include <map> // for map -#include <memory> // for shared_ptr, unique_ptr -#include <string> // for string, basic_string -#include "boost/filesystem/path.hpp" // for path #include "caosdb/authentication.h" // for Authenticator #include "caosdb/configuration.h" // for ConnectionConfigura... #include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransactionSe... @@ -38,7 +34,11 @@ #include "caosdb/info/v1alpha1/main.grpc.pb.h" // for GeneralInfoService:... #include "caosdb/transaction.h" // for Transaction #include "caosdb/transaction_status.h" // for TransactionStatus -#include "grpcpp/channel.h" // for Channel +#include <boost/filesystem/path.hpp> // for path +#include <grpcpp/channel.h> // for Channel +#include <map> // for map +#include <memory> // for shared_ptr, unique_ptr +#include <string> // for string, basic_string namespace caosdb::connection { using boost::filesystem::path; diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h index 42d376698872e086c05a5905484e2f63c11dd346..c084a338272532db652b4d7df85cfa42940c6bb1 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)) {} /** @@ -227,6 +242,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..08378065895c15f494ba5a6bcf1592bb8e6c2284 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -44,6 +44,7 @@ #include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SEQ_... #include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_... #include <cstdint> // for int64_t +#include <google/protobuf/arena.h> // for Arena #include <google/protobuf/message.h> // for RepeatedPtrField #include <iosfwd> // for streamsize #include <iterator> // for iterator, output_iterato... @@ -51,13 +52,14 @@ #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; using boost::filesystem::is_directory; using caosdb::entity::v1alpha1::IdResponse; +using google::protobuf::Arena; using ProtoParent = caosdb::entity::v1alpha1::Parent; using ProtoProperty = caosdb::entity::v1alpha1::Property; using ProtoEntity = caosdb::entity::v1alpha1::Entity; @@ -187,6 +189,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 +365,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>(){}; }; /** @@ -426,14 +452,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 +481,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; } @@ -563,8 +585,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 +600,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 +633,6 @@ private: */ class Properties : public RepeatedPtrFieldWrapper<Property, ProtoProperty> { public: - ~Properties() = default; friend class Entity; private: @@ -635,6 +661,9 @@ private: */ 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); @@ -650,7 +679,7 @@ public: properties.wrapped = this->wrapped->mutable_properties(); parents.wrapped = this->wrapped->mutable_parents(); }; - explicit inline Entity(EntityResponse *response) : Entity(response->release_entity()) { + explicit inline Entity(EntityResponse *response) : Entity(response->mutable_entity()) { this->errors.wrapped->Swap(response->mutable_errors()); this->warnings.wrapped->Swap(response->mutable_warnings()); this->infos.wrapped->Swap(response->mutable_infos()); @@ -671,6 +700,56 @@ public: parents.wrapped = this->wrapped->mutable_parents(); }; + /** + * Move constructor. + */ + explicit inline Entity(Entity &&original) : Entity(original.wrapped) { + original.wrapped = nullptr; + original.value.wrapped = nullptr; + original.data_type.wrapped = nullptr; + this->properties = std::move(original.properties); + this->parents = std::move(original.parents); + 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 +866,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"; @@ -802,6 +890,7 @@ private: static auto CreateMessagesField() -> RepeatedPtrField<ProtoMessage> *; auto SetId(const std::string &id) -> void; auto SetVersionId(const std::string &id) -> void; + auto inline GetArena() const -> Arena * { return get_arena(); } private: FileDescriptor file_descriptor; diff --git a/include/caosdb/info.h b/include/caosdb/info.h index cf2c879120becd8db211e85df39d62ac9ba1434e..e9e7e1773ab81a4676e5be65e904a8026a22d60a 100644 --- a/include/caosdb/info.h +++ b/include/caosdb/info.h @@ -28,6 +28,7 @@ * @brief General information about the CaosDBServer. */ #include "caosdb/info/v1alpha1/main.pb.h" // for VersionInfo +#include "caosdb/protobuf_helper.h" // for get_arena #include <cstdint> // for uint32_t #include <string> // for string @@ -53,7 +54,11 @@ public: * CaosDBConnection::GetVersionInfo() instead to get the version of the * server behind the given connection. */ - explicit inline VersionInfo(ProtoVersionInfo *info) : info(info){}; + explicit inline VersionInfo(ProtoVersionInfo *info) : info(info) { + if (this->info->GetArena() == nullptr) { + caosdb::utility::get_arena()->Own(this->info); + } + }; [[nodiscard]] inline auto GetMajor() const -> int32_t { return this->info->major(); } [[nodiscard]] inline auto GetMinor() const -> int32_t { return this->info->minor(); } [[nodiscard]] inline auto GetPatch() const -> int32_t { return this->info->patch(); } @@ -63,8 +68,7 @@ public: [[nodiscard]] inline auto GetBuild() const -> const std::string & { return this->info->build(); } private: - /// This object is the owner of the Protobuf VersionInfo message. - std::unique_ptr<ProtoVersionInfo> info; + ProtoVersionInfo *info; }; } // namespace caosdb::info diff --git a/include/caosdb/logging.h b/include/caosdb/logging.h index 35c5fdfa1a72ba5f55933f3bd99aa93f313c3e33..7b5a605044521ba33ab1327e96889be3aef6345e 100644 --- a/include/caosdb/logging.h +++ b/include/caosdb/logging.h @@ -24,12 +24,11 @@ #define CAOSDB_LOGGING_H #include "caosdb/log_level.h" // for CAOSDB_LOG_... -#include "boost/log/sources/global_logger_storage.hpp" // for BOOST_LOG_I... -#include "boost/log/sources/record_ostream.hpp" // IWYU pragma: keep -#include "boost/log/sources/severity_channel_logger.hpp" // for BOOST_LOG_C... -#include "boost/log/utility/setup/settings.hpp" // for settings -#include "boost/smart_ptr/intrusive_ptr.hpp" // for intrusive_ptr -#include "boost/smart_ptr/intrusive_ref_counter.hpp" // for intrusive_p... +#include <boost/log/sources/record_ostream.hpp> // IWYU pragma: keep +#include <boost/log/sources/severity_channel_logger.hpp> // for BOOST_LOG_C... +#include <boost/log/utility/setup/settings.hpp> // for settings +#include <boost/smart_ptr/intrusive_ptr.hpp> // for intrusive_ptr +#include <boost/smart_ptr/intrusive_ref_counter.hpp> // for intrusive_p... #include <memory> // for shared_ptr #include <string> // for string #include <vector> // for vector @@ -40,7 +39,24 @@ const std::string logger_name = "caosdb::logging"; typedef boost::log::sources::severity_channel_logger_mt<int, std::string> boost_logger_class; -BOOST_LOG_GLOBAL_LOGGER(logger, boost_logger_class) +class _logger { +public: + static boost_logger_class &get() { return *_logger::GetInstance()._logger_instance; } + static void destroy() { + auto &instance = _logger::GetInstance(); + delete instance._logger_instance; + } + +private: + _logger() { this->_logger_instance = new boost_logger_class(); }; + static _logger &GetInstance() { + static _logger instance; + return instance; + } + boost_logger_class *_logger_instance; +}; + +auto inline get_logger() -> boost_logger_class & { return _logger::get(); } /** * This class stores the integer log level. @@ -187,17 +203,17 @@ void caosdb_log_trace(const char *channel, const char *msg); } // namespace caosdb::logging #define CAOSDB_LOG_FATAL(Channel) \ - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_FATAL) + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), Channel, CAOSDB_LOG_LEVEL_FATAL) #define CAOSDB_LOG_ERROR(Channel) \ - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_ERROR) + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), Channel, CAOSDB_LOG_LEVEL_ERROR) #define CAOSDB_LOG_WARN(Channel) \ - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_WARN) + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), Channel, CAOSDB_LOG_LEVEL_WARN) #define CAOSDB_LOG_INFO(Channel) \ - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_INFO) + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), Channel, CAOSDB_LOG_LEVEL_INFO) #define CAOSDB_LOG_DEBUG(Channel) \ - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_DEBUG) + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), Channel, CAOSDB_LOG_LEVEL_DEBUG) #define CAOSDB_LOG_TRACE(Channel) \ - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), Channel, CAOSDB_LOG_LEVEL_TRACE) + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), Channel, CAOSDB_LOG_LEVEL_TRACE) #define CAOSDB_LOG_ERROR_AND_RETURN_STATUS(Channel, StatusCode, Message) \ CAOSDB_LOG_ERROR(Channel) << "StatusCode (" << StatusCode << ") " \ 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/src/caosdb/authentication.cpp b/src/caosdb/authentication.cpp index 50ff24455ac87227f475775974abae1228fc50d3..ecfbe35344f557671d8529770f73a3987c389ab0 100644 --- a/src/caosdb/authentication.cpp +++ b/src/caosdb/authentication.cpp @@ -19,13 +19,15 @@ * */ #include "caosdb/authentication.h" -#include "grpcpp/security/credentials.h" // for MetadataCredentialsPlugin -#include <grpcpp/impl/codegen/status.h> // for Status, Status::OK -#include <grpcpp/impl/codegen/string_ref.h> // for string_ref -#include <map> // for multimap -#include <memory> // for allocator, shared_ptr -#include <string> // for basic_string, operator+ -#include <utility> // for pair, move, make_pair +#include <grpcpp/impl/codegen/interceptor.h> // for Status +#include <grpcpp/impl/codegen/security/auth_context.h> // for AuthContext +#include <grpcpp/impl/codegen/status.h> // for Status, Status::OK +#include <grpcpp/impl/codegen/string_ref.h> // for string_ref +#include <grpcpp/security/credentials.h> // for MetadataCredentialsPlugin +#include <map> // for multimap +#include <memory> // for allocator, shared_ptr +#include <string> // for basic_string, operator+ +#include <utility> // for pair, move, make_pair namespace caosdb::authentication { using caosdb::utility::base64_encode; diff --git a/src/caosdb/configuration.cpp b/src/caosdb/configuration.cpp index edce302e00bcb5645d734e2ff577be23d0a8bd67..3d78ac70600f2dcbb62199a40c6ec5d5a0299823 100644 --- a/src/caosdb/configuration.cpp +++ b/src/caosdb/configuration.cpp @@ -19,15 +19,6 @@ * */ #include "caosdb/configuration.h" -#include "boost/iterator/iterator_facade.hpp" // for iterator_facad... -#include "boost/json/impl/object.hpp" // for object::at -#include "boost/json/string.hpp" // for string -#include "boost/json/string_view.hpp" // for string_view -#include "boost/log/core/record.hpp" // for record -#include "boost/log/detail/attachable_sstream_buf.hpp" // for basic_ostring... -#include "boost/log/sources/record_ostream.hpp" // for basic_record_o... -#include "boost/preprocessor/seq/limits/enum_256.hpp" // for BOOST_PP_SEQ_E... -#include "boost/preprocessor/seq/limits/size_256.hpp" // for BOOST_PP_SEQ_S... #include "caosdb/authentication.h" // for Authenticator #include "caosdb/connection.h" // for ConnectionManager #include "caosdb/constants.h" // for LIBCAOSDB_CONF... @@ -35,6 +26,20 @@ #include "caosdb/log_level.h" // for CAOSDB_DEFAULT... #include "caosdb/status_code.h" // for StatusCode #include "caosdb/utility.h" // for get_home_direc... +#include <boost/filesystem/operations.hpp> // for exists +#include <boost/filesystem/path.hpp> // for path, path::i... +#include <boost/iterator/iterator_facade.hpp> // for iterator_facad... +#include <boost/json/impl/object.hpp> // for object::at +#include <boost/json/object.hpp> // for object, objec... +#include <boost/json/string.hpp> // for string +#include <boost/json/string_view.hpp> // for string_view +#include <boost/json/value.hpp> // for value, key_va... +#include <boost/json/value_ref.hpp> // for object +#include <boost/log/core/record.hpp> // for record +#include <boost/log/detail/attachable_sstream_buf.hpp> // for basic_ostring... +#include <boost/log/sources/record_ostream.hpp> // for basic_record_o... +#include <boost/preprocessor/seq/limits/enum_256.hpp> // for BOOST_PP_SEQ_E... +#include <boost/preprocessor/seq/limits/size_256.hpp> // for BOOST_PP_SEQ_S... #include <cassert> // for assert #include <cstdlib> // for getenv #include <cstring> // for strcmp diff --git a/src/caosdb/connection.cpp b/src/caosdb/connection.cpp index d6782f8ffa42238888998bdff65dc666fbf55c18..8420d8ffe6459f3431ead22ab660ab6fcd6a50f3 100644 --- a/src/caosdb/connection.cpp +++ b/src/caosdb/connection.cpp @@ -25,12 +25,14 @@ #include "caosdb/info.h" // for VersionInfo #include "caosdb/info/v1alpha1/main.grpc.pb.h" // for GeneralInfoService #include "caosdb/info/v1alpha1/main.pb.h" // for GetVersionInfoRequest +#include "caosdb/protobuf_helper.h" // for get_arena #include "caosdb/transaction.h" // for Transaction #include "caosdb/transaction_status.h" // for TransactionStatus -#include "grpcpp/impl/codegen/status_code_enum.h" // for StatusCode, UNAUTH... +#include <google/protobuf/arena.h> // for Arena #include <grpcpp/create_channel.h> // for CreateChannel #include <grpcpp/impl/codegen/client_context.h> // for ClientContext #include <grpcpp/impl/codegen/status.h> // for Status +#include <grpcpp/impl/codegen/status_code_enum.h> // for StatusCode, UNAUTH... #include <string> // for string, operator+ namespace caosdb::connection { @@ -44,6 +46,8 @@ using caosdb::info::v1alpha1::GetVersionInfoRequest; using caosdb::info::v1alpha1::GetVersionInfoResponse; using caosdb::transaction::Transaction; using caosdb::transaction::TransactionStatus; +using caosdb::utility::get_arena; +using google::protobuf::Arena; Connection::Connection(const ConnectionConfiguration &configuration) { const std::string target = @@ -57,11 +61,11 @@ Connection::Connection(const ConnectionConfiguration &configuration) { auto Connection::RetrieveVersionInfoNoExceptions() const noexcept -> TransactionStatus { - const GetVersionInfoRequest request; - GetVersionInfoResponse response; + const auto *request = Arena::CreateMessage<GetVersionInfoRequest>(get_arena()); + auto *response = Arena::CreateMessage<GetVersionInfoResponse>(get_arena()); grpc::ClientContext context; const grpc::Status grpc_status = - this->general_info_service->GetVersionInfo(&context, request, &response); + this->general_info_service->GetVersionInfo(&context, *request, response); auto status = TransactionStatus::SUCCESS(); if (!grpc_status.ok()) { @@ -78,7 +82,7 @@ auto Connection::RetrieveVersionInfoNoExceptions() const noexcept -> Transaction error_message); } } else { - this->version_info = std::make_unique<VersionInfo>(response.release_version_info()); + this->version_info = std::make_unique<VersionInfo>(response->release_version_info()); } return status; 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/src/caosdb/file_transmission/download_request_handler.cpp b/src/caosdb/file_transmission/download_request_handler.cpp index cbe79e93eb89261d1d85484cf39f4ad5deecba18..755c8a438f0634ee62761a257173918e53280b50 100644 --- a/src/caosdb/file_transmission/download_request_handler.cpp +++ b/src/caosdb/file_transmission/download_request_handler.cpp @@ -128,14 +128,22 @@ void DownloadRequestHandler::handleNewCallState() { CAOSDB_LOG_TRACE(logger_name) << "Enter DownloadRequestHandler::handleNewCallState. local_path = " << file_descriptor_.local_path << ", download_id = " << file_descriptor_.file_transmission_id; + CAOSDB_LOG_TRACE(logger_name) << "HERE 1"; fileWriter_ = std::make_unique<FileWriter>(file_descriptor_.local_path); + CAOSDB_LOG_TRACE(logger_name) << "HERE 2"; - request_->mutable_file_transmission_id()->CopyFrom(*(file_descriptor_.file_transmission_id)); + auto *tid = request_->mutable_file_transmission_id(); + CAOSDB_LOG_TRACE(logger_name) << "HERE 3"; + tid->CopyFrom(*(file_descriptor_.file_transmission_id)); + CAOSDB_LOG_TRACE(logger_name) << "HERE 4"; rpc_ = stub_->PrepareAsyncFileDownload(&ctx_, *request_, cq_); + CAOSDB_LOG_TRACE(logger_name) << "HERE 5"; transaction_status = TransactionStatus::EXECUTING(); + CAOSDB_LOG_TRACE(logger_name) << "HERE 6"; state_ = CallState::SendingRequest; + CAOSDB_LOG_TRACE(logger_name) << "HERE 7"; rpc_->StartCall(tag_); CAOSDB_LOG_TRACE(logger_name) << "Leave DownloadRequestHandler::handleNewCallState"; } diff --git a/src/caosdb/logging.cpp b/src/caosdb/logging.cpp index 4070786b2bb4073da5800f4a57b9c0dfcff5d6ac..906bd7989d3b7b80ea4159bab1ae577c022abfe3 100644 --- a/src/caosdb/logging.cpp +++ b/src/caosdb/logging.cpp @@ -19,35 +19,43 @@ * */ #include "caosdb/logging.h" -#include "boost/core/swap.hpp" // for swap -#include "boost/iterator/iterator_facade.hpp" -#include "boost/log/attributes/clock.hpp" -#include "boost/log/core/core.hpp" // for core -#include "boost/log/core/record.hpp" -#include "boost/log/sources/record_ostream.hpp" -#include "boost/log/utility/setup/from_settings.hpp" -#include "boost/log/utility/setup/settings.hpp" -#include "boost/move/utility_core.hpp" // for move -#include "boost/multi_index/detail/bidir_node_iterator.hpp" -#include "boost/operators.hpp" -#include "boost/preprocessor/seq/limits/enum_256.hpp" -#include "boost/preprocessor/seq/limits/size_256.hpp" -#include "boost/property_tree/detail/exception_implementation.hpp" -#include "boost/smart_ptr/shared_ptr.hpp" -#include "boost/tuple/detail/tuple_basic.hpp" // for get #include "caosdb/log_level.h" +#include <boost/core/swap.hpp> // for swap +#include <boost/iterator/iterator_facade.hpp> +#include <boost/log/attributes/clock.hpp> +#include <boost/log/core/core.hpp> // for core +#include <boost/log/core/record.hpp> +#include <boost/log/sources/record_ostream.hpp> +#include <boost/log/sources/severity_channel_logger.hpp> +#include <boost/log/utility/setup/from_settings.hpp> +#include <boost/log/utility/setup/settings.hpp> +#include <boost/move/utility_core.hpp> // for move +#include <boost/multi_index/detail/bidir_node_iterator.hpp> +#include <boost/operators.hpp> +#include <boost/preprocessor/seq/limits/enum_256.hpp> +#include <boost/preprocessor/seq/limits/size_256.hpp> +#include <boost/property_tree/detail/exception_implementation.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/tuple/detail/tuple_basic.hpp> // for get +#include <iostream> #include <memory> #include <sstream> #include <string> #include <utility> // for move #include <vector> +void __attribute__((constructor)) startup() { + std::cout << "LOADING CAOSDB 1" << std::endl; + boost::log::core::get()->set_logging_enabled(false); + std::cout << "LOADING CAOSDB 2" << std::endl; +} +void __attribute__((destructor)) shutdown() { + std::cout << "UNLOADING CAOSDB 1" << std::endl; + caosdb::logging::_logger::destroy(); +} + namespace caosdb::logging { -BOOST_LOG_GLOBAL_LOGGER_INIT(logger, boost_logger_class) { - boost_logger_class lg; - return lg; -} LoggingConfiguration::LoggingConfiguration(int level) : LevelConfiguration(level) {} auto LoggingConfiguration::AddSink(const std::shared_ptr<SinkConfiguration> &sink) -> void { @@ -114,9 +122,12 @@ SyslogSinkConfiguration::SyslogSinkConfiguration(const std::string &name, int le // Called if no custom logging settings are specified. auto initialize_logging_defaults() -> int { // first: turn everything off - boost::log::settings off_settings; - off_settings["Core.DisableLogging"] = true; - boost::log::init_from_settings(off_settings); + auto core = boost::log::core::get(); + if (core->get_logging_enabled()) { + core->flush(); + core->remove_all_sinks(); + core->set_logging_enabled(false); + } // now set everything up const static std::vector<std::shared_ptr<SinkConfiguration>> default_sinks = { @@ -131,8 +142,7 @@ auto initialize_logging_defaults() -> int { } boost::log::init_from_settings(default_settings); - auto core = boost::log::core::get(); - core->add_global_attribute("TimeStamp", boost::log::attributes::local_clock()); + // core->add_global_attribute("TimeStamp", boost::log::attributes::local_clock()); CAOSDB_LOG_DEBUG(logger_name) << "Initialized default settings."; @@ -142,20 +152,22 @@ auto initialize_logging_defaults() -> int { // Called if custom logging settings are specified. auto initialize_logging(const LoggingConfiguration &configuration) -> void { // first: turn everything off - boost::log::settings off_settings; - off_settings["Core.DisableLogging"] = true; - boost::log::init_from_settings(off_settings); - - // now set everything up - boost::log::settings new_settings; + auto core = boost::log::core::get(); + if (core->get_logging_enabled()) { + core->flush(); + core->remove_all_sinks(); + core->set_logging_enabled(false); + } if (configuration.GetLevel() == CAOSDB_LOG_LEVEL_OFF) { - new_settings["Core.DisableLogging"] = true; + // it is off return; - } else { - new_settings["Core.DisableLogging"] = false; } + // now set everything up + boost::log::settings new_settings; + new_settings["Core.DisableLogging"] = false; + for (const auto &sink : configuration.GetSinks()) { sink->Configure(new_settings); } @@ -166,27 +178,27 @@ auto initialize_logging(const LoggingConfiguration &configuration) -> void { } void caosdb_log_fatal(const char *channel, const char *msg) { - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_FATAL) << msg; + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), channel, CAOSDB_LOG_LEVEL_FATAL) << msg; } void caosdb_log_error(const char *channel, const char *msg) { - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_ERROR) << msg; + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), channel, CAOSDB_LOG_LEVEL_ERROR) << msg; } void caosdb_log_warn(const char *channel, const char *msg) { - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_WARN) << msg; + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), channel, CAOSDB_LOG_LEVEL_WARN) << msg; } void caosdb_log_info(const char *channel, const char *msg) { - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_INFO) << msg; + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), channel, CAOSDB_LOG_LEVEL_INFO) << msg; } void caosdb_log_debug(const char *channel, const char *msg) { - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_DEBUG) << msg; + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), channel, CAOSDB_LOG_LEVEL_DEBUG) << msg; } void caosdb_log_trace(const char *channel, const char *msg) { - BOOST_LOG_CHANNEL_SEV(caosdb::logging::logger::get(), channel, CAOSDB_LOG_LEVEL_TRACE) << msg; + BOOST_LOG_CHANNEL_SEV(caosdb::logging::get_logger(), channel, CAOSDB_LOG_LEVEL_TRACE) << msg; } } // namespace caosdb::logging diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index 002d20d792b49bfb88b160cb39e7d8a8e6a5bd01..d315bf890fdaf5d2382f4fe2b3d2e57ba3a57bc2 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -290,7 +290,7 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { // NOLINT switch (retrieve_response->retrieve_response_case()) { case RetrieveResponseCase::kEntityResponse: { - auto *retrieve_entity_response = retrieve_response->release_entity_response(); + auto *retrieve_entity_response = retrieve_response->mutable_entity_response(); result = std::make_unique<Entity>(retrieve_entity_response); } break; case RetrieveResponseCase::kSelectResult: { @@ -321,17 +321,17 @@ auto Transaction::WaitForIt() const noexcept -> TransactionStatus { // NOLINT } case TransactionResponseCase::kInsertResponse: { - auto *inserted_id_response = sub_response.mutable_insert_response()->release_id_response(); + auto *inserted_id_response = sub_response.mutable_insert_response()->mutable_id_response(); result = std::make_unique<Entity>(inserted_id_response); break; } case TransactionResponseCase::kDeleteResponse: { - auto *deleted_id_response = sub_response.mutable_delete_response()->release_id_response(); + auto *deleted_id_response = sub_response.mutable_delete_response()->mutable_id_response(); result = std::make_unique<Entity>(deleted_id_response); break; } case TransactionResponseCase::kUpdateResponse: { - auto *updated_id_response = sub_response.mutable_update_response()->release_id_response(); + auto *updated_id_response = sub_response.mutable_update_response()->mutable_id_response(); result = std::make_unique<Entity>(updated_id_response); break; } diff --git a/test/test_entity.cpp b/test/test_entity.cpp index de0206f8b547884b7ae438b3bd4873230b9128d8..85f466f74e77f0806089ae71bed7b70f353fa1c8 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,6 +142,129 @@ TEST(test_entity, test_append_property) { EXPECT_EQ(prop.GetDataType(), same_prop.GetDataType()); } +TEST(test_entity, test_copy_constructor) { + Arena arena; + auto *parent = Arena::CreateMessage<ProtoParent>(&arena); + parent->set_description("the parent desc"); + parent->set_id("the parent id"); + parent->set_name("the parent name"); + auto *property = Arena::CreateMessage<ProtoProperty>(&arena); + 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); + auto *entity_response = Arena::CreateMessage<EntityResponse>(&arena); + 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) { + Arena arena; + auto *parent = Arena::CreateMessage<ProtoParent>(&arena); + parent->set_description("the parent desc"); + parent->set_id("the parent id"); + parent->set_name("the parent name"); + auto *property = Arena::CreateMessage<ProtoProperty>(&arena); + 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); + auto *entity_response = Arena::CreateMessage<EntityResponse>(&arena); + 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"); @@ -191,15 +318,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 + Property other_prop = std::move(prop); // 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()); @@ -542,10 +672,11 @@ TEST(test_entity, test_description) { entity.SetDescription("desc entity"); property.SetDescription("desc property"); - // Parent has not setter - ProtoParent protoParent; - protoParent.set_description("desc parent"); - parent = Parent(&protoParent); + // Parent has no setter + Arena arena; + auto *protoParent = Arena::CreateMessage<ProtoParent>(&arena); + protoParent->set_description("desc parent"); + parent = Parent(protoParent); EXPECT_EQ(entity.GetDescription(), "desc entity"); EXPECT_EQ(property.GetDescription(), "desc property"); @@ -565,6 +696,35 @@ TEST(test_entity, test_add_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"); @@ -623,13 +783,14 @@ TEST(test_entity, test_parent_to_string) { } TEST(test_entity, test_messages_to_string) { - IdResponse idResponse; - idResponse.set_id("entity_id"); - auto *error = idResponse.add_errors(); + Arena arena; + auto *idResponse = Arena::CreateMessage<IdResponse>(&arena); + 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); + Entity entity(idResponse); // Messages are not printed, currently. EXPECT_EQ(entity.ToString(), "{\n \"id\": \"entity_id\",\n \"version\": {}\n}\n"); @@ -638,13 +799,14 @@ TEST(test_entity, test_messages_to_string) { } TEST(test_entity, test_message_to_string) { - IdResponse idResponse; - idResponse.set_id("entity_id"); - auto *error = idResponse.add_errors(); + Arena arena; + auto *idResponse = Arena::CreateMessage<IdResponse>(&arena); + 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); + Entity entity(idResponse); // Messages are not printed, currently. EXPECT_EQ(entity.ToString(), "{\n \"id\": \"entity_id\",\n \"version\": {}\n}\n"); diff --git a/test/test_misc.cpp b/test/test_misc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dccaaa817a8a926772502723a231f379d04764dc --- /dev/null +++ b/test/test_misc.cpp @@ -0,0 +1,81 @@ +/* + * + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@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 <gtest/gtest-message.h> // for Message +#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl +#include <gtest/gtest_pred_impl.h> // for Test, TestInfo, EXPECT_EQ, TEST +#include <iostream> // for cout, << +#include <string> // for string +#include <utility> // for move + +namespace caosdb { + +class TestClass { +public: + ~TestClass() = default; + TestClass(TestClass &&other) = default; + TestClass(const TestClass &other); + TestClass(); + explicit TestClass(std::string member); + + auto operator=(const TestClass &other) -> TestClass &; + auto operator=(TestClass &&other) -> TestClass & = default; + + [[nodiscard]] auto ToString() const -> std::string; + std::string member; +}; + +TestClass::TestClass() { std::cout << "Constructor TestClass(): " << ToString() << "\n"; } + +TestClass::TestClass(std::string member) : member(std::move(member)) { + std::cout << "Constructor TestClass(const std:string &): " << ToString() << "\n"; +} + +TestClass::TestClass(const TestClass &other) : member(other.member) { + std::cout << "Copy Constructor TestClass(const TestClass &): " << ToString() << "\n"; +} + +auto TestClass::operator=(const TestClass &other) -> TestClass & { + std::cout << "Copy assignment (" << ToString() << "->"; + if (this != &other) { + this->member = other.member; + } + std::cout << ToString() << ")\n"; + return *this; +} + +auto TestClass::ToString() const -> std::string { return "TestClass(" + member + ")"; } + +TEST(test_misc, test_move) { + TestClass test_class1; + std::cout << "test_class1: " << test_class1.ToString() << "\n"; + + TestClass test_class2 = test_class1; + std::cout << "test_class2: " << test_class2.ToString() << "\n"; + + const TestClass test_class3("member3"); + std::cout << "test_class3: " << test_class3.ToString() << "\n"; + + TestClass test_class4 = test_class3; + std::cout << "test_class4: " << test_class4.ToString() << "\n"; +} + +} // namespace caosdb diff --git a/test/test_protobuf.cpp b/test/test_protobuf.cpp index 6f9bda0740487db475f1e34757e4a612c59061f9..8dde7fe056048f9f91d0c9a7a9d209af3263ae32 100644 --- a/test/test_protobuf.cpp +++ b/test/test_protobuf.cpp @@ -22,86 +22,91 @@ #include "caosdb/data_type.h" // for DataType, ReferenceDataType #include "caosdb/entity.h" // for Entity #include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message +#include <google/protobuf/arena.h> // for Arena #include <gtest/gtest-message.h> // for Message #include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestPa... #include <gtest/gtest_pred_impl.h> // for Test, TestInfo, TEST #include <memory> // for allocator namespace caosdb { +using google::protobuf::Arena; using ProtoEntity = caosdb::entity::v1alpha1::Entity; using caosdb::entity::Entity; using caosdb::entity::v1alpha1::Message; TEST(test_protobuf, test_swap_trivial) { - Message message_source; - message_source.set_code(1234); - message_source.set_description("desc"); + Arena arena; + auto *message_source = Arena::CreateMessage<Message>(&arena); + message_source->set_code(1234); + message_source->set_description("desc"); - Message message_destination; + auto *message_destination = Arena::CreateMessage<Message>(&arena); - EXPECT_EQ(message_source.code(), 1234); - EXPECT_EQ(message_source.description(), "desc"); - EXPECT_EQ(message_destination.code(), 0); - EXPECT_EQ(message_destination.description(), ""); + EXPECT_EQ(message_source->code(), 1234); + EXPECT_EQ(message_source->description(), "desc"); + EXPECT_EQ(message_destination->code(), 0); + EXPECT_EQ(message_destination->description(), ""); - message_source.Swap(&message_destination); + message_source->Swap(message_destination); - EXPECT_EQ(message_source.code(), 0); - EXPECT_EQ(message_source.description(), ""); - EXPECT_EQ(message_destination.code(), 1234); - EXPECT_EQ(message_destination.description(), "desc"); + EXPECT_EQ(message_source->code(), 0); + EXPECT_EQ(message_source->description(), ""); + EXPECT_EQ(message_destination->code(), 1234); + EXPECT_EQ(message_destination->description(), "desc"); } TEST(test_protobuf, test_swap_nested) { - ProtoEntity entity_source; - entity_source.set_id("entity_id"); - auto *version_source = entity_source.mutable_version(); + Arena arena; + auto *entity_source = Arena::CreateMessage<ProtoEntity>(&arena); + entity_source->set_id("entity_id"); + auto *version_source = entity_source->mutable_version(); version_source->set_id("version_id"); - ProtoEntity entity_destination; - auto *version_destination = entity_destination.mutable_version(); + auto *entity_destination = Arena::CreateMessage<ProtoEntity>(&arena); + auto *version_destination = entity_destination->mutable_version(); - EXPECT_EQ(entity_source.id(), "entity_id"); - EXPECT_EQ(entity_source.version().id(), "version_id"); + EXPECT_EQ(entity_source->id(), "entity_id"); + EXPECT_EQ(entity_source->version().id(), "version_id"); EXPECT_EQ(version_source->id(), "version_id"); - EXPECT_EQ(entity_destination.id(), ""); - EXPECT_EQ(entity_destination.version().id(), ""); + EXPECT_EQ(entity_destination->id(), ""); + EXPECT_EQ(entity_destination->version().id(), ""); EXPECT_EQ(version_destination->id(), ""); - entity_source.Swap(&entity_destination); + entity_source->Swap(entity_destination); - EXPECT_EQ(entity_source.id(), ""); - EXPECT_EQ(entity_source.version().id(), ""); - EXPECT_EQ(entity_destination.id(), "entity_id"); - EXPECT_EQ(entity_destination.version().id(), "version_id"); + EXPECT_EQ(entity_source->id(), ""); + EXPECT_EQ(entity_source->version().id(), ""); + EXPECT_EQ(entity_destination->id(), "entity_id"); + EXPECT_EQ(entity_destination->version().id(), "version_id"); // has not been swapped! EXPECT_EQ(version_source->id(), "version_id"); EXPECT_EQ(version_destination->id(), ""); // Member pointers to nested messages have been swapped - EXPECT_EQ(entity_source.mutable_version(), version_destination); - EXPECT_EQ(entity_destination.mutable_version(), version_source); + EXPECT_EQ(entity_source->mutable_version(), version_destination); + EXPECT_EQ(entity_destination->mutable_version(), version_source); } TEST(test_protobuf, test_copy_nested) { - ProtoEntity entity_source; - auto *data_type_source = entity_source.mutable_data_type(); + Arena arena; + auto *entity_source = Arena::CreateMessage<ProtoEntity>(&arena); + auto *data_type_source = entity_source->mutable_data_type(); data_type_source->mutable_reference_data_type()->set_name("src_per"); - ProtoEntity entity_destination; - auto *data_type_destination = entity_destination.mutable_data_type(); + auto *entity_destination = Arena::CreateMessage<ProtoEntity>(&arena); + auto *data_type_destination = entity_destination->mutable_data_type(); data_type_destination->mutable_reference_data_type()->set_name("dest_per"); - EXPECT_EQ(entity_source.data_type().reference_data_type().name(), "src_per"); - EXPECT_EQ(entity_destination.data_type().reference_data_type().name(), "dest_per"); + EXPECT_EQ(entity_source->data_type().reference_data_type().name(), "src_per"); + EXPECT_EQ(entity_destination->data_type().reference_data_type().name(), "dest_per"); - entity_destination.CopyFrom(entity_source); + entity_destination->CopyFrom(*entity_source); - EXPECT_EQ(entity_source.data_type().reference_data_type().name(), "src_per"); - EXPECT_EQ(entity_destination.data_type().reference_data_type().name(), "src_per"); + EXPECT_EQ(entity_source->data_type().reference_data_type().name(), "src_per"); + EXPECT_EQ(entity_destination->data_type().reference_data_type().name(), "src_per"); - Entity entity(&entity_destination); + Entity entity(entity_destination); EXPECT_EQ(entity.GetDataType().GetAsReference().GetName(), "src_per"); const Entity ©_entity(entity); diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp index 7c93ac5d9b081ac4cb2314f34272f54cba0f61c9..34c33d6560bfa68c5510055b23f7daedb29e734a 100644 --- a/test/test_transaction.cpp +++ b/test/test_transaction.cpp @@ -27,6 +27,7 @@ #include "caosdb/transaction_handler.h" // for MultiTransactionResponse #include "caosdb/transaction_status.h" // for ConnectionError #include "caosdb_test_utility.h" // for EXPECT_THROW_MESSAGE +#include <google/protobuf/arena.h> // for Arena #include <gtest/gtest-message.h> // for Message #include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestPa... #include <gtest/gtest_pred_impl.h> // for Test, TestInfo, TEST @@ -40,10 +41,9 @@ namespace caosdb::transaction { using caosdb::configuration::InsecureConnectionConfiguration; using caosdb::connection::Connection; using caosdb::entity::Entity; -using caosdb::exceptions::ConnectionError; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; using caosdb::entity::Role; using caosdb::entity::v1alpha1::RetrieveResponse; +using caosdb::exceptions::ConnectionError; TEST(test_transaction, create_transaction) { const auto *host = "localhost"; @@ -113,9 +113,10 @@ TEST(test_transaction, test_multi_result_set_empty) { TEST(test_transaction, test_multi_result_iterator) { std::vector<std::unique_ptr<Entity>> one_elem; - RetrieveResponse response; - response.mutable_entity_response()->mutable_entity()->set_id("100"); - one_elem.push_back(std::make_unique<Entity>(response.release_entity_response())); + Arena arena; + auto *response = Arena::CreateMessage<RetrieveResponse>(&arena); + response->mutable_entity_response()->mutable_entity()->set_id("100"); + one_elem.push_back(std::make_unique<Entity>(response->mutable_entity_response())); MultiResultSet rs(std::move(one_elem)); EXPECT_EQ(rs.size(), 1); @@ -127,9 +128,10 @@ TEST(test_transaction, test_multi_result_iterator) { TEST(test_transaction, test_multi_result_set_one) { std::vector<std::unique_ptr<Entity>> one_elem; - RetrieveResponse response; - response.mutable_entity_response()->mutable_entity()->set_id("100"); - one_elem.push_back(std::make_unique<Entity>(response.release_entity_response())); + Arena arena; + auto *response = Arena::CreateMessage<RetrieveResponse>(&arena); + response->mutable_entity_response()->mutable_entity()->set_id("100"); + one_elem.push_back(std::make_unique<Entity>(response->mutable_entity_response())); MultiResultSet rs(std::move(one_elem)); EXPECT_EQ(rs.size(), 1); @@ -139,27 +141,28 @@ TEST(test_transaction, test_multi_result_set_one) { TEST(test_transaction, test_multi_result_set_three) { std::vector<std::unique_ptr<Entity>> three_elem; - MultiTransactionResponse response; - response.add_responses() + Arena arena; + auto *response = Arena::CreateMessage<MultiTransactionResponse>(&arena); + response->add_responses() ->mutable_retrieve_response() ->mutable_entity_response() ->mutable_entity() ->set_id("100"); auto *entity_with_error = - response.add_responses()->mutable_retrieve_response()->mutable_entity_response(); + response->add_responses()->mutable_retrieve_response()->mutable_entity_response(); entity_with_error->mutable_entity()->set_id("101"); entity_with_error->add_errors()->set_code(1); - response.add_responses() + response->add_responses() ->mutable_retrieve_response() ->mutable_entity_response() ->mutable_entity() ->set_id("102"); - auto *responses = response.mutable_responses(); + auto *responses = response->mutable_responses(); std::vector<std::unique_ptr<Entity>> entities; for (auto sub_response : *responses) { three_elem.push_back(std::make_unique<Entity>( - sub_response.mutable_retrieve_response()->release_entity_response())); + sub_response.mutable_retrieve_response()->mutable_entity_response())); } MultiResultSet rs(std::move(three_elem));