123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <dirent.h> // for readdir
- #include "jslex.h"
- #include "jsvar.h"
- #include "jsparse.h"
- #include "jswrap_json.h"
- #include "jsinteractive.h"
- #include "jshardware.h"
- #include <finsh.h>
- #define TEST_DIR "tests/"
- bool isRunning = true;
- void nativeQuit(JsVarRef var) {
- NOT_USED(var);
- isRunning = false;
- }
- void nativeInterrupt(JsVarRef var) {
- NOT_USED(var);
- jspSetInterrupted(true);
- }
- const char *read_file(const char *filename) {
- struct stat results;
- if (!stat(filename, &results) == 0) {
- printf("Cannot stat file! '%s'\r\n", filename);
- return 0;
- }
- int size = (int)results.st_size;
- FILE *file = fopen( filename, "rb" );
- /* if we open as text, the number of bytes read may be > the size we read */
- if( !file ) {
- printf("Unable to open file! '%s'\r\n", filename);
- return 0;
- }
- char *buffer = malloc(size+1);
- size_t actualRead = fread(buffer,1,size,file);
- buffer[actualRead]=0;
- buffer[size]=0;
- fclose(file);
- return buffer;
- }
- bool run_test(const char *filename) {
- printf("----------------------------------\r\n");
- printf("----------------------------- TEST %s \r\n", filename);
- char *buffer = (char *)read_file(filename);
- if (!buffer) return (false);
- jshInit();
- jsiInit(false /* do not autoload!!! */);
- jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit);
- jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt);
- jsvUnLock(jspEvaluate(jsiGetParser(), buffer ));
- isRunning = true;
- while (isRunning && jsiHasTimers()) jsiLoop();
- JsVar *result = jsvObjectGetChild(jsiGetParser()->root, "result", 0/*no create*/);
- bool pass = jsvGetBool(result);
- jsvUnLock(result);
- if (pass)
- printf("----------------------------- PASS %s\r\n", filename);
- else {
- printf("----------------------------------\r\n");
- printf("----------------------------- FAIL %s <-------\r\n", filename);
- jsvTrace(jsvGetRef(jsiGetParser()->root), 0);
- printf("----------------------------- FAIL %s <-------\r\n", filename);
- printf("----------------------------------\r\n");
- }
- printf("BEFORE: %d Memory Records Used\r\n", jsvGetMemoryUsage());
- // jsvTrace(jsiGetParser()->root, 0);
- jsiKill();
- printf("AFTER: %d Memory Records Used\r\n", jsvGetMemoryUsage());
- jsvGarbageCollect();
- printf("AFTER GC: %d Memory Records Used (should be 0!)\r\n", jsvGetMemoryUsage());
- jsvShowAllocated();
- jshKill();
- //jsvDottyOutput();
- printf("\r\n");
- free(buffer);
- return pass;
- }
- bool run_all_tests() {
- int count = 0;
- int passed = 0;
- char *fails = malloc(1);
- fails[0] = 0;
- DIR *dir = opendir(TEST_DIR);
- if(dir) {
- struct dirent *pDir=NULL;
- while((pDir = readdir(dir)) != NULL) {
- char *fn = (*pDir).d_name;
- int l = strlen(fn);
- if (l>3 && fn[l-3]=='.' && fn[l-2]=='j' && fn[l-1]=='s') {
- char *full_fn = malloc(1+l+strlen(TEST_DIR));
- strcpy(full_fn, TEST_DIR);
- strcat(full_fn, fn);
- if (run_test(full_fn)) {
- passed++;
- } else {
- char *t = malloc(strlen(fails)+3+strlen(full_fn));
- strcpy(t, fails);
- strcat(t,full_fn);
- strcat(t,"\r\n");
- free(fails);
- fails =t;
- }
- count++;
- }
- }
- closedir(dir);
- } else {
- printf(TEST_DIR" directory not found");
- }
- if (count==0) printf("No tests found in "TEST_DIR"test*.js!\r\n");
- printf("--------------------------------------------------\r\n");
- printf(" %d of %d tests passed\r\n", passed, count);
- if (passed!=count) {
- printf("FAILS:\r\n%s", fails);
- }
- printf("--------------------------------------------------\r\n");
- free(fails);
- return passed == count;
- }
- bool run_memory_test(const char *fn, int vars) {
- int i;
- int min = 20;
- int max = 100;
- if (vars>0) {
- min = vars;
- max = vars+1;
- }
- for (i=min;i<max;i++) {
- jsvSetMaxVarsUsed(i);
- printf("----------------------------------------------------- MEMORY TEST WITH %d VARS\n", i);
- if (!run_test(fn))
- return false;
- }
- return true;
- }
- bool run_memory_tests(int vars) {
- int test_num = 1;
- int count = 0;
- int passed = 0;
- while (test_num<1000) {
- char fn[32];
- sprintf(fn, TEST_DIR"test%03d.js", test_num);
- // check if the file exists - if not, assume we're at the end of our tests
- FILE *f = fopen(fn,"r");
- if (!f) break;
- fclose(f);
- run_memory_test(fn, vars);
- test_num++;
- }
- if (count==0) printf("No tests found in "TEST_DIR"test*.js!\n");
- return true;
- }
- void show_help() {
- printf("Usage:\n");
- printf(" ./espruino : JavaScript immdeiate mode (REPL)\n");
- printf(" ./espruino script.js : Load and run script.js\n");
- printf(" ./espruino -e \"print('Hello World')\" : Print 'Hello World'\n");
- printf("\n");
- printf("Options:\n");
- printf(" -h, --help Print this help screen\n");
- printf(" -e, --eval script Evaluate the JavaScript supplied on the command-line\n");
- printf(" --test-all Run all tests (in 'tests' directory)\n");
- printf(" --test test.js Run the supplied test\n");
- printf(" --test-mem-all Run all Exhaustive Memory crash tests\n");
- printf(" --test-mem test.js Run the supplied Exhaustive Memory crash test\n");
- printf(" --test-mem-n test.js # Run the supplied Exhaustive Memory crash test with # vars\n");
- }
- #define die(txt) \
- do{ \
- printf("%s", txt); \
- return (1); \
- } while(0)
- int espruino(int argc, char **argv) {
- int i;
- for (i=1;i<argc;i++) {
- if (argv[i][0]=='-') {
- // option
- char *a = argv[i];
- if (!strcmp(a,"-h") || !strcmp(a,"--help")) {
- show_help();
- return (1);
- } else if (!strcmp(a,"-e") || !strcmp(a,"--eval")) {
- if (i+1>=argc) die("Expecting an extra argument\n");
- jshInit();
- jsiInit(true);
- jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit);
- jsvUnLock(jspEvaluate(jsiGetParser(), argv[i+1]));
- isRunning = true;
- //while (isRunning && jsiHasTimers()) jsiLoop();
- jsiKill();
- jshKill();
- return (0);
- } else if (!strcmp(a,"--test")) {
- if (i+1>=argc) die("Expecting an extra argument\n");
- bool ok = run_test(argv[i+1]);
- return (ok ? 0 : 1);
- } else if (!strcmp(a,"--test-all")) {
- bool ok = run_all_tests();
- return (ok ? 0 : 1);
- } else if (!strcmp(a,"--test-mem-all")) {
- bool ok = run_memory_tests(0);
- return (ok ? 0 : 1);
- } else if (!strcmp(a,"--test-mem")) {
- if (i+1>=argc) die("Expecting an extra argument\n");
- bool ok = run_memory_test(argv[i+1], 0);
- return (ok ? 0 : 1);
- } else if (!strcmp(a,"--test-mem-n")) {
- if (i+2>=argc) die("Expecting an extra 2 arguments\n");
- bool ok = run_memory_test(argv[i+1], atoi(argv[i+2]));
- return (ok ? 0 : 1);
- } else {
- printf("Unknown Argument %s\n", a);
- show_help();
- return -1;
- }
- }
- }
- if (argc==1) {
- printf("Interactive mode.\n");
- } else if (argc==2) {
- // single file - just run it
- char *buffer = (char *)read_file(argv[1]);
- if (!buffer) return (1);
- // check for '#' as the first char, and if so, skip the first line
- char *cmd = buffer;
- if (cmd[0]=='#') {
- while (cmd[0] && cmd[0]!='\n') cmd++;
- if (cmd[0]=='\n') cmd++;
- }
- jshInit();
- jsiInit(false /* do not autoload!!! */);
- jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit);
- jsvUnLock(jspEvaluate(jsiGetParser(), cmd ));
- free(buffer);
- //isRunning = true;
- //while (isRunning && jsiHasTimers()) jsiLoop();
- jsiKill();
- jshKill();
- return -1;
- } else {
- printf("Unknown arguments!\n");
- show_help();
- return -1;
- }
- printf("Size of JsVar is now %d bytes\n", (int)sizeof(JsVar));
- printf("Size of JsVarRef is now %d bytes\n", (int)sizeof(JsVarRef));
- jshInit();
- jsiInit(true);
- jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit);
- jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt);
- while (isRunning) {
- jsiLoop();
- }
- jsiConsolePrint("\n");
- jsiKill();
- jsvShowAllocated();
- jshKill();
- return 0;
- }
- MSH_CMD_EXPORT(espruino, JavaScript Interpreter)
|