"""Tests for the output parsing module."""
from src.parsing import BBox, ParseResult, parse_boxes, parse_points
class TestBBox:
def test_valid_box_within_bounds(self):
box = BBox(x1=10, y1=20, x2=100, y2=200)
assert box.is_valid(640, 480)
assert box.width == 90
assert box.height == 180
assert box.area == 16200
def test_box_center(self):
box = BBox(x1=0, y1=0, x2=100, y2=100)
assert box.center == (50.0, 50.0)
def test_invalid_box_zero_area(self):
box = BBox(x1=50, y1=50, x2=50, y2=50)
assert not box.is_valid(640, 480)
def test_invalid_box_out_of_bounds(self):
box = BBox(x1=-10, y1=0, x2=100, y2=100)
assert not box.is_valid(640, 480)
def test_clamp(self):
box = BBox(x1=-10, y1=-5, x2=700, y2=500)
clamped = box.clamp(640, 480)
assert clamped.x1 == 0
assert clamped.y1 == 0
assert clamped.x2 == 640
assert clamped.y2 == 480
def test_to_dict(self):
box = BBox(x1=10, y1=20, x2=100, y2=200, confidence=0.9, label="test")
d = box.to_dict()
assert d["x1"] == 10
assert d["label"] == "test"
assert d["confidence"] == 0.9
class TestParseBoxes:
def test_single_box(self):
raw = "<100><200><300><400>"
result = parse_boxes(raw, 1000, 1000)
assert result.num_detections == 1
assert result.boxes[0].x1 == 100.0
assert result.boxes[0].y1 == 200.0
assert result.boxes[0].x2 == 300.0
assert result.boxes[0].y2 == 400.0
def test_multiple_boxes(self):
raw = "<100><100><200><200> some text <500><500><600><600>"
result = parse_boxes(raw, 1000, 1000)
assert result.num_detections == 2
def test_duplicate_boxes_deduplicated(self):
raw = "<100><100><200><200> <100><100><200><200>"
result = parse_boxes(raw, 1000, 1000)
assert result.num_detections == 1
def test_no_boxes(self):
raw = "No objects detected in this image."
result = parse_boxes(raw, 1000, 1000)
assert result.num_detections == 0
def test_coordinate_scaling(self):
raw = "<500><500><1000><1000>"
result = parse_boxes(raw, 640, 480)
assert result.num_detections == 1
assert abs(result.boxes[0].x2 - 640.0) < 0.1
assert abs(result.boxes[0].y2 - 480.0) < 0.1
def test_out_of_bounds_box_discarded(self):
raw = "<999><999><1001><1001>"
result = parse_boxes(raw, 100, 100)
assert result.num_detections == 0
assert len(result.parse_errors) > 0
def test_alt_format(self):
raw = "100, 200, 300, 400"
result = parse_boxes(raw, 1000, 1000)
assert result.num_detections == 1
class TestParsePoints:
def test_single_point(self):
raw = "<500><500>"
points = parse_points(raw, 1000, 1000)
assert len(points) == 1
assert points[0]["x"] == 500.0
assert points[0]["y"] == 500.0
def test_no_points(self):
raw = "nothing here"
points = parse_points(raw, 1000, 1000)
assert len(points) == 0
class TestParseResult:
def test_empty_result(self):
r = ParseResult()
assert r.num_detections == 0
d = r.to_dict()
assert d["num_detections"] == 0
def test_result_with_boxes(self):
r = ParseResult(
boxes=[BBox(10, 20, 100, 200)],
raw_output="<10><20><100><200>",
)
assert r.num_detections == 1
d = r.to_dict()
assert len(d["boxes"]) == 1