#!/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()
