Statistics
| Branch: | Tag: | Revision:

root / astakosclient / astakosclient / tests.py @ 480974e6

History | View | Annotate | Download (37.5 kB)

1
#!/usr/bin/env python
2
#
3
# Copyright (C) 2012, 2013 GRNET S.A. All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or
6
# without modification, are permitted provided that the following
7
# conditions are met:
8
#
9
#   1. Redistributions of source code must retain the above
10
#      copyright notice, this list of conditions and the following
11
#      disclaimer.
12
#
13
#   2. Redistributions in binary form must reproduce the above
14
#      copyright notice, this list of conditions and the following
15
#      disclaimer in the documentation and/or other materials
16
#      provided with the distribution.
17
#
18
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
# POSSIBILITY OF SUCH DAMAGE.
30
#
31
# The views and conclusions contained in the software and
32
# documentation are those of the authors and should not be
33
# interpreted as representing official policies, either expressed
34
# or implied, of GRNET S.A.
35

    
36
"""Unit Tests for the astakos-client module
37

38
Provides unit tests for the code implementing
39
the astakos client library
40

41
"""
42

    
43
import sys
44
import socket
45
import simplejson
46

    
47
import astakosclient
48
from astakosclient import AstakosClient
49
from astakosclient.errors import \
50
    AstakosClientException, Unauthorized, BadRequest, NotFound, \
51
    NoUserName, NoUUID, BadValue, QuotaLimit
52

    
53
# Use backported unittest functionality if Python < 2.7
54
try:
55
    import unittest2 as unittest
56
except ImportError:
57
    if sys.version_info < (2, 7):
58
        raise Exception("The unittest2 package is required for Python < 2.7")
59
    import unittest
60

    
61

    
62
# --------------------------------------------------------------------
63
# Helper functions
64

    
65
# ----------------------------
66
# This functions will be used as mocked requests
67
def _request_offline(conn, method, url, **kwargs):
68
    """This request behaves as we were offline"""
69
    raise socket.gaierror
70

    
71

    
72
def _request_status_302(conn, method, url, **kwargs):
73
    """This request returns 302"""
74
    message = "FOUND"
75
    status = 302
76
    data = '<html>\r\n<head><title>302 Found</title></head>\r\n' \
77
        '<body bgcolor="white">\r\n<center><h1>302 Found</h1></center>\r\n' \
78
        '<hr><center>nginx/0.7.67</center>\r\n</body>\r\n</html>\r\n'
79
    return (message, data, status)
80

    
81

    
82
def _request_status_404(conn, method, url, **kwargs):
83
    """This request returns 404"""
84
    message = "Not Found"
85
    status = 404
86
    data = '<html><head><title>404 Not Found</title></head>' \
87
        '<body><h1>Not Found</h1><p>The requested URL /foo was ' \
88
        'not found on this server.</p><hr><address>Apache Server ' \
89
        'at example.com Port 80</address></body></html>'
90
    return (message, data, status)
91

    
92

    
93
def _request_status_401(conn, method, url, **kwargs):
94
    """This request returns 401"""
95
    message = "UNAUTHORIZED"
96
    status = 401
97
    data = "Invalid X-Auth-Token\n"
98
    return (message, data, status)
99

    
100

    
101
def _request_status_400(conn, method, url, **kwargs):
102
    """This request returns 400"""
103
    message = "BAD REQUEST"
104
    status = 400
105
    data = "Method not allowed.\n"
106
    return (message, data, status)
107

    
108

    
109
def _request_ok(conn, method, url, **kwargs):
110
    """This request behaves like original Astakos does"""
111
    if url.startswith("/im/authenticate"):
112
        return _req_authenticate(conn, method, url, **kwargs)
113
    elif url.startswith("/user_catalogs"):
114
        return _req_catalogs(conn, method, url, **kwargs)
115
    elif url.startswith("/astakos/api/resources"):
116
        return _req_resources(conn, method, url, **kwargs)
117
    elif url.startswith("/astakos/api/quotas"):
118
        return _req_quotas(conn, method, url, **kwargs)
119
    elif url.startswith("/astakos/api/commissions"):
120
        return _req_commission(conn, method, url, **kwargs)
121
    else:
122
        return _request_status_404(conn, method, url, **kwargs)
123

    
124

    
125
def _req_authenticate(conn, method, url, **kwargs):
126
    """Check if user exists and return his profile"""
127
    global user_1, user_2, token_1, token_2
128

    
129
    # Check input
130
    if conn.__class__.__name__ != "HTTPSConnection":
131
        return _request_status_302(conn, method, url, **kwargs)
132
    if method != "GET":
133
        return _request_status_400(conn, method, url, **kwargs)
134
    token = kwargs['headers'].get('X-Auth-Token')
135
    if token == token_1:
136
        user = dict(user_1)
137
    elif token == token_2:
138
        user = dict(user_2)
139
    else:
140
        # No user found
