Skip to content

Commit 2bbf5bc

Browse files
author
Jussi Kukkonen
committed
tests: Cleanup in new Updater tests
Add test for a refresh with just a local root.json. Remove unused code. Add docstrings for raised exceptions, add TODOs for the missing exception handling. Signed-off-by: Jussi Kukkonen <[email protected]>
1 parent 1d45c2a commit 2bbf5bc

File tree

2 files changed

+31
-75
lines changed

2 files changed

+31
-75
lines changed

tests/test_updater_rework.py

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -122,38 +122,17 @@ def setUp(self):
122122
metadata_url,
123123
targets_url)
124124

125-
# Metadata role keys are needed by the test cases to make changes to the
126-
# repository (e.g., adding a new target file to 'targets.json' and then
127-
# requesting a refresh()).
128-
self.role_keys = _load_role_keys(self.keystore_directory)
129-
130-
131-
132125
def tearDown(self):
133126
# We are inheriting from custom class.
134127
unittest_toolbox.Modified_TestCase.tearDown(self)
135128

136129
# Logs stdout and stderr from the sever subprocess.
137130
self.server_process_handler.flush_log()
138131

139-
140-
141-
# UNIT TESTS.
142132
def test_refresh(self):
143133

144134
self.repository_updater.refresh()
145135

146-
for role in ['root', 'timestamp', 'snapshot', 'targets']:
147-
metadata_obj = metadata.Metadata.from_file(os.path.join(
148-
self.client_directory, role + '.json'))
149-
150-
metadata_obj_2 = metadata.Metadata.from_file(os.path.join(
151-
self.repository_directory, 'metadata', role + '.json'))
152-
153-
154-
self.assertDictEqual(metadata_obj.to_dict(),
155-
metadata_obj_2.to_dict())
156-
157136
# Get targetinfo for 'file1.txt' listed in targets
158137
targetinfo1 = self.repository_updater.get_one_valid_targetinfo('file1.txt')
159138
# Get targetinfo for 'file3.txt' listed in the delegated role1
@@ -178,60 +157,16 @@ def test_refresh(self):
178157

179158
self.assertListEqual(updated_targets, [])
180159

160+
def test_refresh_with_only_local_root(self):
161+
os.remove(os.path.join(self.client_directory, "timestamp.json"))
162+
os.remove(os.path.join(self.client_directory, "snapshot.json"))
163+
os.remove(os.path.join(self.client_directory, "targets.json"))
164+
os.remove(os.path.join(self.client_directory, "role1.json"))
165+
166+
self.repository_updater.refresh()
181167

182-
def _load_role_keys(keystore_directory):
183-
184-
# Populating 'self.role_keys' by importing the required public and private
185-
# keys of 'tuf/tests/repository_data/'. The role keys are needed when
186-
# modifying the remote repository used by the test cases in this unit test.
187-
188-
# The pre-generated key files in 'repository_data/keystore' are all encrypted with
189-
# a 'password' passphrase.
190-
EXPECTED_KEYFILE_PASSWORD = 'password'
191-
192-
# Store and return the cryptography keys of the top-level roles, including 1
193-
# delegated role.
194-
role_keys = {}
195-
196-
root_key_file = os.path.join(keystore_directory, 'root_key')
197-
targets_key_file = os.path.join(keystore_directory, 'targets_key')
198-
snapshot_key_file = os.path.join(keystore_directory, 'snapshot_key')
199-
timestamp_key_file = os.path.join(keystore_directory, 'timestamp_key')
200-
delegation_key_file = os.path.join(keystore_directory, 'delegation_key')
201-
202-
role_keys = {'root': {}, 'targets': {}, 'snapshot': {}, 'timestamp': {},
203-
'role1': {}}
204-
205-
# Import the top-level and delegated role public keys.
206-
role_keys['root']['public'] = \
207-
repo_tool.import_rsa_publickey_from_file(root_key_file+'.pub')
208-
role_keys['targets']['public'] = \
209-
repo_tool.import_ed25519_publickey_from_file(targets_key_file+'.pub')
210-
role_keys['snapshot']['public'] = \
211-
repo_tool.import_ed25519_publickey_from_file(snapshot_key_file+'.pub')
212-
role_keys['timestamp']['public'] = \
213-
repo_tool.import_ed25519_publickey_from_file(timestamp_key_file+'.pub')
214-
role_keys['role1']['public'] = \
215-
repo_tool.import_ed25519_publickey_from_file(delegation_key_file+'.pub')
216-
217-
# Import the private keys of the top-level and delegated roles.
218-
role_keys['root']['private'] = \
219-
repo_tool.import_rsa_privatekey_from_file(root_key_file,
220-
EXPECTED_KEYFILE_PASSWORD)
221-
role_keys['targets']['private'] = \
222-
repo_tool.import_ed25519_privatekey_from_file(targets_key_file,
223-
EXPECTED_KEYFILE_PASSWORD)
224-
role_keys['snapshot']['private'] = \
225-
repo_tool.import_ed25519_privatekey_from_file(snapshot_key_file,
226-
EXPECTED_KEYFILE_PASSWORD)
227-
role_keys['timestamp']['private'] = \
228-
repo_tool.import_ed25519_privatekey_from_file(timestamp_key_file,
229-
EXPECTED_KEYFILE_PASSWORD)
230-
role_keys['role1']['private'] = \
231-
repo_tool.import_ed25519_privatekey_from_file(delegation_key_file,
232-
EXPECTED_KEYFILE_PASSWORD)
233-
234-
return role_keys
168+
# Get targetinfo for 'file3.txt' listed in the delegated role1
169+
targetinfo3= self.repository_updater.get_one_valid_targetinfo('file3.txt')
235170

