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

557 строки
20 KiB

  1. #define epsilon 2.2204460492503131E-16
  2. #define testresult int
  3. #define pass 1
  4. #define fail 0
  5. #define print_assert_equal_fail(variable, value, type, format) \
  6. printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
  7. "\n\texpected: " format \
  8. "\n\tgot: " format "\n", \
  9. __FILE__, __LINE__, (type)value, (type)variable)
  10. #define print_assert_not_equal_fail(variable, value, type, format) \
  11. printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
  12. "\n\texpected not: " format \
  13. "\n\tgot anyways: " format "\n", \
  14. __FILE__, __LINE__, (type)value, (type)variable)
  15. #define assert_equal_int(variable, value) \
  16. if (variable != value) { \
  17. print_assert_equal_fail(variable, value, size_t, "%zd"); \
  18. return fail; \
  19. }
  20. #define assert_not_equal_int(variable, value) \
  21. if (variable == value) { \
  22. print_assert_not_equal_fail(variable, value, size_t, "%zd"); \
  23. return fail; \
  24. }
  25. #define assert_no_error() \
  26. if (Globals::error) { \
  27. print_assert_equal_fail(Globals::error, 0, size_t, "%zd"); \
  28. printf("\nExpected no error to occur," \
  29. " but an error occured anyways:\n"); \
  30. log_error(); \
  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_double(variable, value) \
  41. if (fabs((double)variable - (double)value) > epsilon) { \
  42. print_assert_equal_fail(variable, value, double, "%f"); \
  43. return fail; \
  44. }
  45. #define assert_not_equal_double(variable, value) \
  46. if (fabs((double)variable - (double)value) <= epsilon) { \
  47. print_assert_not_equal_fail(variable, value, double, "%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 (Memory::get_type(node) != _type) { \
  57. print_assert_equal_fail( \
  58. Lisp_Object_Type_to_string(Memory::get_type(node)), \
  59. Lisp_Object_Type_to_string(_type), char*, "%s"); \
  60. return fail; \
  61. } \
  62. #define assert_null(variable) \
  63. assert_equal_int(variable, nullptr)
  64. #define assert_not_null(variable) \
  65. assert_not_equal_int(variable, nullptr)
  66. #define invoke_test(name) \
  67. fputs("" #name ":", stdout); \
  68. if (name() == pass) { \
  69. for(size_t i = strlen(#name); i < 70; ++i) \
  70. fputs((i%3==1)? "." : " ", stdout); \
  71. fputs(console_green "passed\n" console_normal, stdout); \
  72. } \
  73. else { \
  74. result = false; \
  75. for(int i = -1; i < 70; ++i) \
  76. fputs((i%3==1)? "." : " ", stdout); \
  77. fputs(console_red "failed\n" console_normal, stdout); \
  78. if(Globals::error) { \
  79. free(Globals::error); \
  80. Globals::error = nullptr; \
  81. } \
  82. } \
  83. #define invoke_test_script(name) \
  84. fputs("" name ":", stdout); \
  85. if (test_file("tests/" name ".slime") == pass) { \
  86. for(size_t i = strlen(name); i < 70; ++i) \
  87. fputs((i%3==1)? "." : " ", stdout); \
  88. fputs(console_green "passed\n" console_normal, stdout); \
  89. } \
  90. else { \
  91. result = false; \
  92. for(int i = -1; i < 70; ++i) \
  93. fputs((i%3==1)? "." : " ", stdout); \
  94. fputs(console_red "failed\n" console_normal, stdout); \
  95. if(Globals::error) { \
  96. free(Globals::error); \
  97. Globals::error = nullptr; \
  98. } \
  99. }
  100. proc test_eval_operands() -> testresult {
  101. char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
  102. Lisp_Object* operands = Parser::parse_single_expression(operands_string);
  103. int operands_length;
  104. operands = eval_arguments(operands, Memory::create_built_ins_environment(), &operands_length);
  105. assert_no_error();
  106. assert_equal_int(list_length(operands), 4);
  107. assert_equal_type(operands, Lisp_Object_Type::Pair);
  108. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::Number);
  109. assert_equal_double(operands->value.pair.first->value.number, 1);
  110. operands = operands->value.pair.rest;
  111. assert_equal_type(operands, Lisp_Object_Type::Pair);
  112. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::Number);
  113. assert_equal_double(operands->value.pair.first->value.number, 3);
  114. operands = operands->value.pair.rest;
  115. assert_equal_type(operands, Lisp_Object_Type::Pair);
  116. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::String);
  117. assert_equal_string(operands->value.pair.first->value.string, "okay");
  118. operands = operands->value.pair.rest;
  119. assert_equal_type(operands, Lisp_Object_Type::Pair);
  120. assert_equal_type(operands->value.pair.first, Lisp_Object_Type::Keyword);
  121. assert_equal_string(operands->value.pair.first->value.identifier, "haha");
  122. return pass;
  123. }
  124. proc test_parse_atom() -> testresult {
  125. int index_in_text = 0;
  126. char string[] =
  127. "123 -1.23e-2 " // numbers
  128. "\"asd\" " // strings
  129. ":key1 :key:2 " // keywords
  130. "sym +"; // symbols
  131. // test numbers
  132. Lisp_Object* result = Parser::parse_atom(string, &index_in_text);
  133. assert_equal_type(result, Lisp_Object_Type::Number);
  134. assert_equal_double(result->value.number, 123);
  135. ++index_in_text;
  136. result = Parser::parse_atom(string, &index_in_text);
  137. assert_equal_type(result, Lisp_Object_Type::Number);
  138. assert_equal_double(result->value.number, -1.23e-2);
  139. // test strings
  140. ++index_in_text;
  141. result = Parser::parse_atom(string, &index_in_text);
  142. assert_equal_type(result, Lisp_Object_Type::String);
  143. assert_equal_string(result->value.string, "asd");
  144. // test keywords
  145. ++index_in_text;
  146. result = Parser::parse_atom(string, &index_in_text);
  147. assert_equal_type(result, Lisp_Object_Type::Keyword);
  148. assert_equal_string(result->value.identifier, "key1");
  149. ++index_in_text;
  150. result = Parser::parse_atom(string, &index_in_text);
  151. assert_equal_type(result, Lisp_Object_Type::Keyword);
  152. assert_equal_string(result->value.identifier, "key:2");
  153. // test symbols
  154. ++index_in_text;
  155. result = Parser::parse_atom(string, &index_in_text);
  156. assert_equal_type(result, Lisp_Object_Type::Symbol);
  157. assert_equal_string(result->value.identifier, "sym");
  158. ++index_in_text;
  159. result = Parser::parse_atom(string, &index_in_text);
  160. assert_equal_type(result, Lisp_Object_Type::Symbol);
  161. assert_equal_string(result->value.identifier, "+");
  162. return pass;
  163. }
  164. proc test_parse_expression() -> testresult {
  165. int index_in_text = 0;
  166. char string[] = "(fun + 12)";
  167. Lisp_Object* result = Parser::parse_expression(string, &index_in_text);
  168. assert_no_error();
  169. assert_equal_type(result, Lisp_Object_Type::Pair);
  170. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  171. assert_equal_string(result->value.pair.first->value.identifier, "fun");
  172. result = result->value.pair.rest;
  173. assert_equal_type(result, Lisp_Object_Type::Pair);
  174. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  175. assert_equal_string(result->value.pair.first->value.identifier, "+");
  176. result = result->value.pair.rest;
  177. assert_equal_type(result, Lisp_Object_Type::Pair);
  178. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Number);
  179. assert_equal_double(result->value.pair.first->value.number, 12);
  180. result = result->value.pair.rest;
  181. assert_equal_type(result, Lisp_Object_Type::Nil);
  182. char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))";
  183. index_in_text = 0;
  184. result = Parser::parse_expression(string2, &index_in_text);
  185. assert_no_error();
  186. assert_equal_type(result, Lisp_Object_Type::Pair);
  187. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  188. assert_equal_string(result->value.pair.first->value.identifier, "define");
  189. result = result->value.pair.rest;
  190. assert_equal_type(result, Lisp_Object_Type::Pair);
  191. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Symbol);
  192. assert_equal_string(result->value.pair.first->value.identifier, "fun");
  193. result = result->value.pair.rest;
  194. assert_equal_type(result, Lisp_Object_Type::Pair);
  195. assert_equal_type(result->value.pair.first, Lisp_Object_Type::Pair);
  196. assert_equal_type(result->value.pair.first->value.pair.first, Lisp_Object_Type::Symbol);
  197. assert_equal_string(result->value.pair.first->value.pair.first->value.identifier, "lambda");
  198. result = result->value.pair.rest;
  199. return pass;
  200. }
  201. proc test_built_in_add() -> testresult {
  202. char exp_string[] = "(+ 10 4)";
  203. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  204. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  205. assert_no_error();
  206. assert_not_null(result);
  207. assert_equal_type(result, Lisp_Object_Type::Number);
  208. assert_equal_double(result->value.number, 14);
  209. return pass;
  210. }
  211. proc test_built_in_substract() -> testresult {
  212. char exp_string[] = "(- 10 4)";
  213. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  214. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  215. assert_no_error();
  216. assert_not_null(result);
  217. assert_equal_type(result, Lisp_Object_Type::Number);
  218. assert_equal_double(result->value.number, 6);
  219. return pass;
  220. }
  221. proc test_built_in_multiply() -> testresult {
  222. char exp_string[] = "(* 10 4)";
  223. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  224. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  225. assert_no_error();
  226. assert_not_null(result);
  227. assert_equal_type(result, Lisp_Object_Type::Number);
  228. assert_equal_double(result->value.number, 40);
  229. return pass;
  230. }
  231. proc test_built_in_divide() -> testresult {
  232. char exp_string[] = "(/ 20 4)";
  233. Lisp_Object* expression = Parser::parse_single_expression(exp_string);
  234. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  235. assert_no_error();
  236. assert_not_null(result);
  237. assert_equal_type(result, Lisp_Object_Type::Number);
  238. assert_equal_double(result->value.number, 5);
  239. return pass;
  240. }
  241. proc test_built_in_if() -> testresult {
  242. char exp_string1[] = "(if 1 4 5)";
  243. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  244. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  245. assert_no_error();
  246. assert_not_null(result);
  247. assert_equal_type(result, Lisp_Object_Type::Number);
  248. assert_equal_double(result->value.number, 4);
  249. char exp_string2[] = "(if () 4 5)";
  250. expression = Parser::parse_single_expression(exp_string2);
  251. result = eval_expr(expression, Memory::create_built_ins_environment());
  252. assert_no_error();
  253. assert_not_null(result);
  254. assert_equal_type(result, Lisp_Object_Type::Number);
  255. assert_equal_double(result->value.number, 5);
  256. return pass;
  257. }
  258. proc test_built_in_and() -> testresult {
  259. char exp_string1[] = "(and 1 \"asd\" 4)";
  260. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  261. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  262. assert_no_error();
  263. assert_not_null(result);
  264. assert_equal_type(result, Lisp_Object_Type::T);
  265. // a false case
  266. char exp_string2[] = "(and () \"asd\" 4)";
  267. expression = Parser::parse_single_expression(exp_string2);
  268. result = eval_expr(expression, Memory::create_built_ins_environment());
  269. assert_no_error();
  270. assert_not_null(result);
  271. assert_equal_type(result, Lisp_Object_Type::Nil);
  272. return pass;
  273. }
  274. proc test_built_in_or() -> testresult {
  275. char exp_string1[] = "(or \"asd\" nil)";
  276. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  277. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  278. assert_no_error();
  279. assert_not_null(result);
  280. assert_equal_type(result, Lisp_Object_Type::T);
  281. // a false case
  282. char exp_string2[] = "(or () ())";
  283. expression = Parser::parse_single_expression(exp_string2);
  284. result = eval_expr(expression, Memory::create_built_ins_environment());
  285. assert_no_error();
  286. assert_not_null(result);
  287. assert_equal_type(result, Lisp_Object_Type::Nil);
  288. return pass;
  289. }
  290. proc test_built_in_not() -> testresult {
  291. char exp_string1[] = "(not ())";
  292. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  293. Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment());
  294. // a true case
  295. assert_no_error();
  296. assert_not_null(result);
  297. assert_equal_type(result, Lisp_Object_Type::T);
  298. // a false case
  299. char exp_string2[] = "(not \"asd xD\")";
  300. expression = Parser::parse_single_expression(exp_string2);
  301. result = eval_expr(expression, Memory::create_built_ins_environment());
  302. assert_no_error();
  303. assert_not_null(result);
  304. assert_equal_type(result, Lisp_Object_Type::Nil);
  305. return pass;
  306. }
  307. proc test_built_in_type() -> testresult {
  308. Environment* env = Memory::create_built_ins_environment();
  309. // normal type testing
  310. char exp_string1[] = "(prog (define a 10)(type a))";
  311. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  312. Lisp_Object* result = eval_expr(expression, env);
  313. assert_no_error();
  314. assert_not_null(result);
  315. assert_equal_type(result, Lisp_Object_Type::Keyword);
  316. assert_equal_string(result->value.identifier, "number");
  317. // setting user type
  318. char exp_string2[] = "(prog (set-type a :my-type)(type a))";
  319. expression = Parser::parse_single_expression(exp_string2);
  320. result = eval_expr(expression, env);
  321. assert_no_error();
  322. assert_not_null(result);
  323. assert_equal_type(result, Lisp_Object_Type::Keyword);
  324. assert_equal_string(result->value.identifier, "my-type");
  325. // trying to set invalid user type
  326. char exp_string3[] = "(prog (set-type a \"wrong tpye\")(type a))";
  327. expression = Parser::parse_single_expression(exp_string3);
  328. without_logging {
  329. result = eval_expr(expression, env);
  330. }
  331. assert_error();
  332. delete_error();
  333. // deleting user type
  334. char exp_string4[] = "(prog (delete-type a)(type a))";
  335. expression = Parser::parse_single_expression(exp_string4);
  336. result = eval_expr(expression, env);
  337. assert_no_error();
  338. assert_not_null(result);
  339. assert_equal_type(result, Lisp_Object_Type::Keyword);
  340. assert_equal_string(result->value.identifier, "number");
  341. return pass;
  342. }
  343. proc test_singular_t_and_nil() -> testresult {
  344. Environment* env = Memory::create_built_ins_environment();
  345. // nil testing
  346. char exp_string1[] = "()";
  347. char exp_string2[] = "nil";
  348. Lisp_Object* expression = Parser::parse_single_expression(exp_string1);
  349. Lisp_Object* result = eval_expr(expression, env);
  350. assert_no_error();
  351. assert_not_null(result);
  352. assert_equal_type(result, Lisp_Object_Type::Nil);
  353. assert_equal_int(expression, result);
  354. Lisp_Object* expression2 = Parser::parse_single_expression(exp_string2);
  355. Lisp_Object* result2 = eval_expr(expression2, env);
  356. assert_no_error();
  357. assert_not_null(result);
  358. assert_equal_type(result, Lisp_Object_Type::Nil);
  359. assert_equal_int(result, result2);
  360. assert_equal_int(expression, Memory::nil);
  361. // t testing
  362. char exp_string3[] = "t";
  363. Lisp_Object* expression3 = Parser::parse_single_expression(exp_string3);
  364. Lisp_Object* result3 = eval_expr(expression3, env);
  365. assert_no_error();
  366. assert_not_null(result3);
  367. return pass;
  368. }
  369. proc test_file(const char* file) -> testresult {
  370. Memory::reset();
  371. assert_no_error();
  372. Environment* env = Memory::create_built_ins_environment();
  373. assert_no_error();
  374. Parser::init(env);
  375. assert_no_error();
  376. built_in_load(Memory::create_string("pre.slime"), env);
  377. assert_no_error();
  378. Lisp_Object* result = built_in_load(Memory::create_string(file), env);
  379. assert_no_error();
  380. return pass;
  381. }
  382. proc run_all_tests() -> bool {
  383. Memory::init(4096 * 2000, 4096 * 16);
  384. Parser::init(Memory::create_built_ins_environment());
  385. bool result = true;
  386. printf("-- Parsing --\n");
  387. invoke_test(test_parse_atom);
  388. invoke_test(test_parse_expression);
  389. printf("\n-- Basic evaluating --\n");
  390. invoke_test(test_eval_operands);
  391. printf("\n-- Built ins --\n");
  392. invoke_test(test_built_in_add);
  393. invoke_test(test_built_in_substract);
  394. invoke_test(test_built_in_multiply);
  395. invoke_test(test_built_in_divide);
  396. invoke_test(test_built_in_if);
  397. invoke_test(test_built_in_and);
  398. invoke_test(test_built_in_or);
  399. invoke_test(test_built_in_not);
  400. invoke_test(test_built_in_type);
  401. printf("\n-- Memory management --\n");
  402. invoke_test(test_singular_t_and_nil);
  403. printf("\n-- Test Files --\n");
  404. invoke_test_script("lexical_scope");
  405. invoke_test_script("class_macro");
  406. invoke_test_script("sicp");
  407. return result;
  408. }
  409. #undef epsilon
  410. #undef testresult
  411. #undef pass
  412. #undef fail
  413. #undef print_assert_equal_fail
  414. #undef print_assert_not_equal_fail
  415. #undef assert_no_error
  416. #undef assert_equal_int
  417. #undef assert_not_equal_int
  418. #undef assert_equal_double
  419. #undef assert_not_equal_double
  420. #undef assert_equal_string
  421. #undef assert_equal_type
  422. #undef assert_null
  423. #undef assert_not_null
  424. #undef invoke_test
  425. #undef invoke_test_script