From f90f0faec0a9ace455f9d205e9ba58b7692d4216 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Thu, 28 Dec 2023 14:01:26 +0100 Subject: [PATCH] chore: add test_iolayer helper to simplify iolayer creation --- CMakeLists.txt | 8 +-- test/test_helpers.h | 45 ++++++++++++++ test/test_iolayer.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 test/test_iolayer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f013809..0f4cf14c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -583,9 +583,9 @@ endif() add_custom_target(symlinks ALL DEPENDS ${SYMLINKS}) if(WITH_TESTS OR WITH_BENCHMARKS) - add_library(test_helpers test/test_helpers.cpp test/test_strings.cpp - test/loremipsum.cpp test/test_dirtree.cpp - test/filter_test_data.cpp) + add_library(test_helpers test/test_helpers.cpp test/test_iolayer.cpp + test/test_strings.cpp test/loremipsum.cpp + test/test_dirtree.cpp test/filter_test_data.cpp) target_link_libraries(test_helpers dwarfs folly) set_property(TARGET test_helpers PROPERTY CXX_STANDARD 20) endif() @@ -614,7 +614,7 @@ if(WITH_TESTS) add_executable(${test} test/${test}.cpp) target_link_libraries( ${test} test_helpers gmock gtest gtest_main - "$" + ${MAIN_TARGETS} ) target_compile_definitions(${test} PRIVATE TEST_DATA_DIR=\"${CMAKE_SOURCE_DIR}/test\" diff --git a/test/test_helpers.h b/test/test_helpers.h index 647e5777..98b0d3d4 100644 --- a/test/test_helpers.h +++ b/test/test_helpers.h @@ -34,8 +34,10 @@ #include #include "dwarfs/file_stat.h" +#include "dwarfs/iolayer.h" #include "dwarfs/os_access.h" #include "dwarfs/script.h" +#include "dwarfs/terminal.h" namespace dwarfs::test { @@ -132,6 +134,49 @@ class script_mock : public script { } }; +class test_terminal : public terminal { + public: + test_terminal(std::ostream& out, std::ostream& err); + + void set_fancy(bool fancy) { fancy_ = fancy; } + void set_width(size_t width) { width_ = width; } + + size_t width() const override; + bool is_fancy(std::ostream& os) const override; + std::string_view color(termcolor color, termstyle style) const override; + std::string colored(std::string text, termcolor color, bool enable, + termstyle style) const override; + + private: + std::ostream* out_; + std::ostream* err_; + bool fancy_{false}; + size_t width_{80}; +}; + +class test_iolayer { + public: + test_iolayer(std::shared_ptr os); + ~test_iolayer(); + + iolayer const& get() const; + + std::string out() const; + std::string err() const; + + void set_in(std::string in); + void set_terminal_fancy(bool fancy); + void set_terminal_width(size_t width); + + private: + std::shared_ptr os_; + std::shared_ptr term_; + std::istringstream in_; + std::ostringstream out_; + std::ostringstream err_; + std::unique_ptr iol_; +}; + extern std::map statmap; std::optional find_binary(std::string_view name); diff --git a/test/test_iolayer.cpp b/test/test_iolayer.cpp new file mode 100644 index 00000000..c04434ce --- /dev/null +++ b/test/test_iolayer.cpp @@ -0,0 +1,137 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#include + +#include + +#include "test_helpers.h" + +namespace dwarfs::test { + +test_terminal::test_terminal(std::ostream& out, std::ostream& err) + : out_{&out} + , err_{&err} {} + +size_t test_terminal::width() const { return width_; } + +bool test_terminal::is_fancy(std::ostream& os) const { + return fancy_ && (&os == out_ || &os == err_); +} + +std::string_view test_terminal::color(termcolor color, termstyle style) const { + static constexpr std::array(termcolor::NUM_COLORS)> + // clang-format off + colors = {{ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }}; // clang-format on + + static constexpr size_t const kBoldOffset{ + static_cast(termcolor::BOLD_RED) - + static_cast(termcolor::RED)}; + static constexpr size_t const kDimOffset{ + static_cast(termcolor::DIM_RED) - + static_cast(termcolor::RED)}; + + switch (style) { + case termstyle::BOLD: + case termstyle::DIM: { + auto ix = static_cast(color); + if (ix < static_cast(termcolor::BOLD_RED)) { + color = static_cast( + ix + (style == termstyle::BOLD ? kBoldOffset : kDimOffset)); + } + } break; + + default: + break; + } + + return colors.at(static_cast(color)); +} + +std::string test_terminal::colored(std::string text, termcolor color, + bool enable, termstyle style) const { + std::string result; + + if (enable) { + auto preamble = this->color(color, style); + auto postamble = this->color(termcolor::NORMAL, termstyle::NORMAL); + + result.reserve(preamble.size() + text.size() + postamble.size()); + result.append(preamble); + result.append(text); + result.append(postamble); + } else { + result.append(text); + } + + return result; +} + +test_iolayer::test_iolayer(std::shared_ptr os) + : os_{std::move(os)} + , term_{std::make_shared(out_, err_)} + , iol_{std::make_unique(iolayer{ + .os = os_, + .term = term_, + .in = in_, + .out = out_, + .err = err_, + })} {} + +test_iolayer::~test_iolayer() = default; + +iolayer const& test_iolayer::get() const { return *iol_; } + +void test_iolayer::set_terminal_fancy(bool fancy) { term_->set_fancy(fancy); } +void test_iolayer::set_terminal_width(size_t width) { term_->set_width(width); } +void test_iolayer::set_in(std::string in) { in_.str(std::move(in)); } + +std::string test_iolayer::out() const { return out_.str(); } +std::string test_iolayer::err() const { return err_.str(); } + +} // namespace dwarfs::test