def test_send_auth_token_required(monkeypatch): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 4, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) mock_post = mock.MagicMock(side_effect=Exception()) monkeypatch.setattr('requests.sessions.Session.post', mock_post) def user_password_input(prompt): if prompt == 'IonQ apiKey > ': return None monkeypatch.setattr('getpass.getpass', user_password_input) # Code to test: info = { 'nq': 1, 'shots': 1, 'meas_mapped': [], 'meas_qubit_ids': [], 'circuit': [], } with pytest.raises(RuntimeError) as excinfo: _ionq_http_client.send(info, device='dummy') mock_post.assert_not_called() assert 'An authentication token is required!' == str(excinfo.value)
def test_send_auth_errors_reraise(monkeypatch): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 4, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) mock_response = mock.MagicMock() mock_response.status_code = 401 auth_error = requests.exceptions.HTTPError(response=mock_response) mock_post = mock.MagicMock(side_effect=auth_error) monkeypatch.setattr('requests.sessions.Session.post', mock_post) def user_password_input(prompt): if prompt == 'IonQ apiKey > ': return 'NotNone' monkeypatch.setattr('getpass.getpass', user_password_input) # Code to test: info = { 'nq': 1, 'shots': 1, 'meas_mapped': [], 'meas_qubit_ids': [], 'circuit': [], } with pytest.raises(requests.exceptions.HTTPError) as excinfo: _ionq_http_client.send(info, device='dummy') mock_post.assert_called_once() assert auth_error is excinfo.value
def test_send_requests_errors_are_caught(monkeypatch, error_type): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 4, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) mock_post = mock.MagicMock(side_effect=error_type()) monkeypatch.setattr('requests.sessions.Session.post', mock_post) def user_password_input(prompt): if prompt == 'IonQ apiKey > ': return 'NotNone' monkeypatch.setattr('getpass.getpass', user_password_input) # Code to test: info = { 'nq': 1, 'shots': 1, 'meas_mapped': [], 'meas_qubit_ids': [], 'circuit': [], } _ionq_http_client.send(info, device='dummy') mock_post.assert_called_once()
def test_timeout_exception(monkeypatch): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 4, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) def mock_post(_self, path, *args, **kwargs): assert path == 'https://api.ionq.co/v0.2/jobs' mock_response = mock.MagicMock() mock_response.json = mock.MagicMock(return_value={ 'id': 'new-job-id', 'status': 'ready', }) return mock_response def mock_get(_self, path, *args, **kwargs): assert path == 'https://api.ionq.co/v0.2/jobs/new-job-id' mock_response = mock.MagicMock() mock_response.json = mock.MagicMock(return_value={ 'id': 'new-job-id', 'status': 'running', }) return mock_response monkeypatch.setattr('requests.sessions.Session.post', mock_post) monkeypatch.setattr('requests.sessions.Session.get', mock_get) def user_password_input(prompt): if prompt == 'IonQ apiKey > ': return 'NotNone' monkeypatch.setattr('getpass.getpass', user_password_input) # Called once per loop in _get_result while the job is not ready. mock_sleep = mock.MagicMock() monkeypatch.setattr(_ionq_http_client.time, 'sleep', mock_sleep) # RequestTimeoutErrors are not caught, and so will raise out. with pytest.raises(RequestTimeoutError) as excinfo: info = { 'nq': 1, 'shots': 1, 'meas_mapped': [], 'meas_qubit_ids': [], 'circuit': [], } _ionq_http_client.send(info, device='dummy', num_retries=1) mock_sleep.assert_called_once() assert 'Timeout. The ID of your submitted job is new-job-id.' == str( excinfo.value)
def test_send_too_many_qubits(monkeypatch): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 3, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) info = { 'nq': 4, 'shots': 1, 'meas_mapped': [2, 3], 'circuit': [ { 'gate': 'x', 'targets': [0] }, { 'gate': 'x', 'targets': [1] }, { 'controls': [0], 'gate': 'cnot', 'targets': [2] }, { 'controls': [1], 'gate': 'cnot', 'targets': [2] }, { 'controls': [0, 1], 'gate': 'cnot', 'targets': [3] }, ], } with pytest.raises(_ionq_http_client.DeviceTooSmall): _ionq_http_client.send( info, device='dummy', token='NotNone', verbose=True, )
def test_send_api_errors_are_raised(monkeypatch, expected_err, err_data): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 4, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) def mock_post(_self, path, **kwargs): assert path == 'https://api.ionq.co/v0.2/jobs' mock_response = mock.MagicMock() mock_response.json = mock.MagicMock(return_value=err_data) return mock_response monkeypatch.setattr('requests.sessions.Session.post', mock_post) def user_password_input(prompt): if prompt == 'IonQ apiKey > ': return 'NotNone' monkeypatch.setattr('getpass.getpass', user_password_input) # Code to test: info = { 'nq': 1, 'shots': 1, 'meas_mapped': [], 'meas_qubit_ids': [], 'circuit': [], } with pytest.raises(JobSubmissionError) as excinfo: _ionq_http_client.send(info, device='dummy') assert expected_err == str(excinfo.value)
def test_send_real_device_online_verbose(monkeypatch): # Patch the method to give back dummy devices def _dummy_update(_self): _self.backends = {'dummy': {'nq': 4, 'target': 'dummy'}} monkeypatch.setattr( _ionq_http_client.IonQ, 'update_devices_list', _dummy_update.__get__(None, _ionq_http_client.IonQ), ) # What the IonQ JSON API request should look like. expected_request = { 'target': 'dummy', 'metadata': { 'sdk': 'ProjectQ', 'meas_qubit_ids': '[2, 3]' }, 'shots': 1, 'registers': { 'meas_mapped': [2, 3] }, 'lang': 'json', 'body': { 'qubits': 4, 'circuit': [ { 'gate': 'x', 'targets': [0] }, { 'gate': 'x', 'targets': [1] }, { 'controls': [0], 'gate': 'cnot', 'targets': [2] }, { 'controls': [1], 'gate': 'cnot', 'targets': [2] }, { 'controls': [0, 1], 'gate': 'cnot', 'targets': [3] }, ], }, } def mock_post(_self, path, *args, **kwargs): assert path == 'https://api.ionq.co/v0.2/jobs' assert 'json' in kwargs assert expected_request == kwargs['json'] mock_response = mock.MagicMock() mock_response.status_code = 200 mock_response.json = mock.MagicMock(return_value={ 'id': 'new-job-id', 'status': 'ready', }) return mock_response def mock_get(_self, path, *args, **kwargs): assert path == 'https://api.ionq.co/v0.2/jobs/new-job-id' mock_response = mock.MagicMock() mock_response.json = mock.MagicMock( return_value={ 'id': 'new-job-id', 'status': 'completed', 'qubits': 4, 'metadata': { 'meas_qubit_ids': '[2, 3]' }, 'registers': { 'meas_mapped': [2, 3] }, 'data': { 'registers': { 'meas_mapped': { '2': 1 } }, }, }) return mock_response monkeypatch.setattr('requests.sessions.Session.post', mock_post) monkeypatch.setattr('requests.sessions.Session.get', mock_get) def user_password_input(prompt): if prompt == 'IonQ apiKey > ': return 'NotNone' monkeypatch.setattr('getpass.getpass', user_password_input) # Code to test: info = { 'nq': 4, 'shots': 1, 'meas_mapped': [2, 3], 'meas_qubit_ids': [2, 3], 'circuit': [ { 'gate': 'x', 'targets': [0] }, { 'gate': 'x', 'targets': [1] }, { 'controls': [0], 'gate': 'cnot', 'targets': [2] }, { 'controls': [1], 'gate': 'cnot', 'targets': [2] }, { 'controls': [0, 1], 'gate': 'cnot', 'targets': [3] }, ], } expected = { 'nq': 4, 'output_probs': { '2': 1 }, 'meas_mapped': [2, 3], 'meas_qubit_ids': [2, 3], } actual = _ionq_http_client.send(info, device='dummy') assert expected == actual