fieldwitness/tests/test_c2pa_importer.py
Aaron D. Lee 16318daea3
Some checks failed
CI / lint (push) Failing after 12s
CI / typecheck (push) Failing after 12s
Add comprehensive test suite: integration tests + Playwright e2e
Integration tests (350 passing):
- test_evidence_summary.py: HTML/PDF generation, XSS safety, anchor rendering
- test_tor.py: Tor module unit tests (mocked, no Tor needed)
- test_c2pa_importer.py: Import result dataclass, trust evaluation, graceful degradation
- test_file_attestation.py: All file types (PNG, PDF, CSV, empty, large), determinism
- test_paths.py: Registry correctness, env var override, all paths under BASE_DIR
- test_killswitch_coverage.py: Tor keys, trusted keys, carrier history destruction

Playwright e2e infrastructure:
- tests/e2e/ with conftest (live server, auth fixtures), helpers (test file generators)
- test_auth.py: Setup flow, login/logout, protected routes
- test_attest.py: Image/PDF/CSV attestation, verify, attestation log
- test_dropbox.py: Token creation, source upload, branding check
- test_keys.py: Identity display, trust store
- test_fieldkit.py: Status dashboard, killswitch page
- test_navigation.py: All nav links, responsive layout

Run: pytest (unit/integration) or pytest -m e2e tests/e2e/ (browser)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:22:12 -04:00

208 lines
7.5 KiB
Python

