// testLoad.c -- calogContextLoad across all four engines. // // Links every engine (built with all CALOG_WITH_* flags, set by the Makefile), so // calogRegisterBuiltinEngines auto-registers Lua, JS, Squirrel, and my-basic, and each // language is loaded by file extension. Also the first exercise of my-basic under the // actor/context-thread model. Verifies: each extension loads and runs its script; the // first registered engine wins when several files share a base name; a base that names // no file returns NULL. #define _POSIX_C_SOURCE 200809L #include "calog.h" #include #include #include #include #define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__) #define PUMP_LIMIT 4000 // ~2s at 0.5ms/iter static CalogT *calog = NULL; static _Atomic int64_t lastHit = 0; static int32_t testsRun = 0; static int32_t testsFailed = 0; static void checkImpl(bool condition, const char *message, const char *file, int32_t line); static int32_t hit(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData); static int64_t loadAndRun(const char *base); static void writeScript(const char *path, const char *content); static void checkImpl(bool condition, const char *message, const char *file, int32_t line) { testsRun++; if (!condition) { testsFailed++; printf("FAIL %s:%d %s\n", file, line, message); } } static int32_t hit(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) { (void)userData; calogValueNil(result); if (argCount >= 1 && args[0].type == calogIntE) { atomic_store(&lastHit, args[0].as.i); } return calogOkE; } static void writeScript(const char *path, const char *content) { FILE *file; file = fopen(path, "wb"); if (file != NULL) { fputs(content, file); fclose(file); } } // Load the script for base, pump until its hit() lands (or timeout), close, and return // the reported value -- 0 if it never ran, -1 if no file matched at all. static int64_t loadAndRun(const char *base) { CalogContextT *context; struct timespec ts = { 0, 500000 }; int32_t i; atomic_store(&lastHit, 0); context = calogContextLoad(calog, base); if (context == NULL) { return -1; } for (i = 0; i < PUMP_LIMIT && atomic_load(&lastHit) == 0; i++) { calogPump(calog); nanosleep(&ts, NULL); } calogContextClose(context); return atomic_load(&lastHit); } int main(void) { calog = calogCreate(); if (calog == NULL) { printf("calog create failed\n"); return 1; } calogRegister(calog, "hit", hit, NULL); calogRegisterBuiltinEngines(calog); // Lua, JS, Squirrel, my-basic (all linked) writeScript("clTest.lua", "hit(11)"); CHECK(loadAndRun("clTest") == 11, "loaded and ran a .lua script by base name"); remove("clTest.lua"); writeScript("clTest.js", "hit(12)"); CHECK(loadAndRun("clTest") == 12, "loaded and ran a .js script by base name"); remove("clTest.js"); writeScript("clTest.nut", "hit(13)"); CHECK(loadAndRun("clTest") == 13, "loaded and ran a .nut Squirrel script by base name"); remove("clTest.nut"); writeScript("clTest.bas", "hit(14)"); CHECK(loadAndRun("clTest") == 14, "loaded and ran a .bas my-basic script by base name"); remove("clTest.bas"); // First match wins: Lua is registered before my-basic, so .lua beats .bas. writeScript("clPrio.lua", "hit(21)"); writeScript("clPrio.bas", "hit(22)"); CHECK(loadAndRun("clPrio") == 21, "first registered engine wins when several files share a base"); remove("clPrio.lua"); remove("clPrio.bas"); // No file with any registered extension exists -> NULL. CHECK(calogContextLoad(calog, "clNoSuchBase") == NULL, "calogContextLoad returns NULL when nothing matches"); calogDestroy(calog); printf("\n%d checks, %d failed\n", testsRun, testsFailed); fflush(stdout); if (testsFailed != 0) { return 1; } return 0; }