| #!/usr/bin/env python3 |
| # |
| # Copyright 2018 - The Android Open Source Project |
| # |
| # 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 mock import Mock |
| from mock import patch |
| import unittest |
| from unittest import TestCase |
| from acts.metrics.logger import LoggerProxy |
| from acts.metrics.logger import MetricLogger |
| |
| CREATE_FROM_INSTANCE = ( |
| 'acts.metrics.logger.subscription_bundle.create_from_instance') |
| LOGGING_ERROR = 'logging.error' |
| LOGGING_DEBUG = 'logging.debug' |
| GET_CONTEXT_FOR_EVENT = 'acts.metrics.logger.get_context_for_event' |
| GET_FILE = 'acts.metrics.logger.inspect.getfile' |
| MKDTEMP = 'acts.metrics.logger.tempfile.mkdtemp' |
| PROTO_METRIC_PUBLISHER = 'acts.metrics.logger.ProtoMetricPublisher' |
| TEST_CASE_LOGGER_PROXY = 'acts.metrics.logger.TestCaseLoggerProxy' |
| TEST_CLASS_LOGGER_PROXY = 'acts.metrics.logger.TestClassLoggerProxy' |
| |
| |
| class MetricLoggerTest(TestCase): |
| """Unit tests for the MetricLogger class.""" |
| |
| @patch(TEST_CASE_LOGGER_PROXY) |
| def test_for_test_case_returns_test_case_proxy(self, proxy_cls): |
| args = (Mock(), ) |
| kwargs = {'mock' : Mock()} |
| logger = MetricLogger.for_test_case(*args, **kwargs) |
| |
| proxy_cls.assert_called_once_with(MetricLogger, args, kwargs) |
| |
| @patch(TEST_CLASS_LOGGER_PROXY) |
| def test_for_test_class_returns_test_class_proxy(self, proxy_cls): |
| args = (Mock(),) |
| kwargs = {'mock': Mock()} |
| logger = MetricLogger.for_test_class(*args, **kwargs) |
| |
| proxy_cls.assert_called_once_with(MetricLogger, args, kwargs) |
| |
| @patch(TEST_CASE_LOGGER_PROXY) |
| def test_for_test_case_works_on_subclases(self, proxy_cls): |
| class TestLogger(MetricLogger): |
| pass |
| args = (Mock(),) |
| kwargs = {'mock': Mock()} |
| logger = TestLogger.for_test_case(*args, **kwargs) |
| |
| proxy_cls.assert_called_once_with(TestLogger, args, kwargs) |
| |
| @patch(TEST_CLASS_LOGGER_PROXY) |
| def test_for_test_class_works_on_subclases(self, proxy_cls): |
| class TestLogger(MetricLogger): |
| pass |
| args = (Mock(),) |
| kwargs = {'mock': Mock()} |
| logger = TestLogger.for_test_class(*args, **kwargs) |
| |
| proxy_cls.assert_called_once_with(TestLogger, args, kwargs) |
| |
| def test_init_empty(self): |
| logger = MetricLogger() |
| |
| self.assertIsNone(logger.context) |
| self.assertIsNone(logger.publisher) |
| |
| def test_init_with_context_and_publisher(self): |
| context = Mock() |
| publisher = Mock() |
| |
| logger = MetricLogger(context=context, publisher=publisher) |
| |
| self.assertEqual(logger.context, context) |
| self.assertEqual(logger.publisher, publisher) |
| |
| @patch(PROTO_METRIC_PUBLISHER) |
| @patch(GET_CONTEXT_FOR_EVENT) |
| def test_init_with_event(self, get_context, publisher_cls): |
| context = Mock() |
| publisher = Mock() |
| get_context.return_value = context |
| publisher_cls.return_value = publisher |
| event = Mock() |
| |
| logger = MetricLogger(event=event) |
| |
| get_context.assert_called_once_with(event) |
| publisher_cls.assert_called_once_with(context) |
| self.assertEqual(logger.context, context) |
| self.assertEqual(logger.publisher, publisher) |
| |
| def test_start_has_default_impl(self): |
| logger = MetricLogger() |
| logger.start(Mock()) |
| |
| def test_end_has_default_impl(self): |
| logger = MetricLogger() |
| logger.end(Mock()) |
| |
| |
| class LoggerProxyTest(TestCase): |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_init(self, create_from_instance): |
| logger_cls = Mock() |
| logger_args = Mock() |
| logger_kwargs = Mock() |
| bundle = Mock() |
| create_from_instance.return_value = bundle |
| proxy = LoggerProxy(logger_cls, |
| logger_args, |
| logger_kwargs) |
| |
| self.assertEqual(proxy._logger_cls, logger_cls) |
| self.assertEqual(proxy._logger_args, logger_args) |
| self.assertEqual(proxy._logger_kwargs, logger_kwargs) |
| self.assertIsNone(proxy._logger) |
| create_from_instance.assert_called_once_with(proxy) |
| bundle.register.assert_called_once_with() |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_setup_proxy(self, create_from_instance): |
| logger_cls = Mock() |
| logger_args = (Mock(), ) |
| logger_kwargs = {'mock': Mock()} |
| bundle = Mock() |
| event = Mock() |
| create_from_instance.return_value = bundle |
| logger = Mock() |
| logger_cls.return_value = logger |
| |
| proxy = LoggerProxy(logger_cls, |
| logger_args, |
| logger_kwargs) |
| proxy._setup_proxy(event) |
| |
| logger_cls.assert_called_once_with(event=event, |
| *logger_args, |
| **logger_kwargs) |
| logger.start.assert_called_once_with(event) |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_teardown_proxy(self, create_from_instance): |
| logger_cls = Mock() |
| logger_args = (Mock(),) |
| logger_kwargs = {'mock': Mock()} |
| bundle = Mock() |
| event = Mock() |
| create_from_instance.return_value = bundle |
| logger = Mock() |
| logger_cls.return_value = logger |
| |
| proxy = LoggerProxy(logger_cls, |
| logger_args, |
| logger_kwargs) |
| proxy._setup_proxy(event) |
| proxy._teardown_proxy(event) |
| |
| logger.end.assert_called_once_with(event) |
| self.assertIsNone(proxy._logger) |
| |
| @patch(LOGGING_DEBUG) |
| @patch(LOGGING_ERROR) |
| @patch(CREATE_FROM_INSTANCE) |
| def test_teardown_proxy_logs_upon_exception(self, create_from_instance, |
| logging_error, logging_debug): |
| logger_cls = Mock() |
| logger_args = (Mock(),) |
| logger_kwargs = {'mock': Mock()} |
| bundle = Mock() |
| event = Mock() |
| create_from_instance.return_value = bundle |
| logger = Mock() |
| logger.end.side_effect = ValueError('test') |
| logger_cls.return_value = logger |
| |
| proxy = LoggerProxy(logger_cls, |
| logger_args, |
| logger_kwargs) |
| proxy._setup_proxy(event) |
| proxy._teardown_proxy(event) |
| |
| self.assertTrue(logging_error.called) |
| self.assertTrue(logging_debug.called) |
| self.assertIsNone(proxy._logger) |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_getattr_forwards_to_logger(self, create_from_instance): |
| logger_cls = Mock() |
| logger_args = (Mock(),) |
| logger_kwargs = {'mock': Mock()} |
| bundle = Mock() |
| event = Mock() |
| create_from_instance.return_value = bundle |
| logger = Mock() |
| logger_cls.return_value = logger |
| |
| proxy = LoggerProxy(logger_cls, |
| logger_args, |
| logger_kwargs) |
| proxy._setup_proxy(event) |
| |
| self.assertEqual(proxy.some_attr, logger.some_attr) |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_getattr_with_no_logger_raises(self, create_from_instance): |
| bundle = Mock() |
| create_from_instance.return_value = bundle |
| |
| proxy = LoggerProxy(Mock(), Mock(), Mock()) |
| |
| self.assertRaises(ValueError, lambda: proxy.some_attr) |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_setattr_forwards_to_logger(self, create_from_instance): |
| logger_cls = Mock() |
| logger_args = (Mock(),) |
| logger_kwargs = {'mock': Mock()} |
| bundle = Mock() |
| event = Mock() |
| create_from_instance.return_value = bundle |
| logger = Mock() |
| logger_cls.return_value = logger |
| value = Mock() |
| |
| proxy = LoggerProxy(logger_cls, |
| logger_args, |
| logger_kwargs) |
| proxy._setup_proxy(event) |
| proxy.some_attr = value |
| |
| self.assertEqual(logger.some_attr, value) |
| |
| @patch(CREATE_FROM_INSTANCE) |
| def test_setattr_with_no_logger_raises(self, create_from_instance): |
| bundle = Mock() |
| create_from_instance.return_value = bundle |
| value = Mock() |
| |
| proxy = LoggerProxy(Mock(), Mock(), Mock()) |
| |
| def try_set(): |
| proxy.some_attr = value |
| self.assertRaises(ValueError, try_set) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |