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