Revision d6a92fa0

b/snf-common/synnefo/settings/test.py
8 8

  
9 9
DATABASES = {
10 10
    'default': {
11
        #'ENGINE': 'django.db.backends.sqlite3',
12
        #'NAME': '/tmp/synnefo_test_db.sqlite',
13

  
14
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
15
        'NAME': 'pithos',
16
        'USER': 'postgres',
17
        'PORT': '5432',
11
        'ENGINE': 'django.db.backends.sqlite3',
12
        'NAME': '/tmp/synnefo_test_db.sqlite',
18 13
    }
19 14
}
20 15

  
......
25 20

  
26 21

  
27 22
SOUTH_TESTS_MIGRATE = bool(int(os.environ.get('SOUTH_TESTS_MIGRATE', True)))
23
SNF_TEST_USE_POSTGRES = bool(int(os.environ.get('SNF_TEST_USE_POSTGRES',
24
                                                False)))
25

  
26
# override default database
27
if SNF_TEST_USE_POSTGRES:
28
    DATABASES['default'] = {
29
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
30
        'NAME': 'pithos',
31
        'TEST_NAME': 'test_pithos',
32
        'USER': 'postgres',
33
        'PORT': '5432',
34
    }
28 35

  
29 36
ASTAKOS_IM_MODULES = ['local', 'shibboleth']
30 37

  
b/snf-pithos-app/pithos/api/test/__init__.py
42 42
from pithos.backends.random_word import get_random_word
43 43
from pithos.api import settings as pithos_settings
44 44

  
45
from synnefo.lib.services import get_service_path
46
from synnefo.lib import join_urls
47

  
45 48
from django.test import TestCase
46 49
from django.utils.http import urlencode
47 50
from django.conf import settings
......
87 90
    #TODO unauthorized request
88 91
    def setUp(self):
89 92
        pithos_settings.BACKEND_DB_MODULE = 'pithos.backends.lib.sqlalchemy'
90
        pithos_settings.BACKEND_DB_CONNECTION = construct_db_connection()
93
        pithos_settings.BACKEND_DB_CONNECTION = django_to_sqlalchemy()
91 94
        pithos_settings.BACKEND_POOL_SIZE = 1
92 95
        self.user = 'user'
96
        self.pithos_path = join_urls(get_service_path(
97
            pithos_settings.pithos_services, 'object-store'))
93 98

  
94 99
    def tearDown(self):
95 100
        #delete additionally created metadata
......
137 142
    def update_account_meta(self, meta):
138 143
        kwargs = dict(
139 144
            ('HTTP_X_ACCOUNT_META_%s' % k, str(v)) for k, v in meta.items())
140
        r = self.post('/v1/%s?update=' % self.user, **kwargs)
145
        url = join_urls(self.pithos_path, self.user)
146
        r = self.post('%s?update=' % url, **kwargs)
141 147
        self.assertEqual(r.status_code, 202)
142 148
        account_meta = self.get_account_meta()
