From 1b48d9a5d2ef72e951707af3d18665606dd51e48 Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Sat, 25 Nov 2023 11:31:40 +0100 Subject: [PATCH 1/4] Migrate basicauth test to Catch2 --- src/Makefile.am | 1 + test/test_basicauth.cpp | 241 +++++++++++----------------------------- 2 files changed, 65 insertions(+), 177 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7aaebf29..cbb92da3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -92,6 +92,7 @@ ___test_test_core_SOURCES=\ ___test_test_parse_id_list_SOURCES=\ ../test/test_parse_id_list.cpp +___test_test_basicauth_CPPFLAGS=$(AM_CPPFLAGS) $(CATCH2_CPPFLAGS) ___test_test_basicauth_SOURCES=\ ../test/test_basicauth.cpp \ ../test/test_request.cpp diff --git a/test/test_basicauth.cpp b/test/test_basicauth.cpp index 6148d956..c93ebf77 100644 --- a/test/test_basicauth.cpp +++ b/test/test_basicauth.cpp @@ -1,15 +1,8 @@ -#include -#include -#include -#include -#include -#include #include -#include -#include - -#include +#include +#include +#include #include "cgimap/basicauth.hpp" #include "cgimap/options.hpp" @@ -17,23 +10,9 @@ #include "cgimap/backend/apidb/transaction_manager.hpp" -template -std::ostream& operator<<(std::ostream& os, std::optional const& opt) -{ - return opt ? os << opt.value() : os; -} - +#define CATCH_CONFIG_MAIN +#include -#define ANNOTATE_EXCEPTION(stmt) \ - { \ - try { \ - stmt; \ - } catch (const std::exception &e) { \ - std::ostringstream ostr; \ - ostr << e.what() << ", during " #stmt ; \ - throw std::runtime_error(ostr.str()); \ - } \ - } Transaction_Owner_Void::Transaction_Owner_Void() {} @@ -45,28 +24,8 @@ std::set& Transaction_Owner_Void::get_prep_stmt() { throw std::runtime_error ("get_prep_stmt is not supported by Transaction_Owner_Void"); } - namespace { -template -void assert_equal(const T &actual, const T &expected) { - if (!(actual == expected)) { - std::ostringstream ostr; - ostr << "Expected `" << expected << "', but got `" << actual << "'"; - throw std::runtime_error(ostr.str()); - } -} - -template -void assert_equal(const T &actual, const T &expected, const std::string& scope) { - if (!(actual == expected)) { - std::ostringstream ostr; - ostr << scope << ": Expected `" << expected << "', but got `" << actual << "'"; - throw std::runtime_error(ostr.str()); - } -} - - class basicauth_test_data_selection : public data_selection { public: @@ -156,214 +115,142 @@ class global_settings_test_no_basic_auth : public global_settings_default { } // anonymous namespace +TEST_CASE("test_md5_without_salt", "[basicauth]") { + CHECK(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "","password") == true); + CHECK(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "", "wrong") == false); +} +TEST_CASE("test_md5_with_salt", "[basicauth]") { + CHECK(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt", "password") == true); + CHECK(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt", "wrong") == false); + CHECK(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "wrong","password") == false); +} -void test_password_hash() { - - // test_md5_without_salt - assert_equal(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "", - "password"), true); - - assert_equal(PasswordHash::check("5f4dcc3b5aa765d61d8327deb882cf99", "", "wrong"), false); - - // test_md5_with_salt - assert_equal(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt", - "password"), true); - assert_equal(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "salt", - "wrong"), false); - assert_equal(PasswordHash::check("67a1e09bb1f83f5007dc119c14d663aa", "wrong", - "password"), false); - - // test_pbkdf2_1000_32_sha512 - assert_equal(PasswordHash::check( +TEST_CASE("test_pbkdf2_1000_32_sha512", "[basicauth]") { + CHECK(PasswordHash::check( "ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=", "sha512!1000!HR4z+hAvKV2ra1gpbRybtoNzm/CNKe4cf7bPKwdUNrk=", - "password"), true); + "password") == true); - assert_equal(PasswordHash::check( + CHECK(PasswordHash::check( "ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=", "sha512!1000!HR4z+hAvKV2ra1gpbRybtoNzm/CNKe4cf7bPKwdUNrk=", - "wrong"), false); + "wrong") == false); - assert_equal(PasswordHash::check( + CHECK(PasswordHash::check( "ApT/28+FsTBLa/J8paWfgU84SoRiTfeY8HjKWhgHy08=", "sha512!1000!HR4z+hAvKV2ra1gwrongtoNzm/CNKe4cf7bPKwdUNrk=", - "password"), false); + "password") == false); +} + - // test_pbkdf2_10000_32_sha512 - assert_equal(PasswordHash::check( +TEST_CASE("test_pbkdf2_10000_32_sha512", "[basicauth]") { + + CHECK(PasswordHash::check( "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=", "sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=", - "password"), true); + "password") == true); - assert_equal(PasswordHash::check( + CHECK(PasswordHash::check( "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=", "sha512!10000!OUQLgtM7eD8huvanFT5/WtWaCwdOdrir8QOtFwxhO0A=", - "wrong"), false); + "wrong") == false); - assert_equal(PasswordHash::check( + CHECK(PasswordHash::check( "3wYbPiOxk/tU0eeIDjUhdvi8aDP3AbFtwYKKxF1IhGg=", "sha512!10000!OUQLgtMwronguvanFT5/WtWaCwdOdrir8QOtFwxhO0A=", - "password"), false); + "password") == false); +} + +TEST_CASE("test argon2", "[basicauth]") { - // test argon2 - assert_equal(PasswordHash::check( + CHECK(PasswordHash::check( "$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg", "", - "password"), true); + "password") == true); - assert_equal(PasswordHash::check( + CHECK(PasswordHash::check( "$argon2id$v=19$m=65536,t=1,p=1$KXGHWfWMf5H5kY4uU3ua8A$YroVvX6cpJpljTio62k19C6UpuIPtW7me2sxyU2dyYg", "", - "wrong"), false); + "wrong") == false); } -void test_authenticate_user() { +TEST_CASE("test_authenticate_user", "[basicauth]") { auto factory = std::make_shared(); - auto txn_readonly = factory->get_default_transaction(); auto sel = factory->make_selection(*txn_readonly); + test_request req; - { - test_request req; + SECTION("Missing Header") { auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{}, "Missing Header"); + CHECK(res == std::optional{}); } - { - test_request req; + SECTION("Empty AUTH header"){ req.set_header("HTTP_AUTHORIZATION",""); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{}, "Empty AUTH header"); + CHECK(res == std::optional{}); } - { - test_request req; + SECTION("Empty AUTH header"){ req.set_header("HTTP_AUTHORIZATION","Basic "); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{}, "Empty AUTH header"); + CHECK(res == std::optional{}); } - { - test_request req; + SECTION("User without password"){ req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbw=="); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{}, "User without password"); + CHECK(res == std::optional{}); } - { - test_request req; + SECTION("User and colon without password"){ req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzo="); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res,std::optional{}, "User and colon without password"); + CHECK(res == std::optional{}); } - { - test_request req; + SECTION("Known user with correct password"){ req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzpwYXNzd29yZA=="); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{4711}, "Known user with correct password"); + CHECK(res == std::optional{4711}); } - { - test_request req; + SECTION("Known user with correct password, argon2") { req.set_header("HTTP_AUTHORIZATION","Basic YXJnb24yOnBhc3N3b3Jk"); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{4712}, "Known user with correct password, argon2"); + CHECK(res == std::optional{4712}); } - { - test_request req; + SECTION("Crap data") { req.set_header("HTTP_AUTHORIZATION","Basic TotalCrapData=="); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{}, "Crap data"); + CHECK(res == std::optional{}); } - // Test with known user and incorrect password - { - test_request req; + SECTION("Test with known user and incorrect password") { req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzppbmNvcnJlY3Q="); - try { - static_cast(basicauth::authenticate_user(req, *sel)); - throw std::runtime_error("Known user, incorrect password: expected http unauthorized exception"); - - } catch (http::exception &e) { - if (e.code() != 401) - throw std::runtime_error( - "Known user / incorrect password: Expected HTTP 401"); - } + REQUIRE_THROWS_AS(static_cast(basicauth::authenticate_user(req, *sel)), http::unauthorized); } - // Test with known user and incorrect password, argon2 - { - test_request req; + SECTION("Test with known user and incorrect password, argon2") { req.set_header("HTTP_AUTHORIZATION","Basic YXJnb24yOndyb25n"); - try { - static_cast(basicauth::authenticate_user(req, *sel)); - throw std::runtime_error("Known user, incorrect password: expected http unauthorized exception"); - - } catch (http::exception &e) { - if (e.code() != 401) - throw std::runtime_error( - "Known user / incorrect password: Expected HTTP 401"); - } + REQUIRE_THROWS_AS(static_cast(basicauth::authenticate_user(req, *sel)), http::unauthorized); } - // Test with unknown user and incorrect password - { - test_request req; + SECTION("Test with unknown user and incorrect password") { req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzI6aW5jb3JyZWN0"); - try { - static_cast(basicauth::authenticate_user(req, *sel)); - throw std::runtime_error("Unknown user / incorrect password: expected http unauthorized exception"); - - } catch (http::exception &e) { - if (e.code() != 401) - throw std::runtime_error( - "Unknown user / incorrect password: Expected HTTP 401"); - } + REQUIRE_THROWS_AS(static_cast(basicauth::authenticate_user(req, *sel)), http::unauthorized); } -} - -void test_basic_auth_disabled_by_global_config() { - - auto factory = std::make_shared(); - - auto txn_readonly = factory->get_default_transaction(); - auto sel = factory->make_selection(*txn_readonly); - // Known user with correct password, but basic auth has been disabled in global config settings - { + SECTION("Known user with correct password; basicauth disabled in config") { auto test_settings = std::unique_ptr(new global_settings_test_no_basic_auth()); global_settings::set_configuration(std::move(test_settings)); - - test_request req; req.set_header("HTTP_AUTHORIZATION","Basic ZGVtbzpwYXNzd29yZA=="); auto res = basicauth::authenticate_user(req, *sel); - assert_equal >(res, std::optional{}, "Known user with correct password, but basic auth disabled in global config"); - } -} - - -int main() { - try { - ANNOTATE_EXCEPTION(test_password_hash()); - ANNOTATE_EXCEPTION(test_authenticate_user()); - ANNOTATE_EXCEPTION(test_basic_auth_disabled_by_global_config()); - - } catch (const std::exception &e) { - std::cerr << "EXCEPTION: " << e.what() << std::endl; - return 1; - - } catch (...) { - std::cerr << "UNKNOWN EXCEPTION" << std::endl; - return 1; + CHECK(res == std::optional{}); } - - return 0; } - - From c10c678f50cc067165db0c9243a1bf8e5c7105b8 Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Sat, 25 Nov 2023 12:16:14 +0100 Subject: [PATCH 2/4] Migrate oauth2 to Catch2 --- src/Makefile.am | 1 + test/test_oauth2.cpp | 175 +++++++++---------------------------------- 2 files changed, 38 insertions(+), 138 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index cbb92da3..8de533cc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -100,6 +100,7 @@ ___test_test_basicauth_SOURCES=\ ___test_test_oauth_SOURCES=\ ../test/test_oauth.cpp +___test_test_oauth2_CPPFLAGS=$(AM_CPPFLAGS) $(CATCH2_CPPFLAGS) ___test_test_oauth2_SOURCES=\ ../test/test_oauth2.cpp \ ../test/test_request.cpp diff --git a/test/test_oauth2.cpp b/test/test_oauth2.cpp index 2224f510..94b32c90 100644 --- a/test/test_oauth2.cpp +++ b/test/test_oauth2.cpp @@ -1,47 +1,15 @@ -#include "cgimap/oauth2.hpp" #include -#include -#include #include -#include -#include -#include - -#include - - -#include -#include #include - -#include - -#include -#include - #include "cgimap/oauth2.hpp" #include "test_request.hpp" - #include "cgimap/backend/apidb/transaction_manager.hpp" -template -std::ostream& operator<<(std::ostream& os, std::optional const& opt) -{ - return opt ? os << opt.value() : os; -} +#define CATCH_CONFIG_MAIN +#include -#define ANNOTATE_EXCEPTION(stmt) \ - { \ - try { \ - stmt; \ - } catch (const std::exception &e) { \ - std::ostringstream ostr; \ - ostr << e.what() << ", during " #stmt ; \ - throw std::runtime_error(ostr.str()); \ - } \ - } Transaction_Owner_Void::Transaction_Owner_Void() {} @@ -53,22 +21,8 @@ std::set& Transaction_Owner_Void::get_prep_stmt() { throw std::runtime_error ("get_prep_stmt is not supported by Transaction_Owner_Void"); } - namespace { - -template -void assert_equal(const T &actual, const T &expected, const std::string& scope = "") { - if (!(actual == expected)) { - std::ostringstream ostr; - if (!scope.empty()) - ostr << scope << ":"; - ostr << "Expected `" << expected << "', but got `" << actual << "'"; - throw std::runtime_error(ostr.str()); - } -} - - struct test_oauth2 : public oauth::store { @@ -154,125 +108,70 @@ struct test_oauth2 } // anonymous namespace +TEST_CASE("test_validate_bearer_token", "[oauth2]") { -void test_validate_bearer_token() { - + bool allow_api_write; + test_request req; auto store = std::make_shared(); - { - bool allow_api_write; - test_request req; + SECTION("Missing Header") { auto res = oauth2::validate_bearer_token(req, store.get(), allow_api_write); - assert_equal >(res, {}, "Missing Header"); + CHECK(res == std::optional{}); } - { - bool allow_api_write; - test_request req; + SECTION("Missing Header") { req.set_header("HTTP_AUTHORIZATION",""); auto res = oauth2::validate_bearer_token(req, store.get(), allow_api_write); - assert_equal >(res, {}, "Empty AUTH header"); + CHECK(res == std::optional{}); } - // Test valid bearer token, no api_write - { - bool allow_api_write; - test_request req; + // + SECTION("Test valid bearer token, no api_write") { req.set_header("HTTP_AUTHORIZATION","Bearer 6GGXRGoDog0i6mRyrBonFmJORQhWZMhZH5WNWLd0qcs"); auto res = oauth2::validate_bearer_token(req, store.get(), allow_api_write); - assert_equal >(res, std::optional{1}, "Bearer token for user 1"); - assert_equal(allow_api_write, false, "Bearer token for user 1, allow_api_write"); + CHECK(res == std::optional{1}); + CHECK(!allow_api_write); } - // Test valid token including all allowed chars & padding chars - api_write allowed - { - bool allow_api_write; - test_request req; + // + SECTION("Test valid token including all allowed chars & padding chars - api_write allowed") { req.set_header("HTTP_AUTHORIZATION","Bearer H4TeKX-zE_VLH.UT33_n6x__yZ8~BA~aQL+wfxQN/cADu7BMMA====="); auto res = oauth2::validate_bearer_token(req, store.get(), allow_api_write); - assert_equal >(res, std::optional{2}, "Bearer token for user 2"); - assert_equal(allow_api_write, true, "Bearer token for user 2, allow_api_write"); + CHECK(res == std::optional{2}); + CHECK(allow_api_write); } - - // Test bearer token invalid format - { - bool allow_api_write; - test_request req; + SECTION("Test bearer token invalid format") { req.set_header("HTTP_AUTHORIZATION","Bearer 6!#c23.-;<<>>"); auto res = oauth2::validate_bearer_token(req, store.get(), allow_api_write); - assert_equal >(res, {}, "Invalid bearer format"); + CHECK(res == std::optional{}); } - // Test invalid bearer token - { - bool allow_api_write; - test_request req; - try { - req.set_header("HTTP_AUTHORIZATION","Bearer nFRBLFyNXPKY1fiTHAIfVsjQYkCD2KoRuH66upvueaQ"); - static_cast(oauth2::validate_bearer_token(req, store.get(), allow_api_write)); - throw std::runtime_error("test_authenticate_user::001: Expected exception"); - } catch (http::unauthorized &e) { - if (std::string(e.what()) != "invalid_token") { - throw std::runtime_error("test_authenticate_user::001: Expected invalid_token"); - } - } + SECTION("Test invalid bearer token") { + + req.set_header("HTTP_AUTHORIZATION","Bearer nFRBLFyNXPKY1fiTHAIfVsjQYkCD2KoRuH66upvueaQ"); + REQUIRE_THROWS_MATCHES(static_cast(oauth2::validate_bearer_token(req, store.get(), allow_api_write)), http::unauthorized, + Catch::Message("invalid_token")); } - // Test expired bearer token - { - bool allow_api_write; - test_request req; - try { - req.set_header("HTTP_AUTHORIZATION","Bearer pwnMeCjSmIfQ9hXVYfAyFLFnE9VOADNvwGMKv4Ylaf0"); - static_cast(oauth2::validate_bearer_token(req, store.get(), allow_api_write)); - throw std::runtime_error("test_authenticate_user::002: Expected exception"); - } catch (http::unauthorized &e) { - if (std::string(e.what()) != "token_expired") { - throw std::runtime_error("test_authenticate_user::002: Expected token_expired"); - } - } + SECTION("Test expired bearer token") { + req.set_header("HTTP_AUTHORIZATION","Bearer pwnMeCjSmIfQ9hXVYfAyFLFnE9VOADNvwGMKv4Ylaf0"); + REQUIRE_THROWS_MATCHES(static_cast(oauth2::validate_bearer_token(req, store.get(), allow_api_write)), + http::unauthorized, + Catch::Message("token_expired")); } - // Test revoked bearer token - { - bool allow_api_write; - test_request req; - try { - req.set_header("HTTP_AUTHORIZATION","Bearer hCXrz5B5fCBHusp0EuD2IGwYSxS8bkAnVw2_aLEdxig"); - static_cast(oauth2::validate_bearer_token(req, store.get(), allow_api_write)); - throw std::runtime_error("test_authenticate_user::003: Expected exception"); - } catch (http::unauthorized &e) { - if (std::string(e.what()) != "token_revoked") { - throw std::runtime_error("test_authenticate_user::003: Expected token_revoked"); - } - } + SECTION("Test revoked bearer token") { + req.set_header("HTTP_AUTHORIZATION","Bearer hCXrz5B5fCBHusp0EuD2IGwYSxS8bkAnVw2_aLEdxig"); + REQUIRE_THROWS_MATCHES(static_cast(oauth2::validate_bearer_token(req, store.get(), allow_api_write)), + http::unauthorized, + Catch::Message("token_revoked")); } - // Test valid bearer token, no api_write - { - bool allow_api_write; - test_request req; + SECTION("Test valid bearer token, no api_write") { req.set_header("HTTP_AUTHORIZATION","Bearer 0LbSEAVj4jQhr-TfNaCUhn4JSAvXmXepNaL9aSAUsVQ"); auto res = oauth2::validate_bearer_token(req, store.get(), allow_api_write); - assert_equal >(res, std::optional{5}, "Bearer token for user 5"); - assert_equal(allow_api_write, false, "Bearer token for user 5, allow_api_write"); + CHECK(res == std::optional{5}); + CHECK(!allow_api_write); } } - - -int main() { - try { - ANNOTATE_EXCEPTION(test_validate_bearer_token()); - } catch (const std::exception &e) { - std::cerr << "EXCEPTION: " << e.what() << std::endl; - return 1; - - } catch (...) { - std::cerr << "UNKNOWN EXCEPTION" << std::endl; - return 1; - } - - return 0; -} - From 357fc918fefae353dc446e0dcaabf9b7379ea26b Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Sat, 25 Nov 2023 12:26:13 +0100 Subject: [PATCH 3/4] Migrate http to Catch2 --- src/Makefile.am | 1 + test/test_http.cpp | 134 +++++++++++++++------------------------------ 2 files changed, 44 insertions(+), 91 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 8de533cc..0109183c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -105,6 +105,7 @@ ___test_test_oauth2_SOURCES=\ ../test/test_oauth2.cpp \ ../test/test_request.cpp +___test_test_http_CPPFLAGS=$(AM_CPPFLAGS) $(CATCH2_CPPFLAGS) ___test_test_http_SOURCES=\ ../test/test_http.cpp diff --git a/test/test_http.cpp b/test/test_http.cpp index c9a55ebf..e9721b7c 100644 --- a/test/test_http.cpp +++ b/test/test_http.cpp @@ -4,117 +4,69 @@ #include #include -namespace { +#define CATCH_CONFIG_MAIN +#include -template -std::ostream& operator<<(std::ostream& os, std::optional const& opt) -{ - return opt ? os << opt.value() : os; -} - -void assert_eq(const std::string &actual, const std::string &expected) { - if (actual != expected) { - std::ostringstream ostr; - ostr << "Test failed: Expecting \"" << expected << "\", but got \"" << actual << "\"."; - throw std::runtime_error(ostr.str()); - } -} -template -void assert_equal(const T &actual, const T &expected) { - if (actual != expected) { - std::ostringstream ostr; - ostr << "Expected `" << expected << "', but got `" << actual << "'"; - throw std::runtime_error(ostr.str()); - } -} - -void http_check_urlencoding() { +TEST_CASE("http_check_urlencoding", "[http]") { // RFC 3986 section 2.5 - assert_eq(http::urlencode("ア"), "%E3%82%A2"); - assert_eq(http::urlencode("À"), "%C3%80"); + CHECK(http::urlencode("ア") == "%E3%82%A2"); + CHECK(http::urlencode("À") == "%C3%80"); // RFC 3986 - unreserved characters not encoded - assert_eq(http::urlencode("abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz"); - assert_eq(http::urlencode("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - assert_eq(http::urlencode("0123456789"), "0123456789"); - assert_eq(http::urlencode("-._~"), "-._~"); + CHECK(http::urlencode("abcdefghijklmnopqrstuvwxyz") == "abcdefghijklmnopqrstuvwxyz"); + CHECK(http::urlencode("ABCDEFGHIJKLMNOPQRSTUVWXYZ") == "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + CHECK(http::urlencode("0123456789") == "0123456789"); + CHECK(http::urlencode("-._~") == "-._~"); // RFC 3986 - % must be encoded - assert_eq(http::urlencode("%"), "%25"); + CHECK(http::urlencode("%") == "%25"); } -void http_check_urldecoding() { - assert_eq(http::urldecode("%E3%82%A2"), "ア"); - assert_eq(http::urldecode("%C3%80"), "À"); +TEST_CASE("http_check_urldecoding", "[http]") { + CHECK(http::urldecode("%E3%82%A2") == "ア"); + CHECK(http::urldecode("%C3%80") == "À"); // RFC 3986 - uppercase A-F are equivalent to lowercase a-f - assert_eq(http::urldecode("%e3%82%a2"), "ア"); - assert_eq(http::urldecode("%c3%80"), "À"); + CHECK(http::urldecode("%e3%82%a2") == "ア"); + CHECK(http::urldecode("%c3%80") == "À"); } -void http_check_parse_params() { +TEST_CASE("http_check_parse_params", "[http]") { using params_t = std::vector >; params_t params = http::parse_params("a2=r%20b&a3=2%20q&a3=a&b5=%3D%253D&c%40=&c2="); - assert_equal(params.size(), 6); - assert_eq(params[0].first, "a2"); assert_eq(params[0].second, "r%20b"); - assert_eq(params[1].first, "a3"); assert_eq(params[1].second, "2%20q"); - assert_eq(params[2].first, "a3"); assert_eq(params[2].second, "a"); - assert_eq(params[3].first, "b5"); assert_eq(params[3].second, "%3D%253D"); - assert_eq(params[4].first, "c%40"); assert_eq(params[4].second, ""); - assert_eq(params[5].first, "c2"); assert_eq(params[5].second, ""); -} - -void http_check_list_methods() { - assert_eq(http::list_methods(http::method::GET), "GET"); - assert_eq(http::list_methods(http::method::POST), "POST"); - assert_eq(http::list_methods(http::method::HEAD), "HEAD"); - assert_eq(http::list_methods(http::method::OPTIONS), "OPTIONS"); - assert_eq( - http::list_methods(http::method::GET | http::method::OPTIONS), - "GET, OPTIONS"); + CHECK(params.size() == 6); + CHECK(params[0].first == "a2"); CHECK(params[0].second == "r%20b"); + CHECK(params[1].first == "a3"); CHECK(params[1].second == "2%20q"); + CHECK(params[2].first == "a3"); CHECK(params[2].second == "a"); + CHECK(params[3].first == "b5"); CHECK(params[3].second == "%3D%253D"); + CHECK(params[4].first == "c%40"); CHECK(params[4].second == ""); + CHECK(params[5].first == "c2"); CHECK(params[5].second == ""); } -void http_check_parse_methods() { - auto assert_eql = assert_equal>; - assert_eql(http::parse_method("GET"), http::method::GET); - assert_eql(http::parse_method("POST"), http::method::POST); - assert_eql(http::parse_method("HEAD"), http::method::HEAD); - assert_eql(http::parse_method("OPTIONS"), http::method::OPTIONS); - assert_eql(http::parse_method(""), {}); +TEST_CASE("http_check_list_methods", "[http]") { + CHECK(http::list_methods(http::method::GET) == "GET"); + CHECK(http::list_methods(http::method::POST) == "POST"); + CHECK(http::list_methods(http::method::HEAD) == "HEAD"); + CHECK(http::list_methods(http::method::OPTIONS) == "OPTIONS"); + CHECK(http::list_methods(http::method::GET | http::method::OPTIONS) == "GET, OPTIONS"); } -void http_check_choose_encoding() { - - assert_eq(http::choose_encoding("deflate, gzip;q=1.0, *;q=0.5")->name(), "gzip"); - assert_eq(http::choose_encoding("gzip;q=1.0, identity;q=0.8, *;q=0.1")->name(), "gzip"); - assert_eq(http::choose_encoding("identity;q=0.8, gzip;q=1.0, *;q=0.1")->name(), "gzip"); - assert_eq(http::choose_encoding("gzip")->name(), "gzip"); - assert_eq(http::choose_encoding("identity")->name(), "identity"); - assert_eq(http::choose_encoding("*")->name(), "identity"); - assert_eq(http::choose_encoding("deflate")->name(), "identity"); +TEST_CASE("http_check_parse_methods", "[http]") { + CHECK(http::parse_method("GET") == http::method::GET); + CHECK(http::parse_method("POST") == http::method::POST); + CHECK(http::parse_method("HEAD") == http::method::HEAD); + CHECK(http::parse_method("OPTIONS") == http::method::OPTIONS); + CHECK(http::parse_method("") == std::optional{}); } -} // anonymous namespace - -int main() { - try { - http_check_urlencoding(); - http_check_urldecoding(); - http_check_parse_params(); - http_check_list_methods(); - http_check_parse_methods(); - http_check_choose_encoding(); - - } catch (const std::exception &e) { - std::cerr << "EXCEPTION: " << e.what() << std::endl; - return 1; - - } catch (...) { - std::cerr << "UNKNOWN EXCEPTION" << std::endl; - return 1; - } - - return 0; +TEST_CASE("http_check_choose_encoding", "[http]") { + CHECK(http::choose_encoding("deflate, gzip;q=1.0, *;q=0.5")->name() == "gzip"); + CHECK(http::choose_encoding("gzip;q=1.0, identity;q=0.8, *;q=0.1")->name() == "gzip"); + CHECK(http::choose_encoding("identity;q=0.8, gzip;q=1.0, *;q=0.1")->name() == "gzip"); + CHECK(http::choose_encoding("gzip")->name() == "gzip"); + CHECK(http::choose_encoding("identity")->name() == "identity"); + CHECK(http::choose_encoding("*")->name() == "identity"); + CHECK(http::choose_encoding("deflate")->name() == "identity"); } From a99d5e1cb796b9ab7e0f198db34bc48d03efb6b5 Mon Sep 17 00:00:00 2001 From: mmd-osm Date: Sat, 25 Nov 2023 12:30:55 +0100 Subject: [PATCH 4/4] No Catch2 migration for OAuth1.0a --- test/test_oauth.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/test_oauth.cpp b/test/test_oauth.cpp index 81b2d793..e1c04bdd 100644 --- a/test/test_oauth.cpp +++ b/test/test_oauth.cpp @@ -12,6 +12,17 @@ #include +/*********************************************************************************** + * + * + * NOTE: OAuth1.0a is scheduled to be removed in 0.9 - no catch2 migration needed + * + * + * + ***********************************************************************************/ + + + template std::ostream& operator<<(std::ostream& os, std::optional const& opt) {