Unitest purge, create_by_manifestation, versionlst
[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         datestring = unicode(r.headers['x-account-until-timestamp'])
345         self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
346
347         """Check if(un)modified_since"""
348         for format in self.client.DATE_FORMATS:
349             now_formated = self.now_unformated.strftime(format)
350             r1 = self.client.account_head(if_modified_since=now_formated, success=(204, 304, 412))
351             sc1 = r1.status_code
352             r1.release()
353             r2 = self.client.account_head(if_unmodified_since=now_formated, success=(204, 304, 412))
354             sc2 = r2.status_code
355             r2.release()
356             self.assertNotEqual(sc1, sc2)
357
358     def test_account_get(self):
359         """Test account_GET"""
360         r = self.client.account_get()
361         self.assertEqual(r.status_code, 200)
362         fullLen = len(r.json)
363         self.assertTrue(fullLen > 2)
364         
365
366         r = self.client.account_get(limit=1)
367         self.assertEqual(len(r.json), 1)
368         
369
370         r = self.client.account_get(marker='c2_')
371         temp_c0 = r.json[0]['name']
372         temp_c2 = r.json[2]['name']
373         
374         r = self.client.account_get(limit=2, marker='c2_')
375         conames = [container['name'] for container in r.json \
376             if container['name'].lower().startswith('c2_')]
377         self.assertTrue(temp_c0 in conames)
378         self.assertFalse(temp_c2 in conames)
379         
380
381         r = self.client.account_get(show_only_shared=True)
382         self.assertTrue(self.c1 in [c['name'] for c in r.json])
383         
384
385         r = self.client.account_get(until=1342609206)
386         self.assertTrue(len(r.json) <= fullLen)
387         
388
389         """Check if(un)modified_since"""
390         for format in self.client.DATE_FORMATS:
391             now_formated = self.now_unformated.strftime(format)
392             r1 = self.client.account_get(if_modified_since=now_formated, success=(200, 304, 412))
393             sc1 = r1.status_code
394             r1.release()
395             r2 = self.client.account_get(if_unmodified_since=now_formated, success=(200, 304, 412))
396             sc2 = r2.status_code
397             r2.release()
398             self.assertNotEqual(sc1, sc2)
399
400     def test_account_post(self):
401         """Test account_POST"""
402         r = self.client.account_post()
403         self.assertEqual(r.status_code, 202)
404         grpName = 'grp'+unicode(self.now)
405         
406
407         """Method set/del_account_meta and set_account_groupcall use account_post internally
408         """
409         self.client.set_account_group(grpName, ['u1', 'u2'])
410         r = self.client.get_account_group()
411         self.assertEqual(r['x-account-group-'+grpName], 'u1,u2')
412         self.client.del_account_group(grpName)
413         r = self.client.get_account_group()
414         self.assertTrue(not r.has_key('x-account-group-'+grpName))
415
416         mprefix = 'meta'+unicode(self.now)
417         self.client.set_account_meta({mprefix+'1':'v1', mprefix+'2':'v2'})
418         r = self.client.get_account_meta()
419         self.assertEqual(r['x-account-meta-'+mprefix+'1'], 'v1')
420         self.assertEqual(r['x-account-meta-'+mprefix+'2'], 'v2')
421
422         self.client.del_account_meta(mprefix+'1')
423         r = self.client.get_account_meta()
424         self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'1'))
425
426         self.client.del_account_meta(mprefix+'2')
427         r = self.client.get_account_meta()
428         self.assertTrue(not r.has_key('x-account-meta-'+mprefix+'2'))
429
430         """Missing testing for quota, versioning, because normally
431         you don't have permitions to modify those at account level
432         """
433
434     def test_container_head(self):
435         """Test container_HEAD"""
436         self.client.container = self.c1
437
438         r = self.client.container_head()
439         self.assertEqual(r.status_code, 204)
440         
441
442         """Check until"""
443         r = self.client.container_head(until=1000000, success=(204, 404))
444         self.assertEqual(r.status_code, 404)
445         
446
447         """Check and if(un)modified_since"""
448         for format in self.client.DATE_FORMATS:
449             now_formated = self.now_unformated.strftime(format)
450             r1 = self.client.container_head(if_modified_since=now_formated, success=(204, 304, 412))
451             sc1=r1.status_code
452             r1.release()
453             r2 = self.client.container_head(if_unmodified_since=now_formated, success=(204, 304, 412))
454             sc2=r2.status_code
455             r2.release()
456             self.assertNotEqual(sc1, sc2)
457
458     def test_container_get(self):
459         """Test container_GET"""
460         self.client.container = self.c1
461
462         r = self.client.container_get()
463         self.assertEqual(r.status_code, 200)
464         fullLen = len(r.json)
465         
466
467         r = self.client.container_get(prefix='test')
468         lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
469         self.assertTrue(len(r.json) > 1)
470         self.assertEqual(len(r.json), len(lalobjects))
471         
472
473         r = self.client.container_get(limit=1)
474         self.assertEqual(len(r.json), 1)
475         
476
477         r = self.client.container_get(marker='another')
478         self.assertTrue(len(r.json) > 1)
479         neobjects = [obj for obj in r.json if obj['name'] > 'another']
480         self.assertEqual(len(r.json), len(neobjects))
481         
482
483         r = self.client.container_get(prefix='another.test', delimiter='.')
484         self.assertTrue(fullLen > len(r.json))
485         
486
487         r = self.client.container_get(path='/')
488         self.assertEqual(fullLen, len(r.json))
489         
490
491         r = self.client.container_get(format='xml')
492         self.assertEqual(r.text.split()[4], 'name="'+self.c1+'">')
493         
494
495         r = self.client.container_get(meta=['incontainer'])
496         self.assertTrue(len(r.json) > 0)
497         
498
499         r = self.client.container_get(show_only_shared=True)
500         self.assertTrue(len(r.json) < fullLen)
501         
502
503         try:
504             r = self.client.container_get(until=1000000000)
505             datestring = unicode(r.headers['x-account-until-timestamp'])
506             self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
507             
508         except ClientError:
509             
510             pass
511
512         """Check and if un/modified_since"""
513         for format in self.client.DATE_FORMATS:
514             now_formated = self.now_unformated.strftime(format)
515             r1 = self.client.container_get(if_modified_since=now_formated, success=(200, 304, 412))
516             sc1 = r1.status_code
517             r1.release()
518             r2 = self.client.container_get(if_unmodified_since=now_formated, success=(200, 304, 412))
519             sc2 = r2.status_code
520             r2.release()
521             self.assertNotEqual(sc1, sc2)
522        
523     def test_container_put(self):
524         """Test container_PUT"""
525         self.client.container = self.c2
526
527         r = self.client.container_put()
528         self.assertEqual(r.status_code, 202)
529         
530
531         r = self.client.get_container_quota(self.client.container)
532         cquota = r.values()[0]
533         newquota = 2*int(cquota)
534
535         r = self.client.container_put(quota=newquota)
536         self.assertEqual(r.status_code, 202)
537         
538         r = self.client.get_container_quota(self.client.container)
539         xquota = int(r.values()[0])
540         self.assertEqual(newquota, xquota)
541
542         r = self.client.container_put(versioning='auto')
543         self.assertEqual(r.status_code, 202)
544         
545         r = self.client.get_container_versioning(self.client.container)
546         nvers = r.values()[0]
547         self.assertEqual('auto', nvers)
548
549         r = self.client.container_put(versioning='none')
550         self.assertEqual(r.status_code, 202)
551         
552         r = self.client.get_container_versioning(self.client.container)
553         nvers = r.values()[0]
554         self.assertEqual('none', nvers)
555
556         r = self.client.container_put(metadata={'m1':'v1', 'm2':'v2'})
557         self.assertEqual(r.status_code, 202)
558         
559         r = self.client.get_container_meta(self.client.container)
560         self.assertTrue(r.has_key('x-container-meta-m1'))
561         self.assertEqual(r['x-container-meta-m1'], 'v1')
562         self.assertTrue(r.has_key('x-container-meta-m2'))
563         self.assertEqual(r['x-container-meta-m2'], 'v2')
564
565         r = self.client.container_put(metadata={'m1':'', 'm2':'v2a'})
566         self.assertEqual(r.status_code, 202)
567         
568         r = self.client.get_container_meta(self.client.container)
569         self.assertTrue(not r.has_key('x-container-meta-m1'))
570         self.assertTrue(r.has_key('x-container-meta-m2'))
571         self.assertEqual(r['x-container-meta-m2'], 'v2a')
572        
573         self.client.del_container_meta(self.client.container)
574
575     def test_container_post(self):
576         """Test container_POST"""
577         self.client.container = self.c2
578
579         """Simple post"""
580         r = self.client.container_post()
581         self.assertEqual(r.status_code, 202)
582         
583
584         """post meta"""
585         self.client.set_container_meta({'m1':'v1', 'm2':'v2'})
586         r = self.client.get_container_meta(self.client.container)
587         self.assertTrue(r.has_key('x-container-meta-m1'))
588         self.assertEqual(r['x-container-meta-m1'], 'v1')
589         self.assertTrue(r.has_key('x-container-meta-m2'))
590         self.assertEqual(r['x-container-meta-m2'], 'v2')
591
592         """post/2del meta"""
593         r = self.client.del_container_meta('m1')
594         r = self.client.set_container_meta({'m2':'v2a'})
595         r = self.client.get_container_meta(self.client.container)
596         self.assertTrue(not r.has_key('x-container-meta-m1'))
597         self.assertTrue(r.has_key('x-container-meta-m2'))
598         self.assertEqual(r['x-container-meta-m2'], 'v2a')
599
600         """check quota"""
601         r = self.client.get_container_quota(self.client.container)
602         cquota = r.values()[0]
603         newquota = 2*int(cquota)
604         r = self.client.set_container_quota(newquota)
605         r = self.client.get_container_quota(self.client.container)
606         xquota = int(r.values()[0])
607         self.assertEqual(newquota, xquota)
608         r = self.client.set_container_quota(cquota)
609         r = self.client.get_container_quota(self.client.container)
610         xquota = r.values()[0]
611         self.assertEqual(cquota, xquota)
612
613         """Check versioning"""
614         self.client.set_container_versioning('auto')
615         r = self.client.get_container_versioning(self.client.container)
616         nvers = r.values()[0]
617         self.assertEqual('auto', nvers)
618         self.client.set_container_versioning('none')
619         r = self.client.get_container_versioning(self.client.container)
620         nvers = r.values()[0]
621         self.assertEqual('none', nvers)
622
623         """put_block uses content_type and content_length to
624         post blocks of data 2 container. All that in upload_object"""
625         """Change a file at fs"""
626         self.create_large_file(1024*1024*100, 'l100M.'+unicode(self.now))
627         """Upload it at a directory in container"""
628         self.client.create_directory('dir')
629         newf = open(self.fname, 'r')
630         self.client.upload_object('/dir/sample.file', newf)
631         newf.close()
632         """Check if file has been uploaded"""
633         r = self.client.get_object_info('/dir/sample.file')
634         self.assertTrue(int(r['content-length']) > 100000000)
635
636         """WTF is tranfer_encoding? What should I check about th** s**t? """
637         #TODO
638
639         """Check update=False"""
640         r = self.client.object_post('test', update=False, metadata={'newmeta':'newval'})
641         
642         r = self.client.get_object_info('test')
643         self.assertTrue(r.has_key('x-object-meta-newmeta'))
644         self.assertFalse(r.has_key('x-object-meta-incontainer'))
645
646         r = self.client.del_container_meta('m2')
647
648     def test_container_delete(self):
649         """Test container_DELETE"""
650
651         """Fail to delete a non-empty container"""
652         self.client.container = self.c2
653         r = self.client.container_delete(success=409)
654         self.assertEqual(r.status_code, 409)
655         
656
657         """Fail to delete c3 (empty) container"""
658         self.client.container = self.c3
659         r = self.client.container_delete(until='1000000000')
660         self.assertEqual(r.status_code, 204)
661         
662
663         """Delete c3 (empty) container"""
664         r = self.client.container_delete()
665         self.assertEqual(r.status_code, 204)
666
667         """Purge container(empty a container), check versionlist"""
668         self.client.container = self.c1
669         r = self.client.object_head('test', success=(200, 404))
670         self.assertEqual(r.status_code, 200)
671         self.client.del_container(delimiter='/')
672         r = self.client.object_head('test', success=(200, 404))
673         self.assertEqual(r.status_code, 404)
674         r = self.client.get_object_versionlist('test')
675         self.assertTrue(len(r) > 0)
676         self.assertTrue(len(r[0])>1)
677         self.client.purge_container()
678         self.assertRaises(ClientError, self.client.get_object_versionlist, 'test')
679
680     def test_object_head(self):
681         """Test object_HEAD"""
682         self.client.container = self.c2
683         obj = 'test'
684
685         r = self.client.object_head(obj)
686         self.assertEqual(r.status_code, 200)
687         etag = r.headers['etag']
688         
689
690         r = self.client.object_head(obj, version=40)
691         self.assertEqual(r.headers['x-object-version'], '40')
692         
693
694         r = self.client.object_head(obj, if_etag_match=etag)
695         self.assertEqual(r.status_code, 200)
696         
697         r = self.client.object_head(obj, if_etag_not_match=etag, success=(200, 412, 304))
698         self.assertNotEqual(r.status_code, 200)
699         
700
701         r = self.client.object_head(obj, version=40, if_etag_match=etag, success=412)
702         self.assertEqual(r.status_code, 412)
703         
704
705         """Check and if(un)modified_since"""
706         for format in self.client.DATE_FORMATS:
707             now_formated = self.now_unformated.strftime(format)
708             r1 = self.client.object_head(obj, if_modified_since=now_formated,
709                 success=(200, 304, 412))
710             sc1 = r1.status_code
711             r1.release()
712             r2 = self.client.object_head(obj, if_unmodified_since=now_formated,
713                 success=(200, 304, 412))
714             sc2 = r2.status_code
715             r2.release()
716             self.assertNotEqual(sc1, sc2)
717
718     def test_object_get(self):
719         """Test object_GET"""
720         self.client.container = self.c1
721         obj = 'test'
722
723         r = self.client.object_get(obj)
724         self.assertEqual(r.status_code, 200)
725
726         osize = int(r.headers['content-length'])
727         etag = r.headers['etag']
728         
729
730         r = self.client.object_get(obj, hashmap=True)
731         self.assertTrue(r.json.has_key('hashes') \
732             and r.json.has_key('block_hash') \
733             and r.json.has_key('block_size') \
734             and r.json.has_key('bytes'))
735         
736
737         r = self.client.object_get(obj, format='xml', hashmap=True)
738         self.assertEqual(len(r.text.split('hash>')), 3)
739         
740
741         rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
742         r = self.client.object_get(obj, data_range=rangestr, success=(200, 206))
743         partsize = int(r.headers['content-length'])
744         self.assertTrue(0 < partsize and partsize <= 1+osize/3)
745         
746
747         rangestr = 'bytes=%s-%s'%(osize/3, osize/2)
748         r = self.client.object_get(obj, data_range=rangestr, if_range=True, success=(200, 206))
749         partsize = int(r.headers['content-length'])
750         self.assertTrue(0 < partsize and partsize <= 1+osize/3)
751         
752
753         r = self.client.object_get(obj, if_etag_match=etag)
754         self.assertEqual(r.status_code, 200)
755         
756
757         r = self.client.object_get(obj, if_etag_not_match=etag+'LALALA')
758         self.assertEqual(r.status_code, 200)
759         
760
761         """Check and if(un)modified_since"""
762         for format in self.client.DATE_FORMATS:
763             now_formated = self.now_unformated.strftime(format)
764             r1 = self.client.object_get(obj, if_modified_since=now_formated,
765                 success=(200, 304, 412))
766             sc1 = r1.status_code
767             r1.release()
768             r2 = self.client.object_get(obj, if_unmodified_since=now_formated, success=(200, 304, 412))
769             sc2 = r2.status_code
770             r2.release()
771             self.assertNotEqual(sc1, sc2)
772
773     def test_object_put(self):
774         """Test object_PUT"""
775
776         self.client.container = self.c2
777         obj='another.test'
778
779         """create the object"""
780         r = self.client.object_put(obj, data='a', content_type='application/octer-stream',
781             permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']},
782             metadata={'key1':'val1', 'key2':'val2'}, content_encoding='UTF-8',
783             content_disposition='attachment; filename="fname.ext"')
784         self.assertEqual(r.status_code, 201)
785         etag = r.headers['etag']
786         
787
788         """Check content-disposition"""
789         r = self.client.get_object_info(obj)
790         self.assertTrue(r.has_key('content-disposition'))
791
792         """Check permitions"""
793         r = self.client.get_object_sharing(obj)
794         self.assertTrue('accx:groupa' in r['read'])
795         self.assertTrue('u1' in r['read'])
796         self.assertTrue('u2' in r['write'])
797         self.assertTrue('u3' in r['write'])
798
799         """Check metadata"""
800         r = self.client.get_object_meta(obj)
801         self.assertEqual(r['x-object-meta-key1'], 'val1')
802         self.assertEqual(r['x-object-meta-key2'], 'val2')
803
804         """Check public and if_etag_match"""
805         r = self.client.object_put(obj, if_etag_match=etag, data='b',
806             content_type='application/octet-stream', public=True)
807         
808         r = self.client.object_get(obj)
809         self.assertTrue(r.headers.has_key('x-object-public'))
810         vers2 = int(r.headers['x-object-version'])
811         etag = r.headers['etag']
812         self.assertEqual(r.text, 'b')
813         
814
815         """Check if_etag_not_match"""
816         r = self.client.object_put(obj, if_etag_not_match=etag, data='c',
817             content_type='application/octet-stream', success=(201, 412))
818         self.assertEqual(r.status_code, 412)
819         
820
821         """Check content_type and content_length"""
822         tmpdir = 'dir'+unicode(self.now)
823         r = self.client.object_put(tmpdir, content_type='application/directory',
824             content_length=0)
825         
826         r = self.client.get_object_info(tmpdir)
827         self.assertEqual(r['content-type'], 'application/directory')
828
829         """Check copy_from, content_encoding"""
830         r = self.client.object_put('%s/%s'%(tmpdir, obj), format=None, 
831             copy_from='/%s/%s'%(self.client.container, obj),
832             content_encoding='application/octet-stream', 
833             source_account=self.client.account,
834             content_length=0, success=201)
835         self.assertEqual(r.status_code, 201)
836         
837
838         """Check cross-container copy_from, content_encoding"""
839         self.client.container = self.c1
840         fromstr = '/'+self.c2+'/'+tmpdir+'/'+obj
841         r = self.client.object_put(obj, format=None, copy_from=fromstr,
842             content_encoding='application/octet-stream', 
843             source_account=self.client.account,
844             content_length=0, success=201)
845         
846         self.assertEqual(r.status_code, 201)
847         r = self.client.get_object_info(obj)
848         self.assertEqual(r['etag'], etag)
849
850         """Check source_account"""
851         self.client.container = self.c2
852         fromstr = '/'+self.c1+'/'+obj
853         r = self.client.object_put(obj+'v2', format=None, move_from=fromstr,
854             content_encoding='application/octet-stream', 
855             source_account='nonExistendAddress@NeverLand.com', 
856             content_length=0, success=(201, 403))
857         self.assertEqual(r.status_code, 403)
858         
859
860         """Check cross-container move_from"""
861         r = self.client.object_put(obj+'v0', format=None, 
862             move_from='/'+self.c1+'/'+obj, 
863             content_encoding='application/octet-stream', 
864             content_length=0, success=201)
865         self.assertEqual(r.status_code, 201)
866         
867         r = self.client.get_object_info(obj+'v0')
868         self.assertEqual(r['etag'], etag)
869
870         """Check move_from"""
871         r = self.client.object_put(obj+'v1', format=None, 
872             move_from='/'+self.c2+'/'+obj,
873             source_version = vers2,
874             content_encoding='application/octet-stream',
875             content_length=0, success=201)
876         
877
878         """Check manifest"""
879         mobj = 'manifest.test'
880         txt = ''
881         for i in range(10):
882             txt += '%s'%i
883             r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
884                 content_type='application/octet-stream', content_encoding='application/octet-stream')
885             
886         r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream',
887             manifest='%s/%s'%(self.client.container, mobj))
888         
889         r = self.client.object_get(mobj)
890         self.assertEqual(r.text, txt)
891         
892
893         """Some problems with transfer-encoding?"""
894
895     def test_object_copy(self):
896         """Test object_COPY"""
897         self.client.container=self.c2
898         obj = 'test2'
899
900         data= '{"key1":"val1", "key2":"val2"}'
901         r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
902             data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
903             permitions={
904                 'read':['accX:groupA', 'u1', 'u2'],
905                 'write':['u2', 'u3']},
906             content_disposition='attachment; filename="fname.ext"')
907         
908         r = self.client.object_copy(obj+'orig',
909             destination = '/'+self.client.container+'/'+obj,
910             ignore_content_type=False, content_type='application/json', 
911             metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
912             permitions={'write':['u5', 'accX:groupB']})
913         self.assertEqual(r.status_code, 201)
914         
915
916         """Check content-disposition"""
917         r = self.client.get_object_info(obj)
918         self.assertTrue(r.has_key('content-disposition'))
919
920         """Check Metadata"""
921         r = self.client.get_object_meta(obj)
922         self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
923         self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
924         self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
925
926         """Check permitions"""
927         r = self.client.get_object_sharing(obj)
928         self.assertFalse(r.has_key('read') or 'u2' in r['write'])
929         self.assertTrue('accx:groupb' in r['write'])
930
931         """Check destination account"""
932         r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
933             content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
934             success=(201, 403))
935         self.assertEqual(r.status_code, 403)
936         
937
938         """Check destination being another container
939         and also content_type and content encoding"""
940         r = self.client.object_copy(obj, destination='/%s/%s'%(self.c1,obj),
941             content_encoding='utf8', content_type='application/json')
942         self.assertEqual(r.status_code, 201)
943         self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
944         
945
946         """Check ignore_content_type and content_type"""
947         r = self.client.object_get(obj)
948         etag = r.headers['etag']
949         ctype = r.headers['content-type']
950         self.assertEqual(ctype, 'application/json')
951         
952         r = self.client.object_copy(obj+'orig',
953             destination = '/'+self.client.container+'/'+obj+'0',
954             ignore_content_type=True, content_type='application/json')
955         self.assertEqual(r.status_code, 201)
956         self.assertNotEqual(r.headers['content-type'], 'application/json')
957         
958
959         """Check if_etag_(not_)match"""
960         r = self.client.object_copy(obj,
961             destination='/'+self.client.container+'/'+obj+'1', if_etag_match=etag)
962         self.assertEqual(r.status_code, 201)
963         
964         r = self.client.object_copy(obj,
965             destination='/'+self.client.container+'/'+obj+'2', if_etag_not_match='lalala')
966         self.assertEqual(r.status_code, 201)
967         vers2 = r.headers['x-object-version']
968         
969
970         """Check source_version, public and format """
971         r = self.client.object_copy(obj+'2', destination='/'+self.client.container+'/'+obj+'3', source_version=vers2, format='xml', public=True)
972         self.assertEqual(r.status_code, 201)
973         self.assertTrue(r.headers['content-type'].index('xml') > 0)
974         
975         r = self.client.get_object_info(obj+'3')
976         self.assertTrue(r.has_key('x-object-public'))
977
978     def test_object_move(self):
979         """Test object_MOVE"""
980         self.client.container= self.c2
981         obj = 'test2'
982
983         data= '{"key1":"val1", "key2":"val2"}'
984         r = self.client.object_put(obj+'orig', content_type='application/octet-stream',
985             data= data, metadata={'mkey1':'mval1', 'mkey2':'mval2'},
986             permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
987         
988         r = self.client.object_move(obj+'orig', destination = '/'+self.client.container+'/'+obj,
989             ignore_content_type=False, content_type='application/json', 
990             metadata={'mkey2':'mval2a', 'mkey3':'mval3'},
991             permitions={'write':['u5', 'accX:groupB']})
992         self.assertEqual(r.status_code, 201)
993         
994
995         """Check Metadata"""
996         r = self.client.get_object_meta(obj)
997         self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
998         self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
999         self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1000
1001         """Check permitions"""
1002         r = self.client.get_object_sharing(obj)
1003         self.assertFalse(r.has_key('read'))
1004         self.assertTrue('u5' in r['write'])
1005         self.assertTrue('accx:groupb' in r['write'])
1006
1007         """Check destination account"""
1008         r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj), content_encoding='utf8',
1009             content_type='application/json', destination_account='nonExistendAddress@NeverLand.com',
1010             success=(201, 403))
1011         self.assertEqual(r.status_code, 403)
1012         
1013
1014         """Check destination being another container and also
1015         content_type, content_disposition and content encoding"""
1016         r = self.client.object_move(obj, destination='/%s/%s'%(self.c1,obj),
1017             content_encoding='utf8', content_type='application/json',
1018             content_disposition='attachment; filename="fname.ext"')
1019         self.assertEqual(r.status_code, 201)
1020         self.assertEqual(r.headers['content-type'], 'application/json; charset=UTF-8')
1021         self.client.container=self.c1
1022         r = self.client.get_object_info(obj)
1023         self.assertTrue(r.has_key('content-disposition') and 'fname.ext' in r['content-disposition'])
1024         etag = r['etag']
1025         ctype = r['content-type']
1026         self.assertEqual(ctype, 'application/json')
1027
1028         """Check ignore_content_type and content_type"""
1029         r = self.client.object_move(obj, destination = '/%s/%s'%(self.c2,obj),
1030             ignore_content_type=True, content_type='application/json')
1031         self.assertEqual(r.status_code, 201)
1032         self.assertNotEqual(r.headers['content-type'], 'application/json')
1033         
1034
1035         """Check if_etag_(not_)match"""
1036         self.client.container=self.c2
1037         r = self.client.object_move(obj, destination='/'+self.client.container+'/'+obj+'0',
1038             if_etag_match=etag)
1039         self.assertEqual(r.status_code, 201)
1040         
1041         r = self.client.object_move(obj+'0', destination='/'+self.client.container+'/'+obj+'1',
1042             if_etag_not_match='lalala')
1043         self.assertEqual(r.status_code, 201)
1044         
1045
1046         """Check public and format """
1047         r = self.client.object_move(obj+'1', destination='/'+self.client.container+'/'+obj+'2',
1048             format='xml', public=True)
1049         self.assertEqual(r.status_code, 201)
1050         self.assertTrue(r.headers['content-type'].index('xml') > 0)
1051         
1052         r = self.client.get_object_info(obj+'2')
1053         self.assertTrue(r.has_key('x-object-public'))
1054
1055     def test_object_post(self):
1056         """Test object_POST"""
1057         self.client.container=self.c2
1058         obj = 'test2'
1059         """create a filesystem file"""
1060         self.fname = obj
1061         newf = open(self.fname, 'w')
1062         newf.writelines(['ello!\n','This is a test line\n','inside a test file\n'])
1063         newf.close()
1064         """create a file on container"""
1065         r = self.client.object_put(obj, content_type='application/octet-stream',
1066             data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1067             permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1068         
1069
1070         """Append tests update, content_range, content_type, content_length"""
1071         newf = open(obj, 'r')
1072         self.client.append_object(obj, newf)
1073         r = self.client.object_get(obj)
1074         self.assertTrue(r.text.startswith('Hello!'))
1075         
1076
1077         """Overwrite tests update, content_type, content_length, content_range"""
1078         newf.seek(0)
1079         r = self.client.overwrite_object(obj, 0, 10, newf)
1080         r = self.client.object_get(obj)
1081         self.assertTrue(r.text.startswith('ello!'))
1082         newf.close()
1083         
1084         
1085         """Truncate tests update, content_range, content_type,
1086         object_bytes and source_object"""
1087         r = self.client.truncate_object(obj, 5)
1088         r = self.client.object_get(obj)
1089         self.assertEqual(r.text, 'ello!')
1090         
1091
1092         """Check metadata"""
1093         self.client.set_object_meta(obj, {'mkey2':'mval2a', 'mkey3':'mval3'})
1094         r = self.client.get_object_meta(obj)
1095         self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1096         self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1097         self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1098         self.client.del_object_meta('mkey1', obj)
1099         r = self.client.get_object_meta(obj)
1100         self.assertFalse(r.has_key('x-object-meta-mkey1'))
1101
1102         """Check permitions"""
1103         self.client.set_object_sharing(obj,
1104             read_permition=['u4', 'u5'], write_permition=['u4'])
1105         r = self.client.get_object_sharing(obj)
1106         self.assertTrue(r.has_key('read'))
1107         self.assertTrue('u5' in r['read'])
1108         self.assertTrue(r.has_key('write'))
1109         self.assertTrue('u4' in r['write'])
1110         self.client.del_object_sharing(obj)
1111         r = self.client.get_object_sharing(obj)
1112         self.assertTrue(len(r) == 0)
1113
1114         """Check publish"""
1115         self.client.publish_object(obj)
1116         r = self.client.get_object_info(obj)
1117         self.assertTrue(r.has_key('x-object-public'))
1118         self.client.unpublish_object(obj)
1119         r = self.client.get_object_info(obj)
1120         self.assertFalse(r.has_key('x-object-public'))
1121
1122         """Check if_etag_(not)match"""
1123         etag = r['etag']
1124         #r = self.client.object_post(obj, update=True, public=True,
1125         #    if_etag_not_match=etag, success=(412,202,204))
1126         #self.assertEqual(r.status_code, 412)
1127         
1128         r = self.client.object_post(obj, update=True, public=True,
1129             if_etag_match=etag, content_encoding='application/json')
1130         
1131         r = self.client.get_object_info(obj)
1132         helloVersion = r['x-object-version']
1133         self.assertTrue(r.has_key('x-object-public'))
1134         self.assertEqual(r['content-encoding'], 'application/json')
1135
1136         """Check source_version and source_account and content_disposition"""
1137         r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1138             content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1139             source_account='thisAccountWillNeverExist@adminland.com',
1140             source_version=helloVersion, data='12345', success=(403, 202, 204))
1141         self.assertEqual(r.status_code, 403)
1142         
1143         r = self.client.object_post(obj, update=True, content_type='application/octet-srteam',
1144             content_length=5, content_range='bytes 1-5/*', source_object='/%s/%s'%(self.c2,obj),
1145             source_account=self.client.account, source_version=helloVersion, data='12345',
1146             content_disposition='attachment; filename="fname.ext"')
1147         
1148         r = self.client.object_get(obj)
1149         self.assertEqual(r.text, 'eello!')
1150         self.assertTrue(r.headers.has_key('content-disposition')
1151             and 'fname.ext' in r.headers['content-disposition'])
1152         
1153
1154         """Check manifest"""
1155         mobj = 'manifest.test'
1156         txt = ''
1157         for i in range(10):
1158             txt += '%s'%i
1159             r = self.client.object_put('%s/%s'%(mobj, i), data='%s'%i, content_length=1, success=201,
1160                 content_encoding='application/octet-stream', content_type='application/octet-stream')
1161             
1162         #r = self.client.object_put(mobj, content_length=0, content_type='application/octet-stream')
1163         self.client.create_object_by_manifestation(mobj, content_type='application/octet-stream')
1164         
1165         r = self.client.object_post(mobj, manifest='%s/%s'%(self.client.container, mobj))
1166         
1167         r = self.client.object_get(mobj)
1168         self.assertEqual(r.text, txt)
1169         
1170
1171         """We need to check transfer_encoding """
1172
1173     def test_object_delete(self):
1174         """Test object_DELETE"""
1175         self.client.container=self.c2
1176         obj = 'test2'
1177         """create a file on container"""
1178         r = self.client.object_put(obj, content_type='application/octet-stream',
1179             data= 'H', metadata={'mkey1':'mval1', 'mkey2':'mval2'},
1180             permitions={'read':['accX:groupA', 'u1', 'u2'], 'write':['u2', 'u3']})
1181         
1182
1183         """Check with false until"""
1184         r = self.client.object_delete(obj, until=1000000)
1185         
1186         r = self.client.object_get(obj, success=(200, 404))
1187         self.assertEqual(r.status_code, 200)
1188         
1189
1190         """Check normal case"""
1191         r = self.client.object_delete(obj)
1192         self.assertEqual(r.status_code, 204)
1193         
1194         r = self.client.object_get(obj, success=(200, 404))
1195         self.assertEqual(r.status_code, 404)
1196         
1197
1198     def create_large_file(self, size, name):
1199         """Create a large file at fs"""
1200         self.fname = name
1201         import random
1202         random.seed(self.now)
1203         f = open(self.fname, 'w')
1204         sys.stdout.write(' create random file %s of size %s'%(name, size)+' 0%')
1205         for hobyte_id in range(size/8):
1206             sss = 'hobt%s'%random.randint(1000, 9999)
1207             f.write(sss)
1208             if 0 == (hobyte_id*800)%size:
1209                 f.write('\n')
1210                 sys.stdout.write('\b\b')
1211                 prs = (hobyte_id*800)//size
1212                 if prs > 10:
1213                     sys.stdout.write('\b')
1214                 sys.stdout.write('%s'%prs+'%')
1215                 sys.stdout.flush()
1216         print('\b\b\b100%')
1217         f.close()
1218         """"""
1219
1220 def init_parser():
1221     parser = ArgumentParser(add_help=False)
1222     parser.add_argument('-h', '--help', dest='help', action='store_true', default=False,
1223         help="Show this help message and exit")
1224     return parser
1225
1226 if __name__ == '__main__':
1227     parser = init_parser()
1228     args, argv = parser.parse_known_args()
1229
1230     if len(argv) > 2 or getattr(args,'help') or len(argv) < 1:
1231         raise Exception('\tusage: tests.py <group> [command]')
1232     suiteFew = unittest.TestSuite()
1233
1234     if len(argv) == 0 or argv[0] == 'pithos':
1235         if len(argv) == 1:
1236             suiteFew.addTest(unittest.makeSuite(testPithos))
1237         else:
1238             suiteFew.addTest(testPithos('test_'+argv[1]))
1239     if len(argv) == 0 or argv[0] == 'cyclades':
1240         if len(argv) == 1:
1241             #suiteFew.addTest(unittest.makeSuite(testCyclades))
1242             suiteFew.addTest(testCyclades('test_000'))
1243         else:
1244             suiteFew.addTest(testCyclades('test_'+argv[1]))
1245
1246     unittest.TextTestRunner(verbosity = 2).run(suiteFew)