# 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')