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