ElementSerializerTest.vala 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /**
  2. * ElementSerializerTest - Unit tests for Element serialization
  3. */
  4. using Implexus.Storage;
  5. public static int main(string[] args) {
  6. int passed = 0;
  7. int failed = 0;
  8. // Test 1: Null element
  9. if (test_null_element()) {
  10. passed++;
  11. stdout.puts("PASS: test_null_element\n");
  12. } else {
  13. failed++;
  14. stdout.puts("FAIL: test_null_element\n");
  15. }
  16. // Test 2: Boolean elements
  17. if (test_bool_element()) {
  18. passed++;
  19. stdout.puts("PASS: test_bool_element\n");
  20. } else {
  21. failed++;
  22. stdout.puts("FAIL: test_bool_element\n");
  23. }
  24. // Test 3: Int64 elements
  25. if (test_int64_element()) {
  26. passed++;
  27. stdout.puts("PASS: test_int64_element\n");
  28. } else {
  29. failed++;
  30. stdout.puts("FAIL: test_int64_element\n");
  31. }
  32. // Test 4: UInt64 elements
  33. if (test_uint64_element()) {
  34. passed++;
  35. stdout.puts("PASS: test_uint64_element\n");
  36. } else {
  37. failed++;
  38. stdout.puts("FAIL: test_uint64_element\n");
  39. }
  40. // Test 5: Double elements
  41. if (test_double_element()) {
  42. passed++;
  43. stdout.puts("PASS: test_double_element\n");
  44. } else {
  45. failed++;
  46. stdout.puts("FAIL: test_double_element\n");
  47. }
  48. // Test 6: String elements
  49. if (test_string_element()) {
  50. passed++;
  51. stdout.puts("PASS: test_string_element\n");
  52. } else {
  53. failed++;
  54. stdout.puts("FAIL: test_string_element\n");
  55. }
  56. // Test 7: Binary elements
  57. if (test_binary_element()) {
  58. passed++;
  59. stdout.puts("PASS: test_binary_element\n");
  60. } else {
  61. failed++;
  62. stdout.puts("FAIL: test_binary_element\n");
  63. }
  64. // Test 8: Array elements
  65. if (test_array_element()) {
  66. passed++;
  67. stdout.puts("PASS: test_array_element\n");
  68. } else {
  69. failed++;
  70. stdout.puts("FAIL: test_array_element\n");
  71. }
  72. // Test 9: Dictionary/Properties elements
  73. if (test_dictionary_element()) {
  74. passed++;
  75. stdout.puts("PASS: test_dictionary_element\n");
  76. } else {
  77. failed++;
  78. stdout.puts("FAIL: test_dictionary_element\n");
  79. }
  80. // Test 10: Round-trip all types
  81. if (test_round_trip()) {
  82. passed++;
  83. stdout.puts("PASS: test_round_trip\n");
  84. } else {
  85. failed++;
  86. stdout.puts("FAIL: test_round_trip\n");
  87. }
  88. // Test 11: Complex nested structure
  89. if (test_nested_structure()) {
  90. passed++;
  91. stdout.puts("PASS: test_nested_structure\n");
  92. } else {
  93. failed++;
  94. stdout.puts("FAIL: test_nested_structure\n");
  95. }
  96. // Test 12: Empty array
  97. if (test_empty_array()) {
  98. passed++;
  99. stdout.puts("PASS: test_empty_array\n");
  100. } else {
  101. failed++;
  102. stdout.puts("FAIL: test_empty_array\n");
  103. }
  104. // Test 13: Empty dictionary
  105. if (test_empty_dictionary()) {
  106. passed++;
  107. stdout.puts("PASS: test_empty_dictionary\n");
  108. } else {
  109. failed++;
  110. stdout.puts("FAIL: test_empty_dictionary\n");
  111. }
  112. // Test 14: Large integers
  113. if (test_large_integers()) {
  114. passed++;
  115. stdout.puts("PASS: test_large_integers\n");
  116. } else {
  117. failed++;
  118. stdout.puts("FAIL: test_large_integers\n");
  119. }
  120. // Test 15: Special string values
  121. if (test_special_strings()) {
  122. passed++;
  123. stdout.puts("PASS: test_special_strings\n");
  124. } else {
  125. failed++;
  126. stdout.puts("FAIL: test_special_strings\n");
  127. }
  128. stdout.printf("\nResults: %d passed, %d failed\n", passed, failed);
  129. return failed > 0 ? 1 : 0;
  130. }
  131. // Test 1: Null element
  132. bool test_null_element() {
  133. try {
  134. var writer = new ElementWriter();
  135. writer.write_null();
  136. var data = writer.to_binary_data();
  137. var reader = new ElementReader(data);
  138. var element = reader.read_element();
  139. return element.is_null();
  140. } catch (StorageError e) {
  141. return false;
  142. }
  143. }
  144. // Test 2: Boolean elements
  145. bool test_bool_element() {
  146. try {
  147. // Test true
  148. var writer1 = new ElementWriter();
  149. writer1.write_element(new Invercargill.NativeElement<bool?>(true));
  150. var reader1 = new ElementReader(writer1.to_binary_data());
  151. var elem1 = reader1.read_element();
  152. if (elem1.is_null()) return false;
  153. bool val1 = elem1.as<bool?>();
  154. if (val1 != true) return false;
  155. // Test false
  156. var writer2 = new ElementWriter();
  157. writer2.write_element(new Invercargill.NativeElement<bool?>(false));
  158. var reader2 = new ElementReader(writer2.to_binary_data());
  159. var elem2 = reader2.read_element();
  160. if (elem2.is_null()) return false;
  161. bool val2 = elem2.as<bool?>();
  162. if (val2 != false) return false;
  163. return true;
  164. } catch (Error e) {
  165. return false;
  166. }
  167. }
  168. // Test 3: Int64 elements
  169. bool test_int64_element() {
  170. try {
  171. int64[] values = { 0, 1, -1, 42, -42, int64.MAX, int64.MIN };
  172. foreach (var val in values) {
  173. var writer = new ElementWriter();
  174. writer.write_element(new Invercargill.NativeElement<int64?>(val));
  175. var reader = new ElementReader(writer.to_binary_data());
  176. var elem = reader.read_element();
  177. if (elem.is_null()) return false;
  178. int64? read_val = elem.as<int64?>();
  179. if (read_val == null || (!) read_val != val) return false;
  180. }
  181. return true;
  182. } catch (Error e) {
  183. return false;
  184. }
  185. }
  186. // Test 4: UInt64 elements
  187. bool test_uint64_element() {
  188. try {
  189. uint64[] values = { 0, 1, 42, uint64.MAX };
  190. foreach (var val in values) {
  191. var writer = new ElementWriter();
  192. writer.write_element(new Invercargill.NativeElement<uint64?>(val));
  193. var reader = new ElementReader(writer.to_binary_data());
  194. var elem = reader.read_element();
  195. if (elem.is_null()) return false;
  196. uint64? read_val = elem.as<uint64?>();
  197. if (read_val == null || (!) read_val != val) return false;
  198. }
  199. return true;
  200. } catch (Error e) {
  201. return false;
  202. }
  203. }
  204. // Test 5: Double elements
  205. bool test_double_element() {
  206. try {
  207. double[] values = { 0.0, 1.0, -1.0, 3.14159, -3.14159, double.MAX, double.MIN };
  208. foreach (var val in values) {
  209. var writer = new ElementWriter();
  210. writer.write_element(new Invercargill.NativeElement<double?>(val));
  211. var reader = new ElementReader(writer.to_binary_data());
  212. var elem = reader.read_element();
  213. if (elem.is_null()) return false;
  214. double? read_val = elem.as<double?>();
  215. if (read_val == null) return false;
  216. // Use approximate comparison for doubles
  217. if (((!) read_val - val).abs() > 0.0001) return false;
  218. }
  219. return true;
  220. } catch (Error e) {
  221. return false;
  222. }
  223. }
  224. // Test 6: String elements
  225. bool test_string_element() {
  226. try {
  227. string[] values = { "", "hello", "Hello, World!", "日本語", "line1\nline2" };
  228. foreach (var val in values) {
  229. var writer = new ElementWriter();
  230. writer.write_element(new Invercargill.NativeElement<string>(val));
  231. var reader = new ElementReader(writer.to_binary_data());
  232. var elem = reader.read_element();
  233. if (elem.is_null()) return false;
  234. string read_val = elem.as<string>();
  235. if (read_val != val) return false;
  236. }
  237. return true;
  238. } catch (Error e) {
  239. return false;
  240. }
  241. }
  242. // Test 7: Binary elements
  243. bool test_binary_element() {
  244. try {
  245. // Create binary data
  246. var data = new uint8[] { 0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD };
  247. var binary = new Invercargill.DataStructures.ByteBuffer.from_byte_array(data);
  248. var writer = new ElementWriter();
  249. writer.write_element(new Invercargill.NativeElement<Invercargill.BinaryData>(binary));
  250. var reader = new ElementReader(writer.to_binary_data());
  251. var elem = reader.read_element();
  252. if (elem.is_null()) return false;
  253. var read_binary = elem.as<Invercargill.BinaryData>();
  254. var read_bytes = read_binary.to_bytes();
  255. if (read_bytes.length != data.length) return false;
  256. for (int i = 0; i < data.length; i++) {
  257. if (read_bytes.get_data()[i] != data[i]) return false;
  258. }
  259. return true;
  260. } catch (Error e) {
  261. return false;
  262. }
  263. }
  264. // Test 8: Array elements
  265. bool test_array_element() {
  266. try {
  267. var array = new Invercargill.DataStructures.Vector<Invercargill.Element>();
  268. array.add(new Invercargill.NativeElement<int64?>(1));
  269. array.add(new Invercargill.NativeElement<int64?>(2));
  270. array.add(new Invercargill.NativeElement<int64?>(3));
  271. var writer = new ElementWriter();
  272. writer.write_element(new Invercargill.NativeElement<Invercargill.Enumerable<Invercargill.Element>>(array));
  273. var reader = new ElementReader(writer.to_binary_data());
  274. var elem = reader.read_element();
  275. if (elem.is_null()) return false;
  276. var read_array = elem.as<Invercargill.Enumerable<Invercargill.Element>>();
  277. var count = read_array.count();
  278. if (count != 3) return false;
  279. int64 expected = 1;
  280. foreach (var item in read_array) {
  281. if (item.is_null()) return false;
  282. int64? val = item.as<int64?>();
  283. if (val == null || (!) val != expected) return false;
  284. expected++;
  285. }
  286. return true;
  287. } catch (Error e) {
  288. return false;
  289. }
  290. }
  291. // Test 9: Dictionary/Properties elements
  292. bool test_dictionary_element() {
  293. try {
  294. var props = new Invercargill.DataStructures.PropertyDictionary();
  295. props.set("name", new Invercargill.NativeElement<string>("John"));
  296. props.set("age", new Invercargill.NativeElement<int64?>(30));
  297. props.set("active", new Invercargill.NativeElement<bool?>(true));
  298. var writer = new ElementWriter();
  299. writer.write_element(new Invercargill.NativeElement<Invercargill.Properties>(props));
  300. var reader = new ElementReader(writer.to_binary_data());
  301. var elem = reader.read_element();
  302. if (elem.is_null()) return false;
  303. var read_props = elem.as<Invercargill.Properties>();
  304. if (read_props.count() != 3) return false;
  305. // Check name
  306. var name_elem = read_props.get("name");
  307. if (name_elem == null || ((!) name_elem).is_null()) return false;
  308. string name = ((!) name_elem).as<string>();
  309. if (name != "John") return false;
  310. // Check age
  311. var age_elem = read_props.get("age");
  312. if (age_elem == null || ((!) age_elem).is_null()) return false;
  313. int64? age = ((!) age_elem).as<int64?>();
  314. if (age == null || (!) age != 30) return false;
  315. // Check active
  316. var active_elem = read_props.get("active");
  317. if (active_elem == null || ((!) active_elem).is_null()) return false;
  318. bool active = ((!) active_elem).as<bool?>();
  319. if (active != true) return false;
  320. return true;
  321. } catch (Error e) {
  322. return false;
  323. }
  324. }
  325. // Test 10: Round-trip all types
  326. bool test_round_trip() {
  327. try {
  328. // Write multiple elements
  329. var writer = new ElementWriter();
  330. writer.write_element(new Invercargill.NativeElement<bool?>(true));
  331. writer.write_element(new Invercargill.NativeElement<int64?>(42));
  332. writer.write_element(new Invercargill.NativeElement<string>("test"));
  333. var data = writer.to_binary_data();
  334. var reader = new ElementReader(data);
  335. // Read and verify
  336. var elem1 = reader.read_element();
  337. if (elem1.is_null()) return false;
  338. bool val1 = elem1.as<bool?>();
  339. if (val1 != true) return false;
  340. var elem2 = reader.read_element();
  341. if (elem2.is_null()) return false;
  342. int64? val2 = elem2.as<int64?>();
  343. if (val2 == null || (!) val2 != 42) return false;
  344. var elem3 = reader.read_element();
  345. if (elem3.is_null()) return false;
  346. string val3 = elem3.as<string>();
  347. if (val3 != "test") return false;
  348. return true;
  349. } catch (Error e) {
  350. return false;
  351. }
  352. }
  353. // Test 11: Complex nested structure
  354. bool test_nested_structure() {
  355. try {
  356. // Create nested structure: array containing dictionaries
  357. var inner_dict = new Invercargill.DataStructures.PropertyDictionary();
  358. inner_dict.set("key", new Invercargill.NativeElement<string>("value"));
  359. var array = new Invercargill.DataStructures.Vector<Invercargill.Element>();
  360. array.add(new Invercargill.NativeElement<Invercargill.Properties>(inner_dict));
  361. var writer = new ElementWriter();
  362. writer.write_element(new Invercargill.NativeElement<Invercargill.Enumerable<Invercargill.Element>>(array));
  363. var reader = new ElementReader(writer.to_binary_data());
  364. var elem = reader.read_element();
  365. if (elem.is_null()) return false;
  366. var read_array = elem.as<Invercargill.Enumerable<Invercargill.Element>>();
  367. if (read_array.count() != 1) return false;
  368. foreach (var item in read_array) {
  369. if (item.is_null()) return false;
  370. var dict = item.as<Invercargill.Properties>();
  371. var key_elem = dict.get("key");
  372. if (key_elem == null || ((!) key_elem).is_null()) return false;
  373. string key = ((!) key_elem).as<string>();
  374. if (key != "value") return false;
  375. }
  376. return true;
  377. } catch (Error e) {
  378. return false;
  379. }
  380. }
  381. // Test 12: Empty array
  382. bool test_empty_array() {
  383. try {
  384. var array = new Invercargill.DataStructures.Vector<Invercargill.Element>();
  385. var writer = new ElementWriter();
  386. writer.write_element(new Invercargill.NativeElement<Invercargill.Enumerable<Invercargill.Element>>(array));
  387. var reader = new ElementReader(writer.to_binary_data());
  388. var elem = reader.read_element();
  389. if (elem.is_null()) return false;
  390. var read_array = elem.as<Invercargill.Enumerable<Invercargill.Element>>();
  391. if (read_array.count() != 0) return false;
  392. return true;
  393. } catch (Error e) {
  394. return false;
  395. }
  396. }
  397. // Test 13: Empty dictionary
  398. bool test_empty_dictionary() {
  399. try {
  400. var props = new Invercargill.DataStructures.PropertyDictionary();
  401. var writer = new ElementWriter();
  402. writer.write_element(new Invercargill.NativeElement<Invercargill.Properties>(props));
  403. var reader = new ElementReader(writer.to_binary_data());
  404. var elem = reader.read_element();
  405. if (elem.is_null()) return false;
  406. var read_props = elem.as<Invercargill.Properties>();
  407. if (read_props.count() != 0) return false;
  408. return true;
  409. } catch (Error e) {
  410. return false;
  411. }
  412. }
  413. // Test 14: Large integers
  414. bool test_large_integers() {
  415. try {
  416. // Test boundary values
  417. int64 max = int64.MAX;
  418. int64 min = int64.MIN;
  419. var writer = new ElementWriter();
  420. writer.write_element(new Invercargill.NativeElement<int64?>(max));
  421. writer.write_element(new Invercargill.NativeElement<int64?>(min));
  422. var reader = new ElementReader(writer.to_binary_data());
  423. var elem1 = reader.read_element();
  424. if (elem1.is_null()) return false;
  425. int64? val1 = elem1.as<int64?>();
  426. if (val1 == null || (!) val1 != max) return false;
  427. var elem2 = reader.read_element();
  428. if (elem2.is_null()) return false;
  429. int64? val2 = elem2.as<int64?>();
  430. if (val2 == null || (!) val2 != min) return false;
  431. return true;
  432. } catch (Error e) {
  433. return false;
  434. }
  435. }
  436. // Test 15: Special string values
  437. bool test_special_strings() {
  438. try {
  439. string[] special = {
  440. "", // Empty
  441. " ", // Space
  442. "\t\n\r", // Whitespace
  443. "null", // Literal "null"
  444. "\"quoted\"", // Quotes
  445. "back\\slash", // Backslash
  446. "日本語", // Unicode
  447. "🎉", // Emoji
  448. "a\0b", // Null byte in string
  449. };
  450. foreach (var str in special) {
  451. var writer = new ElementWriter();
  452. writer.write_element(new Invercargill.NativeElement<string>(str));
  453. var reader = new ElementReader(writer.to_binary_data());
  454. var elem = reader.read_element();
  455. if (elem.is_null()) return false;
  456. string read = elem.as<string>();
  457. if (read != str) return false;
  458. }
  459. return true;
  460. } catch (Error e) {
  461. return false;
  462. }
  463. }