Files
EVEngine/test/climbing_snapshot.cpp

109 lines
4.2 KiB
C++

#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
#include "climbing/Climbing.h"
#include "physics/Body3D.h"
#include "physics/Physics.h"
#include "physics/Shape3D.h"
#include "physics/World3D.h"
#include <memory>
namespace {
struct World {
World() {
world.reset(eve::physics::Physics::create()->newWorld3D(0.f, 0.f, 0.f, false));
body = world->newBody("static", 0.f, 0.5f, 1.f);
shape = body->newBoxShape(2.f, 1.f, 0.5f);
}
std::unique_ptr<eve::physics::World3D> world;
eve::physics::Body3D* body = nullptr;
eve::physics::Shape3D* shape = nullptr;
};
eve::climbing::ClimbingActionDefinition action(float apex = 0.7f) {
eve::climbing::ClimbingActionDefinition result;
result.id = "climb:mantle";
result.minHeight = 0.4f;
result.maxHeight = 1.2f;
result.duration = eve::Duration::fromNanoseconds(600000000);
result.landingForward = 0.6f;
result.apexHeight = apex;
return result;
}
void begin(World& fixture, eve::climbing::ClimbingRuntime& runtime) {
REQUIRE(runtime.upsertAction(action()).ok());
auto begun = runtime.tryBegin(*fixture.world, {{0.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, 1.f, -1}, eve::SimulationTick(10));
REQUIRE(begun.ok());
}
} // namespace
TEST_CASE("climbing.snapshot.roundTripRestoresPinnedExecution") {
World fixture;
eve::climbing::ClimbingRuntime source;
begin(fixture, source);
auto snapshot = source.snapshot();
REQUIRE(snapshot.ok());
eve::climbing::ClimbingRuntime restored;
REQUIRE(restored.restore(snapshot.value(), *fixture.world).ok());
CHECK_EQ(static_cast<int>(restored.phase()), static_cast<int>(eve::climbing::ClimbingPhase::Requested));
CHECK(restored.executionId() == source.executionId());
auto roundTrip = restored.snapshot();
REQUIRE(roundTrip.ok());
CHECK(roundTrip.value() == snapshot.value());
}
TEST_CASE("climbing.snapshot.supportsNMinusOneAndPinsActiveDefinitionAcrossReload") {
World fixture;
eve::climbing::ClimbingRuntime runtime;
begin(fixture, runtime);
REQUIRE(runtime.upsertAction(action(4.0f)).ok());
auto snapshot = runtime.snapshot();
REQUIRE(snapshot.ok());
snapshot.value().set("schemaVersion",
eve::Value(std::int64_t(eve::climbing::ClimbingRuntime::SnapshotSchemaVersion - 1)));
eve::climbing::ClimbingRuntime restored;
REQUIRE(restored.restore(snapshot.value(), *fixture.world).ok());
auto migrated = restored.snapshot();
REQUIRE(migrated.ok());
CHECK_EQ(migrated.value().find("schemaVersion")->asInt(), eve::climbing::ClimbingRuntime::SnapshotSchemaVersion);
const auto* restoredExecution = migrated.value().find("execution")->getIf<eve::Value::Object>();
REQUIRE(restoredExecution != nullptr);
const auto* pinnedAction = restoredExecution->at("action").getIf<eve::Value::Object>();
REQUIRE(pinnedAction != nullptr);
CHECK(pinnedAction->at("apexHeight").asDouble() < 1.0);
}
TEST_CASE("climbing.snapshot.futureVersionAndStaleLinkFailuresAreAtomic") {
World fixture;
eve::climbing::ClimbingRuntime runtime;
begin(fixture, runtime);
auto before = runtime.snapshot();
REQUIRE(before.ok());
eve::Value future = before.value();
future.set("schemaVersion", eve::Value(std::int64_t(eve::climbing::ClimbingRuntime::SnapshotSchemaVersion + 1)));
auto unknown = runtime.restore(future, *fixture.world);
CHECK(!unknown.ok());
CHECK_EQ(static_cast<int>(unknown.error()->code()), static_cast<int>(eve::DiagnosticCode::UnknownVersion));
auto afterUnknown = runtime.snapshot();
REQUIRE(afterUnknown.ok());
CHECK(afterUnknown.value() == before.value());
fixture.world->destroyBody(fixture.body);
fixture.body = nullptr;
fixture.shape = nullptr;
auto stale = runtime.restore(before.value(), *fixture.world);
CHECK(!stale.ok());
CHECK_EQ(static_cast<int>(stale.error()->code()), static_cast<int>(eve::DiagnosticCode::StaleHandle));
auto afterStale = runtime.snapshot();
REQUIRE(afterStale.ok());
CHECK(afterStale.value() == before.value());
}