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 token='Kn+G9dfmlPLR2WFnhfBOow=='
56 account='saxtouri@gmail.com'
57 account='saxtouri@grnet.gr'
58 self.img = 'b2dffe52-64a4-48c3-8a4c-8214cc3165cf'
61 u'updated': u'2012-10-16T09:04:17+00:00',
62 u'name': u'Debian Base',
63 u'created': u'2012-10-16T09:03:12+00:00',
65 u'id': 'b2dffe52-64a4-48c3-8a4c-8214cc3165cf',
69 u'osfamily': u'linux',
74 u'root_partition': u'1',
75 u'description': u'Debian 6.0.6 (Squeeze) Base System',
76 u'partition_table': u'msdos'}
81 #url = 'https://cyclades.okeanos.io/api/v1.1'
82 #token='0TpoyAXqJSPxLdDuZHiLOA=='
83 #account='saxtouri@admin.grnet.gr'
84 #self.img = '43cc8497-61c3-4c46-ae8d-3e33861f8527'
86 # u'status': u'ACTIVE',
87 # u'updated': u'2012-08-21T12:57:39+00:00',
88 # u'name': u'Debian Base',
89 # u'created': u'2012-08-21T12:56:53+00:00',
91 # u'id': u'43cc8497-61c3-4c46-ae8d-3e33861f8527',
94 # u'kernel': u'2.6.32',
95 # u'osfamily': u'linux',
101 # u'1', u'description':
102 # u'Debian Squeeze Base System'}
108 self.now = time.mktime(time.gmtime())
109 self.servname1 = 'serv'+unicode(self.now)
110 self.servname2 = self.servname1+'_v2'
112 #servers have to be created at the begining...
114 self.client = cyclades(url, token)
118 """Destoy servers used in testing"""
119 if 0 >= len(self.servers):
121 there_are_servers_running = True
125 print('-> Found %s servers to delete'%len(self.servers))
126 while there_are_servers_running:
127 there_are_servers_running = False
129 c = ['|','/','-','\\']
131 sys.stdout.write('\t. . . wait %s seconds: '%waitime)
132 for i in range(4*waitime):
134 suffix = '%ss %s'%(i/4, c[i%4])
135 sys.stdout.write(oldlen*'\b'+suffix)
138 oldlen = len(': '+suffix)
139 print(oldlen*'\b'+oldlen*' ')
142 dservers = self.client.list_servers(detail=True)
143 for server in dservers:
144 if server['name'] in self.servers.keys():
145 there_are_servers_running = True
146 sys.stdout.write('\t%s status:%s '%(server['name'], server['status']))
147 if server['status'] == 'BUILD':
150 print('\tDELETE %s'%server['name'])
151 self._delete_server(server['id'])
152 self.servers.pop(server['name'])
153 deleted_servers[server['name']] = 0
155 elif server['name'] in deleted_servers.keys():
156 there_are_servers_running = True
157 sys.stdout.write('\t%s status:%s '%(server['name'], server['status']))
158 retries = deleted_servers[server['name']]
160 print('\tretry DELETE %s'%server['name'])
161 self._delete_server(server['id'])
165 print('\tnot deleted yet ...')
166 deleted_servers[server['name']] = retries + 1
168 def _create_server(self, servername, flavorid, imageid, personality=None):
169 server = self.client.create_server(servername, flavorid, imageid, personality)
170 self.servers[servername] = server
173 def _delete_server(self, servid):
174 self.client.delete_server(servid)
182 def assert_dicts_are_deeply_equal(self, d1, d2):
183 for k,v in d1.items():
184 self.assertTrue(d2.has_key(k))
185 if isinstance(v, dict):
186 self.assert_dicts_are_deeply_equal(v, d2[k])
188 self.assertEqual(unicode(v), unicode(d2[k]))
191 "Prepare a full Cyclades test scenario"
195 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
196 self.server2 = self._create_server(self.servname2, self.flavorid, self.img)
199 sys.stdout.write(' test create server')
200 self._test_create_server()
203 sys.stdout.write(' test list servers')
204 self._test_list_servers()
207 sys.stdout.write(' test get server details')
208 self._test_get_server_details()
211 sys.stdout.write(' test get image details')
212 self._test_get_image_details()
215 sys.stdout.write(' test update_server_name')
216 self._test_update_server_name()
219 sys.stdout.write(' test reboot_server')
220 self._test_reboot_server()
223 sys.stdout.write(' test create_server_metadata')
224 self._test_create_server_metadata()
227 sys.stdout.write(' test get_server_metadata')
228 self._test_get_server_metadata()
231 def _has_status(self, servid, status):
232 r = self.client.get_server_details(servid)
233 return r['status'] == status
234 def _wait_for_status(self, servid, status):
237 while self._has_status(servid, status):
239 sys.stdout.write('\tServer %s in %s. Wait %ss '%(servid, status, wait))
240 for i in range(4*wait):
241 sys.stdout.write('\b%s'%c[i%4])
245 wait = (wait + 7) if wait<60 else 0
248 def test_list_servers(self):
249 """Test list servers"""
250 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
251 self.server2 = self._create_server(self.servname2, self.flavorid, self.img)
252 self._test_list_servers()
254 def _test_list_servers(self):
255 servers = self.client.list_servers()
256 dservers = self.client.list_servers(detail=True)
258 """detailed and simple are same size"""
259 self.assertEqual(len(dservers), len(servers))
260 for i in range(len(servers)):
261 for field in ['created', 'flavorRef', 'hostId', 'imageRef', 'progress',
262 'status', 'updated']:
263 self.assertFalse(servers[i].has_key(field))
264 self.assertTrue(dservers[i].has_key(field))
266 """detailed and simple contain same names"""
267 names = sorted(map(lambda x: x["name"], servers))
268 dnames = sorted(map(lambda x: x["name"], dservers))
269 self.assertEqual(names, dnames)
272 def test_create_server(self):
273 """Test create_server"""
274 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
275 self._test_create_server()
277 def _test_create_server(self):
278 self.assertEqual(self.server1["name"], self.servname1)
279 self.assertEqual(self.server1["flavorRef"], self.flavorid)
280 self.assertEqual(self.server1["imageRef"], self.img)
281 self.assertEqual(self.server1["status"], "BUILD")
284 def test_get_server_details(self):
285 """Test get_server_details"""
286 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
287 self._test_get_server_details()
289 def _test_get_server_details(self):
290 r = self.client.get_server_details(self.server1['id'])
291 self.assertEqual(r["name"], self.servname1)
292 self.assertEqual(r["flavorRef"], self.flavorid)
293 self.assertEqual(r["imageRef"], self.img)
294 self.assertEqual(r["status"], "BUILD")
297 def test_get_image_details(self):
298 """Test get_image_details"""
299 self._test_get_image_details()
301 def _test_get_image_details(self):
302 r = self.client.get_image_details(self.img)
304 self.assert_dicts_are_deeply_equal(r, d)
307 def test_update_server_name(self):
308 """Test update_server_name"""
309 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
310 self._test_update_server_name()
312 def _test_update_server_name(self):
313 new_name = self.servname1+'_new_name'
314 self.client.update_server_name(self.server1['id'], new_name)
315 r = self.client.get_server_details(self.server1['id'], success=(200, 400))
316 self.assertEqual(r['name'], new_name)
317 changed = self.servers.pop(self.servname1)
318 changed['name'] = new_name
319 self.servers[new_name] = changed
322 def test_reboot_server(self):
323 """Test reboot_server"""
324 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
325 self.server2 = self._create_server(self.servname2, self.flavorid, self.img)
326 self._test_reboot_server()
328 def _test_reboot_server(self):
329 self._wait_for_status(self.server1['id'], 'BUILD')
330 self.client.reboot_server(self.server1['id'])
331 self.assertTrue(self._has_status(self.server1['id'], 'REBOOT'))
332 self._wait_for_status(self.server2['id'], 'BUILD')
333 self.client.reboot_server(self.server2['id'], hard=True)
334 self.assertTrue(self._has_status(self.server2['id'], 'REBOOT'))
335 self._wait_for_status(self.server1['id'], 'REBOOT')
336 self._wait_for_status(self.server2['id'], 'REBOOT')
339 def test_get_server_metadata(self):
340 """Test get_server_metadata"""
341 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
342 self._test_get_server_metadata()
343 def _test_get_server_metadata(self):
344 self.client.create_server_metadata(self.server1['id'], 'mymeta_0', 'val_0')
345 r = self.client.get_server_metadata(self.server1['id'], 'mymeta_0')
346 self.assertEqual(r['mymeta_0', 'val_0')
349 def test_create_server_metadata(self):
350 """Test create_server_metadata"""
351 self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
352 self._test_create_server_metadata()
354 def _test_create_server_metadata(self):
355 r1 = self.client.create_server_metadata(self.server1['id'], 'mymeta', 'mymeta val')
356 self.assertTrue(r1.has_key('mymeta'))
357 r2 = self.client.get_server_metadata(self.server1['id'], 'mymeta')
358 self.assert_dicts_are_deeply_equal(r1, r2)
360 class testPithos(unittest.TestCase):
361 """Set up a Pithos+ thorough test"""
364 url = 'http://127.0.0.1:8000/v1'
365 token = 'C/yBXmz3XjTFBnujc2biAg=='
366 token = 'ac0yH8cQMEZu3M3Mp1MWGA=='
367 account = 'admin@adminland.com'
370 url='https://pithos.okeanos.grnet.gr/v1'
372 token='Kn+G9dfmlPLR2WFnhfBOow=='
373 account='saxtouri@grnet.gr'
376 url='https://pithos.okeanos.io/v1'
377 token='0TpoyAXqJSPxLdDuZHiLOA=='
378 account='saxtouri@admin.grnet.gr'
382 def add_handler(name, level, prefix=''):
383 h = logging.StreamHandler()
384 fmt = logging.Formatter(prefix + '%(message)s')
386 logger = logging.getLogger(name)
388 logger.setLevel(level)
390 sendlog = logging.getLogger('clients.send')
391 recvlog = logging.getLogger('clients.recv')
392 add_handler('requests', logging.INFO, prefix='* ')
393 add_handler('clients.send', logging.INFO, prefix='> ')
394 add_handler('clients.recv', logging.INFO, prefix='< ')
399 self.client = pithos(url, token, account, container)
400 self.now = time.mktime(time.gmtime())
401 self.c1 = 'c1_'+unicode(self.now)
402 self.c2 = 'c2_'+unicode(self.now)
403 self.c3 = 'c3_'+unicode(self.now)
406 self.client.create_container(self.c1)
407 self.client.create_container(self.c2)
408 self.client.create_container(self.c3)
409 self.makeNewObject(self.c1, 'test')
410 self.makeNewObject(self.c2, 'test')
411 self.now_unformated = datetime.datetime.utcnow()
412 self.makeNewObject(self.c1, 'test1')
413 self.makeNewObject(self.c2, 'test1')
414 """Prepare an object to be shared - also its container"""
415 self.client.container = self.c1
416 r = self.client.object_post('test', update=True, permitions={'read':'someUser'})
418 self.makeNewObject(self.c1, 'another.test')
420 def makeNewObject(self, container, obj):
421 self.client.container = container
422 r = self.client.object_put(obj, content_type='application/octet-stream',
423 data= 'file '+obj+' that lives in '+container,
424 metadata={'incontainer':container})
426 def forceDeleteContainer(self, container):
427 self.client.container = container
429 r = self.client.list_objects()
434 self.client.del_object(name)
435 r = self.client.container_delete()
439 """Destroy test cases"""
440 if self.fname is not None:
442 os.remove(self.fname)
446 self.forceDeleteContainer(self.c1)
447 self.forceDeleteContainer(self.c2)
449 self.forceDeleteContainer(self.c3)
452 self.client.container=''
455 """Perform a full Pithos+ kamaki support test"""
457 def test_account_head(self):
458 """Test account_HEAD"""
459 r = self.client.account_head()
460 self.assertEqual(r.status_code, 204)
462 r = self.client.account_head(until='1000000000')
463 self.assertEqual(r.status_code, 204)
465 r = self.client.get_account_info(until='1000000000')
466 datestring = unicode(r['x-account-until-timestamp'])
467 self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
469 r = self.client.get_account_quota()
470 self.assertTrue(r.has_key('x-account-policy-quota'))
472 r = self.client.get_account_versioning()
473 self.assertTrue(r.has_key('x-account-policy-versioning'))
475 """Check if(un)modified_since"""
476 for format in self.client.DATE_FORMATS:
477 now_formated = self.now_unformated.strftime(format)
478 r1 = self.client.account_head(if_modified_since=now_formated, success=(204, 304, 412))
481 r2 = self.client.account_head(if_unmodified_since=now_formated, success=(204, 304, 412))
484 self.assertNotEqual(sc1, sc2)
486 def test_account_get(self):
487 """Test account_GET"""
488 #r = self.client.account_get()
489 #self.assertEqual(r.status_code, 200)
490 r = self.client.list_containers()
492 self.assertTrue(fullLen > 2)
494 r = self.client.account_get(limit=1)
495 self.assertEqual(len(r.json), 1)
498 r = self.client.account_get(marker='c2_')
499 temp_c0 = r.json[0]['name']
500 temp_c2 = r.json[2]['name']
502 r = self.client.account_get(limit=2, marker='c2_')
503 conames = [container['name'] for container in r.json \
504 if container['name'].lower().startswith('c2_')]
505 self.assertTrue(temp_c0 in conames)
506 self.assertFalse(temp_c2 in conames)
509 r = self.client.account_get(show_only_shared=True)
510 self.assertTrue(self.c1 in [c['name'] for c in r.json])
512 r = self.client.account_get(until=1342609206)
513 self.assertTrue(len(r.json) <= fullLen)
515 """Check if(un)modified_since"""
516 for format in self.client.DATE_FORMATS:
517 now_formated = self.now_unformated.strftime(format)
518 r1 = self.client.account_get(if_modified_since=now_formated, success=(200, 304, 412))
521 r2 = self.client.account_get(if_unmodified_since=now_formated, success=(200, 304, 412))
524 self.assertNotEqual(sc1, sc2)
526 """Check sharing_accounts"""
527 r = self.client.get_sharing_accounts()
528 self.assertTrue(len(r)>0)
530 def test_account_post(self):
531 """Test account_POST"""
532 r = self.client.account_post()
533 self.assertEqual(r.status_code, 202)
534 grpName = 'grp'+unicode(self.now)
537 """Method set/del_account_meta and set_account_groupcall use account_post internally
539 self.client.set_account_group(grpName, ['u1', 'u2'])
540 r = self.client.get_account_group()
541 self.assertEqual(r['x-account-group-'+grpName], 'u1,u2')
542 self.client.del_account_group(grpName)
543 r = self.client.get_account_group()
544 self.assertTrue(not r.has_key('x-account-group-'+grpName))
546 mprefix = 'meta'+unicode(self.now)
547 self.client.set_account_meta({mprefix+'1':'v1', mprefix+'2':'v2'})
548 r = self.client.get_account_meta()
549 self.assertEqual(r['x-account-meta-'+mprefix+'1'], 'v1')
550 self.assertEqual(r['x-account-meta-'+mprefix+'2'], 'v2')
552 self.client.del_account_meta(mprefix+'1')
553 r = self.client.get_account_meta()
554 self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'1'))
556 self.client.del_account_meta(mprefix+'2')
557 r = self.client.get_account_meta()
558 self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'2'))
560 """Missing testing for quota, versioning, because normally
561 you don't have permitions to modify those at account level
565 self.client.set_account_quota(newquota)
566 #r = self.client.get_account_info()
568 #r = self.client.get_account_quota()
569 #self.assertEqual(r['x-account-policy-quota'], newquota)
570 self.client.set_account_versioning('auto')
572 def test_container_head(self):
573 """Test container_HEAD"""
574 self.client.container = self.c1
576 r = self.client.container_head()
577 self.assertEqual(r.status_code, 204)
580 r = self.client.container_head(until=1000000, success=(204, 404))
581 self.assertEqual(r.status_code, 404)
583 """Check and if(un)modified_since"""
584 for format in self.client.DATE_FORMATS:
585 now_formated = self.now_unformated.strftime(format)
586 r1 = self.client.container_head(if_modified_since=now_formated, success=(204, 304, 412))
589 r2 = self.client.container_head(if_unmodified_since=now_formated, success=(204, 304, 412))
592 self.assertNotEqual(sc1, sc2)
594 """Check container object meta"""
595 r = self.client.get_container_object_meta()
596 self.assertEqual(r['x-container-object-meta'], 'Incontainer')
598 def test_container_get(self):
599 """Test container_GET"""
600 self.client.container = self.c1
602 r = self.client.container_get()
603 self.assertEqual(r.status_code, 200)
604 fullLen = len(r.json)
607 r = self.client.container_get(prefix='test')
608 lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
609 self.assertTrue(len(r.json) > 1)
610 self.assertEqual(len(r.json), len(lalobjects))
613 r = self.client.container_get(limit=1)
614 self.assertEqual(len(r.json), 1)
617 r = self.client.container_get(marker='another')
618 self.assertTrue(len(r.json) > 1)
619 neobjects = [obj for obj in r.json if obj['name'] > 'another']
620 self.assertEqual(len(r.json), len(neobjects))
623 r = self.client.container_get(prefix='another.test', delimiter='.')
624 self.assertTrue(fullLen > len(r.json))
627 r = self.client.container_get(path='/')
628 self.assertEqual(fullLen, len(r.json))
631 r = self.client.container_get(format='xml')
632 self.assertEqual(r.text.split()[4], 'name="'+self.c1+'">')
635 r = self.client.container_get(meta=['incontainer'])
636 self.assertTrue(len(r.json) > 0)
639 r = self.client.container_get(show_only_shared=True)
640 self.assertTrue(len(r.json) < fullLen)
644 r = self.client.container_get(until=1000000000)
645 datestring = unicode(r.headers['x-account-until-timestamp'])
646 self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
652 """Check and if un/modified_since"""
653 for format in self.client.DATE_FORMATS:
654 now_formated = self.now_unformated.strftime(format)
655 r1 = self.client.container_get(if_modified_since=now_formated, success=(200, 304, 412))
658 r2 = self.client.container_get(if_unmodified_since=now_formated, success=(200, 304, 412))
661 self.assertNotEqual(sc1, sc2)
663 def test_container_put(self):
664 """Test container_PUT"""
665 self.client.container = self.c2
667 r = self.client.container_put()
668 self.assertEqual(r.status_code, 202)
671 r = self.client.get_container_quota(self.client.container)
672 cquota = r.values()[0]
673 newquota = 2*int(cquota)
675 r = self.client.container_put(quota=newquota)
676 self.assertEqual(r.status_code, 202)
678 r = self.client.get_container_quota(self.client.container)
679 xquota = int(r.values()[0])
680 self.assertEqual(newquota, xquota)
682 r = self.client.container_put(versioning='auto')
683 self.assertEqual(r.status_code, 202)
685 r = self.client.get_container_versioning(self.client.container)
686 nvers = r.values()[0]
687 self.assertEqual('auto', nvers)
689 r = self.client.container_put(versioning='none')
690 self.assertEqual(r.status_code, 202)
692 r = self.client.get_container_versioning(self.client.container)
693 nvers = r.values()[0]
694 self.assertEqual('none', nvers)
696 r = self.client.container_put(metadata={'m1':'v1', 'm2':'v2'})
697 self.assertEqual(r.status_code, 202)
699 r = self.client.get_container_meta(self.client.container)
700 self.assertTrue(r.has_key('x-container-meta-m1'))
701 self.assertEqual(r['x-container-meta-m1'], 'v1')
702 self.assertTrue(r.has_key('x-container-meta-m2'))
703 self.assertEqual(r['x-container-meta-m2'], 'v2')
705 r = self.client.container_put(metadata={'m1':'', 'm2':'v2a'})
706 self.assertEqual(r.status_code, 202)
708 r = self.client.get_container_meta(self.client.container)
709 self.assertTrue(not r.has_key('x-container-meta-m1'))
710 self.assertTrue(r.has_key('x-container-meta-m2'))
711 self.assertEqual(r['x-container-meta-m2'], 'v2a')
713 self.client.del_container_meta(self.client.container)
715 def test_container_post(self):
716 """Test container_POST"""
717 self.client.container = self.c2
720 r = self.client.container_post()
721 self.assertEqual(r.status_code, 202)
725 self.client.set_container_meta({'m1':'v1', 'm2':'v2'})
726 r = self.client.get_container_meta(self.client.container)
727 self.assertTrue(r.has_key('x-container-meta-m1'))
728 self.assertEqual(r['x-container-meta-m1'], 'v1')
729 self.assertTrue(r.has_key('x-container-meta-m2'))
730 self.assertEqual(r['x-container-meta-m2'], 'v2')
733 r = self.client.del_container_meta('m1')
734 r = self.client.set_container_meta({'m2':'v2a'})
735 r = self.client.get_container_meta(self.client.container)
736 self.assertTrue(not r.has_key('x-container-meta-m1'))
737 self.assertTrue(r.has_key('x-container-meta-m2'))
738 self.assertEqual(r['x-container-meta-m2'], 'v2a')
741 r = self.client.get_container_quota(self.client.container)
742 cquota = r.values()[0]
743 newquota = 2*int(cquota)
744 r = self.client.set_container_quota(newquota)
745 r = self.client.get_container_quota(self.client.container)
746 xquota = int(r.values()[0])
747 self.assertEqual(newquota, xquota)
748 r = self.client.set_container_quota(cquota)
749 r = self.client.get_container_quota(self.client.container)
750 xquota = r.values()[0]
751 self.assertEqual(cquota, xquota)
753 """Check versioning"""
754 self.client.set_container_versioning('auto')
755 r = self.client.get_container_versioning(self.client.container)
756 nvers = r.values()[0]
757 self.assertEqual('auto', nvers)
758 self.client.set_container_versioning('none')
759 r = self.client.get_container_versioning(self.client.container)
760 nvers = r.values()[0]
761 self.assertEqual('none', nvers)
763 """put_block uses content_type and content_length to
764 post blocks of data 2 container. All that in upload_object"""
765 """Change a file at fs"""
766 self.create_large_file(1024*1024*100, 'l100M.'+unicode(self.now))
767 """Upload it at a directory in container"""
768 self.client.create_directory('dir')
769 newf = open(self.fname, 'r')
770 self.client.upload_object('/dir/sample.file', newf)
772 """Check if file has been uploaded"""
773 r = self.client.get_object_info('/dir/sample.file')
774 self.assertTrue(int(r['content-length']) > 100000000)
776 """WTF is tranfer_encoding? What should I check about th** s**t? """
779 """Check update=False"""
780 r = self.client.object_post('test', update=False, metadata={'newmeta':'newval'})
782 r = self.client.get_object_info('test')
783 self.assertTrue(r.has_key('x-object-meta-newmeta'))
784 self.assertFalse(r.has_key('x-object-meta-incontainer'))
786 r = self.client.del_container_meta('m2')
788 def test_container_delete(self):
789 """Test container_DELETE"""
791 """Fail to delete a non-empty container"""
792 self.client.container = self.c2
793 r = self.client.container_delete(success=409)
794 self.assertEqual(r.status_code, 409)
797 """Fail to delete c3 (empty) container"""
798 self.client.container = self.c3
799 r = self.client.container_delete(until='1000000000')
800 self.assertEqual(r.status_code, 204)
803 """Delete c3 (empty) container"""
804 r = self.client.container_delete()
805 self.assertEqual(r.status_code, 204)
807 """Purge container(empty a container), check versionlist"""
808 self.client.container = self.c1
809 r = self.client.object_head('test', success=(200, 404))
810 self.assertEqual(r.status_code, 200)
811 self.client.del_container(delimiter='/')
812 r = self.client.object_head('test', success=(200, 404))
813 self.assertEqual(r.status_code, 404)
814 r = self.client.get_object_versionlist('test')
815 self.assertTrue(len(r) > 0)
816 self.assertTrue(len(r[0])>1)
817 self.client.purge_container()
818 self.assertRaises(ClientError, self.client.get_object_versionlist, 'test')
820 def test_object_head(self):
821 """Test object_HEAD"""
822 self.client.container = self.c2
825 r = self.client.object_head(obj)
826 self.assertEqual(r.status_code, 200)
827 etag = r.headers['etag']
830 r = self.client.object_head(obj, version=40)
831 self.assertEqual(r.headers['x-object-version'], '40')
834 r = self.client.object_head(obj, if_etag_match=etag)
835 self.assertEqual(r.status_code, 200)
837 r = self.client.object_head(obj, if_etag_not_match=etag, success=(200, 412, 304))
838 self.assertNotEqual(r.status_code, 200)
841 r = self.client.object_head(obj, version=40, if_etag_match=etag, success=412)
842 self.assertEqual(r.status_code, 412)
845 """Check and if(un)modified_since"""
846 for format in self.client.DATE_FORMATS:
847 now_formated = self.now_unformated.strftime(format)
848 r1 = self.client.object_head(obj, if_modified_since=now_formated,
849 success=(200, 304, 412))
852 r2 = self.client.object_head(obj, if_unmodified_since=now_formated,
853 success=(200, 304, 412))
856 self.assertNotEqual(sc1, sc2)
858 def test_object_get(self):
859 """Test object_GET"""
860 self.client.container = self.c1
863 r = self.client.object_get(obj)
864 self.assertEqual(r.status_code, 200)
866 osize = int(r.headers['content-length'])
867 etag = r.headers['etag']
870 r = self.client.object_get(obj, hashmap=True)
871 self.assertTrue(r.json.has_key('hashes') \
872 and r.json.has_key('block_hash') \
873 and r.json.has_key('block_size') \
874 and r.json.has_key('bytes'))
877 r = self.client.object_get(obj, format='xml', hashmap=True)
878 self.assertEqual(len(r.text.split('hash>')), 3)
881 rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
882 r = self.client.object_get(obj, data_range=rangestr, success=(200, 206))
883 partsize = int(r.headers['content-length'])
884 self.assertTrue(0 < partsize and partsize <= 1+osize/3)
887 rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
888 r = self.client.object_get(obj, data_range=rangestr, if_range=True, success=(200, 206))
889 partsize = int(r.headers['content-length'])
890 self.assertTrue(0 < partsize and partsize <= 1+osize/3)
893 r = self.client.object_get(obj, if_etag_match=etag)
894 self.assertEqual(r.status_code, 200)
897 r = self.client.object_get(obj, if_etag_not_match=etag+'LALALA')
898 self.assertEqual(r.status_code, 200)
901 """Check and if(un)modified_since"""
902 for format in self.client.DATE_FORMATS:
903 now_formated = self.now_unformated.strftime(format)
904 r1 = self.client.object_get(obj, if_modified_since=now_formated,
905 success=(200, 304, 412))
908 r2 = self.client.object_get(obj, if_unmodified_since=now_formated, success=(200, 304, 412))
911 self.assertNotEqual(sc1, sc2)
913 def test_object_put(self):
914 """Test object_PUT"""
916 self.client.container = self.c2
919 """create the object"""
920 r = self.client.object_put(obj, data='a', content_type='application/octer-stream',
921 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']},
922 metadata={'key1':'val1', 'key2':'val2'}, content_encoding='UTF-8',
923 content_disposition='attachment; filename="fname.ext"')
924 self.assertEqual(r.status_code, 201)
925 etag = r.headers['etag']
927 """Check content-disposition"""
928 r = self.client.get_object_info(obj)
929 self.assertTrue(r.has_key('content-disposition'))
931 """Check permitions"""
932 r = self.client.get_object_sharing(obj)
933 self.assertTrue('accx:groupa' in r['read'])
934 self.assertTrue('u1' in r['read'])
935 self.assertTrue('u2' in r['write'])
936 self.assertTrue('u3' in r['write'])
939 r = self.client.get_object_meta(obj)
940 self.assertEqual(r['x-object-meta-key1'], 'val1')
941 self.assertEqual(r['x-object-meta-key2'], 'val2')
943 """Check public and if_etag_match"""
944 r = self.client.object_put(obj, if_etag_match=etag, data='b',
945 content_type='application/octet-stream', public=True)
947 r = self.client.object_get(obj)
948 self.assertTrue(r.headers.has_key('x-object-public'))
949 vers2 = int(r.headers['x-object-version'])
950 etag = r.headers['etag']
951 self.assertEqual(r.text, 'b')
953 """Check if_etag_not_match"""
954 r = self.client.object_put(obj, if_etag_not_match=etag, data='c',
955 content_type='application/octet-stream', success=(201, 412))
956 self.assertEqual(r.status_code, 412)
959 """Check content_type and content_length"""
960 tmpdir = 'dir'+unicode(self.now)
961 r = self.client.object_put(tmpdir, content_type='application/directory',
964 r = self.client.get_object_info(tmpdir)
965 self.assertEqual(r['content-type'], 'application/directory')
967 """Check copy_from, content_encoding"""
968 r = self.client.object_put('%s/%s'%(tmpdir, obj), format=None,
969 copy_from='/%s/%s'%(self.client.container, obj),
970 content_encoding='application/octet-stream',
971 source_account=self.client.account,
972 content_length=0, success=201)
973 self.assertEqual(r.status_code, 201)
975 """Test copy_object for cross-conctainer copy"""
976 self.client.copy_object(src_container=self.c2, src_object='%s/%s'%(tmpdir, obj),
977 dst_container=self.c1, dst_object=obj)
978 self.client.container = self.c1
979 r1 = self.client.get_object_info(obj)
980 self.client.container = self.c2
981 r2 = self.client.get_object_info('%s/%s'%(tmpdir, obj))
982 self.assertEqual(r1['x-object-hash'],r2['x-object-hash'])
984 """Check cross-container copy_from, content_encoding"""
985 self.client.container = self.c1
986 fromstr = '/'+self.c2+'/'+tmpdir+'/'+obj
987 r = self.client.object_put(obj, format=None, copy_from=fromstr,
988 content_encoding='application/octet-stream',
989 source_account=self.client.account,
990 content_length=0, success=201)
992 self.assertEqual(r.status_code, 201)
993 r = self.client.get_object_info(obj)
994 self.assertEqual(r['etag'], etag)
996 """Check source_account"""
997 self.client.container = self.c2
998 fromstr = '/'+self.c1+'/'+obj
999 r = self.client.object_put(obj+'v2', format=None, move_from=fromstr,
1000 content_encoding='application/octet-stream',
1001 source_account='nonExistendAddress@NeverLand.com',
1002 content_length=0, success=(201, 403))
1003 self.assertEqual(r.status_code, 403)
1005 """Check cross-container move_from"""
1006 self.client.container = self.c1
1007 r1 = self.client.get_object_info(obj)
1008 self.client.container = self.c2
1009 self.client.move_object(src_container=self.c1, src_object=obj, dst_container=self.c2,
1010 dst_object=obj+'v0')
1011 r0 = self.client.get_object_info(obj+'v0')
1012 self.assertEqual(r1['x-object-hash'], r0['x-object-hash'])
1014 """Check move_from"""
1015 r = self.client.object_put(obj+'v1', format=None,
1016 move_from='/'+self.c2+'/'+obj,
1017 source_version = vers2,
1018 content_encoding='application/octet-stream',
1019 content_length=0, success=201)
1021 """Check manifest"""
1022 mobj = 'manifest.test'
1026 r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
1027 content_type='application/octet-stream', content_encoding='application/octet-stream')
1029 r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream',
1030 manifest='%s/%s'%(self.client.container, mobj))
1032 r = self.client.object_get(mobj)
1033 self.assertEqual(r.text, txt)
1035 """Upload a local file with one request"""
1036 self.create_large_file(1024*10, 'l10K.'+unicode(self.now))
1037 newf = open(self.fname, 'r')
1038 self.client.upload_object('sample.file', newf)
1040 """Check if file has been uploaded"""
1041 r = self.client.get_object_info('sample.file')
1042 self.assertEqual(int(r['content-length']), 10260)
1044 """Some problems with transfer-encoding?"""
1046 def test_object_copy(self):
1047 """Test object_COPY"""
1048 self.client.container=self.c2
1051 data= '{"key1":"val1", "key2":"val2"}'
1052 r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
1053 data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1055 'read':['accX:groupA', 'u1', 'u2'],
1056 'write':['u2', 'u3']},
1057 content_disposition='attachment; filename="fname.ext"')
1059 r = self.client.object_copy(obj+'orig',
1060 destination = '/'+self.client.container+'/'+obj,
1061 ignore_content_type=False, content_type='application/json',
1062 metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
1063 permitions={'write':['u5', 'accX:groupB']})
1064 self.assertEqual(r.status_code, 201)
1066 """Check content-disposition"""
1067 r = self.client.get_object_info(obj)
1068 self.assertTrue(r.has_key('content-disposition'))
1070 """Check Metadata"""
1071 r = self.client.get_object_meta(obj)
1072 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1073 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1074 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1076 """Check permitions"""
1077 r = self.client.get_object_sharing(obj)
1078 self.assertFalse(r.has_key('read') or 'u2' in r['write'])
1079 self.assertTrue('accx:groupb' in r['write'])
1081 """Check destination account"""
1082 r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
1083 content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
1085 self.assertEqual(r.status_code, 403)
1088 """Check destination being another container
1089 and also content_type and content encoding"""
1090 r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj),
1091 content_encoding='utf8', content_type='application/json')
1092 self.assertEqual(r.status_code, 201)
1093 self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
1096 """Check ignore_content_type and content_type"""
1097 r = self.client.object_get(obj)
1098 etag = r.headers['etag']
1099 ctype = r.headers['content-type']
1100 self.assertEqual(ctype, 'application/json')
1102 r = self.client.object_copy(obj+'orig',
1103 destination = '/'+self.client.container+'/'+obj+'0',
1104 ignore_content_type=True, content_type='application/json')
1105 self.assertEqual(r.status_code, 201)
1106 self.assertNotEqual(r.headers['content-type'], 'application/json')
1109 """Check if_etag_(not_)match"""
1110 r = self.client.object_copy(obj,
1111 destination='/'+self.client.container+'/'+obj+'1', if_etag_match=etag)
1112 self.assertEqual(r.status_code, 201)
1114 r = self.client.object_copy(obj,
1115 destination='/'+self.client.container+'/'+obj+'2', if_etag_not_match='lalala')
1116 self.assertEqual(r.status_code, 201)
1117 vers2 = r.headers['x-object-version']
1120 """Check source_version, public and format """
1121 r = self.client.object_copy(obj+'2', destination='/'+self.client.container+'/'+obj+'3', source_version=vers2, format='xml', public=True)
1122 self.assertEqual(r.status_code, 201)
1123 self.assertTrue(r.headers['content-type'].index('xml') > 0)
1125 r = self.client.get_object_info(obj+'3')
1126 self.assertTrue(r.has_key('x-object-public'))
1128 def test_object_move(self):
1129 """Test object_MOVE"""
1130 self.client.container= self.c2
1133 data= '{"key1":"val1", "key2":"val2"}'
1134 r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
1135 data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1136 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1138 r = self.client.object_move(obj+'orig', destination = '/'+self.client.container+'/'+obj,
1139 ignore_content_type=False, content_type='application/json',
1140 metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
1141 permitions={'write':['u5', 'accX:groupB']})
1142 self.assertEqual(r.status_code, 201)
1145 """Check Metadata"""
1146 r = self.client.get_object_meta(obj)
1147 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1148 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1149 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1151 """Check permitions"""
1152 r = self.client.get_object_sharing(obj)
1153 self.assertFalse(r.has_key('read'))
1154 self.assertTrue('u5' in r['write'])
1155 self.assertTrue('accx:groupb' in r['write'])
1157 """Check destination account"""
1158 r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
1159 content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
1161 self.assertEqual(r.status_code, 403)
1164 """Check destination being another container and also
1165 content_type, content_disposition and content encoding"""
1166 r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj),
1167 content_encoding='utf8', content_type='application/json',
1168 content_disposition='attachment; filename="fname.ext"')
1169 self.assertEqual(r.status_code, 201)
1170 self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
1171 self.client.container=self.c1
1172 r = self.client.get_object_info(obj)
1173 self.assertTrue(r.has_key('content-disposition') and 'fname.ext' in r['content-disposition'])
1175 ctype = r['content-type']
1176 self.assertEqual(ctype, 'application/json')
1178 """Check ignore_content_type and content_type"""
1179 r = self.client.object_move(obj, destination = '/%s/%s'%(self.c2,obj),
1180 ignore_content_type=True, content_type='application/json')
1181 self.assertEqual(r.status_code, 201)
1182 self.assertNotEqual(r.headers['content-type'], 'application/json')
1185 """Check if_etag_(not_)match"""
1186 self.client.container=self.c2
1187 r = self.client.object_move(obj, destination='/'+self.client.container+'/'+obj+'0',
1189 self.assertEqual(r.status_code, 201)
1191 r = self.client.object_move(obj+'0', destination='/'+self.client.container+'/'+obj+'1',
1192 if_etag_not_match='lalala')
1193 self.assertEqual(r.status_code, 201)
1196 """Check public and format """
1197 r = self.client.object_move(obj+'1', destination='/'+self.client.container+'/'+obj+'2',
1198 format='xml', public=True)
1199 self.assertEqual(r.status_code, 201)
1200 self.assertTrue(r.headers['content-type'].index('xml') > 0)
1202 r = self.client.get_object_info(obj+'2')
1203 self.assertTrue(r.has_key('x-object-public'))
1205 def test_object_post(self):
1206 """Test object_POST"""
1207 self.client.container=self.c2
1209 """create a filesystem file"""
1211 newf = open(self.fname, 'w')
1212 newf.writelines(['ello!\n','This is a test line\n','inside a test file\n'])
1214 """create a file on container"""
1215 r = self.client.object_put(obj, content_type='application/octet-stream',
1216 data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1217 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1220 """Append tests update, content_range, content_type, content_length"""
1221 newf = open(obj, 'r')
1222 self.client.append_object(obj, newf)
1223 r = self.client.object_get(obj)
1224 self.assertTrue(r.text.startswith('Hello!'))
1227 """Overwrite tests update, content_type, content_length, content_range"""
1229 r = self.client.overwrite_object(obj, 0, 10, newf)
1230 r = self.client.object_get(obj)
1231 self.assertTrue(r.text.startswith('ello!'))
1235 """Truncate tests update, content_range, content_type,
1236 object_bytes and source_object"""
1237 r = self.client.truncate_object(obj, 5)
1238 r = self.client.object_get(obj)
1239 self.assertEqual(r.text, 'ello!')
1242 """Check metadata"""
1243 self.client.set_object_meta(obj, {'mkey2':'mval2a', 'mkey3':'mval3'})
1244 r = self.client.get_object_meta(obj)
1245 self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1246 self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1247 self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1248 self.client.del_object_meta('mkey1', obj)
1249 r = self.client.get_object_meta(obj)
1250 self.assertFalse(r.has_key('x-object-meta-mkey1'))
1252 """Check permitions"""
1253 self.client.set_object_sharing(obj,
1254 read_permition=['u4', 'u5'], write_permition=['u4'])
1255 r = self.client.get_object_sharing(obj)
1256 self.assertTrue(r.has_key('read'))
1257 self.assertTrue('u5' in r['read'])
1258 self.assertTrue(r.has_key('write'))
1259 self.assertTrue('u4' in r['write'])
1260 self.client.del_object_sharing(obj)
1261 r = self.client.get_object_sharing(obj)
1262 self.assertTrue(len(r) == 0)
1265 self.client.publish_object(obj)
1266 r = self.client.get_object_info(obj)
1267 self.assertTrue(r.has_key('x-object-public'))
1268 self.client.unpublish_object(obj)
1269 r = self.client.get_object_info(obj)
1270 self.assertFalse(r.has_key('x-object-public'))
1272 """Check if_etag_(not)match"""
1274 #r = self.client.object_post(obj, update=True, public=True,
1275 # if_etag_not_match=etag, success=(412,202,204))
1276 #self.assertEqual(r.status_code, 412)
1278 r = self.client.object_post(obj, update=True, public=True,
1279 if_etag_match=etag, content_encoding='application/json')
1281 r = self.client.get_object_info(obj)
1282 helloVersion = r['x-object-version']
1283 self.assertTrue(r.has_key('x-object-public'))
1284 self.assertEqual(r['content-encoding'], 'application/json')
1286 """Check source_version and source_account and content_disposition"""
1287 r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1288 content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1289 source_account='thisAccountWillNeverExist@adminland.com',
1290 source_version=helloVersion, data='12345', success=(403, 202, 204))
1291 self.assertEqual(r.status_code, 403)
1293 r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1294 content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1295 source_account=self.client.account, source_version=helloVersion, data='12345',
1296 content_disposition='attachment; filename="fname.ext"')
1298 r = self.client.object_get(obj)
1299 self.assertEqual(r.text, 'eello!')
1300 self.assertTrue(r.headers.has_key('content-disposition')
1301 and 'fname.ext' in r.headers['content-disposition'])
1304 """Check manifest"""
1305 mobj = 'manifest.test'
1309 r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
1310 content_encoding='application/octet-stream', content_type='application/octet-stream')
1312 #r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream')
1313 self.client.create_object_by_manifestation(mobj, content_type='application/octet-stream')
1315 r = self.client.object_post(mobj, manifest='%s/%s'%(self.client.container, mobj))
1317 r = self.client.object_get(mobj)
1318 self.assertEqual(r.text, txt)
1321 """We need to check transfer_encoding """
1323 def test_object_delete(self):
1324 """Test object_DELETE"""
1325 self.client.container=self.c2
1327 """create a file on container"""
1328 r = self.client.object_put(obj, content_type='application/octet-stream',
1329 data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1330 permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1333 """Check with false until"""
1334 r = self.client.object_delete(obj, until=1000000)
1336 r = self.client.object_get(obj, success=(200, 404))
1337 self.assertEqual(r.status_code, 200)
1340 """Check normal case"""
1341 r = self.client.object_delete(obj)
1342 self.assertEqual(r.status_code, 204)
1344 r = self.client.object_get(obj, success=(200, 404))
1345 self.assertEqual(r.status_code, 404)
1348 def create_large_file(self, size, name):
1349 """Create a large file at fs"""
1352 random.seed(self.now)
1353 f = open(self.fname, 'w')
1354 sys.stdout.write(' create random file %s of size %s'%(name, size)+' 0%')
1355 for hobyte_id in range(size/8):
1356 sss = 'hobt%s'%random.randint(1000, 9999)
1358 if 0 == (hobyte_id*800)%size:
1360 sys.stdout.write('\b\b')
1361 prs = (hobyte_id*800)//size
1363 sys.stdout.write('\b')
1364 sys.stdout.write('%s'%prs+'%')
1371 parser = ArgumentParser(add_help=False)
1372 parser.add_argument('-h', '--help', dest='help', action='store_true', default=False,
1373 help="Show this help message and exit")
1376 if __name__ == '__main__':
1377 parser = init_parser()
1378 args, argv = parser.parse_known_args()
1380 if len(argv) > 2 or getattr(args,'help') or len(argv) < 1:
1381 raise Exception('\tusage: tests.py <group> [command]')
1382 suiteFew = unittest.TestSuite()
1384 if len(argv) == 0 or argv[0] == 'pithos':
1386 suiteFew.addTest(unittest.makeSuite(testPithos))
1388 suiteFew.addTest(testPithos('test_'+argv[1]))
1389 if len(argv) == 0 or argv[0] == 'cyclades':
1391 #suiteFew.addTest(unittest.makeSuite(testCyclades))
1392 suiteFew.addTest(testCyclades('test_000'))
1394 suiteFew.addTest(testCyclades('test_'+argv[1]))
1396 unittest.TextTestRunner(verbosity = 2).run(suiteFew)