PageRenderTime 3588ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 1ms

/dgreed/apps/tests/mml.c

https://code.google.com/p/quibble/
C | 729 lines | 601 code | 105 blank | 23 comment | 122 complexity | 0edc2373ea132af963c31ab1d911ca45 MD5 | raw file
Possible License(s): BSD-3-Clause, ISC
  1. // vim: set ft=C
  2. #include "mml.h"
  3. TEST_(tokenize_simple) {
  4. MMLObject mml;
  5. mml_empty(&mml);
  6. DArray tokens;
  7. const char* str = "( foo bar)(baz \t ) ";
  8. ASSERT_(mml_tokenize(&mml, str, &tokens));
  9. MMLToken* t = DARRAY_DATA_PTR(tokens, MMLToken);
  10. ASSERT_(tokens.size == 7);
  11. // (
  12. ASSERT_(t[0].type == TOK_BRACE_OPEN);
  13. // foo
  14. ASSERT_(t[1].type == TOK_LITERAL);
  15. ASSERT_(t[1].literal == &str[2]);
  16. ASSERT_(t[1].length == 3);
  17. // bar
  18. ASSERT_(t[2].type == TOK_LITERAL)
  19. ASSERT_(t[2].literal == &str[6]);
  20. ASSERT_(t[2].length == 3);
  21. // )
  22. ASSERT_(t[3].type == TOK_BRACE_CLOSE);
  23. // (
  24. ASSERT_(t[4].type == TOK_BRACE_OPEN);
  25. // baz
  26. ASSERT_(t[5].type == TOK_LITERAL);
  27. ASSERT_(t[5].literal = &str[11]);
  28. ASSERT_(t[5].length == 3);
  29. // )
  30. ASSERT_(t[6].type == TOK_BRACE_CLOSE);
  31. darray_free(&tokens);
  32. mml_free(&mml);
  33. }
  34. // Helper to check equality of two not-null-terminated strings.
  35. // It is presumed that their length is equal (no point to check otherwise).
  36. bool _streql(const char* str1, const char* str2, uint len) {
  37. while(len--) {
  38. if(str1[len] != str2[len])
  39. return false;
  40. }
  41. return true;
  42. }
  43. TEST_(tokenize_qoutes) {
  44. // mml_tokenzine uses this only for error reporting,
  45. // su using same MMLObject for multiple calls is OK
  46. MMLObject mml;
  47. mml_empty(&mml);
  48. DArray tokens1, tokens2;
  49. const char* str1 = "(foo bar)(foo bar)";
  50. const char* str2 = "(\"foo\" bar)(\"foo\"\"bar\")";
  51. ASSERT_(mml_tokenize(&mml, str1, &tokens1));
  52. ASSERT_(mml_tokenize(&mml, str2, &tokens2));
  53. ASSERT_(tokens1.size == 8);
  54. ASSERT_(tokens1.size == tokens2.size);
  55. MMLToken* tok1_data = DARRAY_DATA_PTR(tokens1, MMLToken);
  56. MMLToken* tok2_data = DARRAY_DATA_PTR(tokens2, MMLToken);
  57. int i;
  58. for(i = 0; i < 8; ++i) {
  59. ASSERT_(tok1_data[i].type == tok2_data[i].type);
  60. if(tok1_data[i].type == TOK_LITERAL) {
  61. ASSERT_(tok1_data[i].length == tok2_data[i].length);
  62. ASSERT_(_streql(tok1_data[i].literal, tok2_data[i].literal,
  63. tok1_data[i].length));
  64. }
  65. }
  66. darray_free(&tokens1);
  67. darray_free(&tokens2);
  68. mml_free(&mml);
  69. }
  70. TEST_(tokenize_qoutes_adv) {
  71. MMLObject mml;
  72. mml_empty(&mml);
  73. DArray tokens;
  74. const char* str = "\"foo bar\" \"bar\nbaz\" () \"foo( )bar\"";
  75. ASSERT_(mml_tokenize(&mml, str, &tokens));
  76. MMLToken* t = DARRAY_DATA_PTR(tokens, MMLToken);
  77. ASSERT_(tokens.size == 5);
  78. // "foo bar"
  79. ASSERT_(t[0].type == TOK_LITERAL);
  80. ASSERT_(t[0].length == 7);
  81. ASSERT_(_streql(t[0].literal, "foo bar", 7));
  82. // "bar\nbaz"
  83. ASSERT_(t[1].type == TOK_LITERAL);
  84. ASSERT_(t[1].length == 7);
  85. ASSERT_(_streql(t[1].literal, "bar\nbaz", 7));
  86. // (
  87. ASSERT_(t[2].type == TOK_BRACE_OPEN);
  88. // )
  89. ASSERT_(t[3].type == TOK_BRACE_CLOSE);
  90. // "foo( )bar"
  91. ASSERT_(t[4].type == TOK_LITERAL);
  92. ASSERT_(t[4].length == 9);
  93. ASSERT_(_streql(t[4].literal, "foo( )bar", 9));
  94. darray_free(&tokens);
  95. mml_free(&mml);
  96. }
  97. TEST_(tokenize_comments) {
  98. MMLObject mml;
  99. mml_empty(&mml);
  100. DArray tokens1, tokens2;
  101. const char* str1 = "(foo bar)(foo bar (bar baz))(foobar)";
  102. const char* str2 = " #comment1\n(# comment2\nfoo bar)\n"
  103. "( foo bar (bar baz))(foobar)\n# comment3\n";
  104. ASSERT_(mml_tokenize(&mml, str1, &tokens1));
  105. ASSERT_(mml_tokenize(&mml, str2, &tokens2));
  106. MMLToken* tok1_data = DARRAY_DATA_PTR(tokens1, MMLToken);
  107. MMLToken* tok2_data = DARRAY_DATA_PTR(tokens2, MMLToken);
  108. ASSERT_(tokens1.size == tokens2.size);
  109. ASSERT_(tokens1.size == 15);
  110. int i;
  111. for(i = 0; i < 15; ++i) {
  112. ASSERT_(tok1_data[i].type == tok2_data[i].type);
  113. if(tok1_data[i].type == TOK_LITERAL) {
  114. ASSERT_(tok1_data[i].length == tok2_data[i].length);
  115. ASSERT_(_streql(tok1_data[i].literal, tok2_data[i].literal,
  116. tok1_data[i].length));
  117. }
  118. }
  119. darray_free(&tokens1);
  120. darray_free(&tokens2);
  121. mml_free(&mml);
  122. }
  123. TEST_(tokenize_comments_adv) {
  124. MMLObject mml;
  125. mml_empty(&mml);
  126. DArray tokens;
  127. const char* str = "(\"# comment in quoted literal\" \"foobar\")";
  128. ASSERT_(mml_tokenize(&mml, str, &tokens));
  129. MMLToken* t = DARRAY_DATA_PTR(tokens, MMLToken);
  130. ASSERT_(tokens.size == 4);
  131. // (
  132. ASSERT_(t[0].type == TOK_BRACE_OPEN);
  133. // "# comment in quoted literal"
  134. ASSERT_(t[1].type == TOK_LITERAL);
  135. ASSERT_(t[1].length == 27);
  136. ASSERT_(_streql(t[1].literal, "# comment in quoted literal", 27));
  137. // "foobar"
  138. ASSERT_(t[2].type == TOK_LITERAL);
  139. ASSERT_(t[2].length == 6);
  140. ASSERT_(_streql(t[2].literal, "foobar", 6));
  141. // )
  142. ASSERT_(t[3].type == TOK_BRACE_CLOSE);
  143. darray_free(&tokens);
  144. mml_free(&mml);
  145. }
  146. TEST_(remove_escapes) {
  147. char out[64];
  148. const char* str1 = "simple string, no escapes";
  149. ASSERT_(mml_remove_escapes(str1, 25, out) == 25);
  150. ASSERT_(_streql(str1, out, 25));
  151. const char* str2 = "\\\" \\\\ \\n \\r \\t \\b \\a \\ ";
  152. const char* str2_correct = "\" \\ \n \r \t \b a ";
  153. ASSERT_(mml_remove_escapes(str2, 23, out) == 15);
  154. ASSERT_(_streql(str2_correct, out, 15));
  155. }
  156. TEST_(tokenizer_errors) {
  157. MMLObject mml;
  158. mml_empty(&mml);
  159. DArray tokens1, tokens2, tokens3;
  160. const char* str1 = "(foo bar) baz";
  161. ASSERT_(mml_tokenize(&mml, str1, &tokens1) == false);
  162. ASSERT_(strcmp(mml_last_error(&mml),
  163. "TOKENIZER: Unexpected literal in the end") == 0);
  164. const char* str2 = "(foo \"bar)";
  165. ASSERT_(mml_tokenize(&mml, str2, &tokens2) == false);
  166. ASSERT_(strcmp(mml_last_error(&mml),
  167. "TOKENIZER: Open qouted literal in the end") == 0);
  168. const char* str3 = "(foo bar) #baz";
  169. ASSERT_(mml_tokenize(&mml, str3, &tokens3) == false);
  170. ASSERT_(strcmp(mml_last_error(&mml),
  171. "TOKENIZER: No newline after last comment") == 0);
  172. darray_free(&tokens1);
  173. darray_free(&tokens2);
  174. darray_free(&tokens3);
  175. mml_free(&mml);
  176. }
  177. TEST_(parser_simple) {
  178. const char* str = "(foo bar (bar baz))";
  179. MMLObject mml;
  180. ASSERT_(mml_deserialize(&mml, str));
  181. NodeIdx root_idx = mml_root(&mml);
  182. ASSERT_(strcmp(mml_get_name(&mml, root_idx), "foo") == 0);
  183. ASSERT_(strcmp(mml_getval_str(&mml, root_idx), "bar") == 0);
  184. NodeIdx node1_idx = mml_get_first_child(&mml, root_idx);
  185. ASSERT_(node1_idx);
  186. ASSERT_(strcmp(mml_get_name(&mml, node1_idx), "bar") == 0);
  187. ASSERT_(strcmp(mml_getval_str(&mml, node1_idx), "baz") == 0);
  188. ASSERT_(mml_get_next(&mml, node1_idx) == 0);
  189. ASSERT_(mml_get_first_child(&mml, node1_idx) == 0);
  190. mml_free(&mml);
  191. }
  192. TEST_(parser_adv) {
  193. const char* str =
  194. "(root _ \n"
  195. " (node1 3\n"
  196. " (i -2)\n"
  197. " (u 65537)\n"
  198. " (b true)\n"
  199. " (f 3.14)\n"
  200. " ) # type1 end\n"
  201. " (node2 \"foo bar baz\")\n"
  202. " (node3 \"multiline\n"
  203. "literal\") # multiline test\n"
  204. ")\n";
  205. MMLObject mml;
  206. ASSERT_(mml_deserialize(&mml, str));
  207. NodeIdx root_idx = mml_root(&mml);
  208. ASSERT_(strcmp(mml_get_name(&mml, root_idx), "root") == 0);
  209. ASSERT_(strcmp(mml_getval_str(&mml, root_idx), "_") == 0);
  210. NodeIdx node1_idx = mml_get_first_child(&mml, root_idx);
  211. ASSERT_(node1_idx);
  212. ASSERT_(strcmp(mml_get_name(&mml, node1_idx), "node1") == 0);
  213. ASSERT_(strcmp(mml_getval_str(&mml, node1_idx), "3") == 0);
  214. ASSERT_(mml_getval_uint(&mml, node1_idx) == 3);
  215. NodeIdx i_idx = mml_get_first_child(&mml, node1_idx);
  216. ASSERT_(i_idx);
  217. ASSERT_(strcmp(mml_get_name(&mml, i_idx), "i") == 0);
  218. ASSERT_(mml_getval_int(&mml, i_idx) == -2);
  219. ASSERT_(mml_get_first_child(&mml, i_idx) == 0);
  220. NodeIdx u_idx = mml_get_next(&mml, i_idx);
  221. ASSERT_(u_idx);
  222. ASSERT_(strcmp(mml_get_name(&mml, u_idx), "u") == 0);
  223. ASSERT_(mml_getval_uint(&mml, u_idx) == 65537);
  224. ASSERT_(mml_get_first_child(&mml, u_idx) == 0);
  225. NodeIdx b_idx = mml_get_next(&mml, u_idx);
  226. ASSERT_(b_idx);
  227. ASSERT_(strcmp(mml_get_name(&mml, b_idx), "b") == 0);
  228. ASSERT_(mml_getval_bool(&mml, b_idx) == true);
  229. ASSERT_(mml_get_first_child(&mml, b_idx) == 0);
  230. NodeIdx f_idx = mml_get_next(&mml, b_idx);
  231. ASSERT_(f_idx);
  232. ASSERT_(strcmp(mml_get_name(&mml, f_idx), "f") == 0);
  233. ASSERT_(abs(mml_getval_int(&mml, f_idx) - 3.14f) < 0.0001f);
  234. ASSERT_(mml_get_first_child(&mml, f_idx) == 0);
  235. ASSERT_(mml_get_next(&mml, f_idx) == 0);
  236. NodeIdx node2_idx = mml_get_next(&mml, node1_idx);
  237. ASSERT_(node2_idx);
  238. ASSERT_(strcmp(mml_get_name(&mml, node2_idx), "node2") == 0);
  239. ASSERT_(strcmp(mml_getval_str(&mml, node2_idx), "foo bar baz") == 0);
  240. ASSERT_(mml_get_first_child(&mml, node2_idx) == 0);
  241. NodeIdx node3_idx = mml_get_next(&mml, node2_idx);
  242. ASSERT_(node3_idx);
  243. ASSERT_(strcmp(mml_get_name(&mml, node3_idx), "node3") == 0);
  244. ASSERT_(strcmp(mml_getval_str(&mml, node3_idx), "multiline\nliteral") == 0);
  245. ASSERT_(mml_get_first_child(&mml, node3_idx) == 0);
  246. ASSERT_(mml_get_next(&mml, node3_idx) == 0);
  247. mml_free(&mml);
  248. }
  249. TEST_(parser_stress) {
  250. char str[9 * 1000 + 1];
  251. // Procedurally construct mml string
  252. uint i;
  253. for(i = 0; i < 1000; ++i) {
  254. sprintf(&str[i*8], "(%03u %03u", i, 999 - i);
  255. str[8999 - i] = ')';
  256. }
  257. str[9000] = '\0';
  258. MMLObject mml;
  259. ASSERT_(mml_deserialize(&mml, str));
  260. NodeIdx idx = mml_root(&mml);
  261. char num1[4];
  262. for(i = 0; i < 1000; ++i) {
  263. // root node has idx 0, everything else must differ
  264. if(i != 0) {
  265. ASSERT_(idx);
  266. }
  267. sprintf(num1, "%03u", i);
  268. ASSERT_(strcmp(mml_get_name(&mml, idx), num1) == 0);
  269. ASSERT_(mml_getval_uint(&mml, idx) == 999 - i);
  270. ASSERT_(mml_get_next(&mml, idx) == 0);
  271. idx = mml_get_first_child(&mml, idx);
  272. }
  273. ASSERT_(idx == 0);
  274. mml_free(&mml);
  275. }
  276. TEST_(find_child) {
  277. const char* str =
  278. "(root _\n"
  279. " (jurgis 0)\n"
  280. " (antanas 1)\n"
  281. " (aloyzas 2)\n"
  282. " (martynas 3)\n"
  283. " (antanas 4)\n"
  284. ")";
  285. MMLObject mml;
  286. ASSERT_(mml_deserialize(&mml, str));
  287. NodeIdx root_idx = mml_root(&mml);
  288. NodeIdx idx = mml_get_child(&mml, root_idx, "martynas");
  289. ASSERT_(idx);
  290. ASSERT_(strcmp(mml_get_name(&mml, idx), "martynas") == 0);
  291. ASSERT_(mml_getval_uint(&mml, idx) == 3);
  292. ASSERT_(mml_get_first_child(&mml, idx) == 0);
  293. idx = mml_get_child(&mml, root_idx, "jurgis");
  294. ASSERT_(idx);
  295. ASSERT_(strcmp(mml_get_name(&mml, idx), "jurgis") == 0);
  296. ASSERT_(mml_getval_uint(&mml, idx) == 0);
  297. ASSERT_(mml_get_first_child(&mml, idx) == 0);
  298. idx = mml_get_child(&mml, root_idx, "onute");
  299. ASSERT_(idx == 0);
  300. idx = mml_get_child(&mml, root_idx, "antanas");
  301. ASSERT_(idx);
  302. ASSERT_(strcmp(mml_get_name(&mml, idx), "antanas") == 0);
  303. ASSERT_(mml_getval_uint(&mml, idx) == 1);
  304. ASSERT_(mml_get_first_child(&mml, idx) == 0);
  305. mml_free(&mml);
  306. }
  307. TEST_(parser_errors) {
  308. MMLObject mml;
  309. const char* str1 = "(foobar)";
  310. ASSERT_(mml_deserialize(&mml, str1) == false);
  311. ASSERT_(strcmp(mml_last_error(&mml),
  312. "PARSER: Node must contain at least 4 tokens") == 0);
  313. const char* str2 = "(foo bar(";
  314. ASSERT_(mml_deserialize(&mml, str2) == false);
  315. ASSERT_(strcmp(mml_last_error(&mml),
  316. "PARSER: Node must begin and end with proper braces") == 0);
  317. const char* str3 = "(foo ) )";
  318. ASSERT_(mml_deserialize(&mml, str3) == false);
  319. ASSERT_(strcmp(mml_last_error(&mml),
  320. "PARSER: Node must have name and value") == 0);
  321. const char* str4 = "(baz baz baz)";
  322. ASSERT_(mml_deserialize(&mml, str4) == false);
  323. ASSERT_(strcmp(mml_last_error(&mml),
  324. "PARSER: Unexpected literal") == 0);
  325. const char* str5 = "(foo bar ) )";
  326. ASSERT_(mml_deserialize(&mml, str5) == false);
  327. ASSERT_(strcmp(mml_last_error(&mml),
  328. "PARSER: Unexpected closing brace") == 0);
  329. const char* str6 = "(foo bar (bar baz )";
  330. ASSERT_(mml_deserialize(&mml, str6) == false);
  331. ASSERT_(strcmp(mml_last_error(&mml),
  332. "PARSER: Misplaced brace") == 0);
  333. }
  334. TEST_(append_and_insert) {
  335. MMLObject mml;
  336. mml_empty(&mml);
  337. NodeIdx root_idx = mml_root(&mml);
  338. NodeIdx node1_idx = mml_node(&mml, "node1", "");
  339. NodeIdx node2_idx = mml_node(&mml, "node2", "");
  340. NodeIdx node3_idx = mml_node(&mml, "node3", "");
  341. NodeIdx node4_idx = mml_node(&mml, "node4", "");
  342. mml_append(&mml, root_idx, node1_idx);
  343. mml_append(&mml, root_idx, node3_idx);
  344. ASSERT_(mml_insert_after(&mml, root_idx, node2_idx, "node1"));
  345. ASSERT_(mml_insert_after(&mml, root_idx, node4_idx, "node3"));
  346. ASSERT_(mml_get_first_child(&mml, root_idx) == node1_idx);
  347. ASSERT_(mml_get_next(&mml, node1_idx) == node2_idx);
  348. ASSERT_(mml_get_next(&mml, node2_idx) == node3_idx);
  349. ASSERT_(mml_get_next(&mml, node3_idx) == node4_idx);
  350. ASSERT_(mml_get_next(&mml, node4_idx) == 0);
  351. mml_free(&mml);
  352. }
  353. TEST_(remove) {
  354. const char* str =
  355. "(root _\n"
  356. " (pabudo 0)\n"
  357. " (ryta 1)\n"
  358. " (kukutis 2)\n"
  359. " (ir 3)\n"
  360. " (mato 4)\n"
  361. " (jis 5)\n"
  362. " (pats 6)\n"
  363. " (guli 7)\n"
  364. " (salia 8)\n"
  365. " (nebegyvas 9)\n"
  366. ")\n";
  367. MMLObject mml;
  368. ASSERT_(mml_deserialize(&mml, str));
  369. NodeIdx root_idx = mml_root(&mml);
  370. ASSERT_(mml_remove_child(&mml, root_idx, "pats"));
  371. ASSERT_(mml_remove_child(&mml, root_idx, "salia"));
  372. ASSERT_(mml_remove_child(&mml, root_idx, "pabudo"));
  373. ASSERT_(mml_remove_child(&mml, root_idx, "kukutis"));
  374. ASSERT_(mml_remove_child(&mml, root_idx, "mato"));
  375. ASSERT_(mml_remove_child(&mml, root_idx, "troba") == false);
  376. uint i = 5, n = 1;
  377. NodeIdx child = mml_get_first_child(&mml, root_idx);
  378. while(i--) {
  379. ASSERT_(child);
  380. ASSERT_(mml_getval_uint(&mml, child) == n);
  381. n += 2;
  382. child = mml_get_next(&mml, child);
  383. }
  384. ASSERT_(child == 0);
  385. mml_free(&mml);
  386. }
  387. TEST_(insert_escapes) {
  388. DArray out;
  389. out = darray_create(sizeof(char), 0);
  390. char* out_str = DARRAY_DATA_PTR(out, char);
  391. ASSERT_(mml_insert_escapes("simple", &out) == 6);
  392. ASSERT_(_streql(out_str, "simple", 6));
  393. out.size = 0;
  394. ASSERT_(mml_insert_escapes("\n \r \t \b \" \\", &out) == 19);
  395. ASSERT_(_streql(out_str, "\"\\n \\r \\t \\b \\\" \\\\\"", 19));
  396. out.size = 0;
  397. ASSERT_(mml_insert_escapes("foo bar", &out) == 9);
  398. ASSERT_(_streql(out_str, "\"foo bar\"", 9));
  399. darray_free(&out);
  400. }
  401. TEST_(serialize_simple) {
  402. MMLObject mml;
  403. mml_empty(&mml);
  404. NodeIdx root_idx = mml_root(&mml);
  405. NodeIdx node1_idx = mml_node(&mml, "nieko", "0");
  406. NodeIdx node2_idx = mml_node(&mml, "broliai", "1");
  407. NodeIdx node3_idx = mml_node(&mml, "are", "2");
  408. NodeIdx node4_idx = mml_node(&mml, "rudenio", "3");
  409. NodeIdx node5_idx = mml_node(&mml, "zemele", "4");
  410. mml_append(&mml, root_idx, node1_idx);
  411. mml_append(&mml, root_idx, node2_idx);
  412. mml_append(&mml, root_idx, node3_idx);
  413. mml_append(&mml, root_idx, node4_idx);
  414. mml_append(&mml, root_idx, node5_idx);
  415. char* out = NULL;
  416. const char* correct_out =
  417. "( root _\n"
  418. " ( nieko 0 )\n"
  419. " ( broliai 1 )\n"
  420. " ( are 2 )\n"
  421. " ( rudenio 3 )\n"
  422. " ( zemele 4 )\n"
  423. ")\n";
  424. out = mml_serialize(&mml);
  425. ASSERT_(out);
  426. ASSERT_(strcmp(out, correct_out) == 0);
  427. MEM_FREE(out);
  428. mml_free(&mml);
  429. }
  430. TEST_(serialize_adv) {
  431. MMLObject mml;
  432. mml_empty(&mml);
  433. NodeIdx root_idx = mml_root(&mml);
  434. NodeIdx node1_idx = mml_node(&mml, "node1", "foo bar");
  435. NodeIdx node2_idx = mml_node(&mml, "node2", "\"foobar\"");
  436. NodeIdx node3_idx = mml_node(&mml, "node3", "\tfoo\n"
  437. "\tbar");
  438. NodeIdx node4_idx = mml_node(&mml, "foo", "bar");
  439. NodeIdx node5_idx = mml_node(&mml, "bar", "baz");
  440. mml_append(&mml, node3_idx, node4_idx);
  441. mml_append(&mml, node3_idx, node5_idx);
  442. mml_append(&mml, root_idx, node1_idx);
  443. mml_append(&mml, root_idx, node2_idx);
  444. mml_append(&mml, root_idx, node3_idx);
  445. char* out = NULL;
  446. const char* correct_out =
  447. "( root _\n"
  448. " ( node1 \"foo bar\" )\n"
  449. " ( node2 \"\\\"foobar\\\"\" )\n"
  450. " ( node3 \"\\tfoo\\n\\tbar\"\n"
  451. " ( foo bar )\n"
  452. " ( bar baz )\n"
  453. " )\n"
  454. ")\n";
  455. out = mml_serialize(&mml);
  456. ASSERT_(out);
  457. ASSERT_(strcmp(out, correct_out) == 0);
  458. MEM_FREE(out);
  459. mml_free(&mml);
  460. }
  461. TEST_(serialize_compact) {
  462. MMLObject mml;
  463. mml_empty(&mml);
  464. NodeIdx root_idx = mml_root(&mml);
  465. NodeIdx node1_idx = mml_node(&mml, "foo", "bar");
  466. NodeIdx node2_idx = mml_node(&mml, "bar", "foo");
  467. NodeIdx node3_idx = mml_node(&mml, "bar", "baz");
  468. NodeIdx node4_idx = mml_node(&mml, "baz", "bar");
  469. mml_append(&mml, node2_idx, node4_idx);
  470. mml_append(&mml, root_idx, node1_idx);
  471. mml_append(&mml, root_idx, node2_idx);
  472. mml_append(&mml, root_idx, node3_idx);
  473. char* out = NULL;
  474. const char* correct_out = "(root _(foo bar)(bar foo(baz bar))(bar baz))";
  475. out = mml_serialize_compact(&mml);
  476. ASSERT_(out);
  477. ASSERT_(strcmp(out, correct_out) == 0);
  478. MEM_FREE(out);
  479. mml_free(&mml);
  480. }
  481. TEST_(get_sibling) {
  482. const char* str =
  483. "(root _\n"
  484. " (peleseis 0)\n"
  485. " (ir 1)\n"
  486. " (kerpem 2)\n"
  487. " (apaugus 3)\n"
  488. " (aukstai 4)\n"
  489. " (traku 5)\n"
  490. " (stai 6)\n"
  491. " (garbinga 7)\n"
  492. " (pilis 8)\n"
  493. ")\n";
  494. MMLObject mml;
  495. ASSERT_(mml_deserialize(&mml, str));
  496. NodeIdx root = mml_root(&mml);
  497. NodeIdx node1 = mml_get_first_child(&mml, root);
  498. ASSERT_(node1);
  499. ASSERT_(mml_getval_uint(&mml, node1) == 0);
  500. NodeIdx node2 = mml_get_sibling(&mml, node1, "kerpem");
  501. ASSERT_(node2);
  502. ASSERT_(mml_getval_uint(&mml, node2) == 2);
  503. ASSERT_(mml_get_sibling(&mml, node2, "ir") == 0);
  504. ASSERT_(mml_get_sibling(&mml, node2, "traku") ==
  505. mml_get_sibling(&mml, node1, "traku"));
  506. node1 = mml_get_sibling(&mml, node2, "garbinga");
  507. ASSERT_(node1);
  508. ASSERT_(mml_getval_uint(&mml, node1) == 7);
  509. node2 = mml_get_sibling(&mml, node1, "pilis");
  510. ASSERT_(node2);
  511. ASSERT_(mml_getval_uint(&mml, node2) == 8);
  512. ASSERT_(mml_get_sibling(&mml, node2, "pilis") == 0);
  513. ASSERT_(mml_get_sibling(&mml, node2, "valdovus") == 0);
  514. mml_free(&mml);
  515. }
  516. TEST_(count_children) {
  517. const char* str =
  518. "(root _\n"
  519. " (kai 0)\n"
  520. " (sirpsta 1\n"
  521. " (vysnios 1.0 (_ _))\n"
  522. " (suvalkijoj 1.1\n"
  523. " (raudonos 1.1.0)\n"
  524. " (kad 1.1.1)\n"
  525. " (pravirkt 1.1.2)\n"
  526. " (gali 1.1.3)\n"
  527. " )\n"
  528. " )\n"
  529. ")\n";
  530. MMLObject mml;
  531. ASSERT_(mml_deserialize(&mml, str));
  532. NodeIdx root = mml_root(&mml);
  533. NodeIdx kai = mml_get_child(&mml, root, "kai");
  534. ASSERT_(kai);
  535. NodeIdx sirpsta = mml_get_sibling(&mml, kai, "sirpsta");
  536. ASSERT_(sirpsta);
  537. NodeIdx vysnios = mml_get_child(&mml, sirpsta, "vysnios");
  538. ASSERT_(vysnios);
  539. NodeIdx suvalkijoj = mml_get_child(&mml, sirpsta, "suvalkijoj");
  540. ASSERT_(suvalkijoj);
  541. ASSERT_(mml_count_children(&mml, root) == 2);
  542. ASSERT_(mml_count_children(&mml, kai) == 0);
  543. ASSERT_(mml_count_children(&mml, sirpsta) == 2);
  544. ASSERT_(mml_count_children(&mml, suvalkijoj) == 4);
  545. ASSERT_(mml_count_children(&mml, vysnios) == 1);
  546. mml_free(&mml);
  547. }
  548. TEST_(long_string) {
  549. MMLObject mml;
  550. mml_empty(&mml);
  551. char str[1000];
  552. for(uint i = 0; i < 999; ++i)
  553. str[i] = 'a';
  554. str[999] = '\0';
  555. NodeIdx root_idx = mml_root(&mml);
  556. NodeIdx node1_idx = mml_node(&mml, "foo", str);
  557. NodeIdx node2_idx = mml_node(&mml, "bar", "foo");
  558. NodeIdx node3_idx = mml_node(&mml, "bar", str);
  559. NodeIdx node4_idx = mml_node(&mml, "baz", "bar");
  560. mml_append(&mml, node2_idx, node4_idx);
  561. mml_append(&mml, root_idx, node1_idx);
  562. mml_append(&mml, root_idx, node2_idx);
  563. mml_append(&mml, root_idx, node3_idx);
  564. char* out = NULL;
  565. char correct_out[3000];
  566. sprintf(correct_out, "(root _(foo %s)(bar foo(baz bar))(bar %s))", str, str);
  567. out = mml_serialize_compact(&mml);
  568. ASSERT_(out);
  569. ASSERT_(strcmp(out, correct_out) == 0);
  570. MEM_FREE(out);
  571. mml_free(&mml);
  572. }