143 149
        (self.assertTrue('X-Account-Meta-%s' % k in account_meta) for
......
148 154
    def reset_account_meta(self, meta):
149 155
        kwargs = dict(
150 156
            ('HTTP_X_ACCOUNT_META_%s' % k, str(v)) for k, v in meta.items())
151
        r = self.post('/v1/%s' % self.user, **kwargs)
157
        url = join_urls(self.pithos_path, self.user)
158
        r = self.post(url, **kwargs)
152 159
        self.assertEqual(r.status_code, 202)
153 160
        account_meta = self.get_account_meta()
154 161
        (self.assertTrue('X-Account-Meta-%s' % k in account_meta) for
......
159 166
    def delete_account_meta(self, meta):
160 167
        transform = lambda k: 'HTTP_%s' % k.replace('-', '_').upper()
161 168
        kwargs = dict((transform(k), '') for k, v in meta.items())
162
        r = self.post('/v1/%s?update=' % self.user, **kwargs)
169
        url = join_urls(self.pithos_path, self.user)
170
        r = self.post('%s?update=' % url, **kwargs)
163 171
        self.assertEqual(r.status_code, 202)
164 172
        account_meta = self.get_account_meta()
165 173
        (self.assertTrue('X-Account-Meta-%s' % k not in account_meta) for
......
167 175
        return r
168 176

  
169 177
    def delete_account_groups(self, groups):
170
        r = self.post('/v1/%s?update=' % self.user, **groups)
178
        url = join_urls(self.pithos_path, self.user)
179
        r = self.post('%s?update=' % url, **groups)
171 180
        self.assertEqual(r.status_code, 202)
172 181
        return r
173 182

  
174 183
    def get_account_info(self, until=None):
175
        url = '/v1/%s' % self.user
184
        url = join_urls(self.pithos_path, self.user)
176 185
        if until is not None:
177 186
            parts = list(urlsplit(url))
178 187
            parts[3] = urlencode({
......
200 209
        return headers
201 210

  
202 211
    def list_containers(self, format='json', headers={}, **params):
203
        url = '/v1/%s' % self.user
204
        parts = list(urlsplit(url))
212
        _url = join_urls(self.pithos_path, self.user)
213
        parts = list(urlsplit(_url))
205 214
        params['format'] = format
206 215
        parts[3] = urlencode(params)
207 216
        url = urlunsplit(parts)
......
224 233
            return minidom.parseString(r.content)
225 234

  
226 235
    def delete_container_content(self, cname):
227
        r = self.delete('/v1/%s/%s?delimiter=/' % (self.user, cname))
236
        url = join_urls(self.pithos_path, self.user, cname)
237
        r = self.delete('%s?delimiter=/' % url)
228 238
        self.assertEqual(r.status_code, 204)
229 239
        return r
230 240

  
231 241
    def delete_container(self, cname):
232
        r = self.delete('/v1/%s/%s' % (self.user, cname))
242
        url = join_urls(self.pithos_path, self.user, cname)
243
        r = self.delete(url)
233 244
        self.assertEqual(r.status_code, 204)
234 245
        return r
235 246

  
236 247
    def create_container(self, cname):
237
        r = self.put('/v1/%s/%s' % (self.user, cname), data='')
248
        url = join_urls(self.pithos_path, self.user, cname)
249
        r = self.put(url, data='')
238 250
        self.assertTrue(r.status_code in (202, 201))
239 251
        return r
240 252

  
......
243 255
        data = get_random_word(length=random.randint(1, 1024))
244 256
        headers = dict(('HTTP_X_OBJECT_META_%s' % k.upper(), v)
245 257
                       for k, v in meta.iteritems())
246
        r = self.put('/v1/%s/%s/%s' % (
247
            self.user, cname, oname), data=data, **headers)
258
        url = join_urls(self.pithos_path, self.user, cname, oname)
259
        r = self.put(url, data=data, **headers)
248 260
        self.assertEqual(r.status_code, 201)
249 261
        return oname, data, r
250 262

  
251 263
    def create_folder(self, cname, oname=get_random_word(8), **headers):
252
        r = self.put('/v1/%s/%s/%s' % (
253
            self.user, cname, oname), data='',
254
            content_type='application/directory',
255
            **headers)
264
        url = join_urls(self.pithos_path, self.user, cname, oname)
265
        r = self.put(url, data='', content_type='application/directory',
266
                     **headers)
256 267
        self.assertEqual(r.status_code, 201)
257 268
        return oname, r
258 269

  
259 270
    def list_objects(self, cname):
260
        r = self.get('/v1/%s/%s?format=json' % (self.user, cname))
271
        url = join_urls(self.pithos_path, self.user, cname)
272
        r = self.get('%s?format=json' % url)
261 273
        self.assertTrue(r.status_code in (200, 204))
262 274
        try:
263 275
            objects = json.loads(r.content)
......
331 343
    'django.db.backends.oracle': 'oracle'}
332 344

  
333 345

  
334
def construct_db_connection():
335
    """Convert the django default database to an sqlalchemy connection
336
       string"""
346
def django_to_sqlalchemy():
347
    """Convert the django default database to sqlalchemy connection string"""
348
    # TODO support for more complex configuration
337 349
    db = settings.DATABASES['default']
350
    name = db.get('TEST_NAME', 'test_%s' % db['NAME'])
338 351
    if db['ENGINE'] == 'django.db.backends.sqlite3':
339
        return 'sqlite://'
352
        db.get('TEST_NAME', db['NAME'])
353
        return 'sqlite:///%s' % name
340 354
    else:
341 355
        d = dict(scheme=django_sqlalchemy_engines.get(db['ENGINE']),
342 356
                 user=db['USER'],
343 357
                 pwd=db['PASSWORD'],
344 358
                 host=db['HOST'].lower(),
345 359
                 port=int(db['PORT']) if db['PORT'] != '' else '',
346
                 name=db['NAME'])
360
                 name=name)
347 361
        return '%(scheme)s://%(user)s:%(pwd)s@%(host)s:%(port)s/%(name)s' % d
348 362

  
349 363

  
b/snf-pithos-app/pithos/api/test/accounts.py
37 37
from pithos.api.test import PithosAPITest, AssertMappingInvariant,\
38 38
    DATE_FORMATS
39 39

  
40
from synnefo.lib import join_urls
41

  
40 42
import time as _time
41 43
import datetime
42 44

  
......
181 183
        t1_formats = map(t1.strftime, DATE_FORMATS)
182 184

  
183 185
        # Check not modified
186
        url = join_urls(self.pithos_path, self.user)
184 187
        for t in t1_formats:
185
            r = self.get('/v1/%s' % self.user, HTTP_IF_MODIFIED_SINCE=t)
188
            r = self.get(url, HTTP_IF_MODIFIED_SINCE=t)
186 189
            self.assertEqual(r.status_code, 304)
187 190

  
188 191
        # modify account: add container
......
191 194

  
192 195
        # Check modified
193 196
        for t in t1_formats:
194
            r = self.get('/v1/%s' % self.user, HTTP_IF_MODIFIED_SINCE=t)
197
            r = self.get('%s' % url, HTTP_IF_MODIFIED_SINCE=t)
195 198
            self.assertEqual(r.status_code, 200)
196 199
            self.assertEqual(
197 200
                r.content.split('\n')[:-1],
......
208 211

  
209 212
        # Check modified
210 213
        for t in t2_formats:
211
            r = self.get('/v1/%s' % self.user, HTTP_IF_MODIFIED_SINCE=t)
214
            r = self.get('%s' % url, HTTP_IF_MODIFIED_SINCE=t)
212 215
            self.assertEqual(r.status_code, 200)
213 216
            self.assertEqual(
214 217
                r.content.split('\n')[:-1],
215 218
                ['apples', 'bananas', 'c1', 'kiwis', 'oranges', 'pears'])
216 219

  
217 220
    def test_if_modified_since_invalid_date(self):
218
        r = self.get('/v1/%s' % self.user, HTTP_IF_MODIFIED_SINCE='Monday')
221
        url = join_urls(self.pithos_path, self.user)
222
        r = self.get('%s' % url, HTTP_IF_MODIFIED_SINCE='Monday')
219 223
        self.assertEqual(r.status_code, 200)
220 224
        self.assertEqual(
221 225
            r.content.split('\n')[:-1],
222 226
            ['apples', 'bananas', 'kiwis', 'oranges', 'pears'])
223 227

  
224 228
    def test_if_not_modified_since(self):
229
        url = join_urls(self.pithos_path, self.user)
225 230
        account_info = self.get_account_info()
226 231
        last_modified = account_info['Last-Modified']
227 232
        t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1])
......
230 235
        t1 = t + datetime.timedelta(seconds=1)
231 236
        t1_formats = map(t1.strftime, DATE_FORMATS)
232 237
        for t in t1_formats:
233
            r = self.get('/v1/%s' % self.user, HTTP_IF_UNMODIFIED_SINCE=t)
238
            r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t)
234 239
            self.assertEqual(r.status_code, 200)
235 240
            self.assertEqual(
236 241
                r.content.split('\n')[:-1],
......
248 253

  
249 254
        # Check modified
250 255
        for t in t2_formats:
251
            r = self.get('/v1/%s' % self.user, HTTP_IF_UNMODIFIED_SINCE=t)
256
            r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t)
252 257
            self.assertEqual(r.status_code, 412)
253 258

  
254 259
        # modify account: update account meta
......
263 268

  
264 269
        # Check modified
265 270
        for t in t3_formats:
266
            r = self.get('/v1/%s' % self.user, HTTP_IF_UNMODIFIED_SINCE=t)
271
            r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t)
267 272
            self.assertEqual(r.status_code, 412)
268 273

  
269 274
    def test_if_unmodified_since_invalid_date(self):
270
        r = self.get('/v1/%s' % self.user, HTTP_IF_UNMODIFIED_SINCE='Monday')
275
        url = join_urls(self.pithos_path, self.user)
276
        r = self.get(url, HTTP_IF_UNMODIFIED_SINCE='Monday')
271 277
        self.assertEqual(r.status_code, 200)
272 278
        self.assertEqual(
273 279
            r.content.split('\n')[:-1],
......
292 298
        self.update_account_meta({'foo': 'bar'})
293 299

  
294 300
    def test_update_meta(self):
301
        url = join_urls(self.pithos_path, self.user)
295 302
        with AssertMappingInvariant(self.get_account_groups):
296 303
            initial = self.get_account_meta()
297 304

  
298 305
            meta = {'test': 'tost', 'ping': 'pong'}
299 306
            kwargs = dict(('HTTP_X_ACCOUNT_META_%s' % k, str(v))
300 307
                          for k, v in meta.items())
301
            r = self.post('/v1/%s?update=' % self.user, **kwargs)
308
            r = self.post('%s?update=' % url, **kwargs)
302 309
            self.assertEqual(r.status_code, 202)
303 310

  
304 311
            meta.update(initial)
......
309 316
                k, v in meta.items())
310 317

  
311 318
    def test_reset_meta(self):
319
        url = join_urls(self.pithos_path, self.user)
312 320
        with AssertMappingInvariant(self.get_account_groups):
313 321
            meta = {'test': 'tost', 'ping': 'pong'}
314 322
            self.update_account_meta(meta)
......
317 325
            kwargs = dict((
318 326
                'HTTP_X_ACCOUNT_META_%s' % k, str(v)
319 327
            ) for k, v in new_meta.items())
320
            r = self.post('/v1/%s' % self.user, **kwargs)
328
            r = self.post(url, **kwargs)
321 329
            self.assertEqual(r.status_code, 202)
322 330

  
323 331
            account_meta = self.get_account_meta()
......
330 338
                k in meta.keys())
331 339

  
332 340
    def test_delete_meta(self):
341
        url = join_urls(self.pithos_path, self.user)
333 342
        with AssertMappingInvariant(self.get_account_groups):
334 343
            meta = {'test': 'tost', 'ping': 'pong'}
335 344
            self.update_account_meta(meta)
336 345

  
337 346
            kwargs = dict(
338 347
                ('HTTP_X_ACCOUNT_META_%s' % k, '') for k, v in meta.items())
339
            r = self.post('/v1/%s?update=' % self.user, **kwargs)
348
            r = self.post('%s?update=' % url, **kwargs)
340 349
            self.assertEqual(r.status_code, 202)
341 350

  
342 351
            account_meta = self.get_account_meta()
......
345 354
                k in meta.keys())
346 355

  
347 356
    def test_set_account_groups(self):
357
        url = join_urls(self.pithos_path, self.user)
348 358
        with AssertMappingInvariant(self.get_account_meta):
349 359
            pithosdevs = ['verigak', 'gtsouk', 'chazapis']
350
            r = self.post(
351
                '/v1/%s?update=' % self.user,
352
                HTTP_X_ACCOUNT_GROUP_PITHOSDEV=','.join(pithosdevs))
360
            r = self.post('%s?update=' % url,
361
                          HTTP_X_ACCOUNT_GROUP_PITHOSDEV=','.join(pithosdevs))
353 362
            self.assertEqual(r.status_code, 202)
354 363

  
355 364
            account_groups = self.get_account_groups()
......
360 369
                ','.join(sorted(pithosdevs)))
361 370

  
362 371
            clientdevs = ['pkanavos', 'mvasilak']
363
            r = self.post(
364
                '/v1/%s?update=' % self.user,
365
                HTTP_X_ACCOUNT_GROUP_CLIENTSDEV=','.join(clientdevs))
372
            r = self.post('%s?update=' % url,
373
                          HTTP_X_ACCOUNT_GROUP_CLIENTSDEV=','.join(clientdevs))
366 374
            self.assertEqual(r.status_code, 202)
367 375

  
368 376
            account_groups = self.get_account_groups()
......
378 386
                ','.join(sorted(clientdevs)))
379 387

  
380 388
            clientdevs = ['mvasilak']
381
            r = self.post(
382
                '/v1/%s?update=' % self.user,
383
                HTTP_X_ACCOUNT_GROUP_CLIENTSDEV=''.join(clientdevs))
389
            r = self.post('%s?update=' % url,
390
                          HTTP_X_ACCOUNT_GROUP_CLIENTSDEV=''.join(clientdevs))
384 391
            self.assertEqual(r.status_code, 202)
385 392

  
386 393
            account_groups = self.get_account_groups()
......
396 403
                ','.join(sorted(clientdevs)))
397 404

  
398 405
    def test_reset_account_groups(self):
406
        url = join_urls(self.pithos_path, self.user)
399 407
        with AssertMappingInvariant(self.get_account_meta):
400 408
            groups = {'pithosdev': ['verigak', 'gtsouk', 'chazapis'],
401 409
                      'clientsdev': ['pkanavos', 'mvasilak']}
402 410
            headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v))
403 411
                           for k, v in groups.iteritems())
404
            r = self.post('/v1/%s?update=' % self.user, **headers)
412
            r = self.post('%s?update=' % url, **headers)
405 413
            self.assertEqual(r.status_code, 202)
406 414

  
407 415
            groups = {'pithosdev': ['verigak',
......
413 421
            account_meta = self.get_account_meta()
414 422
            headers.update(dict(('HTTP_%s' % k.upper().replace('-', '_'), v)
415 423
                           for k, v in account_meta.iteritems()))
416
            r = self.post('/v1/%s' % self.user, **headers)
424
            r = self.post(url, **headers)
417 425
            self.assertEqual(r.status_code, 202)
418 426

  
419 427
            account_groups = self.get_account_groups()
......
426 434
                ','.join(sorted(groups['pithosdev'])))
427 435

  
428 436
    def test_delete_account_groups(self):
437
        url = join_urls(self.pithos_path, self.user)
429 438
        with AssertMappingInvariant(self.get_account_meta):
430 439
            groups = {'pithosdev': ['verigak', 'gtsouk', 'chazapis'],
431 440
                      'clientsdev': ['pkanavos', 'mvasilak']}
432 441
            headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v))
433 442
                           for k, v in groups.iteritems())
434
            self.post('/v1/%s?update=' % self.user, **headers)
443
            self.post('%s?update=' % url, **headers)
435 444

  
436 445
            kwargs = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, '')
437 446
                          for k, v in groups.items())
438
            r = self.post('/v1/%s?update=' % self.user, **kwargs)
447
            r = self.post('%s?update=' % url, **kwargs)
439 448
            self.assertEqual(r.status_code, 202)
440 449

  
441 450
            account_groups = self.get_account_groups()
b/snf-pithos-app/pithos/api/test/containers.py
38 38
    strnextling, pithos_settings, pithos_test_settings
39 39
from pithos.backends.random_word import get_random_word
40 40

  
41
from synnefo.lib import join_urls
42

  
41 43
import django.utils.simplejson as json
42 44
from django.http import urlencode
43 45

  
......
62 64
            objects[name] = data
63 65

  
64 66
        t1 = datetime.datetime.utcnow()
65
        r = self.head('/v1/%s/apples' % self.user)
67
        url = join_urls(self.pithos_path, self.user, 'apples')
68
        r = self.head(url)
66 69
        self.assertEqual(int(r['X-Container-Object-Count']), len(objects))
67 70
        self.assertEqual(int(r['X-Container-Bytes-Used']),
68 71
                         sum([len(i) for i in objects.values()]))
......
103 106
        cname = self.cnames[0]
104 107
        onames = self.objects[cname].keys()
105 108
        oname = onames.pop()
106
        r = self.post('/v1/%s/%s/%s' % (self.user, cname, oname),
107
                      content_type='',
108
                      HTTP_X_OBJECT_SHARING='read=*')
109
        url = join_urls(self.pithos_path, self.user, cname, oname)
110
        r = self.post(url, content_type='', HTTP_X_OBJECT_SHARING='read=*')
109 111
        self.assertEqual(r.status_code, 202)
110 112

  
111 113
        # publish another object
