107 lines
5.8 KiB
Python
107 lines
5.8 KiB
Python
"""Meaningful regression checks for the matcher. Run with the same Python as the matcher."""
|
|
import importlib.util
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
import sys
|
|
from pathlib import Path
|
|
from PIL import Image
|
|
|
|
HERE=Path(__file__).resolve().parent
|
|
sys.dont_write_bytecode=True
|
|
spec=importlib.util.spec_from_file_location('matcher',HERE/'Match-KnoxViewpoint.py')
|
|
matcher=importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(matcher)
|
|
|
|
class MatchingTests(unittest.TestCase):
|
|
def test_white_crate_is_not_vanilla_military_sign(self):
|
|
target='kbw_location_military_generic_01_16'
|
|
bindings={'location_military_generic_01_16':{}}
|
|
props={target:{'CustomName':'Crate','container':'militarycrate'},
|
|
'location_military_generic_01_16':{'CustomName':'Sign'}}
|
|
self.assertIsNone(matcher.alias_matches(target,bindings,props))
|
|
|
|
def test_real_crate_alias_matches(self):
|
|
target='kbw_location_military_generic_01_0'
|
|
props={target:{'CustomName':'Crate','container':'militarycrate'},
|
|
target[4:]:{'CustomName':'Crate','container':'militarycrate'}}
|
|
self.assertEqual(matcher.alias_matches(target,{target[4:]:{}},props),target[4:])
|
|
|
|
def test_properties_only_tile_has_no_geometry(self):
|
|
text='''/* fixtures_test_0 */ tile { xy=0x0, properties { Translucent=true, } }
|
|
/* fixtures_test_1 */ tile { xy=1x0, cylinder { min=0x0x0, max=1x1x1, } }'''
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
path=Path(temp)/'tileGeometry.txt';path.write_text(text)
|
|
result=matcher.geometry(path)
|
|
self.assertNotIn('fixtures_test_0',result)
|
|
self.assertIn('fixtures_test_1',result)
|
|
|
|
def test_variant_ids_are_not_sprites(self):
|
|
value={'id':'tile_02','geometry':{'rows':[['walls_interior_house_01_2']]},'requirements':{'id':'tool_03'}}
|
|
self.assertEqual(list(matcher.sprite_strings(value)),['walls_interior_house_01_2'])
|
|
|
|
def test_real_sprite_names_can_have_capitals_and_hyphens(self):
|
|
self.assertTrue(matcher.SPRITE.fullmatch('location_shop_bargNclothes_01_24'))
|
|
self.assertTrue(matcher.SPRITE.fullmatch('signs_one-off_08_269'))
|
|
|
|
def test_native_floor_does_not_need_authored_model(self):
|
|
result=matcher.native_route('floors_test_0',{'floors_test_0':{'solidfloor':''}}, {})
|
|
self.assertEqual(result[0],'native-floor')
|
|
|
|
def test_native_roof_is_candidate_not_visual_confirmation(self):
|
|
self.assertEqual(matcher.native_route('roofs_01_0',{}, {})[0],'native-roof-candidate')
|
|
|
|
def test_suggestions_never_change_assignments(self):
|
|
bindings={'fixtures_test_1':{}}
|
|
props={'fixtures_test_0':{'CustomName':'Shelf'},'fixtures_test_1':{'CustomName':'Shelf'}}
|
|
result=matcher.candidates('fixtures_test_0',bindings,props,{})
|
|
self.assertEqual(result[0]['source'],'fixtures_test_1')
|
|
self.assertEqual(bindings,{'fixtures_test_1':{}})
|
|
|
|
def test_registered_manifest_order_and_source_paths(self):
|
|
workshop=Path('D:/SteamLibrary/steamapps/workshop/content/108600')
|
|
if not workshop.exists(): self.skipTest('Installed Workshop files not present')
|
|
root,bindings=matcher.load_bindings(workshop)
|
|
self.assertEqual(bindings['location_military_generic_01_1']['manifest'],'package-12.properties')
|
|
self.assertTrue((root/bindings['location_military_generic_01_1']['path']).is_file())
|
|
|
|
def test_white_adaptation_preserves_mesh_and_alpha_and_source(self):
|
|
with tempfile.TemporaryDirectory() as temp:
|
|
root=Path(temp)/'source';root.mkdir()
|
|
obj=root/'model.obj';obj.write_text('mtllib model.mtl\nv 0 0 0\n')
|
|
(root/'model.mtl').write_text('newmtl atlas\nmap_Kd texture.png\n')
|
|
image=Image.new('RGBA',(2,1));image.putdata([(20,40,60,255),(80,90,100,0)]);image.save(root/'texture.png')
|
|
before=(root/'texture.png').read_bytes()
|
|
media=Path(temp)/'patch/media'
|
|
relative,tag=matcher.copy_asset(root,{'path':'model.obj'},media,white=True)
|
|
self.assertEqual((media/relative).read_bytes(),obj.read_bytes())
|
|
after=Image.open((media/relative).parent/'texture.png').convert('RGBA')
|
|
self.assertEqual(after.getchannel('A').tobytes(),bytes([255,0]))
|
|
r,g,b,a=after.getpixel((0,0));self.assertEqual(r,g);self.assertEqual(g,b);self.assertGreater(r,100)
|
|
self.assertEqual((root/'texture.png').read_bytes(),before)
|
|
|
|
def test_manual_white_sources_are_crates_not_signs(self):
|
|
reviews=json.loads((HERE/'reviewed-matches.json').read_text())
|
|
self.assertEqual(reviews['matches']['kbw_location_military_generic_01_16']['source'],'location_military_generic_01_8')
|
|
self.assertEqual(reviews['matches']['kbw_location_military_generic_01_17']['source'],'location_military_generic_01_9')
|
|
|
|
def test_gray_variants_use_green_meshes_and_requested_tint(self):
|
|
reviews=json.loads((HERE/'reviewed-matches.json').read_text())
|
|
rules={**reviews['matches'],**reviews['extraSprites']}
|
|
for target,source in zip((8,9,10,11,12,13),(0,1,2,3,4,5)):
|
|
rule=rules[f'kbw_location_military_generic_01_{target}']
|
|
self.assertEqual(rule['source'],f'location_military_generic_01_{source}')
|
|
self.assertEqual(rule['tint'],'#626763')
|
|
|
|
def test_gray_tint_exact_base_shading_and_alpha(self):
|
|
original=Image.new('RGBA',(4,1))
|
|
original.putdata([(85,97,74,255),(85,97,74,255),(42,48,37,255),(85,97,74,0)])
|
|
tinted=matcher.tint_texture(original,'#626763')
|
|
self.assertEqual(tinted.getpixel((0,0)),(98,103,99,255))
|
|
self.assertLess(tinted.getpixel((2,0))[0],98)
|
|
self.assertEqual(tinted.getchannel('A').tobytes(),original.getchannel('A').tobytes())
|
|
self.assertEqual(original.getpixel((0,0)),(85,97,74,255))
|
|
|
|
if __name__=='__main__':
|
|
unittest.main(verbosity=2)
|