141
        return _request_status_401(conn, method, url, **kwargs)
142

    
143
    # Return
144
    if "usage=1" not in url:
145
        # Strip `usage' key from `user'
146
        del user['usage']
147
    return ("", simplejson.dumps(user), 200)
148

    
149

    
150
def _req_catalogs(conn, method, url, **kwargs):
151
    """Return user catalogs"""
152
    global token_1, token_2, user_1, user_2
153

    
154
    # Check input
155
    if conn.__class__.__name__ != "HTTPSConnection":
156
        return _request_status_302(conn, method, url, **kwargs)
157
    if method != "POST":
158
        return _request_status_400(conn, method, url, **kwargs)
159
    token = kwargs['headers'].get('X-Auth-Token')
160
    if token != token_1 and token != token_2:
161
        return _request_status_401(conn, method, url, **kwargs)
162

    
163
    # Return
164
    body = simplejson.loads(kwargs['body'])
165
    if 'uuids' in body:
166
        # Return uuid_catalog
167
        uuids = body['uuids']
168
        catalogs = {}
169
        if user_1['uuid'] in uuids:
170
            catalogs[user_1['uuid']] = user_1['username']
171
        if user_2['uuid'] in uuids:
172
            catalogs[user_2['uuid']] = user_2['username']
173
        return_catalog = {"displayname_catalog": {}, "uuid_catalog": catalogs}
174
    elif 'displaynames' in body:
175
        # Return displayname_catalog
176
        names = body['displaynames']
177
        catalogs = {}
178
        if user_1['username'] in names:
179
            catalogs[user_1['username']] = user_1['uuid']
180
        if user_2['username'] in names:
181
            catalogs[user_2['username']] = user_2['uuid']
182
        return_catalog = {"displayname_catalog": catalogs, "uuid_catalog": {}}
183
    else:
184
        return_catalog = {"displayname_catalog": {}, "uuid_catalog": {}}
185
    return ("", simplejson.dumps(return_catalog), 200)
186

    
187

    
188
def _req_resources(conn, method, url, **kwargs):
189
    """Return quota resources"""
190
    global resources
191

    
192
    # Check input
193
    if conn.__class__.__name__ != "HTTPSConnection":
194
        return _request_status_302(conn, method, url, **kwargs)
195
    if method != "GET":
196
        return _request_status_400(conn, method, url, **kwargs)
197

    
198
    # Return
199
    return ("", simplejson.dumps(resources), 200)
200

    
201

    
202
def _req_quotas(conn, method, url, **kwargs):
203
    """Return quotas for user_1"""
204
    global token_1, quotas
205

    
206
    # Check input
207
    if conn.__class__.__name__ != "HTTPSConnection":
208
        return _request_status_302(conn, method, url, **kwargs)
209
    if method != "GET":
210
        return _request_status_400(conn, method, url, **kwargs)
211
    token = kwargs['headers'].get('X-Auth-Token')
212
    if token != token_1:
213
        return _request_status_401(conn, method, url, **kwargs)
214

    
215
    # Return
216
    return ("", simplejson.dumps(quotas), 200)
217

    
218

    
219
def _req_commission(conn, method, url, **kwargs):
220
    """Perform a commission for user_1"""
221
    global token_1, pending_commissions, \
222
        commission_successful_response, commission_failure_response
223

    
224
    # Check input
225
    if conn.__class__.__name__ != "HTTPSConnection":
226
        return _request_status_302(conn, method, url, **kwargs)
227
    token = kwargs['headers'].get('X-Auth-Token')
228
    if token != token_1:
229
        return _request_status_401(conn, method, url, **kwargs)
230

    
231
    if method == "POST":
232
        if 'body' not in kwargs:
233
            return _request_status_400(conn, method, url, **kwargs)
234
        body = simplejson.loads(unicode(kwargs['body']))
235
        if url == "/astakos/api/commissions":
236
            # Issue Commission
237
            # Check if we have enough resources to give
238
            if body['provisions'][1]['quantity'] > 420000000:
239
                return ("", simplejson.dumps(commission_failure_response), 413)
240
            else:
241
                return \
242
                    ("", simplejson.dumps(commission_successful_response), 200)
243
        else:
244
            # Issue commission action
245
            serial = url.split('/')[4]
246
            if serial == "action":
247
                # Resolve multiple actions
248
                if body == resolve_commissions_req:
249
                    return ("", simplejson.dumps(resolve_commissions_rep), 200)
250
                else:
251
                    return _request_status_400(conn, method, url, **kwargs)
252
            else:
253
                # Issue action for one commission
254
                if serial != str(57):
255
                    return _request_status_404(conn, method, url, **kwargs)
256
                if len(body) != 1:
257
                    return _request_status_400(conn, method, url, **kwargs)
258
                if "accept" not in body.keys() and "reject" not in body.keys():
259
                    return _request_status_400(conn, method, url, **kwargs)
260
                return ("", "", 200)
