test_httpres.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. /* _
  2. * ___ __ _ __ _ _ _(_)
  3. * / __|/ _` |/ _` | | | | |
  4. * \__ \ (_| | (_| | |_| | |
  5. * |___/\__,_|\__, |\__,_|_|
  6. * |___/
  7. *
  8. * Cross-platform library which helps to develop web servers or frameworks.
  9. *
  10. * Copyright (C) 2016-2021 Silvio Clecio <[email protected]>
  11. *
  12. * Sagui library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2.1 of the License, or (at your option) any later version.
  16. *
  17. * Sagui library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Lesser General Public
  23. * License along with Sagui library; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  25. */
  26. #define SG_EXTERN
  27. #include "sg_assert.h"
  28. #include <string.h>
  29. #include "sg_httpres.c"
  30. #include <sagui.h>
  31. #ifndef TEST_HTTPRES_BASE_PATH
  32. #ifdef __ANDROID__
  33. #define TEST_HTTPRES_BASE_PATH SG_ANDROID_TESTS_DEST_DIR "/"
  34. #else /* __ANDROID__ */
  35. #ifdef _WIN32
  36. #define TEST_HTTPRES_BASE_PATH BINARY_DIR "/"
  37. #else /* _WIN32 */
  38. #define TEST_HTTPRES_BASE_PATH "/tmp/"
  39. #endif /* _WIN32 */
  40. #endif /* __ANDROID__ */
  41. #endif /* TEST_HTTPRES_BASE_PATH */
  42. static ssize_t dummy_read_cb(void *handle, uint64_t offset, char *buf,
  43. size_t size) {
  44. (void) handle;
  45. (void) offset;
  46. (void) buf;
  47. (void) size;
  48. return 0;
  49. }
  50. static void dummy_free_cb(void *handle) {
  51. *((int *) handle) = 0;
  52. }
  53. static void test__httpres_new(void) {
  54. struct sg_httpres *res = sg__httpres_new(NULL);
  55. ASSERT(res);
  56. ASSERT(res->status == 500);
  57. sg__httpres_free(res);
  58. }
  59. static void test__httpres_free(void) {
  60. sg__httpres_free(NULL);
  61. }
  62. static void test__httpres_dispatch(struct sg_httpres *res) {
  63. ASSERT(sg__httpres_dispatch(res) == 0);
  64. }
  65. static void test_httpres_headers(struct sg_httpres *res) {
  66. struct sg_strmap **headers;
  67. errno = 0;
  68. ASSERT(!sg_httpres_headers(NULL));
  69. ASSERT(errno == EINVAL);
  70. errno = 0;
  71. res->headers = NULL;
  72. ASSERT(sg_httpres_headers(res));
  73. ASSERT(errno == 0);
  74. headers = sg_httpres_headers(res);
  75. ASSERT(headers);
  76. ASSERT(sg_strmap_count(*headers) == 0);
  77. sg_strmap_add(&res->headers, "foo", "bar");
  78. sg_strmap_add(&res->headers, "abc", "123");
  79. ASSERT(sg_strmap_count(*headers) == 2);
  80. ASSERT(strcmp(sg_strmap_get(*headers, "foo"), "bar") == 0);
  81. ASSERT(strcmp(sg_strmap_get(*headers, "abc"), "123") == 0);
  82. }
  83. static void test_httpres_set_cookie(struct sg_httpres *res) {
  84. struct sg_strmap **fields;
  85. ASSERT(sg_httpres_set_cookie(NULL, "foo", "bar") == EINVAL);
  86. ASSERT(sg_httpres_set_cookie(res, NULL, "bar") == EINVAL);
  87. ASSERT(sg_httpres_set_cookie(res, "foo", NULL) == EINVAL);
  88. fields = sg_httpres_headers(res);
  89. sg_strmap_cleanup(fields);
  90. ASSERT(sg_httpres_set_cookie(res, "foo", "bar") == 0);
  91. ASSERT(
  92. strcmp(sg_strmap_get(*sg_httpres_headers(res), MHD_HTTP_HEADER_SET_COOKIE),
  93. "foo=bar") == 0);
  94. }
  95. static void test_httpres_send(struct sg_httpres *res) {
  96. char *str = "foo";
  97. ASSERT(sg_httpres_send(NULL, str, "text/plain", 200) == EINVAL);
  98. str = NULL;
  99. ASSERT(sg_httpres_send(res, str, "text/plain", 200) == EINVAL);
  100. ASSERT(sg_httpres_send(res, str, NULL, 200) == EINVAL);
  101. ASSERT(sg_httpres_send(res, str, "text/plain", 99) == EINVAL);
  102. ASSERT(sg_httpres_send(res, str, "text/plain", 600) == EINVAL);
  103. res->status = 0;
  104. ASSERT(sg_httpres_send(res, "", "text/plain", 200) == 0);
  105. ASSERT(res->status == 200);
  106. MHD_destroy_response(res->handle);
  107. res->handle = NULL;
  108. res->status = 0;
  109. ASSERT(sg_httpres_send(res, "", "", 204) == 0); /* No content. */
  110. ASSERT(res->status == 204);
  111. MHD_destroy_response(res->handle);
  112. res->handle = NULL;
  113. res->status = 0;
  114. str = "foo";
  115. ASSERT(sg_httpres_send(res, str, "text/plain", 201) == 0);
  116. ASSERT(res->status == 201);
  117. ASSERT(sg_httpres_send(res, str, "text/plain", 200) == EALREADY);
  118. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  119. MHD_HTTP_HEADER_CONTENT_TYPE),
  120. "text/plain") == 0);
  121. ASSERT(res->status == 201);
  122. MHD_destroy_response(res->handle);
  123. res->handle = NULL;
  124. }
  125. static void test_httpres_sendbinary(struct sg_httpres *res) {
  126. char *str = "foo";
  127. const size_t len = strlen(str);
  128. ASSERT(sg_httpres_sendbinary(NULL, str, len, "text/plain", 200) == EINVAL);
  129. ASSERT(sg_httpres_sendbinary(res, NULL, len, "text/plain", 200) == EINVAL);
  130. ASSERT(sg_httpres_sendbinary(res, str, (size_t) -1, "text/plain", 200) ==
  131. EINVAL);
  132. ASSERT(sg_httpres_sendbinary(res, str, len, "text/plain", 99) == EINVAL);
  133. ASSERT(sg_httpres_sendbinary(res, str, len, "text/plain", 600) == EINVAL);
  134. res->status = 0;
  135. ASSERT(sg_httpres_sendbinary(res, str, len, NULL, 200) == 0);
  136. ASSERT(res->status == 200);
  137. MHD_destroy_response(res->handle);
  138. res->handle = NULL;
  139. res->status = 0;
  140. ASSERT(sg_httpres_sendbinary(res, "foo", 0, "text/plain", 200) == 0);
  141. ASSERT(res->status == 200);
  142. MHD_destroy_response(res->handle);
  143. res->handle = NULL;
  144. res->status = 0;
  145. ASSERT(sg_httpres_sendbinary(res, str, len, "", 200) == 0);
  146. ASSERT(res->status == 200);
  147. MHD_destroy_response(res->handle);
  148. res->handle = NULL;
  149. res->status = 0;
  150. ASSERT(sg_httpres_sendbinary(res, "", 0, "", 204) == 0); /* No content. */
  151. ASSERT(res->status == 204);
  152. MHD_destroy_response(res->handle);
  153. res->handle = NULL;
  154. res->status = 0;
  155. ASSERT(sg_httpres_sendbinary(res, str, len, "text/plain", 201) == 0);
  156. ASSERT(res->status == 201);
  157. ASSERT(sg_httpres_sendbinary(res, str, len, "text/plain", 200) == EALREADY);
  158. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  159. MHD_HTTP_HEADER_CONTENT_TYPE),
  160. "text/plain") == 0);
  161. ASSERT(res->status == 201);
  162. MHD_destroy_response(res->handle);
  163. res->handle = NULL;
  164. }
  165. static void test_httpres_download(struct sg_httpres *res) {
  166. #define FILENAME "foo.txt"
  167. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  168. const size_t len = 3;
  169. char str[4];
  170. FILE *file;
  171. char *dir;
  172. ASSERT(sg_httpres_download(NULL, PATH, 200) == EINVAL);
  173. ASSERT(sg_httpres_download(res, NULL, 200) == EINVAL);
  174. ASSERT(sg_httpres_download(res, "", 200) == ENOENT);
  175. dir = sg_tmpdir();
  176. ASSERT(sg_httpres_download(res, dir, 200) == EISDIR);
  177. sg_free(dir);
  178. strcpy(str, "foo");
  179. unlink(PATH);
  180. file = fopen(PATH, "w");
  181. ASSERT(file);
  182. ASSERT(fwrite(str, 1, len, file) == len);
  183. ASSERT(fclose(file) == 0);
  184. ASSERT(sg_httpres_download(res, PATH, 200) == 0);
  185. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  186. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  187. "attachment; filename=\"" FILENAME "\"") == 0);
  188. ASSERT(sg_httpres_download(res, PATH, 200) == EALREADY);
  189. sg_free(res->handle);
  190. res->handle = NULL;
  191. #undef PATH
  192. #undef FILENAME
  193. sg_free(res->handle);
  194. res->handle = NULL;
  195. }
  196. static void test_httpres_render(struct sg_httpres *res) {
  197. #define FILENAME "foo.txt"
  198. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  199. const size_t len = 3;
  200. char str[4];
  201. FILE *file;
  202. char *dir;
  203. ASSERT(sg_httpres_render(NULL, PATH, 200) == EINVAL);
  204. ASSERT(sg_httpres_render(res, NULL, 200) == EINVAL);
  205. ASSERT(sg_httpres_render(res, "", 200) == ENOENT);
  206. dir = sg_tmpdir();
  207. ASSERT(sg_httpres_render(res, dir, 200) == EISDIR);
  208. sg_free(dir);
  209. strcpy(str, "foo");
  210. unlink(PATH);
  211. file = fopen(PATH, "w");
  212. ASSERT(file);
  213. ASSERT(fwrite(str, 1, len, file) == len);
  214. ASSERT(fclose(file) == 0);
  215. ASSERT(sg_httpres_render(res, PATH, 200) == 0);
  216. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  217. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  218. "inline; filename=\"" FILENAME "\"") == 0);
  219. ASSERT(sg_httpres_render(res, PATH, 200) == EALREADY);
  220. sg_free(res->handle);
  221. res->handle = NULL;
  222. #undef PATH
  223. #undef FILENAME
  224. sg_free(res->handle);
  225. res->handle = NULL;
  226. }
  227. static void test_httpres_sendfile2(struct sg_httpres *res) {
  228. #define FILENAME "foo.txt"
  229. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  230. const size_t len = 3;
  231. char str[4];
  232. FILE *file;
  233. char *dir;
  234. size_t size = sizeof(int);
  235. uint64_t max_size = 10, offset = 0;
  236. ASSERT(sg_httpres_sendfile2(NULL, size, max_size, offset, PATH, NULL, 200) ==
  237. EINVAL);
  238. ASSERT(sg_httpres_sendfile2(res, (uint64_t) -1, max_size, offset, PATH, NULL,
  239. 200) == EINVAL);
  240. ASSERT(sg_httpres_sendfile2(res, size, (uint64_t) -1, offset, PATH, NULL,
  241. 200) == EINVAL);
  242. ASSERT(sg_httpres_sendfile2(res, size, max_size, (uint64_t) -1, PATH, NULL,
  243. 200) == EINVAL);
  244. ASSERT(sg_httpres_sendfile2(res, size, max_size, offset, NULL, NULL, 200) ==
  245. EINVAL);
  246. ASSERT(sg_httpres_sendfile2(res, size, max_size, offset, PATH, NULL, 99) ==
  247. EINVAL);
  248. ASSERT(sg_httpres_sendfile2(res, size, max_size, offset, PATH, NULL, 600) ==
  249. EINVAL);
  250. ASSERT(sg_httpres_sendfile2(res, size, max_size, offset, "", NULL, 200) ==
  251. ENOENT);
  252. dir = sg_tmpdir();
  253. ASSERT(sg_httpres_sendfile2(res, size, max_size, offset, dir, NULL, 200) ==
  254. EISDIR);
  255. sg_free(dir);
  256. strcpy(str, "foo");
  257. unlink(PATH);
  258. file = fopen(PATH, "w");
  259. ASSERT(file);
  260. ASSERT(fwrite(str, 1, len, file) == len);
  261. ASSERT(fclose(file) == 0);
  262. ASSERT(sg_httpres_sendfile2(res, size, 1, offset, PATH, NULL, 200) == EFBIG);
  263. ASSERT(
  264. sg_httpres_sendfile2(res, size, len, offset, PATH, "attachment", 200) == 0);
  265. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  266. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  267. "attachment; filename=\"" FILENAME "\"") == 0);
  268. ASSERT(sg_httpres_sendfile2(res, size, len, offset, PATH, "attachment",
  269. 200) == EALREADY);
  270. sg_free(res->handle);
  271. res->handle = NULL;
  272. ASSERT(sg_httpres_sendfile2(res, size, len, offset, PATH, "inline", 201) ==
  273. 0);
  274. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  275. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  276. "inline; filename=\"" FILENAME "\"") == 0);
  277. ASSERT(res->status == 201);
  278. sg_free(res->handle);
  279. res->handle = NULL;
  280. sg_strmap_cleanup(sg_httpres_headers(res));
  281. ASSERT(sg_httpres_sendfile2(res, size, len, offset, PATH, NULL, 200) == 0);
  282. ASSERT(!sg_strmap_get(*sg_httpres_headers(res),
  283. MHD_HTTP_HEADER_CONTENT_DISPOSITION));
  284. ASSERT(res->status == 200);
  285. sg_free(res->handle);
  286. res->handle = NULL;
  287. ASSERT(sg_httpres_sendfile2(res, size, len, offset, PATH, "abc123", 201) ==
  288. 0);
  289. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  290. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  291. "abc123; filename=\"" FILENAME "\"") == 0);
  292. ASSERT(res->status == 201);
  293. #undef PATH
  294. #undef FILENAME
  295. sg_free(res->handle);
  296. res->handle = NULL;
  297. }
  298. static void test_httpres_sendfile(struct sg_httpres *res) {
  299. #define FILENAME "foo.txt"
  300. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  301. const size_t len = 3;
  302. char str[4];
  303. FILE *file;
  304. char *dir;
  305. size_t size = sizeof(int);
  306. uint64_t max_size = 10, offset = 0;
  307. ASSERT(sg_httpres_sendfile(NULL, size, max_size, offset, PATH, false, 200) ==
  308. EINVAL);
  309. ASSERT(sg_httpres_sendfile(res, (uint64_t) -1, max_size, offset, PATH, false,
  310. 200) == EINVAL);
  311. ASSERT(sg_httpres_sendfile(res, size, (uint64_t) -1, offset, PATH, false,
  312. 200) == EINVAL);
  313. ASSERT(sg_httpres_sendfile(res, size, max_size, (uint64_t) -1, PATH, false,
  314. 200) == EINVAL);
  315. ASSERT(sg_httpres_sendfile(res, size, max_size, offset, NULL, false, 200) ==
  316. EINVAL);
  317. ASSERT(sg_httpres_sendfile(res, size, max_size, offset, PATH, false, 99) ==
  318. EINVAL);
  319. ASSERT(sg_httpres_sendfile(res, size, max_size, offset, PATH, false, 600) ==
  320. EINVAL);
  321. ASSERT(sg_httpres_sendfile(res, size, max_size, offset, "", false, 200) ==
  322. ENOENT);
  323. dir = sg_tmpdir();
  324. ASSERT(sg_httpres_sendfile(res, size, max_size, offset, dir, false, 200) ==
  325. EISDIR);
  326. sg_free(dir);
  327. strcpy(str, "foo");
  328. unlink(PATH);
  329. file = fopen(PATH, "w");
  330. ASSERT(file);
  331. ASSERT(fwrite(str, 1, len, file) == len);
  332. ASSERT(fclose(file) == 0);
  333. ASSERT(sg_httpres_sendfile(res, size, 1, offset, PATH, false, 200) == EFBIG);
  334. ASSERT(sg_httpres_sendfile(res, size, len, offset, PATH, true, 200) == 0);
  335. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  336. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  337. "attachment; filename=\"" FILENAME "\"") == 0);
  338. ASSERT(sg_httpres_sendfile(res, size, len, offset, PATH, true, 200) ==
  339. EALREADY);
  340. sg_free(res->handle);
  341. res->handle = NULL;
  342. sg_strmap_cleanup(sg_httpres_headers(res));
  343. ASSERT(sg_httpres_sendfile(res, size, len, offset, PATH, false, 201) == 0);
  344. ASSERT(!sg_strmap_get(*sg_httpres_headers(res),
  345. MHD_HTTP_HEADER_CONTENT_DISPOSITION));
  346. ASSERT(res->status == 201);
  347. #undef PATH
  348. #undef FILENAME
  349. sg_free(res->handle);
  350. res->handle = NULL;
  351. }
  352. static void test_httpres_sendstream(struct sg_httpres *res) {
  353. char *str;
  354. size_t size = sizeof(int);
  355. int buf = 1;
  356. ASSERT(sg_httpres_sendstream(NULL, size, dummy_read_cb, &buf, dummy_free_cb,
  357. 200) == EINVAL);
  358. ASSERT(buf == 0);
  359. buf = 1;
  360. ASSERT(sg_httpres_sendstream(res, (uint64_t) -1, NULL, &buf, dummy_free_cb,
  361. 200) == EINVAL);
  362. ASSERT(buf == 0);
  363. buf = 1;
  364. ASSERT(sg_httpres_sendstream(res, size, NULL, &buf, dummy_free_cb, 200) ==
  365. EINVAL);
  366. ASSERT(buf == 0);
  367. buf = 1;
  368. ASSERT(sg_httpres_sendstream(res, size, dummy_read_cb, &buf, dummy_free_cb,
  369. 99) == EINVAL);
  370. ASSERT(buf == 0);
  371. buf = 1;
  372. ASSERT(sg_httpres_sendstream(res, size, dummy_read_cb, &buf, dummy_free_cb,
  373. 600) == EINVAL);
  374. ASSERT(buf == 0);
  375. size = sizeof(str);
  376. str = sg_alloc(size);
  377. ASSERT(
  378. sg_httpres_sendstream(res, 0, dummy_read_cb, str, dummy_free_cb, 200) == 0);
  379. sg_free(res->handle);
  380. res->handle = NULL;
  381. ASSERT(sg_httpres_sendstream(res, size, dummy_read_cb, str, dummy_free_cb,
  382. 201) == 0);
  383. ASSERT(res->status == 201);
  384. ASSERT(sg_httpres_sendstream(res, size, dummy_read_cb, str, dummy_free_cb,
  385. 200) == EALREADY);
  386. sg_free(res->handle);
  387. res->handle = NULL;
  388. sg_free(str);
  389. }
  390. #ifdef SG_HTTP_COMPRESSION
  391. static void test_httpres_zsend(struct sg_httpres *res) {
  392. char *str = "foo";
  393. ASSERT(sg_httpres_zsend(NULL, str, "text/plain", 200) == EINVAL);
  394. str = NULL;
  395. ASSERT(sg_httpres_zsend(res, str, "text/plain", 200) == EINVAL);
  396. ASSERT(sg_httpres_zsend(res, str, NULL, 200) == EINVAL);
  397. ASSERT(sg_httpres_zsend(res, str, "text/plain", 99) == EINVAL);
  398. ASSERT(sg_httpres_zsend(res, str, "text/plain", 600) == EINVAL);
  399. str = "foooo";
  400. res->status = 0;
  401. sg_strmap_cleanup(&res->headers);
  402. ASSERT(sg_httpres_zsend(res, str, "text/plain", 200) == 0);
  403. ASSERT(!sg_strmap_get(res->headers, "Content-Encoding"));
  404. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Type"), "text/plain") ==
  405. 0);
  406. ASSERT(res->status == 200);
  407. MHD_destroy_response(res->handle);
  408. res->handle = NULL;
  409. str = "fooooooooooobaaaaaaaaaarrrrrrrrrrr";
  410. res->status = 0;
  411. ASSERT(sg_httpres_zsend(res, str, "text/plain", 200) == 0);
  412. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Encoding"), "deflate") ==
  413. 0);
  414. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Type"), "text/plain") ==
  415. 0);
  416. ASSERT(res->status == 200);
  417. MHD_destroy_response(res->handle);
  418. res->handle = NULL;
  419. res->status = 0;
  420. str = "foo";
  421. ASSERT(sg_httpres_zsend(res, str, "", 200) == 0);
  422. ASSERT(res->status == 200);
  423. MHD_destroy_response(res->handle);
  424. res->handle = NULL;
  425. res->status = 0;
  426. ASSERT(sg_httpres_zsend(res, "", "", 204) == 0); /* No content. */
  427. ASSERT(res->status == 204);
  428. MHD_destroy_response(res->handle);
  429. res->handle = NULL;
  430. res->status = 0;
  431. ASSERT(sg_httpres_zsend(res, str, "text/plain", 201) == 0);
  432. ASSERT(res->status == 201);
  433. ASSERT(sg_httpres_zsend(res, str, "text/plain", 200) == EALREADY);
  434. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  435. MHD_HTTP_HEADER_CONTENT_TYPE),
  436. "text/plain") == 0);
  437. ASSERT(res->status == 201);
  438. MHD_destroy_response(res->handle);
  439. res->handle = NULL;
  440. }
  441. static void test_httpres_zsendbinary2(struct sg_httpres *res) {
  442. char *str = "foo";
  443. size_t len = strlen(str);
  444. ASSERT(sg_httpres_zsendbinary2(NULL, -1, str, len, "text/plain", 200) ==
  445. EINVAL);
  446. ASSERT(sg_httpres_zsendbinary2(res, -2, str, len, "text/plain", 200) ==
  447. EINVAL);
  448. ASSERT(sg_httpres_zsendbinary2(res, 10, str, len, "text/plain", 200) ==
  449. EINVAL);
  450. ASSERT(sg_httpres_zsendbinary2(res, -1, NULL, len, "text/plain", 200) ==
  451. EINVAL);
  452. ASSERT(sg_httpres_zsendbinary2(res, -1, str, (size_t) -1, "text/plain",
  453. 200) == EINVAL);
  454. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "text/plain", 99) ==
  455. EINVAL);
  456. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "text/plain", 600) ==
  457. EINVAL);
  458. str = "foooo";
  459. len = strlen(str);
  460. res->status = 0;
  461. sg_strmap_cleanup(&res->headers);
  462. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "text/plain", 200) == 0);
  463. ASSERT(!sg_strmap_get(res->headers, "Content-Encoding"));
  464. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Type"), "text/plain") ==
  465. 0);
  466. ASSERT(res->status == 200);
  467. MHD_destroy_response(res->handle);
  468. res->handle = NULL;
  469. str = "fooooooooooobaaaaaaaaaarrrrrrrrrrr";
  470. len = strlen(str);
  471. res->status = 0;
  472. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "text/plain", 200) == 0);
  473. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Encoding"), "deflate") ==
  474. 0);
  475. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Type"), "text/plain") ==
  476. 0);
  477. ASSERT(res->status == 200);
  478. MHD_destroy_response(res->handle);
  479. res->handle = NULL;
  480. str = "foo";
  481. len = strlen(str);
  482. res->status = 0;
  483. ASSERT(sg_httpres_zsendbinary2(res, -1, "foo", 0, "text/plain", 200) == 0);
  484. ASSERT(res->status == 200);
  485. MHD_destroy_response(res->handle);
  486. res->handle = NULL;
  487. res->status = 0;
  488. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, NULL, 200) == 0);
  489. ASSERT(res->status == 200);
  490. MHD_destroy_response(res->handle);
  491. res->handle = NULL;
  492. res->status = 0;
  493. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "", 200) == 0);
  494. ASSERT(res->status == 200);
  495. MHD_destroy_response(res->handle);
  496. res->handle = NULL;
  497. res->status = 0;
  498. ASSERT(sg_httpres_zsendbinary2(res, -1, "", 0, "", 204) ==
  499. 0); /* No content. */
  500. ASSERT(res->status == 204);
  501. MHD_destroy_response(res->handle);
  502. res->handle = NULL;
  503. res->status = 0;
  504. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "text/plain", 201) == 0);
  505. ASSERT(res->status == 201);
  506. ASSERT(sg_httpres_zsendbinary2(res, -1, str, len, "text/plain", 200) ==
  507. EALREADY);
  508. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  509. MHD_HTTP_HEADER_CONTENT_TYPE),
  510. "text/plain") == 0);
  511. ASSERT(res->status == 201);
  512. MHD_destroy_response(res->handle);
  513. res->handle = NULL;
  514. }
  515. static void test_httpres_zsendbinary(struct sg_httpres *res) {
  516. char *str = "foo";
  517. size_t len = strlen(str);
  518. ASSERT(sg_httpres_zsendbinary(NULL, str, len, "text/plain", 200) == EINVAL);
  519. ASSERT(sg_httpres_zsendbinary(res, NULL, len, "text/plain", 200) == EINVAL);
  520. ASSERT(sg_httpres_zsendbinary(res, str, (size_t) -1, "text/plain", 200) ==
  521. EINVAL);
  522. ASSERT(sg_httpres_zsendbinary(res, str, len, "text/plain", 99) == EINVAL);
  523. ASSERT(sg_httpres_zsendbinary(res, str, len, "text/plain", 600) == EINVAL);
  524. str = "foooo";
  525. len = strlen(str);
  526. res->status = 0;
  527. sg_strmap_cleanup(&res->headers);
  528. ASSERT(sg_httpres_zsendbinary(res, str, len, "text/plain", 200) == 0);
  529. ASSERT(!sg_strmap_get(res->headers, "Content-Encoding"));
  530. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Type"), "text/plain") ==
  531. 0);
  532. ASSERT(res->status == 200);
  533. MHD_destroy_response(res->handle);
  534. res->handle = NULL;
  535. str = "fooooooooooobaaaaaaaaaarrrrrrrrrrr";
  536. len = strlen(str);
  537. res->status = 0;
  538. ASSERT(sg_httpres_zsendbinary(res, str, len, "text/plain", 200) == 0);
  539. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Encoding"), "deflate") ==
  540. 0);
  541. ASSERT(strcmp(sg_strmap_get(res->headers, "Content-Type"), "text/plain") ==
  542. 0);
  543. ASSERT(res->status == 200);
  544. MHD_destroy_response(res->handle);
  545. res->handle = NULL;
  546. str = "foo";
  547. len = strlen(str);
  548. res->status = 0;
  549. ASSERT(sg_httpres_zsendbinary(res, "foo", 0, "text/plain", 200) == 0);
  550. ASSERT(res->status == 200);
  551. MHD_destroy_response(res->handle);
  552. res->handle = NULL;
  553. res->status = 0;
  554. ASSERT(sg_httpres_zsendbinary(res, str, len, NULL, 200) == 0);
  555. ASSERT(res->status == 200);
  556. MHD_destroy_response(res->handle);
  557. res->handle = NULL;
  558. res->status = 0;
  559. ASSERT(sg_httpres_zsendbinary(res, str, len, "", 200) == 0);
  560. ASSERT(res->status == 200);
  561. MHD_destroy_response(res->handle);
  562. res->handle = NULL;
  563. res->status = 0;
  564. ASSERT(sg_httpres_zsendbinary(res, "", 0, "", 204) == 0); /* No content. */
  565. ASSERT(res->status == 204);
  566. MHD_destroy_response(res->handle);
  567. res->handle = NULL;
  568. res->status = 0;
  569. ASSERT(sg_httpres_zsendbinary(res, str, len, "text/plain", 201) == 0);
  570. ASSERT(res->status == 201);
  571. ASSERT(sg_httpres_zsendbinary(res, str, len, "text/plain", 200) == EALREADY);
  572. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  573. MHD_HTTP_HEADER_CONTENT_TYPE),
  574. "text/plain") == 0);
  575. ASSERT(res->status == 201);
  576. MHD_destroy_response(res->handle);
  577. res->handle = NULL;
  578. }
  579. static void test_httpres_zsendstream2(struct sg_httpres *res) {
  580. char *str;
  581. size_t size = sizeof(int);
  582. int buf = 1;
  583. ASSERT(sg_httpres_zsendstream2(NULL, -1, size, dummy_read_cb, &buf,
  584. dummy_free_cb, 200) == EINVAL);
  585. ASSERT(buf == 0);
  586. buf = 1;
  587. ASSERT(sg_httpres_zsendstream2(res, -2, size, dummy_read_cb, &buf,
  588. dummy_free_cb, 200) == EINVAL);
  589. ASSERT(buf == 0);
  590. buf = 1;
  591. ASSERT(sg_httpres_zsendstream2(res, 10, size, dummy_read_cb, &buf,
  592. dummy_free_cb, 200) == EINVAL);
  593. ASSERT(buf == 0);
  594. buf = 1;
  595. ASSERT(sg_httpres_zsendstream2(res, -1, size, NULL, &buf, dummy_free_cb,
  596. 200) == EINVAL);
  597. ASSERT(buf == 0);
  598. buf = 1;
  599. ASSERT(sg_httpres_zsendstream2(res, -1, size, dummy_read_cb, &buf,
  600. dummy_free_cb, 99) == EINVAL);
  601. ASSERT(buf == 0);
  602. buf = 1;
  603. ASSERT(sg_httpres_zsendstream2(res, -1, size, dummy_read_cb, &buf,
  604. dummy_free_cb, 600) == EINVAL);
  605. ASSERT(buf == 0);
  606. str = sg_alloc(sizeof(str));
  607. ASSERT(sg_httpres_zsendstream2(res, -1, size, dummy_read_cb, str,
  608. dummy_free_cb, 200) == 0);
  609. sg_free(res->handle);
  610. res->handle = NULL;
  611. ASSERT(sg_httpres_zsendstream2(res, -1, size, dummy_read_cb, str,
  612. dummy_free_cb, 201) == 0);
  613. ASSERT(res->status == 201);
  614. ASSERT(sg_httpres_zsendstream2(res, -1, size, dummy_read_cb, str,
  615. dummy_free_cb, 200) == EALREADY);
  616. sg_free(res->handle);
  617. res->handle = NULL;
  618. sg_free(str);
  619. }
  620. static void test_httpres_zsendstream(struct sg_httpres *res) {
  621. char *str;
  622. int buf = 1;
  623. ASSERT(sg_httpres_zsendstream(NULL, dummy_read_cb, &buf, dummy_free_cb,
  624. 200) == EINVAL);
  625. ASSERT(buf == 0);
  626. buf = 1;
  627. ASSERT(sg_httpres_zsendstream(res, NULL, &buf, dummy_free_cb, 200) == EINVAL);
  628. ASSERT(buf == 0);
  629. buf = 1;
  630. ASSERT(sg_httpres_zsendstream(res, dummy_read_cb, &buf, dummy_free_cb, 99) ==
  631. EINVAL);
  632. ASSERT(buf == 0);
  633. buf = 1;
  634. ASSERT(sg_httpres_zsendstream(res, dummy_read_cb, &buf, dummy_free_cb, 600) ==
  635. EINVAL);
  636. ASSERT(buf == 0);
  637. str = sg_alloc(sizeof(str));
  638. ASSERT(sg_httpres_zsendstream(res, dummy_read_cb, str, dummy_free_cb, 200) ==
  639. 0);
  640. sg_free(res->handle);
  641. res->handle = NULL;
  642. ASSERT(sg_httpres_zsendstream(res, dummy_read_cb, str, dummy_free_cb, 201) ==
  643. 0);
  644. ASSERT(res->status == 201);
  645. ASSERT(sg_httpres_zsendstream(res, dummy_read_cb, str, dummy_free_cb, 200) ==
  646. EALREADY);
  647. sg_free(res->handle);
  648. res->handle = NULL;
  649. sg_free(str);
  650. }
  651. static void test_httpres_zdownload(struct sg_httpres *res) {
  652. #define FILENAME "foo.txt"
  653. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  654. const size_t len = 3;
  655. char str[4];
  656. FILE *file;
  657. char *dir;
  658. ASSERT(sg_httpres_zdownload(NULL, PATH, 200) == EINVAL);
  659. ASSERT(sg_httpres_zdownload(res, NULL, 200) == EINVAL);
  660. ASSERT(sg_httpres_zdownload(res, "", 200) == ENOENT);
  661. dir = sg_tmpdir();
  662. ASSERT(sg_httpres_zdownload(res, dir, 200) == EISDIR);
  663. sg_free(dir);
  664. strcpy(str, "foo");
  665. unlink(PATH);
  666. file = fopen(PATH, "w");
  667. ASSERT(file);
  668. ASSERT(fwrite(str, 1, len, file) == len);
  669. ASSERT(fclose(file) == 0);
  670. ASSERT(sg_httpres_zdownload(res, PATH, 200) == 0);
  671. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  672. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  673. "attachment; filename=\"" FILENAME "\"") == 0);
  674. ASSERT(sg_httpres_zdownload(res, PATH, 200) == EALREADY);
  675. sg_free(res->handle);
  676. res->handle = NULL;
  677. #undef PATH
  678. #undef FILENAME
  679. sg_free(res->handle);
  680. res->handle = NULL;
  681. }
  682. static void test_httpres_zrender(struct sg_httpres *res) {
  683. #define FILENAME "foo.txt"
  684. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  685. const size_t len = 3;
  686. char str[4];
  687. FILE *file;
  688. char *dir;
  689. ASSERT(sg_httpres_zrender(NULL, PATH, 200) == EINVAL);
  690. ASSERT(sg_httpres_zrender(res, NULL, 200) == EINVAL);
  691. ASSERT(sg_httpres_zrender(res, "", 200) == ENOENT);
  692. dir = sg_tmpdir();
  693. ASSERT(sg_httpres_zrender(res, dir, 200) == EISDIR);
  694. sg_free(dir);
  695. strcpy(str, "foo");
  696. unlink(PATH);
  697. file = fopen(PATH, "w");
  698. ASSERT(file);
  699. ASSERT(fwrite(str, 1, len, file) == len);
  700. ASSERT(fclose(file) == 0);
  701. ASSERT(sg_httpres_zrender(res, PATH, 200) == 0);
  702. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  703. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  704. "inline; filename=\"" FILENAME "\"") == 0);
  705. ASSERT(sg_httpres_zrender(res, PATH, 200) == EALREADY);
  706. sg_free(res->handle);
  707. res->handle = NULL;
  708. #undef PATH
  709. #undef FILENAME
  710. sg_free(res->handle);
  711. res->handle = NULL;
  712. }
  713. static void test_httpres_zsendfile2(struct sg_httpres *res) {
  714. #define FILENAME "foo.txt"
  715. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  716. const size_t len = 3;
  717. char str[4];
  718. FILE *file;
  719. char *dir;
  720. size_t size = sizeof(int);
  721. uint64_t max_size = 10, offset = 0;
  722. ASSERT(sg_httpres_zsendfile2(NULL, -1, size, max_size, offset, PATH, NULL,
  723. 200) == EINVAL);
  724. ASSERT(sg_httpres_zsendfile2(res, -2, size, max_size, offset, PATH, NULL,
  725. 200) == EINVAL);
  726. ASSERT(sg_httpres_zsendfile2(res, 10, size, max_size, offset, PATH, NULL,
  727. 200) == EINVAL);
  728. ASSERT(sg_httpres_zsendfile2(res, -1, (uint64_t) -1, max_size, offset, PATH,
  729. NULL, 200) == EINVAL);
  730. ASSERT(sg_httpres_zsendfile2(res, -1, size, (uint64_t) -1, offset, PATH, NULL,
  731. 200) == EINVAL);
  732. ASSERT(sg_httpres_zsendfile2(res, -1, size, max_size, (uint64_t) -1, PATH,
  733. NULL, 200) == EINVAL);
  734. ASSERT(sg_httpres_zsendfile2(res, -1, size, max_size, offset, NULL, NULL,
  735. 200) == EINVAL);
  736. ASSERT(sg_httpres_zsendfile2(res, -1, size, max_size, offset, PATH, NULL,
  737. 99) == EINVAL);
  738. ASSERT(sg_httpres_zsendfile2(res, -1, size, max_size, offset, PATH, NULL,
  739. 600) == EINVAL);
  740. ASSERT(sg_httpres_zsendfile2(res, -1, size, max_size, offset, "", NULL,
  741. 200) == ENOENT);
  742. dir = sg_tmpdir();
  743. ASSERT(sg_httpres_zsendfile2(res, -1, size, max_size, offset, dir, NULL,
  744. 200) == EISDIR);
  745. sg_free(dir);
  746. strcpy(str, "foo");
  747. unlink(PATH);
  748. file = fopen(PATH, "w");
  749. ASSERT(file);
  750. ASSERT(fwrite(str, 1, len, file) == len);
  751. ASSERT(fclose(file) == 0);
  752. ASSERT(sg_httpres_zsendfile2(res, -1, size, 1, offset, PATH, NULL, 200) ==
  753. EFBIG);
  754. ASSERT(sg_httpres_zsendfile2(res, -1, size, len, offset, PATH, "attachment",
  755. 200) == 0);
  756. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  757. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  758. "attachment; filename=\"" FILENAME "\"") == 0);
  759. ASSERT(sg_httpres_zsendfile2(res, -1, size, len, offset, PATH, "attachment",
  760. 200) == EALREADY);
  761. sg_free(res->handle);
  762. res->handle = NULL;
  763. ASSERT(sg_httpres_zsendfile2(res, -1, size, len, offset, PATH, "inline",
  764. 201) == 0);
  765. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  766. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  767. "inline; filename=\"" FILENAME "\"") == 0);
  768. ASSERT(res->status == 201);
  769. sg_free(res->handle);
  770. res->handle = NULL;
  771. sg_strmap_cleanup(sg_httpres_headers(res));
  772. ASSERT(sg_httpres_zsendfile2(res, -1, size, len, offset, PATH, NULL, 200) ==
  773. 0);
  774. ASSERT(!sg_strmap_get(*sg_httpres_headers(res),
  775. MHD_HTTP_HEADER_CONTENT_DISPOSITION));
  776. ASSERT(res->status == 200);
  777. sg_free(res->handle);
  778. res->handle = NULL;
  779. ASSERT(sg_httpres_zsendfile2(res, -1, size, len, offset, PATH, "abc123",
  780. 201) == 0);
  781. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  782. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  783. "abc123; filename=\"" FILENAME "\"") == 0);
  784. ASSERT(res->status == 201);
  785. #undef PATH
  786. #undef FILENAME
  787. sg_free(res->handle);
  788. res->handle = NULL;
  789. }
  790. static void test_httpres_zsendfile(struct sg_httpres *res) {
  791. #define FILENAME "foo.txt"
  792. #define PATH TEST_HTTPRES_BASE_PATH FILENAME
  793. const size_t len = 3;
  794. char str[4];
  795. FILE *file;
  796. char *dir;
  797. size_t size = sizeof(int);
  798. uint64_t max_size = 10, offset = 0;
  799. ASSERT(sg_httpres_zsendfile(NULL, size, max_size, offset, PATH, false, 200) ==
  800. EINVAL);
  801. ASSERT(sg_httpres_zsendfile(res, (uint64_t) -1, max_size, offset, PATH, false,
  802. 200) == EINVAL);
  803. ASSERT(sg_httpres_zsendfile(res, size, (uint64_t) -1, offset, PATH, false,
  804. 200) == EINVAL);
  805. ASSERT(sg_httpres_zsendfile(res, size, max_size, (uint64_t) -1, PATH, false,
  806. 200) == EINVAL);
  807. ASSERT(sg_httpres_zsendfile(res, size, max_size, offset, NULL, false, 200) ==
  808. EINVAL);
  809. ASSERT(sg_httpres_zsendfile(res, size, max_size, offset, PATH, false, 99) ==
  810. EINVAL);
  811. ASSERT(sg_httpres_zsendfile(res, size, max_size, offset, PATH, false, 600) ==
  812. EINVAL);
  813. ASSERT(sg_httpres_zsendfile(res, size, max_size, offset, "", false, 200) ==
  814. ENOENT);
  815. dir = sg_tmpdir();
  816. ASSERT(sg_httpres_zsendfile(res, size, max_size, offset, dir, false, 200) ==
  817. EISDIR);
  818. sg_free(dir);
  819. strcpy(str, "foo");
  820. unlink(PATH);
  821. file = fopen(PATH, "w");
  822. ASSERT(file);
  823. ASSERT(fwrite(str, 1, len, file) == len);
  824. ASSERT(fclose(file) == 0);
  825. ASSERT(sg_httpres_zsendfile(res, size, 1, offset, PATH, false, 200) == EFBIG);
  826. ASSERT(sg_httpres_zsendfile(res, size, len, offset, PATH, true, 200) == 0);
  827. ASSERT(strcmp(sg_strmap_get(*sg_httpres_headers(res),
  828. MHD_HTTP_HEADER_CONTENT_DISPOSITION),
  829. "attachment; filename=\"" FILENAME "\"") == 0);
  830. ASSERT(sg_httpres_zsendfile(res, size, len, offset, PATH, true, 200) ==
  831. EALREADY);
  832. sg_free(res->handle);
  833. res->handle = NULL;
  834. sg_strmap_cleanup(sg_httpres_headers(res));
  835. ASSERT(sg_httpres_zsendfile(res, size, len, offset, PATH, false, 201) == 0);
  836. ASSERT(!sg_strmap_get(*sg_httpres_headers(res),
  837. MHD_HTTP_HEADER_CONTENT_DISPOSITION));
  838. ASSERT(res->status == 201);
  839. #undef PATH
  840. #undef FILENAME
  841. sg_free(res->handle);
  842. res->handle = NULL;
  843. }
  844. #endif /* SG_HTTP_COMPRESSION */
  845. static void test_httpres_reset(struct sg_httpres *res) {
  846. struct sg_strmap **headers;
  847. ASSERT(sg_httpres_reset(NULL) == EINVAL);
  848. headers = sg_httpres_headers(res);
  849. ASSERT(sg_strmap_add(headers, "foo", "bar") == 0);
  850. ASSERT(sg_strmap_add(headers, "lorem", "ipsum") == 0);
  851. ASSERT(sg_httpres_set_cookie(res, "my", "cookie") == 0);
  852. ASSERT(sg_httpres_send(res, "", "", 200) == 0);
  853. ASSERT(res->handle);
  854. ASSERT(strcmp(sg_strmap_get(*headers, "foo"), "bar") == 0);
  855. ASSERT(strcmp(sg_strmap_get(*headers, "lorem"), "ipsum") == 0);
  856. ASSERT(strcmp(sg_strmap_get(*headers, "Set-Cookie"), "my=cookie") == 0);
  857. ASSERT(res->status == 200);
  858. ASSERT(sg_httpres_reset(res) == 0);
  859. ASSERT(sg_httpres_reset(res) == 0);
  860. ASSERT(!res->handle);
  861. ASSERT(sg_strmap_get(*headers, "foo"));
  862. ASSERT(sg_strmap_get(*headers, "lorem"));
  863. ASSERT(sg_strmap_get(*headers, "Set-Cookie"));
  864. ASSERT(res->status == 500);
  865. }
  866. static void test_httpres_clear(struct sg_httpres *res) {
  867. struct sg_strmap **headers;
  868. ASSERT(sg_httpres_clear(NULL) == EINVAL);
  869. headers = sg_httpres_headers(res);
  870. ASSERT(sg_strmap_add(headers, "foo", "bar") == 0);
  871. ASSERT(sg_strmap_add(headers, "lorem", "ipsum") == 0);
  872. ASSERT(sg_httpres_set_cookie(res, "my", "cookie") == 0);
  873. ASSERT(sg_httpres_send(res, "", "", 200) == 0);
  874. ASSERT(res->handle);
  875. ASSERT(strcmp(sg_strmap_get(*headers, "foo"), "bar") == 0);
  876. ASSERT(strcmp(sg_strmap_get(*headers, "lorem"), "ipsum") == 0);
  877. ASSERT(strcmp(sg_strmap_get(*headers, "Set-Cookie"), "my=cookie") == 0);
  878. ASSERT(res->status == 200);
  879. ASSERT(sg_httpres_clear(res) == 0);
  880. ASSERT(sg_httpres_clear(res) == 0);
  881. ASSERT(!res->handle);
  882. ASSERT(!sg_strmap_get(*headers, "foo"));
  883. ASSERT(!sg_strmap_get(*headers, "lorem"));
  884. ASSERT(!sg_strmap_get(*headers, "Set-Cookie"));
  885. ASSERT(res->status == 500);
  886. }
  887. static void test_httpres_is_empty(struct sg_httpres *res) {
  888. errno = 0;
  889. ASSERT(!sg_httpres_is_empty(NULL));
  890. ASSERT(errno == EINVAL);
  891. errno = 0;
  892. ASSERT(sg_httpres_send(res, "", "text/plain", 200) == 0);
  893. ASSERT(!sg_httpres_is_empty(res));
  894. ASSERT(errno == 0);
  895. MHD_destroy_response(res->handle);
  896. res->handle = NULL;
  897. ASSERT(sg_httpres_is_empty(res));
  898. ASSERT(errno == 0);
  899. }
  900. int main(void) {
  901. struct sg_httpres *res = sg__httpres_new(NULL);
  902. ASSERT(res);
  903. test__httpres_new();
  904. test__httpres_free();
  905. test__httpres_dispatch(res);
  906. test_httpres_headers(res);
  907. test_httpres_set_cookie(res);
  908. test_httpres_send(res);
  909. test_httpres_sendbinary(res);
  910. test_httpres_download(res);
  911. test_httpres_render(res);
  912. test_httpres_sendfile2(res);
  913. test_httpres_sendfile(res);
  914. test_httpres_sendstream(res);
  915. #ifdef SG_HTTP_COMPRESSION
  916. test_httpres_zsend(res);
  917. test_httpres_zsendbinary2(res);
  918. test_httpres_zsendbinary(res);
  919. test_httpres_zsendstream2(res);
  920. test_httpres_zsendstream(res);
  921. test_httpres_zdownload(res);
  922. test_httpres_zrender(res);
  923. test_httpres_zsendfile2(res);
  924. test_httpres_zsendfile(res);
  925. #endif /* SG_HTTP_COMPRESSION */
  926. test_httpres_reset(res);
  927. test_httpres_clear(res);
  928. test_httpres_is_empty(res);
  929. sg__httpres_free(res);
  930. return EXIT_SUCCESS;
  931. }