diff --git a/.gitignore b/.gitignore index e1ac1bfc9..d3655dfad 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ __pycache__/ *$py.class # C extensions -*.so +# *.so # Distribution / packaging .Python diff --git a/README.md b/README.md index b1c3d1587..797cfcffe 100644 --- a/README.md +++ b/README.md @@ -435,7 +435,8 @@ Please read [CONTRIBUTING.md](https://github.com/pact-foundation/pact-python/blo To setup a development environment: 1. If you want to run tests for all Python versions, install 2.7, 3.3, 3.4, 3.5, and 3.6 from source or using a tool like [pyenv] -2. Its recommended to create a Python [virtualenv] for the project +2. Its recommended to create a Python [virtualenv] for the project. +3. We are now using FFI bindings. For mac you might want to read these [setup FFI](https://cffi.readthedocs.io/en/latest/installation.html) The setup the environment, run tests, and package the application, run: `make release` diff --git a/docker/py37.Dockerfile b/docker/py37.Dockerfile index fcb940d80..e0723d79b 100644 --- a/docker/py37.Dockerfile +++ b/docker/py37.Dockerfile @@ -7,7 +7,17 @@ COPY requirements_dev.txt . RUN apk update RUN apk upgrade -RUN apk add gcc py-pip python-dev libffi-dev openssl-dev gcc libc-dev bash make +RUN apk add gcc py-pip python-dev libffi-dev openssl-dev gcc libc-dev bash cmake make libc6-compat +RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 +ENV MUSL_LOCALE_DEPS musl-dev gettext-dev libintl + +RUN apk add --no-cache \ + $MUSL_LOCALE_DEPS \ + && wget https://gitlab.com/rilian-la-te/musl-locales/-/archive/master/musl-locales-master.zip \ + && unzip musl-locales-master.zip \ + && cd musl-locales-master \ + && cmake -DLOCALE_PROFILE=OFF -D CMAKE_INSTALL_PREFIX:PATH=/usr . && make && make install \ + && cd .. && rm -r musl-locales-master RUN python -m pip install psutil RUN pip install -r requirements_dev.txt diff --git a/libs/libpact_ffi-linux-x86_64.so b/libs/libpact_ffi-linux-x86_64.so new file mode 100644 index 000000000..b54037d7b Binary files /dev/null and b/libs/libpact_ffi-linux-x86_64.so differ diff --git a/libs/libpact_ffi-osx-x86_64.dylib b/libs/libpact_ffi-osx-x86_64.dylib new file mode 100644 index 000000000..1c39dc54f Binary files /dev/null and b/libs/libpact_ffi-osx-x86_64.dylib differ diff --git a/musl-locales-master.zip b/musl-locales-master.zip new file mode 100644 index 000000000..f540f1d47 Binary files /dev/null and b/musl-locales-master.zip differ diff --git a/pact/cli/verify.py b/pact/cli/verify.py index b3fa87091..8eea66665 100644 --- a/pact/cli/verify.py +++ b/pact/cli/verify.py @@ -188,12 +188,12 @@ def main(pacts, base_url, pact_url, pact_urls, states_url, states_setup_url, options = dict(filter(lambda item: item[1] != '', options.items())) options = dict(filter(lambda item: is_empty_list(item), options.items())) - success, logs = VerifyWrapper().call_verify(*all_pact_urls, - provider=provider, - provider_base_url=base_url, - enable_pending=enable_pending, - include_wip_pacts_since=include_wip_pacts_since, - **options) + 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) sys.exit(success) diff --git a/pact/ffi/ffi_verifier.py b/pact/ffi/ffi_verifier.py new file mode 100644 index 000000000..4920c9dcf --- /dev/null +++ b/pact/ffi/ffi_verifier.py @@ -0,0 +1,58 @@ +"""Wrapper to pact reference dynamic libraries using FFI.""" +from pact.pact_exception import PactException +from cffi import FFI +import platform + + +class FFIVerify(object): + """A Pact Verifier Wrapper.""" + + def version(self): + """Publish version info.""" + ffi = FFI() + ffi.cdef(""" + char *pactffi_version(void); + """) + lib = self._load_ffi_library(ffi) + result = lib.pactffi_version() + return ffi.string(result).decode('utf-8') + + 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); + """) + lib = self._load_ffi_library(ffi) + result = lib.pactffi_version() + return ffi.string(result).decode('utf-8') + + def _load_ffi_library(self, ffi): + """Load the right library.""" + target_platform = platform.platform().lower() + + if 'darwin' in target_platform or 'macos' in target_platform: + libname = "libs/libpact_ffi-osx-x86_64.dylib" + elif 'linux' in target_platform: + libname = "libs/libpact_ffi-linux-x86_64.so" + elif 'windows' in target_platform: + libname = "libs/libpact_ffi-osx-x86_64.dylib" + else: + msg = ('Unfortunately, {} is not a supported platform. Only Linux,' + ' Windows, and OSX are currently supported.').format( + platform.platform()) + raise Exception(msg) + + return ffi.dlopen(libname) + + def _validate_input(self, pacts, **kwargs): + if len(pacts) == 0 and not self._broker_present(**kwargs): + raise PactException('Pact urls or Pact broker required') + + def _broker_present(self, **kwargs): + if kwargs.get('broker_url') is None: + return False + return True diff --git a/pact/pact_exception.py b/pact/pact_exception.py new file mode 100644 index 000000000..7d7b9e5b1 --- /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 fcd13a0d5..a3475bb53 100644 --- a/pact/verifier.py +++ b/pact/verifier.py @@ -26,6 +26,10 @@ def __str__(self): """ return 'Verifier for {} with url {}'.format(self.provider, self.provider_base_url) + def version(self): + """Return version info.""" + return VerifyWrapper().version() + def validate_publish(self, **kwargs): """Validate publish has a version.""" if ((kwargs.get('publish') is not None) and (kwargs.get('publish_version') is None)): @@ -52,12 +56,12 @@ def verify_pacts(self, *pacts, enable_pending=False, include_wip_pacts_since=Non # rerun_command() # env = options = self.extract_params(**kwargs) - success, logs = VerifyWrapper().call_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) + 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) return success, logs @@ -86,11 +90,11 @@ def verify_with_broker(self, enable_pending=False, include_wip_pacts_since=None, } options.update(self.extract_params(**kwargs)) - success, logs = VerifyWrapper().call_verify(provider=self.provider, - provider_base_url=self.provider_base_url, - enable_pending=enable_pending, - include_wip_pacts_since=include_wip_pacts_since, - **options) + 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) return success, logs def extract_params(self, **kwargs): diff --git a/pact/verify_wrapper.py b/pact/verify_wrapper.py index 854e5b1ac..190a8edd6 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.""" @@ -133,7 +114,7 @@ def _validate_input(self, pacts, **kwargs): if len(pacts) == 0 and not self._broker_present(**kwargs): raise PactException('Pact urls or Pact broker required') - def call_verify( + def verify( self, *pacts, provider_base_url, provider, enable_pending=False, include_wip_pacts_since=None, **kwargs ): @@ -196,12 +177,6 @@ def call_verify( return result.returncode, logs - def publish_results(self, provider_app_version, command): - """Publish results to broker.""" - if not provider_app_version: - # todo implement - raise Exception('todo') - - command.extend(["--provider-app-version", - provider_app_version, - "--publish-verification-results"]) + def version(self): + """Publish version info.""" + return '0.0.0' diff --git a/requirements_dev.txt b/requirements_dev.txt index 7fd673cbc..37d7d91ee 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,15 +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 +six>=1.9.0 +fastapi==0.67.0 +uvicorn==0.14.0 +cffi==1.14.6 diff --git a/setup.py b/setup.py index 5ae1bdb87..9d0e4dc1a 100644 --- a/setup.py +++ b/setup.py @@ -6,15 +6,18 @@ import tarfile from zipfile import ZipFile +import shutil +import gzip from setuptools import setup from setuptools.command.develop import develop from setuptools.command.install import install +from urllib.request import urlopen IS_64 = sys.maxsize > 2 ** 32 PACT_STANDALONE_VERSION = '1.88.51' - +PACT_FFI_VERSION = '0.0.0' here = os.path.abspath(os.path.dirname(__file__)) @@ -40,6 +43,7 @@ def run(self): os.mkdir(bin_path) install_ruby_app(bin_path) + install_rust_app(bin_path) class PactPythonInstallCommand(install): @@ -56,6 +60,71 @@ def run(self): bin_path = os.path.join(self.install_lib, 'pact', 'bin') os.mkdir(bin_path) install_ruby_app(bin_path) + install_rust_app(bin_path) + + +def install_rust_app(bin_path): + """ + Download the relevant rust binaries and install it for use. + + :param bin_path: The path where binaries should be installed. + """ + target_platform = platform.platform().lower() + + if 'darwin' in target_platform or 'macos' in target_platform: + suffix = 'libpact_ffi-osx-x86_64' + elif 'linux' in target_platform: + suffix = 'libpact_ffi-linux-x86_64' + elif 'windows' in target_platform: + suffix = 'pact_ffi-windows-x86_64' + else: + msg = ('Unfortunately, {} is not a supported platform. Only Linux,' + ' Windows, and OSX are currently supported.').format( + platform.platform()) + raise Exception(msg) + + if 'windows' in platform.platform().lower(): + fetch_lib(bin_path, suffix, 'dll') + fetch_lib(bin_path, suffix, 'dll.lib') + fetch_lib(bin_path, suffix, 'lib') + + else: + fetch_lib(bin_path, suffix, 'a') + if 'darwin' in target_platform or 'macos' in target_platform: + fetch_lib(bin_path, suffix, 'dylib') + + elif 'linux' in target_platform: + fetch_lib(bin_path, suffix, 'so') + + +def fetch_lib(bin_path, suffix, type): + """ + Fetch rust binaries to the bin_path. + + :param bin_path: The path where binaries should be installed. + :param suffix: The suffix filenamne unique to this platform (e.g. libpact_ffi-osx-x86_64). + "param type: The type of library (e.g. so|a|dll|dylib) + Raises: + RuntimeError: [description] + + """ + dest = os.path.join(bin_path, f'{suffix}.{type}') + zipped = os.path.join(bin_path, f'{suffix}.{type}.gz') + uri = ( + f"https://github.com/pact-foundation/pact-reference/releases" + f"/download/libpact_ffi-v{PACT_FFI_VERSION}/{suffix}.{type}.gz") + + resp = urlopen(uri) + with open(zipped, 'wb') as f: + if resp.code == 200: + f.write(resp.read()) + else: + raise RuntimeError( + 'Received HTTP {} when downloading {}'.format( + resp.code, resp.url)) + + with gzip.open(zipped) as g, open(dest, 'wb') as f_out: + shutil.copyfileobj(g, f_out) def install_ruby_app(bin_path): @@ -82,11 +151,6 @@ def install_ruby_app(bin_path): platform.platform()) raise Exception(msg) - if sys.version_info.major == 2: - from urllib import urlopen - else: - from urllib.request import urlopen - path = os.path.join(bin_path, suffix) resp = urlopen(uri.format(version=PACT_STANDALONE_VERSION, suffix=suffix)) with open(path, 'wb') as f: @@ -113,6 +177,7 @@ def read(filename): dependencies = [ + 'cffi==1.14.6', 'click>=2.0.0', 'psutil>=2.0.0', 'requests>=2.5.0', diff --git a/tests/cli/test_verify.py b/tests/cli/test_verify.py index b95c92a36..70ddc6861 100644 --- a/tests/cli/test_verify.py +++ b/tests/cli/test_verify.py @@ -69,7 +69,7 @@ def test_provider_base_url_is_required(self): self.assertEqual(result.exit_code, 2) self.assertIn('--provider-base-url', result.output) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") def test_pact_urls_or_broker_are_required(self, mock_wrapper): result = self.runner.invoke( verify.main, ['--provider-base-url=http://localhost']) @@ -78,7 +78,7 @@ def test_pact_urls_or_broker_are_required(self, mock_wrapper): self.assertIn('at least one', result.output) mock_wrapper.assert_not_called() - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") def test_broker_url_but_no_provider_required(self, mock_wrapper): result = self.runner.invoke( verify.main, ['--provider-base-url=http://localhost', @@ -87,17 +87,17 @@ def test_broker_url_but_no_provider_required(self, mock_wrapper): mock_wrapper.assert_not_called() self.assertEqual(result.exit_code, 1) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_wrapper_error_code_returned(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 8, None # rnd number to indicate retval returned result = self.runner.invoke(verify.main, self.all_url_opts) - self.assertFalse(mock_wrapper.call_verify.called) + self.assertFalse(mock_wrapper.verify.called) self.assertEqual(result.exit_code, 8) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_successful_verification(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None # rnd number to indicate retval returned @@ -115,7 +115,7 @@ def test_successful_verification(self, mock_isfile, mock_wrapper): publish_verification_results=False, include_wip_pacts_since=None) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_broker_url_and_provider_required(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None @@ -125,7 +125,7 @@ def test_broker_url_and_provider_required(self, mock_isfile, mock_wrapper): mock_wrapper.assert_called() self.assertEqual(result.exit_code, 0) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_pact_url_param_supported(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None @@ -146,7 +146,7 @@ def test_pact_url_param_supported(self, mock_isfile, mock_wrapper): include_wip_pacts_since=None) self.assertEqual(result.exit_code, 0) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_pact_urls_param_supported(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None @@ -169,7 +169,7 @@ def test_pact_urls_param_supported(self, mock_isfile, mock_wrapper): include_wip_pacts_since=None) self.assertEqual(result.exit_code, 0) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=False) def test_local_pact_urls_must_exist(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None @@ -177,9 +177,9 @@ def test_local_pact_urls_must_exist(self, mock_isfile, mock_wrapper): result = self.runner.invoke(verify.main, self.all_url_opts) self.assertEqual(result.exit_code, 1) self.assertIn('./pacts/consumer-provider.json', result.output) - mock_wrapper.call_verify.assert_not_called + mock_wrapper.verify.assert_not_called - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_failed_verification(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 3, None @@ -198,7 +198,7 @@ def test_failed_verification(self, mock_isfile, mock_wrapper): @patch.dict(os.environ, {'PACT_BROKER_PASSWORD': 'pwd', 'PACT_BROKER_USERNAME': 'broker_user', 'PACT_BROKER_BASE_URL': 'http://broker/'}) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_broker_creds_from_env_var(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None @@ -219,7 +219,7 @@ def test_broker_creds_from_env_var(self, mock_isfile, mock_wrapper): publish_verification_results=False, include_wip_pacts_since=None) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch("pact.verify_wrapper.isfile", return_value=True) def test_all_url_options(self, mock_isfile, mock_wrapper): mock_wrapper.return_value = 0, None @@ -270,7 +270,7 @@ def test_all_url_options(self, mock_isfile, mock_wrapper): publish_verification_results=False, include_wip_pacts_since=None) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") def test_all_broker_options(self, mock_wrapper): mock_wrapper.return_value = 0, None result = self.runner.invoke(verify.main, [ diff --git a/tests/ffi/test_ffi_verifier.py b/tests/ffi/test_ffi_verifier.py new file mode 100644 index 000000000..5b0832536 --- /dev/null +++ b/tests/ffi/test_ffi_verifier.py @@ -0,0 +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 pytest.raises(PactException) as e: + verifier.verify(provider='provider', provider_base_url='http://localhost') + + assert 'Pact urls or Pact broker required' in str(e) diff --git a/tests/test_pact.py b/tests/test_pact.py index b5405cceb..19501e375 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_verifier.py b/tests/test_verifier.py index 3822e4621..961ad63aa 100644 --- a/tests/test_verifier.py +++ b/tests/test_verifier.py @@ -22,9 +22,12 @@ def setUp(self): provider_base_url="http://localhost:8888") self.mock_wrapper = patch.object( - VerifyWrapper, 'call_verify').start() + VerifyWrapper, 'verify').start() - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + def test_version(self): + self.assertEqual(self.verifier.version(), "0.0.0") + + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch('pact.verifier.path_exists', return_value=True) def test_verifier_with_provider_and_files(self, mock_path_exists, mock_wrapper): mock_wrapper.return_value = (True, 'some logs') @@ -44,7 +47,7 @@ def test_verifier_with_provider_and_files(self, mock_path_exists, mock_wrapper): enable_pending=False, include_wip_pacts_since=None) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch('pact.verifier.path_exists', return_value=True) def test_verifier_with_provider_and_files_passes_consumer_selctors(self, mock_path_exists, mock_wrapper): mock_wrapper.return_value = (True, 'some logs') @@ -76,7 +79,7 @@ def test_verifier_with_provider_and_files_passes_consumer_selctors(self, mock_pa def test_validate_on_publish_results(self): self.assertRaises(Exception, self.verifier.verify_pacts, 'path/to/pact1', publish=True) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch('pact.verifier.path_exists', return_value=True) def test_publish_on_success(self, mock_path_exists, mock_wrapper): mock_wrapper.return_value = (True, 'some logs') @@ -101,7 +104,7 @@ def test_raises_error_on_missing_pact_files(self, mock_path_exists): mock_path_exists.assert_called_with('path/to/pact2') - @patch("pact.verify_wrapper.VerifyWrapper.call_verify", return_value=(0, None)) + @patch("pact.verify_wrapper.VerifyWrapper.verify", return_value=(0, None)) @patch('pact.verifier.expand_directories', return_value=['./pacts/pact1', './pacts/pact2']) @patch('pact.verifier.path_exists', return_value=True) def test_expand_directories_called_for_pacts(self, mock_path_exists, mock_expand_dir, mock_wrapper): @@ -110,7 +113,7 @@ def test_expand_directories_called_for_pacts(self, mock_path_exists, mock_expand mock_expand_dir.assert_called_once() - @patch('pact.verify_wrapper.VerifyWrapper.call_verify', return_value=(0, None)) + @patch('pact.verify_wrapper.VerifyWrapper.verify', return_value=(0, None)) def test_passes_enable_pending_flag_value(self, mock_wrapper): for value in (True, False): with self.subTest(value=value): @@ -121,7 +124,7 @@ def test_passes_enable_pending_flag_value(self, mock_wrapper): mock_wrapper.call_args.kwargs, ) - @patch('pact.verify_wrapper.VerifyWrapper.call_verify', return_value=(0, None)) + @patch('pact.verify_wrapper.VerifyWrapper.verify', return_value=(0, None)) @patch('pact.verifier.path_exists', return_value=True) def test_passes_include_wip_pacts_since_value(self, mock_path_exists, mock_wrapper): self.verifier.verify_pacts('any.json', include_wip_pacts_since='2018-01-01') @@ -139,7 +142,7 @@ def setUp(self): provider_base_url="http://localhost:8888") self.mock_wrapper = patch.object( - VerifyWrapper, 'call_verify').start() + VerifyWrapper, 'verify').start() self.broker_username = 'broker_username' self.broker_password = 'broker_password' self.broker_url = 'http://broker' @@ -151,7 +154,7 @@ def setUp(self): 'broker_token': 'token' } - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") def test_verifier_with_broker(self, mock_wrapper): mock_wrapper.return_value = (True, 'some value') @@ -171,7 +174,7 @@ def test_verifier_with_broker(self, mock_wrapper): enable_pending=False, include_wip_pacts_since=None) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") def test_verifier_and_pubish_with_broker(self, mock_wrapper): mock_wrapper.return_value = (True, 'some value') @@ -194,7 +197,7 @@ def test_verifier_and_pubish_with_broker(self, mock_wrapper): provider_app_version='1.0.0', ) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") def test_verifier_with_broker_passes_consumer_selctors(self, mock_wrapper): mock_wrapper.return_value = (True, 'some value') @@ -223,7 +226,7 @@ def test_verifier_with_broker_passes_consumer_selctors(self, mock_wrapper): consumer_selectors=['{"tag": "main", "latest": true}', '{"tag": "test", "latest": false}']) - @patch("pact.verify_wrapper.VerifyWrapper.call_verify") + @patch("pact.verify_wrapper.VerifyWrapper.verify") @patch('pact.verifier.path_exists', return_value=True) def test_publish_on_success(self, mock_path_exists, mock_wrapper): mock_wrapper.return_value = (True, 'some logs') @@ -243,7 +246,7 @@ def test_publish_on_success(self, mock_path_exists, mock_wrapper): enable_pending=False, include_wip_pacts_since=None) - @patch('pact.verify_wrapper.VerifyWrapper.call_verify', return_value=(0, None)) + @patch('pact.verify_wrapper.VerifyWrapper.verify', return_value=(0, None)) def test_passes_enable_pending_flag_value(self, mock_wrapper): for value in (True, False): with self.subTest(value=value): @@ -254,7 +257,7 @@ def test_passes_enable_pending_flag_value(self, mock_wrapper): mock_wrapper.call_args.kwargs, ) - @patch('pact.verify_wrapper.VerifyWrapper.call_verify', return_value=(0, None)) + @patch('pact.verify_wrapper.VerifyWrapper.verify', return_value=(0, None)) @patch('pact.verifier.path_exists', return_value=True) def test_passes_include_wip_pacts_since_value(self, mock_path_exists, mock_wrapper): self.verifier.verify_with_broker(include_wip_pacts_since='2018-01-01') diff --git a/tests/test_verify_wrapper.py b/tests/test_verify_wrapper.py index 5dc247cf7..dfd018691 100644 --- a/tests/test_verify_wrapper.py +++ b/tests/test_verify_wrapper.py @@ -69,19 +69,23 @@ def assertProcess(self, *expected): self.mock_rerun_command.return_value) self.assertTrue(self.mock_Popen.called) + def test_version(self): + wrapper = VerifyWrapper() + self.assertEqual(wrapper.version(), "0.0.0") + def test_pact_urls_or_broker_required(self): self.mock_Popen.return_value.returncode = 2 wrapper = VerifyWrapper() with self.assertRaises(PactException) as context: - wrapper.call_verify(provider='provider', provider_base_url='http://localhost') + wrapper.verify(provider='provider', provider_base_url='http://localhost') self.assertTrue('Pact urls or Pact broker required' in context.exception.message) def test_broker_without_authentication_can_be_used(self): self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - wrapper.call_verify( + wrapper.verify( provider='provider', provider_base_url='http://localhost', broker_url='http://broker.example.com' ) self.assertProcess(*[ @@ -94,10 +98,10 @@ def test_pact_urls_provided(self): self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_verify('./pacts/consumer-provider.json', - './pacts/consumer-provider2.json', - provider='test_provider', - provider_base_url='http://localhost') + result, output = wrapper.verify('./pacts/consumer-provider.json', + './pacts/consumer-provider2.json', + provider='test_provider', + provider_base_url='http://localhost') self.assertProcess(*self.default_call) self.assertEqual(result, 0) @@ -107,19 +111,19 @@ def test_all_url_options(self, mock_isfile): self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_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') + 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') self.assertEqual(result, 0) self.mock_Popen.return_value.wait.assert_called_once_with() @@ -144,14 +148,14 @@ def test_uses_broker_if_no_pacts_and_provider_required(self): self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_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']) + 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']) self.assertProcess(*self.broker_call) self.assertEqual(result, 0) @@ -164,10 +168,10 @@ def test_rerun_command_called(self, mock_rerun_cmd, mock_expand_dirs, mock_sanit self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_verify('path/to/pact1', - 'path/to/pact2', - provider_base_url='http://localhost', - provider='provider') + result, output = wrapper.verify('path/to/pact1', + 'path/to/pact2', + provider_base_url='http://localhost', + provider='provider') mock_rerun_cmd.assert_called_once() @@ -179,10 +183,10 @@ def test_sanitize_called(self, mock_rerun_cmd, mock_expand_dirs, mock_sanitize_l self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_verify('path/to/pact1', - 'path/to/pact2', - provider_base_url='http://localhost', - provider='provider') + result, output = wrapper.verify('path/to/pact1', + 'path/to/pact2', + provider_base_url='http://localhost', + provider='provider') mock_sanitize_logs.assert_called_with(self.mock_Popen.return_value, False) @@ -192,12 +196,12 @@ def test_publishing_with_version(self, mock_sanitize_logs, mock_path_exists): self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_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) + 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) self.default_call.extend(['--provider-app-version', '1.2.3', '--publish-verification-results']) @@ -212,10 +216,10 @@ def test_expand_dirs_called(self, mock_rerun_cmd, mock_expand_dirs, mock_sanitiz self.mock_Popen.return_value.returncode = 0 wrapper = VerifyWrapper() - result, output = wrapper.call_verify('path/to/pact1', - 'path/to/pact2', - provider_base_url='http://localhost', - provider='provider') + result, output = wrapper.verify('path/to/pact1', + 'path/to/pact2', + provider_base_url='http://localhost', + provider='provider') mock_expand_dirs.assert_called_with(['path/to/pact1', 'path/to/pact2'])