Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /tools /bisect_test.py
blob: 0092bc4ed36648052836a8914f08f90f1f3bb878 [file] [log] [blame]
Avi Drissmandfd880852022-09-15 20:11:09[diff] [blame]1# Copyright 2012 The Chromium Authors
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Kuan Huang342fec52024-10-31 18:00:44[diff] [blame]5import base64
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]6import functools
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]7import io
8import json
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]9import os
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]10import re
cjamcl@google.comfb61fc32019-04-18 19:47:20[diff] [blame]11import subprocess
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]12import sys
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]13import tempfile
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]14import unittest
Kuan Huangc93ac262024-09-19 18:53:17[diff] [blame]15import urllib.request
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]16from unittest.mockimport(ANY,Mock,MagicMock, mock_open, patch, call,
17PropertyMock)
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]18
19bisect_builds= __import__('bisect-builds')
20
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]21if'NO_MOCK_SERVER'notin os.environ:
22 maybe_patch= patch
23else:
24# SetupEnvironment for gsutil to connect to real server.
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]25 options= bisect_builds.ParseCommandLine(['-a','linux64','-g','1'])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]26 bisect_builds.SetupEnvironment(options)
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]27 bisect_builds.SetupAndroidEnvironment()
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]28
29# Mock object that always wraps for the spec.
30# This will pass the call through and ignore the return_value and side_effect.
31classWrappedMock(MagicMock):
32
33def __init__(self,
34 spec=None,
35 return_value=None,
36 side_effect=None,
37*args,
38**kwargs):
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]39 wraps= kwargs.pop('wraps', spec)
40 super().__init__(spec,*args,**kwargs, wraps=wraps)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]41
42 maybe_patch= functools.partial(patch, spec=True, new_callable=WrappedMock)
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]43 maybe_patch.object= functools.partial(patch.object,
44 spec=True,
45 new_callable=WrappedMock)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]46
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]47
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]48classBisectTestCase(unittest.TestCase):
49
50@classmethod
51def setUpClass(cls):
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]52# Patch the name pattern for pkgutil to accept "bisect-builds" as module
53# name.
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]54if sys.version_info[:2]>(3,8):
55 dotted_words= r'(?!\d)([\w-]+)(\.(?!\d)(\w+))*'
56 name_pattern= re.compile(
57 f'^(?P<pkg>{dotted_words})'
58 f'(?P<cln>:(?P<obj>{dotted_words})?)?$', re.UNICODE)
59 cls.name_pattern_patcher= patch('pkgutil._NAME_PATTERN', name_pattern)
60 cls.name_pattern_patcher.start()
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]61
Ben Joycec634f812024-09-19 20:13:07[diff] [blame]62# patch cache filename to prevent pollute working dir.
63 fd, cls.tmp_cache_file= tempfile.mkstemp(suffix='.json')
64 os.close(fd)
65 cls.cache_filename_patcher= patch(
66'bisect-builds.ArchiveBuild._rev_list_cache_filename',
67 new=PropertyMock(return_value=cls.tmp_cache_file))
68 cls.cache_filename_patcher.start()
69
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]70@classmethod
71def tearDownClass(cls):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]72if sys.version_info[:2]>(3,8):
73 cls.name_pattern_patcher.stop()
74 cls.cache_filename_patcher.stop()
75 os.unlink(cls.tmp_cache_file)
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]76
77
78classBisectTest(BisectTestCase):
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]79
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]80 max_rev=10000
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]81
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]82def setUp(self):
83 self.patchers=[]
84 self.patchers.append(patch('bisect-builds.DownloadJob._fetch'))
85 self.patchers.append(
86 patch('bisect-builds.ArchiveBuild.run_revision',
87 return_value=(0,'','')))
88 self.patchers.append(
89 patch('bisect-builds.SnapshotBuild._get_rev_list',
90 return_value=range(self.max_rev)))
91for eachin self.patchers:
92 each.start()
93
94def tearDown(self):
95for eachin self.patchers:
96 each.stop()
97
cjamcl@google.comfb61fc32019-04-18 19:47:20[diff] [blame]98def bisect(self, good_rev, bad_rev, evaluate, num_runs=1):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]99 options= bisect_builds.ParseCommandLine([
100'-a','linux64','-g',
101 str(good_rev),'-b',
102 str(bad_rev),'--times',
103 str(num_runs),'--no-local-cache'
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]104])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]105 archive_build= bisect_builds.create_archive_build(options)
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]106(minrev, maxrev)= bisect_builds.Bisect(archive_build=archive_build,
107 evaluate=evaluate,
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]108 try_args=options.args)
cjamcl@google.comfb61fc32019-04-18 19:47:20[diff] [blame]109return(minrev, maxrev)
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]110
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]111@patch('builtins.print')
112def testBisectConsistentAnswer(self, mock_print):
113
114def get_steps():
115 steps=[]
116for callin mock_print.call_args_list:
117if call.argsand call.args[0].startswith('You have'):
118 steps.append(int(re.search(r'(\d+) steps', call.args[0])[1]))
119return steps
120
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]121 self.assertEqual(self.bisect(1000,100,lambda*args:'g'),(100,101))
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]122 self.assertSequenceEqual(get_steps(), range(10,1,-1))
123
124 mock_print.reset_mock()
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]125 self.assertEqual(self.bisect(100,1000,lambda*args:'b'),(100,101))
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]126 self.assertSequenceEqual(get_steps(), range(10,0,-1))
127
128 mock_print.reset_mock()
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]129 self.assertEqual(self.bisect(2000,200,lambda*args:'b'),(1999,2000))
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]130 self.assertSequenceEqual(get_steps(), range(11,0,-1))
131
132 mock_print.reset_mock()
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]133 self.assertEqual(self.bisect(200,2000,lambda*args:'g'),(1999,2000))
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]134 self.assertSequenceEqual(get_steps(), range(11,1,-1))
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]135
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]136@patch('bisect-builds.ArchiveBuild.run_revision', return_value=(0,'',''))
137def test_bisect_should_retry(self, mock_run_revision):
138 evaluator=Mock(side_effect='rgrgrbr')
139 self.assertEqual(self.bisect(9,1, evaluator),(2,3))
140 tested_revisions=[c.args[0]for cin evaluator.call_args_list]
141 self.assertEqual(tested_revisions,[5,5,3,3,2,2])
142 self.assertEqual(mock_run_revision.call_count,6)
143
144 evaluator=Mock(side_effect='rgrrrgrbr')
145 self.assertEqual(self.bisect(1,10, evaluator),(8,9))
146 tested_revisions=[c.args[0]for cin evaluator.call_args_list]
147 self.assertEqual(tested_revisions,[6,6,8,8,8,8,9,9])
148
149def test_bisect_should_unknown(self):
150 evaluator=Mock(side_effect='uuuggggg')
151 self.assertEqual(self.bisect(9,1, evaluator),(1,2))
152 tested_revisions=[c.args[0]for cin evaluator.call_args_list]
153 self.assertEqual(tested_revisions,[5,3,6,7,2])
154
155 evaluator=Mock(side_effect='uuugggggg')
156 self.assertEqual(self.bisect(1,9, evaluator),(8,9))
157 tested_revisions=[c.args[0]for cin evaluator.call_args_list]
158 self.assertEqual(tested_revisions,[5,7,4,3,8])
159
160def test_bisect_should_quit(self):
161 evaluator=Mock(side_effect=SystemExit())
162with self.assertRaises(SystemExit):
163 self.assertEqual(self.bisect(9,1, evaluator),(None,None))
164
165def test_edge_cases(self):
166with self.assertRaises(bisect_builds.BisectException):
167 self.assertEqual(self.bisect(1,1,Mock()),(1,1))
168 self.assertEqual(self.bisect(2,1,Mock()),(1,2))
169 self.assertEqual(self.bisect(1,2,Mock()),(1,2))
170
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]171
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]172classDownloadJobTest(BisectTestCase):
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]173
174@patch('bisect-builds.gsutil_download')
175def test_fetch_gsutil(self, mock_gsutil_download):
176 fetch= bisect_builds.DownloadJob('gs://some-file.zip',123)
177 fetch.start()
178 fetch.wait_for()
179 mock_gsutil_download.assert_called_once()
180
181@patch('urllib.request.urlretrieve')
182def test_fetch_http(self, mock_urlretrieve):
183 fetch= bisect_builds.DownloadJob('http://some-file.zip',123)
184 fetch.start()
185 fetch.wait_for()
186 mock_urlretrieve.assert_called_once()
187
188@patch('tempfile.mkstemp', return_value=(321,'some-file.zip'))
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]189@patch('urllib.request.urlretrieve')
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]190@patch('os.close')
191@patch('os.unlink')
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]192def test_should_del(self, mock_unlink, mock_close, mock_urlretrieve,
193 mock_mkstemp):
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]194 fetch= bisect_builds.DownloadJob('http://some-file.zip',123)
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]195 fetch.start().wait_for()
196 fetch.stop()
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]197 mock_mkstemp.assert_called_once()
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]198 mock_close.assert_called_once()
199 mock_urlretrieve.assert_called_once()
200 mock_unlink.assert_called_with('some-file.zip')
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]201
202@patch('urllib.request.urlretrieve')
203def test_stop_wait_for_should_be_able_to_reenter(self, mock_urlretrieve):
204 fetch= bisect_builds.DownloadJob('http://some-file.zip',123)
205 fetch.start()
206 fetch.wait_for()
207 fetch.wait_for()
208 fetch.stop()
209 fetch.stop()
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]210
211@patch('tempfile.mkstemp',
212 side_effect=[(321,'some-file.apks'),(123,'file2.apk')])
213@patch('bisect-builds.gsutil_download')
214@patch('os.close')
215@patch('os.unlink')
216def test_should_support_multiple_files(self, mock_unlink, mock_close,
217 mock_gsutil, mock_mkstemp):
218 urls={
219'trichrome':
220('gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/high-arm_64/'
221'TrichromeChromeGoogle6432Stable.apks'),
222'trichrome_library':
223('gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/high-arm_64/'
224'TrichromeLibraryGoogle6432Stable.apk'),
225}
226 fetch= bisect_builds.DownloadJob(urls,123)
227 result= fetch.start().wait_for()
Kuan Huang8b5e33dc2024-08-15 17:51:24[diff] [blame]228 fetch.stop()
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]229 self.assertDictEqual(result,{
230'trichrome':'some-file.apks',
231'trichrome_library':'file2.apk',
232})
233 self.assertEqual(mock_mkstemp.call_count,2)
234 self.assertEqual(mock_close.call_count,2)
Ben Joyce3c940d32025-02-12 19:31:52[diff] [blame]235 mock_unlink.assert_has_calls(
236[call('some-file.apks'), call('file2.apk')], any_order=True)
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]237 self.assertEqual(mock_gsutil.call_count,2)
cjamcl@google.comfb61fc32019-04-18 19:47:20[diff] [blame]238
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]239
Kuan Huangc3a4cd1e2024-10-03 21:17:31[diff] [blame]240@patch(
241"urllib.request.urlopen",
242 side_effect=urllib.request.HTTPError('url',404,'Not Found',None,None),
243)
244@patch('subprocess.Popen', spec=subprocess.Popen)
245@patch('bisect-builds.GSUTILS_PATH', new='/some/path')
246def test_download_failure_should_raised(self, mock_Popen, mock_urlopen):
247 fetch= bisect_builds.DownloadJob('http://some-file.zip',123)
248with self.assertRaises(urllib.request.HTTPError):
249 fetch.start().wait_for()
250
251 mock_Popen.return_value.communicate.return_value=(b'', b'status=403')
252 mock_Popen.return_value.returncode=1
253 fetch= bisect_builds.DownloadJob('gs://some-file.zip',123)
254with self.assertRaises(bisect_builds.BisectException):
255 fetch.start().wait_for()
256
257
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]258classArchiveBuildTest(BisectTestCase):
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]259
260def setUp(self):
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]261 self.patcher= patch.multiple(
262 bisect_builds.ArchiveBuild,
263 __abstractmethods__=set(),
264 build_type='release',
265 _get_rev_list=Mock(return_value=list(map(str, range(10)))),
266 _rev_list_cache_key='abc')
267 self.patcher.start()
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]268
269def tearDown(self):
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]270 self.patcher.stop()
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]271
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]272def create_build(self,*args):
273 args=['-a','linux64','-g','0','-b','9',*args]
274 options= bisect_builds.ParseCommandLine(args)
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]275return bisect_builds.ArchiveBuild(options)
276
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]277def test_cache_should_not_work_if_not_enabled(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]278 build= self.create_build('--no-local-cache')
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]279 self.assertFalse(build.use_local_cache)
280with patch('builtins.open')as m:
281 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
282 bisect_builds.ArchiveBuild._get_rev_list.assert_called_once()
283 m.assert_not_called()
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]284
285def test_cache_should_save_and_load(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]286 build= self.create_build()
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]287 self.assertTrue(build.use_local_cache)
288# Load the non-existent cache and write to it.
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]289 cached_data=[]
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]290# The cache file would be opened 3 times:
291# 1. read by _load_rev_list_cache
292# 2. read by _save_rev_list_cache for existing cache
293# 3. write by _save_rev_list_cache
294 write_mock=MagicMock()
295 write_mock.__enter__().write.side_effect=lambda d: cached_data.append(d)
296with patch('builtins.open',
297 side_effect=[FileNotFoundError,FileNotFoundError, write_mock]):
298 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]299 bisect_builds.ArchiveBuild._get_rev_list.assert_called_once()
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]300 cached_json= json.loads(''.join(cached_data))
301 self.assertDictEqual(cached_json,{'abc':[str(x)for xin range(10)]})
302# Load cache with cached data.
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]303 build= self.create_build('--use-local-cache')
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]304 bisect_builds.ArchiveBuild._get_rev_list.reset_mock()
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]305with patch('builtins.open', mock_open(read_data=''.join(cached_data))):
306 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]307 bisect_builds.ArchiveBuild._get_rev_list.assert_not_called()
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]308
309@patch.object(bisect_builds.ArchiveBuild,'_load_rev_list_cache')
310@patch.object(bisect_builds.ArchiveBuild,'_save_rev_list_cache')
311@patch.object(bisect_builds.ArchiveBuild,
312'_get_rev_list',
313 return_value=[str(x)for xin range(10)])
314def test_should_request_partial_rev_list(self, mock_get_rev_list,
315 mock_save_rev_list_cache,
316 mock_load_rev_list_cache):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]317 build= self.create_build('--no-local-cache')
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]318# missing latest
319 mock_load_rev_list_cache.return_value=[str(x)for xin range(5)]
320 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
321 mock_get_rev_list.assert_called_with('4','9')
322# missing old and latest
323 mock_load_rev_list_cache.return_value=[str(x)for xin range(1,5)]
324 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
325 mock_get_rev_list.assert_called_with('0','9')
326# missing old
327 mock_load_rev_list_cache.return_value=[str(x)for xin range(3,10)]
328 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
329 mock_get_rev_list.assert_called_with('0','3')
330# no intersect
331 mock_load_rev_list_cache.return_value=['c','d','e']
332 self.assertEqual(build.get_rev_list(),[str(x)for xin range(10)])
333 mock_save_rev_list_cache.assert_called_with([str(x)for xin range(10)]+
334['c','d','e'])
335 mock_get_rev_list.assert_called_with('0','c')
336
337@patch.object(bisect_builds.ArchiveBuild,'_get_rev_list', return_value=[])
338def test_should_raise_error_when_no_rev_list(self, mock_get_rev_list):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]339 build= self.create_build('--no-local-cache')
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]340with self.assertRaises(bisect_builds.BisectException):
341 build.get_rev_list()
342 mock_get_rev_list.assert_any_call('0','9')
343 mock_get_rev_list.assert_any_call()
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]344
345@unittest.skipIf('NO_MOCK_SERVER'notin os.environ,
346'The test is to ensure NO_MOCK_SERVER working correctly')
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]347@maybe_patch('bisect-builds.GetRevisionFromVersion', return_value=123)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]348def test_no_mock(self, mock_GetRevisionFromVersion):
349 self.assertEqual(bisect_builds.GetRevisionFromVersion('127.0.6533.74'),
3501313161)
351 mock_GetRevisionFromVersion.assert_called()
352
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]353@patch('bisect-builds.ArchiveBuild._install_revision')
354@patch('bisect-builds.ArchiveBuild._launch_revision',
355 return_value=(1,'',''))
356def test_run_revision_should_return_early(self, mock_launch_revision,
357 mock_install_revision):
358 build= self.create_build()
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]359 build.run_revision('','',[])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]360 mock_launch_revision.assert_called_once()
361
362@patch('bisect-builds.ArchiveBuild._install_revision')
363@patch('bisect-builds.ArchiveBuild._launch_revision',
364 return_value=(0,'',''))
365def test_run_revision_should_do_all_runs(self, mock_launch_revision,
366 mock_install_revision):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]367 build= self.create_build('--time','10')
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]368 build.run_revision('','',[])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]369 self.assertEqual(mock_launch_revision.call_count,10)
370
371@patch('bisect-builds.UnzipFilenameToDir')
372@patch('glob.glob', return_value=['temp-dir/linux64/chrome'])
373@patch('os.path.abspath', return_value='/tmp/temp-dir/linux64/chrome')
374def test_install_revision_should_unzip_and_search_executable(
375 self, mock_abspath, mock_glob, mock_UnzipFilenameToDir):
376 build= self.create_build()
377 self.assertEqual(build._install_revision('some-file.zip','temp-dir'),
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]378{'chrome':'/tmp/temp-dir/linux64/chrome'})
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]379 mock_UnzipFilenameToDir.assert_called_once_with('some-file.zip','temp-dir')
380 mock_glob.assert_called_once_with('temp-dir/*/chrome')
381 mock_abspath.assert_called_once_with('temp-dir/linux64/chrome')
382
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]383@patch('bisect-builds.UnzipFilenameToDir')
384@patch('glob.glob',
385 side_effect=[['temp-dir/chrome-linux64/chrome'],
386['temp-dir/chromedriver_linux64/chromedriver']])
387@patch('os.path.abspath',
388 side_effect=[
389'/tmp/temp-dir/chrome-linux64/chrome',
390'/tmp/temp-dir/chromedriver_linux64/chromedriver'
391])
392def test_install_chromedriver(self, mock_abspath, mock_glob,
393 mock_UnzipFilenameToDir):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]394 build= self.create_build('--chromedriver')
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]395 self.assertEqual(
396 build._install_revision(
397{
398'chrome':'some-file.zip',
399'chromedriver':'some-other-file.zip',
400},'temp-dir'),
401{
402'chrome':'/tmp/temp-dir/chrome-linux64/chrome',
403'chromedriver':'/tmp/temp-dir/chromedriver_linux64/chromedriver',
404})
405 mock_UnzipFilenameToDir.assert_has_calls([
406 call('some-file.zip','temp-dir'),
407 call('some-other-file.zip','temp-dir'),
408])
409 mock_glob.assert_has_calls([
410 call('temp-dir/*/chrome'),
411 call('temp-dir/*/chromedriver'),
412])
413 mock_abspath.assert_has_calls([
414 call('temp-dir/chrome-linux64/chrome'),
415 call('temp-dir/chromedriver_linux64/chromedriver')
416])
417
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]418@patch('subprocess.Popen', spec=subprocess.Popen)
419def test_launch_revision_should_run_command(self, mock_Popen):
420 mock_Popen.return_value.communicate.return_value=('','')
421 mock_Popen.return_value.returncode=0
422 build= self.create_build()
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]423 build._launch_revision('temp-dir',{'chrome':'temp-dir/linux64/chrome'},
424[])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]425 mock_Popen.assert_called_once_with(
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]426'temp-dir/linux64/chrome --user-data-dir=temp-dir/profile',
427 cwd=None,
428 shell=True,
429 bufsize=-1,
430 stdout=ANY,
431 stderr=ANY)
432
Kuan Huang94c4a2d12024-11-21 21:46:09[diff] [blame]433@unittest.skipIf(sys.platform.startswith('win'),'This test is not for win')
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]434@patch('subprocess.Popen', spec=subprocess.Popen)
Kuan Huangd3c862c02024-10-31 04:02:14[diff] [blame]435def test_launch_revision_should_run_command_for_mac(self, mock_Popen):
436 mock_Popen.return_value.communicate.return_value=('','')
437 mock_Popen.return_value.returncode=0
438 build= self.create_build()
439 build._launch_revision(
440'temp-dir',{
441'chrome':
442'temp-dir/full-build-mac/'
443'Google Chrome.app/Contents/MacOS/Google Chrome'
444},[])
445 mock_Popen.assert_called_once_with(
446"'temp-dir/full-build-mac/"
447"Google Chrome.app/Contents/MacOS/Google Chrome'"
448' --user-data-dir=temp-dir/profile',
449 cwd=None,
450 shell=True,
451 bufsize=-1,
452 stdout=ANY,
453 stderr=ANY)
454
Kuan Huang94c4a2d12024-11-21 21:46:09[diff] [blame]455@unittest.skipUnless(sys.platform.startswith('win'),
456'This test is for win only')
Kuan Huangd3c862c02024-10-31 04:02:14[diff] [blame]457@patch('subprocess.Popen', spec=subprocess.Popen)
458def test_launch_revision_should_run_command_for_win(self, mock_Popen):
459 mock_Popen.return_value.communicate.return_value=('','')
460 mock_Popen.return_value.returncode=0
461 build= self.create_build()
462 build._launch_revision(
463'C:\\temp-dir',{
464'chrome':'C:\\temp-dir\\full-build-win\\chrome.exe'
465},[])
466 mock_Popen.assert_called_once_with(
Kuan Huang94c4a2d12024-11-21 21:46:09[diff] [blame]467"C:\\temp-dir\\full-build-win\\chrome.exe "
Kuan Huangd3c862c02024-10-31 04:02:14[diff] [blame]468'--user-data-dir=C:\\temp-dir/profile',
469 cwd=None,
470 shell=True,
471 bufsize=-1,
472 stdout=ANY,
473 stderr=ANY)
474
475@patch('subprocess.Popen', spec=subprocess.Popen)
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]476def test_command_replacement(self, mock_Popen):
477 mock_Popen.return_value.communicate.return_value=('','')
478 mock_Popen.return_value.returncode=0
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]479 build= self.create_build(
480'--chromedriver','-c',
481'CHROMEDRIVER=%d BROWSER_EXECUTABLE_PATH=%p pytest %a')
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]482 build._launch_revision('/tmp',{
483'chrome':'/tmp/chrome',
484'chromedriver':'/tmp/chromedriver'
485},['--args','--args2="word 1"','word 2'])
Kuan Huang94c4a2d12024-11-21 21:46:09[diff] [blame]486if sys.platform.startswith('win'):
487 mock_Popen.assert_called_once_with(
488'CHROMEDRIVER=/tmp/chromedriver BROWSER_EXECUTABLE_PATH=/tmp/chrome '
489'pytest --user-data-dir=/tmp/profile --args "--args2=\\"word 1\\"" '
490'"word 2"',
491 cwd=None,
492 shell=True,
493 bufsize=-1,
494 stdout=ANY,
495 stderr=ANY)
496else:
497 mock_Popen.assert_called_once_with(
498'CHROMEDRIVER=/tmp/chromedriver BROWSER_EXECUTABLE_PATH=/tmp/chrome '
499'pytest --user-data-dir=/tmp/profile --args \'--args2="word 1"\' '
500'\'word 2\'',
501 cwd=None,
502 shell=True,
503 bufsize=-1,
504 stdout=ANY,
505 stderr=ANY)
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]506
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]507
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]508classReleaseBuildTest(BisectTestCase):
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]509
510def test_should_look_up_path_context(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]511 options= bisect_builds.ParseCommandLine(
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]512['-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.88'])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]513 self.assertEqual(options.archive,'linux64')
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]514 build= bisect_builds.create_archive_build(options)
515 self.assertIsInstance(build, bisect_builds.ReleaseBuild)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]516 self.assertEqual(build.binary_name,'chrome')
517 self.assertEqual(build.listing_platform_dir,'linux64/')
518 self.assertEqual(build.archive_name,'chrome-linux64.zip')
519 self.assertEqual(build.archive_extract_dir,'chrome-linux64')
520
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]521@maybe_patch(
522'bisect-builds.GsutilList',
523 return_value=[
524'gs://chrome-unsigned/desktop-5c0tCh/%s/linux64/chrome-linux64.zip'%
525 xfor xin['127.0.6533.74','127.0.6533.75','127.0.6533.76']
526])
527def test_get_rev_list(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]528 options= bisect_builds.ParseCommandLine([
529'-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.76',
530'--no-local-cache'
531])
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]532 build= bisect_builds.create_archive_build(options)
533 self.assertIsInstance(build, bisect_builds.ReleaseBuild)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]534 self.assertEqual(build.get_rev_list(),
535['127.0.6533.74','127.0.6533.75','127.0.6533.76'])
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]536 mock_GsutilList.assert_any_call('gs://chrome-unsigned/desktop-5c0tCh')
537 mock_GsutilList.assert_any_call(*[
538'gs://chrome-unsigned/desktop-5c0tCh/%s/linux64/chrome-linux64.zip'% x
539for xin['127.0.6533.74','127.0.6533.75','127.0.6533.76']
540],
541 ignore_fail=True)
542 self.assertEqual(mock_GsutilList.call_count,2)
543
544@patch('bisect-builds.GsutilList',
545 return_value=['127.0.6533.74','127.0.6533.75','127.0.6533.76'])
546def test_should_save_and_load_cache(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]547 options= bisect_builds.ParseCommandLine([
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]548'-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.77',
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]549'--use-local-cache'
550])
551 build= bisect_builds.create_archive_build(options)
552 self.assertIsInstance(build, bisect_builds.ReleaseBuild)
553# Load the non-existent cache and write to it.
554 cached_data=[]
555 write_mock=MagicMock()
556 write_mock.__enter__().write.side_effect=lambda d: cached_data.append(d)
557with patch('builtins.open',
558 side_effect=[FileNotFoundError,FileNotFoundError, write_mock]):
559 self.assertEqual(build.get_rev_list(),
560['127.0.6533.74','127.0.6533.75','127.0.6533.76'])
561 mock_GsutilList.assert_called()
562 cached_json= json.loads(''.join(cached_data))
563 self.assertDictEqual(
564 cached_json,{
565 build._rev_list_cache_key:
566['127.0.6533.74','127.0.6533.75','127.0.6533.76']
567})
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]568# Load cache with cached data and merge with new data
569 mock_GsutilList.return_value=['127.0.6533.76','127.0.6533.77']
570 build= bisect_builds.create_archive_build(options)
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]571with patch('builtins.open', mock_open(read_data=''.join(cached_data))):
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]572 self.assertEqual(
573 build.get_rev_list(),
574['127.0.6533.74','127.0.6533.75','127.0.6533.76','127.0.6533.77'])
575print(mock_GsutilList.call_args)
576 mock_GsutilList.assert_any_call(
577'gs://chrome-unsigned/desktop-5c0tCh'
578'/127.0.6533.76/linux64/chrome-linux64.zip',
579'gs://chrome-unsigned/desktop-5c0tCh'
580'/127.0.6533.77/linux64/chrome-linux64.zip',
581 ignore_fail=True)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]582
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]583def test_get_download_url(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]584 options= bisect_builds.ParseCommandLine(
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]585['-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.77'])
586 build= bisect_builds.create_archive_build(options)
587 self.assertIsInstance(build, bisect_builds.ReleaseBuild)
588 download_urls= build.get_download_url('127.0.6533.74')
589 self.assertEqual(
590 download_urls,'gs://chrome-unsigned/desktop-5c0tCh'
591'/127.0.6533.74/linux64/chrome-linux64.zip')
592
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]593 options= bisect_builds.ParseCommandLine([
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]594'-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.77',
595'--chromedriver'
596])
597 build= bisect_builds.create_archive_build(options)
598 self.assertIsInstance(build, bisect_builds.ReleaseBuild)
599 download_urls= build.get_download_url('127.0.6533.74')
600 self.assertEqual(
601 download_urls,{
602'chrome':
603'gs://chrome-unsigned/desktop-5c0tCh'
604'/127.0.6533.74/linux64/chrome-linux64.zip',
605'chromedriver':
606'gs://chrome-unsigned/desktop-5c0tCh'
607'/127.0.6533.74/linux64/chromedriver_linux64.zip',
608})
609
610@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
611'The test only valid when NO_MOCK_SERVER')
612@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'stdout',''))
613def test_run_revision_with_real_zipfile(self, mock_run):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]614 options= bisect_builds.ParseCommandLine([
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]615'-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.77',
616'--chromedriver','-c','driver=%d prog=%p'
617])
618 build= bisect_builds.create_archive_build(options)
619 self.assertIsInstance(build, bisect_builds.ReleaseBuild)
620 download_job= build.get_download_job('127.0.6533.74')
621 zip_file= download_job.start().wait_for()
622with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
623 build.run_revision(zip_file, tempdir,[])
624 self.assertRegex(mock_run.call_args.args[0],
625 r'driver=.+/chromedriver prog=.+/chrome')
626
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]627
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]628classArchiveBuildWithCommitPositionTest(BisectTestCase):
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]629
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]630def setUp(self):
631 patch.multiple(bisect_builds.ArchiveBuildWithCommitPosition,
632 __abstractmethods__=set(),
633 build_type='release').start()
634
635@maybe_patch('bisect-builds.GetRevisionFromVersion', return_value=1313161)
636@maybe_patch('bisect-builds.GetChromiumRevision', return_value=999999999)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]637def test_should_convert_revision_as_commit_position(
638 self, mock_GetChromiumRevision, mock_GetRevisionFromVersion):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]639 options= bisect_builds.ParseCommandLine(
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]640['-a','linux64','-g','127.0.6533.74'])
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]641 build= bisect_builds.ArchiveBuildWithCommitPosition(options)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]642 self.assertEqual(build.good_revision,1313161)
643 self.assertEqual(build.bad_revision,999999999)
644 mock_GetRevisionFromVersion.assert_called_once_with('127.0.6533.74')
645 mock_GetChromiumRevision.assert_called()
646
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]647
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]648classOfficialBuildTest(BisectTestCase):
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]649
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]650def test_should_lookup_path_context(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]651 options= bisect_builds.ParseCommandLine(
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]652['-o','-a','linux64','-g','0','-b','10'])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]653 self.assertEqual(options.archive,'linux64')
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]654 build= bisect_builds.create_archive_build(options)
655 self.assertIsInstance(build, bisect_builds.OfficialBuild)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]656 self.assertEqual(build.binary_name,'chrome')
657 self.assertEqual(build.listing_platform_dir,'linux-builder-perf/')
658 self.assertEqual(build.archive_name,'chrome-perf-linux.zip')
659 self.assertEqual(build.archive_extract_dir,'full-build-linux')
660
Kuan Huangc63de402024-08-12 22:15:27[diff] [blame]661@maybe_patch('bisect-builds.GsutilList',
662 return_value=[
663'full-build-linux_%d.zip'% x
664for xin range(1313161,1313164)
665])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]666def test_get_rev_list(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]667 options= bisect_builds.ParseCommandLine([
668'-o','-a','linux64','-g','1313161','-b','1313163',
669'--no-local-cache'
670])
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]671 build= bisect_builds.create_archive_build(options)
672 self.assertIsInstance(build, bisect_builds.OfficialBuild)
673 self.assertEqual(build.get_rev_list(), list(range(1313161,1313164)))
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]674 mock_GsutilList.assert_called_once_with(
675'gs://chrome-test-builds/official-by-commit/linux-builder-perf/')
676
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]677@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
678'The test only valid when NO_MOCK_SERVER')
679@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'stdout',''))
680def test_run_revision_with_real_zipfile(self, mock_run):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]681 options= bisect_builds.ParseCommandLine([
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]682'-o','-a','linux64','-g','1313161','-b','1313163',
683'--chromedriver','-c','driver=%d prog=%p'
684])
685 build= bisect_builds.create_archive_build(options)
686 self.assertIsInstance(build, bisect_builds.OfficialBuild)
687 download_job= build.get_download_job(1334339)
688 zip_file= download_job.start().wait_for()
689with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
690 build.run_revision(zip_file, tempdir,[])
691 self.assertRegex(mock_run.call_args.args[0],
692 r'driver=.+/chromedriver prog=.+/chrome')
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]693
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]694classSnapshotBuildTest(BisectTestCase):
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]695
696def test_should_lookup_path_context(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]697 options= bisect_builds.ParseCommandLine(
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]698['-a','linux64','-g','0','-b','10'])
699 self.assertEqual(options.archive,'linux64')
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]700 build= bisect_builds.create_archive_build(options)
701 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]702 self.assertEqual(build.binary_name,'chrome')
703 self.assertEqual(build.listing_platform_dir,'Linux_x64/')
704 self.assertEqual(build.archive_name,'chrome-linux.zip')
705 self.assertEqual(build.archive_extract_dir,'chrome-linux')
706
707CommonDataXMLContent='''<?xml version='1.0' encoding='UTF-8'?>
708 <ListBucketResult xmlns='http://doc.s3.amazonaws.com/2006-03-01'>
709 <Name>chromium-browser-snapshots</Name>
710 <Prefix>Linux_x64/</Prefix>
711 <Marker></Marker>
712 <NextMarker></NextMarker>
713 <Delimiter>/</Delimiter>
714 <IsTruncated>true</IsTruncated>
715 <CommonPrefixes>
716 <Prefix>Linux_x64/1313161/</Prefix>
717 </CommonPrefixes>
718 <CommonPrefixes>
719 <Prefix>Linux_x64/1313163/</Prefix>
720 </CommonPrefixes>
721 <CommonPrefixes>
722 <Prefix>Linux_x64/1313185/</Prefix>
723 </CommonPrefixes>
724 </ListBucketResult>
725 '''
726
727@maybe_patch('urllib.request.urlopen',
Kuan Huang05058842024-10-24 21:22:26[diff] [blame]728 return_value=io.BytesIO(CommonDataXMLContent.encode('utf8')))
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]729@patch('bisect-builds.GetChromiumRevision', return_value=1313185)
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]730def test_get_rev_list(self, mock_GetChromiumRevision, mock_urlopen):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]731 options= bisect_builds.ParseCommandLine(
732['-a','linux64','-g','1313161','-b','1313185','--no-local-cache'])
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]733 build= bisect_builds.create_archive_build(options)
734 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]735 rev_list= build.get_rev_list()
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]736 mock_urlopen.assert_any_call(
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]737'http://commondatastorage.googleapis.com/chromium-browser-snapshots/'
738'?delimiter=/&prefix=Linux_x64/&marker=Linux_x64/1313161')
739 self.assertEqual(mock_urlopen.call_count,1)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]740 self.assertEqual(rev_list,[1313161,1313163,1313185])
741
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]742@patch('bisect-builds.SnapshotBuild._fetch_and_parse',
743 return_value=([int(s)
744for sin sorted([str(x)for xin range(1,11)])],None))
745def test_get_rev_list_should_start_from_a_marker(self, mock_fetch_and_parse):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]746 options= bisect_builds.ParseCommandLine(
747['-a','linux64','-g','0','-b','9','--no-local-cache'])
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]748 build= bisect_builds.create_archive_build(options)
749 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
750 rev_list= build._get_rev_list(0,9)
751 self.assertEqual(rev_list, list(range(1,10)))
752 mock_fetch_and_parse.assert_called_once_with(
753'http://commondatastorage.googleapis.com/chromium-browser-snapshots/'
754'?delimiter=/&prefix=Linux_x64/&marker=Linux_x64/0')
755 mock_fetch_and_parse.reset_mock()
756 rev_list= build._get_rev_list(1,9)
757 self.assertEqual(rev_list, list(range(1,10)))
758 mock_fetch_and_parse.assert_called_once_with(
759'http://commondatastorage.googleapis.com/chromium-browser-snapshots/'
760'?delimiter=/&prefix=Linux_x64/&marker=Linux_x64/1')
761
762@patch('bisect-builds.SnapshotBuild._fetch_and_parse',
763 return_value=([int(s)
764for sin sorted([str(x)for xin range(1,11)])],None))
765def test_get_rev_list_should_scan_all_pages(self, mock_fetch_and_parse):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]766 options= bisect_builds.ParseCommandLine(
767['-a','linux64','-g','3','-b','11','--no-local-cache'])
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]768 build= bisect_builds.create_archive_build(options)
769 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
770 rev_list= build._get_rev_list(0,11)
771 self.assertEqual(sorted(rev_list), list(range(1,11)))
772 mock_fetch_and_parse.assert_called_once_with(
773'http://commondatastorage.googleapis.com/chromium-browser-snapshots/'
774'?delimiter=/&prefix=Linux_x64/')
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]775
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]776def test_get_download_url(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]777 options= bisect_builds.ParseCommandLine(
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]778['-a','linux64','-g','3','-b','11'])
779 build= bisect_builds.create_archive_build(options)
780 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
781 download_urls= build.get_download_url(123)
782 self.assertEqual(
783 download_urls,
784'http://commondatastorage.googleapis.com/chromium-browser-snapshots'
785'/Linux_x64/123/chrome-linux.zip',
786)
787
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]788 options= bisect_builds.ParseCommandLine(
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]789['-a','linux64','-g','3','-b','11','--chromedriver'])
790 build= bisect_builds.create_archive_build(options)
791 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
792 download_urls= build.get_download_url(123)
793 self.assertDictEqual(
794 download_urls,{
795'chrome':
796'http://commondatastorage.googleapis.com/chromium-browser-snapshots'
797'/Linux_x64/123/chrome-linux.zip',
798'chromedriver':
799'http://commondatastorage.googleapis.com/chromium-browser-snapshots'
800'/Linux_x64/123/chromedriver_linux64.zip'
801})
802
803@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
804'The test only valid when NO_MOCK_SERVER')
805@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'stdout',''))
806def test_run_revision_with_real_zipfile(self, mock_run):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]807 options= bisect_builds.ParseCommandLine([
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]808'-a','linux64','-g','1313161','-b','1313185','--chromedriver',
809'-c','driver=%d prog=%p'
810])
811 build= bisect_builds.create_archive_build(options)
812 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
813 download_job= build.get_download_job(1313161)
814 zip_file= download_job.start().wait_for()
815with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
816 build.run_revision(zip_file, tempdir,[])
817 self.assertRegex(mock_run.call_args.args[0],
818 r'driver=.+/chromedriver prog=.+/chrome')
819
Kuan Huange8443752024-09-16 19:05:20[diff] [blame]820@patch('bisect-builds.GetChromiumRevision', return_value=1313185)
821def test_get_bad_revision(self, mock_GetChromiumRevision):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]822 options= bisect_builds.ParseCommandLine(['-a','linux64','-g','1313161'])
Kuan Huange8443752024-09-16 19:05:20[diff] [blame]823 build= bisect_builds.create_archive_build(options)
824 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
825 mock_GetChromiumRevision.assert_called_once_with(
826'http://commondatastorage.googleapis.com/chromium-browser-snapshots'
827'/Linux_x64/LAST_CHANGE')
828 self.assertEqual(build.bad_revision,1313185)
829
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]830
Kuan Huang2dd3a33f2024-12-13 17:52:52[diff] [blame]831classChromeForTestingBuild(BisectTestCase):
832
833def test_should_lookup_path_context(self):
834 options= bisect_builds.ParseCommandLine(
835['-cft','-a','linux64','-g','0','-b','10'])
836 self.assertEqual(options.archive,'linux64')
837 build= bisect_builds.create_archive_build(options)
838 self.assertIsInstance(build, bisect_builds.ChromeForTestingBuild)
839 self.assertEqual(build.binary_name,'chrome')
840 self.assertEqual(build.listing_platform_dir,'linux64/')
841 self.assertEqual(build.archive_name,'chrome-linux64.zip')
842 self.assertEqual(build.chromedriver_binary_name,'chromedriver')
843 self.assertEqual(build.chromedriver_archive_name,
844'chromedriver-linux64.zip')
845
846CommonDataXMLContent='''<?xml version='1.0' encoding='UTF-8'?>
847 <ListBucketResult xmlns="http://doc.s3.amazonaws.com/2006-03-01">
848 <Name>chrome-for-testing-per-commit-public</Name>
849 <Prefix>linux64/</Prefix>
850 <Marker/>
851 <Delimiter>/</Delimiter>
852 <IsTruncated>false</IsTruncated>
853 <Contents>
854 <Key>linux64/LAST_CHANGE</Key>
855 <Generation>1733959087133532</Generation>
856 <MetaGeneration>1</MetaGeneration>
857 <LastModified>2024-12-11T23:18:07.235Z</LastModified>
858 <ETag>"dd60cb93e225ab33d7254beca56b507a"</ETag>
859 <Size>7</Size>
860 </Contents>
861 <CommonPrefixes>
862 <Prefix>linux64/r1390729/</Prefix>
863 </CommonPrefixes>
864 <CommonPrefixes>
865 <Prefix>linux64/r1390746/</Prefix>
866 </CommonPrefixes>
867 <CommonPrefixes>
868 <Prefix>linux64/r1390757/</Prefix>
869 </CommonPrefixes>
870 </ListBucketResult>
871 '''
872
873@maybe_patch('urllib.request.urlopen',
874 return_value=io.BytesIO(CommonDataXMLContent.encode('utf8')))
875@patch('bisect-builds.GetChromiumRevision', return_value=1390757)
876def test_get_rev_list(self, mock_GetChromiumRevision, mock_urlopen):
877 options= bisect_builds.ParseCommandLine([
878'-cft','-a','linux64','-g','1390729','-b','1390757',
879'--no-local-cache'
880])
881 build= bisect_builds.create_archive_build(options)
882 self.assertIsInstance(build, bisect_builds.ChromeForTestingBuild)
883 rev_list= build.get_rev_list()
884 mock_urlopen.assert_any_call(
885'https://storage.googleapis.com/chrome-for-testing-per-commit-public/'
886'?delimiter=/&prefix=linux64/&marker=linux64/r1390729')
887 self.assertEqual(mock_urlopen.call_count,1)
888 self.assertEqual(rev_list,[1390729,1390746,1390757])
889
890def test_get_marker(self):
891 options= bisect_builds.ParseCommandLine(
892['-cft','-a','linux64','-g','1','-b','3'])
893 build= bisect_builds.create_archive_build(options)
894 self.assertIsInstance(build, bisect_builds.ChromeForTestingBuild)
895 self.assertEqual('linux64/r1390729',
896 build._get_marker_for_revision(1390729))
897
898def test_get_download_url(self):
899 options= bisect_builds.ParseCommandLine(
900['-cft','-a','linux64','-g','3','-b','11'])
901 build= bisect_builds.create_archive_build(options)
902 self.assertIsInstance(build, bisect_builds.ChromeForTestingBuild)
903 download_urls= build.get_download_url(123)
904 self.assertEqual(
905 download_urls,
906'https://storage.googleapis.com/chrome-for-testing-per-commit-public'
907'/linux64/r123/chrome-linux64.zip',
908)
909
910 options= bisect_builds.ParseCommandLine(
911['-cft','-a','linux64','-g','3','-b','11','--chromedriver'])
912 build= bisect_builds.create_archive_build(options)
913 self.assertIsInstance(build, bisect_builds.ChromeForTestingBuild)
914 download_urls= build.get_download_url(123)
915 download_urls= build.get_download_url(123)
916 self.assertEqual(
917 download_urls,{
918'chrome':
919'https://storage.googleapis.com/chrome-for-testing-per-commit-public'
920'/linux64/r123/chrome-linux64.zip',
921'chromedriver':
922'https://storage.googleapis.com/chrome-for-testing-per-commit-public'
923'/linux64/r123/chromedriver-linux64.zip',
924})
925
926@patch('bisect-builds.GetChromiumRevision', return_value=1390757)
927def test_get_bad_revision(self, mock_GetChromiumRevision):
928 options= bisect_builds.ParseCommandLine(
929['-cft','-a','linux64','-g','3'])
930 build= bisect_builds.create_archive_build(options)
931 self.assertIsInstance(build, bisect_builds.ChromeForTestingBuild)
932 mock_GetChromiumRevision.assert_called_once_with(
933'https://storage.googleapis.com/chrome-for-testing-per-commit-public'
934'/linux64/LAST_CHANGE')
935 self.assertEqual(build.bad_revision,1390757)
936
937@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
938'The test only valid when NO_MOCK_SERVER')
939@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'stdout',''))
940def test_run_revision_with_real_zipfile(self, mock_run):
941 options= bisect_builds.ParseCommandLine([
942'--cft','-a','linux64','-g','1','--chromedriver','-c',
943'driver=%d prog=%p'
944])
945 build= bisect_builds.create_archive_build(options)
946 self.assertIsInstance(build, bisect_builds.SnapshotBuild)
947 download_job= build.get_download_job(build.bad_revision)
948 zip_file= download_job.start().wait_for()
949with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
950 build.run_revision(zip_file, tempdir,[])
951 self.assertRegex(mock_run.call_args.args[0],
952 r'driver=.+/chromedriver prog=.+/chrome')
953
954
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]955classASANBuildTest(BisectTestCase):
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]956
957CommonDataXMLContent='''<?xml version='1.0' encoding='UTF-8'?>
958 <ListBucketResult xmlns='http://doc.s3.amazonaws.com/2006-03-01'>
959 <Name>chromium-browser-asan</Name>
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]960 <Prefix>mac-release/asan-mac-release</Prefix>
961 <Marker></Marker>
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]962 <NextMarker></NextMarker>
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]963 <Delimiter>.zip</Delimiter>
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]964 <IsTruncated>true</IsTruncated>
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]965 <CommonPrefixes>
966 <Prefix>mac-release/asan-mac-release-1313186.zip</Prefix>
967 </CommonPrefixes>
968 <CommonPrefixes>
969 <Prefix>mac-release/asan-mac-release-1313195.zip</Prefix>
970 </CommonPrefixes>
971 <CommonPrefixes>
972 <Prefix>mac-release/asan-mac-release-1313210.zip</Prefix>
973 </CommonPrefixes>
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]974 </ListBucketResult>
975 '''
976
977@maybe_patch('urllib.request.urlopen',
Kuan Huang05058842024-10-24 21:22:26[diff] [blame]978 return_value=io.BytesIO(CommonDataXMLContent.encode('utf8')))
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]979def test_get_rev_list(self, mock_urlopen):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]980 options= bisect_builds.ParseCommandLine([
981'--asan','-a','mac','-g','1313161','-b','1313210',
982'--no-local-cache'
983])
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]984 build= bisect_builds.create_archive_build(options)
985 self.assertIsInstance(build, bisect_builds.ASANBuild)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]986 rev_list= build.get_rev_list()
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]987# print(mock_urlopen.call_args_list)
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]988 mock_urlopen.assert_any_call(
Kuan Huangc8dd77a2024-08-12 22:13:42[diff] [blame]989'http://commondatastorage.googleapis.com/chromium-browser-asan/'
Kuan Huanga716032a2024-08-14 22:15:46[diff] [blame]990'?delimiter=.zip&prefix=mac-release/asan-mac-release'
991'&marker=mac-release/asan-mac-release-1313161.zip')
992 self.assertEqual(mock_urlopen.call_count,1)
993 self.assertEqual(rev_list,[1313186,1313195,1313210])
Kuan Huang49a2c6412024-08-12 22:12:33[diff] [blame]994
995
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]996classAndroidBuildTest(BisectTestCase):
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]997
998def setUp(self):
999# patch for devil_imports
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]1000 self.patchers=[]
1001 flag_changer_patcher= maybe_patch('bisect-builds.flag_changer',
1002 create=True)
1003 self.patchers.append(flag_changer_patcher)
1004 self.mock_flag_changer= flag_changer_patcher.start()
1005 chrome_patcher= maybe_patch('bisect-builds.chrome', create=True)
1006 self.patchers.append(chrome_patcher)
1007 self.mock_chrome= chrome_patcher.start()
1008 version_codes_patcher= maybe_patch('bisect-builds.version_codes',
1009 create=True)
1010 self.patchers.append(version_codes_patcher)
1011 self.mock_version_codes= version_codes_patcher.start()
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1012 self.mock_version_codes.LOLLIPOP=21
1013 self.mock_version_codes.NOUGAT=24
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1014 self.mock_version_codes.PIE=28
1015 self.mock_version_codes.Q=29
1016 initial_android_device_patcher= patch(
1017'bisect-builds.InitializeAndroidDevice')
1018 self.patchers.append(initial_android_device_patcher)
1019 self.mock_initial_android_device= initial_android_device_patcher.start()
1020 self.device= self.mock_initial_android_device.return_value
1021 self.set_sdk_level(bisect_builds.version_codes.Q)
1022
1023def set_sdk_level(self, level):
1024 self.device.build_version_sdk= level
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1025
1026def tearDown(self):
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]1027for patcherin self.patchers:
1028 patcher.stop()
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1029
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1030
1031classAndroidReleaseBuildTest(AndroidBuildTest):
1032
1033def setUp(self):
1034 super().setUp()
1035 self.set_sdk_level(bisect_builds.version_codes.PIE)
1036
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1037@maybe_patch(
1038'bisect-builds.GsutilList',
1039 return_value=[
1040'gs://chrome-signed/android-B0urB0N/%s/arm_64/MonochromeStable.apk'%
1041 xfor xin['127.0.6533.76','127.0.6533.78','127.0.6533.79']
1042])
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1043def test_get_android_rev_list(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1044 options= bisect_builds.ParseCommandLine([
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1045'-r','-a','android-arm64','--apk','chrome_stable','-g',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1046'127.0.6533.76','-b','127.0.6533.79','--signed','--no-local-cache'
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1047])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1048 build= bisect_builds.create_archive_build(options)
1049 self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
1050 self.assertEqual(build.get_rev_list(),
1051['127.0.6533.76','127.0.6533.78','127.0.6533.79'])
1052 mock_GsutilList.assert_any_call('gs://chrome-signed/android-B0urB0N')
1053 mock_GsutilList.assert_any_call(*[
1054'gs://chrome-signed/android-B0urB0N/%s/arm_64/MonochromeStable.apk'% x
1055for xin['127.0.6533.76','127.0.6533.78','127.0.6533.79']
1056],
1057 ignore_fail=True)
1058 self.assertEqual(mock_GsutilList.call_count,2)
1059
1060@patch('bisect-builds.InstallOnAndroid')
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1061def test_install_revision(self, mock_InstallOnAndroid):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1062 options= bisect_builds.ParseCommandLine([
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1063'-r','-a','android-arm64','-g','127.0.6533.76','-b',
1064'127.0.6533.79','--apk','chrome'
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1065])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1066 build= bisect_builds.create_archive_build(options)
1067 self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
1068 build._install_revision('chrome.apk','temp-dir')
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1069 mock_InstallOnAndroid.assert_called_once_with(self.device,'chrome.apk')
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1070
1071@patch('bisect-builds.LaunchOnAndroid')
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1072def test_launch_revision(self, mock_LaunchOnAndroid):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1073 options= bisect_builds.ParseCommandLine([
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1074'-r','-a','android-arm64','-g','127.0.6533.76','-b',
1075'127.0.6533.79','--apk','chrome'
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1076])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1077 build= bisect_builds.create_archive_build(options)
1078 self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
1079 build._launch_revision('temp-dir',None)
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1080 mock_LaunchOnAndroid.assert_called_once_with(self.device,'chrome')
1081
Kuan Huangfb55c272024-09-16 20:56:42[diff] [blame]1082@patch('bisect-builds.LaunchOnAndroid')
1083def test_webview_launch_revision(self, mock_LaunchOnAndroid):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1084 options= bisect_builds.ParseCommandLine([
Kuan Huangfb55c272024-09-16 20:56:42[diff] [blame]1085'-r','-a','android-arm64','-g','127.0.6533.76','-b',
1086'127.0.6533.79','--apk','system_webview'
1087])
1088 build= bisect_builds.create_archive_build(options)
1089 self.assertIsInstance(build, bisect_builds.AndroidReleaseBuild)
1090 build._launch_revision('temp-dir',None)
1091 mock_LaunchOnAndroid.assert_called_once_with(self.device,'system_webview')
1092with self.assertRaises(bisect_builds.BisectException):
1093 build._launch_revision('temp-dir',None,['args'])
1094
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1095
1096classAndroidSnapshotBuildTest(AndroidBuildTest):
1097
1098def setUp(self):
1099 super().setUp()
1100 self.set_sdk_level(bisect_builds.version_codes.PIE)
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1101
Kuan Huangbeba95a52025-01-06 23:10:10[diff] [blame]1102@patch('bisect-builds.UnzipFilenameToDir')
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1103@patch('bisect-builds.InstallOnAndroid')
Kuan Huangbeba95a52025-01-06 23:10:10[diff] [blame]1104@patch('glob.glob', return_value=['Monochrome.apk'])
1105def test_install_revision(self, mock_glob, mock_InstallOnAndroid, mock_unzip):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1106 options= bisect_builds.ParseCommandLine([
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1107'-a','android-arm64','-g','1313161','-b','1313210','--apk',
1108'chrome'
1109])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1110 build= bisect_builds.create_archive_build(options)
1111 self.assertIsInstance(build, bisect_builds.AndroidSnapshotBuild)
1112 build._install_revision('chrome.zip','temp-dir')
Kuan Huangbeba95a52025-01-06 23:10:10[diff] [blame]1113 mock_glob.assert_called_once_with('temp-dir/*/apks/Monochrome.apk')
1114 mock_InstallOnAndroid.assert_called_once_with(self.device,'Monochrome.apk')
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1115
Kuan Huangbeba95a52025-01-06 23:10:10[diff] [blame]1116@patch('bisect-builds.UnzipFilenameToDir')
1117@patch('sys.stdout', new_callable=io.StringIO)
1118@patch('glob.glob',
1119 side_effect=[[],
1120[
1121"temp-dir/full-build-linux/apks/MonochromeBeta.apk",
1122"temp-dir/full-build-linux/apks/ChromePublic.apk"
1123]])
1124def test_install_revision_with_show_available_apks(self, mock_glob,
1125 mock_stdout, mock_unzip):
1126 options= bisect_builds.ParseCommandLine([
1127'-a','android-arm64','-g','1313161','-b','1313210','--apk',
1128'chrome'
1129])
1130 build= bisect_builds.create_archive_build(options)
1131 self.assertIsInstance(build, bisect_builds.AndroidSnapshotBuild)
1132with self.assertRaises(bisect_builds.BisectException):
1133 build._install_revision('chrome.zip','temp-dir')
1134 self.assertIn("The list of available --apk:", mock_stdout.getvalue())
1135 self.assertIn("chrome_beta", mock_stdout.getvalue())
1136 self.assertIn("chromium", mock_stdout.getvalue())
1137
1138@patch('bisect-builds.UnzipFilenameToDir')
1139@patch('sys.stdout', new_callable=io.StringIO)
1140@patch('glob.glob',
1141 side_effect=[[],["temp-dir/full-build-linux/apks/unknown.apks"]])
1142def test_install_revision_with_show_unknown_apks(self, mock_glob, mock_stdout,
1143 mock_unzip):
1144 options= bisect_builds.ParseCommandLine([
1145'-a','android-arm64','-g','1313161','-b','1313210','--apk',
1146'chrome'
1147])
1148 build= bisect_builds.create_archive_build(options)
1149 self.assertIsInstance(build, bisect_builds.AndroidSnapshotBuild)
1150with self.assertRaises(bisect_builds.BisectException):
1151 build._install_revision('chrome.zip','temp-dir')
1152 self.assertIn("No supported apk found. But found following",
1153 mock_stdout.getvalue())
1154 self.assertIn("unknown.apks", mock_stdout.getvalue())
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1155
1156classAndroidTrichromeReleaseBuildTest(AndroidBuildTest):
1157
1158def setUp(self):
1159 super().setUp()
1160 self.set_sdk_level(bisect_builds.version_codes.Q)
1161
1162@maybe_patch(
1163'bisect-builds.GsutilList',
1164 side_effect=[[
1165'gs://chrome-unsigned/android-B0urB0N/%s/'% xfor xin[
1166'129.0.6626.0','129.0.6626.1','129.0.6627.0','129.0.6627.1',
1167'129.0.6628.0','129.0.6628.1'
1168]
1169],
1170[('gs://chrome-unsigned/android-B0urB0N/%s/'
1171'high-arm_64/TrichromeChromeGoogle6432Stable.apks')% x
1172for xin['129.0.6626.0','129.0.6627.0','129.0.6628.0']]])
1173def test_get_rev_list(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1174 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1175'-r','-a','android-arm64-high','--apk','chrome_stable','-g',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1176'129.0.6626.0','-b','129.0.6628.0','--no-local-cache'
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1177])
1178 build= bisect_builds.create_archive_build(options)
1179 self.assertIsInstance(build, bisect_builds.AndroidTrichromeReleaseBuild)
1180 self.assertEqual(build.get_rev_list(),
1181['129.0.6626.0','129.0.6627.0','129.0.6628.0'])
1182print(mock_GsutilList.call_args_list)
1183 mock_GsutilList.assert_any_call('gs://chrome-unsigned/android-B0urB0N')
1184 mock_GsutilList.assert_any_call(*[
1185('gs://chrome-unsigned/android-B0urB0N/%s/'
1186'high-arm_64/TrichromeChromeGoogle6432Stable.apks')% xfor xin[
1187'129.0.6626.0','129.0.6626.1','129.0.6627.0','129.0.6627.1',
1188'129.0.6628.0'
1189]
1190],
1191 ignore_fail=True)
1192 self.assertEqual(mock_GsutilList.call_count,2)
1193
1194def test_should_raise_exception_for_PIE(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1195 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1196'-r','-a','android-arm64-high','--apk','chrome_stable','-g',
1197'129.0.6626.0','-b','129.0.6667.0'
1198])
1199 self.set_sdk_level(bisect_builds.version_codes.PIE)
1200with self.assertRaises(bisect_builds.BisectException):
1201 bisect_builds.create_archive_build(options)
1202
1203def test_get_download_url(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1204 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1205'-r','-a','android-arm64-high','--apk','chrome_stable','-g',
1206'129.0.6626.0','-b','129.0.6628.0'
1207])
1208 build= bisect_builds.create_archive_build(options)
1209 self.assertIsInstance(build, bisect_builds.AndroidTrichromeReleaseBuild)
1210 download_urls= build.get_download_url('129.0.6626.0')
1211 self.maxDiff=1000
1212 self.assertDictEqual(
1213 download_urls,{
1214'trichrome':
1215('gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/high-arm_64/'
1216'TrichromeChromeGoogle6432Stable.apks'),
1217'trichrome_library':
1218('gs://chrome-unsigned/android-B0urB0N/129.0.6626.0/high-arm_64/'
1219'TrichromeLibraryGoogle6432Stable.apk'),
1220})
1221
1222@patch('bisect-builds.InstallOnAndroid')
1223def test_install_revision(self, mock_InstallOnAndroid):
1224 downloads={
1225'trichrome':'some-file.apks',
1226'trichrome_library':'file2.apk',
1227}
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1228 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1229'-r','-a','android-arm64-high','--apk','chrome_stable','-g',
1230'129.0.6626.0','-b','129.0.6628.0'
1231])
1232 build= bisect_builds.create_archive_build(options)
1233 self.assertIsInstance(build, bisect_builds.AndroidTrichromeReleaseBuild)
1234 build._install_revision(downloads,'tmp-dir')
1235 mock_InstallOnAndroid.assert_any_call(self.device,'some-file.apks')
1236 mock_InstallOnAndroid.assert_any_call(self.device,'file2.apk')
1237
1238
1239classAndroidTrichromeOfficialBuildTest(AndroidBuildTest):
1240
1241@maybe_patch('bisect-builds.GsutilList',
1242 return_value=[
1243'full-build-linux_%d.zip'% x
1244for xin[1334339,1334342,1334344,1334345,1334356]
1245])
1246def test_get_rev_list(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1247 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1248'-o','-a','android-arm64-high','--apk','chrome','-g','1334338',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1249'-b','1334380','--no-local-cache'
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1250])
1251 build= bisect_builds.create_archive_build(options)
1252 self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
1253 self.assertEqual(build.get_rev_list(),
1254[1334339,1334342,1334344,1334345,1334356])
1255 mock_GsutilList.assert_called_once_with(
1256'gs://chrome-test-builds/official-by-commit/'
1257'android_arm64_high_end-builder-perf/')
1258
1259def test_get_download_url(self):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1260 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1261'-o','-a','android-arm64-high','--apk','chrome','-g','1334338',
1262'-b','1334380'
1263])
1264 build= bisect_builds.create_archive_build(options)
1265 self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
1266 self.assertEqual(
1267 build.get_download_url(1334338),
1268'gs://chrome-test-builds/official-by-commit'
1269'/android_arm64_high_end-builder-perf/full-build-linux_1334338.zip')
1270
1271@patch('glob.glob',
1272 side_effect=[[
1273'temp-dir/full-build-linux/apks/TrichromeChromeGoogle6432.apks'
1274],['temp-dir/full-build-linux/apks/TrichromeLibraryGoogle6432.apk']])
1275@patch('bisect-builds.UnzipFilenameToDir')
1276@patch('bisect-builds.InstallOnAndroid')
1277def test_install_revision(self, mock_InstallOnAndroid,
1278 mock_UnzipFilenameToDir, mock_glob):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1279 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1280'-o','-a','android-arm64-high','--apk','chrome','-g','1334338',
1281'-b','1334380'
1282])
1283 build= bisect_builds.create_archive_build(options)
1284 self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
1285 build._install_revision('download.zip','tmp-dir')
1286 mock_UnzipFilenameToDir.assert_called_once_with('download.zip','tmp-dir')
1287 mock_InstallOnAndroid.assert_any_call(
1288 self.device,
1289'temp-dir/full-build-linux/apks/TrichromeLibraryGoogle6432.apk')
1290 mock_InstallOnAndroid.assert_any_call(
1291 self.device,
1292'temp-dir/full-build-linux/apks/TrichromeChromeGoogle6432.apks')
1293
Kuan Huangbeba95a52025-01-06 23:10:10[diff] [blame]1294@patch('sys.stdout', new_callable=io.StringIO)
1295@patch('glob.glob',
1296 side_effect=[[],
1297['temp-dir/TrichromeChromeGoogle6432Canary.minimal.apks']
1298])
1299@patch('bisect-builds.UnzipFilenameToDir')
1300def test_install_revision_with_show_available_apks(self,
1301 mock_UnzipFilenameToDir,
1302 mock_glob, mock_stdout):
1303 options= bisect_builds.ParseCommandLine([
1304'-o','-a','android-arm64-high','--apk','chrome','-g','1334338',
1305'-b','1334380'
1306])
1307 build= bisect_builds.create_archive_build(options)
1308 self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
1309with self.assertRaises(bisect_builds.BisectException):
1310 build._install_revision('download.zip','tmp-dir')
1311 self.assertIn("The list of available --apk:", mock_stdout.getvalue())
1312 self.assertIn("chrome_canary", mock_stdout.getvalue())
1313
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1314@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
1315'The test only valid when NO_MOCK_SERVER')
1316@patch('bisect-builds.InstallOnAndroid')
1317@patch('bisect-builds.LaunchOnAndroid')
1318def test_run_revision_with_real_zipfile(self, mock_LaunchOnAndroid,
1319 mock_InstallOnAndroid):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1320 options= bisect_builds.ParseCommandLine([
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1321'-o','-a','android-arm64-high','--apk','chrome','-g','1334338',
1322'-b','1334380'
1323])
1324 build= bisect_builds.create_archive_build(options)
1325 self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
1326 download_job= build.get_download_job(1334339)
1327 zip_file= download_job.start().wait_for()
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]1328with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
1329 build.run_revision(zip_file, tempdir,[])
Kuan Huangfeb4fa552024-08-21 20:40:28[diff] [blame]1330print(mock_InstallOnAndroid.call_args_list)
1331 self.assertRegex(mock_InstallOnAndroid.mock_calls[0].args[1],
1332'full-build-linux/apks/TrichromeLibraryGoogle6432.apk$')
1333 self.assertRegex(
1334 mock_InstallOnAndroid.mock_calls[1].args[1],
1335'full-build-linux/apks/TrichromeChromeGoogle6432.minimal.apks$')
1336 mock_LaunchOnAndroid.assert_called_once_with(self.device,'chrome')
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1337
Trung Nguyend391d052025-06-04 09:35:09[diff] [blame]1338@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
1339'The test only valid when NO_MOCK_SERVER')
1340@patch('bisect-builds.InstallOnAndroid')
1341@patch('bisect-builds.LaunchOnAndroid')
1342def test_run_revision_with_webview_apk_with_unsupported_versions(
1343 self, mock_LaunchOnAndroid, mock_InstallOnAndroid):
1344 options= bisect_builds.ParseCommandLine([
1345'-o','-a','android-arm64-high','--apk','system_webview','-g',
1346'100000','-b','100010'
1347])
1348
1349with self.assertRaises(bisect_builds.BisectException):
1350 _= bisect_builds.create_archive_build(options)
1351
1352@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
1353'The test only valid when NO_MOCK_SERVER')
1354@patch('bisect-builds.InstallOnAndroid')
1355@patch('bisect-builds.LaunchOnAndroid')
1356def test_webview_launch_revision(self, mock_LaunchOnAndroid,
1357 mock_InstallOnAndroid):
1358 options= bisect_builds.ParseCommandLine([
1359'-o','-a','android-arm64-high','--apk','system_webview','-g',
1360'1350000','-b','1350010'
1361])
1362
1363 build= bisect_builds.create_archive_build(options)
1364
1365 self.assertIsInstance(build, bisect_builds.AndroidTrichromeOfficialBuild)
1366 download_job= build.get_download_job(1334339)
1367 zip_file= download_job.start().wait_for()
1368with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
1369 build.run_revision(zip_file, tempdir,[])
1370print(mock_InstallOnAndroid.call_args_list)
1371 self.assertRegex(mock_InstallOnAndroid.mock_calls[0].args[1],
1372'full-build-linux/apks/TrichromeLibraryGoogle6432.apk$')
1373 self.assertRegex(
1374 mock_InstallOnAndroid.mock_calls[1].args[1],
1375'full-build-linux/apks/TrichromeWebViewGoogle6432.minimal.apks$')
1376 mock_LaunchOnAndroid.assert_called_once_with(self.device,'system_webview')
1377
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1378
Kuan Huangdc7d212b2024-08-19 20:53:30[diff] [blame]1379classLinuxReleaseBuildTest(BisectTestCase):
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1380
1381@patch('subprocess.Popen', spec=subprocess.Popen)
1382def test_launch_revision_should_has_no_sandbox(self, mock_Popen):
1383 mock_Popen.return_value.communicate.return_value=('','')
1384 mock_Popen.return_value.returncode=0
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1385 options= bisect_builds.ParseCommandLine(
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1386['-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.88'])
1387 build= bisect_builds.create_archive_build(options)
1388 self.assertIsInstance(build, bisect_builds.LinuxReleaseBuild)
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]1389 build._launch_revision('temp-dir',{'chrome':'temp-dir/linux64/chrome'},
1390[])
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1391 mock_Popen.assert_called_once_with(
Kuan Huang89fe2eef2024-09-13 23:04:02[diff] [blame]1392'temp-dir/linux64/chrome --user-data-dir=temp-dir/profile --no-sandbox',
Kuan Huangabd69f22024-09-13 23:03:48[diff] [blame]1393 cwd=None,
1394 shell=True,
Kuan Huangd608f1592024-08-15 23:31:35[diff] [blame]1395 bufsize=-1,
1396 stdout=ANY,
1397 stderr=ANY)
1398
1399
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1400classIOSReleaseBuildTest(BisectTestCase):
1401
1402@maybe_patch(
1403'bisect-builds.GsutilList',
1404 side_effect=[[
1405'gs://chrome-unsigned/ios-G1N/127.0.6533.76/',
1406'gs://chrome-unsigned/ios-G1N/127.0.6533.77/',
1407'gs://chrome-unsigned/ios-G1N/127.0.6533.78/'
1408],
1409[
1410'gs://chrome-unsigned/ios-G1N'
1411'/127.0.6533.76/iphoneos17.5/ios/10863/canary.ipa',
1412'gs://chrome-unsigned/ios-G1N'
1413'/127.0.6533.77/iphoneos17.5/ios/10866/canary.ipa',
1414'gs://chrome-unsigned/ios-G1N'
1415'/127.0.6533.78/iphoneos17.5/ios/10868/canary.ipa'
1416]])
1417def test_list_rev(self, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1418 options= bisect_builds.ParseCommandLine([
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1419'-r','-a','ios','--ipa=canary.ipa','--device-id','321','-g',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1420'127.0.6533.74','-b','127.0.6533.78','--no-local-cache'
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1421])
1422 build= bisect_builds.create_archive_build(options)
1423 self.assertIsInstance(build, bisect_builds.IOSReleaseBuild)
1424 self.assertEqual(build.get_rev_list(),
1425['127.0.6533.76','127.0.6533.77','127.0.6533.78'])
1426 mock_GsutilList.assert_any_call('gs://chrome-unsigned/ios-G1N')
1427 mock_GsutilList.assert_any_call(*[
1428'gs://chrome-unsigned/ios-G1N/%s/*/ios/*/canary.ipa'% x
1429for xin['127.0.6533.76','127.0.6533.77','127.0.6533.78']
1430],
1431 ignore_fail=True)
1432
1433@patch('bisect-builds.UnzipFilenameToDir')
1434@patch('glob.glob', return_value=['Payload/canary.app/Info.plist'])
1435@patch('subprocess.Popen', spec=subprocess.Popen)
1436def test_install_revision(self, mock_Popen, mock_glob,
1437 mock_UnzipFilenameToDir):
1438 mock_Popen.return_value.communicate.return_value=('','')
1439 mock_Popen.return_value.returncode=0
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1440 options= bisect_builds.ParseCommandLine([
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1441'-r','-a','ios','--ipa=canary.ipa','--device-id','321','-g',
1442'127.0.6533.74','-b','127.0.6533.78'
1443])
1444 build= bisect_builds.create_archive_build(options)
1445 self.assertIsInstance(build, bisect_builds.IOSReleaseBuild)
1446 build._install_revision('canary.ipa','tempdir')
1447 mock_glob.assert_called_once_with('tempdir/Payload/*/Info.plist')
1448 mock_Popen.assert_has_calls([
1449 call([
1450'xcrun','devicectl','device','install','app','--device','321',
1451'canary.ipa'
1452],
1453 cwd=None,
Kuan Huangabd69f22024-09-13 23:03:48[diff] [blame]1454 shell=False,
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1455 bufsize=-1,
1456 stdout=-1,
1457 stderr=-1),
1458 call([
1459'plutil','-extract','CFBundleIdentifier','raw',
1460'Payload/canary.app/Info.plist'
1461],
1462 cwd=None,
Kuan Huangabd69f22024-09-13 23:03:48[diff] [blame]1463 shell=False,
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1464 bufsize=-1,
1465 stdout=-1,
1466 stderr=-1)
1467],
1468 any_order=True)
1469
1470@patch('subprocess.Popen', spec=subprocess.Popen)
1471def test_launch_revision(self, mock_Popen):
1472 mock_Popen.return_value.communicate.return_value=('','')
1473 mock_Popen.return_value.returncode=0
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1474 options= bisect_builds.ParseCommandLine([
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1475'-r','-a','ios','--ipa=canary.ipa','--device-id','321','-g',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1476'127.0.6533.74','-b','127.0.6533.78','--','args1','args2'
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1477])
1478 build= bisect_builds.create_archive_build(options)
1479 self.assertIsInstance(build, bisect_builds.IOSReleaseBuild)
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1480 build._launch_revision('tempdir','com.google.chrome.ios', options.args)
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1481 mock_Popen.assert_any_call([
1482'xcrun','devicectl','device','process','launch','--device','321',
1483'com.google.chrome.ios','args1','args2'
1484],
1485 cwd=None,
Kuan Huangabd69f22024-09-13 23:03:48[diff] [blame]1486 shell=False,
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1487 bufsize=-1,
1488 stdout=-1,
1489 stderr=-1)
1490
1491@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
1492'The test only valid when NO_MOCK_SERVER')
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1493@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'stdout',''))
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1494def test_run_revision(self, mock_run):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1495 options= bisect_builds.ParseCommandLine([
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1496'-r','-a','ios','--ipa=canary.ipa','--device-id','321','-g',
1497'127.0.6533.74','-b','127.0.6533.78'
1498])
1499 build= bisect_builds.create_archive_build(options)
1500 self.assertIsInstance(build, bisect_builds.IOSReleaseBuild)
1501 job= build.get_download_job('127.0.6533.76')
1502 ipa= job.start().wait_for()
Kuan Huangc2fec792024-09-03 21:57:38[diff] [blame]1503with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1504 build.run_revision(ipa, tempdir, options.args)
Kuan Huang22770072024-08-27 20:06:53[diff] [blame]1505 mock_run.assert_has_calls([
1506 call([
1507'xcrun','devicectl','device','install','app','--device','321',
1508 ANY
1509]),
1510 call(['plutil','-extract','CFBundleIdentifier','raw', ANY]),
1511 call([
1512'xcrun','devicectl','device','process','launch','--device',
1513'321','stdout'
1514])
1515])
1516
1517
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1518classIOSSimulatorReleaseBuildTest(BisectTestCase):
1519
1520@maybe_patch(
1521'bisect-builds.GsutilList',
1522 side_effect=[
1523[
1524'gs://bling-archive/128.0.6534.0/',
1525'gs://bling-archive/128.0.6534.1/',
1526'gs://bling-archive/128.0.6535.0/',
1527'gs://bling-archive/128.0.6535.1/',
1528'gs://bling-archive/128.0.6536.0/',
1529],
1530[
1531'gs://bling-archive/128.0.6534.0/20240612011643/Chromium.tar.gz',
1532'gs://bling-archive/128.0.6536.0/20240613011356/Chromium.tar.gz',
1533]
1534])
Kuan Huang725c93052024-10-10 19:33:10[diff] [blame]1535@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'',''))
1536def test_list_rev(self, mock_run, mock_GsutilList):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1537 options= bisect_builds.ParseCommandLine([
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1538'-r','-a','ios-simulator','--device-id','321','-g','128.0.6534.0',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1539'-b','128.0.6536.0','--no-local-cache'
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1540])
1541 build= bisect_builds.create_archive_build(options)
1542 self.assertIsInstance(build, bisect_builds.IOSSimulatorReleaseBuild)
1543 self.assertEqual(build.get_rev_list(),['128.0.6534.0','128.0.6536.0'])
Kuan Huang725c93052024-10-10 19:33:10[diff] [blame]1544 mock_run.assert_called_once_with(['xcrun','simctl','boot','321'])
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1545 mock_GsutilList.assert_any_call('gs://bling-archive')
1546 mock_GsutilList.assert_any_call(*[
1547'gs://bling-archive/%s/*/Chromium.tar.gz'% xfor xin[
1548'128.0.6534.0','128.0.6534.1','128.0.6535.0','128.0.6535.1',
1549'128.0.6536.0'
1550]
1551],
1552 ignore_fail=True)
1553
1554@patch('bisect-builds.UnzipFilenameToDir')
1555@patch('glob.glob', return_value=['Info.plist'])
1556@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'',''))
1557def test_install_revision(self, mock_run, mock_glob, mock_UnzipFilenameToDir):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1558 options= bisect_builds.ParseCommandLine([
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1559'-r','-a','ios-simulator','--device-id','321','-g','128.0.6534.0',
1560'-b','128.0.6539.0'
1561])
1562 build= bisect_builds.create_archive_build(options)
1563 self.assertIsInstance(build, bisect_builds.IOSSimulatorReleaseBuild)
1564 build._install_revision('Chromium.tar.gz','tempdir')
1565 mock_UnzipFilenameToDir.assert_called_once_with('Chromium.tar.gz',
1566'tempdir')
1567 self.assertEqual(mock_glob.call_count,2)
1568 mock_run.assert_has_calls([
Kuan Huang725c93052024-10-10 19:33:10[diff] [blame]1569 call(['xcrun','simctl','boot','321']),
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1570 call(['xcrun','simctl','install','321', ANY]),
1571 call(['plutil','-extract','CFBundleIdentifier','raw','Info.plist']),
1572])
1573
1574@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'',''))
1575def test_launch_revision(self, mock_run):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1576 options= bisect_builds.ParseCommandLine([
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1577'-r','-a','ios-simulator','--device-id','321','-g','128.0.6534.0',
1578'-b','128.0.6539.0'
1579])
1580 build= bisect_builds.create_archive_build(options)
1581 self.assertIsInstance(build, bisect_builds.IOSSimulatorReleaseBuild)
1582 build._launch_revision('tempdir','com.google.chrome.ios.dev',
1583['args1','args2'])
1584 mock_run.assert_any_call([
1585'xcrun','simctl','launch','321','com.google.chrome.ios.dev',
1586'args1','args2'
1587])
1588
1589@unittest.skipUnless('NO_MOCK_SERVER'in os.environ,
1590'The test only valid when NO_MOCK_SERVER')
1591@patch('bisect-builds.ArchiveBuild._run', return_value=(0,'stdout',''))
1592def test_run_revision(self, mock_run):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1593 options= bisect_builds.ParseCommandLine([
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1594'-r','-a','ios-simulator','--device-id','321','-g','128.0.6534.0',
1595'-b','128.0.6539.0'
1596])
1597 build= bisect_builds.create_archive_build(options)
1598 self.assertIsInstance(build, bisect_builds.IOSSimulatorReleaseBuild)
1599 job= build.get_download_job('128.0.6534.0')
1600 download= job.start().wait_for()
1601with tempfile.TemporaryDirectory(prefix='bisect_tmp')as tempdir:
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1602 build.run_revision(download, tempdir, options.args)
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1603 mock_run.assert_has_calls([
Kuan Huang725c93052024-10-10 19:33:10[diff] [blame]1604 call(['xcrun','simctl','boot','321']),
Kuan Huangb4c8df52024-09-05 17:59:18[diff] [blame]1605 call(['xcrun','simctl','install','321', ANY]),
1606 call(['plutil','-extract','CFBundleIdentifier','raw', ANY]),
1607 call(['xcrun','simctl','launch','321','stdout'])
1608])
1609
1610
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1611classMaybeSwitchBuildTypeTest(BisectTestCase):
1612
1613def test_generate_new_command_without_cache(self):
1614 command_line=[
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1615'-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.88',
1616'--no-local-cache'
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1617]
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1618 options= bisect_builds.ParseCommandLine(command_line)
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1619with patch('sys.argv',['bisect-builds.py',*command_line]):
1620 new_cmd= bisect_builds.MaybeSwitchBuildType(
Kuan Huang6f7f57942024-12-05 19:26:30[diff] [blame]1621 options, bisect_builds.ChromiumVersion('127.0.6533.74'),
1622 bisect_builds.ChromiumVersion('127.0.6533.88'))
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1623 self.assertEqual(new_cmd[1:],[
1624'-o','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.88',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1625'--verify-range','--no-local-cache'
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1626])
1627
1628def test_android_signed_with_args(self):
1629 command_line=[
1630'-r','--archive=android-arm64-high','--good=127.0.6533.74','-b',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1631'127.0.6533.88','--apk=chrome','--signed','--no-local-cache','--',
1632'args1','--args2'
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1633]
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1634 options= bisect_builds.ParseCommandLine(command_line)
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1635with patch('sys.argv',['bisect-builds.py',*command_line]):
1636 new_cmd= bisect_builds.MaybeSwitchBuildType(options,'127.0.6533.74',
1637'127.0.6533.88')
1638 self.assertEqual(new_cmd[1:],[
1639'-o','-a','android-arm64-high','-g','127.0.6533.74','-b',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1640'127.0.6533.88','--verify-range','--apk=chrome','--no-local-cache',
1641'--','args1','--args2'
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1642])
1643
1644def test_no_official_build(self):
1645 command_line=[
1646'-r','-a','ios','--ipa=canary.ipa','--device-id','321','-g',
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1647'127.0.6533.74','-b','127.0.6533.78','--no-local-cache'
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1648]
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1649 options= bisect_builds.ParseCommandLine(command_line)
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1650with patch('sys.argv',['bisect-builds.py',*command_line]):
1651 new_cmd= bisect_builds.MaybeSwitchBuildType(options,'127.0.6533.74',
1652'127.0.6533.88')
1653 self.assertEqual(new_cmd,None)
1654
1655@patch('bisect-builds.ArchiveBuild.get_rev_list', return_value=list(range(3)))
1656def test_generate_suggestion_with_cache(self, mock_get_rev_list):
1657 command_line=[
1658'-r','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.88',
1659'--use-local-cache'
1660]
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1661 options= bisect_builds.ParseCommandLine(command_line)
Kuan Huang95f6df072024-09-12 20:56:42[diff] [blame]1662with patch('sys.argv',['bisect-builds.py',*command_line]):
1663 new_cmd= bisect_builds.MaybeSwitchBuildType(options,'127.0.6533.74',
1664'127.0.6533.88')
1665 self.assertEqual(new_cmd[1:],[
1666'-o','-a','linux64','-g','127.0.6533.74','-b','127.0.6533.88',
1667'--verify-range','--use-local-cache'
1668])
1669 mock_get_rev_list.assert_called()
1670
1671
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1672classMethodTest(BisectTestCase):
1673
Kuan Huang9a1ad2b2024-09-30 23:16:31[diff] [blame]1674@patch('sys.stderr', new_callable=io.StringIO)
1675def test_ParseCommandLine(self, mock_stderr):
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1676 opts= bisect_builds.ParseCommandLine(
1677['-a','linux64','-g','1','args1','args2 3','-b','2'])
1678 self.assertEqual(opts.build_type,'snapshot')
1679 self.assertEqual(opts.args,['args1','args2 3'])
1680
1681 opts= bisect_builds.ParseCommandLine(
1682['-a','linux64','-g','1','args1','args2 3'])
1683 self.assertEqual(opts.args,['args1','args2 3'])
1684
1685 opts= bisect_builds.ParseCommandLine(
1686['-a','linux64','-g','1','--','args1','args2 3','-b','2'])
1687 self.assertEqual(opts.args,['args1','args2 3','-b','2'])
1688
Kuan Huang9a1ad2b2024-09-30 23:16:31[diff] [blame]1689with self.assertRaises(SystemExit):
1690 bisect_builds.ParseCommandLine(['-a','mac64','-o','-g','1'])
1691 self.assertRegexpMatches(
1692 mock_stderr.getvalue(), r'To bisect for mac64, please choose from '
1693 r'release(-r), snapshot(-s)')
1694
Kuan Huangb790d5d2024-11-07 21:53:00[diff] [blame]1695@patch('bisect-builds._DetectArchive', return_value='linux64')
1696def test_ParseCommandLine_DetectArchive(self, mock_detect_archive):
1697 opts= bisect_builds.ParseCommandLine(['-o','-g','1'])
1698 self.assertEqual(opts.archive,'linux64')
1699
Kuan Huang908c55212025-01-06 23:09:01[diff] [blame]1700def test_ParseCommandLine_default_apk(self):
1701 opts= bisect_builds.ParseCommandLine(
1702['-o','-a','android-arm','-g','1'])
1703 self.assertEqual(opts.apk,'chrome')
1704
1705 opts= bisect_builds.ParseCommandLine(['-a','android-arm64','-g','1'])
1706 self.assertEqual(opts.apk,'chromium')
1707
1708def test_ParseCommandLine_default_ipa(self):
1709 opts= bisect_builds.ParseCommandLine(
1710['-r','-a','ios','-g','127.0.6533.74','-b','127.0.6533.88'])
1711 self.assertEqual(opts.ipa,'canary')
1712
1713def test_ParseCommandLine_DetectArchive_with_apk(self):
1714 opts= bisect_builds.ParseCommandLine(['-o','--apk','chrome','-g','1'])
1715 self.assertEqual(opts.archive,'android-arm64')
1716
1717def test_ParseCommandLine_DetectArchive_with_ipa(self):
1718 opts= bisect_builds.ParseCommandLine(
1719['-r','--ipa','stable','-g','127.0.6533.74','-b','127.0.6533.88'])
1720 self.assertEqual(opts.archive,'ios-simulator')
1721
1722@patch('sys.stderr', new_callable=io.StringIO)
1723def test_ParseCommandLine_apk_error(self, mock_stderr):
1724with self.assertRaises(SystemExit):
1725 bisect_builds.ParseCommandLine(
1726['-a','linux64','--apk','chrome','-g','1'])
1727 self.assertIn('--apk is only supported', mock_stderr.getvalue())
1728
1729@patch('sys.stderr', new_callable=io.StringIO)
1730def test_ParseCommandLine_ipa_error(self, mock_stderr):
1731with self.assertRaises(SystemExit):
1732 bisect_builds.ParseCommandLine(
1733['-a','linux64','--ipa','stable','-g','1'])
1734 self.assertIn('--ipa is only supported', mock_stderr.getvalue())
1735
1736@patch('sys.stderr', new_callable=io.StringIO)
1737def test_ParseCommandLine_signed_error(self, mock_stderr):
1738with self.assertRaises(SystemExit):
1739 bisect_builds.ParseCommandLine(['-a','linux64','--signed','-g','1'])
1740 self.assertIn('--signed is only supported', mock_stderr.getvalue())
1741
Trung Nguyend391d052025-06-04 09:35:09[diff] [blame]1742@patch('sys.stderr', new_callable=io.StringIO)
1743def test_ParseCommandLine_webview_incompatibility_error(self, mock_stderr):
1744with self.assertRaises(SystemExit):
1745 _= bisect_builds.ParseCommandLine([
1746'-r','-a','android-arm64-high','-g','127.0.6533.76','-b',
1747'127.0.6533.79','--apk','system_webview'
1748])
1749 self.assertIn(
1750'Bisecting WebView for android-arm64-high, please choose official '
1751'builds (-o)', mock_stderr.getvalue())
1752
1753 opts= bisect_builds.ParseCommandLine([
1754'-o','-a','android-arm64-high','-g','1334017','-b','1335078',
1755'--apk','system_webview'
1756])
1757 self.assertEqual(opts.apk,'system_webview')
1758 self.assertEqual(opts.archive,'android-arm64-high')
1759 self.assertEqual(opts.build_type,'official')
1760
1761
Kuan Huang342fec52024-10-31 18:00:44[diff] [blame]1762@patch('urllib.request.urlopen')
1763@patch('builtins.open')
1764@patch('sys.stdout', new_callable=io.StringIO)
1765def test_update_script(self, mock_stdout, mock_open, mock_urlopen):
1766 mock_urlopen.return_value= io.BytesIO(
1767 base64.b64encode('content'.encode('utf-8')))
1768with self.assertRaises(SystemExit):
1769 bisect_builds.ParseCommandLine(['--update-script'])
1770 mock_urlopen.assert_called_once_with(
1771'https://chromium.googlesource.com/chromium/src/+/HEAD/'
1772'tools/bisect-builds.py?format=TEXT')
1773 mock_open.assert_called_once()
1774 mock_open.return_value.__enter__().write.assert_called_once_with('content')
1775 self.assertEqual(mock_stdout.getvalue(),'Update successful!\n')
1776
Kuan Huangc93ac262024-09-19 18:53:17[diff] [blame]1777@patch("urllib.request.urlopen",
1778 side_effect=[
1779 urllib.request.HTTPError('url',404,'Not Found',None,None),
1780 urllib.request.HTTPError('url',404,'Not Found',None,None),
Kuan Huang05058842024-10-24 21:22:26[diff] [blame]1781 io.BytesIO(b"NOT_A_JSON"),
1782 io.BytesIO(b'{"chromium_main_branch_position": 123}'),
Kuan Huangc93ac262024-09-19 18:53:17[diff] [blame]1783])
1784def test_GetRevisionFromVersion(self, mock_urlopen):
1785 self.assertEqual(123,
1786 bisect_builds.GetRevisionFromVersion('127.0.6533.134'))
1787 mock_urlopen.assert_has_calls([
1788 call('https://chromiumdash.appspot.com/fetch_version'
1789'?version=127.0.6533.134'),
1790 call('https://chromiumdash.appspot.com/fetch_version'
1791'?version=127.0.6533.0'),
1792])
1793
Kuan Huang05058842024-10-24 21:22:26[diff] [blame]1794@maybe_patch("urllib.request.urlopen",
1795 side_effect=[
1796 io.BytesIO(b'{"chromium_main_branch_position": null}'),
1797 io.BytesIO(b'{"message": "DEP\\n"}'),
1798 io.BytesIO(b')]}\'\n{"message": "Cr-Branched-From: '
1799 b'3d60439cfb36485e76a1c5bb7f513d3721b20da1-'
1800 b'refs/heads/master@{#870763}\\n"}'),
1801])
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]1802def test_GetRevisionFromSourceTag(self, mock_urlopen):
Kuan Huang05058842024-10-24 21:22:26[diff] [blame]1803 self.assertEqual(870763,
1804 bisect_builds.GetRevisionFromVersion('91.0.4472.38'))
1805 mock_urlopen.assert_has_calls([
1806 call('https://chromiumdash.appspot.com/fetch_version'
1807'?version=91.0.4472.38'),
1808 call('https://chromium.googlesource.com/chromium/src/'
1809'+/refs/tags/91.0.4472.38?format=JSON'),
1810 call('https://chromium.googlesource.com/chromium/src/'
1811'+/refs/tags/91.0.4472.38^?format=JSON'),
1812])
Kuan Huang008965f92024-10-08 21:53:15[diff] [blame]1813
Kuan Huang94c4a2d12024-11-21 21:46:09[diff] [blame]1814def test_join_args(self):
1815 test_data=['a','b c','C:\\a b\\c','/a b/c','"a"',"'a'"]
1816 quoted_command= bisect_builds.join_args(
1817[sys.executable,'-c','import sys, json; print(json.dumps(sys.argv))']
1818+ test_data)
1819
1820 subproc= subprocess.Popen(
1821 quoted_command, shell=True, stdout=subprocess.PIPE)
1822 stdout, _= subproc.communicate()
1823 dumped_argv= json.loads(stdout.decode('utf-8'))
1824
1825 self.assertListEqual(dumped_argv,['-c']+ test_data)
1826
Kuan Huang37d0daa2024-09-19 18:03:08[diff] [blame]1827
Kuan Huang6f7f57942024-12-05 19:26:30[diff] [blame]1828classChromiumVersionTest(BisectTestCase):
1829def test_cmpare_version_numbers(self):
1830 v127_0_6533_74= bisect_builds.ChromiumVersion('127.0.6533.74')
1831 v127_0_6533_75= bisect_builds.ChromiumVersion('127.0.6533.75')
1832 v127_0_6533_75_with_space= bisect_builds.ChromiumVersion('127.0.6533.75 ')
1833 v127= bisect_builds.ChromiumVersion('127')
1834
1835 self.assertLess(v127_0_6533_74, v127_0_6533_75)
1836 self.assertLessEqual(v127_0_6533_74, v127_0_6533_75)
1837 self.assertGreater(v127_0_6533_75, v127_0_6533_74)
1838 self.assertGreaterEqual(v127_0_6533_75, v127_0_6533_74)
1839 self.assertEqual(v127_0_6533_75, v127_0_6533_75_with_space)
1840 self.assertLess(v127, v127_0_6533_74)
1841
enne@chromium.orgeadd95d2012-11-02 22:42:09[diff] [blame]1842if __name__=='__main__':
1843 unittest.main()

[8]ページ先頭

©2009-2025 Movatter.jp