test_encode.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. # -*- coding: utf-8 -*-
  2. from unittest import TestCase
  3. import mimetypes
  4. import poster.encode
  5. import StringIO
  6. import sys
  7. def unix2dos(s):
  8. return s.replace("\n", "\r\n")
  9. class TestEncode_String(TestCase):
  10. def test_simple(self):
  11. expected = unix2dos("""--XXXXXXXXX
  12. Content-Disposition: form-data; name="foo"
  13. Content-Type: text/plain; charset=utf-8
  14. bar
  15. """)
  16. self.assertEqual(expected,
  17. poster.encode.encode_string("XXXXXXXXX", "foo", "bar"))
  18. def test_quote_name_space(self):
  19. expected = unix2dos("""--XXXXXXXXX
  20. Content-Disposition: form-data; name="foo baz"
  21. Content-Type: text/plain; charset=utf-8
  22. bar
  23. """)
  24. self.assertEqual(expected,
  25. poster.encode.encode_string("XXXXXXXXX", "foo baz", "bar"))
  26. def test_quote_name_phparray(self):
  27. expected = unix2dos("""--XXXXXXXXX
  28. Content-Disposition: form-data; name="files[]"
  29. Content-Type: text/plain; charset=utf-8
  30. bar
  31. """)
  32. self.assertEqual(expected,
  33. poster.encode.encode_string("XXXXXXXXX", "files[]", "bar"))
  34. def test_quote_unicode_name(self):
  35. expected = unix2dos("""--XXXXXXXXX
  36. Content-Disposition: form-data; name="=?utf-8?b?4piD?="
  37. Content-Type: text/plain; charset=utf-8
  38. bar
  39. """)
  40. self.assertEqual(expected,
  41. poster.encode.encode_string("XXXXXXXXX", u"\N{SNOWMAN}", "bar"))
  42. def test_quote_value(self):
  43. expected = unix2dos("""--XXXXXXXXX
  44. Content-Disposition: form-data; name="foo"
  45. Content-Type: text/plain; charset=utf-8
  46. bar baz@bat
  47. """)
  48. self.assertEqual(expected,
  49. poster.encode.encode_string("XXXXXXXXX", "foo", "bar baz@bat"))
  50. def test_boundary(self):
  51. expected = unix2dos("""--ABC+DEF
  52. Content-Disposition: form-data; name="foo"
  53. Content-Type: text/plain; charset=utf-8
  54. bar
  55. """)
  56. self.assertEqual(expected,
  57. poster.encode.encode_string("ABC DEF", "foo", "bar"))
  58. def test_unicode(self):
  59. expected = unix2dos("""--XXXXXXXXX
  60. Content-Disposition: form-data; name="foo"
  61. Content-Type: text/plain; charset=utf-8
  62. b\xc3\xa1r
  63. """)
  64. self.assertEqual(expected,
  65. poster.encode.encode_string("XXXXXXXXX", "foo", u"bár"))
  66. class TestEncode_File(TestCase):
  67. def test_simple(self):
  68. expected = unix2dos("""--XXXXXXXXX
  69. Content-Disposition: form-data; name="foo"
  70. Content-Type: text/plain; charset=utf-8
  71. """)
  72. self.assertEqual(expected,
  73. poster.encode.encode_file_header("XXXXXXXXX", "foo", 42))
  74. def test_content_type(self):
  75. expected = unix2dos("""--XXXXXXXXX
  76. Content-Disposition: form-data; name="foo"
  77. Content-Type: text/html
  78. """)
  79. self.assertEqual(expected,
  80. poster.encode.encode_file_header("XXXXXXXXX", "foo", 42, filetype="text/html"))
  81. def test_filename_simple(self):
  82. expected = unix2dos("""--XXXXXXXXX
  83. Content-Disposition: form-data; name="foo"; filename="test.txt"
  84. Content-Type: text/plain; charset=utf-8
  85. """)
  86. self.assertEqual(expected,
  87. poster.encode.encode_file_header("XXXXXXXXX", "foo", 42,
  88. "test.txt"))
  89. def test_quote_filename(self):
  90. expected = unix2dos("""--XXXXXXXXX
  91. Content-Disposition: form-data; name="foo"; filename="test file.txt"
  92. Content-Type: text/plain; charset=utf-8
  93. """)
  94. self.assertEqual(expected,
  95. poster.encode.encode_file_header("XXXXXXXXX", "foo", 42,
  96. "test file.txt"))
  97. expected = unix2dos("""--XXXXXXXXX
  98. Content-Disposition: form-data; name="foo"; filename="test\\"file.txt"
  99. Content-Type: text/plain; charset=utf-8
  100. """)
  101. self.assertEqual(expected,
  102. poster.encode.encode_file_header("XXXXXXXXX", "foo", 42,
  103. "test\"file.txt"))
  104. def test_unicode_filename(self):
  105. expected = unix2dos("""--XXXXXXXXX
  106. Content-Disposition: form-data; name="foo"; filename="☃.txt"
  107. Content-Type: text/plain; charset=utf-8
  108. """)
  109. self.assertEqual(expected,
  110. poster.encode.encode_file_header("XXXXXXXXX", "foo", 42,
  111. u"\N{SNOWMAN}.txt"))
  112. class TestEncodeAndQuote(TestCase):
  113. def test(self):
  114. self.assertEqual("foo+bar", poster.encode.encode_and_quote("foo bar"))
  115. self.assertEqual("foo%40bar", poster.encode.encode_and_quote("foo@bar"))
  116. self.assertEqual("%28%C2%A9%29+2008",
  117. poster.encode.encode_and_quote(u"(©) 2008"))
  118. class TestMultiparam(TestCase):
  119. def test_from_params(self):
  120. fp = open("tests/test_encode.py")
  121. expected = [poster.encode.MultipartParam("foo", "bar"),
  122. poster.encode.MultipartParam("baz", fileobj=fp,
  123. filename=fp.name,
  124. filetype=mimetypes.guess_type(fp.name)[0])]
  125. self.assertEqual(poster.encode.MultipartParam.from_params(
  126. [("foo", "bar"), ("baz", fp)]), expected)
  127. self.assertEqual(poster.encode.MultipartParam.from_params(
  128. (("foo", "bar"), ("baz", fp))), expected)
  129. self.assertEqual(poster.encode.MultipartParam.from_params(
  130. {"foo": "bar", "baz": fp}), expected)
  131. self.assertEqual(poster.encode.MultipartParam.from_params(
  132. [expected[0], expected[1]]), expected)
  133. def test_from_params_dict(self):
  134. p = poster.encode.MultipartParam('file', fileobj=open("tests/test_encode.py"))
  135. params = {"foo": "bar", "file": p}
  136. expected = [poster.encode.MultipartParam("foo", "bar"), p]
  137. retval = poster.encode.MultipartParam.from_params(params)
  138. expected.sort()
  139. retval.sort()
  140. self.assertEqual(retval, expected)
  141. def test_from_params_assertion(self):
  142. p = poster.encode.MultipartParam('file', fileobj=open("tests/test_encode.py"))
  143. params = {"foo": "bar", "baz": p}
  144. self.assertRaises(AssertionError, poster.encode.MultipartParam.from_params,
  145. params)
  146. def test_simple(self):
  147. p = poster.encode.MultipartParam("foo", "bar")
  148. boundary = "XYZXYZXYZ"
  149. expected = unix2dos("""--XYZXYZXYZ
  150. Content-Disposition: form-data; name="foo"
  151. Content-Type: text/plain; charset=utf-8
  152. bar
  153. --XYZXYZXYZ--
  154. """)
  155. self.assertEqual(p.encode(boundary), expected[:-len(boundary)-6])
  156. self.assertEqual(p.get_size(boundary), len(expected)-len(boundary)-6)
  157. self.assertEqual(poster.encode.get_body_size([p], boundary),
  158. len(expected))
  159. self.assertEqual(poster.encode.get_headers([p], boundary),
  160. {'Content-Length': str(len(expected)),
  161. 'Content-Type': 'multipart/form-data; boundary=%s' % boundary})
  162. datagen, headers = poster.encode.multipart_encode([p], boundary)
  163. self.assertEqual(headers, {'Content-Length': str(len(expected)),
  164. 'Content-Type': 'multipart/form-data; boundary=%s' % boundary})
  165. self.assertEqual("".join(datagen), expected)
  166. def test_multiple_keys(self):
  167. params = poster.encode.MultipartParam.from_params(
  168. [("key", "value1"), ("key", "value2")])
  169. boundary = "XYZXYZXYZ"
  170. datagen, headers = poster.encode.multipart_encode(params, boundary)
  171. encoded = "".join(datagen)
  172. expected = unix2dos("""--XYZXYZXYZ
  173. Content-Disposition: form-data; name="key"
  174. Content-Type: text/plain; charset=utf-8
  175. value1
  176. --XYZXYZXYZ
  177. Content-Disposition: form-data; name="key"
  178. Content-Type: text/plain; charset=utf-8
  179. value2
  180. --XYZXYZXYZ--
  181. """)
  182. self.assertEqual(encoded, expected)
  183. def test_stringio(self):
  184. fp = StringIO.StringIO("file data")
  185. params = poster.encode.MultipartParam.from_params( [("foo", fp)] )
  186. boundary = "XYZXYZXYZ"
  187. datagen, headers = poster.encode.multipart_encode(params, boundary)
  188. encoded = "".join(datagen)
  189. expected = unix2dos("""--XYZXYZXYZ
  190. Content-Disposition: form-data; name="foo"
  191. Content-Type: text/plain; charset=utf-8
  192. file data
  193. --XYZXYZXYZ--
  194. """)
  195. self.assertEqual(encoded, expected)
  196. def test_reset_string(self):
  197. p = poster.encode.MultipartParam("foo", "bar")
  198. boundary = "XYZXYZXYZ"
  199. datagen, headers = poster.encode.multipart_encode([p], boundary)
  200. expected = unix2dos("""--XYZXYZXYZ
  201. Content-Disposition: form-data; name="foo"
  202. Content-Type: text/plain; charset=utf-8
  203. bar
  204. --XYZXYZXYZ--
  205. """)
  206. self.assertEquals("".join(datagen), expected)
  207. datagen.reset()
  208. self.assertEquals("".join(datagen), expected)
  209. def test_reset_multiple_keys(self):
  210. params = poster.encode.MultipartParam.from_params(
  211. [("key", "value1"), ("key", "value2")])
  212. boundary = "XYZXYZXYZ"
  213. datagen, headers = poster.encode.multipart_encode(params, boundary)
  214. expected = unix2dos("""--XYZXYZXYZ
  215. Content-Disposition: form-data; name="key"
  216. Content-Type: text/plain; charset=utf-8
  217. value1
  218. --XYZXYZXYZ
  219. Content-Disposition: form-data; name="key"
  220. Content-Type: text/plain; charset=utf-8
  221. value2
  222. --XYZXYZXYZ--
  223. """)
  224. encoded = "".join(datagen)
  225. self.assertEqual(encoded, expected)
  226. datagen.reset()
  227. encoded = "".join(datagen)
  228. self.assertEqual(encoded, expected)
  229. def test_reset_file(self):
  230. fp = StringIO.StringIO("file data")
  231. params = poster.encode.MultipartParam.from_params( [("foo", fp)] )
  232. boundary = "XYZXYZXYZ"
  233. datagen, headers = poster.encode.multipart_encode(params, boundary)
  234. expected = unix2dos("""--XYZXYZXYZ
  235. Content-Disposition: form-data; name="foo"
  236. Content-Type: text/plain; charset=utf-8
  237. file data
  238. --XYZXYZXYZ--
  239. """)
  240. encoded = "".join(datagen)
  241. self.assertEqual(encoded, expected)
  242. datagen.reset()
  243. encoded = "".join(datagen)
  244. self.assertEqual(encoded, expected)
  245. def test_MultipartParam_cb(self):
  246. log = []
  247. def cb(p, current, total):
  248. log.append( (p, current, total) )
  249. p = poster.encode.MultipartParam("foo", "bar", cb=cb)
  250. boundary = "XYZXYZXYZ"
  251. datagen, headers = poster.encode.multipart_encode([p], boundary)
  252. "".join(datagen)
  253. l = p.get_size(boundary)
  254. self.assertEquals(log[-1], (p, l, l))
  255. def test_MultipartParam_file_cb(self):
  256. log = []
  257. def cb(p, current, total):
  258. log.append( (p, current, total) )
  259. p = poster.encode.MultipartParam("foo", fileobj=open("tests/test_encode.py"),
  260. cb=cb)
  261. boundary = poster.encode.gen_boundary()
  262. list(p.iter_encode(boundary))
  263. l = p.get_size(boundary)
  264. self.assertEquals(log[-1], (p, l, l))
  265. def test_multipart_encode_cb(self):
  266. log = []
  267. def cb(p, current, total):
  268. log.append( (p, current, total) )
  269. p = poster.encode.MultipartParam("foo", "bar")
  270. boundary = "XYZXYZXYZ"
  271. datagen, headers = poster.encode.multipart_encode([p], boundary, cb=cb)
  272. "".join(datagen)
  273. l = int(headers['Content-Length'])
  274. self.assertEquals(log[-1], (None, l, l))
  275. class TestGenBoundary(TestCase):
  276. def testGenBoundary(self):
  277. boundary1 = poster.encode.gen_boundary()
  278. boundary2 = poster.encode.gen_boundary()
  279. self.assertNotEqual(boundary1, boundary2)
  280. self.assert_(len(boundary1) > 0)
  281. class TestBackupGenBoundary(TestGenBoundary):
  282. _orig_import = __import__
  283. def setUp(self):
  284. # Make import uuid fail
  285. def my_import(name, *args, **kwargs):
  286. if name == 'uuid':
  287. raise ImportError("Disabled for testing")
  288. return self._orig_import(name, *args, **kwargs)
  289. __builtins__['__import__'] = my_import
  290. reload(poster.encode)
  291. def tearDown(self):
  292. __builtins__['__import__'] = self._orig_import
  293. reload(poster.encode)