diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 398b1932..ff25b9c9 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -138,6 +138,11 @@ jobs: run: python scripts/export_native.py --all --fetch --output-dir "$RUNNER_TEMP/native" - name: Run test suite + # No test downloads a release asset: 252 MB files fetched into the + # shared cache filled the runner's disk and changed what later tests + # resolved. The download tests mock the network and clear it. + env: + RETROBIOS_OFFLINE: "1" run: python -m unittest discover tests -v label-pr: diff --git a/scripts/largefiles.py b/scripts/largefiles.py index d0be38ec..458f9fef 100644 --- a/scripts/largefiles.py +++ b/scripts/largefiles.py @@ -173,7 +173,10 @@ def _fetch_asset( # (gh release upload --clobber): only a download can answer, and # it replaces the copy only if it verifies. - if offline: + # RETROBIOS_OFFLINE forbids every download whatever a caller passes: the + # CI test job sets it, since tests fetching 252 MB assets into the shared + # cache filled the runner's disk and changed what later tests resolved. + if offline or os.environ.get("RETROBIOS_OFFLINE"): return None os.makedirs(dest_dir, exist_ok=True) diff --git a/tests/test_e2e.py b/tests/test_e2e.py index f61c477e..519b36b6 100644 --- a/tests/test_e2e.py +++ b/tests/test_e2e.py @@ -25,6 +25,7 @@ import tempfile import unittest import zipfile from pathlib import Path +from unittest import mock sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts")) @@ -5304,7 +5305,9 @@ struct BurnDriver BurnDrvneogeo = { original = largefiles.urllib.request.urlopen largefiles.urllib.request.urlopen = fake_urlopen try: - with tempfile.TemporaryDirectory() as tmpdir: + with tempfile.TemporaryDirectory() as tmpdir, mock.patch.dict( + os.environ, {"RETROBIOS_OFFLINE": ""} + ): path = common.fetch_large_file( "MAME 0.174 Arcade XML.dat", dest_dir=tmpdir ) diff --git a/tests/test_large_file_cache.py b/tests/test_large_file_cache.py index e951f98a..ab9ef4d0 100644 --- a/tests/test_large_file_cache.py +++ b/tests/test_large_file_cache.py @@ -32,6 +32,20 @@ PAYLOAD_A = b"A" * (256 * 1024) PAYLOAD_B = b"B" * (256 * 1024) +# These tests download through a mocked urlopen into their own directory; +# the CI test job sets RETROBIOS_OFFLINE to keep every other test off the +# network, so it is cleared here. +_ONLINE = mock.patch.dict(os.environ, {"RETROBIOS_OFFLINE": ""}) + + +def setUpModule(): + _ONLINE.start() + + +def tearDownModule(): + _ONLINE.stop() + + class _SlowResponse(io.BytesIO): """Serve a payload in chunks, yielding between them.""" @@ -220,6 +234,19 @@ class LargeFileCacheTest(unittest.TestCase): self.assertEqual(os.listdir(self.dir), ["asset.bin"]) +class TheOfflineSwitchHoldsEverywhere(unittest.TestCase): + """RETROBIOS_OFFLINE stops a download whatever the caller asked.""" + + def test_no_request_is_made(self): + with tempfile.TemporaryDirectory() as tmp, mock.patch.dict( + os.environ, {"RETROBIOS_OFFLINE": "1"} + ), mock.patch.object(largefiles.urllib.request, "urlopen") as urlopen: + self.assertIsNone( + largefiles.fetch_large_file("asset.bin", dest_dir=tmp, offline=False) + ) + urlopen.assert_not_called() + + class HashCacheKeepsEveryDigest(unittest.TestCase): """A cache hit must serve the same five digests a fresh hash produces.