#include "async_resp.hpp" // IWYU pragma: keep #include "http_request.hpp" #include "routing.hpp" #include "utility.hpp" #include // IWYU pragma: keep #include #include #include #include #include #include // IWYU pragma: keep // IWYU pragma: no_include // IWYU pragma: no_include "gtest/gtest_pred_impl.h" // IWYU pragma: no_include // IWYU pragma: no_include // IWYU pragma: no_include // IWYU pragma: no_forward_declare bmcweb::AsyncResp namespace crow { namespace { using ::crow::utility::getParameterTag; TEST(Router, AllowHeader) { // Callback handler that does nothing auto nullCallback = [](const Request&, const std::shared_ptr&) {}; Router router; std::error_code ec; constexpr std::string_view url = "/foo"; Request req{{boost::beast::http::verb::get, url, 11}, ec}; // No route should return no methods. router.validate(); EXPECT_EQ(router.findRoute(req).allowHeader, ""); EXPECT_EQ(router.findRoute(req).route.rule, nullptr); router.newRuleTagged(std::string(url)) .methods(boost::beast::http::verb::get)(nullCallback); router.validate(); EXPECT_EQ(router.findRoute(req).allowHeader, "GET"); EXPECT_NE(router.findRoute(req).route.rule, nullptr); Request patchReq{{boost::beast::http::verb::patch, url, 11}, ec}; EXPECT_EQ(router.findRoute(patchReq).route.rule, nullptr); router.newRuleTagged(std::string(url)) .methods(boost::beast::http::verb::patch)(nullCallback); router.validate(); EXPECT_EQ(router.findRoute(req).allowHeader, "GET, PATCH"); EXPECT_NE(router.findRoute(req).route.rule, nullptr); EXPECT_NE(router.findRoute(patchReq).route.rule, nullptr); } TEST(Router, OverlapingRoutes) { // Callback handler that does nothing auto fooCallback = [](const Request&, const std::shared_ptr&) { EXPECT_FALSE(true); }; bool barCalled = false; auto foobarCallback = [&barCalled](const Request&, const std::shared_ptr&, const std::string& bar) { barCalled = true; EXPECT_EQ(bar, "bar"); }; Router router; std::error_code ec; router.newRuleTagged")>("/foo/")( foobarCallback); router.newRuleTagged("/foo")(fooCallback); router.validate(); { constexpr std::string_view url = "/foo/bar"; auto req = std::make_shared( Request::Body{boost::beast::http::verb::get, url, 11}, ec); std::shared_ptr asyncResp = std::make_shared(); router.handle(req, asyncResp); } EXPECT_TRUE(barCalled); } TEST(Router, 404) { bool notFoundCalled = false; // Callback handler that does nothing auto nullCallback = [¬FoundCalled](const Request&, const std::shared_ptr&) { notFoundCalled = true; }; Router router; std::error_code ec; constexpr std::string_view url = "/foo/bar"; auto req = std::make_shared( Request::Body{boost::beast::http::verb::get, url, 11}, ec); router.newRuleTagged("/foo/") .notFound()(nullCallback); router.validate(); { std::shared_ptr asyncResp = std::make_shared(); router.handle(req, asyncResp); } EXPECT_TRUE(notFoundCalled); } TEST(Router, 405) { // Callback handler that does nothing auto nullCallback = [](const Request&, const std::shared_ptr&) {}; bool called = false; auto notAllowedCallback = [&called](const Request&, const std::shared_ptr&) { called = true; }; Router router; std::error_code ec; constexpr std::string_view url = "/foo/bar"; auto req = std::make_shared( Request::Body{boost::beast::http::verb::patch, url, 11}, ec); router.newRuleTagged(std::string(url)) .methods(boost::beast::http::verb::get)(nullCallback); router.newRuleTagged("/foo/") .methodNotAllowed()(notAllowedCallback); router.validate(); { std::shared_ptr asyncResp = std::make_shared(); router.handle(req, asyncResp); } EXPECT_TRUE(called); } } // namespace } // namespace crow