261

    
262
    elif method == "GET":
263
        if url == "/astakos/api/commissions":
264
            # Return pending commission
265
            return ("", simplejson.dumps(pending_commissions), 200)
266
        else:
267
            # Return commissions's description
268
            serial = url[25:]
269
            if serial == str(57):
270
                return ("", simplejson.dumps(commission_description), 200)
271
            else:
272
                return _request_status_404(conn, method, url, **kwargs)
273
    else:
274
        return _request_status_400(conn, method, url, **kwargs)
275

    
276

    
277
# ----------------------------
278
# Mock the actual _doRequest
279
def _mock_request(new_requests):
280
    """Mock the actual request
281

282
    Given a list of requests to use (in rotation),
283
    replace the original _doRequest function with
284
    a new one
285

286
    """
287
    def _mock(conn, method, url, **kwargs):
288
        # Get first request
289
        request = _mock.requests[0]
290
        # Rotate requests
291
        _mock.requests = _mock.requests[1:] + _mock.requests[:1]
292
        # Use first request
293
        return request(conn, method, url, **kwargs)
294

    
295
    _mock.requests = new_requests
296
    # Replace `_doRequest' with our `_mock'
297
    astakosclient._do_request = _mock
298

    
299

    
300
# ----------------------------
301
# Local users
302
token_1 = "skzleaFlBl+fasFdaf24sx=="
303
user_1 = \
304
    {"username": "user1@example.com",
305
     "auth_token_created": 1359386939000,
306
     "name": "Example User One",
307
     "email": ["user1@example.com"],
308
     "auth_token_expires": 1361978939000,
309
     "id": 108,
310
     "uuid": "73917abc-abcd-477e-a1f1-1763abcdefab",
311
     "usage": [
312
         {"currValue": 42949672960,
313
          "display_name": "System Disk",
314
          "name": "cyclades.disk"},
315
         {"currValue": 4,
316
          "display_name": "CPU",
317
          "name": "cyclades.cpu"},
318
         {"currValue": 4294967296,
319
          "display_name": "RAM",
320
          "name": "cyclades.ram"},
321
         {"currValue": 3,
322
          "display_name": "VM",
323
          "name": "cyclades.vm"},
324
         {"currValue": 0,
325
          "display_name": "private network",
326
          "name": "cyclades.network.private"},
327
         {"currValue": 152,
328
          "display_name": "Storage Space",
329
          "name": "pithos+.diskspace"}]}
330

    
331
token_2 = "fasdfDSFdf98923DF+sdfk=="
332
user_2 = \
333
    {"username": "user2@example.com",
334
     "auth_token_created": 1358386938997,
335
     "name": "Example User Two",
336
     "email": ["user1@example.com"],
337
     "auth_token_expires": 1461998939000,
338
     "id": 109,
339
     "uuid": "73917bca-1234-5678-a1f1-1763abcdefab",
340
     "usage": [
341
         {"currValue": 68719476736,
342
          "display_name": "System Disk",
343
          "name": "cyclades.disk"},
344
         {"currValue": 1,
345
          "display_name": "CPU",
346
          "name": "cyclades.cpu"},
347
         {"currValue": 1073741824,
348
          "display_name": "RAM",
349
          "name": "cyclades.ram"},
350
         {"currValue": 2,
351
          "display_name": "VM",
352
          "name": "cyclades.vm"},
353
         {"currValue": 1,
354
          "display_name": "private network",
355
          "name": "cyclades.network.private"},
356
         {"currValue": 2341634510,
357
          "display_name": "Storage Space",
358
          "name": "pithos+.diskspace"}]}
359

    
360
resources = {
361
    "cyclades.vm": {
362
        "unit": None,
363
        "description": "Number of virtual machines",
364
        "service": "cyclades"},
365
    "cyclades.ram": {
366
        "unit": "bytes",
367
        "description": "Virtual machine memory",
368
        "service": "cyclades"}}
369

    
370
quotas = {
371
    "system": {
372
        "cyclades.ram": {
373
            "pending": 0,
374
            "limit": 1073741824,
375
            "usage": 536870912},
376
        "cyclades.vm": {
377
            "pending": 0,
378
            "limit": 2,
379
            "usage": 2}},
380
    "project:1": {
381
        "cyclades.ram": {
382
            "pending": 0,
383
            "limit": 2147483648,
384
            "usage": 2147483648},
385
        "cyclades.vm": {
386
            "pending": 1,
387
            "limit": 5,
388
            "usage": 2}}}
389

    
390
commission_request = {
391
    "force": False,
392
    "auto_accept": False,
393
    "provisions": [
394
        {
395
            "holder": "c02f315b-7d84-45bc-a383-552a3f97d2ad",
396
            "source": "system",
397
            "resource": "cyclades.vm",
398
            "quantity": 1
399
        },
400
        {
401
            "holder": "c02f315b-7d84-45bc-a383-552a3f97d2ad",
402
            "source": "system",
403
            "resource": "cyclades.ram",
404
            "quantity": 30000
405
        }]}
