1#!/usr/bin/env vpython3 2# Copyright 2020 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 6import logging 7import os 8import subprocess 9import sys 10import tempfile 11import time 12import unittest 13 14import mock 15from parameterized import parameterized 16 17import test_runner 18 19 20class TestRunnerTest(unittest.TestCase): 21 def setUp(self): 22 logging.disable(logging.CRITICAL) 23 time.sleep = mock.Mock() 24 25 def tearDown(self): 26 logging.disable(logging.NOTSET) 27 28 @mock.patch.object(os.path, 29 'dirname', 30 return_value='chromium/src/build/lacros') 31 def test_expand_filter_file(self, _): 32 args = ['--some_flag="flag"'] 33 test_runner._ExpandFilterFileIfNeeded('browser_tests', args) 34 self.assertTrue(args[1].endswith( 35 'chromium/src/' 36 'testing/buildbot/filters/linux-lacros.browser_tests.filter')) 37 self.assertTrue(args[1].startswith('--test-launcher-filter-file=')) 38 39 args = ['--some_flag="flag"'] 40 test_runner._ExpandFilterFileIfNeeded('random_tests', args) 41 self.assertEqual(len(args), 1) 42 43 args = ['--test-launcher-filter-file=new/filter'] 44 test_runner._ExpandFilterFileIfNeeded('browser_tests', args) 45 self.assertEqual(len(args), 1) 46 self.assertTrue(args[0].endswith('new/filter')) 47 48 @parameterized.expand([ 49 'url_unittests', 50 './url_unittests', 51 'out/release/url_unittests', 52 './out/release/url_unittests', 53 ]) 54 @mock.patch.object(os.path, 'isfile', return_value=True) 55 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 56 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 57 # Tests that the test runner doesn't attempt to download ash-chrome if not 58 # required. 59 def test_do_not_require_ash_chrome(self, command, mock_popen, mock_download, 60 _): 61 args = ['script_name', 'test', command] 62 with mock.patch.object(sys, 'argv', args): 63 test_runner.Main() 64 self.assertEqual(1, mock_popen.call_count) 65 mock_popen.assert_called_with([command]) 66 self.assertFalse(mock_download.called) 67 68 @parameterized.expand([ 69 'browser_tests', 'components_browsertests', 'content_browsertests', 70 'lacros_chrome_browsertests', 71 'browser_tests --enable-pixel-output-in-tests' 72 ]) 73 @mock.patch.object(os, 74 'listdir', 75 return_value=['wayland-exo', 'wayland-exo.lock']) 76 @mock.patch.object(tempfile, 77 'mkdtemp', 78 side_effect=['/tmp/xdg', '/tmp/ash-data', '/tmp/unique']) 79 @mock.patch.object(os.environ, 'copy', side_effect=[{}, {}]) 80 @mock.patch.object(os.path, 'exists', return_value=True) 81 @mock.patch.object(os.path, 'isfile', return_value=True) 82 @mock.patch.object(os.path, 'abspath', return_value='/a/b/filter') 83 @mock.patch.object(test_runner, 84 '_GetLatestVersionOfAshChrome', 85 return_value='793554') 86 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 87 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 88 # Tests that the test runner downloads and spawns ash-chrome if ash-chrome is 89 # required. 90 def test_require_ash_chrome(self, command, mock_popen, mock_download, *_): 91 command_parts = command.split() 92 args = ['script_name', 'test'] 93 args.extend(command_parts) 94 with mock.patch.object(sys, 'argv', args): 95 test_runner.Main() 96 mock_download.assert_called_with('793554') 97 self.assertEqual(2, mock_popen.call_count) 98 99 ash_chrome_args = mock_popen.call_args_list[0][0][0] 100 self.assertTrue(ash_chrome_args[0].endswith( 101 'build/lacros/prebuilt_ash_chrome/793554/test_ash_chrome')) 102 expected_ash_chrome_args = [ 103 '--user-data-dir=/tmp/ash-data', 104 '--enable-wayland-server', 105 '--no-startup-window', 106 '--disable-input-event-activation-protection', 107 '--disable-lacros-keep-alive', 108 '--disable-login-lacros-opening', 109 '--enable-field-trial-config', 110 '--enable-logging=stderr', 111 '--enable-features=LacrosSupport,LacrosPrimary,LacrosOnly', 112 '--ash-ready-file-path=/tmp/ash-data/ash_ready.txt', 113 '--wayland-server-socket=wayland-exo', 114 ] 115 if '--enable-pixel-output-in-tests' not in command_parts: 116 expected_ash_chrome_args.append('--disable-gl-drawing-for-tests') 117 if command == 'lacros_chrome_browsertests': 118 expected_ash_chrome_args.append( 119 '--lacros-mojo-socket-for-testing=/tmp/ash-data/lacros.sock') 120 self.assertListEqual(expected_ash_chrome_args, ash_chrome_args[1:]) 121 ash_chrome_env = mock_popen.call_args_list[0][1].get('env', {}) 122 self.assertDictEqual({'XDG_RUNTIME_DIR': '/tmp/xdg'}, ash_chrome_env) 123 124 test_args = mock_popen.call_args_list[1][0][0] 125 if command == 'lacros_chrome_browsertests': 126 self.assertListEqual([ 127 command, '--test-launcher-filter-file=/a/b/filter', 128 '--lacros-mojo-socket-for-testing=/tmp/ash-data/lacros.sock', 129 '--ash-chrome-path=' + ash_chrome_args[0], 130 '--unique-ash-dir=/tmp/unique' 131 ], test_args) 132 else: 133 self.assertListEqual(test_args[:len(command_parts)], command_parts) 134 135 test_env = mock_popen.call_args_list[1][1].get('env', {}) 136 self.assertDictEqual( 137 { 138 'WAYLAND_DISPLAY': 'wayland-exo', 139 'XDG_RUNTIME_DIR': '/tmp/xdg', 140 'EGL_PLATFORM': 'surfaceless' 141 }, test_env) 142 143 @mock.patch.object(os, 144 'listdir', 145 return_value=['wayland-exo', 'wayland-exo.lock']) 146 @mock.patch.object(os.path, 'exists', return_value=True) 147 @mock.patch.object(os.path, 'isfile', return_value=True) 148 @mock.patch.object(test_runner, 149 '_GetLatestVersionOfAshChrome', 150 return_value='793554') 151 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 152 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 153 # Tests that when a ash-chrome version is specified, that version is used 154 # instead of the latest one. 155 def test_specify_ash_chrome_version(self, mock_popen, mock_download, *_): 156 args = [ 157 'script_name', 'test', 'browser_tests', '--ash-chrome-version', '781122' 158 ] 159 with mock.patch.object(sys, 'argv', args): 160 test_runner.Main() 161 mock_download.assert_called_with('781122') 162 163 @mock.patch.object(os, 164 'listdir', 165 return_value=['wayland-exo', 'wayland-exo.lock']) 166 @mock.patch.object(os.path, 'exists', return_value=True) 167 @mock.patch.object(os.path, 'isfile', return_value=True) 168 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 169 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 170 # Tests that if a ash-chrome version is specified, uses ash-chrome to run 171 # tests anyway even if |_TARGETS_REQUIRE_ASH_CHROME| indicates an ash-chrome 172 # is not required. 173 def test_overrides_do_not_require_ash_chrome(self, mock_popen, mock_download, 174 *_): 175 args = [ 176 'script_name', 'test', './url_unittests', '--ash-chrome-version', 177 '793554' 178 ] 179 with mock.patch.object(sys, 'argv', args): 180 test_runner.Main() 181 mock_download.assert_called_with('793554') 182 self.assertEqual(2, mock_popen.call_count) 183 184 @mock.patch.object(os, 185 'listdir', 186 return_value=['wayland-exo', 'wayland-exo.lock']) 187 @mock.patch.object(os.path, 'exists', return_value=True) 188 @mock.patch.object(os.path, 'isfile', return_value=True) 189 @mock.patch.object(test_runner, '_GetLatestVersionOfAshChrome') 190 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 191 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 192 # Tests that when an ash-chrome path is specified, the test runner doesn't try 193 # to download prebuilt ash-chrome. 194 def test_specify_ash_chrome_path(self, mock_popen, mock_download, 195 mock_get_latest_version, *_): 196 args = [ 197 'script_name', 198 'test', 199 'browser_tests', 200 '--ash-chrome-path', 201 '/ash/test_ash_chrome', 202 ] 203 with mock.patch.object(sys, 'argv', args): 204 test_runner.Main() 205 self.assertFalse(mock_get_latest_version.called) 206 self.assertFalse(mock_download.called) 207 208 @mock.patch.object(os.path, 'isfile', return_value=True) 209 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 210 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 211 # Tests that arguments not known to the test runner are forwarded to the 212 # command that invokes tests. 213 def test_command_arguments(self, mock_popen, mock_download, _): 214 args = [ 215 'script_name', 'test', './url_unittests', '--gtest_filter=Suite.Test' 216 ] 217 with mock.patch.object(sys, 'argv', args): 218 test_runner.Main() 219 mock_popen.assert_called_with( 220 ['./url_unittests', '--gtest_filter=Suite.Test']) 221 self.assertFalse(mock_download.called) 222 223 @mock.patch.dict(os.environ, {'ASH_WRAPPER': 'gdb --args'}, clear=False) 224 @mock.patch.object(os, 225 'listdir', 226 return_value=['wayland-exo', 'wayland-exo.lock']) 227 @mock.patch.object(tempfile, 228 'mkdtemp', 229 side_effect=['/tmp/xdg', '/tmp/ash-data', '/tmp/unique']) 230 @mock.patch.object(os.environ, 'copy', side_effect=[{}, {}]) 231 @mock.patch.object(os.path, 'exists', return_value=True) 232 @mock.patch.object(os.path, 'isfile', return_value=True) 233 @mock.patch.object(test_runner, 234 '_GetLatestVersionOfAshChrome', 235 return_value='793554') 236 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 237 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 238 # Tests that, when the ASH_WRAPPER environment variable is set, it forwards 239 # the commands to the invocation of ash. 240 def test_ash_wrapper(self, mock_popen, *_): 241 args = [ 242 'script_name', 'test', './browser_tests', '--gtest_filter=Suite.Test' 243 ] 244 with mock.patch.object(sys, 'argv', args): 245 test_runner.Main() 246 ash_args = mock_popen.call_args_list[0][0][0] 247 self.assertTrue(ash_args[2].endswith('test_ash_chrome')) 248 self.assertEqual(['gdb', '--args'], ash_args[:2]) 249 250 251 # Test when ash is newer, test runner skips running tests and returns 0. 252 @mock.patch.object(os.path, 'exists', return_value=True) 253 @mock.patch.object(os.path, 'isfile', return_value=True) 254 @mock.patch.object(test_runner, '_FindLacrosMajorVersion', return_value=91) 255 def test_version_skew_ash_newer(self, *_): 256 args = [ 257 'script_name', 'test', './browser_tests', '--gtest_filter=Suite.Test', 258 '--ash-chrome-path-override=\ 259lacros_version_skew_tests_v92.0.100.0/test_ash_chrome' 260 ] 261 with mock.patch.object(sys, 'argv', args): 262 self.assertEqual(test_runner.Main(), 0) 263 264 @mock.patch.object(os.path, 'exists', return_value=True) 265 def test_lacros_version_from_chrome_version(self, *_): 266 version_data = '''\ 267MAJOR=95 268MINOR=0 269BUILD=4615 270PATCH=0\ 271''' 272 open_lib = '__builtin__.open' 273 if sys.version_info[0] >= 3: 274 open_lib = 'builtins.open' 275 with mock.patch(open_lib, 276 mock.mock_open(read_data=version_data)) as mock_file: 277 version = test_runner._FindLacrosMajorVersion() 278 self.assertEqual(95, version) 279 280 @mock.patch.object(os.path, 'exists', return_value=True) 281 def test_lacros_version_from_metadata(self, *_): 282 metadata_json = ''' 283{ 284 "content": { 285 "version": "92.1.4389.2" 286 }, 287 "metadata_version": 1 288} 289 ''' 290 open_lib = '__builtin__.open' 291 if sys.version_info[0] >= 3: 292 open_lib = 'builtins.open' 293 with mock.patch(open_lib, 294 mock.mock_open(read_data=metadata_json)) as mock_file: 295 version = test_runner._FindLacrosMajorVersionFromMetadata() 296 self.assertEqual(92, version) 297 mock_file.assert_called_with('metadata.json', 'r') 298 299 300if __name__ == '__main__': 301 unittest.main() 302