From ee5977c79423a8916e1577ba4a4ad830c3b10ec8 Mon Sep 17 00:00:00 2001 From: Sergey Yakubov <sergey.yakubov@desy.de> Date: Wed, 14 Feb 2018 17:44:46 +0100 Subject: [PATCH] Start working at configuration files --- CMakeModules/testing_cpp.cmake | 64 ++++++++------- common/cpp/CMakeLists.txt | 3 + common/cpp/include/json_parser/json_parser.h | 29 +++++++ common/cpp/src/data_structs/CMakeLists.txt | 2 +- common/cpp/src/data_structs/data_structs.cpp | 46 +++-------- common/cpp/src/database/CMakeLists.txt | 2 +- common/cpp/src/json_parser/CMakeLists.txt | 23 ++++++ .../src/json_parser/json_string_parser.cpp | 26 +++++++ common/cpp/src/json_parser/rapid_json.cpp | 78 +++++++++++++++++++ common/cpp/src/json_parser/rapid_json.h | 30 +++++++ .../json_parser/test_json_string_parser.cpp | 76 ++++++++++++++++++ worker/api/cpp/CMakeLists.txt | 2 +- 12 files changed, 314 insertions(+), 67 deletions(-) create mode 100644 common/cpp/include/json_parser/json_parser.h create mode 100644 common/cpp/src/json_parser/CMakeLists.txt create mode 100644 common/cpp/src/json_parser/json_string_parser.cpp create mode 100644 common/cpp/src/json_parser/rapid_json.cpp create mode 100644 common/cpp/src/json_parser/rapid_json.h create mode 100644 common/cpp/unittests/json_parser/test_json_string_parser.cpp diff --git a/CMakeModules/testing_cpp.cmake b/CMakeModules/testing_cpp.cmake index dd66bda81..5efbb83b0 100644 --- a/CMakeModules/testing_cpp.cmake +++ b/CMakeModules/testing_cpp.cmake @@ -15,7 +15,7 @@ if (BUILD_TESTS) if (CMAKE_COMPILER_IS_GNUCXX) include(CodeCoverage) APPEND_COVERAGE_COMPILER_FLAGS() - endif() + endif () endif () function(gtest target test_source_files linktarget) @@ -23,14 +23,22 @@ function(gtest target test_source_files linktarget) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) link_directories(${gtest_SOURCE_DIR}/lib) - if (NOT ${linktarget} STREQUAL "") - get_target_property(target_type ${linktarget} TYPE) - if (target_type STREQUAL "OBJECT_LIBRARY") - add_executable(test-${target} ${test_source_files} $<TARGET_OBJECTS:${linktarget}>) - else() - add_executable(test-${target} ${test_source_files}) - target_link_libraries(test-${target} ${linktarget}) + FOREACH (lib ${linktarget}) + if (NOT ${lib} STREQUAL "") + get_target_property(target_type ${lib} TYPE) + if (target_type STREQUAL "OBJECT_LIBRARY") + list(APPEND OBJECT "$<TARGET_OBJECTS:${lib}>") + else () + list(APPEND libs "${lib}") + + endif () endif () + ENDFOREACH () + + add_executable(test-${target} ${test_source_files} ${OBJECT}) + + if (NOT ${libs} STREQUAL "") + target_link_libraries(test-${target} ${libs}) endif () IF (WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug") @@ -46,10 +54,10 @@ function(gtest target test_source_files linktarget) message(STATUS "Added test 'test-${target}'") if (CMAKE_COMPILER_IS_GNUCXX) - set(COVERAGE_EXCLUDES "*/unittests/*" "*/3d_party/*" ) + set(COVERAGE_EXCLUDES "*/unittests/*" "*/3d_party/*") if (ARGN) set(COVERAGE_EXCLUDES ${COVERAGE_EXCLUDES} ${ARGN}) - endif() + endif () SETUP_TARGET_FOR_COVERAGE(NAME coverage-${target} EXECUTABLE test-${target} ${target}) add_test(NAME coveragetest-${target} COMMAND ${CMAKE_MODULE_PATH}/check_test.sh @@ -91,9 +99,9 @@ function(add_test_setup exename) if (BUILD_INTEGRATION_TESTS) IF (WIN32) add_test(NAME test-${exename}-setup COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/setup_windows.bat) - ELSE() + ELSE () add_test(NAME test-${exename}-setup COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/setup_linux.sh) - ENDIF() + ENDIF () set_tests_properties(test-${exename}-setup PROPERTIES FIXTURES_SETUP test-${exename}-fixture) endif () endfunction() @@ -102,9 +110,9 @@ function(add_test_cleanup exename) if (BUILD_INTEGRATION_TESTS) IF (WIN32) add_test(NAME test-${exename}-cleanup COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cleanup_windows.bat) - ELSE() + ELSE () add_test(NAME test-${exename}-cleanup COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/cleanup_linux.sh) - ENDIF() + ENDIF () set_tests_properties(test-${exename}-cleanup PROPERTIES FIXTURES_CLEANUP test-${exename}-fixture) endif () endfunction() @@ -142,22 +150,22 @@ function(add_script_test testname arguments) separate_arguments(args) IF (WIN32) add_test(NAME test-${testname} COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/check_windows.bat - ${args}) - ELSE() + ${args}) + ELSE () add_test(NAME test-${testname} COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/check_linux.sh - ${args}) - if (MEMORYCHECK_COMMAND) - if (ARGN) - set(commandargs ${ARGN}) + ${args}) + if (MEMORYCHECK_COMMAND) + if (ARGN) + set(commandargs ${ARGN}) + endif () + if (NOT "${ARGN}" STREQUAL "nomem") + set(memargs ${MEMORYCHECK_COMMAND} ${MEMORYCHECK_COMMAND_OPTIONS} ${arguments}) + separate_arguments(memargs) + add_test(NAME memtest-${testname} COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/check_linux.sh + ${memargs}) + endif () endif () - if (NOT "${ARGN}" STREQUAL "nomem") - set(memargs ${MEMORYCHECK_COMMAND} ${MEMORYCHECK_COMMAND_OPTIONS} ${arguments}) - separate_arguments(memargs) - add_test(NAME memtest-${testname} COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/check_linux.sh - ${memargs}) - endif() - endif() - ENDIF() + ENDIF () set_tests_properties(test-${testname} PROPERTIES LABELS "example;all" ) diff --git a/common/cpp/CMakeLists.txt b/common/cpp/CMakeLists.txt index 7865db18d..0b489c5d4 100644 --- a/common/cpp/CMakeLists.txt +++ b/common/cpp/CMakeLists.txt @@ -1,5 +1,8 @@ add_subdirectory(src/system_io) + +add_subdirectory(src/json_parser) + add_subdirectory(src/data_structs) if(BUILD_MONGODB_CLIENTLIB) diff --git a/common/cpp/include/json_parser/json_parser.h b/common/cpp/include/json_parser/json_parser.h new file mode 100644 index 000000000..46d2b01e8 --- /dev/null +++ b/common/cpp/include/json_parser/json_parser.h @@ -0,0 +1,29 @@ +#ifndef HIDRA2_JSON_PARSER_H +#define HIDRA2_JSON_PARSER_H + +#include <string> +#include <memory> + +#include "common/error.h" + +namespace hidra2 { + +class RapidJson; + +class JsonStringParser { + public: + JsonStringParser(const std::string& json); + ~JsonStringParser(); + Error GetUInt64(const std::string& name, uint64_t* val) const noexcept; + Error GetString(const std::string& name, std::string* val) const noexcept; + private: + std::unique_ptr<RapidJson> rapid_json_; +}; + +} + + + + + +#endif //HIDRA2_JSON_PARSER_H diff --git a/common/cpp/src/data_structs/CMakeLists.txt b/common/cpp/src/data_structs/CMakeLists.txt index 617f5c89b..203f68cf8 100644 --- a/common/cpp/src/data_structs/CMakeLists.txt +++ b/common/cpp/src/data_structs/CMakeLists.txt @@ -16,7 +16,7 @@ target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR ################################ set(TEST_SOURCE_FILES ../../unittests/data_structs/test_data_structs.cpp) -set(TEST_LIBRARIES "${TARGET_NAME}") +set(TEST_LIBRARIES "${TARGET_NAME};json_parser") include_directories(${HIDRA2_CXX_COMMON_INCLUDE_DIR}) gtest(${TARGET_NAME} "${TEST_SOURCE_FILES}" "${TEST_LIBRARIES}") diff --git a/common/cpp/src/data_structs/data_structs.cpp b/common/cpp/src/data_structs/data_structs.cpp index 0467bea29..c6127e0ff 100644 --- a/common/cpp/src/data_structs/data_structs.cpp +++ b/common/cpp/src/data_structs/data_structs.cpp @@ -1,8 +1,6 @@ #include "common/data_structs.h" -#include "rapidjson/document.h" - -using namespace rapidjson; +#include "json_parser/json_parser.h" namespace hidra2 { @@ -18,21 +16,10 @@ std::string FileInfo::Json() const { return s; } -bool IntFromJson(const Document& d, const std::string name, uint64_t* val) { - auto iterator = d.FindMember(name.c_str()); - if (iterator == d.MemberEnd()) { - return false; - } - if (iterator->value.IsInt64()) { - *val = iterator->value.GetInt64(); - return true; - } - return false; -} -bool TimeFromJson(const Document& d, const std::string name, std::chrono::system_clock::time_point* val) { +bool TimeFromJson(const JsonStringParser& parser, const std::string name, std::chrono::system_clock::time_point* val) { uint64_t nanoseconds_from_epoch; - if (!IntFromJson(d, name, &nanoseconds_from_epoch)) { + if (parser.GetUInt64(name, &nanoseconds_from_epoch)) { return false; } @@ -43,31 +30,18 @@ bool TimeFromJson(const Document& d, const std::string name, std::chrono::system return true; } -bool StringFromJson(const Document& d, const std::string name, std::string* val) { - auto iterator = d.FindMember(name.c_str()); - if (iterator == d.MemberEnd()) { - return false; - } - if (iterator->value.IsString()) { - *val = iterator->value.GetString(); - return true; - } - return false; -} + bool FileInfo::SetFromJson(const std::string& json_string) { auto old = *this; - Document d; - if ( d.Parse(json_string.c_str()).HasParseError()) { - return false; - } + JsonStringParser parser(json_string); - if (!IntFromJson(d, "_id", &id) || - !IntFromJson(d, "size", &size) || - !StringFromJson(d, "base_name", &base_name) || - !StringFromJson(d, "relative_path", &relative_path) || - !TimeFromJson(d, "lastchange", &modify_date)) { + if (parser.GetUInt64("_id", &id) || + parser.GetUInt64("size", &size) || + parser.GetString("base_name", &base_name) || + parser.GetString("relative_path", &relative_path) || + !TimeFromJson(parser, "lastchange", &modify_date)) { *this = old; return false; } diff --git a/common/cpp/src/database/CMakeLists.txt b/common/cpp/src/database/CMakeLists.txt index d68b39e61..44b6ab28b 100644 --- a/common/cpp/src/database/CMakeLists.txt +++ b/common/cpp/src/database/CMakeLists.txt @@ -12,7 +12,7 @@ message ("-- mongoc include path \"${MONGOC_STATIC_INCLUDE_DIRS}\"") message ("-- mongoc libraries \"${MONGOC_STATIC_LIBRARIES}\"") -add_library(${TARGET_NAME} STATIC ${SOURCE_FILES} $<TARGET_OBJECTS:data_structs>) +add_library(${TARGET_NAME} STATIC ${SOURCE_FILES} $<TARGET_OBJECTS:data_structs> $<TARGET_OBJECTS:json_parser>) target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR} PUBLIC "${MONGOC_STATIC_INCLUDE_DIRS}") target_link_libraries (${TARGET_NAME} PRIVATE "${MONGOC_STATIC_LIBRARIES}") diff --git a/common/cpp/src/json_parser/CMakeLists.txt b/common/cpp/src/json_parser/CMakeLists.txt new file mode 100644 index 000000000..286f641e5 --- /dev/null +++ b/common/cpp/src/json_parser/CMakeLists.txt @@ -0,0 +1,23 @@ +set(TARGET_NAME json_parser) +set(SOURCE_FILES + json_string_parser.cpp + rapid_json.cpp) + +################################ +# Library +################################ + +add_library(${TARGET_NAME} OBJECT ${SOURCE_FILES}) +target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR} + ${CMAKE_SOURCE_DIR}/3d_party/rapidjson/include) + +################################ +# Testing +################################ + + +set(TEST_SOURCE_FILES ../../unittests/json_parser/test_json_string_parser.cpp) + +set(TEST_LIBRARIES "${TARGET_NAME}") +include_directories(${HIDRA2_CXX_COMMON_INCLUDE_DIR}) +gtest(${TARGET_NAME} "${TEST_SOURCE_FILES}" "${TEST_LIBRARIES}") diff --git a/common/cpp/src/json_parser/json_string_parser.cpp b/common/cpp/src/json_parser/json_string_parser.cpp new file mode 100644 index 000000000..e3a35f712 --- /dev/null +++ b/common/cpp/src/json_parser/json_string_parser.cpp @@ -0,0 +1,26 @@ + +#include "json_parser/json_parser.h" +#include "rapid_json.h" + +namespace hidra2 { + + +JsonStringParser::~JsonStringParser() { + +} + +JsonStringParser::JsonStringParser(const std::string& json) : rapid_json_{new RapidJson(json)} { +} + +Error JsonStringParser::GetUInt64(const std::string& name, uint64_t* val) const noexcept { + return rapid_json_->GetUInt64(name, val); +} + +Error JsonStringParser::GetString(const std::string& name, std::string* val) const noexcept { + return rapid_json_->GetString(name, val); +} + +} + + + diff --git a/common/cpp/src/json_parser/rapid_json.cpp b/common/cpp/src/json_parser/rapid_json.cpp new file mode 100644 index 000000000..42974c6eb --- /dev/null +++ b/common/cpp/src/json_parser/rapid_json.cpp @@ -0,0 +1,78 @@ +#include "rapid_json.h" + +using namespace rapidjson; + +namespace hidra2 { + +RapidJson::RapidJson(const std::string& json): json_{json} { + +} + +bool RapidJson::LazyInitialize()const noexcept { + if (initialized_) + return true; + + if ( doc_.Parse(json_.c_str()).HasParseError()) { + return false; + } + + return true; + +} + +hidra2::Error CheckValueType(const std::string& name, ValueType type, const Value& val) { + bool res = false; + switch (type) { + case ValueType::kString: + res = val.IsString(); + break; + case ValueType::kUint64: + res = val.IsInt64(); + break; + } + if (!res) { + return TextError("wrong type: " + name); + } + + return nullptr; +} + + +hidra2::Error RapidJson::GetValue(const std::string& name, ValueType type, Value* val)const noexcept { + if (!LazyInitialize()) { + return TextError("cannot parse document"); + } + + auto iterator = doc_.FindMember(name.c_str()); + if (iterator == doc_.MemberEnd()) { + return TextError("cannot find: " + name); + } + + *val = iterator->value; + return CheckValueType(name, type, *val); +} + + +Error RapidJson::GetUInt64(const std::string& name, uint64_t* val) const noexcept { + Value json_val; + if (Error err = GetValue(name, ValueType::kUint64, &json_val)) { + return err; + } + *val = json_val.GetInt64(); + return nullptr; +} + + + + +Error RapidJson::GetString(const std::string& name, std::string* val) const noexcept { + Value json_val; + if (Error err = GetValue(name, ValueType::kString, &json_val)) { + return err; + } + *val = json_val.GetString(); + return nullptr; +} + + +} \ No newline at end of file diff --git a/common/cpp/src/json_parser/rapid_json.h b/common/cpp/src/json_parser/rapid_json.h new file mode 100644 index 000000000..379ccd631 --- /dev/null +++ b/common/cpp/src/json_parser/rapid_json.h @@ -0,0 +1,30 @@ +#ifndef HIDRA2_RAPID_JSON_H +#define HIDRA2_RAPID_JSON_H + +#include "rapidjson/document.h" +#include "common/error.h" + +namespace hidra2 { + +enum class ValueType { + kUint64, + kString +}; + + +class RapidJson { + public: + RapidJson(const std::string& json); + Error GetUInt64(const std::string& name, uint64_t* val) const noexcept; + Error GetString(const std::string& name, std::string* val) const noexcept; + private: + mutable rapidjson::Document doc_; + std::string json_; + mutable bool initialized_ = false; + bool LazyInitialize() const noexcept; + hidra2::Error GetValue(const std::string& name, ValueType type, rapidjson::Value* val)const noexcept; + +}; + +} +#endif //HIDRA2_RAPID_JSON_H diff --git a/common/cpp/unittests/json_parser/test_json_string_parser.cpp b/common/cpp/unittests/json_parser/test_json_string_parser.cpp new file mode 100644 index 000000000..926043424 --- /dev/null +++ b/common/cpp/unittests/json_parser/test_json_string_parser.cpp @@ -0,0 +1,76 @@ + +#include <gmock/gmock.h> +#include "gtest/gtest.h" +#include <chrono> + +#include "json_parser/json_parser.h" + +using ::testing::AtLeast; +using ::testing::Eq; +using ::testing::Ne; +using ::testing::Test; +using ::testing::_; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::HasSubstr; + +using hidra2::JsonStringParser; + +namespace { + +TEST(ParseString, CorrectConvertToJson) { + ASSERT_THAT(1, Eq(1)); + std::string json = R"({"_id":2,"foo":"foo","bar":1})"; + + JsonStringParser parser{json}; + + uint64_t id, bar; + std::string foo; + auto err1 = parser.GetUInt64("_id", &id); + auto err2 = parser.GetString("foo", &foo); + auto err3 = parser.GetUInt64("bar", &bar); + + ASSERT_THAT(err1, Eq(nullptr)); + ASSERT_THAT(err2, Eq(nullptr)); + ASSERT_THAT(err3, Eq(nullptr)); + + ASSERT_THAT(id, Eq(2)); + ASSERT_THAT(foo, Eq("foo")); + ASSERT_THAT(bar, Eq(1)); + +} + + +TEST(ParseString, ErrorOnWrongType) { + ASSERT_THAT(1, Eq(1)); + std::string json = R"({"_id":"2"})"; + + JsonStringParser parser{json}; + + uint64_t id; + auto err = parser.GetUInt64("_id", &id); + + ASSERT_THAT(err, Ne(nullptr)); + ASSERT_THAT(err->Explain(), ::testing::HasSubstr("type")); + +} + +TEST(ParseString, ErrorOnWrongDocument) { + ASSERT_THAT(1, Eq(1)); + std::string json = R"({"_id":2)"; + + JsonStringParser parser{json}; + + uint64_t id; + auto err = parser.GetUInt64("_id", &id); + + ASSERT_THAT(err, Ne(nullptr)); + ASSERT_THAT(err->Explain(), ::testing::HasSubstr("parse")); + +} + + + +} \ No newline at end of file diff --git a/worker/api/cpp/CMakeLists.txt b/worker/api/cpp/CMakeLists.txt index 49bcfa605..914d87840 100644 --- a/worker/api/cpp/CMakeLists.txt +++ b/worker/api/cpp/CMakeLists.txt @@ -13,7 +13,7 @@ set(SOURCE_FILES # Library ################################ add_library(${TARGET_NAME} STATIC ${SOURCE_FILES} $<TARGET_OBJECTS:system_io> - $<TARGET_OBJECTS:data_structs>) + $<TARGET_OBJECTS:json_parser> $<TARGET_OBJECTS:data_structs> ) set (CMAKE_PREFIX_PATH "${LIBCURL_DIR}") find_package (CURL REQUIRED) -- GitLab