|
18 | 18 | from unittest.mock import mock_open, patch |
19 | 19 | import ctypes |
20 | 20 | import warnings |
| 21 | +import pytest |
| 22 | +from cryptography.hazmat.primitives import hashes, serialization |
| 23 | +from cryptography.hazmat.primitives.asymmetric import padding |
| 24 | +from cryptography.hazmat.backends import default_backend |
21 | 25 |
|
22 | 26 | from c2pa import Builder, C2paError as Error, Reader, C2paSigningAlg as SigningAlg, C2paSignerInfo, Signer, sdk_version |
23 | | -from c2pa.c2pa import Stream, read_ingredient_file, read_file, sign_file, load_settings |
| 27 | +from c2pa.c2pa import Stream, read_ingredient_file, read_file, sign_file, load_settings, create_signer |
24 | 28 |
|
25 | 29 | # Suppress deprecation warnings |
26 | 30 | warnings.filterwarnings("ignore", category=DeprecationWarning) |
@@ -1006,5 +1010,66 @@ def test_sign_file(self): |
1006 | 1010 | os.remove(output_path) |
1007 | 1011 |
|
1008 | 1012 |
|
| 1013 | +class TestCreateSigner(unittest.TestCase): |
| 1014 | + """Test cases for the create_signer function.""" |
| 1015 | + |
| 1016 | + def setUp(self): |
| 1017 | + """Set up test fixtures.""" |
| 1018 | + self.data_dir = FIXTURES_DIR |
| 1019 | + |
| 1020 | + # Load test certificates and key |
| 1021 | + with open(os.path.join(self.data_dir, "es256_certs.pem"), "rb") as cert_file: |
| 1022 | + self.certs = cert_file.read().decode('utf-8') |
| 1023 | + with open(os.path.join(self.data_dir, "es256_private.key"), "rb") as key_file: |
| 1024 | + self.key = key_file.read().decode('utf-8') |
| 1025 | + |
| 1026 | + def test_create_signer_with_callback(self): |
| 1027 | + """Test creating a signer with a callback function.""" |
| 1028 | + def mock_sign_callback(data: bytes) -> bytes: |
| 1029 | + """Mock signing callback that returns a fake signature.""" |
| 1030 | + # Return a fake signature (64 bytes for Ed25519) |
| 1031 | + return b"fake_signature_" + b"0" * 50 |
| 1032 | + |
| 1033 | + # Test with Ed25519 algorithm |
| 1034 | + signer = create_signer( |
| 1035 | + callback=mock_sign_callback, |
| 1036 | + alg=SigningAlg.ED25519, |
| 1037 | + certs=self.certs |
| 1038 | + ) |
| 1039 | + |
| 1040 | + # Verify the signer was created successfully |
| 1041 | + self.assertIsInstance(signer, Signer) |
| 1042 | + self.assertFalse(signer.closed) |
| 1043 | + |
| 1044 | + # Test that reserve_size works |
| 1045 | + reserve_size = signer.reserve_size() |
| 1046 | + self.assertIsInstance(reserve_size, int) |
| 1047 | + self.assertGreaterEqual(reserve_size, 0) |
| 1048 | + |
| 1049 | + # Clean up |
| 1050 | + signer.close() |
| 1051 | + |
| 1052 | + def test_create_signer_callback_error_handling(self): |
| 1053 | + """Test that callback errors are properly handled.""" |
| 1054 | + def error_callback(data: bytes) -> bytes: |
| 1055 | + """Callback that raises an exception.""" |
| 1056 | + raise ValueError("Test callback error") |
| 1057 | + |
| 1058 | + # The create_signer function doesn't wrap callbacks with error handling |
| 1059 | + # The error handling happens when the callback is actually called during signing |
| 1060 | + # So creating the signer should succeed, but using it might fail |
| 1061 | + signer = create_signer( |
| 1062 | + callback=error_callback, |
| 1063 | + alg=SigningAlg.ES256, |
| 1064 | + certs=self.certs |
| 1065 | + ) |
| 1066 | + |
| 1067 | + # Verify the signer was created successfully |
| 1068 | + self.assertIsInstance(signer, Signer) |
| 1069 | + self.assertFalse(signer.closed) |
| 1070 | + |
| 1071 | + # Clean up |
| 1072 | + signer.close() |
| 1073 | + |
1009 | 1074 | if __name__ == '__main__': |
1010 | 1075 | unittest.main() |
0 commit comments