Skip to content

Commit 1383df1

Browse files
committed
fix: One more test
1 parent 2e713fa commit 1383df1

File tree

1 file changed

+313
-0
lines changed

1 file changed

+313
-0
lines changed

tests/test_unit_tests_threaded.py

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,41 @@ def read_metadata():
6262
thread1.join()
6363
thread2.join()
6464

65+
def test_stream_read_async(self):
66+
"""Test reading C2PA metadata from a file using async tasks"""
67+
async def read_metadata_async():
68+
with open(self.testPath, "rb") as file:
69+
reader = Reader("image/jpeg", file)
70+
json_data = reader.json()
71+
self.assertIn("C.jpg", json_data)
72+
return json_data
73+
74+
async def run_async_tests():
75+
# Create multiple async tasks
76+
tasks = []
77+
num_tasks = 2
78+
for i in range(num_tasks):
79+
task = asyncio.create_task(read_metadata_async())
80+
tasks.append(task)
81+
82+
# Wait for all tasks to complete and collect results
83+
results = await asyncio.gather(*tasks, return_exceptions=True)
84+
85+
# Process results
86+
errors = []
87+
for i, result in enumerate(results):
88+
if isinstance(result, Exception):
89+
errors.append(f"Async task {i} failed with exception: {str(result)}")
90+
elif result is None: # No result indicates an error
91+
errors.append(f"Async task {i} returned None")
92+
93+
# If any errors occurred, fail the test with all error messages
94+
if errors:
95+
self.fail("\n".join(errors))
96+
97+
# Run the async tests
98+
asyncio.run(run_async_tests())
99+
65100
def test_stream_read_and_parse(self):
66101
def read_and_parse():
67102
with open(self.testPath, "rb") as file:
@@ -273,6 +308,33 @@ def setUp(self):
273308
]
274309
}
275310

311+
# Define a V2 manifest as a dictionary
312+
self.manifestDefinitionV2_1 = {
313+
"claim_generator": "python_test",
314+
"claim_generator_info": [{
315+
"name": "python_test",
316+
"version": "0.0.1",
317+
}],
318+
# claim version 2 is the default
319+
# "claim_version": 2,
320+
"format": "image/jpeg",
321+
"title": "Python Test Image V2",
322+
"ingredients": [],
323+
"assertions": [
324+
{
325+
"label": "c2pa.actions",
326+
"data": {
327+
"actions": [
328+
{
329+
"action": "c2pa.created",
330+
"digitalSourceType": "http://cv.iptc.org/newscodes/digitalsourcetype/digitalCreation"
331+
}
332+
]
333+
}
334+
}
335+
]
336+
}
337+
276338
def test_sign_all_files(self):
277339
"""Test signing all files in both fixtures directories using a thread pool"""
278340
signing_dir = os.path.join(self.data_dir, "files-for-signing-tests")
@@ -2024,5 +2086,256 @@ async def run_async_tests():
20242086
# Settings are thread-local, so we reset to the default "true" here
20252087
load_settings('{"builder": { "thumbnail": {"enabled": true}}}')
20262088

