xref: /openbmc/bmcweb/test/http/router_test.cpp (revision f2caadce)
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         [&notFoundCalled](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