112 114
        other = onames.pop()
113
        r = self.post('/v1/%s/%s/%s' % (self.user, cname, other),
114
                      content_type='',
115
                      HTTP_X_OBJECT_PUBLIC='true')
115
        url = join_urls(self.pithos_path, self.user, cname, other)
116
        r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true')
116 117
        self.assertEqual(r.status_code, 202)
117 118

  
118 119
        # list shared and assert only the shared object is returned
119
        r = self.get('/v1/%s/%s?shared=' % (self.user, cname))
120
        url = join_urls(self.pithos_path, self.user, cname)
121
        r = self.get('%s?shared=' % url)
120 122
        self.assertEqual(r.status_code, 200)
121 123
        objects = r.content.split('\n')
122 124
        objects.remove('')
123 125
        self.assertEqual([oname], objects)
124 126

  
125 127
        # list detailed shared and assert only the shared object is returned
126
        r = self.get('/v1/%s/%s?shared=&format=json' % (self.user, cname))
128
        url = join_urls(self.pithos_path, self.user, cname)
129
        r = self.get('%s?shared=&format=json' % url)
127 130
        self.assertEqual(r.status_code, 200)
128 131
        try:
129 132
            objects = json.loads(r.content)
......
135 138

  
136 139
        # publish the shared object and assert it is still listed in the
137 140
        # shared objects
138
        r = self.post('/v1/%s/%s/%s' % (self.user, cname, oname),
139
                      content_type='',
140
                      HTTP_X_OBJECT_PUBLIC='true')
141
        url = join_urls(self.pithos_path, self.user, cname, oname)
142
        r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true')
141 143
        self.assertEqual(r.status_code, 202)
142
        r = self.get('/v1/%s/%s?shared=&format=json' % (self.user, cname))
144
        url = join_urls(self.pithos_path, self.user, cname)
145
        r = self.get('%s?shared=&format=json' % url)
143 146
        self.assertEqual(r.status_code, 200)
144 147
        try:
145 148
            objects = json.loads(r.content)
......
154 157
        descendant = strnextling(oname)
155 158
        self.upload_object(cname, descendant)
156 159
        # request shared and assert child obejct is not listed
157
        r = self.get('/v1/%s/%s?shared=' % (self.user, cname))
160
        url = join_urls(self.pithos_path, self.user, cname)
161
        r = self.get('%s?shared=' % url)
158 162
        self.assertEqual(r.status_code, 200)
159 163
        objects = r.content.split('\n')
160 164
        objects.remove('')
......
167 171
        descendant = '%s/%s' % (oname, get_random_word(8))
168 172
        self.upload_object(cname, descendant)
169 173
        # request shared
170
        r = self.get('/v1/%s/%s?shared=' % (self.user, cname))
174
        url = join_urls(self.pithos_path, self.user, cname)
175
        r = self.get('%s?shared=' % url)
171 176
        self.assertEqual(r.status_code, 200)
172 177
        objects = r.content.split('\n')
173 178
        objects.remove('')
......
179 184
        cname = self.cnames[0]
180 185
        onames = self.objects[cname].keys()
181 186
        oname = onames.pop()
182
        r = self.post('/v1/%s/%s/%s' % (self.user, cname, oname),
183
                      content_type='',
184
                      HTTP_X_OBJECT_PUBLIC='true')
187
        url = join_urls(self.pithos_path, self.user, cname, oname)
188
        r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true')
185 189
        self.assertEqual(r.status_code, 202)
186 190

  
187 191
        # share another
188 192
        other = onames.pop()
189
        r = self.post('/v1/%s/%s/%s' % (self.user, cname, other),
190
                      content_type='',
191
                      HTTP_X_OBJECT_SHARING='read=alice')
193
        url = join_urls(self.pithos_path, self.user, cname, other)
194
        r = self.post(url, content_type='', HTTP_X_OBJECT_SHARING='read=alice')
192 195
        self.assertEqual(r.status_code, 202)
193 196

  
194 197
        # list public and assert only the public object is returned
195
        r = self.get('/v1/%s/%s?public=' % (self.user, cname))
198
        url = join_urls(self.pithos_path, self.user, cname)
199
        r = self.get('%s?public=' % url)
196 200
        objects = r.content.split('\n')
197 201
        self.assertEqual(r.status_code, 200)
198 202
        self.assertTrue(oname in r.content.split('\n'))
199 203
        (self.assertTrue(o not in objects) for o in o_names[1:])
200 204

  
201 205
        # list detailed public and assert only the public object is returned
202
        r = self.get('/v1/%s/%s?public=&format=json' % (self.user, cname))
206
        url = join_urls(self.pithos_path, self.user, cname)
207
        r = self.get('%s?public=&format=json' % url)
203 208
        self.assertEqual(r.status_code, 200)
204 209
        try:
205 210
            objects = json.loads(r.content)
......
211 216

  
212 217
        # share the public object and assert it is still listed in the
213 218
        # public objects
214
        r = self.post('/v1/%s/%s/%s' % (self.user, cname, oname),
215
                      content_type='',
216
                      HTTP_X_OBJECT_SHARING='read=alice')
219
        url = join_urls(self.pithos_path, self.user, cname, oname)
220
        r = self.post(url, content_type='', HTTP_X_OBJECT_SHARING='read=alice')
