@@ -1818,203 +1818,6 @@ async def run_async_tests():
18181818 # Verify all readers completed
18191819 self .assertEqual (active_readers , 0 , "Not all readers completed" )
18201820
1821- def test_builder_sign_with_multiple_ingredients_from_stream (self ):
1822- """Test Builder class operations with multiple ingredients using streams."""
1823- # Test creating builder from JSON
1824- builder = Builder .from_json (self .manifestDefinition )
1825- assert builder ._handle is not None
1826-
1827- # Thread synchronization
1828- add_errors = []
1829- add_lock = threading .Lock ()
1830- completed_threads = 0
1831- completion_lock = threading .Lock ()
1832-
1833- def add_ingredient_from_stream (ingredient_json , file_path , thread_id ):
1834- nonlocal completed_threads
1835- try :
1836- with open (file_path , 'rb' ) as f :
1837- builder .add_ingredient_from_stream (
1838- ingredient_json , "image/jpeg" , f )
1839- with add_lock :
1840- add_errors .append (None ) # Success case
1841- except Exception as e :
1842- with add_lock :
1843- add_errors .append (f"Thread { thread_id } error: { str (e )} " )
1844- finally :
1845- with completion_lock :
1846- completed_threads += 1
1847-
1848- # Create and start two threads for parallel ingredient addition
1849- thread1 = threading .Thread (
1850- target = add_ingredient_from_stream ,
1851- args = ('{"title": "Test Ingredient Stream 1"}' , self .testPath3 , 1 )
1852- )
1853- thread2 = threading .Thread (
1854- target = add_ingredient_from_stream ,
1855- args = ('{"title": "Test Ingredient Stream 2"}' , self .testPath4 , 2 )
1856- )
1857-
1858- # Start both threads
1859- thread1 .start ()
1860- thread2 .start ()
1861-
1862- # Wait for both threads to complete
1863- thread1 .join ()
1864- thread2 .join ()
1865-
1866- # Check for errors during ingredient addition
1867- if any (error for error in add_errors if error is not None ):
1868- self .fail (
1869- "\n " .join (
1870- error for error in add_errors if error is not None ))
1871-
1872- # Verify both ingredients were added successfully
1873- self .assertEqual (
1874- completed_threads ,
1875- 2 ,
1876- "Both threads should have completed" )
1877- self .assertEqual (
1878- len (add_errors ),
1879- 2 ,
1880- "Both threads should have completed without errors" )
1881-
1882- # Now sign the manifest with the added ingredients
1883- with open (self .testPath2 , "rb" ) as file :
1884- output = io .BytesIO (bytearray ())
1885- builder .sign (self .signer , "image/jpeg" , file , output )
1886- output .seek (0 )
1887- reader = Reader ("image/jpeg" , output )
1888- json_data = reader .json ()
1889- manifest_data = json .loads (json_data )
1890-
1891- # Verify active manifest exists
1892- self .assertIn ("active_manifest" , manifest_data )
1893- active_manifest_id = manifest_data ["active_manifest" ]
1894-
1895- # Verify active manifest object exists
1896- self .assertIn ("manifests" , manifest_data )
1897- self .assertIn (active_manifest_id , manifest_data ["manifests" ])
1898- active_manifest = manifest_data ["manifests" ][active_manifest_id ]
1899-
1900- # Verify ingredients array exists in active manifest
1901- self .assertIn ("ingredients" , active_manifest )
1902- self .assertIsInstance (active_manifest ["ingredients" ], list )
1903- self .assertEqual (len (active_manifest ["ingredients" ]), 2 )
1904-
1905- # Verify both ingredients exist in the array (order doesn't matter)
1906- ingredient_titles = [ing ["title" ]
1907- for ing in active_manifest ["ingredients" ]]
1908- self .assertIn ("Test Ingredient Stream 1" , ingredient_titles )
1909- self .assertIn ("Test Ingredient Stream 2" , ingredient_titles )
1910-
1911- builder .close ()
1912-
1913- def test_builder_sign_with_same_ingredient_multiple_times (self ):
1914- """Test Builder class operations with the same ingredient added multiple times from different threads."""
1915- # Test creating builder from JSON
1916- builder = Builder .from_json (self .manifestDefinition )
1917- assert builder ._handle is not None
1918-
1919- # Thread synchronization
1920- add_errors = []
1921- add_lock = threading .Lock ()
1922- completed_threads = 0
1923- completion_lock = threading .Lock ()
1924-
1925- def add_ingredient (ingredient_json , thread_id ):
1926- nonlocal completed_threads
1927- try :
1928- with open (self .testPath3 , 'rb' ) as f :
1929- builder .add_ingredient (ingredient_json , "image/jpeg" , f )
1930- with add_lock :
1931- add_errors .append (None ) # Success case
1932- except Exception as e :
1933- with add_lock :
1934- add_errors .append (f"Thread { thread_id } error: { str (e )} " )
1935- finally :
1936- with completion_lock :
1937- completed_threads += 1
1938-
1939- # Create and start 5 threads for parallel ingredient addition
1940- threads = []
1941- for i in range (1 , 6 ):
1942- # Create unique manifest JSON for each thread
1943- ingredient_json = json .dumps ({
1944- "title" : f"Test Ingredient Thread { i } "
1945- })
1946-
1947- thread = threading .Thread (
1948- target = add_ingredient ,
1949- args = (ingredient_json , i )
1950- )
1951- threads .append (thread )
1952- thread .start ()
1953-
1954- # Wait for all threads to complete
1955- for thread in threads :
1956- thread .join ()
1957-
1958- # Check for errors during ingredient addition
1959- if any (error for error in add_errors if error is not None ):
1960- self .fail (
1961- "\n " .join (
1962- error for error in add_errors if error is not None ))
1963-
1964- # Verify all ingredients were added successfully
1965- self .assertEqual (
1966- completed_threads ,
1967- 5 ,
1968- "All 5 threads should have completed" )
1969- self .assertEqual (
1970- len (add_errors ),
1971- 5 ,
1972- "All 5 threads should have completed without errors" )
1973-
1974- # Now sign the manifest with the added ingredients
1975- with open (self .testPath2 , "rb" ) as file :
1976- output = io .BytesIO (bytearray ())
1977- builder .sign (self .signer , "image/jpeg" , file , output )
1978- output .seek (0 )
1979- reader = Reader ("image/jpeg" , output )
1980- json_data = reader .json ()
1981- manifest_data = json .loads (json_data )
1982-
1983- # Verify active manifest exists
1984- self .assertIn ("active_manifest" , manifest_data )
1985- active_manifest_id = manifest_data ["active_manifest" ]
1986-
1987- # Verify active manifest object exists
1988- self .assertIn ("manifests" , manifest_data )
1989- self .assertIn (active_manifest_id , manifest_data ["manifests" ])
1990- active_manifest = manifest_data ["manifests" ][active_manifest_id ]
1991-
1992- # Verify ingredients array exists in active manifest
1993- self .assertIn ("ingredients" , active_manifest )
1994- self .assertIsInstance (active_manifest ["ingredients" ], list )
1995- self .assertEqual (len (active_manifest ["ingredients" ]), 5 )
1996-
1997- # Verify all ingredients exist in the array with correct thread IDs
1998- # and unique metadata
1999- ingredient_titles = [ing ["title" ]
2000- for ing in active_manifest ["ingredients" ]]
2001-
2002- # Check that we have 5 unique titles
2003- self .assertEqual (len (set (ingredient_titles )), 5 ,
2004- "Should have 5 unique ingredient titles" )
2005-
2006- # Verify each thread's ingredient exists with correct metadata
2007- for i in range (1 , 6 ):
2008- # Find ingredients with this thread ID
2009- thread_ingredients = [ing for ing in active_manifest ["ingredients" ]
2010- if ing ["title" ] == f"Test Ingredient Thread { i } " ]
2011- self .assertEqual (
2012- len (thread_ingredients ),
2013- 1 ,
2014- f"Should find exactly one ingredient for thread { i } " )
2015-
2016- builder .close ()
2017-
20181821 def test_builder_sign_with_multiple_ingredient_random_many_threads (self ):
20191822 """Test Builder class operations with 12 threads, each adding 3 specific ingredients and signing a file."""
20201823 # Number of threads to use in the test
@@ -2857,118 +2660,6 @@ async def run_async_tests():
28572660 self .fail ("\n " .join (read_errors ))
28582661 self .assertEqual (active_readers , 0 )
28592662
2860- def test_builder_sign_with_multiple_ingredients_from_stream (self ):
2861- """Test Builder with multiple ingredients from streams using context APIs"""
2862- ctx = Context ()
2863- builder = Builder .from_json (self .manifestDefinition , context = ctx )
2864- assert builder ._handle is not None
2865- add_errors = []
2866- add_lock = threading .Lock ()
2867- completed_threads = 0
2868- completion_lock = threading .Lock ()
2869-
2870- def add_ingredient_from_stream (ingredient_json , file_path , thread_id ):
2871- nonlocal completed_threads
2872- try :
2873- with open (file_path , 'rb' ) as f :
2874- builder .add_ingredient_from_stream (ingredient_json , "image/jpeg" , f )
2875- with add_lock :
2876- add_errors .append (None )
2877- except Exception as e :
2878- with add_lock :
2879- add_errors .append (f"Thread { thread_id } error: { str (e )} " )
2880- finally :
2881- with completion_lock :
2882- completed_threads += 1
2883-
2884- thread1 = threading .Thread (target = add_ingredient_from_stream , args = ('{"title": "Test Ingredient Stream 1"}' , self .testPath3 , 1 ))
2885- thread2 = threading .Thread (target = add_ingredient_from_stream , args = ('{"title": "Test Ingredient Stream 2"}' , self .testPath4 , 2 ))
2886- thread1 .start ()
2887- thread2 .start ()
2888- thread1 .join ()
2889- thread2 .join ()
2890- if any (e for e in add_errors if e is not None ):
2891- self .fail ("\n " .join (e for e in add_errors if e is not None ))
2892- self .assertEqual (completed_threads , 2 )
2893- self .assertEqual (len (add_errors ), 2 )
2894- with open (self .testPath2 , "rb" ) as file :
2895- output = io .BytesIO (bytearray ())
2896- builder .sign (self .signer , "image/jpeg" , file , output )
2897- output .seek (0 )
2898- read_ctx = Context ()
2899- reader = Reader ("image/jpeg" , output , context = read_ctx )
2900- json_data = reader .json ()
2901- manifest_data = json .loads (json_data )
2902- self .assertIn ("active_manifest" , manifest_data )
2903- active_manifest_id = manifest_data ["active_manifest" ]
2904- self .assertIn ("manifests" , manifest_data )
2905- self .assertIn (active_manifest_id , manifest_data ["manifests" ])
2906- active_manifest = manifest_data ["manifests" ][active_manifest_id ]
2907- self .assertIn ("ingredients" , active_manifest )
2908- self .assertEqual (len (active_manifest ["ingredients" ]), 2 )
2909- ingredient_titles = [ing ["title" ] for ing in active_manifest ["ingredients" ]]
2910- self .assertIn ("Test Ingredient Stream 1" , ingredient_titles )
2911- self .assertIn ("Test Ingredient Stream 2" , ingredient_titles )
2912- builder .close ()
2913-
2914- def test_builder_sign_with_same_ingredient_multiple_times (self ):
2915- """Test Builder with same ingredient added multiple times from different threads using context APIs"""
2916- ctx = Context ()
2917- builder = Builder .from_json (self .manifestDefinition , context = ctx )
2918- assert builder ._handle is not None
2919- add_errors = []
2920- add_lock = threading .Lock ()
2921- completed_threads = 0
2922- completion_lock = threading .Lock ()
2923-
2924- def add_ingredient (ingredient_json , thread_id ):
2925- nonlocal completed_threads
2926- try :
2927- with open (self .testPath3 , 'rb' ) as f :
2928- builder .add_ingredient (ingredient_json , "image/jpeg" , f )
2929- with add_lock :
2930- add_errors .append (None )
2931- except Exception as e :
2932- with add_lock :
2933- add_errors .append (f"Thread { thread_id } error: { str (e )} " )
2934- finally :
2935- with completion_lock :
2936- completed_threads += 1
2937-
2938- threads = []
2939- for i in range (1 , 6 ):
2940- ingredient_json = json .dumps ({"title" : f"Test Ingredient Thread { i } " })
2941- thread = threading .Thread (target = add_ingredient , args = (ingredient_json , i ))
2942- threads .append (thread )
2943- thread .start ()
2944- for thread in threads :
2945- thread .join ()
2946- if any (e for e in add_errors if e is not None ):
2947- self .fail ("\n " .join (e for e in add_errors if e is not None ))
2948- self .assertEqual (completed_threads , 5 )
2949- self .assertEqual (len (add_errors ), 5 )
2950- with open (self .testPath2 , "rb" ) as file :
2951- output = io .BytesIO (bytearray ())
2952- builder .sign (self .signer , "image/jpeg" , file , output )
2953- output .seek (0 )
2954- read_ctx = Context ()
2955- reader = Reader ("image/jpeg" , output , context = read_ctx )
2956- json_data = reader .json ()
2957- manifest_data = json .loads (json_data )
2958- self .assertIn ("active_manifest" , manifest_data )
2959- active_manifest_id = manifest_data ["active_manifest" ]
2960- self .assertIn ("manifests" , manifest_data )
2961- self .assertIn (active_manifest_id , manifest_data ["manifests" ])
2962- active_manifest = manifest_data ["manifests" ][active_manifest_id ]
2963- self .assertIn ("ingredients" , active_manifest )
2964- self .assertEqual (len (active_manifest ["ingredients" ]), 5 )
2965- ingredient_titles = [ing ["title" ] for ing in active_manifest ["ingredients" ]]
2966- self .assertEqual (len (set (ingredient_titles )), 5 )
2967- for i in range (1 , 6 ):
2968- thread_ingredients = [ing for ing in active_manifest ["ingredients" ] if ing ["title" ] == f"Test Ingredient Thread { i } " ]
2969- self .assertEqual (len (thread_ingredients ), 1 )
2970- builder .close ()
2971-
29722663 def test_builder_sign_with_multiple_ingredient_random_many_threads (self ):
29732664 """Test Builder with 12 threads adding ingredients and signing using context APIs"""
29742665 TOTAL_THREADS_USED = 12
0 commit comments