1#!/usr/bin/env python3 2# 3# Copyright 2018 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from mock import Mock 18from mock import patch 19import unittest 20from unittest import TestCase 21from acts.metrics.logger import LoggerProxy 22from acts.metrics.logger import MetricLogger 23 24CREATE_FROM_INSTANCE = ( 25 'acts.metrics.logger.subscription_bundle.create_from_instance') 26LOGGING_ERROR = 'logging.error' 27LOGGING_DEBUG = 'logging.debug' 28GET_CONTEXT_FOR_EVENT = 'acts.metrics.logger.get_context_for_event' 29GET_FILE = 'acts.metrics.logger.inspect.getfile' 30MKDTEMP = 'acts.metrics.logger.tempfile.mkdtemp' 31PROTO_METRIC_PUBLISHER = 'acts.metrics.logger.ProtoMetricPublisher' 32TEST_CASE_LOGGER_PROXY = 'acts.metrics.logger.TestCaseLoggerProxy' 33TEST_CLASS_LOGGER_PROXY = 'acts.metrics.logger.TestClassLoggerProxy' 34 35 36class MetricLoggerTest(TestCase): 37 """Unit tests for the MetricLogger class.""" 38 39 @patch(TEST_CASE_LOGGER_PROXY) 40 def test_for_test_case_returns_test_case_proxy(self, proxy_cls): 41 args = (Mock(), ) 42 kwargs = {'mock' : Mock()} 43 logger = MetricLogger.for_test_case(*args, **kwargs) 44 45 proxy_cls.assert_called_once_with(MetricLogger, args, kwargs) 46 47 @patch(TEST_CLASS_LOGGER_PROXY) 48 def test_for_test_class_returns_test_class_proxy(self, proxy_cls): 49 args = (Mock(),) 50 kwargs = {'mock': Mock()} 51 logger = MetricLogger.for_test_class(*args, **kwargs) 52 53 proxy_cls.assert_called_once_with(MetricLogger, args, kwargs) 54 55 @patch(TEST_CASE_LOGGER_PROXY) 56 def test_for_test_case_works_on_subclases(self, proxy_cls): 57 class TestLogger(MetricLogger): 58 pass 59 args = (Mock(),) 60 kwargs = {'mock': Mock()} 61 logger = TestLogger.for_test_case(*args, **kwargs) 62 63 proxy_cls.assert_called_once_with(TestLogger, args, kwargs) 64 65 @patch(TEST_CLASS_LOGGER_PROXY) 66 def test_for_test_class_works_on_subclases(self, proxy_cls): 67 class TestLogger(MetricLogger): 68 pass 69 args = (Mock(),) 70 kwargs = {'mock': Mock()} 71 logger = TestLogger.for_test_class(*args, **kwargs) 72 73 proxy_cls.assert_called_once_with(TestLogger, args, kwargs) 74 75 def test_init_empty(self): 76 logger = MetricLogger() 77 78 self.assertIsNone(logger.context) 79 self.assertIsNone(logger.publisher) 80 81 def test_init_with_context_and_publisher(self): 82 context = Mock() 83 publisher = Mock() 84 85 logger = MetricLogger(context=context, publisher=publisher) 86 87 self.assertEqual(logger.context, context) 88 self.assertEqual(logger.publisher, publisher) 89 90 @patch(PROTO_METRIC_PUBLISHER) 91 @patch(GET_CONTEXT_FOR_EVENT) 92 def test_init_with_event(self, get_context, publisher_cls): 93 context = Mock() 94 publisher = Mock() 95 get_context.return_value = context 96 publisher_cls.return_value = publisher 97 event = Mock() 98 99 logger = MetricLogger(event=event) 100 101 get_context.assert_called_once_with(event) 102 publisher_cls.assert_called_once_with(context) 103 self.assertEqual(logger.context, context) 104 self.assertEqual(logger.publisher, publisher) 105 106 def test_start_has_default_impl(self): 107 logger = MetricLogger() 108 logger.start(Mock()) 109 110 def test_end_has_default_impl(self): 111 logger = MetricLogger() 112 logger.end(Mock()) 113 114 115class LoggerProxyTest(TestCase): 116 117 @patch(CREATE_FROM_INSTANCE) 118 def test_init(self, create_from_instance): 119 logger_cls = Mock() 120 logger_args = Mock() 121 logger_kwargs = Mock() 122 bundle = Mock() 123 create_from_instance.return_value = bundle 124 proxy = LoggerProxy(logger_cls, 125 logger_args, 126 logger_kwargs) 127 128 self.assertEqual(proxy._logger_cls, logger_cls) 129 self.assertEqual(proxy._logger_args, logger_args) 130 self.assertEqual(proxy._logger_kwargs, logger_kwargs) 131 self.assertIsNone(proxy._logger) 132 create_from_instance.assert_called_once_with(proxy) 133 bundle.register.assert_called_once_with() 134 135 @patch(CREATE_FROM_INSTANCE) 136 def test_setup_proxy(self, create_from_instance): 137 logger_cls = Mock() 138 logger_args = (Mock(), ) 139 logger_kwargs = {'mock': Mock()} 140 bundle = Mock() 141 event = Mock() 142 create_from_instance.return_value = bundle 143 logger = Mock() 144 logger_cls.return_value = logger 145 146 proxy = LoggerProxy(logger_cls, 147 logger_args, 148 logger_kwargs) 149 proxy._setup_proxy(event) 150 151 logger_cls.assert_called_once_with(event=event, 152 *logger_args, 153 **logger_kwargs) 154 logger.start.assert_called_once_with(event) 155 156 @patch(CREATE_FROM_INSTANCE) 157 def test_teardown_proxy(self, create_from_instance): 158 logger_cls = Mock() 159 logger_args = (Mock(),) 160 logger_kwargs = {'mock': Mock()} 161 bundle = Mock() 162 event = Mock() 163 create_from_instance.return_value = bundle 164 logger = Mock() 165 logger_cls.return_value = logger 166 167 proxy = LoggerProxy(logger_cls, 168 logger_args, 169 logger_kwargs) 170 proxy._setup_proxy(event) 171 proxy._teardown_proxy(event) 172 173 logger.end.assert_called_once_with(event) 174 self.assertIsNone(proxy._logger) 175 176 @patch(LOGGING_DEBUG) 177 @patch(LOGGING_ERROR) 178 @patch(CREATE_FROM_INSTANCE) 179 def test_teardown_proxy_logs_upon_exception(self, create_from_instance, 180 logging_error, logging_debug): 181 logger_cls = Mock() 182 logger_args = (Mock(),) 183 logger_kwargs = {'mock': Mock()} 184 bundle = Mock() 185 event = Mock() 186 create_from_instance.return_value = bundle 187 logger = Mock() 188 logger.end.side_effect = ValueError('test') 189 logger_cls.return_value = logger 190 191 proxy = LoggerProxy(logger_cls, 192 logger_args, 193 logger_kwargs) 194 proxy._setup_proxy(event) 195 proxy._teardown_proxy(event) 196 197 self.assertTrue(logging_error.called) 198 self.assertTrue(logging_debug.called) 199 self.assertIsNone(proxy._logger) 200 201 @patch(CREATE_FROM_INSTANCE) 202 def test_getattr_forwards_to_logger(self, create_from_instance): 203 logger_cls = Mock() 204 logger_args = (Mock(),) 205 logger_kwargs = {'mock': Mock()} 206 bundle = Mock() 207 event = Mock() 208 create_from_instance.return_value = bundle 209 logger = Mock() 210 logger_cls.return_value = logger 211 212 proxy = LoggerProxy(logger_cls, 213 logger_args, 214 logger_kwargs) 215 proxy._setup_proxy(event) 216 217 self.assertEqual(proxy.some_attr, logger.some_attr) 218 219 @patch(CREATE_FROM_INSTANCE) 220 def test_getattr_with_no_logger_raises(self, create_from_instance): 221 bundle = Mock() 222 create_from_instance.return_value = bundle 223 224 proxy = LoggerProxy(Mock(), Mock(), Mock()) 225 226 self.assertRaises(ValueError, lambda: proxy.some_attr) 227 228 @patch(CREATE_FROM_INSTANCE) 229 def test_setattr_forwards_to_logger(self, create_from_instance): 230 logger_cls = Mock() 231 logger_args = (Mock(),) 232 logger_kwargs = {'mock': Mock()} 233 bundle = Mock() 234 event = Mock() 235 create_from_instance.return_value = bundle 236 logger = Mock() 237 logger_cls.return_value = logger 238 value = Mock() 239 240 proxy = LoggerProxy(logger_cls, 241 logger_args, 242 logger_kwargs) 243 proxy._setup_proxy(event) 244 proxy.some_attr = value 245 246 self.assertEqual(logger.some_attr, value) 247 248 @patch(CREATE_FROM_INSTANCE) 249 def test_setattr_with_no_logger_raises(self, create_from_instance): 250 bundle = Mock() 251 create_from_instance.return_value = bundle 252 value = Mock() 253 254 proxy = LoggerProxy(Mock(), Mock(), Mock()) 255 256 def try_set(): 257 proxy.some_attr = value 258 self.assertRaises(ValueError, try_set) 259 260 261if __name__ == '__main__': 262 unittest.main() 263