1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #include "async_resp.hpp" 4 #include "http_request.hpp" 5 #include "routing.hpp" 6 #include "utility.hpp" 7 8 #include <boost/beast/http/verb.hpp> 9 10 #include <memory> 11 #include <string> 12 #include <string_view> 13 #include <system_error> 14 15 #include <gtest/gtest.h> 16 17 // IWYU pragma: no_forward_declare bmcweb::AsyncResp 18 19 namespace crow 20 { 21 namespace 22 { 23 24 using ::crow::utility::getParameterTag; 25 TEST(Router,AllowHeader)26 TEST(Router, AllowHeader) 27 { 28 // Callback handler that does nothing 29 auto nullCallback = 30 [](const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) {}; 31 32 Router router; 33 std::error_code ec; 34 35 constexpr std::string_view url = "/foo"; 36 37 Request req{{boost::beast::http::verb::get, url, 11}, ec}; 38 39 // No route should return no methods. 40 router.validate(); 41 EXPECT_EQ(router.findRoute(req).allowHeader, ""); 42 EXPECT_EQ(router.findRoute(req).route.rule, nullptr); 43 44 router.newRuleTagged<getParameterTag(url)>(std::string(url)) 45 .methods(boost::beast::http::verb::get)(nullCallback); 46 router.validate(); 47 EXPECT_EQ(router.findRoute(req).allowHeader, "GET"); 48 EXPECT_NE(router.findRoute(req).route.rule, nullptr); 49 50 Request patchReq{{boost::beast::http::verb::patch, url, 11}, ec}; 51 EXPECT_EQ(router.findRoute(patchReq).route.rule, nullptr); 52 53 router.newRuleTagged<getParameterTag(url)>(std::string(url)) 54 .methods(boost::beast::http::verb::patch)(nullCallback); 55 router.validate(); 56 EXPECT_EQ(router.findRoute(req).allowHeader, "GET, PATCH"); 57 EXPECT_NE(router.findRoute(req).route.rule, nullptr); 58 EXPECT_NE(router.findRoute(patchReq).route.rule, nullptr); 59 } 60 TEST(Router,OverlapingRoutes)61 TEST(Router, OverlapingRoutes) 62 { 63 // Callback handler that does nothing 64 auto fooCallback = 65 [](const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) { 66 EXPECT_FALSE(true); 67 }; 68 bool barCalled = false; 69 auto foobarCallback = 70 [&barCalled](const Request&, const std::shared_ptr<bmcweb::AsyncResp>&, 71 const std::string& bar) { 72 barCalled = true; 73 EXPECT_EQ(bar, "bar"); 74 }; 75 76 Router router; 77 std::error_code ec; 78 79 router.newRuleTagged<getParameterTag("/foo/<str>")>("/foo/<str>")( 80 foobarCallback); 81 router.newRuleTagged<getParameterTag("/foo")>("/foo")(fooCallback); 82 router.validate(); 83 { 84 constexpr std::string_view url = "/foo/bar"; 85 86 auto req = std::make_shared<Request>( 87 Request::Body{boost::beast::http::verb::get, url, 11}, ec); 88 89 std::shared_ptr<bmcweb::AsyncResp> asyncResp = 90 std::make_shared<bmcweb::AsyncResp>(); 91 92 router.handle(req, asyncResp); 93 } 94 EXPECT_TRUE(barCalled); 95 } 96 97 TEST(Router, 404) 98 { 99 bool notFoundCalled = false; 100 // Callback handler that does nothing 101 auto nullCallback = 102 [¬FoundCalled](const Request&, __anone77675800502(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) 103 const std::shared_ptr<bmcweb::AsyncResp>&) { 104 notFoundCalled = true; 105 }; 106 107 Router router; 108 std::error_code ec; 109 110 constexpr std::string_view url = "/foo/bar"; 111 112 auto req = std::make_shared<Request>( 113 Request::Body{boost::beast::http::verb::get, url, 11}, ec); 114 115 router.newRuleTagged<getParameterTag(url)>("/foo/<path>") 116 .notFound()(nullCallback); 117 router.validate(); 118 { 119 std::shared_ptr<bmcweb::AsyncResp> asyncResp = 120 std::make_shared<bmcweb::AsyncResp>(); 121 122 router.handle(req, asyncResp); 123 } 124 EXPECT_TRUE(notFoundCalled); 125 } 126 127 TEST(Router, 405) 128 { 129 // Callback handler that does nothing 130 auto nullCallback = __anone77675800602(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) 131 [](const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) {}; 132 bool called = false; 133 auto notAllowedCallback = __anone77675800702(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) 134 [&called](const Request&, const std::shared_ptr<bmcweb::AsyncResp>&) { 135 called = true; 136 }; 137 138 Router router; 139 std::error_code ec; 140 141 constexpr std::string_view url = "/foo/bar"; 142 143 auto req = std::make_shared<Request>( 144 Request::Body{boost::beast::http::verb::patch, url, 11}, ec); 145 146 router.newRuleTagged<getParameterTag(url)>(std::string(url)) 147 .methods(boost::beast::http::verb::get)(nullCallback); 148 router.newRuleTagged<getParameterTag(url)>("/foo/<path>") 149 .methodNotAllowed()(notAllowedCallback); 150 router.validate(); 151 { 152 std::shared_ptr<bmcweb::AsyncResp> asyncResp = 153 std::make_shared<bmcweb::AsyncResp>(); 154 155 router.handle(req, asyncResp); 156 } 157 EXPECT_TRUE(called); 158 } 159 } // namespace 160 } // namespace crow 161