From cbf8ea03feb648f70f01bc588cc340d97cadd0cd Mon Sep 17 00:00:00 2001 From: Elliott Murray Date: Sat, 24 Jul 2021 10:54:02 +0100 Subject: [PATCH] feat: refactoring to prepare verify --- pact/cli/verify.py | 10 ++--- pact/ffi/ffi_verifier.py | 15 +++++-- pact/pact.py | 2 +- pact/pact_exception.py | 21 ++++++++++ pact/verifier.py | 18 ++++----- pact/verify_wrapper.py | 21 +--------- requirements_dev.txt | 9 +++-- tests/ffi/test_ffi_verifier.py | 15 +++++++ tests/test_pact.py | 2 +- tests/test_verify_wrapper.py | 72 +++++++++++++++++----------------- 10 files changed, 105 insertions(+), 80 deletions(-) create mode 100644 pact/pact_exception.py diff --git a/pact/cli/verify.py b/pact/cli/verify.py index 7d4e64c16c..8eea66665f 100644 --- a/pact/cli/verify.py +++ b/pact/cli/verify.py @@ -189,11 +189,11 @@ def main(pacts, base_url, pact_url, pact_urls, states_url, states_setup_url, options = dict(filter(lambda item: is_empty_list(item), options.items())) success, logs = VerifyWrapper().verify(*all_pact_urls, - provider=provider, - provider_base_url=base_url, - enable_pending=enable_pending, - include_wip_pacts_since=include_wip_pacts_since, - **options) + provider=provider, + provider_base_url=base_url, + enable_pending=enable_pending, + include_wip_pacts_since=include_wip_pacts_since, + **options) sys.exit(success) diff --git a/pact/ffi/ffi_verifier.py b/pact/ffi/ffi_verifier.py index 6381123e0d..4e9bc56a44 100644 --- a/pact/ffi/ffi_verifier.py +++ b/pact/ffi/ffi_verifier.py @@ -1,7 +1,9 @@ """Wrapper to pact reference dynamic libraries using FFI.""" +from pact import pact_exception from cffi import FFI import platform + class FFIVerify(object): """A Pact Verifier Wrapper.""" @@ -15,9 +17,12 @@ def version(self): result = lib.pactffi_version() return ffi.string(result).decode('utf-8') - - def verify(self): + def verify(self, *pacts, provider_base_url, provider, enable_pending=False, + include_wip_pacts_since=None, **kwargs): """Call verify method.""" + + self._validate_input(pacts, **kwargs) + ffi = FFI() ffi.cdef(""" char *pactffi_verify(void); @@ -26,8 +31,6 @@ def verify(self): result = lib.pactffi_version() return ffi.string(result).decode('utf-8') -# pactffi_verify - def _load_ffi_library(self, ffi): """Load the right library.""" target_platform = platform.platform().lower() @@ -45,3 +48,7 @@ def _load_ffi_library(self, ffi): raise Exception(msg) return ffi.dlopen(libname) + + def _validate_input(self, pacts, **kwargs): + if len(pacts) == 0 and not self._broker_present(**kwargs): + raise pact_exception('Pact urls or Pact broker required') diff --git a/pact/pact.py b/pact/pact.py index ef5600c8fc..a6ec2cdecc 100644 --- a/pact/pact.py +++ b/pact/pact.py @@ -264,7 +264,7 @@ def verify(self): """ self._interactions = [] resp = requests.get( - self.uri + "/interactions/verification", headers=self.HEADERS, verify=False, allow_redirects=True + self.uri + "/interactions/verification", headers=self.HEADERS, verify=False ) assert resp.status_code == 200, resp.text resp = requests.post(self.uri + "/pact", headers=self.HEADERS, verify=False) diff --git a/pact/pact_exception.py b/pact/pact_exception.py new file mode 100644 index 0000000000..7d7b9e5b18 --- /dev/null +++ b/pact/pact_exception.py @@ -0,0 +1,21 @@ +"""Custom Pact Exception.""" + +class PactException(Exception): + """PactException when input isn't valid. + + Args: + Exception ([type]): [description] + + Raises: + KeyError: [description] + Exception: [description] + + Returns: + [type]: [description] + + """ + + def __init__(self, *args, **kwargs): + """Create wrapper.""" + super().__init__(*args, **kwargs) + self.message = args[0] diff --git a/pact/verifier.py b/pact/verifier.py index 285225585c..a3475bb534 100644 --- a/pact/verifier.py +++ b/pact/verifier.py @@ -57,11 +57,11 @@ def verify_pacts(self, *pacts, enable_pending=False, include_wip_pacts_since=Non options = self.extract_params(**kwargs) success, logs = VerifyWrapper().verify(*pacts, - provider=self.provider, - provider_base_url=self.provider_base_url, - enable_pending=enable_pending, - include_wip_pacts_since=include_wip_pacts_since, - **options) + provider=self.provider, + provider_base_url=self.provider_base_url, + enable_pending=enable_pending, + include_wip_pacts_since=include_wip_pacts_since, + **options) return success, logs @@ -91,10 +91,10 @@ def verify_with_broker(self, enable_pending=False, include_wip_pacts_since=None, options.update(self.extract_params(**kwargs)) success, logs = VerifyWrapper().verify(provider=self.provider, - provider_base_url=self.provider_base_url, - enable_pending=enable_pending, - include_wip_pacts_since=include_wip_pacts_since, - **options) + provider_base_url=self.provider_base_url, + enable_pending=enable_pending, + include_wip_pacts_since=include_wip_pacts_since, + **options) return success, logs def extract_params(self, **kwargs): diff --git a/pact/verify_wrapper.py b/pact/verify_wrapper.py index 88955c0ee3..190a8edd61 100644 --- a/pact/verify_wrapper.py +++ b/pact/verify_wrapper.py @@ -1,6 +1,7 @@ """Wrapper to verify previously created pacts.""" from pact.constants import VERIFIER_PATH +from pact.pact_exception import PactException import sys import os import platform @@ -101,26 +102,6 @@ def rerun_command(): env['PACT_INTERACTION_RERUN_COMMAND'] = command return env -class PactException(Exception): - """PactException when input isn't valid. - - Args: - Exception ([type]): [description] - - Raises: - KeyError: [description] - Exception: [description] - - Returns: - [type]: [description] - - """ - - def __init__(self, *args, **kwargs): - """Create wrapper.""" - super().__init__(*args, **kwargs) - self.message = args[0] - class VerifyWrapper(object): """A Pact Verifier Wrapper.""" diff --git a/requirements_dev.txt b/requirements_dev.txt index 6f490d81ba..37d7d91ee9 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,18 +2,19 @@ Click>=2.0.0 coverage==5.4 Flask==1.1.1 configparser==3.5.0 +fastapi==0.67.0 flake8==3.8.3 mock==3.0.5 psutil==5.7.0 pycodestyle==2.6.0 pydocstyle==4.0.1 -tox==3.14.0 +tox==3.24.1 pytest==5.4.1 pytest-cov==2.11.1 requests==2.26 -tox-travis==0.8 urllib3>=1.26.5 wheel==0.24.0 -requests>=2.5.0 six>=1.9.0 -cffi==1.14.6 \ No newline at end of file +fastapi==0.67.0 +uvicorn==0.14.0 +cffi==1.14.6 diff --git a/tests/ffi/test_ffi_verifier.py b/tests/ffi/test_ffi_verifier.py index 2ceff09d16..65d4e66adc 100644 --- a/tests/ffi/test_ffi_verifier.py +++ b/tests/ffi/test_ffi_verifier.py @@ -1,4 +1,19 @@ +import pytest +import mock + +from pact.pact_exception import PactException from pact.ffi.ffi_verifier import FFIVerify def test_version(): assert FFIVerify().version() == "0.0.0" + + +@mock.patch("os.listdir") +def test_pact_urls_or_broker_required(mock_Popen): + # mock_Popen.return_value.returncode = 2 + verifier = FFIVerify() + + with assertRaises(PactException) as context: + verifier.verify(provider='provider', provider_base_url='http://localhost') + + assert 'Pact urls or Pact broker required' in context.exception.message diff --git a/tests/test_pact.py b/tests/test_pact.py index b5405cceb3..19501e375c 100644 --- a/tests/test_pact.py +++ b/tests/test_pact.py @@ -484,6 +484,7 @@ def setUp(self): .upon_receiving('a specific request to the server') .with_request('GET', '/path') .will_respond_with(200, body='success')) + self.get_verification_call = call( 'get', 'http://localhost:1234/interactions/verification', headers={'X-Pact-Mock-Service': 'true'}, @@ -530,7 +531,6 @@ def test_error_writing_pacts_to_file(self): self.mock_requests.assert_has_calls([ self.get_verification_call, self.post_publish_pacts_call]) - class PactContextManagerTestCase(PactTestCase): def setUp(self): super(PactContextManagerTestCase, self).setUp() diff --git a/tests/test_verify_wrapper.py b/tests/test_verify_wrapper.py index 029504cc4b..dfd0186914 100644 --- a/tests/test_verify_wrapper.py +++ b/tests/test_verify_wrapper.py @@ -99,9 +99,9 @@ def test_pact_urls_provided(self): wrapper = VerifyWrapper() result, output = wrapper.verify('./pacts/consumer-provider.json', - './pacts/consumer-provider2.json', - provider='test_provider', - provider_base_url='http://localhost') + './pacts/consumer-provider2.json', + provider='test_provider', + provider_base_url='http://localhost') self.assertProcess(*self.default_call) self.assertEqual(result, 0) @@ -112,18 +112,18 @@ def test_all_url_options(self, mock_isfile): wrapper = VerifyWrapper() result, output = wrapper.verify('./pacts/consumer-provider5.json', - './pacts/consumer-provider3.json', - provider_base_url='http://localhost', - provider_states_setup_url='http://localhost/provider-states/set', - provider='provider', - provider_app_version='1.2.3', - custom_provider_headers=['Authorization: Basic cGFj', 'CustomHeader: somevalue'], - log_dir='tmp/logs/pact.test.log', - log_level='INFO', - timeout=60, - verbose=True, - enable_pending=True, - include_wip_pacts_since='2018-01-01') + './pacts/consumer-provider3.json', + provider_base_url='http://localhost', + provider_states_setup_url='http://localhost/provider-states/set', + provider='provider', + provider_app_version='1.2.3', + custom_provider_headers=['Authorization: Basic cGFj', 'CustomHeader: somevalue'], + log_dir='tmp/logs/pact.test.log', + log_level='INFO', + timeout=60, + verbose=True, + enable_pending=True, + include_wip_pacts_since='2018-01-01') self.assertEqual(result, 0) self.mock_Popen.return_value.wait.assert_called_once_with() @@ -149,13 +149,13 @@ def test_uses_broker_if_no_pacts_and_provider_required(self): wrapper = VerifyWrapper() result, output = wrapper.verify(provider='test_provider', - provider_base_url='http://localhost', - broker_username='username', - broker_password='pwd', - broker_token='token', - broker_url='http://broker', - consumer_tags=['prod', 'dev'], - provider_tags=['dev', 'qa']) + provider_base_url='http://localhost', + broker_username='username', + broker_password='pwd', + broker_token='token', + broker_url='http://broker', + consumer_tags=['prod', 'dev'], + provider_tags=['dev', 'qa']) self.assertProcess(*self.broker_call) self.assertEqual(result, 0) @@ -169,9 +169,9 @@ def test_rerun_command_called(self, mock_rerun_cmd, mock_expand_dirs, mock_sanit wrapper = VerifyWrapper() result, output = wrapper.verify('path/to/pact1', - 'path/to/pact2', - provider_base_url='http://localhost', - provider='provider') + 'path/to/pact2', + provider_base_url='http://localhost', + provider='provider') mock_rerun_cmd.assert_called_once() @@ -184,9 +184,9 @@ def test_sanitize_called(self, mock_rerun_cmd, mock_expand_dirs, mock_sanitize_l wrapper = VerifyWrapper() result, output = wrapper.verify('path/to/pact1', - 'path/to/pact2', - provider_base_url='http://localhost', - provider='provider') + 'path/to/pact2', + provider_base_url='http://localhost', + provider='provider') mock_sanitize_logs.assert_called_with(self.mock_Popen.return_value, False) @@ -197,11 +197,11 @@ def test_publishing_with_version(self, mock_sanitize_logs, mock_path_exists): wrapper = VerifyWrapper() result, output = wrapper.verify('./pacts/consumer-provider.json', - './pacts/consumer-provider2.json', - provider='test_provider', - provider_base_url='http://localhost', - provider_app_version='1.2.3', - publish_verification_results=True) + './pacts/consumer-provider2.json', + provider='test_provider', + provider_base_url='http://localhost', + provider_app_version='1.2.3', + publish_verification_results=True) self.default_call.extend(['--provider-app-version', '1.2.3', '--publish-verification-results']) @@ -217,9 +217,9 @@ def test_expand_dirs_called(self, mock_rerun_cmd, mock_expand_dirs, mock_sanitiz wrapper = VerifyWrapper() result, output = wrapper.verify('path/to/pact1', - 'path/to/pact2', - provider_base_url='http://localhost', - provider='provider') + 'path/to/pact2', + provider_base_url='http://localhost', + provider='provider') mock_expand_dirs.assert_called_with(['path/to/pact1', 'path/to/pact2'])