Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / test.py @ 9c6c3d69

History | View | Annotate | Download (10.5 kB)

1 85898ca4 Stavros Sachtouris
# Copyright 2013 GRNET S.A. All rights reserved.
2 c1004a00 Stavros Sachtouris
#
3 c1004a00 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 c1004a00 Stavros Sachtouris
# without modification, are permitted provided that the following
5 c1004a00 Stavros Sachtouris
# conditions are met:
6 c1004a00 Stavros Sachtouris
#
7 c1004a00 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 c1004a00 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 c1004a00 Stavros Sachtouris
#      disclaimer.
10 c1004a00 Stavros Sachtouris
#
11 c1004a00 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 c1004a00 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 c1004a00 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 c1004a00 Stavros Sachtouris
#      provided with the distribution.
15 c1004a00 Stavros Sachtouris
#
16 c1004a00 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 c1004a00 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 c1004a00 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 c1004a00 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 c1004a00 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 c1004a00 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 c1004a00 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 c1004a00 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 c1004a00 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 c1004a00 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 c1004a00 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 c1004a00 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 c1004a00 Stavros Sachtouris
#
29 c1004a00 Stavros Sachtouris
# The views and conclusions contained in the software and
30 c1004a00 Stavros Sachtouris
# documentation are those of the authors and should not be
31 c1004a00 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 c1004a00 Stavros Sachtouris
# or implied, of GRNET S.A.
33 c1004a00 Stavros Sachtouris
34 db113224 Stavros Sachtouris
from unittest import makeSuite, TestSuite, TextTestRunner, TestCase
35 db113224 Stavros Sachtouris
from time import sleep
36 85898ca4 Stavros Sachtouris
from inspect import getmembers, isclass
37 f4de4c91 Stavros Sachtouris
from json import loads
38 9c6c3d69 Stavros Sachtouris
from random import randint
39 c1004a00 Stavros Sachtouris
40 27058e48 Stavros Sachtouris
from kamaki.clients.connection.test import (
41 27058e48 Stavros Sachtouris
    KamakiConnection,
42 27058e48 Stavros Sachtouris
    KamakiHTTPConnection,
43 27058e48 Stavros Sachtouris
    KamakiResponse,
44 27058e48 Stavros Sachtouris
    KamakiHTTPResponse)
45 480585cd Stavros Sachtouris
from kamaki.clients.utils.test import Utils
46 85898ca4 Stavros Sachtouris
from kamaki.clients.astakos.test import Astakos
47 55faa0bc Stavros Sachtouris
from kamaki.clients.compute.test import Compute, ComputeRest
48 55faa0bc Stavros Sachtouris
from kamaki.clients.cyclades.test import Cyclades, CycladesRest
49 85898ca4 Stavros Sachtouris
from kamaki.clients.image.test import Image
50 c608d6e9 Stavros Sachtouris
from kamaki.clients.storage.test import Storage
51 55faa0bc Stavros Sachtouris
from kamaki.clients.pithos.test import Pithos, PithosRest
52 c1004a00 Stavros Sachtouris
53 c1004a00 Stavros Sachtouris
54 f4de4c91 Stavros Sachtouris
class ClientError(TestCase):
55 f4de4c91 Stavros Sachtouris
56 f4de4c91 Stavros Sachtouris
    def test___init__(self):
57 f4de4c91 Stavros Sachtouris
        from kamaki.clients import ClientError
