diff options
-rw-r--r-- | oslo/__init__.py | 13 | ||||
-rw-r--r-- | oslo/middleware/__init__.py | 28 | ||||
-rw-r--r-- | oslo/middleware/base.py | 13 | ||||
-rw-r--r-- | oslo/middleware/catch_errors.py | 13 | ||||
-rw-r--r-- | oslo/middleware/correlation_id.py | 13 | ||||
-rw-r--r-- | oslo/middleware/debug.py | 13 | ||||
-rw-r--r-- | oslo/middleware/request_id.py | 13 | ||||
-rw-r--r-- | oslo/middleware/sizelimit.py | 13 | ||||
-rw-r--r-- | setup.cfg | 4 | ||||
-rw-r--r-- | tests/__init__.py | 0 | ||||
-rw-r--r-- | tests/test_catch_errors.py | 47 | ||||
-rw-r--r-- | tests/test_correlation_id.py | 53 | ||||
-rw-r--r-- | tests/test_request_id.py | 37 | ||||
-rw-r--r-- | tests/test_sizelimit.py | 108 | ||||
-rw-r--r-- | tests/test_warning.py | 61 |
15 files changed, 429 insertions, 0 deletions
diff --git a/oslo/__init__.py b/oslo/__init__.py new file mode 100644 index 0000000..dc130d6 --- /dev/null +++ b/oslo/__init__.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +__import__('pkg_resources').declare_namespace(__name__) diff --git a/oslo/middleware/__init__.py b/oslo/middleware/__init__.py new file mode 100644 index 0000000..1407ce1 --- /dev/null +++ b/oslo/middleware/__init__.py @@ -0,0 +1,28 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import warnings + +from oslo_middleware import * + + +def deprecated(): + new_name = __name__.replace('.', '_') + warnings.warn( + ('The oslo namespace package is deprecated. Please use %s instead.' % + new_name), + DeprecationWarning, + stacklevel=3, + ) + + +deprecated() diff --git a/oslo/middleware/base.py b/oslo/middleware/base.py new file mode 100644 index 0000000..53e25e9 --- /dev/null +++ b/oslo/middleware/base.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_middleware.base import * # noqa diff --git a/oslo/middleware/catch_errors.py b/oslo/middleware/catch_errors.py new file mode 100644 index 0000000..81e4c6c --- /dev/null +++ b/oslo/middleware/catch_errors.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_middleware.catch_errors import * # noqa diff --git a/oslo/middleware/correlation_id.py b/oslo/middleware/correlation_id.py new file mode 100644 index 0000000..fff548c --- /dev/null +++ b/oslo/middleware/correlation_id.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_middleware.correlation_id import * # noqa diff --git a/oslo/middleware/debug.py b/oslo/middleware/debug.py new file mode 100644 index 0000000..2907289 --- /dev/null +++ b/oslo/middleware/debug.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_middleware.debug import * # noqa diff --git a/oslo/middleware/request_id.py b/oslo/middleware/request_id.py new file mode 100644 index 0000000..81e3164 --- /dev/null +++ b/oslo/middleware/request_id.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_middleware.request_id import * # noqa diff --git a/oslo/middleware/sizelimit.py b/oslo/middleware/sizelimit.py new file mode 100644 index 0000000..c04c1cd --- /dev/null +++ b/oslo/middleware/sizelimit.py @@ -0,0 +1,13 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_middleware.sizelimit import * # noqa @@ -21,7 +21,11 @@ classifier = [files] packages = + oslo + oslo.middleware oslo_middleware +namespace_packages = + oslo [entry_points] oslo.config.opts = diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/__init__.py diff --git a/tests/test_catch_errors.py b/tests/test_catch_errors.py new file mode 100644 index 0000000..9e71f5b --- /dev/null +++ b/tests/test_catch_errors.py @@ -0,0 +1,47 @@ +# Copyright (c) 2013 NEC Corporation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock +from oslotest import base as test_base +import webob.dec +import webob.exc + +from oslo.middleware import catch_errors + + +class CatchErrorsTest(test_base.BaseTestCase): + + def _test_has_request_id(self, application, expected_code=None): + app = catch_errors.CatchErrors(application) + req = webob.Request.blank('/test') + res = req.get_response(app) + self.assertEqual(expected_code, res.status_int) + + def test_success_response(self): + @webob.dec.wsgify + def application(req): + return 'Hello, World!!!' + + self._test_has_request_id(application, webob.exc.HTTPOk.code) + + def test_internal_server_error(self): + @webob.dec.wsgify + def application(req): + raise Exception() + + with mock.patch.object(catch_errors.LOG, 'exception') as log_exc: + self._test_has_request_id(application, + webob.exc.HTTPInternalServerError.code) + self.assertEqual(1, log_exc.call_count) diff --git a/tests/test_correlation_id.py b/tests/test_correlation_id.py new file mode 100644 index 0000000..b927e1d --- /dev/null +++ b/tests/test_correlation_id.py @@ -0,0 +1,53 @@ +# Copyright (c) 2013 Rackspace Hosting +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import uuid + +import mock +from oslotest import base as test_base +from oslotest import moxstubout + +from oslo.middleware import correlation_id + + +class CorrelationIdTest(test_base.BaseTestCase): + + def setUp(self): + super(CorrelationIdTest, self).setUp() + self.stubs = self.useFixture(moxstubout.MoxStubout()).stubs + + def test_process_request(self): + app = mock.Mock() + req = mock.Mock() + req.headers = {} + + mock_uuid4 = mock.Mock() + mock_uuid4.return_value = "fake_uuid" + self.stubs.Set(uuid, 'uuid4', mock_uuid4) + + middleware = correlation_id.CorrelationId(app) + middleware(req) + + self.assertEqual(req.headers.get("X_CORRELATION_ID"), "fake_uuid") + + def test_process_request_should_not_regenerate_correlation_id(self): + app = mock.Mock() + req = mock.Mock() + req.headers = {"X_CORRELATION_ID": "correlation_id"} + + middleware = correlation_id.CorrelationId(app) + middleware(req) + + self.assertEqual(req.headers.get("X_CORRELATION_ID"), "correlation_id") diff --git a/tests/test_request_id.py b/tests/test_request_id.py new file mode 100644 index 0000000..549d7be --- /dev/null +++ b/tests/test_request_id.py @@ -0,0 +1,37 @@ +# Copyright (c) 2013 NEC Corporation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from oslotest import base as test_base +from testtools import matchers +import webob +import webob.dec + +from oslo.middleware import request_id + + +class RequestIdTest(test_base.BaseTestCase): + def test_generate_request_id(self): + @webob.dec.wsgify + def application(req): + return req.environ[request_id.ENV_REQUEST_ID] + + app = request_id.RequestId(application) + req = webob.Request.blank('/test') + res = req.get_response(app) + res_req_id = res.headers.get(request_id.HTTP_RESP_HEADER_REQUEST_ID) + self.assertThat(res_req_id, matchers.StartsWith(b'req-')) + # request-id in request environ is returned as response body + self.assertEqual(res_req_id, res.body) diff --git a/tests/test_sizelimit.py b/tests/test_sizelimit.py new file mode 100644 index 0000000..0f26a49 --- /dev/null +++ b/tests/test_sizelimit.py @@ -0,0 +1,108 @@ +# Copyright (c) 2012 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslotest import base as test_base +import six +import webob + +from oslo.config import fixture as config +from oslo.middleware import sizelimit + + +class TestLimitingReader(test_base.BaseTestCase): + + def test_limiting_reader(self): + BYTES = 1024 + bytes_read = 0 + data = six.StringIO("*" * BYTES) + for chunk in sizelimit.LimitingReader(data, BYTES): + bytes_read += len(chunk) + + self.assertEqual(bytes_read, BYTES) + + bytes_read = 0 + data = six.StringIO("*" * BYTES) + reader = sizelimit.LimitingReader(data, BYTES) + byte = reader.read(1) + while len(byte) != 0: + bytes_read += 1 + byte = reader.read(1) + + self.assertEqual(bytes_read, BYTES) + + def test_read_default_value(self): + BYTES = 1024 + data_str = "*" * BYTES + data = six.StringIO(data_str) + reader = sizelimit.LimitingReader(data, BYTES) + res = reader.read() + self.assertEqual(data_str, res) + + def test_limiting_reader_fails(self): + BYTES = 1024 + + def _consume_all_iter(): + bytes_read = 0 + data = six.StringIO("*" * BYTES) + for chunk in sizelimit.LimitingReader(data, BYTES - 1): + bytes_read += len(chunk) + + self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + _consume_all_iter) + + def _consume_all_read(): + bytes_read = 0 + data = six.StringIO("*" * BYTES) + reader = sizelimit.LimitingReader(data, BYTES - 1) + byte = reader.read(1) + while len(byte) != 0: + bytes_read += 1 + byte = reader.read(1) + + self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + _consume_all_read) + + +class TestRequestBodySizeLimiter(test_base.BaseTestCase): + + def setUp(self): + super(TestRequestBodySizeLimiter, self).setUp() + fixture = self.useFixture(config.Config(sizelimit.CONF)) + self.MAX_REQUEST_BODY_SIZE = \ + fixture.conf.oslo_middleware.max_request_body_size + + @webob.dec.wsgify() + def fake_app(req): + return webob.Response(req.body) + + self.middleware = sizelimit.RequestBodySizeLimiter(fake_app) + self.request = webob.Request.blank('/', method='POST') + + def test_content_length_acceptable(self): + self.request.headers['Content-Length'] = self.MAX_REQUEST_BODY_SIZE + self.request.body = b"0" * self.MAX_REQUEST_BODY_SIZE + response = self.request.get_response(self.middleware) + self.assertEqual(response.status_int, 200) + + def test_content_length_too_large(self): + self.request.headers['Content-Length'] = self.MAX_REQUEST_BODY_SIZE + 1 + self.request.body = b"0" * (self.MAX_REQUEST_BODY_SIZE + 1) + response = self.request.get_response(self.middleware) + self.assertEqual(response.status_int, 413) + + def test_request_too_large_no_content_length(self): + self.request.body = b"0" * (self.MAX_REQUEST_BODY_SIZE + 1) + self.request.headers['Content-Length'] = None + response = self.request.get_response(self.middleware) + self.assertEqual(response.status_int, 413) diff --git a/tests/test_warning.py b/tests/test_warning.py new file mode 100644 index 0000000..8e7d96c --- /dev/null +++ b/tests/test_warning.py @@ -0,0 +1,61 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import imp +import os +import warnings + +import mock +from oslotest import base as test_base +import six + + +class DeprecationWarningTest(test_base.BaseTestCase): + + @mock.patch('warnings.warn') + def test_warning(self, mock_warn): + import oslo.middleware + imp.reload(oslo.middleware) + self.assertTrue(mock_warn.called) + args = mock_warn.call_args + self.assertIn('oslo_middleware', args[0][0]) + self.assertIn('deprecated', args[0][0]) + self.assertTrue(issubclass(args[0][1], DeprecationWarning)) + + def test_real_warning(self): + with warnings.catch_warnings(record=True) as warning_msgs: + warnings.resetwarnings() + warnings.simplefilter('always', DeprecationWarning) + import oslo.middleware + + # Use a separate function to get the stack level correct + # so we know the message points back to this file. This + # corresponds to an import or reload, which isn't working + # inside the test under Python 3.3. That may be due to a + # difference in the import implementation not triggering + # warnings properly when the module is reloaded, or + # because the warnings module is mostly implemented in C + # and something isn't cleanly resetting the global state + # used to track whether a warning needs to be + # emitted. Whatever the cause, we definitely see the + # warnings.warn() being invoked on a reload (see the test + # above) and warnings are reported on the console when we + # run the tests. A simpler test script run outside of + # testr does correctly report the warnings. + def foo(): + oslo.middleware.deprecated() + + foo() + self.assertEqual(1, len(warning_msgs)) + msg = warning_msgs[0] + self.assertIn('oslo_middleware', six.text_type(msg.message)) + self.assertEqual('test_warning.py', os.path.basename(msg.filename)) |