1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import unittest 6import subprocess 7 8bisect_builds = __import__('bisect-builds') 9 10 11class FakeProcess: 12 called_num_times = 0 13 14 def __init__(self, returncode): 15 self.returncode = returncode 16 FakeProcess.called_num_times += 1 17 18 def communicate(self): 19 return ('', '') 20 21 22class BisectTest(unittest.TestCase): 23 24 patched = [] 25 max_rev = 10000 26 fake_process_return_code = 0 27 28 def monkey_patch(self, obj, name, new): 29 self.patched.append((obj, name, getattr(obj, name))) 30 setattr(obj, name, new) 31 32 def clear_patching(self): 33 for obj, name, old in self.patched: 34 setattr(obj, name, old) 35 self.patched = [] 36 37 def setUp(self): 38 FakeProcess.called_num_times = 0 39 self.fake_process_return_code = 0 40 self.monkey_patch(bisect_builds.DownloadJob, 'Start', lambda *args: None) 41 self.monkey_patch(bisect_builds.DownloadJob, 'Stop', lambda *args: None) 42 self.monkey_patch(bisect_builds.DownloadJob, 'WaitFor', lambda *args: None) 43 self.monkey_patch(bisect_builds, 'UnzipFilenameToDir', lambda *args: None) 44 self.monkey_patch( 45 subprocess, 'Popen', 46 lambda *args, **kwargs: FakeProcess(self.fake_process_return_code)) 47 self.monkey_patch(bisect_builds.PathContext, 'ParseDirectoryIndex', 48 lambda *args: range(self.max_rev)) 49 50 def tearDown(self): 51 self.clear_patching() 52 53 def bisect(self, good_rev, bad_rev, evaluate, num_runs=1): 54 base_url = bisect_builds.CHROMIUM_BASE_URL 55 archive = 'linux' 56 asan = False 57 use_local_cache = False 58 context = bisect_builds.PathContext(base_url, archive, good_rev, bad_rev, 59 asan, use_local_cache) 60 (minrev, maxrev, _) = bisect_builds.Bisect( 61 context=context, 62 evaluate=evaluate, 63 num_runs=num_runs, 64 profile=None, 65 try_args=[]) 66 return (minrev, maxrev) 67 68 def testBisectConsistentAnswer(self): 69 self.assertEqual(self.bisect(1000, 100, lambda *args: 'g'), (100, 101)) 70 self.assertEqual(self.bisect(100, 1000, lambda *args: 'b'), (100, 101)) 71 self.assertEqual(self.bisect(2000, 200, lambda *args: 'b'), (1999, 2000)) 72 self.assertEqual(self.bisect(200, 2000, lambda *args: 'g'), (1999, 2000)) 73 74 def testBisectMultipleRunsEarlyReturn(self): 75 self.fake_process_return_code = 1 76 self.assertEqual(self.bisect(1, 3, lambda *args: 'b', num_runs=10), (1, 2)) 77 self.assertEqual(FakeProcess.called_num_times, 1) 78 79 def testBisectAllRunsWhenAllSucceed(self): 80 self.assertEqual(self.bisect(1, 3, lambda *args: 'b', num_runs=10), (1, 2)) 81 self.assertEqual(FakeProcess.called_num_times, 10) 82 83 84if __name__ == '__main__': 85 unittest.main() 86