| """Unit tests for pipeline/validation.py.""" |
|
|
| from __future__ import annotations |
|
|
| import base64 |
|
|
| import pytest |
|
|
| from pipeline.validation import InputValidator, ValidationResult |
|
|
|
|
| class TestInputValidator: |
| def test_no_input_rejected(self): |
| v = InputValidator() |
| r = v.validate() |
| assert not r.valid |
| assert "No image input" in r.error |
|
|
| def test_url_valid(self): |
| v = InputValidator() |
| r = v.validate(image_url="https://example.com/image.jpg") |
| assert r.valid |
| assert r.source == "url" |
|
|
| def test_url_invalid_scheme(self): |
| v = InputValidator() |
| r = v.validate(image_url="ftp://example.com/image.jpg") |
| assert not r.valid |
| assert "scheme" in r.error |
|
|
| def test_url_missing_host(self): |
| v = InputValidator() |
| r = v.validate(image_url="https:///image.jpg") |
| assert not r.valid |
| assert "host" in r.error |
|
|
| def test_url_localhost_rejected(self): |
| v = InputValidator() |
| r = v.validate(image_url="http://localhost/image.jpg") |
| assert not r.valid |
| assert "Localhost" in r.error |
|
|
| def test_url_127_rejected(self): |
| v = InputValidator() |
| r = v.validate(image_url="http://127.0.0.1/image.jpg") |
| assert not r.valid |
|
|
| def test_base64_valid(self, sample_image_b64): |
| v = InputValidator() |
| r = v.validate(image_base64=sample_image_b64) |
| assert r.valid |
| assert r.source == "base64" |
| assert r.image_bytes is not None |
| assert r.format == "jpeg" |
|
|
| def test_base64_with_data_uri_prefix(self, sample_image_b64): |
| v = InputValidator() |
| r = v.validate(image_base64="data:image/jpeg;base64," + sample_image_b64) |
| assert r.valid |
|
|
| def test_base64_invalid(self): |
| v = InputValidator() |
| r = v.validate(image_base64="!!!not-base64!!!") |
| assert not r.valid |
|
|
| def test_base64_too_large(self): |
| v = InputValidator(max_bytes=100) |
| |
| big = b"\xff\xd8\xff" + b"x" * 200 |
| b64 = base64.b64encode(big).decode() |
| r = v.validate(image_base64=b64) |
| assert not r.valid |
| assert "exceeds" in r.error |
|
|
| def test_bytes_valid(self, sample_image_bytes): |
| v = InputValidator() |
| r = v.validate(image_bytes=sample_image_bytes) |
| assert r.valid |
| assert r.source == "bytes" |
| assert r.format == "jpeg" |
|
|
| def test_bytes_invalid_magic(self): |
| v = InputValidator() |
| r = v.validate(image_bytes=b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b") |
| assert not r.valid |
| assert "format" in r.error.lower() |
|
|
| def test_bytes_too_small(self): |
| v = InputValidator() |
| r = v.validate(image_bytes=b"\xff\xd8\xff") |
| |
| assert not r.valid |
|
|
| def test_png_format_detected(self): |
| |
| png = b"\x89PNG\r\n\x1a\n" + b"\x00" * 50 |
| v = InputValidator() |
| r = v.validate(image_bytes=png) |
| assert r.valid |
| assert r.format == "png" |
|
|