Skip to content

Commit 64cc050

Browse files
committed
test(cli/cache): ✅ add regression test for 'cache warm --crate'
1 parent 33012b6 commit 64cc050

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

tests/test_cli_cache.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,68 @@ def test_warm_url_combined_with_profile_warms_both(
242242
assert "https://example.org/explicit" in result.output
243243

244244

245+
# ====================================================================
246+
# cache warm: --crate (remote RO-Crate)
247+
# ====================================================================
248+
@pytest.fixture
249+
def mock_network_gzip(monkeypatch):
250+
"""
251+
Same as ``mock_network``, but returns a ``Content-Encoding: gzip`` body.
252+
This encoded response is required to reproduce the warm-crate bug.
253+
"""
254+
import gzip
255+
256+
from requests.adapters import HTTPAdapter
257+
258+
body = gzip.compress(b'{"@context": "https://w3id.org/ro/crate/1.2/context"}')
259+
260+
def fake_send(self, request, **kwargs):
261+
raw = urllib3.HTTPResponse(
262+
body=io.BytesIO(body),
263+
headers={
264+
"Content-Type": "application/json",
265+
"Content-Encoding": "gzip",
266+
"Content-Length": str(len(body)),
267+
},
268+
status=200,
269+
preload_content=False,
270+
decode_content=False,
271+
)
272+
return self.build_response(request, raw)
273+
274+
monkeypatch.setattr(HTTPAdapter, "send", fake_send)
275+
276+
277+
def test_warm_crate_caches_remote_metadata(cli_runner, mock_network_gzip, tmp_cache):
278+
"""
279+
Regression: ``cache warm --crate <url>`` must consume the body via
280+
``response.content`` rather than streaming ``response.raw``.
281+
282+
With ``stream=True`` + ``shutil.copyfileobj(response.raw, ...)`` the warm-up
283+
crashed with urllib3's "Calling read(decode_content=False) is not supported
284+
after read(decode_content=True) was called": requests_cache buffers the
285+
streamed body (decode_content=True) to store it, after which a raw read
286+
(decode_content=False) is rejected. The body must therefore be touched in a
287+
way that goes through the already-decoded content.
288+
"""
289+
url = "https://example.org/ro-crate/ro-crate-metadata.json"
290+
result = cli_runner.invoke(
291+
cli,
292+
["cache", "warm", "--cache-path", str(tmp_cache), "--crate", url],
293+
)
294+
assert result.exit_code == 0, result.output
295+
assert "Fetching remote RO-Crates" in result.output
296+
assert "Summary: 1 cached, 0 failed, 0 skipped" in result.output
297+
298+
# The fetched crate must actually be retrievable from the cache afterwards.
299+
listed = cli_runner.invoke(
300+
cli,
301+
["cache", "list", "--cache-path", str(tmp_cache)],
302+
)
303+
assert listed.exit_code == 0, listed.output
304+
assert "ro-crate-metadata.json" in listed.output
305+
306+
245307
# ====================================================================
246308
# cache list / ls
247309
# ====================================================================

0 commit comments

Comments
 (0)