mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Use a fictional restart_test mock plugin added as a before step instead of global_chat for the .checkRestartRequired() test. Prevents the test from failing if the integration tests are not also run. Also fixes the fixture not accounting for setting load_plugin causing restartRequired to be set to true due to the integration tests having already set it to the same value.
617 lines
24 KiB
JavaScript
617 lines
24 KiB
JavaScript
"use strict";
|
|
const path = require("node:path");
|
|
const assert = require("assert").strict;
|
|
const { Controller, HostRecord, InstanceRecord, UserRecord } = require("@clusterio/controller");
|
|
const { EventEmitter } = require("stream");
|
|
const events = require("node:events");
|
|
const http = require("node:http");
|
|
const express = require("express");
|
|
|
|
const {
|
|
ControllerConfig, Address, RequestError,
|
|
InstanceConfig, SystemInfo, Role, ModPack,
|
|
addPluginConfigFields,
|
|
} = require("@clusterio/lib");
|
|
|
|
class MockEvent {}
|
|
|
|
class MockInstanceConfig extends EventEmitter {
|
|
constructor(data = new Map()) {
|
|
super();
|
|
this._data = data;
|
|
}
|
|
|
|
get(field) {
|
|
return this._data.get(field);
|
|
}
|
|
|
|
set(field, value) {
|
|
const prev = this.get(field);
|
|
this._data.set(field, value);
|
|
this.emit("fieldChanged", field, value, prev);
|
|
}
|
|
}
|
|
|
|
describe("controller/src/Controller", function() {
|
|
describe("class Controller", function() {
|
|
/** @type {Controller} */
|
|
let controller, mockInstanceConfig;
|
|
const controllerVersion = require("@clusterio/controller/package.json").version;
|
|
before(async function() {
|
|
const controllerConfig = new ControllerConfig("controller", { "controller.version": controllerVersion });
|
|
controller = new Controller({}, [], controllerConfig);
|
|
mockInstanceConfig = new MockInstanceConfig(new Map([
|
|
["instance.id", 100], ["instance.name", "test"], ["factorio.settings", []],
|
|
]));
|
|
await controller.instances.createInstance(mockInstanceConfig);
|
|
});
|
|
function check(list, ip, present = true) {
|
|
if (present === false) {
|
|
assert(!list.check(ip), `${ip} unexpectedly in list`);
|
|
} else {
|
|
assert(list.check(ip), `${ip} missing from list`);
|
|
}
|
|
}
|
|
describe(".serveWeb()", function() {
|
|
let server, port;
|
|
before(async function() {
|
|
const app = express();
|
|
app.locals.controller = { config: { get: () => "Test Cluster" } };
|
|
app.locals.mainBundle = "static/main.abc.js";
|
|
for (let route of ["/", "/instances/:id/view"]) {
|
|
app.get(route, Controller.serveWeb(route));
|
|
}
|
|
server = http.createServer(app);
|
|
server.listen(0, "localhost");
|
|
await events.once(server, "listening");
|
|
port = server.address().port;
|
|
});
|
|
after(function() {
|
|
server.close();
|
|
});
|
|
it("should serve the root with static/ in staticRoot", async function() {
|
|
const html = await (await fetch(`http://localhost:${port}/`)).text();
|
|
assert(html.includes("<title>Test Cluster</title>"));
|
|
assert(html.includes("src=\"./static/main.abc.js\""));
|
|
assert(html.includes("new URL(\"./\", document.location)"));
|
|
assert(html.includes("new URL(\"./static/\", document.location)"));
|
|
});
|
|
it("should use relative roots for nested routes", async function() {
|
|
let html = await (await fetch(`http://localhost:${port}/instances/1/view`)).text();
|
|
assert(html.includes("src=\"../../static/main.abc.js\""));
|
|
assert(html.includes("new URL(\"../../\", document.location)"));
|
|
assert(html.includes("new URL(\"../../static/\", document.location)"));
|
|
html = await (await fetch(`http://localhost:${port}/instances/1/view/`)).text();
|
|
assert(html.includes("src=\"../../../static/main.abc.js\""));
|
|
assert(html.includes("new URL(\"../../../static/\", document.location)"));
|
|
});
|
|
});
|
|
describe(".parseTrustedProxies()", function() {
|
|
it("should parse addresses", function() {
|
|
controller.config.set("controller.trusted_proxies", "10.0.0.1");
|
|
let list = controller.parseTrustedProxies();
|
|
check(list, "10.0.0.1");
|
|
check(list, "10.0.0.2", false);
|
|
controller.config.set("controller.trusted_proxies", "10.0.0.1, 10.0.0.2, 10.1.2.3");
|
|
list = controller.parseTrustedProxies();
|
|
check(list, "10.0.0.1");
|
|
check(list, "10.0.0.2");
|
|
check(list, "10.0.0.3", false);
|
|
});
|
|
it("should ignore invalid entries", function() {
|
|
controller.config.set("controller.trusted_proxies", "10.0.0.1, invalid, 0.0.0.0/200, 10.0.0.2");
|
|
const list = controller.parseTrustedProxies();
|
|
check(list, "10.0.0.1");
|
|
check(list, "10.0.0.2");
|
|
check(list, "10.0.0.3", false);
|
|
});
|
|
it("should parse CIDR blocks", function() {
|
|
controller.config.set("controller.trusted_proxies", "10.0.0.1/24, 192.168.0.16/31");
|
|
const list = controller.parseTrustedProxies();
|
|
check(list, "10.0.0.0");
|
|
check(list, "10.0.0.1");
|
|
check(list, "10.0.0.10");
|
|
check(list, "10.0.0.255");
|
|
check(list, "10.0.1.0", false);
|
|
check(list, "192.168.0.15", false);
|
|
check(list, "192.168.0.16");
|
|
check(list, "192.168.0.17");
|
|
check(list, "192.168.0.18", false);
|
|
});
|
|
});
|
|
|
|
describe(".sendRequest()", function() {
|
|
it("should error on loopback", function() {
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), Address.fromShorthand("controller")),
|
|
new Error(`Message would return back to sender ${Address.fromShorthand("controller")}.`)
|
|
);
|
|
});
|
|
it("should error on invalid controller", function() {
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), Address.fromShorthand({ controlId: 99 })),
|
|
new RequestError("Target control connection does not exist.")
|
|
);
|
|
});
|
|
it("should error on invalid instance", function() {
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), Address.fromShorthand({ instanceId: 99 })),
|
|
new RequestError("Instance with ID 99 does not exist")
|
|
);
|
|
});
|
|
it("should error on unassigned instance", function() {
|
|
mockInstanceConfig.set("instance.assigned_host", null);
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), Address.fromShorthand({ instanceId: 100 })),
|
|
new RequestError("Instance is not assigned to a host")
|
|
);
|
|
});
|
|
it("should error on instance with disconnected host", function() {
|
|
mockInstanceConfig.set("instance.assigned_host", 99);
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), Address.fromShorthand({ instanceId: 100 })),
|
|
new RequestError("Host containing instance is not connected")
|
|
);
|
|
});
|
|
it("should error on invalid host", function() {
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), Address.fromShorthand({ hostId: 99 })),
|
|
new RequestError("Host is not connected")
|
|
);
|
|
});
|
|
it("should error on invalid broadcast", function() {
|
|
// This is different to sendEvent because requests do not support broadcasting
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), new Address(Address.broadcast, 99)),
|
|
new Error(`Unknown address type ${Address.broadcast}`)
|
|
);
|
|
});
|
|
it("should error on invalid address", function() {
|
|
assert.throws(
|
|
() => controller.sendRequest(new MockEvent(), new Address(99, 99)),
|
|
new Error("Unknown address type 99")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".sendEvent()", function() {
|
|
it("should error on loopback", function() {
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), Address.fromShorthand("controller")),
|
|
new Error(`Message would return back to sender ${Address.fromShorthand("controller")}.`)
|
|
);
|
|
});
|
|
it("should error on invalid controller", function() {
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), Address.fromShorthand({ controlId: 99 })),
|
|
new Error("Target control connection does not exist.")
|
|
);
|
|
});
|
|
it("should error on invalid instance", function() {
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), Address.fromShorthand({ instanceId: 99 })),
|
|
new Error("Instance with ID 99 does not exist")
|
|
);
|
|
});
|
|
it("should error on unassigned instance", function() {
|
|
mockInstanceConfig.set("instance.assigned_host", null);
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), Address.fromShorthand({ instanceId: 100 })),
|
|
new Error("Instance is not assigned to a host")
|
|
);
|
|
});
|
|
it("should error on instance with disconnected host", function() {
|
|
mockInstanceConfig.set("instance.assigned_host", 99);
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), Address.fromShorthand({ instanceId: 100 })),
|
|
new Error("Host containing instance is not connected")
|
|
);
|
|
});
|
|
it("should error on invalid host", function() {
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), Address.fromShorthand({ hostId: 99 })),
|
|
new Error("Host is not connected")
|
|
);
|
|
});
|
|
it("should error on invalid broadcast", function() {
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), new Address(Address.broadcast, 99)),
|
|
new Error("Unexpected broadcast target 99")
|
|
);
|
|
});
|
|
it("should error on invalid address", function() {
|
|
assert.throws(
|
|
() => controller.sendEvent(new MockEvent(), new Address(99, 99)),
|
|
new Error("Unknown address type 99")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".instances", function() {
|
|
it("should set the dirty flag if the config is updated", function() {
|
|
controller.instances.records.dirty = false;
|
|
mockInstanceConfig.set("instance.assigned_host", null);
|
|
assert(controller.instances.records.dirty === true, "dirty flag was not set");
|
|
});
|
|
});
|
|
describe(".checkRestartRequired()", function() {
|
|
before(function() {
|
|
addPluginConfigFields([{ name: "restart_test" }]);
|
|
});
|
|
beforeEach(function() {
|
|
// Would not be needed if controller setup was beforeEach
|
|
controller.config.set("controller.version", controllerVersion);
|
|
controller.config.set("restart_test.load_plugin", true);
|
|
controller.config.restartRequired = false;
|
|
controller.pluginInfos[0] = {
|
|
name: "restart_test",
|
|
packagePath: require.resolve("@clusterio/controller/package.json"),
|
|
version: controllerVersion,
|
|
};
|
|
});
|
|
it("returns false when no changes are present", async function() {
|
|
controller.pluginInfos[0].webEntrypoint = true;
|
|
controller.pluginInfos[0].controllerEntrypoint = true;
|
|
const result = await controller.checkRestartRequired();
|
|
assert.equal(result, false);
|
|
assert.equal(controller.config.restartRequired, false);
|
|
});
|
|
it("returns false when an unloaded plugin version changes", async function() {
|
|
controller.pluginInfos[0].version = "0.0.0";
|
|
controller.pluginInfos[0].webEntrypoint = true;
|
|
controller.pluginInfos[0].controllerEntrypoint = true;
|
|
controller.config.set("restart_test.load_plugin", false);
|
|
controller.config.restartRequired = false; // Setting load_plugin requires a restart
|
|
const result = await controller.checkRestartRequired();
|
|
assert.equal(result, false);
|
|
assert.equal(controller.config.restartRequired, false);
|
|
});
|
|
it("returns true when the config flag is set", async function() {
|
|
controller.config.restartRequired = true;
|
|
const result = await controller.checkRestartRequired();
|
|
assert.equal(result, true);
|
|
assert.equal(controller.config.restartRequired, true);
|
|
});
|
|
it("returns true when clusterio version changes", async function() {
|
|
controller.config.set("controller.version", "0.0.0");
|
|
const result = await controller.checkRestartRequired();
|
|
assert.equal(result, true);
|
|
assert.equal(controller.config.restartRequired, true);
|
|
});
|
|
it("returns true when a controller plugin version changes", async function() {
|
|
controller.pluginInfos[0].version = "0.0.0";
|
|
controller.pluginInfos[0].controllerEntrypoint = true;
|
|
const result = await controller.checkRestartRequired();
|
|
assert.equal(result, true);
|
|
assert.equal(controller.config.restartRequired, true);
|
|
});
|
|
it("returns true when a web plugin version changes", async function() {
|
|
controller.pluginInfos[0].version = "0.0.0";
|
|
controller.pluginInfos[0].webEntrypoint = true;
|
|
const result = await controller.checkRestartRequired();
|
|
assert.equal(result, true);
|
|
assert.equal(controller.config.restartRequired, true);
|
|
});
|
|
});
|
|
describe(".checkRestartDowngrade()", function() {
|
|
it("returns null when the installed version matches", async function() {
|
|
controller.config.set("controller.version", controllerVersion);
|
|
assert.equal(await controller.checkRestartDowngrade(), null);
|
|
});
|
|
it("returns null when the installed version is newer", async function() {
|
|
controller.config.set("controller.version", "0.0.0");
|
|
assert.equal(await controller.checkRestartDowngrade(), null);
|
|
});
|
|
it("returns both versions when the installed version is older", async function() {
|
|
controller.config.set("controller.version", "999.0.0");
|
|
assert.deepEqual(await controller.checkRestartDowngrade(), {
|
|
installedVersion: controllerVersion,
|
|
runningVersion: "999.0.0",
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".factorioVersions", function() {
|
|
const _fetch = global.fetch;
|
|
const fetchCalls = [];
|
|
before(function() {
|
|
global.fetch = async (url) => {
|
|
fetchCalls.push(url);
|
|
return { ok: false, status: 503, statusText: "Service Unavailable" };
|
|
};
|
|
});
|
|
it("should handle fetch failure", async function() {
|
|
await assert.deepEqual(
|
|
await controller.factorioVersions.get(0),
|
|
[],
|
|
);
|
|
assert(fetchCalls.length === 1, "expected one fetch call");
|
|
assert(fetchCalls[0].indexOf("/download") !== -1, "fetch call to be to a URL with /download in it");
|
|
});
|
|
after(function() {
|
|
global.fetch = _fetch;
|
|
});
|
|
});
|
|
});
|
|
describe("finalise", function() {
|
|
describe(".finaliseHosts()", function() {
|
|
it("resets the connected state to false", function() {
|
|
const hostInfo = new HostRecord(1, "", "", new Map(), true);
|
|
Controller.finaliseHosts(hostInfo);
|
|
assert.equal(hostInfo.connected, false);
|
|
assert(hostInfo.updatedAtMs > 0, "updatedAtMs not incremented");
|
|
});
|
|
it("does not increment updatedAtMs when there are no changes", function() {
|
|
const hostInfo = new HostRecord(1, "", "", new Map(), false);
|
|
Controller.finaliseHosts(hostInfo);
|
|
assert.equal(hostInfo.connected, false);
|
|
assert(hostInfo.updatedAtMs === 0, "updatedAtMs incremented");
|
|
});
|
|
});
|
|
describe(".finaliseInstances()", function() {
|
|
it("resets the stats for assigned instances", function() {
|
|
const instanceConfig = new InstanceConfig("controller", { "instance.assigned_host": 1 });
|
|
const instanceRecord = new InstanceRecord(instanceConfig, "running");
|
|
Controller.finaliseInstances(instanceRecord);
|
|
assert.equal(instanceRecord.status, "unknown");
|
|
assert(instanceRecord.updatedAtMs > 0, "updatedAtMs not incremented");
|
|
});
|
|
it("resets the status for unassigned instances", function() {
|
|
const instanceConfig = new InstanceConfig("controller", { "instance.assigned_host": null });
|
|
const instanceRecord = new InstanceRecord(instanceConfig, "running");
|
|
Controller.finaliseInstances(instanceRecord);
|
|
assert.equal(instanceRecord.status, "unassigned");
|
|
assert(instanceRecord.updatedAtMs > 0, "updatedAtMs not incremented");
|
|
});
|
|
it("does not update updatedAtMs when there are no changes (assigned)", function() {
|
|
const instanceConfig = new InstanceConfig("controller", { "instance.assigned_host": 1 });
|
|
const instanceRecord = new InstanceRecord(instanceConfig, "unknown");
|
|
Controller.finaliseInstances(instanceRecord);
|
|
assert.equal(instanceRecord.status, "unknown");
|
|
assert(instanceRecord.updatedAtMs === 0, "updatedAtMs incremented");
|
|
});
|
|
it("does not update updatedAtMs when there are no changes (unassigned)", function() {
|
|
const instanceConfig = new InstanceConfig("controller", { "instance.assigned_host": null });
|
|
const instanceRecord = new InstanceRecord(instanceConfig, "unassigned");
|
|
Controller.finaliseInstances(instanceRecord);
|
|
assert.equal(instanceRecord.status, "unassigned");
|
|
assert(instanceRecord.updatedAtMs === 0, "updatedAtMs incremented");
|
|
});
|
|
});
|
|
describe(".finaliseUsers()", function() {
|
|
it("returns the user when there is no existing user", function() {
|
|
const user = new UserRecord(0, "TestUser", new Set([1]));
|
|
user.playerStats.onlineTimeMs = 100;
|
|
|
|
const users = new Map();
|
|
const result = Controller.finaliseUsers(user, users);
|
|
assert.equal(users.size, 0);
|
|
assert.equal(result, user);
|
|
});
|
|
it("does not merge users with different ids", function() {
|
|
const existingUser = new UserRecord(0, "UserOne", new Set([1]));
|
|
existingUser.playerStats.onlineTimeMs = 100;
|
|
|
|
const otherUser = new UserRecord(0, "UserTwo", new Set([2]));
|
|
otherUser.playerStats.onlineTimeMs = 50;
|
|
|
|
const users = new Map([[existingUser.id, existingUser]]);
|
|
const result = Controller.finaliseUsers(otherUser, users);
|
|
assert.equal(users.size, 1);
|
|
assert.equal(result, otherUser);
|
|
assert(!result.roleIds.has(1), "users were merged");
|
|
});
|
|
it("merges into existing user when onlineTimeMs is lower", function() {
|
|
const existingUser = new UserRecord(0, "TestUser", new Set([1]));
|
|
existingUser.playerStats.onlineTimeMs = 100;
|
|
|
|
const user = new UserRecord(0, "TestUser", new Set([2]));
|
|
user.playerStats.onlineTimeMs = 50;
|
|
|
|
const users = new Map([[existingUser.id, existingUser]]);
|
|
const result = Controller.finaliseUsers(user, users);
|
|
assert.equal(users.size, 1);
|
|
assert.equal(result, existingUser);
|
|
assert(result.roleIds.has(2), "other user not merged");
|
|
});
|
|
it("merges into existing user when onlineTimeMs is equal", function() {
|
|
const existingUser = new UserRecord(0, "TestUser", new Set([1]));
|
|
existingUser.playerStats.onlineTimeMs = 100;
|
|
|
|
const user = new UserRecord(0, "TestUser", new Set([2]));
|
|
user.playerStats.onlineTimeMs = 100;
|
|
|
|
const users = new Map([[existingUser.id, existingUser]]);
|
|
const result = Controller.finaliseUsers(user, users);
|
|
assert.equal(users.size, 1);
|
|
assert.equal(result, existingUser);
|
|
assert(result.roleIds.has(2), "other user not merged");
|
|
});
|
|
it("merges existing user into new user when onlineTimeMs is higher", function() {
|
|
const existingUser = new UserRecord(0, "TestUser", new Set([1]));
|
|
existingUser.playerStats.onlineTimeMs = 50;
|
|
|
|
const user = new UserRecord(0, "TestUser", new Set([2]));
|
|
user.playerStats.onlineTimeMs = 100;
|
|
|
|
const users = new Map([[existingUser.id, existingUser]]);
|
|
const result = Controller.finaliseUsers(user, users);
|
|
assert.equal(users.size, 1);
|
|
assert.equal(result, user);
|
|
assert(result.roleIds.has(1), "existing user not merged");
|
|
});
|
|
});
|
|
});
|
|
describe("migrations", function() {
|
|
describe(".migrateSystems()", function() {
|
|
it("migrates 'canRestart' from undefined to false", function() { // Alpha 17
|
|
const result = Controller.migrateSystems([
|
|
{}, { canRestart: true }, { canRestart: false },
|
|
]);
|
|
assert.equal(result[0].canRestart, false);
|
|
assert.equal(result[1].canRestart, true);
|
|
assert.equal(result[2].canRestart, false);
|
|
});
|
|
it("migrates 'restartRequired' from undefined to false", function() { // Alpha 21
|
|
const result = Controller.migrateSystems([
|
|
{}, { restartRequired: true }, { restartRequired: false },
|
|
]);
|
|
assert.equal(result[0].restartRequired, false);
|
|
assert.equal(result[1].restartRequired, true);
|
|
assert.equal(result[2].restartRequired, false);
|
|
});
|
|
it("migrates 'systemStartedAtMs' from undefined to Date.now", function() { // Alpha 23
|
|
const result = Controller.migrateSystems([
|
|
{}, { systemStartedAtMs: 0 }, { systemStartedAtMs: 500 },
|
|
]);
|
|
const now = Date.now();
|
|
const r0 = result[0].systemStartedAtMs;
|
|
assert.ok(r0 > now - 100 && r0 <= now);
|
|
assert.equal(result[1].systemStartedAtMs, 0);
|
|
assert.equal(result[2].systemStartedAtMs, 500);
|
|
});
|
|
it("migrates 'processStartedAtMs' from undefined to Date.now", function() { // Alpha 23
|
|
const result = Controller.migrateSystems([
|
|
{}, { processStartedAtMs: 0 }, { processStartedAtMs: 500 },
|
|
]);
|
|
const now = Date.now();
|
|
const r0 = result[0].processStartedAtMs;
|
|
assert.ok(r0 > now - 100 && r0 <= now);
|
|
assert.equal(result[1].processStartedAtMs, 0);
|
|
assert.equal(result[2].processStartedAtMs, 500);
|
|
});
|
|
it("does nothing for upto date data", function() {
|
|
const systemInfo = new SystemInfo(
|
|
1, "name", "n", "k", "m", "cm", "cr", "mc", "ma", "dc", "da", false, false, 0, 0, 0, false
|
|
);
|
|
const jsonString = JSON.stringify(systemInfo);
|
|
const systemInfoJson = JSON.parse(jsonString);
|
|
const systemInfoJsonCopy = JSON.parse(jsonString);
|
|
const result = Controller.migrateSystems([
|
|
systemInfoJson, systemInfoJson, systemInfoJson,
|
|
]);
|
|
assert.deepEqual(result, [
|
|
systemInfoJsonCopy, systemInfoJsonCopy, systemInfoJsonCopy,
|
|
]);
|
|
});
|
|
});
|
|
describe(".migrateHosts()", function() {
|
|
it("migrates to the new format", function() { // Alpha 19
|
|
const result = Controller.migrateHosts([
|
|
["", "foo"], ["", "bar"], ["", "baz"],
|
|
]);
|
|
assert.deepEqual(result, [
|
|
"foo", "bar", "baz",
|
|
]);
|
|
});
|
|
it("does nothing for upto date data", function() {
|
|
const hostInfo = new HostRecord(1, "", "", new Map());
|
|
const jsonString = JSON.stringify(hostInfo);
|
|
const hostInfoJson = JSON.parse(jsonString);
|
|
const hostInfoJsonCopy = JSON.parse(jsonString);
|
|
const result = Controller.migrateHosts([
|
|
hostInfoJson, hostInfoJson, hostInfoJson,
|
|
]);
|
|
assert.deepEqual(result, [
|
|
hostInfoJsonCopy, hostInfoJsonCopy, hostInfoJsonCopy,
|
|
]);
|
|
});
|
|
});
|
|
describe(".migrateInstances()", function() {
|
|
it("migrates to the new format", function() { // Alpha 14
|
|
const result = Controller.migrateInstances([
|
|
{ name: "foo" }, { name: "bar" }, { name: "baz" },
|
|
]);
|
|
assert.deepEqual(result, [
|
|
{ config: { name: "foo" }, status: "running" },
|
|
{ config: { name: "bar" }, status: "running" },
|
|
{ config: { name: "baz" }, status: "running" },
|
|
]);
|
|
});
|
|
it("does nothing for upto date data", function() {
|
|
const instanceConfig = new InstanceConfig("controller");
|
|
const instanceRecord = new InstanceRecord(instanceConfig, "unknown");
|
|
const jsonString = JSON.stringify(instanceRecord);
|
|
const instanceRecordJson = JSON.parse(jsonString);
|
|
const instanceRecordJsonCopy = JSON.parse(jsonString);
|
|
const result = Controller.migrateInstances([
|
|
instanceRecordJson, instanceRecordJson, instanceRecordJson,
|
|
]);
|
|
assert.deepEqual(result, [
|
|
instanceRecordJsonCopy, instanceRecordJsonCopy, instanceRecordJsonCopy,
|
|
]);
|
|
});
|
|
});
|
|
describe(".migrateModPacks()", function() {
|
|
it("migrates builtin mod versions to X.Y.Z", function() {
|
|
const modPacks = Controller.migrateModPacks([{
|
|
id: 0,
|
|
name: "name",
|
|
factorio_version: "2.0",
|
|
mods: [
|
|
{ name: "base", version: "2.0" },
|
|
{ name: "my-mod", version: "1.0.0" },
|
|
],
|
|
}]);
|
|
assert.deepEqual(modPacks, [{
|
|
id: 0,
|
|
name: "name",
|
|
factorio_version: "2.0",
|
|
mods: [
|
|
{ name: "base", version: "2.0.0" },
|
|
{ name: "my-mod", version: "1.0.0" },
|
|
],
|
|
}]);
|
|
});
|
|
it("does nothing for upto date data", function() {
|
|
const modPack = ModPack.fromJSON({
|
|
id: 0,
|
|
name: "name",
|
|
factorio_version: "2.0",
|
|
mods: [
|
|
{ name: "base", version: "2.0.0" },
|
|
{ name: "my-mod", version: "1.0.0" },
|
|
],
|
|
});
|
|
const jsonString = JSON.stringify(modPack);
|
|
const modPackJson = JSON.parse(jsonString);
|
|
const modPackJsonCopy = JSON.parse(jsonString);
|
|
const result = Controller.migrateModPacks([
|
|
modPackJson, modPackJson, modPackJson,
|
|
]);
|
|
assert.deepEqual(result, [
|
|
modPackJsonCopy, modPackJsonCopy, modPackJsonCopy,
|
|
]);
|
|
});
|
|
});
|
|
describe(".migrateRoles()", function() {
|
|
it("migrates renamed permissions", function() { // Alpha 17
|
|
const result = Controller.migrateRoles([
|
|
{ permissions: ["foo", "bar", "core.instance.save.list.subscribe"] },
|
|
{ permissions: ["bar", "core.instance.save.list.subscribe"] },
|
|
{ permissions: ["core.instance.save.subscribe"] },
|
|
]);
|
|
assert.deepEqual(result, [
|
|
{ permissions: ["foo", "bar", "core.instance.save.subscribe"] },
|
|
{ permissions: ["bar", "core.instance.save.subscribe"] },
|
|
{ permissions: ["core.instance.save.subscribe"] },
|
|
]);
|
|
});
|
|
it("does nothing for upto date data", function() {
|
|
const role = new Role(
|
|
0, "n", "d", new Set("p1", "p2"), 0, false
|
|
);
|
|
const jsonString = JSON.stringify(role);
|
|
const roleJson = JSON.parse(jsonString);
|
|
const roleJsonCopy = JSON.parse(jsonString);
|
|
const result = Controller.migrateRoles([
|
|
roleJson, roleJson, roleJson,
|
|
]);
|
|
assert.deepEqual(result, [
|
|
roleJsonCopy, roleJsonCopy, roleJsonCopy,
|
|
]);
|
|
});
|
|
});
|
|
});
|
|
});
|