58 f4de4c91 Stavros Sachtouris
        for msg, status, details, exp_msg, exp_status, exp_details in (
59 f4de4c91 Stavros Sachtouris
                ('some msg', 42, 0.28, 0, 0, 0),
60 f4de4c91 Stavros Sachtouris
                ('some msg', 'fail', [], 0, 0, 0),
61 f4de4c91 Stavros Sachtouris
                ('some msg', 42, 'details on error', 0, 0, 0),
62 f4de4c91 Stavros Sachtouris
                (
63 f4de4c91 Stavros Sachtouris
                    '404 {"ExampleError":'
64 f4de4c91 Stavros Sachtouris
                    ' {"message": "a msg", "code": 42, "details": "dets"}}',
65 f4de4c91 Stavros Sachtouris
                    404,
66 f4de4c91 Stavros Sachtouris
                    0,
67 f4de4c91 Stavros Sachtouris
                    '404 ExampleError (a msg)\n',
68 f4de4c91 Stavros Sachtouris
                    42,
69 f4de4c91 Stavros Sachtouris
                    ['dets']),
70 f4de4c91 Stavros Sachtouris
                (
71 f4de4c91 Stavros Sachtouris
                    '404 {"ExampleError":'
72 f4de4c91 Stavros Sachtouris
                    ' {"message": "a msg", "code": 42}}',
73 f4de4c91 Stavros Sachtouris
                    404,
74 f4de4c91 Stavros Sachtouris
                    'details on error',
75 f4de4c91 Stavros Sachtouris
                    '404 ExampleError (a msg)\n',
76 f4de4c91 Stavros Sachtouris
                    42,
77 f4de4c91 Stavros Sachtouris
                    0),
78 f4de4c91 Stavros Sachtouris
                (
79 f4de4c91 Stavros Sachtouris
                    '404 {"ExampleError":'
80 f4de4c91 Stavros Sachtouris
                    ' {"details": "Explain your error"}}',
81 f4de4c91 Stavros Sachtouris
                    404,
82 f4de4c91 Stavros Sachtouris
                    'details on error',
83 f4de4c91 Stavros Sachtouris
                    '404 ExampleError',
84 f4de4c91 Stavros Sachtouris
                    0,
85 f4de4c91 Stavros Sachtouris
                    ['details on error', 'Explain your error']),
86 f4de4c91 Stavros Sachtouris
                ('some msg\n', -10, ['details', 'on', 'error'], 0, 0, 0)):
87 f4de4c91 Stavros Sachtouris
            ce = ClientError(msg, status, details)
88 f4de4c91 Stavros Sachtouris
            exp_msg = exp_msg or (msg if msg.endswith('\n') else msg + '\n')
89 f4de4c91 Stavros Sachtouris
            exp_status = exp_status or status
90 f4de4c91 Stavros Sachtouris
            exp_details = exp_details or details
91 f4de4c91 Stavros Sachtouris
            self.assertEqual('%s' % ce, exp_msg)
92 f4de4c91 Stavros Sachtouris
            self.assertEqual(
93 f4de4c91 Stavros Sachtouris
                exp_status if isinstance(exp_status, int) else 0,
94 f4de4c91 Stavros Sachtouris
                ce.status)
95 f4de4c91 Stavros Sachtouris
            self.assertEqual(exp_details, ce.details)
96 db113224 Stavros Sachtouris
97 f4de4c91 Stavros Sachtouris
98 f4de4c91 Stavros Sachtouris
class SilentEvent(TestCase):
99 db113224 Stavros Sachtouris
100 27abfa9f Stavros Sachtouris
    def thread_content(self, methodid, raiseException=0):
101 db113224 Stavros Sachtouris
        wait = 0.1
102 f4de4c91 Stavros Sachtouris
        self.can_finish = -1
103 db113224 Stavros Sachtouris
        while self.can_finish < methodid and wait < 4:
104 db113224 Stavros Sachtouris
            sleep(wait)
105 db113224 Stavros Sachtouris
            wait = 2 * wait
106 27abfa9f Stavros Sachtouris
        if raiseException and raiseException == methodid:
107 27abfa9f Stavros Sachtouris
            raise Exception('Some exception')
108 03493855 Stavros Sachtouris
        self._value = methodid
109 db113224 Stavros Sachtouris
        self.assertTrue(wait < 4)
