aboutsummaryrefslogtreecommitdiff
path: root/advtrains/spec/atcjit_spec.lua
blob: 62896e4fd87e90f5f8dd371d16846db0af0b4054 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package.path  =  "../?.lua;" .. package.path
advtrains = {}
minetest = {}
_G.advtrains = advtrains
_G.minetest = minetest
function _G.attrans(...) return ... end
function advtrains.invert_train() end
function advtrains.train_ensure_init() end

local on_mods_loaded = function() end
function minetest.register_on_mods_loaded(f)
	on_mods_loaded = f
end

local atcjit = require("atcjit")

local function assert_atc(train, warn, err, res)
	local w, e = atcjit.execute(train.id,train)
	assert.same(err, e)
	if w then assert.same(warn, w) end
	assert.same(res, train)
end

local function thisatc(desc, train, warn, err, res)
	it(desc, function() assert_atc(train, warn, err, res) end)
end

describe("simple ATC track", function()
	local t = {
		atc_arrow = true,
		atc_command = " B12WB8WBBWOLD15ORD15OCD1RS10WSM",
		door_open = 0,
		max_speed = 20,
		tarvelocity = 10,
		velocity = 0,
	}
	thisatc("should make the train slow down to 12", t, {}, nil,{
		atc_arrow = true,
		atc_brake_target = 12,
		atc_command = "B8WBBWOLD15ORD15OCD1RS10WSM",
		atc_wait_finish = true,
		door_open = 0,
		max_speed = 20,
		tarvelocity = 10,
		velocity = 0,
	})
	thisatc("should make the train brake to 8", t, {}, nil, {
		atc_arrow = true,
		atc_brake_target = 8,
		atc_command  = "BBWOLD15ORD15OCD1RS10WSM",
		atc_wait_finish = true,
		door_open = 0,
		max_speed = 20,
		tarvelocity = 8,
		velocity = 0,
	})
	thisatc("should make the train stop", t, {}, nil, {
		atc_arrow = true,
		atc_brake_target = -1,
		atc_command = "OLD15ORD15OCD1RS10WSM",
		atc_wait_finish = true,
		door_open = 0,
		max_speed = 20,
		tarvelocity = 0,
		velocity = 0,
	})
	thisatc("should make the train open its left doors", t, {}, nil, {
		atc_arrow = true,
		atc_brake_target = -1,
		atc_command = "ORD15OCD1RS10WSM",
		atc_delay = 15,
		atc_wait_finish = true,
		door_open = -1,
		max_speed = 20,
		tarvelocity = 0,
		velocity = 0,
	})
	thisatc("should make the train open its right doors", t, {}, nil,{
		atc_arrow = true,
		atc_brake_target = -1,
		atc_command = "OCD1RS10WSM",
		atc_delay = 15,
		atc_wait_finish = true,
		door_open = 1,
		max_speed = 20,
		tarvelocity = 0,
		velocity = 0,
	})
	thisatc("should make the train close its doors", t, {}, nil, {
		atc_arrow = true,
		atc_brake_target = -1,
		atc_command = "RS10WSM",
		atc_delay = 1,
		atc_wait_finish = true,
		door_open = 0,
		max_speed = 20,
		tarvelocity = 0,
		velocity = 0,
	})
	thisatc("should make the train depart and accelerate to 10", t, {}, nil, {
		atc_arrow = true,
		atc_brake_target = -1,
		atc_command = "SM",
		atc_delay = 1,
		atc_wait_finish = true,
		door_open = 0,
		max_speed = 20,
		tarvelocity = 10,
		velocity = 0,
	})
	thisatc("should make the train accelerate to 20", t, {}, nil, {
		atc_arrow = true,
		atc_brake_target = -1,
		atc_delay = 1,
		atc_wait_finish = true,
		door_open = 0,
		max_speed = 20,
		tarvelocity = 20,
		velocity = 0,
	})
end)

describe("ATC track with whitespaces", function()
	local t = {
		atc_command = " \t\n OC \n S20 \r "
	}
	thisatc("should not cause errors", t, {}, nil, {
		door_open = 0,
		tarvelocity = 20,
	})
end)

