|
|
@@ -0,0 +1,300 @@
|
|
|
+#include "pocketpy_c.h"
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+
|
|
|
+//tests the c bindings for pocketpy
|
|
|
+
|
|
|
+void check_impl(pkpy_vm* vm, bool result, int lineno) {
|
|
|
+ if (!result) {
|
|
|
+ printf("ERROR: failed where it should have succeed at line %i\n", lineno);
|
|
|
+ char* message;
|
|
|
+ if (!pkpy_clear_error(vm, &message)) {
|
|
|
+ printf("clear error reported everything was fine\n");
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("%s\n", message);
|
|
|
+ free(message);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void fail_impl(pkpy_vm* vm, bool result, int lineno) {
|
|
|
+ if (result) {
|
|
|
+ printf("ERROR: succeeded where it should have failed line %i\n", lineno);
|
|
|
+ exit(1);
|
|
|
+ } else {
|
|
|
+ char* message;
|
|
|
+ if (pkpy_clear_error(vm, &message)) {
|
|
|
+ printf("actually errored!\n");
|
|
|
+ free(message);
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void error_impl(pkpy_vm* vm, bool result, int lineno) {
|
|
|
+ if (result) {
|
|
|
+ printf("ERROR: succeeded where it should have failed line %i\n", lineno);
|
|
|
+ exit(1);
|
|
|
+ } else {
|
|
|
+ char* message;
|
|
|
+ if (!pkpy_clear_error(vm, &message))
|
|
|
+ printf("clear error reported everything was fine\n");
|
|
|
+ else {
|
|
|
+ printf("successfully errored with this message: \n");
|
|
|
+ printf("%s\n", message);
|
|
|
+ free(message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+#define check(r) check_impl(vm, (r), __LINE__)
|
|
|
+#define fail(r) fail_impl(vm, (r), __LINE__)
|
|
|
+#define error(r) error_impl(vm, (r), __LINE__)
|
|
|
+
|
|
|
+int test_binding(pkpy_vm* vm) {
|
|
|
+ pkpy_push_int(vm, 12);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+int test_multiple_return(pkpy_vm* vm) {
|
|
|
+ pkpy_push_int(vm, 12);
|
|
|
+ pkpy_push_int(vm, 13);
|
|
|
+ return 2;
|
|
|
+}
|
|
|
+
|
|
|
+int test_return_none(pkpy_vm* vm) {
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int test_error_propagate(pkpy_vm* vm) {
|
|
|
+ pkpy_get_global(vm, "does not exist");
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+pkpy_vm* vm;
|
|
|
+
|
|
|
+void cleanup(void) {
|
|
|
+ pkpy_vm_destroy(vm);
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char** argv) {
|
|
|
+
|
|
|
+ vm = pkpy_vm_create(true, true);
|
|
|
+ atexit(cleanup);
|
|
|
+
|
|
|
+ //test run
|
|
|
+ check(pkpy_vm_run(vm, "print('hello world!')"));
|
|
|
+
|
|
|
+ error(pkpy_get_global(vm, "nonexistatn"));
|
|
|
+
|
|
|
+ printf("\ntesting int methods\n");
|
|
|
+ int r_int;
|
|
|
+ check(pkpy_push_int(vm, 11));
|
|
|
+ check(pkpy_set_global(vm, "eleven"));
|
|
|
+ check(pkpy_vm_run(vm, "print(eleven)"));
|
|
|
+ check(pkpy_get_global(vm, "eleven"));
|
|
|
+ check(pkpy_is_int(vm, -1));
|
|
|
+ check(pkpy_to_int(vm, -1, &r_int));
|
|
|
+ printf("%i\n", r_int);
|
|
|
+ fail(pkpy_is_float(vm, -1));
|
|
|
+ fail(pkpy_is_bool(vm, -1));
|
|
|
+ fail(pkpy_is_string(vm, -1));
|
|
|
+ fail(pkpy_is_none(vm, -1));
|
|
|
+ fail(pkpy_is_voidp(vm, -1));
|
|
|
+
|
|
|
+ printf("\ntesting float methods\n");
|
|
|
+ double r_float;
|
|
|
+ check(pkpy_push_float(vm, 11.11));
|
|
|
+ check(pkpy_set_global(vm, "elevenf"));
|
|
|
+ check(pkpy_vm_run(vm, "print(elevenf)"));
|
|
|
+ check(pkpy_get_global(vm, "elevenf"));
|
|
|
+ check(pkpy_is_float(vm, -1));
|
|
|
+ check(pkpy_to_float(vm, -1, &r_float));
|
|
|
+ printf("%f\n", r_float);
|
|
|
+ fail(pkpy_is_int(vm, -1));
|
|
|
+ fail(pkpy_is_bool(vm, -1));
|
|
|
+ fail(pkpy_is_string(vm, -1));
|
|
|
+ fail(pkpy_is_none(vm, -1));
|
|
|
+ fail(pkpy_is_voidp(vm, -1));
|
|
|
+
|
|
|
+ printf("\ntesting bool methods\n");
|
|
|
+ bool r_bool;
|
|
|
+ check(pkpy_push_bool(vm, false));
|
|
|
+ check(pkpy_set_global(vm, "false_test"));
|
|
|
+ check(pkpy_vm_run(vm, "print(false_test)"));
|
|
|
+ check(pkpy_get_global(vm, "false_test"));
|
|
|
+ check(pkpy_is_bool(vm, -1));
|
|
|
+ check(pkpy_to_bool(vm, -1, &r_bool));
|
|
|
+ printf("%i\n", r_bool);
|
|
|
+ fail(pkpy_is_int(vm, -1));
|
|
|
+ fail(pkpy_is_float(vm, -1));
|
|
|
+ fail(pkpy_is_string(vm, -1));
|
|
|
+ fail(pkpy_is_none(vm, -1));
|
|
|
+ fail(pkpy_is_voidp(vm, -1));
|
|
|
+
|
|
|
+ printf("\ntesting string methods\n");
|
|
|
+ char* r_string;
|
|
|
+ check(pkpy_push_string(vm, "hello!"));
|
|
|
+ check(pkpy_set_global(vm, "hello1"));
|
|
|
+ check(pkpy_vm_run(vm, "print(hello1)"));
|
|
|
+ check(pkpy_push_stringn(vm, "hello!", 5));
|
|
|
+ check(pkpy_is_string(vm, -1));
|
|
|
+ check(pkpy_to_string(vm, -1, &r_string));
|
|
|
+ printf("%s\n", r_string);
|
|
|
+ free(r_string);
|
|
|
+ const char* r_stringn;
|
|
|
+ int r_size;
|
|
|
+ check(pkpy_to_stringn(vm, -1, &r_stringn, &r_size));
|
|
|
+ printf("%.*s\n", r_size, r_stringn);
|
|
|
+ fail(pkpy_is_int(vm, -1));
|
|
|
+ fail(pkpy_is_float(vm, -1));
|
|
|
+ fail(pkpy_is_bool(vm, -1));
|
|
|
+ fail(pkpy_is_none(vm, -1));
|
|
|
+ fail(pkpy_is_voidp(vm, -1));
|
|
|
+
|
|
|
+ printf("\ntesting None methods\n");
|
|
|
+ check(pkpy_push_none(vm));
|
|
|
+ check(pkpy_set_global(vm, "none"));
|
|
|
+ check(pkpy_vm_run(vm, "print(none)"));
|
|
|
+ check(pkpy_get_global(vm, "none"));
|
|
|
+ check(pkpy_is_none(vm, -1));
|
|
|
+ fail(pkpy_is_int(vm, -1));
|
|
|
+ fail(pkpy_is_float(vm, -1));
|
|
|
+ fail(pkpy_is_bool(vm, -1));
|
|
|
+ fail(pkpy_is_string(vm, -1));
|
|
|
+ fail(pkpy_is_voidp(vm, -1));
|
|
|
+
|
|
|
+ printf("\ntesting voidp methods\n");
|
|
|
+ void* vp = (void*) 123;
|
|
|
+ check(pkpy_push_voidp(vm, vp));
|
|
|
+ check(pkpy_set_global(vm, "vp"));
|
|
|
+ check(pkpy_vm_run(vm, "print(vp)"));
|
|
|
+ check(pkpy_get_global(vm, "vp"));
|
|
|
+ check(pkpy_is_voidp(vm, -1));
|
|
|
+ vp = NULL;
|
|
|
+ check(pkpy_to_voidp(vm, -1, &vp));
|
|
|
+ printf("%i\n", (int) (intptr_t) vp);
|
|
|
+ fail(pkpy_is_int(vm, -1));
|
|
|
+ fail(pkpy_is_float(vm, -1));
|
|
|
+ fail(pkpy_is_bool(vm, -1));
|
|
|
+ fail(pkpy_is_string(vm, -1));
|
|
|
+ fail(pkpy_is_none(vm, -1));
|
|
|
+
|
|
|
+
|
|
|
+ printf("\ntesting sizing and indexing\n");
|
|
|
+ int stack_size = pkpy_stack_size(vm);
|
|
|
+ printf("stack size %i\n", stack_size);
|
|
|
+ check(pkpy_check_stack(vm, 10));
|
|
|
+ check(pkpy_check_stack(vm, 26));
|
|
|
+ fail(pkpy_check_stack(vm, 27));
|
|
|
+ check(pkpy_is_int(vm, 0));
|
|
|
+ check(pkpy_is_float(vm, 1));
|
|
|
+ check(pkpy_is_bool(vm, 2));
|
|
|
+ check(pkpy_is_string(vm, 3));
|
|
|
+ check(pkpy_is_none(vm, 4));
|
|
|
+ check(pkpy_is_voidp(vm, 5));
|
|
|
+ check(pkpy_is_int(vm, -6));
|
|
|
+ check(pkpy_is_float(vm, -5));
|
|
|
+ check(pkpy_is_bool(vm, -4));
|
|
|
+ check(pkpy_is_string(vm, -3));
|
|
|
+ check(pkpy_is_none(vm, -2));
|
|
|
+ check(pkpy_is_voidp(vm, -1));
|
|
|
+
|
|
|
+ printf("\ntesting error catching\n");
|
|
|
+ error(pkpy_vm_run(vm, "let's make sure syntax errors get caught"));
|
|
|
+ check(pkpy_stack_size(vm) == 0); //stack should be cleared after error is resolved
|
|
|
+
|
|
|
+ printf("\ntesting calls\n");
|
|
|
+
|
|
|
+ check(pkpy_vm_run(vm, "def x(x, y) : return x - y"));
|
|
|
+ check(pkpy_vm_run(vm, "def vararg_x(*x) : return sum(x)"));
|
|
|
+ check(pkpy_vm_run(vm, "def keyword_x(x=1, y=1) : return x+y"));
|
|
|
+ check(pkpy_vm_run(vm, "def retmany_x() : return 1, 2, 3"));
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "x"));
|
|
|
+ check(pkpy_push_int(vm, 2));
|
|
|
+ check(pkpy_push_int(vm, 3));
|
|
|
+ check(pkpy_call(vm, 2));
|
|
|
+ check(pkpy_to_int(vm, -1, &r_int));
|
|
|
+ printf("x : %i\n", r_int);
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "vararg_x"));
|
|
|
+ check(pkpy_push_int(vm, 1));
|
|
|
+ check(pkpy_push_int(vm, 2));
|
|
|
+ check(pkpy_push_int(vm, 3));
|
|
|
+ check(pkpy_push_int(vm, 4));
|
|
|
+ check(pkpy_push_int(vm, 5));
|
|
|
+ check(pkpy_push_int(vm, 6));
|
|
|
+ check(pkpy_call(vm, 6));
|
|
|
+ check(pkpy_to_int(vm, -1, &r_int));
|
|
|
+ printf("vararg_x : %i\n", r_int);
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "keyword_x"));
|
|
|
+ check(pkpy_push_int(vm, 3));
|
|
|
+ check(pkpy_call(vm, 1));
|
|
|
+ check(pkpy_to_int(vm, -1, &r_int));
|
|
|
+ printf("keyword_x : %i\n", r_int);
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "keyword_x"));
|
|
|
+ check(pkpy_call(vm, 0));
|
|
|
+ check(pkpy_to_int(vm, -1, &r_int));
|
|
|
+ printf("keyword_x : %i\n", r_int);
|
|
|
+
|
|
|
+ check(pkpy_stack_size(vm) == 4);
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "retmany_x"));
|
|
|
+ check(pkpy_call(vm, 0));
|
|
|
+ check(pkpy_stack_size(vm) == 7);
|
|
|
+ check(pkpy_to_int(vm, -3, &r_int));
|
|
|
+ printf("retmany_x : %i\n", r_int);
|
|
|
+ check(pkpy_to_int(vm, -2, &r_int));
|
|
|
+ printf("retmany_x : %i\n", r_int);
|
|
|
+ check(pkpy_to_int(vm, -1, &r_int));
|
|
|
+ printf("retmany_x : %i\n", r_int);
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "x"));
|
|
|
+ error(pkpy_call(vm, 0));
|
|
|
+
|
|
|
+ check(pkpy_vm_run(vm, "l = []"));
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "l"));
|
|
|
+ check(pkpy_push_string(vm, "hello"));
|
|
|
+ check(pkpy_call_method(vm, "append", 1));
|
|
|
+ check(pkpy_vm_run(vm, "print(l)"));
|
|
|
+
|
|
|
+
|
|
|
+ printf("\ntesting pushing functions\n");
|
|
|
+
|
|
|
+ check(pkpy_push_function(vm, test_binding));
|
|
|
+ check(pkpy_set_global(vm, "test_binding"));
|
|
|
+ check(pkpy_vm_run(vm, "print(test_binding())"));
|
|
|
+
|
|
|
+ check(pkpy_push_function(vm, test_multiple_return));
|
|
|
+ check(pkpy_set_global(vm, "test_multiple_return"));
|
|
|
+
|
|
|
+ //uncomment if _exec changes
|
|
|
+ //check(pkpy_vm_run(vm, "test_multiple_return()"));
|
|
|
+ //check(pkpy_stack_size(vm) == 2);
|
|
|
+
|
|
|
+ check(pkpy_push_function(vm, test_error_propagate));
|
|
|
+ check(pkpy_set_global(vm, "test_error_propagate"));
|
|
|
+ error(pkpy_vm_run(vm, "test_error_propagate()"));
|
|
|
+
|
|
|
+ check(pkpy_get_global(vm, "test_multiple_return"));
|
|
|
+ check(pkpy_call(vm, 0));
|
|
|
+ check(pkpy_stack_size(vm) == 2);
|
|
|
+
|
|
|
+ check(pkpy_pop(vm, 2));
|
|
|
+ check(pkpy_stack_size(vm) == 0);
|
|
|
+
|
|
|
+ check(pkpy_check_global(vm, "test_error_propagate"));
|
|
|
+ fail(pkpy_check_global(vm, "nonexistant"));
|
|
|
+ pkpy_vm_run(vm, "test_error_propagate()");
|
|
|
+ check(pkpy_check_error(vm));
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|