Enable py35 functional test env

This patch also adds the necessary changes to fix py35 compatibility
and ensure that the current functional/unit tests pass.

Change-Id: Iaced98e98db29882a35bea1abd98e50dd167b511
This commit is contained in:
Paul Van Eck 2017-03-07 19:10:39 -08:00
parent f70ac93713
commit 9ea5721d51
8 changed files with 50 additions and 35 deletions

View File

@ -176,7 +176,7 @@ class ProductsController(validation.BaseRestControllerWithValidation):
if _id not in result: if _id not in result:
result[_id] = s result[_id] = s
result[_id]['can_manage'] = True result[_id]['can_manage'] = True
products = result.values() products = list(result.values())
except Exception as ex: except Exception as ex:
LOG.exception('An error occurred during ' LOG.exception('An error occurred during '
'operation with database: %s' % ex) 'operation with database: %s' % ex)
@ -201,7 +201,7 @@ class ProductsController(validation.BaseRestControllerWithValidation):
if not is_admin: if not is_admin:
admin_only_keys = ['created_by_user', 'created_at', 'updated_at', admin_only_keys = ['created_by_user', 'created_at', 'updated_at',
'properties'] 'properties']
for key in product.keys(): for key in list(product):
if key in admin_only_keys: if key in admin_only_keys:
product.pop(key) product.pop(key)

View File

@ -57,7 +57,7 @@ class BaseRestControllerWithValidation(rest.RestController):
def post(self, ): def post(self, ):
"""POST handler.""" """POST handler."""
self.validator.validate(pecan.request) self.validator.validate(pecan.request)
item = json.loads(pecan.request.body) item = json.loads(pecan.request.body.decode('utf-8'))
item_id = self.store_item(item) item_id = self.store_item(item)
pecan.response.status = 201 pecan.response.status = 201
return item_id return item_id

View File

@ -166,12 +166,11 @@ class VendorsController(validation.BaseRestControllerWithValidation):
if _id not in result: if _id not in result:
result[_id] = vendor result[_id] = vendor
result[_id]['can_manage'] = True result[_id]['can_manage'] = True
vendors = result.values() vendors = list(result.values())
except Exception as ex: except Exception as ex:
LOG.exception('An error occurred during ' LOG.exception('An error occurred during '
'operation with database: %s' % ex) 'operation with database: %s' % ex)
pecan.abort(400) pecan.abort(400)
return {'vendors': vendors} return {'vendors': vendors}
@pecan.expose('json') @pecan.expose('json')

View File

