1#!/usr/bin/env vpython3 2# Copyright 2020 The Chromium Authors. All rights reserved. 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 @parameterized.expand([ 29 'url_unittests', 30 './url_unittests', 31 'out/release/url_unittests', 32 './out/release/url_unittests', 33 ]) 34 @mock.patch.object(os.path, 'isfile', return_value=True) 35 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 36 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 37 # Tests that the test runner doesn't attempt to download ash-chrome if not 38 # required. 39 def test_do_not_require_ash_chrome(self, command, mock_popen, mock_download, 40 _): 41 args = ['script_name', 'test', command] 42 with mock.patch.object(sys, 'argv', args): 43 test_runner.Main() 44 self.assertEqual(1, mock_popen.call_count) 45 mock_popen.assert_called_with([command]) 46 self.assertFalse(mock_download.called) 47 48 @parameterized.expand([ 49 'browser_tests', 50 'components_browsertests', 51 'content_browsertests', 52 'lacros_chrome_browsertests', 53 ]) 54 @mock.patch.object(os, 55 'listdir', 56 return_value=['wayland-0', 'wayland-0.lock']) 57 @mock.patch.object(tempfile, 58 'mkdtemp', 59 side_effect=['/tmp/xdg', '/tmp/ash-data']) 60 @mock.patch.object(os.environ, 'copy', side_effect=[{}, {}]) 61 @mock.patch.object(os.path, 'exists', return_value=True) 62 @mock.patch.object(os.path, 'isfile', return_value=True) 63 @mock.patch.object(test_runner, 64 '_GetLatestVersionOfAshChrome', 65 return_value='793554') 66 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 67 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 68 # Tests that the test runner downloads and spawns ash-chrome if ash-chrome is 69 # required. 70 def test_require_ash_chrome(self, command, mock_popen, mock_download, *_): 71 args = ['script_name', 'test', command] 72 with mock.patch.object(sys, 'argv', args): 73 test_runner.Main() 74 mock_download.assert_called_with('793554') 75 self.assertEqual(2, mock_popen.call_count) 76 77 ash_chrome_args = mock_popen.call_args_list[0][0][0] 78 self.assertTrue(ash_chrome_args[0].endswith( 79 'build/lacros/prebuilt_ash_chrome/793554/test_ash_chrome')) 80 expected_ash_chrome_args = [ 81 '--user-data-dir=/tmp/ash-data', 82 '--enable-wayland-server', 83 '--no-startup-window', 84 ] 85 if command == 'lacros_chrome_browsertests': 86 expected_ash_chrome_args.append( 87 '--lacros-mojo-socket-for-testing=/tmp/ash-data/lacros.sock') 88 self.assertListEqual(expected_ash_chrome_args, ash_chrome_args[1:]) 89 ash_chrome_env = mock_popen.call_args_list[0][1].get('env', {}) 90 self.assertDictEqual({'XDG_RUNTIME_DIR': '/tmp/xdg'}, ash_chrome_env) 91 92 test_args = mock_popen.call_args_list[1][0][0] 93 if command == 'lacros_chrome_browsertests': 94 self.assertListEqual([ 95 command, 96 '--lacros-mojo-socket-for-testing=/tmp/ash-data/lacros.sock' 97 ], test_args) 98 else: 99 self.assertListEqual([command], test_args) 100 101 test_env = mock_popen.call_args_list[1][1].get('env', {}) 102 self.assertDictEqual( 103 { 104 'XDG_RUNTIME_DIR': '/tmp/xdg', 105 'EGL_PLATFORM': 'surfaceless' 106 }, test_env) 107 108 109 @mock.patch.object(os, 110 'listdir', 111 return_value=['wayland-0', 'wayland-0.lock']) 112 @mock.patch.object(os.path, 'exists', return_value=True) 113 @mock.patch.object(os.path, 'isfile', return_value=True) 114 @mock.patch.object(test_runner, 115 '_GetLatestVersionOfAshChrome', 116 return_value='793554') 117 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 118 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 119 # Tests that when a ash-chrome version is specified, that version is used 120 # instead of the latest one. 121 def test_specify_ash_chrome_version(self, mock_popen, mock_download, *_): 122 args = [ 123 'script_name', 'test', 'browser_tests', '--ash-chrome-version', '781122' 124 ] 125 with mock.patch.object(sys, 'argv', args): 126 test_runner.Main() 127 mock_download.assert_called_with('781122') 128 129 @mock.patch.object(os, 130 'listdir', 131 return_value=['wayland-0', 'wayland-0.lock']) 132 @mock.patch.object(os.path, 'exists', return_value=True) 133 @mock.patch.object(os.path, 'isfile', return_value=True) 134 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 135 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 136 # Tests that if a ash-chrome version is specified, uses ash-chrome to run 137 # tests anyway even if |_TARGETS_REQUIRE_ASH_CHROME| indicates an ash-chrome 138 # is not required. 139 def test_overrides_do_not_require_ash_chrome(self, mock_popen, mock_download, 140 *_): 141 args = [ 142 'script_name', 'test', './url_unittests', '--ash-chrome-version', 143 '793554' 144 ] 145 with mock.patch.object(sys, 'argv', args): 146 test_runner.Main() 147 mock_download.assert_called_with('793554') 148 self.assertEqual(2, mock_popen.call_count) 149 150 @mock.patch.object(os, 151 'listdir', 152 return_value=['wayland-0', 'wayland-0.lock']) 153 @mock.patch.object(os.path, 'exists', return_value=True) 154 @mock.patch.object(os.path, 'isfile', return_value=True) 155 @mock.patch.object(test_runner, '_GetLatestVersionOfAshChrome') 156 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 157 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 158 # Tests that when an ash-chrome path is specified, the test runner doesn't try 159 # to download prebuilt ash-chrome. 160 def test_specify_ash_chrome_path(self, mock_popen, mock_download, 161 mock_get_latest_version, *_): 162 args = [ 163 'script_name', 164 'test', 165 'browser_tests', 166 '--ash-chrome-path', 167 '/ash/test_ash_chrome', 168 ] 169 with mock.patch.object(sys, 'argv', args): 170 test_runner.Main() 171 self.assertFalse(mock_get_latest_version.called) 172 self.assertFalse(mock_download.called) 173 174 @mock.patch.object(os.path, 'isfile', return_value=True) 175 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 176 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 177 # Tests that arguments not known to the test runner are forwarded to the 178 # command that invokes tests. 179 def test_command_arguments(self, mock_popen, mock_download, _): 180 args = [ 181 'script_name', 'test', './url_unittests', '--gtest_filter=Suite.Test' 182 ] 183 with mock.patch.object(sys, 'argv', args): 184 test_runner.Main() 185 mock_popen.assert_called_with( 186 ['./url_unittests', '--gtest_filter=Suite.Test']) 187 self.assertFalse(mock_download.called) 188 189 @mock.patch.dict(os.environ, {'ASH_WRAPPER': 'gdb --args'}, clear=False) 190 @mock.patch.object(os, 191 'listdir', 192 return_value=['wayland-0', 'wayland-0.lock']) 193 @mock.patch.object(tempfile, 194 'mkdtemp', 195 side_effect=['/tmp/xdg', '/tmp/ash-data']) 196 @mock.patch.object(os.environ, 'copy', side_effect=[{}, {}]) 197 @mock.patch.object(os.path, 'exists', return_value=True) 198 @mock.patch.object(os.path, 'isfile', return_value=True) 199 @mock.patch.object(test_runner, 200 '_GetLatestVersionOfAshChrome', 201 return_value='793554') 202 @mock.patch.object(test_runner, '_DownloadAshChromeIfNecessary') 203 @mock.patch.object(subprocess, 'Popen', return_value=mock.Mock()) 204 # Tests that, when the ASH_WRAPPER environment variable is set, it forwards 205 # the commands to the invocation of ash. 206 def test_ash_wrapper(self, mock_popen, *_): 207 args = [ 208 'script_name', 'test', './browser_tests', '--gtest_filter=Suite.Test' 209 ] 210 with mock.patch.object(sys, 'argv', args): 211 test_runner.Main() 212 ash_args = mock_popen.call_args_list[0][0][0] 213 self.assertTrue(ash_args[2].endswith('test_ash_chrome')) 214 self.assertEqual(['gdb', '--args'], ash_args[:2]) 215 216 217 # Test when ash is newer, test runner skips running tests and returns 0. 218 @mock.patch.object(os.path, 'exists', return_value=True) 219 @mock.patch.object(os.path, 'isfile', return_value=True) 220 @mock.patch.object(test_runner, '_FindLacrosMajorVersion', return_value=91) 221 def test_version_skew_ash_newer(self, *_): 222 args = [ 223 'script_name', 'test', './browser_tests', '--gtest_filter=Suite.Test', 224 '--ash-chrome-path-override=\ 225lacros_version_skew_tests_v92.0.100.0/test_ash_chrome' 226 ] 227 with mock.patch.object(sys, 'argv', args): 228 self.assertEqual(test_runner.Main(), 0) 229 230 @mock.patch.object(os.path, 'exists', return_value=True) 231 def test_lacros_version_from_chrome_version(self, *_): 232 version_data = '''\ 233MAJOR=95 234MINOR=0 235BUILD=4615 236PATCH=0\ 237''' 238 open_lib = '__builtin__.open' 239 if sys.version_info[0] >= 3: 240 open_lib = 'builtins.open' 241 with mock.patch(open_lib, 242 mock.mock_open(read_data=version_data)) as mock_file: 243 version = test_runner._FindLacrosMajorVersion() 244 self.assertEqual(95, version) 245 246 @mock.patch.object(os.path, 'exists', return_value=True) 247 def test_lacros_version_from_metadata(self, *_): 248 metadata_json = ''' 249{ 250 "content": { 251 "version": "92.1.4389.2" 252 }, 253 "metadata_version": 1 254} 255 ''' 256 open_lib = '__builtin__.open' 257 if sys.version_info[0] >= 3: 258 open_lib = 'builtins.open' 259 with mock.patch(open_lib, 260 mock.mock_open(read_data=metadata_json)) as mock_file: 261 version = test_runner._FindLacrosMajorVersionFromMetadata() 262 self.assertEqual(92, version) 263 mock_file.assert_called_with('metadata.json', 'r') 264 265 266if __name__ == '__main__': 267 unittest.main() 268