From 80255af52e5c4df2fe3af8045da7c2db247ba5b1 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Wed, 13 Apr 2022 16:48:09 -0400 Subject: [PATCH] Split up some of the native testing code. Makes running specific tests a little cleaner. --- src/env.c | 181 +++++++++++++++++++++++++++++------------------------- src/env.h | 8 +-- 2 files changed, 102 insertions(+), 87 deletions(-) diff --git a/src/env.c b/src/env.c index d5891ef..4881023 100644 --- a/src/env.c +++ b/src/env.c @@ -115,14 +115,19 @@ struct Environment envForLambda(const Object* params, const Object* arguments, i .refs = 1, }; + // Evaluate the `argument` list + const Object* param = params->list; const Object* argument = arguments; - for (int i = 0; i < paramCount; i++) { - const char* paramName = itemAt(params, i)->string; - // Eval the `argument` list - Object newEnvObj = argument ? eval(argument, outer) : errorWithContext(NOT_ENOUGH_ARGUMENTS, paramName); - addToEnv(&env, paramName, newEnvObj); // Could use eval_forms? + for (int i = 0; i < paramCount && param; i++) { + Object newEnvObj = eval(argument, outer); + + const char* paramName = param->string; + addToEnv(&env, paramName, newEnvObj); + cleanObject(&newEnvObj); + argument = argument ? argument->forward : NULL; + param = param->forward; } env.outer = outer; @@ -224,8 +229,7 @@ struct Environment defaultEnv() #endif }; - unsigned i; - for (i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) { + for (unsigned i = 0; i < sizeof(symFuncs) / sizeof(symFuncs[0]); i++) { addFunc(symFuncs[i].sym, symFuncs[i].func, &e); } @@ -391,26 +395,27 @@ Object help(Object* params, int length, struct Environment* env) } for (int i = 0; i < currentHelp; i++) { struct helpText h = helpTexts[i]; - if (strcmp(symbol, h.symbol) == 0) { - Object text = withLen(1024, TYPE_STRING); - char* textCursor = text.string; - textCursor += sprintf(textCursor, "%s", h.help); - for (int ti = 0; ti < h.testCount; ti += 2) { - const char* test = h.tests[ti]; - const char* expected = h.tests[ti + 1]; - if (test[0] == ';') { - textCursor += sprintf(textCursor, "\n %s => %s", test + 1, expected); - continue; - } - textCursor += sprintf(textCursor, "\n %s => ", test); - if (expected[0] == '\0') { - textCursor += sprintf(textCursor, ""); - } else { - textCursor += sprintf(textCursor, "%s", expected); - } - } - return text; + if (strcmp(symbol, h.symbol) != 0) { + continue; } + Object text = withLen(1024, TYPE_STRING); + char* textCursor = text.string; + textCursor += sprintf(textCursor, "%s", h.help); + for (int ti = 0; ti < h.testCount; ti += 2) { + const char* test = h.tests[ti]; + const char* expected = h.tests[ti + 1]; + if (test[0] == ';') { + textCursor += sprintf(textCursor, "\n %s => %s", test + 1, expected); + continue; + } + textCursor += sprintf(textCursor, "\n %s => ", test); + if (expected[0] == '\0') { + textCursor += sprintf(textCursor, ""); + } else { + textCursor += sprintf(textCursor, "%s", expected); + } + } + return text; } for (int i = 0; i < dictionary.structCount; i++) { @@ -438,79 +443,91 @@ Object help(Object* params, int length, struct Environment* env) return nullTerminated("Help not found!"); } +/// Returns 1 if the test passed, or 0 if it failed +int runTest(const char* test, const char* expected, int detailed) +{ + struct Environment env = defaultEnv(); + Object o = parseEval(test, &env); + size_t length; + char* result = stringObj(&o, &length); + cleanObject(&o); + int expectedLen = 0; + while (expected[expectedLen] && expected[expectedLen] != ';') { + expectedLen++; + } + int ret; + if (strncmp(result, expected, expectedLen) != 0) { + ret = 0; + printf("Test failed!\n"); + printf("%s\n", test); + printf("Expected '%s' but received '%s'\n", expected, result); + } else { + if (detailed) { + printf("✓"); + } + ret = 1; + } + free(result); + deleteEnv(&env); + return ret; +} + +void runHelpTests(struct helpText h, int detailed, int* failureCount, int* passCount) +{ + if (!h.tests) { + return; + } + if (detailed && h.testCount > 0) { + printf(" `%s` ", h.symbol); + } + for (int ti = 0; ti < h.testCount; ti += 2) { + const char* test = h.tests[ti]; + const char* expected = h.tests[ti + 1]; + if (test[0] == ';') { + continue; + } + int* outcome = runTest(test, expected, detailed) ? passCount : failureCount; + *outcome = *outcome + 1; + } + if (detailed && h.testCount > 0) { + printf("\n"); + } +} + // Returns number of failures, or -1 if the requested specificTest is invalid int runTests(int detailed, int specificTest) { - int isSpecific = specificTest != -1; if (specificTest >= currentHelp) { return -1; } - if (!isSpecific) { - printf("::NATIVE TESTS::\n"); - } int failureCount = 0; int passCount = 0; - int start = isSpecific ? specificTest : 0; - int end = isSpecific ? specificTest + 1 : currentHelp; - for (int hi = start; hi < end; hi++) { - struct helpText h = helpTexts[hi]; - if (h.tests) { - if (detailed && h.testCount > 0) { - if (isSpecific) { - printf("`%s` ", h.symbol); - } else { - printf(" `%s` ", h.symbol); - } - } - for (int ti = 0; ti < h.testCount; ti += 2) { - const char* test = h.tests[ti]; - const char* expected = h.tests[ti + 1]; - if (test[0] == ';') { - continue; - } - struct Environment env = defaultEnv(); - Object o = parseEval(test, &env); - size_t length; - char* result = stringObj(&o, &length); - cleanObject(&o); - int expectedLen = 0; - while (expected[expectedLen] && expected[expectedLen] != ';') { - expectedLen++; - } - if (strncmp(result, expected, expectedLen) != 0) { - failureCount++; - printf("Test failed!\n"); - printf("%s\n", test); - printf("Expected '%s' but received '%s'\n", expected, result); - } else { - if (detailed) { - printf("✓"); - } - passCount++; - } - free(result); - deleteEnv(&env); - } - if (detailed && h.testCount > 0) { - printf("\n"); - } - } + + int isSpecificTest = specificTest != -1; + if(isSpecificTest) { + struct helpText h = helpTexts[specificTest]; + runHelpTests(h, detailed, &failureCount, &passCount); + return failureCount; } + + printf("::NATIVE TESTS::\n"); + + for (int hi = 0; hi < currentHelp; hi++) { + runHelpTests(helpTexts[hi], detailed, &failureCount, &passCount); + } + if (passCount > 0) { printf(""); } - if (!isSpecific) { - printf("%d tests passed!\n", passCount); - } + printf("%d tests passed!\n", passCount); if (failureCount > 0) { - printf(""); - } - if (!isSpecific || failureCount != 0) { - printf("%d tests failed!\n", failureCount); + printf("%d tests failed!\n", failureCount); } + // fprintf(stderr, "TOTAL ALLOCATIONS: %d\n", getAllocations()); // fprintf(stderr, "TOTAL BYTES: %zu\n", getBytes()); + return failureCount; } diff --git a/src/env.h b/src/env.h index 935bb51..31d5616 100644 --- a/src/env.h +++ b/src/env.h @@ -59,10 +59,6 @@ void printColored(const char* code); int runTests(int detailed, int specificTest); -int getTotalSearchDepth(); - -int getTotalSearches(); - #define unused __attribute__((unused)) #define array_length(_array) (sizeof(_array) / sizeof((_array)[0])) @@ -91,7 +87,9 @@ fn(help, "?", " (? Output) => \"{ stdout stderr }\"\n" "\n" " Other objects:\n" - " (? \"Hello\") => \"Hello\"" + " (? \"Hello\") => \"Hello\"\n" + "\n" + "Note: The included repl allows you to drop the parentheses." );