From e063311e9de105ac2526b4c1c61214919f5ee5fe Mon Sep 17 00:00:00 2001 From: Jessica James Date: Sat, 29 Sep 2018 16:01:11 -0500 Subject: [PATCH] Added tests for config, parser --- src/common/config.cpp | 6 +- src/test/CMakeLists.txt | 2 +- src/test/config.cpp | 136 ++++++++++++++++++++++++++++++++++++++++ src/test/parser.cpp | 113 +++++++++++++++++++++++++++++++++ src/test/test.hpp | 2 + 5 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 src/test/config.cpp create mode 100644 src/test/parser.cpp diff --git a/src/common/config.cpp b/src/common/config.cpp index b899190..85accfa 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -114,7 +114,7 @@ object config::read_object(const std::filesystem::path& in_filename, const std:: } // Deserialize1 - return deserialize_object(file, in_format); + return deserialize_object(file, get_format(in_filename, in_format)); } void config::write_object(const object& in_object, const std::filesystem::path& in_filename, const std::string& in_format) { @@ -126,10 +126,10 @@ void config::write_object(const object& in_object, const std::filesystem::path& } // Deserialize1 - return serialize_object(file, in_object, in_format); + return serialize_object(file, in_object, get_format(in_filename, in_format)); } -std::string get_format(const std::filesystem::path& in_filename, const std::string& in_format) { +std::string config::get_format(const std::filesystem::path& in_filename, const std::string& in_format) { if (!in_format.empty()) { // Use specified format return in_format; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index a22e495..36a6f40 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.8) # Setup source files include_directories(../include) set(SOURCE_FILES - timer.cpp thread_pool.cpp util.cpp object.cpp) + timer.cpp thread_pool.cpp util.cpp object.cpp parser.cpp config.cpp) # Setup gtest add_subdirectory(googletest/googletest) diff --git a/src/test/config.cpp b/src/test/config.cpp new file mode 100644 index 0000000..03f49bd --- /dev/null +++ b/src/test/config.cpp @@ -0,0 +1,136 @@ +/** + * Copyright (C) 2018 Jessica James. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Written by Jessica James + */ + +#include +#include +#include +#include "test.hpp" +#include "config.hpp" +#include "serialize.hpp" // format_not_available + +using namespace jessilib; +using namespace std::literals; + +// NOTE: see test/parser.cpp for test_parser implementation and details for format "test" + +std::filesystem::path make_tmp_file(std::filesystem::path in_filename, const std::string& in_data) { + // Build path + std::filesystem::path path = std::filesystem::temp_directory_path(); + path /= in_filename; + + // Delete any previously existing file + std::filesystem::remove(path); + + // Populate file + { + std::ofstream file{ path, std::ios::binary | std::ios::out }; + file << in_data << std::flush; + } + + // Return fstream to file + return path; + //return std::fstream{ path, std::ios::binary | std::ios::out | std::ios::in }; +} + +TEST(ConfigTest, get_format) { + EXPECT_EQ(config::get_format("example.json"), "json"); + EXPECT_EQ(config::get_format("example.json", "xml"), "xml"); + EXPECT_EQ(config::get_format("example", "json"), "json"); +} + +TEST(ConfigTest, read_object) { + std::filesystem::path file_path = make_tmp_file("read_object.test", "some_data"); + EXPECT_EQ(config::read_object(file_path).get(), "some_data"); +} + +TEST(ConfigTest, write_object) { + std::filesystem::path file_path = make_tmp_file("write_object.test", "some_data"); + config::write_object(object{}, file_path); + + EXPECT_EQ(config::read_object(file_path).get(), "serialize_result"); +} + +TEST(ConfigTest, load) { + config l_config; + + // Write temp file out + std::filesystem::path file_path = make_tmp_file("load.test", "some_data"); + + // Load data from disk + l_config.load(file_path); + + // Verify + EXPECT_EQ(l_config.data().get(), "some_data"); + EXPECT_EQ(l_config.filename(), file_path); + EXPECT_EQ(l_config.format(), "test"); +} + +TEST(ConfigTest, reload) { + config l_config; + + // Write temp file out + std::filesystem::path file_path = make_tmp_file("reload.test", "some_data"); + + // Load data from disk + l_config.load(file_path); + + // Write new data to disk + make_tmp_file("reload.test", "some_other_data"); + + // Reload data from disk and compare + l_config.reload(); + EXPECT_EQ(l_config.data().get(), "some_other_data"); +} + +TEST(ConfigTest, set_data) { + config l_config; + + l_config.set_data("some_data"); + EXPECT_EQ(l_config.data().get(), "some_data"); +} + +TEST(ConfigTest, write) { + config l_config; + std::filesystem::path file_path = make_tmp_file("write.test", ""); + + l_config.set_data("some_data"); + l_config.write(file_path); + + l_config.reload(); + EXPECT_EQ(l_config.data().get(), "some_data"); +} + +TEST(ConfigTest, rewrite) { + config l_config; + + // Write temp file out + std::filesystem::path file_path = make_tmp_file("rewrite.test", "some_data"); + + // Load data from disk + l_config.load(file_path); + + // Set some other data + l_config.set_data("some_other_data"); + + // Write data to disk + l_config.write(); + + // Reload from disk and verify + l_config.reload(); + EXPECT_EQ(l_config.data().get(), "some_other_data"); +} diff --git a/src/test/parser.cpp b/src/test/parser.cpp new file mode 100644 index 0000000..c1a22a6 --- /dev/null +++ b/src/test/parser.cpp @@ -0,0 +1,113 @@ +/** + * Copyright (C) 2018 Jessica James. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Written by Jessica James + */ + +#include +#include +#include "test.hpp" +#include "parser.hpp" +#include "serialize.hpp" + +using namespace jessilib; +using namespace std::literals; + +/** test_parser */ + +class test_parser : public parser { +public: + /** deserialize/serialize overrides */ + virtual object deserialize(std::string_view in_data) override { + return deserialize_impl(in_data); + } + + virtual std::string serialize(const object& in_object) override { + return serialize_impl(in_object); + } + + /** helpers */ + static void reset() { + serialize_impl = &serialize_default; + deserialize_impl = &deserialize_default; + } + + /** default serialize/deserialize implementations */ + static std::string serialize_default(const object& in_object) { + if (in_object.has()) { + return in_object.get(); + } + + return DEFAULT_SERIALIZE_RESULT; + } + + static object deserialize_default(std::string_view in_data) { + return object{ in_data }; + } + + /** static members */ + static constexpr const char DEFAULT_SERIALIZE_RESULT[]{ "serialize_result" }; + static std::function serialize_impl; + static std::function deserialize_impl; +}; + +std::function test_parser::serialize_impl{ &serialize_default }; +std::function test_parser::deserialize_impl{ &deserialize_default }; + +parser_registration test_parser_registration{ "test" }; + +/** ParserTest */ + +class ParserTest : public base_test { + virtual void SetUp() override { + test_parser::reset(); + } + + virtual void TearDown() override { + test_parser::reset(); + } +}; + +/** Parser tests */ + +TEST_F(ParserTest, find_parser) { + EXPECT_NO_THROW(serialize_object("test_data", "test")); + EXPECT_NO_THROW(deserialize_object("test_data"sv, "test")); + + EXPECT_THROW(serialize_object("test_data", "invalid_format_test"), format_not_available); + EXPECT_THROW(deserialize_object("test_data"sv, "invalid_format_test"), format_not_available); +} + +TEST_F(ParserTest, temp_parser) { + EXPECT_THROW(serialize_object("test_data", "test_tmp"), format_not_available); + EXPECT_THROW(deserialize_object("test_data"sv, "test_tmp"), format_not_available); + + { + parser_registration test_tmp_registration{ "test_tmp" }; + EXPECT_NO_THROW(serialize_object("test_data", "test_tmp")); + EXPECT_NO_THROW(deserialize_object("test_data"sv, "test_tmp")); + } + + EXPECT_THROW(serialize_object("test_data", "test_tmp"), format_not_available); + EXPECT_THROW(deserialize_object("test_data"sv, "test_tmp"), format_not_available); +} + +TEST_F(ParserTest, serialize) { + EXPECT_EQ(serialize_object("test_data", "test"), "test_data"); +} + +TEST_F(ParserTest, deserialize) { + EXPECT_EQ(deserialize_object("test_data"sv, "test").get(), "test_data"); +} diff --git a/src/test/test.hpp b/src/test/test.hpp index f70fc2c..58aafd0 100644 --- a/src/test/test.hpp +++ b/src/test/test.hpp @@ -24,3 +24,5 @@ // Helper macros #define UNIQUE_LABEL( LABEL ) LABEL ## __LINE__ ## __ #define repeat( ITERATIONS ) for (size_t UNIQUE_LABEL(iteration_) = 0; UNIQUE_LABEL(iteration_) != (ITERATIONS); ++ UNIQUE_LABEL(iteration_) ) + +using base_test = ::testing::Test;