#!/usr/bin/env python2
#
# 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

from StringIO import StringIO

import copy
import json
import mock
import test_flag
import unittest

import generate_report
import results_report

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.assertItemsEqual(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.assertItemsEqual(original_bench_data.keys(), bench_data.keys())
    for bench_name, original_runs in original_bench_data.iteritems():
      bench_runs = bench_data[bench_name]
      self.assertEquals(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
    # sanely. If it doesn't, testCutResultsInPlace should give an indication as
    # to what, exactly, is broken.
    self.assertEqual(results['foo'][0][0].items(), [('retval', 0)])
    self.assertEqual(results['bar'][0][0].items(), [('retval', 1)])
    self.assertEqual(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.assertItemsEqual(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.assertItemsEqual(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()
