comparison test/rest_common.py @ 5606:5fc476d4e34c

Merge REST API changes
author Ralf Schlatterbeck <rsc@runtux.com>
date Wed, 30 Jan 2019 18:11:02 +0100
parents ed02a1e0aa5d
children 1c4adab65faf
comparison
equal deleted inserted replaced
5553:a75285092156 5606:5fc476d4e34c
1 import unittest
2 import os
3 import shutil
4 import errno
5
6 from roundup.cgi.exceptions import *
7 from roundup import password, hyperdb
8 from roundup.rest import RestfulInstance
9 from roundup.backends import list_backends
10 from roundup.cgi import client
11 import random
12
13 from .db_test_base import setupTracker
14
15 NEEDS_INSTANCE = 1
16
17
18 class TestCase():
19
20 backend = None
21
22 def setUp(self):
23 self.dirname = '_test_rest'
24 # set up and open a tracker
25 self.instance = setupTracker(self.dirname, self.backend)
26
27 # open the database
28 self.db = self.instance.open('admin')
29
30 # Get user id (user4 maybe). Used later to get data from db.
31 self.joeid = self.db.user.create(
32 username='joe',
33 password=password.Password('random'),
34 address='random@home.org',
35 realname='Joe Random',
36 roles='User'
37 )
38
39 self.db.commit()
40 self.db.close()
41 self.db = self.instance.open('joe')
42 # Allow joe to retire
43 p = self.db.security.addPermission(name='Retire', klass='issue')
44 self.db.security.addPermissionToRole('User', p)
45
46 self.db.tx_Source = 'web'
47
48 self.db.issue.addprop(tx_Source=hyperdb.String())
49 self.db.msg.addprop(tx_Source=hyperdb.String())
50
51 self.db.post_init()
52
53 thisdir = os.path.dirname(__file__)
54 vars = {}
55 with open(os.path.join(thisdir, "tx_Source_detector.py")) as f:
56 code = compile(f.read(), "tx_Source_detector.py", "exec")
57 exec(code, vars)
58 vars['init'](self.db)
59
60 env = {
61 'PATH_INFO': 'http://localhost/rounduptest/rest/',
62 'HTTP_HOST': 'localhost',
63 'TRACKER_NAME': 'rounduptest'
64 }
65 self.dummy_client = client.Client(self.instance, None, env, [], None)
66 self.empty_form = cgi.FieldStorage()
67
68 self.server = RestfulInstance(self.dummy_client, self.db)
69
70 def tearDown(self):
71 self.db.close()
72 try:
73 shutil.rmtree(self.dirname)
74 except OSError as error:
75 if error.errno not in (errno.ENOENT, errno.ESRCH):
76 raise
77
78 def testGet(self):
79 """
80 Retrieve all three users
81 obtain data for 'joe'
82 """
83 # Retrieve all three users.
84 results = self.server.get_collection('user', self.empty_form)
85 self.assertEqual(self.dummy_client.response_code, 200)
86 self.assertEqual(len(results['data']), 3)
87
88 # Obtain data for 'joe'.
89 results = self.server.get_element('user', self.joeid, self.empty_form)
90 results = results['data']
91 self.assertEqual(self.dummy_client.response_code, 200)
92 self.assertEqual(results['attributes']['username'], 'joe')
93 self.assertEqual(results['attributes']['realname'], 'Joe Random')
94
95 # Obtain data for 'joe'.
96 results = self.server.get_attribute(
97 'user', self.joeid, 'username', self.empty_form
98 )
99 self.assertEqual(self.dummy_client.response_code, 200)
100 self.assertEqual(results['data']['data'], 'joe')
101
102 def testFilter(self):
103 """
104 Retrieve all three users
105 obtain data for 'joe'
106 """
107 # create sample data
108 try:
109 self.db.status.create(name='open')
110 except ValueError:
111 pass
112 try:
113 self.db.status.create(name='closed')
114 except ValueError:
115 pass
116 try:
117 self.db.priority.create(name='normal')
118 except ValueError:
119 pass
120 try:
121 self.db.priority.create(name='critical')
122 except ValueError:
123 pass
124 self.db.issue.create(
125 title='foo4',
126 status=self.db.status.lookup('closed'),
127 priority=self.db.priority.lookup('critical')
128 )
129 self.db.issue.create(
130 title='foo1',
131 status=self.db.status.lookup('open'),
132 priority=self.db.priority.lookup('normal')
133 )
134 issue_open_norm = self.db.issue.create(
135 title='foo2',
136 status=self.db.status.lookup('open'),
137 priority=self.db.priority.lookup('normal')
138 )
139 issue_closed_norm = self.db.issue.create(
140 title='foo3',
141 status=self.db.status.lookup('closed'),
142 priority=self.db.priority.lookup('normal')
143 )
144 issue_closed_crit = self.db.issue.create(
145 title='foo4',
146 status=self.db.status.lookup('closed'),
147 priority=self.db.priority.lookup('critical')
148 )
149 issue_open_crit = self.db.issue.create(
150 title='foo5',
151 status=self.db.status.lookup('open'),
152 priority=self.db.priority.lookup('critical')
153 )
154 base_path = self.dummy_client.env['PATH_INFO'] + 'data/issue/'
155
156 # Retrieve all issue status=open
157 form = cgi.FieldStorage()
158 form.list = [
159 cgi.MiniFieldStorage('where_status', 'open')
160 ]
161 results = self.server.get_collection('issue', form)
162 self.assertEqual(self.dummy_client.response_code, 200)
163 self.assertIn(get_obj(base_path, issue_open_norm), results['data'])
164 self.assertIn(get_obj(base_path, issue_open_crit), results['data'])
165 self.assertNotIn(
166 get_obj(base_path, issue_closed_norm), results['data']
167 )
168
169 # Retrieve all issue status=closed and priority=critical
170 form = cgi.FieldStorage()
171 form.list = [
172 cgi.MiniFieldStorage('where_status', 'closed'),
173 cgi.MiniFieldStorage('where_priority', 'critical')
174 ]
175 results = self.server.get_collection('issue', form)
176 self.assertEqual(self.dummy_client.response_code, 200)
177 self.assertIn(get_obj(base_path, issue_closed_crit), results['data'])
178 self.assertNotIn(get_obj(base_path, issue_open_crit), results['data'])
179 self.assertNotIn(
180 get_obj(base_path, issue_closed_norm), results['data']
181 )
182
183 # Retrieve all issue status=closed and priority=normal,critical
184 form = cgi.FieldStorage()
185 form.list = [
186 cgi.MiniFieldStorage('where_status', 'closed'),
187 cgi.MiniFieldStorage('where_priority', 'normal,critical')
188 ]
189 results = self.server.get_collection('issue', form)
190 self.assertEqual(self.dummy_client.response_code, 200)
191 self.assertIn(get_obj(base_path, issue_closed_crit), results['data'])
192 self.assertIn(get_obj(base_path, issue_closed_norm), results['data'])
193 self.assertNotIn(get_obj(base_path, issue_open_crit), results['data'])
194 self.assertNotIn(get_obj(base_path, issue_open_norm), results['data'])
195
196 def testPagination(self):
197 """
198 Retrieve all three users
199 obtain data for 'joe'
200 """
201 # create sample data
202 for i in range(0, random.randint(5, 10)):
203 self.db.issue.create(title='foo' + str(i))
204
205 # Retrieving all the issues
206 results = self.server.get_collection('issue', self.empty_form)
207 self.assertEqual(self.dummy_client.response_code, 200)
208 total_length = len(results['data'])
209
210 # Pagination will be 70% of the total result
211 page_size = total_length * 70 // 100
212 page_zero_expected = page_size
213 page_one_expected = total_length - page_zero_expected
214
215 # Retrieve page 0
216 form = cgi.FieldStorage()
217 form.list = [
218 cgi.MiniFieldStorage('page_size', page_size),
219 cgi.MiniFieldStorage('page_index', 0)
220 ]
221 results = self.server.get_collection('issue', form)
222 self.assertEqual(self.dummy_client.response_code, 200)
223 self.assertEqual(len(results['data']), page_zero_expected)
224
225 # Retrieve page 1
226 form = cgi.FieldStorage()
227 form.list = [
228 cgi.MiniFieldStorage('page_size', page_size),
229 cgi.MiniFieldStorage('page_index', 1)
230 ]
231 results = self.server.get_collection('issue', form)
232 self.assertEqual(self.dummy_client.response_code, 200)
233 self.assertEqual(len(results['data']), page_one_expected)
234
235 # Retrieve page 2
236 form = cgi.FieldStorage()
237 form.list = [
238 cgi.MiniFieldStorage('page_size', page_size),
239 cgi.MiniFieldStorage('page_index', 2)
240 ]
241 results = self.server.get_collection('issue', form)
242 self.assertEqual(self.dummy_client.response_code, 200)
243 self.assertEqual(len(results['data']), 0)
244
245 def testPut(self):
246 """
247 Change joe's 'realname'
248 Check if we can't change admin's detail
249 """
250 # change Joe's realname via attribute uri
251 form = cgi.FieldStorage()
252 form.list = [
253 cgi.MiniFieldStorage('data', 'Joe Doe Doe')
254 ]
255 results = self.server.put_attribute(
256 'user', self.joeid, 'realname', form
257 )
258 results = self.server.get_attribute(
259 'user', self.joeid, 'realname', self.empty_form
260 )
261 self.assertEqual(self.dummy_client.response_code, 200)
262 self.assertEqual(results['data']['data'], 'Joe Doe Doe')
263
264 # Reset joe's 'realname'.
265 form = cgi.FieldStorage()
266 form.list = [
267 cgi.MiniFieldStorage('realname', 'Joe Doe')
268 ]
269 results = self.server.put_element('user', self.joeid, form)
270 results = self.server.get_element('user', self.joeid, self.empty_form)
271 self.assertEqual(self.dummy_client.response_code, 200)
272 self.assertEqual(results['data']['attributes']['realname'], 'Joe Doe')
273
274 # check we can't change admin's details
275 results = self.server.put_element('user', '1', form)
276 self.assertEqual(self.dummy_client.response_code, 403)
277 self.assertEqual(results['error']['status'], 403)
278
279 def testPost(self):
280 """
281 Post a new issue with title: foo
282 Verify the information of the created issue
283 """
284 form = cgi.FieldStorage()
285 form.list = [
286 cgi.MiniFieldStorage('title', 'foo')
287 ]
288 results = self.server.post_collection('issue', form)
289 self.assertEqual(self.dummy_client.response_code, 201)
290 issueid = results['data']['id']
291 results = self.server.get_element('issue', issueid, self.empty_form)
292 self.assertEqual(self.dummy_client.response_code, 200)
293 self.assertEqual(results['data']['attributes']['title'], 'foo')
294 self.assertEqual(self.db.issue.get(issueid, "tx_Source"), 'web')
295
296 def testPostFile(self):
297 """
298 Post a new file with content: hello\r\nthere
299 Verify the information of the created file
300 """
301 form = cgi.FieldStorage()
302 form.list = [
303 cgi.MiniFieldStorage('content', 'hello\r\nthere')
304 ]
305 results = self.server.post_collection('file', form)
306 self.assertEqual(self.dummy_client.response_code, 201)
307 fileid = results['data']['id']
308 results = self.server.get_element('file', fileid, self.empty_form)
309 results = results['data']
310 self.assertEqual(self.dummy_client.response_code, 200)
311 self.assertEqual(results['attributes']['content'], 'hello\r\nthere')
312
313 def testAuthDeniedPut(self):
314 """
315 Test unauthorized PUT request
316 """
317 # Wrong permissions (caught by roundup security module).
318 form = cgi.FieldStorage()
319 form.list = [
320 cgi.MiniFieldStorage('realname', 'someone')
321 ]
322 results = self.server.put_element('user', '1', form)
323 self.assertEqual(self.dummy_client.response_code, 403)
324 self.assertEqual(results['error']['status'], 403)
325
326 def testAuthDeniedPost(self):
327 """
328 Test unauthorized POST request
329 """
330 form = cgi.FieldStorage()
331 form.list = [
332 cgi.MiniFieldStorage('username', 'blah')
333 ]
334 results = self.server.post_collection('user', form)
335 self.assertEqual(self.dummy_client.response_code, 403)
336 self.assertEqual(results['error']['status'], 403)
337
338 def testAuthAllowedPut(self):
339 """
340 Test authorized PUT request
341 """
342 self.db.setCurrentUser('admin')
343 form = cgi.FieldStorage()
344 form.list = [
345 cgi.MiniFieldStorage('realname', 'someone')
346 ]
347 try:
348 self.server.put_element('user', '2', form)
349 except Unauthorised as err:
350 self.fail('raised %s' % err)
351 finally:
352 self.db.setCurrentUser('joe')
353
354 def testAuthAllowedPost(self):
355 """
356 Test authorized POST request
357 """
358 self.db.setCurrentUser('admin')
359 form = cgi.FieldStorage()
360 form.list = [
361 cgi.MiniFieldStorage('username', 'blah')
362 ]
363 try:
364 self.server.post_collection('user', form)
365 except Unauthorised as err:
366 self.fail('raised %s' % err)
367 finally:
368 self.db.setCurrentUser('joe')
369
370 def testDeleteAttributeUri(self):
371 """
372 Test Delete an attribute
373 """
374 # create a new issue with userid 1 in the nosy list
375 issue_id = self.db.issue.create(title='foo', nosy=['1'])
376
377 # remove the title and nosy
378 results = self.server.delete_attribute(
379 'issue', issue_id, 'title', self.empty_form
380 )
381 self.assertEqual(self.dummy_client.response_code, 200)
382
383 results = self.server.delete_attribute(
384 'issue', issue_id, 'nosy', self.empty_form
385 )
386 self.assertEqual(self.dummy_client.response_code, 200)
387
388 # verify the result
389 results = self.server.get_element('issue', issue_id, self.empty_form)
390 results = results['data']
391 self.assertEqual(self.dummy_client.response_code, 200)
392 self.assertEqual(len(results['attributes']['nosy']), 0)
393 self.assertListEqual(results['attributes']['nosy'], [])
394 self.assertEqual(results['attributes']['title'], None)
395
396 def testPatchAdd(self):
397 """
398 Test Patch op 'Add'
399 """
400 # create a new issue with userid 1 in the nosy list
401 issue_id = self.db.issue.create(title='foo', nosy=['1'])
402
403 # add userid 2 to the nosy list
404 form = cgi.FieldStorage()
405 form.list = [
406 cgi.MiniFieldStorage('op', 'add'),
407 cgi.MiniFieldStorage('nosy', '2')
408 ]
409 results = self.server.patch_element('issue', issue_id, form)
410 self.assertEqual(self.dummy_client.response_code, 200)
411
412 # verify the result
413 results = self.server.get_element('issue', issue_id, self.empty_form)
414 results = results['data']
415 self.assertEqual(self.dummy_client.response_code, 200)
416 self.assertEqual(len(results['attributes']['nosy']), 2)
417 self.assertListEqual(results['attributes']['nosy'], ['1', '2'])
418
419 def testPatchReplace(self):
420 """
421 Test Patch op 'Replace'
422 """
423 # create a new issue with userid 1 in the nosy list and status = 1
424 issue_id = self.db.issue.create(title='foo', nosy=['1'], status='1')
425
426 # replace userid 2 to the nosy list and status = 3
427 form = cgi.FieldStorage()
428 form.list = [
429 cgi.MiniFieldStorage('op', 'replace'),
430 cgi.MiniFieldStorage('nosy', '2'),
431 cgi.MiniFieldStorage('status', '3')
432 ]
433 results = self.server.patch_element('issue', issue_id, form)
434 self.assertEqual(self.dummy_client.response_code, 200)
435
436 # verify the result
437 results = self.server.get_element('issue', issue_id, self.empty_form)
438 results = results['data']
439 self.assertEqual(self.dummy_client.response_code, 200)
440 self.assertEqual(results['attributes']['status'], '3')
441 self.assertEqual(len(results['attributes']['nosy']), 1)
442 self.assertListEqual(results['attributes']['nosy'], ['2'])
443
444 def testPatchRemoveAll(self):
445 """
446 Test Patch Action 'Remove'
447 """
448 # create a new issue with userid 1 and 2 in the nosy list
449 issue_id = self.db.issue.create(title='foo', nosy=['1', '2'])
450
451 # remove the nosy list and the title
452 form = cgi.FieldStorage()
453 form.list = [
454 cgi.MiniFieldStorage('op', 'remove'),
455 cgi.MiniFieldStorage('nosy', ''),
456 cgi.MiniFieldStorage('title', '')
457 ]
458 results = self.server.patch_element('issue', issue_id, form)
459 self.assertEqual(self.dummy_client.response_code, 200)
460
461 # verify the result
462 results = self.server.get_element('issue', issue_id, self.empty_form)
463 results = results['data']
464 self.assertEqual(self.dummy_client.response_code, 200)
465 self.assertEqual(results['attributes']['title'], None)
466 self.assertEqual(len(results['attributes']['nosy']), 0)
467 self.assertEqual(results['attributes']['nosy'], [])
468
469 def testPatchAction(self):
470 """
471 Test Patch Action 'Action'
472 """
473 # create a new issue with userid 1 and 2 in the nosy list
474 issue_id = self.db.issue.create(title='foo')
475
476 # execute action retire
477 form = cgi.FieldStorage()
478 form.list = [
479 cgi.MiniFieldStorage('op', 'action'),
480 cgi.MiniFieldStorage('action_name', 'retire')
481 ]
482 results = self.server.patch_element('issue', issue_id, form)
483 self.assertEqual(self.dummy_client.response_code, 200)
484
485 # verify the result
486 self.assertTrue(self.db.issue.is_retired(issue_id))
487
488 def testPatchRemove(self):
489 """
490 Test Patch Action 'Remove' only some element from a list
491 """
492 # create a new issue with userid 1, 2, 3 in the nosy list
493 issue_id = self.db.issue.create(title='foo', nosy=['1', '2', '3'])
494
495 # remove the nosy list and the title
496 form = cgi.FieldStorage()
497 form.list = [
498 cgi.MiniFieldStorage('op', 'remove'),
499 cgi.MiniFieldStorage('nosy', '1, 2'),
500 ]
501 results = self.server.patch_element('issue', issue_id, form)
502 self.assertEqual(self.dummy_client.response_code, 200)
503
504 # verify the result
505 results = self.server.get_element('issue', issue_id, self.empty_form)
506 results = results['data']
507 self.assertEqual(self.dummy_client.response_code, 200)
508 self.assertEqual(len(results['attributes']['nosy']), 1)
509 self.assertEqual(results['attributes']['nosy'], ['3'])
510
511
512 def get_obj(path, id):
513 return {
514 'id': id,
515 'link': path + id
516 }
517
518 if __name__ == '__main__':
519 runner = unittest.TextTestRunner()
520 unittest.main(testRunner=runner)

Roundup Issue Tracker: http://roundup-tracker.org/