From 52c022da0f14413d3e1225accaeb5ac146bbd7b7 Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Mon, 5 Jul 2021 13:31:57 +0200
Subject: [PATCH] DRAFT: conan packaging

---
 CMakeLists.txt              | 101 +++++++++++++++++++++++-------------
 include/CMakeLists.txt      |   1 +
 include/caosdb/connection.h |  17 +++---
 include/caosdb/exceptions.h |   3 ++
 include/caosdb/info.h       |  55 ++++++++++++++++++++
 src/CMakeLists.txt          |   1 +
 src/caosdb/connection.cpp   |  27 ++++++----
 src/caosdb/info.cpp         |  50 ++++++++++++++++++
 src/caosdbcli.cpp           |  14 ++---
 test/CMakeLists.txt         |  35 +++++++++++--
 test/test_connection.cpp    |  38 ++++++++------
 test/test_info.cpp          |  47 +++++++++++++++++
 test_package/CMakeLists.txt |  44 +++++++++++++---
 test_package/conanfile.py   |   4 +-
 test_package/example.cpp    |   8 ---
 test_package/test_info.cpp  |   1 +
 16 files changed, 347 insertions(+), 99 deletions(-)
 create mode 100644 include/caosdb/info.h
 create mode 100644 src/caosdb/info.cpp
 create mode 100644 test/test_info.cpp
 delete mode 100644 test_package/example.cpp
 create mode 120000 test_package/test_info.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b25980..af9a8c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,73 +27,85 @@ project(libcaosdb
     DESCRIPTION "C++ client libraries for CaosDB"
     LANGUAGES CXX)
 
-# override options with variables (globally)
-# needed for turning off unused code from grpc
-cmake_policy(SET CMP0077 NEW)
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 
-# dependency management with conan
+###########################################
+### DEPENDENCY MANAGEMENT with CONAN
+###########################################
 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
 conan_basic_setup()
 
+###########################################
+### GENERAL SETUP of SOURCES
+###########################################
 set(PROJECT_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include")
+add_subdirectory(src)
+add_subdirectory(include)
+add_subdirectory(doc)
+
+add_library(caosdb STATIC ${libcaosdb_INCL} ${libcaosdb_SRC})
+add_executable(caosdbcli src/caosdbcli.cpp)
 
-option(LINTING "clang-tidy and iwye" ON)
-if(LINTING)
-    find_program(iwyu NAMES include-what-you-use iwyu PATHS ${CMAKE_SOURCE_DIR}/tools/include-what-you-use/${iwyu_os}/bin)
+#######################################################
+### LINTING with CLANG-TIDY and INCLUDE-WHAT-YOU-USE
+#######################################################
+
+# linting is active when BUILD_TYPE == "Debug"
+if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
+  #set(_LINTING ON)
+endif()
+if(_LINTING)
+    find_program(iwyu
+        NAMES include-what-you-use iwyu
+        PATHS ${CMAKE_SOURCE_DIR}/tools/include-what-you-use/${iwyu_os}/bin)
     if(NOT iwyu)
-        message(STATUS "include-what-you-use: Not found")
+        message(WARNING "include-what-you-use: Not found")
     else()
         message(STATUS "include-what-you-use: ${iwyu}")
-        set(_CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${iwyu})
+        set(_CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${iwyu} "-Xiwyu" "--cxx17ns")
     endif()
 
     find_program(clang_tidy NAMES clang-tidy clang-tidy-11)
     if(NOT clang_tidy)
-        message(STATUS "clang-tidy: Not found")
+        message(WARNING "clang-tidy: Not found")
     else()
         message(STATUS "clang-tidy: ${clang_tidy}")
+        set(_CMAKE_CXX_CLANG_TIDY_CHECKS
+            "--checks=*,-fuchsia-*,-llvm-include-order,-llvmlibc-*")
         set(_CMAKE_CXX_CLANG_TIDY "${clang_tidy}"
             "--header-filter=caosdb/.*[^\(\.pb\.h\)]$"
-            "--checks=*,-fuchsia-*,-llvm-include-order,-llvmlibc-*"
             "--warnings-as-errors=*")
+        option(AUTO_FIX_LINTING "Append --fix option to clang-tidy" OFF)
+        if(AUTO_FIX_LINTING)
+            set(APPEND AUTO_FIX_LINTING "--fix")
+        endif()
     endif()
-else()
-    message(STATUS "LINTING is OFF")
+    set_target_properties(caosdb PROPERTIES
+        CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}"
+        CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
+        )
+    set_target_properties(caosdbcli PROPERTIES
+        CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}"
+        CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
+        )
 endif()
 
