140 lines
4.5 KiB
C
140 lines
4.5 KiB
C
// 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 <stdatomic.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#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); // every engine the build linked (all seven)
|
|
|
|
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");
|
|
|
|
writeScript("clTest.scm", "(hit 15)");
|
|
CHECK(loadAndRun("clTest") == 15, "loaded and ran a .scm Scheme script by base name");
|
|
remove("clTest.scm");
|
|
|
|
writeScript("clTest.wren", "Calog.call(\"hit\", [16])");
|
|
CHECK(loadAndRun("clTest") == 16, "loaded and ran a .wren script by base name");
|
|
remove("clTest.wren");
|
|
|
|
writeScript("clTest.be", "hit(17)");
|
|
CHECK(loadAndRun("clTest") == 17, "loaded and ran a .be Berry script by base name");
|
|
remove("clTest.be");
|
|
|
|
// 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;
|
|
}
|