110 db113224 Stavros Sachtouris
111 db113224 Stavros Sachtouris
    def setUp(self):
112 db113224 Stavros Sachtouris
        from kamaki.clients import SilentEvent
113 db113224 Stavros Sachtouris
        self.SE = SilentEvent
114 db113224 Stavros Sachtouris
115 27abfa9f Stavros Sachtouris
    def test_run(self):
116 27abfa9f Stavros Sachtouris
        threads = [self.SE(self.thread_content, i) for i in range(4)]
117 db113224 Stavros Sachtouris
        for t in threads:
118 db113224 Stavros Sachtouris
            t.start()
119 db113224 Stavros Sachtouris
120 db113224 Stavros Sachtouris
        for i in range(4):
121 db113224 Stavros Sachtouris
            self.assertTrue(threads[i].is_alive())
122 db113224 Stavros Sachtouris
            self.can_finish = i
123 db113224 Stavros Sachtouris
            threads[i].join()
124 db113224 Stavros Sachtouris
            self.assertFalse(threads[i].is_alive())
125 db113224 Stavros Sachtouris
126 27abfa9f Stavros Sachtouris
    def test_value(self):
127 27abfa9f Stavros Sachtouris
        threads = [self.SE(self.thread_content, i) for i in range(4)]
128 27abfa9f Stavros Sachtouris
        for t in threads:
129 27abfa9f Stavros Sachtouris
            t.start()
130 27abfa9f Stavros Sachtouris
131 27abfa9f Stavros Sachtouris
        for mid, t in enumerate(threads):
132 27abfa9f Stavros Sachtouris
            if t.is_alive():
133 27abfa9f Stavros Sachtouris
                self.can_finish = mid
134 27abfa9f Stavros Sachtouris
                continue
135 27abfa9f Stavros Sachtouris
            self.assertTrue(mid, t.value)
136 27abfa9f Stavros Sachtouris
137 27abfa9f Stavros Sachtouris
    def test_exception(self):
138 27abfa9f Stavros Sachtouris
        threads = [self.SE(self.thread_content, i, (i % 2)) for i in range(4)]
139 27abfa9f Stavros Sachtouris
        for t in threads:
140 27abfa9f Stavros Sachtouris
            t.start()
141 27abfa9f Stavros Sachtouris
142 27abfa9f Stavros Sachtouris
        for i, t in enumerate(threads):
143 27abfa9f Stavros Sachtouris
            if t.is_alive():
144 27abfa9f Stavros Sachtouris
                self.can_finish = i
145 27abfa9f Stavros Sachtouris
                continue
146 27abfa9f Stavros Sachtouris
            if i % 2:
147 27abfa9f Stavros Sachtouris
                self.assertTrue(isinstance(t.exception, Exception))
148 27abfa9f Stavros Sachtouris
            else:
149 27abfa9f Stavros Sachtouris
                self.assertFalse(t.exception)
150 27abfa9f Stavros Sachtouris
151 db113224 Stavros Sachtouris
152 5a71b3a1 Stavros Sachtouris
class FakeConnection(object):
153 5a71b3a1 Stavros Sachtouris
    """A fake Connection class"""
154 5a71b3a1 Stavros Sachtouris
155 5a71b3a1 Stavros Sachtouris
    def __init__(self):
156 5a71b3a1 Stavros Sachtouris
        pass
157 5a71b3a1 Stavros Sachtouris
158 5a71b3a1 Stavros Sachtouris
159 5a71b3a1 Stavros Sachtouris
class Client(TestCase):
160 5a71b3a1 Stavros Sachtouris
161 5a71b3a1 Stavros Sachtouris
    def assert_dicts_are_equal(self, d1, d2):
162 5a71b3a1 Stavros Sachtouris
        for k, v in d1.items():
163 5a71b3a1 Stavros Sachtouris
            self.assertTrue(k in d2)
