# Copyright 2017 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 json
import unittest

from core import perf_data_generator
from core.perf_data_generator import BenchmarkMetadata

import mock


class PerfDataGeneratorTest(unittest.TestCase):
  def setUp(self):
    # Test config can be big, so set maxDiff to None to see the full comparision
    # diff when assertEquals fails.
    self.maxDiff = None

  def testVerifyAllTestsInBenchmarkCsvPassesWithCorrectInput(self):
    tests = {
        'AAAAA1 AUTOGENERATED': {},
        'Android Nexus5 Perf (2)': {
            'scripts': [
                {'name': 'benchmark_name_1'},
                {'name': 'benchmark_name_2'}
            ]
        },
        'Linux Perf': {
            'isolated_scripts': [
                {'name': 'benchmark_name_2.reference'},
                {'name': 'benchmark_name_3'}
            ]
        }
    }
    benchmarks = {
        'benchmark_name_1': BenchmarkMetadata('foo@bar.com'),
        'benchmark_name_2':
            BenchmarkMetadata('darth@deathstar'),
        'benchmark_name_3':
            BenchmarkMetadata('neo@matrix.org')
    }

    # Mock out content of unowned_benchmarks.txt and sharding map
    data = {
      "0": {
        "benchmarks": {
            "benchmark_name_2": {}
        }
      }
    }
    with mock.patch('__builtin__.open',
                    mock.mock_open(read_data=json.dumps(data))):
      perf_data_generator.verify_all_tests_in_benchmark_csv(tests, benchmarks)


  def testVerifyAllTestsInBenchmarkCsvCatchesMismatchedTests(self):
    tests = {
        'Android Nexus5 Perf (2)': {
            'scripts': [
                {'name': 'benchmark_name_1'},
                {'name': 'benchmark_name_2'}
            ]
        }
    }
    benchmarks = {
        'benchmark_name_2': BenchmarkMetadata('baz@foo.com'),
        'benchmark_name_3': BenchmarkMetadata('darth@vader.com'),
    }

    with self.assertRaises(AssertionError) as context:
      perf_data_generator.verify_all_tests_in_benchmark_csv(tests, benchmarks)
    exception = context.exception.message
    self.assertTrue('Add benchmark_name_1' in exception)
    self.assertTrue('Remove benchmark_name_3' in exception)


  def testVerifyAllTestsInBenchmarkCsvFindsFakeTest(self):
    tests = {'Random fake test': {}}
    benchmarks = {
        'benchmark_name_1': BenchmarkMetadata('deathstar@empire.com')
    }

    with self.assertRaises(AssertionError) as context:
      perf_data_generator.verify_all_tests_in_benchmark_csv(tests, benchmarks)
    self.assertTrue('Unknown test' in context.exception.message)


  def testGenerateCPlusPlusTestSuite(self):
    swarming_dimensions = [
        {'os': 'SkyNet', 'pool': 'T-RIP'}
    ]
    test_config = {
        'platform': 'win',
        'dimension': swarming_dimensions,
    }
    test = {
        'isolate': 'angle_perftest',
        'telemetry': False,
        'num_shards': 1
    }
    returned_test = perf_data_generator.generate_performance_test(
        test_config, test)

    expected_generated_test = {
        'override_compile_targets': ['angle_perftest'],
        'isolate_name': 'angle_perftest',
        'args': ['--gtest-benchmark-name', 'angle_perftest',
                 '--non-telemetry=true', '--migrated-test=true'],
        'trigger_script': {
          'args': [
            '--multiple-dimension-script-verbose',
            'True'
          ],
          'script': '//testing/trigger_scripts/perf_device_trigger.py'
        },
        'merge': {
          'args': [
            '--service-account-file',
            'C:\\creds\\service_accounts\\service-account-chromium-perf-histograms.json'
          ],
          'script': '//tools/perf/process_perf_results.py'
        },
        'swarming': {
          'ignore_task_failure': False,
          'can_use_on_swarming_builders': True,
          'expiration': 7200,
          'io_timeout': 1800,
          'hard_timeout': 25200,
          'upload_test_results': True,
          'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]],
          'shards': 1
        },
        'name': 'angle_perftest'
      }
    self.assertEquals(returned_test, expected_generated_test)

  def testGeneratePerformanceTestSuiteWebview(self):
    swarming_dimensions = [
        {'os': 'SkyNet', 'pool': 'T-RIP'}
    ]
    test_config = {
        'platform': 'android-webview',
        'dimension': swarming_dimensions,
    }
    test = {
        'isolate': 'performance_test_suite',
        'extra_args': [
            '--run-ref-build',
            '--test-shard-map-filename=shard_map.json',
          ],
        'num_shards': 26
    }
    returned_test = perf_data_generator.generate_performance_test(
        test_config, test)

    expected_generated_test = {
        'override_compile_targets': ['performance_test_suite'],
        'isolate_name': 'performance_test_suite',
        'args': ['-v', '--browser=android-webview', '--upload-results',
                 '--webview-embedder-apk=../../out/Release/apks/SystemWebViewShell.apk',
                 '--run-ref-build',
                 '--test-shard-map-filename=shard_map.json'],
        'trigger_script': {
          'args': [
            '--multiple-dimension-script-verbose',
            'True'
          ],
          'script': '//testing/trigger_scripts/perf_device_trigger.py'
        },
        'merge': {
          'args': [
            '--service-account-file',
            '/creds/service_accounts/service-account-chromium-perf-histograms.json'
          ],
          'script': '//tools/perf/process_perf_results.py'
        },
        'swarming': {
          'ignore_task_failure': False,
          'can_use_on_swarming_builders': True,
          'expiration': 7200,
          'io_timeout': 1800,
          'hard_timeout': 25200,
          'upload_test_results': True,
          'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]],
          'shards': 26
        },
        'name': 'performance_test_suite'
      }
    self.assertEquals(returned_test, expected_generated_test)

  def testGeneratePerformanceTestSuite(self):
    swarming_dimensions = [
        {'os': 'SkyNet', 'pool': 'T-RIP'}
    ]
    test_config = {
        'platform': 'android',
        'dimension': swarming_dimensions,
    }
    test = {
        'isolate': 'performance_test_suite',
        'extra_args': [
            '--run-ref-build',
            '--test-shard-map-filename=shard_map.json',
          ],
        'num_shards': 26
    }
    returned_test = perf_data_generator.generate_performance_test(
        test_config, test)

    expected_generated_test = {
        'override_compile_targets': ['performance_test_suite'],
        'isolate_name': 'performance_test_suite',
        'args': ['-v', '--browser=android-chromium', '--upload-results',
                 '--run-ref-build',
                 '--test-shard-map-filename=shard_map.json'],
        'trigger_script': {
          'args': [
            '--multiple-dimension-script-verbose',
            'True'
          ],
          'script': '//testing/trigger_scripts/perf_device_trigger.py'
        },
        'merge': {
          'args': [
            '--service-account-file',
            '/creds/service_accounts/service-account-chromium-perf-histograms.json'
          ],
          'script': '//tools/perf/process_perf_results.py'
        },
        'swarming': {
          'ignore_task_failure': False,
          'can_use_on_swarming_builders': True,
          'expiration': 7200,
          'io_timeout': 1800,
          'hard_timeout': 25200,
          'upload_test_results': True,
          'dimension_sets': [[{'os': 'SkyNet', 'pool': 'T-RIP'}]],
          'shards': 26
        },
        'name': 'performance_test_suite'
      }
    self.assertEquals(returned_test, expected_generated_test)

