16
16
from tuf .api .metadata import (
17
17
SPECIFICATION_VERSION ,
18
18
TOP_LEVEL_ROLE_NAMES ,
19
+ DelegatedRole ,
19
20
TargetFile ,
20
21
Targets ,
21
22
)
@@ -27,17 +28,40 @@ class TestConsistentSnapshot(unittest.TestCase):
27
28
'prefix_targets_with_hash' and verify that the correct URLs
28
29
are formed for each combination"""
29
30
31
+ # set dump_dir to trigger repository state dumps
32
+ dump_dir : Optional [str ] = None
33
+
30
34
def setUp (self ) -> None :
31
35
# pylint: disable=consider-using-with
36
+ self .subtest_count = 0
32
37
self .temp_dir = tempfile .TemporaryDirectory ()
33
38
self .metadata_dir = os .path .join (self .temp_dir .name , "metadata" )
34
39
self .targets_dir = os .path .join (self .temp_dir .name , "targets" )
35
40
os .mkdir (self .metadata_dir )
36
41
os .mkdir (self .targets_dir )
42
+ self .sim : RepositorySimulator
37
43
38
44
def tearDown (self ) -> None :
39
45
self .temp_dir .cleanup ()
40
46
47
+ def setup_subtest (
48
+ self , consistent_snapshot : bool , prefix_targets : bool = True
49
+ ) -> None :
50
+ self .sim = self ._init_repo (consistent_snapshot , prefix_targets )
51
+
52
+ self .subtest_count += 1
53
+ if self .dump_dir is not None :
54
+ # create subtest dumpdir
55
+ name = f"{ self .id ().split ('.' )[- 1 ]} -{ self .subtest_count } "
56
+ self .sim .dump_dir = os .path .join (self .dump_dir , name )
57
+ os .mkdir (self .sim .dump_dir )
58
+
59
+ def teardown_subtest (self ) -> None :
60
+ if self .dump_dir is not None :
61
+ self .sim .write ()
62
+
63
+ utils .cleanup_dir (self .metadata_dir )
64
+
41
65
def _init_repo (
42
66
self , consistent_snapshot : bool , prefix_targets : bool = True
43
67
) -> RepositorySimulator :
@@ -54,24 +78,16 @@ def _init_repo(
54
78
55
79
return sim
56
80
57
- def _init_updater (self , sim : RepositorySimulator ) -> Updater :
81
+ def _init_updater (self ) -> Updater :
58
82
"""Create a new Updater instance"""
59
83
return Updater (
60
84
self .metadata_dir ,
61
85
"https://example.com/metadata/" ,
62
86
self .targets_dir ,
63
87
"https://example.com/targets/" ,
64
- sim ,
88
+ self . sim ,
65
89
)
66
90
67
- @staticmethod
68
- def _cleanup_dir (path : str ) -> None :
69
- """Delete all files inside a directory"""
70
- for filepath in [
71
- os .path .join (path , filename ) for filename in os .listdir (path )
72
- ]:
73
- os .remove (filepath )
74
-
75
91
def _assert_metadata_files_exist (self , roles : Iterable [str ]) -> None :
76
92
"""Assert that local metadata files exist for 'roles'"""
77
93
local_metadata_files = os .listdir (self .metadata_dir )
@@ -111,22 +127,23 @@ def test_top_level_roles_update(
111
127
) -> None :
112
128
# Test if the client fetches and stores metadata files with the
113
129
# correct version prefix, depending on 'consistent_snapshot' config
114
- consistent_snapshot : bool = test_case_data ["consistent_snapshot" ]
115
- expected_calls : List [Any ] = test_case_data ["calls" ]
116
-
117
- sim = self ._init_repo (consistent_snapshot )
118
- updater = self ._init_updater (sim )
130
+ try :
131
+ consistent_snapshot : bool = test_case_data ["consistent_snapshot" ]
132
+ exp_calls : List [Any ] = test_case_data ["calls" ]
119
133
120
- # cleanup fetch tracker metadata
121
- sim .fetch_tracker .metadata .clear ()
122
- updater .refresh ()
134
+ self .setup_subtest (consistent_snapshot )
135
+ updater = self ._init_updater ()
123
136
124
- # metadata files are fetched with the expected version (or None)
125
- self .assertListEqual (sim .fetch_tracker .metadata , expected_calls )
126
- # metadata files are always persisted without a version prefix
127
- self ._assert_metadata_files_exist (TOP_LEVEL_ROLE_NAMES )
137
+ # cleanup fetch tracker metadata
138
+ self .sim .fetch_tracker .metadata .clear ()
139
+ updater .refresh ()
128
140
129
- self ._cleanup_dir (self .metadata_dir )
141
+ # metadata files are fetched with the expected version (or None)
142
+ self .assertListEqual (self .sim .fetch_tracker .metadata , exp_calls )
143
+ # metadata files are always persisted without a version prefix
144
+ self ._assert_metadata_files_exist (TOP_LEVEL_ROLE_NAMES )
145
+ finally :
146
+ self .teardown_subtest ()
130
147
131
148
delegated_roles_data : utils .DataSet = {
132
149
"consistent_snaphot disabled" : {
@@ -145,31 +162,35 @@ def test_delegated_roles_update(
145
162
) -> None :
146
163
# Test if the client fetches and stores delegated metadata files with
147
164
# the correct version prefix, depending on 'consistent_snapshot' config
148
- consistent_snapshot : bool = test_case_data ["consistent_snapshot" ]
149
- expected_version : Optional [int ] = test_case_data ["expected_version" ]
150
- rolenames = ["role1" , ".." , "." ]
151
- expected_calls = [(role , expected_version ) for role in rolenames ]
152
-
153
- sim = self ._init_repo (consistent_snapshot )
154
- # Add new delegated targets
155
- spec_version = "." .join (SPECIFICATION_VERSION )
156
- targets = Targets (1 , spec_version , sim .safe_expiry , {}, None )
157
- for role in rolenames :
158
- sim .add_delegation ("targets" , role , targets , False , ["*" ], None )
159
- sim .update_snapshot ()
160
- updater = self ._init_updater (sim )
161
- updater .refresh ()
162
-
163
- # cleanup fetch tracker metadata
164
- sim .fetch_tracker .metadata .clear ()
165
- # trigger updater to fetch the delegated metadata
166
- updater .get_targetinfo ("anything" )
167
- # metadata files are fetched with the expected version (or None)
168
- self .assertListEqual (sim .fetch_tracker .metadata , expected_calls )
169
- # metadata files are always persisted without a version prefix
170
- self ._assert_metadata_files_exist (rolenames )
171
-
172
- self ._cleanup_dir (self .metadata_dir )
165
+ try :
166
+ consistent_snapshot : bool = test_case_data ["consistent_snapshot" ]
167
+ exp_version : Optional [int ] = test_case_data ["expected_version" ]
168
+ rolenames = ["role1" , ".." , "." ]
169
+ exp_calls = [(role , exp_version ) for role in rolenames ]
170
+
171
+ self .setup_subtest (consistent_snapshot )
172
+ # Add new delegated targets
173
+ spec_version = "." .join (SPECIFICATION_VERSION )
174
+ for role in rolenames :
175
+ delegated_role = DelegatedRole (role , [], 1 , False , ["*" ], None )
176
+ targets = Targets (
177
+ 1 , spec_version , self .sim .safe_expiry , {}, None
178
+ )
179
+ self .sim .add_delegation ("targets" , delegated_role , targets )
180
+ self .sim .update_snapshot ()
181
+ updater = self ._init_updater ()
182
+ updater .refresh ()
183
+
184
+ # cleanup fetch tracker metadata
185
+ self .sim .fetch_tracker .metadata .clear ()
186
+ # trigger updater to fetch the delegated metadata
187
+ updater .get_targetinfo ("anything" )
188
+ # metadata files are fetched with the expected version (or None)
189
+ self .assertListEqual (self .sim .fetch_tracker .metadata , exp_calls )
190
+ # metadata files are always persisted without a version prefix
191
+ self ._assert_metadata_files_exist (rolenames )
192
+ finally :
193
+ self .teardown_subtest ()
173
194
174
195
targets_download_data : utils .DataSet = {
175
196
"consistent_snaphot disabled" : {
@@ -197,42 +218,49 @@ def test_download_targets(self, test_case_data: Dict[str, Any]) -> None:
197
218
# Test if the client fetches and stores target files with
198
219
# the correct hash prefix, depending on 'consistent_snapshot'
199
220
# and 'prefix_targets_with_hash' config
200
- consistent_snapshot : bool = test_case_data ["consistent_snapshot" ]
201
- prefix_targets_with_hash : bool = test_case_data ["prefix_targets" ]
202
- hash_algo : Optional [str ] = test_case_data ["hash_algo" ]
203
- targetpaths : List [str ] = test_case_data ["targetpaths" ]
204
-
205
- sim = self ._init_repo (consistent_snapshot , prefix_targets_with_hash )
206
- # Add targets to repository
207
- for targetpath in targetpaths :
208
- sim .targets .version += 1
209
- sim .add_target ("targets" , b"content" , targetpath )
210
- sim .update_snapshot ()
211
-
212
- updater = self ._init_updater (sim )
213
- updater .config .prefix_targets_with_hash = prefix_targets_with_hash
214
- updater .refresh ()
215
-
216
- for targetpath in targetpaths :
217
- info = updater .get_targetinfo (targetpath )
218
- assert isinstance (info , TargetFile )
219
- updater .download_target (info )
220
-
221
- # target files are always persisted without hash prefix
222
- self ._assert_targets_files_exist ([info .path ])
223
-
224
- # files are fetched with the expected hash prefix (or None)
225
- expected_fetches = [
226
- (targetpath , None if not hash_algo else info .hashes [hash_algo ])
227
- ]
228
-
229
- self .assertListEqual (sim .fetch_tracker .targets , expected_fetches )
230
- sim .fetch_tracker .targets .clear ()
231
-
232
- self ._cleanup_dir (self .targets_dir )
221
+ try :
222
+ consistent_snapshot : bool = test_case_data ["consistent_snapshot" ]
223
+ prefix_targets_with_hash : bool = test_case_data ["prefix_targets" ]
224
+ hash_algo : Optional [str ] = test_case_data ["hash_algo" ]
225
+ targetpaths : List [str ] = test_case_data ["targetpaths" ]
226
+
227
+ self .setup_subtest (consistent_snapshot , prefix_targets_with_hash )
228
+ # Add targets to repository
229
+ for targetpath in targetpaths :
230
+ self .sim .targets .version += 1
231
+ self .sim .add_target ("targets" , b"content" , targetpath )
232
+ self .sim .update_snapshot ()
233
+
234
+ updater = self ._init_updater ()
235
+ updater .config .prefix_targets_with_hash = prefix_targets_with_hash
236
+ updater .refresh ()
237
+
238
+ for path in targetpaths :
239
+ info = updater .get_targetinfo (path )
240
+ assert isinstance (info , TargetFile )
241
+ updater .download_target (info )
242
+
243
+ # target files are always persisted without hash prefix
244
+ self ._assert_targets_files_exist ([info .path ])
245
+
246
+ # files are fetched with the expected hash prefix (or None)
247
+ exp_calls = [
248
+ (path , None if not hash_algo else info .hashes [hash_algo ])
249
+ ]
250
+
251
+ self .assertListEqual (self .sim .fetch_tracker .targets , exp_calls )
252
+ self .sim .fetch_tracker .targets .clear ()
253
+ finally :
254
+ self .teardown_subtest ()
233
255
234
256
235
257
if __name__ == "__main__" :
258
+ if "--dump" in sys .argv :
259
+ TestConsistentSnapshot .dump_dir = tempfile .mkdtemp ()
260
+ print (
261
+ f"Repository Simulator dumps in { TestConsistentSnapshot .dump_dir } "
262
+ )
263
+ sys .argv .remove ("--dump" )
236
264
237
265
utils .configure_test_logging (sys .argv )
238
266
unittest .main ()
0 commit comments