mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
287 lines
9.3 KiB
JavaScript
287 lines
9.3 KiB
JavaScript
/* eslint-disable no-console */
|
|
"use strict";
|
|
const path = require("path");
|
|
const fs = require("fs-extra");
|
|
const child_process = require("child_process");
|
|
const jwt = require("jsonwebtoken");
|
|
const phin = require("phin");
|
|
const util = require("util");
|
|
const events = require("events");
|
|
|
|
const lib = require("@clusterio/lib");
|
|
const { LineSplitter, ConsoleTransport, logger } = lib;
|
|
|
|
// Make sure permissions from plugins are loaded
|
|
require("../../plugins/global_chat/dist/plugin/info");
|
|
require("../../plugins/player_auth/dist/plugin/info");
|
|
require("../../plugins/research_sync/dist/plugin/info");
|
|
require("../../plugins/statistics_exporter/dist/plugin/info");
|
|
require("../../plugins/subspace_storage/dist/plugin/info");
|
|
|
|
|
|
class TestControl extends lib.Link {
|
|
constructor(connector, subscribe = true) {
|
|
super(connector);
|
|
this.hostUpdates = [];
|
|
this.instanceUpdates = [];
|
|
this.saveListUpdates = [];
|
|
this.modUpdates = [];
|
|
this.modPackUpdates = [];
|
|
this.userUpdates = [];
|
|
|
|
this.connector.on("connect", () => {
|
|
if (!subscribe) {
|
|
return;
|
|
}
|
|
this.send(
|
|
new lib.SubscriptionRequest(lib.HostUpdateEvent.name, true)
|
|
).catch(err => logger.error(`Error setting host subscriptions:\n${err.stack}`));
|
|
this.send(
|
|
new lib.SubscriptionRequest(lib.InstanceDetailsUpdateEvent.name, true)
|
|
).catch(err => logger.error(`Error setting instance subscriptions:\n${err.stack}`));
|
|
this.send(
|
|
new lib.SubscriptionRequest(lib.InstanceSaveListUpdateEvent.name, true)
|
|
).catch(err => logger.error(`Error setting save list subscriptions:\n${err.stack}`));
|
|
this.send(
|
|
new lib.SubscriptionRequest(lib.ModUpdateEvent.name, true)
|
|
).catch(err => logger.error(`Error setting mod subscriptions:\n${err.stack}`));
|
|
this.send(
|
|
new lib.SubscriptionRequest(lib.ModPackUpdateEvent.name, true)
|
|
).catch(err => logger.error(`Error setting mod pack subscriptions:\n${err.stack}`));
|
|
this.send(
|
|
new lib.SubscriptionRequest(lib.UserUpdateEvent.name, true)
|
|
).catch(err => logger.error(`Error setting user subscriptions:\n${err.stack}`));
|
|
});
|
|
|
|
this.handle(lib.AccountUpdateEvent);
|
|
this.handle(lib.HostUpdateEvent, this.handleHostUpdateEvent.bind(this));
|
|
this.handle(lib.InstanceDetailsUpdateEvent, this.handleInstanceDetailsUpdateEvent.bind(this));
|
|
this.handle(lib.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this));
|
|
this.handle(lib.ModUpdateEvent, this.handleModUpdateEvent.bind(this));
|
|
this.handle(lib.ModPackUpdateEvent, this.handleModPackUpdateEvent.bind(this));
|
|
this.handle(lib.UserUpdateEvent, this.handleUserUpdateEvent.bind(this));
|
|
}
|
|
|
|
async handleHostUpdateEvent(event) {
|
|
this.hostUpdates.push(event.update);
|
|
}
|
|
|
|
async handleInstanceDetailsUpdateEvent(event) {
|
|
this.instanceUpdates.push(event.details);
|
|
}
|
|
|
|
async handleInstanceSaveListUpdateEvent(event) {
|
|
this.saveListUpdates.push(event);
|
|
}
|
|
|
|
async handleModUpdateEvent(event) {
|
|
this.modUpdates.push(event.mod);
|
|
}
|
|
|
|
async handleModPackUpdateEvent(event) {
|
|
this.modPackUpdates.push(event.modPack);
|
|
}
|
|
|
|
async handleUserUpdateEvent(event) {
|
|
this.userUpdates.push(event.user);
|
|
}
|
|
}
|
|
|
|
class TestControlConnector extends lib.WebSocketClientConnector {
|
|
register() {
|
|
this.sendHandshake(
|
|
new lib.MessageRegisterControl(
|
|
new lib.RegisterControlData(
|
|
this.token,
|
|
"clusterioctl",
|
|
"test",
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
// Mark that this test takes a lot of time, or depeneds on a test
|
|
// that takes a lot of time.
|
|
function slowTest(test) {
|
|
// eslint-disable-next-line node/no-process-env
|
|
if (process.env.FAST_TEST) {
|
|
test.skip();
|
|
}
|
|
|
|
test.timeout(20000);
|
|
}
|
|
|
|
async function get(urlPath) {
|
|
let res = await phin({
|
|
method: "GET",
|
|
url: `https://localhost:4443${urlPath}`,
|
|
core: { rejectUnauthorized: false },
|
|
});
|
|
if (res.statusCode !== 200) {
|
|
throw new Error(`Got response code ${res.statusCode}, content: ${res.body}`);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
let controllerProcess;
|
|
let hostProcess;
|
|
let control;
|
|
|
|
let url = "https://localhost:4443/";
|
|
let controlToken = jwt.sign({ aud: "user", user: "test" }, Buffer.from("TestSecretDoNotUse", "base64"));
|
|
let instancesDir = path.join("temp", "test", "instances");
|
|
let databaseDir = path.join("temp", "test", "database");
|
|
let pluginListPath = path.join("temp", "test", "plugin-list.json");
|
|
let controllerConfigPath = path.join("temp", "test", "config-controller.json");
|
|
let hostConfigPath = path.join("temp", "test", "config-host.json");
|
|
let controlConfigPath = path.join("temp", "test", "config-control.json");
|
|
|
|
async function exec(command, options = {}) {
|
|
// Uncomment to show commands run in tests
|
|
// console.log(command);
|
|
options = { cwd: path.join("temp", "test"), ...options };
|
|
return await util.promisify(child_process.exec)(command, options);
|
|
}
|
|
|
|
async function execCtl(...args) {
|
|
args[0] = `node ../../packages/ctl ${args[0]}`;
|
|
return await exec(...args);
|
|
}
|
|
|
|
async function sendRcon(instanceId, command) {
|
|
return await control.sendTo({ instanceId }, new lib.InstanceSendRconRequest(command));
|
|
}
|
|
|
|
function getControl() {
|
|
return control;
|
|
}
|
|
|
|
function spawn(name, cmd, waitFor) {
|
|
return new Promise((resolve, reject) => {
|
|
console.log(cmd);
|
|
let parts = cmd.split(" ");
|
|
let process = child_process.spawn(parts[0], parts.slice(1), { cwd: path.join("temp", "test") });
|
|
let stdout = new LineSplitter({ readableObjectMode: true });
|
|
stdout.on("data", line => {
|
|
line = line.toString("utf8");
|
|
if (waitFor.test(line)) {
|
|
resolve(process);
|
|
}
|
|
console.log(name, line);
|
|
});
|
|
let stderr = new LineSplitter({ readableObjectMode: true });
|
|
stderr.on("data", line => { console.log(name, line.toString("utf8")); });
|
|
process.stdout.pipe(stdout);
|
|
process.stderr.pipe(stderr);
|
|
});
|
|
}
|
|
|
|
before(async function() {
|
|
this.timeout(40000);
|
|
|
|
// Some integration tests may cause log events
|
|
logger.add(new ConsoleTransport({
|
|
level: "info",
|
|
format: new lib.TerminalFormat(),
|
|
}));
|
|
|
|
await fs.remove(databaseDir);
|
|
await fs.remove(instancesDir);
|
|
|
|
await fs.remove(pluginListPath);
|
|
await fs.remove(controllerConfigPath);
|
|
await fs.remove(hostConfigPath);
|
|
await fs.remove(controlConfigPath);
|
|
|
|
await fs.ensureDir(path.join("temp", "test"));
|
|
|
|
await exec("node ../../packages/controller config set controller.auth_secret TestSecretDoNotUse");
|
|
await exec("node ../../packages/controller config set controller.http_port 8880");
|
|
await exec("node ../../packages/controller config set controller.https_port 4443");
|
|
await exec("node ../../packages/controller config set controller.heartbeat_interval 0.25");
|
|
await exec("node ../../packages/controller config set controller.session_timeout 2");
|
|
await exec("node ../../packages/controller config set controller.tls_certificate ../../test/file/tls/cert.pem");
|
|
await exec("node ../../packages/controller config set controller.tls_private_key ../../test/file/tls/key.pem");
|
|
|
|
await exec("node ../../packages/ctl plugin add ../../plugins/global_chat");
|
|
await exec("node ../../packages/ctl plugin add ../../plugins/research_sync");
|
|
await exec("node ../../packages/ctl plugin add ../../plugins/statistics_exporter");
|
|
await exec("node ../../packages/ctl plugin add ../../plugins/subspace_storage");
|
|
await exec("node ../../packages/ctl plugin add ../../plugins/player_auth");
|
|
|
|
await exec("node ../../packages/controller bootstrap create-admin test");
|
|
await exec("node ../../packages/controller bootstrap create-ctl-config test");
|
|
await exec("node ../../packages/ctl control-config set control.tls_ca ../../test/file/tls/cert.pem");
|
|
|
|
controllerProcess = await spawn("controller:", "node ../../packages/controller run", /Started controller/);
|
|
|
|
await execCtl("host create-config --id 4 --name host --generate-token");
|
|
await exec(`node ../../packages/host config set host.factorio_directory ${path.join("..", "..", "factorio")}`);
|
|
await exec("node ../../packages/host config set host.tls_ca ../../test/file/tls/cert.pem");
|
|
|
|
hostProcess = await spawn("host:", "node ../../packages/host run", /Started host/);
|
|
|
|
let tlsCa = await fs.readFile("test/file/tls/cert.pem");
|
|
let controlConnector = new TestControlConnector(url, 2, tlsCa);
|
|
controlConnector.token = controlToken;
|
|
control = new TestControl(controlConnector);
|
|
await controlConnector.connect();
|
|
|
|
const testPack = lib.ModPack.fromJSON({});
|
|
testPack.id = 12;
|
|
testPack.name = "subspace_storage-pack";
|
|
testPack.factorioVersion = "1.1.0";
|
|
testPack.mods.set("clusterio_lib", { name: "clusterio_lib", enabled: true, version: "0.1.2" });
|
|
testPack.mods.set("subspace_storage", { name: "subspace_storage", enabled: true, version: "1.99.8" });
|
|
await control.sendTo("controller", new lib.ModPackCreateRequest(testPack));
|
|
await control.sendTo(
|
|
"controller",
|
|
new lib.ControllerConfigSetFieldRequest("controller.default_mod_pack_id", "12"),
|
|
);
|
|
});
|
|
|
|
after(async function() {
|
|
this.timeout(20000);
|
|
if (hostProcess) {
|
|
console.log("Shutting down host");
|
|
hostProcess.kill("SIGINT");
|
|
await events.once(hostProcess, "exit");
|
|
}
|
|
if (controllerProcess) {
|
|
console.log("Shutting down controller");
|
|
controllerProcess.kill("SIGINT");
|
|
await events.once(controllerProcess, "exit");
|
|
}
|
|
if (control) {
|
|
await control.connector.close();
|
|
}
|
|
});
|
|
|
|
// Ensure the test processes are stopped.
|
|
process.on("exit", () => {
|
|
if (hostProcess) { hostProcess.kill(); }
|
|
if (controllerProcess) { controllerProcess.kill(); }
|
|
});
|
|
|
|
|
|
module.exports = {
|
|
TestControl,
|
|
TestControlConnector,
|
|
slowTest,
|
|
get,
|
|
exec,
|
|
execCtl,
|
|
sendRcon,
|
|
getControl,
|
|
spawn,
|
|
|
|
url,
|
|
controlToken,
|
|
instancesDir,
|
|
databaseDir,
|
|
controllerConfigPath,
|
|
hostConfigPath,
|
|
controlConfigPath,
|
|
};
|