• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, True])
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.assertEqual(serial_boot_device.main('reboot'), 0)
65        mock_run.assert_called_once_with(
66            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot'])
67
68    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False, True])
69    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False])
70    @mock.patch('subprocess.run',
71                return_value=CompletedProcess(args=['/bin'], returncode=0))
72    def test_boot_undetectable_not_must_boot(self, mock_run, *_) -> None:
73        self.assertTrue(
74            serial_boot_device.boot_device('fuchsia-node-id',
75                                           'fuchsia-serial-num',
76                                           BootMode.REGULAR,
77                                           must_boot=False))
78        mock_run.assert_called_once_with(
79            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot'])
80
81    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False])
82    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False, True])
83    @mock.patch('subprocess.run',
84                return_value=CompletedProcess(args=['/bin'], returncode=0))
85    def test_boot_undetectable_to_fastboot(self, mock_run, *_) -> None:
86        self.assertEqual(serial_boot_device.main('reboot-fastboot'), 0)
87        mock_run.assert_called_once_with(
88            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot-bootloader'])
89
90    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False])
91    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True, True])
92    @mock.patch('subprocess.run',
93                return_value=CompletedProcess(args=['/bin'], returncode=0))
94    def test_boot_from_fuchsia_to_fuchsia(self, mock_run, *_) -> None:
95        self.assertEqual(serial_boot_device.main('reboot'), 0)
96        mock_run.assert_called_once_with(
97            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot'])
98
99    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False])
100    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True])
101    @mock.patch('subprocess.run',
102                return_value=CompletedProcess(args=['/bin'], returncode=0))
103    def test_boot_from_fuchsia_to_fuchsia_not_must_boot(self, mock_run,
104                                                        *_) -> None:
105        self.assertTrue(
106            serial_boot_device.boot_device('fuchsia-node-id',
107                                           'fuchsia-serial-num',
108                                           BootMode.REGULAR,
109                                           must_boot=False))
110        mock_run.assert_not_called()
111
112    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False, True])
113    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[True])
114    @mock.patch('subprocess.run',
115                return_value=CompletedProcess(args=['/bin'], returncode=0))
116    def test_boot_from_fastboot_to_fuchsia(self, mock_run, *_) -> None:
117        self.assertEqual(serial_boot_device.main('reboot'), 0)
118        mock_run.assert_called_once_with(
119            ['fastboot', 'reboot', '-s', 'fuchsia-serial-num'],
120            capture_output=True,
121            timeout=30)
122
123    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[True])
124    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[False, True])
125    @mock.patch('subprocess.run',
126                return_value=CompletedProcess(args=['/bin'], returncode=0))
127    def test_boot_from_fuchsia_to_fastboot(self, mock_run, *_) -> None:
128        self.assertEqual(serial_boot_device.main('reboot-fastboot'), 0)
129        mock_run.assert_called_once_with(
130            ['serialio', 'fuchsia-node-id', 'send', 'dm', 'reboot-bootloader'])
131
132    @mock.patch('serial_boot_device.is_in_fuchsia', side_effect=[False])
133    @mock.patch('serial_boot_device.is_in_fastboot', side_effect=[True])
134    @mock.patch('subprocess.run',
135                return_value=CompletedProcess(args=['/bin'], returncode=0))
136    def test_boot_from_fastboot_to_fastboot(self, mock_run, *_) -> None:
137        self.assertEqual(serial_boot_device.main('reboot-fastboot'), 0)
138        mock_run.assert_not_called()
139
140
141if __name__ == '__main__':
142    unittest.main()
143