PageRenderTime 26ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/integration/s3/test_key.py

https://bitbucket.org/davidgorski/boto
Python | 375 lines | 337 code | 8 blank | 30 comment | 5 complexity | 824c7aeea51ebea1052fd7d31eacc133 MD5 | raw file
  1. # Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
  2. # All rights reserved.
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a
  5. # copy of this software and associated documentation files (the
  6. # "Software"), to deal in the Software without restriction, including
  7. # without limitation the rights to use, copy, modify, merge, publish, dis-
  8. # tribute, sublicense, and/or sell copies of the Software, and to permit
  9. # persons to whom the Software is furnished to do so, subject to the fol-
  10. # lowing conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included
  13. # in all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  16. # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
  17. # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  18. # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. # IN THE SOFTWARE.
  22. """
  23. Some unit tests for S3 Key
  24. """
  25. from tests.unit import unittest
  26. import time
  27. import StringIO
  28. from boto.s3.connection import S3Connection
  29. from boto.s3.key import Key
  30. from boto.exception import S3ResponseError
  31. class S3KeyTest (unittest.TestCase):
  32. s3 = True
  33. def setUp(self):
  34. self.conn = S3Connection()
  35. self.bucket_name = 'keytest-%d' % int(time.time())
  36. self.bucket = self.conn.create_bucket(self.bucket_name)
  37. def tearDown(self):
  38. for key in self.bucket:
  39. key.delete()
  40. self.bucket.delete()
  41. def test_set_contents_from_file_dataloss(self):
  42. # Create an empty stringio and write to it.
  43. content = "abcde"
  44. sfp = StringIO.StringIO()
  45. sfp.write(content)
  46. # Try set_contents_from_file() without rewinding sfp
  47. k = self.bucket.new_key("k")
  48. try:
  49. k.set_contents_from_file(sfp)
  50. self.fail("forgot to rewind so should fail.")
  51. except AttributeError:
  52. pass
  53. # call with rewind and check if we wrote 5 bytes
  54. k.set_contents_from_file(sfp, rewind=True)
  55. self.assertEqual(k.size, 5)
  56. # check actual contents by getting it.
  57. kn = self.bucket.new_key("k")
  58. ks = kn.get_contents_as_string()
  59. self.assertEqual(ks, content)
  60. # finally, try with a 0 length string
  61. sfp = StringIO.StringIO()
  62. k = self.bucket.new_key("k")
  63. k.set_contents_from_file(sfp)
  64. self.assertEqual(k.size, 0)
  65. # check actual contents by getting it.
  66. kn = self.bucket.new_key("k")
  67. ks = kn.get_contents_as_string()
  68. self.assertEqual(ks, "")
  69. def test_set_contents_as_file(self):
  70. content="01234567890123456789"
  71. sfp = StringIO.StringIO(content)
  72. # fp is set at 0 for just opened (for read) files.
  73. # set_contents should write full content to key.
  74. k = self.bucket.new_key("k")
  75. k.set_contents_from_file(sfp)
  76. self.assertEqual(k.size, 20)
  77. kn = self.bucket.new_key("k")
  78. ks = kn.get_contents_as_string()
  79. self.assertEqual(ks, content)
  80. # set fp to 5 and set contents. this should
  81. # set "567890123456789" to the key
  82. sfp.seek(5)
  83. k = self.bucket.new_key("k")
  84. k.set_contents_from_file(sfp)
  85. self.assertEqual(k.size, 15)
  86. kn = self.bucket.new_key("k")
  87. ks = kn.get_contents_as_string()
  88. self.assertEqual(ks, content[5:])
  89. # set fp to 5 and only set 5 bytes. this should
  90. # write the value "56789" to the key.
  91. sfp.seek(5)
  92. k = self.bucket.new_key("k")
  93. k.set_contents_from_file(sfp, size=5)
  94. self.assertEqual(k.size, 5)
  95. self.assertEqual(sfp.tell(), 10)
  96. kn = self.bucket.new_key("k")
  97. ks = kn.get_contents_as_string()
  98. self.assertEqual(ks, content[5:10])
  99. def test_set_contents_with_md5(self):
  100. content="01234567890123456789"
  101. sfp = StringIO.StringIO(content)
  102. # fp is set at 0 for just opened (for read) files.
  103. # set_contents should write full content to key.
  104. k = self.bucket.new_key("k")
  105. good_md5 = k.compute_md5(sfp)
  106. k.set_contents_from_file(sfp, md5=good_md5)
  107. kn = self.bucket.new_key("k")
  108. ks = kn.get_contents_as_string()
  109. self.assertEqual(ks, content)
  110. # set fp to 5 and only set 5 bytes. this should
  111. # write the value "56789" to the key.
  112. sfp.seek(5)
  113. k = self.bucket.new_key("k")
  114. good_md5 = k.compute_md5(sfp, size=5)
  115. k.set_contents_from_file(sfp, size=5, md5=good_md5)
  116. self.assertEqual(sfp.tell(), 10)
  117. kn = self.bucket.new_key("k")
  118. ks = kn.get_contents_as_string()
  119. self.assertEqual(ks, content[5:10])
  120. # let's try a wrong md5 by just altering it.
  121. k = self.bucket.new_key("k")
  122. sfp.seek(0)
  123. hexdig, base64 = k.compute_md5(sfp)
  124. bad_md5 = (hexdig, base64[3:])
  125. try:
  126. k.set_contents_from_file(sfp, md5=bad_md5)
  127. self.fail("should fail with bad md5")
  128. except S3ResponseError:
  129. pass
  130. def test_get_contents_with_md5(self):
  131. content="01234567890123456789"
  132. sfp = StringIO.StringIO(content)
  133. k = self.bucket.new_key("k")
  134. k.set_contents_from_file(sfp)
  135. kn = self.bucket.new_key("k")
  136. s = kn.get_contents_as_string()
  137. self.assertEqual(kn.md5, k.md5)
  138. self.assertEqual(s, content)
  139. def test_file_callback(self):
  140. def callback(wrote, total):
  141. self.my_cb_cnt += 1
  142. self.assertNotEqual(wrote, self.my_cb_last, "called twice with same value")
  143. self.my_cb_last = wrote
  144. # Zero bytes written => 1 call
  145. self.my_cb_cnt = 0
  146. self.my_cb_last = None
  147. k = self.bucket.new_key("k")
  148. k.BufferSize = 2
  149. sfp = StringIO.StringIO("")
  150. k.set_contents_from_file(sfp, cb=callback, num_cb=10)
  151. self.assertEqual(self.my_cb_cnt, 1)
  152. self.assertEqual(self.my_cb_last, 0)
  153. sfp.close()
  154. # Read back zero bytes => 1 call
  155. self.my_cb_cnt = 0
  156. self.my_cb_last = None
  157. s = k.get_contents_as_string(cb=callback)
  158. self.assertEqual(self.my_cb_cnt, 1)
  159. self.assertEqual(self.my_cb_last, 0)
  160. content="01234567890123456789"
  161. sfp = StringIO.StringIO(content)
  162. # expect 2 calls due start/finish
  163. self.my_cb_cnt = 0
  164. self.my_cb_last = None
  165. k = self.bucket.new_key("k")
  166. k.set_contents_from_file(sfp, cb=callback, num_cb=10)
  167. self.assertEqual(self.my_cb_cnt, 2)
  168. self.assertEqual(self.my_cb_last, 20)
  169. # Read back all bytes => 2 calls
  170. self.my_cb_cnt = 0
  171. self.my_cb_last = None
  172. s = k.get_contents_as_string(cb=callback)
  173. self.assertEqual(self.my_cb_cnt, 2)
  174. self.assertEqual(self.my_cb_last, 20)
  175. self.assertEqual(s, content)
  176. # rewind sfp and try upload again. -1 should call
  177. # for every read/write so that should make 11 when bs=2
  178. sfp.seek(0)
  179. self.my_cb_cnt = 0
  180. self.my_cb_last = None
  181. k = self.bucket.new_key("k")
  182. k.BufferSize = 2
  183. k.set_contents_from_file(sfp, cb=callback, num_cb=-1)
  184. self.assertEqual(self.my_cb_cnt, 11)
  185. self.assertEqual(self.my_cb_last, 20)
  186. # Read back all bytes => 11 calls
  187. self.my_cb_cnt = 0
  188. self.my_cb_last = None
  189. s = k.get_contents_as_string(cb=callback, num_cb=-1)
  190. self.assertEqual(self.my_cb_cnt, 11)
  191. self.assertEqual(self.my_cb_last, 20)
  192. self.assertEqual(s, content)
  193. # no more than 1 times => 2 times
  194. # last time always 20 bytes
  195. sfp.seek(0)
  196. self.my_cb_cnt = 0
  197. self.my_cb_last = None
  198. k = self.bucket.new_key("k")
  199. k.BufferSize = 2
  200. k.set_contents_from_file(sfp, cb=callback, num_cb=1)
  201. self.assertTrue(self.my_cb_cnt <= 2)
  202. self.assertEqual(self.my_cb_last, 20)
  203. # no more than 1 times => 2 times
  204. self.my_cb_cnt = 0
  205. self.my_cb_last = None
  206. s = k.get_contents_as_string(cb=callback, num_cb=1)
  207. self.assertTrue(self.my_cb_cnt <= 2)
  208. self.assertEqual(self.my_cb_last, 20)
  209. self.assertEqual(s, content)
  210. # no more than 2 times
  211. # last time always 20 bytes
  212. sfp.seek(0)
  213. self.my_cb_cnt = 0
  214. self.my_cb_last = None
  215. k = self.bucket.new_key("k")
  216. k.BufferSize = 2
  217. k.set_contents_from_file(sfp, cb=callback, num_cb=2)
  218. self.assertTrue(self.my_cb_cnt <= 2)
  219. self.assertEqual(self.my_cb_last, 20)
  220. # no more than 2 times
  221. self.my_cb_cnt = 0
  222. self.my_cb_last = None
  223. s = k.get_contents_as_string(cb=callback, num_cb=2)
  224. self.assertTrue(self.my_cb_cnt <= 2)
  225. self.assertEqual(self.my_cb_last, 20)
  226. self.assertEqual(s, content)
  227. # no more than 3 times
  228. # last time always 20 bytes
  229. sfp.seek(0)
  230. self.my_cb_cnt = 0
  231. self.my_cb_last = None
  232. k = self.bucket.new_key("k")
  233. k.BufferSize = 2
  234. k.set_contents_from_file(sfp, cb=callback, num_cb=3)
  235. self.assertTrue(self.my_cb_cnt <= 3)
  236. self.assertEqual(self.my_cb_last, 20)
  237. # no more than 3 times
  238. self.my_cb_cnt = 0
  239. self.my_cb_last = None
  240. s = k.get_contents_as_string(cb=callback, num_cb=3)
  241. self.assertTrue(self.my_cb_cnt <= 3)
  242. self.assertEqual(self.my_cb_last, 20)
  243. self.assertEqual(s, content)
  244. # no more than 4 times
  245. # last time always 20 bytes
  246. sfp.seek(0)
  247. self.my_cb_cnt = 0
  248. self.my_cb_last = None
  249. k = self.bucket.new_key("k")
  250. k.BufferSize = 2
  251. k.set_contents_from_file(sfp, cb=callback, num_cb=4)
  252. self.assertTrue(self.my_cb_cnt <= 4)
  253. self.assertEqual(self.my_cb_last, 20)
  254. # no more than 4 times
  255. self.my_cb_cnt = 0
  256. self.my_cb_last = None
  257. s = k.get_contents_as_string(cb=callback, num_cb=4)
  258. self.assertTrue(self.my_cb_cnt <= 4)
  259. self.assertEqual(self.my_cb_last, 20)
  260. self.assertEqual(s, content)
  261. # no more than 6 times
  262. # last time always 20 bytes
  263. sfp.seek(0)
  264. self.my_cb_cnt = 0
  265. self.my_cb_last = None
  266. k = self.bucket.new_key("k")
  267. k.BufferSize = 2
  268. k.set_contents_from_file(sfp, cb=callback, num_cb=6)
  269. self.assertTrue(self.my_cb_cnt <= 6)
  270. self.assertEqual(self.my_cb_last, 20)
  271. # no more than 6 times
  272. self.my_cb_cnt = 0
  273. self.my_cb_last = None
  274. s = k.get_contents_as_string(cb=callback, num_cb=6)
  275. self.assertTrue(self.my_cb_cnt <= 6)
  276. self.assertEqual(self.my_cb_last, 20)
  277. self.assertEqual(s, content)
  278. # no more than 10 times
  279. # last time always 20 bytes
  280. sfp.seek(0)
  281. self.my_cb_cnt = 0
  282. self.my_cb_last = None
  283. k = self.bucket.new_key("k")
  284. k.BufferSize = 2
  285. k.set_contents_from_file(sfp, cb=callback, num_cb=10)
  286. self.assertTrue(self.my_cb_cnt <= 10)
  287. self.assertEqual(self.my_cb_last, 20)
  288. # no more than 10 times
  289. self.my_cb_cnt = 0
  290. self.my_cb_last = None
  291. s = k.get_contents_as_string(cb=callback, num_cb=10)
  292. self.assertTrue(self.my_cb_cnt <= 10)
  293. self.assertEqual(self.my_cb_last, 20)
  294. self.assertEqual(s, content)
  295. # no more than 1000 times
  296. # last time always 20 bytes
  297. sfp.seek(0)
  298. self.my_cb_cnt = 0
  299. self.my_cb_last = None
  300. k = self.bucket.new_key("k")
  301. k.BufferSize = 2
  302. k.set_contents_from_file(sfp, cb=callback, num_cb=1000)
  303. self.assertTrue(self.my_cb_cnt <= 1000)
  304. self.assertEqual(self.my_cb_last, 20)
  305. # no more than 1000 times
  306. self.my_cb_cnt = 0
  307. self.my_cb_last = None
  308. s = k.get_contents_as_string(cb=callback, num_cb=1000)
  309. self.assertTrue(self.my_cb_cnt <= 1000)
  310. self.assertEqual(self.my_cb_last, 20)
  311. self.assertEqual(s, content)
  312. def test_website_redirects(self):
  313. self.bucket.configure_website('index.html')
  314. key = self.bucket.new_key('redirect-key')
  315. self.assertTrue(key.set_redirect('http://www.amazon.com/'))
  316. self.assertEqual(key.get_redirect(), 'http://www.amazon.com/')
  317. self.assertTrue(key.set_redirect('http://aws.amazon.com/'))
  318. self.assertEqual(key.get_redirect(), 'http://aws.amazon.com/')
  319. def test_website_redirect_none_configured(self):
  320. key = self.bucket.new_key('redirect-key')
  321. key.set_contents_from_string('')
  322. self.assertEqual(key.get_redirect(), None)
  323. def test_website_redirect_with_bad_value(self):
  324. self.bucket.configure_website('index.html')
  325. key = self.bucket.new_key('redirect-key')
  326. with self.assertRaises(key.provider.storage_response_error):
  327. # Must start with a / or http
  328. key.set_redirect('ftp://ftp.example.org')
  329. with self.assertRaises(key.provider.storage_response_error):
  330. # Must start with a / or http
  331. key.set_redirect('')