def test_write_directory(self): url = join_urls( self.pithos_path, self.user, self.container, self.object) for type in ('application/directory', 'application/folder'): # change content type r = self.put(url, data='', content_type=type, HTTP_X_MOVE_FROM='/%s/%s' % ( self.container, self.object)) self.assertEqual(r.status_code, 201) info = self.get_object_info(self.container, self.object) self.assertEqual(info['Content-Type'], type) url = join_urls( self.pithos_path, self.user, self.container, self.object) r = self.post( url, content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_OBJECT_SHARING='write=*') self._assert_write(self.object, self.users) url = join_urls( self.pithos_path, self.user, self.container, self.object) r = self.post( url, content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_OBJECT_SHARING='write=%s' % ','.join( self.users[:2])) self._assert_write(self.object, self.users[:2]) group = self.groups.keys()[0] members = self.groups[group] url = join_urls( self.pithos_path, self.user, self.container, self.object) r = self.post( url, content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_OBJECT_SHARING='write=%s:%s' % (self.user, group)) self._assert_write(self.object, members)
def test_manifestation(self): self.create_container("κουβάς") prefix = "μέρη/" data = "" for i in range(5): part = "%s%d" % (prefix, i) data += self.upload_object("κουβάς", part)[1] self.create_container("φάκελος") url = join_urls(self.pithos_path, self.user, "φάκελος", "άπαντα") r = self.put(url, data="", HTTP_X_OBJECT_MANIFEST="κουβάς/%s" % prefix) self.assertEqual(r.status_code, 201) r = self.head(url) self.assertEqual(r.status_code, 200) r = self.get(url) self.assertEqual(r.status_code, 200) self.assertEqual(r.content, data) # wrong manifestation url = join_urls(self.pithos_path, self.user, "φάκελος", "άπαντα") r = self.put(url, data="", HTTP_X_OBJECT_MANIFEST="κουβάς/λάθος") self.assertEqual(r.status_code, 201) r = self.get(url) self.assertEqual(r.status_code, 200) self.assertTrue(r.content != data)
def test_not_allowed(self): cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] url = join_urls(self.pithos_path, self.user) r = self.head(url, user='******') self.assertEqual(r.status_code, 403) r = self.get(url, user='******') self.assertEqual(r.status_code, 403) r = self.post(url, user='******', data=get_random_data()) self.assertEqual(r.status_code, 403) url = join_urls(self.pithos_path, self.user, cname) r = self.head(url, user='******') self.assertEqual(r.status_code, 403) r = self.get(url, user='******') self.assertEqual(r.status_code, 403) r = self.put(url, user='******', data=get_random_data()) self.assertEqual(r.status_code, 403) r = self.post(url, user='******', data=get_random_data()) self.assertEqual(r.status_code, 403) r = self.delete(url, user='******') self.assertEqual(r.status_code, 403) url = join_urls(self.pithos_path, self.user, cname, oname) r = self.head(url, user='******') self.assertEqual(r.status_code, 403) r = self.get(url, user='******') self.assertEqual(r.status_code, 403) r = self.put(url, user='******', data=get_random_data()) self.assertEqual(r.status_code, 403) r = self.post(url, user='******', data=get_random_data()) self.assertEqual(r.status_code, 403) r = self.delete(url, user='******') self.assertEqual(r.status_code, 403)
def test_rud(self, mrapi): vol = VolumeFactory(status="IN_USE") user = vol.userid # READ r = self.get(join_urls(VOLUMES_URL, "detail"), user) api_vols = json.loads(r.content)["volumes"] self.assertEqual(len(api_vols), 1) api_vol = api_vols[0] self.assertEqual(api_vol["id"], str(vol.id)) self.assertEqual(api_vol["display_name"], vol.name) self.assertEqual(api_vol["display_description"], vol.description) volume_url = join_urls(VOLUMES_URL, str(vol.id)) r = self.get(volume_url, user) self.assertSuccess(r) # UPDATE data = { "volume": { "display_name": "lolo", "display_description": "lala" } } r = self.put(volume_url, user, json.dumps(data), "json") self.assertSuccess(r) api_vol = json.loads(r.content)["volume"] self.assertEqual(api_vol["display_name"], "lolo") self.assertEqual(api_vol["display_description"], "lala") # DELETE mrapi().ModifyInstance.return_value = 42 r = self.delete(volume_url, user) self.assertSuccess(r)
def test_get(self): response = self.get(join_urls(EXTENSIONS_URL, "SNF"), "user") self.assertEqual(response.status_code, 404) response = self.get(join_urls(EXTENSIONS_URL, "SNF_asfas_da"), "user") self.assertEqual(response.status_code, 404) response = self.get(join_urls(EXTENSIONS_URL, "SNF-AD"), "user") self.assertEqual(response.status_code, 404)
def test_manifestation(self): self.create_container('κουβάς') prefix = 'μέρη/' data = '' for i in range(5): part = '%s%d' % (prefix, i) data += self.upload_object('κουβάς', part)[1] self.create_container('φάκελος') url = join_urls(self.pithos_path, self.user, 'φάκελος', 'άπαντα') r = self.put(url, data='', HTTP_X_OBJECT_MANIFEST='κουβάς/%s' % prefix) self.assertEqual(r.status_code, 201) r = self.head(url) self.assertEqual(r.status_code, 200) r = self.get(url) self.assertEqual(r.status_code, 200) self.assertEqual("".join(r.streaming_content), data) # wrong manifestation url = join_urls(self.pithos_path, self.user, 'φάκελος', 'άπαντα') r = self.put(url, data='', HTTP_X_OBJECT_MANIFEST='κουβάς/λάθος') self.assertEqual(r.status_code, 201) r = self.get(url) self.assertEqual(r.status_code, 200) self.assertTrue("".join(r.streaming_content) != data)
def test_not_allowed(self): self.view_path = join_urls(get_service_path( pithos_settings.pithos_services, 'pithos_ui'), 'view') self.view_url = join_urls(self.view_path, self.user, get_random_name(), get_random_name()) r = self.delete(self.view_url) self.assertEqual(r.status_code, 405) self.assertTrue('Allow' in r) self.assertEqual(sorted(r['Allow'].split(', ')), ['GET', 'HEAD']) r = self.post(self.view_url) self.assertEqual(r.status_code, 405) self.assertTrue('Allow' in r) self.assertEqual(sorted(r['Allow'].split(', ')), ['GET', 'HEAD']) r = self.put(self.view_url) self.assertEqual(r.status_code, 405) self.assertTrue('Allow' in r) self.assertEqual(sorted(r['Allow'].split(', ')), ['GET', 'HEAD']) r = self.copy(self.view_url) self.assertEqual(r.status_code, 405) self.assertTrue('Allow' in r) self.assertEqual(sorted(r['Allow'].split(', ')), ['GET', 'HEAD']) r = self.move(self.view_url) self.assertEqual(r.status_code, 405) self.assertTrue('Allow' in r) self.assertEqual(sorted(r['Allow'].split(', ')), ['GET', 'HEAD'])
def test_set_unset_set(self): cname = get_random_name() self.create_container(cname) oname, odata = self.upload_object(cname)[:-1] self._assert_not_public_object(cname, oname) # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) public = self._assert_public_object(cname, oname, odata) # unset public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='false') self.assertEqual(r.status_code, 202) self._assert_not_public_object(cname, oname) # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) public2 = self._assert_public_object(cname, oname, odata) self.assertTrue(public != public2) # unset public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='false') self.assertEqual(r.status_code, 202) self._assert_not_public_object(cname, oname)
def test_groups(self): # create a group headers = {"HTTP_X_ACCOUNT_GROUP_γκρουπ": "chazapis,διογένης"} url = join_urls(self.pithos_path, self.user) r = self.post(url, **headers) self.assertEqual(r.status_code, 202) groups = self.get_account_groups() self.assertTrue("γκρουπ" in groups) self.assertEqual(groups["γκρουπ"], "chazapis,διογένης") # check read access self.create_container("φάκελος") odata = self.upload_object("φάκελος", "ο1")[1] r = self.head(url, user="******") self.assertEqual(r.status_code, 403) r = self.get(url, user="******") self.assertEqual(r.status_code, 403) # share for read url = join_urls(self.pithos_path, self.user, "φάκελος", "ο1") r = self.post(url, content_type="", HTTP_X_OBJECT_SHARING="read=%s:γκρουπ" % self.user) self.assertEqual(r.status_code, 202) r = self.head(url, user="******") self.assertEqual(r.status_code, 200) r = self.get(url, user="******") self.assertEqual(r.status_code, 200) # check write access appended_data = get_random_data() r = self.post( url, user="******", data=appended_data, content_type="application/octet-stream", HTTP_CONTENT_LENGTH=str(len(appended_data)), HTTP_CONTENT_RANGE="bytes */*", ) self.assertEqual(r.status_code, 403) # share for write url = join_urls(self.pithos_path, self.user, "φάκελος", "ο1") r = self.post(url, content_type="", HTTP_X_OBJECT_SHARING="write=%s:γκρουπ" % self.user) self.assertEqual(r.status_code, 202) r = self.post( url, user="******", data=appended_data, content_type="application/octet-stream", HTTP_CONTENT_LENGTH=str(len(appended_data)), HTTP_CONTENT_RANGE="bytes */*", ) self.assertEqual(r.status_code, 204) r = self.get(url, user="******") self.assertEqual(r.status_code, 200) self.assertEqual(r.content, odata + appended_data)
def test_public_multiple_range(self): cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] url = join_urls(self.pithos_path, self.user, cname, oname) # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] l = ['0-499', '-500', '1000-'] ranges = 'bytes=%s' % ','.join(l) r = self.get(public_url, HTTP_RANGE=ranges) self.assertEqual(r.status_code, 206) self.assertTrue('content-type' in r) p = re.compile( 'multipart/byteranges; boundary=(?P<boundary>[0-9a-f]{32}\Z)', re.I) m = p.match(r['content-type']) if m is None: self.fail('Invalid multiple range content type') boundary = m.groupdict()['boundary'] cparts = r.content.split('--%s' % boundary)[1:-1] # assert content parts length self.assertEqual(len(cparts), len(l)) # for each content part assert headers i = 0 for cpart in cparts: content = cpart.split('\r\n') headers = content[1:3] content_range = headers[0].split(': ') self.assertEqual(content_range[0], 'Content-Range') r = l[i].split('-') if not r[0] and not r[1]: pass elif not r[0]: start = len(odata) - int(r[1]) end = len(odata) elif not r[1]: start = int(r[0]) end = len(odata) else: start = int(r[0]) end = int(r[1]) + 1 fdata = odata[start:end] sdata = '\r\n'.join(content[4:-1]) self.assertEqual(len(fdata), len(sdata)) self.assertEquals(fdata, sdata) i += 1
def setUp(self): PithosAPITest.setUp(self) self.cname = self.create_container()[0] self.oname, self.odata = self.upload_object(self.cname, 'φωτογραφία.JPG')[:-1] self.view_path = join_urls(get_service_path( pithos_settings.pithos_services, 'pithos_ui'), 'view') self.view_url = join_urls(self.view_path, self.user, self.cname, self.oname) self.api_url = join_urls(self.pithos_path, self.user, self.cname, self.oname)
def test_create_container(self): cname = 'φάκελος' self.create_container(cname) url = join_urls(self.pithos_path, self.user, cname) r = self.head(url) self.assertEqual(r.status_code, 204) url = join_urls(self.pithos_path, self.user) r = self.get(url) self.assertEqual(r.status_code, 200) containers = r.content.split('\n') self.assertTrue('φάκελος' in containers)
def test_volume_metadata(self): vol = VolumeFactory() volume_metadata_url = join_urls(join_urls(VOLUMES_URL, str(vol.id)), "metadata") # Empty metadata response = self.get(volume_metadata_url, vol.userid) self.assertSuccess(response) metadata = json.loads(response.content)["metadata"] self.assertEqual(metadata, {}) # Create metadata items meta1 = {"metadata": {"key1": "val1", "\u2601": "\u2602"}} response = self.post(volume_metadata_url, vol.userid, json.dumps(meta1), "json") self.assertSuccess(response) response = self.get(volume_metadata_url, vol.userid) self.assertSuccess(response) metadata = json.loads(response.content) self.assertEqual(metadata, meta1) # Update existing metadata and add new meta2 = {"metadata": {"\u2601": "unicode_val_2", "key3": "val3"}} meta_db = {"metadata": {"key1": "val1", "\u2601": "unicode_val_2", "key3": "val3"}} response = self.post(volume_metadata_url, vol.userid, json.dumps(meta2), "json") self.assertSuccess(response) metadata = json.loads(response.content) self.assertEqual(metadata, meta_db) response = self.get(volume_metadata_url, vol.userid) self.assertSuccess(response) metadata = json.loads(response.content) self.assertEqual(metadata, meta_db) # Replace all metadata meta3 = {"metadata": {"key4": "val4"}} response = self.put(volume_metadata_url, vol.userid, json.dumps(meta3), "json") self.assertSuccess(response) response = self.get(volume_metadata_url, vol.userid) self.assertSuccess(response) metadata = json.loads(response.content) self.assertEqual(metadata, meta3) # Delete metadata key response = self.delete(join_urls(volume_metadata_url, "key4"), vol.userid) self.assertSuccess(response) response = self.get(volume_metadata_url, vol.userid) self.assertSuccess(response) metadata = json.loads(response.content)["metadata"] self.assertEqual(metadata, {})
def get_url_patterns(self): _patterns = patterns( '', url(r'^%s/?$' % join_urls(self.endpoints_prefix, self.authorization_endpoint.rstrip('/')), self.auth_view, name='%s_authenticate' % self.id), url(r'^%s/?$' % join_urls(self.endpoints_prefix, self.token_endpoint.rstrip('/')), self.token_view, name='%s_token' % self.id), ) return _patterns
def test_shared_with_me(self): container = self.create_container(user='******')[0] obj, data = self.upload_object(container, user='******')[:-1] # share object url = join_urls(self.pithos_path, 'alice', container, obj) self.post(url, user='******', content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_OBJECT_SHARING='read=user') url = join_urls(self.view_path, 'alice', container, obj) r = self.view(url) self.assertEqual(r.status_code, 200) self.assertEqual(r.content, data)
def delete_object(self, cname, oname, user=None, verify_status=True): user = user or self.user url = join_urls(self.pithos_path, user, cname, oname) r = self.delete(url, user=user) if verify_status: self.assertEqual(r.status_code, 204) return r
def test_list_objects_containing_slash(self): self.create_container('test') self.upload_object('test', quote('/objectname', '')) url = join_urls(self.pithos_path, self.user, 'test') r = self.get(url) objects = r.content.split('\n') if '' in objects: objects.remove('') self.assertEqual(objects, ['/objectname']) r = self.get('%s?format=json' % url) try: objects = json.loads(r.content) except: self.fail('json format expected') self.assertEqual([o['name'] for o in objects], ['/objectname']) r = self.get('%s?format=xml' % url) try: objects = minidom.parseString(r.content) except: self.fail('xml format expected') self.assertEqual( [n.firstChild.data for n in objects.getElementsByTagName('name')], ['/objectname'])
def test_public_get_multiple_if_match(self): cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] def assert_multiple_match(etag): quoted = lambda s: '"%s"' % s r = self.get(public_url, HTTP_IF_MATCH=','.join( [quoted(etag), quoted(get_random_data(64))])) # assert get success self.assertEqual(r.status_code, 200) # assert response content self.assertEqual(r.content, odata) # perform get with If-Match if pithos_settings.UPDATE_MD5: assert_multiple_match(md5_hash(odata)) else: assert_multiple_match(merkle(odata))
def test_get_meta(self): self.create_container('apples') # populate with objects objects = {} for i in range(random.randint(1, 100)): # upload object meta = {'foo%s' % i: 'bar'} name, data, resp = self.upload_object('apples', **meta) objects[name] = data t1 = datetime.datetime.utcnow() url = join_urls(self.pithos_path, self.user, 'apples') r = self.head(url) self.assertEqual(int(r['X-Container-Object-Count']), len(objects)) self.assertEqual(int(r['X-Container-Bytes-Used']), sum([len(i) for i in objects.values()])) self.assertTrue('X-Container-Block-Size' in r) self.assertTrue('X-Container-Block-Hash' in r) self.assertTrue('X-Container-Until-Timestamp' not in r) self.assertEqual(r['X-Container-Policy-Versioning'], 'auto') self.assertEqual(int(r['X-Container-Policy-Quota']), 0) t2 = datetime.datetime.strptime(r['Last-Modified'], DATE_FORMATS[2]) delta = (t2 - t1) threashold = datetime.timedelta(seconds=1) self.assertTrue(delta < threashold) self.assertTrue(r['X-Container-Object-Meta']) (self.assertTrue('foo%s' % i in r['X-Container-Object-Meta']) for i in range(len(objects)))
def test_params_create(self): from synnefo.vmapi.models import create_server_params from synnefo.vmapi import backend try: from synnefo.db.models import VirtualMachine except ImportError: print "Skipping test_params_create" return # mimic server creation signal called vm = VirtualMachine() params = {'password': '******', 'personality': {}} uuid = create_server_params(sender=vm, created_vm_params=params) self.assertEqual(vm.config_url, join_urls(BASE_HOST, self.api_path, 'server-params/%s' % uuid)) key = "vmapi_%s" % uuid self.assertEqual(type(backend.get(key)), str) data = json.loads(backend.get(key)) self.assertEqual('password' in data, True) self.assertEqual('personality' in data, True) self.assertEqual(data.get('password'), 'X^942Jjfdsa') response = self.myget('server-params/%s' % uuid) self.assertEqual(response.status_code, 200) response = self.myget('server-params/%s' % uuid) self.assertEqual(response.status_code, 404)
def test_forbidden(self): container = self.create_container(user='******')[0] obj = self.upload_object(container, user='******')[0] url = join_urls(self.view_path, 'alice', container, obj) r = self.view(url) self.assertEqual(r.status_code, 403)
def delete_container_content(self, cname, user=None, verify_status=True): user = user or self.user url = join_urls(self.pithos_path, user, cname) r = self.delete('%s?delimiter=/' % url, user=user) if verify_status: self.assertEqual(r.status_code, 204) return r
def test_reset_meta(self): url = join_urls(self.pithos_path, self.user) with AssertMappingInvariant(self.get_account_groups): meta = {'test': 'tost', 'ping': 'pong'} self.update_account_meta(meta) new_meta = {'test': 'test33'} kwargs = dict(( 'HTTP_X_ACCOUNT_META_%s' % k, str(v) ) for k, v in new_meta.items()) r = self.post(url, **kwargs) self.assertEqual(r.status_code, 202) account_meta = self.get_account_meta() (self.assertTrue(k in account_meta) for k in new_meta.keys()) (self.assertEqual(account_meta[k], v) for k, v in new_meta.items()) (self.assertTrue(k not in account_meta) for k in meta.keys()) # test metadata limit limit = pithos_settings.RESOURCE_MAX_METADATA kwargs = dict(('HTTP_X_ACCOUNT_META_%s' % i, str(i)) for i in range(limit + 1)) r = self.post('%s?update=' % url, **kwargs) self.assertEqual(r.status_code, 400)
def test_reset_account_groups(self): url = join_urls(self.pithos_path, self.user) with AssertMappingInvariant(self.get_account_meta): groups = {'pithosdev': ['verigak', 'gtsouk', 'chazapis'], 'clientsdev': ['pkanavos', 'mvasilak']} headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v)) for k, v in groups.iteritems()) r = self.post('%s?update=' % url, **headers) self.assertEqual(r.status_code, 202) groups = {'pithosdev': ['verigak', 'gtsouk', 'chazapis', 'papagian']} headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v)) for k, v in groups.iteritems()) account_meta = self.get_account_meta() headers.update(dict(('HTTP_X_ACCOUNT_META_%s' % k.upper().replace('-', '_'), v) for k, v in account_meta.iteritems())) r = self.post(url, **headers) self.assertEqual(r.status_code, 202) account_groups = self.get_account_groups() self.assertTrue('Pithosdev' in account_groups) self.assertTrue('Clientsdev' not in account_groups) self.assertEqual(account_groups['Pithosdev'], ','.join(sorted(groups['pithosdev'])))
def test_list_objects_with_limit_marker(self): cname = self.cnames[0] url = join_urls(self.pithos_path, self.user, cname) r = self.get('%s?limit=qwert' % url) self.assertTrue(r.status_code != 500) r = self.get('%s?limit=2' % url) self.assertEqual(r.status_code, 200) objects = r.content.split('\n') if '' in objects: objects.remove('') onames = sorted(self.objects[cname].keys()) self.assertEqual(objects, onames[:2]) markers = ['How To Win Friends And Influence People.pdf', 'moms_birthday.jpg'] limit = 4 for m in markers: r = self.get('%s?limit=%s&marker=%s' % (url, limit, m)) objects = r.content.split('\n') if '' in objects: objects.remove('') start = onames.index(m) + 1 end = start + limit end = end if len(onames) >= end else len(onames) self.assertEqual(objects, onames[start:end])
def test_update_meta(self): url = join_urls(self.pithos_path, self.user) with AssertMappingInvariant(self.get_account_groups): initial = self.get_account_meta() meta = {'Test': 'tost', 'Ping': 'pong'} kwargs = dict(('HTTP_X_ACCOUNT_META_%s' % k, str(v)) for k, v in meta.items()) r = self.post('%s?update=' % url, **kwargs) self.assertEqual(r.status_code, 202) meta.update(initial) account_meta = self.get_account_meta() self.assertEqual(account_meta, meta) # test metadata limit limit = pithos_settings.RESOURCE_MAX_METADATA kwargs = dict(('HTTP_X_ACCOUNT_META_%s' % i, str(i)) for i in range(limit - len(meta) + 1)) r = self.post('%s?update=' % url, **kwargs) self.assertEqual(r.status_code, 400) meta.update(initial) account_meta = self.get_account_meta() self.assertEqual(account_meta, meta)
def test_if_modified_since_invalid_date(self): cname = 'apples' url = join_urls(self.pithos_path, self.user, cname) r = self.get(url, HTTP_IF_MODIFIED_SINCE='Monday') self.assertEqual(r.status_code, 200) self.assertEqual(r.content.split('\n')[:-1], sorted(self.objects['apples'].keys()))
def test_public_if_none_match(self): # upload object cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] def assert_non_match(etag): # perform get with If-None-Match r = self.get(public_url, HTTP_IF_NONE_MATCH=etag) # assert precondition_failed self.assertEqual(r.status_code, 304) # update object data r = self.append_object_data(cname, oname)[-1] self.assertTrue(etag != r['ETag']) # perform get with If-None-Match r = self.get(public_url, HTTP_IF_NONE_MATCH=etag) # assert get success self.assertEqual(r.status_code, 200) if pithos_settings.UPDATE_MD5: assert_non_match(md5_hash(odata)) else: assert_non_match(merkle(odata))
def test_list_until(self): account_info = self.get_account_info() t = datetime.datetime.strptime(account_info['Last-Modified'], DATE_FORMATS[2]) t1 = t + datetime.timedelta(seconds=1) until = int(_time.mktime(t1.timetuple())) _time.sleep(2) cname = self.cnames[0] self.upload_object(cname) oname = self.objects[cname].keys()[-1] self.delete_object(cname, oname) url = join_urls(self.pithos_path, self.user, cname) r = self.get('%s?until=%s' % (url, until)) self.assertTrue(r.status_code, 200) objects = r.content.split('\n') if '' in objects: objects.remove('') self.assertEqual(objects, sorted(self.objects[cname].keys())) r = self.get('%s?until=%s&format=json' % (url, until)) self.assertTrue(r.status_code, 200) try: objects = json.loads(r.content) except: self.fail('json format expected') self.assertEqual([o['name'] for o in objects], sorted(self.objects[cname].keys()))
def test_public_if_modified_sinse(self): cname = get_random_name() self.create_container(cname) oname, odata = self.upload_object(cname)[:-1] self._assert_not_public_object(cname, oname) # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public = info['X-Object-Public'] object_info = self.get_object_info(cname, oname) last_modified = object_info['Last-Modified'] t1 = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) t1_formats = map(t1.strftime, DATE_FORMATS) for t in t1_formats: r = self.get(public, user='******', HTTP_IF_MODIFIED_SINCE=t, token=None) self.assertEqual(r.status_code, 304) _time.sleep(1) # update object data appended_data = self.append_object_data(cname, oname)[1] # Check modified since for t in t1_formats: r = self.get(public, user='******', HTTP_IF_MODIFIED_SINCE=t, token=None) self.assertEqual(r.status_code, 200) self.assertEqual(r.content, odata + appended_data)
def test_upload_blocks(self): cname = self.create_container()[0] url = join_urls(self.pithos_path, self.user, cname) r = self.post(url, data=get_random_data()) self.assertEqual(r.status_code, 202) url = join_urls(self.pithos_path, 'chuck', cname) r = self.post(url, data=get_random_data()) self.assertEqual(r.status_code, 403) # share object for read only oname = self.upload_object(cname)[0] url = join_urls(self.pithos_path, self.user, cname, oname) self.post(url, content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_OBJECT_SHARING='read=*') url = join_urls(self.pithos_path, 'chuck', cname) r = self.post(url, data=get_random_data()) self.assertEqual(r.status_code, 403) # share object for write only oname = self.upload_object(cname)[0] url = join_urls(self.pithos_path, self.user, cname, oname) self.post(url, content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_OBJECT_SHARING='write=*') url = join_urls(self.pithos_path, 'chuck', cname) r = self.post(url, data=get_random_data()) self.assertEqual(r.status_code, 403)
def test_objects_with_trailing_spaces(self): cname = self.cname r = self.view(quote('%s ' % self.view_url)) self.assertEqual(r.status_code, 404) # delete object self.delete(self.api_url) r = self.view(self.view_url) self.assertEqual(r.status_code, 404) # upload object with trailing space oname = self.upload_object(cname, quote('%s ' % get_random_name()))[0] view_url = join_urls(self.view_path, self.user, cname, oname) r = self.view(view_url) self.assertEqual(r.status_code, 200) view_url = join_urls(self.view_path, self.user, cname, oname[:-1]) r = self.view(view_url) self.assertEqual(r.status_code, 404)
def test_list_limit_exceeds(self): self.create_container('container') url = join_urls(self.pithos_path, self.user, 'container') for _ in range(pithos_settings.API_LIST_LIMIT + 1): self.upload_object('container') r = self.get('%s?format=json' % url) try: objects = json.loads(r.content) except: self.fail('json format expected') self.assertEqual(pithos_settings.API_LIST_LIMIT, len(objects))
def upload_object(self, cname, oname=None, length=None, verify_status=True, user=None, **meta): oname = oname or get_random_name() length = length or random.randint(TEST_BLOCK_SIZE, 2 * TEST_BLOCK_SIZE) user = user or self.user data = get_random_data(length=length) headers = dict(('HTTP_X_OBJECT_META_%s' % k.upper(), v) for k, v in meta.iteritems()) url = join_urls(self.pithos_path, user, cname, oname) r = self.put(url, user=user, data=data, **headers) if verify_status: self.assertEqual(r.status_code, 201) return oname, data, r
def test_update_metadata_item(self, backend): backend().__enter__().get_image.return_value = self.image request = {'metadata': {'foo': 'bar_new', 'foo4': 'bar4'}} response = self.post(join_urls(IMAGES_URL, '42/metadata'), 'user', json.dumps(request), 'json') self.assertEqual(response.status_code, 201) backend().__enter__().update_metadata.assert_called_once_with( '42', {'properties': { 'foo': 'bar_new', 'foo2': 'bar2', 'foo4': 'bar4' }})
def reset_account_meta(self, meta, user=None, verify_status=True): user = user or self.user kwargs = dict( ('HTTP_X_ACCOUNT_META_%s' % k, str(v)) for k, v in meta.items()) url = join_urls(self.pithos_path, user) r = self.post(url, user=user, **kwargs) if verify_status: self.assertEqual(r.status_code, 202) account_meta = self.get_account_meta(user=user) (self.assertTrue('X-Account-Meta-%s' % k in account_meta) for k in meta.keys()) (self.assertEqual(account_meta['X-Account-Meta-%s' % k], v) for k, v in meta.items())
def get_account_info(self, until=None, user=None, verify_status=True): user = user or self.user url = join_urls(self.pithos_path, user) if until is not None: parts = list(urlsplit(url)) parts[3] = urlencode({ 'until': until }) url = urlunsplit(parts) r = self.head(url, user=user) if verify_status: self.assertEqual(r.status_code, 204) return r
def delete_account_meta(self, meta, user=None, verify_status=True): user = user or self.user transform = lambda k: 'HTTP_X_ACCOUNT_META_%s' %\ k.replace('-', '_').upper() kwargs = dict((transform(k), '') for k in meta) url = join_urls(self.pithos_path, user) r = self.post('%s?update=' % url, user=user, **kwargs) if verify_status: self.assertEqual(r.status_code, 202) account_meta = self.get_account_meta(user=user) (self.assertTrue('X-Account-Meta-%s' % k not in account_meta) for k in meta.keys()) return r
def test_public_if_public_not_modified_since(self): cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] last_modified = info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) # Check unmodified t1 = t + datetime.timedelta(seconds=1) t1_formats = map(t1.strftime, DATE_FORMATS) for t in t1_formats: r = self.get(public_url, HTTP_IF_UNMODIFIED_SINCE=t) self.assertEqual(r.status_code, 200) self.assertEqual("".join(r.streaming_content), odata) # modify object _time.sleep(2) self.append_object_data(cname, oname) info = self.get_object_info(cname, oname) last_modified = info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) t2 = t - datetime.timedelta(seconds=1) t2_formats = map(t2.strftime, DATE_FORMATS) # check modified for t in t2_formats: r = self.get(public_url, HTTP_IF_UNMODIFIED_SINCE=t) self.assertEqual(r.status_code, 412) # modify account: update object meta _time.sleep(1) self.update_object_meta(cname, oname, {'foo': 'bar'}) info = self.get_object_info(cname, oname) last_modified = info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) t3 = t - datetime.timedelta(seconds=1) t3_formats = map(t3.strftime, DATE_FORMATS) # check modified for t in t3_formats: r = self.get(public_url, HTTP_IF_UNMODIFIED_SINCE=t) self.assertEqual(r.status_code, 412)
def test_delete_public_object_history(self): cname = get_random_name() self.create_container(cname) oname, odata = self.upload_object(cname)[:-1] self._assert_not_public_object(cname, oname) # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) public = self._assert_public_object(cname, oname, odata) for _ in range(random.randint(1, 10)): odata += self.append_object_data(cname, oname)[1] _time.sleep(1) # get object versions url = join_urls(self.pithos_path, self.user, cname, oname) r = self.get('%s?version=list&format=json' % url) version_list = json.loads(r.content)['versions'] mtime = [int(float(t[1])) for t in version_list] # delete object history i = random.randrange(len(mtime)) self.delete('%s?until=%d' % (url, mtime[i])) public2 = self._assert_public_object(cname, oname, odata) self.assertEqual(public, public2) # delete object history until now _time.sleep(1) t = datetime.datetime.utcnow() now = int(_time.mktime(t.timetuple())) r = self.delete('%s?intil=%d' % (url, now)) self.assertEqual(r.status_code, 204) r = self.get(url) self.assertEqual(r.status_code, 404) r = self.get(public) self.assertEqual(r.status_code, 404)
def test_method_not_allowed(self, *args): # /images/ allows only POST, GET response = self.put(IMAGES_URL, '', '') self.assertMethodNotAllowed(response) response = self.delete(IMAGES_URL, '') self.assertMethodNotAllowed(response) # /images/<imgid>/ allows only GET, DELETE response = self.post(join_urls(IMAGES_URL, "42"), 'user') self.assertMethodNotAllowed(response) response = self.put(join_urls(IMAGES_URL, "42"), 'user') self.assertMethodNotAllowed(response) # /images/<imgid>/metadata/ allows only POST, GET response = self.put(join_urls(IMAGES_URL, "42", "metadata"), 'user') self.assertMethodNotAllowed(response) response = self.delete(join_urls(IMAGES_URL, "42", "metadata"), 'user') self.assertMethodNotAllowed(response) # /images/<imgid>/metadata/<key> allows only PUT, GET, DELETE response = self.post(join_urls(IMAGES_URL, "42", "metadata", "foo"), 'user') self.assertMethodNotAllowed(response)
def list_objects(self, cname, prefix=None, user=None, verify_status=True): user = user or self.user url = join_urls(self.pithos_path, user, cname) path = '%s?format=json' % url if prefix is not None: path = '%s&prefix=%s' % (path, prefix) r = self.get(path, user=user) if verify_status: self.assertTrue(r.status_code in (200, 204)) try: objects = json.loads(r.content) except: self.fail('json format expected') return objects
def test_if_unmodified_since(self): cname = 'apples' url = join_urls(self.pithos_path, self.user, cname) container_info = self.get_container_info(cname) last_modified = container_info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) t = t + datetime.timedelta(seconds=1) t_formats = map(t.strftime, DATE_FORMATS) for tf in t_formats: r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=tf) self.assertEqual(r.status_code, 200) self.assertEqual( r.content.split('\n')[:-1], sorted(self.objects['apples']))
def test_delete_meta(self): url = join_urls(self.pithos_path, self.user) with AssertMappingInvariant(self.get_account_groups): meta = {'test': 'tost', 'ping': 'pong'} self.update_account_meta(meta) kwargs = dict( ('HTTP_X_ACCOUNT_META_%s' % k, '') for k, v in meta.items()) r = self.post('%s?update=' % url, **kwargs) self.assertEqual(r.status_code, 202) account_meta = self.get_account_meta() (self.assertTrue(k not in account_meta) for k in meta.keys())
def test_update_subnet_allocation_pools(self): """Update the allocation pools of a subnet, raises 400 BadRequest""" test_net = mf.NetworkFactory() test_sub = mf.IPv4SubnetFactory(network=test_net) request = { 'subnet': { 'allocation_pools': [{ 'start': '10.0.3.0', 'end': '10.0.3.255'} ]} } url = join_urls(SUBNETS_URL, str(test_sub.id)) response = self.put(url, test_net.userid, json.dumps(request), "json") self.assertBadRequest(response)
def test_public_if_modified_since_invalid_date(self): cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] r = self.get(public_url, HTTP_IF_MODIFIED_SINCE='Monday') self.assertEqual(r.status_code, 200) self.assertEqual("".join(r.streaming_content), odata)
def test_delete_object(self): self.create_container('φάκελος') self.upload_object('φάκελος', 'αντικείμενο') url = join_urls(self.pithos_path, self.user, 'φάκελος') r = self.get(url) self.assertEqual(r.status_code, 200) objects = r.content.split('\n') self.assertTrue('αντικείμενο' in objects) url = join_urls(self.pithos_path, self.user, 'φάκελος', 'αντικείμενο') r = self.head(url) self.assertEqual(r.status_code, 200) r = self.get(url) self.assertEqual(r.status_code, 200) r = self.delete(url) r = self.head(url) self.assertEqual(r.status_code, 404) r = self.get(url) self.assertEqual(r.status_code, 404) url = join_urls(self.pithos_path, self.user, 'φάκελος') r = self.get(url) objects = r.content.split('\n') self.assertTrue('αντικείμενο' not in objects)
def test_public_if_match_precondition_failed(self): cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] # perform get with If-Match r = self.get(public_url, HTTP_IF_MATCH=get_random_name()) self.assertEqual(r.status_code, 412)
def test_update_meta(self): url = join_urls(self.pithos_path, self.user) with AssertMappingInvariant(self.get_account_groups): initial = self.get_account_meta() meta = {'test': 'tost', 'ping': 'pong'} kwargs = dict(('HTTP_X_ACCOUNT_META_%s' % k, str(v)) for k, v in meta.items()) r = self.post('%s?update=' % url, **kwargs) self.assertEqual(r.status_code, 202) meta.update(initial) account_meta = self.get_account_meta() (self.assertTrue(k in account_meta) for k in meta.keys()) (self.assertEqual(account_meta[k], v) for k, v in meta.items())
def create_container(self, cname=None, user=None, verify_status=True, meta=None): meta = meta or {} cname = cname or get_random_name() user = user or self.user url = join_urls(self.pithos_path, user, cname) kwargs = dict( ('HTTP_X_CONTAINER_META_%s' % k, str(v)) for k, v in meta.items()) r = self.put(url, user=user, data='', **kwargs) if verify_status: self.assertTrue(r.status_code in (202, 201)) return cname, r
def test_authenticate(self): url = join_urls(self.pithos_path, '/') r = self.get(url, token=None) self.assertEqual(r.status_code, 400) r = self.get(url, token=None, HTTP_X_AUTH_USER=self.user) self.assertEqual(r.status_code, 400) r = self.get(url, token=None, HTTP_X_AUTH_USER=self.user, HTTP_X_AUTH_KEY='DummyToken') self.assertEqual(r.status_code, 204) self.assertTrue('X-Auth-Token' in r) self.assertTrue(r['X-Auth-Token'], 'DummyToken')
def update_container_meta(self, container, meta=None, user=None, verify_status=True): user = user or self.user meta = meta or {get_random_name(): get_random_name()} kwargs = dict( ('HTTP_X_CONTAINER_META_%s' % k, str(v)) for k, v in meta.items()) url = join_urls(self.pithos_path, user, container) r = self.post('%s?update=' % url, user=user, **kwargs) if verify_status: self.assertEqual(r.status_code, 202) container_meta = self.get_container_meta(container, user=user) (self.assertTrue('X-Container-Meta-%s' % k in container_meta) for k in meta.keys()) (self.assertEqual(container_meta['X-Container-Meta-%s' % k], v) for k, v in meta.items()) return r
def get_object_info(self, container, object, version=None, until=None, user=None, verify_status=True): user = user or self.user url = join_urls(self.pithos_path, user, container, object) if until is not None: parts = list(urlsplit(url)) parts[3] = urlencode({ 'until': until }) url = urlunsplit(parts) if version: url = '%s?version=%s' % (url, version) r = self.head(url, user=user) if verify_status: self.assertEqual(r.status_code, 200) return r
def update_object_meta(self, container, object, meta=None, user=None, verify_status=True): user = user or self.user meta = meta or {get_random_name(): get_random_name()} kwargs = dict( ('HTTP_X_OBJECT_META_%s' % k, str(v)) for k, v in meta.items()) url = join_urls(self.pithos_path, user, container, object) r = self.post('%s?update=' % url, user=user, content_type='', **kwargs) if verify_status: self.assertEqual(r.status_code, 202) object_meta = self.get_object_meta(container, object, user=user) (self.assertTrue('X-Objecr-Meta-%s' % k in object_meta) for k in meta.keys()) (self.assertEqual(object_meta['X-Object-Meta-%s' % k], v) for k, v in meta.items()) return r
def test_extended_list_json(self): url = join_urls(self.pithos_path, self.user, 'apples') params = { 'format': 'json', 'limit': 2, 'prefix': 'photos/animals', 'delimiter': '/' } r = self.get('%s?%s' % (url, urlencode(params))) self.assertEqual(r.status_code, 200) try: objects = json.loads(r.content) except: self.fail('json format expected') self.assertEqual(objects[0]['subdir'], 'photos/animals/cats/') self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/')
def fill_endpoints(services, base_url): for name, service in services.iteritems(): prefix = service['prefix'] endpoints = service['endpoints'] for endpoint in endpoints: try: expose_version = endpoint['SNF:exposeVersion'] except KeyError: endpoint['SNF:exposeVersion'] = expose_version = True version = endpoint['versionId'] if expose_version else "" publicURL = endpoint['publicURL'] if publicURL is not None: continue publicURL = join_urls(base_url, prefix, version).rstrip('/') endpoint['publicURL'] = publicURL
def test_update_from_another_object(self): self.create_container('κουβάς') initial_data = self.upload_object('κουβάς', 'νέο')[1] length = TEST_BLOCK_SIZE + random.randint(1, TEST_BLOCK_SIZE - 1) src_data = self.upload_object('κουβάς', 'πηγή', length=length)[1] url = join_urls(self.pithos_path, self.user, 'κουβάς', 'νέο') r = self.post(url, content_type='', HTTP_CONTENT_RANGE='bytes */*', HTTP_X_SOURCE_OBJECT='/κουβάς/πηγή') self.assertEqual(r.status_code, 204) r = self.get(url) self.assertEqual(r.status_code, 200) self.assertEqual("".join(r.streaming_content), initial_data + src_data)
def test_if_not_modified_since(self): cname = 'apples' url = join_urls(self.pithos_path, self.user, cname) container_info = self.get_container_info(cname) last_modified = container_info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) # Check unmodified t1 = t + datetime.timedelta(seconds=1) t1_formats = map(t1.strftime, DATE_FORMATS) for t in t1_formats: r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t) self.assertEqual(r.status_code, 200) self.assertEqual( r.content.split('\n')[:-1], sorted(self.objects['apples'])) # modify account: add container _time.sleep(2) self.upload_object(cname) container_info = self.get_container_info(cname) last_modified = container_info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) t2 = t - datetime.timedelta(seconds=1) t2_formats = map(t2.strftime, DATE_FORMATS) # Check modified for t in t2_formats: r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t) self.assertEqual(r.status_code, 412) # modify account: update account meta _time.sleep(1) self.update_container_meta(cname, {'foo': 'bar'}) container_info = self.get_container_info(cname) last_modified = container_info['Last-Modified'] t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1]) t3 = t - datetime.timedelta(seconds=1) t3_formats = map(t3.strftime, DATE_FORMATS) # Check modified for t in t3_formats: r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t) self.assertEqual(r.status_code, 412)
def test_public_if_none_match_star(self): # upload object cname = self.create_container()[0] oname, odata = self.upload_object(cname)[:-1] # set public url = join_urls(self.pithos_path, self.user, cname, oname) r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true') self.assertEqual(r.status_code, 202) info = self.get_object_info(cname, oname) public_url = info['X-Object-Public'] # perform get with If-None-Match with star r = self.get(public_url, HTTP_IF_NONE_MATCH='*') self.assertEqual(r.status_code, 304)
def test_group_delete(self): # create a group headers = {'HTTP_X_ACCOUNT_GROUP_γκρουπ': 'chazapis,διογένης'} url = join_urls(self.pithos_path, self.user) r = self.post(url, **headers) self.assertEqual(r.status_code, 202) groups = self.get_account_groups() self.assertTrue('γκρουπ' in groups) self.assertEqual(groups['γκρουπ'], 'chazapis,διογένης') headers = {'HTTP_X_ACCOUNT_GROUP_γκρουπ': ''} r = self.post('%s?update=' % url, **headers) self.assertEqual(r.status_code, 202) groups = self.get_account_groups() self.assertTrue('γκρουπ' not in groups)