Revision f0eacc2c pithos/api/tests.py
b/pithos/api/tests.py | ||
---|---|---|
36 | 36 |
from django.utils import simplejson as json |
37 | 37 |
from xml.dom import minidom |
38 | 38 |
from StringIO import StringIO |
39 |
import time as _time |
|
39 | 40 |
import types |
40 | 41 |
import hashlib |
41 | 42 |
import os |
... | ... | |
45 | 46 |
import string |
46 | 47 |
import re |
47 | 48 |
|
48 |
#from pithos.backends import backend |
|
49 |
|
|
50 | 49 |
DATE_FORMATS = ["%a %b %d %H:%M:%S %Y", |
51 | 50 |
"%A, %d-%b-%y %H:%M:%S GMT", |
52 | 51 |
"%a, %d %b %Y %H:%M:%S GMT"] |
... | ... | |
54 | 53 |
DEFAULT_HOST = 'pithos.dev.grnet.gr' |
55 | 54 |
#DEFAULT_HOST = '127.0.0.1:8000' |
56 | 55 |
DEFAULT_API = 'v1' |
57 |
DEFAULT_USER = 'papagian'
|
|
58 |
DEFAULT_AUTH = '0004'
|
|
56 |
DEFAULT_USER = 'test'
|
|
57 |
DEFAULT_AUTH = '0000'
|
|
59 | 58 |
|
60 | 59 |
class BaseTestCase(unittest.TestCase): |
61 | 60 |
#TODO unauthorized request |
62 | 61 |
def setUp(self): |
63 |
self.client = Pithos_Client(DEFAULT_HOST, DEFAULT_AUTH, DEFAULT_USER, DEFAULT_API) |
|
64 |
self.headers = { |
|
65 |
'account': ('x-account-container-count', |
|
66 |
'x-account-bytes-used', |
|
67 |
'last-modified', |
|
68 |
'content-length', |
|
69 |
'date', |
|
70 |
'content_type', |
|
71 |
'server',), |
|
72 |
'object': ('etag', |
|
73 |
'content-length', |
|
74 |
'content_type', |
|
75 |
'content-encoding', |
|
76 |
'last-modified', |
|
77 |
'date', |
|
78 |
'x-object-manifest', |
|
79 |
'content-range', |
|
80 |
'x-object-modified-by', |
|
81 |
'x-object-version', |
|
82 |
'x-object-version-timestamp', |
|
83 |
'server',), |
|
84 |
'container': ('x-container-object-count', |
|
85 |
'x-container-bytes-used', |
|
86 |
'content_type', |
|
87 |
'last-modified', |
|
88 |
'content-length', |
|
89 |
'date', |
|
90 |
'x-container-block-size', |
|
91 |
'x-container-block-hash', |
|
92 |
'x-container-policy-quota', |
|
93 |
'x-container-policy-versioning', |
|
94 |
'server', |
|
95 |
'x-container-object-meta', |
|
96 |
'x-container-policy-versioning', |
|
97 |
'server',)} |
|
98 |
|
|
99 |
self.contentTypes = {'xml':'application/xml', |
|
100 |
'json':'application/json', |
|
101 |
'':'text/plain'} |
|
62 |
self.client = Pithos_Client(DEFAULT_HOST, |
|
63 |
DEFAULT_AUTH, |
|
64 |
DEFAULT_USER, |
|
65 |
DEFAULT_API) |
|
66 |
self.invalid_client = Pithos_Client(DEFAULT_HOST, |
|
67 |
DEFAULT_AUTH, |
|
68 |
'invalid', |
|
69 |
DEFAULT_API) |
|
70 |
#self.headers = { |
|
71 |
# 'account': ('x-account-container-count', |
|
72 |
# 'x-account-bytes-used', |
|
73 |
# 'last-modified', |
|
74 |
# 'content-length', |
|
75 |
# 'date', |
|
76 |
# 'content_type', |
|
77 |
# 'server',), |
|
78 |
# 'object': ('etag', |
|
79 |
# 'content-length', |
|
80 |
# 'content_type', |
|
81 |
# 'content-encoding', |
|
82 |
# 'last-modified', |
|
83 |
# 'date', |
|
84 |
# 'x-object-manifest', |
|
85 |
# 'content-range', |
|
86 |
# 'x-object-modified-by', |
|
87 |
# 'x-object-version', |
|
88 |
# 'x-object-version-timestamp', |
|
89 |
# 'server',), |
|
90 |
# 'container': ('x-container-object-count', |
|
91 |
# 'x-container-bytes-used', |
|
92 |
# 'content_type', |
|
93 |
# 'last-modified', |
|
94 |
# 'content-length', |
|
95 |
# 'date', |
|
96 |
# 'x-container-block-size', |
|
97 |
# 'x-container-block-hash', |
|
98 |
# 'x-container-policy-quota', |
|
99 |
# 'x-container-policy-versioning', |
|
100 |
# 'server', |
|
101 |
# 'x-container-object-meta', |
|
102 |
# 'x-container-policy-versioning', |
|
103 |
# 'server',)} |
|
104 |
# |
|
105 |
#self.contentTypes = {'xml':'application/xml', |
|
106 |
# 'json':'application/json', |
|
107 |
# '':'text/plain'} |
|
102 | 108 |
self.extended = { |
103 | 109 |
'container':( |
104 | 110 |
'name', |
... | ... | |
146 | 152 |
# data = minidom.parseString(data) |
147 | 153 |
# return status, headers, data |
148 | 154 |
|
149 |
def assert_headers(self, headers, type, **exp_meta): |
|
150 |
prefix = 'x-%s-meta-' %type |
|
151 |
system_headers = [h for h in headers if not h.startswith(prefix)] |
|
152 |
for k,v in headers.items(): |
|
153 |
if k in system_headers: |
|
154 |
self.assertTrue(k in headers[type]) |
|
155 |
elif exp_meta: |
|
156 |
k = k.split(prefix)[-1] |
|
157 |
self.assertEqual(v, exp_meta[k]) |
|
158 |
|
|
159 |
#def assert_extended(self, data, format, type, size): |
|
160 |
# if format == 'xml': |
|
161 |
# self._assert_xml(data, type, size) |
|
162 |
# elif format == 'json': |
|
163 |
# self._assert_json(data, type, size) |
|
164 |
|
|
165 |
#def _assert_json(self, data, type, size): |
|
166 |
# print '#', data |
|
167 |
# convert = lambda s: s.lower() |
|
168 |
# info = [convert(elem) for elem in self.extended[type]] |
|
169 |
# data = json.loads(data) |
|
170 |
# self.assertTrue(len(data) <= size) |
|
171 |
# for item in info: |
|
172 |
# for i in data: |
|
173 |
# if 'subdir' in i.keys(): |
|
174 |
# continue |
|
175 |
# self.assertTrue(item in i.keys()) |
|
176 |
|
|
177 |
#def _assert_xml(self, data, type, size): |
|
178 |
# print '#', data |
|
179 |
# convert = lambda s: s.lower() |
|
180 |
# info = [convert(elem) for elem in self.extended[type]] |
|
181 |
# try: |
|
182 |
# info.remove('content_encoding') |
|
183 |
# except ValueError: |
|
184 |
# pass |
|
185 |
# xml = minidom.parseString(data) |
|
186 |
# entities = xml.getElementsByTagName(type) |
|
187 |
# self.assertTrue(len(entities) <= size) |
|
188 |
# for e in entities: |
|
189 |
# for item in info: |
|
190 |
# self.assertTrue(e.hasAttribute(item)) |
|
155 |
#def assert_headers(self, headers, type, **exp_meta): |
|
156 |
# prefix = 'x-%s-meta-' %type |
|
157 |
# system_headers = [h for h in headers if not h.startswith(prefix)] |
|
158 |
# for k,v in headers.items(): |
|
159 |
# if k in system_headers: |
|
160 |
# self.assertTrue(k in headers[type]) |
|
161 |
# elif exp_meta: |
|
162 |
# k = k.split(prefix)[-1] |
|
163 |
# self.assertEqual(v, exp_meta[k]) |
|
164 |
|
|
165 |
def assert_extended(self, data, format, type, size): |
|
166 |
if format == 'xml': |
|
167 |
self._assert_xml(data, type, size) |
|
168 |
elif format == 'json': |
|
169 |
self._assert_json(data, type, size) |
|
170 |
|
|
171 |
def _assert_json(self, data, type, size): |
|
172 |
print '#', data |
|
173 |
convert = lambda s: s.lower() |
|
174 |
info = [convert(elem) for elem in self.extended[type]] |
|
175 |
self.assertTrue(len(data) <= size) |
|
176 |
for item in info: |
|
177 |
for i in data: |
|
178 |
if 'subdir' in i.keys(): |
|
179 |
continue |
|
180 |
self.assertTrue(item in i.keys()) |
|
181 |
|
|
182 |
def _assert_xml(self, data, type, size): |
|
183 |
convert = lambda s: s.lower() |
|
184 |
info = [convert(elem) for elem in self.extended[type]] |
|
185 |
try: |
|
186 |
info.remove('content_encoding') |
|
187 |
except ValueError: |
|
188 |
pass |
|
189 |
xml = data |
|
190 |
entities = xml.getElementsByTagName(type) |
|
191 |
self.assertTrue(len(entities) <= size) |
|
192 |
for e in entities: |
|
193 |
for item in info: |
|
194 |
print '#', item |
|
195 |
self.assertTrue(e.hasAttribute(item)) |
|
191 | 196 |
|
192 | 197 |
def assert_raises_fault(self, status, callableObj, *args, **kwargs): |
193 | 198 |
""" |
... | ... | |
265 | 270 |
for item in self.containers: |
266 | 271 |
self.client.create_container(item) |
267 | 272 |
|
273 |
def tearDown(self): |
|
274 |
self.client.delete_account_metadata(['foo']) |
|
275 |
BaseTestCase.tearDown(self) |
|
276 |
|
|
268 | 277 |
def test_get_account_meta(self): |
269 | 278 |
meta = self.client.retrieve_account_metadata() |
270 | 279 |
|
... | ... | |
277 | 286 |
size = size + int(m['x-container-bytes-used']) |
278 | 287 |
self.assertEqual(meta['x-account-bytes-used'], str(size)) |
279 | 288 |
|
280 |
#def test_get_account_401(self): |
|
281 |
# response = self.get_account_meta('non-existing-account') |
|
282 |
# print response |
|
283 |
# self.assertEqual(response.status_code, 401) |
|
289 |
def test_get_account_401(self): |
|
290 |
self.assert_raises_fault(401, |
|
291 |
self.invalid_client.retrieve_account_metadata) |
|
292 |
|
|
293 |
def test_get_account_meta_until(self): |
|
294 |
t = datetime.datetime.utcnow() |
|
295 |
past = t - datetime.timedelta(minutes=-15) |
|
296 |
past = int(_time.mktime(past.timetuple())) |
|
297 |
|
|
298 |
meta = {'foo':'bar'} |
|
299 |
self.client.update_account_metadata(**meta) |
|
300 |
meta = self.client.retrieve_account_metadata(restricted=True, |
|
301 |
until=past) |
|
302 |
self.assertTrue('foo' not in meta) |
|
303 |
|
|
304 |
meta = self.client.retrieve_account_metadata(restricted=True) |
|
305 |
self.assertTrue('foo' in meta) |
|
306 |
|
|
307 |
def test_get_account_meta_until_invalid_date(self): |
|
308 |
meta = {'foo':'bar'} |
|
309 |
self.client.update_account_metadata(**meta) |
|
310 |
meta = self.client.retrieve_account_metadata(restricted=True, |
|
311 |
until='kshfksfh') |
|
312 |
self.assertTrue('foo' in meta) |
|
284 | 313 |
|
285 | 314 |
class AccountGet(BaseTestCase): |
286 | 315 |
def setUp(self): |
... | ... | |
296 | 325 |
containers = self.client.list_containers() |
297 | 326 |
self.assertEquals(self.containers, containers) |
298 | 327 |
|
299 |
#def test_list_204(self): |
|
300 |
# response = self.list_containers('non-existing-account') |
|
301 |
# self.assertEqual(response.status_code, 204) |
|
328 |
def test_list_401(self): |
|
329 |
self.assert_raises_fault(401, self.invalid_client.list_containers) |
|
302 | 330 |
|
303 | 331 |
def test_list_with_limit(self): |
304 | 332 |
limit = 2 |
... | ... | |
318 | 346 |
i = self.containers.index(m) + 1 |
319 | 347 |
self.assertEquals(self.containers[i:(i+l)], containers) |
320 | 348 |
|
321 |
#def test_extended_list(self): |
|
322 |
# self.list_containers(self.account, limit=3, format='xml') |
|
323 |
# self.list_containers(self.account, limit=3, format='json') |
|
324 |
|
|
325 | 349 |
def test_list_json_with_marker(self): |
326 | 350 |
l = 2 |
327 | 351 |
m = 'bananas' |
328 |
containers = self.client.list_containers(limit=l, marker=m, detail=True) |
|
352 |
containers = self.client.list_containers(limit=l, marker=m, format='json') |
|
353 |
self.assert_extended(containers, 'json', 'container', l) |
|
329 | 354 |
self.assertEqual(containers[0]['name'], 'kiwis') |
330 | 355 |
self.assertEqual(containers[1]['name'], 'oranges') |
331 | 356 |
|
332 |
#def test_list_xml_with_marker(self): |
|
333 |
# l = 2 |
|
334 |
# m = 'oranges' |
|
335 |
# status, headers, xml = self.list_containers(limit=l, marker=m, format='xml') |
|
336 |
# nodes = xml.getElementsByTagName('name') |
|
337 |
# self.assertEqual(len(nodes), 1) |
|
338 |
# self.assertEqual(nodes[0].childNodes[0].data, 'pears') |
|
357 |
def test_list_xml_with_marker(self): |
|
358 |
l = 2 |
|
359 |
m = 'oranges' |
|
360 |
xml = self.client.list_containers(limit=l, marker=m, format='xml') |
|
361 |
#self.assert_extended(xml, 'xml', 'container', l) |
|
362 |
nodes = xml.getElementsByTagName('name') |
|
363 |
self.assertEqual(len(nodes), 1) |
|
364 |
self.assertEqual(nodes[0].childNodes[0].data, 'pears') |
|
339 | 365 |
|
340 | 366 |
def test_if_modified_since(self): |
341 | 367 |
t = datetime.datetime.utcnow() |
... | ... | |
404 | 430 |
self.client.update_account_metadata(**meta) |
405 | 431 |
self.assertEqual(meta, self.client.retrieve_account_metadata(restricted=True)) |
406 | 432 |
|
407 |
#def test_invalid_account_update_meta(self): |
|
408 |
# with AssertMappingInvariant(self.get_account_meta, self.account): |
|
409 |
# meta = {'HTTP_X_ACCOUNT_META_TEST':'test', |
|
410 |
# 'HTTP_X_ACCOUNT_META_TOST':'tost'} |
|
411 |
# response = self.update_account_meta('non-existing-account', **meta) |
|
433 |
def test_invalid_account_update_meta(self): |
|
434 |
meta = {'HTTP_X_ACCOUNT_META_TEST':'test', |
|
435 |
'HTTP_X_ACCOUNT_META_TOST':'tost'} |
|
436 |
self.assert_raises_fault(401, |
|
437 |
self.invalid_client.update_account_metadata, |
|
438 |
**meta) |
|
412 | 439 |
|
413 | 440 |
class ContainerHead(BaseTestCase): |
414 | 441 |
def setUp(self): |
... | ... | |
486 | 513 |
self.assertEquals(['photos/me.jpg'], objects) |
487 | 514 |
|
488 | 515 |
def test_extended_list_json(self): |
489 |
objects = self.client.list_objects(self.container[1], detail=True,
|
|
516 |
objects = self.client.list_objects(self.container[1], format='json',
|
|
490 | 517 |
limit=2, prefix='photos/animals', |
491 | 518 |
delimiter='/') |
492 | 519 |
self.assertEqual(objects[0]['subdir'], 'photos/animals/cats/') |
493 | 520 |
self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/') |
494 | 521 |
|
495 |
#def test_extended_list_xml(self):
|
|
496 |
# xml = self.client.list_objects(self.container[1], format='xml', limit=4,
|
|
497 |
# prefix='photos', delimiter='/')
|
|
498 |
# dirs = xml.getElementsByTagName('subdir')
|
|
499 |
# self.assertEqual(len(dirs), 2)
|
|
500 |
# self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/')
|
|
501 |
# self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/')
|
|
502 |
# |
|
503 |
# objects = xml.getElementsByTagName('name')
|
|
504 |
# self.assertEqual(len(objects), 1)
|
|
505 |
# self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg')
|
|
522 |
def test_extended_list_xml(self): |
|
523 |
xml = self.client.list_objects(self.container[1], format='xml', limit=4, |
|
524 |
prefix='photos', delimiter='/') |
|
525 |
dirs = xml.getElementsByTagName('subdir') |
|
526 |
self.assertEqual(len(dirs), 2) |
|
527 |
self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/') |
|
528 |
self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/') |
|
529 |
|
|
530 |
objects = xml.getElementsByTagName('name') |
|
531 |
self.assertEqual(len(objects), 1) |
|
532 |
self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg') |
|
506 | 533 |
|
507 | 534 |
def test_list_meta_double_matching(self): |
508 | 535 |
meta = {'quality':'aaa', 'stock':'true'} |
... | ... | |
978 | 1005 |
fname = 'largefile' |
979 | 1006 |
o = self.upload_random_data(self.containers[1], fname, l) |
980 | 1007 |
if o: |
981 |
data = self.client.retrieve_object(self.containers[1], fname, detail=True) |
|
1008 |
data = self.client.retrieve_object(self.containers[1], fname, |
|
1009 |
format='json') |
|
982 | 1010 |
body = json.loads(data) |
983 | 1011 |
hashes = body['hashes'] |
984 | 1012 |
block_size = body['block_size'] |
... | ... | |
1026 | 1054 |
self.assert_raises_fault(422, self.upload_random_data, self.container, |
1027 | 1055 |
o_names[0], **meta) |
1028 | 1056 |
|
1029 |
def test_chucked_transfer(self):
|
|
1057 |
def test_chunked_transfer(self):
|
|
1030 | 1058 |
data = get_random_data() |
1031 | 1059 |
objname = 'object' |
1032 | 1060 |
self.client.create_object_using_chunks(self.container, objname, |
... | ... | |
1197 | 1225 |
self.containers[0], self.obj['name']): |
1198 | 1226 |
self.test_update_object(499, 0, True) |
1199 | 1227 |
|
1200 |
#no use if the server resets the content-legth |
|
1201 | 1228 |
def test_update_object_invalid_range_and_length(self): |
1202 | 1229 |
with AssertContentInvariant(self.client.retrieve_object, |
1203 | 1230 |
self.containers[0], self.obj['name']): |
1204 | 1231 |
self.test_update_object(499, 0, True, -1) |
1205 | 1232 |
|
1206 |
#no use if the server resets the content-legth |
|
1207 | 1233 |
def test_update_object_invalid_range_with_no_content_length(self): |
1208 | 1234 |
with AssertContentInvariant(self.client.retrieve_object, |
1209 | 1235 |
self.containers[0], self.obj['name']): |
Also available in: Unified diff