406

    
407
commission_successful_response = {"serial": 57}
408

    
409
commission_failure_response = {
410
    "overLimit": {
411
        "message": "a human-readable error message",
412
        "code": 413,
413
        "data": {
414
            "provision": {
415
                "holder": "c02f315b-7d84-45bc-a383-552a3f97d2ad",
416
                "source": "system",
417
                "resource": "cyclades.ram",
418
                "quantity": 520000000},
419
            "name": "NoCapacityError",
420
            "limit": 600000000,
421
            "usage": 180000000}}}
422

    
423
pending_commissions = [100, 200]
424

    
425
commission_description = {
426
    "serial": 57,
427
    "issue_time": "2013-04-08T10:19:15.0373",
428
    "provisions": [
429
        {
430
            "holder": "c02f315b-7d84-45bc-a383-552a3f97d2ad",
431
            "source": "system",
432
            "resource": "cyclades.vm",
433
            "quantity": 1
434
        },
435
        {
436
            "holder": "c02f315b-7d84-45bc-a383-552a3f97d2ad",
437
            "source": "system",
438
            "resource": "cyclades.ram",
439
            "quantity": 536870912
440
        }]}
441

    
442
resolve_commissions_req = {
443
    "accept": [56, 57],
444
    "reject": [56, 58, 59]}
445

    
446
resolve_commissions_rep = {
447
    "accepted": [57],
448
    "rejected": [59],
449
    "failed": [
450
        [56, {
451
            "badRequest": {
452
                "message": "cannot both accept and reject serial 56",
453
                "code": 400}}],
454
        [58, {
455
            "itemNotFound": {
456
                "message": "serial 58 does not exist",
457
                "code": 404}}]]}
458

    
459

    
460
# --------------------------------------------------------------------
461
# The actual tests
462

    
463
class TestCallAstakos(unittest.TestCase):
464
    """Test cases for function _callAstakos"""
465

    
466
    # ----------------------------------
467
    # Test the response we get if we don't have internet access
468
    def _offline(self, pool):
469
        global token_1
470
        _mock_request([_request_offline])
471
        try:
472
            client = AstakosClient("https://example.com", use_pool=pool)
473
            client._call_astakos(token_1, "/im/authenticate")
474
        except AstakosClientException:
475
            pass
476
        else:
477
            self.fail("Should have raised AstakosClientException")
478

    
479
    def test_offline(self):
480
        """Test _offline without pool"""
481
        self._offline(False)
482

    
483
    def test_offline_pool(self):
484
        """Test _offline using pool"""
485
        self._offline(True)
486

    
487
    # ----------------------------------
488
    # Test the response we get if we send invalid token
489
    def _invalid_token(self, pool):
490
        token = "skaksaFlBl+fasFdaf24sx=="
491
        _mock_request([_request_ok])
492
        try:
493
            client = AstakosClient("https://example.com", use_pool=pool)
494
            client._call_astakos(token, "/im/authenticate")
495
        except Unauthorized:
496
            pass
497
        except Exception:
498
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
499
        else:
500
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
501

    
502
    def test_invalid_token(self):
503
        """Test _invalid_token without pool"""
504
        self._invalid_token(False)
505

    
506
    def test_invalid_token_pool(self):
507
        """Test _invalid_token using pool"""
508
        self._invalid_token(True)
509

    
510
    # ----------------------------------
511
    # Test the response we get if we send invalid url
512
    def _invalid_url(self, pool):
513
        global token_1
514
        _mock_request([_request_ok])
515
        try:
516
            client = AstakosClient("https://example.com", use_pool=pool)
517
            client._call_astakos(token_1, "/im/misspelled")
518
        except NotFound:
519
            pass
520
        except Exception:
521
            self.fail("Should have returned 404 (Not Found)")
522
        else:
523
            self.fail("Should have returned 404 (Not Found)")
524

    
525
    def test_invalid_url(self):
526
        """Test _invalid_url without pool"""
527
        self._invalid_url(False)
528

    
529
    def test_invalid_url_pool(self):
530
        """Test _invalid_url using pool"""
531
        self._invalid_url(True)
532

    
533
    # ----------------------------------
534
    # Test the response we get if we use an unsupported scheme
535
    def _unsupported_scheme(self, pool):
536
        global token_1
537
        _mock_request([_request_ok])
538
        try:
539
            client = AstakosClient("ftp://example.com", use_pool=pool)
540
            client._call_astakos(token_1, "/im/authenticate")
541
        except BadValue:
542
            pass
543
        except Exception:
544
            self.fail("Should have raise BadValue Exception")
545
        else:
546
            self.fail("Should have raise BadValue Exception")
547

    
548
    def test_unsupported_scheme(self):
549
        """Test _unsupported_scheme without pool"""
550
        self._unsupported_scheme(False)
