live_test.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. '''Test live services.'''
  2. import codecs
  3. import glob
  4. import os
  5. import os.path
  6. import unittest
  7. from terroroftinytown.services.registry import registry
  8. from terroroftinytown.services.status import URLStatus
  9. from terroroftinytown.six import u
  10. import terroroftinytown
  11. import time
  12. from terroroftinytown.client.errors import MalformedResponse
  13. MOCK_PARAMS = {
  14. 'isgd': {
  15. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_',
  16. 'url_template': 'https://is.gd/{shortcode}',
  17. 'redirect_codes': [301, 302],
  18. 'no_redirect_codes': [404],
  19. 'unavailable_codes': [200, 410],
  20. 'banned_codes': [403, 420, 429, 502],
  21. 'method': 'get',
  22. 'location_anti_regex': r'^https://is\.gd/'
  23. },
  24. 'vgd': {
  25. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_',
  26. 'url_template': 'https://v.gd/{shortcode}',
  27. 'redirect_codes': [301, 302],
  28. 'no_redirect_codes': [404],
  29. 'unavailable_codes': [200, 410],
  30. 'banned_codes': [403, 420, 429, 502],
  31. 'method': 'get',
  32. },
  33. 'bitly': {
  34. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
  35. 'url_template': 'http://bit.ly/{shortcode}',
  36. 'redirect_codes': [301, 302],
  37. 'no_redirect_codes': [404],
  38. 'unavailable_codes': [410],
  39. 'banned_codes': [403],
  40. 'method': 'head',
  41. },
  42. 'xco': {
  43. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  44. 'url_template': 'http://x.co/{shortcode}',
  45. 'redirect_codes': [301],
  46. 'no_redirect_codes': [200],
  47. 'banned_codes': [403, 420, 429],
  48. 'method': 'head',
  49. },
  50. 'pub-vitrue-com': {
  51. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  52. 'url_template': 'http://pub.vitrue.com/{shortcode}',
  53. 'redirect_codes': [301],
  54. 'no_redirect_codes': [302],
  55. 'banned_codes': [403, 420, 429],
  56. 'method': 'head',
  57. },
  58. 'tighturl-com': {
  59. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  60. 'url_template': 'http://tighturl.com/{shortcode}',
  61. 'redirect_codes': [301],
  62. 'no_redirect_codes': [404],
  63. 'banned_codes': [420, 429],
  64. 'method': 'head',
  65. },
  66. 'tinyurl': {
  67. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyz',
  68. 'url_template': 'http://tinyurl.com/{shortcode}',
  69. 'redirect_codes': [200, 301, 307],
  70. 'no_redirect_codes': [404],
  71. 'unavailable_codes': [302],
  72. 'banned_codes': [420, 429],
  73. 'method': 'head',
  74. },
  75. 'adjix': {
  76. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyz',
  77. 'url_template': 'http://adjix.com/{shortcode}',
  78. 'redirect_codes': [200],
  79. 'no_redirect_codes': [403, 404],
  80. 'unavailable_codes': [],
  81. 'banned_codes': [420, 429],
  82. 'method': 'get',
  83. },
  84. 'yatuc': {
  85. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyz',
  86. 'url_template': 'http://yatuc.com/{shortcode}',
  87. 'redirect_codes': [302],
  88. 'no_redirect_codes': [],
  89. 'unavailable_codes': [],
  90. 'banned_codes': [420, 429],
  91. 'method': 'head',
  92. },
  93. 'shar-es': {
  94. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  95. 'url_template': 'http://shar.es/{shortcode}',
  96. 'redirect_codes': [200, 301],
  97. 'no_redirect_codes': [404],
  98. 'unavailable_codes': [],
  99. 'banned_codes': [403, 420, 429],
  100. 'method': 'get',
  101. 'body_regex': r'<a id="clickthrough"\s+href="(.*)">',
  102. },
  103. 'feedly': {
  104. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
  105. 'url_template': 'http://feedly.com/e/{shortcode}',
  106. 'redirect_codes': [302],
  107. 'no_redirect_codes': [],
  108. 'unavailable_codes': [],
  109. 'banned_codes': [403, 420, 429],
  110. 'method': 'head',
  111. },
  112. 'awe-sm': {
  113. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  114. 'url_template': 'http://awe.sm/{shortcode}',
  115. 'redirect_codes': [301],
  116. 'no_redirect_codes': [],
  117. 'unavailable_codes': [],
  118. 'banned_codes': [403, 420, 429],
  119. 'method': 'head',
  120. },
  121. 'ow-ly': {
  122. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  123. 'url_template': 'http://ow.ly/{shortcode}',
  124. 'redirect_codes': [301, 302],
  125. 'no_redirect_codes': [404],
  126. 'unavailable_codes': [410],
  127. 'banned_codes': [403, 420, 429],
  128. 'method': 'head',
  129. },
  130. 'snipurl': {
  131. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyz-_~',
  132. 'url_template': 'http://snipurl.com/{shortcode}',
  133. 'redirect_codes': [301],
  134. 'no_redirect_codes': [410],
  135. 'unavailable_codes': [],
  136. 'banned_codes': [403, 420, 429],
  137. 'method': 'head',
  138. },
  139. 'sharedby-co': {
  140. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  141. 'url_template': 'http://sharedby.co/{shortcode}',
  142. 'redirect_codes': [200, 301],
  143. 'no_redirect_codes': [302],
  144. 'unavailable_codes': [],
  145. 'banned_codes': [403, 420, 429],
  146. 'method': 'get',
  147. 'body_regex': r'<iframe id="[^"]+" src="([^"]+)">'
  148. },
  149. 'mysp-ac': {
  150. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  151. 'url_template': 'https://mysp.ac/{shortcode}',
  152. 'redirect_codes': [301, 302],
  153. 'no_redirect_codes': [0],
  154. 'unavailable_codes': [],
  155. 'banned_codes': [403, 420, 429],
  156. 'method': 'head',
  157. },
  158. 'alturl-com': {
  159. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyz',
  160. 'url_template': 'http://alturl.com/{shortcode}',
  161. 'redirect_codes': [302],
  162. 'no_redirect_codes': [200],
  163. 'unavailable_codes': [301, 410],
  164. 'banned_codes': [403, 420, 429],
  165. 'method': 'get',
  166. },
  167. 'tinyurl-hu': {
  168. 'alphabet': '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  169. 'url_template': 'http://tinyurl.hu/{shortcode}/',
  170. 'redirect_codes': [200],
  171. 'no_redirect_codes': [],
  172. 'unavailable_codes': [],
  173. 'banned_codes': [403, 420, 429],
  174. 'method': 'get',
  175. 'body_regex': r'<b></b> <a href="(.*)">',
  176. },
  177. }
  178. class TestLive(unittest.TestCase):
  179. # @unittest.skipIf(os.environ.get('NO_LIVE_SERVICE_TEST'), 'no live test')
  180. def test_custom_services(self):
  181. # for python 2.6 compatbility
  182. if os.environ.get('NO_LIVE_SERVICE_TEST'):
  183. print('SKIP')
  184. return
  185. filenames = get_definition_filenames()
  186. for filename in filenames:
  187. service_name = os.path.split(filename)[-1].replace('.txt', '')
  188. # if service_name not in ('tinyurl',):
  189. # print('Skip', service_name)
  190. # continue
  191. params = MOCK_PARAMS[service_name]
  192. service = registry[u(service_name)](params)
  193. print('Brought up service', service)
  194. service.prepare()
  195. with codecs.open(filename, 'rb') as def_file:
  196. for shortcode, expected_result in iterate_definition_file(def_file):
  197. service.current_shortcode = shortcode
  198. url = params['url_template'].format(shortcode=shortcode)
  199. print('Requesting', url, 'Expect:', expected_result)
  200. try:
  201. response = service.fetch_url(url)
  202. except MalformedResponse:
  203. url_status, result_url, encoding = (URLStatus.unavailable, None, None)
  204. else:
  205. url_status, result_url, encoding = service.process_response(response)
  206. if terroroftinytown.six.PY2 and \
  207. isinstance(result_url, terroroftinytown.six.binary_type):
  208. result_url = result_url.decode(encoding)
  209. print(' Got', url_status, result_url, encoding)
  210. if url_status == URLStatus.ok:
  211. self.assertEqual(expected_result, result_url)
  212. else:
  213. self.assertEqual(expected_result, url_status)
  214. time.sleep(0.7)
  215. def iterate_definition_file(file):
  216. for line in file:
  217. line = line.strip()
  218. if not line or line.startswith(b'#'):
  219. continue
  220. if line.startswith(b'?'):
  221. encoding, line = line[1:].split(b'?', 1)
  222. encoding = encoding.decode('ascii')
  223. line = line.decode(encoding)
  224. else:
  225. line = line.decode('utf-8')
  226. shortcode, result = line.split('|', 1)
  227. yield (shortcode, result)
  228. def get_definition_filenames():
  229. def_path = os.path.join(os.path.dirname(__file__), 'test-definitions')
  230. return sorted(glob.glob(def_path + '/*.txt'))