|
| 1 | +import contextlib |
1 | 2 | import os
|
2 | 3 | import pathlib
|
| 4 | +import random |
| 5 | +from typing import Any |
3 | 6 |
|
4 | 7 | import pytest
|
| 8 | +import requests |
5 | 9 |
|
6 | 10 | from cads_api_client import ApiClient, Results
|
7 | 11 |
|
| 12 | +does_not_raise = contextlib.nullcontext |
| 13 | + |
8 | 14 |
|
9 | 15 | @pytest.fixture
|
10 | 16 | def results(api_anon_client: ApiClient) -> Results:
|
@@ -45,3 +51,60 @@ def test_results_progress(
|
45 | 51 | submitted.download(target=str(tmp_path / "test.grib"))
|
46 | 52 | captured = capsys.readouterr()
|
47 | 53 | assert captured.err if progress else not captured.err
|
| 54 | + |
| 55 | + |
| 56 | +@pytest.mark.parametrize( |
| 57 | + "maximum_tries,raises", |
| 58 | + [ |
| 59 | + (500, does_not_raise()), |
| 60 | + (1, pytest.raises(requests.ConnectionError, match="Random error.")), |
| 61 | + ], |
| 62 | +) |
| 63 | +def test_results_robust_download( |
| 64 | + api_root_url: str, |
| 65 | + api_anon_key: str, |
| 66 | + monkeypatch: pytest.MonkeyPatch, |
| 67 | + tmp_path: pathlib.Path, |
| 68 | + maximum_tries: int, |
| 69 | + raises: contextlib.nullcontext[Any], |
| 70 | +) -> None: |
| 71 | + from multiurl.http import FullHTTPDownloader |
| 72 | + |
| 73 | + def patched_iter_content(self, *args, **kwargs): # type: ignore |
| 74 | + for chunk in self.iter_content(chunk_size=1): |
| 75 | + if random.choice([True, False]): |
| 76 | + raise requests.ConnectionError("Random error.") |
| 77 | + yield chunk |
| 78 | + |
| 79 | + def make_stream(self): # type: ignore |
| 80 | + request = self.issue_request(self.range) |
| 81 | + return request.patched_iter_content |
| 82 | + |
| 83 | + client = ApiClient( |
| 84 | + url=api_root_url, key=api_anon_key, retry_after=0, maximum_tries=maximum_tries |
| 85 | + ) |
| 86 | + results = client.submit_and_wait_on_results("test-adaptor-dummy", size=10) |
| 87 | + monkeypatch.setattr( |
| 88 | + requests.Response, "patched_iter_content", patched_iter_content, raising=False |
| 89 | + ) |
| 90 | + monkeypatch.setattr(FullHTTPDownloader, "make_stream", make_stream) |
| 91 | + |
| 92 | + target = tmp_path / "test.grib" |
| 93 | + with raises: |
| 94 | + results.download(str(target)) |
| 95 | + |
| 96 | + |
| 97 | +def test_results_override(api_anon_client: ApiClient, tmp_path: pathlib.Path) -> None: |
| 98 | + target_1 = tmp_path / "tmp1.grib" |
| 99 | + api_anon_client.retrieve("test-adaptor-dummy", size=1, target=str(target_1)) |
| 100 | + |
| 101 | + target_2 = tmp_path / "tmp2.grib" |
| 102 | + api_anon_client.retrieve("test-adaptor-dummy", size=2, target=str(target_2)) |
| 103 | + |
| 104 | + target = tmp_path / "tmp.grib" |
| 105 | + api_anon_client.retrieve("test-adaptor-dummy", size=1, target=str(target)) |
| 106 | + assert target.read_bytes() == target_1.read_bytes() |
| 107 | + api_anon_client.retrieve("test-adaptor-dummy", size=2, target=str(target)) |
| 108 | + assert target.read_bytes() == target_2.read_bytes() |
| 109 | + api_anon_client.retrieve("test-adaptor-dummy", size=1, target=str(target)) |
| 110 | + assert target.read_bytes() == target_1.read_bytes() |
0 commit comments