-
Notifications
You must be signed in to change notification settings - Fork 5.8k
/
test_tools.py
182 lines (138 loc) · 6 KB
/
test_tools.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import unittest
import cherrypy
from cherrypy.lib.sessions import RamSession
from mock import patch
from ..services.exception import handle_rados_error
from .helper import ControllerTestCase
from ..controllers import RESTController, ApiController, BaseController
from ..tools import is_valid_ipv6_address, dict_contains_path
# pylint: disable=W0613
@ApiController('foo')
class FooResource(RESTController):
elems = []
def list(self):
return FooResource.elems
def create(self, a):
FooResource.elems.append({'a': a})
return {'a': a}
def get(self, key):
return {'detail': (key, [])}
def delete(self, key):
del FooResource.elems[int(key)]
def bulk_delete(self):
FooResource.elems = []
def set(self, key, newdata):
FooResource.elems[int(key)] = {'newdata': newdata}
return dict(key=key, newdata=newdata)
@ApiController('foo/:key/:method')
class FooResourceDetail(RESTController):
def list(self, key, method):
return {'detail': (key, [method])}
@ApiController('rgw/proxy/{path:.*}')
class GenerateControllerRoutesController(BaseController):
@cherrypy.expose
def __call__(self, path, **params):
pass
@ApiController('fooargs')
class FooArgs(RESTController):
def set(self, code, name=None, opt1=None, opt2=None):
return {'code': code, 'name': name, 'opt1': opt1, 'opt2': opt2}
@handle_rados_error('foo')
def create(self, my_arg_name):
return my_arg_name
def list(self):
raise cherrypy.NotFound()
# pylint: disable=C0102
class Root(object):
foo = FooResource()
fooargs = FooArgs()
class RESTControllerTest(ControllerTestCase):
@classmethod
def setup_server(cls):
cls.setup_controllers(
[FooResource, FooResourceDetail, FooArgs, GenerateControllerRoutesController])
def test_empty(self):
self._delete("/foo")
self.assertStatus(204)
self._get("/foo")
self.assertStatus('200 OK')
self.assertHeader('Content-Type', 'application/json')
self.assertBody('[]')
def test_fill(self):
sess_mock = RamSession()
with patch('cherrypy.session', sess_mock, create=True):
data = {'a': 'b'}
for _ in range(5):
self._post("/foo", data)
self.assertJsonBody(data)
self.assertStatus(201)
self.assertHeader('Content-Type', 'application/json')
self._get("/foo")
self.assertStatus('200 OK')
self.assertHeader('Content-Type', 'application/json')
self.assertJsonBody([data] * 5)
self._put('/foo/0', {'newdata': 'newdata'})
self.assertStatus('200 OK')
self.assertHeader('Content-Type', 'application/json')
self.assertJsonBody({'newdata': 'newdata', 'key': '0'})
def test_not_implemented(self):
self._put("/foo")
self.assertStatus(404)
body = self.jsonBody()
self.assertIsInstance(body, dict)
assert body['detail'] == "The path '/foo' was not found."
assert '404' in body['status']
assert 'traceback' in body
def test_args_from_json(self):
self._put("/fooargs/hello", {'name': 'world'})
self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': None, 'opt2': None})
self._put("/fooargs/hello", {'name': 'world', 'opt1': 'opt1'})
self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': 'opt1', 'opt2': None})
self._put("/fooargs/hello", {'name': 'world', 'opt2': 'opt2'})
self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': None, 'opt2': 'opt2'})
def test_detail_route(self):
self._get('/foo/default')
self.assertJsonBody({'detail': ['default', []]})
self._get('/foo/default/default')
self.assertJsonBody({'detail': ['default', ['default']]})
self._get('/foo/1/detail')
self.assertJsonBody({'detail': ['1', ['detail']]})
self._post('/foo/1/detail', 'post-data')
self.assertStatus(404)
def test_developer_page(self):
self.getPage('/foo', headers=[('Accept', 'text/html')])
self.assertIn('<p>GET', self.body.decode('utf-8'))
self.assertIn('Content-Type: text/html', self.body.decode('utf-8'))
self.assertIn('<form action="/api/foo/" method="post">', self.body.decode('utf-8'))
self.assertIn('<input type="hidden" name="_method" value="post" />',
self.body.decode('utf-8'))
def test_developer_exception_page(self):
self.getPage('/foo',
headers=[('Accept', 'text/html'), ('Content-Length', '0')],
method='put')
self.assertStatus(404)
def test_create_form(self):
self.getPage('/fooargs', headers=[('Accept', 'text/html')])
self.assertIn('my_arg_name', self.body.decode('utf-8'))
def test_generate_controller_routes(self):
# We just need to add this controller in setup_server():
# noinspection PyStatementEffect
# pylint: disable=pointless-statement
GenerateControllerRoutesController
class TestFunctions(unittest.TestCase):
def test_is_valid_ipv6_address(self):
self.assertTrue(is_valid_ipv6_address('::'))
self.assertTrue(is_valid_ipv6_address('::1'))
self.assertFalse(is_valid_ipv6_address('127.0.0.1'))
self.assertFalse(is_valid_ipv6_address('localhost'))
self.assertTrue(is_valid_ipv6_address('1200:0000:AB00:1234:0000:2552:7777:1313'))
self.assertFalse(is_valid_ipv6_address('1200::AB00:1234::2552:7777:1313'))
def test_dict_contains_path(self):
x = {'a': {'b': {'c': 'foo'}}}
self.assertTrue(dict_contains_path(x, ['a', 'b', 'c']))
self.assertTrue(dict_contains_path(x, ['a', 'b', 'c']))
self.assertTrue(dict_contains_path(x, ['a']))
self.assertFalse(dict_contains_path(x, ['a', 'c']))
self.assertTrue(dict_contains_path(x, []))