mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Send updates to the master server when the running status of instances change and add onInstanceStatusChanged hook to master plugins.
123 lines
4.4 KiB
JavaScript
123 lines
4.4 KiB
JavaScript
const assert = require('assert').strict;
|
|
const fs = require('fs-extra');
|
|
const path = require('path');
|
|
|
|
const mock = require('../mock');
|
|
const link = require('lib/link');
|
|
const plugin = require('lib/plugin');
|
|
const errors = require('lib/errors');
|
|
|
|
|
|
describe("lib/plugin", function() {
|
|
describe("class BaseInstancePlugin", function() {
|
|
let instancePlugin;
|
|
it("should be constructible", async function() {
|
|
instancePlugin = new plugin.BaseInstancePlugin();
|
|
await instancePlugin.init();
|
|
})
|
|
it("should define defaults for hooks", async function() {
|
|
await instancePlugin.onMetrics();
|
|
await instancePlugin.onStart();
|
|
await instancePlugin.onStop();
|
|
instancePlugin.onExit();
|
|
await instancePlugin.onOutput({});
|
|
instancePlugin.onMasterConnectionEvent("connect");
|
|
await instancePlugin.onPrepareMasterDisconnect();
|
|
})
|
|
});
|
|
|
|
describe("class BaseMasterPlugin", function() {
|
|
let masterPlugin;
|
|
it("should be constructible", async function() {
|
|
masterPlugin = new plugin.BaseMasterPlugin();
|
|
await masterPlugin.init();
|
|
})
|
|
it("should define defaults for hooks", async function() {
|
|
await masterPlugin.onInstanceStatusChanged({}, "running", "initialized");
|
|
await masterPlugin.onMetrics();
|
|
await masterPlugin.onShutdown();
|
|
masterPlugin.onSlaveConnectionEvent({}, "connect");
|
|
await masterPlugin.onPrepareSlaveDisconnect({});
|
|
})
|
|
});
|
|
|
|
describe("loadPluginInfos()", function() {
|
|
let baseDir = path.join("temp", "test", "plugin");
|
|
let emptyDir = path.join(baseDir, 'emptyDir');
|
|
let emptyPlugin = path.join(baseDir, 'emptyPlugin');
|
|
let testPlugin = path.join(baseDir, 'testPlugin');
|
|
let brokenPlugin = path.join(baseDir, 'brokenPlugin');
|
|
let invalidPlugin = path.join(baseDir, 'invalidPlugin');
|
|
before(async function() {
|
|
await fs.ensureDir(emptyDir);
|
|
await fs.ensureDir(path.join(emptyPlugin, 'empty'));
|
|
|
|
async function writePlugin(pluginPath, name, infoName = name) {
|
|
await fs.outputFile(
|
|
path.join(pluginPath, name, 'info.js'),
|
|
`module.exports = { name: "${infoName}" };`
|
|
);
|
|
}
|
|
|
|
await writePlugin(testPlugin, 'test');
|
|
await writePlugin(brokenPlugin, 'broken');
|
|
await fs.outputFile(path.join(brokenPlugin, 'broken', 'info.js'), "Syntax Error");
|
|
await writePlugin(invalidPlugin, 'invalid', 'wrong');
|
|
});
|
|
|
|
it("should return an empty array for an empty directory", async function() {
|
|
assert.deepEqual(await plugin.loadPluginInfos(emptyDir), []);
|
|
});
|
|
it("should ignore plugin dirs without info module", async function() {
|
|
assert.deepEqual(await plugin.loadPluginInfos(emptyPlugin), []);
|
|
});
|
|
it("should discover test plugin", async function() {
|
|
assert.deepEqual(
|
|
await plugin.loadPluginInfos(testPlugin),
|
|
[{ name: 'test' }]
|
|
);
|
|
});
|
|
it("should reject on broken plugin", async function() {
|
|
await assert.rejects(
|
|
plugin.loadPluginInfos(brokenPlugin),
|
|
{ message: "PluginError: Unexpected identifier" }
|
|
);
|
|
});
|
|
it("should reject on invalid plugin", async function() {
|
|
await assert.rejects(
|
|
plugin.loadPluginInfos(invalidPlugin),
|
|
{ message: `Plugin dir ${invalidPlugin}/invalid does not match the name of the plugin (wrong)` }
|
|
);
|
|
});
|
|
|
|
after(async function() {
|
|
await fs.unlink(path.join(brokenPlugin, 'broken', 'info.js'));
|
|
});
|
|
});
|
|
|
|
describe("attachPluginMessages()", function() {
|
|
let mockLink = new link.Link('source', 'target', new mock.MockConnector());
|
|
let mockEvent = new link.Event({ type: "test:test", links: ["target-source"] });
|
|
it("should accept pluginInfo without messages", function() {
|
|
plugin.attachPluginMessages(mockLink, {}, null);
|
|
});
|
|
it("should attach handler for the given message", function() {
|
|
let mockEventEventHandler = function() {};
|
|
plugin.attachPluginMessages(mockLink, { name: "test", messages: { mockEvent }}, { mockEventEventHandler });
|
|
assert(mockLink._handlers.get("test:test_event"), "handler was not registered");
|
|
});
|
|
it("should throw if missing handler for the given message", function() {
|
|
assert.throws(
|
|
() => plugin.attachPluginMessages(mockLink, { name: "test", messages: { mockEvent }}, {}),
|
|
new Error("Missing handler for test:test_event on source-target link")
|
|
);
|
|
});
|
|
it("should throw if message starts with the wrong prefix", function() {
|
|
assert.throws(
|
|
() => plugin.attachPluginMessages(mockLink, { name: "foo", messages: { mockEvent }}, {}),
|
|
new Error('Type of mockEvent message must start with "foo:"')
|
|
);
|
|
});
|
|
});
|
|
});
|