mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
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
This commit is contained in:
parent
ccaedc3987
commit
ab3b2d8515
|
@ -679,15 +679,15 @@ endif()
|
||||||
if (CHATTERINO_GENERATE_COVERAGE)
|
if (CHATTERINO_GENERATE_COVERAGE)
|
||||||
include(CodeCoverage)
|
include(CodeCoverage)
|
||||||
append_coverage_compiler_flags_to_target(${LIBRARY_PROJECT})
|
append_coverage_compiler_flags_to_target(${LIBRARY_PROJECT})
|
||||||
target_link_libraries(${LIBRARY_PROJECT} PUBLIC gcov)
|
|
||||||
message(STATUS "project source dir: ${PROJECT_SOURCE_DIR}/src")
|
message(STATUS "project source dir: ${PROJECT_SOURCE_DIR}/src")
|
||||||
setup_target_for_coverage_lcov(
|
setup_target_for_coverage_gcovr_html(
|
||||||
NAME coverage
|
NAME coverage
|
||||||
EXECUTABLE ./bin/chatterino-test
|
EXECUTABLE ctest
|
||||||
BASE_DIRECTORY ${PROJECT_SOURCE_DIR}/src
|
|
||||||
EXCLUDE "/usr/include/*"
|
EXCLUDE "/usr/include/*"
|
||||||
EXCLUDE "build-*/*"
|
EXCLUDE "build-*/*"
|
||||||
EXCLUDE "lib/*"
|
EXCLUDE "lib/*"
|
||||||
|
EXCLUDE "*/ui_*.h"
|
||||||
|
EXCLUDE "*/moc_*.cpp"
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
@ -2,24 +2,4 @@
|
||||||
|
|
||||||
namespace chatterino::filters {
|
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
|
} // namespace chatterino::filters
|
||||||
|
|
|
@ -16,10 +16,10 @@ class Expression
|
||||||
public:
|
public:
|
||||||
virtual ~Expression() = default;
|
virtual ~Expression() = default;
|
||||||
|
|
||||||
virtual QVariant execute(const ContextMap &context) const;
|
virtual QVariant execute(const ContextMap &context) const = 0;
|
||||||
virtual PossibleType synthesizeType(const TypingContext &context) const;
|
virtual PossibleType synthesizeType(const TypingContext &context) const = 0;
|
||||||
virtual QString debug(const TypingContext &context) const;
|
virtual QString debug(const TypingContext &context) const = 0;
|
||||||
virtual QString filterString() const;
|
virtual QString filterString() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ExpressionPtr = std::unique_ptr<Expression>;
|
using ExpressionPtr = std::unique_ptr<Expression>;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "controllers/accounts/AccountController.hpp"
|
#include "controllers/accounts/AccountController.hpp"
|
||||||
|
#include "controllers/filters/lang/expressions/UnaryOperation.hpp"
|
||||||
#include "controllers/filters/lang/Filter.hpp"
|
#include "controllers/filters/lang/Filter.hpp"
|
||||||
#include "controllers/filters/lang/Types.hpp"
|
#include "controllers/filters/lang/Types.hpp"
|
||||||
#include "controllers/highlights/HighlightController.hpp"
|
#include "controllers/highlights/HighlightController.hpp"
|
||||||
|
@ -285,3 +286,88 @@ TEST_F(FiltersF, TypingContextChecks)
|
||||||
|
|
||||||
delete privmsg;
|
delete privmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(FiltersF, ExpressionDebug)
|
||||||
|
{
|
||||||
|
struct TestCase {
|
||||||
|
QString input;
|
||||||
|
QString debugString;
|
||||||
|
QString filterString;
|
||||||
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
std::vector<TestCase> 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<Filter>(&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) << "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue