import unittest import json import endpoints.decorated # Register the various exceptions via decorators. from app import app from endpoints.v2 import v2_bp from initdb import setup_database_for_testing, finished_database_for_testing from test.specs import build_v2_index_specs app.register_blueprint(v2_bp, url_prefix='/v2') NO_ACCESS_USER = 'freshuser' READ_ACCESS_USER = 'reader' ADMIN_ACCESS_USER = 'devtable' CREATOR_ACCESS_USER = 'creator' class EndpointTestCase(unittest.TestCase): def setUp(self): setup_database_for_testing(self) def tearDown(self): finished_database_for_testing(self) class _SpecTestBuilder(type): @staticmethod def _test_generator(url, test_spec, attrs): def test(self): with app.test_client() as c: headers = [] expected_index_status = getattr(test_spec, attrs['result_attr']) if attrs['auth_username']: # Get a signed JWT. username = attrs['auth_username'] password = 'password' jwt_scope = test_spec.get_scope_string() query_string = 'service=' + app.config['SERVER_HOSTNAME'] + '&scope=' + jwt_scope arv = c.open('/v2/auth', headers=[('authorization', test_spec.gen_basic_auth(username, password))], query_string=query_string) msg = 'Auth failed for %s %s: got %s, expected: 200' % ( test_spec.method_name, test_spec.index_name, arv.status_code) self.assertEqual(arv.status_code, 200, msg) headers = [('authorization', 'Bearer ' + json.loads(arv.data)['token'])] rv = c.open(url, headers=headers, method=test_spec.method_name) msg = '%s %s: got %s, expected: %s (auth: %s | headers %s)' % (test_spec.method_name, test_spec.index_name, rv.status_code, expected_index_status, attrs['auth_username'], len(headers)) self.assertEqual(rv.status_code, expected_index_status, msg) return test def __new__(cls, name, bases, attrs): with app.test_request_context() as ctx: specs = attrs['spec_func']() for test_spec in specs: test_name = '%s_%s_%s_%s_%s' % (test_spec.index_name, test_spec.method_name, test_spec.repo_name, attrs['auth_username'] or 'anon', attrs['result_attr']) test_name = test_name.replace('/', '_').replace('-', '_') test_name = 'test_' + test_name.lower().replace('v2.', 'v2_') url = test_spec.get_url() attrs[test_name] = _SpecTestBuilder._test_generator(url, test_spec, attrs) return type(name, bases, attrs) class TestAnonymousAccess(EndpointTestCase): __metaclass__ = _SpecTestBuilder spec_func = build_v2_index_specs result_attr = 'anon_code' auth_username = None class TestNoAccess(EndpointTestCase): __metaclass__ = _SpecTestBuilder spec_func = build_v2_index_specs result_attr = 'no_access_code' auth_username = NO_ACCESS_USER class TestReadAccess(EndpointTestCase): __metaclass__ = _SpecTestBuilder spec_func = build_v2_index_specs result_attr = 'read_code' auth_username = READ_ACCESS_USER class TestCreatorAccess(EndpointTestCase): __metaclass__ = _SpecTestBuilder spec_func = build_v2_index_specs result_attr = 'creator_code' auth_username = CREATOR_ACCESS_USER class TestAdminAccess(EndpointTestCase): __metaclass__ = _SpecTestBuilder spec_func = build_v2_index_specs result_attr = 'admin_code' auth_username = ADMIN_ACCESS_USER if __name__ == '__main__': unittest.main()