1#!/usr/bin/env vpython3 2# Copyright 2022 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 log_manager.py.""" 6 7import sys 8import unittest 9import unittest.mock as mock 10 11import log_manager 12 13_LOGS_DIR = 'test_logs_dir' 14 15 16class LogManagerTest(unittest.TestCase): 17 """Unittests for log_manager.py.""" 18 19 @mock.patch('log_manager.run_continuous_ffx_command') 20 def test_no_logs(self, mock_ffx) -> None: 21 """Test |start_system_log| does nothing when logging is off.""" 22 23 log = log_manager.LogManager(None) 24 log_manager.start_system_log(log, False) 25 self.assertEqual(mock_ffx.call_count, 0) 26 27 @mock.patch('log_manager.run_continuous_ffx_command') 28 def test_log_to_stdout(self, mock_ffx) -> None: 29 """Test |start_system_log| logs to stdout when log manager is off.""" 30 31 log = log_manager.LogManager(None) 32 log_manager.start_system_log(log, True) 33 self.assertEqual(mock_ffx.call_args_list[0][1]['stdout'], sys.stdout) 34 self.assertEqual(mock_ffx.call_count, 1) 35 36 @mock.patch('log_manager.run_continuous_ffx_command') 37 @mock.patch('builtins.open') 38 def test_log_to_file(self, mock_open, mock_ffx) -> None: 39 """Test |start_system_log| logs to log file when log manager is on.""" 40 41 log = log_manager.LogManager(_LOGS_DIR) 42 log_manager.start_system_log(log, False) 43 self.assertEqual(mock_ffx.call_args_list[0][1]['stdout'], 44 mock_open.return_value) 45 self.assertEqual(mock_ffx.call_count, 1) 46 47 @mock.patch('log_manager.run_continuous_ffx_command') 48 def test_log_with_log_args(self, mock_ffx) -> None: 49 """Test log args are used when passed in to |start_system_log|.""" 50 51 log = log_manager.LogManager(None) 52 log_manager.start_system_log(log, True, log_args=['test_log_args']) 53 self.assertEqual( 54 mock_ffx.call_args_list[0][0][0], 55 ['log', '--symbolize', 'off', '--no-color', 'test_log_args']) 56 self.assertEqual(mock_ffx.call_count, 1) 57 58 @mock.patch('log_manager.run_continuous_ffx_command') 59 def test_log_with_symbols(self, mock_ffx) -> None: 60 """Test symbols are used when pkg_paths are set.""" 61 62 log = log_manager.LogManager(_LOGS_DIR) 63 with mock.patch('os.path.isfile', return_value=True), \ 64 mock.patch('builtins.open'), \ 65 mock.patch('log_manager.run_symbolizer'): 66 log_manager.start_system_log(log, False, pkg_paths=['test_pkg']) 67 log.stop() 68 self.assertEqual(mock_ffx.call_count, 1) 69 self.assertEqual(mock_ffx.call_args_list[0][0][0], 70 ['log', '--symbolize', 'off', '--no-color']) 71 72 def test_no_logging_dir_exception(self) -> None: 73 """Tests empty LogManager throws an exception on |open_log_file|.""" 74 75 log = log_manager.LogManager(None) 76 with self.assertRaises(Exception): 77 log.open_log_file('test_log_file') 78 79 @mock.patch('log_manager.ScopedFfxConfig') 80 @mock.patch('log_manager.stop_ffx_daemon') 81 def test_log_manager(self, mock_stop_ffx_daemon, 82 mock_scoped_config) -> None: 83 """Tests LogManager as a context manager.""" 84 85 with mock.patch('log_manager.running_unattended', return_value=False): 86 context_mock = mock.Mock() 87 mock_scoped_config.return_value = context_mock 88 context_mock.__enter__ = mock.Mock(return_value=None) 89 context_mock.__exit__ = mock.Mock(return_value=None) 90 with log_manager.LogManager(_LOGS_DIR): 91 pass 92 self.assertEqual(mock_scoped_config.call_count, 1) 93 self.assertEqual(context_mock.__enter__.call_count, 1) 94 self.assertEqual(context_mock.__exit__.call_count, 1) 95 self.assertEqual(mock_stop_ffx_daemon.call_count, 2) 96 97 @mock.patch('log_manager.ScopedFfxConfig') 98 @mock.patch('log_manager.stop_ffx_daemon') 99 def test_log_manager_unattended_no_daemon_stop(self, mock_stop_ffx_daemon, 100 mock_scoped_config) -> None: 101 """Tests LogManager as a context manager in unattended mode.""" 102 103 with mock.patch('log_manager.running_unattended', return_value=True): 104 context_mock = mock.Mock() 105 mock_scoped_config.return_value = context_mock 106 context_mock.__enter__ = mock.Mock(return_value=None) 107 context_mock.__exit__ = mock.Mock(return_value=None) 108 with log_manager.LogManager(_LOGS_DIR): 109 pass 110 self.assertEqual(mock_scoped_config.call_count, 1) 111 self.assertEqual(context_mock.__enter__.call_count, 1) 112 self.assertEqual(context_mock.__exit__.call_count, 1) 113 self.assertEqual(mock_stop_ffx_daemon.call_count, 0) 114 115 def test_main_exception(self) -> None: 116 """Tests |main| function to throw exception on incompatible flags.""" 117 118 with mock.patch('sys.argv', 119 ['log_manager.py', '--packages', 'test_package']): 120 with self.assertRaises(ValueError): 121 log_manager.main() 122 123 @mock.patch('log_manager.read_package_paths') 124 @mock.patch('log_manager.start_system_log') 125 def test_main(self, mock_system_log, mock_read_paths) -> None: 126 """Tests |main| function.""" 127 128 with mock.patch('sys.argv', [ 129 'log_manager.py', '--packages', 'test_package', '--out-dir', 130 'test_out_dir' 131 ]): 132 with mock.patch('common.time.sleep', 133 side_effect=KeyboardInterrupt): 134 log_manager.main() 135 self.assertEqual(mock_system_log.call_count, 1) 136 self.assertEqual(mock_read_paths.call_count, 1) 137 138 139if __name__ == '__main__': 140 unittest.main() 141