test_lib.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <yuarel.h>
  5. #include "minunit.h"
  6. int tests_run;
  7. static int
  8. strcmp_wrap(const char *str, const char *str2)
  9. {
  10. if (NULL == str && NULL == str2) {
  11. return 0;
  12. }
  13. if (NULL == str) {
  14. return 1;
  15. }
  16. if (NULL == str2) {
  17. return -1;
  18. }
  19. return strcmp(str, str2);
  20. }
  21. #define assert_struct(as_url, as_scheme, as_user, as_pass, as_host, as_port, as_path, as_query, as_fragment) \
  22. mu_silent_assert("should set the scheme attribute correctly", 0 == strcmp_wrap(as_url.scheme, as_scheme)); \
  23. mu_silent_assert("should set the username attribute correctly", 0 == strcmp_wrap(as_url.username, as_user)); \
  24. mu_silent_assert("should set the password attribute correctly", 0 == strcmp_wrap(as_url.password, as_pass)); \
  25. mu_silent_assert("should set the host attribute correctly", 0 == strcmp_wrap(as_url.host, as_host)); \
  26. mu_silent_assert("should set the port attribute correctly", as_port == as_url.port); \
  27. mu_silent_assert("should set the path attribute correctly", 0 == strcmp_wrap(as_url.path, as_path)); \
  28. mu_silent_assert("should set the query attribute correctly", 0 == strcmp_wrap(as_url.query, as_query)); \
  29. mu_silent_assert("should set the fragment attribute correctly", 0 == strcmp_wrap(as_url.fragment, as_fragment));
  30. static unsigned char *
  31. test_parse_http_url_ok()
  32. {
  33. int rc;
  34. struct yuarel url;
  35. char *url_string;
  36. /* Minimal URL */
  37. url_string = strdup("http://example.com");
  38. rc = yuarel_parse(&url, url_string);
  39. mu_assert("minimal HTTP URL", -1 != rc);
  40. assert_struct(url, "http", NULL, NULL, "example.com", 0, NULL, NULL, NULL);
  41. free(url_string);
  42. /* With path (/) */
  43. url_string = strdup("http://example.com/");
  44. rc = yuarel_parse(&url, url_string);
  45. mu_assert("with path ('/')", -1 != rc);
  46. assert_struct(url, "http", NULL, NULL, "example.com", 0, "", NULL, NULL);
  47. free(url_string);
  48. /* With path */
  49. url_string = strdup("http://example.com/path");
  50. rc = yuarel_parse(&url, url_string);
  51. mu_assert("with path ('/path')", -1 != rc);
  52. assert_struct(url, "http", NULL, NULL, "example.com", 0, "path", NULL, NULL);
  53. free(url_string);
  54. /* With port */
  55. url_string = strdup("http://example.com:80");
  56. rc = yuarel_parse(&url, url_string);
  57. mu_assert("with port only", -1 != rc);
  58. assert_struct(url, "http", NULL, NULL, "example.com", 80, NULL, NULL, NULL);
  59. free(url_string);
  60. /* With query */
  61. url_string = strdup("http://example.com?query=only");
  62. rc = yuarel_parse(&url, url_string);
  63. mu_assert("with query only", -1 != rc);
  64. assert_struct(url, "http", NULL, NULL, "example.com", 0, NULL, "query=only", NULL);
  65. free(url_string);
  66. /* With fragment */
  67. url_string = strdup("http://example.com#frag=f1");
  68. rc = yuarel_parse(&url, url_string);
  69. mu_assert("with fragment only", -1 != rc);
  70. assert_struct(url, "http", NULL, NULL, "example.com", 0, NULL, NULL, "frag=f1");
  71. free(url_string);
  72. /* With credentials */
  73. url_string = strdup("http://u:p@example.com");
  74. rc = yuarel_parse(&url, url_string);
  75. mu_assert("with credentials only", -1 != rc);
  76. assert_struct(url, "http", "u", "p", "example.com", 0, NULL, NULL, NULL);
  77. free(url_string);
  78. /* With port and path */
  79. url_string = strdup("http://example.com:8080/port/and/path");
  80. rc = yuarel_parse(&url, url_string);
  81. mu_assert("with port and path", -1 != rc);
  82. assert_struct(url, "http", NULL, NULL, "example.com", 8080, "port/and/path", NULL, NULL);
  83. free(url_string);
  84. /* With port and query */
  85. url_string = strdup("http://example.com:8080?query=portANDquery");
  86. rc = yuarel_parse(&url, url_string);
  87. mu_assert("with port and query", -1 != rc);
  88. assert_struct(url, "http", NULL, NULL, "example.com", 8080, NULL, "query=portANDquery", NULL);
  89. free(url_string);
  90. /* With port and fragment */
  91. url_string = strdup("http://example.com:8080#f1");
  92. rc = yuarel_parse(&url, url_string);
  93. mu_assert("with port and fragment", -1 != rc);
  94. assert_struct(url, "http", NULL, NULL, "example.com", 8080, NULL, NULL, "f1");
  95. free(url_string);
  96. /* With port and credentials */
  97. url_string = strdup("http://u:p@example.com:8080");
  98. rc = yuarel_parse(&url, url_string);
  99. mu_assert("with port and credentials", -1 != rc);
  100. assert_struct(url, "http", "u", "p", "example.com", 8080, NULL, NULL, NULL);
  101. free(url_string);
  102. /* With path and query */
  103. url_string = strdup("http://example.com/path/and/query?q=yes");
  104. rc = yuarel_parse(&url, url_string);
  105. mu_assert("with path and query", -1 != rc);
  106. assert_struct(url, "http", NULL, NULL, "example.com", 0, "path/and/query", "q=yes", NULL);
  107. free(url_string);
  108. /* With path and fragment */
  109. url_string = strdup("http://example.com/path/and#fragment");
  110. rc = yuarel_parse(&url, url_string);
  111. mu_assert("with path and fragment", -1 != rc);
  112. assert_struct(url, "http", NULL, NULL, "example.com", 0, "path/and", NULL, "fragment");
  113. free(url_string);
  114. /* With query and fragment */
  115. url_string = strdup("http://example.com?q=yes#f1");
  116. rc = yuarel_parse(&url, url_string);
  117. mu_assert("with query and fragment", -1 != rc);
  118. assert_struct(url, "http", NULL, NULL, "example.com", 0, NULL, "q=yes", "f1");
  119. free(url_string);
  120. /* With query and credentials */
  121. url_string = strdup("http://u:p@example.com?q=yes");
  122. rc = yuarel_parse(&url, url_string);
  123. mu_assert("with query and credentials", -1 != rc);
  124. assert_struct(url, "http", "u", "p", "example.com", 0, NULL, "q=yes", NULL);
  125. free(url_string);
  126. /* With empty credentials */
  127. url_string = strdup("http://:@example.com");
  128. rc = yuarel_parse(&url, url_string);
  129. mu_assert("with empty credentials", -1 != rc);
  130. assert_struct(url, "http", "", "", "example.com", 0, NULL, NULL, NULL);
  131. free(url_string);
  132. /* With empty credentials and port */
  133. url_string = strdup("http://:@example.com:89");
  134. rc = yuarel_parse(&url, url_string);
  135. mu_assert("with empty credentials and port", -1 != rc);
  136. assert_struct(url, "http", "", "", "example.com", 89, NULL, NULL, NULL);
  137. free(url_string);
  138. /* Full URL */
  139. url_string = strdup("https://jack:password@localhost:8989/path/to/test?query=yes&q=jack#fragment1");
  140. rc = yuarel_parse(&url, url_string);
  141. mu_assert("with port, path and query", -1 != rc);
  142. assert_struct(url, "https", "jack", "password", "localhost", 8989, "path/to/test", "query=yes&q=jack", "fragment1");
  143. free(url_string);
  144. return 0;
  145. }
  146. static unsigned char *
  147. test_parse_http_rel_url_ok()
  148. {
  149. int rc;
  150. struct yuarel url;
  151. char *url_string;
  152. /* Minimal relative URL */
  153. url_string = strdup("/");
  154. rc = yuarel_parse(&url, url_string);
  155. mu_assert("minimal relative URL", -1 != rc);
  156. assert_struct(url, NULL, NULL, NULL, NULL, 0, "", NULL, NULL);
  157. free(url_string);
  158. /* Path only */
  159. url_string = strdup("/hejsan");
  160. rc = yuarel_parse(&url, url_string);
  161. mu_assert("path only", -1 != rc);
  162. assert_struct(url, NULL, NULL, NULL, NULL, 0, "hejsan", NULL, NULL);
  163. free(url_string);
  164. /* Path and query */
  165. url_string = strdup("/hejsan?q=yes");
  166. rc = yuarel_parse(&url, url_string);
  167. mu_assert("path only", -1 != rc);
  168. assert_struct(url, NULL, NULL, NULL, NULL, 0, "hejsan", "q=yes", NULL);
  169. free(url_string);
  170. /* Path and fragment */
  171. url_string = strdup("/hejsan#fragment");
  172. rc = yuarel_parse(&url, url_string);
  173. mu_assert("path and fragment", -1 != rc);
  174. assert_struct(url, NULL, NULL, NULL, NULL, 0, "hejsan", NULL, "fragment");
  175. free(url_string);
  176. /* Path, query and fragment */
  177. url_string = strdup("/?q=yes&q2=no#fragment");
  178. rc = yuarel_parse(&url, url_string);
  179. mu_assert("path, query and fragment", -1 != rc);
  180. assert_struct(url, NULL, NULL, NULL, NULL, 0, "", "q=yes&q2=no", "fragment");
  181. free(url_string);
  182. return 0;
  183. }
  184. static unsigned char *
  185. test_parse_url_fail()
  186. {
  187. int rc;
  188. struct yuarel url;
  189. char *url_string;
  190. /* Empty */
  191. url_string = strdup("");
  192. rc = yuarel_parse(&url, url_string);
  193. mu_assert("empty string should return -1", -1 == rc);
  194. free(url_string);
  195. /* Scheme only */
  196. url_string = strdup("rtsp://");
  197. rc = yuarel_parse(&url, url_string);
  198. mu_assert("scheme only should return -1", -1 == rc);
  199. free(url_string);
  200. /* Hostname only */
  201. url_string = strdup("hostname");
  202. rc = yuarel_parse(&url, url_string);
  203. mu_assert("hostname only should return -1", -1 == rc);
  204. free(url_string);
  205. /* Query only */
  206. url_string = strdup("?query=only");
  207. rc = yuarel_parse(&url, url_string);
  208. mu_assert("query only should return -1", -1 == rc);
  209. free(url_string);
  210. /* Missing scheme */
  211. url_string = strdup("://");
  212. rc = yuarel_parse(&url, url_string);
  213. mu_assert("missing scheme should return -1", -1 == rc);
  214. free(url_string);
  215. /* Missing hostname */
  216. url_string = strdup("rtsp://:8910/path");
  217. rc = yuarel_parse(&url, url_string);
  218. mu_assert("missing hostname should return -1", -1 == rc);
  219. free(url_string);
  220. /* Missing credentials */
  221. url_string = strdup("rtsp://@hostname:8910/path");
  222. rc = yuarel_parse(&url, url_string);
  223. mu_assert("missing credentials should return -1", -1 == rc);
  224. free(url_string);
  225. return 0;
  226. }
  227. static unsigned char *
  228. test_split_path_ok()
  229. {
  230. int rc;
  231. char *path;
  232. char *parts[10];
  233. /* Simple path */
  234. path = strdup("/this/is/a/path");
  235. rc = yuarel_split_path(path, parts, 10);
  236. mu_assert("should be able to parse a regular path", 4 == rc);
  237. mu_silent_assert("first part should be 'this'", 0 == strcmp("this", parts[0]));
  238. mu_silent_assert("second part should be 'is'", 0 == strcmp("is", parts[1]));
  239. mu_silent_assert("third part should be 'a'", 0 == strcmp("a", parts[2]));
  240. mu_silent_assert("fourth part should be 'path'", 0 == strcmp("path", parts[3]));
  241. free(path);
  242. /* Relative path */
  243. path = strdup("this/is/a/path");
  244. rc = yuarel_split_path(path, parts, 10);
  245. mu_assert("should be able to parse a relative path", 4 == rc);
  246. mu_silent_assert("first part should be 'this'", 0 == strcmp("this", parts[0]));
  247. mu_silent_assert("second part should be 'is'", 0 == strcmp("is", parts[1]));
  248. mu_silent_assert("third part should be 'a'", 0 == strcmp("a", parts[2]));
  249. mu_silent_assert("fourth part should be 'path'", 0 == strcmp("path", parts[3]));
  250. free(path);
  251. /* Path with empty parts */
  252. path = strdup("//this//is/a/path/");
  253. rc = yuarel_split_path(path, parts, 10);
  254. mu_assert("should treat multiple slashes as one", 4 == rc);
  255. mu_silent_assert("first part should be 'this'", 0 == strcmp("this", parts[0]));
  256. mu_silent_assert("second part should be 'is'", 0 == strcmp("is", parts[1]));
  257. mu_silent_assert("third part should be 'a'", 0 == strcmp("a", parts[2]));
  258. mu_silent_assert("fourth part should be 'path'", 0 == strcmp("path", parts[3]));
  259. free(path);
  260. /* Just one level */
  261. path = strdup("/one_level");
  262. rc = yuarel_split_path(path, parts, 10);
  263. mu_assert("should be able to parse a path with one level", 1 == rc);
  264. mu_silent_assert("first part should be 'this'", 0 == strcmp("one_level", parts[0]));
  265. free(path);
  266. return 0;
  267. }
  268. static unsigned char *
  269. test_parse_query_ok()
  270. {
  271. int rc;
  272. char *q;
  273. struct yuarel_param params[10];
  274. /* One param query */
  275. q = strdup("q=yes");
  276. rc = yuarel_parse_query(q, '&', params, 10);
  277. mu_assert("single parameter with value", 1 == rc);
  278. mu_silent_assert("first param key should be 'q'", 0 == strcmp("q", params[0].key));
  279. mu_silent_assert("first param val should be 'yes'", 0 == strcmp("yes", params[0].val));
  280. free(q);
  281. /* One param query without value */
  282. q = strdup("q");
  283. rc = yuarel_parse_query(q, '&', params, 10);
  284. mu_assert("single parameter without value", 1 == rc);
  285. mu_silent_assert("first param key should be 'q'", 0 == strcmp("q", params[0].key));
  286. mu_silent_assert("first param val should be NULL", NULL == params[0].val);
  287. free(q);
  288. /* Two param query */
  289. q = strdup("query=yes&a1=hello");
  290. rc = yuarel_parse_query(q, '&', params, 10);
  291. mu_assert("multiple params with value", 2 == rc);
  292. mu_silent_assert("first param key should be 'query'", 0 == strcmp("query", params[0].key));
  293. mu_silent_assert("first param val should be 'yes'", 0 == strcmp("yes", params[0].val));
  294. mu_silent_assert("second param key should be 'a1'", 0 == strcmp("a1", params[1].key));
  295. mu_silent_assert("second param val should be 'hello'", 0 == strcmp("hello", params[1].val));
  296. free(q);
  297. /* Two param query, one without value */
  298. q = strdup("query=yes&forceHttps");
  299. rc = yuarel_parse_query(q, '&', params, 10);
  300. mu_assert("multiple params one without value", 2 == rc);
  301. mu_silent_assert("first param key should be 'query'", 0 == strcmp("query", params[0].key));
  302. mu_silent_assert("first param val should be 'yes'", 0 == strcmp("yes", params[0].val));
  303. mu_silent_assert("second param key should be 'forceHttps'", 0 == strcmp("forceHttps", params[1].key));
  304. mu_silent_assert("second param val should be NULL", NULL == params[1].val);
  305. free(q);
  306. /* Three param query, all without value */
  307. q = strdup("query&forceHttps&log");
  308. rc = yuarel_parse_query(q, '&', params, 10);
  309. mu_assert("multiple params all without value", 3 == rc);
  310. mu_silent_assert("first param key should be 'query'", 0 == strcmp("query", params[0].key));
  311. mu_silent_assert("first param val should be NULL", NULL == params[0].val);
  312. mu_silent_assert("second param key should be 'forceHttps'", 0 == strcmp("forceHttps", params[1].key));
  313. mu_silent_assert("second param val should be NULL", NULL == params[1].val);
  314. mu_silent_assert("third param key should be 'log'", 0 == strcmp("log", params[2].key));
  315. mu_silent_assert("third param val should be NULL", NULL == params[2].val);
  316. free(q);
  317. /* Param with empty value */
  318. q = strdup("param=&query=no");
  319. rc = yuarel_parse_query(q, '&', params, 10);
  320. mu_assert("param with empty value", 2 == rc);
  321. mu_silent_assert("first param key should be 'param'", 0 == strcmp("param", params[0].key));
  322. mu_silent_assert("first param val should be ''", 0 == strcmp("", params[0].val));
  323. mu_silent_assert("second param key should be 'query'", 0 == strcmp("query", params[1].key));
  324. mu_silent_assert("second param val should be 'no'", 0 == strcmp("no", params[1].val));
  325. free(q);
  326. /* Double delimiter */
  327. q = strdup("param=jack&&query=no");
  328. rc = yuarel_parse_query(q, '&', params, 10);
  329. mu_assert("double delimiter", 3 == rc);
  330. mu_silent_assert("first param key should be 'param'", 0 == strcmp("param", params[0].key));
  331. mu_silent_assert("first param val should be 'jack'", 0 == strcmp("jack", params[0].val));
  332. mu_silent_assert("second param key should be ''", 0 == strcmp("", params[1].key));
  333. mu_silent_assert("second param val should be NULL", NULL == params[1].val);
  334. mu_silent_assert("third param key should be 'query'", 0 == strcmp("query", params[2].key));
  335. mu_silent_assert("third param val should be 'no'", 0 == strcmp("no", params[2].val));
  336. free(q);
  337. /* Delimiter in beginning */
  338. q = strdup("&param=jack&query=no");
  339. rc = yuarel_parse_query(q, '&', params, 10);
  340. mu_assert("delimiter in beginning", 3 == rc);
  341. mu_silent_assert("first param key should be ''", 0 == strcmp("", params[0].key));
  342. mu_silent_assert("first param val should be NULL", NULL == params[0].val);
  343. mu_silent_assert("second param key should be 'param'", 0 == strcmp("param", params[1].key));
  344. mu_silent_assert("second param val should be 'jack'", 0 == strcmp("jack", params[1].val));
  345. mu_silent_assert("third param key should be 'query'", 0 == strcmp("query", params[2].key));
  346. mu_silent_assert("third param val should be 'no'", 0 == strcmp("no", params[2].val));
  347. free(q);
  348. /* Delimiter at the end */
  349. q = strdup("param=jack&query=no&");
  350. rc = yuarel_parse_query(q, '&', params, 10);
  351. mu_assert("delimiter at the end", 3 == rc);
  352. mu_silent_assert("first param key should be 'param'", 0 == strcmp("param", params[0].key));
  353. mu_silent_assert("first param val should be 'jack'", 0 == strcmp("jack", params[0].val));
  354. mu_silent_assert("second param key should be 'query'", 0 == strcmp("query", params[1].key));
  355. mu_silent_assert("second param val should be 'no'", 0 == strcmp("no", params[1].val));
  356. mu_silent_assert("third param key should be ''", 0 == strcmp("", params[2].key));
  357. mu_silent_assert("third param val should be NULL", NULL == params[2].val);
  358. free(q);
  359. return 0;
  360. }
  361. static unsigned char *
  362. all_tests()
  363. {
  364. mu_group("yuarel_parse() with an HTTP URL");
  365. mu_run_test(test_parse_http_url_ok);
  366. mu_group("yuarel_parse() with an relative URL");
  367. mu_run_test(test_parse_http_rel_url_ok);
  368. mu_group("yuarel_parse() with faulty values");
  369. mu_run_test(test_parse_url_fail);
  370. mu_group("yuarel_split_path()");
  371. mu_run_test(test_split_path_ok);
  372. mu_group("yuarel_parse_query()");
  373. mu_run_test(test_parse_query_ok);
  374. return 0;
  375. }
  376. int
  377. main(void)
  378. {
  379. unsigned char *result;
  380. result = all_tests();
  381. if (result != 0) {
  382. exit(EXIT_FAILURE);
  383. }
  384. exit(EXIT_SUCCESS);
  385. }