# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import re from requests_mock import adapter from . import base from requests_mock.response import _MatcherResponse ANY = adapter.ANY class TestMatcher(base.TestCase): def match(self, target, url, matcher_method='GET', request_method='GET', complete_qs=False, headers=None, request_data=None, request_headers={}, additional_matcher=None, real_http=False, case_sensitive=False): matcher = adapter._Matcher(matcher_method, target, [], complete_qs=complete_qs, additional_matcher=additional_matcher, request_headers=request_headers, real_http=real_http, case_sensitive=case_sensitive) request = adapter._RequestObjectProxy._create(request_method, url, headers, data=request_data) return matcher._match(request) def assertMatch(self, target=ANY, url='http://example.com/requests-mock', matcher_method='GET', request_method='GET', **kwargs): self.assertEqual(True, self.match(target, url, matcher_method=matcher_method, request_method=request_method, **kwargs), 'Matcher %s %s failed to match %s %s' % (matcher_method, target, request_method, url)) def assertMatchBoth(self, target=ANY, url='http://example.com/requests-mock', matcher_method='GET', request_method='GET', **kwargs): self.assertMatch(target, url, matcher_method=matcher_method, request_method=request_method, **kwargs) self.assertMatch(url, target, matcher_method=request_method, request_method=matcher_method, **kwargs) def assertNoMatch(self, target=ANY, url='http://example.com/requests-mock', matcher_method='GET', request_method='GET', **kwargs): self.assertEqual(False, self.match(target, url, matcher_method=matcher_method, request_method=request_method, **kwargs), 'Matcher %s %s unexpectedly matched %s %s' % (matcher_method, target, request_method, url)) def assertNoMatchBoth(self, target=ANY, url='http://example.com/requests-mock', matcher_method='GET', request_method='GET', **kwargs): self.assertNoMatch(target, url, matcher_method=matcher_method, request_method=request_method, **kwargs) self.assertNoMatch(url, target, matcher_method=request_method, request_method=matcher_method, **kwargs) def assertMatchMethodBoth(self, matcher_method, request_method, **kwargs): url = 'http://www.test.com' self.assertMatchBoth(url, url, request_method=request_method, matcher_method=matcher_method, **kwargs) def assertNoMatchMethodBoth(self, matcher_method, request_method, **kwargs): url = 'http://www.test.com' self.assertNoMatchBoth(url, url, request_method=request_method, matcher_method=matcher_method, **kwargs) def test_url_matching(self): self.assertMatchBoth('http://www.test.com', 'http://www.test.com') self.assertMatchBoth('http://www.test.com', 'http://www.test.com/') self.assertMatchBoth('http://www.test.com/abc', 'http://www.test.com/abc') self.assertMatchBoth('http://www.test.com:5000/abc', 'http://www.test.com:5000/abc') self.assertNoMatchBoth('https://www.test.com', 'http://www.test.com') self.assertNoMatchBoth('http://www.test.com/abc', 'http://www.test.com') self.assertNoMatchBoth('http://test.com', 'http://www.test.com') self.assertNoMatchBoth('http://test.com', 'http://www.test.com') self.assertNoMatchBoth('http://test.com/abc', 'http://www.test.com/abc/') self.assertNoMatchBoth('http://test.com/abc/', 'http://www.test.com/abc') self.assertNoMatchBoth('http://test.com:5000/abc/', 'http://www.test.com/abc') self.assertNoMatchBoth('http://test.com/abc/', 'http://www.test.com:5000/abc') def test_quotation(self): self.assertMatchBoth('http://www.test.com/a string%url', 'http://www.test.com/a string%url') self.assertMatchBoth('http://www.test.com/ABC 123', 'http://www.test.com/ABC%20123') self.assertMatchBoth('http://www.test.com/user@example.com', 'http://www.test.com/user@example.com') def test_subset_match(self): self.assertMatch('/path', 'http://www.test.com/path') self.assertMatch('/path', 'http://www.test.com/path') self.assertMatch('//www.test.com/path', 'http://www.test.com/path') self.assertMatch('//www.test.com/path', 'https://www.test.com/path') def test_query_string(self): self.assertMatch('/path?a=1&b=2', 'http://www.test.com/path?a=1&b=2') self.assertMatch('/path?a=1', 'http://www.test.com/path?a=1&b=2', complete_qs=False) self.assertNoMatch('/path?a=1', 'http://www.test.com/path?a=1&b=2', complete_qs=True) self.assertNoMatch('/path?a=1&b=2', 'http://www.test.com/path?a=1') def test_query_empty_string(self): self.assertMatch('/path?a', 'http://www.test.com/path?a') self.assertMatch('/path?bob&paul', 'http://www.test.com/path?paul&bob') self.assertNoMatch('/path?bob', 'http://www.test.com/path?paul') self.assertNoMatch('/path?pual&bob', 'http://www.test.com/path?bob') def test_method_match(self): self.assertNoMatchMethodBoth('GET', 'POST') self.assertMatchMethodBoth('GET', 'get') self.assertMatchMethodBoth('GeT', 'geT') def test_match_ANY_url(self): self.assertMatch(ANY, 'http://anything') self.assertMatch(ANY, 'http://somethingelse') self.assertNoMatch(ANY, 'http://somethingelse', request_method='POST') def test_match_ANY_method(self): for m in ('GET', 'POST', 'HEAD', 'OPTION'): self.assertMatch('http://www.test.com', 'http://www.test.com', matcher_method=ANY, request_method=m) self.assertNoMatch('http://www.test.com', 'http://another', matcher_method=ANY) def test_match_with_regex(self): r1 = re.compile('test.com/a') r2 = re.compile('/b/c') self.assertMatch(r1, 'http://mock.test.com/a/b') self.assertMatch(r1, 'http://test.com/a/') self.assertMatch(r1, 'mock://test.com/a/b') self.assertNoMatch(r1, 'mock://test.com/') self.assertMatch(r2, 'http://anything/a/b/c/d') self.assertMatch(r2, 'mock://anything/a/b/c/d') def test_match_with_headers(self): self.assertMatch('/path', 'http://www.test.com/path', headers={'A': 'abc', 'b': 'def'}, request_headers={'a': 'abc'}) self.assertMatch('/path', 'http://www.test.com/path', headers={'A': 'abc', 'b': 'def'}) self.assertNoMatch('/path', 'http://www.test.com/path', headers={'A': 'abc', 'b': 'def'}, request_headers={'b': 'abc'}) self.assertNoMatch('/path', 'http://www.test.com/path', headers={'A': 'abc', 'b': 'def'}, request_headers={'c': 'ghi'}) # headers should be key insensitive and value sensitive, we have no # choice here because they go into an insensitive dict. self.assertMatch('/path', 'http://www.test.com/path', headers={'aBc': 'abc', 'DEF': 'def'}, request_headers={'abC': 'abc'}) self.assertNoMatch('/path', 'http://www.test.com/path', headers={'abc': 'aBC', 'DEF': 'def'}, request_headers={'abc': 'Abc'}) def test_case_sensitive_ignored_for_netloc_and_protocol(self): for case_sensitive in (True, False): self.assertMatch('http://AbC.CoM', 'http://aBc.CoM', case_sensitive=case_sensitive) self.assertMatch('htTP://abc.com', 'hTTp://abc.com', case_sensitive=case_sensitive) self.assertMatch('htTP://aBC.cOm', 'hTTp://AbC.Com', case_sensitive=case_sensitive) def assertSensitiveMatch(self, target, url, **kwargs): self.assertMatch(target, url, case_sensitive=False, **kwargs) self.assertNoMatch(target, url, case_sensitive=True, **kwargs) def test_case_sensitive_paths(self): self.assertSensitiveMatch('http://abc.com/pAtH', 'http://abc.com/path') self.assertSensitiveMatch('/pAtH', 'http://abc.com/path') def test_case_sensitive_query(self): self.assertSensitiveMatch('http://abc.com/path?abCD=efGH', 'http://abc.com/path?abCd=eFGH') self.assertSensitiveMatch('http://abc.com/path?abcd=efGH', 'http://abc.com/path?abcd=eFGH') def test_additional_matcher(self): def test_match_body(request): return 'hello' in request.text self.assertMatch(request_method='POST', matcher_method='POST', request_data='hello world', additional_matcher=test_match_body) self.assertNoMatch(request_method='POST', matcher_method='POST', request_data='goodbye world', additional_matcher=test_match_body) def test_reset_reverts_count(self): url = 'mock://test/site/' matcher = adapter._Matcher('GET', url, [_MatcherResponse()], complete_qs=False, additional_matcher=None, request_headers={}, real_http=False, case_sensitive=False) request = adapter._RequestObjectProxy._create('GET', url) call_count = 3 for _ in range(call_count): matcher(request) self.assertEqual(matcher.call_count, call_count) matcher.reset() self.assertEqual(matcher.call_count, 0)