]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/tests/test_tools.py
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / pybind / mgr / dashboard / tests / test_tools.py
CommitLineData
11fdf7f2
TL
1# -*- coding: utf-8 -*-
2from __future__ import absolute_import
3
4import unittest
5
6import cherrypy
7from cherrypy.lib.sessions import RamSession
8from mock import patch
9
10from . import ControllerTestCase
11from ..services.exception import handle_rados_error
12from ..controllers import RESTController, ApiController, Controller, \
13 BaseController, Proxy
14from ..tools import is_valid_ipv6_address, dict_contains_path, \
15 RequestLoggingTool
16
17
18# pylint: disable=W0613
19@Controller('/foo', secure=False)
20class FooResource(RESTController):
21 elems = []
22
23 def list(self):
24 return FooResource.elems
25
26 def create(self, a):
27 FooResource.elems.append({'a': a})
28 return {'a': a}
29
30 def get(self, key):
31 return {'detail': (key, [])}
32
33 def delete(self, key):
34 del FooResource.elems[int(key)]
35
36 def bulk_delete(self):
37 FooResource.elems = []
38
39 def set(self, key, newdata):
40 FooResource.elems[int(key)] = {'newdata': newdata}
41 return dict(key=key, newdata=newdata)
42
43
44@Controller('/foo/:key/:method', secure=False)
45class FooResourceDetail(RESTController):
46 def list(self, key, method):
47 return {'detail': (key, [method])}
48
49
50@ApiController('/rgw/proxy', secure=False)
51class GenerateControllerRoutesController(BaseController):
52 @Proxy()
53 def __call__(self, path, **params):
54 pass
55
56
57@ApiController('/fooargs', secure=False)
58class FooArgs(RESTController):
59 def set(self, code, name=None, opt1=None, opt2=None):
60 return {'code': code, 'name': name, 'opt1': opt1, 'opt2': opt2}
61
62 @handle_rados_error('foo')
63 def create(self, my_arg_name):
64 return my_arg_name
65
66 def list(self):
67 raise cherrypy.NotFound()
68
69
70# pylint: disable=blacklisted-name
71class Root(object):
72 foo = FooResource()
73 fooargs = FooArgs()
74
75
76class RESTControllerTest(ControllerTestCase):
77
78 @classmethod
79 def setup_server(cls):
80 cls.setup_controllers(
81 [FooResource, FooResourceDetail, FooArgs, GenerateControllerRoutesController])
82
83 def test_empty(self):
84 self._delete("/foo")
85 self.assertStatus(204)
86 self._get("/foo")
87 self.assertStatus('200 OK')
88 self.assertHeader('Content-Type', 'application/json')
89 self.assertBody('[]')
90
91 def test_fill(self):
92 sess_mock = RamSession()
93 with patch('cherrypy.session', sess_mock, create=True):
94 data = {'a': 'b'}
95 for _ in range(5):
96 self._post("/foo", data)
97 self.assertJsonBody(data)
98 self.assertStatus(201)
99 self.assertHeader('Content-Type', 'application/json')
100
101 self._get("/foo")
102 self.assertStatus('200 OK')
103 self.assertHeader('Content-Type', 'application/json')
104 self.assertJsonBody([data] * 5)
105
106 self._put('/foo/0', {'newdata': 'newdata'})
107 self.assertStatus('200 OK')
108 self.assertHeader('Content-Type', 'application/json')
109 self.assertJsonBody({'newdata': 'newdata', 'key': '0'})
110
111 def test_not_implemented(self):
112 self._put("/foo")
113 self.assertStatus(404)
114 body = self.jsonBody()
115 self.assertIsInstance(body, dict)
116 assert body['detail'] == "The path '/foo' was not found."
117 assert '404' in body['status']
11fdf7f2
TL
118
119 def test_args_from_json(self):
120 self._put("/api/fooargs/hello", {'name': 'world'})
121 self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': None, 'opt2': None})
122
123 self._put("/api/fooargs/hello", {'name': 'world', 'opt1': 'opt1'})
124 self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': 'opt1', 'opt2': None})
125
126 self._put("/api/fooargs/hello", {'name': 'world', 'opt2': 'opt2'})
127 self.assertJsonBody({'code': 'hello', 'name': 'world', 'opt1': None, 'opt2': 'opt2'})
128
129 def test_detail_route(self):
130 self._get('/foo/default')
131 self.assertJsonBody({'detail': ['default', []]})
132
133 self._get('/foo/default/default')
134 self.assertJsonBody({'detail': ['default', ['default']]})
135
136 self._get('/foo/1/detail')
137 self.assertJsonBody({'detail': ['1', ['detail']]})
138
139 self._post('/foo/1/detail', 'post-data')
140 self.assertStatus(404)
141
142 def test_generate_controller_routes(self):
143 # We just need to add this controller in setup_server():
144 # noinspection PyStatementEffect
145 # pylint: disable=pointless-statement
146 GenerateControllerRoutesController
147
148
149class RequestLoggingToolTest(ControllerTestCase):
150
151 def __init__(self, *args, **kwargs):
152 cherrypy.tools.request_logging = RequestLoggingTool()
153 cherrypy.config.update({'tools.request_logging.on': True})
154 super(RequestLoggingToolTest, self).__init__(*args, **kwargs)
155
156 @classmethod
157 def setup_server(cls):
158 cls.setup_controllers([FooResource])
159
160 def test_is_logged(self):
161 with patch('logging.Logger.debug') as mock_logger_debug:
162 self._put('/foo/0', {'newdata': 'xyz'})
163 self.assertStatus(200)
164 call_args_list = mock_logger_debug.call_args_list
165 _, host, _, method, user, path = call_args_list[0][0]
166 self.assertEqual(host, '127.0.0.1')
167 self.assertEqual(method, 'PUT')
168 self.assertIsNone(user)
169 self.assertEqual(path, '/foo/0')
170
171
172class TestFunctions(unittest.TestCase):
173
174 def test_is_valid_ipv6_address(self):
175 self.assertTrue(is_valid_ipv6_address('::'))
176 self.assertTrue(is_valid_ipv6_address('::1'))
177 self.assertFalse(is_valid_ipv6_address('127.0.0.1'))
178 self.assertFalse(is_valid_ipv6_address('localhost'))
179 self.assertTrue(is_valid_ipv6_address('1200:0000:AB00:1234:0000:2552:7777:1313'))
180 self.assertFalse(is_valid_ipv6_address('1200::AB00:1234::2552:7777:1313'))
181
182 def test_dict_contains_path(self):
183 x = {'a': {'b': {'c': 'foo'}}}
184 self.assertTrue(dict_contains_path(x, ['a', 'b', 'c']))
185 self.assertTrue(dict_contains_path(x, ['a', 'b', 'c']))
186 self.assertTrue(dict_contains_path(x, ['a']))
187 self.assertFalse(dict_contains_path(x, ['a', 'c']))
188 self.assertTrue(dict_contains_path(x, []))