Files
EVEngine/test/module_lazy_bind.cpp
T

223 lines
9.2 KiB
C++

#include "common/Module.h"
#include "common/Runtime.h"
#include "Fixtures.h"
#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
#include <squirrel.h>
using namespace eve;
namespace {
bool eveRawHas(HSQUIRRELVM vm, const char* key) {
const SQInteger top = sq_gettop(vm);
sq_pushroottable(vm);
sq_pushstring(vm, "eve", -1);
if (SQ_FAILED(sq_get(vm, -2))) {
sq_settop(vm, top);
return false;
}
sq_pushstring(vm, key, -1);
const bool has = SQ_SUCCEEDED(sq_rawget(vm, -2));
sq_settop(vm, top);
return has;
}
} // namespace
TEST_CASE("moduleExpose.defersNativeClassUntilFirstGet") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
HSQUIRRELVM vm = runtime.handle();
CHECK(!eveRawHas(vm, "Graphics"));
CHECK(!eveRawHas(vm, "Window"));
CHECK(!eveRawHas(vm, "WindowSettings"));
runtime.runSource("g <- eve.Graphics\n", "lazy-graphics.nut");
CHECK(eveRawHas(vm, "Graphics"));
CHECK(!eveRawHas(vm, "Window"));
runtime.runSource("s <- eve.WindowSettings()\n", "lazy-window-settings.nut");
CHECK(eveRawHas(vm, "Window"));
CHECK(eveRawHas(vm, "WindowSettings"));
}
TEST_CASE("moduleExpose.eagerCompatibilityKeepsCanonicalSpriteBinding") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
runtime.runSource("if (eve._bindAllNativeClasses() < 0) throw \"native binding failed\"\n",
"eager-native-binding-setup.nut");
CHECK(eveRawHas(runtime.handle(), "_ecsSlotsCache"));
CHECK(eveRawHas(runtime.handle(), "_ecsTypes"));
runtime.runSource(
"sprite <- eve.Sprite2D()\n"
"sprite.setBlend(\"alpha\")\n"
"sprite.setAnchor(0.5, 0.5)\n"
"class CompatComponent extends eve.Component { value = 1 }\n"
"class CompatEntity extends eve.Entity { data = CompatComponent }\n"
"compatEntity <- CompatEntity.create()\n"
"if (compatEntity.data.value != 1) throw \"script ECS component creation failed\"\n"
"if (eve.view(CompatEntity).len() != 1) throw \"script ECS view failed\"\n"
"class CompatSystem extends eve.System {\n"
" function update(dt) { return dt + 1 }\n"
"}\n"
"compatSystem <- CompatSystem()\n"
"if (compatSystem.update(2) != 3) throw \"script ECS System was replaced\"\n"
"if (\"getPlatform\" in compatSystem) throw \"native System leaked into script ECS\"\n"
"class CompatEntity extends eve.Entity {\n"
" function update(dt) { return dt + 2 }\n"
"}\n"
"compatEntity <- CompatEntity()\n"
"if (compatEntity.update(2) != 4) throw \"script ECS Entity identity changed\"\n"
"vehicle <- eve.Vehicle()\n"
"if (!(\"update\" in vehicle)) throw \"Vehicle binding lost update\"\n"
"scene <- eve.Scene()\n"
"if (!(\"update\" in scene)) throw \"Scene binding lost update\"\n",
"eager-native-binding.nut");
}
TEST_CASE("moduleExpose.lazyGraphicsPreservesReturnedSpriteSurface") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
runtime.runSource("g <- eve.Graphics()\n", "lazy-graphics-instance.nut");
REQUIRE(ModuleManager::expose_pending() >= 0);
runtime.runSource(R"(
s <- g.newSprite2D()
if (!(s instanceof eve.Sprite2D)) throw "wrong Sprite2D class after pending exposers"
s.setBlend("alpha")
s.setAnchor(0.25, 0.75)
s.destroy()
)", "lazy-graphics-sprite.nut");
}
TEST_CASE("moduleExpose.allBindingsPreserveScriptEcsOverrides") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
REQUIRE(ModuleManager::expose_pending() >= 0);
runtime.runSource(R"(
class LazyPosition extends eve.Component { x = 0.0 }
class LazyEntity extends eve.Entity { position = LazyPosition }
class LazySystem extends eve.System {
constructor() { base.constructor(LazyEntity) }
function update(dt) {
foreach (entity in entities()) entity.position.x += dt
}
}
if (typeof eve._ecsSlotsCache != "table") throw "ECS slot cache was replaced"
if (!(eve.isSubclass(LazyEntity, eve.Entity))) throw "ECS entity inheritance was lost"
if (!(eve.isSubclass(LazyPosition, eve.Component))) throw "ECS component inheritance was lost"
if (!(eve.isSubclass(LazySystem, eve.System))) throw "ECS system inheritance was lost"
local lazyFields = eve.inspectClassFields(LazyEntity)
if (typeof lazyFields != "table") throw "ECS field inspection was replaced"
if (!("position" in lazyFields)) throw "ECS entity field inspection lost position"
if (lazyFields.position != LazyPosition) throw "ECS entity field inspection changed position"
if (!(eve._ecsIsComponentClass(lazyFields.position))) throw "ECS component classification failed"
lazyEntity <- LazyEntity.create()
lazySystem <- LazySystem()
lazySystem.update(0.5)
if (lazyEntity.position.x != 0.5) throw "script ECS override was lost"
hostSystem <- eve.HostSystem()
if (hostSystem.getName() != "System") throw "host System module binding was lost"
)", "lazy-script-ecs.nut");
}
TEST_CASE("moduleExpose.hostSystemSlotDoesNotAcceptStdlibFunction") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
REQUIRE(ModuleManager::expose_pending() >= 0);
runtime.runSource(R"(
function moduleSlotLive(slot) {
return slot in getroottable() && getroottable()[slot] != null &&
typeof getroottable()[slot] == "instance"
}
if (moduleSlotLive("system")) throw "stdlib system function was accepted as a module instance"
system <- eve.HostSystem()
if (!moduleSlotLive("system")) throw "HostSystem instance was not accepted"
system.limitFrame()
)", "host-system-slot-collision.nut");
}
TEST_CASE("moduleExpose.allBindingsPreserveRenderable3DSurface") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
runtime.runSource("g <- eve.Graphics()\n", "lazy-graphics-3d-instance.nut");
REQUIRE(ModuleManager::expose_pending() >= 0);
runtime.runSource(R"(
renderable <- eve.Renderable3D()
renderable.clearMeshLod()
renderable.setPosition(1.0, 2.0, 3.0)
renderable.setRoughness(0.8)
renderable.setPackedNormalMask(true)
renderable.setLayer(8)
if (renderable.getLayer() != 8) throw "Renderable3D layer binding was lost"
renderable.setCastShadow(true)
renderable.setReceiveShadow(true)
)", "lazy-graphics-3d.nut");
}
TEST_CASE("moduleExpose.allBindingsPreserveProcgenRockSurface") {
eve::graphics::Graphics* graphics = nullptr;
openHeadlessGfx(graphics, 128, 128);
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
REQUIRE(ModuleManager::expose_pending() >= 0);
runtime.runSource(R"(
procgen <- eve.Procgen()
paramsResult <- procgen.newParams()
if (!paramsResult.ok) throw "Procgen parameter creation failed"
rockParams <- paramsResult.value
rockParams.setSeed(1847)
rockParams.setInt("subdivisions", 3)
rockParams.setString("baseShape", "mixed")
rockParams.setFloat("variation", 0.48)
rockParams.setFloat("radius", 0.72)
rockParams.setSize(256, 256)
gfx <- eve.Graphics()
meshResult <- procgen.generateMesh("mesh.rock", rockParams, gfx)
if (!meshResult.ok) throw "Procgen rock mesh generation failed"
textureResult <- procgen.generateTexture("tex.stone", rockParams, gfx)
if (!textureResult.ok) throw "Procgen stone texture generation failed"
normalResult <- procgen.generateNormalImage("tex.stone", rockParams)
if (!normalResult.ok) throw "Procgen normal image generation failed"
normalTexture <- gfx.newTexture(normalResult.value, true, true)
if (normalTexture == null) throw "Procgen normal texture upload failed"
camera <- eve.Camera3D()
camera.setEye(3.25, 2.15, 5.1)
camera.setTarget(-0.4, -0.1, 0.0)
camera.setFov(37.0)
)", "lazy-procgen-rock.nut");
}
TEST_CASE("moduleExpose.allBindingsPreserveVehicleFrameSurface") {
Runtime runtime(1024, ssq::Libs::ALL);
ModuleManager::expose(runtime);
REQUIRE(ModuleManager::expose_pending() >= 0);
runtime.runSource(R"(
vehicle <- eve.Vehicle()
vehicle.registerVehiclesFromJson(
"[{\"id\":\"probe\",\"mobility\":\"kinematic\",\"maxSpeed\":80,\"accel\":60}]"
)
probeVehicle <- vehicle.newVehicle("probe", 0.0, 0.0, 0.0, "probe")
if (!(probeVehicle instanceof eve.VehicleEntity)) throw "Vehicle entity binding was replaced"
vehicle.setPosition(probeVehicle, 1.0, 2.0)
if (vehicle.getX(probeVehicle) != 1.0 || vehicle.getY(probeVehicle) != 2.0)
throw "Vehicle state binding was lost"
vehicle.moveTo(probeVehicle, 10.0, 0.0)
vehicle.update(0.1)
local visible = false
foreach (candidate in eve.view(eve.VehicleEntity)) {
if (candidate.getId() == probeVehicle.getId()) visible = true
}
if (!visible) throw "Vehicle ECS view binding was lost"
)", "lazy-vehicle-frame.nut");
}