@@ -32,7 +32,7 @@ class TestDelegation:
3232 keyids : List [str ] = field (default_factory = list )
3333 threshold : int = 1
3434 terminating : bool = False
35- paths : List [str ] = field (default_factory = lambda : ["*" ])
35+ paths : Optional [ List [str ] ] = field (default_factory = lambda : ["*" ])
3636 path_hash_prefixes : Optional [List [str ]] = None
3737
3838
@@ -362,6 +362,69 @@ def test_safely_encoded_rolenames(self) -> None:
362362 exp_calls = [(quoted [:- 5 ], 1 ) for quoted in roles_to_filenames .values ()]
363363 self .assertListEqual (self .sim .fetch_tracker .metadata , exp_calls )
364364
365+ hash_bins_graph : utils .DataSet = {
366+ "delegations" : DelegationsTestCase (
367+ delegations = [
368+ TestDelegation (
369+ "targets" ,
370+ "role1" ,
371+ paths = None ,
372+ path_hash_prefixes = ["8" , "9" , "a" , "b" ],
373+ ),
374+ TestDelegation (
375+ "targets" ,
376+ "role2" ,
377+ paths = None ,
378+ path_hash_prefixes = ["0" , "1" , "2" , "3" ],
379+ ),
380+ TestDelegation (
381+ "targets" ,
382+ "role3" ,
383+ paths = None ,
384+ path_hash_prefixes = ["c" , "d" , "e" , "f" ],
385+ ),
386+ ],
387+ visited_order = ["role1" , "role2" , "role3" ],
388+ ),
389+ }
390+
391+ @utils .run_sub_tests_with_dataset (hash_bins_graph )
392+ def test_hash_bins_graph_traversal (
393+ self , test_data : DelegationsTestCase
394+ ) -> None :
395+ """Test that delegated roles are traversed in the order of appearance
396+ in the delegator's metadata, using pre-order depth-first search and that
397+ they correctly reffer to the corresponding hash bin prefixes"""
398+
399+ try :
400+ exp_files = [* TOP_LEVEL_ROLE_NAMES , * test_data .visited_order ]
401+ exp_calls = [(role , 1 ) for role in test_data .visited_order ]
402+
403+ self ._init_repo (test_data )
404+ self .setup_subtest ()
405+
406+ updater = self ._init_updater ()
407+ # Call explicitly refresh to simplify the expected_calls list
408+ updater .refresh ()
409+ self .sim .fetch_tracker .metadata .clear ()
410+ # Check that metadata dir contains only top-level roles
411+ self ._assert_files_exist (TOP_LEVEL_ROLE_NAMES )
412+
413+ # Looking for a non-existing targetpath forces updater
414+ # to visit a correspondning delegated role
415+ targetfile = updater .get_targetinfo ("missingpath" )
416+ self .assertIsNone (targetfile )
417+ targetfile = updater .get_targetinfo ("othermissingpath" )
418+ self .assertIsNone (targetfile )
419+ targetfile = updater .get_targetinfo ("thirdmissingpath" )
420+ self .assertIsNone (targetfile )
421+ # Check that the delegated roles were visited in the expected
422+ # order and the corresponding metadata files were persisted
423+ self .assertListEqual (self .sim .fetch_tracker .metadata , exp_calls )
424+ self ._assert_files_exist (exp_files )
425+ finally :
426+ self .teardown_subtest ()
427+
365428
366429class TestTargetFileSearch (TestDelegations ):
367430 r"""
0 commit comments