|
17 | 17 |
|
18 | 18 | from datetime import datetime, timedelta
|
19 | 19 | from dateutil.relativedelta import relativedelta
|
| 20 | +from typing import Any, Dict |
20 | 21 |
|
21 | 22 | from tests import utils
|
22 | 23 |
|
@@ -453,43 +454,40 @@ def test_metadata_targets(self):
|
453 | 454 | tar_d = targets_obj.to_dict()
|
454 | 455 | self.assertEqual(targets_dict["signed"], targets_obj.to_dict())
|
455 | 456 |
|
456 |
| - def setup_dict_with_unrecognized_field(self, file_path, field, value): |
457 |
| - json_dict = {} |
458 |
| - with open(file_path) as f: |
459 |
| - json_dict = json.loads(f.read()) |
460 |
| - # We are changing the json dict without changing the signature. |
461 |
| - # This could be a problem if we want to do verification on this dict. |
462 |
| - json_dict["signed"][field] = value |
463 |
| - return json_dict |
| 457 | + # Insert item into every dictionary in signed (where allowed by spec) |
| 458 | + @staticmethod |
| 459 | + def poison_signed(signed: Dict[str, Any], key: str): |
| 460 | + named_dicts = [("signed", signed)] |
| 461 | + while named_dicts: |
| 462 | + name, container = named_dicts.pop() |
| 463 | + |
| 464 | + # Process all child dicts. spec does not contain any |
| 465 | + # dicts inside arrays so no need to check those |
| 466 | + for valname, value in container.items(): |
| 467 | + if isinstance(value, dict): |
| 468 | + named_dicts.append((valname, value)) |
| 469 | + |
| 470 | + # if dicts keys are limited in spec or if dicts values are |
| 471 | + # strictly defined, skip it |
| 472 | + if name in ["hashes", "keys", "meta", "roles", "targets"]: |
| 473 | + continue |
| 474 | + |
| 475 | + # Add a custom item to this dict |
| 476 | + container[key]="dummyvalue" |
464 | 477 |
|
465 | 478 | def test_support_for_unrecognized_fields(self):
|
466 | 479 | for metadata in ["root", "timestamp", "snapshot", "targets"]:
|
467 | 480 | path = os.path.join(self.repo_dir, "metadata", metadata + ".json")
|
468 |
| - dict1 = self.setup_dict_with_unrecognized_field(path, "f", "b") |
469 |
| - # Test that the metadata classes store unrecognized fields when |
470 |
| - # initializing and passes them when casting the instance to a dict. |
471 |
| - |
472 |
| - # Add unrecognized fields to all metadata sub (helper) classes. |
473 |
| - if metadata == "root": |
474 |
| - for keyid in dict1["signed"]["keys"].keys(): |
475 |
| - dict1["signed"]["keys"][keyid]["d"] = "c" |
476 |
| - for role_str in dict1["signed"]["roles"].keys(): |
477 |
| - dict1["signed"]["roles"][role_str]["e"] = "g" |
478 |
| - |
479 |
| - temp_copy = copy.deepcopy(dict1) |
480 |
| - metadata_obj = Metadata.from_dict(temp_copy) |
481 |
| - |
482 |
| - self.assertEqual(dict1["signed"], metadata_obj.signed.to_dict()) |
483 |
| - |
484 |
| - # Test that two instances of the same class could have different |
485 |
| - # unrecognized fields. |
486 |
| - dict2 = self.setup_dict_with_unrecognized_field(path, "f2", "b2") |
487 |
| - temp_copy2 = copy.deepcopy(dict2) |
488 |
| - metadata_obj2 = Metadata.from_dict(temp_copy2) |
489 |
| - self.assertNotEqual( |
490 |
| - metadata_obj.signed.to_dict(), metadata_obj2.signed.to_dict() |
491 |
| - ) |
| 481 | + with open(path) as f: |
| 482 | + json_dict = json.loads(f.read()) |
| 483 | + |
| 484 | + # insert extra items into signed |
| 485 | + self.poison_signed(json_dict["signed"], "keythatwontcollide") |
492 | 486 |
|
| 487 | + # All unrecognized fields should stay intact through a |
| 488 | + # deserialize/serialize cycle |
| 489 | + md = Metadata.from_dict(copy.deepcopy(json_dict)) |
| 490 | + self.assertEqual(json_dict["signed"], md.signed.to_dict()) |
493 | 491 |
|
494 | 492 | # Run unit test.
|
495 | 493 | if __name__ == '__main__':
|
|
0 commit comments