blob: 693176e75ce75b9ed745fa183f1b4f0f260c625c [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright 2021 - The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for RemoteEmulatorConsole."""
import unittest
import subprocess
from unittest import mock
from acloud import errors
from acloud.internal.lib import driver_test_lib
from acloud.internal.lib import emulator_console
class EmulatorConsoleTest(driver_test_lib.BaseDriverTest):
"""Unit tests for RemoteEmulatorConsole."""
_LOCAL_PORT = 56789
_TIMEOUT_SECS = 100
def setUp(self):
"""Create mock objects."""
super().setUp()
self._mock_pick_free_port = self.Patch(
emulator_console.utils, "PickFreePort",
return_value=self._LOCAL_PORT)
self._mock_establish_ssh_tunnel = self.Patch(
emulator_console.utils,
"EstablishSshTunnel")
self._mock_release_port = self.Patch(
emulator_console.utils,
"ReleasePort")
self._mock_connection = mock.Mock()
self._mock_create_connection = self.Patch(
emulator_console.socket,
"create_connection",
return_value=self._mock_connection)
def _CreateRemoteEmulatorConsole(self):
"""_Create a RemoteEmulatorConsole."""
console = emulator_console.RemoteEmulatorConsole(
"192.0.2.1", 5444, "user", "key_path", "extra args",
self._TIMEOUT_SECS)
self._mock_pick_free_port.assert_called_once()
self._mock_establish_ssh_tunnel.assert_called_once_with(
"192.0.2.1", "key_path", "user",
[(self._LOCAL_PORT, 5444)], "extra args")
self._mock_create_connection.assert_called_once_with(
("127.0.0.1", self._LOCAL_PORT), self._TIMEOUT_SECS)
self._mock_connection.settimeout.assert_called_once_with(
self._TIMEOUT_SECS)
self._mock_release_port.assert_not_called()
self._mock_connection.close.assert_not_called()
self._mock_pick_free_port.reset_mock()
self._mock_establish_ssh_tunnel.reset_mock()
self._mock_create_connection.reset_mock()
self._mock_connection.settimeout.reset_mock()
return console
def testInitSshTunnelError(self):
"""Test not releasing port if SSH tunnel fails."""
self._mock_establish_ssh_tunnel.side_effect = (
subprocess.CalledProcessError(returncode=1, cmd="ssh"))
with self.assertRaises(errors.DeviceConnectionError):
emulator_console.RemoteEmulatorConsole(
"192.0.2.1", 5444, "user", "key_path", "extra args",
self._TIMEOUT_SECS)
self._mock_connection.settimeout.assert_not_called()
self._mock_connection.close.assert_not_called()
self._mock_release_port.assert_not_called()
def testInitConnectionError(self):
"""Test releasing port when create_connection fails."""
self._mock_create_connection.side_effect = OSError()
with self.assertRaises(errors.DeviceConnectionError):
emulator_console.RemoteEmulatorConsole(
"192.0.2.1", 5444, "user", "key_path", "extra args",
self._TIMEOUT_SECS)
self._mock_connection.settimeout.assert_not_called()
self._mock_connection.close.assert_not_called()
self._mock_release_port.assert_called_once()
def testInitSocketError(self):
"""Test closing socket when settimeout fails."""
self._mock_connection.settimeout.side_effect = OSError()
with self.assertRaises(errors.DeviceConnectionError):
emulator_console.RemoteEmulatorConsole(
"192.0.2.1", 5444, "user", "key_path", "extra args",
self._TIMEOUT_SECS)
self._mock_connection.settimeout.assert_called_once()
self._mock_connection.close.assert_called_once()
self._mock_release_port.assert_called_once()
def testContext(self):
"""Test RemoteEmulatorConsole as a context manager."""
with self._CreateRemoteEmulatorConsole():
pass
self._mock_connection.close.assert_called_once()
self._mock_release_port.assert_called_once()
def testReconnect(self):
"""Test RemoteEmulatorConsole.Reconnect."""
console = self._CreateRemoteEmulatorConsole()
console.Reconnect()
self._mock_pick_free_port.assert_not_called()
self._mock_establish_ssh_tunnel.assert_not_called()
self._mock_release_port.assert_not_called()
self._mock_connection.close.assert_called_once()
self._mock_create_connection.assert_called_once_with(
("127.0.0.1", self._LOCAL_PORT), self._TIMEOUT_SECS)
self._mock_connection.settimeout.assert_called_once_with(
self._TIMEOUT_SECS)
def testSend(self):
"""Test RemoteEmulatorConsole.Send."""
console = self._CreateRemoteEmulatorConsole()
console.Send("ping")
self._mock_connection.send.assert_called_with(b"ping\n")
self._mock_connection.send.side_effect = OSError()
with self.assertRaises(errors.DeviceConnectionError):
console.Send("ping")
def testRecv(self):
"""Test RemoteEmulatorConsole.Recv."""
console = self._CreateRemoteEmulatorConsole()
self._mock_connection.recv.side_effect = [b"1", b"1"]
self.assertEqual("11", console.Recv("11", buffer_size=1))
self._mock_connection.recv.side_effect = [b"12"]
self.assertEqual("12", console.Recv("2"))
self._mock_connection.recv.side_effect = [b"1", b""]
with self.assertRaises(errors.DeviceConnectionError):
console.Recv("2")
self._mock_connection.recv.side_effect = OSError()
with self.assertRaises(errors.DeviceConnectionError):
console.Recv("1")
def testPing(self):
"""Test RemoteEmulatorConsole.Ping."""
console = self._CreateRemoteEmulatorConsole()
self._mock_connection.recv.side_effect = [b"I am alive!\r\nOK\r\n"]
self.assertTrue(console.Ping())
self._mock_connection.recv.side_effect = [b""]
self.assertFalse(console.Ping())
self._mock_connection.recv.side_effect = OSError()
self.assertFalse(console.Ping())
def testKill(self):
"""Test RemoteEmulatorConsole.Kill."""
console = self._CreateRemoteEmulatorConsole()
self._mock_connection.recv.side_effect = [b"bye bye\r\n"]
console.Kill()
if __name__ == "__main__":
unittest.main()