Files
factorio-clusterio/test/slave.js
T
Hornwitser 14934a0d3a Move checkFilename and cleanFilename to libFileOps
These are also useful for managing mod zip files on the master.
2022-08-24 15:42:26 +02:00

180 lines
6.3 KiB
JavaScript

"use strict";
const assert = require("assert").strict;
const path = require("path");
const fs = require("fs-extra");
const libLink = require("@clusterio/lib/link");
const libConfig = require("@clusterio/lib/config");
const Instance = require("@clusterio/slave/src/Instance");
const Slave = require("@clusterio/slave/src/Slave");
describe("Slave testing", function() {
before(function() {
libConfig.InstanceConfig.finalize();
});
describe("symlinkMods()", function() {
let testDir = path.join("temp", "test", "symlink");
let instance;
before(async function() {
// Remove previous test output
await fs.remove(testDir);
// Add some test mods
await fs.outputFile(path.join(testDir, "shared", "mod_a.zip"), "a");
await fs.outputFile(path.join(testDir, "shared", "mod_b.zip"), "b");
await fs.outputFile(path.join(testDir, "shared", "mod.dat"), "c");
await fs.outputFile(path.join(testDir, "shared", "mod-list.json"), "d");
let instanceConfig = new libConfig.InstanceConfig("slave");
await instanceConfig.init();
instanceConfig.set("instance.name", "test");
instance = new Instance(
{}, new libLink.VirtualConnector(), path.join(testDir, "instance"), "factorioDir", instanceConfig
);
await fs.outputFile(instance.path("mods", "mod_i.zip"), "i");
});
it("should link mods and data files", async function() {
await Instance._symlinkMods(instance, path.join(testDir, "shared"));
assert.equal(await fs.readFile(instance.path("mods", "mod_a.zip"), "utf-8"), "a");
assert.equal(await fs.readFile(instance.path("mods", "mod_b.zip"), "utf-8"), "b");
assert.equal(await fs.readFile(instance.path("mods", "mod.dat"), "utf-8"), "c");
assert.equal(await fs.readFile(instance.path("mods", "mod-list.json"), "utf-8"), "d");
assert.equal(await fs.readFile(instance.path("mods", "mod_i.zip"), "utf-8"), "i");
});
it("should ignore directories", async function() {
await fs.ensureDir(path.join(testDir, "shared", "dir"));
await Instance._symlinkMods(instance, path.join(testDir, "shared"));
assert(!await fs.exists(instance.path("mods", "dir"), "utf-8"), "dir was unxpectedly linked");
});
it("should ignore files", async function() {
await fs.outputFile(path.join(testDir, "shared", "file"), "f");
await Instance._symlinkMods(instance, path.join(testDir, "shared"));
assert(!await fs.exists(instance.path("mods", "file"), "utf-8"), "dir was unxpectedly linked");
});
it("should unlink removed mods", async function() {
// This does not work on Windows
if (process.platform === "win32") {
this.skip();
}
await fs.unlink(path.join(testDir, "shared", "mod_a.zip"));
await Instance._symlinkMods(instance, path.join(testDir, "shared"));
await assert.rejects(fs.lstat(instance.path("mods", "mod_a.zip")), { code: "ENOENT" });
assert.equal(await fs.readFile(instance.path("mods", "mod_b.zip"), "utf-8"), "b");
assert.equal(await fs.readFile(instance.path("mods", "mod.dat"), "utf-8"), "c");
assert.equal(await fs.readFile(instance.path("mods", "mod-list.json"), "utf-8"), "d");
assert.equal(await fs.readFile(instance.path("mods", "mod_i.zip"), "utf-8"), "i");
});
});
describe("discoverInstances()", function() {
it("should discover test instance", async function() {
let instancePath = path.join("test", "file", "instances");
let instanceInfos = await Slave._discoverInstances(instancePath);
let referenceConfig = new libConfig.InstanceConfig("slave");
await referenceConfig.init();
referenceConfig.set("instance.id", 1);
referenceConfig.set("instance.name", "test");
assert.deepEqual(instanceInfos, new Map([
[1, {
config: referenceConfig,
path: path.join(instancePath, "test"),
}],
]));
});
});
describe("class Slave", function() {
describe(".syncUserListsEventHandler()", function() {
let mockSlave;
beforeEach(function() {
mockSlave = {
adminlist: new Set(),
whitelist: new Set(),
banlist: new Map(),
broadcasts: [],
broadcastEventToInstance(message, event) {
this.broadcasts.push(message["data"]);
},
syncUserListsEventHandler: Slave.prototype.syncUserListsEventHandler,
syncLists(adminlist, banlist, whitelist) {
return this.syncUserListsEventHandler({ "data": {
"adminlist": adminlist,
"banlist": banlist,
"whitelist": whitelist,
}});
},
};
});
it("should broadcast new entries to adminlist", async function() {
await mockSlave.syncLists(["admin1"], [], []);
await mockSlave.syncLists(["admin1", "admin2"], [], []);
assert.deepEqual(mockSlave.broadcasts, [
{ "name": "admin1", "admin": true },
{ "name": "admin2", "admin": true },
]);
});
it("should broadcast removals from adminlist", async function() {
mockSlave.adminlist.add("admin1").add("admin2");
await mockSlave.syncLists(["admin1"], [], []);
assert.deepEqual(mockSlave.broadcasts, [
{ "name": "admin2", "admin": false },
]);
});
it("should broadcast new entries to whitelist", async function() {
await mockSlave.syncLists([], [], ["player1"]);
await mockSlave.syncLists([], [], ["player1", "player2"]);
assert.deepEqual(mockSlave.broadcasts, [
{ "name": "player1", "whitelisted": true },
{ "name": "player2", "whitelisted": true },
]);
});
it("should broadcast removals from whitelist", async function() {
mockSlave.whitelist.add("player1").add("player2");
await mockSlave.syncLists([], [], ["player1"]);
assert.deepEqual(mockSlave.broadcasts, [
{ "name": "player2", "whitelisted": false },
]);
});
it("should broadcast new entries to banlist", async function() {
await mockSlave.syncLists([], [["badie1", "greifing"]], []);
await mockSlave.syncLists([], [["badie1", "greifing"], ["badie2", "annoying"]], []);
assert.deepEqual(mockSlave.broadcasts, [
{ "name": "badie1", "banned": true, "reason": "greifing" },
{ "name": "badie2", "banned": true, "reason": "annoying" },
]);
});
it("should broadcast removals to banlist", async function() {
mockSlave.banlist.set("badie1", "greifing").set("badie2", "annoying");
await mockSlave.syncLists([], [["badie1", "greifing"]], []);
assert.deepEqual(mockSlave.broadcasts, [
{ "name": "badie2", "banned": false, "reason": "" },
]);
});
});
});
});