# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import unittest

from mapreduce import test_support
import mock

from google.appengine.ext import testbed

from dashboard import bench_find_anomalies
from dashboard import find_change_points_exp
from dashboard import layered_cache
from dashboard import testing_common
from dashboard import utils
from dashboard.models import anomaly
from dashboard.models import anomaly_config
from dashboard.models import graph_data
from dashboard.models import sheriff

_SAMPLE_SERIES = [
    (1, 50.0), (2, 50.0), (3, 50.0),
    (4, 60.0), (5, 60.0), (6, 60.0),
    (7, 50.0), (8, 50.0), (9, 50.0),
    (10, 50.0), (11, 50.0), (12, 50.0)]

_LARGE_SAMPLE_SERIES = [
    (1, 50.0), (2, 50.0), (3, 50.0), (4, 60.0), (5, 60.0), (6, 60.0),
    (7, 80.0), (8, 80.0), (9, 80.0), (10, 80.0), (11, 80.0), (12, 80.0),
    (13, 90.0), (14, 90.0), (15, 90.0), (16, 50.0), (17, 50.0), (18, 50.0)]


class BenchFindChangePointsTest(testing_common.TestCase):

  def setUp(self):
    super(BenchFindChangePointsTest, self).setUp()
    self.sheriff = sheriff.Sheriff(
        email='a@google.com', id=bench_find_anomalies._TEST_DATA_SHERIFF).put()

  def _AddTestData(self, test_name, rows,
                   improvement_direction=anomaly.UNKNOWN, config=None):
    testing_common.AddTests(
        ['ChromiumGPU'],
        ['linux-release'], {
            'scrolling_benchmark': {
                test_name: {},
            },
        })
    test = utils.TestKey(
        'ChromiumGPU/linux-release/scrolling_benchmark/' + test_name).get()
    test.improvement_direction = improvement_direction
    test_container_key = utils.GetTestContainerKey(test.key)

    sheriff_entity = self.sheriff.get()
    if sheriff_entity.patterns:
      sheriff_entity.patterns.append(test.test_path)
    else:
      sheriff_entity.patterns = [test.test_path]
    sheriff_entity.put()

    for row in rows:
      graph_data.Row(id=row[0], value=row[1], parent=test_container_key).put()

    # Add test config.
    if not config:
      config = {
          'max_window_size': 50,
          'multiple_of_std_dev': 3.5,
          'min_relative_change': 0.1,
          'min_absolute_change': 1.0,
          'min_segment_size': 3,
      }
    anomaly_config.AnomalyConfig(
        id='config_' + test_name, config=config,
        patterns=[test.test_path]).put()

    test.put()
    return test

  def _AddAnomalyForTest(self, end_revision, bug_id, test_key):
    anomaly_key = anomaly.Anomaly(
        start_revision=end_revision - 1,
        end_revision=end_revision,
        test=test_key,
        median_before_anomaly=50,
        segment_size_after=3,
        window_end_revision=6,
        std_dev_before_anomaly=10,
        bug_id=bug_id,
        sheriff=self.sheriff).put()
    return anomaly_key

  @mock.patch.object(bench_find_anomalies, '_AddReportToLog')
  def testBenchFindChangePoints_Basic(self, add_report_to_log_mock):
    test = self._AddTestData('test', _SAMPLE_SERIES, anomaly.DOWN)

    # Add untriaged anomalies.
    self._AddAnomalyForTest(7, None, test.key)

    # Add confirmed anomalies.
    self._AddAnomalyForTest(4, 123, test.key)

    # Add invalid anomalies.
    self._AddAnomalyForTest(10, -1, test.key)

    bench_find_anomalies.SetupBaseDataForBench()

    self.ExecuteDeferredTasks(bench_find_anomalies._TASK_QUEUE_NAME)

    test_benches = bench_find_anomalies.TestBench.query().fetch()
    self.assertEqual(1, len(test_benches))

    self.assertEqual(_SAMPLE_SERIES, test_benches[0].data_series)
    self.assertEqual([[1, 2, 3, 4, 5, 6, 7, 8]],
                     test_benches[0].base_anomaly_revs)
    self.assertEqual([[6, 7, 8, 9, 10, 11, 12]],
                     test_benches[0].invalid_anomaly_revs)
    self.assertEqual([[1, 2, 3, 4, 5, 6, 7, 8]],
                     test_benches[0].confirmed_anomaly_revs)

    bench_name = 'find_change_points_default'
    bench_description = 'A description.'
    bench_find_anomalies.BenchFindChangePoints(bench_name, bench_description)

    # Layered cache set.
    bench_key = '%s.%s' % (bench_name, bench_description)
    self.assertEqual({bench_key: True}, layered_cache.Get(
        bench_find_anomalies._FIND_ANOMALIES_BENCH_CACHE_KEY))

    taskq = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
    test_support.execute_until_empty(taskq,
                                     bench_find_anomalies._TASK_QUEUE_NAME)

    expected_result_dict = {
        'bench_name': bench_name,
        'description': bench_description,
        'invalid_alerts': '0/1',
        'confirmed_alerts': '1/1',
        'new_alerts': 0,
        'total_alerts': '1/1',
        'unconfirmed_alert_links': '',
        'extra_alert_links': '',
    }
    add_report_to_log_mock.assert_called_once_with(expected_result_dict)

  def testBenchFindChangePoints_UniqueBenchRunsOnce(self):
    test = self._AddTestData('test', _SAMPLE_SERIES, anomaly.DOWN)
    self._AddAnomalyForTest(4, 123, test.key)

    bench_find_anomalies.SetupBaseDataForBench()

    self.ExecuteDeferredTasks(bench_find_anomalies._TASK_QUEUE_NAME)

    bench_name = 'a_bench_name1'
    bench_description = 'Test find_change_points v1'
    bench_find_anomalies._EXPERIMENTAL_FUNCTIONS = {
        bench_name: find_change_points_exp.RunFindChangePoints
    }

    bench_find_anomalies.BenchFindChangePoints(bench_name, bench_description)

    # A task should be added.
    taskq = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME)
    tasks = taskq.GetTasks(bench_find_anomalies._TASK_QUEUE_NAME)
    self.assertEqual(1, len(tasks))

    with self.assertRaises(ValueError):
      bench_find_anomalies.BenchFindChangePoints(bench_name, bench_description)


if __name__ == '__main__':
  unittest.main()