-add_subdirectory(src)
-add_subdirectory(include)
-add_subdirectory(doc)
 
-add_library(caosdb STATIC ${libcaosdb_INCL} ${libcaosdb_SRC})
-set_target_properties(caosdb PROPERTIES
-    CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY}"
-    CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
-    )
-add_executable(caosdbcli src/caosdbcli.cpp)
-set_target_properties(caosdbcli PROPERTIES
-    CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY}"
-    CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
-    )
-target_link_libraries(caosdbcli caosdb caosdb_info_v1alpha1 ${CONAN_LIBS})
+#######################################################
+### UNIT TEST
+#######################################################
 
 if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
-    # supress warnings during build of gtest
-    cmake_policy(SET CMP0054 NEW)
-    target_link_libraries(caosdb gcov)
-    enable_testing()
     add_subdirectory(test)
     set_target_properties(caosdb PROPERTIES
         COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}")
-
 endif()
 
 ####################################################################
-## CODE GENERATION (WITH GRPC)
+### CODE GENERATION (WITH GRPC)
 ####################################################################
 
 # Protobuf/Grpc source files
@@ -149,8 +161,13 @@ target_include_directories(caosdb_info_v1alpha1 PUBLIC
    )
 
 target_link_libraries(caosdb
-caosdb_info_v1alpha1
-${CONAN_LIBS}
+  caosdb_info_v1alpha1
+  ${CONAN_LIBS}
+)
+target_link_libraries(caosdbcli
+  caosdb
+  caosdb_info_v1alpha1
+  ${CONAN_LIBS}
 )
 
 
@@ -265,3 +282,17 @@ write_basic_package_version_file(
 )
 install(FILES ${PROJECT_SOURCE_DIR}/caosdbConfigVersion.cmake
     DESTINATION ${libcaosdb_CMAKE_DEST})
