Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

614 строки
22 KiB

  1. namespace Slime {
  2. typedef s32 testresult;
  3. #define epsilon 2.2204460492503131E-16
  4. #define pass 1
  5. #define fail 0
  6. #define print_assert_equal_fail(variable, value, type, format) \
  7. print("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
  8. "\n\texpected: " format \
  9. "\n\tgot: " format "\n", \
  10. __FILE__, __LINE__, (type)value, (type)variable)
  11. #define print_assert_not_equal_fail(variable, value, type, format) \
  12. print("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
  13. "\n\texpected not: " format \
  14. "\n\tgot anyways: " format "\n", \
  15. __FILE__, __LINE__, (type)value, (type)variable)
  16. #define assert_equal_int(variable, value) \
  17. if (variable != value) { \
  18. print_assert_equal_fail(variable, value, size_t, "%zd"); \
  19. return fail; \
  20. }
  21. #define assert_not_equal_int(variable, value) \
  22. if (variable == value) { \
  23. print_assert_not_equal_fail(variable, value, size_t, "%zd"); \
  24. return fail; \
  25. }
  26. #define assert_no_error() \
  27. if (Globals::error) { \
  28. print_assert_equal_fail(Globals::error, 0, size_t, "%zd"); \
  29. printf("\nExpected no error to occur," \
  30. " but an error occured anyways:\n"); \
  31. return fail; \
  32. } \
  33. #define assert_error() \
  34. if (!Globals::error) { \
  35. print_assert_not_equal_fail(Globals::error, 0, size_t, "%zd"); \
  36. printf("\nExpected an error to occur," \
  37. " but no error occured:\n"); \
  38. return fail; \
  39. } \
  40. #define assert_equal_f64(variable, value) \
  41. if (fabsl((f64)variable - (f64)value) > epsilon) { \
  42. print_assert_equal_fail(variable, value, f64, "%Lf"); \
  43. return fail; \
  44. }
  45. #define assert_not_equal_f64(variable, value) \
  46. if (fabsl((f64)variable - (f64)value) <= epsilon) { \
  47. print_assert_not_equal_fail(variable, value, f64, "L%f"); \
  48. return fail; \
  49. }
  50. #define assert_equal_string(variable, value) \
  51. if (!string_equal(variable, value)) { \
  52. print_assert_equal_fail(variable.data, value, char*, "%s"); \
  53. return fail; \
  54. }
  55. #define assert_equal_type(node, _type) \
  56. if (node->type != _type) { \
  57. print_assert_equal_fail(node->type, _type, Lisp_Object_Type, \
  58. "%{l_o_t}"); \
  59. return fail; \
  60. } \
  61. #define assert_null(variable) \
  62. assert_equal_int(variable, nullptr)
  63. #define assert_not_null(variable) \
  64. assert_not_equal_int(variable, nullptr)
  65. #define invoke_test(name) \
  66. fputs("" #name ":", stdout); \
  67. if (name() == pass) { \
  68. for(size_t i = strlen(#name); i < 70; ++i) \
  69. fputs((i%3==1)? "." : " ", stdout); \
  70. fputs(console_green "passed\n" console_normal, stdout); \
  71. } \
  72. else { \
  73. result = false; \
  74. for(s32 i = -1; i < 70; ++i) \
  75. fputs((i%3==1)? "." : " ", stdout); \
  76. fputs(console_red "failed\n" console_normal, stdout); \
  77. if(Globals::error) { \
  78. free(Globals::error); \
  79. Globals::error = nullptr; \
  80. } \
  81. } \
  82. #define invoke_test_script(name) \
  83. fputs("" name ":", stdout); \
  84. if (test_file("tests/" name ".slime") == pass) { \
  85. for(size_t i = strlen(name); i < 70; ++i) \
  86. fputs((i%3==1)? "." : " ", stdout); \
  87. fputs(console_green "passed\n" console_normal, stdout); \
  88. } \
  89. else { \
  90. result = false; \
  91. for(s32 i = -1; i < 70; ++i) \
  92. fputs((i%3==1)? "." : " ", stdout); \
  93. fputs(console_red "failed\n" console_normal, stdout); \
  94. if(Globals::error) { \
  95. free(Globals::error); \
  96. Globals::error = nullptr; \
  97. } \
  98. }
  99. proc test_array_lists_adding_and_removing() -> testresult {
  100. // test adding and removing
  101. Array_List<s32> list;
  102. list.alloc();
  103. defer {
  104. list.dealloc();
  105. };
  106. list.append(1);
  107. list.append(2);
  108. list.append(3);
  109. list.append(4);
  110. assert_equal_int(list.next_index, 4);
  111. list.remove_index(0);
  112. assert_equal_int(list.next_index, 3);
  113. assert_equal_int(list[0], 4);
  114. assert_equal_int(list[1], 2);
  115. assert_equal_int(list[2], 3);
  116. list.remove_index(2);
  117. assert_equal_int(list.next_index, 2);
  118. assert_equal_int(list[0], 4);
  119. assert_equal_int(list[1], 2);
  120. return pass;
  121. }
  122. proc test_array_lists_sorting() -> testresult {
  123. // test adding and removing
  124. Array_List<s32> list;
  125. list.alloc();
  126. defer {
  127. list.dealloc();
  128. };
  129. list.append(1);
  130. list.append(2);
  131. list.append(3);
  132. list.append(4);
  133. list.sort();
  134. assert_equal_int(list.next_index, 4);
  135. assert_equal_int(list[0], 1);
  136. assert_equal_int(list[1], 2);
  137. assert_equal_int(list[2], 3);
  138. assert_equal_int(list[3], 4);
  139. list.append(0);
  140. list.append(5);
  141. assert_equal_int(list.next_index, 6);
  142. list.sort();
  143. assert_equal_int(list[0], 0);
  144. assert_equal_int(list[1], 1);
  145. assert_equal_int(list[2], 2);
  146. assert_equal_int(list[3], 3);
  147. assert_equal_int(list[4], 4);
  148. assert_equal_int(list[5], 5);
  149. return pass;
  150. }
  151. proc test_array_lists_searching() -> testresult {
  152. Array_List<s32> list;
  153. list.alloc();
  154. defer {
  155. list.dealloc();
  156. };
  157. list.append(1);
  158. list.append(2);
  159. list.append(3);
  160. list.append(4);
  161. s32 index = list.sorted_find(3);
  162. assert_equal_int(index, 2);
  163. index = list.sorted_find(1);
  164. assert_equal_int(index, 0);
  165. index = list.sorted_find(5);
  166. assert_equal_int(index, -1);
  167. return pass;
  168. }
  169. proc test_parse_atom() -> testresult {
  170. u32 index_in_text = 0;
  171. char string[] =
  172. "123 -1.23e-2 " // numbers
  173. "\"asd\" " // strings
  174. ":key1 :key:2 " // keywords
  175. "sym +"; // symbols
  176. // test numbers
  177. Lisp_Object* result = Parser::parse_atom(string, &index_in_text);
  178. assert_equal_type(result, Lisp_Object_Type::Number);
  179. assert_equal_f64(result->value.number, 123);
  180. ++index_in_text;
  181. result = Parser::parse_atom(string, &index_in_text);
  182. assert_equal_type(result, Lisp_Object_Type::Number);
  183. assert_equal_f64(result->value.number, -1.23e-2);
  184. // test strings
  185. ++index_in_text;
  186. result = Parser::parse_atom(string, &index_in_text);
  187. assert_equal_type(result, Lisp_Object_Type::String);
  188. assert_equal_string(result->value.string, "asd");
  189. // test keywords
  190. ++index_in_text;
  191. result = Parser::parse_atom(string, &index_in_text);
  192. assert_equal_type(result, Lisp_Object_Type::Keyword);
  193. assert_equal_string(result->value.symbol, "key1");
  194. ++index_in_text;
  195. result = Parser::parse_atom(string, &index_in_text);
  196. assert_equal_type(result, Lisp_Object_Type::Keyword);
  197. assert_equal_string(result->value.symbol, "key:2");
  198. // test symbols
  199. ++index_in_text;
  200. result = Parser::parse_atom(string, &index_in_text);
  201. assert_equal_type(result, Lisp_Object_Type::Symbol);
  202. assert_equal_string(result->value.symbol, "sym");
  203. ++index_in_text;
  204. result = Parser::parse_atom(string, &index_in_text);
  205. assert_equal_type(result, Lisp_Object_Type::Symbol);
  206. assert_equal_string(result->value.symbol, "+");
  207. return pass;
  208. }
  209. proc test_parse_expression() -> testresult {
  210. u32 index_in_text = 0;
  211. char string[] = "(fun + 12)";
  212. Lisp_Object* result = Parser::parse_expression(string, &index_in_text);
  213. assert_no_error();
  214. assert_equal_type(result, Lisp_Object_Type::Pair);
  215. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  216. assert_equal_string(result->value.pair.first->value.symbol, "fun");
  217. result = result->value.pair.rest;
  218. assert_equal_type(result, Lisp_Object_Type::Pair);
  219. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  220. assert_equal_string(result->value.pair.first->value.symbol, "+");
  221. result = result->value.pair.rest;
  222. assert_equal_type(result, Lisp_Object_Type::Pair);
  223. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Number);
  224. assert_equal_f64(result->value.pair.first->value.number, 12);
  225. result = result->value.pair.rest;
  226. assert_equal_type(result, Lisp_Object_Type::Nil);
  227. char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))";
  228. index_in_text = 0;
  229. result = Parser::parse_expression(string2, &index_in_text);
  230. assert_no_error();
  231. assert_equal_type(result, Lisp_Object_Type::Pair);
  232. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  233. assert_equal_string(result->value.pair.first->value.symbol, "define");
  234. result = result->value.pair.rest;
  235. assert_equal_type(result, Lisp_Object_Type::Pair);
  236. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  237. assert_equal_string(result->value.pair.first->value.symbol, "fun");
  238. result = result->value.pair.rest;
  239. assert_equal_type(result, Lisp_Object_Type::Pair);
  240. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Pair);
  241. assert_equal_type(result->value.pair.first->value.pair.first, Lisp_Object_Type::Symbol);
  242. assert_equal_string(result->value.pair.first->value.pair.first->value.symbol, "lambda");
  243. result = result->value.pair.rest;
  244. return pass;
  245. }
  246. proc test_string_copy() -> testresult {
  247. Lisp_Object* str = Memory::create_lisp_object("Hello World");
  248. Lisp_Object* cpy = Memory::copy_lisp_object(str);
  249. assert_not_equal_int(str, cpy);
  250. assert_not_equal_int(str->value.string.data, cpy->value.string.data);
  251. return pass;
  252. }
  253. proc test_simple_stuff() -> testresult {
  254. { // built in add
  255. char exp_string[] = "(+ 10 4)";
  256. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  257. Lisp_Object* result;
  258. try result = eval_expr(expression);
  259. assert_no_error();
  260. assert_not_null(result);
  261. assert_equal_type(result, Lisp_Object_Type::Number);
  262. assert_equal_f64(result->value.number, 14);
  263. }
  264. { // built in subtract
  265. char exp_string[] = "(- 10 4)";
  266. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  267. Lisp_Object* result;
  268. try result = eval_expr(expression);
  269. assert_no_error();
  270. assert_not_null(result);
  271. assert_equal_type(result, Lisp_Object_Type::Number);
  272. assert_equal_f64(result->value.number, 6);
  273. }
  274. { // built in multiply
  275. char exp_string[] = "(* 10 4)";
  276. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  277. Lisp_Object* result;
  278. try result = eval_expr(expression);
  279. assert_no_error();
  280. assert_not_null(result);
  281. assert_equal_type(result, Lisp_Object_Type::Number);
  282. assert_equal_f64(result->value.number, 40);
  283. }
  284. { // built in divide
  285. char exp_string[] = "(/ 20 4)";
  286. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  287. Lisp_Object* result;
  288. try result = eval_expr(expression);
  289. assert_no_error();
  290. assert_not_null(result);
  291. assert_equal_type(result, Lisp_Object_Type::Number);
  292. assert_equal_f64(result->value.number, 5);
  293. }
  294. { // built in if
  295. char exp_string1[] = "(if 1 4 5)";
  296. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  297. Lisp_Object* result;
  298. try result = eval_expr(expression);
  299. assert_no_error();
  300. assert_not_null(result);
  301. assert_equal_type(result, Lisp_Object_Type::Number);
  302. assert_equal_f64(result->value.number, 4);
  303. char exp_string2[] = "(if () 4 5)";
  304. expression = Parser::parse_single_expression(exp_string2);
  305. try result = eval_expr(expression);
  306. assert_no_error();
  307. assert_not_null(result);
  308. assert_equal_type(result, Lisp_Object_Type::Number);
  309. assert_equal_f64(result->value.number, 5);
  310. }
  311. { // built in and
  312. char exp_string1[] = "(and 1 \"asd\" 4)";
  313. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  314. Lisp_Object* result;
  315. try result = eval_expr(expression);
  316. assert_no_error();
  317. assert_not_null(result);
  318. assert_equal_type(result, Lisp_Object_Type::T);
  319. // a false case
  320. char exp_string2[] = "(and () \"asd\" 4)";
  321. expression = Parser::parse_single_expression(exp_string2);
  322. try result = eval_expr(expression);
  323. assert_no_error();
  324. assert_not_null(result);
  325. assert_equal_type(result, Lisp_Object_Type::Nil);
  326. }
  327. { // built in or
  328. char exp_string1[] = "(or \"asd\" nil)";
  329. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  330. Lisp_Object* result;
  331. try result = eval_expr(expression);
  332. assert_no_error();
  333. assert_not_null(result);
  334. assert_equal_type(result, Lisp_Object_Type::T);
  335. // a false case
  336. char exp_string2[] = "(or () ())";
  337. expression = Parser::parse_single_expression(exp_string2);
  338. try result = eval_expr(expression);
  339. assert_no_error();
  340. assert_not_null(result);
  341. assert_equal_type(result, Lisp_Object_Type::Nil);
  342. }
  343. { // buit in not
  344. char exp_string1[] = "(not ())";
  345. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  346. Lisp_Object* result;
  347. try result = eval_expr(expression);
  348. // a true case
  349. assert_no_error();
  350. assert_not_null(result);
  351. assert_equal_type(result, Lisp_Object_Type::T);
  352. // a false case
  353. char exp_string2[] = "(not \"asd xD\")";
  354. expression = Parser::parse_single_expression(exp_string2);
  355. try result = eval_expr(expression);
  356. assert_no_error();
  357. assert_not_null(result);
  358. assert_equal_type(result, Lisp_Object_Type::Nil);
  359. }
  360. { // built in type
  361. // normal type testing
  362. char exp_string1[] = "(begin (define a 10)(type a))";
  363. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  364. Lisp_Object* result = eval_expr(expression);
  365. assert_no_error();
  366. assert_not_null(result);
  367. assert_equal_type(result, Lisp_Object_Type::Keyword);
  368. assert_equal_string(result->value.symbol, "number");
  369. // setting user type
  370. char exp_string2[] = "(begin (set-type! a :my-type)(type a))";
  371. expression = Parser::parse_single_expression(exp_string2);
  372. result = eval_expr(expression);
  373. assert_no_error();
  374. assert_not_null(result);
  375. assert_equal_type(result, Lisp_Object_Type::Keyword);
  376. assert_equal_string(result->value.symbol, "my-type");
  377. // deleting user type
  378. char exp_string4[] = "(begin (delete-type! a)(type a))";
  379. expression = Parser::parse_single_expression(exp_string4);
  380. result = eval_expr(expression);
  381. assert_no_error();
  382. assert_not_null(result);
  383. assert_equal_type(result, Lisp_Object_Type::Keyword);
  384. assert_equal_string(result->value.symbol, "number");
  385. }
  386. return pass;
  387. }
  388. proc test_singular_t_and_nil() -> testresult {
  389. // nil testing
  390. char exp_string1[] = "()";
  391. char exp_string2[] = "nil";
  392. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  393. Lisp_Object* result = eval_expr(expression);
  394. assert_no_error();
  395. assert_not_null(result);
  396. assert_equal_type(result, Lisp_Object_Type::Nil);
  397. assert_equal_int(expression, result);
  398. Lisp_Object* expression2 = Parser::parse_single_expression(exp_string2);
  399. Lisp_Object* result2 = eval_expr(expression2);
  400. assert_no_error();
  401. assert_not_null(result);
  402. assert_equal_type(result, Lisp_Object_Type::Nil);
  403. assert_equal_int(result, result2);
  404. assert_equal_int(expression, Memory::nil);
  405. // t testing
  406. char exp_string3[] = "t";
  407. Lisp_Object* expression3 = Parser::parse_single_expression(exp_string3);
  408. Lisp_Object* result3 = eval_expr(expression3);
  409. assert_no_error();
  410. assert_not_null(result3);
  411. return pass;
  412. }
  413. proc test_singular_symbols() -> testresult {
  414. auto cc_s_aa = Memory::get_symbol("aa");
  415. auto cc_s_aa2 = Memory::get_symbol("aa2");
  416. String s1 = Memory::create_string("aa");
  417. String s2 = Memory::create_string("aa2");
  418. auto s_s_aa = Memory::get_symbol(s1);
  419. auto s_s_aa2 = Memory::get_symbol(s2);
  420. free(s1.data);
  421. free(s2.data);
  422. assert_equal_int(cc_s_aa, s_s_aa);
  423. assert_equal_int(cc_s_aa2, s_s_aa2);
  424. assert_not_equal_int(cc_s_aa, cc_s_aa2);
  425. return pass;
  426. }
  427. proc test_file(const char* file) -> testresult {
  428. profile_with_name(file);
  429. push_environment(Memory::create_child_environment(get_current_environment()));
  430. String name = Memory::create_string(file);
  431. built_in_load(name);
  432. free(name.data);
  433. assert_no_error();
  434. pop_environment();
  435. return pass;
  436. }
  437. proc run_all_tests() -> bool {
  438. profile_this();
  439. bool result = true;
  440. push_environment(Memory::create_child_environment(
  441. get_current_environment()));
  442. printf("-- Util --\n");
  443. invoke_test(test_array_lists_adding_and_removing);
  444. invoke_test(test_array_lists_sorting);
  445. invoke_test(test_array_lists_searching);
  446. printf("\n -- Parsing --\n");
  447. invoke_test(test_parse_atom);
  448. invoke_test(test_parse_expression);
  449. printf("\n-- Built ins --\n");
  450. invoke_test(test_simple_stuff);
  451. invoke_test(test_string_copy);
  452. printf("\n-- Memory management --\n");
  453. invoke_test(test_singular_t_and_nil);
  454. invoke_test(test_singular_symbols);
  455. pop_environment();
  456. printf("\n-- Test Files --\n");
  457. invoke_test_script("regression");
  458. invoke_test_script("continuations");
  459. invoke_test_script("evaluation_of_default_args");
  460. invoke_test_script("case_and_cond");
  461. invoke_test_script("lexical_scope");
  462. invoke_test_script("singular_imports");
  463. invoke_test_script("hashmaps");
  464. invoke_test_script("import_and_load");
  465. invoke_test_script("macro_expand");
  466. invoke_test_script("sicp");
  467. invoke_test_script("simple_built_ins");
  468. invoke_test_script("modules");
  469. invoke_test_script("class_macro");
  470. invoke_test_script("automata");
  471. invoke_test_script("alists");
  472. return result;
  473. }
  474. #undef epsilon
  475. #undef testresult
  476. #undef pass
  477. #undef fail
  478. #undef print_assert_equal_fail
  479. #undef print_assert_not_equal_fail
  480. #undef assert_no_error
  481. #undef assert_equal_int
  482. #undef assert_not_equal_int
  483. #undef assert_equal_f64
  484. #undef assert_not_equal_f64
  485. #undef assert_equal_string
  486. #undef assert_equal_type
  487. #undef assert_null
  488. #undef assert_not_null
  489. #undef invoke_test
  490. #undef invoke_test_script
  491. }