]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Css: Add some c++ unit tests
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 12 Mar 2021 17:58:52 +0000 (17:58 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 12 Mar 2021 17:58:52 +0000 (17:58 +0000)
contrib/DEPENDENCY_INFO.md
src/libserver/css/css.cxx
src/libserver/css/css_value.cxx
src/libserver/css/css_value.hxx
test/CMakeLists.txt
test/rspamd_cxx_unit.cxx [new file with mode: 0644]

index 12e00df26c3a9e346d1d77e7cce3fceb80953018..9f6a156f98568069d297335c172d0d6be800219b 100644 (file)
@@ -32,3 +32,4 @@
 | robin-hood    | 3.9.1   | MIT                 | NO      |                    |
 | frozen        | 1.0.1   | Apache 2            | NO      |                    |
 | fmt           | 7.1.3   | MIT                 | NO      |                    |
+| doctest       | 2.4.5   | MIT                 | NO      |                    |
index 6633b68fd8714058c373bb9560b3c30026fd7c4d..49bab734dc911b1ca6f67bf104a0b15d82fd17e4 100644 (file)
@@ -18,6 +18,9 @@
 #include "css.hxx"
 #include "css_style.hxx"
 #include "css_parser.hxx"
+#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#define DOCTEST_CONFIG_IMPLEMENT
+#include "doctest/doctest.h"
 
 rspamd_css
 rspamd_css_parse_style (rspamd_mempool_t *pool, const guchar *begin, gsize len,
index 5470e8f30afa1232ccfe2a409e9e8a6e840dcca3..a2b4ba5d7257fc9bb4466607f98eb970d15bcba5 100644 (file)
 #include "frozen/unordered_map.h"
 #include "frozen/string.h"
 #include "contrib/robin-hood/robin_hood.h"
+#include "fmt/core.h"
+
+#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#include "doctest/doctest.h"
+
+/* Helper for unit test stringification */
+namespace doctest {
+template<> struct StringMaker<rspamd::css::css_color> {
+       static String convert(const rspamd::css::css_color& value) {
+               return fmt::format("r={};g={};b={};alpha={}",
+                               value.r, value.g, value.b, value.alpha).c_str();
+       }
+};
+
+}
 
 namespace rspamd::css {
 
 auto css_value::maybe_color_from_string(const std::string_view &input)
-       -> std::optional<css_value>
-{
+-> std::optional<css_value> {
        auto found_it = css_colors_map.find(input);
 
        if (found_it != css_colors_map.end()) {
@@ -34,17 +48,16 @@ auto css_value::maybe_color_from_string(const std::string_view &input)
        return std::nullopt;
 }
 
-constexpr static inline auto hexpair_decode(char c1, char c2) -> std::uint8_t
-{
+constexpr static inline auto hexpair_decode(char c1, char c2) -> std::uint8_t {
        std::uint8_t ret = 0;
 
-       if      (c1 >= '0' && c1 <= '9') ret = c1 - '0';
+       if (c1 >= '0' && c1 <= '9') ret = c1 - '0';
        else if (c1 >= 'A' && c1 <= 'F') ret = c1 - 'A' + 10;
        else if (c1 >= 'a' && c1 <= 'f') ret = c1 - 'a' + 10;
 
        ret *= 16;
 
-       if      (c2 >= '0' && c2 <= '9') ret += c2 - '0';
+       if (c2 >= '0' && c2 <= '9') ret += c2 - '0';
        else if (c2 >= 'A' && c2 <= 'F') ret += c2 - 'A' + 10;
        else if (c2 >= 'a' && c2 <= 'f') ret += c2 - 'a' + 10;
 
@@ -52,8 +65,7 @@ constexpr static inline auto hexpair_decode(char c1, char c2) -> std::uint8_t
 }
 
 auto css_value::maybe_color_from_hex(const std::string_view &input)
-       -> std::optional<css_value>
-{
+-> std::optional<css_value> {
        if (input.length() == 6) {
                /* Plain RGB */
                css_color col(hexpair_decode(input[0], input[1]),
@@ -81,8 +93,7 @@ auto css_value::maybe_color_from_hex(const std::string_view &input)
 }
 
 constexpr static inline auto rgb_color_component_convert(const css_parser_token &tok)
-       -> std::uint8_t
-{
+-> std::uint8_t {
        std::uint8_t ret = 0;
 
        if (tok.type == css_parser_token::token_type::number_token) {
@@ -95,7 +106,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token
                        else if (dbl < 0) {
                                dbl = 0;
                        }
-                       ret = (std::uint8_t)(dbl / 100.0 * 255.0);
+                       ret = (std::uint8_t) (dbl / 100.0 * 255.0);
                }
                else {
                        if (dbl > 1) {
@@ -105,7 +116,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token
                                dbl = 0;
                        }
 
-                       ret = (std::uint8_t)(dbl * 255.0);
+                       ret = (std::uint8_t) (dbl * 255.0);
                }
        }
 
@@ -113,8 +124,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token
 }
 
 constexpr static inline auto alpha_component_convert(const css_parser_token &tok)
-       -> std::uint8_t
-{
+-> std::uint8_t {
        double ret = 1.0;
 
        if (tok.type == css_parser_token::token_type::number_token) {
@@ -141,12 +151,11 @@ constexpr static inline auto alpha_component_convert(const css_parser_token &tok
                }
        }
 
-       return (std::uint8_t)(ret * 255.0);
+       return (std::uint8_t) (ret * 255.0);
 }
 
 constexpr static inline auto h_component_convert(const css_parser_token &tok)
-       -> double
-{
+-> double {
        double ret = 0.0;
 
        if (tok.type == css_parser_token::token_type::number_token) {
@@ -162,7 +171,7 @@ constexpr static inline auto h_component_convert(const css_parser_token &tok)
                        ret = (dbl / 100.0);
                }
                else {
-                       dbl = ((((int)dbl % 360) + 360) % 360); /* Deal with rotations */
+                       dbl = ((((int) dbl % 360) + 360) % 360); /* Deal with rotations */
                        ret = dbl / 360.0; /* Normalize to 0..1 */
                }
        }
@@ -171,8 +180,7 @@ constexpr static inline auto h_component_convert(const css_parser_token &tok)
 }
 
 constexpr static inline auto sl_component_convert(const css_parser_token &tok)
-       -> double
-{
+-> double {
        double ret = 0.0;
 
        if (tok.type == css_parser_token::token_type::number_token) {
@@ -183,8 +191,7 @@ constexpr static inline auto sl_component_convert(const css_parser_token &tok)
 }
 
 static inline auto hsl_to_rgb(double h, double s, double l)
-       -> css_color
-{
+-> css_color {
        css_color ret;
 
        constexpr auto hue2rgb = [](auto p, auto q, auto t) -> auto {
@@ -201,7 +208,7 @@ static inline auto hsl_to_rgb(double h, double s, double l)
                        return q;
                }
                if (t * 3. < 2.) {
-                       return p + (q - p) * (2.0/3.0 - t) * 6.0;
+                       return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
                }
                return p;
        };
@@ -226,8 +233,7 @@ static inline auto hsl_to_rgb(double h, double s, double l)
 }
 
 auto css_value::maybe_color_from_function(const css_consumed_block::css_function_block &func)
-       -> std::optional<css_value>
-{
+-> std::optional<css_value> {
 
        if (func.as_string() == "rgb" && func.args.size() == 3) {
                css_color col{rgb_color_component_convert(func.args[0]->get_token_or_empty()),
@@ -268,8 +274,7 @@ auto css_value::maybe_color_from_function(const css_consumed_block::css_function
 }
 
 auto css_value::maybe_dimension_from_number(const css_parser_token &tok)
--> std::optional<css_value>
-{
+-> std::optional<css_value> {
        if (std::holds_alternative<double>(tok.value)) {
                auto dbl = std::get<double>(tok.value);
                css_dimension dim;
@@ -290,34 +295,33 @@ auto css_value::maybe_dimension_from_number(const css_parser_token &tok)
 }
 
 constexpr const auto display_names_map = frozen::make_unordered_map<frozen::string, css_display_value>({
-               {"hidden", css_display_value::DISPLAY_HIDDEN},
-               {"none", css_display_value::DISPLAY_HIDDEN},
-               {"inline", css_display_value::DISPLAY_NORMAL},
-               {"block", css_display_value::DISPLAY_NORMAL},
-               {"content", css_display_value::DISPLAY_NORMAL},
-               {"flex", css_display_value::DISPLAY_NORMAL},
-               {"grid" , css_display_value::DISPLAY_NORMAL},
-               {"inline-block", css_display_value::DISPLAY_NORMAL},
-               {"inline-flex", css_display_value::DISPLAY_NORMAL},
-               {"inline-grid", css_display_value::DISPLAY_NORMAL},
-               {"inline-table", css_display_value::DISPLAY_NORMAL},
-               {"list-item", css_display_value::DISPLAY_NORMAL},
-               {"run-in", css_display_value::DISPLAY_NORMAL},
-               {"table", css_display_value::DISPLAY_NORMAL},
-               {"table-caption", css_display_value::DISPLAY_NORMAL},
+               {"hidden",             css_display_value::DISPLAY_HIDDEN},
+               {"none",               css_display_value::DISPLAY_HIDDEN},
+               {"inline",             css_display_value::DISPLAY_NORMAL},
+               {"block",              css_display_value::DISPLAY_NORMAL},
+               {"content",            css_display_value::DISPLAY_NORMAL},
+               {"flex",               css_display_value::DISPLAY_NORMAL},
+               {"grid",               css_display_value::DISPLAY_NORMAL},
+               {"inline-block",       css_display_value::DISPLAY_NORMAL},
+               {"inline-flex",        css_display_value::DISPLAY_NORMAL},
+               {"inline-grid",        css_display_value::DISPLAY_NORMAL},
+               {"inline-table",       css_display_value::DISPLAY_NORMAL},
+               {"list-item",          css_display_value::DISPLAY_NORMAL},
+               {"run-in",             css_display_value::DISPLAY_NORMAL},
+               {"table",              css_display_value::DISPLAY_NORMAL},
+               {"table-caption",      css_display_value::DISPLAY_NORMAL},
                {"table-column-group", css_display_value::DISPLAY_NORMAL},
                {"table-header-group", css_display_value::DISPLAY_NORMAL},
                {"table-footer-group", css_display_value::DISPLAY_NORMAL},
-               {"table-row-group", css_display_value::DISPLAY_NORMAL},
-               {"table-cell", css_display_value::DISPLAY_NORMAL},
-               {"table-column", css_display_value::DISPLAY_NORMAL},
-               {"table-row", css_display_value::DISPLAY_NORMAL},
-               {"initial", css_display_value::DISPLAY_NORMAL},
+               {"table-row-group",    css_display_value::DISPLAY_NORMAL},
+               {"table-cell",         css_display_value::DISPLAY_NORMAL},
+               {"table-column",       css_display_value::DISPLAY_NORMAL},
+               {"table-row",          css_display_value::DISPLAY_NORMAL},
+               {"initial",            css_display_value::DISPLAY_NORMAL},
 });
 
 auto css_value::maybe_display_from_string(const std::string_view &input)
-       -> std::optional<css_value>
-{
+-> std::optional<css_value> {
        auto f = display_names_map.find(input);
 
        if (f != display_names_map.end()) {
@@ -328,18 +332,17 @@ auto css_value::maybe_display_from_string(const std::string_view &input)
 }
 
 
-auto css_value::debug_str() const -> std::string
-{
+auto css_value::debug_str() const -> std::string {
        std::string ret;
 
-       std::visit([&](const autoarg) {
+       std::visit([&](const auto &arg) {
                using T = std::decay_t<decltype(arg)>;
 
                if constexpr (std::is_same_v<T, css_color>) {
                        ret += "color: r=" + std::to_string(arg.r) +
-                                       "; g=" + std::to_string(arg.g) +
-                                       "; b=" + std::to_string(arg.b) +
-                                       "; a=" + std::to_string(arg.alpha);
+                                  "; g=" + std::to_string(arg.g) +
+                                  "; b=" + std::to_string(arg.b) +
+                                  "; a=" + std::to_string(arg.alpha);
                }
                else if constexpr (std::is_same_v<T, double>) {
                        ret += "size: " + std::to_string(arg);
@@ -365,4 +368,24 @@ auto css_value::debug_str() const -> std::string
        return ret;
 }
 
+TEST_SUITE("css values") {
+       TEST_CASE("css hex colors") {
+               const std::pair<const char*, css_color> hex_tests[] = {
+                               {"000", css_color(0, 0, 0)},
+                               {"000000", css_color(0, 0, 0)},
+                               {"f00", css_color(255, 0, 0)},
+                               {"FEDCBA", css_color(254, 220, 186)},
+                               {"234", css_color(34, 51, 68)},
+               };
+
+               for (const auto &p : hex_tests) {
+                       auto col_parsed = css_value::maybe_color_from_hex(p.first);
+                       //CHECK_UNARY(col_parsed);
+                       //CHECK_UNARY(col_parsed.value().to_color());
+                       auto final_col = col_parsed.value().to_color().value();
+                       CHECK(final_col == p.second);
+               }
+       }
+};
+
 }
index 93324a57c38fa2d4fa7a82e528a248678c10f392..4c013124c549576d454f17ad33be3eeeb3fc5682 100644 (file)
@@ -23,6 +23,7 @@
 #include <variant>
 #include <optional>
 #include <vector>
+#include <iosfwd>
 #include "parse_error.hxx"
 #include "css_parser.hxx"
 #include "contrib/expected/expected.hpp"
@@ -39,6 +40,9 @@ struct alignas(int) css_color {
        css_color(std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _alpha = 255) :
                r(_r), g(_g), b(_b), alpha(_alpha) {}
        css_color() = default;
+       friend bool operator==(const css_color& l, const css_color& r) {
+               return (memcmp(&l, &r, sizeof(css_color)) == 0);
+       }
 };
 
 struct css_dimension {
@@ -137,4 +141,5 @@ struct css_value {
 
 }
 
+
 #endif //RSPAMD_CSS_VALUE_HXX
index 0d85b08de96ff07a1a6f20fb1855037733e26469..934b141c7f1fd04351e20d95e97a5ee3c9731e7c 100644 (file)
@@ -21,6 +21,16 @@ IF(USE_CXX_LINKER)
 ENDIF()
 TARGET_LINK_LIBRARIES(rspamd-test rspamd-server)
 
+SET(CXXTESTSSRC                rspamd_cxx_unit.cxx)
+
+ADD_EXECUTABLE(rspamd-test-cxx EXCLUDE_FROM_ALL ${CXXTESTSSRC})
+SET_TARGET_PROPERTIES(rspamd-test-cxx PROPERTIES LINKER_LANGUAGE CXX)
+ADD_DEPENDENCIES(rspamd-test-cxx rspamd-server)
+ADD_DEPENDENCIES(rspamd-test-cxx doctest)
+TARGET_LINK_LIBRARIES(rspamd-test-cxx PRIVATE rspamd-server)
+TARGET_LINK_LIBRARIES(rspamd-test-cxx PRIVATE doctest)
+SET_TARGET_PROPERTIES(rspamd-test-cxx PROPERTIES LINKER_LANGUAGE CXX)
+
 IF(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
        # Also add dependencies for convenience
        FILE(GLOB_RECURSE LUA_TESTS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/lua/*.*")
diff --git a/test/rspamd_cxx_unit.cxx b/test/rspamd_cxx_unit.cxx
new file mode 100644 (file)
index 0000000..eb456d2
--- /dev/null
@@ -0,0 +1,32 @@
+/*-
+ * Copyright 2021 Vsevolod Stakhov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#include "doctest/doctest.h"
+
+int
+main(int argc, char** argv)
+{
+       doctest::Context context(argc, argv);
+       int res = context.run();
+
+       if(context.shouldExit()) {
+               return res;
+       }
+
+       return res;
+}
\ No newline at end of file