77
88import builtins
99import datetime
10+ import logging
1011import os
1112import sys
1213import tempfile
@@ -62,10 +63,6 @@ def setUp(self) -> None:
6263
6364 self .sim = RepositorySimulator ()
6465
65- # boostrap client with initial root metadata
66- with open (os .path .join (self .metadata_dir , "root.json" ), "bw" ) as f :
67- f .write (self .sim .signed_roots [0 ])
68-
6966 if self .dump_dir is not None :
7067 # create test specific dump directory
7168 name = self .id ().split ("." )[- 1 ]
@@ -75,22 +72,13 @@ def setUp(self) -> None:
7572 def tearDown (self ) -> None :
7673 self .temp_dir .cleanup ()
7774
78- def _run_refresh (self ) -> Updater :
75+ def _run_refresh (self , skip_bootstrap : bool = False ) -> Updater :
7976 """Create a new Updater instance and refresh"""
80- if self .dump_dir is not None :
81- self .sim .write ()
82-
83- updater = Updater (
84- self .metadata_dir ,
85- "https://example.com/metadata/" ,
86- self .targets_dir ,
87- "https://example.com/targets/" ,
88- self .sim ,
89- )
77+ updater = self ._init_updater (skip_bootstrap )
9078 updater .refresh ()
9179 return updater
9280
93- def _init_updater (self ) -> Updater :
81+ def _init_updater (self , skip_bootstrap : bool = False ) -> Updater :
9482 """Create a new Updater instance"""
9583 if self .dump_dir is not None :
9684 self .sim .write ()
@@ -101,6 +89,7 @@ def _init_updater(self) -> Updater:
10189 self .targets_dir ,
10290 "https://example.com/targets/" ,
10391 self .sim ,
92+ bootstrap = None if skip_bootstrap else self .sim .signed_roots [0 ]
10493 )
10594
10695 def _assert_files_exist (self , roles : Iterable [str ]) -> None :
@@ -126,9 +115,6 @@ def _assert_version_equals(self, role: str, expected_version: int) -> None:
126115 self .assertEqual (md .signed .version , expected_version )
127116
128117 def test_first_time_refresh (self ) -> None :
129- # Metadata dir contains only the mandatory initial root.json
130- self ._assert_files_exist ([Root .type ])
131-
132118 # Add one more root version to repository so that
133119 # refresh() updates from local trusted root (v1) to
134120 # remote root (v2)
@@ -142,10 +128,11 @@ def test_first_time_refresh(self) -> None:
142128 version = 2 if role == Root .type else None
143129 self ._assert_content_equals (role , version )
144130
145- def test_trusted_root_missing (self ) -> None :
146- os .remove (os .path .join (self .metadata_dir , "root.json" ))
131+ def test_cached_root_missing_without_bootstrap (self ) -> None :
132+ # Run update without a bootstrap, with empty cache: this fails since there is no
133+ # trusted root
147134 with self .assertRaises (OSError ):
148- self ._run_refresh ()
135+ self ._run_refresh (skip_bootstrap = True )
149136
150137 # Metadata dir is empty
151138 self .assertFalse (os .listdir (self .metadata_dir ))
@@ -178,15 +165,15 @@ def test_trusted_root_expired(self) -> None:
178165 self ._assert_files_exist (TOP_LEVEL_ROLE_NAMES )
179166 self ._assert_content_equals (Root .type , 3 )
180167
181- def test_trusted_root_unsigned (self ) -> None :
182- # Local trusted root is not signed
168+ def test_trusted_root_unsigned_without_bootstrap (self ) -> None :
169+ # Cached root is not signed, bootstrap root is not used
183170 root_path = os .path .join (self .metadata_dir , "root.json" )
184- md_root = Metadata .from_file ( root_path )
171+ md_root = Metadata .from_bytes ( self . sim . signed_roots [ 0 ] )
185172 md_root .signatures .clear ()
186173 md_root .to_file (root_path )
187174
188175 with self .assertRaises (UnsignedMetadataError ):
189- self ._run_refresh ()
176+ self ._run_refresh (skip_bootstrap = True )
190177
191178 # The update failed, no changes in metadata
192179 self ._assert_files_exist ([Root .type ])
@@ -204,10 +191,7 @@ def test_max_root_rotations(self) -> None:
204191 self .sim .root .version += 1
205192 self .sim .publish_root ()
206193
207- md_root = Metadata .from_file (
208- os .path .join (self .metadata_dir , "root.json" )
209- )
210- initial_root_version = md_root .signed .version
194+ initial_root_version = 1
211195
212196 updater .refresh ()
213197
@@ -712,26 +696,18 @@ def test_load_metadata_from_cache(self, wrapped_open: MagicMock) -> None:
712696 updater = self ._run_refresh ()
713697 updater .get_targetinfo ("non_existent_target" )
714698
715- # Clean up calls to open during refresh()
699+ # Clear statistics for calls and metadata requests
716700 wrapped_open .reset_mock ()
717- # Clean up fetch tracker metadata
718701 self .sim .fetch_tracker .metadata .clear ()
719702
720703 # Create a new updater and perform a second update while
721704 # the metadata is already stored in cache (metadata dir)
722- updater = Updater (
723- self .metadata_dir ,
724- "https://example.com/metadata/" ,
725- self .targets_dir ,
726- "https://example.com/targets/" ,
727- self .sim ,
728- )
705+ updater = self ._init_updater ()
729706 updater .get_targetinfo ("non_existent_target" )
730707
731708 # Test that metadata is loaded from cache and not downloaded
732709 wrapped_open .assert_has_calls (
733710 [
734- call (os .path .join (self .metadata_dir , "root.json" ), "rb" ),
735711 call (os .path .join (self .metadata_dir , "root_history/2.root.json" ), "rb" ),
736712 call (os .path .join (self .metadata_dir , "timestamp.json" ), "rb" ),
737713 call (os .path .join (self .metadata_dir , "snapshot.json" ), "rb" ),
0 commit comments