test_utils.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /* _
  2. * ___ __ _ __ _ _ _(_)
  3. * / __|/ _` |/ _` | | | | |
  4. * \__ \ (_| | (_| | |_| | |
  5. * |___/\__,_|\__, |\__,_|_|
  6. * |___/
  7. *
  8. * Cross-platform library which helps to develop web servers or frameworks.
  9. *
  10. * Copyright (C) 2016-2024 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. #include "sg_assert.h"
  27. #include <stdlib.h>
  28. #include <errno.h>
  29. #include <string.h>
  30. #ifdef _WIN32
  31. #include <ws2tcpip.h>
  32. #include <winsock2.h>
  33. #include <windows.h>
  34. #else /* _WIN32 */
  35. #include <sys/socket.h>
  36. #endif /* _WIN32 */
  37. #include "sg_macros.h"
  38. #include "sg_utils.h"
  39. #include <sagui.h>
  40. static void test__strdup(void) {
  41. char *str1, *str2;
  42. ASSERT(!sg__strdup(NULL));
  43. str1 = sg__strdup("");
  44. ASSERT(strcmp(str1, "") == 0);
  45. sg_free(str1);
  46. str1 = sg__strdup("abc123");
  47. ASSERT(strcmp(str1, "abc123") == 0);
  48. str2 = sg__strdup(str1);
  49. ASSERT(str1 != str2);
  50. ASSERT(strcmp(str1, str2) == 0);
  51. sg_free(str1);
  52. sg_free(str2);
  53. }
  54. static void test__pow(void) {
  55. ASSERT(sg__pow(1, 2) == 0);
  56. }
  57. static void test__fmod(void) {
  58. ASSERT(sg__fmod(1, 2) == 0);
  59. }
  60. static void test__toasciilower(void) {
  61. char str[100];
  62. memset(str, 0, sizeof(str));
  63. ASSERT(strcmp(str, "") == 0);
  64. sg__toasciilower(str);
  65. ASSERT(strcmp(str, "") == 0);
  66. sprintf(str, "A");
  67. ASSERT(strcmp(str, "A") == 0);
  68. sg__toasciilower(str);
  69. ASSERT(strcmp(str, "a") == 0);
  70. sprintf(str, "ABC");
  71. sg__toasciilower(str);
  72. ASSERT(strcmp(str, "abc") == 0);
  73. sprintf(str, "ABC123 def456");
  74. sg__toasciilower(str);
  75. ASSERT(strcmp(str, "abc123 def456") == 0);
  76. sprintf(str, "ABC");
  77. sg__toasciilower(str);
  78. ASSERT(strcmp(str, "abc") == 0);
  79. sprintf(str, "ABÇñãÁÊD");
  80. sg__toasciilower(str);
  81. ASSERT(strcmp(str, "abÇñãÁÊd") == 0);
  82. }
  83. static void test__strjoin(void) {
  84. char *str;
  85. ASSERT(!sg__strjoin(0, "", ""));
  86. ASSERT(!sg__strjoin('/', NULL, ""));
  87. ASSERT(!sg__strjoin('/', "", NULL));
  88. str = sg__strjoin('/', "", "");
  89. ASSERT(strcmp(str, "") == 0);
  90. sg_free(str);
  91. str = sg__strjoin('/', "abc", "");
  92. ASSERT(strcmp(str, "abc") == 0);
  93. sg_free(str);
  94. str = sg__strjoin('/', "", "123");
  95. ASSERT(strcmp(str, "123") == 0);
  96. sg_free(str);
  97. str = sg__strjoin('/', "abc", "123");
  98. ASSERT(strcmp(str, "abc/123") == 0);
  99. sg_free(str);
  100. str = sg__strjoin('/', "a", "b");
  101. ASSERT(strcmp(str, "a/b") == 0);
  102. sg_free(str);
  103. }
  104. static void test__is_cookie_name(void) {
  105. char *str = strdup("");
  106. ASSERT(sg__is_cookie_name(str));
  107. sg_free(str);
  108. str = strdup("a");
  109. ASSERT(sg__is_cookie_name(str));
  110. sg_free(str);
  111. str = strdup("abc");
  112. ASSERT(sg__is_cookie_name(str));
  113. sg_free(str);
  114. str = strdup("abc_123");
  115. ASSERT(sg__is_cookie_name(str));
  116. sg_free(str);
  117. str = strdup("123_abc");
  118. ASSERT(sg__is_cookie_name(str));
  119. sg_free(str);
  120. str = strdup("abc-123");
  121. ASSERT(!sg__is_cookie_name(str));
  122. sg_free(str);
  123. str = strdup("abc 123");
  124. ASSERT(!sg__is_cookie_name(str));
  125. sg_free(str);
  126. str = strdup("abc|123");
  127. ASSERT(!sg__is_cookie_name(str));
  128. sg_free(str);
  129. str = strdup("abç");
  130. ASSERT(!sg__is_cookie_name(str));
  131. sg_free(str);
  132. str = strdup("abc\a123");
  133. ASSERT(!sg__is_cookie_name(str));
  134. sg_free(str);
  135. str = strdup("abc(123");
  136. ASSERT(!sg__is_cookie_name(str));
  137. sg_free(str);
  138. str = strdup("abc)123");
  139. ASSERT(!sg__is_cookie_name(str));
  140. sg_free(str);
  141. str = strdup("abc<123");
  142. ASSERT(!sg__is_cookie_name(str));
  143. sg_free(str);
  144. str = strdup("abc>123");
  145. ASSERT(!sg__is_cookie_name(str));
  146. sg_free(str);
  147. str = strdup("abc@123");
  148. ASSERT(!sg__is_cookie_name(str));
  149. sg_free(str);
  150. str = strdup("abc,123");
  151. ASSERT(!sg__is_cookie_name(str));
  152. sg_free(str);
  153. str = strdup("abc;123");
  154. ASSERT(!sg__is_cookie_name(str));
  155. sg_free(str);
  156. str = strdup("abc:123");
  157. ASSERT(!sg__is_cookie_name(str));
  158. sg_free(str);
  159. str = strdup("abc\\123");
  160. ASSERT(!sg__is_cookie_name(str));
  161. sg_free(str);
  162. str = strdup("abc\"123");
  163. ASSERT(!sg__is_cookie_name(str));
  164. sg_free(str);
  165. str = strdup("abc/123");
  166. ASSERT(!sg__is_cookie_name(str));
  167. sg_free(str);
  168. str = strdup("abc[123");
  169. ASSERT(!sg__is_cookie_name(str));
  170. sg_free(str);
  171. str = strdup("abc]123");
  172. ASSERT(!sg__is_cookie_name(str));
  173. sg_free(str);
  174. str = strdup("abc?123");
  175. ASSERT(!sg__is_cookie_name(str));
  176. sg_free(str);
  177. str = strdup("abc=123");
  178. ASSERT(!sg__is_cookie_name(str));
  179. sg_free(str);
  180. str = strdup("abc{123");
  181. ASSERT(!sg__is_cookie_name(str));
  182. sg_free(str);
  183. str = strdup("abc}123");
  184. ASSERT(!sg__is_cookie_name(str));
  185. sg_free(str);
  186. }
  187. static void test__is_cookie_val(void) {
  188. char *str = strdup("");
  189. ASSERT(sg__is_cookie_val(str));
  190. sg_free(str);
  191. str = strdup("a");
  192. ASSERT(sg__is_cookie_val(str));
  193. sg_free(str);
  194. str = strdup("abc");
  195. ASSERT(sg__is_cookie_val(str));
  196. sg_free(str);
  197. str = strdup("abc_123");
  198. ASSERT(sg__is_cookie_val(str));
  199. sg_free(str);
  200. str = strdup("123_abc");
  201. ASSERT(sg__is_cookie_val(str));
  202. sg_free(str);
  203. str = strdup("abc=123");
  204. ASSERT(sg__is_cookie_val(str));
  205. sg_free(str);
  206. str = strdup("abc-123");
  207. ASSERT(sg__is_cookie_val(str));
  208. sg_free(str);
  209. str = strdup("\"abc123\"");
  210. ASSERT(sg__is_cookie_val(str));
  211. sg_free(str);
  212. str = strdup("abc 123");
  213. ASSERT(sg__is_cookie_val(str));
  214. sg_free(str);
  215. str = strdup("abc\"123");
  216. ASSERT(sg__is_cookie_val(str));
  217. sg_free(str);
  218. str = strdup("abc,123");
  219. ASSERT(sg__is_cookie_val(str));
  220. sg_free(str);
  221. str = strdup("abc;123");
  222. ASSERT(sg__is_cookie_val(str));
  223. sg_free(str);
  224. str = strdup("abc\\123");
  225. ASSERT(sg__is_cookie_val(str));
  226. sg_free(str);
  227. str = strdup("abc\a123");
  228. ASSERT(!sg__is_cookie_val(str));
  229. sg_free(str);
  230. }
  231. static void test_version(void) {
  232. const char *ver_original;
  233. char ver_local[9];
  234. size_t ver_len;
  235. ASSERT(sg_version() == ((SG_VERSION_MAJOR << 16) | (SG_VERSION_MINOR << 8) |
  236. (SG_VERSION_PATCH)));
  237. ver_original = sg_version_str();
  238. ASSERT(ver_original);
  239. ver_len = strlen(ver_original);
  240. ASSERT(ver_len > 0);
  241. sprintf(ver_local, "%d.%d.%d", SG_VERSION_MAJOR, SG_VERSION_MINOR,
  242. SG_VERSION_PATCH);
  243. ASSERT(strcmp(ver_original, ver_local) == 0);
  244. ASSERT(ver_original[ver_len] == '\0');
  245. }
  246. static int mm_tester = 0;
  247. static void *mm_malloc(size_t size) {
  248. mm_tester = size;
  249. return &mm_tester;
  250. }
  251. static void *mm_realloc(void *ptr, size_t size) {
  252. *((int *) ptr) = size;
  253. return ptr;
  254. }
  255. static void mm_free(void *ptr) {
  256. *((int *) ptr) = 0;
  257. }
  258. static void test_mm_set(void) {
  259. ASSERT(sg_mm_set(NULL, mm_realloc, mm_free) == EINVAL);
  260. ASSERT(sg_mm_set(mm_malloc, NULL, mm_free) == EINVAL);
  261. ASSERT(sg_mm_set(mm_malloc, mm_realloc, NULL) == EINVAL);
  262. ASSERT(sg_mm_set(mm_malloc, mm_realloc, mm_free) == 0);
  263. mm_tester = 0;
  264. ASSERT(sg_malloc(123) == &mm_tester);
  265. ASSERT(mm_tester == 123);
  266. ASSERT(sg_realloc(&mm_tester, 456) == &mm_tester);
  267. ASSERT(mm_tester == 456);
  268. sg_free(&mm_tester);
  269. ASSERT(mm_tester == 0);
  270. sg_mm_set(malloc, realloc, free);
  271. }
  272. static void test_malloc(void) {
  273. char *buf;
  274. #define TEST_MEM_BUF_LEN 10
  275. buf = sg_malloc(TEST_MEM_BUF_LEN);
  276. ASSERT(buf);
  277. memset(buf, 'a', TEST_MEM_BUF_LEN - 1);
  278. buf[TEST_MEM_BUF_LEN - 1] = '\0';
  279. ASSERT(strlen(buf) == TEST_MEM_BUF_LEN - 1);
  280. #undef TEST_MEM_BUF_LEN
  281. sg_free(buf);
  282. }
  283. static void test_alloc(void) {
  284. char *buf;
  285. #define TEST_MEM_BUF_LEN 10
  286. buf = sg_alloc(TEST_MEM_BUF_LEN);
  287. ASSERT(buf);
  288. for (unsigned char i = 0; i < TEST_MEM_BUF_LEN; i++)
  289. ASSERT(buf[i] == 0);
  290. memset(buf, 'a', TEST_MEM_BUF_LEN - 1);
  291. buf[TEST_MEM_BUF_LEN - 1] = '\0';
  292. ASSERT(strlen(buf) == TEST_MEM_BUF_LEN - 1);
  293. #undef TEST_MEM_BUF_LEN
  294. sg_free(buf);
  295. }
  296. static void test_realloc(void) {
  297. char *buf;
  298. #define TEST_MEM_BUF_LEN 10
  299. buf = sg_alloc(TEST_MEM_BUF_LEN / 2);
  300. ASSERT(buf);
  301. buf = sg_realloc(buf, TEST_MEM_BUF_LEN);
  302. ASSERT(buf);
  303. memset(buf, 'a', TEST_MEM_BUF_LEN - 1);
  304. buf[TEST_MEM_BUF_LEN - 1] = '\0';
  305. ASSERT(strlen(buf) == TEST_MEM_BUF_LEN - 1);
  306. #undef TEST_MEM_BUF_LEN
  307. sg_free(buf);
  308. }
  309. static void test_free(void) {
  310. sg_free(NULL);
  311. }
  312. static double math_tester_x = 0;
  313. static double math_tester_y = 0;
  314. static double math_pow(double x, double y) {
  315. math_tester_x = x;
  316. math_tester_y = y;
  317. return 789;
  318. }
  319. static double math_fmod(double x, double y) {
  320. math_tester_x = x;
  321. math_tester_y = y;
  322. return 789;
  323. }
  324. static void test_math_set(void) {
  325. ASSERT(sg_math_set(NULL, math_fmod) == EINVAL);
  326. ASSERT(sg_math_set(math_pow, NULL) == EINVAL);
  327. ASSERT(sg_math_set(math_pow, math_fmod) == 0);
  328. math_tester_x = 0;
  329. math_tester_y = 0;
  330. ASSERT(sg__pow(123, 456) == 789);
  331. ASSERT(math_tester_x == 123);
  332. ASSERT(math_tester_y == 456);
  333. math_tester_x = 0;
  334. math_tester_y = 0;
  335. ASSERT(sg__fmod(123, 456) == 789);
  336. ASSERT(math_tester_x == 123);
  337. ASSERT(math_tester_y == 456);
  338. sg_math_set(sg__pow, sg__fmod);
  339. }
  340. static void test_strerror(void) {
  341. char err[256];
  342. ASSERT(!sg_strerror(0, NULL, sizeof(err)));
  343. ASSERT(!sg_strerror(0, err, 0));
  344. ASSERT(sg_strerror(EINTR, err, sizeof(err)) == err);
  345. ASSERT(strcmp(err, strerror(EINTR)) == 0);
  346. ASSERT(sg_strerror(EINVAL, err, sizeof(err)) == err);
  347. ASSERT(strcmp(err, strerror(EINVAL)) == 0);
  348. }
  349. static void test_is_post(void) {
  350. ASSERT(!sg_is_post(NULL));
  351. ASSERT(!sg_is_post(""));
  352. ASSERT(!sg_is_post("abc"));
  353. ASSERT(!sg_is_post("GET"));
  354. ASSERT(!sg_is_post("HEAD"));
  355. ASSERT(sg_is_post("POST"));
  356. ASSERT(sg_is_post("PUT"));
  357. ASSERT(sg_is_post("DELETE"));
  358. ASSERT(sg_is_post("OPTIONS"));
  359. }
  360. static void test_extract_entrypoint(void) {
  361. char *str;
  362. errno = 0;
  363. ASSERT(!sg_extract_entrypoint(NULL));
  364. ASSERT(errno == EINVAL);
  365. ASSERT((str = sg_extract_entrypoint("")));
  366. ASSERT(strcmp(str, "/") == 0);
  367. sg_free(str);
  368. ASSERT((str = sg_extract_entrypoint("/")));
  369. ASSERT(strcmp(str, "/") == 0);
  370. sg_free(str);
  371. ASSERT((str = sg_extract_entrypoint("//")));
  372. ASSERT(strcmp(str, "/") == 0);
  373. sg_free(str);
  374. ASSERT((str = sg_extract_entrypoint("///////")));
  375. ASSERT(strcmp(str, "/") == 0);
  376. sg_free(str);
  377. ASSERT((str = sg_extract_entrypoint("foo")));
  378. ASSERT(strcmp(str, "/foo") == 0);
  379. sg_free(str);
  380. ASSERT((str = sg_extract_entrypoint("/foo")));
  381. ASSERT(strcmp(str, "/foo") == 0);
  382. sg_free(str);
  383. ASSERT((str = sg_extract_entrypoint("//foo")));
  384. ASSERT(strcmp(str, "/foo") == 0);
  385. sg_free(str);
  386. ASSERT((str = sg_extract_entrypoint("///////foo")));
  387. ASSERT(strcmp(str, "/foo") == 0);
  388. sg_free(str);
  389. ASSERT((str = sg_extract_entrypoint("foo/")));
  390. ASSERT(strcmp(str, "/foo") == 0);
  391. sg_free(str);
  392. ASSERT((str = sg_extract_entrypoint("foo//")));
  393. ASSERT(strcmp(str, "/foo") == 0);
  394. sg_free(str);
  395. ASSERT((str = sg_extract_entrypoint("/foo/")));
  396. ASSERT(strcmp(str, "/foo") == 0);
  397. sg_free(str);
  398. ASSERT((str = sg_extract_entrypoint("///foo///")));
  399. ASSERT(strcmp(str, "/foo") == 0);
  400. sg_free(str);
  401. ASSERT((str = sg_extract_entrypoint("/foo/bar")));
  402. ASSERT(strcmp(str, "/foo") == 0);
  403. sg_free(str);
  404. ASSERT((str = sg_extract_entrypoint("///foo/bar")));
  405. ASSERT(strcmp(str, "/foo") == 0);
  406. sg_free(str);
  407. ASSERT((str = sg_extract_entrypoint("/foo///bar")));
  408. ASSERT(strcmp(str, "/foo") == 0);
  409. sg_free(str);
  410. ASSERT((str = sg_extract_entrypoint("///foo///bar")));
  411. ASSERT(strcmp(str, "/foo") == 0);
  412. sg_free(str);
  413. ASSERT((str = sg_extract_entrypoint("/a")));
  414. ASSERT(strcmp(str, "/a") == 0);
  415. sg_free(str);
  416. ASSERT((str = sg_extract_entrypoint("/a/b")));
  417. ASSERT(strcmp(str, "/a") == 0);
  418. sg_free(str);
  419. ASSERT((str = sg_extract_entrypoint("//a/b")));
  420. ASSERT(strcmp(str, "/a") == 0);
  421. sg_free(str);
  422. ASSERT((str = sg_extract_entrypoint("//a//b")));
  423. ASSERT(strcmp(str, "/a") == 0);
  424. sg_free(str);
  425. }
  426. static void test_tmpdir(void) {
  427. #ifdef _WIN32
  428. char path[MAX_PATH + 1];
  429. size_t len;
  430. #endif /* _WIN32 */
  431. char *tmp = sg_tmpdir();
  432. ASSERT(tmp != NULL);
  433. #if defined(_WIN32)
  434. len = GetTempPath(MAX_PATH + 1, path);
  435. if (path[len - 1] == '\\') {
  436. len--;
  437. path[len] = '\0';
  438. }
  439. ASSERT(strcmp(tmp, path) == 0);
  440. #elif defined(__ANDROID__) /* _WIN32 */
  441. ASSERT(strcmp(tmp, "/data/local/tmp") == 0);
  442. #elif defined(__APPLE__) /* __ANDROID__*/
  443. ASSERT(strncmp(tmp, getenv("TMPDIR"), strlen(tmp)) == 0);
  444. #else /* __APPLE__ */
  445. ASSERT(strcmp(tmp, "/tmp") == 0);
  446. #endif /* _WIN32 */
  447. sg_free(tmp);
  448. }
  449. static void test_ip(void) {
  450. struct sockaddr sa;
  451. char buf[46];
  452. memset(&sa, 0, sizeof(struct sockaddr));
  453. ASSERT(sg_ip(NULL, buf, sizeof(buf)) == EINVAL);
  454. ASSERT(sg_ip(&sa, NULL, sizeof(buf)) == EINVAL);
  455. ASSERT(sg_ip(&sa, buf, -1) == EINVAL);
  456. sa.sa_family = AF_INET;
  457. ASSERT(sg_ip(&sa, buf, sizeof(buf)) == 0);
  458. ASSERT(strcmp(buf, "0.0.0.0") == 0);
  459. /* we do not need massive testing for inet_ntop() since it is already tested by the glibc team. */
  460. }
  461. int main(void) {
  462. test__strdup();
  463. test__pow();
  464. test__fmod();
  465. test__toasciilower();
  466. test__strjoin();
  467. test__is_cookie_name();
  468. test__is_cookie_val();
  469. test_version();
  470. test_mm_set();
  471. test_malloc();
  472. test_alloc();
  473. test_realloc();
  474. test_free();
  475. test_math_set();
  476. test_strerror();
  477. test_is_post();
  478. test_extract_entrypoint();
  479. test_tmpdir();
  480. test_ip();
  481. return EXIT_SUCCESS;
  482. }