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. 16import unittest 17from unittest import TestCase 18 19from mock import Mock 20from mock import patch 21 22from acts.event import event_bus 23from acts.event.event import Event 24from acts.event.event_subscription import EventSubscription 25 26 27class EventBusTest(TestCase): 28 """Tests the event_bus functions.""" 29 30 def setUp(self): 31 """Clears all state from the event_bus between test cases.""" 32 event_bus._event_bus = event_bus._EventBus() 33 34 def get_subscription_argument(self, register_subscription_call): 35 """Gets the subscription argument from a register_subscription call.""" 36 return register_subscription_call[0][0] 37 38 @patch('acts.event.event_bus._event_bus.register_subscription') 39 def test_register_registers_a_subscription(self, register_subscription): 40 """Tests that register creates and registers a subscription.""" 41 mock_event = Mock() 42 mock_func = Mock() 43 order = 43 44 event_bus.register(mock_event, mock_func, order=order) 45 46 args, _ = register_subscription.call_args 47 subscription = args[0] 48 49 # Instead of writing an equality operator for only testing, 50 # check the internals to make sure they are expected values. 51 self.assertEqual(subscription._event_type, mock_event) 52 self.assertEqual(subscription._func, mock_func) 53 self.assertEqual(subscription.order, order) 54 55 @patch('acts.event.event_bus._event_bus.register_subscription') 56 def test_register_subscriptions_for_list(self, register_subscription): 57 """Tests that register_subscription is called for each subscription.""" 58 mocks = [Mock(), Mock(), Mock()] 59 subscriptions = [ 60 EventSubscription(mocks[0], lambda _: None), 61 EventSubscription(mocks[1], lambda _: None), 62 EventSubscription(mocks[2], lambda _: None), 63 ] 64 65 event_bus.register_subscriptions(subscriptions) 66 received_subscriptions = set() 67 for index, call in enumerate(register_subscription.call_args_list): 68 received_subscriptions.add(self.get_subscription_argument(call)) 69 70 self.assertEqual(register_subscription.call_count, len(subscriptions)) 71 self.assertSetEqual(received_subscriptions, set(subscriptions)) 72 73 def test_register_subscription_new_event_type(self): 74 """Tests that the event_bus can register a new event type.""" 75 mock_type = Mock() 76 bus = event_bus._event_bus 77 subscription = EventSubscription(mock_type, lambda _: None) 78 79 reg_id = event_bus.register_subscription(subscription) 80 81 self.assertTrue(mock_type in bus._subscriptions.keys()) 82 self.assertTrue(subscription in bus._subscriptions[mock_type]) 83 self.assertTrue(reg_id in bus._registration_id_map.keys()) 84 85 def test_register_subscription_existing_type(self): 86 """Tests that the event_bus can register an existing event type.""" 87 mock_type = Mock() 88 bus = event_bus._event_bus 89 bus._subscriptions[mock_type] = [ 90 EventSubscription(mock_type, lambda _: None) 91 ] 92 new_subscription = EventSubscription(mock_type, lambda _: True) 93 94 reg_id = event_bus.register_subscription(new_subscription) 95 96 self.assertTrue(new_subscription in bus._subscriptions[mock_type]) 97 self.assertTrue(reg_id in bus._registration_id_map.keys()) 98 99 def test_post_to_unregistered_event_does_not_call_other_funcs(self): 100 """Tests posting an unregistered event will not call other funcs.""" 101 mock_subscription = Mock() 102 bus = event_bus._event_bus 103 mock_type = Mock() 104 mock_subscription.event_type = mock_type 105 bus._subscriptions[mock_type] = [mock_subscription] 106 107 event_bus.post(Mock()) 108 109 self.assertEqual(mock_subscription.deliver.call_count, 0) 110 111 def test_post_to_registered_event_calls_all_registered_funcs(self): 112 """Tests posting to a registered event calls all registered funcs.""" 113 mock_subscriptions = [Mock(), Mock(), Mock()] 114 bus = event_bus._event_bus 115 for subscription in mock_subscriptions: 116 subscription.order = 0 117 mock_event = Mock() 118 bus._subscriptions[type(mock_event)] = mock_subscriptions 119 120 event_bus.post(mock_event) 121 122 for subscription in mock_subscriptions: 123 subscription.deliver.assert_called_once_with(mock_event) 124 125 def test_post_with_ignore_errors_calls_all_registered_funcs(self): 126 """Tests posting with ignore_errors=True calls all registered funcs, 127 even if they raise errors. 128 """ 129 130 def _raise(_): 131 raise Exception 132 133 mock_event = Mock() 134 mock_subscriptions = [Mock(), Mock(), Mock()] 135 mock_subscriptions[0].deliver.side_effect = _raise 136 bus = event_bus._event_bus 137 for i, subscription in enumerate(mock_subscriptions): 138 subscription.order = i 139 bus._subscriptions[type(mock_event)] = mock_subscriptions 140 141 event_bus.post(mock_event, ignore_errors=True) 142 143 for subscription in mock_subscriptions: 144 subscription.deliver.assert_called_once_with(mock_event) 145 146 @patch('acts.event.event_bus._event_bus.unregister') 147 def test_unregister_all_from_list(self, unregister): 148 """Tests unregistering from a list unregisters the specified list.""" 149 unregister_list = [Mock(), Mock()] 150 151 event_bus.unregister_all(from_list=unregister_list) 152 153 self.assertEqual(unregister.call_count, len(unregister_list)) 154 for args, _ in unregister.call_args_list: 155 subscription = args[0] 156 self.assertTrue(subscription in unregister_list) 157 158 @patch('acts.event.event_bus._event_bus.unregister') 159 def test_unregister_all_from_event(self, unregister): 160 """Tests that all subscriptions under the event are unregistered.""" 161 mock_event = Mock() 162 mock_event_2 = Mock() 163 bus = event_bus._event_bus 164 unregister_list = [Mock(), Mock()] 165 bus._subscriptions[type(mock_event_2)] = [Mock(), Mock(), Mock()] 166 bus._subscriptions[type(mock_event)] = unregister_list 167 for sub_type in bus._subscriptions.keys(): 168 for subscription in bus._subscriptions[sub_type]: 169 subscription.event_type = sub_type 170 bus._registration_id_map[id(subscription)] = subscription 171 172 event_bus.unregister_all(from_event=type(mock_event)) 173 174 self.assertEqual(unregister.call_count, len(unregister_list)) 175 for args, _ in unregister.call_args_list: 176 subscription = args[0] 177 self.assertTrue(subscription in unregister_list) 178 179 @patch('acts.event.event_bus._event_bus.unregister') 180 def test_unregister_all_no_args_unregisters_everything(self, unregister): 181 """Tests unregister_all without arguments will unregister everything.""" 182 mock_event_1 = Mock() 183 mock_event_2 = Mock() 184 bus = event_bus._event_bus 185 unregister_list_1 = [Mock(), Mock()] 186 unregister_list_2 = [Mock(), Mock(), Mock()] 187 bus._subscriptions[type(mock_event_1)] = unregister_list_1 188 bus._subscriptions[type(mock_event_2)] = unregister_list_2 189 for sub_type in bus._subscriptions.keys(): 190 for subscription in bus._subscriptions[sub_type]: 191 subscription.event_type = sub_type 192 bus._registration_id_map[id(subscription)] = subscription 193 194 event_bus.unregister_all() 195 196 self.assertEqual(unregister.call_count, 197 len(unregister_list_1) + len(unregister_list_2)) 198 for args, _ in unregister.call_args_list: 199 subscription = args[0] 200 self.assertTrue(subscription in unregister_list_1 201 or subscription in unregister_list_2) 202 203 def test_unregister_given_an_event_subscription(self): 204 """Tests that unregister can unregister a given EventSubscription.""" 205 mock_event = Mock() 206 bus = event_bus._event_bus 207 subscription = EventSubscription(type(mock_event), lambda _: None) 208 bus._registration_id_map[id(subscription)] = subscription 209 bus._subscriptions[type(mock_event)] = [subscription] 210 211 val = event_bus.unregister(subscription) 212 213 self.assertTrue(val) 214 self.assertTrue(subscription not in bus._registration_id_map) 215 self.assertTrue( 216 subscription not in bus._subscriptions[type(mock_event)]) 217 218 def test_unregister_given_a_registration_id(self): 219 """Tests that unregister can unregister a given EventSubscription.""" 220 mock_event = Mock() 221 bus = event_bus._event_bus 222 subscription = EventSubscription(type(mock_event), lambda _: None) 223 registration_id = id(subscription) 224 bus._registration_id_map[id(subscription)] = subscription 225 bus._subscriptions[type(mock_event)] = [subscription] 226 227 val = event_bus.unregister(registration_id) 228 229 self.assertTrue(val) 230 self.assertTrue(subscription not in bus._registration_id_map) 231 self.assertTrue( 232 subscription not in bus._subscriptions[type(mock_event)]) 233 234 def test_unregister_given_object_that_is_not_a_subscription(self): 235 """Asserts that a ValueError is raised upon invalid arguments.""" 236 with self.assertRaises(ValueError): 237 event_bus.unregister(Mock()) 238 239 def test_unregister_given_invalid_registration_id(self): 240 """Asserts that a false is returned upon invalid registration_id.""" 241 val = event_bus.unregister(9) 242 self.assertFalse(val) 243 244 def test_listen_for_registers_listener(self): 245 """Tests listen_for registers the listener within the with statement.""" 246 bus = event_bus._event_bus 247 248 def event_listener(_): 249 pass 250 251 with event_bus.listen_for(Event, event_listener): 252 self.assertEqual(len(bus._registration_id_map), 1) 253 254 def test_listen_for_unregisters_listener(self): 255 """Tests listen_for unregisters the listener after the with statement. 256 """ 257 bus = event_bus._event_bus 258 259 def event_listener(_): 260 pass 261 262 with event_bus.listen_for(Event, event_listener): 263 pass 264 265 self.assertEqual(len(bus._registration_id_map), 0) 266 267 268if __name__ == '__main__': 269 unittest.main() 270