18d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Copyright 2013 Google Inc. 28d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Copyright 2011, Nexenta Systems Inc. 38d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 48d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# Permission is hereby granted, free of charge, to any person obtaining a 58d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# copy of this software and associated documentation files (the 68d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# "Software"), to deal in the Software without restriction, including 78d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# without limitation the rights to use, copy, modify, merge, publish, dis- 88d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# tribute, sublicense, and/or sell copies of the Software, and to permit 98d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# persons to whom the Software is furnished to do so, subject to the fol- 108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# lowing conditions: 118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# The above copyright notice and this permission notice shall be included 138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# in all copies or substantial portions of the Software. 148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# 158d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 168d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 178d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 188d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 198d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 208d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 218d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi# IN THE SOFTWARE. 228d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 238d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport os 248d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiimport unittest 258d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom boto.s3.keyfile import KeyFile 268d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom tests.integration.s3.mock_storage_service import MockConnection 278d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoifrom tests.integration.s3.mock_storage_service import MockBucket 288d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 298d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 308d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoiclass KeyfileTest(unittest.TestCase): 318d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 328d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def setUp(self): 338d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi service_connection = MockConnection() 348d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.contents = '0123456789' 358d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi bucket = MockBucket(service_connection, 'mybucket') 368d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi key = bucket.new_key('mykey') 378d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi key.set_contents_from_string(self.contents) 388d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile = KeyFile(key) 398d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 408d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def tearDown(self): 418d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.close() 428d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 438d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testReadFull(self): 448d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(len(self.contents)), self.contents) 458d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 468d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testReadPartial(self): 478d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(5), self.contents[:5]) 488d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(5), self.contents[5:]) 498d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 508d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testTell(self): 518d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.tell(), 0) 528d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.read(4) 538d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.tell(), 4) 548d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.read(6) 558d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.tell(), 10) 568d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.close() 578d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 588d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.tell() 598d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except ValueError as e: 608d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(str(e), 'I/O operation on closed file') 618d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 628d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testSeek(self): 638d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(4), self.contents[:4]) 648d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(0) 658d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(4), self.contents[:4]) 668d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(5) 678d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(5), self.contents[5:]) 688d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 698d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Seeking negative should raise. 708d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 718d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(-5) 728d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except IOError as e: 738d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(str(e), 'Invalid argument') 748d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 758d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Reading past end of file is supposed to return empty string. 768d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.read(10) 778d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(20), '') 788d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 798d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Seeking past end of file is supposed to silently work. 808d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(50) 818d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.tell(), 50) 828d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(1), '') 838d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 848d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testSeekEnd(self): 858d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(4), self.contents[:4]) 868d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(0, os.SEEK_END) 878d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(1), '') 888d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(-1, os.SEEK_END) 898d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.tell(), 9) 908d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(1), '9') 918d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Test attempt to seek backwards past the start from the end. 928d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi try: 938d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(-100, os.SEEK_END) 948d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi except IOError as e: 958d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(str(e), 'Invalid argument') 968d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 978d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testSeekCur(self): 988d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(1), self.contents[0]) 998d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.seek(1, os.SEEK_CUR) 1008d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.tell(), 2) 1018d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.read(4), self.contents[2:6]) 1028d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1038d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi def testSetEtag(self): 1048d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # Make sure both bytes and strings work as contents. This is one of the 1058d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # very few places Boto uses the mock key object. 1068d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi # https://github.com/GoogleCloudPlatform/gsutil/issues/214#issuecomment-49906044 1078d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.key.data = b'test' 1088d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.key.set_etag() 1098d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.key.etag, '098f6bcd4621d373cade4e832627b4f6') 1108d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi 1118d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.key.etag = None 1128d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.key.data = 'test' 1138d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.keyfile.key.set_etag() 1148d2b206a675ec20ea07100c35df34e65ee1e45e8Ruchi Kandoi self.assertEqual(self.keyfile.key.etag, '098f6bcd4621d373cade4e832627b4f6') 115