551

    
552
    def test_unsupported_scheme_pool(self):
553
        """Test _unsupported_scheme using pool"""
554
        self._unsupported_scheme(True)
555

    
556
    # ----------------------------------
557
    # Test the response we get if we use http instead of https
558
    def _http_scheme(self, pool):
559
        global token_1
560
        _mock_request([_request_ok])
561
        try:
562
            client = AstakosClient("http://example.com", use_pool=pool)
563
            client._call_astakos(token_1, "/im/authenticate")
564
        except AstakosClientException as err:
565
            if err.status != 302:
566
                self.fail("Should have returned 302 (Found)")
567
        else:
568
            self.fail("Should have returned 302 (Found)")
569

    
570
    def test_http_scheme(self):
571
        """Test _http_scheme without pool"""
572
        self._http_scheme(False)
573

    
574
    def test_http_scheme_pool(self):
575
        """Test _http_scheme using pool"""
576
        self._http_scheme(True)
577

    
578
    # ----------------------------------
579
    # Test the response we get if we use authenticate with POST
580
    def _post_authenticate(self, pool):
581
        global token_1
582
        _mock_request([_request_ok])
583
        try:
584
            client = AstakosClient("https://example.com", use_pool=pool)
585
            client._call_astakos(token_1, "/im/authenticate", method="POST")
586
        except BadRequest:
587
            pass
588
        except Exception:
589
            self.fail("Should have returned 400 (Method not allowed)")
590
        else:
591
            self.fail("Should have returned 400 (Method not allowed)")
592

    
593
    def test_post_authenticate(self):
594
        """Test _post_authenticate without pool"""
595
        self._post_authenticate(False)
596

    
597
    def test_post_authenticate_pool(self):
598
        """Test _post_authenticate using pool"""
599
        self._post_authenticate(True)
600

    
601
    # ----------------------------------
602
    # Test the response if we request user_catalogs with GET
603
    def _get_user_catalogs(self, pool):
604
        global token_1
605
        _mock_request([_request_ok])
606
        try:
607
            client = AstakosClient("https://example.com", use_pool=pool)
608
            client._call_astakos(token_1, "/user_catalogs")
609
        except BadRequest:
610
            pass
611
        except Exception:
612
            self.fail("Should have returned 400 (Method not allowed)")
613
        else:
614
            self.fail("Should have returned 400 (Method not allowed)")
615

    
616
    def test_get_user_catalogs(self):
617
        """Test _get_user_catalogs without pool"""
618
        self._get_user_catalogs(False)
619

    
620
    def test_get_user_catalogs_pool(self):
621
        """Test _get_user_catalogs using pool"""
622
        self._get_user_catalogs(True)
623

    
624

    
625
class TestAuthenticate(unittest.TestCase):
626
    """Test cases for function getUserInfo"""
627

    
628
    # ----------------------------------
629
    # Test the response we get if we don't have internet access
630
    def test_offline(self):
631
        """Test offline after 3 retries"""
632
        global token_1
633
        _mock_request([_request_offline])
634
        try:
635
            client = AstakosClient("https://example.com", retry=3)
636
            client.get_user_info(token_1)
637
        except AstakosClientException:
638
            pass
639
        else:
640
            self.fail("Should have raised AstakosClientException exception")
641

    
642
    # ----------------------------------
643
    # Test the response we get for invalid token
644
    def _invalid_token(self, pool):
645
        token = "skaksaFlBl+fasFdaf24sx=="
646
        _mock_request([_request_ok])
647
        try:
648
            client = AstakosClient("https://example.com", use_pool=pool)
649
            client.get_user_info(token)
650
        except Unauthorized:
651
            pass
652
        except Exception:
653
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
654
        else:
655
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
656

    
657
    def test_invalid_token(self):
658
        """Test _invalid_token without pool"""
659
        self._invalid_token(False)
660

    
661
    def test_invalid_token_pool(self):
662
        """Test _invalid_token using pool"""
663
        self._invalid_token(True)
664

    
665
    #- ---------------------------------
666
    # Test response for user 1
667
    def _auth_user(self, token, user_info, usage, pool):
668
        _mock_request([_request_ok])
669
        try:
670
            client = AstakosClient("https://example.com", use_pool=pool)
671
            auth_info = client.get_user_info(token, usage=usage)
672
        except:
673
            self.fail("Shouldn't raise an Exception")
674
        self.assertEqual(user_info, auth_info)
675

    
676
    def test_auth_user_one(self):
677
        """Test _auth_user for User 1 without pool, without usage"""
678
        global token_1, user_1
679
        user_info = dict(user_1)
680
        del user_info['usage']
681
        self._auth_user(token_1, user_info, False, False)
682

    
683
    def test_auth_user_one_usage(self):
684
        """Test _auth_user for User 1 without pool, with usage"""
685
        global token_1, user_1
686
        self._auth_user(token_1, user_1, True, False)
687

    
688
    def test_auth_user_one_usage_pool(self):
