Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ngclient: Avoid loading targets metadata twice #1593

Merged
merged 1 commit into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions tests/test_updater_with_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
"""Test ngclient Updater using the repository simulator.
"""

import builtins
import os
import sys
import tempfile
import unittest
from typing import Optional, Tuple
from unittest.mock import MagicMock, Mock, patch

from tests import utils
from tests.repository_simulator import RepositorySimulator
Expand Down Expand Up @@ -230,6 +232,32 @@ def test_snapshot_rollback_with_local_snapshot_hash_mismatch(self):
with self.assertRaises(BadVersionNumberError):
self._run_refresh()

@patch.object(builtins, "open", wraps=builtins.open)
def test_not_loading_targets_twice(self, wrapped_open: MagicMock):
# Do not load targets roles more than once when traversing
# the delegations tree

# Add new delegated targets, update the snapshot
spec_version = ".".join(SPECIFICATION_VERSION)
targets = Targets(1, spec_version, self.sim.safe_expiry, {}, None)
self.sim.add_delegation("targets", "role1", targets, False, ["*"], None)
self.sim.update_snapshot()

# Run refresh, top-level roles are loaded
updater = self._run_refresh()
# Clean up calls to open during refresh()
wrapped_open.reset_mock()
Comment on lines +246 to +249
Copy link
Member

@jku jku Nov 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're adding a test for a specific bug fix, that makes sense... but this obviously leads to "shouldn't we check that refresh opens correct files the correct number of times as well?" Maybe a follow up issue if you don't feel like handling here?

Copy link
Contributor Author

@sechkova sechkova Nov 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was planning to open an issue about testing the loading of metadata. Doing it now ... #1681


# First time looking for "somepath", only 'role1' must be loaded
updater.get_targetinfo("somepath")
wrapped_open.assert_called_once_with(
os.path.join(self.metadata_dir, "role1.json"), "rb"
)
wrapped_open.reset_mock()
# Second call to get_targetinfo, all metadata is already loaded
updater.get_targetinfo("somepath")
wrapped_open.assert_not_called()


if __name__ == "__main__":
if "--dump" in sys.argv:
Expand Down
5 changes: 5 additions & 0 deletions tuf/ngclient/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ def _load_snapshot(self) -> None:

def _load_targets(self, role: str, parent_role: str) -> Metadata[Targets]:
"""Load local (and if needed remote) metadata for 'role'."""

# Avoid loading 'role' more than once during "get_targetinfo"
if role in self._trusted_set:
return self._trusted_set[role]

try:
data = self._load_local_metadata(role)
delegated_targets = self._trusted_set.update_delegated_targets(
Expand Down