benchmark_run_unittest.py revision a93683485612c985c661eb4ebbb02a7ae1c4a623
1#!/usr/bin/python
2
3# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""Testing of benchmark_run."""
7
8import mock
9import unittest
10import inspect
11
12from cros_utils import logger
13
14import benchmark_run
15
16from suite_runner import MockSuiteRunner
17from suite_runner import SuiteRunner
18from label import MockLabel
19from benchmark import Benchmark
20from machine_manager import MockMachineManager
21from machine_manager import MachineManager
22from machine_manager import MockCrosMachine
23from results_cache import MockResultsCache
24from results_cache import CacheConditions
25from results_cache import Result
26from results_cache import ResultsCache
27
28
29class BenchmarkRunTest(unittest.TestCase):
30  """Unit tests for the BenchmarkRun class and all of its methods.
31  """
32
33  def setUp(self):
34    self.test_benchmark = Benchmark('page_cycler.netsim.top_10',   # name
35                                    'page_cycler.netsim.top_10',   # test_name
36                                    '',                            # test_args
37                                    1,                             # iterations
38                                    False,                      # rm_chroot_tmp
39                                    '',                            # perf_args
40                                    suite='telemetry_Crosperf')    # suite
41
42    self.test_label = MockLabel('test1',
43                                'image1',
44                                '/tmp/test_benchmark_run',
45                                'x86-alex',
46                                'chromeos2-row1-rack4-host9.cros',
47                                image_args='',
48                                cache_dir='',
49                                cache_only=False,
50                                log_level='average',
51                                compiler='gcc')
52
53    self.test_cache_conditions = [CacheConditions.CACHE_FILE_EXISTS,
54                                  CacheConditions.CHECKSUMS_MATCH]
55
56    self.mock_logger = logger.GetLogger(log_dir='', mock=True)
57
58    self.mock_machine_manager = mock.Mock(spec=MachineManager)
59
60  def testDryRun(self):
61    my_label = MockLabel('test1',
62                         'image1',
63                         '/tmp/test_benchmark_run',
64                         'x86-alex',
65                         'chromeos2-row1-rack4-host9.cros',
66                         image_args='',
67                         cache_dir='',
68                         cache_only=False,
69                         log_level='average',
70                         compiler='gcc')
71
72    logging_level = 'average'
73    m = MockMachineManager('/tmp/chromeos_root', 0, logging_level, '')
74    m.AddMachine('chromeos2-row1-rack4-host9.cros')
75    bench = Benchmark('page_cycler.netsim.top_10',    # name
76                      'page_cycler.netsim.top_10',    # test_name
77                      '',             # test_args
78                      1,              # iterations
79                      False,          # rm_chroot_tmp
80                      '',             # perf_args
81                      suite='telemetry_Crosperf')     # suite
82    b = benchmark_run.MockBenchmarkRun('test run', bench, my_label, 1, [], m,
83                                       logger.GetLogger(), logging_level, '')
84    b.cache = MockResultsCache()
85    b.suite_runner = MockSuiteRunner()
86    b.start()
87
88    # Make sure the arguments to BenchmarkRun.__init__ have not changed
89    # since the last time this test was updated:
90    args_list = ['self', 'name', 'benchmark', 'label', 'iteration',
91                 'cache_conditions', 'machine_manager', 'logger_to_use',
92                 'log_level', 'share_cache']
93    arg_spec = inspect.getargspec(benchmark_run.BenchmarkRun.__init__)
94    self.assertEqual(len(arg_spec.args), len(args_list))
95    self.assertEqual(arg_spec.args, args_list)
96
97  def test_init(self):
98    # Nothing really worth testing here; just field assignments.
99    pass
100
101  def test_read_cache(self):
102    # Nothing really worth testing here, either.
103    pass
104
105  def test_run(self):
106    br = benchmark_run.BenchmarkRun(
107        'test_run', self.test_benchmark, self.test_label, 1,
108        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
109        'average', '')
110
111    def MockLogOutput(msg, print_to_console=False):
112      'Helper function for test_run.'
113      self.log_output.append(msg)
114
115    def MockLogError(msg, print_to_console=False):
116      'Helper function for test_run.'
117      self.log_error.append(msg)
118
119    def MockRecordStatus(msg):
120      'Helper function for test_run.'
121      self.status.append(msg)
122
123    def FakeReadCache():
124      'Helper function for test_run.'
125      br.cache = mock.Mock(spec=ResultsCache)
126      self.called_ReadCache = True
127      return 0
128
129    def FakeReadCacheSucceed():
130      'Helper function for test_run.'
131      br.cache = mock.Mock(spec=ResultsCache)
132      br.result = mock.Mock(spec=Result)
133      br.result.out = 'result.out stuff'
134      br.result.err = 'result.err stuff'
135      br.result.retval = 0
136      self.called_ReadCache = True
137      return 0
138
139    def FakeReadCacheException():
140      'Helper function for test_run.'
141      raise Exception('This is an exception test; it is supposed to happen')
142
143    def FakeAcquireMachine():
144      'Helper function for test_run.'
145      mock_machine = MockCrosMachine('chromeos1-row3-rack5-host7.cros',
146                                     'chromeos', 'average')
147      return mock_machine
148
149    def FakeRunTest(_machine):
150      'Helper function for test_run.'
151      mock_result = mock.Mock(spec=Result)
152      mock_result.retval = 0
153      return mock_result
154
155    def FakeRunTestFail(_machine):
156      'Helper function for test_run.'
157      mock_result = mock.Mock(spec=Result)
158      mock_result.retval = 1
159      return mock_result
160
161    def ResetTestValues():
162      'Helper function for test_run.'
163      self.log_output = []
164      self.log_error = []
165      self.status = []
166      br.result = None
167      self.called_ReadCache = False
168
169    # Assign all the fake functions to the appropriate objects.
170    br._logger.LogOutput = MockLogOutput
171    br._logger.LogError = MockLogError
172    br.timeline.Record = MockRecordStatus
173    br.ReadCache = FakeReadCache
174    br.RunTest = FakeRunTest
175    br.AcquireMachine = FakeAcquireMachine
176
177    # First test:  No cache hit, all goes well.
178    ResetTestValues()
179    br.run()
180    self.assertTrue(self.called_ReadCache)
181    self.assertEqual(self.log_output,
182                     ['test_run: No cache hit.',
183                      'Releasing machine: chromeos1-row3-rack5-host7.cros',
184                      'Released machine: chromeos1-row3-rack5-host7.cros'])
185    self.assertEqual(len(self.log_error), 0)
186    self.assertEqual(self.status, ['WAITING', 'SUCCEEDED'])
187
188    # Second test: No cached result found; test run was "terminated" for some
189    # reason.
190    ResetTestValues()
191    br.terminated = True
192    br.run()
193    self.assertTrue(self.called_ReadCache)
194    self.assertEqual(self.log_output,
195                     ['test_run: No cache hit.',
196                      'Releasing machine: chromeos1-row3-rack5-host7.cros',
197                      'Released machine: chromeos1-row3-rack5-host7.cros'])
198    self.assertEqual(len(self.log_error), 0)
199    self.assertEqual(self.status, ['WAITING'])
200
201    # Third test.  No cached result found; RunTest failed for some reason.
202    ResetTestValues()
203    br.terminated = False
204    br.RunTest = FakeRunTestFail
205    br.run()
206    self.assertTrue(self.called_ReadCache)
207    self.assertEqual(self.log_output,
208                     ['test_run: No cache hit.',
209                      'Releasing machine: chromeos1-row3-rack5-host7.cros',
210                      'Released machine: chromeos1-row3-rack5-host7.cros'])
211    self.assertEqual(len(self.log_error), 0)
212    self.assertEqual(self.status, ['WAITING', 'FAILED'])
213
214    # Fourth test: ReadCache found a cached result.
215    ResetTestValues()
216    br.RunTest = FakeRunTest
217    br.ReadCache = FakeReadCacheSucceed
218    br.run()
219    self.assertTrue(self.called_ReadCache)
220    self.assertEqual(self.log_output,
221                     ['test_run: Cache hit.', 'result.out stuff',
222                      'Releasing machine: chromeos1-row3-rack5-host7.cros',
223                      'Released machine: chromeos1-row3-rack5-host7.cros'])
224    self.assertEqual(self.log_error, ['result.err stuff'])
225    self.assertEqual(self.status, ['SUCCEEDED'])
226
227    # Fifth test: ReadCache generates an exception; does the try/finally block
228    # work?
229    ResetTestValues()
230    br.ReadCache = FakeReadCacheException
231    br.machine = FakeAcquireMachine()
232    br.run()
233    self.assertEqual(self.log_error, [
234        "Benchmark run: 'test_run' failed: This is an exception test; it is "
235                     "supposed to happen"
236    ])
237    self.assertEqual(self.status, ['FAILED'])
238
239  def test_terminate_pass(self):
240    br = benchmark_run.BenchmarkRun(
241        'test_run', self.test_benchmark, self.test_label, 1,
242        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
243        'average', '')
244
245    def GetLastEventPassed():
246      'Helper function for test_terminate_pass'
247      return benchmark_run.STATUS_SUCCEEDED
248
249    def RecordStub(status):
250      'Helper function for test_terminate_pass'
251      self.status = status
252
253    self.status = benchmark_run.STATUS_SUCCEEDED
254    self.assertFalse(br.terminated)
255    self.assertFalse(br.suite_runner._ct.IsTerminated())
256
257    br.timeline.GetLastEvent = GetLastEventPassed
258    br.timeline.Record = RecordStub
259
260    br.Terminate()
261
262    self.assertTrue(br.terminated)
263    self.assertTrue(br.suite_runner._ct.IsTerminated())
264    self.assertEqual(self.status, benchmark_run.STATUS_FAILED)
265
266  def test_terminate_fail(self):
267    br = benchmark_run.BenchmarkRun(
268        'test_run', self.test_benchmark, self.test_label, 1,
269        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
270        'average', '')
271
272    def GetLastEventFailed():
273      'Helper function for test_terminate_fail'
274      return benchmark_run.STATUS_FAILED
275
276    def RecordStub(status):
277      'Helper function for test_terminate_fail'
278      self.status = status
279
280    self.status = benchmark_run.STATUS_SUCCEEDED
281    self.assertFalse(br.terminated)
282    self.assertFalse(br.suite_runner._ct.IsTerminated())
283
284    br.timeline.GetLastEvent = GetLastEventFailed
285    br.timeline.Record = RecordStub
286
287    br.Terminate()
288
289    self.assertTrue(br.terminated)
290    self.assertTrue(br.suite_runner._ct.IsTerminated())
291    self.assertEqual(self.status, benchmark_run.STATUS_SUCCEEDED)
292
293  def test_acquire_machine(self):
294    br = benchmark_run.BenchmarkRun(
295        'test_run', self.test_benchmark, self.test_label, 1,
296        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
297        'average', '')
298
299    br.terminated = True
300    self.assertRaises(Exception, br.AcquireMachine)
301
302    br.terminated = False
303    mock_machine = MockCrosMachine('chromeos1-row3-rack5-host7.cros',
304                                   'chromeos', 'average')
305    self.mock_machine_manager.AcquireMachine.return_value = mock_machine
306
307    machine = br.AcquireMachine()
308    self.assertEqual(machine.name, 'chromeos1-row3-rack5-host7.cros')
309
310  def test_get_extra_autotest_args(self):
311    br = benchmark_run.BenchmarkRun(
312        'test_run', self.test_benchmark, self.test_label, 1,
313        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
314        'average', '')
315
316    def MockLogError(err_msg):
317      'Helper function for test_get_extra_autotest_args'
318      self.err_msg = err_msg
319
320    self.mock_logger.LogError = MockLogError
321
322    result = br._GetExtraAutotestArgs()
323    self.assertEqual(result, '')
324
325    self.test_benchmark.perf_args = 'record -e cycles'
326    result = br._GetExtraAutotestArgs()
327    self.assertEqual(
328        result,
329        "--profiler=custom_perf --profiler_args='perf_options=\"record -a -e "
330        "cycles\"'")
331
332    self.test_benchmark.suite = 'telemetry'
333    result = br._GetExtraAutotestArgs()
334    self.assertEqual(result, '')
335    self.assertEqual(self.err_msg, 'Telemetry does not support profiler.')
336
337    self.test_benchmark.perf_args = 'record -e cycles'
338    self.test_benchmark.suite = 'test_that'
339    result = br._GetExtraAutotestArgs()
340    self.assertEqual(result, '')
341    self.assertEqual(self.err_msg, 'test_that does not support profiler.')
342
343    self.test_benchmark.perf_args = 'junk args'
344    self.test_benchmark.suite = 'telemetry_Crosperf'
345    self.assertRaises(Exception, br._GetExtraAutotestArgs)
346
347  @mock.patch.object(SuiteRunner, 'Run')
348  @mock.patch.object(Result, 'CreateFromRun')
349  def test_run_test(self, mock_result, mock_runner):
350    br = benchmark_run.BenchmarkRun(
351        'test_run', self.test_benchmark, self.test_label, 1,
352        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
353        'average', '')
354
355    self.status = []
356
357    def MockRecord(status):
358      self.status.append(status)
359
360    br.timeline.Record = MockRecord
361    mock_machine = MockCrosMachine('chromeos1-row3-rack5-host7.cros',
362                                   'chromeos', 'average')
363    mock_runner.return_value = [0, "{'Score':100}", '']
364
365    br.RunTest(mock_machine)
366
367    self.assertTrue(br.run_completed)
368    self.assertEqual(self.status, [benchmark_run.STATUS_IMAGING,
369                                   benchmark_run.STATUS_RUNNING])
370
371    self.assertEqual(br.machine_manager.ImageMachine.call_count, 1)
372    br.machine_manager.ImageMachine.assert_called_with(mock_machine,
373                                                       self.test_label)
374    self.assertEqual(mock_runner.call_count, 1)
375    mock_runner.assert_called_with(mock_machine.name, br.label, br.benchmark,
376                                   '', br.profiler_args)
377
378    self.assertEqual(mock_result.call_count, 1)
379    mock_result.assert_called_with(
380        self.mock_logger, 'average', self.test_label, None, "{'Score':100}", '',
381        0, False, 'page_cycler.netsim.top_10', 'telemetry_Crosperf')
382
383  def test_set_cache_conditions(self):
384    br = benchmark_run.BenchmarkRun(
385        'test_run', self.test_benchmark, self.test_label, 1,
386        self.test_cache_conditions, self.mock_machine_manager, self.mock_logger,
387        'average', '')
388
389    phony_cache_conditions = [123, 456, True, False]
390
391    self.assertEqual(br.cache_conditions, self.test_cache_conditions)
392
393    br.SetCacheConditions(phony_cache_conditions)
394    self.assertEqual(br.cache_conditions, phony_cache_conditions)
395
396    br.SetCacheConditions(self.test_cache_conditions)
397    self.assertEqual(br.cache_conditions, self.test_cache_conditions)
398
399
400if __name__ == '__main__':
401  unittest.main()
402