@@ -142,6 +142,7 @@ def test_invalid_role_serialization(self, test_case_data: Dict[str, str]):
142142 valid_roles : DataSet = {
143143 "all" : '{"keyids": ["keyid"], "threshold": 3}' ,
144144 "many keyids" : '{"keyids": ["a", "b", "c", "d", "e"], "threshold": 1}' ,
145+ "empty keyids" : '{"keyids": [], "threshold": 1}' ,
145146 "unrecognized field" : '{"keyids": ["keyid"], "threshold": 3, "foo": "bar"}' ,
146147 }
147148
@@ -155,14 +156,23 @@ def test_role_serialization(self, test_case_data: str):
155156 valid_roots : DataSet = {
156157 "all" : '{"_type": "root", "spec_version": "1.0.0", "version": 1, \
157158 "expires": "2030-01-01T00:00:00Z", "consistent_snapshot": false, \
158- "keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \
159- "roles": { "targets": {"keyids": ["keyid"], "threshold": 3}} \
159+ "keys": { \
160+ "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}, \
161+ "keyid2" : {"keytype": "ed25519", "scheme": "ed25519", "keyval": {"public": "bar"}}}, \
162+ "roles": { \
163+ "targets": {"keyids": ["keyid1"], "threshold": 1}, \
164+ "snapshot": {"keyids": ["keyid2"], "threshold": 1}} \
160165 }' ,
161166 "no consistent_snapshot" : '{ "_type": "root", "spec_version": "1.0.0", "version": 1, \
162167 "expires": "2030-01-01T00:00:00Z", \
163168 "keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"} }}, \
164169 "roles": { "targets": {"keyids": ["keyid"], "threshold": 3} } \
165170 }' ,
171+ "empty keys and roles" : '{"_type": "root", "spec_version": "1.0.0", "version": 1, \
172+ "expires": "2030-01-01T00:00:00Z", "consistent_snapshot": false, \
173+ "keys": {}, \
174+ "roles": {} \
175+ }' ,
166176 "unrecognized field" : '{"_type": "root", "spec_version": "1.0.0", "version": 1, \
167177 "expires": "2030-01-01T00:00:00Z", "consistent_snapshot": false, \
168178 "keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \
@@ -198,6 +208,7 @@ def test_invalid_metafile_serialization(self, test_case_data: Dict[str, str]):
198208 "no length" : '{"hashes": {"sha256" : "abc"}, "version": 1 }' ,
199209 "no hashes" : '{"length": 12, "version": 1}' ,
200210 "unrecognized field" : '{"hashes": {"sha256" : "abc"}, "length": 12, "version": 1, "foo": "bar"}' ,
211+ "many hashes" : '{"hashes": {"sha256" : "abc", "sha512": "cde"}, "length": 12, "version": 1}' ,
201212 }
202213
203214 @run_sub_tests_with_dataset (valid_metafiles )
@@ -206,6 +217,16 @@ def test_metafile_serialization(self, test_case_data: str):
206217 metafile = MetaFile .from_dict (copy .copy (case_dict ))
207218 self .assertDictEqual (case_dict , metafile .to_dict ())
208219
220+ invalid_timestamps : DataSet = {
221+ "no metafile" : '{ "_type": "timestamp", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z"}' ,
222+ }
223+
224+ @run_sub_tests_with_dataset (invalid_timestamps )
225+ def test_invalid_timestamp_serialization (self , test_case_data : Dict [str , str ]):
226+ case_dict = json .loads (test_case_data )
227+ with self .assertRaises ((ValueError , KeyError )):
228+ Timestamp .from_dict (copy .deepcopy (case_dict ))
229+
209230
210231 valid_timestamps : DataSet = {
211232 "all" : '{ "_type": "timestamp", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
@@ -223,7 +244,13 @@ def test_timestamp_serialization(self, test_case_data: str):
223244
224245 valid_snapshots : DataSet = {
225246 "all" : '{ "_type": "snapshot", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
226- "meta": { "file.txt": { "hashes": {"sha256" : "abc"}, "version": 1 }}}' ,
247+ "meta": { \
248+ "file1.txt": {"hashes": {"sha256" : "abc"}, "version": 1}, \
249+ "file2.txt": {"hashes": {"sha256" : "cde"}, "version": 1} \
250+ }}' ,
251+ "empty meta" : '{ "_type": "snapshot", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
252+ "meta": {} \
253+ }' ,
227254 "unrecognized field" : '{ "_type": "snapshot", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
228255 "meta": { "file.txt": { "hashes": {"sha256" : "abc"}, "version": 1 }}, "foo": "bar"}' ,
229256 }
@@ -236,15 +263,22 @@ def test_snapshot_serialization(self, test_case_data: str):
236263
237264
238265 valid_delegated_roles : DataSet = {
266+ # DelegatedRole inherits Role and some use cases can be found in the valid_roles.
239267 "no hash prefix attribute" :
240268 '{"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], \
241269 "terminating": false, "threshold": 1}' ,
242270 "no path attribute" :
243271 '{"keyids": ["keyid"], "name": "a", "terminating": false, \
244272 "path_hash_prefixes": ["h1", "h2"], "threshold": 99}' ,
273+ "empty paths" : '{"keyids": ["keyid"], "name": "a", "paths": [], \
274+ "terminating": false, "threshold": 1}' ,
275+ "empty path_hash_prefixes" : '{"keyids": ["keyid"], "name": "a", "terminating": false, \
276+ "path_hash_prefixes": [], "threshold": 99}' ,
245277 "unrecognized field" :
246- '{"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], \
247- "terminating": true, "threshold": 3, "foo": "bar"}' ,
278+ '{"keyids": ["keyid"], "name": "a", "terminating": true, "paths": ["fn1"], "threshold": 3, "foo": "bar"}' ,
279+ "many keyids" :
280+ '{"keyids": ["keyid1", "keyid2"], "name": "a", "paths": ["fn1", "fn2"], \
281+ "terminating": false, "threshold": 1}' ,
248282 }
249283
250284 @run_sub_tests_with_dataset (valid_delegated_roles )
@@ -255,6 +289,7 @@ def test_delegated_role_serialization(self, test_case_data: str):
255289
256290
257291 invalid_delegated_roles : DataSet = {
292+ # DelegatedRole inherits Role and some use cases can be found in the invalid_roles.
258293 "missing hash prefixes and paths" :
259294 '{"name": "a", "keyids": ["keyid"], "threshold": 1, "terminating": false}' ,
260295 "both hash prefixes and paths" :
@@ -270,12 +305,21 @@ def test_invalid_delegated_role_serialization(self, test_case_data: str):
270305
271306
272307 valid_delegations : DataSet = {
273- "all" : '{"keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \
274- "roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ]}' ,
308+ "all" :
309+ '{"keys": { \
310+ "keyid1" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}, \
311+ "keyid2" : {"keytype": "ed25519", "scheme": "ed25519", "keyval": {"public": "bar"}}}, \
312+ "roles": [ \
313+ {"keyids": ["keyid"], "name": "a", "terminating": true, "paths": ["fn1"], "threshold": 3}, \
314+ {"keyids": ["keyid2"], "name": "b", "terminating": true, "paths": ["fn2"], "threshold": 4} ] \
315+ }' ,
275316 "unrecognized field" :
276317 '{"keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \
277318 "roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ], \
278319 "foo": "bar"}' ,
320+ "empty keys and roles" : '{"keys": {}, \
321+ "roles": [] \
322+ }' ,
279323 }
280324
281325 @run_sub_tests_with_dataset (valid_delegations )
@@ -316,11 +360,17 @@ def test_targetfile_serialization(self, test_case_data: str):
316360
317361 valid_targets : DataSet = {
318362 "all attributes" : '{"_type": "targets", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
319- "targets": { "file.txt": {"length": 12, "hashes": {"sha256" : "abc"} } }, \
320- "delegations": {"keys": {"keyid" : {"keytype": "rsa", \
321- "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"} }}, \
322- "roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ]} \
323- }' ,
363+ "targets": { \
364+ "file.txt": {"length": 12, "hashes": {"sha256" : "abc"} }, \
365+ "file2.txt": {"length": 50, "hashes": {"sha256" : "cde"} } }, \
366+ "delegations": { \
367+ "keys": { \
368+ "keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}, \
369+ "keyid2": {"keytype": "ed25519", "scheme": "ed25519", "keyval": {"public": "bar"}}}, \
370+ "roles": [ \
371+ {"keyids": ["keyid"], "name": "a", "terminating": true, "paths": ["fn1"], "threshold": 3}, \
372+ {"keyids": ["keyid2"], "name": "b", "terminating": true, "paths": ["fn2"], "threshold": 4} ] \
373+ }}' ,
324374 "empty targets" : '{"_type": "targets", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
325375 "targets": {}, \
326376 "delegations": {"keys": {"keyid" : {"keytype": "rsa", \
0 commit comments