212875ed0d
- .claude/agents/fn-orquestador/SKILL.md - .claude/commands/fn_claude.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - .claude/rules/ids_naming.md - CHANGELOG.md - apps/dag_engine/README.md - apps/dag_engine/api.go - apps/dag_engine/dags_migrated/example.yaml - apps/dag_engine/dags_migrated/example_lineage_tracking.yaml - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
108 lines
3.5 KiB
C++
108 lines
3.5 KiB
C++
// Tests para lua_engine_cpp_core.
|
|
// Catch2 amalgamated. No requiere ImGui context.
|
|
#include <catch_amalgamated.hpp>
|
|
#include "core/lua_engine.h"
|
|
|
|
// Helper: compila + eval con RowCtx vacia (sin columnas).
|
|
static std::string quick_eval(const std::string& formula, std::string* err = nullptr) {
|
|
lua_engine::Engine* e = lua_engine::get();
|
|
std::string compile_err;
|
|
int id = lua_engine::compile(e, formula, &compile_err);
|
|
if (id < 0) {
|
|
if (err) *err = compile_err;
|
|
return "";
|
|
}
|
|
lua_engine::RowCtx ctx;
|
|
std::string eval_err;
|
|
std::string result = lua_engine::eval(e, id, ctx, &eval_err);
|
|
lua_engine::release(e, id);
|
|
if (err) *err = eval_err;
|
|
return result;
|
|
}
|
|
|
|
TEST_CASE("lua_engine: eval expr simple", "[lua_engine]") {
|
|
std::string err;
|
|
std::string result = quick_eval("2 + 3", &err);
|
|
REQUIRE(err.empty());
|
|
REQUIRE(result == "5");
|
|
}
|
|
|
|
TEST_CASE("lua_engine: eval con vars via RowCtx", "[lua_engine]") {
|
|
// Prepara tabla: 1 fila, 2 columnas (price=10, qty=3).
|
|
const char* price_str = "10";
|
|
const char* qty_str = "3";
|
|
const char* cells[] = { price_str, qty_str };
|
|
|
|
std::vector<std::string> headers = { "price", "qty" };
|
|
std::unordered_map<std::string,int> name_to_col = { {"price", 0}, {"qty", 1} };
|
|
|
|
data_table::ColumnType types[] = {
|
|
data_table::ColumnType::Float,
|
|
data_table::ColumnType::Float
|
|
};
|
|
|
|
lua_engine::RowCtx ctx;
|
|
ctx.cells = cells;
|
|
ctx.orig_cols = 2;
|
|
ctx.row = 0;
|
|
ctx.header_names = &headers;
|
|
ctx.name_to_col = &name_to_col;
|
|
ctx.types_orig = types;
|
|
ctx.n_types_orig = 2;
|
|
|
|
lua_engine::Engine* e = lua_engine::get();
|
|
std::string err;
|
|
int id = lua_engine::compile(e, "[price] * [qty]", &err);
|
|
REQUIRE(err.empty());
|
|
REQUIRE(id >= 0);
|
|
|
|
std::string result = lua_engine::eval(e, id, ctx, &err);
|
|
lua_engine::release(e, id);
|
|
REQUIRE(err.empty());
|
|
// 10 * 3 = 30 (integer)
|
|
REQUIRE(result == "30");
|
|
}
|
|
|
|
TEST_CASE("lua_engine: error en expr invalida", "[lua_engine]") {
|
|
std::string err;
|
|
int id = lua_engine::compile(lua_engine::get(), "this is not lua !!!", &err);
|
|
REQUIRE(id < 0);
|
|
REQUIRE(!err.empty());
|
|
}
|
|
|
|
TEST_CASE("lua_engine: sandbox bloquea io.open", "[lua_engine]") {
|
|
std::string err;
|
|
// io fue eliminado del sandbox; acceder a io.open debe producir error en runtime.
|
|
std::string result = quick_eval("io.open('/etc/passwd', 'r')", &err);
|
|
// Debe fallar (io es nil -> intento de indexar nil -> runtime error).
|
|
REQUIRE(!err.empty());
|
|
REQUIRE(result.empty());
|
|
}
|
|
|
|
TEST_CASE("lua_engine: preprocess convierte [col] a row[\"col\"]", "[lua_engine]") {
|
|
std::string out = lua_engine::preprocess("[price] * [qty]");
|
|
// Debe contener row["price"] y row["qty"], y auto-return al ser expresion.
|
|
REQUIRE(out.find("row[\"price\"]") != std::string::npos);
|
|
REQUIRE(out.find("row[\"qty\"]") != std::string::npos);
|
|
REQUIRE(out.rfind("return", 0) == 0);
|
|
}
|
|
|
|
TEST_CASE("lua_engine: fn.* builtins disponibles", "[lua_engine]") {
|
|
std::string err;
|
|
std::string result = quick_eval("fn.upper('hello')", &err);
|
|
REQUIRE(err.empty());
|
|
REQUIRE(result == "HELLO");
|
|
}
|
|
|
|
TEST_CASE("lua_engine: shutdown y reinicio", "[lua_engine]") {
|
|
lua_engine::shutdown();
|
|
// Tras shutdown, get() debe crear un nuevo estado limpio.
|
|
lua_engine::Engine* e = lua_engine::get();
|
|
REQUIRE(e != nullptr);
|
|
std::string err;
|
|
std::string result = quick_eval("1 + 1", &err);
|
|
REQUIRE(err.empty());
|
|
REQUIRE(result == "2");
|
|
lua_engine::shutdown();
|
|
}
|