test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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. else {
  40. printf("successfully errored with this message: \n");
  41. printf("%s\n", message);
  42. free(message);
  43. }
  44. }
  45. }
  46. #define check(r) check_impl(vm, (r), __LINE__)
  47. #define fail(r) fail_impl(vm, (r), __LINE__)
  48. #define error(r) error_impl(vm, (r), __LINE__)
  49. int test_binding(pkpy_vm* vm) {
  50. pkpy_push_int(vm, 12);
  51. return 1;
  52. }
  53. int test_multiple_return(pkpy_vm* vm) {
  54. pkpy_push_int(vm, 12);
  55. pkpy_push_int(vm, 13);
  56. return 2;
  57. }
  58. int test_return_none(pkpy_vm* vm) {
  59. return 0;
  60. }
  61. int test_error_propagate(pkpy_vm* vm) {
  62. pkpy_get_global(vm, "does not exist");
  63. return 1;
  64. }
  65. int test_nested_error(pkpy_vm* vm) {
  66. pkpy_get_global(vm, "error_from_python");
  67. pkpy_call(vm, 0);
  68. return 0;
  69. }
  70. pkpy_vm* vm;
  71. int main(int argc, char** argv) {
  72. vm = pkpy_vm_create(true, true);
  73. //test run
  74. check(pkpy_vm_run(vm, "print('hello world!')"));
  75. error(pkpy_get_global(vm, "nonexistatn"));
  76. printf("\ntesting int methods\n");
  77. int r_int;
  78. check(pkpy_push_int(vm, 11));
  79. check(pkpy_set_global(vm, "eleven"));
  80. check(pkpy_vm_run(vm, "print(eleven)"));
  81. check(pkpy_get_global(vm, "eleven"));
  82. check(pkpy_is_int(vm, -1));
  83. check(pkpy_to_int(vm, -1, &r_int));
  84. printf("%i\n", r_int);
  85. fail(pkpy_is_float(vm, -1));
  86. fail(pkpy_is_bool(vm, -1));
  87. fail(pkpy_is_string(vm, -1));
  88. fail(pkpy_is_none(vm, -1));
  89. fail(pkpy_is_voidp(vm, -1));
  90. printf("\ntesting float methods\n");
  91. double r_float;
  92. check(pkpy_push_float(vm, 11.11));
  93. check(pkpy_set_global(vm, "elevenf"));
  94. check(pkpy_vm_run(vm, "print(elevenf)"));
  95. check(pkpy_get_global(vm, "elevenf"));
  96. check(pkpy_is_float(vm, -1));
  97. check(pkpy_to_float(vm, -1, &r_float));
  98. printf("%f\n", r_float);
  99. fail(pkpy_is_int(vm, -1));
  100. fail(pkpy_is_bool(vm, -1));
  101. fail(pkpy_is_string(vm, -1));
  102. fail(pkpy_is_none(vm, -1));
  103. fail(pkpy_is_voidp(vm, -1));
  104. printf("\ntesting bool methods\n");
  105. bool r_bool;
  106. check(pkpy_push_bool(vm, false));
  107. check(pkpy_set_global(vm, "false_test"));
  108. check(pkpy_vm_run(vm, "print(false_test)"));
  109. check(pkpy_get_global(vm, "false_test"));
  110. check(pkpy_is_bool(vm, -1));
  111. check(pkpy_to_bool(vm, -1, &r_bool));
  112. printf("%i\n", r_bool);
  113. fail(pkpy_is_int(vm, -1));
  114. fail(pkpy_is_float(vm, -1));
  115. fail(pkpy_is_string(vm, -1));
  116. fail(pkpy_is_none(vm, -1));
  117. fail(pkpy_is_voidp(vm, -1));
  118. printf("\ntesting string methods\n");
  119. char* r_string;
  120. check(pkpy_push_string(vm, "hello!"));
  121. check(pkpy_set_global(vm, "hello1"));
  122. check(pkpy_vm_run(vm, "print(hello1)"));
  123. check(pkpy_push_stringn(vm, "hello!", 5));
  124. check(pkpy_is_string(vm, -1));
  125. check(pkpy_to_string(vm, -1, &r_string));
  126. printf("%s\n", r_string);
  127. free(r_string);
  128. const char* r_stringn;
  129. int r_size;
  130. check(pkpy_to_stringn(vm, -1, &r_stringn, &r_size));
  131. printf("%.*s\n", r_size, r_stringn);
  132. fail(pkpy_is_int(vm, -1));
  133. fail(pkpy_is_float(vm, -1));
  134. fail(pkpy_is_bool(vm, -1));
  135. fail(pkpy_is_none(vm, -1));
  136. fail(pkpy_is_voidp(vm, -1));
  137. printf("\ntesting None methods\n");
  138. check(pkpy_push_none(vm));
  139. check(pkpy_set_global(vm, "none"));
  140. check(pkpy_vm_run(vm, "print(none)"));
  141. check(pkpy_get_global(vm, "none"));
  142. check(pkpy_is_none(vm, -1));
  143. fail(pkpy_is_int(vm, -1));
  144. fail(pkpy_is_float(vm, -1));
  145. fail(pkpy_is_bool(vm, -1));
  146. fail(pkpy_is_string(vm, -1));
  147. fail(pkpy_is_voidp(vm, -1));
  148. printf("\ntesting voidp methods\n");
  149. void* vp = (void*) 123;
  150. check(pkpy_push_voidp(vm, vp));
  151. check(pkpy_set_global(vm, "vp"));
  152. check(pkpy_vm_run(vm, "print(vp)"));
  153. check(pkpy_get_global(vm, "vp"));
  154. check(pkpy_is_voidp(vm, -1));
  155. vp = NULL;
  156. check(pkpy_to_voidp(vm, -1, &vp));
  157. printf("%i\n", (int) (intptr_t) vp);
  158. fail(pkpy_is_int(vm, -1));
  159. fail(pkpy_is_float(vm, -1));
  160. fail(pkpy_is_bool(vm, -1));
  161. fail(pkpy_is_string(vm, -1));
  162. fail(pkpy_is_none(vm, -1));
  163. printf("\ntesting sizing and indexing\n");
  164. int stack_size = pkpy_stack_size(vm);
  165. printf("stack size %i\n", stack_size);
  166. check(pkpy_check_stack(vm, 10));
  167. check(pkpy_check_stack(vm, 26));
  168. fail(pkpy_check_stack(vm, 27));
  169. check(pkpy_is_int(vm, 0));
  170. check(pkpy_is_float(vm, 1));
  171. check(pkpy_is_bool(vm, 2));
  172. check(pkpy_is_string(vm, 3));
  173. check(pkpy_is_none(vm, 4));
  174. check(pkpy_is_voidp(vm, 5));
  175. check(pkpy_is_int(vm, -6));
  176. check(pkpy_is_float(vm, -5));
  177. check(pkpy_is_bool(vm, -4));
  178. check(pkpy_is_string(vm, -3));
  179. check(pkpy_is_none(vm, -2));
  180. check(pkpy_is_voidp(vm, -1));
  181. check(pkpy_push(vm, -3));
  182. check(pkpy_is_string(vm, -1));
  183. printf("\ntesting error catching\n");
  184. error(pkpy_vm_run(vm, "let's make sure syntax errors get caught"));
  185. check(pkpy_stack_size(vm) == 0); //stack should be cleared after error is resolved
  186. printf("\ntesting calls\n");
  187. check(pkpy_vm_run(vm, "def x(x, y) : return x - y"));
  188. check(pkpy_vm_run(vm, "def vararg_x(*x) : return sum(x)"));
  189. check(pkpy_vm_run(vm, "def keyword_x(x=1, y=1) : return x+y"));
  190. check(pkpy_vm_run(vm, "def retmany_x() : return 1, 2, 3"));
  191. check(pkpy_get_global(vm, "x"));
  192. check(pkpy_push_int(vm, 2));
  193. check(pkpy_push_int(vm, 3));
  194. check(pkpy_call(vm, 2));
  195. check(pkpy_to_int(vm, -1, &r_int));
  196. printf("x : %i\n", r_int);
  197. check(pkpy_get_global(vm, "vararg_x"));
  198. check(pkpy_push_int(vm, 1));
  199. check(pkpy_push_int(vm, 2));
  200. check(pkpy_push_int(vm, 3));
  201. check(pkpy_push_int(vm, 4));
  202. check(pkpy_push_int(vm, 5));
  203. check(pkpy_push_int(vm, 6));
  204. check(pkpy_call(vm, 6));
  205. check(pkpy_to_int(vm, -1, &r_int));
  206. printf("vararg_x : %i\n", r_int);
  207. check(pkpy_get_global(vm, "keyword_x"));
  208. check(pkpy_push_int(vm, 3));
  209. check(pkpy_call(vm, 1));
  210. check(pkpy_to_int(vm, -1, &r_int));
  211. printf("keyword_x : %i\n", r_int);
  212. check(pkpy_get_global(vm, "keyword_x"));
  213. check(pkpy_call(vm, 0));
  214. check(pkpy_to_int(vm, -1, &r_int));
  215. printf("keyword_x : %i\n", r_int);
  216. check(pkpy_stack_size(vm) == 4);
  217. check(pkpy_get_global(vm, "retmany_x"));
  218. check(pkpy_call(vm, 0));
  219. check(pkpy_stack_size(vm) == 7);
  220. check(pkpy_to_int(vm, -3, &r_int));
  221. printf("retmany_x : %i\n", r_int);
  222. check(pkpy_to_int(vm, -2, &r_int));
  223. printf("retmany_x : %i\n", r_int);
  224. check(pkpy_to_int(vm, -1, &r_int));
  225. printf("retmany_x : %i\n", r_int);
  226. check(pkpy_get_global(vm, "x"));
  227. error(pkpy_call(vm, 0));
  228. check(pkpy_vm_run(vm, "l = []"));
  229. check(pkpy_get_global(vm, "l"));
  230. check(pkpy_push_string(vm, "hello"));
  231. check(pkpy_call_method(vm, "append", 1));
  232. check(pkpy_vm_run(vm, "print(l)"));
  233. printf("\ntesting pushing functions\n");
  234. check(pkpy_push_function(vm, test_binding));
  235. check(pkpy_set_global(vm, "test_binding"));
  236. check(pkpy_vm_run(vm, "print(test_binding())"));
  237. check(pkpy_push_function(vm, test_multiple_return));
  238. check(pkpy_set_global(vm, "test_multiple_return"));
  239. //uncomment if _exec changes
  240. //check(pkpy_vm_run(vm, "test_multiple_return()"));
  241. //check(pkpy_stack_size(vm) == 2);
  242. check(pkpy_push_function(vm, test_error_propagate));
  243. check(pkpy_set_global(vm, "test_error_propagate"));
  244. error(pkpy_vm_run(vm, "test_error_propagate()"));
  245. check(pkpy_get_global(vm, "test_multiple_return"));
  246. check(pkpy_call(vm, 0));
  247. check(pkpy_stack_size(vm) == 2);
  248. check(pkpy_pop(vm, 2));
  249. check(pkpy_stack_size(vm) == 0);
  250. check(pkpy_check_global(vm, "test_error_propagate"));
  251. fail(pkpy_check_global(vm, "nonexistant"));
  252. error(pkpy_vm_run(vm, "raise NameError('testing error throwing from python')"));
  253. pkpy_vm_run(vm, "test_error_propagate()");
  254. check(pkpy_check_error(vm));
  255. // testing code going to standard error, can ignore next error
  256. pkpy_clear_error(vm, NULL);
  257. //with the current way execptions are handled, this will fail and pass the
  258. //error clean through, ignoring the python handling
  259. //
  260. //maybe worth fixing someday, but for now it is functionating as implemented
  261. check(pkpy_vm_run(vm, "try : test_error_propagate(); except NameError : pass"));
  262. error(pkpy_error(vm, "_", "test direct error mechanism"));
  263. //more complicated error handling
  264. //
  265. //at the moment this is disabled, as this use case is not supported
  266. //it will cause the program to abort
  267. //
  268. //a python exception thrown from python can not pass through a c binding
  269. //
  270. //this means for now the api can only be used to make shallow bindings, or
  271. //else care must be taken to not let an exception go through a c binding by
  272. //catching it in python first
  273. //
  274. //at such a time this interferes with a real world use case of the bindings
  275. //we can revisit it
  276. //
  277. check(pkpy_vm_run(vm, "def error_from_python() : raise NotImplementedError()"));
  278. check(pkpy_push_function(vm, test_nested_error));
  279. check(pkpy_set_global(vm, "test_nested_error"));
  280. error(pkpy_vm_run(vm, "test_nested_error()"));
  281. check(pkpy_vm_run(vm, "import math"));
  282. check(pkpy_get_global(vm, "math"));
  283. check(pkpy_getattr(vm, "pi"));
  284. check(pkpy_to_float(vm, -1, &r_float));
  285. printf("pi: %.2f\n", r_float);
  286. check(pkpy_eval(vm, "math.pi"));
  287. check(pkpy_to_float(vm, -1, &r_float));
  288. printf("pi: %.2f\n", r_float);
  289. check(pkpy_pop(vm, 1));
  290. // math.pi = 2
  291. check(pkpy_push_int(vm, 2));
  292. check(pkpy_eval(vm, "math"));
  293. check(pkpy_setattr(vm, "pi"));
  294. check(pkpy_vm_run(vm, "print(math.pi)"));
  295. pkpy_vm_destroy(vm);
  296. return 0;
  297. }