From ab3b2d85151c73c446f8b367eda8c6b28fcb4c1f Mon Sep 17 00:00:00 2001 From: pajlada Date: Sat, 14 Oct 2023 10:41:10 +0200 Subject: [PATCH] Add some more filter tests (#4897) This changes the `make coverage` function to use `gcovr` instead of `lcov`, and to have it generate an html file directly at `coverage/index.html` under the build directory The only thing this changes, other than adding tests, is making the `Expression` class pure virtual. Every derived class should implement each of the functions --- src/CMakeLists.txt | 8 +- .../filters/lang/expressions/Expression.cpp | 20 ----- .../filters/lang/expressions/Expression.hpp | 8 +- tests/src/Filters.cpp | 86 +++++++++++++++++++ 4 files changed, 94 insertions(+), 28 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ef7fb162..6f462d3e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -679,15 +679,15 @@ endif() if (CHATTERINO_GENERATE_COVERAGE) include(CodeCoverage) append_coverage_compiler_flags_to_target(${LIBRARY_PROJECT}) - target_link_libraries(${LIBRARY_PROJECT} PUBLIC gcov) message(STATUS "project source dir: ${PROJECT_SOURCE_DIR}/src") - setup_target_for_coverage_lcov( + setup_target_for_coverage_gcovr_html( NAME coverage - EXECUTABLE ./bin/chatterino-test - BASE_DIRECTORY ${PROJECT_SOURCE_DIR}/src + EXECUTABLE ctest EXCLUDE "/usr/include/*" EXCLUDE "build-*/*" EXCLUDE "lib/*" + EXCLUDE "*/ui_*.h" + EXCLUDE "*/moc_*.cpp" ) endif () diff --git a/src/controllers/filters/lang/expressions/Expression.cpp b/src/controllers/filters/lang/expressions/Expression.cpp index 74f987f2..0c353d8c 100644 --- a/src/controllers/filters/lang/expressions/Expression.cpp +++ b/src/controllers/filters/lang/expressions/Expression.cpp @@ -2,24 +2,4 @@ namespace chatterino::filters { -QVariant Expression::execute(const ContextMap & /*context*/) const -{ - return false; -} - -PossibleType Expression::synthesizeType(const TypingContext & /*context*/) const -{ - return IllTyped{this, "Not implemented"}; -} - -QString Expression::debug(const TypingContext & /*context*/) const -{ - return ""; -} - -QString Expression::filterString() const -{ - return ""; -} - } // namespace chatterino::filters diff --git a/src/controllers/filters/lang/expressions/Expression.hpp b/src/controllers/filters/lang/expressions/Expression.hpp index d08fa6ef..fe4fddac 100644 --- a/src/controllers/filters/lang/expressions/Expression.hpp +++ b/src/controllers/filters/lang/expressions/Expression.hpp @@ -16,10 +16,10 @@ class Expression public: virtual ~Expression() = default; - virtual QVariant execute(const ContextMap &context) const; - virtual PossibleType synthesizeType(const TypingContext &context) const; - virtual QString debug(const TypingContext &context) const; - virtual QString filterString() const; + virtual QVariant execute(const ContextMap &context) const = 0; + virtual PossibleType synthesizeType(const TypingContext &context) const = 0; + virtual QString debug(const TypingContext &context) const = 0; + virtual QString filterString() const = 0; }; using ExpressionPtr = std::unique_ptr; diff --git a/tests/src/Filters.cpp b/tests/src/Filters.cpp index 87f95c78..011c18c2 100644 --- a/tests/src/Filters.cpp +++ b/tests/src/Filters.cpp @@ -1,4 +1,5 @@ #include "controllers/accounts/AccountController.hpp" +#include "controllers/filters/lang/expressions/UnaryOperation.hpp" #include "controllers/filters/lang/Filter.hpp" #include "controllers/filters/lang/Types.hpp" #include "controllers/highlights/HighlightController.hpp" @@ -285,3 +286,88 @@ TEST_F(FiltersF, TypingContextChecks) delete privmsg; } + +TEST_F(FiltersF, ExpressionDebug) +{ + struct TestCase { + QString input; + QString debugString; + QString filterString; + }; + + // clang-format off + std::vector tests{ + { + .input = R".(1 + 1).", + .debugString = "BinaryOp[Plus](Val(1) : Int, Val(1) : Int)", + .filterString = "(1 + 1)", + }, + { + .input = R".(author.color == "#ff0000").", + .debugString = "BinaryOp[Eq](Val(author.color) : Color, Val(#ff0000) : String)", + .filterString = R".((author.color == "#ff0000")).", + }, + { + .input = R".(1).", + .debugString = "Val(1)", + .filterString = R".(1).", + }, + { + .input = R".("asd").", + .debugString = R".(Val(asd)).", + .filterString = R".("asd").", + }, + { + .input = R".(("asd")).", + .debugString = R".(Val(asd)).", + .filterString = R".("asd").", + }, + { + .input = R".(author.subbed).", + .debugString = R".(Val(author.subbed)).", + .filterString = R".(author.subbed).", + }, + { + .input = R".(!author.subbed).", + .debugString = R".(UnaryOp[Not](Val(author.subbed) : Bool)).", + .filterString = R".((!author.subbed)).", + }, + { + .input = R".({"foo", "bar"} contains "foo").", + .debugString = R".(BinaryOp[Contains](List(Val(foo) : String, Val(bar) : String) : StringList, Val(foo) : String)).", + .filterString = R".(({"foo", "bar"} contains "foo")).", + }, + { + .input = R".(!({"foo", "bar"} contains "foo")).", + .debugString = R".(UnaryOp[Not](BinaryOp[Contains](List(Val(foo) : String, Val(bar) : String) : StringList, Val(foo) : String) : Bool)).", + .filterString = R".((!({"foo", "bar"} contains "foo"))).", + }, + { + .input = R".(message.content match r"(\d\d)/(\d\d)/(\d\d\d\d)").", + .debugString = R".(BinaryOp[Match](Val(message.content) : String, RegEx((\d\d)/(\d\d)/(\d\d\d\d)) : RegularExpression)).", + .filterString = R".((message.content match r"(\d\d)/(\d\d)/(\d\d\d\d)")).", + }, + }; + // clang-format on + + for (const auto &[input, debugString, filterString] : tests) + { + const auto filterResult = Filter::fromString(input); + const auto *filter = std::get_if(&filterResult); + EXPECT_NE(filter, nullptr) + << "Filter::fromString(" << qUtf8Printable(input) + << ") did not build a proper filter"; + + const auto actualDebugString = filter->debugString(typingContext); + EXPECT_EQ(actualDebugString, debugString) + << "filter->debugString() on '" << qUtf8Printable(input) + << "' should be '" << qUtf8Printable(debugString) << "', but got '" + << qUtf8Printable(actualDebugString) << "'"; + + const auto actualFilterString = filter->filterString(); + EXPECT_EQ(actualFilterString, filterString) + << "filter->filterString() on '" << qUtf8Printable(input) + << "' should be '" << qUtf8Printable(filterString) << "', but got '" + << qUtf8Printable(actualFilterString) << "'"; + } +}