From d1852b1003201b3f7f7347fb5fa75756132bb1cc Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Wed, 7 Jul 2021 12:37:17 +0200
Subject: [PATCH] WIP: retrieve simple entity

---
 CMakeLists.txt               |  2 +-
 README_SETUP.md              |  4 ++++
 include/caosdb/entity.h      | 14 +++++++----
 include/caosdb/transaction.h |  7 +++---
 src/caosdb/entity.cpp        | 15 ++++++++----
 src/caosdb/transaction.cpp   | 19 ++++++++++-----
 src/caosdbcli.cpp            | 27 +++++++++++++++-------
 test/CMakeLists.txt          |  5 ++--
 test/caosdb_test_utility.h   | 45 ++++++++++++++++++++++++++++++++++++
 test/test_transaction.cpp    | 10 ++++++--
 10 files changed, 118 insertions(+), 30 deletions(-)
 create mode 100644 test/caosdb_test_utility.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 33cda78..95bc176 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -286,7 +286,7 @@ install(FILES ${PROJECT_SOURCE_DIR}/caosdbConfigVersion.cmake
 #######################################################
 option(AUTOFORMATTING "call clang-format at configure time" ON)
 if(AUTOFORMATTING)
-    file(GLOB format_test_sources test/*.cpp)
+    file(GLOB format_test_sources test/*.cpp test/*.h)
     execute_process(COMMAND clang-format -i --verbose ${libcaosdb_INCL}
         ${libcaosdb_SRC} ${libcaosdb_TEST_SRC}
         ${PROJECT_SOURCE_DIR}/src/caosdbcli.cpp
diff --git a/README_SETUP.md b/README_SETUP.md
index bf48fa3..c68df92 100644
--- a/README_SETUP.md
+++ b/README_SETUP.md
@@ -48,6 +48,10 @@ The coverage report can be viewed in a browser by opening
 * 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
+
+Please adhere to [Google's C++ naming conventions](https://google.github.io/styleguide/cppguide.html#Naming).
+
 ## Documentation
 
 In the build directory, run
diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h
index d9bdf06..69be0c6 100644
--- a/include/caosdb/entity.h
+++ b/include/caosdb/entity.h
@@ -25,20 +25,23 @@
 #ifndef CAOSDB_ENTITY_H
 #define CAOSDB_ENTITY_H
 
-#include <string>
+#include <memory>                           // for shared_ptr
+#include <string>                           // for string
+#include "caosdb/entity/v1alpha1/main.pb.h" // for Entity
 
 namespace caosdb::entity {
+using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 
 /**
  * Entity ID.
  */
 class EntityID {
 private:
-  std::string id;
+  std::shared_ptr<std::string> id;
 
 public:
-  EntityID(std::string id);
-  [[nodiscard]] auto ToString() const -> std::string;
+  explicit EntityID(const std::string &id);
+  explicit EntityID(const std::shared_ptr<std::string> &id);
 };
 
 /**
@@ -47,11 +50,14 @@ public:
 class Entity {
 private:
   EntityID id;
+  std::shared_ptr<ProtoEntity> delegate;
 
 public:
+  explicit Entity(ProtoEntity *delegate);
   [[nodiscard]] auto GetId() const -> EntityID;
   auto SetId(EntityID id) -> void;
   [[nodiscard]] auto GetName() const -> std::string;
+  [[nodiscard]] auto GetDescription() const -> std::string;
 };
 
 } // namespace caosdb::entity
diff --git a/include/caosdb/transaction.h b/include/caosdb/transaction.h
index 552f1f0..856f8ca 100644
--- a/include/caosdb/transaction.h
+++ b/include/caosdb/transaction.h
@@ -39,8 +39,8 @@ using caosdb::entity::v1alpha1::EntityTransactionService;
 using caosdb::entity::v1alpha1::RetrieveRequest;
 
 class ResultSet {
-public:
-  [[nodiscard]] auto GetById(EntityID id) const -> Entity;
+  // public:
+  //[[nodiscard]] auto GetEntityById(EntityID id) const -> Entity;
 };
 
 class UniqueResult : public ResultSet {
@@ -48,7 +48,8 @@ private:
   Entity entity;
 
 public:
-  UniqueResult(ProtoEntity entity);
+  UniqueResult(Entity entity);
+  [[nodiscard]] auto GetEntity() const -> Entity;
 };
 
 enum TransactionState { INIT = 10, EXECUTING = 20, SUCCESS = 30, ERROR = 40 };
diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp
index dc3cbf3..71f4808 100644
--- a/src/caosdb/entity.cpp
+++ b/src/caosdb/entity.cpp
@@ -20,17 +20,24 @@
  */
 
 #include "caosdb/entity.h"
-
 #include <utility>
 
 namespace caosdb::entity {
 
-EntityID::EntityID(std::string id) { this->id = std::move(id); }
+EntityID::EntityID(const std::string &id) {
+  this->id = std::make_shared<std::string>(id);
+}
 
-[[nodiscard]] auto EntityID::ToString() const -> std::string {
-  return this->id;
+EntityID::EntityID(const std::shared_ptr<std::string> &id) {
+  this->id = std::make_shared<std::string>(*id);
 }
 
+Entity::Entity(ProtoEntity *delegate)
+  : id(EntityID(delegate->eid())), delegate(delegate) {}
+
+[[nodiscard]] auto Entity::GetDescription() const -> std::string {
+  return this->delegate->description();
+}
 [[nodiscard]] auto Entity::GetId() const -> EntityID { return this->id; }
 
 auto Entity::SetId(EntityID id) -> void { this->id = std::move(id); }
diff --git a/src/caosdb/transaction.cpp b/src/caosdb/transaction.cpp
index 1b0faad..8355f76 100644
--- a/src/caosdb/transaction.cpp
+++ b/src/caosdb/transaction.cpp
@@ -1,6 +1,5 @@
 /*
  * This file is a part of the CaosDB Project.
- *
  * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
  * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
  *
@@ -36,18 +35,24 @@ namespace caosdb::transaction {
 using caosdb::entity::v1alpha1::EntityTransactionService;
 using caosdb::entity::v1alpha1::RetrieveRequest;
 using caosdb::entity::v1alpha1::RetrieveResponse;
+using ProtoEntity = caosdb::entity::v1alpha1::Entity;
 using caosdb::exceptions::AuthenticationError;
 using caosdb::exceptions::ConnectionError;
 
+UniqueResult::UniqueResult(Entity entity) : entity(std::move(entity)) {}
+
+[[nodiscard]] auto UniqueResult::GetEntity() const -> Entity {
+  return this->entity;
+}
+
 Transaction::Transaction(
   std::shared_ptr<EntityTransactionService::Stub> service_stub) {
   this->service_stub = std::move(service_stub);
 }
 
-auto Transaction::Retrieve(const EntityID &id) -> void {
-
+auto Transaction::Retrieve(const EntityID & /*id*/) -> void {
+  // TODO(tf)
   RetrieveRequest request;
-  request.mutable_entity()->set_eid(id.ToString());
 
   this->request = request;
 }
@@ -72,8 +77,10 @@ auto Transaction::Execute() -> void {
       throw std::runtime_error(status.error_message());
     }
   }
-  // TODO(tf)
-  this->result_set = std::make_shared<ResultSet>();
+
+  auto entity = Entity(response.release_entity());
+  auto result_set = std::make_shared<UniqueResult>(entity);
+  this->result_set = result_set;
 }
 
 auto Transaction::WaitForIt() const -> void {
diff --git a/src/caosdbcli.cpp b/src/caosdbcli.cpp
index 3151919..37f9fbe 100644
--- a/src/caosdbcli.cpp
+++ b/src/caosdbcli.cpp
@@ -46,11 +46,8 @@ auto main() -> int {
   const auto port = std::stoi(port_str);
   const auto user = caosdb::utils::get_env_var("CAOSDB_USER", "admin");
   const auto password = caosdb::utils::get_env_var("CAOSDB_PASSWORD", "caosdb");
-  std::cout << "USER: " << user << "\n";
-  std::cout << "PORT: " << port_str << "\n";
-  std::cout << "HOST: " << host << "\n";
-  std::cout << "CACERT: " << pem_file << "\n";
 
+  // setup the connection
   auto auth =
     std::make_shared<caosdb::authentication::PlainPasswordAuthenticator>(
       user, password);
@@ -59,10 +56,24 @@ auto main() -> int {
   auto config = std::make_shared<caosdb::connection::SslCaosDBConnectionConfig>(
     host, port, cacert, auth);
   caosdb::connection::CaosDBConnection connection(config);
-  std::cout << std::endl << connection << std::endl;
+
+  // get version info of the server
   const auto &v_info = connection.GetVersionInfo();
-  std::cout << "VersionInfo(" << v_info->GetMajor() << "." << v_info->GetMinor()
-            << "." << v_info->GetPatch() << "-" << v_info->GetPreRelease()
-            << "-" << v_info->GetBuild() << ")" << std::endl;
+  std::cout << "Server Version: " << v_info->GetMajor() << "."
+            << v_info->GetMinor() << "." << v_info->GetPatch() << "-"
+            << v_info->GetPreRelease() << "-" << v_info->GetBuild()
+            << std::endl;
+
+  // retrieve an entity
+  auto transaction(connection.CreateTransaction());
+  transaction->Retrieve(caosdb::entity::EntityID("someid"));
+  transaction->Execute();
+  auto result_set(std::static_pointer_cast<caosdb::transaction::UniqueResult>(
+    transaction->GetResultSet()));
+
+  // print description
+  std::cout << "Entity Description: "
+            << result_set->GetEntity().GetDescription() << std::endl;
+
   return 0;
 }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 78e25be..2616296 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -26,14 +26,13 @@ set(test_cases
     test_utils
     )
 
-
 ###################################################
 ### Set up tests using GoogleTest (GTest)
 ###################################################
 
 # 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"
+  "${_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"
 )
 
 # add special cmake functions for gtest
@@ -49,6 +48,8 @@ foreach (i RANGE "${len_test_cases}")
         ${libcaosdb_TEST_SRC}")
     target_link_libraries(${test_case_name}
         PRIVATE ${LIBCAOSDB} ${CONAN_LIBS_GTEST} ${CONAN_LIBS_BOOST})
+    target_include_directories(${test_case_name}
+      PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
     if(_LINTING)
     set_target_properties(${test_case_name}
         PROPERTIES
diff --git a/test/caosdb_test_utility.h b/test/caosdb_test_utility.h
new file mode 100644
index 0000000..981c458
--- /dev/null
+++ b/test/caosdb_test_utility.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CAOSDB_TEST_UTILITY_H
+#define CAOSDB_TEST_UTILITY_H
+/**
+ * @file caosdb_test_utility.h
+ * @brief Utility for the unit tests
+ * @author Timm Fitschen
+ * @date 2021-07-07
+ */
+#define EXPECT_THROW_MESSAGE(statement, exeption_type, message)                \
+  EXPECT_THROW(                                                                \
+    try { statement; } catch (const exeption_type &e) {                        \
+      EXPECT_EQ(std::string(e.what()), message);                               \
+      throw;                                                                   \
+    },                                                                         \
+    exeption_type)
+#define ASSERT_THROW_MESSAGE(statement, exeption_type, message)                \
+  ASSERT_THROW(                                                                \
+    try { statement; } catch (const exeption_type &e) {                        \
+      ASSERT_EQ(std::string(e.what()), message);                               \
+      throw;                                                                   \
+    },                                                                         \
+    exeption_type)
+#endif
diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp
index cb13a3f..6c41925 100644
--- a/test/test_transaction.cpp
+++ b/test/test_transaction.cpp
@@ -23,12 +23,17 @@
 #include <memory>                  // for allocator, make_shared, unique_ptr
 #include "caosdb/connection.h"     // for InsecureCaosDBConnectionConfig
 #include "caosdb/entity.h"         // for EntityID
+#include "caosdb/exceptions.h"     // for ConnectionError
 #include "caosdb/transaction.h"    // for Transaction, EntityID
-#include "gtest/gtest_pred_impl.h" // for Test, SuiteApiResolver, TEST, Tes...
+#include "gtest/gtest-message.h"   // for Message
+#include "gtest/gtest-test-part.h" // for TestPartResult
+#include "gtest/gtest.h"           // for Test, SuiteApiResolver, TestInfo ...
+#include "caosdb_test_utility.h"   // for EXPECT_THROW_MESSAGE
 
 namespace caosdb::transaction {
 using caosdb::connection::CaosDBConnection;
 using caosdb::connection::InsecureCaosDBConnectionConfig;
+using caosdb::exceptions::ConnectionError;
 
 TEST(test_transaction, create_transaction) {
   const auto *pHost = "localhost";
@@ -37,7 +42,8 @@ TEST(test_transaction, create_transaction) {
   auto transaction = connection.CreateTransaction();
 
   transaction->Retrieve(EntityID("someid"));
-  transaction->Execute();
+  EXPECT_THROW_MESSAGE(transaction->Execute(), ConnectionError,
+                       "failed to connect to all addresses");
 }
 
 } // namespace caosdb::transaction
-- 
GitLab