2089+
def test_streams_sign_with_thumbnail_resource(self):
2090+
"""Test Builder class operations with thumbnail resource using multiple threads."""
2091+
# Thread synchronization
2092+
thread_results = {}
2093+
completed_threads = 0
2094+
thread_lock = threading.Lock()
2095+
2096+
def thread_work(thread_id):
2097+
nonlocal completed_threads
2098+
try:
2099+
with open(self.testPath2, "rb") as file:
2100+
builder = Builder(self.manifestDefinitionV2_1)
2101+
output = io.BytesIO(bytearray())
2102+
2103+
with open(self.testPath2, "rb") as thumbnail_file:
2104+
builder.add_resource("thumbnail", thumbnail_file)
2105+
2106+
builder.sign(self.signer, "image/jpeg", file, output)
2107+
output.seek(0)
2108+
reader = Reader("image/jpeg", output)
2109+
json_data = reader.json()
2110+
2111+
# Store results for verification
2112+
with thread_lock:
2113+
thread_results[thread_id] = {
2114+
'json_data': json_data,
2115+
'thread_id': thread_id
2116+
}
2117+
2118+
# Verify the JSON data contains expected content
2119+
self.assertIn("Python Test", json_data)
2120+
self.assertNotIn("validation_status", json_data)
2121+
2122+
output.close()
2123+
2124+
except Exception as e:
2125+
with thread_lock:
2126+
thread_results[thread_id] = {
2127+
'error': str(e),
2128+
'thread_id': thread_id
2129+
}
2130+
finally:
2131+
with thread_lock:
2132+
completed_threads += 1
2133+
2134+
# Create and start multiple threads
2135+
threads = []
2136+
num_threads = 3
2137+
for i in range(1, num_threads + 1):
2138+
thread = threading.Thread(target=thread_work, args=(i,))
2139+
threads.append(thread)
2140+
thread.start()
2141+
2142+
# Wait for all threads to complete
2143+
for thread in threads:
2144+
thread.join()
2145+
2146+
# Verify all threads completed
2147+
self.assertEqual(completed_threads, num_threads, f"All {num_threads} threads should have completed")
2148+
self.assertEqual(len(thread_results), num_threads, f"Should have results from all {num_threads} threads")
2149+
2150+
# Verify results for each thread
2151+
for thread_id in range(1, num_threads + 1):
2152+
result = thread_results[thread_id]
2153+
2154+
# Check if thread encountered an error
2155+
if 'error' in result:
2156+
self.fail(f"Thread {thread_id} failed with error: {result['error']}")
2157+
2158+
json_data = result['json_data']
2159+
2160+
# Verify the JSON data contains expected content
2161+
self.assertIn("Python Test", json_data)
2162+
self.assertNotIn("validation_status", json_data)
2163+
2164+
def test_streams_sign_with_thumbnail_resource_async(self):
2165+
"""Test Builder class operations with thumbnail resource using async tasks."""
2166+
async def async_thread_work(task_id):
2167+
try:
2168+
with open(self.testPath2, "rb") as file:
2169+
builder = Builder(self.manifestDefinitionV2_1)
2170+
output = io.BytesIO(bytearray())
2171+
2172+
with open(self.testPath2, "rb") as thumbnail_file:
2173+
builder.add_resource("thumbnail", thumbnail_file)
2174+
2175+
builder.sign(self.signer, "image/jpeg", file, output)
2176+
output.seek(0)
2177+
reader = Reader("image/jpeg", output)
2178+
json_data = reader.json()
2179+
2180+
# Verify the JSON data contains expected content
2181+
self.assertIn("Python Test", json_data)
2182+
self.assertNotIn("validation_status", json_data)
2183+
2184+
output.close()
2185+
return None # Success case
2186+
2187+
except Exception as e:
2188+
return f"Async task {task_id} error: {str(e)}"
2189+
2190+
async def run_async_tests():
2191+
# Create multiple async tasks
2192+
tasks = []
2193+
num_tasks = 3
2194+
for i in range(1, num_tasks + 1):
2195+
task = asyncio.create_task(async_thread_work(i))
2196+
tasks.append(task)
2197+
2198+
# Wait for all tasks to complete and collect results
2199+
results = await asyncio.gather(*tasks, return_exceptions=True)
2200+
2201+
# Process results
2202+
errors = []
2203+
for i, result in enumerate(results, 1):
2204+
if isinstance(result, Exception):
2205+
errors.append(f"Async task {i} failed with exception: {str(result)}")
2206+
elif result: # Non-None result indicates an error
2207+
errors.append(result)
2208+
2209+
# If any errors occurred, fail the test with all error messages
2210+
if errors:
2211+
self.fail("\n".join(errors))
2212+
2213+
# Run the async tests
2214+
asyncio.run(run_async_tests())
2215+
2216+
def test_remote_sign_using_returned_bytes_V2(self):
2217+
"""Test Builder class operations with remote signing using returned bytes and multiple threads."""
2218+
# Thread synchronization
2219+
thread_results = {}
2220+
completed_threads = 0
2221+
thread_lock = threading.Lock()
2222+
2223+
def thread_work(thread_id):
2224+
nonlocal completed_threads
2225+
try:
2226+
with open(self.testPath, "rb") as file:
2227+
builder = Builder(self.manifestDefinitionV2_1)
2228+
builder.set_no_embed()
2229+
with io.BytesIO() as output_buffer:
2230+
manifest_data = builder.sign(
2231+
self.signer, "image/jpeg", file, output_buffer)
2232+
output_buffer.seek(0)
2233+
read_buffer = io.BytesIO(output_buffer.getvalue())
2234+
2235+
with Reader("image/jpeg", read_buffer, manifest_data) as reader:
2236+
manifest_data = reader.json()
2237+
2238+
# Store results for verification
2239+
with thread_lock:
2240+
thread_results[thread_id] = {
2241+
'manifest_data': manifest_data,
2242+
'thread_id': thread_id
2243+
}
2244+
2245+
# Verify the manifest data contains expected content
2246+
self.assertIn("Python Test", manifest_data)
2247+
self.assertNotIn("validation_status", manifest_data)
2248+
2249+
except Exception as e:
2250+
with thread_lock:
2251+
thread_results[thread_id] = {
2252+
'error': str(e),
2253+
'thread_id': thread_id
2254+
}
2255+
finally:
2256+
with thread_lock:
2257+
completed_threads += 1
2258+
2259+
# Create and start multiple threads
2260+
threads = []
2261+
num_threads = 3
2262+
for i in range(1, num_threads + 1):
2263+
thread = threading.Thread(target=thread_work, args=(i,))
2264+
threads.append(thread)
2265+
thread.start()
2266+
2267+
# Wait for all threads to complete
2268+
for thread in threads:
2269+
thread.join()
2270+
2271+
# Verify all threads completed
2272+
self.assertEqual(completed_threads, num_threads, f"All {num_threads} threads should have completed")
2273+
self.assertEqual(len(thread_results), num_threads, f"Should have results from all {num_threads} threads")
2274+
2275+
# Verify results for each thread
2276+
for thread_id in range(1, num_threads + 1):
2277+
result = thread_results[thread_id]
2278+
2279+
# Check if thread encountered an error
2280+
if 'error' in result:
2281+
self.fail(f"Thread {thread_id} failed with error: {result['error']}")
2282+
2283+
manifest_data = result['manifest_data']
2284+
2285+
# Verify the manifest data contains expected content
2286+
self.assertIn("Python Test", manifest_data)
2287+
self.assertNotIn("validation_status", manifest_data)
2288+
2289+
def test_remote_sign_using_returned_bytes_V2_async(self):
2290+
"""Test Builder class operations with remote signing using returned bytes and async tasks."""
2291+
async def async_thread_work(task_id):
2292+
try:
2293+
with open(self.testPath, "rb") as file:
2294+
builder = Builder(self.manifestDefinitionV2_1)
2295+
builder.set_no_embed()
2296+
with io.BytesIO() as output_buffer:
2297+
manifest_data = builder.sign(
2298+
self.signer, "image/jpeg", file, output_buffer)
2299+
output_buffer.seek(0)
2300+
read_buffer = io.BytesIO(output_buffer.getvalue())
2301+
2302+
with Reader("image/jpeg", read_buffer, manifest_data) as reader:
2303+
manifest_data = reader.json()
2304+
2305+
# Verify the manifest data contains expected content
2306+
self.assertIn("Python Test", manifest_data)
2307+
self.assertNotIn("validation_status", manifest_data)
2308+
2309+
return None # Success case
2310+
2311+
except Exception as e:
2312+
return f"Async task {task_id} error: {str(e)}"
2313+
2314+
async def run_async_tests():
2315+
# Create multiple async tasks
2316+
tasks = []
2317+
num_tasks = 3
2318+
for i in range(1, num_tasks + 1):
2319+
task = asyncio.create_task(async_thread_work(i))
2320+
tasks.append(task)
2321+
2322+
# Wait for all tasks to complete and collect results
2323+
results = await asyncio.gather(*tasks, return_exceptions=True)
2324+
2325+
# Process results
2326+
errors = []
2327+
for i, result in enumerate(results, 1):
2328+
if isinstance(result, Exception):
2329+
errors.append(f"Async task {i} failed with exception: {str(result)}")
2330+
elif result: # Non-None result indicates an error
2331+
errors.append(result)
2332+
2333+
# If any errors occurred, fail the test with all error messages
2334+
if errors:
2335+
self.fail("\n".join(errors))
2336+
2337+
# Run the async tests
2338+
asyncio.run(run_async_tests())
2339+
20272340
if __name__ == '__main__':
20282341
unittest.main()

0 commit comments

Comments
 (0)