1 # Copyright 2011 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
11 # 2. Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials
14 # provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
35 #Monkey-patch everything for gevent early on
36 gevent.monkey.patch_all()
38 from argparse import ArgumentParser
40 import time, datetime, os, sys
41 from shutil import copyfile
43 from kamaki.clients import ClientError
44 from kamaki.clients.pithos import PithosClient as pithos
45 from kamaki.clients.cyclades import CycladesClient as cyclades
49 class testCyclades(unittest.TestCase):
50 """Set up a Cyclades thorough test"""
53 url='https://cyclades.okeanos.grnet.gr/api/v1.1'
54 token='MI6PT0yrXJ9Ji/x8l9Wmig=='
55 account='saxtouri@gmail.com'
56 self.img = '1395fdfb-51b4-419f-bb02-f7d632860611'
59 url = 'https://cyclades.okeanos.io/api/v1.1'
60 token='0TpoyAXqJSPxLdDuZHiLOA=='
61 account='saxtouri@admin.grnet.gr'
62 self.img = '43cc8497-61c3-4c46-ae8d-3e33861f8527'
65 u'updated': u'2012-08-21T12:57:39+00:00',
66 u'name': u'Debian Base',
67 u'created': u'2012-08-21T12:56:53+00:00',
69 u'id': u'43cc8497-61c3-4c46-ae8d-3e33861f8527',
73 u'osfamily': u'linux',
80 u'Debian Squeeze Base System'}
86 self.now = time.mktime(time.gmtime())
87 self.servname1 = 'serv'+unicode(self.now)
88 self.servname2 = self.servname1+'_v2'
90 #servers have to be created at the begining...
92 self.client = cyclades(url, token)
96 """Destoy servers used in testing"""
97 if 0 >= len(self.servers):
99 there_are_servers_running = True
103 print('-> Found %s servers to delete'%len(self.servers))
104 while there_are_servers_running:
105 there_are_servers_running = False
107 c = ['|','/','-','\\']
109 sys.stdout.write('\t. . . wait %s seconds: '%waitime)
110 for i in range(4*waitime):
112 suffix = '%ss %s'%(i/4, c[i%4])
113 sys.stdout.write(oldlen*'\b'+suffix)
116 oldlen = len(': '+suffix)
117 print(oldlen*'\b'+oldlen*' ')
120 dservers = self.client.list_servers(detail=True)
121 for server in dservers:
122 if server['name'] in self.servers.keys():
123 there_are_servers_running = True
124 sys.stdout.write('\t%s status:%s '%(server['name'], server['status']))
125 if server['status'] == 'BUILD':
128 print('\tDELETE %s'%server['name'])
129 self._delete_server(server['id'])
130 self.servers.pop(server['name'])
131 deleted_servers[server['name']] = 0
133 elif server['name'] in deleted_servers.keys():
134 there_are_servers_running = True
135 sys.stdout.write('\t%s status:%s '%(server['name'], server['status']))
136 retries = deleted_servers[server['name']]
138 print('\tretry DELETE %s'%server['name'])
139 self._delete_server(server['id'])
143 print('\tnot deleted yet ...')
144 deleted_servers[server['name']] = retries + 1
146 def _create_server(self, servername, flavorid, imageid, personality=None):
147 server = self.client.create_server(servername, flavorid, imageid, personality)
148 self.servers[servername] = server
151 def _delete_server(self, servid):
152 self.client.delete_server(servid)
160 def assert_dicts_are_deeply_equal(self, d1, d2):
161 for k,v in d1.items():
162 self.assertTrue(d2.has_key(k))
163 if isinstance(v, dict):
164 self.assert_dicts_are_deeply_equal(v, d2[k])
166 self.assertEqual(unicode(v), unicode(d2[k]))
170 "Prepare a full Cyclades test scenario"
174 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
175 self.server2 = self._create_server(self.servname2, self.flavorid, self.img)
178 sys.stdout.write(' test create server')
179 self._test_create_server()
182 sys.stdout.write(' test list servers')
183 self._test_list_servers()
186 sys.stdout.write(' test get server details')
187 self._test_get_server_details()
190 sys.stdout.write(' test get image details')
191 self._test_get_image_details()
195 def test_list_servers(self):
196 """Test list servers"""
199 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
200 self.server2 = self._create_server(self.servname2, self.flavorid, self.img)
201 self._test_list_servers()
203 def _test_list_servers(self):
204 servers = self.client.list_servers()
205 dservers = self.client.list_servers(detail=True)
207 """detailed and simple are same size"""
208 self.assertEqual(len(dservers), len(servers))
209 for i in range(len(servers)):
210 for field in ['created', 'flavorRef', 'hostId', 'imageRef', 'progress',
211 'status', 'updated']:
212 self.assertFalse(servers[i].has_key(field))
213 self.assertTrue(dservers[i].has_key(field))
215 """detailed and simple contain same names"""
216 names = sorted(map(lambda x: x["name"], servers))
217 dnames = sorted(map(lambda x: x["name"], dservers))
218 self.assertEqual(names, dnames)
220 def test_create_server(self):
221 """Test create_server"""
224 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
225 self._test_create_server()
227 def _test_create_server(self):
228 self.assertEqual(self.server1["name"], self.servname1)
229 self.assertEqual(self.server1["flavorRef"], self.flavorid)
230 self.assertEqual(self.server1["imageRef"], self.img)
231 self.assertEqual(self.server1["status"], "BUILD")
233 def test_get_server_details(self):
234 """Test get_server_details"""
237 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
238 self._test_get_server_details()
240 def _test_get_server_details(self):
241 r = self.client.get_server_details(self.server1['id'])
242 self.assertEqual(r["name"], self.servname1)
243 self.assertEqual(r["flavorRef"], self.flavorid)
244 self.assertEqual(r["imageRef"], self.img)
245 self.assertEqual(r["status"], "BUILD")
247 def test_get_image_details(self):
248 """Test get_image_details"""
251 self._test_get_image_details()
253 def _test_get_image_details(self):
254 r = self.client.get_image_details(self.img)
256 self.assert_dicts_are_deeply_equal(r, d)
258 class testPithos(unittest.TestCase):
259 """Set up a Pithos+ thorough test"""
262 url = 'http://127.0.0.1:8000/v1'
263 token = 'C/yBXmz3XjTFBnujc2biAg=='
264 token = 'ac0yH8cQMEZu3M3Mp1MWGA=='
265 account = 'admin@adminland.com'
267 url='https://pithos.okeanos.grnet.gr/v1'
268 token='MI6PT0yrXJ9Ji/x8l9Wmig=='
269 account='saxtouri@gmail.com'
272 url='https://pithos.okeanos.io/v1'
273 token='0TpoyAXqJSPxLdDuZHiLOA=='
274 account='saxtouri@admin.grnet.gr'
278 self.client = pithos(url, token, account, container)
279 self.now = time.mktime(time.gmtime())
280 self.c1 = 'c1_'+unicode(self.now)
281 self.c2 = 'c2_'+unicode(self.now)
282 self.c3 = 'c3_'+unicode(self.now)
283 self.client.create_container(self.c1)
284 self.client.create_container(self.c2)
285 self.client.create_container(self.c3)
286 self.makeNewObject(self.c1, 'test')
287 self.makeNewObject(self.c2, 'test')
288 self.now_unformated = datetime.datetime.utcnow()
289 self.makeNewObject(self.c1, 'test1')
290 self.makeNewObject(self.c2, 'test1')
291 """Prepare an object to be shared - also its container"""
292 self.client.container = self.c1
293 r = self.client.object_post('test', update=True, permitions={'read':'someUser'})
295 self.makeNewObject(self.c1, 'another.test')
297 def makeNewObject(self, container, obj):
298 self.client.container = container
299 r = self.client.object_put(obj, content_type='application/octet-stream',
300 data= 'file '+obj+' that lives in '+container,
301 metadata={'incontainer':container})
304 def forceDeleteContainer(self, container):
305 self.client.container = container
307 r = self.client.list_objects()
312 self.client.del_object(name)
313 r = self.client.container_delete()
318 """Destroy test cases"""
319 if self.fname is not None:
321 os.remove(self.fname)
325 self.forceDeleteContainer(self.c1)
326 self.forceDeleteContainer(self.c2)
328 self.forceDeleteContainer(self.c3)
331 self.client.container=''
334 """Perform a full Pithos+ kamaki support test"""
336 def test_account_head(self):
337 """Test account_HEAD"""
338 r = self.client.account_head()
339 self.assertEqual(r.status_code, 204)
341 r = self.client.account_head(until='1000000000')
342 self.assertEqual(r.status_code, 204)
344 datestring = unicode(r.headers['x-account-until-timestamp'])
345 self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
347 """Check if(un)modified_since"""
348 for format in self.client.DATE_FORMATS:
349 now_formated = self.now_unformated.strftime(format)
350 r1 = self.client.account_head(if_modified_since=now_formated, success=(204, 304, 412))
353 r2 = self.client.account_head(if_unmodified_since=now_formated, success=(204, 304, 412))
356 self.assertNotEqual(sc1, sc2)
358 def test_account_get(self):
359 """Test account_GET"""
360 r = self.client.account_get()
361 self.assertEqual(r.status_code, 200)
362 fullLen = len(r.json)
363 self.assertTrue(fullLen > 2)
366 r = self.client.account_get(limit=1)
367 self.assertEqual(len(r.json), 1)
370 r = self.client.account_get(marker='c2_')
371 temp_c0 = r.json[0]['name']
372 temp_c2 = r.json[2]['name']
374 r = self.client.account_get(limit=2, marker='c2_')
375 conames = [container['name'] for container in r.json \
376 if container['name'].lower().startswith('c2_')]
377 self.assertTrue(temp_c0 in conames)
378 self.assertFalse(temp_c2 in conames)
381 r = self.client.account_get(show_only_shared=True)
382 self.assertTrue(self.c1 in [c['name'] for c in r.json])
385 r = self.client.account_get(until=1342609206)
386 self.assertTrue(len(r.json) <= fullLen)
389 """Check if(un)modified_since"""
390 for format in self.client.DATE_FORMATS:
391 now_formated = self.now_unformated.strftime(format)
392 r1 = self.client.account_get(if_modified_since=now_formated, success=(200, 304, 412))
395 r2 = self.client.account_get(if_unmodified_since=now_formated, success=(200, 304, 412))
398 self.assertNotEqual(sc1, sc2)
400 def test_account_post(self):
401 """Test account_POST"""
402 r = self.client.account_post()
403 self.assertEqual(r.status_code, 202)
404 grpName = 'grp'+unicode(self.now)
407 """Method set/del_account_meta and set_account_groupcall use account_post internally
409 self.client.set_account_group(grpName, ['u1', 'u2'])
410 r = self.client.get_account_group()
411 self.assertEqual(r['x-account-group-'+grpName], 'u1,u2')
412 self.client.del_account_group(grpName)
413 r = self.client.get_account_group()
414 self.assertTrue(not r.has_key('x-account-group-'+grpName))
416 mprefix = 'meta'+unicode(self.now)
417 self.client.set_account_meta({mprefix+'1':'v1', mprefix+'2':'v2'})
418 r = self.client.get_account_meta()
419 self.assertEqual(r['x-account-meta-'+mprefix+'1'], 'v1')
420 self.assertEqual(r['x-account-meta-'+mprefix+'2'], 'v2')
422 self.client.del_account_meta(mprefix+'1')
423 r = self.client.get_account_meta()
424 self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'1'))
426 self.client.del_account_meta(mprefix+'2')
427 r = self.client.get_account_meta()
428 self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'2'))
430 """Missing testing for quota, versioning, because normally
431 you don't have permitions to modify those at account level
434 def test_container_head(self):
435 """Test container_HEAD"""
436 self.client.container = self.c1
438 r = self.client.container_head()
439 self.assertEqual(r.status_code, 204)
443 r = self.client.container_head(until=1000000, success=(204, 404))
444 self.assertEqual(r.status_code, 404)
447 """Check and if(un)modified_since"""
448 for format in self.client.DATE_FORMATS:
449 now_formated = self.now_unformated.strftime(format)
450 r1 = self.client.container_head(if_modified_since=now_formated, success=(204, 304, 412))
453 r2 = self.client.container_head(if_unmodified_since=now_formated, success=(204, 304, 412))
456 self.assertNotEqual(sc1, sc2)
458 def test_container_get(self):
459 """Test container_GET"""
460 self.client.container = self.c1
462 r = self.client.container_get()
463 self.assertEqual(r.status_code, 200)
464 fullLen = len(r.json)
467 r = self.client.container_get(prefix='test')
468 lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
469 self.assertTrue(len(r.json) > 1)
470 self.assertEqual(len(r.json), len(lalobjects))
473 r = self.client.container_get(limit=1)
474 self.assertEqual(len(r.json), 1)
477 r = self.client.container_get(marker='another')
478 self.assertTrue(len(r.json) > 1)
479 neobjects = [obj for obj in r.json if obj['name'] > 'another']
480 self.assertEqual(len(r.json), len(neobjects))
483 r = self.client.container_get(prefix='another.test', delimiter='.')
484 self.assertTrue(fullLen > len(r.json))
487 r = self.client.container_get(path='/')
488 self.assertEqual(fullLen, len(r.json))
491 r = self.client.container_get(format='xml')
492 self.assertEqual(r.text.split()[4], 'name="'+self.c1+'">')
495 r = self.client.container_get(meta=['incontainer'])
496 self.assertTrue(len(r.json) > 0)
499 r = self.client.container_get(show_only_shared=True)
500 self.assertTrue(len(r.json) < fullLen)
504 r = self.client.container_get(until=1000000000)
505 datestring = unicode(r.headers['x-account-until-timestamp'])
506 self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
512 """Check and if un/modified_since"""
513 for format in self.client.DATE_FORMATS:
514 now_formated = self.now_unformated.strftime(format)
515 r1 = self.client.container_get(if_modified_since=now_formated, success=(200, 304, 412))
518 r2 = self.client.container_get(if_unmodified_since=now_formated, success=(200, 304, 412))
521 self.assertNotEqual(sc1, sc2)
523 def test_container_put(self):
524 """Test container_PUT"""
525 self.client.container = self.c2
527 r = self.client.container_put()
528 self.assertEqual(r.status_code, 202)
531 r = self.client.get_container_quota(self.client.container)
532 cquota = r.values()[0]
533 newquota = 2*int(cquota)
535 r = self.client.container_put(quota=newquota)
536 self.assertEqual(r.status_code, 202)
538 r = self.client.get_container_quota(self.client.container)
539 xquota = int(r.values()[0])
540 self.assertEqual(newquota, xquota)
542 r = self.client.container_put(versioning='auto')
543 self.assertEqual(r.status_code, 202)
545 r = self.client.get_container_versioning(self.client.container)
546 nvers = r.values()[0]
547 self.assertEqual('auto', nvers)
549 r = self.client.container_put(versioning='none')
550 self.assertEqual(r.status_code, 202)
552 r = self.client.get_container_versioning(self.client.container)
553 nvers = r.values()[0]
554 self.assertEqual('none', nvers)
556 r = self.client.container_put(metadata={'m1':'v1', 'm2':'v2'})
557 self.assertEqual(r.status_code, 202)
559 r = self.client.get_container_meta(self.client.container)
560 self.assertTrue(r.has_key('x-container-meta-m1'))
561 self.assertEqual(r['x-container-meta-m1'], 'v1')
562 self.assertTrue(r.has_key('x-container-meta-m2'))
563 self.assertEqual(r['x-container-meta-m2'], 'v2')
565 r = self.client.container_put(metadata={'m1':'', 'm2':'v2a'})
566 self.assertEqual(r.status_code, 202)
568 r = self.client.get_container_meta(self.client.container)
569 self.assertTrue(not r.has_key('x-container-meta-m1'))
570 self.assertTrue(r.has_key('x-container-meta-m2'))
571 self.assertEqual(r['x-container-meta-m2'], 'v2a')
573 self.client.del_container_meta(self.client.container)
575 def test_container_post(self):
576 """Test container_POST"""
577 self.client.container = self.c2
580 r = self.client.container_post()
581 self.assertEqual(r.status_code, 202)
585 self.client.set_container_meta({'m1':'v1', 'm2':'v2'})
586 r = self.client.get_container_meta(self.client.container)
587 self.assertTrue(r.has_key('x-container-meta-m1'))
588 self.assertEqual(r['x-container-meta-m1'], 'v1')
589 self.assertTrue(r.has_key('x-container-meta-m2'))
590 self.assertEqual(r['x-container-meta-m2'], 'v2')
593 r = self.client.del_container_meta('m1')
594 r = self.client.set_container_meta({'m2':'v2a'})
595 r = self.client.get_container_meta(self.client.container)
596 self.assertTrue(not r.has_key('x-container-meta-m1'))
597 self.assertTrue(r.has_key('x-container-meta-m2'))
598 self.assertEqual(r['x-container-meta-m2'], 'v2a')
601 r = self.client.get_container_quota(self.client.container)
602 cquota = r.values()[0]
603 newquota = 2*int(cquota)
604 r = self.client.set_container_quota(newquota)
605 r = self.client.get_container_quota(self.client.container)
606 xquota = int(r.values()[0])
607 self.assertEqual(newquota, xquota)
608 r = self.client.set_container_quota(cquota)
609 r = self.client.get_container_quota(self.client.container)
610 xquota = r.values()[0]
611 self.assertEqual(cquota, xquota)
613 """Check versioning"""
614 self.client.set_container_versioning('auto')
615 r = self.client.get_container_versioning(self.client.container)
616 nvers = r.values()[0]
617 self.assertEqual('auto', nvers)
618 self.client.set_container_versioning('none')
619 r = self.client.get_container_versioning(self.client.container)
620 nvers = r.values()[0]
621 self.assertEqual('none', nvers)
623 """put_block uses content_type and content_length to
624 post blocks of data 2 container. All that in upload_object"""
625 """Change a file at fs"""
626 self.create_large_file(1024*1024*100, 'l100M.'+unicode(self.now))
627 """Upload it at a directory in container"""
628 self.client.create_directory('dir')
629 newf = open(self.fname, 'r')
630 self.client.upload_object('/dir/sample.file', newf)
632 """Check if file has been uploaded"""
633 r = self.client.get_object_info('/dir/sample.file')
634 self.assertTrue(int(r['content-length']) > 100000000)
636 """WTF is tranfer_encoding? What should I check about th** s**t? """
639 """Check update=False"""
640 r = self.client.object_post('test', update=False, metadata={'newmeta':'newval'})
642 r = self.client.get_object_info('test')
643 self.assertTrue(r.has_key('x-object-meta-newmeta'))
644 self.assertFalse(r.has_key('x-object-meta-incontainer'))
646 r = self.client.del_container_meta('m2')
648 def test_container_delete(self):
649 """Test container_DELETE"""
651 """Fail to delete a non-empty container"""
652 self.client.container = self.c2
653 r = self.client.container_delete(success=409)
654 self.assertEqual(r.status_code, 409)
657 """Fail to delete c3 (empty) container"""
658 self.client.container = self.c3
659 r = self.client.container_delete(until='1000000000')
660 self.assertEqual(r.status_code, 204)
663 """Delete c3 (empty) container"""
664 r = self.client.container_delete()
665 self.assertEqual(r.status_code, 204)
667 """Purge container(empty a container), check versionlist"""
668 self.client.container = self.c1
669 r = self.client.object_head('test', success=(200, 404))
670 self.assertEqual(r.status_code, 200)
671 self.client.del_container(delimiter='/')
672 r = self.client.object_head('test', success=(200, 404))
673 self.assertEqual(r.status_code, 404)
674 r = self.client.get_object_versionlist('test')
675 self.assertTrue(len(r) > 0)
676 self.assertTrue(len(r[0])>1)
677 self.client.purge_container()
678 self.assertRaises(ClientError, self.client.get_object_versionlist, 'test')
680 def test_object_head(self):
681 """Test object_HEAD"""
682 self.client.container = self.c2
685 r = self.client.object_head(obj)
686 self.assertEqual(r.status_code, 200)
687 etag = r.headers['etag']
690 r = self.client.object_head(obj, version=40)
691 self.assertEqual(r.headers['x-object-version'], '40')
694 r = self.client.object_head(obj, if_etag_match=etag)
695 self.assertEqual(r.status_code, 200)
697 r = self.client.object_head(obj, if_etag_not_match=etag, success=(200, 412, 304))
698 self.assertNotEqual(r.status_code, 200)
701 r = self.client.object_head(obj, version=40, if_etag_match=etag, success=412)
702 self.assertEqual(r.status_code, 412)
705 """Check and if(un)modified_since"""
706 for format in self.client.DATE_FORMATS:
707 now_formated = self.now_unformated.strftime(format)
708 r1 = self.client.object_head(obj, if_modified_since=now_formated,
709 success=(200, 304, 412))
712 r2 = self.client.object_head(obj, if_unmodified_since=now_formated,
713 success=(200, 304, 412))
716 self.assertNotEqual(sc1, sc2)
718 def test_object_get(self):
719 """Test object_GET"""
720 self.client.container = self.c1
723 r = self.client.object_get(obj)
724 self.assertEqual(r.status_code, 200)
726 osize = int(r.headers['content-length'])
727 etag = r.headers['etag']
730 r = self.client.object_get(obj, hashmap=True)
731 self.assertTrue(r.json.has_key('hashes') \
732 and r.json.has_key('block_hash') \
733 and r.json.has_key('block_size') \
734 and r.json.has_key('bytes'))
737 r = self.client.object_get(obj, format='xml', hashmap=True)
738 self.assertEqual(len(r.text.split('hash>')), 3)
741 rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
742 r = self.client.object_get(obj, data_range=rangestr, success=(200, 206))
743 partsize = int(r.headers['content-length'])
744 self.assertTrue(0 < partsize and partsize <= 1+osize/3)
747 rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
748 r = self.client.object_get(obj, data_range=rangestr, if_range=True, success=(200, 206))
749 partsize = int(r.headers['content-length'])
750 self.assertTrue(0 < partsize and partsize <= 1+osize/3)
753 r = self.client.object_get(obj, if_etag_match=etag)
754 self.assertEqual(r.status_code, 200)
757 r = self.client.object_get(obj, if_etag_not_match=etag+'LALALA')
758 self.assertEqual(r.status_code, 200)
761 """Check and if(un)modified_since"""
762 for format in self.client.DATE_FORMATS:
763 now_formated = self.now_unformated.strftime(format)
764 r1 = self.client.object_get(obj, if_modified_since=now_formated,
765 success=(200, 304, 412))
768 r2 = self.client.object_get(obj, if_unmodified_since=now_formated, success=(200, 304, 412))
771 self.assertNotEqual(sc1, sc2)
773 def test_object_put(self):
774 """Test object_PUT"""
776 self.client.container = self.c2
779 """create the object"""
780 r = self.client.object_put(obj, data='a', content_type='application/octer-stream',
781 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']},
782 metadata={'key1':'val1', 'key2':'val2'}, content_encoding='UTF-8',
783 content_disposition='attachment; filename="fname.ext"')
784 self.assertEqual(r.status_code, 201)
785 etag = r.headers['etag']
788 """Check content-disposition"""
789 r = self.client.get_object_info(obj)
790 self.assertTrue(r.has_key('content-disposition'))
792 """Check permitions"""
793 r = self.client.get_object_sharing(obj)
794 self.assertTrue('accx:groupa' in r['read'])
795 self.assertTrue('u1' in r['read'])
796 self.assertTrue('u2' in r['write'])
797 self.assertTrue('u3' in r['write'])
800 r = self.client.get_object_meta(obj)
801 self.assertEqual(r['x-object-meta-key1'], 'val1')
802 self.assertEqual(r['x-object-meta-key2'], 'val2')
804 """Check public and if_etag_match"""
805 r = self.client.object_put(obj, if_etag_match=etag, data='b',
806 content_type='application/octet-stream', public=True)
808 r = self.client.object_get(obj)
809 self.assertTrue(r.headers.has_key('x-object-public'))
810 vers2 = int(r.headers['x-object-version'])
811 etag = r.headers['etag']
812 self.assertEqual(r.text, 'b')
815 """Check if_etag_not_match"""
816 r = self.client.object_put(obj, if_etag_not_match=etag, data='c',
817 content_type='application/octet-stream', success=(201, 412))
818 self.assertEqual(r.status_code, 412)
821 """Check content_type and content_length"""
822 tmpdir = 'dir'+unicode(self.now)
823 r = self.client.object_put(tmpdir, content_type='application/directory',
826 r = self.client.get_object_info(tmpdir)
827 self.assertEqual(r['content-type'], 'application/directory')
829 """Check copy_from, content_encoding"""
830 r = self.client.object_put('%s/%s'%(tmpdir, obj), format=None,
831 copy_from='/%s/%s'%(self.client.container, obj),
832 content_encoding='application/octet-stream',
833 source_account=self.client.account,
834 content_length=0, success=201)
835 self.assertEqual(r.status_code, 201)
838 """Check cross-container copy_from, content_encoding"""
839 self.client.container = self.c1
840 fromstr = '/'+self.c2+'/'+tmpdir+'/'+obj
841 r = self.client.object_put(obj, format=None, copy_from=fromstr,
842 content_encoding='application/octet-stream',
843 source_account=self.client.account,
844 content_length=0, success=201)
846 self.assertEqual(r.status_code, 201)
847 r = self.client.get_object_info(obj)
848 self.assertEqual(r['etag'], etag)
850 """Check source_account"""
851 self.client.container = self.c2
852 fromstr = '/'+self.c1+'/'+obj
853 r = self.client.object_put(obj+'v2', format=None, move_from=fromstr,
854 content_encoding='application/octet-stream',
855 source_account='nonExistendAddress@NeverLand.com',
856 content_length=0, success=(201, 403))
857 self.assertEqual(r.status_code, 403)
860 """Check cross-container move_from"""
861 r = self.client.object_put(obj+'v0', format=None,
862 move_from='/'+self.c1+'/'+obj,
863 content_encoding='application/octet-stream',
864 content_length=0, success=201)
865 self.assertEqual(r.status_code, 201)
867 r = self.client.get_object_info(obj+'v0')
868 self.assertEqual(r['etag'], etag)
870 """Check move_from"""
871 r = self.client.object_put(obj+'v1', format=None,
872 move_from='/'+self.c2+'/'+obj,
873 source_version = vers2,
874 content_encoding='application/octet-stream',
875 content_length=0, success=201)
879 mobj = 'manifest.test'
883 r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
884 content_type='application/octet-stream', content_encoding='application/octet-stream')
886 r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream',
887 manifest='%s/%s'%(self.client.container, mobj))
889 r = self.client.object_get(mobj)
890 self.assertEqual(r.text, txt)
893 """Some problems with transfer-encoding?"""
895 def test_object_copy(self):
896 """Test object_COPY"""
897 self.client.container=self.c2
900 data= '{"key1":"val1", "key2":"val2"}'
901 r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
902 data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
904 'read':['accX:groupA', 'u1', 'u2'],
905 'write':['u2', 'u3']},
906 content_disposition='attachment; filename="fname.ext"')
908 r = self.client.object_copy(obj+'orig',
909 destination = '/'+self.client.container+'/'+obj,
910 ignore_content_type=False, content_type='application/json',
911 metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
912 permitions={'write':['u5', 'accX:groupB']})
913 self.assertEqual(r.status_code, 201)
916 """Check content-disposition"""
917 r = self.client.get_object_info(obj)
918 self.assertTrue(r.has_key('content-disposition'))
921 r = self.client.get_object_meta(obj)
922 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
923 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
924 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
926 """Check permitions"""
927 r = self.client.get_object_sharing(obj)
928 self.assertFalse(r.has_key('read') or 'u2' in r['write'])
929 self.assertTrue('accx:groupb' in r['write'])
931 """Check destination account"""
932 r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
933 content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
935 self.assertEqual(r.status_code, 403)
938 """Check destination being another container
939 and also content_type and content encoding"""
940 r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj),
941 content_encoding='utf8', content_type='application/json')
942 self.assertEqual(r.status_code, 201)
943 self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
946 """Check ignore_content_type and content_type"""
947 r = self.client.object_get(obj)
948 etag = r.headers['etag']
949 ctype = r.headers['content-type']
950 self.assertEqual(ctype, 'application/json')
952 r = self.client.object_copy(obj+'orig',
953 destination = '/'+self.client.container+'/'+obj+'0',
954 ignore_content_type=True, content_type='application/json')
955 self.assertEqual(r.status_code, 201)
956 self.assertNotEqual(r.headers['content-type'], 'application/json')
959 """Check if_etag_(not_)match"""
960 r = self.client.object_copy(obj,
961 destination='/'+self.client.container+'/'+obj+'1', if_etag_match=etag)
962 self.assertEqual(r.status_code, 201)
964 r = self.client.object_copy(obj,
965 destination='/'+self.client.container+'/'+obj+'2', if_etag_not_match='lalala')
966 self.assertEqual(r.status_code, 201)
967 vers2 = r.headers['x-object-version']
970 """Check source_version, public and format """
971 r = self.client.object_copy(obj+'2', destination='/'+self.client.container+'/'+obj+'3', source_version=vers2, format='xml', public=True)
972 self.assertEqual(r.status_code, 201)
973 self.assertTrue(r.headers['content-type'].index('xml') > 0)
975 r = self.client.get_object_info(obj+'3')
976 self.assertTrue(r.has_key('x-object-public'))
978 def test_object_move(self):
979 """Test object_MOVE"""
980 self.client.container= self.c2
983 data= '{"key1":"val1", "key2":"val2"}'
984 r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
985 data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
986 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
988 r = self.client.object_move(obj+'orig', destination = '/'+self.client.container+'/'+obj,
989 ignore_content_type=False, content_type='application/json',
990 metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
991 permitions={'write':['u5', 'accX:groupB']})
992 self.assertEqual(r.status_code, 201)
996 r = self.client.get_object_meta(obj)
997 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
998 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
999 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1001 """Check permitions"""
1002 r = self.client.get_object_sharing(obj)
1003 self.assertFalse(r.has_key('read'))
1004 self.assertTrue('u5' in r['write'])
1005 self.assertTrue('accx:groupb' in r['write'])
1007 """Check destination account"""
1008 r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
1009 content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
1011 self.assertEqual(r.status_code, 403)
1014 """Check destination being another container and also
1015 content_type, content_disposition and content encoding"""
1016 r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj),
1017 content_encoding='utf8', content_type='application/json',
1018 content_disposition='attachment; filename="fname.ext"')
1019 self.assertEqual(r.status_code, 201)
1020 self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
1021 self.client.container=self.c1
1022 r = self.client.get_object_info(obj)
1023 self.assertTrue(r.has_key('content-disposition') and 'fname.ext' in r['content-disposition'])
1025 ctype = r['content-type']
1026 self.assertEqual(ctype, 'application/json')
1028 """Check ignore_content_type and content_type"""
1029 r = self.client.object_move(obj, destination = '/%s/%s'%(self.c2,obj),
1030 ignore_content_type=True, content_type='application/json')
1031 self.assertEqual(r.status_code, 201)
1032 self.assertNotEqual(r.headers['content-type'], 'application/json')
1035 """Check if_etag_(not_)match"""
1036 self.client.container=self.c2
1037 r = self.client.object_move(obj, destination='/'+self.client.container+'/'+obj+'0',
1039 self.assertEqual(r.status_code, 201)
1041 r = self.client.object_move(obj+'0', destination='/'+self.client.container+'/'+obj+'1',
1042 if_etag_not_match='lalala')
1043 self.assertEqual(r.status_code, 201)
1046 """Check public and format """
1047 r = self.client.object_move(obj+'1', destination='/'+self.client.container+'/'+obj+'2',
1048 format='xml', public=True)
1049 self.assertEqual(r.status_code, 201)
1050 self.assertTrue(r.headers['content-type'].index('xml') > 0)
1052 r = self.client.get_object_info(obj+'2')
1053 self.assertTrue(r.has_key('x-object-public'))
1055 def test_object_post(self):
1056 """Test object_POST"""
1057 self.client.container=self.c2
1059 """create a filesystem file"""
1061 newf = open(self.fname, 'w')
1062 newf.writelines(['ello!\n','This is a test line\n','inside a test file\n'])
1064 """create a file on container"""
1065 r = self.client.object_put(obj, content_type='application/octet-stream',
1066 data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1067 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1070 """Append tests update, content_range, content_type, content_length"""
1071 newf = open(obj, 'r')
1072 self.client.append_object(obj, newf)
1073 r = self.client.object_get(obj)
1074 self.assertTrue(r.text.startswith('Hello!'))
1077 """Overwrite tests update, content_type, content_length, content_range"""
1079 r = self.client.overwrite_object(obj, 0, 10, newf)
1080 r = self.client.object_get(obj)
1081 self.assertTrue(r.text.startswith('ello!'))
1085 """Truncate tests update, content_range, content_type,
1086 object_bytes and source_object"""
1087 r = self.client.truncate_object(obj, 5)
1088 r = self.client.object_get(obj)
1089 self.assertEqual(r.text, 'ello!')
1092 """Check metadata"""
1093 self.client.set_object_meta(obj, {'mkey2':'mval2a', 'mkey3':'mval3'})
1094 r = self.client.get_object_meta(obj)
1095 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1096 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1097 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1098 self.client.del_object_meta('mkey1', obj)
1099 r = self.client.get_object_meta(obj)
1100 self.assertFalse(r.has_key('x-object-meta-mkey1'))
1102 """Check permitions"""
1103 self.client.set_object_sharing(obj,
1104 read_permition=['u4', 'u5'], write_permition=['u4'])
1105 r = self.client.get_object_sharing(obj)
1106 self.assertTrue(r.has_key('read'))
1107 self.assertTrue('u5' in r['read'])
1108 self.assertTrue(r.has_key('write'))
1109 self.assertTrue('u4' in r['write'])
1110 self.client.del_object_sharing(obj)
1111 r = self.client.get_object_sharing(obj)
1112 self.assertTrue(len(r) == 0)
1115 self.client.publish_object(obj)
1116 r = self.client.get_object_info(obj)
1117 self.assertTrue(r.has_key('x-object-public'))
1118 self.client.unpublish_object(obj)
1119 r = self.client.get_object_info(obj)
1120 self.assertFalse(r.has_key('x-object-public'))
1122 """Check if_etag_(not)match"""
1124 #r = self.client.object_post(obj, update=True, public=True,
1125 # if_etag_not_match=etag, success=(412,202,204))
1126 #self.assertEqual(r.status_code, 412)
1128 r = self.client.object_post(obj, update=True, public=True,
1129 if_etag_match=etag, content_encoding='application/json')
1131 r = self.client.get_object_info(obj)
1132 helloVersion = r['x-object-version']
1133 self.assertTrue(r.has_key('x-object-public'))
1134 self.assertEqual(r['content-encoding'], 'application/json')
1136 """Check source_version and source_account and content_disposition"""
1137 r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1138 content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1139 source_account='thisAccountWillNeverExist@adminland.com',
1140 source_version=helloVersion, data='12345', success=(403, 202, 204))
1141 self.assertEqual(r.status_code, 403)
1143 r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1144 content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1145 source_account=self.client.account, source_version=helloVersion, data='12345',
1146 content_disposition='attachment; filename="fname.ext"')
1148 r = self.client.object_get(obj)
1149 self.assertEqual(r.text, 'eello!')
1150 self.assertTrue(r.headers.has_key('content-disposition')
1151 and 'fname.ext' in r.headers['content-disposition'])
1154 """Check manifest"""
1155 mobj = 'manifest.test'
1159 r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
1160 content_encoding='application/octet-stream', content_type='application/octet-stream')
1162 #r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream')
1163 self.client.create_object_by_manifestation(mobj, content_type='application/octet-stream')
1165 r = self.client.object_post(mobj, manifest='%s/%s'%(self.client.container, mobj))
1167 r = self.client.object_get(mobj)
1168 self.assertEqual(r.text, txt)
1171 """We need to check transfer_encoding """
1173 def test_object_delete(self):
1174 """Test object_DELETE"""
1175 self.client.container=self.c2
1177 """create a file on container"""
1178 r = self.client.object_put(obj, content_type='application/octet-stream',
1179 data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1180 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1183 """Check with false until"""
1184 r = self.client.object_delete(obj, until=1000000)
1186 r = self.client.object_get(obj, success=(200, 404))
1187 self.assertEqual(r.status_code, 200)
1190 """Check normal case"""
1191 r = self.client.object_delete(obj)
1192 self.assertEqual(r.status_code, 204)
1194 r = self.client.object_get(obj, success=(200, 404))
1195 self.assertEqual(r.status_code, 404)
1198 def create_large_file(self, size, name):
1199 """Create a large file at fs"""
1202 random.seed(self.now)
1203 f = open(self.fname, 'w')
1204 sys.stdout.write(' create random file %s of size %s'%(name, size)+' 0%')
1205 for hobyte_id in range(size/8):
1206 sss = 'hobt%s'%random.randint(1000, 9999)
1208 if 0 == (hobyte_id*800)%size:
1210 sys.stdout.write('\b\b')
1211 prs = (hobyte_id*800)//size
1213 sys.stdout.write('\b')
1214 sys.stdout.write('%s'%prs+'%')
1221 parser = ArgumentParser(add_help=False)
1222 parser.add_argument('-h', '--help', dest='help', action='store_true', default=False,
1223 help="Show this help message and exit")
1226 if __name__ == '__main__':
1227 parser = init_parser()
1228 args, argv = parser.parse_known_args()
1230 if len(argv) > 2 or getattr(args,'help') or len(argv) < 1:
1231 raise Exception('\tusage: tests.py <group> [command]')
1232 suiteFew = unittest.TestSuite()
1234 if len(argv) == 0 or argv[0] == 'pithos':
1236 suiteFew.addTest(unittest.makeSuite(testPithos))
1238 suiteFew.addTest(testPithos('test_'+argv[1]))
1239 if len(argv) == 0 or argv[0] == 'cyclades':
1241 #suiteFew.addTest(unittest.makeSuite(testCyclades))
1242 suiteFew.addTest(testCyclades('test_000'))
1244 suiteFew.addTest(testCyclades('test_'+argv[1]))
1246 unittest.TextTestRunner(verbosity = 2).run(suiteFew)