diff --git a/.docker/Dockerfile b/.docker/Dockerfile index b894c62ae3953b96aca1e3a88da795d4c8f13a69..870c810c33b9182d9e2566f928f10ead44ea4d0c 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -3,7 +3,7 @@ FROM debian:buster-backports RUN apt-get update RUN apt-get install -y cmake/buster-backports RUN apt-get install -y lcov -RUN apt-get install -y doxygen +RUN apt-get install -y doxygen graphviz RUN apt-get install -y clang-format-11 clang-tidy-11 RUN apt-get install -y python3-pip RUN apt-get install -y git diff --git a/CHANGELOG.md b/CHANGELOG.md index ec80782f4ac28d9e9081599f0ccc3639a2bb6a8c..3bdcb8c0730e90929ce25970850b0c801f1f6d09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,5 +23,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * #11 - Transaction::GetResultSet() now always returns a valid reference. +* #25 - Compiles on MacOS with LLVM now. ### Security diff --git a/CMakeLists.txt b/CMakeLists.txt index f5cb9b433d85d891bdb8c87a42313c608d10bea8..06aabe8f9b25c3f72e46062e2dc20496187e9cb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.13) -set(libcaosdb_VERSION 0.0.18) +set(libcaosdb_VERSION 0.1.0) set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0) set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5) set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0) @@ -86,8 +86,8 @@ add_subdirectory(doc) # Protobuf/Grpc source files set(PROTO_FILES - ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1alpha1/main.proto - ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1alpha1/main.proto + ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1/main.proto + ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1/main.proto ) set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md deleted file mode 100644 index 55949748d9d513367c2fbb98b5354bd95d97713e..0000000000000000000000000000000000000000 --- a/DEPENDENCIES.md +++ /dev/null @@ -1,30 +0,0 @@ -# GENERAL - -* >=conan-1.37.2 (e.g. with `pip install conan`) -* >=cmake-3.13 -* >=gcc-10.2.0 | >=clang-11 - -# OPTIONAL - -* For checking the schema of a json configuration file: >=jsonschema-3.2.0 - -# BUILD DOCS - -* doxygen -* >=python-3.7 -* >=pip-21.0.1 -* python packages from the `doc/requirements.txt` file. - -# BUILD AND RUN TESTS - -* >=clang-tidy-11 -* >=gtest-1.10.0 - -# COVERAGE - -* >=gcc-10.2.0 -* >=lcov-1.15 - -# FORMATTING - -* >=clang-formatting-11 diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md new file mode 120000 index 0000000000000000000000000000000000000000..afcb4b6000019170e46b6dde462897bacd9855e1 --- /dev/null +++ b/DEPENDENCIES.md @@ -0,0 +1 @@ +doc/DEPENDENCIES.md \ No newline at end of file diff --git a/FEATURES.md b/FEATURES.md index 8b137891791fe96927ad78e64b0aad7bded08bdc..8ca4a13956a6ae5ea25a91c21253c4b68cc7b481 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -1 +1,39 @@ +# Features +This library provides a client for communication with a CaosDB server over the +CaosDB GRPC-APIs. The client supports + +* Transaction of entities and file transmission. +* Authentication via Username/Password. +* Secure communication via TLS. +* Multiple connections with different servers. +* Logging. +* File-based configuration. + +The core is written in C++ and makes heavy use of object-oriented patterns. It +results in a c++ library -- libcaosdb. + +For using the library in a plain C context, a thin wrapper is included +-- libccaosdb. It wrapps the C++ classes into structs and the member methods +into functions which operate on the wrapped C++ instances. + +Minimal testing executables in C++ and C are included as well, but they only +serve as just that -- minimal testing. + +## CaosDB Entitiy API + +This library implements a subset of the CaosDB Entitiy API (caosdb.entity.v1) as a client. + +Current limitations: The implementation does not support mixing retrievals with write-transactions. + +## CaosDB Info API + +This library implements the CaosDB Info API (caosdb.info.v1) as a client without limitations. + +## Thread-safety and Concurrency + +Currently, the library should not be considered thread-safe. + +The `caosdb::transaction::Transaction` class is designed with an with an +interface ready for concurrent and asyncronous transactions. However, the +functions are actually implemented in a blocking, synchronous way. diff --git a/conanfile.py b/conanfile.py index 895f8651c099ec9c6c4f861f9aa449d0a059a481..619d2d3b4729064c81aac8c5697c079100acbead 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools class CaosdbConan(ConanFile): name = "caosdb" - version = "0.0.18" + version = "0.1.0" license = "AGPL-3.0-or-later" author = "Timm C. Fitschen <t.fitschen@indiscale.com>" url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git" @@ -18,7 +18,10 @@ class CaosdbConan(ConanFile): ("gtest/1.11.0"), ("grpc/1.39.1"), ] - exports = "*.cpp", "*.h", "*.cmake", "*CMakeLists.txt", "*.in", "*.proto", "*.c" + exports = ("*.cmake", "*CMakeLists.txt", "*.in", + "*.h", "*.proto", "*.c", "*.cpp", + "*.rst", "*.md", + ) exports_sources = "src", "doc", "include", "test", "cmake", "proto" def config_options(self): diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 4255ab7d0f5531187491de7586a8c7b6c61545f7..6c123d26653fcbabb57a0b4547b5230ef04a4936 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -89,12 +89,12 @@ if (DOXYGEN_FOUND) VERBATIM ) # Copying files is necessary: https://stackoverflow.com/a/45808534/232888 - # TODO fix for docs - #FILE(COPY - #Examples.rst - #README_SETUP.md + file(COPY + Examples.rst + README_SETUP.md + DEPENDENCIES.md # Tutorial.rst - #DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") + DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") else () message("Sphinx need to be installed to generate the sphinx documentation") endif () diff --git a/doc/DEPENDENCIES.md b/doc/DEPENDENCIES.md new file mode 100644 index 0000000000000000000000000000000000000000..d5a81677b32a72548176d407e7d6114b6b5ddeb5 --- /dev/null +++ b/doc/DEPENDENCIES.md @@ -0,0 +1,42 @@ +# Dependencies # + +## General ## + +``` +>=conan-1.37.2 (e.g. with `pip install conan`) +>=cmake-3.13 +>=gcc-10.2.0 | >=clang-11 +``` + +## Optional ## + +* For checking the schema of a json configuration file: `>=jsonschema-3.2.0` + +## Build docs ## + +``` +doxygen +>=python-3.7 +>=pip-21.0.1 +python packages from the `doc/requirements.txt` file +``` + +## Build and run tests ## + +``` +>=clang-tidy-11 +>=gtest-1.10.0 +``` + +## Coverage ## + +``` +>=gcc-10.2.0 +>=lcov-1.15 +``` + +## Formatting ## + +``` +>=clang-formatting-11 +``` diff --git a/doc/Examples.rst b/doc/Examples.rst index ddb24e0bdd6fd7a4f4881a8eb163cb63184b0bb8..eef2976aa3122edae7a5edf268075c0b93f5b5ec 100644 --- a/doc/Examples.rst +++ b/doc/Examples.rst @@ -5,10 +5,10 @@ Examples Connect to a CaosDB server -------------------------- -See also the hints on how to :doc:`get started<README_SETUP>`, and set-up of -libcaosdb. In order to connect to a CaosDB server with libcaosdb you first have to configure the -connection via a configuration file as explained in the :ref:`configuration section <Client Configuration>`. Once the configuration is set up, connecting to the server is -as easy as +See also the hints on how to :doc:`get started<README_SETUP>`, and set-up of libcaosdb. In order to +connect to a CaosDB server with libcaosdb you first have to configure the connection via a +configuration file as explained in the :ref:`"Client Configuration" section <Client +Configuration>`. Once the configuration is set up, connecting to the server is as easy as .. code:: cpp diff --git a/doc/README_SETUP.md b/doc/README_SETUP.md index 33a652c27e384b80db874655892aee8cc413d25d..8374ffade4eb1529736c4d5a99202ad80dac1dc8 100644 --- a/doc/README_SETUP.md +++ b/doc/README_SETUP.md @@ -2,11 +2,12 @@ ## Dependencies -* See [DEPENDENCIES.md](Dependencies.md) +* See the [dependencies](DEPENDENCIES.md) file. ## Build -We use [cmake](https://cmake.org) as build tool and assume gcc as compiler. +We use [cmake](https://cmake.org) as build tool, with Conan as package manager. +The compiler must support the C++17 standard. 0. clone/update the subrepo `git submodule update --init proto` 1. `mkdir build && cd build` @@ -23,6 +24,10 @@ The default install prefix is `~/.local`. It can be set by adding `-DCMAKE_INSTALL_PREFIX=/path/to/install/prefix` to the first cmake command (3.). +If you want to build or install libcaosdb without the use of Conan, feel free to rewrite the +CMakeLists.txt as needed. The CaosDB project is open to merge requests which support multiple ways +of installation. + ### How to build on MacOS If you use apple-clang as the compiler: Instead of the above conan command (2.) use @@ -36,7 +41,7 @@ variable. #### Problems and solutions #### -- Make sure that your conan version supports your XCode version. A typical symptom of version +- Make sure that your Conan version supports your XCode version. A typical symptom of version mismatch is for example conan complaining about incompatible `compiler.version` settings. You may need to rerun any conan and cmake commands (and delete cache files first) after compiler updates. @@ -48,13 +53,18 @@ as compiler. We use [cmake](https://cmake.org/download/) as build tool. 0. clone/update the subrepo `git submodule update --init proto` 1. `mkdir build` 2. `cd build` -3. `conan install .. -g visual_studio -s arch=x86_64 -s build_type=Release -s compiler.toolset=v142 -s compiler.version=16 -s compiler.runtime=MD --build=missing --update` +3. `conan install .. -g visual_studio -s arch=x86_64 -s build_type=Release -s compiler.toolset=v142 -s compiler.version=16 -s compiler.runtime=MD --build=missing --update` 4. `cmake -B . ..` 5. open ` libcaosdb.sln` with Visual Studio, change the buildtype to `Release` and build the project. (You can open Tools/Command Line/Developer Command Prompt and execute `msbuild libcaosdb.sln /property:Configuration=Release`) -### Creating a Local Conan Package ## +#### Known problems #### + +- Linking dynamic libraries currently fails on Windows. So probably other CaosDB libraries which + make use of libcaosdb also will not build. + +### Creating a local Conan package ## Building and installing libcaosdb with Conan is just a single command: `make conan` @@ -62,7 +72,7 @@ For MacOS, you probably should adjust the option as mentioned above. ### Troubleshooting -#### `conan install` Fails Due to Missing Prebuilts +#### `conan install` fails due to missing prebuilts When `conan install` fails during the installation of the dependencies because a precompiled package is not available for your specific settings, try adding @@ -70,8 +80,8 @@ the `--build=missing` option: `conan install .. [ other options ] --build=missing`. This should download and compile the sources of the dependencies. -#### cmake fails when using the Debug flag -Depending on the clang version it might be necessary to use additionally the following flag: +#### cmake fails when using the debug flag +Depending on the clang version it might be necessary to additionally use the following flag: `-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"` #### conan uses outdated cppstd during install @@ -81,31 +91,54 @@ to, e.g., `std::string_view` being unavailable, try specifying the cpp standard manually by `conan install .. [other options] -s "compiler.cppstd=17"`. -## Unit Tests +## Client Configuration ## + +You can use a json file for the configuration of the client. See +`test/test_data/test_caosdb_client.json` for an example. You may use +`caosdb-client-configuration-schema.json` to validate your schema. +Typically, you will need to provide the path to your SSL certificate. + +The client will load the configuration file from the first existing +file in the following locations (precedence from highest to lowest): + +1. A file specified by the environment variable +`$CAOSDB_CLIENT_CONFIGURATION`. +2. `$PWD/caosdb_client.json` +3. `$PWD/caosdb-client.json` +4. `$PWD/.caosdb_client.json` +5. `$PWD/.caosdb-client.json` +6. `$HOME/caosdb_client.json` +7. `$HOME/caosdb-client.json` +8. `$HOME/.caosdb_client.json` +9. `$HOME/.caosdb-client.json` + +## Develop ## + +### Unit tests ### -### Build +#### Build #### For the tests there is a slightly different setup required (with option `-D CMAKE_BUILD_TYPE=Debug`) 1. `mkdir build && cd build/` 2. `conan install .. ` (with gcc, append ` -s "compiler.libcxx=libstdc++11"`, with apple-clang, - append ` -s compiler.cppstd=17`) +append ` -s compiler.cppstd=17`) 3. `cmake -B . -D CMAKE_BUILD_TYPE=Debug ..` - * If your clang-format version is too old, formatting, linting etc. can be skipped: - `cmake -B . -D CMAKE_BUILD_TYPE=Debug -D SKIP_LINTING=ON ..` - * Depending on the clang version it might be necessary to also add - `-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"` +* If your clang-format version is too old, formatting, linting etc. can be skipped: + `cmake -B . -D CMAKE_BUILD_TYPE=Debug -D SKIP_LINTING=ON ..` +* Depending on the clang version it might be necessary to also add + `-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"` 5. `cmake --build .` -### Run +#### Run #### In the build directory, run `ctest` -### Framework +#### Framework #### We use [GoogleTest](https://google.github.io/googletest/) for unit testing. -### Coverage +#### Test coverage #### We use [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html) and [lcov](https://github.com/linux-test-project/lcov) for generating test coverage @@ -120,39 +153,18 @@ necessary to run `ctest` prior to this target. The coverage report can be viewed in a browser by opening `<build_directory>/unit_test_coverage/index.html`. -## Code Formatting +### Code formatting ### * install clang-format on your system. * `clang-format -i --verbose $(find test/ src/ include/ -type f -iname "*.cpp" -o -iname "*.h" -o -iname "*.h.in")` -## Naming Convention +### Naming conventions ### Please adhere to [Google's C++ naming conventions](https://google.github.io/styleguide/cppguide.html#Naming). -## Client Configuration - -You can use a json file for the configuration of the client. See -`test/test_data/test_caosdb_client.json` for an example. You may use -`caosdb-client-configuration-schema.json` to validate your schema. -Typically, you will need to provide the path to your SSL certificate. - -The client will load the configuration file from the first existing -file in the following locations (precedence from highest to lowest): - -1. A file specified by the environment variable - `$CAOSDB_CLIENT_CONFIGURATION`. -2. `$PWD/caosdb_client.json` -3. `$PWD/caosdb-client.json` -4. `$PWD/.caosdb_client.json` -5. `$PWD/.caosdb-client.json` -6. `$HOME/caosdb_client.json` -7. `$HOME/caosdb-client.json` -8. `$HOME/.caosdb_client.json` -9. `$HOME/.caosdb-client.json` - -## Documentation +### Documentation ### -In the build directory, run +To build the documentation, run in the build directory * `cmake --build . --target doc-doxygen` (generate Doxygen) * `cmake --build . --target doc-sphinx` (generate Sphinx) diff --git a/doc/capi/index.rst.in b/doc/capi/index.rst.in index dad5482336472aa01355467687b2441b0a282a7b..71c78372ceebba9d03d77fcefe2d33b01ae1d757 100644 --- a/doc/capi/index.rst.in +++ b/doc/capi/index.rst.in @@ -21,19 +21,25 @@ .. _capi_root: -C API -===== +======= + C API +======= + +.. warning:: + + The C API is intended for developers of other libraries. Special carre needs to be taken for + correct memory management. .. note:: - When working with libcaosdb's C API keep the following in - mind. Delete all objects (transactions, entities, properties, - parents, ...) that you created using a `caosdb_..._create_...` - function or released using a `caosdb_..._release_...` and only - those. This means, that any objects set by a `caosdb_..._get_...` - function, are managed by another owning object (e.g., a connection - object managed by the connection manager) should not be deleted - manually. + When working with libcaosdb's C API keep the following in mind: + + Delete all objects (transactions, entities, properties, parents, ...) that you created using a + call to ``caosdb_..._create_...`` or released using ``caosdb_..._release_...`` and only those. + + Specifically, any objects set by a ``caosdb_..._get_...`` function are managed by another owning + object (e.g., a connection object is managed by the connection manager) and thus should not be + deleted manually. The underlying reason is that all C++ objects are realized in the Extern C interface as mutable structs containing a void pointer to diff --git a/doc/cppapi/index.rst.in b/doc/cppapi/index.rst.in index c9780a92355ab99e7bbdb9cfc1c405c33c3efd30..97a36582e8993b6e31a72117e0fa48db09cc15f8 100644 --- a/doc/cppapi/index.rst.in +++ b/doc/cppapi/index.rst.in @@ -21,8 +21,27 @@ .. _cppapi_root: -C++ API -======= +========= + C++ API +========= + +This is the C++ library for connecting to CaosDB. If you are interested in code examples, please +refer to the corresponding :doc:`documentation section<examples.rst>`. + + +A note on thread safety +^^^^^^^^^^^^^^^^^^^^^^^ + +Only the components which handle GRPC and server connections are thread-safe, Entity and Transaction +objects are not thread-safe. Therefore derived client libraries, such as those for `Julia +<https://gitlab.indiscale.com/caosdb/src/caosdb-julialib>`_ and `Octave +<https://gitlab.indiscale.com/caosdb/src/caosdb-octavelib>`_ probably are not thread-safe either. + +There is a `known bug <https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib/-/issues/17>`_ which +may cause a segmentation fault upon program termination, after leaving the ``main`` function, when +logging is enabled and multiple threads or processes were started. If this bothers you, turn the +logging off in the configuration. + .. toctree:: :glob: diff --git a/include/caosdb/connection.h b/include/caosdb/connection.h index f9aaa8b56c4029f7809f32776a1e607525c8661c..3211c17d47d584b92b940a9aba6213b55528fc2e 100644 --- a/include/caosdb/connection.h +++ b/include/caosdb/connection.h @@ -34,8 +34,8 @@ #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 <filesystem> // 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 @@ -43,10 +43,10 @@ namespace caosdb::connection { using caosdb::authentication::Authenticator; using caosdb::configuration::ConnectionConfiguration; -using caosdb::entity::v1alpha1::EntityTransactionService; -using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::entity::v1::EntityTransactionService; +using caosdb::entity::v1::FileTransmissionService; using caosdb::info::VersionInfo; -using caosdb::info::v1alpha1::GeneralInfoService; +using caosdb::info::v1::GeneralInfoService; using caosdb::transaction::Transaction; using caosdb::transaction::TransactionStatus; using std::filesystem::path; diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h index 42d376698872e086c05a5905484e2f63c11dd346..11909c012e3105ed29185637b3f32801f1613ccf 100644 --- a/include/caosdb/data_type.h +++ b/include/caosdb/data_type.h @@ -28,17 +28,17 @@ #ifndef CAOSDB_DATA_TYPE_H #define CAOSDB_DATA_TYPE_H -#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper -#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message -#include <memory> // for unique_ptr -#include <string> // for string +#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper +#include "caosdb/entity/v1/main.pb.h" // for RepeatedPtrField, Message +#include <memory> // for unique_ptr +#include <string> // for string namespace caosdb::entity { -using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType; -using ProtoDataType = caosdb::entity::v1alpha1::DataType; -using ProtoListDataType = caosdb::entity::v1alpha1::ListDataType; -using ProtoReferenceDataType = caosdb::entity::v1alpha1::ReferenceDataType; -using DataTypeCase = caosdb::entity::v1alpha1::DataType::DataTypeCase; -using ListDataTypeCase = caosdb::entity::v1alpha1::ListDataType::ListDataTypeCase; +using ProtoAtomicDataType = caosdb::entity::v1::AtomicDataType; +using ProtoDataType = caosdb::entity::v1::DataType; +using ProtoListDataType = caosdb::entity::v1::ListDataType; +using ProtoReferenceDataType = caosdb::entity::v1::ReferenceDataType; +using DataTypeCase = caosdb::entity::v1::DataType::DataTypeCase; +using ListDataTypeCase = caosdb::entity::v1::ListDataType::ListDataTypeCase; using caosdb::utility::ProtoMessageWrapper; using caosdb::utility::ScalarProtoMessageWrapper; @@ -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 3e24624a79bff94e72b7398b01b562f962c426ef..6fea70ed8501c04d0da5628956cb9b1157f53e3c 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -30,7 +30,7 @@ #define CAOSDB_ENTITY_H #include "caosdb/data_type.h" // for DataType -#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField +#include "caosdb/entity/v1/main.pb.h" // for RepeatedPtrField #include "caosdb/logging.h" // for CAOSDB_LOG_WARN #include "caosdb/message_code.h" // for get_message_code #include "caosdb/protobuf_helper.h" // for get_arena @@ -50,25 +50,25 @@ #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 caosdb::entity::v1alpha1::IdResponse; using std::filesystem::exists; using std::filesystem::is_directory; -using ProtoParent = caosdb::entity::v1alpha1::Parent; -using ProtoProperty = caosdb::entity::v1alpha1::Property; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; -using ProtoFileDescriptor = caosdb::entity::v1alpha1::FileDescriptor; -using ProtoMessage = caosdb::entity::v1alpha1::Message; -using ProtoValue = caosdb::entity::v1alpha1::Value; -using ProtoDataType = caosdb::entity::v1alpha1::DataType; -using caosdb::entity::v1alpha1::EntityRole; -using ProtoImportance = caosdb::entity::v1alpha1::Importance; +using caosdb::entity::v1::IdResponse; +using ProtoParent = caosdb::entity::v1::Parent; +using ProtoProperty = caosdb::entity::v1::Property; +using ProtoEntity = caosdb::entity::v1::Entity; +using ProtoFileDescriptor = caosdb::entity::v1::FileDescriptor; +using ProtoMessage = caosdb::entity::v1::Message; +using ProtoValue = caosdb::entity::v1::Value; +using ProtoDataType = caosdb::entity::v1::DataType; +using caosdb::entity::v1::EntityRole; +using ProtoImportance = caosdb::entity::v1::Importance; using caosdb::StatusCode; -using caosdb::entity::v1alpha1::EntityResponse; -using caosdb::entity::v1alpha1::FileTransmissionId; +using caosdb::entity::v1::EntityResponse; +using caosdb::entity::v1::FileTransmissionId; using caosdb::utility::get_arena; using caosdb::utility::ProtoMessageWrapper; using ::google::protobuf::RepeatedPtrField; @@ -186,6 +186,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) @@ -336,15 +362,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>(){}; }; /** @@ -358,6 +382,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. @@ -425,14 +480,12 @@ private: */ class Parents : public RepeatedPtrFieldWrapper<Parent, ProtoParent> { public: - ~Parents() = default; friend class Entity; private: - inline Parents() : RepeatedPtrFieldWrapper(){}; - explicit inline Parents( - ::google::protobuf::RepeatedPtrField<caosdb::entity::v1alpha1::Parent> *wrapped) - : RepeatedPtrFieldWrapper(wrapped){}; + inline Parents() : RepeatedPtrFieldWrapper<Parent, ProtoParent>(){}; + explicit inline Parents(::google::protobuf::RepeatedPtrField<caosdb::entity::v1::Parent> *wrapped) + : RepeatedPtrFieldWrapper<Parent, ProtoParent>(wrapped){}; }; /** @@ -455,13 +508,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; } @@ -476,6 +526,8 @@ public: : ScalarProtoMessageWrapper<ProtoProperty>(), value(static_cast<ProtoValue *>(nullptr)), data_type(static_cast<ProtoDataType *>(nullptr)){}; + ~Property() = default; + /** * Return the id of this property */ @@ -562,8 +614,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; } @@ -573,7 +629,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; @@ -605,7 +662,6 @@ private: */ class Properties : public RepeatedPtrFieldWrapper<Property, ProtoProperty> { public: - ~Properties() = default; friend class Entity; private: @@ -623,17 +679,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); @@ -670,6 +732,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(); }; @@ -786,6 +900,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/exceptions.h b/include/caosdb/exceptions.h index 304216679200329660c5068362fa9e089f089235..415d0722580e1199f014358f524caf75f9d68b32 100644 --- a/include/caosdb/exceptions.h +++ b/include/caosdb/exceptions.h @@ -101,12 +101,12 @@ public: }; /** - * @brief The connection isn't known to the ConnectionManager under this name. + * @brief Exception for errors during the configuration of the connection. */ -class UnknownConnectionError : public Exception { +class ConnectionConfigurationError : public Exception { public: - explicit UnknownConnectionError(const std::string &what_arg) - : Exception(StatusCode::UNKNOWN_CONNECTION_ERROR, what_arg) {} + explicit ConnectionConfigurationError(const std::string &what_arg) + : Exception(StatusCode::CONNECTION_CONFIGURATION_ERROR, what_arg) {} }; } // namespace caosdb::exceptions diff --git a/include/caosdb/file_transmission/download_request_handler.h b/include/caosdb/file_transmission/download_request_handler.h index 3af72cc5939ced7a2f6c2edf86981cc8ef62cbb0..0a8e13aac4237b2a9c5e1262dd8fdd0b742a0f29 100644 --- a/include/caosdb/file_transmission/download_request_handler.h +++ b/include/caosdb/file_transmission/download_request_handler.h @@ -50,8 +50,8 @@ #define CAOSDB_FILE_TRANSMISSION_DOWNLOAD_REQUEST_HANDLER_H #include "caosdb/entity.h" // for FileDescriptor -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/entity/v1alpha1/main.pb.h" // for FileDownloadResponse +#include "caosdb/entity/v1/main.grpc.pb.h" // for FileTransmissionS... +#include "caosdb/entity/v1/main.pb.h" // for FileDownloadResponse #include "caosdb/file_transmission/file_writer.h" // for FileWriter #include "caosdb/handler_interface.h" // for HandlerTag, Handl... #include <grpcpp/impl/codegen/async_stream.h> // for ClientAsyncReader @@ -62,9 +62,9 @@ namespace caosdb::transaction { using caosdb::entity::FileDescriptor; -using caosdb::entity::v1alpha1::FileDownloadRequest; -using caosdb::entity::v1alpha1::FileDownloadResponse; -using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::entity::v1::FileDownloadRequest; +using caosdb::entity::v1::FileDownloadResponse; +using caosdb::entity::v1::FileTransmissionService; using caosdb::transaction::HandlerInterface; using caosdb::transaction::HandlerTag; diff --git a/include/caosdb/file_transmission/register_file_upload_handler.h b/include/caosdb/file_transmission/register_file_upload_handler.h index f4586220980b056891effb142c4d736efc809fcf..37df2dbf0fb895cd77f63bab2596a0b124c48b9c 100644 --- a/include/caosdb/file_transmission/register_file_upload_handler.h +++ b/include/caosdb/file_transmission/register_file_upload_handler.h @@ -49,9 +49,9 @@ #ifndef CAOSDB_FILE_TRANSMISSION_REGISTER_FILE_UPLOAD_H #define CAOSDB_FILE_TRANSMISSION_REGISTER_FILE_UPLOAD_H -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/entity/v1alpha1/main.pb.h" // for FileDownloadResponse -#include "caosdb/handler_interface.h" // for HandlerTag, Handl... +#include "caosdb/entity/v1/main.grpc.pb.h" // for FileTransmissionS... +#include "caosdb/entity/v1/main.pb.h" // for FileDownloadResponse +#include "caosdb/handler_interface.h" // for HandlerTag, Handl... #include "caosdb/unary_rpc_handler.h" #include <grpcpp/impl/codegen/async_unary_call.h> // for ClientAsyncRespons... #include <grpcpp/impl/codegen/completion_queue.h> // for CompletionQueue @@ -59,9 +59,9 @@ namespace caosdb::transaction { -using caosdb::entity::v1alpha1::FileTransmissionService; -using caosdb::entity::v1alpha1::RegisterFileUploadRequest; -using caosdb::entity::v1alpha1::RegisterFileUploadResponse; +using caosdb::entity::v1::FileTransmissionService; +using caosdb::entity::v1::RegisterFileUploadRequest; +using caosdb::entity::v1::RegisterFileUploadResponse; class RegisterFileUploadHandler final : public UnaryRpcHandler { public: diff --git a/include/caosdb/file_transmission/upload_request_handler.h b/include/caosdb/file_transmission/upload_request_handler.h index 9965d54ef870c0ab0ae21b65e456859fb1ef34a3..cb9748f868290d362bb21bb66eaacb0267c14eed 100644 --- a/include/caosdb/file_transmission/upload_request_handler.h +++ b/include/caosdb/file_transmission/upload_request_handler.h @@ -50,8 +50,8 @@ #define CAOSDB_FILE_TRANSMISSION_UPLOAD_REQUEST_HANDLER_H #include "caosdb/entity.h" // for FileDescriptor -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/entity/v1alpha1/main.pb.h" // for FileUploadRequest +#include "caosdb/entity/v1/main.grpc.pb.h" // for FileTransmissionS... +#include "caosdb/entity/v1/main.pb.h" // for FileUploadRequest #include "caosdb/file_transmission/file_reader.h" // for FileReader #include "caosdb/handler_interface.h" // for HandlerTag, Handl... #include <cstdint> // for uint64_t @@ -63,9 +63,9 @@ namespace caosdb::transaction { using caosdb::entity::FileDescriptor; -using caosdb::entity::v1alpha1::FileTransmissionService; -using caosdb::entity::v1alpha1::FileUploadRequest; -using caosdb::entity::v1alpha1::FileUploadResponse; +using caosdb::entity::v1::FileTransmissionService; +using caosdb::entity::v1::FileUploadRequest; +using caosdb::entity::v1::FileUploadResponse; using caosdb::transaction::HandlerInterface; using caosdb::transaction::HandlerTag; diff --git a/include/caosdb/info.h b/include/caosdb/info.h index cf2c879120becd8db211e85df39d62ac9ba1434e..0c4132f770d7bd68f10a74743246c0c037364f01 100644 --- a/include/caosdb/info.h +++ b/include/caosdb/info.h @@ -27,13 +27,13 @@ * @date 2021-07-02 * @brief General information about the CaosDBServer. */ -#include "caosdb/info/v1alpha1/main.pb.h" // for VersionInfo -#include <cstdint> // for uint32_t -#include <string> // for string +#include "caosdb/info/v1/main.pb.h" // for VersionInfo +#include <cstdint> // for uint32_t +#include <string> // for string namespace caosdb::info { -using ProtoVersionInfo = caosdb::info::v1alpha1::VersionInfo; +using ProtoVersionInfo = caosdb::info::v1::VersionInfo; /** * A read-only version object which represents the version of the server. diff --git a/include/caosdb/message_code.h b/include/caosdb/message_code.h index a277656cd3848931bdc6dff6d3a802dab8da3282..ce539c188eabfa0d20762eac9fbe1083185286ea 100644 --- a/include/caosdb/message_code.h +++ b/include/caosdb/message_code.h @@ -22,7 +22,7 @@ #ifndef CAOSDB_MESSAGE_CODE_H #define CAOSDB_MESSAGE_CODE_H -#include "caosdb/entity/v1alpha1/main.pb.h" // for Entity, RepeatedField +#include "caosdb/entity/v1/main.pb.h" // for Entity, RepeatedField /** * MessageCodes for entity messages. @@ -38,16 +38,68 @@ namespace caosdb::entity { +#define _MAP_MESSAGE_CODE(name) name = caosdb::entity::v1::MessageCode::MESSAGE_CODE_##name + enum MessageCode { - UNSPECIFIED = caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_UNSPECIFIED, - UNKNOWN = caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_UNKNOWN, - ENTITY_DOES_NOT_EXIST = caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_ENTITY_DOES_NOT_EXIST, - ENTITY_HAS_NO_PROPERTIES = - caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_ENTITY_HAS_NO_PROPERTIES, - INTEGER_VALUE_OUT_OF_RANGE = - caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_INTEGER_VALUE_OUT_OF_RANGE, - ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY = - caosdb::entity::v1alpha1::MessageCode::MESSAGE_CODE_ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY, + _MAP_MESSAGE_CODE(UNSPECIFIED), + _MAP_MESSAGE_CODE(UNKNOWN), + _MAP_MESSAGE_CODE(ENTITY_DOES_NOT_EXIST), + _MAP_MESSAGE_CODE(ENTITY_HAS_NO_PROPERTIES), + _MAP_MESSAGE_CODE(ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY), + _MAP_MESSAGE_CODE(ENTITY_HAS_UNQUALIFIED_PROPERTIES), + _MAP_MESSAGE_CODE(ENTITY_HAS_UNQUALIFIED_PARENTS), + _MAP_MESSAGE_CODE(ENTITY_HAS_NO_ID), + _MAP_MESSAGE_CODE(REQUIRED_BY_PERSISTENT_ENTITY), + _MAP_MESSAGE_CODE(PROPERTY_HAS_NO_DATA_TYPE), + _MAP_MESSAGE_CODE(ENTITY_HAS_NO_DESCRIPTION), + _MAP_MESSAGE_CODE(ENTITY_HAS_NO_NAME), + _MAP_MESSAGE_CODE(OBLIGATORY_PROPERTY_MISSING), + _MAP_MESSAGE_CODE(ENTITY_HAS_NO_PARENTS), + _MAP_MESSAGE_CODE(FILE_HAS_NO_TARGET_PATH), + _MAP_MESSAGE_CODE(TARGET_PATH_NOT_ALLOWED), + _MAP_MESSAGE_CODE(TARGET_PATH_EXISTS), + _MAP_MESSAGE_CODE(PROPERTY_HAS_NO_UNIT), + _MAP_MESSAGE_CODE(CANNOT_PARSE_VALUE), + _MAP_MESSAGE_CODE(CHECKSUM_TEST_FAILED), + _MAP_MESSAGE_CODE(SIZE_TEST_FAILED), + _MAP_MESSAGE_CODE(CANNOT_CREATE_PARENT_FOLDER), + _MAP_MESSAGE_CODE(FILE_HAS_NOT_BEEN_UPLOAED), + _MAP_MESSAGE_CODE(CANNOT_MOVE_FILE_TO_TARGET_PATH), + _MAP_MESSAGE_CODE(CANNOT_PARSE_DATETIME_VALUE), + _MAP_MESSAGE_CODE(CANNOT_PARSE_DOUBLE_VALUE), + _MAP_MESSAGE_CODE(CANNOT_PARSE_INT_VALUE), + _MAP_MESSAGE_CODE(CANNOT_PARSE_BOOL_VALUE), + _MAP_MESSAGE_CODE(FILE_NOT_FOUND), + _MAP_MESSAGE_CODE(WARNING_OCCURED), + _MAP_MESSAGE_CODE(ENTITY_NAME_IS_NOT_UNIQUE), + _MAP_MESSAGE_CODE(QUERY_EXCEPTION), + _MAP_MESSAGE_CODE(TRANSACTION_ROLL_BACK), + _MAP_MESSAGE_CODE(UNKNOWN_UNIT), + _MAP_MESSAGE_CODE(AUTHORIZATION_ERROR), + _MAP_MESSAGE_CODE(REFERENCE_IS_NOT_ALLOWED_BY_DATA_TYPE), + _MAP_MESSAGE_CODE(ENTITY_NAME_DUPLICATES), + _MAP_MESSAGE_CODE(DATA_TYPE_NAME_DUPLICATES), + _MAP_MESSAGE_CODE(ENTITY_HAS_NO_NAME_OR_ID), + _MAP_MESSAGE_CODE(AFFILIATION_ERROR), + _MAP_MESSAGE_CODE(QUERY_PARSING_ERROR), + _MAP_MESSAGE_CODE(NAME_PROPERTIES_MUST_BE_TEXT), + _MAP_MESSAGE_CODE(PARENT_DUPLICATES_WARNING), + _MAP_MESSAGE_CODE(PARENT_DUPLICATES_ERROR), + _MAP_MESSAGE_CODE(ATOMICITY_ERROR), + _MAP_MESSAGE_CODE(NO_SUCH_ENTITY_ROLE), + _MAP_MESSAGE_CODE(REQUIRED_BY_UNQUALIFIED), + _MAP_MESSAGE_CODE(ENTITY_HAS_UNQUALIFIED_REFERENCE), + _MAP_MESSAGE_CODE(REFERENCED_ENTITY_DOES_NOT_EXIST), + _MAP_MESSAGE_CODE(REFERENCE_NAME_DUPLICATES), + _MAP_MESSAGE_CODE(DATA_TYPE_INHERITANCE_AMBIGUOUS), + _MAP_MESSAGE_CODE(DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES), + _MAP_MESSAGE_CODE(CANNOT_PARSE_UNIT), + _MAP_MESSAGE_CODE(ADDITIONAL_PROPERTY), + _MAP_MESSAGE_CODE(PROPERTY_WITH_DATA_TYPE_OVERRIDE), + _MAP_MESSAGE_CODE(PROPERTY_WITH_DESCRIPTION_OVERRIDE), + _MAP_MESSAGE_CODE(PROPERTY_WITH_NAME_OVERRIDE), + _MAP_MESSAGE_CODE(INTEGER_VALUE_OUT_OF_RANGE), + _MAP_MESSAGE_CODE(INTEGRITY_VIOLATION), }; [[nodiscard]] inline auto get_message_code(int code) noexcept -> MessageCode { @@ -57,12 +109,65 @@ enum MessageCode { MessageCode::UNKNOWN, MessageCode::ENTITY_DOES_NOT_EXIST, MessageCode::ENTITY_HAS_NO_PROPERTIES, - MessageCode::INTEGER_VALUE_OUT_OF_RANGE, MessageCode::ENTITY_HAS_BEEN_DELETED_SUCCESSFULLY, + MessageCode::ENTITY_HAS_UNQUALIFIED_PROPERTIES, + MessageCode::ENTITY_HAS_UNQUALIFIED_PARENTS, + MessageCode::ENTITY_HAS_NO_ID, + MessageCode::REQUIRED_BY_PERSISTENT_ENTITY, + MessageCode::PROPERTY_HAS_NO_DATA_TYPE, + MessageCode::ENTITY_HAS_NO_DESCRIPTION, + MessageCode::ENTITY_HAS_NO_NAME, + MessageCode::OBLIGATORY_PROPERTY_MISSING, + MessageCode::ENTITY_HAS_NO_PARENTS, + MessageCode::FILE_HAS_NO_TARGET_PATH, + MessageCode::TARGET_PATH_NOT_ALLOWED, + MessageCode::TARGET_PATH_EXISTS, + MessageCode::PROPERTY_HAS_NO_UNIT, + MessageCode::CANNOT_PARSE_VALUE, + MessageCode::CHECKSUM_TEST_FAILED, + MessageCode::SIZE_TEST_FAILED, + MessageCode::CANNOT_CREATE_PARENT_FOLDER, + MessageCode::FILE_HAS_NOT_BEEN_UPLOAED, + MessageCode::CANNOT_MOVE_FILE_TO_TARGET_PATH, + MessageCode::CANNOT_PARSE_DATETIME_VALUE, + MessageCode::CANNOT_PARSE_DOUBLE_VALUE, + MessageCode::CANNOT_PARSE_INT_VALUE, + MessageCode::CANNOT_PARSE_BOOL_VALUE, + MessageCode::FILE_NOT_FOUND, + MessageCode::WARNING_OCCURED, + MessageCode::ENTITY_NAME_IS_NOT_UNIQUE, + MessageCode::QUERY_EXCEPTION, + MessageCode::TRANSACTION_ROLL_BACK, + MessageCode::UNKNOWN_UNIT, + MessageCode::AUTHORIZATION_ERROR, + MessageCode::REFERENCE_IS_NOT_ALLOWED_BY_DATA_TYPE, + MessageCode::ENTITY_NAME_DUPLICATES, + MessageCode::DATA_TYPE_NAME_DUPLICATES, + MessageCode::ENTITY_HAS_NO_NAME_OR_ID, + MessageCode::AFFILIATION_ERROR, + MessageCode::QUERY_PARSING_ERROR, + MessageCode::NAME_PROPERTIES_MUST_BE_TEXT, + MessageCode::PARENT_DUPLICATES_WARNING, + MessageCode::PARENT_DUPLICATES_ERROR, + MessageCode::ATOMICITY_ERROR, + MessageCode::NO_SUCH_ENTITY_ROLE, + MessageCode::REQUIRED_BY_UNQUALIFIED, + MessageCode::ENTITY_HAS_UNQUALIFIED_REFERENCE, + MessageCode::REFERENCED_ENTITY_DOES_NOT_EXIST, + MessageCode::REFERENCE_NAME_DUPLICATES, + MessageCode::DATA_TYPE_INHERITANCE_AMBIGUOUS, + MessageCode::DATA_TYPE_DOES_NOT_ACCEPT_COLLECTION_VALUES, + MessageCode::CANNOT_PARSE_UNIT, + MessageCode::ADDITIONAL_PROPERTY, + MessageCode::PROPERTY_WITH_DATA_TYPE_OVERRIDE, + MessageCode::PROPERTY_WITH_DESCRIPTION_OVERRIDE, + MessageCode::PROPERTY_WITH_NAME_OVERRIDE, + MessageCode::INTEGER_VALUE_OUT_OF_RANGE, + MessageCode::INTEGRITY_VIOLATION, }; for (MessageCode known_code : all_codes) { - if (known_code == code) { + if (static_cast<int>(known_code) == code) { return known_code; } } diff --git a/include/caosdb/protobuf_helper.h b/include/caosdb/protobuf_helper.h index c111ac96748a057be21b7d20bb84324ac442e285..dad62a9af2f8a538ce23d86fa52189df2c75c4b9 100644 --- a/include/caosdb/protobuf_helper.h +++ b/include/caosdb/protobuf_helper.h @@ -69,11 +69,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/include/caosdb/status_code.h b/include/caosdb/status_code.h index e458b1727af51720451cbc057d4e40cee35a4a4e..e1a382191b5bd4559c554e2fc3e084103c27c3cc 100644 --- a/include/caosdb/status_code.h +++ b/include/caosdb/status_code.h @@ -62,7 +62,7 @@ enum StatusCode { GENERIC_ERROR = 21, GENERIC_TRANSACTION_ERROR = 22, CONFIGURATION_ERROR = 23, - UNKNOWN_CONNECTION_ERROR = 24, + CONNECTION_CONFIGURATION_ERROR = 24, TRANSACTION_STATUS_ERROR = 25, TRANSACTION_TYPE_ERROR = 26, UNSUPPORTED_FEATURE = 27, diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h index 19afde62f7020d3004dd7a4def58cb6330a92599..31a537e4483b1a715d01dec0929d18f27c6a6a79 100644 --- a/include/caosdb/transaction.h +++ b/include/caosdb/transaction.h @@ -22,8 +22,8 @@ #define CAOSDB_TRANSACTION_H #include "caosdb/entity.h" // for Entity, FileDe... -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransact... -#include "caosdb/entity/v1alpha1/main.pb.h" // for MultiTransacti... +#include "caosdb/entity/v1/main.grpc.pb.h" // for EntityTransact... +#include "caosdb/entity/v1/main.pb.h" // for MultiTransacti... #include "caosdb/handler_interface.h" // for HandlerInterface #include "caosdb/transaction_handler.h" // for EntityTransactionHandler #include "caosdb/logging.h" // for CAOSDB_LOG_ERR... @@ -92,7 +92,7 @@ } \ switch (this->transaction_type) { \ case TransactionType::NONE: \ - this->transaction_type = TransactionType::DELETE_ONLY; \ + this->transaction_type = TransactionType::MIXED_WRITE; \ case TransactionType::DELETE_ONLY: \ case TransactionType::MIXED_WRITE: \ case TransactionType::MIXED_READ_AND_WRITE: \ @@ -114,7 +114,7 @@ } \ switch (this->transaction_type) { \ case TransactionType::NONE: \ - this->transaction_type = TransactionType::INSERT_ONLY; \ + this->transaction_type = TransactionType::MIXED_WRITE; \ case TransactionType::INSERT_ONLY: \ case TransactionType::MIXED_WRITE: \ case TransactionType::MIXED_READ_AND_WRITE: \ @@ -136,7 +136,7 @@ } \ switch (this->transaction_type) { \ case TransactionType::NONE: \ - this->transaction_type = TransactionType::UPDATE_ONLY; \ + this->transaction_type = TransactionType::MIXED_WRITE; \ case TransactionType::UPDATE_ONLY: \ case TransactionType::MIXED_WRITE: \ case TransactionType::MIXED_READ_AND_WRITE: \ @@ -163,22 +163,21 @@ namespace caosdb::transaction { using caosdb::entity::Entity; using caosdb::entity::FileDescriptor; -using caosdb::entity::v1alpha1::EntityResponse; -using caosdb::entity::v1alpha1::EntityTransactionService; -using caosdb::entity::v1alpha1::FileDownloadRequest; -using caosdb::entity::v1alpha1::FileDownloadResponse; -using caosdb::entity::v1alpha1::FileTransmissionId; -using caosdb::entity::v1alpha1::FileTransmissionService; -using caosdb::entity::v1alpha1::FileUploadRequest; -using caosdb::entity::v1alpha1::FileUploadResponse; -using caosdb::entity::v1alpha1::IdResponse; -using caosdb::entity::v1alpha1::MultiTransactionRequest; -using caosdb::entity::v1alpha1::MultiTransactionResponse; -using caosdb::entity::v1alpha1::RegisterFileUploadRequest; -using caosdb::entity::v1alpha1::RegisterFileUploadResponse; +using caosdb::entity::v1::EntityResponse; +using caosdb::entity::v1::EntityTransactionService; +using caosdb::entity::v1::FileDownloadRequest; +using caosdb::entity::v1::FileDownloadResponse; +using caosdb::entity::v1::FileTransmissionId; +using caosdb::entity::v1::FileTransmissionService; +using caosdb::entity::v1::FileUploadRequest; +using caosdb::entity::v1::FileUploadResponse; +using caosdb::entity::v1::IdResponse; +using caosdb::entity::v1::MultiTransactionRequest; +using caosdb::entity::v1::MultiTransactionResponse; +using caosdb::entity::v1::RegisterFileUploadRequest; +using caosdb::entity::v1::RegisterFileUploadResponse; using caosdb::transaction::TransactionStatus; -using TransactionResponseCase = - caosdb::entity::v1alpha1::TransactionResponse::TransactionResponseCase; +using TransactionResponseCase = caosdb::entity::v1::TransactionResponse::TransactionResponseCase; using caosdb::utility::get_arena; using google::protobuf::Arena; diff --git a/include/caosdb/transaction_handler.h b/include/caosdb/transaction_handler.h index 18cb5fcfcaa87a924ff0f36b0c5356d10fc9f70b..6fa386be32628d5d0ae80a90dda1e1293d1eae70 100644 --- a/include/caosdb/transaction_handler.h +++ b/include/caosdb/transaction_handler.h @@ -1,6 +1,6 @@ #pragma once -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for FileTransmissionS... -#include "caosdb/entity/v1alpha1/main.pb.h" // for FileDownloadResponse +#include "caosdb/entity/v1/main.grpc.pb.h" // for FileTransmissionS... +#include "caosdb/entity/v1/main.pb.h" // for FileDownloadResponse #include "caosdb/handler_interface.h" // for HandlerTag #include "caosdb/unary_rpc_handler.h" // for HandlerTag, Handl... #include <grpcpp/impl/codegen/async_unary_call.h> // for ClientAsyncRespons... @@ -9,9 +9,9 @@ namespace caosdb::transaction { -using caosdb::entity::v1alpha1::EntityTransactionService; -using caosdb::entity::v1alpha1::MultiTransactionRequest; -using caosdb::entity::v1alpha1::MultiTransactionResponse; +using caosdb::entity::v1::EntityTransactionService; +using caosdb::entity::v1::MultiTransactionRequest; +using caosdb::entity::v1::MultiTransactionResponse; class EntityTransactionHandler final : public UnaryRpcHandler { public: diff --git a/include/caosdb/value.h b/include/caosdb/value.h index 8296be311a8262339b58de06d49940100fc183f3..a92847a82d3cd15ad2dda61e64c6843b99ac6d75 100644 --- a/include/caosdb/value.h +++ b/include/caosdb/value.h @@ -21,14 +21,14 @@ #ifndef CAOSDB_VALUE_H #define CAOSDB_VALUE_H -#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper -#include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message -#include <cstdint> // for int64_t -#include <google/protobuf/arena.h> // for Arena -#include <memory> // for unique_ptr -#include <string> // for string, operator== -#include <utility> // for move -#include <vector> // for vector +#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper +#include "caosdb/entity/v1/main.pb.h" // for RepeatedPtrField, Message +#include <cstdint> // for int64_t +#include <google/protobuf/arena.h> // for Arena +#include <memory> // for unique_ptr +#include <string> // for string, operator== +#include <utility> // for move +#include <vector> // for vector #define LIST_VALUE_CONSTRUCTOR(TYPE, SETTER) \ explicit inline Value(const std::vector<TYPE> &values) \ @@ -43,11 +43,11 @@ using caosdb::utility::get_arena; using caosdb::utility::ProtoMessageWrapper; using caosdb::utility::ScalarProtoMessageWrapper; using google::protobuf::Arena; -using ProtoSpecialValue = caosdb::entity::v1alpha1::SpecialValue; -using ProtoValue = caosdb::entity::v1alpha1::Value; -using ProtoScalarValue = caosdb::entity::v1alpha1::ScalarValue; -using ValueCase = caosdb::entity::v1alpha1::Value::ValueCase; -using ScalarValueCase = caosdb::entity::v1alpha1::ScalarValue::ScalarValueCase; +using ProtoSpecialValue = caosdb::entity::v1::SpecialValue; +using ProtoValue = caosdb::entity::v1::Value; +using ProtoScalarValue = caosdb::entity::v1::ScalarValue; +using ValueCase = caosdb::entity::v1::Value::ValueCase; +using ScalarValueCase = caosdb::entity::v1::ScalarValue::ScalarValueCase; class ScalarValue; class Value; diff --git a/proto b/proto index 73d85fb20bb16902c0a89dda697eed17994712bc..9fa41dce325d370eb8da60a77e921d4a0618f513 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 73d85fb20bb16902c0a89dda697eed17994712bc +Subproject commit 9fa41dce325d370eb8da60a77e921d4a0618f513 diff --git a/requirements.txt b/requirements.txt index 2911ae69101c3c4bd492308915b7a5a653a2d170..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.37.2 -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/connection.cpp b/src/caosdb/connection.cpp index d6782f8ffa42238888998bdff65dc666fbf55c18..02c190ee1beff00fc3cbffa950628a67b5ffa32d 100644 --- a/src/caosdb/connection.cpp +++ b/src/caosdb/connection.cpp @@ -23,8 +23,8 @@ #include "caosdb/configuration.h" // for ConnectionConfigur... #include "caosdb/exceptions.h" // for ConfigurationError #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/info/v1/main.grpc.pb.h" // for GeneralInfoService +#include "caosdb/info/v1/main.pb.h" // for GetVersionInfoRequest #include "caosdb/transaction.h" // for Transaction #include "caosdb/transaction_status.h" // for TransactionStatus #include "grpcpp/impl/codegen/status_code_enum.h" // for StatusCode, UNAUTH... @@ -36,12 +36,12 @@ namespace caosdb::connection { using caosdb::configuration::ConfigurationManager; using caosdb::configuration::ConnectionConfiguration; -using caosdb::entity::v1alpha1::EntityTransactionService; -using caosdb::entity::v1alpha1::FileTransmissionService; +using caosdb::entity::v1::EntityTransactionService; +using caosdb::entity::v1::FileTransmissionService; using caosdb::info::VersionInfo; -using caosdb::info::v1alpha1::GeneralInfoService; -using caosdb::info::v1alpha1::GetVersionInfoRequest; -using caosdb::info::v1alpha1::GetVersionInfoResponse; +using caosdb::info::v1::GeneralInfoService; +using caosdb::info::v1::GetVersionInfoRequest; +using caosdb::info::v1::GetVersionInfoResponse; using caosdb::transaction::Transaction; using caosdb::transaction::TransactionStatus; @@ -109,8 +109,8 @@ auto ConnectionManager::mGetConnection(const std::string &name) const auto connection = ConfigurationManager::GetConnectionConfiguration(name); connections[name] = std::make_shared<Connection>(*connection.release()); } catch (const caosdb::exceptions::ConfigurationError &exc) { - throw caosdb::exceptions::UnknownConnectionError("No connection named '" + name + - "' present."); + throw caosdb::exceptions::ConnectionConfigurationError("Error with the connection named '" + + name + "': " + exc.what()); } } return this->connections.at(name); diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp index bb73431e4af00ed1db48b8f87fa883db6f4f9b31..127d5b4e41ef5b859bbb17d5ebcec1b2c678fa43 100644 --- a/src/caosdb/entity.cpp +++ b/src/caosdb/entity.cpp @@ -20,26 +20,24 @@ * */ #include "caosdb/entity.h" -#include "caosdb/data_type.h" // for DataType -#include "caosdb/entity/v1alpha1/main.pb.h" // for Messages -#include "caosdb/protobuf_helper.h" // for get_arena -#include "caosdb/value.h" // for Value -#include <google/protobuf/arena.h> // for Arena -#include <new> // for operator new +#include "caosdb/data_type.h" // for DataType +#include "caosdb/entity/v1/main.pb.h" // for Messages +#include "caosdb/protobuf_helper.h" // for get_arena +#include "caosdb/value.h" // for Value +#include <google/protobuf/arena.h> // for Arena +#include <new> // for operator new namespace caosdb::entity { -using ProtoParent = caosdb::entity::v1alpha1::Parent; -using ProtoProperty = caosdb::entity::v1alpha1::Property; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; -using ProtoImportance = caosdb::entity::v1alpha1::Importance; -using caosdb::entity::v1alpha1::EntityRole; -using ProtoMessage = caosdb::entity::v1alpha1::Message; -using ProtoFileDescriptor = caosdb::entity::v1alpha1::FileDescriptor; +using ProtoParent = caosdb::entity::v1::Parent; +using ProtoProperty = caosdb::entity::v1::Property; +using ProtoEntity = caosdb::entity::v1::Entity; +using ProtoImportance = caosdb::entity::v1::Importance; +using caosdb::entity::v1::EntityRole; +using ProtoMessage = caosdb::entity::v1::Message; +using ProtoFileDescriptor = caosdb::entity::v1::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/file_reader.cpp b/src/caosdb/file_transmission/file_reader.cpp index 3d08f5d8ad1a2d5b012086cf9f75e52327d9dfda..e943153ca7cfcc87907ed88afb1995ad31cde71d 100644 --- a/src/caosdb/file_transmission/file_reader.cpp +++ b/src/caosdb/file_transmission/file_reader.cpp @@ -58,7 +58,7 @@ FileReader::FileReader(std::filesystem::path filename) : filename_(std::move(fil } void FileReader::openFile() { - stream_.open(filename_, std::ios::binary | std::ios::ate); + stream_.open(filename_.generic_string(), std::ios::binary | std::ios::ate); if (!stream_) { throw FileIOError("Can't open file for reading: " + filename_.string()); } diff --git a/src/caosdb/file_transmission/file_writer.cpp b/src/caosdb/file_transmission/file_writer.cpp index 3f49ea43df85a54fd3dec6c5c8125be46b43d676..0f0161fbcafe1df7f6ffa271dcce8af9cc10fe82 100644 --- a/src/caosdb/file_transmission/file_writer.cpp +++ b/src/caosdb/file_transmission/file_writer.cpp @@ -58,7 +58,7 @@ FileWriter::FileWriter(std::filesystem::path filename) : filename_(std::move(fil } void FileWriter::openFile() { - stream_.open(filename_, std::ios::binary | std::ios::trunc); + stream_.open(filename_.generic_string(), std::ios::binary | std::ios::trunc); if (!stream_) { throw FileIOError("Can't open file for writing: " + filename_.string()); } diff --git a/src/caosdb/status_code_description.cpp b/src/caosdb/status_code_description.cpp index d5e08e7820ca0f7380723087570f838465a9c261..5823943cfd7f79416cabb61662f778bac5de9bf8 100644 --- a/src/caosdb/status_code_description.cpp +++ b/src/caosdb/status_code_description.cpp @@ -131,8 +131,9 @@ auto get_status_description(int code) -> const std::string & { "The transaction terminated unsuccessfully with transaction errors."}, {StatusCode::CONFIGURATION_ERROR, "An error occurred during the configuration of the ConfigurationManager."}, - {StatusCode::UNKNOWN_CONNECTION_ERROR, - "The ConnectionManager does not know any connection of this name."}, + {StatusCode::CONNECTION_CONFIGURATION_ERROR, + "Wither there is no connection of the given name or the given connection has a faulty " + "configuration"}, {StatusCode::TRANSACTION_STATUS_ERROR, "The Transaction is in a wrong state for the attempted action."}, {StatusCode::TRANSACTION_TYPE_ERROR, diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp index 8a1fe4adeb969adddef7e46c4736e9f122a0113a..694274a1af888c22b0892a3b78ef2a1f93260a4b 100644 --- a/src/caosdb/transaction.cpp +++ b/src/caosdb/transaction.cpp @@ -18,8 +18,8 @@ * */ #include "caosdb/transaction.h" -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransac... -#include "caosdb/entity/v1alpha1/main.pb.h" // for TransactionRe... +#include "caosdb/entity/v1/main.grpc.pb.h" // for EntityTransac... +#include "caosdb/entity/v1/main.pb.h" // for TransactionRe... #include "caosdb/file_transmission/download_request_handler.h" // Download... #include "caosdb/file_transmission/file_reader.h" // for path #include "caosdb/file_transmission/register_file_upload_handler.h" // for RegisterFileUploadHandler @@ -45,17 +45,16 @@ #include <utility> // for move, pair namespace caosdb::transaction { -using caosdb::entity::v1alpha1::EntityTransactionService; -using caosdb::entity::v1alpha1::FileTransmissionService; -using caosdb::entity::v1alpha1::MultiTransactionRequest; -using caosdb::entity::v1alpha1::MultiTransactionResponse; -using TransactionResponseCase = - caosdb::entity::v1alpha1::TransactionResponse::TransactionResponseCase; -using RetrieveResponseCase = caosdb::entity::v1alpha1::RetrieveResponse::RetrieveResponseCase; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; +using caosdb::entity::v1::EntityTransactionService; +using caosdb::entity::v1::FileTransmissionService; +using caosdb::entity::v1::MultiTransactionRequest; +using caosdb::entity::v1::MultiTransactionResponse; +using TransactionResponseCase = caosdb::entity::v1::TransactionResponse::TransactionResponseCase; +using RetrieveResponseCase = caosdb::entity::v1::RetrieveResponse::RetrieveResponseCase; +using ProtoEntity = caosdb::entity::v1::Entity; using google::protobuf::Arena; using NextStatus = grpc::CompletionQueue::NextStatus; -using RegistrationStatus = caosdb::entity::v1alpha1::RegistrationStatus; +using RegistrationStatus = caosdb::entity::v1::RegistrationStatus; ResultSet::iterator::iterator(const ResultSet *result_set_param, int index) : current_index(index), result_set(result_set_param) {} @@ -157,7 +156,7 @@ auto Transaction::InsertEntity(Entity *entity) noexcept -> StatusCode { entity->SetFileTransmissionId(file_transmission_id); upload_files.push_back(entity->GetFileDescriptor()); } - this->status = TransactionStatus::READY(); + this->status = TransactionStatus::GO_ON(); return this->status.GetCode(); } @@ -174,7 +173,7 @@ auto Transaction::UpdateEntity(Entity *entity) noexcept -> StatusCode { entity->SetFileTransmissionId(file_transmission_id); upload_files.push_back(entity->GetFileDescriptor()); } - this->status = TransactionStatus::READY(); + this->status = TransactionStatus::GO_ON(); return this->status.GetCode(); } @@ -193,16 +192,10 @@ auto Transaction::ExecuteAsynchronously() noexcept -> StatusCode { // NOLINT return StatusCode::TRANSACTION_STATUS_ERROR; } switch (this->transaction_type) { - case TransactionType::MIXED_WRITE: - CAOSDB_LOG_ERROR_AND_RETURN_STATUS( - logger_name, StatusCode::UNSUPPORTED_FEATURE, - "MIXED_WRITE UNSUPPORTED: The current implementation does not support " - "mixed write transactions (containing insertions, deletions, and updates " - "in one transaction).") - case TransactionType::MIXED_READ_AND_WRITE: + case MIXED_READ_AND_WRITE: CAOSDB_LOG_ERROR_AND_RETURN_STATUS( logger_name, StatusCode::UNSUPPORTED_FEATURE, - "MIXED_WRITE UNSUPPORTED: The current implementation does not support " + "MIXED_READ_AND_WRITE UNSUPPORTED: The current implementation does not support " "mixed read and write transactions (containing retrievals, insertions, " "deletions, and updates in one transaction).") default: 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_ccaosdb.cpp b/test/test_ccaosdb.cpp index 41a0b9bbcda73145dbc777ddbe43ebcafffe7555..1059f161525d513389efd4df95cdd04ec5a088db 100644 --- a/test/test_ccaosdb.cpp +++ b/test/test_ccaosdb.cpp @@ -987,8 +987,7 @@ TEST_F(test_ccaosdb, test_insert_update_delete) { caosdb_entity_entity_set_file_path(&entity, "some_name"); auto return_code = caosdb_transaction_transaction_insert_entity(&insert_transaction, &entity); - // For now, nothing further can be done here, so it should be READY - EXPECT_EQ(return_code, caosdb::StatusCode::READY); + EXPECT_EQ(return_code, caosdb::StatusCode::GO_ON); caosdb_transaction_transaction update_transaction; caosdb_connection_connection_create_transaction(&connection, &update_transaction); diff --git a/test/test_connection.cpp b/test/test_connection.cpp index 99391536edf031fbe4a326f56e24f68e5a50b5d3..4a5260e10964bc652c4ac803bf376b6b6cf39ead 100644 --- a/test/test_connection.cpp +++ b/test/test_connection.cpp @@ -22,7 +22,7 @@ #include "caosdb/certificate_provider.h" // for PemCertificateProvider #include "caosdb/configuration.h" // for InsecureConnectionConfigura... #include "caosdb/connection.h" // for ConnectionManager -#include "caosdb/exceptions.h" // for UnknownConnectionError +#include "caosdb/exceptions.h" // for ConnectionConfigurationError #include "caosdb_test_utility.h" // for EXPECT_THROW_MESSAGE, TEST_... #include <gtest/gtest-message.h> // for Message #include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestPartR... @@ -65,9 +65,16 @@ TEST_F(test_connection, configure_ssl_localhost_8080) { } TEST_F(test_connection, connection_manager_unknown_connection) { - EXPECT_THROW_MESSAGE(ConnectionManager::GetConnection("test"), - caosdb::exceptions::UnknownConnectionError, - "No connection named 'test' present."); + EXPECT_THROW_MESSAGE( + ConnectionManager::GetConnection("test"), caosdb::exceptions::ConnectionConfigurationError, + "Error with the connection named 'test': The connection 'test' has not been defined."); +} + +TEST_F(test_connection, connection_missing_certificate) { + EXPECT_THROW_MESSAGE(ConnectionManager::GetConnection("missing"), + caosdb::exceptions::ConnectionConfigurationError, + std::string("Error with the connection named 'missing': ") + + "File does not exist (server_certificate_path): /missing"); } TEST_F(test_connection, connection_manager_get_default_connection) { diff --git a/test/test_data/test_caosdb_client.json b/test/test_data/test_caosdb_client.json index 2007413021b332c3bd32686363e241804a8d62ab..276c542f75353090b28918ab0ef9b33f9f0815e1 100644 --- a/test/test_data/test_caosdb_client.json +++ b/test/test_data/test_caosdb_client.json @@ -13,6 +13,16 @@ "local-caosdb": { "host": "localhost", "port": 8443, + "authentication": { + "type": "plain", + "username": "me", + "password": "secret!" + } + }, + "missing": { + "host": "localhost", + "port": 8443, + "server_certificate_path": "/missing", "authentication": { "type": "plain", "username": "me", diff --git a/test/test_data_type.cpp b/test/test_data_type.cpp index 78e5100f3ce984ece46918df4aca9ffb8f1d2522..c846dceb5ca196db3b58a5aae901f735ee9dc3f2 100644 --- a/test/test_data_type.cpp +++ b/test/test_data_type.cpp @@ -22,7 +22,7 @@ #include "caosdb/data_type.h" // for DataType, AtomicDataType #include "caosdb/entity.h" // for Entity -#include "caosdb/entity/v1alpha1/main.pb.h" // for DataType, Ato... +#include "caosdb/entity/v1/main.pb.h" // for DataType, Ato... #include "caosdb/logging.h" // for CAOSDB_LOG_DEBUG #include "caosdb/protobuf_helper.h" // for CAOSDB_DEBUG_... #include <boost/log/core/record.hpp> // for record @@ -39,10 +39,10 @@ #include <utility> // for pair namespace caosdb::entity { -using ProtoEntity = caosdb::entity::v1alpha1::Entity; -using ProtoParent = caosdb::entity::v1alpha1::Parent; -using ProtoDataType = caosdb::entity::v1alpha1::DataType; -using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType; +using ProtoEntity = caosdb::entity::v1::Entity; +using ProtoParent = caosdb::entity::v1::Parent; +using ProtoDataType = caosdb::entity::v1::DataType; +using ProtoAtomicDataType = caosdb::entity::v1::AtomicDataType; TEST(test_data_type, test_atomic) { ProtoDataType proto_data_type; @@ -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..a027ad7e8e3e5bac30d7e8c33e15f0e15ee6a91f 100644 --- a/test/test_entity.cpp +++ b/test/test_entity.cpp @@ -20,31 +20,35 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. * */ -#include "caosdb/data_type.h" // for DataType, AtomicDat... -#include "caosdb/entity.h" // for Entity, Property -#include "caosdb/entity/v1alpha1/main.grpc.pb.h" // for EntityTransactionSe... -#include "caosdb/entity/v1alpha1/main.pb.h" // for IdResponse, Message -#include "caosdb/message_code.h" // for MessageCode, ENTITY... -#include "caosdb/protobuf_helper.h" // for get_arena -#include "caosdb/status_code.h" // for StatusCode, FILE_DO... -#include "caosdb/transaction.h" // for Transaction -#include "caosdb/value.h" // for Value -#include "caosdb_test_utility.h" // for TEST_DATA_DIR -#include <google/protobuf/arena.h> // for Arena -#include <gtest/gtest-message.h> // for Message -#include <gtest/gtest-test-part.h> // for TestPartResult, Sui... -#include <gtest/gtest_pred_impl.h> // for Test, EXPECT_EQ -#include <iostream> // for operator<<, basic_o... -#include <memory> // for allocator, shared_ptr -#include <stdexcept> // for out_of_range -#include <string> // for operator+, to_string -#include <utility> // for move +#include "caosdb/data_type.h" // for DataType, AtomicDat... +#include "caosdb/entity.h" // for Entity, Property +#include "caosdb/entity/v1/main.grpc.pb.h" // for EntityTransactionSe... +#include "caosdb/entity/v1/main.pb.h" // for IdResponse, Message +#include "caosdb/message_code.h" // for MessageCode, ENTITY... +#include "caosdb/protobuf_helper.h" // for get_arena +#include "caosdb/status_code.h" // for StatusCode, FILE_DO... +#include "caosdb/transaction.h" // for Transaction +#include "caosdb/value.h" // for Value +#include "caosdb_test_utility.h" // for TEST_DATA_DIR +#include <google/protobuf/arena.h> // for Arena +#include <gtest/gtest-message.h> // for Message +#include <gtest/gtest-test-part.h> // for TestPartResult, Sui... +#include <gtest/gtest_pred_impl.h> // for Test, EXPECT_EQ +#include <iostream> // for operator<<, basic_o... +#include <memory> // for allocator, shared_ptr +#include <stdexcept> // for out_of_range +#include <string> // for operator+, to_string +#include <utility> // for move namespace caosdb::entity { -using caosdb::entity::v1alpha1::IdResponse; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; -using ProtoParent = caosdb::entity::v1alpha1::Parent; +using caosdb::entity::v1::IdResponse; +using ProtoEntity = caosdb::entity::v1::Entity; +using ProtoParent = caosdb::entity::v1::Parent; +using ProtoProperty = caosdb::entity::v1::Property; +using ProtoAtomicDataType = caosdb::entity::v1::AtomicDataType; +using caosdb::entity::v1::EntityResponse; using caosdb::utility::get_arena; +using ProtoEntityRole = caosdb::entity::v1::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_info.cpp b/test/test_info.cpp index a95870200ac51343f86b7bb5ff4c0c433d692f0c..4331219ab02ae5c60e165bee7992c6466d4889f2 100644 --- a/test/test_info.cpp +++ b/test/test_info.cpp @@ -20,15 +20,15 @@ * */ -#include "caosdb/info.h" // for VersionInfo -#include "caosdb/info/v1alpha1/main.pb.h" // for VersionInfo -#include <gtest/gtest-message.h> // for Message -#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiRe... -#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST -#include <memory> // for allocator +#include "caosdb/info.h" // for VersionInfo +#include "caosdb/info/v1/main.pb.h" // for VersionInfo +#include <gtest/gtest-message.h> // for Message +#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiRe... +#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST +#include <memory> // for allocator namespace caosdb::info { -using ProtoVersionInfo = caosdb::info::v1alpha1::VersionInfo; +using ProtoVersionInfo = caosdb::info::v1::VersionInfo; TEST(test_info, create_info_from_proto_info) { auto *origial = new ProtoVersionInfo(); diff --git a/test/test_list_properties.cpp b/test/test_list_properties.cpp index bc82896f5e7623643cb249979f381f3a7097d40d..8e69ba381c20808fa4112eca06270c8bda5fa351 100644 --- a/test/test_list_properties.cpp +++ b/test/test_list_properties.cpp @@ -20,23 +20,23 @@ * */ -#include "caosdb/data_type.h" // for DataType, AtomicDataType -#include "caosdb/entity.h" // for Entity -#include "caosdb/entity/v1alpha1/main.pb.h" // for AtomicDataType, DataType -#include "caosdb/value.h" // for Value -#include <cstdint> // for int64_t -#include <gtest/gtest-message.h> // for Message -#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApi... -#include <gtest/gtest_pred_impl.h> // for AssertionResult, Test -#include <memory> // for allocator_traits<>::valu... -#include <string> // for string -#include <vector> // for vector +#include "caosdb/data_type.h" // for DataType, AtomicDataType +#include "caosdb/entity.h" // for Entity +#include "caosdb/entity/v1/main.pb.h" // for AtomicDataType, DataType +#include "caosdb/value.h" // for Value +#include <cstdint> // for int64_t +#include <gtest/gtest-message.h> // for Message +#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApi... +#include <gtest/gtest_pred_impl.h> // for AssertionResult, Test +#include <memory> // for allocator_traits<>::valu... +#include <string> // for string +#include <vector> // for vector namespace caosdb::entity { -using ProtoEntity = caosdb::entity::v1alpha1::Entity; -using ProtoParent = caosdb::entity::v1alpha1::Parent; -using ProtoDataType = caosdb::entity::v1alpha1::DataType; -using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType; +using ProtoEntity = caosdb::entity::v1::Entity; +using ProtoParent = caosdb::entity::v1::Parent; +using ProtoDataType = caosdb::entity::v1::DataType; +using ProtoAtomicDataType = caosdb::entity::v1::AtomicDataType; TEST(test_list_property, test_list_of_text) { Property list_property; diff --git a/test/test_protobuf.cpp b/test/test_protobuf.cpp index 6f9bda0740487db475f1e34757e4a612c59061f9..8e5c84e2e5ccb80e4a03d99cf8914593df996131 100644 --- a/test/test_protobuf.cpp +++ b/test/test_protobuf.cpp @@ -19,18 +19,18 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. * */ -#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 <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 +#include "caosdb/data_type.h" // for DataType, ReferenceDataType +#include "caosdb/entity.h" // for Entity +#include "caosdb/entity/v1/main.pb.h" // for RepeatedPtrField, Message +#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 ProtoEntity = caosdb::entity::v1alpha1::Entity; +using ProtoEntity = caosdb::entity::v1::Entity; using caosdb::entity::Entity; -using caosdb::entity::v1alpha1::Message; +using caosdb::entity::v1::Message; TEST(test_protobuf, test_swap_trivial) { Message message_source; diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp index 7c93ac5d9b081ac4cb2314f34272f54cba0f61c9..535f7587aca4ef4e2b44225b5db8eef9ebdc8fd6 100644 --- a/test/test_transaction.cpp +++ b/test/test_transaction.cpp @@ -17,11 +17,11 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -#include "caosdb/configuration.h" // for InsecureConnectionConfig... -#include "caosdb/connection.h" // for Connection -#include "caosdb/entity.h" // for Entity -#include "caosdb/entity/v1alpha1/main.pb.h" // for Entity -#include "caosdb/exceptions.h" // for ConnectionError +#include "caosdb/configuration.h" // for InsecureConnectionConfig... +#include "caosdb/connection.h" // for Connection +#include "caosdb/entity.h" // for Entity +#include "caosdb/entity/v1/main.pb.h" // for Entity +#include "caosdb/exceptions.h" // for ConnectionError #include "caosdb/status_code.h" #include "caosdb/transaction.h" // for Transaction #include "caosdb/transaction_handler.h" // for MultiTransactionResponse @@ -41,9 +41,9 @@ using caosdb::configuration::InsecureConnectionConfiguration; using caosdb::connection::Connection; using caosdb::entity::Entity; using caosdb::exceptions::ConnectionError; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; +using ProtoEntity = caosdb::entity::v1::Entity; using caosdb::entity::Role; -using caosdb::entity::v1alpha1::RetrieveResponse; +using caosdb::entity::v1::RetrieveResponse; TEST(test_transaction, create_transaction) { const auto *host = "localhost"; diff --git a/test/test_value.cpp b/test/test_value.cpp index 241f2bd0ce2a7291184a79cdaa0612f2b99fa204..8de10b9051c5ded66f8ea3b4a23581f861a75b8d 100644 --- a/test/test_value.cpp +++ b/test/test_value.cpp @@ -20,24 +20,24 @@ * */ -#include "caosdb/value.h" // for Value -#include "caosdb/entity/v1alpha1/main.pb.h" // for AtomicDataType, DataType -#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper -#include <algorithm> // for max -#include <cmath> // for isnan -#include <gtest/gtest-message.h> // for Message -#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApi... -#include <gtest/gtest_pred_impl.h> // for AssertionResult, Test -#include <initializer_list> // for initializer_list -#include <string> // for string, basic_string -#include <vector> // for vector +#include "caosdb/value.h" // for Value +#include "caosdb/entity/v1/main.pb.h" // for AtomicDataType, DataType +#include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper +#include <algorithm> // for max +#include <cmath> // for isnan +#include <gtest/gtest-message.h> // for Message +#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApi... +#include <gtest/gtest_pred_impl.h> // for AssertionResult, Test +#include <initializer_list> // for initializer_list +#include <string> // for string, basic_string +#include <vector> // for vector namespace caosdb::entity { -using ProtoValue = caosdb::entity::v1alpha1::Value; -using ProtoEntity = caosdb::entity::v1alpha1::Entity; -using ProtoParent = caosdb::entity::v1alpha1::Parent; -using ProtoDataType = caosdb::entity::v1alpha1::DataType; -using ProtoAtomicDataType = caosdb::entity::v1alpha1::AtomicDataType; +using ProtoValue = caosdb::entity::v1::Value; +using ProtoEntity = caosdb::entity::v1::Entity; +using ProtoParent = caosdb::entity::v1::Parent; +using ProtoDataType = caosdb::entity::v1::DataType; +using ProtoAtomicDataType = caosdb::entity::v1::AtomicDataType; TEST(test_value, test_null) { Value value; @@ -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