|
1 | 1 | import arrow |
| 2 | +import pytest |
2 | 3 | import responses |
| 4 | +from pyfakefs.fake_filesystem import FakeFilesystem |
3 | 5 |
|
| 6 | +from cycode.cli.exceptions.custom_exceptions import HttpUnauthorizedError |
4 | 7 | from cycode.cyclient.cycode_token_based_client import CycodeTokenBasedClient |
5 | 8 | from tests.conftest import _EXPECTED_API_TOKEN, create_token_based_client |
6 | 9 |
|
@@ -66,6 +69,51 @@ def test_access_token_cached_creator_changed( |
66 | 69 | assert client2._expires_in is None |
67 | 70 |
|
68 | 71 |
|
| 72 | +@responses.activate |
| 73 | +def test_access_token_mint_conflict_prefers_token_persisted_by_another_process( |
| 74 | + api_token_url: str, fs: FakeFilesystem |
| 75 | +) -> None: |
| 76 | + client = create_token_based_client() |
| 77 | + |
| 78 | + def _refuse_while_another_process_wins(_request: object) -> tuple: |
| 79 | + # the process that won the race persists its token while this one is being refused |
| 80 | + client._credentials_manager.update_access_token( |
| 81 | + _EXPECTED_API_TOKEN, arrow.utcnow().shift(hours=1).timestamp(), client._create_jwt_creator() |
| 82 | + ) |
| 83 | + return 401, {}, '' |
| 84 | + |
| 85 | + responses.add_callback(responses.POST, api_token_url, callback=_refuse_while_another_process_wins) |
| 86 | + |
| 87 | + assert client.get_access_token() == _EXPECTED_API_TOKEN |
| 88 | + assert len(responses.calls) == 1 |
| 89 | + |
| 90 | + |
| 91 | +@responses.activate |
| 92 | +def test_access_token_mint_conflict_retries_when_no_other_process_won( |
| 93 | + api_token_url: str, api_token_response: responses.Response, fs: FakeFilesystem |
| 94 | +) -> None: |
| 95 | + client = create_token_based_client() |
| 96 | + |
| 97 | + responses.add(responses.Response(method=responses.POST, url=api_token_url, status=401)) |
| 98 | + responses.add(api_token_response) |
| 99 | + |
| 100 | + assert client.get_access_token() == _EXPECTED_API_TOKEN |
| 101 | + assert len(responses.calls) == 2 |
| 102 | + |
| 103 | + |
| 104 | +@responses.activate |
| 105 | +def test_access_token_mint_conflict_raises_when_retry_is_refused_too(api_token_url: str, fs: FakeFilesystem) -> None: |
| 106 | + client = create_token_based_client() |
| 107 | + |
| 108 | + responses.add(responses.Response(method=responses.POST, url=api_token_url, status=401)) |
| 109 | + responses.add(responses.Response(method=responses.POST, url=api_token_url, status=401)) |
| 110 | + |
| 111 | + with pytest.raises(HttpUnauthorizedError): |
| 112 | + client.get_access_token() |
| 113 | + |
| 114 | + assert len(responses.calls) == 2 |
| 115 | + |
| 116 | + |
69 | 117 | @responses.activate |
70 | 118 | def test_access_token_invalidation( |
71 | 119 | token_based_client: CycodeTokenBasedClient, api_token_response: responses.Response |
|
0 commit comments