Skip to content

Commit 53cc81b

Browse files
committed
Add test for parallel refresh
This likely fails on all platforms right now, but the Windows behaviour cannot be fixed without actual locking. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
1 parent e4e841f commit 53cc81b

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

tests/refresh_script.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import sys
2+
3+
from tuf.ngclient import Updater
4+
5+
print(f"Creating and refreshing a client {sys.argv[1]} times:")
6+
print(f" metadata dir: {sys.argv[2]}")
7+
print(f" metadata url: {sys.argv[3]}")
8+
9+
10+
for i in range(int(sys.argv[1])):
11+
try:
12+
u = Updater(metadata_dir=sys.argv[2], metadata_base_url=sys.argv[3])
13+
u.refresh()
14+
except OSError as e:
15+
sys.exit(f"Failed on iteration {i}: {e}")

tests/test_updater_ng.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import shutil
1111
import sys
1212
import tempfile
13+
import subprocess
1314
import unittest
1415
from collections.abc import Iterable
1516
from typing import TYPE_CHECKING, Callable, ClassVar
@@ -354,6 +355,44 @@ def test_user_agent(self) -> None:
354355
self.assertEqual(ua[:23], "MyApp/1.2.3 python-tuf/")
355356

356357

358+
class TestParallelUpdater(TestUpdater):
359+
def test_parallel_updaters(self) -> None:
360+
# Refresh two updaters in parallel many times, using the same local metadata cache.
361+
# This should reveal race conditions.
362+
363+
iterations = 100
364+
365+
# The project root is the parent of the tests directory
366+
project_root = os.path.dirname(utils.TESTS_DIR)
367+
368+
command = [
369+
sys.executable,
370+
"-m",
371+
"tests.refresh_script",
372+
str(iterations),
373+
self.client_directory,
374+
self.metadata_url,
375+
]
376+
377+
p1 = subprocess.Popen(
378+
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=project_root
379+
)
380+
p2 = subprocess.Popen(
381+
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=project_root
382+
)
383+
384+
stdout1, stderr1 = p1.communicate()
385+
stdout2, stderr2 = p2.communicate()
386+
387+
if p1.returncode != 0 or p2.returncode != 0:
388+
self.fail(
389+
"Parallel refresh failed"
390+
f"\nprocess 1 stdout: \n{stdout1.decode()}"
391+
f"\nprocess 1 stderr: \n{stderr1.decode()}"
392+
f"\nprocess 2 stdout: \n{stdout2.decode()}"
393+
f"\nprocess 2 stderr: \n{stderr2.decode()}"
394+
)
395+
357396
if __name__ == "__main__":
358397
utils.configure_test_logging(sys.argv)
359398
unittest.main()

0 commit comments

Comments
 (0)