179 lines
5.8 KiB
Python
Executable File
179 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
# Copyright 2016 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Test for generate_report.py."""
|
|
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
import copy
|
|
import json
|
|
import unittest
|
|
import unittest.mock as mock
|
|
|
|
import generate_report
|
|
import results_report
|
|
import test_flag
|
|
|
|
# pylint: disable=deprecated-module
|
|
try:
|
|
from StringIO import StringIO # for Python 2
|
|
except ImportError:
|
|
from io import StringIO # for Python 3
|
|
|
|
|
|
class _ContextualStringIO(StringIO):
|
|
"""StringIO that can be used in `with` statements."""
|
|
|
|
def __init__(self, *args):
|
|
StringIO.__init__(self, *args)
|
|
|
|
def __enter__(self):
|
|
return self
|
|
|
|
def __exit__(self, _type, _value, _traceback):
|
|
pass
|
|
|
|
|
|
class GenerateReportTests(unittest.TestCase):
|
|
"""Tests for generate_report.py."""
|
|
|
|
def testCountBenchmarks(self):
|
|
runs = {
|
|
'foo': [[{}, {}, {}], [{}, {}, {}, {}]],
|
|
'bar': [],
|
|
'baz': [[], [{}], [{}, {}, {}]]
|
|
}
|
|
results = generate_report.CountBenchmarks(runs)
|
|
expected_results = [('foo', 4), ('bar', 0), ('baz', 3)]
|
|
self.assertCountEqual(expected_results, results)
|
|
|
|
def testCutResultsInPlace(self):
|
|
bench_data = {
|
|
'foo': [[{
|
|
'a': 1,
|
|
'b': 2,
|
|
'c': 3
|
|
}, {
|
|
'a': 3,
|
|
'b': 2.5,
|
|
'c': 1
|
|
}]],
|
|
'bar': [[{
|
|
'd': 11,
|
|
'e': 12,
|
|
'f': 13
|
|
}]],
|
|
'baz': [[{
|
|
'g': 12,
|
|
'h': 13
|
|
}]],
|
|
'qux': [[{
|
|
'i': 11
|
|
}]],
|
|
}
|
|
original_bench_data = copy.deepcopy(bench_data)
|
|
|
|
max_keys = 2
|
|
results = generate_report.CutResultsInPlace(
|
|
bench_data, max_keys=max_keys, complain_on_update=False)
|
|
# Cuts should be in-place.
|
|
self.assertIs(results, bench_data)
|
|
self.assertCountEqual(
|
|
list(original_bench_data.keys()), list(bench_data.keys()))
|
|
for bench_name, original_runs in original_bench_data.items():
|
|
bench_runs = bench_data[bench_name]
|
|
self.assertEqual(len(original_runs), len(bench_runs))
|
|
# Order of these sub-lists shouldn't have changed.
|
|
for original_list, new_list in zip(original_runs, bench_runs):
|
|
self.assertEqual(len(original_list), len(new_list))
|
|
for original_keyvals, sub_keyvals in zip(original_list, new_list):
|
|
# sub_keyvals must be a subset of original_keyvals
|
|
self.assertDictContainsSubset(sub_keyvals, original_keyvals)
|
|
|
|
def testCutResultsInPlaceLeavesRetval(self):
|
|
bench_data = {
|
|
'foo': [[{
|
|
'retval': 0,
|
|
'a': 1
|
|
}]],
|
|
'bar': [[{
|
|
'retval': 1
|
|
}]],
|
|
'baz': [[{
|
|
'RETVAL': 1
|
|
}]],
|
|
}
|
|
results = generate_report.CutResultsInPlace(
|
|
bench_data, max_keys=0, complain_on_update=False)
|
|
# Just reach into results assuming we know it otherwise outputs things in
|
|
# the expected way. If it doesn't, testCutResultsInPlace should give an
|
|
# indication as to what, exactly, is broken.
|
|
self.assertEqual(list(results['foo'][0][0].items()), [('retval', 0)])
|
|
self.assertEqual(list(results['bar'][0][0].items()), [('retval', 1)])
|
|
self.assertEqual(list(results['baz'][0][0].items()), [])
|
|
|
|
def _RunMainWithInput(self, args, input_obj):
|
|
assert '-i' not in args
|
|
args += ['-i', '-']
|
|
input_buf = _ContextualStringIO(json.dumps(input_obj))
|
|
with mock.patch('generate_report.PickInputFile', return_value=input_buf) \
|
|
as patched_pick:
|
|
result = generate_report.Main(args)
|
|
patched_pick.assert_called_once_with('-')
|
|
return result
|
|
|
|
@mock.patch('generate_report.RunActions')
|
|
def testMain(self, mock_run_actions):
|
|
# Email is left out because it's a bit more difficult to test, and it'll be
|
|
# mildly obvious if it's failing.
|
|
args = ['--json', '--html', '--text']
|
|
return_code = self._RunMainWithInput(args, {'platforms': [], 'data': {}})
|
|
self.assertEqual(0, return_code)
|
|
self.assertEqual(mock_run_actions.call_count, 1)
|
|
ctors = [ctor for ctor, _ in mock_run_actions.call_args[0][0]]
|
|
self.assertEqual(ctors, [
|
|
results_report.JSONResultsReport,
|
|
results_report.TextResultsReport,
|
|
results_report.HTMLResultsReport,
|
|
])
|
|
|
|
@mock.patch('generate_report.RunActions')
|
|
def testMainSelectsHTMLIfNoReportsGiven(self, mock_run_actions):
|
|
args = []
|
|
return_code = self._RunMainWithInput(args, {'platforms': [], 'data': {}})
|
|
self.assertEqual(0, return_code)
|
|
self.assertEqual(mock_run_actions.call_count, 1)
|
|
ctors = [ctor for ctor, _ in mock_run_actions.call_args[0][0]]
|
|
self.assertEqual(ctors, [results_report.HTMLResultsReport])
|
|
|
|
# We only mock print_exc so we don't have exception info printed to stdout.
|
|
@mock.patch('generate_report.WriteFile', side_effect=ValueError('Oh noo'))
|
|
@mock.patch('traceback.print_exc')
|
|
def testRunActionsRunsAllActionsRegardlessOfExceptions(
|
|
self, mock_print_exc, mock_write_file):
|
|
actions = [(None, 'json'), (None, 'html'), (None, 'text'), (None, 'email')]
|
|
output_prefix = '-'
|
|
ok = generate_report.RunActions(
|
|
actions, {}, output_prefix, overwrite=False, verbose=False)
|
|
self.assertFalse(ok)
|
|
self.assertEqual(mock_write_file.call_count, len(actions))
|
|
self.assertEqual(mock_print_exc.call_count, len(actions))
|
|
|
|
@mock.patch('generate_report.WriteFile')
|
|
def testRunActionsReturnsTrueIfAllActionsSucceed(self, mock_write_file):
|
|
actions = [(None, 'json'), (None, 'html'), (None, 'text')]
|
|
output_prefix = '-'
|
|
ok = generate_report.RunActions(
|
|
actions, {}, output_prefix, overwrite=False, verbose=False)
|
|
self.assertEqual(mock_write_file.call_count, len(actions))
|
|
self.assertTrue(ok)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
test_flag.SetTestMode(True)
|
|
unittest.main()
|