@ -65,7 +65,7 @@ class BaseValidator(object):
def validate(self, request): def validate(self, request):
"""Validate request.""" """Validate request."""
try: try:
body = json.loads(request.body) body = json.loads(request.body.decode('utf-8'))
except (ValueError, TypeError) as e: except (ValueError, TypeError) as e:
raise api_exc.ValidationError('Malformed request', e) raise api_exc.ValidationError('Malformed request', e)
@ -135,7 +135,7 @@ class TestResultValidator(BaseValidator):
raise api_exc.ValidationError('Malformed public key', e) raise api_exc.ValidationError('Malformed public key', e)
verifier = key.verifier(sign, padding.PKCS1v15(), hashes.SHA256()) verifier = key.verifier(sign, padding.PKCS1v15(), hashes.SHA256())
verifier.update(request.body.encode('utf-8')) verifier.update(request.body)
try: try:
verifier.verify() verifier.verify()
except InvalidSignature: except InvalidSignature:
@ -146,7 +146,7 @@ class TestResultValidator(BaseValidator):
def _is_empty_result(self, request): def _is_empty_result(self, request):
"""Check if the test results list is empty.""" """Check if the test results list is empty."""
body = json.loads(request.body) body = json.loads(request.body.decode('utf-8'))
if len(body['results']) != 0: if len(body['results']) != 0:
return False return False
return True return True
@ -173,7 +173,7 @@ class PubkeyValidator(BaseValidator):
def validate(self, request): def validate(self, request):
"""Validate uploaded test results.""" """Validate uploaded test results."""
super(PubkeyValidator, self).validate(request) super(PubkeyValidator, self).validate(request)
body = json.loads(request.body) body = json.loads(request.body.decode('utf-8'))
key_format = body['raw_key'].strip().split()[0] key_format = body['raw_key'].strip().split()[0]
if key_format not in ('ssh-dss', 'ssh-rsa', if key_format not in ('ssh-dss', 'ssh-rsa',
@ -215,7 +215,7 @@ class VendorValidator(BaseValidator):
def validate(self, request): def validate(self, request):
"""Validate uploaded vendor data.""" """Validate uploaded vendor data."""
super(VendorValidator, self).validate(request) super(VendorValidator, self).validate(request)
body = json.loads(request.body) body = json.loads(request.body.decode('utf-8'))
self.check_emptyness(body, ['name']) self.check_emptyness(body, ['name'])
@ -239,7 +239,7 @@ class ProductValidator(BaseValidator):
def validate(self, request): def validate(self, request):
"""Validate uploaded test results.""" """Validate uploaded test results."""
super(ProductValidator, self).validate(request) super(ProductValidator, self).validate(request)
body = json.loads(request.body) body = json.loads(request.body.decode('utf-8'))
self.check_emptyness(body, ['name', 'product_type']) self.check_emptyness(body, ['name', 'product_type'])
@ -260,6 +260,6 @@ class ProductVersionValidator(BaseValidator):
def validate(self, request): def validate(self, request):
"""Validate product version data.""" """Validate product version data."""
super(ProductVersionValidator, self).validate(request) super(ProductVersionValidator, self).validate(request)
body = json.loads(request.body) body = json.loads(request.body.decode('utf-8'))
self.check_emptyness(body, ['version']) self.check_emptyness(body, ['version'])

View File

@ -62,9 +62,9 @@ class TestProfileEndpoint(api.FunctionalTest):
pubkey = key.public_key().public_bytes( pubkey = key.public_key().public_bytes(
serialization.Encoding.OpenSSH, serialization.Encoding.OpenSSH,
serialization.PublicFormat.OpenSSH serialization.PublicFormat.OpenSSH
) ).decode('utf-8')
body = {'raw_key': pubkey, body = {'raw_key': pubkey,
'self_signature': binascii.b2a_hex(sign)} 'self_signature': binascii.b2a_hex(sign).decode('utf-8')}
json_params = json.dumps(body) json_params = json.dumps(body)
# POST endpoint # POST endpoint

View File

@ -147,7 +147,7 @@ class ResultsControllerTestCase(BaseControllerTestCase):
@mock.patch('refstack.db.store_results') @mock.patch('refstack.db.store_results')
def test_post(self, mock_store_results): def test_post(self, mock_store_results):
self.mock_request.body = '{"answer": 42}' self.mock_request.body = b'{"answer": 42}'
self.mock_request.headers = {} self.mock_request.headers = {}
mock_store_results.return_value = 'fake_test_id' mock_store_results.return_value = 'fake_test_id'
result = self.controller.post() result = self.controller.post()
@ -167,7 +167,7 @@ class ResultsControllerTestCase(BaseControllerTestCase):
@mock.patch('refstack.db.get_pubkey') @mock.patch('refstack.db.get_pubkey')
def test_post_with_sign(self, mock_get_pubkey, mock_store_results, def test_post_with_sign(self, mock_get_pubkey, mock_store_results,
mock_get_version, mock_check, mock_foundation): mock_get_version, mock_check, mock_foundation):
self.mock_request.body = '{"answer": 42, "cpid": "123"}' self.mock_request.body = b'{"answer": 42, "cpid": "123"}'
self.mock_request.headers = { self.mock_request.headers = {
'X-Signature': 'fake-sign', 'X-Signature': 'fake-sign',
'X-Public-Key': 'ssh-rsa Zm9vIGJhcg==' 'X-Public-Key': 'ssh-rsa Zm9vIGJhcg=='
@ -438,7 +438,7 @@ class BaseRestControllerWithValidationTestCase(BaseControllerTestCase):
@mock.patch('pecan.response') @mock.patch('pecan.response')
@mock.patch('pecan.request') @mock.patch('pecan.request')
def test_post(self, mock_request, mock_response): def test_post(self, mock_request, mock_response):
mock_request.body = '[42]' mock_request.body = b'[42]'
self.controller.store_item = mock.Mock(return_value='fake_id') self.controller.store_item = mock.Mock(return_value='fake_id')
result = self.controller.post() result = self.controller.post()
@ -724,7 +724,9 @@ class PublicKeysControllerTestCase(BaseControllerTestCase):
'comment': 'Don\'t_Panic.', 'comment': 'Don\'t_Panic.',
'openid': 'fake_id' 'openid': 'fake_id'
} }
self.mock_request.body = json.dumps({'raw_key': raw_key}) self.mock_request.body = json.dumps(
{'raw_key': raw_key}
).encode('utf-8')
self.controller.post() self.controller.post()
self.assertEqual(201, self.mock_response.status) self.assertEqual(201, self.mock_response.status)
mock_store_pubkey.assert_called_once_with(fake_pubkey) mock_store_pubkey.assert_called_once_with(fake_pubkey)
@ -737,7 +739,9 @@ class PublicKeysControllerTestCase(BaseControllerTestCase):
'comment': '', 'comment': '',
'openid': 'fake_id' 'openid': 'fake_id'
} }
self.mock_request.body = json.dumps({'raw_key': raw_key}) self.mock_request.body = json.dumps(
{'raw_key': raw_key}
).encode('utf-8')
self.controller.post() self.controller.post()
mock_store_pubkey.assert_called_once_with(fake_pubkey) mock_store_pubkey.assert_called_once_with(fake_pubkey)