164 5a71b3a1 Stavros Sachtouris
            if isinstance(v, dict):
165 5a71b3a1 Stavros Sachtouris
                self.assert_dicts_are_equal(v, d2[k])
166 5a71b3a1 Stavros Sachtouris
            else:
167 5a71b3a1 Stavros Sachtouris
                self.assertEqual(unicode(v), unicode(d2[k]))
168 5a71b3a1 Stavros Sachtouris
169 5a71b3a1 Stavros Sachtouris
    def setUp(self):
170 5a71b3a1 Stavros Sachtouris
        from kamaki.clients import Client
171 5a71b3a1 Stavros Sachtouris
        self.base_url = 'http://example.com'
172 5a71b3a1 Stavros Sachtouris
        self.token = 's0m370k3n=='
173 5a71b3a1 Stavros Sachtouris
        self.client = Client(self.base_url, self.token, FakeConnection())
174 5a71b3a1 Stavros Sachtouris
175 5a71b3a1 Stavros Sachtouris
    def test___init__(self):
176 5a71b3a1 Stavros Sachtouris
        self.assertEqual(self.client.base_url, self.base_url)
177 5a71b3a1 Stavros Sachtouris
        self.assertEqual(self.client.token, self.token)
178 5a71b3a1 Stavros Sachtouris
        self.assert_dicts_are_equal(self.client.headers, {})
179 5a71b3a1 Stavros Sachtouris
        DATE_FORMATS = [
180 5a71b3a1 Stavros Sachtouris
            '%a %b %d %H:%M:%S %Y',
181 5a71b3a1 Stavros Sachtouris
            '%A, %d-%b-%y %H:%M:%S GMT',
182 5a71b3a1 Stavros Sachtouris
            '%a, %d %b %Y %H:%M:%S GMT']
183 5a71b3a1 Stavros Sachtouris
        self.assertEqual(self.client.DATE_FORMATS, DATE_FORMATS)
184 5a71b3a1 Stavros Sachtouris
        self.assertTrue(isinstance(self.client.http_client, FakeConnection))
185 5a71b3a1 Stavros Sachtouris
186 9c6c3d69 Stavros Sachtouris
    def test__init_thread_limit(self):
187 9c6c3d69 Stavros Sachtouris
        exp = 'Nothing set here'
188 9c6c3d69 Stavros Sachtouris
        for faulty in (-1, 0.5, 'a string', {}):
189 9c6c3d69 Stavros Sachtouris
            self.assertRaises(
190 9c6c3d69 Stavros Sachtouris
                AssertionError,
191 9c6c3d69 Stavros Sachtouris
                self.client._init_thread_limit,
192 9c6c3d69 Stavros Sachtouris
                faulty)
193 9c6c3d69 Stavros Sachtouris
            self.assertEqual(exp, getattr(self.client, '_thread_limit', exp))
194 9c6c3d69 Stavros Sachtouris
            self.assertEqual(exp, getattr(self.client, '_elapsed_old', exp))
195 9c6c3d69 Stavros Sachtouris
            self.assertEqual(exp, getattr(self.client, '_elapsed_new', exp))
196 9c6c3d69 Stavros Sachtouris
        self.client._init_thread_limit(42)
197 9c6c3d69 Stavros Sachtouris
        self.assertEqual(42, self.client._thread_limit)
198 9c6c3d69 Stavros Sachtouris
        self.assertEqual(0.0, self.client._elapsed_old)
199 9c6c3d69 Stavros Sachtouris
        self.assertEqual(0.0, self.client._elapsed_new)
200 9c6c3d69 Stavros Sachtouris
201 9c6c3d69 Stavros Sachtouris
    def test__watch_thread_limit(self):