217 221
        self.assertEqual(r.status_code, 202)
218
        r = self.get('/v1/%s/%s?public=&format=json' % (self.user, cname))
222
        url = join_urls(self.pithos_path, self.user, cname)
223
        r = self.get('%s?public=&format=json' % url)
219 224
        self.assertEqual(r.status_code, 200)
220 225
        try:
221 226
            objects = json.loads(r.content)
......
225 230
        self.assertTrue('x_object_sharing' in objects[0])
226 231
        self.assertTrue('x_object_public' in objects[0])
227 232

  
233
        url = join_urls(self.pithos_path, self.user, cname)
234

  
228 235
        # Assert listing the container public contents is forbidden to not
229 236
        # shared users
230
        r = self.get('/v1/%s/%s?public=&format=json' % (
231
            self.user, cname), user='bob')
237
        r = self.get('%s?public=&format=json' % url, user='bob')
232 238
        self.assertEqual(r.status_code, 403)
233 239

  
234 240
        # Assert listing the container public contents to shared users
235
        r = self.get('/v1/%s/%s?public=&format=json' % (
236
            self.user, cname), user='alice')
241
        r = self.get('%s?public=&format=json' % url, user='alice')
237 242
        self.assertEqual(r.status_code, 200)
238 243
        try:
239 244
            objects = json.loads(r.content)
......
249 254
        descendant = strnextling(oname)
250 255
        self.upload_object(cname, descendant)
251 256
        # request public and assert child obejct is not listed
252
        r = self.get('/v1/%s/%s?public=' % (self.user, cname))
257
        r = self.get('%s?public=' % url)
253 258
        objects = r.content.split('\n')
254 259
        objects.remove('')
255 260
        self.assertEqual(r.status_code, 200)
......
262 267
        descendant = '%s/%s' % (oname, get_random_word(8))
263 268
        self.upload_object(cname, descendant)
264 269
        # request public
265
        r = self.get('/v1/%s/%s?public=' % (self.user, cname))
270
        r = self.get('%s?public=' % url)
266 271
        self.assertEqual(r.status_code, 200)
267 272
        objects = r.content.split('\n')
268 273
        self.assertTrue(oname in objects)
......
341 346
#
342 347
#
343 348
#        o = self.upload_random_data(self.container[1], 'folder2/object')
344
#        objs = self.client.list_objects(self.container[1], shared=True, public=True)
349
#        objs = self.client.list_objects(
350
#            self.container[1], shared=True, public=True)
345 351
#        self.assertEqual(objs, ['folder1', 'folder1/object', 'folder2'])
346 352
#        objs = cl.list_objects(
347 353
#            self.container[1], shared=True, public=True, account=get_user()
......
350 356
#
351 357
    def test_list_objects(self):
352 358
        cname = self.cnames[0]
353
        r = self.get('/v1/%s/%s' % (self.user, cname))
359
        url = join_urls(self.pithos_path, self.user, cname)
360
        r = self.get(url)
354 361
        self.assertTrue(r.status_code, 200)
355 362
        objects = r.content.split('\n')
356 363
        if '' in objects:
......
361 368
        self.create_container('test')
362 369
        self.upload_object('test', '/objectname')
363 370

  
364
        r = self.get('/v1/%s/test' % self.user)
371
        url = join_urls(self.pithos_path, self.user, 'test')
372

  
373
        r = self.get(url)
365 374
        objects = r.content.split('\n')
366 375
        if '' in objects:
367 376
            objects.remove('')
368 377
        self.assertEqual(objects, ['/objectname'])
369 378

  
370
        r = self.get('/v1/%s/test?format=json' % self.user)
379
        r = self.get('%s?format=json' % url)
371 380
        try:
372 381
            objects = json.loads(r.content)
373 382
        except:
374 383
            self.fail('json format expected')
375 384
        self.assertEqual([o['name'] for o in objects], ['/objectname'])
376 385

  
377
        r = self.get('/v1/%s/test?format=xml' % self.user)
386
        r = self.get('%s?format=xml' % url)
378 387
        try:
379 388
            objects = minidom.parseString(r.content)
380 389
        except:
......
385 394

  
386 395
    def test_list_objects_with_limit_marker(self):
387 396
        cname = self.cnames[0]
388
        r = self.get('/v1/%s/%s?limit=qwert' % (self.user, cname))
397
        url = join_urls(self.pithos_path, self.user, cname)
398
        r = self.get('%s?limit=qwert' % url)
389 399
        self.assertTrue(r.status_code != 500)
390 400

  
391
        r = self.get('/v1/%s/%s?limit=2' % (self.user, cname))
401
        r = self.get('%s?limit=2' % url)
392 402
        self.assertEqual(r.status_code, 200)
393 403
        objects = r.content.split('\n')
394 404
        if '' in objects:
......
401 411
                   'moms_birthday.jpg']
402 412
        limit = 4
403 413
        for m in markers:
404
            r = self.get('/v1/%s/%s?limit=%s&marker=%s' % (
405
                self.user, cname, limit, m))
414
            r = self.get('%s?limit=%s&marker=%s' % (url, limit, m))
406 415
            objects = r.content.split('\n')
407 416
            if '' in objects:
408 417
                objects.remove('')
......
414 423
    @pithos_test_settings(API_LIST_LIMIT=10)