describe("empty ATC track", function()
	local t = {atc_command = ""}
	thisatc("should not do anything", t, {}, nil, {})
end)

describe("ATC track with nested I statements", function()
	local t = {
		atc_arrow = false,
		atc_command = "I+OREI>5I<=10S16WORES12;D15;;OC",
		velocity = 10,
		door_open = 0,
	}
	thisatc("should make the train accelerate to 16", t, {}, nil,{
		atc_arrow = false,
		atc_command = "ORD15OC",
		atc_wait_finish = true,
		velocity = 10,
		door_open = 0,
		tarvelocity = 16,
	})
end)

describe("ATC track with invalid statement", function()
	local t = { atc_command = "Ifoo" }
	thisatc("should report an error", t, {}, "Invalid command or malformed I statement: Ifoo", t)
end)

describe("ATC track with invalid I condition", function()
	local t = { atc_command = "I?;" }
	thisatc("should report an error", t, {}, "Invalid I statement", t)
end)

describe("ATC track reusing existing code", function()
	local t = { atc_command = " B12WB8WBBWOLD15ORD15OCD1RS10WSM", tarvelocity = 15 }
	thisatc("should do the same thing as in the first test", t, {}, nil, {
		atc_brake_target = 12,
		atc_command = "B8WBBWOLD15ORD15OCD1RS10WSM",
		atc_wait_finish = true,
		tarvelocity = 12
	})
end)

describe("ATC track reusing malformed code", function()
	local t = {atc_command = "I?;"}
	thisatc("should report the invalid I statement", t, {}, "Invalid I statement", t)
end)

describe("ATC track that sets ARS modes", function()
	local t = {atc_command = "A0WA1WAFWAT"}
	thisatc("should disable ARS on the train with A0", t, {}, nil, {atc_wait_finish=true, ars_disable=true,  atc_command="A1WAFWAT"})
	thisatc("should enable ARS on the train with A1",  t, {}, nil, {atc_wait_finish=true, ars_disable=false, atc_command="AFWAT"})
	thisatc("should disable ARS on the train with AF", t, {}, nil, {atc_wait_finish=true, ars_disable=true,  atc_command="AT"})
	thisatc("should enable ARS on the train with AT",  t, {}, nil, {atc_wait_finish=true, ars_disable=false,})
end)

insulate("ATC scheduling commands without line automation", function()
	_G.os.time = function() return 12 end
	local t = {atc_command = "Ds+5Ds20+10W"}
	thisatc("should do the same as D5", t, {}, nil, {atc_delay=5, atc_command="Ds20+10W"})
	thisatc("should do the same as D15", t, {}, nil, {atc_delay=18, atc_command="W"})
end)

insulate("ATC scheduling commands with line automation", function()
	advtrains.lines = {
		rwt = mock{
			now = function() return 12 end,
			next_rpt = function(n, i, o) return n+i-(n-o)%i end,
		},
		sched = mock{
			enqueue = function() end,
			enqueue_in = function() end,
			register_callback = function() end,
		},
	}
	local rwt, sched = advtrains.lines.rwt, advtrains.lines.sched
	on_mods_loaded()
	it("should have line automation modules loaded", function() assert.stub(sched.register_callback).was.called() end)
	it("should schedule the train in 0;05", function()
		assert_atc({id="foo", atc_command="Ds+5W", atc_arrow = true}, {}, nil, {id="foo", atc_arrow=true})
		assert.stub(sched.enqueue_in).was.called_with(5, "atcjit", {trainid="foo", cmd="W", arrow=true}, "atcjit-foo", 1)
	end)
	it("should schedule the train at 0;25", function()
		assert_atc({id="bar", atc_command="Ds20+5W", atc_arrow = true}, {}, nil, {id="bar", atc_arrow=true})
		assert.stub(sched.enqueue).was.called_with(25, "atcjit", {trainid="bar", cmd="W", arrow=true}, "atcjit-bar", 1)
	end)
end)