"""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"