415 424
    def test_list_limit_exceeds(self):
416 425
        self.create_container('container')
426
        url = join_urls(self.pithos_path, self.user, 'container')
417 427

  
418 428
        for _ in range(pithos_settings.API_LIST_LIMIT + 1):
419 429
            self.upload_object('container')
420 430

  
421
        r = self.get('/v1/%s/container?format=json' % self.user)
431
        r = self.get('%s?format=json' % url)
422 432
        try:
423 433
            objects = json.loads(r.content)
424 434
        except:
......
427 437
                         len(objects))
428 438

  
429 439
    def test_list_pseudo_hierarchical_folders(self):
430
        r = self.get('/v1/%s/apples?prefix=photos&delimiter=/' % self.user)
440
        url = join_urls(self.pithos_path, self.user, 'apples')
441
        r = self.get('%s?prefix=photos&delimiter=/' % url)
431 442
        self.assertEqual(r.status_code, 200)
432 443
        objects = r.content.split('\n')
433 444
        if '' in objects:
......
436 447
            ['photos/animals/', 'photos/me.jpg', 'photos/plants/'],
437 448
            objects)
438 449

  
439
        r = self.get(
440
            '/v1/%s/apples?prefix=photos/animals&delimiter=/' % self.user)
450
        r = self.get('%s?prefix=photos/animals&delimiter=/' % url)
441 451
        objects = r.content.split('\n')
442 452
        if '' in objects:
443 453
            objects.remove('')
444 454
        self.assertEquals(
445 455
            ['photos/animals/cats/', 'photos/animals/dogs/'], objects)
446 456

  
447
        r = self.get('/v1/%s/apples?path=photos' % self.user)
457
        r = self.get('%s?path=photos' % url)
448 458
        objects = r.content.split('\n')
449 459
        if '' in objects:
450 460
            objects.remove('')
451 461
        self.assertEquals(['photos/me.jpg'], objects)
452 462

  
453 463
    def test_extended_list_json(self):
464
        url = join_urls(self.pithos_path, self.user, 'apples')
454 465
        params = {'format': 'json', 'limit': 2, 'prefix': 'photos/animals',
455 466
                  'delimiter': '/'}
456
        r = self.get('/v1/%s/apples?%s' % (self.user, urlencode(params)))
467
        r = self.get('%s?%s' % (url, urlencode(params)))
457 468
        self.assertEqual(r.status_code, 200)
458 469
        try:
459 470
            objects = json.loads(r.content)
......
463 474
        self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/')
464 475

  
465 476
    def test_extended_list_xml(self):
477
        url = join_urls(self.pithos_path, self.user, 'apples')
466 478
        params = {'format': 'xml', 'limit': 4, 'prefix': 'photos',
467 479
                  'delimiter': '/'}
468
        r = self.get('/v1/%s/apples?%s' % (self.user, urlencode(params)))
480
        r = self.get('%s?%s' % (url, urlencode(params)))
469 481
        self.assertEqual(r.status_code, 200)
470 482
        try:
471 483
            xml = minidom.parseString(r.content)
......
484 496
    def test_list_meta_double_matching(self):
485 497
        # update object meta
486 498
        cname = 'apples'
499
        container_url = join_urls(self.pithos_path, self.user, cname)
487 500
        oname = self.objects[cname].keys().pop()
488 501
        meta = {'quality': 'aaa', 'stock': 'true'}
489 502
        headers = dict(('HTTP_X_OBJECT_META_%s' % k.upper(), v)
490 503
                       for k, v in meta.iteritems())
491
        self.post('/v1/%s/%s/%s' % (self.user, cname, oname),
492
                  content_type='', **headers)
504
        object_url = join_urls(container_url, oname)
505
        self.post(object_url, content_type='', **headers)
493 506

  
494 507
        # list objects that satisfy the criteria
495
        r = self.get('/v1/%s/%s?meta=Quality,Stock' % (self.user, cname))
508
        r = self.get('%s?meta=Quality,Stock' % container_url)
496 509
        self.assertEqual(r.status_code, 200)
497 510
        objects = r.content.split('\n')
498 511
        if '' in objects:
499 512
            objects.remove('')
500 513
        self.assertEqual(objects, [oname])
501 514

  
502
    def tearDown(self):
503
        pass
504

  
505 515
    def test_list_using_meta(self):
506 516
        # update object meta
507 517
        cname = 'apples'
518
        container_url = join_urls(self.pithos_path, self.user, cname)
519

  
508 520
        oname1 = self.objects[cname].keys().pop()
509
        self.post('/v1/%s/%s/%s' % (self.user, cname, oname1),
510
                  content_type='', HTTP_X_OBJECT_META_QUALITY='aaa')
521
        url = join_urls(container_url, oname1)
522
        self.post(url, content_type='', HTTP_X_OBJECT_META_QUALITY='aaa')
523

  
511 524
        oname2 = self.objects[cname].keys().pop()
512
        self.post('/v1/%s/%s/%s' % (self.user, cname, oname2),
513
                  content_type='', HTTP_X_OBJECT_META_QUALITY='ab')
525
        url = join_urls(container_url, cname, oname2)
526
        self.post(url, content_type='', HTTP_X_OBJECT_META_QUALITY='ab')
