xref: /aosp_15_r20/external/angle/build/fuchsia/test/serial_boot_device_unittests.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1#!/usr/bin/env vpython3
2# Copyright 2023 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""File for testing serial_boot_device.py."""
6
7import json
8import os
9import unittest
10import unittest.mock as mock
11
12from subprocess import CompletedProcess
13
14import serial_boot_device
15
16from boot_device import BootMode
17
18
19# pylint: disable=too-many-public-methods, missing-function-docstring
20@mock.patch('shutil.which', return_value='/bin')
21class SerialBootDeviceTest(unittest.TestCase):
22    """Unittests for serial_boot_device.py."""
23    def setUp(self) -> None:
24        os.environ['FUCHSIA_NODENAME'] = 'fuchsia-node-id'
25        os.environ['FUCHSIA_FASTBOOT_SERNUM'] = 'fuchsia-serial-num'
26
27    def test_does_not_boot_without_binaries(self, *_) -> None:
28        with mock.patch('shutil.which', return_value=None):
29            self.assertNotEqual(serial_boot_device.main('reboot'), 0)
30
31    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True])
32    @mock.patch('subprocess.run',
33                return_value=CompletedProcess(args=['/bin'], returncode=0))
34    @mock.patch('builtins.print')
35    def test_check_health_in_fuchsia(self, mock_print, *_) -> None:
36        self.assertEqual(serial_boot_device.main('health-check'), 0)
37        result = json.loads(mock_print.call_args.args[0])
38        self.assertEqual(result[0]['nodename'], 'fuchsia-node-id')
39        self.assertEqual(result[0]['state'], 'healthy')
40
41    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[True])
42    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False])
43    @mock.patch('subprocess.run',
44                return_value=CompletedProcess(args=['/bin'], returncode=0))
45    @mock.patch('builtins.print')
46    def test_check_health_in_fastboot(self, mock_print, *_) -> None:
47        self.assertEqual(serial_boot_device.main('health-check'), 0)
48        result = json.loads(mock_print.call_args.args[0])
49        self.assertEqual(result[0]['nodename'], 'fuchsia-node-id')
50        self.assertEqual(result[0]['state'], 'healthy')
51
52    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False])
53    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False])
54    @mock.patch('subprocess.run',
55                return_value=CompletedProcess(args=['/bin'], returncode=0))
56    def test_check_health_undetectable(self, *_) -> None:
57        self.assertNotEqual(serial_boot_device.main('health-check'), 0)
58
59    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False])
60    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False])
61    @mock.patch('subprocess.run',
62                return_value=CompletedProcess(args=['/bin'], returncode=0))
63    def test_boot_undetectable(self, mock_run, *_) -> None:
64        self.assertNotEqual(serial_boot_device.main('reboot'), 0)
65        mock_run.assert_not_called()
66
67    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True, True])
68    @mock.patch('subprocess.run',
69                return_value=CompletedProcess(args=['/bin'], returncode=0))
70    def test_boot_from_fuchsia_to_fuchsia(self, mock_run, *_) -> None:
71        self.assertEqual(serial_boot_device.main('reboot'), 0)
72        mock_run.assert_called_once_with(
73            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot'])
74
75    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True])
76    @mock.patch('subprocess.run',
77                return_value=CompletedProcess(args=['/bin'], returncode=0))
78    def test_boot_from_fuchsia_to_fuchsia_not_must_boot(self, mock_run,
79                                                        *_) -> None:
80        self.assertTrue(
81            serial_boot_device.boot_device('fuchsia-node-id',
82                                           'fuchsia-serial-num',
83                                           BootMode.REGULAR,
84                                           must_boot=False))
85        mock_run.assert_not_called()
86
87    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False, True])
88    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[True])
89    @mock.patch('subprocess.run',
90                return_value=CompletedProcess(args=['/bin'], returncode=0))
91    def test_boot_from_fastboot_to_fuchsia(self, mock_run, *_) -> None:
92        self.assertEqual(serial_boot_device.main('reboot'), 0)
93        mock_run.assert_called_once_with(
94            ['fastboot', 'reboot', '-s', 'fuchsia-serial-num'],
95            capture_output=True,
96            timeout=30)
97
98    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True])
99    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[True])
100    @mock.patch('subprocess.run',
101                return_value=CompletedProcess(args=['/bin'], returncode=0))
102    def test_boot_from_fuchsia_to_fastboot(self, mock_run, *_) -> None:
103        self.assertEqual(serial_boot_device.main('reboot-fastboot'), 0)
104        mock_run.assert_called_once_with(
105            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot-bootloader'])
106
107    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False])
108    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[True])
109    @mock.patch('subprocess.run',
110                return_value=CompletedProcess(args=['/bin'], returncode=0))
111    def test_boot_from_fastboot_to_fastboot(self, mock_run, *_) -> None:
112        self.assertEqual(serial_boot_device.main('reboot-fastboot'), 0)
113        mock_run.assert_not_called()
114
115
116if __name__ == '__main__':
117    unittest.main()
118