• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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