- System test framework can now assert specific response codes automatically

- Revised system test for issue #85 based on clarification from Ziad
- Added system test to attempt admin action using a service token
This commit is contained in:
Dolph Mathews
2011-07-19 15:25:21 -05:00
parent a93bc04dde
commit 9dcd6c1cd2
4 changed files with 79 additions and 24 deletions

View File

@@ -5,7 +5,7 @@ class HttpTestCase(unittest.TestCase):
"""Performs generic HTTP request testing"""
def request(self, host='127.0.0.1', port=80, method='GET', path='/',
headers={}, body=None, expect_exception=False,):
headers={}, body=None, assert_status=None):
"""Perform request and fetch httplib.HTTPResponse from the server"""
# Initialize a connection
@@ -22,26 +22,26 @@ class HttpTestCase(unittest.TestCase):
connection.close()
# Automatically assert HTTP status code
if not expect_exception:
self.assertSuccessfulResponse(response)
if assert_status:
self.assertResponseStatus(response, assert_status)
else:
self.assertExceptionalResponse(response)
self.assertResponseSuccessful(response)
# Contains the response headers, body, etc
return response
def assertSuccessfulResponse(self, response):
def assertResponseSuccessful(self, response):
"""Asserts that a status code lies inside the 2xx range"""
self.assertTrue(response.status >= 200 and response.status <= 299,
'Status code %d is outside of the expected range (2xx) \n\n%s' %
(response.status, response.body))
def assertExceptionalResponse(self, response):
"""Asserts that a status code lies outside the 2xx range"""
self.assertFalse(response.status >= 200 and response.status <= 299,
'Status code %d is outside of the expected range (not 2xx)\n\n%s' %
'Status code %d is outside of the expected range (2xx)\n\n%s' %
(response.status, response.body))
def assertResponseStatus(self, response, assert_status):
"""Asserts a specific status code on the response"""
self.assertEqual(response.status, assert_status,
'Status code %s is not %s, as expected)\n\n%s' %
(response.status, assert_status, response.body))
class RestfulTestCase(HttpTestCase):
"""Performs restful HTTP request testing"""

View File

@@ -18,6 +18,58 @@ class TestAdminAuthentication(KeystoneTestCase):
self.assertTrue(r.json['auth']['token']['id'])
self.assertTrue(r.json['auth']['token']['expires'])
class TestAdminAuthenticationNegative(KeystoneTestCase):
"""Negative test admin-side user authentication"""
user_id = KeystoneTestCase._uuid()
user_id2 = KeystoneTestCase._uuid()
def test_service_token_as_admin_token(self):
"""Admin actions should fail for mere service tokens"""
# Admin create a user
self.admin_request(method='PUT', path='/users',
json={
'user': {
'id': self.user_id,
'password': 'secrete',
'email': self.user_id + '@openstack.org',
'enabled': True,
}
})
# User authenticates to get a token
r = self.service_request(method='POST', path='/tokens',
json={
'passwordCredentials': {
'username': self.user_id,
'password': 'secrete',
}
})
self.service_token = r.json['auth']['token']['id']
# Prepare to use the service token as an admin token
self.admin_token_backup = self.admin_token
self.admin_token = self.service_token
# Try creating another user
self.admin_request(method='PUT', path='/users', assert_status=401,
json={
'user': {
'id': self.user_id2,
'password': 'secrete',
'email': self.user_id2 + '@openstack.org',
'enabled': True,
}
})
def tearDown(self):
# Restore our admin token so we can clean up
self.admin_token = self.admin_token_backup
# Delete user
self.admin_request(method='DELETE', path='/users/%s' % self.user_id)
class TestServiceAuthentication(KeystoneTestCase):
"""Test service-side user authentication"""
@@ -32,7 +84,7 @@ class TestServiceAuthentication(KeystoneTestCase):
'user': {
'id': self.user_id,
'password': 'secrete',
'email': 'user@openstack.org',
'email': self.user_id + '@openstack.org',
'enabled': True,
}
})

View File

@@ -20,7 +20,7 @@ class TestIssue85(KeystoneTestCase):
}
})
# Create a user
# Create a user for a specific tenant
self.admin_request(method='PUT', path='/users',
json={
'user':{
@@ -28,7 +28,7 @@ class TestIssue85(KeystoneTestCase):
'password': 'secrete',
'email': 'user@openstack.org',
'enabled': True,
'tenant_id': 'tenant',
'tenantId': self.tenant_id
}
})
@@ -43,18 +43,20 @@ class TestIssue85(KeystoneTestCase):
def test_disabling_tenant_disables_token(self):
"""Disabling a tenant should invalidate previously-issued tokens"""
# Authenticate as user to get a token
# Authenticate as user to get a token *for a specific tenant*
r = self.service_request(method='POST', path='/tokens',
json={
'passwordCredentials': {
'username': self.user_id,
'password': 'secrete',
'tenantId': self.tenant_id
}
})
self.service_token = r.json['auth']['token']['id']
# Validate tenant token
self.admin_request(path='/tokens/%s' % self.service_token)
# Validate and check that token belongs to tenant
self.admin_request(path='/tokens/%s?belongsTo=%s' %
(self.service_token, self.tenant_id))
# Disable tenant
r = self.admin_request(method='PUT',
@@ -67,10 +69,11 @@ class TestIssue85(KeystoneTestCase):
})
self.assertEqual(r.json['tenant']['enabled'], False)
# Assert tenant token invalidated
# Commented this out because it will fail this test
# self.admin_request(path='/tokens/%s' % self.service_token,
# expect_exception=True)
# Assert that token belonging to disabled tenant is invalid
r = self.admin_request(path='/tokens/%s?belongsTo=%s' %
(self.service_token, self.tenant_id),
assert_status=403)
self.assertTrue(r.json['tenantDisabled'], 'Tenant is disabled')
if __name__ == '__main__':
unittest.main()

View File

@@ -56,7 +56,7 @@ class TestContentTypes(KeystoneTestCase):
"""Content-Type should be honored even on 404 errors (Issue #13)"""
_r = self.service_request(path='/completely-invalid-path',
headers={'Accept': 'application/xml'},
expect_exception=True)
assert_status=404)
# Commenting this assertion out, as it currently fails
# self.assertTrue('application/xml' in r.getheader('Content-Type'),