test.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. #include "pocketpy_c.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. //tests the c bindings for pocketpy
  5. void check_impl(pkpy_vm* vm, bool result, int lineno) {
  6. if (!result) {
  7. printf("ERROR: failed where it should have succeed at line %i\n", lineno);
  8. char* message;
  9. if (!pkpy_clear_error(vm, &message)) {
  10. printf("clear error reported everything was fine\n");
  11. exit(1);
  12. }
  13. printf("%s\n", message);
  14. free(message);
  15. exit(1);
  16. }
  17. }
  18. void fail_impl(pkpy_vm* vm, bool result, int lineno) {
  19. if (result) {
  20. printf("ERROR: succeeded where it should have failed line %i\n", lineno);
  21. exit(1);
  22. } else {
  23. char* message;
  24. if (pkpy_clear_error(vm, &message)) {
  25. printf("actually errored! line %i\n", lineno);
  26. free(message);
  27. exit(1);
  28. }
  29. }
  30. }
  31. void error_impl(pkpy_vm* vm, bool result, int lineno) {
  32. if (result) {
  33. printf("ERROR: succeeded where it should have failed line %i\n", lineno);
  34. exit(1);
  35. } else {
  36. char* message;
  37. if (!pkpy_clear_error(vm, &message)){
  38. printf("clear error reported everything was fine\n");
  39. exit(1);
  40. } else {
  41. printf("successfully errored with this message: \n");
  42. printf("%s\n", message);
  43. free(message);
  44. }
  45. }
  46. }
  47. #define check(r) check_impl(vm, (r), __LINE__)
  48. #define fail(r) fail_impl(vm, (r), __LINE__)
  49. #define error(r) error_impl(vm, (r), __LINE__)
  50. int test_binding(pkpy_vm* vm) {
  51. pkpy_push_int(vm, 12);
  52. return 1;
  53. }
  54. int test_multiple_return(pkpy_vm* vm) {
  55. pkpy_push_int(vm, 12);
  56. pkpy_push_int(vm, 13);
  57. return 2;
  58. }
  59. int test_minus(pkpy_vm* vm) {
  60. int a, b;
  61. pkpy_to_int(vm, 0, &a);
  62. pkpy_to_int(vm, 1, &b);
  63. pkpy_push_int(vm, a - b);
  64. return 1;
  65. }
  66. int test_fib(pkpy_vm* vm) {
  67. int n;
  68. pkpy_to_int(vm, 0, &n);
  69. if (n == 1) {
  70. pkpy_push_int(vm, n);
  71. } else {
  72. pkpy_getglobal(vm, pkpy_name("test_fib"));
  73. pkpy_push_null(vm);
  74. pkpy_push_int(vm, n-1);
  75. pkpy_vectorcall(vm, 1);
  76. int r_int;
  77. pkpy_to_int(vm, -1, &r_int);
  78. pkpy_pop_top(vm);
  79. pkpy_push_int(vm, r_int + n);
  80. }
  81. return 1;
  82. }
  83. int test_default_argument(pkpy_vm* vm){
  84. int x;
  85. pkpy_to_int(vm, -1, &x);
  86. bool ok = x == 5;
  87. pkpy_push_bool(vm, ok);
  88. return 1;
  89. }
  90. int test_return_none(pkpy_vm* vm) {
  91. return 0;
  92. }
  93. int test_error_propagate(pkpy_vm* vm) {
  94. pkpy_error(vm, "NameError", pkpy_string("catch me"));
  95. return 1;
  96. }
  97. int test_nested_error(pkpy_vm* vm) {
  98. pkpy_getglobal(vm, pkpy_name("error_from_python"));
  99. pkpy_push_null(vm);
  100. pkpy_vectorcall(vm, 0);
  101. return 0;
  102. }
  103. #define PRINT_TITLE(x) printf("\n====== %s ======\n", x)
  104. int main(int argc, char** argv) {
  105. pkpy_vm* vm = pkpy_new_vm(true);
  106. PRINT_TITLE("test basic exec");
  107. check(pkpy_exec(vm, "print('hello world!')"));
  108. fail(pkpy_getglobal(vm, pkpy_name("nonexistatn")));
  109. // test int methods
  110. PRINT_TITLE("test int methods");
  111. int r_int;
  112. check(pkpy_push_int(vm, 11));
  113. pkpy_CName m_eleven = pkpy_name("eleven");
  114. check(pkpy_setglobal(vm, m_eleven));
  115. check(pkpy_exec(vm, "print(eleven)"));
  116. check(pkpy_getglobal(vm, m_eleven));
  117. check(pkpy_is_int(vm, -1));
  118. check(pkpy_to_int(vm, -1, &r_int));
  119. printf("%i\n", r_int); // 11
  120. printf("%i\n", pkpy_stack_size(vm)); // 1
  121. fail(pkpy_is_float(vm, -1));
  122. fail(pkpy_is_bool(vm, -1));
  123. fail(pkpy_is_string(vm, -1));
  124. fail(pkpy_is_none(vm, -1));
  125. fail(pkpy_is_voidp(vm, -1));
  126. PRINT_TITLE("test float methods");
  127. double r_float;
  128. check(pkpy_push_float(vm, 11.125));
  129. pkpy_CName m_elevenf = pkpy_name("elevenf");
  130. check(pkpy_setglobal(vm, m_elevenf));
  131. check(pkpy_exec(vm, "print(elevenf)"));
  132. check(pkpy_getglobal(vm, m_elevenf));
  133. check(pkpy_is_float(vm, -1));
  134. check(pkpy_to_float(vm, -1, &r_float));
  135. printf("%.3f\n", r_float);
  136. fail(pkpy_is_int(vm, -1));
  137. fail(pkpy_is_bool(vm, -1));
  138. fail(pkpy_is_string(vm, -1));
  139. fail(pkpy_is_none(vm, -1));
  140. fail(pkpy_is_voidp(vm, -1));
  141. PRINT_TITLE("test bool methods");
  142. bool r_bool;
  143. check(pkpy_push_bool(vm, false));
  144. pkpy_CName m_false_test = pkpy_name("false_test");
  145. check(pkpy_setglobal(vm, m_false_test));
  146. check(pkpy_exec(vm, "print(false_test)"));
  147. check(pkpy_getglobal(vm, m_false_test));
  148. check(pkpy_is_bool(vm, -1));
  149. check(pkpy_to_bool(vm, -1, &r_bool));
  150. printf("%i\n", r_bool);
  151. fail(pkpy_is_int(vm, -1));
  152. fail(pkpy_is_float(vm, -1));
  153. fail(pkpy_is_string(vm, -1));
  154. fail(pkpy_is_none(vm, -1));
  155. fail(pkpy_is_voidp(vm, -1));
  156. PRINT_TITLE("test string methods");
  157. pkpy_CString r_string;
  158. check(pkpy_push_string(vm, pkpy_string("hello!")));
  159. check(pkpy_setglobal(vm, pkpy_name("hello1")));
  160. check(pkpy_exec(vm, "print(hello1)"));
  161. check(pkpy_push_string(vm, pkpy_string("hello!")));
  162. check(pkpy_is_string(vm, -1));
  163. check(pkpy_to_string(vm, -1, &r_string));
  164. for(int i=0; i<r_string.size; i++) {
  165. putchar(r_string.data[i]);
  166. }
  167. putchar('\n');
  168. fail(pkpy_is_int(vm, -1));
  169. fail(pkpy_is_float(vm, -1));
  170. fail(pkpy_is_bool(vm, -1));
  171. fail(pkpy_is_none(vm, -1));
  172. fail(pkpy_is_voidp(vm, -1));
  173. PRINT_TITLE("test none methods");
  174. check(pkpy_push_none(vm));
  175. pkpy_CName m_none = pkpy_name("none");
  176. check(pkpy_setglobal(vm, m_none));
  177. check(pkpy_exec(vm, "print(none)"));
  178. check(pkpy_getglobal(vm, m_none));
  179. check(pkpy_is_none(vm, -1));
  180. fail(pkpy_is_int(vm, -1));
  181. fail(pkpy_is_float(vm, -1));
  182. fail(pkpy_is_bool(vm, -1));
  183. fail(pkpy_is_string(vm, -1));
  184. fail(pkpy_is_voidp(vm, -1));
  185. PRINT_TITLE("test voidp methods");
  186. void* vp = (void*) 123;
  187. check(pkpy_push_voidp(vm, vp));
  188. check(pkpy_setglobal(vm, pkpy_name("vp")));
  189. check(pkpy_exec(vm, "print(vp)"));
  190. check(pkpy_getglobal(vm, pkpy_name("vp")));
  191. check(pkpy_is_voidp(vm, -1));
  192. vp = NULL;
  193. check(pkpy_to_voidp(vm, -1, &vp));
  194. printf("%i\n", (int) (intptr_t) vp);
  195. fail(pkpy_is_int(vm, -1));
  196. fail(pkpy_is_float(vm, -1));
  197. fail(pkpy_is_bool(vm, -1));
  198. fail(pkpy_is_string(vm, -1));
  199. fail(pkpy_is_none(vm, -1));
  200. PRINT_TITLE("test sizing and indexing");
  201. int stack_size = pkpy_stack_size(vm);
  202. printf("stack size %i\n", stack_size);
  203. check(pkpy_is_int(vm, 0));
  204. check(pkpy_is_float(vm, 1));
  205. check(pkpy_is_bool(vm, 2));
  206. check(pkpy_is_string(vm, 3));
  207. check(pkpy_is_none(vm, 4));
  208. check(pkpy_is_voidp(vm, 5));
  209. check(pkpy_is_int(vm, -6));
  210. check(pkpy_is_float(vm, -5));
  211. check(pkpy_is_bool(vm, -4));
  212. check(pkpy_is_string(vm, -3));
  213. check(pkpy_is_none(vm, -2));
  214. check(pkpy_is_voidp(vm, -1));
  215. PRINT_TITLE("test error catching");
  216. error(pkpy_exec(vm, "let's make sure syntax errors get caught"));
  217. //stack should be cleared after error is resolved
  218. check(pkpy_stack_size(vm) == 0);
  219. PRINT_TITLE("test simple call");
  220. check(pkpy_exec(vm, "def x(x, y) : return x - y"));
  221. check(pkpy_getglobal(vm, pkpy_name("x")));
  222. check(pkpy_push_null(vm));
  223. check(pkpy_push_int(vm, 2));
  224. check(pkpy_push_int(vm, 3));
  225. check(pkpy_vectorcall(vm, 2));
  226. check(pkpy_to_int(vm, -1, &r_int));
  227. printf("x : %i\n", r_int);
  228. PRINT_TITLE("test vararg call");
  229. check(pkpy_exec(vm, "def vararg_x(*x) : return sum(x)"));
  230. check(pkpy_getglobal(vm, pkpy_name("vararg_x")));
  231. check(pkpy_push_null(vm));
  232. check(pkpy_push_int(vm, 1));
  233. check(pkpy_push_int(vm, 2));
  234. check(pkpy_push_int(vm, 3));
  235. check(pkpy_push_int(vm, 4));
  236. check(pkpy_push_int(vm, 5));
  237. check(pkpy_push_int(vm, 6));
  238. check(pkpy_vectorcall(vm, 6));
  239. check(pkpy_to_int(vm, -1, &r_int));
  240. printf("vararg_x : %i\n", r_int);
  241. PRINT_TITLE("test keyword call");
  242. check(pkpy_exec(vm, "def keyword_x(x=1, y=1) : return x+y"));
  243. check(pkpy_getglobal(vm, pkpy_name("keyword_x")));
  244. check(pkpy_push_null(vm));
  245. check(pkpy_push_int(vm, 3));
  246. check(pkpy_vectorcall(vm, 1));
  247. check(pkpy_to_int(vm, -1, &r_int));
  248. printf("keyword_x : %i\n", r_int); // 3+1
  249. check(pkpy_getglobal(vm, pkpy_name("keyword_x")));
  250. check(pkpy_push_null(vm));
  251. check(pkpy_vectorcall(vm, 0));
  252. check(pkpy_to_int(vm, -1, &r_int));
  253. printf("keyword_x : %i\n", r_int); // 1+1
  254. check(pkpy_stack_size(vm) == 4);
  255. check(pkpy_pop(vm, 4)); // clear stack
  256. PRINT_TITLE("test return many");
  257. check(pkpy_exec(vm, "def retmany_x() : return 1, 2, 3"));
  258. check(pkpy_getglobal(vm, pkpy_name("retmany_x")));
  259. check(pkpy_push_null(vm));
  260. check(pkpy_vectorcall(vm, 0));
  261. check(pkpy_stack_size(vm) == 1);
  262. check(pkpy_unpack_sequence(vm, 3));
  263. check(pkpy_stack_size(vm) == 3);
  264. check(pkpy_to_int(vm, -3, &r_int));
  265. printf("retmany_x : %i\n", r_int);
  266. check(pkpy_to_int(vm, -2, &r_int));
  267. printf("retmany_x : %i\n", r_int);
  268. check(pkpy_to_int(vm, -1, &r_int));
  269. printf("retmany_x : %i\n", r_int);
  270. // test argument error
  271. check(pkpy_getglobal(vm, pkpy_name("x")));
  272. check(pkpy_push_null(vm));
  273. error(pkpy_vectorcall(vm, 0));
  274. check(pkpy_exec(vm, "l = []"));
  275. check(pkpy_getglobal(vm, pkpy_name("l")));
  276. check(pkpy_get_unbound_method(vm, pkpy_name("append")));
  277. check(pkpy_push_string(vm, pkpy_string("hello")));
  278. check(pkpy_vectorcall(vm, 1));
  279. check(pkpy_pop_top(vm)); // pop None returned by append()
  280. check(pkpy_exec(vm, "print(l)"));
  281. PRINT_TITLE("test bindings");
  282. check(pkpy_push_function(vm, "test_binding()", test_binding));
  283. check(pkpy_setglobal(vm, pkpy_name("test_binding")));
  284. check(pkpy_exec(vm, "print(test_binding())"));
  285. check(pkpy_stack_size(vm) == 0);
  286. check(pkpy_push_function(vm, "test_multiple_return()", test_multiple_return));
  287. check(pkpy_setglobal(vm, pkpy_name("test_multiple_return")));
  288. check(pkpy_stack_size(vm) == 0);
  289. check(pkpy_push_function(vm, "test_default_argument(x=5)", test_default_argument));
  290. check(pkpy_push_null(vm));
  291. check(pkpy_vectorcall(vm, 0));
  292. check(pkpy_stack_size(vm) == 1);
  293. check(pkpy_is_bool(vm, -1) == true);
  294. check(pkpy_to_bool(vm, -1, &r_bool));
  295. check(r_bool == true);
  296. check(pkpy_pop_top(vm));
  297. check(pkpy_stack_size(vm) == 0);
  298. PRINT_TITLE("test bindings 2");
  299. check(pkpy_push_function(vm, "test_minus(a, b)", test_minus));
  300. check(pkpy_setglobal(vm, pkpy_name("test_minus")));
  301. check(pkpy_exec(vm, "print(test_minus(5, 3))"));
  302. check(pkpy_exec(vm, "for i in range(5): print(test_minus(5, i))"));
  303. check(pkpy_stack_size(vm) == 0);
  304. PRINT_TITLE("test bindings fib");
  305. check(pkpy_push_function(vm, "test_fib(n: int) -> int", test_fib));
  306. check(pkpy_setglobal(vm, pkpy_name("test_fib")));
  307. check(pkpy_exec(vm, "print(test_fib(10))"));
  308. check(pkpy_stack_size(vm) == 0);
  309. PRINT_TITLE("test error propagate");
  310. check(pkpy_push_function(vm, "test_error_propagate()", test_error_propagate));
  311. check(pkpy_setglobal(vm, pkpy_name("test_error_propagate")));
  312. error(pkpy_exec(vm, "test_error_propagate()"));
  313. check(pkpy_getglobal(vm, pkpy_name("test_multiple_return")));
  314. check(pkpy_push_null(vm));
  315. check(pkpy_vectorcall(vm, 0));
  316. check(pkpy_stack_size(vm) == 1);
  317. check(pkpy_unpack_sequence(vm, 2));
  318. check(pkpy_stack_size(vm) == 2);
  319. check(pkpy_pop(vm, 2));
  320. check(pkpy_stack_size(vm) == 0);
  321. PRINT_TITLE("test other errors");
  322. check(pkpy_getglobal(vm, pkpy_name("test_error_propagate")));
  323. check(pkpy_pop_top(vm));
  324. fail(pkpy_getglobal(vm, pkpy_name("nonexistant")));
  325. error(pkpy_exec(vm, "raise NameError('testing error throwing from python')"));
  326. PRINT_TITLE("test TypeError");
  327. check(pkpy_push_float(vm, 2.0));
  328. error(pkpy_to_int(vm, -1, &r_int));
  329. PRINT_TITLE("test complicated errors");
  330. pkpy_exec(vm, "test_error_propagate()");
  331. check(pkpy_check_error(vm));
  332. pkpy_clear_error(vm, NULL);
  333. //this should be catchable
  334. check(pkpy_exec(vm, "try : test_error_propagate(); except NameError : pass"));
  335. error(pkpy_error(vm, "Exception", pkpy_string("test direct error mechanism")));
  336. //more complicated error handling
  337. check(pkpy_exec(vm, "def error_from_python() : raise NotImplementedError()"));
  338. check(pkpy_push_function(vm, "test_nested_error()", test_nested_error));
  339. check(pkpy_setglobal(vm, pkpy_name("test_nested_error")));
  340. error(pkpy_exec(vm, "test_nested_error()"));
  341. PRINT_TITLE("test getattr/setattr");
  342. check(pkpy_stack_size(vm) == 0);
  343. check(pkpy_exec(vm, "import math"));
  344. check(pkpy_getglobal(vm, pkpy_name("math")));
  345. check(pkpy_getattr(vm, pkpy_name("pi")));
  346. check(pkpy_to_float(vm, -1, &r_float));
  347. printf("pi: %.2f\n", (float)r_float);
  348. check(pkpy_pop(vm, 1));
  349. // math.pi = 2
  350. check(pkpy_push_int(vm, 2));
  351. check(pkpy_eval(vm, "math"));
  352. check(pkpy_setattr(vm, pkpy_name("pi")));
  353. check(pkpy_exec(vm, "print(math.pi)"));
  354. PRINT_TITLE("test eval");
  355. check(pkpy_eval(vm, "math.pi"));
  356. check(pkpy_to_float(vm, -1, &r_float));
  357. printf("pi: %.2f\n", (float)r_float);
  358. check(pkpy_pop(vm, 1));
  359. check(pkpy_stack_size(vm) == 0);
  360. PRINT_TITLE("test py_repr");
  361. check(pkpy_eval(vm, "['1', 2, (3, '4')]"));
  362. check(pkpy_py_repr(vm));
  363. check(pkpy_to_string(vm, -1, &r_string));
  364. for(int i = 0; i < r_string.size; i++) putchar(r_string.data[i]);
  365. putchar('\n');
  366. check(pkpy_pop_top(vm));
  367. check(pkpy_stack_size(vm) == 0);
  368. return 0;
  369. }