Skip to content

Commit 56ef1fa

Browse files
committed
Add more unit tests
1 parent 8b1cf53 commit 56ef1fa

File tree

4 files changed

+159
-7
lines changed

4 files changed

+159
-7
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "c2pa-python"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2021"
55
authors = ["Gavin Peacock <[email protected]"]
66

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This library enables you to read and validate C2PA data in supported media files
99
Install from PyPI by entering this command:
1010

1111
```
12-
pip install c2pa-python
12+
pip install -U c2pa-python
1313
```
1414

1515
## Usage
@@ -19,15 +19,15 @@ pip install c2pa-python
1919
Import the C2PA module as follows:
2020

2121
```py
22-
import c2pa-python as c2pa
22+
import c2pa_python as c2pa
2323
```
2424

2525
### Read and validate C2PA data in a file
2626

2727
Use the `verify_from_file_json` function to read C2PA data from the specified file:
2828

2929
```py
30-
json_store = c2pa.verify_from_file_json("path/to/media_file.jpg", data_dir)
30+
json_store = c2pa.verify_from_file_json("path/to/media_file.jpg", "path/to/data_dir")
3131
```
3232

3333
This function examines the specified media file for C2PA data and generates a JSON report of any data it finds. If there are validation errors, the report includes a `validation_status` field. For a summary of supported media types, see [Supported file formats](#supported-file-formats).
@@ -57,7 +57,7 @@ The parameters (in order) are:
5757
- `sign_info`, a `SignerInfo` object instance; see [Generating SignerInfo](#generating-signerinfo) below.
5858
- `data_dir` optionally specifies a directory path from which to load resource files referenced in the manifest JSON identifier fields; for example, thumbnails, icons, and manifest data for ingredients.
5959

60-
### Generating SignerInfo
60+
### Create a SignerInfo Instance
6161

6262
A `SignerInfo` object contains information about a signature. To create an instance of `SignerInfo`, first set up the signer information from the public and private key `.pem` files as follows:
6363

tests/example.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2023 Adobe. All rights reserved.
2+
# This file is licensed to you under the Apache License,
3+
# Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
4+
# or the MIT license (http://opensource.org/licenses/MIT),
5+
# at your option.
6+
# Unless required by applicable law or agreed to in writing,
7+
# this software is distributed on an "AS IS" BASIS, WITHOUT
8+
# WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or
9+
# implied. See the LICENSE-MIT and LICENSE-APACHE files for the
10+
# specific language governing permissions and limitations under
11+
# each license.
12+
13+
# This example shows how to add a do not train assertion to an asset and then verify it
14+
15+
import json
16+
import os
17+
import sys
18+
import c2pa_python as c2pa;
19+
20+
# set up paths to the files we we are using
21+
PROJECT_PATH = os.getcwd()
22+
testFile = os.path.join(PROJECT_PATH,"tests","fixtures","A.jpg")
23+
pemFile = os.path.join(PROJECT_PATH,"tests","fixtures","es256_certs.pem")
24+
keyFile = os.path.join(PROJECT_PATH,"tests","fixtures","es256_private.key")
25+
testOutputFile = os.path.join(PROJECT_PATH,"target","dnt.jpg")
26+
27+
# a little helper function to get a value from a nested dictionary
28+
from functools import reduce
29+
import operator
30+
def getitem(d, key):
31+
return reduce(operator.getitem, key, d)
32+
33+
print("version = " + c2pa.version())
34+

tests/test_c2pa.py

Lines changed: 120 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,18 @@
1313

1414
import c2pa_python as c2pa
1515
import pytest
16+
import json
17+
import tempfile
18+
import shutil
19+
20+
# a little helper function to get a value from a nested dictionary
21+
from functools import reduce
22+
import operator
23+
def getitem(d, key):
24+
return reduce(operator.getitem, key, d)
1625

1726
def test_version():
18-
assert c2pa.version() == "0.2.0"
27+
assert c2pa.version() == "0.2.1"
1928

2029
def test_sdk_version():
2130
assert c2pa.sdk_version() == "0.26.0"
@@ -29,4 +38,113 @@ def test_verify_from_file_no_store():
2938
with pytest.raises(c2pa.Error.Sdk) as err:
3039
json_store = c2pa.verify_from_file_json("tests/fixtures/A.jpg", None)
3140
assert str(err.value) == "no JUMBF data found"
32-
41+
42+
def test_verify_from_file_get_thumbnail():
43+
with tempfile.TemporaryDirectory() as data_dir:
44+
store_json = c2pa.verify_from_file_json("tests/fixtures/C.jpg", data_dir)
45+
manifest_store = json.loads(store_json)
46+
manifest = manifest_store["manifests"][manifest_store["active_manifest"]]
47+
print (store_json)
48+
assert "make_test_images" in manifest["claim_generator"]
49+
assert manifest["title"]== "C.jpg"
50+
assert manifest,["format"] == "image/jpeg"
51+
# There should be no validation status errors
52+
assert manifest.get("validation_status") == None
53+
# read creative work assertion (author name)
54+
assert getitem(manifest,("assertions",0,"label")) == "stds.schema-org.CreativeWork"
55+
assert getitem(manifest,("assertions",0,"data","author",0,"name")) == "Adobe make_test"
56+
# read Actions assertion
57+
assert getitem(manifest,("assertions",1,"label")) == "c2pa.actions"
58+
assert getitem(manifest,("assertions",1,"data","actions",0,"action")) == "c2pa.created"
59+
# read signature info
60+
assert getitem(manifest,("signature_info","issuer")) == "C2PA Test Signing Cert"
61+
# read thumbnail data from file
62+
assert getitem(manifest,("thumbnail","format")) == "image/jpeg"
63+
thumb_name = getitem(manifest,("thumbnail","identifier"))
64+
with open(data_dir + "/" + thumb_name, "rb") as thumb_file:
65+
thumb_data = thumb_file.read()
66+
assert len(thumb_data) == 31608
67+
68+
def test_ingredient_from_file_get_thumbnail():
69+
with tempfile.TemporaryDirectory() as data_dir:
70+
ingredient_json = c2pa.ingredient_from_file_json("tests/fixtures/C.jpg", data_dir)
71+
ingredient = json.loads(ingredient_json)
72+
assert ingredient["title"]== "C.jpg"
73+
assert ingredient,["format"] == "image/jpeg"
74+
# read thumbnail data from file
75+
assert getitem(ingredient,("thumbnail","format")) == "image/jpeg"
76+
thumb_name = getitem(ingredient,("thumbnail","identifier"))
77+
with open(data_dir + "/" + thumb_name, "rb") as thumb_file:
78+
thumb_data = thumb_file.read()
79+
assert len(thumb_data) == 31608
80+
#read c2pa data from file
81+
assert getitem(ingredient,("manifest_data","format")) == "c2pa"
82+
data_name = getitem(ingredient,("manifest_data","identifier"))
83+
with open(data_dir + "/" + data_name, "rb") as c2pa_file:
84+
c2pa_data = c2pa_file.read()
85+
assert len(c2pa_data) == 51240
86+
87+
def test_sign_info():
88+
# set up the signer info loading the pem and key files
89+
test_pem = open("tests/fixtures/es256_certs.pem","rb").read()
90+
test_key = open("tests/fixtures/es256_private.key","rb").read()
91+
sign_info = c2pa.SignerInfo(test_pem, test_key, "es256", "http://timestamp.digicert.com")
92+
assert sign_info.alg == "es256"
93+
assert sign_info.tsa_url == "http://timestamp.digicert.com"
94+
95+
def test_add_manifest_to_file():
96+
# define a source folder for any assets we need to read
97+
data_dir = "tests/fixtures"
98+
99+
# create temp folder for writing things
100+
with tempfile.TemporaryDirectory() as output_dir:
101+
# define a manifest with the do not train assertion
102+
manifest_json = json.dumps({
103+
"claim_generator": "python_test/0.1",
104+
"title": "My Title",
105+
"thumbnail": {
106+
"format": "image/jpeg",
107+
"identifier": "A.jpg"
108+
},
109+
"assertions": [
110+
{
111+
"label": "c2pa.training-mining",
112+
"data": {
113+
"entries": {
114+
"c2pa.ai_generative_training": { "use": "notAllowed" },
115+
"c2pa.ai_inference": { "use": "notAllowed" },
116+
"c2pa.ai_training": { "use": "notAllowed" },
117+
"c2pa.data_mining": { "use": "notAllowed" }
118+
}
119+
}
120+
}
121+
]
122+
})
123+
124+
# set up the signer info loading the pem and key files
125+
test_pem = open("tests/fixtures/es256_certs.pem","rb").read()
126+
test_key = open("tests/fixtures/es256_private.key","rb").read()
127+
sign_info = c2pa.SignerInfo(test_pem, test_key, "es256", "http://timestamp.digicert.com")
128+
129+
# add the manifest to the asset
130+
c2pa_data = c2pa.add_manifest_to_file_json(data_dir + "/A.jpg", output_dir+"/out.jpg", manifest_json, sign_info, data_dir)
131+
assert len(c2pa_data) == 75860 #check the size of returned c2pa_manifest data
132+
133+
# verify the asset and check the manifest has what we expect
134+
store_json = c2pa.verify_from_file_json(output_dir + "/out.jpg", output_dir)
135+
manifest_store = json.loads(store_json)
136+
manifest = manifest_store["manifests"][manifest_store["active_manifest"]]
137+
print (store_json)
138+
assert "python_test" in manifest["claim_generator"]
139+
# check custom title and format
140+
assert manifest["title"]== "My Title"
141+
assert manifest,["format"] == "image/jpeg"
142+
# There should be no validation status errors
143+
assert manifest.get("validation_status") == None
144+
# check the thumbnail data
145+
thumb_name = getitem(manifest,("thumbnail","identifier"))
146+
with open(output_dir + "/" + thumb_name, "rb") as thumb_file:
147+
thumb_data = thumb_file.read()
148+
assert len(thumb_data) == 61720
149+
150+

0 commit comments

Comments
 (0)