689
        """Test _auth_user for User 1 using pool, with usage"""
690
        global token_1, user_1
691
        self._auth_user(token_1, user_1, True, True)
692

    
693
    def test_auth_user_two(self):
694
        """Test _auth_user for User 2 without pool, without usage"""
695
        global token_2, user_2
696
        user_info = dict(user_2)
697
        del user_info['usage']
698
        self._auth_user(token_2, user_info, False, False)
699

    
700
    def test_auth_user_two_usage(self):
701
        """Test _auth_user for User 2 without pool, with usage"""
702
        global token_2, user_2
703
        self._auth_user(token_2, user_2, True, False)
704

    
705
    def test_auth_user_two_usage_pool(self):
706
        """Test _auth_user for User 2 using pool, with usage"""
707
        global token_2, user_2
708
        self._auth_user(token_2, user_2, True, True)
709

    
710
    # ----------------------------------
711
    # Test retry functionality
712
    def test_offline_retry(self):
713
        """Test retry functionality for getUserInfo"""
714
        global token_1, user_1
715
        _mock_request([_request_offline, _request_offline, _request_ok])
716
        try:
717
            client = AstakosClient("https://example.com", retry=2)
718
            auth_info = client.get_user_info(token_1, usage=True)
719
        except:
720
            self.fail("Shouldn't raise an Exception")
721
        self.assertEqual(user_1, auth_info)
722

    
723

    
724
class TestDisplayNames(unittest.TestCase):
725
    """Test cases for functions getDisplayNames/getDisplayName"""
726

    
727
    # ----------------------------------
728
    # Test the response we get for invalid token
729
    def test_invalid_token(self):
730
        """Test the response we get for invalid token (without pool)"""
731
        global user_1
732
        token = "skaksaFlBl+fasFdaf24sx=="
733
        _mock_request([_request_ok])
734
        try:
735
            client = AstakosClient("https://example.com")
736
            client.get_usernames(token, [user_1['uuid']])
737
        except Unauthorized:
738
            pass
739
        except Exception:
740
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
741
        else:
742
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
743

    
744
    # ----------------------------------
745
    # Get Info for both users
746
    def test_usernames(self):
747
        """Test get_usernames with both users"""
748
        global token_1, user_1, user_2
749
        _mock_request([_request_ok])
750
        try:
751
            client = AstakosClient("https://example.com")
752
            catalog = client.get_usernames(
753
                token_1, [user_1['uuid'], user_2['uuid']])
754
        except:
755
            self.fail("Shouldn't raise an Exception")
756
        self.assertEqual(catalog[user_1['uuid']], user_1['username'])
757
        self.assertEqual(catalog[user_2['uuid']], user_2['username'])
758

    
759
    # ----------------------------------
760
    # Get info for user 1
761
    def test_username_user_one(self):
762
        """Test get_username for User One"""
763
        global token_2, user_1
764
        _mock_request([_request_offline, _request_ok])
765
        try:
766
            client = AstakosClient(
767
                "https://example.com", use_pool=True, retry=2)
768
            info = client.get_username(token_2, user_1['uuid'])
769
        except:
770
            self.fail("Shouldn't raise an Exception")
771
        self.assertEqual(info, user_1['username'])
772

    
773
    # ----------------------------------
774
    # Get info with wrong uuid
775
    def test_no_username(self):
776
        global token_1
777
        _mock_request([_request_ok])
778
        try:
779
            client = AstakosClient("https://example.com")
780
            client.get_username(token_1, "1234")
781
        except NoUserName:
782
            pass
783
        except:
784
            self.fail("Should have raised NoDisplayName exception")
785
        else:
786
            self.fail("Should have raised NoDisplayName exception")
787

    
788

    
789
class TestGetUUIDs(unittest.TestCase):
790
    """Test cases for functions getUUIDs/getUUID"""
791

    
792
    # ----------------------------------
793
    # Test the response we get for invalid token
794
    def test_invalid_token(self):
795
        """Test the response we get for invalid token (using pool)"""
796
        global user_1
797
        token = "skaksaFlBl+fasFdaf24sx=="
798
        _mock_request([_request_ok])
799
        try:
800
            client = AstakosClient("https://example.com")
801
            client.get_uuids(token, [user_1['username']])
802
        except Unauthorized:
803
            pass
804
        except Exception:
805
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
806
        else:
807
            self.fail("Should have returned 401 (Invalid X-Auth-Token)")
808

    
809
    # ----------------------------------
810
    # Get info for both users
811
    def test_uuids(self):
812
        """Test get_uuids with both users"""
813
        global token_1, user_1, user_2
814
        _mock_request([_request_ok])
815
        try:
816
            client = AstakosClient("https://example.com")
817
            catalog = client.get_uuids(
818
                token_1, [user_1['username'], user_2['username']])
819
        except:
820
            self.fail("Shouldn't raise an Exception")
