Files
EVEngine/test/orders.cpp
T

123 lines
4.8 KiB
C++

#include "zeroerr/assert.h"
#include "zeroerr/unittest.h"
#include "common/Module.h"
#include "orders/Orders.h"
#include <simplesquirrel/simplesquirrel.hpp>
#include <string>
using namespace eve::orders;
TEST_CASE("orders.append.priorityAndStableIds") {
OrderQueue queue;
const auto first = queue.append("first", 1);
const auto low = queue.append("low", 1);
const auto high = queue.append("high", 10);
CHECK_EQ(first, std::string("order-0000000000000001"));
CHECK_EQ(low, std::string("order-0000000000000002"));
CHECK_EQ(high, std::string("order-0000000000000003"));
REQUIRE(queue.current() != nullptr);
CHECK_EQ(queue.current()->kind, std::string("first"));
CHECK(queue.complete(first));
CHECK_EQ(queue.current()->kind, std::string("high"));
CHECK(queue.complete(high));
CHECK_EQ(queue.current()->kind, std::string("low"));
}
TEST_CASE("orders.replace.cancelsUnfinishedDeterministically") {
OrderQueue queue;
const auto active = queue.append("work");
const auto queued = queue.append("later");
const auto next = queue.replace("replacement", 5);
CHECK_EQ(static_cast<int>(queue.find(active)->state), static_cast<int>(OrderState::Cancelled));
CHECK_EQ(static_cast<int>(queue.find(queued)->state), static_cast<int>(OrderState::Cancelled));
CHECK_EQ(queue.current()->id, next);
REQUIRE(queue.eventCount() == 7);
CHECK_EQ(queue.eventAt(0)->sequence, uint64_t{1});
CHECK_EQ(static_cast<int>(queue.eventAt(0)->to), static_cast<int>(OrderState::Queued));
CHECK_EQ(queue.eventAt(3)->orderId, active);
CHECK_EQ(queue.eventAt(3)->reason, std::string("replaced"));
CHECK_EQ(queue.eventAt(4)->orderId, queued);
CHECK_EQ(queue.eventAt(5)->orderId, next);
CHECK_EQ(static_cast<int>(queue.eventAt(6)->to), static_cast<int>(OrderState::Active));
}
TEST_CASE("orders.interrupt.honoursPriority") {
OrderQueue queue;
const auto active = queue.append("critical", 20);
CHECK(queue.interrupt("weak", 19).empty());
CHECK_EQ(queue.current()->id, active);
const auto urgent = queue.interrupt("urgent", 20);
CHECK(!urgent.empty());
CHECK_EQ(static_cast<int>(queue.find(active)->state), static_cast<int>(OrderState::Cancelled));
CHECK_EQ(queue.find(active)->reason, std::string("interrupted"));
CHECK_EQ(queue.current()->id, urgent);
}
TEST_CASE("orders.lifecycle.completeFailCancel") {
OrderQueue queue;
const auto one = queue.append("one");
const auto two = queue.append("two");
const auto three = queue.append("three");
CHECK(queue.complete(one));
CHECK_EQ(static_cast<int>(queue.find(one)->state), static_cast<int>(OrderState::Completed));
CHECK(queue.fail(two, "policy_rejected"));
CHECK_EQ(static_cast<int>(queue.find(two)->state), static_cast<int>(OrderState::Failed));
CHECK_EQ(queue.find(two)->reason, std::string("policy_rejected"));
CHECK(queue.cancel(three, "owner_removed"));
CHECK_EQ(static_cast<int>(queue.find(three)->state), static_cast<int>(OrderState::Cancelled));
CHECK(queue.current() == nullptr);
CHECK(!queue.complete(three));
}
TEST_CASE("orders.timeout.failsAndActivatesNext") {
OrderQueue queue;
const auto timed = queue.append("timed", 0, 0.5);
const auto next = queue.append("next");
queue.update(0.25);
CHECK_EQ(queue.current()->id, timed);
queue.update(0.25);
CHECK_EQ(static_cast<int>(queue.find(timed)->state), static_cast<int>(OrderState::Failed));
CHECK_EQ(queue.find(timed)->reason, std::string("timeout"));
CHECK_EQ(queue.current()->id, next);
}
TEST_CASE("orders.payload.isDeterministicJsonCompatible") {
OrderQueue queue;
const auto id = queue.append("custom");
auto* payload = &queue.find(id)->payload;
REQUIRE(payload != nullptr);
payload->setString("name", "A\nB");
payload->setNumber("x", 12.5);
payload->setBool("enabled", true);
CHECK(payload->setJson("nested", "{\"target\":7}"));
CHECK(!payload->setJson("bad", "not-json"));
CHECK_EQ(payload->toJson(), std::string("{\"enabled\":true,\"name\":\"A\\nB\","
"\"nested\":{\"target\":7},\"x\":12.5}"));
}
TEST_CASE("orders.script.queueAndPayloadApi") {
ssq::VM vm(1024, ssq::Libs::ALL);
eve::ModuleManager::expose(vm);
vm.run(vm.compileSource(R"(
result <- "fail";
local module = eve.Orders();
local queue = module.newQueue();
local id = queue.append("custom_action", 7, 1.0);
local order = queue.current();
order.getPayload().setJson("context", "{\"zone\":3}");
if (order.getId() == id && order.getKind() == "custom_action" &&
order.getPayload().getJson("context") == "{\"zone\":3}") {
queue.complete(id);
result = order.getState();
}
)"));
CHECK_EQ(vm.find("result").toString(), std::string("completed"));
}