Mercurial > p > roundup > code
comparison test/rest_common.py @ 5651:a02ef29b4242
Fix REST tests for Python 3.
FieldStorage requires a file storing bytes not strings. With dispatch
returning bytes (as required to work end-to-end), tests of the
dispatch method that use its return value must handle decoding it.
| author | Joseph Myers <jsm@polyomino.org.uk> |
|---|---|
| date | Sun, 17 Mar 2019 16:41:49 +0000 |
| parents | e8ca7072c629 |
| children | 207e0f5d551c |
comparison
equal
deleted
inserted
replaced
| 5650:e8ca7072c629 | 5651:a02ef29b4242 |
|---|---|
| 6 from roundup.cgi.exceptions import * | 6 from roundup.cgi.exceptions import * |
| 7 from roundup import password, hyperdb | 7 from roundup import password, hyperdb |
| 8 from roundup.rest import RestfulInstance, calculate_etag | 8 from roundup.rest import RestfulInstance, calculate_etag |
| 9 from roundup.backends import list_backends | 9 from roundup.backends import list_backends |
| 10 from roundup.cgi import client | 10 from roundup.cgi import client |
| 11 from roundup.anypy.strings import b2s, s2b | |
| 11 import random | 12 import random |
| 12 | 13 |
| 13 from .db_test_base import setupTracker | 14 from .db_test_base import setupTracker |
| 14 | 15 |
| 15 from .mocknull import MockNull | 16 from .mocknull import MockNull |
| 16 | 17 |
| 17 from io import StringIO | 18 from io import BytesIO |
| 18 import json | 19 import json |
| 19 | 20 |
| 20 NEEDS_INSTANCE = 1 | 21 NEEDS_INSTANCE = 1 |
| 21 | 22 |
| 22 | 23 |
| 407 """ | 408 """ |
| 408 # Set joe's 'realname' using json data. | 409 # Set joe's 'realname' using json data. |
| 409 # simulate: /rest/data/user/<id>/realname | 410 # simulate: /rest/data/user/<id>/realname |
| 410 # use etag in header | 411 # use etag in header |
| 411 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 412 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 412 body=u'{ "data": "Joe Doe 1" }' | 413 body=b'{ "data": "Joe Doe 1" }' |
| 413 env = { "CONTENT_TYPE": "application/json", | 414 env = { "CONTENT_TYPE": "application/json", |
| 414 "CONTENT_LENGTH": len(body), | 415 "CONTENT_LENGTH": len(body), |
| 415 "REQUEST_METHOD": "PUT" | 416 "REQUEST_METHOD": "PUT" |
| 416 } | 417 } |
| 417 headers={"accept": "application/json", | 418 headers={"accept": "application/json", |
| 420 } | 421 } |
| 421 self.headers=headers | 422 self.headers=headers |
| 422 # we need to generate a FieldStorage the looks like | 423 # we need to generate a FieldStorage the looks like |
| 423 # FieldStorage(None, None, 'string') rather than | 424 # FieldStorage(None, None, 'string') rather than |
| 424 # FieldStorage(None, None, []) | 425 # FieldStorage(None, None, []) |
| 425 body_file=StringIO(body) # FieldStorage needs a file | 426 body_file=BytesIO(body) # FieldStorage needs a file |
| 426 form = cgi.FieldStorage(body_file, | 427 form = cgi.FieldStorage(body_file, |
| 427 headers=headers, | 428 headers=headers, |
| 428 environ=env) | 429 environ=env) |
| 429 self.server.client.request.headers.get=self.get_header | 430 self.server.client.request.headers.get=self.get_header |
| 430 results = self.server.dispatch('PUT', | 431 results = self.server.dispatch('PUT', |
| 440 | 441 |
| 441 # Set joe's 'realname' using json data. | 442 # Set joe's 'realname' using json data. |
| 442 # simulate: /rest/data/user/<id>/realname | 443 # simulate: /rest/data/user/<id>/realname |
| 443 # use etag in payload | 444 # use etag in payload |
| 444 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 445 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 445 body=u'{ "@etag": "%s", "data": "Joe Doe 2" }'%etag | 446 body=s2b('{ "@etag": "%s", "data": "Joe Doe 2" }'%etag) |
| 446 env = { "CONTENT_TYPE": "application/json", | 447 env = { "CONTENT_TYPE": "application/json", |
| 447 "CONTENT_LENGTH": len(body), | 448 "CONTENT_LENGTH": len(body), |
| 448 "REQUEST_METHOD": "PUT" | 449 "REQUEST_METHOD": "PUT" |
| 449 } | 450 } |
| 450 headers={"accept": "application/json", | 451 headers={"accept": "application/json", |
| 451 "content-type": env['CONTENT_TYPE'] | 452 "content-type": env['CONTENT_TYPE'] |
| 452 } | 453 } |
| 453 self.headers=headers | 454 self.headers=headers |
| 454 body_file=StringIO(body) # FieldStorage needs a file | 455 body_file=BytesIO(body) # FieldStorage needs a file |
| 455 form = cgi.FieldStorage(body_file, | 456 form = cgi.FieldStorage(body_file, |
| 456 headers=headers, | 457 headers=headers, |
| 457 environ=env) | 458 environ=env) |
| 458 self.server.client.request.headers.get=self.get_header | 459 self.server.client.request.headers.get=self.get_header |
| 459 results = self.server.dispatch('PUT', | 460 results = self.server.dispatch('PUT', |
| 490 self.assertEqual(self.dummy_client.response_code, 200) | 491 self.assertEqual(self.dummy_client.response_code, 200) |
| 491 results = self.server.dispatch('GET', | 492 results = self.server.dispatch('GET', |
| 492 "/rest/data/user/%s/realname"%self.joeid, | 493 "/rest/data/user/%s/realname"%self.joeid, |
| 493 self.empty_form) | 494 self.empty_form) |
| 494 self.assertEqual(self.dummy_client.response_code, 200) | 495 self.assertEqual(self.dummy_client.response_code, 200) |
| 495 json_dict = json.loads(results) | 496 json_dict = json.loads(b2s(results)) |
| 496 | 497 |
| 497 self.assertEqual(json_dict['data']['data'], 'Joe Doe') | 498 self.assertEqual(json_dict['data']['data'], 'Joe Doe') |
| 498 self.assertEqual(json_dict['data']['link'], | 499 self.assertEqual(json_dict['data']['link'], |
| 499 "http://tracker.example/cgi-bin/" | 500 "http://tracker.example/cgi-bin/" |
| 500 "roundup.cgi/bugs/rest/data/user/3/realname") | 501 "roundup.cgi/bugs/rest/data/user/3/realname") |
| 508 stored_results = self.server.get_element('user', self.joeid, | 509 stored_results = self.server.get_element('user', self.joeid, |
| 509 self.empty_form) | 510 self.empty_form) |
| 510 self.assertEqual(self.dummy_client.response_code, 200) | 511 self.assertEqual(self.dummy_client.response_code, 200) |
| 511 | 512 |
| 512 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 513 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 513 body=u'{ "address": "demo2@example.com", "@etag": "%s"}'%etag | 514 body=s2b('{ "address": "demo2@example.com", "@etag": "%s"}'%etag) |
| 514 env = { "CONTENT_TYPE": "application/json", | 515 env = { "CONTENT_TYPE": "application/json", |
| 515 "CONTENT_LENGTH": len(body), | 516 "CONTENT_LENGTH": len(body), |
| 516 "REQUEST_METHOD": "PATCH" | 517 "REQUEST_METHOD": "PATCH" |
| 517 } | 518 } |
| 518 headers={"accept": "application/json", | 519 headers={"accept": "application/json", |
| 519 "content-type": env['CONTENT_TYPE'] | 520 "content-type": env['CONTENT_TYPE'] |
| 520 } | 521 } |
| 521 self.headers=headers | 522 self.headers=headers |
| 522 body_file=StringIO(body) # FieldStorage needs a file | 523 body_file=BytesIO(body) # FieldStorage needs a file |
| 523 form = cgi.FieldStorage(body_file, | 524 form = cgi.FieldStorage(body_file, |
| 524 headers=headers, | 525 headers=headers, |
| 525 environ=env) | 526 environ=env) |
| 526 self.server.client.request.headers.get=self.get_header | 527 self.server.client.request.headers.get=self.get_header |
| 527 results = self.server.dispatch('PATCH', | 528 results = self.server.dispatch('PATCH', |
| 534 self.assertEqual(results['data']['attributes']['address'], | 535 self.assertEqual(results['data']['attributes']['address'], |
| 535 'demo2@example.com') | 536 'demo2@example.com') |
| 536 | 537 |
| 537 # and set it back | 538 # and set it back |
| 538 etag = calculate_etag(self.db.user.getnode(self.joeid)) | 539 etag = calculate_etag(self.db.user.getnode(self.joeid)) |
| 539 body=u'{ "address": "%s", "@etag": "%s"}'%( | 540 body=s2b('{ "address": "%s", "@etag": "%s"}'%( |
| 540 stored_results['data']['attributes']['address'], | 541 stored_results['data']['attributes']['address'], |
| 541 etag) | 542 etag)) |
| 542 # reuse env and headers from prior test. | 543 # reuse env and headers from prior test. |
| 543 body_file=StringIO(body) # FieldStorage needs a file | 544 body_file=BytesIO(body) # FieldStorage needs a file |
| 544 form = cgi.FieldStorage(body_file, | 545 form = cgi.FieldStorage(body_file, |
| 545 headers=headers, | 546 headers=headers, |
| 546 environ=env) | 547 environ=env) |
| 547 self.server.client.request.headers.get=self.get_header | 548 self.server.client.request.headers.get=self.get_header |
| 548 results = self.server.dispatch('PATCH', | 549 results = self.server.dispatch('PATCH', |
| 555 self.assertEqual(results['data']['attributes']['address'], | 556 self.assertEqual(results['data']['attributes']['address'], |
| 556 'random@home.org') | 557 'random@home.org') |
| 557 del(self.headers) | 558 del(self.headers) |
| 558 | 559 |
| 559 # POST to create new issue | 560 # POST to create new issue |
| 560 body=u'{ "title": "foo bar", "priority": "critical" }' | 561 body=b'{ "title": "foo bar", "priority": "critical" }' |
| 561 | 562 |
| 562 env = { "CONTENT_TYPE": "application/json", | 563 env = { "CONTENT_TYPE": "application/json", |
| 563 "CONTENT_LENGTH": len(body), | 564 "CONTENT_LENGTH": len(body), |
| 564 "REQUEST_METHOD": "POST" | 565 "REQUEST_METHOD": "POST" |
| 565 } | 566 } |
| 566 headers={"accept": "application/json", | 567 headers={"accept": "application/json", |
| 567 "content-type": env['CONTENT_TYPE'] | 568 "content-type": env['CONTENT_TYPE'] |
| 568 } | 569 } |
| 569 self.headers=headers | 570 self.headers=headers |
| 570 body_file=StringIO(body) # FieldStorage needs a file | 571 body_file=BytesIO(body) # FieldStorage needs a file |
| 571 form = cgi.FieldStorage(body_file, | 572 form = cgi.FieldStorage(body_file, |
| 572 headers=headers, | 573 headers=headers, |
| 573 environ=env) | 574 environ=env) |
| 574 self.server.client.request.headers.get=self.get_header | 575 self.server.client.request.headers.get=self.get_header |
| 575 results = self.server.dispatch('POST', | 576 results = self.server.dispatch('POST', |
| 576 "/rest/data/issue", | 577 "/rest/data/issue", |
| 577 form) | 578 form) |
| 578 | 579 |
| 579 self.assertEqual(self.server.client.response_code, 201) | 580 self.assertEqual(self.server.client.response_code, 201) |
| 580 json_dict = json.loads(results) | 581 json_dict = json.loads(b2s(results)) |
| 581 issue_id=json_dict['data']['id'] | 582 issue_id=json_dict['data']['id'] |
| 582 results = self.server.get_element('issue', | 583 results = self.server.get_element('issue', |
| 583 str(issue_id), # must be a string not unicode | 584 str(issue_id), # must be a string not unicode |
| 584 self.empty_form) | 585 self.empty_form) |
| 585 self.assertEqual(self.dummy_client.response_code, 200) | 586 self.assertEqual(self.dummy_client.response_code, 200) |