821
        self.assertEqual(catalog[user_1['username']], user_1['uuid'])
822
        self.assertEqual(catalog[user_2['username']], user_2['uuid'])
823

    
824
    # ----------------------------------
825
    # Get uuid for user 2
826
    def test_get_uuid_user_two(self):
827
        """Test get_uuid for User Two"""
828
        global token_1, user_2
829
        _mock_request([_request_offline, _request_ok])
830
        try:
831
            client = AstakosClient("https://example.com", retry=1)
832
            info = client.get_uuid(token_2, user_1['username'])
833
        except:
834
            self.fail("Shouldn't raise an Exception")
835
        self.assertEqual(info, user_1['uuid'])
836

    
837
    # ----------------------------------
838
    # Get uuid with wrong username
839
    def test_no_uuid(self):
840
        global token_1
841
        _mock_request([_request_ok])
842
        try:
843
            client = AstakosClient("https://example.com")
844
            client.get_uuid(token_1, "1234")
845
        except NoUUID:
846
            pass
847
        except:
848
            self.fail("Should have raised NoUUID exception")
849
        else:
850
            self.fail("Should have raised NoUUID exception")
851

    
852

    
853
class TestResources(unittest.TestCase):
854
    """Test cases for function get_resources"""
855

    
856
    # ----------------------------------
857
    def test_get_resources(self):
858
        """Test function call of get_resources"""
859
        global resources
860
        _mock_request([_request_offline, _request_ok])
861
        try:
862
            client = AstakosClient("https://example.com", retry=1)
863
            result = client.get_resources()
864
        except Exception as err:
865
            self.fail("Shouldn't raise Exception %s" % err)
866
        self.assertEqual(resources, result)
867

    
868

    
869
class TestQuotas(unittest.TestCase):
870
    """Test cases for function get_quotas"""
871

    
872
    # ----------------------------------
873
    def test_get_quotas(self):
874
        """Test function call of get_quotas"""
875
        global quotas, token_1
876
        _mock_request([_request_ok])
877
        try:
878
            client = AstakosClient("https://example.com")
879
            result = client.get_quotas(token_1)
880
        except Exception as err:
881
            self.fail("Shouldn't raise Exception %s" % err)
882
        self.assertEqual(quotas, result)
883

    
884
    # -----------------------------------
885
    def test_get_quotas_unauthorized(self):
886
        """Test function call of get_quotas with wrong token"""
887
        global token_2
888
        _mock_request([_request_ok])
889
        try:
890
            client = AstakosClient("https://example.com")
891
            client.get_quotas(token_2)
892
        except Unauthorized:
893
            pass
894
        except Exception as err:
895
            self.fail("Shouldn't raise Exception %s" % err)
896
        else:
897
            self.fail("Should have raised Unauthorized Exception")
898

    
899
    # ----------------------------------
900
    def test_get_quotas_without_token(self):
901
        """Test function call of get_quotas without token"""
902
        _mock_request([_request_ok])
903
        try:
904
            client = AstakosClient("https://example.com")
905
            client.get_quotas(None)
906
        except Unauthorized:
907
            pass
908
        except Exception as err:
909
            self.fail("Shouldn't raise Exception %s" % err)
910
        else:
911
            self.fail("Should have raised Unauthorized Exception")
912

    
913

    
914
class TestCommissions(unittest.TestCase):
915
    """Test cases for quota commissions"""
916

    
917
    # ----------------------------------
918
    def test_issue_commission(self):
919
        """Test function call of issue_commission"""
920
        global token_1, commission_request, commission_successful_reqsponse
921
        _mock_request([_request_ok])
922
        try:
923
            client = AstakosClient("https://example.com")
924
            response = client.issue_commission(token_1, commission_request)
925
        except Exception as err:
926
            self.fail("Shouldn't raise Exception %s" % err)
927
        self.assertEqual(response, commission_successful_response['serial'])
928

    
929
    # ----------------------------------
930
    def test_issue_commission_quota_limit(self):
931
        """Test function call of issue_commission with limit exceeded"""
932
        global token_1, commission_request, commission_failure_response
933
        _mock_request([_request_ok])
934
        new_request = dict(commission_request)
935
        new_request['provisions'][1]['quantity'] = 520000000
936
        try:
937
            client = AstakosClient("https://example.com")
938
            client.issue_commission(token_1, new_request)
939
        except QuotaLimit:
940
            pass
941
        except Exception as err:
942
            self.fail("Shouldn't raise Exception %s" % err)
943
        else:
944
            self.fail("Should have raised QuotaLimit Exception")
945

    
946
    # ----------------------------------
947
    def test_issue_one_commission(self):
948
        """Test function call of issue_one_commission"""
949
        global token_1, commission_successful_response
950
        _mock_request([_request_ok])
951
        try:
952
            client = AstakosClient("https://example.com")
