xref: /aosp_15_r20/external/cronet/build/lacros/test_runner_test.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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