#include #include #include #include #include #include #include #include "Compiler.h" #include "Script.h" #include "Tokenizer.h" static int doneTests = 0; static int allTests = 0; static char path[PATH_MAX] = {'\0'}; static int pathIndex = 0; #define TEST_BUFFER_LENGTH (1024 * 2) static char testBuffer[TEST_BUFFER_LENGTH]; static int testBufferIndex = 0; static void tsPrintToBuffer(const char* format, ...) { va_list args; va_start(args, format); int leftBytes = TEST_BUFFER_LENGTH - testBufferIndex; testBufferIndex += vsnprintf(testBuffer + testBufferIndex, leftBytes, format, args); if(testBufferIndex > TEST_BUFFER_LENGTH) { testBufferIndex = TEST_BUFFER_LENGTH; } va_end(args); } static bool tsPrinter(Object* o) { if(testBufferIndex >= TEST_BUFFER_LENGTH) { return true; } switch(o->type) { case OT_INT: tsPrintToBuffer("%d\n", o->data.intValue); return false; case OT_FLOAT: tsPrintToBuffer("%.2f\n", o->data.floatValue); return false; case OT_NULL: tsPrintToBuffer("null\n"); return false; case OT_BOOL: tsPrintToBuffer(o->data.intValue ? "true\n" : "false\n"); return false; } return true; } static void tsAppend(const char* s) { for(int i = 0; pathIndex < (PATH_MAX - 1) && s[i] != '\0'; i++) { path[pathIndex++] = s[i]; } path[pathIndex] = '\0'; } static int tsEnter(const char* s) { int marker = pathIndex; tsAppend("/"); tsAppend(s); return marker; } static void tsReset(int marker) { path[marker] = '\0'; pathIndex = marker; } static void tsCompareResults(FILE* file) { for(int i = 0; i < testBufferIndex; i++) { char a = fgetc(file); char b = testBuffer[i]; if(a != b) { printf("error in '%s': expected %c, got:\n%s", path, a, testBuffer + i); return; } } if(fgetc(file) != EOF) { printf("error in '%s': no full read\n", path); return; } doneTests++; } static void tsCheckScript(Script* sc) { testBufferIndex = 0; sRun(sc); tsAppend(".out"); FILE* file = fopen(path, "r"); if(file == NULL) { printf("cannot open result file '%s'\n", path); return; } tsCompareResults(file); fclose(file); } static void tsCheckFile() { allTests++; if(tTokenize(path)) { puts(path); puts(tGetError()); return; } ByteCode* bc = cCompile(); if(bc == NULL) { puts(path); puts(cGetError()); return; } Script* sc = sInit(bc); tsCheckScript(sc); sDelete(sc); } static void tsScanDirectory() { DIR* dir = opendir(path); if(dir == NULL) { printf("cannot open '%s': %s\n", path, strerror(errno)); return; } while(true) { struct dirent* e = readdir(dir); if(e == NULL) { return; } else if(strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) { continue; } else if(e->d_type == DT_DIR) { int marker = tsEnter(e->d_name); tsScanDirectory(); tsReset(marker); } else if(e->d_type == DT_REG && strchr(e->d_name, '.') == NULL) { int marker = tsEnter(e->d_name); tsCheckFile(); tsReset(marker); } } if(closedir(dir)) { printf("cannot close '%s': %s\n", path, strerror(errno)); } } void tsStart(const char* path) { sSetPrinter(tsPrinter); doneTests = 0; allTests = 0; tsAppend(path); tsScanDirectory(); printf("%d / %d tests succeeded\n", doneTests, allTests); }