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