test_matcher.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  2. # not use this file except in compliance with the License. You may obtain
  3. # a copy of the License at
  4. #
  5. # https://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. # License for the specific language governing permissions and limitations
  11. # under the License.
  12. import re
  13. from requests_mock import adapter
  14. from . import base
  15. from requests_mock.response import _MatcherResponse
  16. ANY = adapter.ANY
  17. class TestMatcher(base.TestCase):
  18. def match(self,
  19. target,
  20. url,
  21. matcher_method='GET',
  22. request_method='GET',
  23. complete_qs=False,
  24. headers=None,
  25. request_data=None,
  26. request_headers={},
  27. additional_matcher=None,
  28. real_http=False,
  29. case_sensitive=False):
  30. matcher = adapter._Matcher(matcher_method,
  31. target,
  32. [],
  33. complete_qs=complete_qs,
  34. additional_matcher=additional_matcher,
  35. request_headers=request_headers,
  36. real_http=real_http,
  37. case_sensitive=case_sensitive)
  38. request = adapter._RequestObjectProxy._create(request_method,
  39. url,
  40. headers,
  41. data=request_data)
  42. return matcher._match(request)
  43. def assertMatch(self,
  44. target=ANY,
  45. url='http://example.com/requests-mock',
  46. matcher_method='GET',
  47. request_method='GET',
  48. **kwargs):
  49. self.assertEqual(True,
  50. self.match(target,
  51. url,
  52. matcher_method=matcher_method,
  53. request_method=request_method,
  54. **kwargs),
  55. 'Matcher %s %s failed to match %s %s' %
  56. (matcher_method, target, request_method, url))
  57. def assertMatchBoth(self,
  58. target=ANY,
  59. url='http://example.com/requests-mock',
  60. matcher_method='GET',
  61. request_method='GET',
  62. **kwargs):
  63. self.assertMatch(target,
  64. url,
  65. matcher_method=matcher_method,
  66. request_method=request_method,
  67. **kwargs)
  68. self.assertMatch(url,
  69. target,
  70. matcher_method=request_method,
  71. request_method=matcher_method,
  72. **kwargs)
  73. def assertNoMatch(self,
  74. target=ANY,
  75. url='http://example.com/requests-mock',
  76. matcher_method='GET',
  77. request_method='GET',
  78. **kwargs):
  79. self.assertEqual(False,
  80. self.match(target,
  81. url,
  82. matcher_method=matcher_method,
  83. request_method=request_method,
  84. **kwargs),
  85. 'Matcher %s %s unexpectedly matched %s %s' %
  86. (matcher_method, target, request_method, url))
  87. def assertNoMatchBoth(self,
  88. target=ANY,
  89. url='http://example.com/requests-mock',
  90. matcher_method='GET',
  91. request_method='GET',
  92. **kwargs):
  93. self.assertNoMatch(target,
  94. url,
  95. matcher_method=matcher_method,
  96. request_method=request_method,
  97. **kwargs)
  98. self.assertNoMatch(url,
  99. target,
  100. matcher_method=request_method,
  101. request_method=matcher_method,
  102. **kwargs)
  103. def assertMatchMethodBoth(self, matcher_method, request_method, **kwargs):
  104. url = 'http://www.test.com'
  105. self.assertMatchBoth(url,
  106. url,
  107. request_method=request_method,
  108. matcher_method=matcher_method,
  109. **kwargs)
  110. def assertNoMatchMethodBoth(self,
  111. matcher_method,
  112. request_method,
  113. **kwargs):
  114. url = 'http://www.test.com'
  115. self.assertNoMatchBoth(url,
  116. url,
  117. request_method=request_method,
  118. matcher_method=matcher_method,
  119. **kwargs)
  120. def test_url_matching(self):
  121. self.assertMatchBoth('http://www.test.com',
  122. 'http://www.test.com')
  123. self.assertMatchBoth('http://www.test.com',
  124. 'http://www.test.com/')
  125. self.assertMatchBoth('http://www.test.com/abc',
  126. 'http://www.test.com/abc')
  127. self.assertMatchBoth('http://www.test.com:5000/abc',
  128. 'http://www.test.com:5000/abc')
  129. self.assertNoMatchBoth('https://www.test.com',
  130. 'http://www.test.com')
  131. self.assertNoMatchBoth('http://www.test.com/abc',
  132. 'http://www.test.com')
  133. self.assertNoMatchBoth('http://test.com',
  134. 'http://www.test.com')
  135. self.assertNoMatchBoth('http://test.com',
  136. 'http://www.test.com')
  137. self.assertNoMatchBoth('http://test.com/abc',
  138. 'http://www.test.com/abc/')
  139. self.assertNoMatchBoth('http://test.com/abc/',
  140. 'http://www.test.com/abc')
  141. self.assertNoMatchBoth('http://test.com:5000/abc/',
  142. 'http://www.test.com/abc')
  143. self.assertNoMatchBoth('http://test.com/abc/',
  144. 'http://www.test.com:5000/abc')
  145. def test_quotation(self):
  146. self.assertMatchBoth('http://www.test.com/a string%url',
  147. 'http://www.test.com/a string%url')
  148. self.assertMatchBoth('http://www.test.com/ABC 123',
  149. 'http://www.test.com/ABC%20123')
  150. self.assertMatchBoth('http://www.test.com/user@example.com',
  151. 'http://www.test.com/user@example.com')
  152. def test_subset_match(self):
  153. self.assertMatch('/path', 'http://www.test.com/path')
  154. self.assertMatch('/path', 'http://www.test.com/path')
  155. self.assertMatch('//www.test.com/path', 'http://www.test.com/path')
  156. self.assertMatch('//www.test.com/path', 'https://www.test.com/path')
  157. def test_query_string(self):
  158. self.assertMatch('/path?a=1&b=2',
  159. 'http://www.test.com/path?a=1&b=2')
  160. self.assertMatch('/path?a=1',
  161. 'http://www.test.com/path?a=1&b=2',
  162. complete_qs=False)
  163. self.assertNoMatch('/path?a=1',
  164. 'http://www.test.com/path?a=1&b=2',
  165. complete_qs=True)
  166. self.assertNoMatch('/path?a=1&b=2',
  167. 'http://www.test.com/path?a=1')
  168. def test_query_empty_string(self):
  169. self.assertMatch('/path?a',
  170. 'http://www.test.com/path?a')
  171. self.assertMatch('/path?bob&paul',
  172. 'http://www.test.com/path?paul&bob')
  173. self.assertNoMatch('/path?bob',
  174. 'http://www.test.com/path?paul')
  175. self.assertNoMatch('/path?pual&bob',
  176. 'http://www.test.com/path?bob')
  177. def test_method_match(self):
  178. self.assertNoMatchMethodBoth('GET', 'POST')
  179. self.assertMatchMethodBoth('GET', 'get')
  180. self.assertMatchMethodBoth('GeT', 'geT')
  181. def test_match_ANY_url(self):
  182. self.assertMatch(ANY, 'http://anything')
  183. self.assertMatch(ANY, 'http://somethingelse')
  184. self.assertNoMatch(ANY, 'http://somethingelse', request_method='POST')
  185. def test_match_ANY_method(self):
  186. for m in ('GET', 'POST', 'HEAD', 'OPTION'):
  187. self.assertMatch('http://www.test.com',
  188. 'http://www.test.com',
  189. matcher_method=ANY,
  190. request_method=m)
  191. self.assertNoMatch('http://www.test.com',
  192. 'http://another',
  193. matcher_method=ANY)
  194. def test_match_with_regex(self):
  195. r1 = re.compile('test.com/a')
  196. r2 = re.compile('/b/c')
  197. self.assertMatch(r1, 'http://mock.test.com/a/b')
  198. self.assertMatch(r1, 'http://test.com/a/')
  199. self.assertMatch(r1, 'mock://test.com/a/b')
  200. self.assertNoMatch(r1, 'mock://test.com/')
  201. self.assertMatch(r2, 'http://anything/a/b/c/d')
  202. self.assertMatch(r2, 'mock://anything/a/b/c/d')
  203. def test_match_with_headers(self):
  204. self.assertMatch('/path',
  205. 'http://www.test.com/path',
  206. headers={'A': 'abc', 'b': 'def'},
  207. request_headers={'a': 'abc'})
  208. self.assertMatch('/path',
  209. 'http://www.test.com/path',
  210. headers={'A': 'abc', 'b': 'def'})
  211. self.assertNoMatch('/path',
  212. 'http://www.test.com/path',
  213. headers={'A': 'abc', 'b': 'def'},
  214. request_headers={'b': 'abc'})
  215. self.assertNoMatch('/path',
  216. 'http://www.test.com/path',
  217. headers={'A': 'abc', 'b': 'def'},
  218. request_headers={'c': 'ghi'})
  219. # headers should be key insensitive and value sensitive, we have no
  220. # choice here because they go into an insensitive dict.
  221. self.assertMatch('/path',
  222. 'http://www.test.com/path',
  223. headers={'aBc': 'abc', 'DEF': 'def'},
  224. request_headers={'abC': 'abc'})
  225. self.assertNoMatch('/path',
  226. 'http://www.test.com/path',
  227. headers={'abc': 'aBC', 'DEF': 'def'},
  228. request_headers={'abc': 'Abc'})
  229. def test_case_sensitive_ignored_for_netloc_and_protocol(self):
  230. for case_sensitive in (True, False):
  231. self.assertMatch('http://AbC.CoM',
  232. 'http://aBc.CoM',
  233. case_sensitive=case_sensitive)
  234. self.assertMatch('htTP://abc.com',
  235. 'hTTp://abc.com',
  236. case_sensitive=case_sensitive)
  237. self.assertMatch('htTP://aBC.cOm',
  238. 'hTTp://AbC.Com',
  239. case_sensitive=case_sensitive)
  240. def assertSensitiveMatch(self, target, url, **kwargs):
  241. self.assertMatch(target, url, case_sensitive=False, **kwargs)
  242. self.assertNoMatch(target, url, case_sensitive=True, **kwargs)
  243. def test_case_sensitive_paths(self):
  244. self.assertSensitiveMatch('http://abc.com/pAtH', 'http://abc.com/path')
  245. self.assertSensitiveMatch('/pAtH', 'http://abc.com/path')
  246. def test_case_sensitive_query(self):
  247. self.assertSensitiveMatch('http://abc.com/path?abCD=efGH',
  248. 'http://abc.com/path?abCd=eFGH')
  249. self.assertSensitiveMatch('http://abc.com/path?abcd=efGH',
  250. 'http://abc.com/path?abcd=eFGH')
  251. def test_additional_matcher(self):
  252. def test_match_body(request):
  253. return 'hello' in request.text
  254. self.assertMatch(request_method='POST',
  255. matcher_method='POST',
  256. request_data='hello world',
  257. additional_matcher=test_match_body)
  258. self.assertNoMatch(request_method='POST',
  259. matcher_method='POST',
  260. request_data='goodbye world',
  261. additional_matcher=test_match_body)
  262. def test_reset_reverts_count(self):
  263. url = 'mock://test/site/'
  264. matcher = adapter._Matcher('GET',
  265. url,
  266. [_MatcherResponse()],
  267. complete_qs=False,
  268. additional_matcher=None,
  269. request_headers={},
  270. real_http=False,
  271. case_sensitive=False)
  272. request = adapter._RequestObjectProxy._create('GET', url)
  273. call_count = 3
  274. for _ in range(call_count):
  275. matcher(request)
  276. self.assertEqual(matcher.call_count, call_count)
  277. matcher.reset()
  278. self.assertEqual(matcher.call_count, 0)