"""Integration tests for c2pa_bridge/importer.py — data-mapping logic.
All tests run without c2pa-python installed. Tests that exercise the full
import pipeline are skipped automatically when c2pa-python is absent.
"""
from __future__ import annotations
from dataclasses import fields
from typing import Any
import pytest
from fieldwitness.c2pa_bridge.importer import C2PAImportResult, import_c2pa
# ---------------------------------------------------------------------------
# test_c2pa_import_result_dataclass
# ---------------------------------------------------------------------------
class TestC2PAImportResultDataclass:
def test_required_fields_exist(self):
expected = {"success", "manifests", "attestation_record",
"fieldwitness_assertions", "trust_status"}
actual = {f.name for f in fields(C2PAImportResult)}
assert expected.issubset(actual)
def test_error_field_exists(self):
field_names = {f.name for f in fields(C2PAImportResult)}
assert "error" in field_names
def test_construct_success_result(self):
result = C2PAImportResult(
success=True,
manifests=[],
attestation_record=None,
fieldwitness_assertions={},
trust_status="unknown",
error=None,
)
assert result.success is True
assert result.error is None
def test_construct_failure_result(self):
result = C2PAImportResult(
success=False,
manifests=[],
attestation_record=None,
fieldwitness_assertions={},
trust_status="invalid",
error="c2pa-python is not installed",
)
assert result.success is False
assert result.error is not None
def test_manifests_is_list(self):
result = C2PAImportResult(
success=False,
manifests=[{"key": "value"}],
attestation_record=None,
fieldwitness_assertions={},
trust_status="unknown",
)
assert isinstance(result.manifests, list)
def test_fieldwitness_assertions_is_dict(self):
result = C2PAImportResult(
success=True,
manifests=[],
attestation_record=None,
fieldwitness_assertions={"org.fieldwitness.perceptual-hashes": {}},
trust_status="self-signed",
)
assert isinstance(result.fieldwitness_assertions, dict)
# ---------------------------------------------------------------------------
# test_import_without_c2pa_returns_error
# ---------------------------------------------------------------------------
class TestImportWithoutC2pa:
def test_returns_failure_result(self):
"""import_c2pa must never raise — it returns a failure C2PAImportResult."""
# Pass dummy bytes; without c2pa-python this should fail gracefully.
result = import_c2pa(b"dummy image data", "jpeg")
# Either c2pa is installed (success possible) or we get a clean failure.
if not result.success:
assert result.error is not None
assert len(result.error) > 0
def test_no_exception_raised_for_any_input(self):
"""import_c2pa must not propagate exceptions regardless of input."""
# Various bad inputs — all must be caught internally.
for image_data, fmt in [
(b"", "jpeg"),
(b"\x00" * 100, "png"),
(b"not an image", "webp"),
]:
result = import_c2pa(image_data, fmt)
assert isinstance(result, C2PAImportResult)
def test_failure_result_has_trust_status(self):
"""Even a failure result must carry a trust_status string."""
result = import_c2pa(b"garbage", "jpeg")
assert isinstance(result.trust_status, str)
assert len(result.trust_status) > 0
def test_failure_result_has_empty_manifests(self):
"""On failure without c2pa, manifests must be an empty list."""
try:
import c2pa # noqa: F401
pytest.skip("c2pa-python is installed — this test covers the absent case")
except ImportError:
pass
result = import_c2pa(b"garbage", "jpeg")
assert result.manifests == []
def test_error_message_mentions_install(self):
"""When c2pa is absent, the error message must include install guidance."""
try:
import c2pa # noqa: F401
pytest.skip("c2pa-python is installed — this test covers the absent case")
except ImportError:
pass
result = import_c2pa(b"dummy", "jpeg")
assert not result.success
assert "pip install" in (result.error or "")
def test_unsupported_format_returns_failure(self):
"""An unsupported image format must return success=False with an error."""
try:
import c2pa # noqa: F401
except ImportError:
pytest.skip("c2pa-python not installed; format validation not reached")
result = import_c2pa(b"dummy", "bmp")
assert not result.success
assert result.error is not None
# ---------------------------------------------------------------------------
# test_trust_status_values
# ---------------------------------------------------------------------------
class TestTrustStatusValues:
"""Verify the four trust statuses are valid, non-empty strings."""
VALID_STATUSES = {"trusted", "self-signed", "unknown", "invalid"}
def test_trusted_is_valid_string(self):
assert "trusted" in self.VALID_STATUSES
def test_self_signed_is_valid_string(self):
assert "self-signed" in self.VALID_STATUSES
def test_unknown_is_valid_string(self):
assert "unknown" in self.VALID_STATUSES
def test_invalid_is_valid_string(self):
assert "invalid" in self.VALID_STATUSES
def test_all_statuses_are_non_empty(self):
for status in self.VALID_STATUSES:
assert len(status) > 0
def test_result_trust_status_is_one_of_valid(self):
"""Every C2PAImportResult.trust_status value must be in the valid set."""
# Absent c2pa returns "unknown"; with c2pa and corrupt data returns "invalid".
result = import_c2pa(b"not a real image", "jpeg")
assert result.trust_status in self.VALID_STATUSES
def test_evaluate_trust_invalid_flag(self):
"""Internal _evaluate_trust must return 'invalid' when _fw_invalid is set."""
from fieldwitness.c2pa_bridge.importer import _evaluate_trust
manifest: dict[str, Any] = {"_fw_invalid": True}
assert _evaluate_trust(manifest, trusted_certs=None) == "invalid"
def test_evaluate_trust_unknown_for_no_cert(self):
"""No cert chain and no invalid flag -> 'unknown'."""
from fieldwitness.c2pa_bridge.importer import _evaluate_trust
manifest: dict[str, Any] = {"signature_info": {}}
assert _evaluate_trust(manifest, trusted_certs=None) == "unknown"
def test_evaluate_trust_self_signed_fw(self):
"""Self-signed cert + 'FieldWitness' in claim_generator -> 'self-signed'."""
from unittest.mock import MagicMock, patch
from fieldwitness.c2pa_bridge.importer import _evaluate_trust
dummy_pem = "DUMMY_PEM"
with patch("fieldwitness.c2pa_bridge.importer._cert_is_self_signed", return_value=True):
manifest: dict[str, Any] = {
"claim_generator": "FieldWitness/0.3.0",
"signature_info": {"cert_chain": [dummy_pem]},
}
result = _evaluate_trust(manifest, trusted_certs=None)
assert result == "self-signed"