Files
ai-game-2/tools/ora_editor/test_ora_ops.py
Bryce 319c2565c6 Add ora_ops module for ORA file operations
- Implements core ORA reading/writing functions
- Layer add, rename, delete, reorder, visibility operations
- Full test suite with 8 passing tests
2026-03-27 08:46:49 -07:00

357 lines
11 KiB
Python

#!/usr/bin/env python3
"""Tests for ora_ops module."""
import io
import os
import sys
import tempfile
import zipfile
from pathlib import Path
from PIL import Image
# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))
from ora_editor.ora_ops import (
load_ora, create_ora_from_png, add_masked_layer, rename_layer,
delete_layer, reorder_layer, get_layer_visibility, set_layer_visibility,
save_ora, parse_stack_xml, get_image_size, get_groups_and_layers
)
def test_create_ora_from_png():
"""Test creating an ORA from a PNG file."""
# Create a simple test PNG
test_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
test_img.save(png_f.name)
png_path = png_f.name
with tempfile.NamedTemporaryFile(suffix='.ora', delete=False) as ora_f:
ora_path = ora_f.name
try:
result = create_ora_from_png(png_path, ora_path)
assert result['success'], f"Failed to create ORA: {result.get('error')}"
assert os.path.exists(ora_path), "ORA file was not created"
# Verify we can load it back
loaded = load_ora(ora_path)
assert 'layers' in loaded, "Loaded ORA has no layers"
assert len(loaded['layers']) == 1, f"Expected 1 layer, got {len(loaded['layers'])}"
print("✓ create_ora_from_png passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
def test_load_ora():
"""Test loading an existing ORA file."""
with tempfile.NamedTemporaryFile(suffix='.ora', delete=False) as ora_f:
ora_path = ora_f.name
try:
# Create a test PNG first
test_img = Image.new('RGBA', (200, 150), (0, 255, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
test_img.save(png_f.name)
png_path = png_f.name
try:
create_ora_from_png(png_path, ora_path)
loaded = load_ora(ora_path)
assert loaded['width'] == 200, f"Expected width 200, got {loaded['width']}"
assert loaded['height'] == 150, f"Expected height 150, got {loaded['height']}"
assert len(loaded['layers']) > 0, "No layers found in ORA"
print("✓ load_ora passed")
return True
finally:
os.unlink(png_path)
finally:
if os.path.exists(ora_path):
os.unlink(ora_path)
def test_add_masked_layer():
"""Test adding a masked layer to an ORA."""
# Create base PNG
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
base_img.save(png_f.name)
png_path = png_f.name
ora_path = png_path.replace('.png', '.ora')
# Create mask (white where visible, black where transparent)
mask_img = Image.new('L', (100, 100), 255)
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
mask_img.save(mask_f.name)
mask_path = mask_f.name
try:
result = add_masked_layer(ora_path, 'door', mask_path)
assert result['success'], f"Failed to add masked layer: {result.get('error')}"
assert 'layer_name' in result, "No layer_name in result"
assert result['layer_name'] == 'door_0', f"Expected door_0, got {result['layer_name']}"
# Verify the layer was added
loaded = load_ora(ora_path)
layer_names = [l['name'] for l in loaded['layers']]
assert 'base' in layer_names, "Base layer missing"
assert 'door_0' in layer_names, "Door layer not found"
print("✓ add_masked_layer passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
os.unlink(mask_path)
def test_rename_layer():
"""Test renaming a layer."""
# Create base PNG
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
base_img.save(png_f.name)
png_path = png_f.name
ora_path = png_path.replace('.png', '.ora')
# Create mask for a new layer
mask_img = Image.new('L', (100, 100), 255)
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
mask_img.save(mask_f.name)
mask_path = mask_f.name
try:
# First add a layer to rename
result = add_masked_layer(ora_path, 'door', mask_path)
assert result['success']
# Now rename it
result = rename_layer(ora_path, 'door_0', 'wooden_door_0')
assert result['success'], f"Failed to rename: {result.get('error')}"
loaded = load_ora(ora_path)
layer_names = [l['name'] for l in loaded['layers']]
assert 'wooden_door_0' in layer_names, "Renamed layer not found"
assert 'door_0' not in layer_names, "Old layer name still exists"
print("✓ rename_layer passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
os.unlink(mask_path)
def test_delete_layer():
"""Test deleting a layer."""
# Create base PNG
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
base_img.save(png_f.name)
png_path = png_f.name
ora_path = png_path.replace('.png', '.ora')
# Create mask for a new layer
mask_img = Image.new('L', (100, 100), 255)
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
mask_img.save(mask_f.name)
mask_path = mask_f.name
try:
# First add a layer to delete
result = add_masked_layer(ora_path, 'door', mask_path)
assert result['success']
# Now delete it
result = delete_layer(ora_path, 'door_0')
assert result['success'], f"Failed to delete: {result.get('error')}"
loaded = load_ora(ora_path)
layer_names = [l['name'] for l in loaded['layers']]
assert 'door_0' not in layer_names, "Deleted layer still exists"
print("✓ delete_layer passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
os.unlink(mask_path)
def test_reorder_layer():
"""Test reordering layers."""
# Create base PNG
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
base_img.save(png_f.name)
png_path = png_f.name
ora_path = png_path.replace('.png', '.ora')
# Create mask for new layers
mask_img = Image.new('L', (100, 100), 255)
layer_paths = []
for i in range(3):
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
mask_img.save(mask_f.name)
layer_paths.append(mask_f.name)
try:
# Add multiple layers
for i, mask_path in enumerate(layer_paths):
result = add_masked_layer(ora_path, f'layer{i}', mask_path)
assert result['success'], f"Failed to add layer {i}"
# Get initial order
loaded = load_ora(ora_path)
initial_order = [l['name'] for l in loaded['layers']]
# Move layer0_0 down (it should stay or move one position)
result = reorder_layer(ora_path, 'layer0_0', 'down')
assert result['success'], f"Failed to reorder: {result.get('error')}"
loaded = load_ora(ora_path)
new_order = [l['name'] for l in loaded['layers']]
# Verify order changed or stayed valid
assert len(new_order) == len(initial_order), "Layer count changed during reorder"
print("✓ reorder_layer passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
for path in layer_paths:
os.unlink(path)
def test_set_layer_visibility():
"""Test setting layer visibility."""
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
base_img.save(png_f.name)
png_path = png_f.name
ora_path = png_path.replace('.png', '.ora')
mask_img = Image.new('L', (100, 100), 255)
with tempfile.NamedTemporaryFile(suffix='.mask.png', delete=False) as mask_f:
mask_img.save(mask_f.name)
mask_path = mask_f.name
try:
add_masked_layer(ora_path, 'door', mask_path)
# Set visibility to false
result = set_layer_visibility(ora_path, 'door_0', False)
assert result['success'], f"Failed to set visibility: {result.get('error')}"
visible = get_layer_visibility(ora_path, 'door_0')
assert visible is False, "Layer should be hidden"
# Set visibility back to true
result = set_layer_visibility(ora_path, 'door_0', True)
assert result['success']
visible = get_layer_visibility(ora_path, 'door_0')
assert visible is True, "Layer should be visible"
print("✓ set_layer_visibility passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
os.unlink(mask_path)
def test_save_ora():
"""Test saving an ORA file."""
base_img = Image.new('RGBA', (100, 100), (255, 0, 0, 255))
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as png_f:
base_img.save(png_f.name)
png_path = png_f.name
ora_path = png_path.replace('.png', '.ora')
try:
create_ora_from_png(png_path, ora_path)
# Save should work without errors
result = save_ora(ora_path)
assert result, "Failed to save ORA"
# Verify we can still load it
loaded = load_ora(ora_path)
assert len(loaded['layers']) > 0, "Layers missing after save"
print("✓ save_ora passed")
return True
finally:
os.unlink(png_path)
if os.path.exists(ora_path):
os.unlink(ora_path)
if __name__ == '__main__':
tests = [
test_create_ora_from_png,
test_load_ora,
test_add_masked_layer,
test_rename_layer,
test_delete_layer,
test_reorder_layer,
test_set_layer_visibility,
test_save_ora,
]
passed = 0
failed = 0
for test in tests:
try:
if test():
passed += 1
else:
failed += 1
except Exception as e:
print(f"{test.__name__} failed with exception: {e}")
import traceback
traceback.print_exc()
failed += 1
print(f"\n{passed}/{len(tests)} tests passed")
if failed > 0:
sys.exit(1)