View File

@ -97,7 +97,7 @@ class TestResultValidatorTestCase(base.BaseTestCase):
def test_validation(self): def test_validation(self):
with mock.patch('jsonschema.validate') as mock_validate: with mock.patch('jsonschema.validate') as mock_validate:
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(self.FAKE_JSON) request.body = json.dumps(self.FAKE_JSON).encode('utf-8')
request.headers = {} request.headers = {}
self.validator.validate(request) self.validator.validate(request)
mock_validate.assert_called_once_with(self.FAKE_JSON, mock_validate.assert_called_once_with(self.FAKE_JSON,
@ -105,7 +105,7 @@ class TestResultValidatorTestCase(base.BaseTestCase):
def test_validation_with_signature(self): def test_validation_with_signature(self):
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(self.FAKE_JSON) request.body = json.dumps(self.FAKE_JSON).encode('utf-8')
key = rsa.generate_private_key( key = rsa.generate_private_key(
public_exponent=65537, public_exponent=65537,
@ -113,7 +113,7 @@ class TestResultValidatorTestCase(base.BaseTestCase):
backend=default_backend() backend=default_backend()
) )
signer = key.signer(padding.PKCS1v15(), hashes.SHA256()) signer = key.signer(padding.PKCS1v15(), hashes.SHA256())
signer.update(request.body.encode('utf-8')) signer.update(request.body)
sign = signer.finalize() sign = signer.finalize()
pubkey = key.public_key().public_bytes( pubkey = key.public_key().public_bytes(
serialization.Encoding.OpenSSH, serialization.Encoding.OpenSSH,
@ -127,7 +127,7 @@ class TestResultValidatorTestCase(base.BaseTestCase):
def test_validation_fail_no_json(self): def test_validation_fail_no_json(self):
wrong_request = mock.Mock() wrong_request = mock.Mock()
wrong_request.body = 'foo' wrong_request.body = b'foo'
self.assertRaises(api_exc.ValidationError, self.assertRaises(api_exc.ValidationError,
self.validator.validate, self.validator.validate,
wrong_request) wrong_request)
@ -140,7 +140,7 @@ class TestResultValidatorTestCase(base.BaseTestCase):
wrong_request = mock.Mock() wrong_request = mock.Mock()
wrong_request.body = json.dumps({ wrong_request.body = json.dumps({
'foo': 'bar' 'foo': 'bar'
}) }).encode('utf-8')
self.assertRaises(api_exc.ValidationError, self.assertRaises(api_exc.ValidationError,
self.validator.validate, self.validator.validate,
wrong_request) wrong_request)
@ -151,7 +151,9 @@ class TestResultValidatorTestCase(base.BaseTestCase):
def test_validation_fail_with_empty_result(self): def test_validation_fail_with_empty_result(self):
wrong_request = mock.Mock() wrong_request = mock.Mock()
wrong_request.body = json.dumps(self.FAKE_JSON_WITH_EMPTY_RESULTS) wrong_request.body = json.dumps(
self.FAKE_JSON_WITH_EMPTY_RESULTS
).encode('utf-8')
self.assertRaises(api_exc.ValidationError, self.assertRaises(api_exc.ValidationError,
self.validator.validate, self.validator.validate,
wrong_request) wrong_request)
@ -160,7 +162,7 @@ class TestResultValidatorTestCase(base.BaseTestCase):
def test_validation_with_broken_signature(self, mock_validate): def test_validation_with_broken_signature(self, mock_validate):
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(self.FAKE_JSON) request.body = json.dumps(self.FAKE_JSON).encode('utf-8')
key = rsa.generate_private_key( key = rsa.generate_private_key(
public_exponent=65537, public_exponent=65537,
key_size=2048, key_size=2048,
@ -224,12 +226,12 @@ class PubkeyValidatorTestCase(base.BaseTestCase):
def test_validation(self): def test_validation(self):
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(self.FAKE_JSON) request.body = json.dumps(self.FAKE_JSON).encode('utf-8')
self.validator.validate(request) self.validator.validate(request)
def test_validation_fail_no_json(self): def test_validation_fail_no_json(self):
wrong_request = mock.Mock() wrong_request = mock.Mock()
wrong_request.body = 'foo' wrong_request.body = b'foo'
self.assertRaises(api_exc.ValidationError, self.assertRaises(api_exc.ValidationError,
self.validator.validate, self.validator.validate,
wrong_request) wrong_request)
@ -242,7 +244,7 @@ class PubkeyValidatorTestCase(base.BaseTestCase):
wrong_request = mock.Mock() wrong_request = mock.Mock()
wrong_request.body = json.dumps({ wrong_request.body = json.dumps({
'foo': 'bar' 'foo': 'bar'
}) }).encode('utf-8')
self.assertRaises(api_exc.ValidationError, self.assertRaises(api_exc.ValidationError,
self.validator.validate, self.validator.validate,
wrong_request) wrong_request)
@ -257,7 +259,7 @@ class PubkeyValidatorTestCase(base.BaseTestCase):
body['self_signature'] = 'deadbeef' body['self_signature'] = 'deadbeef'
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(body) request.body = json.dumps(body).encode('utf-8')
try: try:
self.validator.validate(request) self.validator.validate(request)
except api_exc.ValidationError as e: except api_exc.ValidationError as e:
@ -269,7 +271,7 @@ class PubkeyValidatorTestCase(base.BaseTestCase):
'self_signature': 'deadbeef' 'self_signature': 'deadbeef'
} }
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(body) request.body = json.dumps(body).encode('utf-8')
try: try:
self.validator.validate(request) self.validator.validate(request)
except api_exc.ValidationError as e: except api_exc.ValidationError as e:
@ -281,7 +283,7 @@ class PubkeyValidatorTestCase(base.BaseTestCase):
'self_signature': 'deadbeef?' 'self_signature': 'deadbeef?'
} }
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(body) request.body = json.dumps(body).encode('utf-8')
try: try:
self.validator.validate(request) self.validator.validate(request)
except api_exc.ValidationError as e: except api_exc.ValidationError as e:
@ -293,7 +295,7 @@ class PubkeyValidatorTestCase(base.BaseTestCase):
'self_signature': 'deadbeef' 'self_signature': 'deadbeef'
} }
request = mock.Mock() request = mock.Mock()
request.body = json.dumps(body) request.body = json.dumps(body).encode('utf-8')
try: try:
self.validator.validate(request) self.validator.validate(request)
except api_exc.ValidationError as e: except api_exc.ValidationError as e:

