From 895850b1973d6c021f73445c318ace0514e99f4a Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Thu, 6 Sep 2018 19:10:05 +0300 Subject: [PATCH 1/2] Fix failing unit test on Windows test_xmlrpclib was failing with "can't pickle thread.lock objects" on Windows. Other small issues were related to backslashes in paths and different line endings. --- tests/integration/test_requests.py | 2 +- tests/integration/test_wild.py | 15 +++++++++++---- tests/unit/test_request.py | 2 +- tests/unit/test_vcr.py | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/integration/test_requests.py b/tests/integration/test_requests.py index f970c95..cc5e7f5 100644 --- a/tests/integration/test_requests.py +++ b/tests/integration/test_requests.py @@ -254,7 +254,7 @@ def test_nested_cassettes_with_session_created_before_nesting(httpbin_both, tmpd def test_post_file(tmpdir, httpbin_both): '''Ensure that we handle posting a file.''' url = httpbin_both + '/post' - with vcr.use_cassette(str(tmpdir.join('post_file.yaml'))) as cass, open('tox.ini') as f: + with vcr.use_cassette(str(tmpdir.join('post_file.yaml'))) as cass, open('tox.ini', 'rb') as f: original_response = requests.post(url, f).content # This also tests that we do the right thing with matching the body when they are files. diff --git a/tests/integration/test_wild.py b/tests/integration/test_wild.py index 65c76e2..da85629 100644 --- a/tests/integration/test_wild.py +++ b/tests/integration/test_wild.py @@ -81,16 +81,23 @@ def test_amazon_doctype(tmpdir): assert 'html' in r.text +def start_rpc_server(q): + httpd = xmlrpc_server.SimpleXMLRPCServer(('127.0.0.1', 0)) + httpd.register_function(pow) + q.put('http://{}:{}'.format(*httpd.server_address)) + httpd.serve_forever() + + @pytest.yield_fixture(scope='session') def rpc_server(): - httpd = xmlrpc_server.SimpleXMLRPCServer(('', 0)) - httpd.register_function(pow) + q = multiprocessing.Queue() proxy_process = multiprocessing.Process( - target=httpd.serve_forever, + target=start_rpc_server, + args=(q,) ) try: proxy_process.start() - yield 'http://{}:{}'.format(*httpd.server_address) + yield q.get() finally: proxy_process.terminate() diff --git a/tests/unit/test_request.py b/tests/unit/test_request.py index dfd68d7..6dca476 100644 --- a/tests/unit/test_request.py +++ b/tests/unit/test_request.py @@ -5,7 +5,7 @@ from vcr.request import Request, HeadersDict def test_str(): req = Request('GET', 'http://www.google.com/', '', {}) - str(req) == '' + assert str(req) == '' def test_headers(): diff --git a/tests/unit/test_vcr.py b/tests/unit/test_vcr.py index 5a6bb6e..f473db3 100644 --- a/tests/unit/test_vcr.py +++ b/tests/unit/test_vcr.py @@ -147,7 +147,7 @@ def test_vcr_path_transformer(): # and it should still work with cassette_library_dir vcr = VCR(cassette_library_dir='/foo') with vcr.use_cassette('test') as cassette: - assert cassette._path == '/foo/test' + assert os.path.abspath(cassette._path) == os.path.abspath('/foo/test') @pytest.fixture From 302ea35d9a394949abf1b9e8a8e49fa3b52663ec Mon Sep 17 00:00:00 2001 From: Martin Valgur Date: Thu, 6 Sep 2018 19:18:28 +0300 Subject: [PATCH 2/2] Fix matching on 'body' failing when Unicode symbols are present in them Matching on bodies uses urllib.parse.parse_qs(), which fails to handle UTF-8+URLEncoded POST bodies when the input is `bytes` rather than `str`, causing matching to fail.. Fixed this by always doing decode('ascii') on URLEncoded POST bodies first. --- tests/integration/test_requests.py | 14 ++++++++++++++ vcr/matchers.py | 9 ++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_requests.py b/tests/integration/test_requests.py index cc5e7f5..ba92741 100644 --- a/tests/integration/test_requests.py +++ b/tests/integration/test_requests.py @@ -282,3 +282,17 @@ def test_filter_post_params(tmpdir, httpbin_both): requests.post(url, data={'key': 'value'}) with vcr.use_cassette(cass_loc, filter_post_data_parameters=['key']) as cass: assert b'key=value' not in cass.requests[0].body + + +def test_post_unicode_match_on_body(tmpdir, httpbin_both): + '''Ensure that matching on POST body that contains Unicode characters works.''' + data = {'key1': 'value1', '●‿●': '٩(●̮̮̃•̃)۶'} + url = httpbin_both + '/post' + + with vcr.use_cassette(str(tmpdir.join('requests.yaml')), additional_matchers=('body',)): + req1 = requests.post(url, data).content + + with vcr.use_cassette(str(tmpdir.join('requests.yaml')), additional_matchers=('body',)): + req2 = requests.post(url, data).content + + assert req1 == req2 diff --git a/vcr/matchers.py b/vcr/matchers.py index ad04a45..a464a02 100644 --- a/vcr/matchers.py +++ b/vcr/matchers.py @@ -56,9 +56,12 @@ def _transform_json(body): _xml_header_checker = _header_checker('text/xml') _xmlrpc_header_checker = _header_checker('xmlrpc', header='User-Agent') _checker_transformer_pairs = ( - (_header_checker('application/x-www-form-urlencoded'), urllib.parse.parse_qs), - (_header_checker('application/json'), _transform_json), - (lambda request: _xml_header_checker(request) and _xmlrpc_header_checker(request), xmlrpc_client.loads), + (_header_checker('application/x-www-form-urlencoded'), + lambda body: urllib.parse.parse_qs(body.decode('ascii'))), + (_header_checker('application/json'), + _transform_json), + (lambda request: _xml_header_checker(request) and _xmlrpc_header_checker(request), + xmlrpc_client.loads), )