mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
The staging copy made by Config.set() went through the constructor, so plugin migrations ran a second time on the live fields. A version-gated migration was applied twice when setPluginVersions() changed the version. Staging now copies the fields with update() instead. A config saved without <plugin>.version got the running version as its default, so setPluginVersions() saw no change and nothing saved the stamp. The constructor now writes the registered plugin versions after the migrations run and marks the config dirty when that changes a loaded value. Controller.bootstrap() saves the instances that came out dirty, and setPluginVersions() is gone. Restructure the SyncHook and plugin config tests by method, and suggest the controller config version for role migrations in the docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
152 lines
5.9 KiB
JavaScript
152 lines
5.9 KiB
JavaScript
import * as lib from "@clusterio/lib";
|
|
import assert from "node:assert/strict";
|
|
|
|
// Each migration test should indicate which version introduced the migration
|
|
|
|
describe("lib/config/definitions/migrations", function() {
|
|
describe("Controller Config", function() {
|
|
it("should migrate 'external_address' to 'public_url'", function() { // Alpha 19
|
|
const config = lib.ControllerConfig.fromJSON({
|
|
"controller.external_address": "https://example.com:4000",
|
|
}, "controller");
|
|
|
|
assert.equal(config.get("controller.public_url"), "https://example.com:4000",
|
|
"public_url contains the wrong value");
|
|
assert.equal(config.fields["controller.external_address"], undefined,
|
|
"external_address was not removed");
|
|
});
|
|
});
|
|
describe("Host Config", function() {
|
|
|
|
});
|
|
describe("Instance Config", function() {
|
|
it("should migrate boolean sync to string enum", function() { // Alpha 19
|
|
const configTrue = lib.InstanceConfig.fromJSON({
|
|
"factorio.sync_adminlist": true,
|
|
"factorio.sync_whitelist": true,
|
|
"factorio.sync_banlist": true,
|
|
}, "controller");
|
|
|
|
assert.equal(configTrue.get("factorio.sync_adminlist"), "enabled", "sync_adminlist contains wrong value");
|
|
assert.equal(configTrue.get("factorio.sync_whitelist"), "enabled", "sync_adminlist contains wrong value");
|
|
assert.equal(configTrue.get("factorio.sync_banlist"), "enabled", "sync_adminlist contains wrong value");
|
|
|
|
const configFalse = lib.InstanceConfig.fromJSON({
|
|
"factorio.sync_adminlist": false,
|
|
"factorio.sync_whitelist": false,
|
|
"factorio.sync_banlist": false,
|
|
}, "controller");
|
|
|
|
assert.equal(configFalse.get("factorio.sync_adminlist"), "disabled", "sync_adminlist contains wrong value");
|
|
assert.equal(configFalse.get("factorio.sync_whitelist"), "disabled", "sync_adminlist contains wrong value");
|
|
assert.equal(configFalse.get("factorio.sync_banlist"), "disabled", "sync_adminlist contains wrong value");
|
|
});
|
|
});
|
|
describe("Ctl Config", function() {
|
|
|
|
});
|
|
describe("Plugin Config", function() {
|
|
const pluginInfo = {
|
|
name: "test_plugin",
|
|
version: "1.2.0",
|
|
instanceEntrypoint: "instance.js",
|
|
instanceConfigFields: {
|
|
"test_plugin.delay": { type: "number", initialValue: 1 },
|
|
},
|
|
};
|
|
before(function() {
|
|
lib.addPluginConfigFields([pluginInfo]);
|
|
});
|
|
afterEach(function() {
|
|
lib.InstanceConfig.pluginMigrations.clear();
|
|
lib.Config.pluginVersions.clear();
|
|
});
|
|
after(function() {
|
|
for (const Config of [lib.ControllerConfig, lib.HostConfig, lib.InstanceConfig]) {
|
|
for (const name of Object.keys(Config.fieldDefinitions)) {
|
|
if (name.startsWith("test_plugin.")) {
|
|
delete Config.fieldDefinitions[name];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
describe("static .pluginMigrations", function() {
|
|
it("should run on load", function() {
|
|
lib.InstanceConfig.pluginMigrations.attach("test_plugin", config => (
|
|
lib.renameConfigPrefix(config, "old_plugin.", "test_plugin.")
|
|
));
|
|
const config = lib.InstanceConfig.fromJSON({
|
|
"old_plugin.load_plugin": false,
|
|
"old_plugin.delay": 5,
|
|
}, "controller");
|
|
assert.equal(config.get("test_plugin.load_plugin"), false);
|
|
assert.equal(config.get("test_plugin.delay"), 5);
|
|
assert.equal(config.toJSON()["old_plugin.delay"], undefined);
|
|
});
|
|
it("should run after core migrations", function() {
|
|
lib.InstanceConfig.pluginMigrations.attach("test_plugin", config => {
|
|
assert.equal(config["factorio.sync_adminlist"], "enabled");
|
|
return config;
|
|
});
|
|
lib.InstanceConfig.fromJSON({ "factorio.sync_adminlist": true }, "controller");
|
|
});
|
|
it("should see the version the config was saved with", function() {
|
|
let seen;
|
|
lib.InstanceConfig.pluginMigrations.attach("test_plugin", config => {
|
|
seen = config["test_plugin.version"];
|
|
return config;
|
|
});
|
|
lib.InstanceConfig.fromJSON({ "test_plugin.version": "1.1.0" }, "controller");
|
|
assert.equal(seen, "1.1.0");
|
|
});
|
|
it("should not run again when the config is changed", function() {
|
|
lib.Config.pluginVersions.set("test_plugin", "1.2.0");
|
|
let calls = 0;
|
|
lib.InstanceConfig.pluginMigrations.attach("test_plugin", config => {
|
|
calls += 1;
|
|
if (config["test_plugin.version"] === "1.1.0") {
|
|
config["test_plugin.delay"] *= 60;
|
|
}
|
|
return config;
|
|
});
|
|
const config = lib.InstanceConfig.fromJSON({
|
|
"test_plugin.version": "1.1.0",
|
|
"test_plugin.delay": 2,
|
|
}, "controller");
|
|
config.set("instance.name", "changed");
|
|
assert.equal(config.get("test_plugin.delay"), 120);
|
|
assert.equal(calls, 1);
|
|
});
|
|
});
|
|
describe("static .pluginVersions", function() {
|
|
it("should write the version after migrations run", function() {
|
|
lib.Config.pluginVersions.set("test_plugin", "1.2.0");
|
|
const config = lib.InstanceConfig.fromJSON({ "test_plugin.version": "1.1.0" }, "controller");
|
|
assert.equal(config.get("test_plugin.version"), "1.2.0");
|
|
assert.equal(config.dirty, true);
|
|
});
|
|
it("should mark configs saved without a version as dirty", function() {
|
|
lib.Config.pluginVersions.set("test_plugin", "1.2.0");
|
|
const config = lib.InstanceConfig.fromJSON({}, "controller");
|
|
assert.equal(config.get("test_plugin.version"), "1.2.0");
|
|
assert.equal(config.dirty, true);
|
|
});
|
|
it("should not mark configs already at the version as dirty", function() {
|
|
lib.Config.pluginVersions.set("test_plugin", "1.2.0");
|
|
const config = lib.InstanceConfig.fromJSON({ "test_plugin.version": "1.2.0" }, "controller");
|
|
assert.equal(config.dirty, false);
|
|
});
|
|
it("should write the version to new configs", function() {
|
|
lib.Config.pluginVersions.set("test_plugin", "1.2.0");
|
|
const config = new lib.InstanceConfig("controller");
|
|
assert.equal(config.get("test_plugin.version"), "1.2.0");
|
|
});
|
|
it("should leave the version empty when no versions are registered", function() {
|
|
const config = new lib.InstanceConfig("controller");
|
|
assert.equal(config.get("test_plugin.version"), "");
|
|
});
|
|
});
|
|
});
|
|
});
|