aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorY. Wang <yw05@forksworld.de>2022-11-04 11:15:04 +0100
committerY. Wang <yw05@forksworld.de>2023-03-23 20:06:02 +0100
commitba98fa53780bf19266d7e5049fd7ec31eaad18bf (patch)
tree9cd93792726c3a68d591f399df52a64ec434b67e
parentd61c72002008280d70a7489f806d181250747c9a (diff)
downloadadvtrains-ba98fa53780bf19266d7e5049fd7ec31eaad18bf.tar.gz
advtrains-ba98fa53780bf19266d7e5049fd7ec31eaad18bf.tar.bz2
advtrains-ba98fa53780bf19266d7e5049fd7ec31eaad18bf.zip
Harden type 2 signal group API; add test for type 2 main signals
-rw-r--r--advtrains_interlocking/signal_aspects.lua17
-rw-r--r--advtrains_interlocking/spec/type2_spec.lua103
2 files changed, 115 insertions, 5 deletions
diff --git a/advtrains_interlocking/signal_aspects.lua b/advtrains_interlocking/signal_aspects.lua
index 37af7aa..65e970f 100644
--- a/advtrains_interlocking/signal_aspects.lua
+++ b/advtrains_interlocking/signal_aspects.lua
@@ -9,13 +9,15 @@ local type2defs = {}
local function register_type2(def)
local t = {type = 2}
local name = def.name
- if type2defs[name] then
- return error("Name " .. name .. " already used")
- elseif type(name) ~= "string" then
+ if type(name) ~= "string" then
return error("Name is not a string")
+ elseif type2defs[name] then
+ return error(string.format("Attempt to redefine type 2 signal aspect group %q, previously defined in %s", name, type2defs[name].defined))
end
t.name = name
+ t.defined = debug.getinfo(2, "S").short_src or "[?]"
+
local label = def.label or name
if type(label) ~= "string" then
return error("Label is not a string")
@@ -54,7 +56,12 @@ end
-- @return[1] The definition for the signal group (if present).
-- @return[2] The nil constant (otherwise).
local function get_type2_definition(name)
- return type2defs[name]
+ local t = type2defs[name]
+ if t then
+ return table.copy(t)
+ else
+ return nil
+ end
end
--- Get the name of the distant aspect before the current aspect.
@@ -151,7 +158,7 @@ local function type1_to_type2main(asp, group, shift)
return t_main[math.max(1, idx-(shift or 0))].name
end
---- Compare two signal aspect tables.
+--- Compare two type 1 signal aspect tables.
-- @function equalp
-- @param asp1 The first signal aspect table.
-- @param asp2 The second signal aspect table.
diff --git a/advtrains_interlocking/spec/type2_spec.lua b/advtrains_interlocking/spec/type2_spec.lua
new file mode 100644
index 0000000..514f6aa
--- /dev/null
+++ b/advtrains_interlocking/spec/type2_spec.lua
@@ -0,0 +1,103 @@
+require "mineunit"
+mineunit("core")
+
+_G.advtrains = {
+ interlocking = {
+ aspects = sourcefile("signal_aspects"),
+ },
+ ndb = {
+ get_node = minetest.get_node,
+ swap_node = minetest.swap_node,
+ }
+}
+
+fixture("advtrains_helpers")
+sourcefile("database")
+sourcefile("signal_api")
+sourcefile("distant")
+sourcefile("signal_aspect_accessors")
+
+local A = advtrains.interlocking.aspects
+local D = advtrains.distant
+local I = advtrains.interlocking
+local N = advtrains.ndb
+
+local type2def = {
+ name = "foo",
+ main = {
+ {name = "proceed", main = -1},
+ {name = "caution"},
+ {name = "danger", main = 0},
+ },
+}
+
+local asps = {}
+for _, v in pairs(type2def.main) do
+ minetest.register_node("advtrains_interlocking:" .. v.name, {
+ advtrains = {
+ supported_aspects = {
+ type = 2,
+ group = "foo",
+ },
+ get_aspect = function() return v.name end,
+ set_aspect = function(pos, _, name)
+ N.swap_node(pos, {name = "advtrains_interlocking:" .. name})
+ end,
+ }
+ })
+ asps[v.name] = {
+ main = v.main,
+ type2group = "foo",
+ type2name = v.name,
+ }
+end
+
+local origin = vector.new(0, 0, 0)
+local dstpos = vector.new(0, 0, 1)
+
+world.layout {
+ {origin, "advtrains_interlocking:danger"},
+ {dstpos, "advtrains_interlocking:proceed"},
+}
+
+describe("type 2 signal group registration", function()
+ it("should work", function()
+ A.register_type2(type2def)
+ assert(A.get_type2_definition("foo"))
+ end)
+ it("should only be allowed once for the same group", function()
+ assert.has.errors(function() A.register_type2(type2def) end)
+ end)
+ it("should handle nonexistant groups", function()
+ assert.is_nil(A.get_type2_definition("something_else"))
+ end)
+end)
+
+describe("signal aspect conversion", function()
+ it("should work for converting from type 1 to type 2", function()
+ assert.equal("danger", A.type1_to_type2main({main = 0}, "foo"))
+ assert.equal("caution", A.type1_to_type2main({main = 6}, "foo"))
+ assert.equal("proceed", A.type1_to_type2main({}, "foo"))
+ end)
+ -- Type 2 -> type 1 conversion is tested with signal aspect accessors
+end)
+
+describe("type 2 signals", function()
+ it("should support distant signaling", function()
+ assert.equal("caution", A.get_type2_dst("foo", 3))
+ assert.equal("proceed", A.get_type2_dst("foo", "caution"))
+ assert.equal("proceed", A.get_type2_dst("foo", "proceed"))
+ end)
+ it("should work with accessors", function()
+ assert.same(asps.danger, I.signal_get_aspect(origin))
+ local newasp = {type2group = "foo", type2name = "proceed", main = 6}
+ I.signal_set_aspect(origin, newasp)
+ assert.same(newasp, I.signal_get_aspect(origin))
+ end)
+ it("should work with distant signaling", function()
+ assert.same(asps.proceed, I.signal_get_aspect(dstpos))
+ local dstasp = {type2group = "foo", type2name = "proceed", dst = 6, main = -1}
+ D.assign(origin, dstpos)
+ assert.same(dstasp, I.signal_get_aspect(dstpos))
+ end)
+end)