168 lines
5.2 KiB
C
168 lines
5.2 KiB
C
// testPolyglot.c -- integration test: one broker, two engines.
|
|
//
|
|
// Demonstrates the whole point of the broker: a single C native registered once
|
|
// is callable from both Lua and my-basic, and a function written in Lua is
|
|
// callable from a my-basic program -- routed entirely through the broker, with
|
|
// neither engine aware the other exists.
|
|
|
|
#include "calogInternal.h"
|
|
#include "luaAdapter.h"
|
|
#include "mybasicAdapter.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define CHECK(cond, msg) checkImpl((cond), (msg), __FILE__, __LINE__)
|
|
|
|
#define LUA_CTX_ID 1
|
|
#define BASIC_CTX_ID 2
|
|
|
|
static CalogT *broker = NULL;
|
|
static CalogLuaT *lua = NULL;
|
|
static CalogMyBasicT *basic = NULL;
|
|
static CalogFnT *luaCallable = NULL;
|
|
static CalogValueT recorded;
|
|
static int32_t testsRun = 0;
|
|
static int32_t testsFailed = 0;
|
|
|
|
static int32_t basicRun(const char *source);
|
|
static int32_t callableTrampoline(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
|
|
static void checkImpl(bool condition, const char *message, const char *file, int32_t line);
|
|
static int32_t nativeAdd(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
|
|
static int32_t nativeRecord(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData);
|
|
static void testBasicCallsLua(void);
|
|
static void testSharedNative(void);
|
|
|
|
|
|
static int32_t basicRun(const char *source) {
|
|
int32_t status;
|
|
|
|
if (basic != NULL) {
|
|
calogMyBasicDestroy(basic);
|
|
basic = NULL;
|
|
}
|
|
status = calogMyBasicCreate(&basic, broker, BASIC_CTX_ID);
|
|
if (status != calogOkE) {
|
|
return status;
|
|
}
|
|
calogMyBasicExpose(basic, "add");
|
|
calogMyBasicExpose(basic, "record");
|
|
calogMyBasicExpose(basic, "luaDouble");
|
|
return calogMyBasicRun(basic, source);
|
|
}
|
|
|
|
|
|
static int32_t callableTrampoline(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
|
|
return calogFnInvoke((CalogFnT *)userData, args, argCount, result);
|
|
}
|
|
|
|
|
|
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 nativeAdd(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
|
|
(void)userData;
|
|
if (argCount != 2 || args[0].type != calogIntE || args[1].type != calogIntE) {
|
|
return calogFail(result, calogErrArgE, "add expects two integers");
|
|
}
|
|
calogValueInt(result, args[0].as.i + args[1].as.i);
|
|
return calogOkE;
|
|
}
|
|
|
|
|
|
static int32_t nativeRecord(CalogValueT *args, int32_t argCount, CalogValueT *result, void *userData) {
|
|
int32_t status;
|
|
|
|
(void)userData;
|
|
calogValueNil(result);
|
|
calogValueFree(&recorded);
|
|
if (argCount < 1) {
|
|
return calogOkE;
|
|
}
|
|
status = calogValueCopy(&recorded, &args[0]);
|
|
if (status != calogOkE) {
|
|
return calogFail(result, status, "record copy failed");
|
|
}
|
|
return calogOkE;
|
|
}
|
|
|
|
|
|
static void testBasicCallsLua(void) {
|
|
int32_t status;
|
|
|
|
// luaDouble is implemented in Lua; my-basic calls it by name through the
|
|
// broker with no knowledge that another language is involved.
|
|
status = basicRun("record(luadouble(21))");
|
|
CHECK(status == calogOkE, "BASIC calling a Lua function run");
|
|
CHECK(recorded.type == calogIntE && recorded.as.i == 42, "BASIC invoked the Lua function via the broker");
|
|
}
|
|
|
|
|
|
static void testSharedNative(void) {
|
|
int32_t status;
|
|
|
|
status = calogLuaRun(lua, "record(add(2, 3))");
|
|
CHECK(status == calogOkE, "shared native from Lua run");
|
|
CHECK(recorded.type == calogIntE && recorded.as.i == 5, "one C native called from Lua");
|
|
|
|
status = basicRun("record(add(10, 20))");
|
|
CHECK(status == calogOkE, "shared native from BASIC run");
|
|
CHECK(recorded.type == calogIntE && recorded.as.i == 30, "the same C native called from BASIC");
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
int32_t status;
|
|
|
|
calogValueNil(&recorded);
|
|
broker = calogBrokerCreate();
|
|
if (broker == NULL) {
|
|
printf("broker create failed\n");
|
|
return 1;
|
|
}
|
|
calogRegister(broker, "add", nativeAdd, NULL);
|
|
calogRegister(broker, "record", nativeRecord, NULL);
|
|
|
|
status = calogLuaCreate(&lua, broker, LUA_CTX_ID);
|
|
if (status != calogOkE) {
|
|
printf("lua context create failed\n");
|
|
return 1;
|
|
}
|
|
calogLuaExpose(lua, "add");
|
|
calogLuaExpose(lua, "record");
|
|
|
|
// Define a function in Lua, export it, and register it as a broker native so
|
|
// any other language can call it.
|
|
calogLuaRun(lua, "function luaDouble(x) return x * 2 end");
|
|
status = calogLuaExport(lua, "luaDouble", &luaCallable);
|
|
if (status != calogOkE) {
|
|
printf("lua export failed\n");
|
|
return 1;
|
|
}
|
|
calogRegister(broker, "luaDouble", callableTrampoline, luaCallable);
|
|
|
|
testSharedNative();
|
|
testBasicCallsLua();
|
|
|
|
calogValueFree(&recorded);
|
|
if (basic != NULL) {
|
|
calogMyBasicDestroy(basic);
|
|
}
|
|
calogFnRelease(luaCallable);
|
|
calogLuaDestroy(lua);
|
|
calogBrokerDestroy(broker);
|
|
|
|
printf("\n%d checks, %d failed\n", testsRun, testsFailed);
|
|
fflush(stdout);
|
|
if (testsFailed != 0) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|