Venket / tests /test_placement_engine.py
venki101's picture
Add files using upload-large-folder tool
1a12965 verified
Raw History Blame Contribute Delete
3.95 kB
"""Unit tests for src.placement.placement_engine."""
from __future__ import annotations
import numpy as np
from src.config.schema import PlacementConfig
from src.placement.placement_engine import MIN_SIGNATURE_HEIGHT_PX, PlacementEngine
from src.utils.random_utils import SeedManager
def _synthetic_signature(w: int = 300, h: int = 150) -> np.ndarray:
"""A simple synthetic RGBA "signature": a diagonal opaque stroke on transparency."""
rgba = np.zeros((h, w, 4), dtype=np.uint8)
for x in range(w):
y = int((x / w) * (h - 1))
rgba[max(y - 3, 0):y + 3, x, :3] = (20, 20, 25)
rgba[max(y - 3, 0):y + 3, x, 3] = 255
return rgba
def test_placement_is_deterministic_for_same_seed():
cfg = PlacementConfig(rotation_deg={"min": -5, "max": 5}, scale_factor={"min": 0.7, "max": 1.0})
engine = PlacementEngine(cfg)
sig = _synthetic_signature()
r1 = engine.place(sig, target_box=(100, 100, 300, 200), canvas_size=(800, 600), seed_manager=SeedManager(1, 5))
r2 = engine.place(sig, target_box=(100, 100, 300, 200), canvas_size=(800, 600), seed_manager=SeedManager(1, 5))
assert r1.rotation_deg == r2.rotation_deg
assert r1.scale_factor == r2.scale_factor
assert r1.intended_bbox == r2.intended_bbox
assert np.array_equal(r1.layer, r2.layer)
def test_placement_differs_for_different_sample_index():
cfg = PlacementConfig(rotation_deg={"min": -5, "max": 5}, scale_factor={"min": 0.7, "max": 1.0})
engine = PlacementEngine(cfg)
sig = _synthetic_signature()
r1 = engine.place(sig, target_box=(100, 100, 300, 200), canvas_size=(800, 600), seed_manager=SeedManager(1, 1))
r2 = engine.place(sig, target_box=(100, 100, 300, 200), canvas_size=(800, 600), seed_manager=SeedManager(1, 2))
assert r1.rotation_deg != r2.rotation_deg or r1.scale_factor != r2.scale_factor
def test_placement_respects_aspect_ratio_when_not_rotated():
cfg = PlacementConfig(rotation_deg=0.0, scale_factor=0.5, margin=0.0)
engine = PlacementEngine(cfg)
sig = _synthetic_signature(w=300, h=150) # aspect ratio 2:1
result = engine.place(sig, target_box=(0, 0, 400, 400), canvas_size=(800, 800), seed_manager=SeedManager(1, 1))
x1, y1, x2, y2 = result.intended_bbox
placed_w, placed_h = x2 - x1, y2 - y1
assert abs((placed_w / placed_h) - 2.0) < 0.05
def test_placement_output_layer_matches_canvas_size():
cfg = PlacementConfig()
engine = PlacementEngine(cfg)
sig = _synthetic_signature()
result = engine.place(sig, target_box=(10, 10, 200, 100), canvas_size=(640, 480), seed_manager=SeedManager(2, 0))
assert result.layer.shape == (480, 640, 4)
def test_tiny_box_still_produces_a_legible_minimum_height_signature():
cfg = PlacementConfig(rotation_deg=0.0, scale_factor=1.0, margin=0.05)
engine = PlacementEngine(cfg)
sig = _synthetic_signature(w=300, h=150)
# A box far shorter than the natural signature height.
result = engine.place(sig, target_box=(0, 0, 300, 6), canvas_size=(800, 800), seed_manager=SeedManager(1, 1))
x1, y1, x2, y2 = result.intended_bbox
assert (y2 - y1) >= MIN_SIGNATURE_HEIGHT_PX - 1 # allow rounding
def test_misplacement_never_triggers_when_probability_zero():
cfg = PlacementConfig(misplacement_probability=0.0)
engine = PlacementEngine(cfg)
sig = _synthetic_signature()
for i in range(20):
result = engine.place(sig, target_box=(50, 50, 250, 150), canvas_size=(800, 600), seed_manager=SeedManager(1, i))
assert result.misplaced is False
def test_misplacement_always_triggers_when_probability_one():
cfg = PlacementConfig(misplacement_probability=1.0, misplacement_strength=0.5)
engine = PlacementEngine(cfg)
sig = _synthetic_signature()
for i in range(10):
result = engine.place(sig, target_box=(50, 50, 250, 150), canvas_size=(800, 600), seed_manager=SeedManager(1, i))
assert result.misplaced is True