@@ -29,6 +29,13 @@ class TargetTest:
2929 targetpath : str
3030
3131
32+ @dataclass
33+ class TargetTestCase :
34+ targetpath : str
35+ found : bool
36+ visited_order : list [str ] = field (default_factory = list )
37+
38+
3239@dataclass
3340class DelegationsTestCase :
3441 """A delegations graph as lists of delegations and target files
@@ -41,6 +48,7 @@ class DelegationsTestCase:
4148
4249# DataSet is only here so type hints can be used.
4350DataSet = dict [str , DelegationsTestCase ]
51+ DataSetTarget = dict [str , TargetTestCase ]
4452
4553
4654graphs : DataSet = {
@@ -194,3 +202,75 @@ def test_graph_traversal(
194202 # "('root', 2), ('timestamp', None)" gets prepended
195203 # in every case, so we compare from the 3rd item in the list.
196204 assert repo .metadata_statistics [2 :] == exp_calls
205+
206+
207+ r"""
208+ Create a single repository with the following delegations:
209+
210+ targets
211+ *.doc, *md / \ release/*/*
212+ A B
213+ release/x/* / \ release/y/*.zip
214+ C D
215+
216+ Test that Updater successfully finds the target files metadata,
217+ traversing the delegations as expected.
218+ """
219+ delegations_tree = DelegationsTestCase (
220+ delegations = [
221+ DelegationTester ("targets" , "A" , paths = ["*.doc" , "*.md" ]),
222+ DelegationTester ("targets" , "B" , paths = ["releases/*/*" ]),
223+ DelegationTester ("B" , "C" , paths = ["releases/x/*" ]),
224+ DelegationTester ("B" , "D" , paths = ["releases/y/*.zip" ]),
225+ ],
226+ target_files = [
227+ TargetTest ("targets" , b"targetfile content" , "targetfile" ),
228+ TargetTest ("A" , b"README by A" , "README.md" ),
229+ TargetTest ("C" , b"x release by C" , "releases/x/x_v1" ),
230+ TargetTest ("D" , b"y release by D" , "releases/y/y_v1.zip" ),
231+ TargetTest ("D" , b"z release by D" , "releases/z/z_v1.zip" ),
232+ ],
233+ )
234+
235+ targets : DataSetTarget = {
236+ "no delegations" : TargetTestCase ("targetfile" , True , []),
237+ "targetpath matches wildcard" : TargetTestCase ("README.md" , True , ["A" ]),
238+ "targetpath with separators x" : TargetTestCase ("releases/x/x_v1" , True , ["B" , "C" ]),
239+ "targetpath with separators y" : TargetTestCase (
240+ "releases/y/y_v1.zip" , True , ["B" , "D" ]
241+ ),
242+ "targetpath is not delegated by all roles in the chain" : TargetTestCase (
243+ "releases/z/z_v1.zip" , False , ["B" ]
244+ ),
245+ }
246+
247+
248+ targets_ids = targets .keys ()
249+ targets_cases = targets .values ()
250+
251+
252+ @pytest .mark .parametrize ("target" , targets_cases , ids = targets_ids )
253+ def test_targetfile_search (
254+ client : ClientRunner , server : SimulatorServer , target : TargetTestCase
255+ ) -> None :
256+ exp_calls = [(role , 1 ) for role in target .visited_order ]
257+
258+ init_data , repo = server .new_test (client .test_name )
259+ assert client .init_client (init_data ) == 0
260+ init_repo (repo , delegations_tree )
261+
262+ # Call explicitly refresh to simplify the expected_calls list
263+ assert client .refresh (init_data ) == 0
264+ repo .metadata_statistics .clear ()
265+ if target .found :
266+ assert client .download_target (init_data , target .targetpath ) == 0
267+ assert client .get_downloaded_target_bytes () == [
268+ repo .artifacts [target .targetpath ].data
269+ ]
270+ else :
271+ assert client .download_target (init_data , target .targetpath ) == 1
272+
273+ # repo prepends [('root', 2), ('timestamp', None)]
274+ # so we compare equality from the 2nd call to the 3rd-last
275+ # call.
276+ assert repo .metadata_statistics [2 :] == exp_calls
0 commit comments