514 527

  
515 528
        oname3 = self.objects[cname].keys().pop()
516
        self.post('/v1/%s/%s/%s' % (self.user, cname, oname3),
517
                  content_type='', HTTP_X_OBJECT_META_STOCK='100')
529
        url = join_urls(container_url, oname3)
530
        self.post(url, content_type='', HTTP_X_OBJECT_META_STOCK='100')
531

  
518 532
        oname4 = self.objects[cname].keys().pop()
519
        self.post('/v1/%s/%s/%s' % (self.user, cname, oname4),
520
                  content_type='', HTTP_X_OBJECT_META_STOCK='200')
533
        url = join_urls(container_url, oname4)
534
        self.post(url, content_type='', HTTP_X_OBJECT_META_STOCK='200')
521 535

  
522 536
        # test multiple existence criteria matches
523
        r = self.get('/v1/%s/%s?meta=Quality,Stock' % (self.user, cname))
537
        r = self.get('%s?meta=Quality,Stock' % container_url)
524 538
        self.assertEqual(r.status_code, 200)
525 539
        objects = r.content.split('\n')
526 540
        if '' in objects:
......
528 542
        self.assertTrue(objects, sorted([oname1, oname2, oname3, oname4]))
529 543

  
530 544
        # list objects that satisfy the existence criteria
531
        r = self.get('/v1/%s/%s?meta=Stock' % (self.user, cname))
545
        r = self.get('%s?meta=Stock' % container_url)
532 546
        self.assertEqual(r.status_code, 200)
533 547
        objects = r.content.split('\n')
534 548
        if '' in objects:
......
536 550
        self.assertTrue(objects, sorted([oname3, oname4]))
537 551

  
538 552
        # test case insensitive existence criteria matching
539
        r = self.get('/v1/%s/%s?meta=quality' % (self.user, cname))
553
        r = self.get('%s?meta=quality' % container_url)
540 554
        self.assertEqual(r.status_code, 200)
541 555
        objects = r.content.split('\n')
542 556
        if '' in objects:
......
544 558
        self.assertTrue(objects, sorted([oname1, oname2]))
545 559

  
546 560
        # test do not all existencecriteria match
547
        r = self.get('/v1/%s/%s?meta=Quality,Foo' % (self.user, cname))
561
        r = self.get('%s?meta=Quality,Foo' % container_url)
548 562
        self.assertEqual(r.status_code, 200)
549 563
        objects = r.content.split('\n')
550 564
        if '' in objects:
......
552 566
        self.assertTrue(objects, sorted([oname1, oname2]))
553 567

  
554 568
        # test equals criteria
555
        r = self.get('/v1/%s/%s?meta=%s' % (self.user, cname,
556
                     quote('Quality=aaa')))
569
        r = self.get('%s?meta=%s' % (container_url, quote('Quality=aaa')))
557 570
        self.assertEqual(r.status_code, 200)
558 571
        objects = r.content.split('\n')
559 572
        if '' in objects:
......
561 574
        self.assertTrue(objects, [oname1])
562 575

  
563 576
        # test not equals criteria
564
        r = self.get('/v1/%s/%s?meta=%s' % (self.user, cname,
565
                     urlencode('Quality!=aaa')))
577
        r = self.get('%s?meta=%s' % (container_url, urlencode('Quality!=aaa')))
566 578
        self.assertEqual(r.status_code, 200)
567 579
        objects = r.content.split('\n')
568 580
        if '' in objects:
......
570 582
        self.assertTrue(objects, [oname2])
571 583

  
572 584
        # test lte criteria
573
        r = self.get('/v1/%s/%s?meta=%s' % (self.user, cname,
574
                     urlencode('Stock<=120')))
585
        r = self.get('%s?meta=%s' % (container_url, urlencode('Stock<=120')))
575 586
        self.assertEqual(r.status_code, 200)
576 587
        objects = r.content.split('\n')
577 588
        if '' in objects:
......
579 590
        self.assertTrue(objects, [oname3])
580 591

  
581 592
        # test gte criteria
582
        r = self.get('/v1/%s/%s?meta=%s' % (self.user, cname,
583
                     urlencode('Stock>=200')))
593
        r = self.get('%s?meta=%s' % (container_url, urlencode('Stock>=200')))
584 594
        self.assertEqual(r.status_code, 200)
585 595
        objects = r.content.split('\n')
586 596
        if '' in objects:
......
626 636
#        since = now + datetime.timedelta(1)
627 637
#
628 638
#        for f in DATE_FORMATS:
629
#            obj = self.client.list_objects(self.container[0],
630
#                                           if_unmodified_since=since.strftime(f))
639
#            obj = self.client.list_objects(
640
#                self.container[0], if_unmodified_since=since.strftime(f))
631 641
#
632 642
#            #assert unmodified
633 643
#            self.assertEqual(obj, self.client.list_objects(self.container[0]))
......
676 686
#
677 687
#        args = [self.containers[0], 'o1']
678 688
#        kwargs = {'length':101}
679
#        self.assert_raises_fault(413, self.upload_random_data, *args, **kwargs)
689
#        self.assert_raises_fault(
690
#            413, self.upload_random_data, *args, **kwargs)
680 691
#
681 692
#        #reset quota
682 693
#        policy = {'quota':0}

Also available in: Unified diff