202 9c6c3d69 Stavros Sachtouris
        waits = (
203 9c6c3d69 Stavros Sachtouris
            dict(args=((0.1, 1), (0.1, 2), (0.2, 1), (0.7, 1), (0.3, 2))),
204 9c6c3d69 Stavros Sachtouris
            dict(args=((1.0 - (i / 10.0), (i + 1)) for i in range(7))),
205 9c6c3d69 Stavros Sachtouris
            dict(max=1, args=tuple([(randint(1, 10) / 3.0, 1), ] * 10)),
206 9c6c3d69 Stavros Sachtouris
            dict(
207 9c6c3d69 Stavros Sachtouris
                limit=5,
208 9c6c3d69 Stavros Sachtouris
                args=tuple([
209 9c6c3d69 Stavros Sachtouris
                    (1.0 + (i / 10.0), (5 - i - 1)) for i in range(4)] + [
210 9c6c3d69 Stavros Sachtouris
                    (2.0, 1), (1.9, 2), (2.0, 1), (2.0, 2)])),
211 9c6c3d69 Stavros Sachtouris
            dict(args=tuple(
212 9c6c3d69 Stavros Sachtouris
                [(1.0 - (i / 10.0), (i + 1)) for i in range(7)] + [
213 9c6c3d69 Stavros Sachtouris
                (0.1, 7), (0.2, 6), (0.4, 5), (0.3, 6), (0.2, 7), (0.1, 7)])),)
214 9c6c3d69 Stavros Sachtouris
        for wait_dict in waits:
215 9c6c3d69 Stavros Sachtouris
            if 'max' in wait_dict:
216 9c6c3d69 Stavros Sachtouris
                self.client.MAX_THREADS = wait_dict['max']
217 9c6c3d69 Stavros Sachtouris
            else:
218 9c6c3d69 Stavros Sachtouris
                self.client.MAX_THREADS = 7
219 9c6c3d69 Stavros Sachtouris
            if 'limit' in wait_dict:
220 9c6c3d69 Stavros Sachtouris
                self.client._init_thread_limit(wait_dict['limit'])
221 9c6c3d69 Stavros Sachtouris
            else:
222 9c6c3d69 Stavros Sachtouris
                self.client._init_thread_limit()
223 9c6c3d69 Stavros Sachtouris
                self.client._watch_thread_limit(list())
224 9c6c3d69 Stavros Sachtouris
                self.assertEqual(1, self.client._thread_limit)
225 9c6c3d69 Stavros Sachtouris
            for wait, exp_limit in wait_dict['args']:
226 9c6c3d69 Stavros Sachtouris
                self.client._elapsed_new = wait
227 9c6c3d69 Stavros Sachtouris
                self.client._watch_thread_limit(list())
228 9c6c3d69 Stavros Sachtouris
                self.assertEqual(exp_limit, self.client._thread_limit)
229 9c6c3d69 Stavros Sachtouris
230 5a71b3a1 Stavros Sachtouris
231 85898ca4 Stavros Sachtouris
#  TestCase auxiliary methods
232 85898ca4 Stavros Sachtouris
233 657dc0c8 Stavros Sachtouris
def runTestCase(cls, test_name, args=[], failure_collector=[]):
234 657dc0c8 Stavros Sachtouris
    """
235 657dc0c8 Stavros Sachtouris
    :param cls: (TestCase) a set of Tests
236 657dc0c8 Stavros Sachtouris

237 657dc0c8 Stavros Sachtouris
    :param test_name: (str)
238 657dc0c8 Stavros Sachtouris

239 657dc0c8 Stavros Sachtouris
    :param args: (list) these are prefixed with test_ and used as params when
240 657dc0c8 Stavros Sachtouris
        instantiating cls
241 657dc0c8 Stavros Sachtouris

242 657dc0c8 Stavros Sachtouris
    :param failure_collector: (list) collects info of test failures
243 657dc0c8 Stavros Sachtouris

244 657dc0c8 Stavros Sachtouris
    :returns: (int) total # of run tests
245 657dc0c8 Stavros Sachtouris
    """