14
tox.ini
View File

@ -1,8 +1,8 @@
[tox] [tox]
# py34 tests should be run before py27 # py3* tests should be run before py27
# it is a workaround for testr bug # it is a workaround for testr bug
# https://bugs.launchpad.net/testrepository/+bug/1229445 # https://bugs.launchpad.net/testrepository/+bug/1229445
envlist = py34,py27,pep8,pip-check-reqs envlist = py35,py27,pep8,pip-check-reqs
minversion = 1.6 minversion = 1.6
skipsdist = True skipsdist = True
@ -27,6 +27,16 @@ setenv = SUBUNIT_TEST_PATH=./refstack/tests/api
# require cleanup of database # require cleanup of database
commands = {toxinidir}/setup-mysql-tests.sh python setup.py testr --slowest --testr-args='{posargs:--concurrency=1}' commands = {toxinidir}/setup-mysql-tests.sh python setup.py testr --slowest --testr-args='{posargs:--concurrency=1}'
[testenv:py35-func-mysql]
basepython = python3.5
setenv = SUBUNIT_TEST_PATH=./refstack/tests/api
# Integration/functional tests
# must not be run in parallel (--concurrency=1),
# because each of these tests
# require cleanup of database
commands = {toxinidir}/setup-mysql-tests.sh python setup.py testr --slowest --testr-args='{posargs:--concurrency=1}'
[testenv:pep8] [testenv:pep8]
commands = commands =
flake8 {posargs} flake8 {posargs}