This commit is contained in:
nq
2026-10-14 11:16:43 +00:00
parent ac550e327d
commit dfaa54ed8e
119 changed files with 8860 additions and 0 deletions
+88
View File
@@ -0,0 +1,88 @@
"""Synthetic native IMG regression tests; does not assert real Garmin compatibility."""
import sqlite3
import struct
import subprocess
import sys
import tempfile
from pathlib import Path
from make_fixture import gen,coord,u24
binary=Path(sys.argv[1]); work=Path(tempfile.mkdtemp(prefix='garmin2osmand-'))
try:
classic=work/'classic.img';gen(classic)
gmp=work/'gmp.img'
original=classic.read_bytes()
b=bytearray(len(original))
b[0:0x600]=original[:0x600]
# Garmin FAT record for one GMP file, backed by four 512-byte blocks.
b[0x600]=1;b[0x601:0x609]=b'TESTMAP '
b[0x609:0x60c]=b'GMP'
struct.pack_into('<IH',b,0x60c,2048,0)
for k in range(4):struct.pack_into('<H',b,0x620+2*k,8+k)
struct.pack_into('<H',b,0x628,0xffff)
g=bytearray(2048)
struct.pack_into('<H',g,0,0x35);g[2:12]=b'GARMIN GMP'
struct.pack_into('<II',g,0x19,0x100,0x400)
tre=bytearray(original[8*512:9*512]);rgn=bytearray(original[9*512:10*512])
struct.pack_into('<II',tre,0x21,0x1c0,4)
struct.pack_into('<II',tre,0x29,0x1c4,14)
struct.pack_into('<II',rgn,0x15,0x47d,struct.unpack_from('<I',rgn,0x19)[0])
g[0x100:0x100+0xd2]=tre[:0xd2]
g[0x400:0x400+0x8b]=rgn[:0x8b]
# RGN1 data has to live at its new absolute GMP offset.
g[0x47d:0x47d+20]=rgn[0x7d:0x7d+20]
b[8*512:12*512]=g
gmp.write_bytes(b)
for kind,img in [('classic',classic),('gmp',gmp)]:
info=subprocess.run([binary,'--input',img,'--info'],capture_output=True,text=True)
assert info.returncode==0,(kind,info.stderr)
out=work/f'{kind}.sqlitedb'
cmd=[binary,'--input',img,'--output',out,'--bbox','24.5,41.85,25.05,42.35','--min-zoom','12','--max-zoom','12']
p=subprocess.run(cmd,capture_output=True,text=True)
assert p.returncode==0,(kind,p.stdout,p.stderr)
db=sqlite3.connect(out)
count=db.execute('select count(*) from tiles').fetchone()[0]
assert count>0,kind
assert db.execute('pragma integrity_check').fetchone()[0]=='ok'
assert db.execute('select hex(substr(image,1,8)) from tiles limit 1').fetchone()[0]=='89504E470D0A1A0A'
assert db.execute('select tilenumbering from info').fetchone()[0]=='simple'
db.close()
resumed=subprocess.run(cmd+['--resume'],capture_output=True,text=True)
assert resumed.returncode==0,(kind,resumed.stderr)
capped=subprocess.run(cmd[:-0]+['--max-tiles','1'] if False else
[binary,'--input',img,'--output',work/f'{kind}-cap.sqlitedb','--max-tiles','1'],capture_output=True,text=True)
assert capped.returncode!=0 and not (work/f'{kind}-cap.sqlitedb').exists()
# Plan mode must not create a DB, and --whole-map bypasses 100k budget automatically.
plan=subprocess.run([binary,'--input',img,'--whole-map','--min-zoom','12','--max-zoom','12','--plan'],capture_output=True,text=True)
assert plan.returncode==0,(kind,plan.stdout,plan.stderr)
assert 'Tile candidates:' in plan.stdout
whole=work/f'{kind}-whole.sqlitedb'
full_cmd=[binary,'--input',img,'--output',whole,'--whole-map','--min-zoom','12','--max-zoom','12']
p=subprocess.run(full_cmd,capture_output=True,text=True)
assert p.returncode==0,(kind,p.stdout,p.stderr)
with sqlite3.connect(whole) as db:
assert db.execute('pragma integrity_check').fetchone()[0]=='ok'
assert db.execute('select count(*) from tiles').fetchone()[0]>0
assert db.execute('select count(*) from progress').fetchone()[0]>0
assert db.execute('select count(*) from converter_settings').fetchone()[0]==1
original=db.execute('select count(*) from tiles').fetchone()[0]
resumed=subprocess.run(full_cmd+['--resume'],capture_output=True,text=True)
assert resumed.returncode==0 and 'candidate tiles visited=0' in resumed.stdout,(kind,resumed.stdout,resumed.stderr)
with sqlite3.connect(whole) as db:
assert db.execute('select count(*) from tiles').fetchone()[0]==original
changed=subprocess.run(full_cmd+['--resume','--aa','1'],capture_output=True,text=True)
assert changed.returncode!=0 and 'Resume settings do not match' in changed.stderr
# Force a small byte budget to exercise persistent scanline checkpoints.
limited=work/f'{kind}-limited.sqlitedb'
lim_cmd=[binary,'--input',img,'--output',limited,'--whole-map','--min-zoom','12','--max-zoom','12']
failrun=subprocess.run(lim_cmd+['--max-bytes','1'],capture_output=True,text=True)
assert failrun.returncode!=0 and limited.is_file()
recovery=subprocess.run(lim_cmd+['--max-bytes','100000000','--resume'],capture_output=True,text=True)
assert recovery.returncode==0,(kind,recovery.stdout,recovery.stderr)
with sqlite3.connect(limited) as db:
assert db.execute('pragma integrity_check').fetchone()[0]=='ok'
assert db.execute('select count(*) from tiles').fetchone()[0]==original
print(kind, 'PASSED tiles',count,'plus whole-map, checkpoint, restart and settings validation')
finally:
import shutil
shutil.rmtree(work)