84ff1ebe4fe337d3031ee0d47ff9133c0c2cf6a0
[kamaki] / kamaki / clients / tests.py
1 # Copyright 2011 GRNET S.A. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
5 # conditions are met:
6 #
7 #   1. Redistributions of source code must retain the above
8 #      copyright notice, this list of conditions and the following
9 #      disclaimer.
10 #
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.
15 #
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.
28 #
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.
33
34 import gevent.monkey
35 #Monkey-patch everything for gevent early on
36 gevent.monkey.patch_all()
37
38 from argparse import ArgumentParser
39 import unittest
40 import time, datetime, os, sys
41 from shutil import copyfile
42
43 from kamaki.clients import ClientError
44 from kamaki.clients.pithos import PithosClient as pithos
45 from kamaki.clients.cyclades import CycladesClient as cyclades
46
47 TEST_ALL = False
48
49 class testCyclades(unittest.TestCase):
50     """Set up a Cyclades thorough test"""
51     def setUp(self):
52         """okeanos"""
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'
57
58         """okeanos.io"""
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'
63         self.img_details= {
64             u'status': u'ACTIVE',
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',
68             u'progress': 100,
69             u'id': u'43cc8497-61c3-4c46-ae8d-3e33861f8527',
70             u'metadata': {
71                 u'values': {
72                     u'kernel': u'2.6.32',
73                     u'osfamily': u'linux', 
74                     u'users': u'root', 
75                     u'gui': u'No GUI', 
76                     u'sortorder': u'1', 
77                     u'os': u'debian', 
78                     u'root_partition': 
79                     u'1', u'description': 
80                     u'Debian Squeeze Base System'}
81                 }
82             }
83         flavorid = 1
84
85         self.servers = {}
86         self.now = time.mktime(time.gmtime())
87         self.servname1 = 'serv'+unicode(self.now)
88         self.servname2 = self.servname1+'_v2'
89         self.flavorid = 1
90         #servers have to be created at the begining...
91
92         self.client = cyclades(url, token)
93         pass
94
95     def tearDown(self):
96         """Destoy servers used in testing"""
97         if 0 >= len(self.servers):
98             return
99         there_are_servers_running = True
100         deleted_servers = {}
101         waitime = 0
102         print
103         print('-> Found %s servers to delete'%len(self.servers))
104         while there_are_servers_running:
105             there_are_servers_running = False
106             if waitime > 0:
107                 c = ['|','/','-','\\']
108                 suffix = ''
109                 sys.stdout.write('\t. . . wait %s seconds: '%waitime)
110                 for i in range(4*waitime):
111                     oldlen = len(suffix)
112                     suffix = '%ss %s'%(i/4, c[i%4])
113                     sys.stdout.write(oldlen*'\b'+suffix)
114                     sys.stdout.flush()
115                     time.sleep(0.25)
116                 oldlen = len(': '+suffix)
117                 print(oldlen*'\b'+oldlen*' ')
118                 sys.stdout.flush()
119             waitime += 7
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':
126                         print('\twait...')
127                     else:
128                         print('\tDELETE %s'%server['name'])
129                         self._delete_server(server['id'])
130                         self.servers.pop(server['name'])
131                         deleted_servers[server['name']] = 0
132                         waitime =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']]
137                     if retries > 10:
138                         print('\tretry DELETE %s'%server['name'])
139                         self._delete_server(server['id'])
140                         retries = 0
141                         waitime = 0
142                     else:
143                         print('\tnot deleted yet ...')
144                     deleted_servers[server['name']] = retries + 1
145
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
149         return server
150
151     def _delete_server(self, servid):
152         self.client.delete_server(servid)
153
154     def dont_test(self):
155         global TEST_ALL
156         if TEST_ALL:
157             return True
158         return False
159
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])
165             else:
166                 self.assertEqual(unicode(v), unicode(d2[k]))
167
168
169     def test_000(self):
170         "Prepare a full Cyclades test scenario"
171         global TEST_ALL
172         TEST_ALL = True
173
174         self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
175         self.server2 = self._create_server(self.servname2, self.flavorid, self.img)
176
177         print('testing')
178         sys.stdout.write(' test create server')
179         self._test_create_server()
180         print('...ok')
181
182         sys.stdout.write(' test list servers')
183         self._test_list_servers()
184         print('...ok')
185
186         sys.stdout.write(' test get server details')
187         self._test_get_server_details()
188         print('...ok')
189
190         sys.stdout.write(' test get image details')
191         self._test_get_image_details()
192         print('...ok')
193
194
195     def test_list_servers(self):
196         """Test list servers"""
197         if self.dont_test():
198             return
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()
202
203     def _test_list_servers(self):
204         servers = self.client.list_servers()
205         dservers = self.client.list_servers(detail=True)
206
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))
214
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)
219
220     def test_create_server(self):
221         """Test create_server"""
222         if self.dont_test():
223             return
224         self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
225         self._test_create_server()
226
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")
232
233     def test_get_server_details(self):
234         """Test get_server_details"""
235         if self.dont_test():
236             return
237         self.server1 = self._create_server(self.servname1, self.flavorid, self.img)
238         self._test_get_server_details()
239
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")
246
247     def test_get_image_details(self):
248         """Test get_image_details"""
249         if self.dont_test():
250             return
251         self._test_get_image_details()
252
253     def _test_get_image_details(self):
254         r = self.client.get_image_details(self.img)
255         d = self.img_details
256         self.assert_dicts_are_deeply_equal(r, d)
257
258 class testPithos(unittest.TestCase):
259     """Set up a Pithos+ thorough test"""
260     def setUp(self):
261         """
262         url = 'http://127.0.0.1:8000/v1'
263         token = 'C/yBXmz3XjTFBnujc2biAg=='
264         token = 'ac0yH8cQMEZu3M3Mp1MWGA=='
265         account = 'admin@adminland.com'
266
267         url='https://pithos.okeanos.grnet.gr/v1'
268         token='MI6PT0yrXJ9Ji/x8l9Wmig=='
269         account='saxtouri@gmail.com'
270         """
271
272         url='https://pithos.okeanos.io/v1'
273         token='0TpoyAXqJSPxLdDuZHiLOA=='
274         account='saxtouri@admin.grnet.gr'
275         
276         self.fname = None
277         container=None
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'})
294         
295         self.makeNewObject(self.c1, 'another.test')
296
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})
302         
303
304     def forceDeleteContainer(self, container):
305         self.client.container = container
306         try:
307             r = self.client.list_objects()
308         except ClientError:
309             return
310         for obj in r:
311             name = obj['name']
312             self.client.del_object(name)
313         r = self.client.container_delete()
314         self.container = ''
315         
316
317     def tearDown(self):
318         """Destroy test cases"""
319         if self.fname is not None:
320             try:
321                 os.remove(self.fname)
322             except OSError:
323                 pass
324             self.fname = None
325         self.forceDeleteContainer(self.c1)
326         self.forceDeleteContainer(self.c2)
327         try:
328             self.forceDeleteContainer(self.c3)
329         except ClientError:
330             pass
331         self.client.container=''
332
333     def test_000(self):
334         """Perform a full Pithos+ kamaki support test"""
335
336     def test_account_head(self):
337         """Test account_HEAD"""
338         r = self.client.account_head()
339         self.assertEqual(r.status_code, 204)
340         
341         r = self.client.account_head(until='1000000000')
342         self.assertEqual(r.status_code, 204)
343        
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)
347
348         r = self.client.get_account_quota()
349         self.assertTrue(r.has_key('x-account-policy-quota'))
350
351         r = self.client.get_account_versioning()
352         self.assertTrue(r.has_key('x-account-policy-versioning'))
353
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))
358             sc1 = r1.status_code
359             r1.release()
360             r2 = self.client.account_head(if_unmodified_since=now_formated, success=(204, 304, 412))
361             sc2 = r2.status_code
362             r2.release()
363             self.assertNotEqual(sc1, sc2)
364
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()
370         fullLen = len(r)
371         self.assertTrue(fullLen > 2)
372         
373         r = self.client.account_get(limit=1)
374         self.assertEqual(len(r.json), 1)
375         
376
377         r = self.client.account_get(marker='c2_')
378         temp_c0 = r.json[0]['name']
379         temp_c2 = r.json[2]['name']
380         
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)
386         
387
388         r = self.client.account_get(show_only_shared=True)
389         self.assertTrue(self.c1 in [c['name'] for c in r.json])
390         
391         r = self.client.account_get(until=1342609206)
392         self.assertTrue(len(r.json) <= fullLen)
393         
394
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))
399             sc1 = r1.status_code
400             r1.release()
401             r2 = self.client.account_get(if_unmodified_since=now_formated, success=(200, 304, 412))
402             sc2 = r2.status_code
403             r2.release()
404             self.assertNotEqual(sc1, sc2)
405
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)
411         
412
413         """Method set/del_account_meta and set_account_groupcall use account_post internally
414         """
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))
421
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')
427
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'))
431
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'))
435
436         """Missing testing for quota, versioning, because normally
437         you don't have permitions to modify those at account level
438         """
439
440         newquota=1000000
441         self.client.set_account_quota(newquota)
442         #r = self.client.get_account_info()
443         #print(unicode(r))
444         #r = self.client.get_account_quota()
445         #self.assertEqual(r['x-account-policy-quota'], newquota)
446         self.client.set_account_versioning('auto')
447
448     def test_container_head(self):
449         """Test container_HEAD"""
450         self.client.container = self.c1
451
452         r = self.client.container_head()
453         self.assertEqual(r.status_code, 204)
454         
455         """Check until"""
456         r = self.client.container_head(until=1000000, success=(204, 404))
457         self.assertEqual(r.status_code, 404)
458         
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))
463             sc1=r1.status_code
464             r1.release()
465             r2 = self.client.container_head(if_unmodified_since=now_formated, success=(204, 304, 412))
466             sc2=r2.status_code
467             r2.release()
468             self.assertNotEqual(sc1, sc2)
469
470         """Check container object meta"""
471         r = self.client.get_container_object_meta()
472         self.assertEqual(r['x-container-object-meta'], 'Incontainer')
473
474     def test_container_get(self):
475         """Test container_GET"""
476         self.client.container = self.c1
477
478         r = self.client.container_get()
479         self.assertEqual(r.status_code, 200)
480         fullLen = len(r.json)
481         
482
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))
487         
488
489         r = self.client.container_get(limit=1)
490         self.assertEqual(len(r.json), 1)
491         
492
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))
497         
498
499         r = self.client.container_get(prefix='another.test', delimiter='.')
500         self.assertTrue(fullLen > len(r.json))
501         
502
503         r = self.client.container_get(path='/')
504         self.assertEqual(fullLen, len(r.json))
505         
506
507         r = self.client.container_get(format='xml')
508         self.assertEqual(r.text.split()[4], 'name="'+self.c1+'">')
509         
510
511         r = self.client.container_get(meta=['incontainer'])
512         self.assertTrue(len(r.json) > 0)
513         
514
515         r = self.client.container_get(show_only_shared=True)
516         self.assertTrue(len(r.json) < fullLen)
517         
518
519         try:
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)
523             
524         except ClientError:
525             
526             pass
527
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))
532             sc1 = r1.status_code
533             r1.release()
534             r2 = self.client.container_get(if_unmodified_since=now_formated, success=(200, 304, 412))
535             sc2 = r2.status_code
536             r2.release()
537             self.assertNotEqual(sc1, sc2)
538        
539     def test_container_put(self):
540         """Test container_PUT"""
541         self.client.container = self.c2
542
543         r = self.client.container_put()
544         self.assertEqual(r.status_code, 202)
545         
546
547         r = self.client.get_container_quota(self.client.container)
548         cquota = r.values()[0]
549         newquota = 2*int(cquota)
550
551         r = self.client.container_put(quota=newquota)
552         self.assertEqual(r.status_code, 202)
553         
554         r = self.client.get_container_quota(self.client.container)
555         xquota = int(r.values()[0])
556         self.assertEqual(newquota, xquota)
557
558         r = self.client.container_put(versioning='auto')
559         self.assertEqual(r.status_code, 202)
560         
561         r = self.client.get_container_versioning(self.client.container)
562         nvers = r.values()[0]
563         self.assertEqual('auto', nvers)
564
565         r = self.client.container_put(versioning='none')
566         self.assertEqual(r.status_code, 202)
567         
568         r = self.client.get_container_versioning(self.client.container)
569         nvers = r.values()[0]
570         self.assertEqual('none', nvers)
571
572         r = self.client.container_put(metadata={'m1':'v1', 'm2':'v2'})
573         self.assertEqual(r.status_code, 202)
574         
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')
580
581         r = self.client.container_put(metadata={'m1':'', 'm2':'v2a'})
582         self.assertEqual(r.status_code, 202)
583         
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')
588        
589         self.client.del_container_meta(self.client.container)
590
591     def test_container_post(self):
592         """Test container_POST"""
593         self.client.container = self.c2
594
595         """Simple post"""
596         r = self.client.container_post()
597         self.assertEqual(r.status_code, 202)
598         
599
600         """post meta"""
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')
607
608         """post/2del meta"""
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')
615
616         """check quota"""
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)
628
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)
638
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)
647         newf.close()
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)
651
652         """WTF is tranfer_encoding? What should I check about th** s**t? """
653         #TODO
654
655         """Check update=False"""
656         r = self.client.object_post('test', update=False, metadata={'newmeta':'newval'})
657         
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'))
661
662         r = self.client.del_container_meta('m2')
663
664     def test_container_delete(self):
665         """Test container_DELETE"""
666
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)
671         
672
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)
677         
678
679         """Delete c3 (empty) container"""
680         r = self.client.container_delete()
681         self.assertEqual(r.status_code, 204)
682
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')
695
696     def test_object_head(self):
697         """Test object_HEAD"""
698         self.client.container = self.c2
699         obj = 'test'
700
701         r = self.client.object_head(obj)
702         self.assertEqual(r.status_code, 200)
703         etag = r.headers['etag']
704         
705
706         r = self.client.object_head(obj, version=40)
707         self.assertEqual(r.headers['x-object-version'], '40')
708         
709
710         r = self.client.object_head(obj, if_etag_match=etag)
711         self.assertEqual(r.status_code, 200)
712         
713         r = self.client.object_head(obj, if_etag_not_match=etag, success=(200, 412, 304))
714         self.assertNotEqual(r.status_code, 200)
715         
716
717         r = self.client.object_head(obj, version=40, if_etag_match=etag, success=412)
718         self.assertEqual(r.status_code, 412)
719         
720
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))
726             sc1 = r1.status_code
727             r1.release()
728             r2 = self.client.object_head(obj, if_unmodified_since=now_formated,
729                 success=(200, 304, 412))
730             sc2 = r2.status_code
731             r2.release()
732             self.assertNotEqual(sc1, sc2)
733
734     def test_object_get(self):
735         """Test object_GET"""
736         self.client.container = self.c1
737         obj = 'test'
738
739         r = self.client.object_get(obj)
740         self.assertEqual(r.status_code, 200)
741
742         osize = int(r.headers['content-length'])
743         etag = r.headers['etag']
744         
745
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'))
751         
752
753         r = self.client.object_get(obj, format='xml', hashmap=True)
754         self.assertEqual(len(r.text.split('hash>')), 3)
755         
756
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)
761         
762
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)
767         
768
769         r = self.client.object_get(obj, if_etag_match=etag)
770         self.assertEqual(r.status_code, 200)
771         
772
773         r = self.client.object_get(obj, if_etag_not_match=etag+'LALALA')
774         self.assertEqual(r.status_code, 200)
775         
776
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))
782             sc1 = r1.status_code
783             r1.release()
784             r2 = self.client.object_get(obj, if_unmodified_since=now_formated, success=(200, 304, 412))
785             sc2 = r2.status_code
786             r2.release()
787             self.assertNotEqual(sc1, sc2)
788
789     def test_object_put(self):
790         """Test object_PUT"""
791
792         self.client.container = self.c2
793         obj='another.test'
794
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']
802         
803         """Check content-disposition"""
804         r = self.client.get_object_info(obj)
805         self.assertTrue(r.has_key('content-disposition'))
806
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'])
813
814         """Check metadata"""
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')
818
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)
822         
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')
828         
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)
833         
834
835         """Check content_type and content_length"""
836         tmpdir = 'dir'+unicode(self.now)
837         r = self.client.object_put(tmpdir, content_type='application/directory',
838             content_length=0)
839         
840         r = self.client.get_object_info(tmpdir)
841         self.assertEqual(r['content-type'], 'application/directory')
842
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)
850         
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)
858         
859         self.assertEqual(r.status_code, 201)
860         r = self.client.get_object_info(obj)
861         self.assertEqual(r['etag'], etag)
862
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)
871         
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)
878         
879         r = self.client.get_object_info(obj+'v0')
880         self.assertEqual(r['etag'], etag)
881
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)
888         
889         """Check manifest"""
890         mobj = 'manifest.test'
891         txt = ''
892         for i in range(10):
893             txt += '%s'%i
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')
896             
897         r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream',
898             manifest='%s/%s'%(self.client.container, mobj))
899         
900         r = self.client.object_get(mobj)
901         self.assertEqual(r.text, txt)
902        
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)
907         newf.close()
908         """Check if file has been uploaded"""
909         r = self.client.get_object_info('sample.file')
910         self.assertEqual(int(r['content-length']), 10260)
911
912         """Some problems with transfer-encoding?"""
913
914     def test_object_copy(self):
915         """Test object_COPY"""
916         self.client.container=self.c2
917         obj = 'test2'
918
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'},
922             permitions={
923                 'read':['accX:groupA', 'u1', 'u2'],
924                 'write':['u2', 'u3']},
925             content_disposition='attachment; filename="fname.ext"')
926         
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)
933         
934         """Check content-disposition"""
935         r = self.client.get_object_info(obj)
936         self.assertTrue(r.has_key('content-disposition'))
937
938         """Check Metadata"""
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')
943
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'])
948
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',
952             success=(201, 403))
953         self.assertEqual(r.status_code, 403)
954         
955
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')
962         
963
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')
969         
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')
975         
976
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)
981         
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']
986         
987
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)
992         
993         r = self.client.get_object_info(obj+'3')
994         self.assertTrue(r.has_key('x-object-public'))
995
996     def test_object_move(self):
997         """Test object_MOVE"""
998         self.client.container= self.c2
999         obj = 'test2'
1000
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']})
1005         
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)
1011         
1012
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')
1018
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'])
1024
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',
1028             success=(201, 403))
1029         self.assertEqual(r.status_code, 403)
1030         
1031
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'])
1042         etag = r['etag']
1043         ctype = r['content-type']
1044         self.assertEqual(ctype, 'application/json')
1045
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')
1051         
1052
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',
1056             if_etag_match=etag)
1057         self.assertEqual(r.status_code, 201)
1058         
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)
1062         
1063
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)
1069         
1070         r = self.client.get_object_info(obj+'2')
1071         self.assertTrue(r.has_key('x-object-public'))
1072
1073     def test_object_post(self):
1074         """Test object_POST"""
1075         self.client.container=self.c2
1076         obj = 'test2'
1077         """create a filesystem file"""
1078         self.fname = obj
1079         newf = open(self.fname, 'w')
1080         newf.writelines(['ello!\n','This is a test line\n','inside a test file\n'])
1081         newf.close()
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']})
1086         
1087
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!'))
1093         
1094
1095         """Overwrite tests update, content_type, content_length, content_range"""
1096         newf.seek(0)
1097         r = self.client.overwrite_object(obj, 0, 10, newf)
1098         r = self.client.object_get(obj)
1099         self.assertTrue(r.text.startswith('ello!'))
1100         newf.close()
1101         
1102         
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!')
1108         
1109
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'))
1119
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)
1131
1132         """Check publish"""
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'))
1139
1140         """Check if_etag_(not)match"""
1141         etag = r['etag']
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)
1145         
1146         r = self.client.object_post(obj, update=True, public=True,
1147             if_etag_match=etag, content_encoding='application/json')
1148         
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')
1153
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)
1160         
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"')
1165         
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'])
1170         
1171
1172         """Check manifest"""
1173         mobj = 'manifest.test'
1174         txt = ''
1175         for i in range(10):
1176             txt += '%s'%i
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')
1179             
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')
1182         
1183         r = self.client.object_post(mobj, manifest='%s/%s'%(self.client.container, mobj))
1184         
1185         r = self.client.object_get(mobj)
1186         self.assertEqual(r.text, txt)
1187         
1188
1189         """We need to check transfer_encoding """
1190
1191     def test_object_delete(self):
1192         """Test object_DELETE"""
1193         self.client.container=self.c2
1194         obj = 'test2'
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']})
1199         
1200
1201         """Check with false until"""
1202         r = self.client.object_delete(obj, until=1000000)
1203         
1204         r = self.client.object_get(obj, success=(200, 404))
1205         self.assertEqual(r.status_code, 200)
1206         
1207
1208         """Check normal case"""
1209         r = self.client.object_delete(obj)
1210         self.assertEqual(r.status_code, 204)
1211         
1212         r = self.client.object_get(obj, success=(200, 404))
1213         self.assertEqual(r.status_code, 404)
1214         
1215
1216     def create_large_file(self, size, name):
1217         """Create a large file at fs"""
1218         self.fname = name
1219         import random
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)
1225             f.write(sss)
1226             if 0 == (hobyte_id*800)%size:
1227                 f.write('\n')
1228                 sys.stdout.write('\b\b')
1229                 prs = (hobyte_id*800)//size
1230                 if prs > 10:
1231                     sys.stdout.write('\b')
1232                 sys.stdout.write('%s'%prs+'%')
1233                 sys.stdout.flush()
1234         print('\b\b\b100%')
1235         f.close()
1236         """"""
1237
1238 def init_parser():
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")
1242     return parser
1243
1244 if __name__ == '__main__':
1245     parser = init_parser()
1246     args, argv = parser.parse_known_args()
1247
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()
1251
1252     if len(argv) == 0 or argv[0] == 'pithos':
1253         if len(argv) == 1:
1254             suiteFew.addTest(unittest.makeSuite(testPithos))
1255         else:
1256             suiteFew.addTest(testPithos('test_'+argv[1]))
1257     if len(argv) == 0 or argv[0] == 'cyclades':
1258         if len(argv) == 1:
1259             #suiteFew.addTest(unittest.makeSuite(testCyclades))
1260             suiteFew.addTest(testCyclades('test_000'))
1261         else:
1262             suiteFew.addTest(testCyclades('test_'+argv[1]))
1263
1264     unittest.TextTestRunner(verbosity = 2).run(suiteFew)