async def test_continues_polling_when_resource_not_found(): class _command: calls = 0 operation_complete = False async def command(): """Simulate service responding 404 a few times before 2xx""" assert not _command.operation_complete, "polling method shouldn't invoke the command after completion" if _command.calls < 3: _command.calls += 1 raise ResourceNotFoundError() _command.operation_complete = True polling_method = AsyncDeleteRecoverPollingMethod(command, final_resource=None, finished=False) sleep = mock.Mock(return_value=get_completed_future()) with mock.patch(SLEEP, sleep): await polling_method.run() assert sleep.call_count == _command.calls
async def test_initialization_get_key_successful(): """If the client is able to get key material, it shouldn't do so again""" key_id = "https://localhost/fake/key/version" mock_key = mock.Mock() mock_key.key.kid = key_id mock_client = mock.Mock() mock_client.get_key.return_value = get_completed_future(mock_key) client = CryptographyClient(key_id, mock.Mock()) client._client = mock_client assert mock_client.get_key.call_count == 0 with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") args, _ = get_provider.call_args assert len(args) == 1 and isinstance(args[0], JsonWebKey) and args[0].kid == key_id for _ in range(3): assert mock_client.get_key.call_count == 1 assert get_provider.call_count == 1 await client.verify(SignatureAlgorithm.rs256, b"...", b"...")
async def test_continuation_token(): """Methods returning pollers should accept continuation tokens""" expected_token = "token" mock_generated_client = mock.Mock() mock_methods = [ getattr(mock_generated_client, method_name) for method_name in ( "begin_full_backup", "begin_full_restore_operation", "begin_selective_key_restore_operation", ) ] for method in mock_methods: # the mock client's methods must return awaitables, and we don't have AsyncMock before 3.8 method.return_value = get_completed_future() backup_client = KeyVaultBackupClient("vault-url", object()) backup_client._client = mock_generated_client await backup_client.begin_restore("storage uri", "sas", continuation_token=expected_token) await backup_client.begin_backup("storage uri", "sas", continuation_token=expected_token) await backup_client.begin_selective_restore( "storage uri", "sas", "key", continuation_token=expected_token) for method in mock_methods: assert method.call_count == 1 _, kwargs = method.call_args assert kwargs["continuation_token"] == expected_token
async def test_initialization_transient_failure_getting_key(): """If the client is not forbidden to get key material, it should retry after failing to do so""" mock_client = mock.Mock() mock_client.get_key.side_effect = HttpResponseError(response=mock.Mock(status_code=500)) mock_client.verify.return_value = get_completed_future(mock.Mock()) client = CryptographyClient("https://localhost/fake/key/version", mock.Mock()) client._client = mock_client for i in range(3): assert mock_client.get_key.call_count == i await client.verify(SignatureAlgorithm.rs256, b"...", b"...")
async def test_initialization_forbidden_to_get_key(): """If the client is forbidden to get key material, it should try to do so exactly once""" mock_client = mock.Mock() mock_client.get_key.side_effect = HttpResponseError(response=mock.Mock(status_code=403)) mock_client.verify.return_value = get_completed_future(mock.Mock()) client = CryptographyClient("https://localhost/fake/key/version", mock.Mock()) client._client = mock_client assert mock_client.get_key.call_count == 0 for _ in range(3): await client.verify(SignatureAlgorithm.rs256, b"...", b"...") assert mock_client.get_key.call_count == 1
async def test_initialization_given_key(): """If the client is given key material, it should not attempt to get this from the vault""" mock_client = mock.Mock() key = mock.Mock(spec=KeyVaultKey, id="https://localhost/fake/key/version") client = CryptographyClient(key, mock.Mock()) client._client = mock_client mock_client.get_key.return_value = get_completed_future() with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") get_provider.assert_called_once_with(key) assert mock_client.get_key.call_count == 0
async def test_terminal_first_response(): """The polling method shouldn't sleep when Key Vault's first response indicates the operation is complete""" command = mock.Mock(return_value=get_completed_future()) polling_method = AsyncDeleteRecoverPollingMethod(command, final_resource=None, finished=False) with mock.patch( SLEEP, raise_exception( "polling method shouldn't sleep after the operation completes") ): await polling_method.run() assert command.call_count == 1 assert polling_method.finished()
async def test_run_idempotence(): """After the polling method completes, calling 'run' again shouldn't change state or invoke the command""" max_calls = 3 class _command: calls = 0 operation_complete = False async def command(): """Simulate service responding 404 a few times before 2xx""" assert not _command.operation_complete, "polling method shouldn't invoke the command after completion" if _command.calls < max_calls: _command.calls += 1 raise ResourceNotFoundError() _command.operation_complete = True resource = object() polling_method = AsyncDeleteRecoverPollingMethod(command, final_resource=resource, finished=False) assert not polling_method.finished() sleep = mock.Mock(return_value=get_completed_future()) with mock.patch(SLEEP, sleep): # when run is first called, the polling method should invoke the command until it indicates completion await polling_method.run() assert _command.calls == max_calls assert sleep.call_count == _command.calls # invoking run again should not change the resource or finished status, invoke the command, or sleep with mock.patch( SLEEP, raise_exception( "polling method shouldn't sleep when 'run' is called after completion" )): for _ in range(4): assert polling_method.resource() is resource assert polling_method.finished() await polling_method.run()
async def test_initialization_get_key_successful(): """If the client is able to get key material, it shouldn't do so again""" mock_client = mock.Mock() mock_client.get_key.return_value = mock.Mock(spec=KeyVaultKey) client = CryptographyClient("https://localhost/fake/key/version", mock.Mock()) client._client = mock_client mock_key = mock.Mock() mock_client.get_key.return_value = get_completed_future(mock_key) assert mock_client.get_key.call_count == 0 with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") get_provider.assert_called_once_with(mock_key) for _ in range(3): assert mock_client.get_key.call_count == 1 assert get_provider.call_count == 1 await client.verify(SignatureAlgorithm.rs256, b"...", b"...")