953
            response = client.issue_one_commission(
954
                token_1, "c02f315b-7d84-45bc-a383-552a3f97d2ad",
955
                "system", [("cyclades.vm", 1), ("cyclades.ram", 30000)])
956
        except Exception as err:
957
            self.fail("Shouldn't have raised Exception %s" % err)
958
        self.assertEqual(response, commission_successful_response['serial'])
959

    
960
    # ----------------------------------
961
    def test_get_pending_commissions(self):
962
        """Test function call of get_pending_commissions"""
963
        global token_1, pending_commissions
964
        _mock_request([_request_ok])
965
        try:
966
            client = AstakosClient("https://example.com")
967
            response = client.get_pending_commissions(token_1)
968
        except Exception as err:
969
            self.fail("Shouldn't raise Exception %s" % err)
970
        self.assertEqual(response, pending_commissions)
971

    
972
    # ----------------------------------
973
    def test_get_commission_info(self):
974
        """Test function call of get_commission_info"""
975
        global token_1, commission_description
976
        _mock_request([_request_ok])
977
        try:
978
            client = \
979
                AstakosClient("https://example.com", use_pool=True, pool_size=2)
980
            response = client.get_commission_info(token_1, 57)
981
        except Exception as err:
982
            self.fail("Shouldn't raise Exception %s" % err)
983
        self.assertEqual(response, commission_description)
984

    
985
    # ----------------------------------
986
    def test_get_commission_info_not_found(self):
987
        """Test function call of get_commission_info with invalid serial"""
988
        global token_1
989
        _mock_request([_request_ok])
990
        try:
991
            client = AstakosClient("https://example.com")
992
            client.get_commission_info(token_1, "57lala")
993
        except NotFound:
994
            pass
995
        except Exception as err:
996
            self.fail("Shouldn't raise Exception %s" % err)
997
        else:
998
            self.fail("Should have raised NotFound")
999

    
1000
    # ----------------------------------
1001
    def test_get_commission_info_without_serial(self):
1002
        """Test function call of get_commission_info without serial"""
1003
        global token_1
1004
        _mock_request([_request_ok])
1005
        try:
1006
            client = AstakosClient("https://example.com")
1007
            client.get_commission_info(token_1, None)
1008
        except BadValue:
1009
            pass
1010
        except Exception as err:
1011
            self.fail("Shouldn't raise Exception %s" % err)
1012
        else:
1013
            self.fail("Should have raise BadValue")
1014

    
1015
    # ----------------------------------
1016
    def test_commision_action(self):
1017
        """Test function call of commision_action with wrong action"""
1018
        global token_1
1019
        _mock_request([_request_ok])
1020
        try:
1021
            client = AstakosClient("https://example.com")
1022
            client.commission_action(token_1, 57, "lala")
1023
        except BadRequest:
1024
            pass
1025
        except Exception as err:
1026
            self.fail("Shouldn't raise Exception %s" % err)
1027
        else:
1028
            self.fail("Should have raised BadRequest")
1029

    
1030
    # ----------------------------------
1031
    def test_accept_commission(self):
1032
        """Test function call of accept_commission"""
1033
        global token_1
1034
        _mock_request([_request_ok])
1035
        try:
1036
            client = AstakosClient("https://example.com")
1037
            client.accept_commission(token_1, 57)
1038
        except Exception as err:
1039
            self.fail("Shouldn't raise Exception %s" % err)
1040

    
1041
    # ----------------------------------
1042
    def test_reject_commission(self):
1043
        """Test function call of reject_commission"""
1044
        global token_1
1045
        _mock_request([_request_ok])
1046
        try:
1047
            client = AstakosClient("https://example.com")
1048
            client.reject_commission(token_1, 57)
1049
        except Exception as err:
1050
            self.fail("Shouldn't raise Exception %s" % err)
1051

    
1052
    # ----------------------------------
1053
    def test_accept_commission_not_found(self):
1054
        """Test function call of accept_commission with wrong serial"""
1055
        global token_1
1056
        _mock_request([_request_ok])
1057
        try:
1058
            client = AstakosClient("https://example.com")
1059
            client.reject_commission(token_1, 20)
1060
        except NotFound:
1061
            pass
1062
        except Exception as err:
1063
            self.fail("Shouldn't raise Exception %s" % err)
1064
        else:
1065
            self.fail("Should have raised NotFound")
1066

    
1067
    # ----------------------------------
1068
    def test_resolve_commissions(self):
1069
        """Test function call of resolve_commissions"""
1070
        global token_1
1071
        _mock_request([_request_ok])
1072
        try:
1073
            client = AstakosClient("https://example.com")
1074
            result = client.resolve_commissions(token_1, [56, 57], [56, 58, 59])
1075
        except Exception as err:
1076
            self.fail("Shouldn't raise Exception %s" % err)
1077
        self.assertEqual(result, resolve_commissions_rep)
1078

    
1079

    
1080
# ----------------------------
1081
# Run tests
1082
if __name__ == "__main__":
1083
    unittest.main()