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 r = self.client.get_account_info(until='1000000000')
345 datestring = unicode(r['x-account-until-timestamp'])
346 self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
348 r = self.client.get_account_quota()
349 self.assertTrue(r.has_key('x-account-policy-quota'))
351 r = self.client.get_account_versioning()
352 self.assertTrue(r.has_key('x-account-policy-versioning'))
354 """Check if(un)modified_since"""
355 for format in self.client.DATE_FORMATS:
356 now_formated = self.now_unformated.strftime(format)
357 r1 = self.client.account_head(if_modified_since=now_formated, success=(204, 304, 412))
360 r2 = self.client.account_head(if_unmodified_since=now_formated, success=(204, 304, 412))
363 self.assertNotEqual(sc1, sc2)
365 def test_account_get(self):
366 """Test account_GET"""
367 #r = self.client.account_get()
368 #self.assertEqual(r.status_code, 200)
369 r = self.client.list_containers()
371 self.assertTrue(fullLen > 2)
373 r = self.client.account_get(limit=1)
374 self.assertEqual(len(r.json), 1)
377 r = self.client.account_get(marker='c2_')
378 temp_c0 = r.json[0]['name']
379 temp_c2 = r.json[2]['name']
381 r = self.client.account_get(limit=2, marker='c2_')
382 conames = [container['name'] for container in r.json \
383 if container['name'].lower().startswith('c2_')]
384 self.assertTrue(temp_c0 in conames)
385 self.assertFalse(temp_c2 in conames)
388 r = self.client.account_get(show_only_shared=True)
389 self.assertTrue(self.c1 in [c['name'] for c in r.json])
391 r = self.client.account_get(until=1342609206)
392 self.assertTrue(len(r.json) <= fullLen)
395 """Check if(un)modified_since"""
396 for format in self.client.DATE_FORMATS:
397 now_formated = self.now_unformated.strftime(format)
398 r1 = self.client.account_get(if_modified_since=now_formated, success=(200, 304, 412))
401 r2 = self.client.account_get(if_unmodified_since=now_formated, success=(200, 304, 412))
404 self.assertNotEqual(sc1, sc2)
406 def test_account_post(self):
407 """Test account_POST"""
408 r = self.client.account_post()
409 self.assertEqual(r.status_code, 202)
410 grpName = 'grp'+unicode(self.now)
413 """Method set/del_account_meta and set_account_groupcall use account_post internally
415 self.client.set_account_group(grpName, ['u1', 'u2'])
416 r = self.client.get_account_group()
417 self.assertEqual(r['x-account-group-'+grpName], 'u1,u2')
418 self.client.del_account_group(grpName)
419 r = self.client.get_account_group()
420 self.assertTrue(not r.has_key('x-account-group-'+grpName))
422 mprefix = 'meta'+unicode(self.now)
423 self.client.set_account_meta({mprefix+'1':'v1', mprefix+'2':'v2'})
424 r = self.client.get_account_meta()
425 self.assertEqual(r['x-account-meta-'+mprefix+'1'], 'v1')
426 self.assertEqual(r['x-account-meta-'+mprefix+'2'], 'v2')
428 self.client.del_account_meta(mprefix+'1')
429 r = self.client.get_account_meta()
430 self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'1'))
432 self.client.del_account_meta(mprefix+'2')
433 r = self.client.get_account_meta()
434 self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'2'))
436 """Missing testing for quota, versioning, because normally
437 you don't have permitions to modify those at account level
441 self.client.set_account_quota(newquota)
442 #r = self.client.get_account_info()
444 #r = self.client.get_account_quota()
445 #self.assertEqual(r['x-account-policy-quota'], newquota)
446 self.client.set_account_versioning('auto')
448 def test_container_head(self):
449 """Test container_HEAD"""
450 self.client.container = self.c1
452 r = self.client.container_head()
453 self.assertEqual(r.status_code, 204)
456 r = self.client.container_head(until=1000000, success=(204, 404))
457 self.assertEqual(r.status_code, 404)
459 """Check and if(un)modified_since"""
460 for format in self.client.DATE_FORMATS:
461 now_formated = self.now_unformated.strftime(format)
462 r1 = self.client.container_head(if_modified_since=now_formated, success=(204, 304, 412))
465 r2 = self.client.container_head(if_unmodified_since=now_formated, success=(204, 304, 412))
468 self.assertNotEqual(sc1, sc2)
470 """Check container object meta"""
471 r = self.client.get_container_object_meta()
472 self.assertEqual(r['x-container-object-meta'], 'Incontainer')
474 def test_container_get(self):
475 """Test container_GET"""
476 self.client.container = self.c1
478 r = self.client.container_get()
479 self.assertEqual(r.status_code, 200)
480 fullLen = len(r.json)
483 r = self.client.container_get(prefix='test')
484 lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
485 self.assertTrue(len(r.json) > 1)
486 self.assertEqual(len(r.json), len(lalobjects))
489 r = self.client.container_get(limit=1)
490 self.assertEqual(len(r.json), 1)
493 r = self.client.container_get(marker='another')
494 self.assertTrue(len(r.json) > 1)
495 neobjects = [obj for obj in r.json if obj['name'] > 'another']
496 self.assertEqual(len(r.json), len(neobjects))
499 r = self.client.container_get(prefix='another.test', delimiter='.')
500 self.assertTrue(fullLen > len(r.json))
503 r = self.client.container_get(path='/')
504 self.assertEqual(fullLen, len(r.json))
507 r = self.client.container_get(format='xml')
508 self.assertEqual(r.text.split()[4], 'name="'+self.c1+'">')
511 r = self.client.container_get(meta=['incontainer'])
512 self.assertTrue(len(r.json) > 0)
515 r = self.client.container_get(show_only_shared=True)
516 self.assertTrue(len(r.json) < fullLen)
520 r = self.client.container_get(until=1000000000)
521 datestring = unicode(r.headers['x-account-until-timestamp'])
522 self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
528 """Check and if un/modified_since"""
529 for format in self.client.DATE_FORMATS:
530 now_formated = self.now_unformated.strftime(format)
531 r1 = self.client.container_get(if_modified_since=now_formated, success=(200, 304, 412))
534 r2 = self.client.container_get(if_unmodified_since=now_formated, success=(200, 304, 412))
537 self.assertNotEqual(sc1, sc2)
539 def test_container_put(self):
540 """Test container_PUT"""
541 self.client.container = self.c2
543 r = self.client.container_put()
544 self.assertEqual(r.status_code, 202)
547 r = self.client.get_container_quota(self.client.container)
548 cquota = r.values()[0]
549 newquota = 2*int(cquota)
551 r = self.client.container_put(quota=newquota)
552 self.assertEqual(r.status_code, 202)
554 r = self.client.get_container_quota(self.client.container)
555 xquota = int(r.values()[0])
556 self.assertEqual(newquota, xquota)
558 r = self.client.container_put(versioning='auto')
559 self.assertEqual(r.status_code, 202)
561 r = self.client.get_container_versioning(self.client.container)
562 nvers = r.values()[0]
563 self.assertEqual('auto', nvers)
565 r = self.client.container_put(versioning='none')
566 self.assertEqual(r.status_code, 202)
568 r = self.client.get_container_versioning(self.client.container)
569 nvers = r.values()[0]
570 self.assertEqual('none', nvers)
572 r = self.client.container_put(metadata={'m1':'v1', 'm2':'v2'})
573 self.assertEqual(r.status_code, 202)
575 r = self.client.get_container_meta(self.client.container)
576 self.assertTrue(r.has_key('x-container-meta-m1'))
577 self.assertEqual(r['x-container-meta-m1'], 'v1')
578 self.assertTrue(r.has_key('x-container-meta-m2'))
579 self.assertEqual(r['x-container-meta-m2'], 'v2')
581 r = self.client.container_put(metadata={'m1':'', 'm2':'v2a'})
582 self.assertEqual(r.status_code, 202)
584 r = self.client.get_container_meta(self.client.container)
585 self.assertTrue(not r.has_key('x-container-meta-m1'))
586 self.assertTrue(r.has_key('x-container-meta-m2'))
587 self.assertEqual(r['x-container-meta-m2'], 'v2a')
589 self.client.del_container_meta(self.client.container)
591 def test_container_post(self):
592 """Test container_POST"""
593 self.client.container = self.c2
596 r = self.client.container_post()
597 self.assertEqual(r.status_code, 202)
601 self.client.set_container_meta({'m1':'v1', 'm2':'v2'})
602 r = self.client.get_container_meta(self.client.container)
603 self.assertTrue(r.has_key('x-container-meta-m1'))
604 self.assertEqual(r['x-container-meta-m1'], 'v1')
605 self.assertTrue(r.has_key('x-container-meta-m2'))
606 self.assertEqual(r['x-container-meta-m2'], 'v2')
609 r = self.client.del_container_meta('m1')
610 r = self.client.set_container_meta({'m2':'v2a'})
611 r = self.client.get_container_meta(self.client.container)
612 self.assertTrue(not r.has_key('x-container-meta-m1'))
613 self.assertTrue(r.has_key('x-container-meta-m2'))
614 self.assertEqual(r['x-container-meta-m2'], 'v2a')
617 r = self.client.get_container_quota(self.client.container)
618 cquota = r.values()[0]
619 newquota = 2*int(cquota)
620 r = self.client.set_container_quota(newquota)
621 r = self.client.get_container_quota(self.client.container)
622 xquota = int(r.values()[0])
623 self.assertEqual(newquota, xquota)
624 r = self.client.set_container_quota(cquota)
625 r = self.client.get_container_quota(self.client.container)
626 xquota = r.values()[0]
627 self.assertEqual(cquota, xquota)
629 """Check versioning"""
630 self.client.set_container_versioning('auto')
631 r = self.client.get_container_versioning(self.client.container)
632 nvers = r.values()[0]
633 self.assertEqual('auto', nvers)
634 self.client.set_container_versioning('none')
635 r = self.client.get_container_versioning(self.client.container)
636 nvers = r.values()[0]
637 self.assertEqual('none', nvers)
639 """put_block uses content_type and content_length to
640 post blocks of data 2 container. All that in upload_object"""
641 """Change a file at fs"""
642 self.create_large_file(1024*1024*100, 'l100M.'+unicode(self.now))
643 """Upload it at a directory in container"""
644 self.client.create_directory('dir')
645 newf = open(self.fname, 'r')
646 self.client.upload_object('/dir/sample.file', newf)
648 """Check if file has been uploaded"""
649 r = self.client.get_object_info('/dir/sample.file')
650 self.assertTrue(int(r['content-length']) > 100000000)
652 """WTF is tranfer_encoding? What should I check about th** s**t? """
655 """Check update=False"""
656 r = self.client.object_post('test', update=False, metadata={'newmeta':'newval'})
658 r = self.client.get_object_info('test')
659 self.assertTrue(r.has_key('x-object-meta-newmeta'))
660 self.assertFalse(r.has_key('x-object-meta-incontainer'))
662 r = self.client.del_container_meta('m2')
664 def test_container_delete(self):
665 """Test container_DELETE"""
667 """Fail to delete a non-empty container"""
668 self.client.container = self.c2
669 r = self.client.container_delete(success=409)
670 self.assertEqual(r.status_code, 409)
673 """Fail to delete c3 (empty) container"""
674 self.client.container = self.c3
675 r = self.client.container_delete(until='1000000000')
676 self.assertEqual(r.status_code, 204)
679 """Delete c3 (empty) container"""
680 r = self.client.container_delete()
681 self.assertEqual(r.status_code, 204)
683 """Purge container(empty a container), check versionlist"""
684 self.client.container = self.c1
685 r = self.client.object_head('test', success=(200, 404))
686 self.assertEqual(r.status_code, 200)
687 self.client.del_container(delimiter='/')
688 r = self.client.object_head('test', success=(200, 404))
689 self.assertEqual(r.status_code, 404)
690 r = self.client.get_object_versionlist('test')
691 self.assertTrue(len(r) > 0)
692 self.assertTrue(len(r[0])>1)
693 self.client.purge_container()
694 self.assertRaises(ClientError, self.client.get_object_versionlist, 'test')
696 def test_object_head(self):
697 """Test object_HEAD"""
698 self.client.container = self.c2
701 r = self.client.object_head(obj)
702 self.assertEqual(r.status_code, 200)
703 etag = r.headers['etag']
706 r = self.client.object_head(obj, version=40)
707 self.assertEqual(r.headers['x-object-version'], '40')
710 r = self.client.object_head(obj, if_etag_match=etag)
711 self.assertEqual(r.status_code, 200)
713 r = self.client.object_head(obj, if_etag_not_match=etag, success=(200, 412, 304))
714 self.assertNotEqual(r.status_code, 200)
717 r = self.client.object_head(obj, version=40, if_etag_match=etag, success=412)
718 self.assertEqual(r.status_code, 412)
721 """Check and if(un)modified_since"""
722 for format in self.client.DATE_FORMATS:
723 now_formated = self.now_unformated.strftime(format)
724 r1 = self.client.object_head(obj, if_modified_since=now_formated,
725 success=(200, 304, 412))
728 r2 = self.client.object_head(obj, if_unmodified_since=now_formated,
729 success=(200, 304, 412))
732 self.assertNotEqual(sc1, sc2)
734 def test_object_get(self):
735 """Test object_GET"""
736 self.client.container = self.c1
739 r = self.client.object_get(obj)
740 self.assertEqual(r.status_code, 200)
742 osize = int(r.headers['content-length'])
743 etag = r.headers['etag']
746 r = self.client.object_get(obj, hashmap=True)
747 self.assertTrue(r.json.has_key('hashes') \
748 and r.json.has_key('block_hash') \
749 and r.json.has_key('block_size') \
750 and r.json.has_key('bytes'))
753 r = self.client.object_get(obj, format='xml', hashmap=True)
754 self.assertEqual(len(r.text.split('hash>')), 3)
757 rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
758 r = self.client.object_get(obj, data_range=rangestr, success=(200, 206))
759 partsize = int(r.headers['content-length'])
760 self.assertTrue(0 < partsize and partsize <= 1+osize/3)
763 rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
764 r = self.client.object_get(obj, data_range=rangestr, if_range=True, success=(200, 206))
765 partsize = int(r.headers['content-length'])
766 self.assertTrue(0 < partsize and partsize <= 1+osize/3)
769 r = self.client.object_get(obj, if_etag_match=etag)
770 self.assertEqual(r.status_code, 200)
773 r = self.client.object_get(obj, if_etag_not_match=etag+'LALALA')
774 self.assertEqual(r.status_code, 200)
777 """Check and if(un)modified_since"""
778 for format in self.client.DATE_FORMATS:
779 now_formated = self.now_unformated.strftime(format)
780 r1 = self.client.object_get(obj, if_modified_since=now_formated,
781 success=(200, 304, 412))
784 r2 = self.client.object_get(obj, if_unmodified_since=now_formated, success=(200, 304, 412))
787 self.assertNotEqual(sc1, sc2)
789 def test_object_put(self):
790 """Test object_PUT"""
792 self.client.container = self.c2
795 """create the object"""
796 r = self.client.object_put(obj, data='a', content_type='application/octer-stream',
797 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']},
798 metadata={'key1':'val1', 'key2':'val2'}, content_encoding='UTF-8',
799 content_disposition='attachment; filename="fname.ext"')
800 self.assertEqual(r.status_code, 201)
801 etag = r.headers['etag']
803 """Check content-disposition"""
804 r = self.client.get_object_info(obj)
805 self.assertTrue(r.has_key('content-disposition'))
807 """Check permitions"""
808 r = self.client.get_object_sharing(obj)
809 self.assertTrue('accx:groupa' in r['read'])
810 self.assertTrue('u1' in r['read'])
811 self.assertTrue('u2' in r['write'])
812 self.assertTrue('u3' in r['write'])
815 r = self.client.get_object_meta(obj)
816 self.assertEqual(r['x-object-meta-key1'], 'val1')
817 self.assertEqual(r['x-object-meta-key2'], 'val2')
819 """Check public and if_etag_match"""
820 r = self.client.object_put(obj, if_etag_match=etag, data='b',
821 content_type='application/octet-stream', public=True)
823 r = self.client.object_get(obj)
824 self.assertTrue(r.headers.has_key('x-object-public'))
825 vers2 = int(r.headers['x-object-version'])
826 etag = r.headers['etag']
827 self.assertEqual(r.text, 'b')
829 """Check if_etag_not_match"""
830 r = self.client.object_put(obj, if_etag_not_match=etag, data='c',
831 content_type='application/octet-stream', success=(201, 412))
832 self.assertEqual(r.status_code, 412)
835 """Check content_type and content_length"""
836 tmpdir = 'dir'+unicode(self.now)
837 r = self.client.object_put(tmpdir, content_type='application/directory',
840 r = self.client.get_object_info(tmpdir)
841 self.assertEqual(r['content-type'], 'application/directory')
843 """Check copy_from, content_encoding"""
844 r = self.client.object_put('%s/%s'%(tmpdir, obj), format=None,
845 copy_from='/%s/%s'%(self.client.container, obj),
846 content_encoding='application/octet-stream',
847 source_account=self.client.account,
848 content_length=0, success=201)
849 self.assertEqual(r.status_code, 201)
851 """Check cross-container copy_from, content_encoding"""
852 self.client.container = self.c1
853 fromstr = '/'+self.c2+'/'+tmpdir+'/'+obj
854 r = self.client.object_put(obj, format=None, copy_from=fromstr,
855 content_encoding='application/octet-stream',
856 source_account=self.client.account,
857 content_length=0, success=201)
859 self.assertEqual(r.status_code, 201)
860 r = self.client.get_object_info(obj)
861 self.assertEqual(r['etag'], etag)
863 """Check source_account"""
864 self.client.container = self.c2
865 fromstr = '/'+self.c1+'/'+obj
866 r = self.client.object_put(obj+'v2', format=None, move_from=fromstr,
867 content_encoding='application/octet-stream',
868 source_account='nonExistendAddress@NeverLand.com',
869 content_length=0, success=(201, 403))
870 self.assertEqual(r.status_code, 403)
872 """Check cross-container move_from"""
873 r = self.client.object_put(obj+'v0', format=None,
874 move_from='/'+self.c1+'/'+obj,
875 content_encoding='application/octet-stream',
876 content_length=0, success=201)
877 self.assertEqual(r.status_code, 201)
879 r = self.client.get_object_info(obj+'v0')
880 self.assertEqual(r['etag'], etag)
882 """Check move_from"""
883 r = self.client.object_put(obj+'v1', format=None,
884 move_from='/'+self.c2+'/'+obj,
885 source_version = vers2,
886 content_encoding='application/octet-stream',
887 content_length=0, success=201)
890 mobj = 'manifest.test'
894 r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
895 content_type='application/octet-stream', content_encoding='application/octet-stream')
897 r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream',
898 manifest='%s/%s'%(self.client.container, mobj))
900 r = self.client.object_get(mobj)
901 self.assertEqual(r.text, txt)
903 """Upload a local file with one request"""
904 self.create_large_file(1024*10, 'l10K.'+unicode(self.now))
905 newf = open(self.fname, 'r')
906 self.client.upload_object('sample.file', newf)
908 """Check if file has been uploaded"""
909 r = self.client.get_object_info('sample.file')
910 self.assertEqual(int(r['content-length']), 10260)
912 """Some problems with transfer-encoding?"""
914 def test_object_copy(self):
915 """Test object_COPY"""
916 self.client.container=self.c2
919 data= '{"key1":"val1", "key2":"val2"}'
920 r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
921 data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
923 'read':['accX:groupA', 'u1', 'u2'],
924 'write':['u2', 'u3']},
925 content_disposition='attachment; filename="fname.ext"')
927 r = self.client.object_copy(obj+'orig',
928 destination = '/'+self.client.container+'/'+obj,
929 ignore_content_type=False, content_type='application/json',
930 metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
931 permitions={'write':['u5', 'accX:groupB']})
932 self.assertEqual(r.status_code, 201)
934 """Check content-disposition"""
935 r = self.client.get_object_info(obj)
936 self.assertTrue(r.has_key('content-disposition'))
939 r = self.client.get_object_meta(obj)
940 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
941 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
942 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
944 """Check permitions"""
945 r = self.client.get_object_sharing(obj)
946 self.assertFalse(r.has_key('read') or 'u2' in r['write'])
947 self.assertTrue('accx:groupb' in r['write'])
949 """Check destination account"""
950 r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
951 content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
953 self.assertEqual(r.status_code, 403)
956 """Check destination being another container
957 and also content_type and content encoding"""
958 r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj),
959 content_encoding='utf8', content_type='application/json')
960 self.assertEqual(r.status_code, 201)
961 self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
964 """Check ignore_content_type and content_type"""
965 r = self.client.object_get(obj)
966 etag = r.headers['etag']
967 ctype = r.headers['content-type']
968 self.assertEqual(ctype, 'application/json')
970 r = self.client.object_copy(obj+'orig',
971 destination = '/'+self.client.container+'/'+obj+'0',
972 ignore_content_type=True, content_type='application/json')
973 self.assertEqual(r.status_code, 201)
974 self.assertNotEqual(r.headers['content-type'], 'application/json')
977 """Check if_etag_(not_)match"""
978 r = self.client.object_copy(obj,
979 destination='/'+self.client.container+'/'+obj+'1', if_etag_match=etag)
980 self.assertEqual(r.status_code, 201)
982 r = self.client.object_copy(obj,
983 destination='/'+self.client.container+'/'+obj+'2', if_etag_not_match='lalala')
984 self.assertEqual(r.status_code, 201)
985 vers2 = r.headers['x-object-version']
988 """Check source_version, public and format """
989 r = self.client.object_copy(obj+'2', destination='/'+self.client.container+'/'+obj+'3', source_version=vers2, format='xml', public=True)
990 self.assertEqual(r.status_code, 201)
991 self.assertTrue(r.headers['content-type'].index('xml') > 0)
993 r = self.client.get_object_info(obj+'3')
994 self.assertTrue(r.has_key('x-object-public'))
996 def test_object_move(self):
997 """Test object_MOVE"""
998 self.client.container= self.c2
1001 data= '{"key1":"val1", "key2":"val2"}'
1002 r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
1003 data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1004 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1006 r = self.client.object_move(obj+'orig', destination = '/'+self.client.container+'/'+obj,
1007 ignore_content_type=False, content_type='application/json',
1008 metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
1009 permitions={'write':['u5', 'accX:groupB']})
1010 self.assertEqual(r.status_code, 201)
1013 """Check Metadata"""
1014 r = self.client.get_object_meta(obj)
1015 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1016 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1017 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1019 """Check permitions"""
1020 r = self.client.get_object_sharing(obj)
1021 self.assertFalse(r.has_key('read'))
1022 self.assertTrue('u5' in r['write'])
1023 self.assertTrue('accx:groupb' in r['write'])
1025 """Check destination account"""
1026 r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
1027 content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
1029 self.assertEqual(r.status_code, 403)
1032 """Check destination being another container and also
1033 content_type, content_disposition and content encoding"""
1034 r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj),
1035 content_encoding='utf8', content_type='application/json',
1036 content_disposition='attachment; filename="fname.ext"')
1037 self.assertEqual(r.status_code, 201)
1038 self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
1039 self.client.container=self.c1
1040 r = self.client.get_object_info(obj)
1041 self.assertTrue(r.has_key('content-disposition') and 'fname.ext' in r['content-disposition'])
1043 ctype = r['content-type']
1044 self.assertEqual(ctype, 'application/json')
1046 """Check ignore_content_type and content_type"""
1047 r = self.client.object_move(obj, destination = '/%s/%s'%(self.c2,obj),
1048 ignore_content_type=True, content_type='application/json')
1049 self.assertEqual(r.status_code, 201)
1050 self.assertNotEqual(r.headers['content-type'], 'application/json')
1053 """Check if_etag_(not_)match"""
1054 self.client.container=self.c2
1055 r = self.client.object_move(obj, destination='/'+self.client.container+'/'+obj+'0',
1057 self.assertEqual(r.status_code, 201)
1059 r = self.client.object_move(obj+'0', destination='/'+self.client.container+'/'+obj+'1',
1060 if_etag_not_match='lalala')
1061 self.assertEqual(r.status_code, 201)
1064 """Check public and format """
1065 r = self.client.object_move(obj+'1', destination='/'+self.client.container+'/'+obj+'2',
1066 format='xml', public=True)
1067 self.assertEqual(r.status_code, 201)
1068 self.assertTrue(r.headers['content-type'].index('xml') > 0)
1070 r = self.client.get_object_info(obj+'2')
1071 self.assertTrue(r.has_key('x-object-public'))
1073 def test_object_post(self):
1074 """Test object_POST"""
1075 self.client.container=self.c2
1077 """create a filesystem file"""
1079 newf = open(self.fname, 'w')
1080 newf.writelines(['ello!\n','This is a test line\n','inside a test file\n'])
1082 """create a file on container"""
1083 r = self.client.object_put(obj, content_type='application/octet-stream',
1084 data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1085 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1088 """Append tests update, content_range, content_type, content_length"""
1089 newf = open(obj, 'r')
1090 self.client.append_object(obj, newf)
1091 r = self.client.object_get(obj)
1092 self.assertTrue(r.text.startswith('Hello!'))
1095 """Overwrite tests update, content_type, content_length, content_range"""
1097 r = self.client.overwrite_object(obj, 0, 10, newf)
1098 r = self.client.object_get(obj)
1099 self.assertTrue(r.text.startswith('ello!'))
1103 """Truncate tests update, content_range, content_type,
1104 object_bytes and source_object"""
1105 r = self.client.truncate_object(obj, 5)
1106 r = self.client.object_get(obj)
1107 self.assertEqual(r.text, 'ello!')
1110 """Check metadata"""
1111 self.client.set_object_meta(obj, {'mkey2':'mval2a', 'mkey3':'mval3'})
1112 r = self.client.get_object_meta(obj)
1113 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1114 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1115 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1116 self.client.del_object_meta('mkey1', obj)
1117 r = self.client.get_object_meta(obj)
1118 self.assertFalse(r.has_key('x-object-meta-mkey1'))
1120 """Check permitions"""
1121 self.client.set_object_sharing(obj,
1122 read_permition=['u4', 'u5'], write_permition=['u4'])
1123 r = self.client.get_object_sharing(obj)
1124 self.assertTrue(r.has_key('read'))
1125 self.assertTrue('u5' in r['read'])
1126 self.assertTrue(r.has_key('write'))
1127 self.assertTrue('u4' in r['write'])
1128 self.client.del_object_sharing(obj)
1129 r = self.client.get_object_sharing(obj)
1130 self.assertTrue(len(r) == 0)
1133 self.client.publish_object(obj)
1134 r = self.client.get_object_info(obj)
1135 self.assertTrue(r.has_key('x-object-public'))
1136 self.client.unpublish_object(obj)
1137 r = self.client.get_object_info(obj)
1138 self.assertFalse(r.has_key('x-object-public'))
1140 """Check if_etag_(not)match"""
1142 #r = self.client.object_post(obj, update=True, public=True,
1143 # if_etag_not_match=etag, success=(412,202,204))
1144 #self.assertEqual(r.status_code, 412)
1146 r = self.client.object_post(obj, update=True, public=True,
1147 if_etag_match=etag, content_encoding='application/json')
1149 r = self.client.get_object_info(obj)
1150 helloVersion = r['x-object-version']
1151 self.assertTrue(r.has_key('x-object-public'))
1152 self.assertEqual(r['content-encoding'], 'application/json')
1154 """Check source_version and source_account and content_disposition"""
1155 r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1156 content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1157 source_account='thisAccountWillNeverExist@adminland.com',
1158 source_version=helloVersion, data='12345', success=(403, 202, 204))
1159 self.assertEqual(r.status_code, 403)
1161 r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1162 content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1163 source_account=self.client.account, source_version=helloVersion, data='12345',
1164 content_disposition='attachment; filename="fname.ext"')
1166 r = self.client.object_get(obj)
1167 self.assertEqual(r.text, 'eello!')
1168 self.assertTrue(r.headers.has_key('content-disposition')
1169 and 'fname.ext' in r.headers['content-disposition'])
1172 """Check manifest"""
1173 mobj = 'manifest.test'
1177 r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
1178 content_encoding='application/octet-stream', content_type='application/octet-stream')
1180 #r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream')
1181 self.client.create_object_by_manifestation(mobj, content_type='application/octet-stream')
1183 r = self.client.object_post(mobj, manifest='%s/%s'%(self.client.container, mobj))
1185 r = self.client.object_get(mobj)
1186 self.assertEqual(r.text, txt)
1189 """We need to check transfer_encoding """
1191 def test_object_delete(self):
1192 """Test object_DELETE"""
1193 self.client.container=self.c2
1195 """create a file on container"""
1196 r = self.client.object_put(obj, content_type='application/octet-stream',
1197 data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1198 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1201 """Check with false until"""
1202 r = self.client.object_delete(obj, until=1000000)
1204 r = self.client.object_get(obj, success=(200, 404))
1205 self.assertEqual(r.status_code, 200)
1208 """Check normal case"""
1209 r = self.client.object_delete(obj)
1210 self.assertEqual(r.status_code, 204)
1212 r = self.client.object_get(obj, success=(200, 404))
1213 self.assertEqual(r.status_code, 404)
1216 def create_large_file(self, size, name):
1217 """Create a large file at fs"""
1220 random.seed(self.now)
1221 f = open(self.fname, 'w')
1222 sys.stdout.write(' create random file %s of size %s'%(name, size)+' 0%')
1223 for hobyte_id in range(size/8):
1224 sss = 'hobt%s'%random.randint(1000, 9999)
1226 if 0 == (hobyte_id*800)%size:
1228 sys.stdout.write('\b\b')
1229 prs = (hobyte_id*800)//size
1231 sys.stdout.write('\b')
1232 sys.stdout.write('%s'%prs+'%')
1239 parser = ArgumentParser(add_help=False)
1240 parser.add_argument('-h', '--help', dest='help', action='store_true', default=False,
1241 help="Show this help message and exit")
1244 if __name__ == '__main__':
1245 parser = init_parser()
1246 args, argv = parser.parse_known_args()
1248 if len(argv) > 2 or getattr(args,'help') or len(argv) < 1:
1249 raise Exception('\tusage: tests.py <group> [command]')
1250 suiteFew = unittest.TestSuite()
1252 if len(argv) == 0 or argv[0] == 'pithos':
1254 suiteFew.addTest(unittest.makeSuite(testPithos))
1256 suiteFew.addTest(testPithos('test_'+argv[1]))
1257 if len(argv) == 0 or argv[0] == 'cyclades':
1259 #suiteFew.addTest(unittest.makeSuite(testCyclades))
1260 suiteFew.addTest(testCyclades('test_000'))
1262 suiteFew.addTest(testCyclades('test_'+argv[1]))
1264 unittest.TextTestRunner(verbosity = 2).run(suiteFew)