diff --git a/allgo/__init__.py b/allgo/__init__.py index 8fc1ab605bab04bb2865561febd1e38ed2edc52f..b881109cb786d0fe81f5df5e1f3c2cc098eab304 100644 --- a/allgo/__init__.py +++ b/allgo/__init__.py @@ -106,7 +106,7 @@ class StatusError(AllgoError): return self._response.json()['error'] -def _local_token(): +def _local_token(): # pragma: no cover """read and return the content of TOKEN_FILE or None.""" if os.path.exists(TOKEN_FILE): with open(TOKEN_FILE) as f: @@ -523,7 +523,6 @@ class Client: return out_dict # should never goes here - return out_dict # pragma: no cover def get_log(self, job_id): """Generator of log file content. diff --git a/tests/test_allgo.py b/tests/test_allgo.py index c030980643551ada8b584dae94f0326af118bc03..182790685312ba2279611c93bf5fbeb5f2cdb97b 100644 --- a/tests/test_allgo.py +++ b/tests/test_allgo.py @@ -226,6 +226,81 @@ def test_create_job__param_error(mock_post, client): # ~ assert err.msg.startswith('Invalid parameters') +@pytest.mark.success +@patch('allgo.Client._request_api') +def test_create_job__params_default(mock_request, client, tmp_path): + """Here I'll check the params transmission.""" + app_name = 'fake' + client.create_job(app_name) + + data = { # default values, except for app_name + "job[webapp_id]" : app_name, + "job[param]" : '', + "job[version]" : None, + "job[queue]" : None, + } + file_dict = {} + + # -- tests + mock_request.assert_called_once_with('post', + url_end='jobs', + data=data, + files=file_dict) + + +@pytest.mark.success +@patch('allgo.Client._request_api') +def test_create_job__params(mock_request, client, tmp_path): + """Here I'll check the params transmission. + For that I'll mock the _request_api so that it returns + the params = data and files dict.""" + # Mock + def side_effect(method, url_end, **kwargs): + return kwargs + mock_request.side_effect = side_effect + + # create files to load + filepaths = [] + for i, f in enumerate(['f1','f2','f3']): + filepath = os.path.join(str(tmp_path), f ) + with open(filepath, "w") as fs: + fs.write(f) # content doesn't matter + filepaths.append(filepath) + + app_name = 'fake' + params = 'un de kvar' + version = '1.42' + queue = 'quick' + transmitted_params = client.create_job(app_name, + version=version, + params=params, + files=filepaths, + queue=queue) + # expected + data = { # default values, except for app_name + "job[webapp_id]" : app_name, + "job[param]" : params, + "job[version]" : version, + "job[queue]" : queue, + } + file_dict_keys = [ "file[{}]".format(i) for i, _ in enumerate(filepaths) ] + + # -- tests + assert 'data' in transmitted_params + assert data == transmitted_params['data'] + assert 'files' in transmitted_params + assert sorted(file_dict_keys) == sorted(transmitted_params['files'].keys()) + + if 2 == sys.version_info.major: + file_type = file + else: + from io import BufferedReader + file_type = BufferedReader + for handle in transmitted_params['files'].values(): + assert isinstance(handle, file_type) + handle.close() + + @pytest.mark.success @patch('allgo.requests.post') def test_create_job__response(mock_post, client): @@ -387,6 +462,34 @@ def test_run_job__args(mock_sleep, mock_status, mock_create, client, capsys): assert x_output == capsys.readouterr().out +# ------------------------------------------------ +@pytest.mark.error +@patch('allgo.requests.get') +def test__request_file(mock_get, client): + """assert a StatusError is raised if the request fail. + The error message is not checked.""" + # -- mock + err_code = 666 + mock_get.return_value = Mock(status_code=err_code) + # ~ mock_get.return_value.json.return_value = \ + # ~ {'error': 'API request without http authorisation'} + + # -- tests + with pytest.raises(StatusError) as err_info: + client._request_file('url_bidon') + + err = err_info.value + assert err_code == err.status_code + # ~ assert '' == err.msg + + +@pytest.mark.error +def test_app_metrics(client): + """app_metrics method is not yet implemented.""" + with pytest.raises(NotImplementedError): + client.app_metrics('fake', 'what') + + # ------------------------------------------------ def __mock_file(mock_get): file_content = "fake line1.\nline2 is fake too.\n" @@ -443,6 +546,43 @@ def test_download_file__outdir(mock_get, client, tmp_path): assert file_content == content +@pytest.mark.error +@patch('allgo.requests.get') +def test_download_file__outdir_already_exists(mock_get, client, tmp_path): + """The method should not raise an error if the output dir already exist.""" + # -- mock + __mock_file(mock_get) + + # -- tests + file_url = "https://whatever.fr/x" + try: + client.download_file(file_url, outdir=tmp_path) + except Exception: + pytest.fail("In download_file, existing outdir should not raise an error.") + + +@pytest.mark.error +@patch('allgo.os.makedirs') +@patch('allgo.requests.get') +def test_download_file__outdir_error(mock_get, mock_mkdir, client, tmp_path): + """The method should raise an error if the output dir cannot be created.""" + # -- mock + __mock_file(mock_get) + + err_code = errno.EPERM + err_msg = 'fake msg' + mock_mkdir.side_effect = OSError(err_code, err_msg) + + # -- tests + file_url = "https://whatever.fr/x" + with pytest.raises(OSError) as err_info: + client.download_file(file_url, outdir=tmp_path) + + err = err_info.value + assert err_code == err.errno + assert err_msg == err.strerror + + @pytest.mark.success @patch('allgo.requests.get') def test_download_file__force(mock_get, client): @@ -576,3 +716,30 @@ def test_get_log__big(mock_get, mock_status, client): # ------------------------------------------------ +@pytest.mark.success +@patch('allgo.requests.get') +def test__request_api__manage_ValueErrors(mock_get, client): + """_request_api method should manage well error that can occurr in querying. + if ValueError the response should be returned. + + ValueError happens when response content cannot be converted to json.""" + # -- mock + response = mock_get.return_value + response.status_code = 200 + response.json = Mock(side_effect=ValueError()) + + # -- tests + resp = client._request_api('get', 'fin_url') + assert response == resp + + +@pytest.mark.error +def test__request_api__manage_KeyErrors(client): + """_request_api method should manage well error that can occurr in querying. + if KeyError is raised, an AllgoError should be raised. + + KeyError happens when an unknown actions is used as param.""" + + # -- tests + with pytest.raises(AllgoError): + client._request_api('fail', 'fin_url')