+
+#######################################################
+### code formatting with clang-format
+#######################################################
+option(AUTOFORMATTING "call clang-format at configure time" ON)
+if(AUTOFORMATTING)
+    file(GLOB format_test_sources test/*.cpp)
+    execute_process(COMMAND clang-format -i --verbose ${libcaosdb_INCL}
+        ${libcaosdb_SRC} ${libcaosdb_TEST_SRC}
+        ${PROJECT_SOURCE_DIR}/src/caosdbcli.cpp
+        ${format_test_sources}
+        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+endif()
+
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index b60f5df..a71690f 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -24,6 +24,7 @@ set(libcaosdb_INCL
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/connection.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utils.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/info.h
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/exceptions.h
     )
 
diff --git a/include/caosdb/connection.h b/include/caosdb/connection.h
index 1f8bc94..3e5be41 100644
--- a/include/caosdb/connection.h
+++ b/include/caosdb/connection.h
@@ -22,7 +22,7 @@
 #ifndef CAOSDB_CONNECTION_H
 #define CAOSDB_CONNECTION_H
 /**
- * @file connection.h
+ * @file caosdb/connection.h
  * @author Timm Fitschen
  * @date 2021-05-18
  * @brief Configuration and setup of the connection.
@@ -34,23 +34,19 @@
 namespace caosdb {
 namespace authentication {
 class Authenticator;
-}
-} // namespace caosdb
-namespace caosdb {
+} // namespace authentication
 namespace info {
-namespace v1alpha1 {
 class VersionInfo;
-}
 } // namespace info
 } // namespace caosdb
 namespace grpc {
 class ChannelCredentials;
-}
+} // namespace grpc
 
 namespace caosdb::connection {
 using caosdb::authentication::Authenticator;
+using caosdb::info::VersionInfo;
 using caosdb::info::v1alpha1::GeneralInfoService;
-using caosdb::info::v1alpha1::VersionInfo;
 using grpc::ChannelCredentials;
 
 class CACertificateProvider {
@@ -103,6 +99,9 @@ private:
 
 public:
   InsecureCaosDBConnectionConfig(const std::string &host, int port);
+  InsecureCaosDBConnectionConfig(
+    const std::string &host, int port,
+    const std::shared_ptr<Authenticator> &authenticator);
   [[nodiscard]] auto getChannelCredentials() const
     -> std::shared_ptr<ChannelCredentials> override;
   [[nodiscard]] auto toString() const -> std::string override;
@@ -139,7 +138,7 @@ public:
     -> std::ostream &;
   [[nodiscard]] auto getGeneralInfoService() const
     -> GeneralInfoService::Stub &;
-  [[nodiscard]] auto getVersionInfo() const -> VersionInfo;
+  [[nodiscard]] auto getVersionInfo() const -> std::unique_ptr<VersionInfo>;
 };
 } // namespace caosdb::connection
 #endif
diff --git a/include/caosdb/exceptions.h b/include/caosdb/exceptions.h
index 8e70fec..59ff3d4 100644
--- a/include/caosdb/exceptions.h
+++ b/include/caosdb/exceptions.h
@@ -36,6 +36,9 @@ public:
     : runtime_error(what_arg) {}
 };
 
+/**
+ * @brief The connection to the CaosDB server is down.
+ */
 class ConnectionError : public runtime_error {
 public:
   explicit ConnectionError(const std::string &what_arg)
diff --git a/include/caosdb/info.h b/include/caosdb/info.h
new file mode 100644
index 0000000..e5961cd
--- /dev/null
+++ b/include/caosdb/info.h
@@ -0,0 +1,55 @@
+/*
+ * 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_INFO_H
+#define CAOSDB_INFO_H
+/**
+ * @file caosdb/info.h
+ * @author Timm Fitschen
+ * @date 2021-07-02
+ * @brief General information about the CaosDBServer.
+ */
+#include <cstdint>                        // for uint32_t
+#include <string>                         // for string
+#include "caosdb/info/v1alpha1/main.pb.h" // for VersionInfo
+
+namespace caosdb::info {
+
+using ProtoVersionInfo = caosdb::info::v1alpha1::VersionInfo;
+
+/**
+ * @brief Wrapper class for the VersionInfo protobuf.
+ */
+class VersionInfo {
+private:
+  ProtoVersionInfo *info;
+
+public:
+  explicit VersionInfo(ProtoVersionInfo *info);
+  [[nodiscard]] auto GetMajor() const -> uint32_t;
+  [[nodiscard]] auto GetMinor() const -> uint32_t;
+  [[nodiscard]] auto GetPatch() const -> uint32_t;
+  [[nodiscard]] auto GetPreRelease() const -> const std::string &;
+  [[nodiscard]] auto GetBuild() const -> const std::string &;
+};
+
+} // namespace caosdb::info
+#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cb2e20a..5f7f41c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -23,6 +23,7 @@
 set(libcaosdb_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/authentication.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/connection.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/info.cpp
     )
 
 # pass variable to parent scope
diff --git a/src/caosdb/connection.cpp b/src/caosdb/connection.cpp
index 2dff753..f2a3bfd 100644
--- a/src/caosdb/connection.cpp
+++ b/src/caosdb/connection.cpp
@@ -32,6 +32,7 @@
 #include "caosdb/info/v1alpha1/main.grpc.pb.h"    // for GeneralInfoService
 #include "caosdb/info/v1alpha1/main.pb.h"         // for GetVersionInfoResp...
 #include "caosdb/utils.h"                         // for load_string_file
+#include "caosdb/info.h"                          // for VersionInfo
 #include "grpcpp/impl/codegen/status_code_enum.h" // for StatusCode, UNAUTH...
 namespace grpc {
 class Channel;
@@ -41,10 +42,10 @@ namespace caosdb::connection {
 using caosdb::authentication::Authenticator;
 using caosdb::exceptions::AuthenticationError;
 using caosdb::exceptions::ConnectionError;
+using caosdb::info::VersionInfo;
 using caosdb::info::v1alpha1::GeneralInfoService;
 using caosdb::info::v1alpha1::GetVersionInfoRequest;
 using caosdb::info::v1alpha1::GetVersionInfoResponse;
-using caosdb::info::v1alpha1::VersionInfo;
 using caosdb::utils::load_string_file;
 using grpc::InsecureChannelCredentials;
 using grpc::SslCredentials;
@@ -87,7 +88,15 @@ auto operator<<(std::ostream &out, const CaosDBConnectionConfig &config)
 InsecureCaosDBConnectionConfig::InsecureCaosDBConnectionConfig(
   const std::string &host, int port)
   : CaosDBConnectionConfig(host, port) {
-  this->credentials = grpc::InsecureChannelCredentials();
+  this->credentials = InsecureChannelCredentials();
+}
+
+InsecureCaosDBConnectionConfig::InsecureCaosDBConnectionConfig(
+  const std::string &host, int port,
+  const std::shared_ptr<Authenticator> &authenticator)
+  : CaosDBConnectionConfig(host, port) {
+  this->credentials = grpc::CompositeChannelCredentials(
+    InsecureChannelCredentials(), authenticator->getCallCredentials());
 }
 
 auto InsecureCaosDBConnectionConfig::getChannelCredentials() const
@@ -106,6 +115,7 @@ SslCaosDBConnectionConfig::SslCaosDBConnectionConfig(
   : CaosDBConnectionConfig(host, port) {
   SslCredentialsOptions options;
   options.pem_root_certs = cacert->getCACertPem();
+  std::cout << "HERE" << options.pem_root_certs;
   this->credentials = SslCredentials(options);
 }
 
@@ -147,13 +157,9 @@ auto operator<<(std::ostream &out, const CaosDBConnection &connection)
   return out;
 }
 
-auto CaosDBConnection::getGeneralInfoService() const
-  -> GeneralInfoService::Stub & {
-  return *stub_;
-}
-
-[[nodiscard]] auto CaosDBConnection::getVersionInfo() const -> VersionInfo {
-  const GetVersionInfoRequest request;
+[[nodiscard]] auto CaosDBConnection::getVersionInfo() const
+  -> std::unique_ptr<VersionInfo> {
+  GetVersionInfoRequest request;
   GetVersionInfoResponse response;
   grpc::ClientContext context;
   const grpc::Status status =
@@ -170,8 +176,7 @@ auto CaosDBConnection::getGeneralInfoService() const
       throw std::runtime_error(status.error_message());
     }
   }
-  VersionInfo result(response.version_info());
-  return result;
+  return std::make_unique<VersionInfo>(response.release_version_info());
 }
 
 } // namespace caosdb::connection
diff --git a/src/caosdb/info.cpp b/src/caosdb/info.cpp
new file mode 100644
index 0000000..b492dad
--- /dev/null
+++ b/src/caosdb/info.cpp
@@ -0,0 +1,50 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "caosdb/info.h"
+#include "caosdb/info/v1alpha1/main.pb.h" // for GetVersionInfoResponse
+
+namespace caosdb::info {
+using ProtoVersionInfo = caosdb::info::v1alpha1::VersionInfo;
+
+VersionInfo::VersionInfo(ProtoVersionInfo *info) { this->info = info; }
+
+[[nodiscard]] auto VersionInfo::GetMajor() const -> uint32_t {
+  return this->info->major();
+}
+
+[[nodiscard]] auto VersionInfo::GetMinor() const -> uint32_t {
+  return this->info->minor();
+}
+
+[[nodiscard]] auto VersionInfo::GetPatch() const -> uint32_t {
+  return this->info->patch();
+}
+
+[[nodiscard]] auto VersionInfo::GetPreRelease() const -> const std::string & {
+  return this->info->pre_release();
+}
+
+[[nodiscard]] auto VersionInfo::GetBuild() const -> const std::string & {
+  return this->info->build();
+}
+
+} // namespace caosdb::info
diff --git a/src/caosdbcli.cpp b/src/caosdbcli.cpp
index 7770d23..1aaab54 100644
--- a/src/caosdbcli.cpp
+++ b/src/caosdbcli.cpp
@@ -24,11 +24,11 @@
 #include <iostream>
 #include <memory>
 #include <string>
-#include "caosdb/info/v1alpha1/main.pb.h"
 #include "caosdb/constants.h"
 #include "caosdb/connection.h"
 #include "caosdb/authentication.h"
 #include "caosdb/utils.h"
+#include "caosdb/info.h"
 
 auto main() -> int {
 
@@ -46,6 +46,9 @@ 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";
 
   auto auth =
     std::make_shared<caosdb::authentication::PlainPasswordAuthenticator>(
@@ -53,13 +56,12 @@ auto main() -> int {
   auto cacert =
     std::make_shared<caosdb::connection::PemFileCACertProvider>(pem_file);
   auto config = std::make_shared<caosdb::connection::SslCaosDBConnectionConfig>(
-    host, port, cacert, auth);
+    host, port, cacert);
   caosdb::connection::CaosDBConnection connection(config);
   std::cout << std::endl << connection << std::endl;
   const auto &v_info = connection.getVersionInfo();
-  // const auto &build = v_info.build();
-  // std::cout << "BUILD(" << build[0] << ")" << std::endl;
-  std::cout << "VersionInfo(" << v_info.major() << "." << v_info.minor() << "."
-            << v_info.patch() << ")" << std::endl;
+  std::cout << "VersionInfo(" << v_info->GetMajor() << "." << v_info->GetMinor()
+            << "." << v_info->GetPatch() << "-" << v_info->GetPreRelease()
+            << "-" << v_info->GetBuild() << ")" << std::endl;
   return 0;
 }
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a088705..447e04d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -22,8 +22,23 @@
 set(test_cases
     test_connection
     test_utils
+    test_info
     )
 
+
+###################################################
+### 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"
+)
+
+# supress warnings during build of gtest
+cmake_policy(SET CMP0054 NEW)
+enable_testing()
+
 # add special cmake functions for gtest
 include(GoogleTest)
 
@@ -33,17 +48,30 @@ math(EXPR len_test_cases "${len_test_cases} - 1")
 foreach (i RANGE "${len_test_cases}")
     list(GET test_cases ${i} test_case_name)
     add_executable(${test_case_name} ${test_case_name}.cpp)
-    target_link_libraries(${test_case_name} PRIVATE caosdb ${CONAN_LIBS_GTEST} ${CONAN_LIBS_BOOST})
-    set_target_properties(${test_case_name} PROPERTIES CXX_CLANG_TIDY "")
+    set(libcaosdb_TEST_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${test_case_name}.cpp
+        ${libcaosdb_TEST_SRC}")
+    target_link_libraries(${test_case_name} PRIVATE caosdb
+        caosdb_info_v1alpha1 ${CONAN_LIBS_GTEST} ${CONAN_LIBS_BOOST})
+    if(_LINTING)
+    set_target_properties(${test_case_name}
+        PROPERTIES
+        CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS}"
+        CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}")
+    endif()
     gtest_discover_tests(${test_case_name}
         PROPERTIES
             LABELS "caosdb-cpplib-unit-tests")
 endforeach ()
 
-# code coverage report
+
+###################################################
+### Set up test coverage repor (Gcov + Lcov)
+###################################################
+
 include(CodeCoverage)
 
 if (LCOV_PATH)
+    target_link_libraries(caosdb gcov)
     setup_target_for_coverage_lcov(
         NAME unit_test_coverage
         EXECUTABLE ctest -L caosdb-cpplib-unit-tests
@@ -55,4 +83,3 @@ if (LCOV_PATH)
 else ()
     message(WARNING "Could not generate code coverage report. Please install lcov.")
 endif ()
-
diff --git a/test/test_connection.cpp b/test/test_connection.cpp
index bee68e2..0660671 100644
--- a/test/test_connection.cpp
+++ b/test/test_connection.cpp
@@ -20,32 +20,36 @@
  *
  */
 
-#include "caosdb/connection.h"
-#include <gtest/gtest-message.h>
-#include <gtest/gtest-test-part.h>
-#include <memory>
-#include <type_traits>
-#include "gtest/gtest_pred_impl.h"
+#include <gtest/gtest-message.h>   // for Message
+#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver
+#include <memory>                  // for allocator, operator!=, shared_ptr
+#include "caosdb/connection.h"     // for PemCACertProvider, InsecureCaosDB...
+#include "gtest/gtest_pred_impl.h" // for Test, AssertionResult, EXPECT_EQ
+namespace grpc {
+class ChannelCredentials;
+}
+
+namespace caosdb::connection {
 
 TEST(test_connection, configure_insecure_localhost_8080) {
-  caosdb::connection::InsecureCaosDBConnectionConfig config("localhost", 8000);
+  InsecureCaosDBConnectionConfig config("localhost", 8000);
 
-  ASSERT_EQ("localhost", config.getHost());
-  ASSERT_EQ(8000, config.getPort());
+  EXPECT_EQ("localhost", config.getHost());
+  EXPECT_EQ(8000, config.getPort());
   std::shared_ptr<grpc::ChannelCredentials> icc =
     config.getChannelCredentials();
-  ASSERT_TRUE(icc != nullptr);
+  EXPECT_TRUE(icc != nullptr);
 }
 
 TEST(test_connection, configure_ssl_localhost_8080) {
-  auto cacert =
-    std::make_shared<caosdb::connection::PemCACertProvider>("ca chain");
-  caosdb::connection::SslCaosDBConnectionConfig config("localhost", 44300,
-                                                       cacert);
+  auto cacert = std::make_shared<PemCACertProvider>("ca chain");
+  SslCaosDBConnectionConfig config("localhost", 44300, cacert);
 
-  ASSERT_EQ("localhost", config.getHost());
-  ASSERT_EQ(44300, config.getPort());
+  EXPECT_EQ("localhost", config.getHost());
+  EXPECT_EQ(44300, config.getPort());
   std::shared_ptr<grpc::ChannelCredentials> sslcc =
     config.getChannelCredentials();
-  ASSERT_TRUE(sslcc != nullptr);
+  EXPECT_TRUE(sslcc != nullptr);
 }
+
+} // namespace caosdb::connection
diff --git a/test/test_info.cpp b/test/test_info.cpp
new file mode 100644
index 0000000..9b503e4
--- /dev/null
+++ b/test/test_info.cpp
@@ -0,0 +1,47 @@
+/*
+ *
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
+ * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <gtest/gtest-message.h>          // for Message
+#include <gtest/gtest-test-part.h>        // for TestPartResult, SuiteApiRe...
+#include <memory>                         // for allocator
+#include "caosdb/info.h"                  // for VersionInfo
+#include "caosdb/info/v1alpha1/main.pb.h" // for VersionInfo
+#include "gtest/gtest_pred_impl.h"        // for Test, EXPECT_EQ, TEST
+
+namespace caosdb::info {
+using ProtoVersionInfo = caosdb::info::v1alpha1::VersionInfo;
+
+TEST(test_info, create_info_from_proto_info) {
+  auto *origial = new ProtoVersionInfo();
+  origial->set_major(12);
+  origial->set_pre_release("SNAPSHOT");
+
+  VersionInfo wrapper(origial);
+
+  EXPECT_EQ(12, wrapper.GetMajor());
+  EXPECT_EQ("SNAPSHOT", wrapper.GetPreRelease());
+
+  // default value.
+  EXPECT_EQ(0, wrapper.GetMinor());
+}
+
+} // namespace caosdb::info
diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt
index c575fe0..d11580a 100644
--- a/test_package/CMakeLists.txt
+++ b/test_package/CMakeLists.txt
@@ -1,14 +1,44 @@
 cmake_minimum_required(VERSION 3.1)
 project(PackageTest CXX)
 
+#######################################################################
+### append test cases here (file name without the ".cpp" suffix)
+#######################################################################
+set(test_cases
+    test_info
+    )
+
+###################################################
+### Set up tests using GoogleTest (GTest)
+###################################################
+
+# dependencies
 include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
 conan_basic_setup()
 
-add_executable(example example.cpp)
-target_link_libraries(example ${CONAN_LIBS})
+# supress warnings during build of gtest
+cmake_policy(SET CMP0054 NEW)
+enable_testing()
+
+# add special cmake functions for gtest
+include(GoogleTest REQUIRED)
 
-# CTest is a testing tool that can be used to test your project.
-# enable_testing()
-# add_test(NAME example
-#          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-#          COMMAND example)
+# loop over all test cases and add them to the test runner
+list(LENGTH test_cases len_test_cases)
+math(EXPR len_test_cases "${len_test_cases} - 1")
+foreach (i RANGE "${len_test_cases}")
+    list(GET test_cases ${i} test_case_name)
+    add_executable(${test_case_name} ${test_case_name}.cpp)
+    target_link_libraries(${test_case_name} PRIVATE ${CONAN_LIBS_CAOSDB}
+        ${CONAN_LIBS_GTEST} ${CONAN_LIBS_GRPC} ${CONAN_LIBS_ABSEIL}
+        ${CONAN_LIBS_OPENSSL} ${CONAN_LIBS_C-ARES} ${CONAN_LIBS_BZIP2}
+        ${CONAN_LIBS_PROTOBUF} ${CONAN_LIBS_ZLIB})
+    target_include_directories(${test_case_name} PUBLIC ${CONAN_INCLUDE_DIRS})
+    set_target_properties(${test_case_name}
+        PROPERTIES
+        CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY}"
+        CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}")
+    gtest_discover_tests(${test_case_name}
+        PROPERTIES
+            LABELS "caosdb-cpplib-int-tests")
+endforeach ()
diff --git a/test_package/conanfile.py b/test_package/conanfile.py
index fb6117e..a003a6b 100644
--- a/test_package/conanfile.py
+++ b/test_package/conanfile.py
@@ -21,5 +21,5 @@ class LibcaosdbTestConan(ConanFile):
 
     def test(self):
         if not tools.cross_building(self):
-            os.chdir("bin")
-            self.run(".%sexample" % os.sep)
+            cmake = CMake(self)
+            cmake.test()
diff --git a/test_package/example.cpp b/test_package/example.cpp
deleted file mode 100644
index 9921648..0000000
--- a/test_package/example.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <iostream>
-#include "caosdb/connection.h"
-
-int main() {
-  caosdb::connection::InsecureCaosDBConnectionConfig config("localhost", 8443);
-
-  std::cout << config << "\n";
-}
diff --git a/test_package/test_info.cpp b/test_package/test_info.cpp
new file mode 120000
index 0000000..e0e5ee2
--- /dev/null
+++ b/test_package/test_info.cpp
@@ -0,0 +1 @@
+../test/test_info.cpp
\ No newline at end of file
-- 
GitLab