test.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include <gtest/gtest.h>
  2. #include <httplib.h>
  3. #include <future>
  4. #include <iostream>
  5. #define SERVER_CERT_FILE "./cert.pem"
  6. #define SERVER_PRIVATE_KEY_FILE "./key.pem"
  7. #ifdef _WIN32
  8. #include <process.h>
  9. #define msleep(n) ::Sleep(n)
  10. #else
  11. #define msleep(n) ::usleep(n * 1000)
  12. #endif
  13. using namespace std;
  14. using namespace httplib;
  15. const char* HOST = "localhost";
  16. const int PORT = 1234;
  17. #ifdef _WIN32
  18. TEST(StartupTest, WSAStartup)
  19. {
  20. WSADATA wsaData;
  21. int ret = WSAStartup(0x0002, &wsaData);
  22. ASSERT_EQ(0, ret);
  23. }
  24. #endif
  25. TEST(SplitTest, ParseQueryString)
  26. {
  27. string s = "key1=val1&key2=val2&key3=val3";
  28. map<string, string> dic;
  29. detail::split(s.c_str(), s.c_str() + s.size(), '&', [&](const char* b, const char* e) {
  30. string key, val;
  31. detail::split(b, e, '=', [&](const char* b, const char* e) {
  32. if (key.empty()) {
  33. key.assign(b, e);
  34. } else {
  35. val.assign(b, e);
  36. }
  37. });
  38. dic[key] = val;
  39. });
  40. EXPECT_EQ("val1", dic["key1"]);
  41. EXPECT_EQ("val2", dic["key2"]);
  42. EXPECT_EQ("val3", dic["key3"]);
  43. }
  44. TEST(ParseQueryTest, ParseQueryString)
  45. {
  46. string s = "key1=val1&key2=val2&key3=val3";
  47. map<string, string> dic;
  48. detail::parse_query_text(s, dic);
  49. EXPECT_EQ("val1", dic["key1"]);
  50. EXPECT_EQ("val2", dic["key2"]);
  51. EXPECT_EQ("val3", dic["key3"]);
  52. }
  53. TEST(SocketTest, OpenClose)
  54. {
  55. socket_t sock = detail::create_server_socket(HOST, PORT);
  56. ASSERT_NE(-1, sock);
  57. auto ret = detail::close_socket(sock);
  58. EXPECT_EQ(0, ret);
  59. }
  60. TEST(GetHeaderValueTest, DefaultValue)
  61. {
  62. MultiMap map = {{"Dummy","Dummy"}};
  63. auto val = detail::get_header_value(map, "Content-Type", "text/plain");
  64. ASSERT_STREQ("text/plain", val);
  65. }
  66. TEST(GetHeaderValueTest, DefaultValueInt)
  67. {
  68. MultiMap map = {{"Dummy","Dummy"}};
  69. auto val = detail::get_header_value_int(map, "Content-Length", 100);
  70. EXPECT_EQ(100, val);
  71. }
  72. TEST(GetHeaderValueTest, RegularValue)
  73. {
  74. MultiMap map = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
  75. auto val = detail::get_header_value(map, "Content-Type", "text/plain");
  76. ASSERT_STREQ("text/html", val);
  77. }
  78. TEST(GetHeaderValueTest, RegularValueInt)
  79. {
  80. MultiMap map = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
  81. auto val = detail::get_header_value_int(map, "Content-Length", 0);
  82. EXPECT_EQ(100, val);
  83. }
  84. class ServerTest : public ::testing::Test {
  85. protected:
  86. ServerTest()
  87. : cli_(HOST, PORT)
  88. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  89. , svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  90. #endif
  91. , up_(false) {}
  92. virtual void SetUp() {
  93. svr_.set_base_dir("./www");
  94. svr_.get("/hi", [&](const Request& req, Response& res) {
  95. res.set_content("Hello World!", "text/plain");
  96. });
  97. svr_.get("/", [&](const Request& req, Response& res) {
  98. res.set_redirect("/hi");
  99. });
  100. svr_.post("/person", [&](const Request& req, Response& res) {
  101. if (req.has_param("name") && req.has_param("note")) {
  102. persons_[req.params.at("name")] = req.params.at("note");
  103. } else {
  104. res.status = 400;
  105. }
  106. });
  107. svr_.get("/person/(.*)", [&](const Request& req, Response& res) {
  108. string name = req.matches[1];
  109. if (persons_.find(name) != persons_.end()) {
  110. auto note = persons_[name];
  111. res.set_content(note, "text/plain");
  112. } else {
  113. res.status = 404;
  114. }
  115. });
  116. svr_.get("/stop", [&](const Request& req, Response& res) {
  117. svr_.stop();
  118. });
  119. persons_["john"] = "programmer";
  120. f_ = async([&](){
  121. up_ = true;
  122. svr_.listen(HOST, PORT);
  123. });
  124. while (!up_) {
  125. msleep(1);
  126. }
  127. }
  128. virtual void TearDown() {
  129. //svr_.stop(); // NOTE: This causes dead lock on Windows.
  130. cli_.get("/stop");
  131. f_.get();
  132. }
  133. map<string, string> persons_;
  134. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  135. SSLClient cli_;
  136. SSLServer svr_;
  137. #else
  138. Client cli_;
  139. Server svr_;
  140. #endif
  141. future<void> f_;
  142. bool up_;
  143. };
  144. TEST_F(ServerTest, GetMethod200)
  145. {
  146. auto res = cli_.get("/hi");
  147. ASSERT_TRUE(res != nullptr);
  148. EXPECT_EQ(200, res->status);
  149. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  150. EXPECT_EQ("Hello World!", res->body);
  151. }
  152. TEST_F(ServerTest, GetMethod302)
  153. {
  154. auto res = cli_.get("/");
  155. ASSERT_TRUE(res != nullptr);
  156. EXPECT_EQ(302, res->status);
  157. EXPECT_EQ("/hi", res->get_header_value("Location"));
  158. }
  159. TEST_F(ServerTest, GetMethod404)
  160. {
  161. auto res = cli_.get("/invalid");
  162. ASSERT_TRUE(res != nullptr);
  163. EXPECT_EQ(404, res->status);
  164. }
  165. TEST_F(ServerTest, HeadMethod200)
  166. {
  167. auto res = cli_.head("/hi");
  168. ASSERT_TRUE(res != nullptr);
  169. EXPECT_EQ(200, res->status);
  170. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  171. EXPECT_EQ("", res->body);
  172. }
  173. TEST_F(ServerTest, HeadMethod404)
  174. {
  175. auto res = cli_.head("/invalid");
  176. ASSERT_TRUE(res != nullptr);
  177. EXPECT_EQ(404, res->status);
  178. EXPECT_EQ("", res->body);
  179. }
  180. TEST_F(ServerTest, GetMethodPersonJohn)
  181. {
  182. auto res = cli_.get("/person/john");
  183. ASSERT_TRUE(res != nullptr);
  184. EXPECT_EQ(200, res->status);
  185. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  186. EXPECT_EQ("programmer", res->body);
  187. }
  188. TEST_F(ServerTest, PostMethod1)
  189. {
  190. auto res = cli_.get("/person/john1");
  191. ASSERT_TRUE(res != nullptr);
  192. ASSERT_EQ(404, res->status);
  193. res = cli_.post("/person", "name=john1&note=coder", "application/x-www-form-urlencoded");
  194. ASSERT_TRUE(res != nullptr);
  195. ASSERT_EQ(200, res->status);
  196. res = cli_.get("/person/john1");
  197. ASSERT_TRUE(res != nullptr);
  198. ASSERT_EQ(200, res->status);
  199. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  200. ASSERT_EQ("coder", res->body);
  201. }
  202. TEST_F(ServerTest, PostMethod2)
  203. {
  204. auto res = cli_.get("/person/john2");
  205. ASSERT_TRUE(res != nullptr);
  206. ASSERT_EQ(404, res->status);
  207. Map params;
  208. params["name"] = "john2";
  209. params["note"] = "coder";
  210. res = cli_.post("/person", params);
  211. ASSERT_TRUE(res != nullptr);
  212. ASSERT_EQ(200, res->status);
  213. res = cli_.get("/person/john2");
  214. ASSERT_TRUE(res != nullptr);
  215. ASSERT_EQ(200, res->status);
  216. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  217. ASSERT_EQ("coder", res->body);
  218. }
  219. TEST_F(ServerTest, GetMethodDir)
  220. {
  221. auto res = cli_.get("/dir/");
  222. ASSERT_TRUE(res != nullptr);
  223. EXPECT_EQ(200, res->status);
  224. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  225. auto body = R"(<html>
  226. <head>
  227. </head>
  228. <body>
  229. <a href="/dir/test.html">Test</a>
  230. <a href="/hi">hi</a>
  231. </body>
  232. </html>
  233. )";
  234. EXPECT_EQ(body, res->body);
  235. }
  236. TEST_F(ServerTest, GetMethodDirTest)
  237. {
  238. auto res = cli_.get("/dir/test.html");
  239. ASSERT_TRUE(res != nullptr);
  240. EXPECT_EQ(200, res->status);
  241. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  242. EXPECT_EQ("test.html", res->body);
  243. }
  244. TEST_F(ServerTest, InvalidBaseDir)
  245. {
  246. EXPECT_EQ(false, svr_.set_base_dir("invalid_dir"));
  247. EXPECT_EQ(true, svr_.set_base_dir("."));
  248. }
  249. #ifdef _WIN32
  250. TEST(CleanupTest, WSACleanup)
  251. {
  252. int ret = WSACleanup();
  253. ASSERT_EQ(0, ret);
  254. }
  255. #endif
  256. // vim: et ts=4 sw=4 cin cino={1s ff=unix