Home | History | Annotate | Download | only in sl4a_lib
      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 import errno
     17 import mock
     18 from socket import timeout
     19 from socket import error as socket_error
     20 import unittest
     21 from mock import patch
     22 
     23 from acts.controllers.sl4a_lib import sl4a_ports
     24 from acts.controllers.sl4a_lib import sl4a_session
     25 from acts.controllers.sl4a_lib import rpc_client
     26 
     27 
     28 class Sl4aSessionTest(unittest.TestCase):
     29     """Tests the sl4a_session.Sl4aSession class."""
     30 
     31     def test_is_alive_true_on_not_terminated(self):
     32         """Tests sl4a_session.Sl4aSession.is_alive.
     33 
     34         Tests that the session is_alive when it has not been terminated.
     35         """
     36         session = mock.Mock()
     37         session._terminated = False
     38         session.is_alive = sl4a_session.Sl4aSession.is_alive
     39         self.assertNotEqual(session._terminated, session.is_alive)
     40 
     41     def test_is_alive_false_on_terminated(self):
     42         """Tests sl4a_session.Sl4aSession.is_alive.
     43 
     44         Tests that the session is_alive when it has not been terminated.
     45         """
     46         session = mock.Mock()
     47         session._terminated = True
     48         session.is_alive = sl4a_session.Sl4aSession.is_alive
     49         self.assertNotEqual(session._terminated, session.is_alive)
     50 
     51     @patch('acts.controllers.sl4a_lib.event_dispatcher.EventDispatcher')
     52     def test_get_event_dispatcher_create_on_none(self, _):
     53         """Tests sl4a_session.Sl4aSession.get_event_dispatcher.
     54 
     55         Tests that a new event_dispatcher is created if one does not exist.
     56         """
     57         session = mock.Mock()
     58         session._event_dispatcher = None
     59         ed = sl4a_session.Sl4aSession.get_event_dispatcher(session)
     60         self.assertTrue(session._event_dispatcher is not None)
     61         self.assertEqual(session._event_dispatcher, ed)
     62 
     63     def test_get_event_dispatcher_returns_existing_event_dispatcher(self):
     64         """Tests sl4a_session.Sl4aSession.get_event_dispatcher.
     65 
     66         Tests that the existing event_dispatcher is returned.
     67         """
     68         session = mock.Mock()
     69         session._event_dispatcher = 'Something that is not None'
     70         ed = sl4a_session.Sl4aSession.get_event_dispatcher(session)
     71         self.assertEqual(session._event_dispatcher, ed)
     72 
     73     def test_create_client_side_connection_hint_already_in_use(self):
     74         """Tests sl4a_session.Sl4aSession._create_client_side_connection().
     75 
     76         Tests that if the hinted port is already in use, the function will
     77         call itself with a hinted port of 0 (random).
     78         """
     79         session = mock.Mock()
     80         session._create_client_side_connection = mock.Mock()
     81         with mock.patch('socket.socket') as socket:
     82             # Throw an error when trying to bind to the hinted port.
     83             error = OSError()
     84             error.errno = errno.EADDRINUSE
     85             socket_instance = mock.Mock()
     86             socket_instance.bind = mock.Mock()
     87             socket_instance.bind.side_effect = error
     88             socket.return_value = socket_instance
     89 
     90             sl4a_session.Sl4aSession._create_client_side_connection(
     91                 session, sl4a_ports.Sl4aPorts(1, 2, 3))
     92 
     93         fn = session._create_client_side_connection
     94         self.assertEqual(fn.call_count, 1)
     95         # Asserts that the 1st argument (Sl4aPorts) sent to the function
     96         # has a client port of 0.
     97         self.assertEqual(fn.call_args_list[0][0][0].client_port, 0)
     98 
     99     def test_create_client_side_connection_catches_timeout(self):
    100         """Tests sl4a_session.Sl4aSession._create_client_side_connection().
    101 
    102         Tests that the function will raise an Sl4aConnectionError upon timeout.
    103         """
    104         session = mock.Mock()
    105         session._create_client_side_connection = mock.Mock()
    106         error = timeout()
    107         with mock.patch('socket.socket') as socket:
    108             # Throw an error when trying to bind to the hinted port.
    109             socket_instance = mock.Mock()
    110             socket_instance.connect = mock.Mock()
    111             socket_instance.connect.side_effect = error
    112             socket.return_value = socket_instance
    113 
    114             with self.assertRaises(rpc_client.Sl4aConnectionError):
    115                 sl4a_session.Sl4aSession._create_client_side_connection(
    116                     session, sl4a_ports.Sl4aPorts(0, 2, 3))
    117 
    118     def test_create_client_side_connection_hint_taken_during_fn(self):
    119         """Tests sl4a_session.Sl4aSession._create_client_side_connection().
    120 
    121         Tests that the function will call catch an EADDRNOTAVAIL OSError and
    122         call itself again, this time with a hinted port of 0 (random).
    123         """
    124         session = mock.Mock()
    125         session._create_client_side_connection = mock.Mock()
    126         error = socket_error()
    127         error.errno = errno.EADDRNOTAVAIL
    128         with mock.patch('socket.socket') as socket:
    129             # Throw an error when trying to bind to the hinted port.
    130             socket_instance = mock.Mock()
    131             socket_instance.connect = mock.Mock()
    132             socket_instance.connect.side_effect = error
    133             socket.return_value = socket_instance
    134 
    135             sl4a_session.Sl4aSession._create_client_side_connection(
    136                 session, sl4a_ports.Sl4aPorts(0, 2, 3))
    137 
    138         fn = session._create_client_side_connection
    139         self.assertEqual(fn.call_count, 1)
    140         # Asserts that the 1st argument (Sl4aPorts) sent to the function
    141         # has a client port of 0.
    142         self.assertEqual(fn.call_args_list[0][0][0].client_port, 0)
    143 
    144     def test_create_client_side_connection_re_raises_uncaught_errors(self):
    145         """Tests sl4a_session.Sl4aSession._create_client_side_connection().
    146 
    147         Tests that the function will re-raise any socket error that does not
    148         have errno.EADDRNOTAVAIL.
    149         """
    150         session = mock.Mock()
    151         session._create_client_side_connection = mock.Mock()
    152         error = socket_error()
    153         # Some error that isn't EADDRNOTAVAIL
    154         error.errno = errno.ESOCKTNOSUPPORT
    155         with mock.patch('socket.socket') as socket:
    156             # Throw an error when trying to bind to the hinted port.
    157             socket_instance = mock.Mock()
    158             socket_instance.connect = mock.Mock()
    159             socket_instance.connect.side_effect = error
    160             socket.return_value = socket_instance
    161 
    162             with self.assertRaises(socket_error):
    163                 sl4a_session.Sl4aSession._create_client_side_connection(
    164                     session, sl4a_ports.Sl4aPorts(0, 2, 3))
    165 
    166     def test_terminate_only_closes_if_not_terminated(self):
    167         """Tests sl4a_session.Sl4aSession.terminate()
    168 
    169         Tests that terminate only runs termination steps if the session has not
    170         already been terminated.
    171         """
    172         session = mock.Mock()
    173         session._terminate_lock = mock.MagicMock()
    174         session._terminated = True
    175         sl4a_session.Sl4aSession.terminate(session)
    176 
    177         self.assertFalse(session._event_dispatcher.close.called)
    178         self.assertFalse(session.rpc_client.terminate.called)
    179 
    180     def test_terminate_closes_session_first(self):
    181         """Tests sl4a_session.Sl4aSession.terminate()
    182 
    183         Tests that terminate only runs termination steps if the session has not
    184         already been terminated.
    185         """
    186         session = mock.Mock()
    187         session._terminate_lock = mock.MagicMock()
    188         session._terminated = True
    189         sl4a_session.Sl4aSession.terminate(session)
    190 
    191         self.assertFalse(session._event_dispatcher.close.called)
    192         self.assertFalse(session.rpc_client.terminate.called)
    193 
    194 
    195 if __name__ == '__main__':
    196     unittest.main()
    197