mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 07:04:53 +09:00
Move all functions and classes currently available through lib/name and libName to be under a single flat namespace in lib. This make reorganising the lib namespace much simpler as the location of symbols can move without breaking the consumers of lib. The multi-entrypoint design was already problematic for the web plugin system which couldn't effectively use it due to how webpack's shared module system is awkward to set up with multiple entrypoints per package.
239 lines
4.9 KiB
JavaScript
239 lines
4.9 KiB
JavaScript
"use strict";
|
|
const events = require("events");
|
|
const http = require("http");
|
|
const express = require("express");
|
|
|
|
const lib = require("@clusterio/lib");
|
|
|
|
const UserManager = require("@clusterio/controller/src/UserManager");
|
|
|
|
const addr = lib.Address.fromShorthand;
|
|
|
|
class MockLogger {
|
|
child() { return this; }
|
|
|
|
fatal() { }
|
|
|
|
error() { }
|
|
|
|
warn() { }
|
|
|
|
audit() { }
|
|
|
|
info() { }
|
|
|
|
server() { }
|
|
|
|
verbose() { }
|
|
}
|
|
|
|
class MockSocket {
|
|
constructor() {
|
|
this.sentMessages = [];
|
|
this.events = new Map();
|
|
}
|
|
|
|
send(message) {
|
|
this.sentMessages.push(message);
|
|
}
|
|
|
|
on(event, fn) {
|
|
this.events.set(event, fn);
|
|
}
|
|
|
|
/* eslint-disable accessor-pairs */
|
|
set onclose(fn) {
|
|
this.on("close", (code, reason) => fn({ code, reason }));
|
|
}
|
|
|
|
set onerror(fn) {
|
|
this.on("error", fn);
|
|
}
|
|
|
|
set onopen(fn) {
|
|
this.on("open", fn);
|
|
}
|
|
|
|
set onmessage(fn) {
|
|
this.on("message", (data) => fn({ data }));
|
|
}
|
|
|
|
terminate() {
|
|
this.terminateCalled = true;
|
|
}
|
|
|
|
close() {
|
|
this.closeCalled = true;
|
|
}
|
|
}
|
|
|
|
class MockConnector extends lib.BaseConnector {
|
|
constructor(src, dst) {
|
|
super(src, dst);
|
|
|
|
this.connected = true;
|
|
this.sentMessages = [];
|
|
}
|
|
|
|
send(message) {
|
|
this.sentMessages.push(message);
|
|
setImmediate(() => this.emit("send", message));
|
|
}
|
|
}
|
|
|
|
class MockServer extends events.EventEmitter {
|
|
constructor() {
|
|
super();
|
|
this.reset();
|
|
}
|
|
|
|
reset() {
|
|
this.rconCommands = [];
|
|
this.rconCommandResults = new Map();
|
|
}
|
|
|
|
async sendRcon(command) {
|
|
this.rconCommands.push(command);
|
|
let result = this.rconCommandResults.get(command);
|
|
if (!result) {
|
|
result = { response: "" };
|
|
}
|
|
if (result instanceof Error || typeof result === "string") {
|
|
result = { response: result };
|
|
}
|
|
if (result.time) {
|
|
await lib.wait(result.time);
|
|
}
|
|
if (result.response instanceof Error) {
|
|
throw result.response;
|
|
}
|
|
return result.response || "";
|
|
}
|
|
}
|
|
|
|
class MockInstance extends lib.Link {
|
|
constructor() {
|
|
super(new MockConnector(addr({ instanceId: 7357 }), addr({ hostId: 1 })));
|
|
this.logger = new MockLogger();
|
|
this.server = new MockServer();
|
|
this.name = "test";
|
|
this.id = 7357;
|
|
this.status = "running";
|
|
this.mockConfigEntries = new Map([
|
|
["instance.id", 7357],
|
|
["factorio.enable_save_patching", true],
|
|
]);
|
|
this.config = {
|
|
get: (name) => {
|
|
if (this.mockConfigEntries.has(name)) {
|
|
return this.mockConfigEntries.get(name);
|
|
}
|
|
throw Error(`mock for field ${name} is not implemented`);
|
|
},
|
|
};
|
|
}
|
|
|
|
async sendRcon(command, expectEmpty, plugin) {
|
|
return await this.server.sendRcon(command);
|
|
}
|
|
}
|
|
|
|
class MockHost extends lib.Link {
|
|
constructor() {
|
|
super(new MockConnector(addr({ hostId: 1 }), addr("controller")));
|
|
}
|
|
}
|
|
|
|
class MockControl extends lib.Link { }
|
|
|
|
class MockController {
|
|
constructor() {
|
|
this.app = express();
|
|
this.app.locals.controller = this;
|
|
this.app.locals.streams = new Map();
|
|
this.mockConfigEntries = new Map([
|
|
["controller.external_address", "test"],
|
|
["controller.auth_secret", "TestSecretDoNotUse"],
|
|
["controller.proxy_stream_timeout", 1],
|
|
]);
|
|
this.config = {
|
|
get: (name) => {
|
|
if (this.mockConfigEntries.has(name)) {
|
|
return this.mockConfigEntries.get(name);
|
|
}
|
|
throw Error(`mock for field ${name} is not implemented`);
|
|
},
|
|
};
|
|
|
|
this.userManager = new UserManager();
|
|
this.userManager.roles = new Map([
|
|
[0, new lib.Role({ id: 0, name: "Admin", description: "admin", permissions: ["core.admin"] })],
|
|
[1, new lib.Role({ id: 1, name: "Player", description: "player", permissions: [] })],
|
|
]);
|
|
this.userManager.roles.get(1).grantDefaultPermissions();
|
|
|
|
this.userManager.users = new Map([
|
|
["test", new lib.User({ name: "test", roles: [0, 1] }, this.userManager.roles)],
|
|
["player", new lib.User({ name: "player", roles: [1] }, this.userManager.roles)],
|
|
]);
|
|
this.instances = new Map();
|
|
this.hosts = new Map();
|
|
}
|
|
|
|
handle() {
|
|
}
|
|
|
|
getControllerUrl() {
|
|
return "http://controller.example/";
|
|
}
|
|
|
|
async startServer() {
|
|
this.server = http.createServer(this.app);
|
|
await new Promise(resolve => {
|
|
this.server.listen(0, "127.0.0.1", resolve);
|
|
});
|
|
let address = this.server.address();
|
|
return `http://127.0.0.1:${address.port}`;
|
|
}
|
|
|
|
async stopServer() {
|
|
if (this.server) {
|
|
this.server.close();
|
|
this.server.unref();
|
|
}
|
|
}
|
|
}
|
|
|
|
async function createControllerPlugin(ControllerPluginClass, info) {
|
|
lib.registerPluginMessages([info]);
|
|
let controller = new MockController();
|
|
let metrics = {};
|
|
let logger = new MockLogger();
|
|
let plugin = new ControllerPluginClass(info, controller, metrics, logger);
|
|
await plugin.init();
|
|
return plugin;
|
|
}
|
|
|
|
async function createInstancePlugin(InstancePluginClass, info) {
|
|
let instance = new MockInstance();
|
|
let host = new MockHost();
|
|
let plugin = new InstancePluginClass(info, instance, host);
|
|
await plugin.init();
|
|
return plugin;
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
MockLogger,
|
|
MockSocket,
|
|
MockConnector,
|
|
MockServer,
|
|
MockInstance,
|
|
MockHost,
|
|
MockControl,
|
|
MockController,
|
|
|
|
createControllerPlugin,
|
|
createInstancePlugin,
|
|
};
|