Files

112 lines
4.9 KiB
Python

# coding: utf-8
"""Catalog coverage plus Lua 5.0 menu/permission/warp integration checks.
Usage: python3 test_ring.py SERVER_LIBLUA_DIRECTORY [LIVE_MAP_INDEX] [COMPILED_OBJECT_ROOT]
"""
import importlib.util
import json
import subprocess
import sys
import tempfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location('ring_generate', ROOT / 'generate.py')
generator = importlib.util.module_from_spec(spec)
spec.loader.exec_module(generator)
quest = generator.generate()
assert quest == (ROOT / 'ring_warp.quest').read_text(encoding='utf-8'), 'regenerate quest'
catalog = json.loads((ROOT / 'maps.json').read_text(encoding='utf-8'))
maps = [m for c in catalog['categories'] for m in c['maps']]
byid = {m['id']:m for m in maps}
assert len(maps) == len(byid) == 65
if len(sys.argv) > 2:
live = dict((int(line.split()[0]),line.split()[1]) for line in Path(sys.argv[2]).read_text().splitlines() if line.strip() and not line.lstrip().startswith('#'))
assert {m['id']:m['directory'] for m in maps} == live
for m in maps:
assert m['mode'] in ('direct', 'entrance', 'gm', 'event')
target = byid[m['target'][0]]
for j in range(2):
assert target['base'][j] <= m['target'][j+1] < target['base'][j] + target['size'][j] * 25600, m
assert {m['id'] for m in maps if m['mode']=='entrance'} == {66,71,72,73,208,216,217,351}
assert byid[217]['target'][0] == 104 and byid[208]['target'][0] == 64
assert 'remove_item' not in quest and 'socket' not in quest and 'setqf' not in quest
# Run the actual generated functions/event body under the server's Lua 5.0.
helper = quest.split(' function destinations()',1)[1].split(' when 10031.sig_use begin',1)[0]
body = quest.split(' when 10031.sig_use begin',1)[1].rsplit(' end',1)[0]
script = 'ring_warp = {}\nfunction ring_warp.destinations()' + helper + '\nfunction use_ring()\n' + body + '\nend\n'
if len(sys.argv) > 3:
objects = Path(sys.argv[3])
state = (objects/'state/ring_warp').read_bytes().decode('gbk')
event = (objects/'10031/sig_use/ring_warp.start').read_bytes().decode('gbk')
script = state + '\nfunction use_ring()\n' + event + '\nend\n'
script += '''
local categories = ring_warp.destinations()
local queue = {}
local cursor = 0
local gm = false
local can_warp = true
local warps = {}
pc = {
is_gm = function() return gm end,
can_warp = function() return can_warp end,
warp = function(x,y) table.insert(warps,{x,y}) end,
}
say_title = function(text) end
say = function(text) end
wait = function() end
select_table = function(options)
assert(table.getn(options) <= 8, "menu too tall")
cursor = cursor + 1
local choice = queue[cursor]
assert(choice and choice >= 1 and choice <= table.getn(options), "bad selection")
return choice
end
select = function(...) return select_table(arg) end
local runs = 0
function run(answers, is_gm, allowed)
queue = answers; cursor = 0; gm = is_gm; can_warp = allowed; warps = {}
use_ring()
assert(cursor == table.getn(queue), "unexpected navigation")
runs = runs + 1
end
for category = 1, table.getn(categories) do
local maps = categories[category].maps
for index = 1, table.getn(maps) do
local page = math.floor((index-1)/5)+1
local answer = {}
table.insert(answer, category)
for p = 1,page-1 do table.insert(answer, p==1 and 6 or 7) end
table.insert(answer, math.mod(index-1,5)+1)
local m = maps[index]
local blocked = m.mode == "gm" or m.mode == "event"
if blocked then
local count = math.min(5,table.getn(maps)-(page-1)*5)
local buttons = count + 1
if page > 1 then buttons = buttons + 1 end
if page*5 < table.getn(maps) then buttons = buttons + 1 end
table.insert(answer,buttons); table.insert(answer,7)
else table.insert(answer,1) end
run(answer,false,true)
assert(table.getn(warps) == (blocked and 0 or 1))
if not blocked then assert(warps[1][1]==m.x and warps[1][2]==m.y) end
end
end
run({7},false,true) -- close
run({1,6,2,7,7},false,true) -- next, previous, return list/category, close
run({1,1,1},false,false) -- blocked by active trade etc.
assert(table.getn(warps)==0)
run({6,1,1},true,true) -- GM test-map access
assert(table.getn(warps)==1 and warps[1][1]==categories[6].maps[1].x)
print("PASS: 65 map selections, paging, back/cancel, warp guard and GM access; " .. runs .. " runs")
'''
lua = Path(sys.argv[1])
with tempfile.TemporaryDirectory(prefix='ring-warp-test-') as d:
d = Path(d)
sources = [p for p in sorted((lua/'src').glob('*.c')) if p.name != 'ltests.c']
sources += [lua/'src/lib'/name for name in ('lauxlib.c','lbaselib.c','ltablib.c','lstrlib.c','lmathlib.c')]
command = ['cc','-w','-I'+str(lua/'include'),'-I'+str(lua/'src'),str(ROOT/'tests/lua_runner.c'),*[str(p) for p in sources],'-lm','-o',str(d/'lua')]
subprocess.run(command,check=True)
(d/'test.lua').write_bytes(script.encode('gbk'))
subprocess.run([str(d/'lua'),str(d/'test.lua')],check=True)
print('PASS: catalog matches server index, coordinates in bounds, GBK source safe')