diff --git a/.gitignore b/.gitignore index f5e46b698cdb99eb18c7bac8e226c7692325cbd7..2df735637f2c21743cd290bccc49bee78a57da95 100644 --- a/.gitignore +++ b/.gitignore @@ -144,3 +144,9 @@ flycheck_*.el # Python/Sphinx env/ + +# Conan +conan.lock +conanbuildinfo* +conaninfo.txt +graph_info.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..449e4256f907780bfbd0ce3d6a23853f20de0ae6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +### Changed + +* Integer values are 32 bit now. + +### Deprecated + +### Removed + +### Fixed + +### Security diff --git a/CMakeLists.txt b/CMakeLists.txt index f367a02d498b2b5b4f14ff93fc82a52203b9f531..e4c84cfc7a4482175b39037dc6b29cdd60e8f695 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ add_subdirectory(test) ####################################################### option(AUTOFORMATTING "call clang-format at configure time" ON) if(AUTOFORMATTING) + message("Autoformatting is on. To disable, call cmake with '-D AUTOFORMATTING=OFF'.") file(GLOB format_test_sources test/*.cpp test/*.h) execute_process(COMMAND clang-format -i --verbose ${format_test_sources} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a1e463721011de1db6145c4c2fcb96342b01c2d6 --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +# ** header v3.0 +# This file is a part of the CaosDB Project. +# +# Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> +# Copyright (C) 2021 Daniel Hornung <d.hornung@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/>. +# +# ** end header + +# This Makefile is a wrapper for several other scripts. + + +CLANG-FORMAT = clang-format-11 +CLANG-TIDY = clang-tidy-11 + +CLANG_TIDY_CHECKS = "--checks=*,-fuchsia-*,-llvmlibc-*,-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-pro-type-vararg,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay" +CLANG_TIDY_CMD = $(CLANG-TIDY) \ + --header-filter=caosdb/.*[^\(\.pb\.h\)]$ \ + --fix \ + $(CLANG_TIDY_CHECKS) + + +.PHONY: help +help: + @echo "Targets:" + @echo " conan-install - Install locally with Conan." + @echo " style - auto-format the source files." + +conan-install: + conan install . -s "compiler.libcxx=libstdc++11" +.PHONY: conan-install + +format: conan-install + $(CLANG-FORMAT) -i --verbose \ + $$(find test/ -type f -iname "*.cpp" -o -iname "*.h" -o -iname "*.h.in") + $(CLANG_TIDY_CMD) $$(find test/ -type f -iname "*.cpp" -o -iname "*.h" -o -iname "*.h.in") +.PHONY: format diff --git a/README.md b/README.md index 9d2b880004b551f8e32eb0254e47377744584e69..a1e449184088f9eb762c8cbbae16d0360c7ef71f 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,7 @@ Create a local conan package from the caosdb-cpplib repository - CAOSDB_SERVER_GRPC_PORT_HTTPS - CAOSDB_SERVER_CERT 6. Run with `ctest` in the build directory. + +## Formatting, style, linting ## + +`make format` diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c388869d9b0df41f78f478145c61f653bde21c51..ec9d39041bf87350c1b018615f96203475ae01a9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ add_compiler_flag("-g") ####################################################### option(LINTING "clang-tidy and iwye" ON) if(LINTING) + message("Linting is on. To disable, call cmake with '-D LINTING=OFF'.") ### set paranoid compiler flags #add_compiler_flag("-Wall") #add_compiler_flag("-Wextra") @@ -80,7 +81,6 @@ if(LINTING) message(STATUS "clang-tidy: ${clang_tidy}") set(_CMAKE_CXX_CLANG_TIDY "${clang_tidy}" "--header-filter=caosdb/.*[^\(\.pb\.h\)]$" - "--warnings-as-errors=*" "--fix") set(_CMAKE_CXX_CLANG_TIDY_CHECKS "--checks=*,-fuchsia-*,-llvmlibc-*,-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-pro-type-vararg,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay") diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp index c5daf6d362099bb6e14bb68f3de76265ec3329fa..844c829b78f0ebe76bbb7df4291a34764b2df303 100644 --- a/test/test_transaction.cpp +++ b/test/test_transaction.cpp @@ -30,7 +30,8 @@ #include <boost/filesystem/operations.hpp> // for remove #include <boost/filesystem/path.hpp> // for path #include <boost/filesystem/path_traits.hpp> // for filesystem -#include <gtest/gtest-message.h> // for Message +#include <boost/lexical_cast.hpp> +#include <gtest/gtest-message.h> // for Message #include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver #include <gtest/gtest_pred_impl.h> // for Test, EXPECT_EQ, AssertionResult #include <iostream> @@ -47,12 +48,56 @@ using caosdb::entity::MessageCode; using caosdb::entity::Parent; using caosdb::entity::Property; using caosdb::entity::Role; +using caosdb::entity::Value; class test_transaction : public ::testing::Test { +public: + // public utility functions + // //////////////////////////////////////////////////////// + + /** + * Generate a vector with useful values for testing. + */ + template <typename T> static auto generateValues() -> std::vector<T> { + std::vector<T> values = { + 0, 1, + // (T)6.91629132943846e-310, + std::numeric_limits<T>::max(), std::numeric_limits<T>::min(), + std::numeric_limits<T>::denorm_min(), std::numeric_limits<T>::lowest(), + std::numeric_limits<T>::epsilon() // 0 for integers, but who cares? + }; + + return values; + } + + template <typename T> static auto getValueAs(const Value & /*value*/) -> T { + throw std::logic_error("Template not implemented for this type."); + } + static void DeleteEntities() { + // delete all entities + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + auto query_transaction(connection->CreateTransaction()); + query_transaction->Query("FIND ENTITY WITH id > 99"); + query_transaction->Execute(); + if (query_transaction->GetResultSet().size() > 0) { + std::cout << "Cleanup: Deleting " + << query_transaction->GetResultSet().size() << " entities." + << std::endl; + auto delete_transaction(connection->CreateTransaction()); + for (const Entity &entity : query_transaction->GetResultSet()) { + delete_transaction->DeleteById(entity.GetId()); + } + delete_transaction->Execute(); + } + } + protected: fs::path test_upload_file_1; fs::path test_download_file_1; + // Fixture methods ////////////////////////////////////////////////////////// + void SetUp() override { DeleteEntities(); @@ -73,24 +118,18 @@ protected: fs::remove(test_download_file_1); DeleteEntities(); } - - static void DeleteEntities() { - // delete all entities - const auto &connection = - caosdb::connection::ConnectionManager::GetDefaultConnection(); - auto query_transaction(connection->CreateTransaction()); - query_transaction->Query("FIND ENTITY WITH id > 99"); - query_transaction->Execute(); - if (query_transaction->GetResultSet().size() > 0) { - auto delete_transaction(connection->CreateTransaction()); - for (const Entity &entity : query_transaction->GetResultSet()) { - delete_transaction->DeleteById(entity.GetId()); - } - delete_transaction->Execute(); - } - } }; +template <> +auto test_transaction::getValueAs<double>(const Value &value) -> double { + return value.AsDouble(); +} + +template <> +auto test_transaction::getValueAs<int32_t>(const Value &value) -> int32_t { + return value.AsInteger(); +} + /* * Test the retrieval of a non-existing entity * @@ -640,6 +679,90 @@ TEST_F(test_transaction, test_query) { EXPECT_EQ(count_query_trans->GetCountResult(), 1); } +/** + * Test numeric values (template). + */ +template <typename T> +auto test_numeric_values_impl(AtomicDataType a_type) -> void { + const auto &connection = + caosdb::connection::ConnectionManager::GetDefaultConnection(); + + // Insert entities + auto values_orig = test_transaction::generateValues<T>(); + auto props_orig = std::vector<Entity>(); + size_t i = 0; + for (auto value : values_orig) { + auto insert_transaction(connection->CreateTransaction()); + Entity prop; + prop.SetRole(Role::PROPERTY); + const auto name = + std::string("Prop ") + std::to_string(i); + std::cout << "Creating: " << name << std::endl; + prop.SetName(name); + prop.SetDataType(a_type); + std::cout << "Setting value " << value << std::endl; + prop.SetValue(value); + props_orig.push_back(prop); + auto i_stat = insert_transaction->InsertEntity(&prop); + EXPECT_EQ(i_stat, StatusCode::READY); + insert_transaction->ExecuteAsynchronously(); + auto t_stat = insert_transaction->WaitForIt(); + EXPECT_TRUE(t_stat.IsTerminated()); + EXPECT_FALSE(t_stat.IsError()); + ++i; + } + + // Retrieve and verify + i = 0; + for (const auto value : values_orig) { + auto retrieve_transaction(connection->CreateTransaction()); + const auto prop = props_orig[i]; + const auto name = + std::string("Prop ") + std::to_string(i); + std::cout << "Retrieving: " << name << std::endl; + const auto query = std::string("FIND ENTITY \"") + name + "\""; + retrieve_transaction->Query(query); + retrieve_transaction->ExecuteAsynchronously(); + const auto t_stat = retrieve_transaction->WaitForIt(); + EXPECT_TRUE(t_stat.IsTerminated()); + EXPECT_FALSE(t_stat.IsError()); + + const auto result = retrieve_transaction->GetResultSet().at(0); + EXPECT_EQ(result.GetDataType(), a_type); + const auto &retrieved_value = + test_transaction::getValueAs<T>(result.GetValue()); + // std::cout << "retrieved_value: " << retrieved_value << std::endl; + EXPECT_EQ(retrieved_value, value); + ++i; + } +} + +/** + * Test numeric values (wrapper for types). + */ +TEST_F(test_transaction, test_numeric_values) { + test_numeric_values_impl<double>(AtomicDataType::DOUBLE); + test_transaction::DeleteEntities(); + test_numeric_values_impl<int32_t>(AtomicDataType::INTEGER); +} + +// /* +// * test miscellaneous queries +// */ +// TEST_F(test_transaction, test_queries_misc) { +// const auto &connection = +// caosdb::connection::ConnectionManager::GetDefaultConnection(); + +// // query empty database +// auto query_transaction(connection->CreateTransaction()); +// query_transaction->Query("FIND Property \"Prop *\""); +// query_transaction->ExecuteAsynchronously(); +// auto t_stat = query_transaction->WaitForIt(); +// std::cout << "status: " << t_stat.GetCode() << " // " +// << t_stat.GetDescription() << std::endl; +// EXPECT_TRUE(t_stat.GetCode() >= 0); +// } + /* * insert three recordtypes and the submit multiple queries in different * combinations @@ -935,7 +1058,7 @@ TEST_F(test_transaction, test_full_workflow) { experiment_rec.AppendProperty(volt_for_rt); notes_for_rt2.SetValue("This is important!"); experiment_rec.AppendProperty(notes_for_rt2); - part_for_rt3.SetValue(static_cast<int64_t>(6)); + part_for_rt3.SetValue(static_cast<int32_t>(6)); experiment_rec.AppendProperty(part_for_rt3); succ_for_rt.SetValue(true); experiment_rec.AppendProperty(succ_for_rt);