236171
if __name__ == '__main__':
237172
utils.configure_test_logging(sys.argv)

tuf/client_rework/updater_rework.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,17 @@ def __init__(
4848
):
4949
"""
5050
Args:
51-
repository_dir: Local metadata directory. Must contain root.json
51+
repository_dir: Local metadata directory. Directory must be
52+
writable and it must contain at least a root.json file.
5253
metadata_base_url: Base URL for all remote metadata downloads
5354
target_base_url: Optional; Default base URL for all remote target
5455
downloads. Can be individually set in download_target()
5556
fetcher: Optional; FetcherInterface implementation used to download
5657
both metadata and targets. Default is RequestsFetcher
58+
59+
Raises:
60+
OSError: Local root.json cannot be read
61+
RepositoryError: Local root.json is invalid
5762
"""
5863
self._dir = repository_dir
5964
self._metadata_base_url = _ensure_trailing_slash(metadata_base_url)
@@ -83,6 +88,11 @@ def refresh(self) -> None:
8388
8489
The refresh() method should be called by the client before any target
8590
requests.
91+
92+
Raises:
93+
OSError: New metadata could not be written to disk
94+
RepositoryError: Metadata failed to verify in some way
95+
TODO: download-related errors
8696
"""
8797

8898
self._load_root()
@@ -102,6 +112,11 @@ def get_one_valid_targetinfo(self, target_path: str) -> Dict:
102112
(https://url.spec.whatwg.org/#path-relative-url-string).
103113
Typically this is also the unix file path of the eventually
104114
downloaded file.
115+
116+
Raises:
117+
OSError: New metadata could not be written to disk
118+
RepositoryError: Metadata failed to verify in some way
119+
TODO: download-related errors
105120
"""
106121
return self._preorder_depth_first_walk(target_path)
107122

@@ -172,6 +187,10 @@ def download_target(
172187
destination_directory as required.
173188
target_base_url: Optional; Base URL used to form the final target
174189
download URL. Default is the value provided in Updater()
190+
191+
Raises:
192+
TODO: download-related errors
193+
TODO: file write errors
175194
"""
176195
if target_base_url is None and self._target_base_url is None:
177196
raise ValueError(
@@ -269,6 +288,7 @@ def _load_snapshot(self) -> None:
269288
try:
270289
data = self._load_local_metadata("snapshot")
271290
self._bundle.update_snapshot(data)
291+
logger.debug("Local snapshot is valid: not downloading new one")
272292
except (OSError, exceptions.RepositoryError) as e:
273293
# Local load failed: we must update from remote
274294
logger.debug("Failed to load local snapshot %s", e)
@@ -288,6 +308,7 @@ def _load_targets(self, role: str, parent_role: str) -> None:
288308
try:
289309
data = self._load_local_metadata(role)
290310
self._bundle.update_delegated_targets(data, role, parent_role)
311+
logger.debug("Local %s is valid: not downloading new one", role)
291312
except (OSError, exceptions.RepositoryError) as e:
292313
# Local load failed: we must update from remote
293314
logger.debug("Failed to load local %s: %s", role, e)

0 commit comments

Comments
 (0)