246 85898ca4 Stavros Sachtouris
    suite = TestSuite()
247 85898ca4 Stavros Sachtouris
    if args:
248 85898ca4 Stavros Sachtouris
        suite.addTest(cls('_'.join(['test'] + args)))
249 85898ca4 Stavros Sachtouris
    else:
250 85898ca4 Stavros Sachtouris
        suite.addTest(makeSuite(cls))
251 85898ca4 Stavros Sachtouris
    print('* Test * %s *' % test_name)
252 657dc0c8 Stavros Sachtouris
    r = TextTestRunner(verbosity=2).run(suite)
253 657dc0c8 Stavros Sachtouris
    failure_collector += r.failures
254 657dc0c8 Stavros Sachtouris
    return r.testsRun
255 85898ca4 Stavros Sachtouris
256 85898ca4 Stavros Sachtouris
257 85898ca4 Stavros Sachtouris
def _add_value(foo, value):
258 85898ca4 Stavros Sachtouris
    def wrap(self):
259 85898ca4 Stavros Sachtouris
        return foo(self, value)
260 85898ca4 Stavros Sachtouris
    return wrap
261 85898ca4 Stavros Sachtouris
262 85898ca4 Stavros Sachtouris
263 85898ca4 Stavros Sachtouris
def get_test_classes(module=__import__(__name__), name=''):
264 85898ca4 Stavros Sachtouris
    module_stack = [module]
265 85898ca4 Stavros Sachtouris
    while module_stack:
266 85898ca4 Stavros Sachtouris
        module = module_stack[-1]
267 85898ca4 Stavros Sachtouris
        module_stack = module_stack[:-1]
268 85898ca4 Stavros Sachtouris
        for objname, obj in getmembers(module):
269 85898ca4 Stavros Sachtouris
            if (objname == name or not name):
270 85898ca4 Stavros Sachtouris
                if isclass(obj) and objname != 'TestCase' and (
271 85898ca4 Stavros Sachtouris
                        issubclass(obj, TestCase)):
272 85898ca4 Stavros Sachtouris
                    yield (obj, objname)
273 85898ca4 Stavros Sachtouris
274 85898ca4 Stavros Sachtouris
275 c1004a00 Stavros Sachtouris
def main(argv):
276 d86c3c7d Stavros Sachtouris
    found = False
277 657dc0c8 Stavros Sachtouris
    failure_collector = list()
278 657dc0c8 Stavros Sachtouris
    num_of_tests = 0
279 c1004a00 Stavros Sachtouris
    for cls, name in get_test_classes(name=argv[1] if len(argv) > 1 else ''):
280 d86c3c7d Stavros Sachtouris
        found = True
281 657dc0c8 Stavros Sachtouris
        num_of_tests += runTestCase(cls, name, argv[2:], failure_collector)
282 d86c3c7d Stavros Sachtouris
    if not found:
283 d86c3c7d Stavros Sachtouris
        print('Test "%s" not found' % ' '.join(argv[1:]))
284 657dc0c8 Stavros Sachtouris
    else:
285 657dc0c8 Stavros Sachtouris
        for i, failure in enumerate(failure_collector):
286 657dc0c8 Stavros Sachtouris
            print('Failure %s: ' % (i + 1))
287 657dc0c8 Stavros Sachtouris
            for field in failure:
288 657dc0c8 Stavros Sachtouris
                print('\t%s' % field)
289 657dc0c8 Stavros Sachtouris
        print('\nTotal tests run: %s' % num_of_tests)
290 657dc0c8 Stavros Sachtouris
        print('Total failures: %s' % len(failure_collector))
291 c1004a00 Stavros Sachtouris
292 c1004a00 Stavros Sachtouris
293 c1004a00 Stavros Sachtouris
if __name__ == '__main__':
294 c1004a00 Stavros Sachtouris
    from sys import argv
295 c1004a00 Stavros Sachtouris
    main(argv)