# Copyright 2014 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.

"""Common steps for recipes that sync/build Cronet sources."""

import sys

from recipe_engine.types import freeze
from recipe_engine import recipe_api

class CronetApi(recipe_api.RecipeApi):
  def __init__(self, **kwargs):
    super(CronetApi, self).__init__(**kwargs)
    self._repo_path = None

  INSTRUMENTATION_TESTS = freeze([
    {
      'target': 'cronet_sample_test_apk',
    },
    {
      'target': 'cronet_smoketests_missing_native_library_instrumentation_apk',
    },
    {
      'target': 'cronet_smoketests_platform_only_instrumentation_apk',
    },
    {
      'target': 'cronet_test_instrumentation_apk',
    },
  ])

  UNIT_TESTS = freeze([
    'cronet_unittests_android',
    'net_unittests',
  ])

  # TODO(jbudorick): Remove this once we're no longer building
  # M65 or below.
  UNIT_TESTS_M65_AND_BELOW = freeze ([
    'cronet_unittests',
    'net_unittests',
  ])

  DASHBOARD_UPLOAD_URL = 'https://chromeperf.appspot.com'

  def init_and_sync(self, recipe_config, kwargs,
                    chromium_apply_config=None):
    default_kwargs = {
      'REPO_URL': 'https://chromium.googlesource.com/chromium/src',
      'INTERNAL': False,
      'REPO_NAME': 'src',
      'BUILD_CONFIG': 'Debug'
    }
    droid = self.m.chromium_android
    droid.configure_from_properties(
        recipe_config,
        **dict(default_kwargs.items() + kwargs.items()))
    droid.apply_config('use_devil_provision')
    self.m.chromium.apply_config('cronet_builder')
    for c in chromium_apply_config or []:
      self.m.chromium.apply_config(c)
    droid.init_and_sync(use_bot_update=True)


  def build(self, mastername=None, buildername=None, targets=None,
            use_goma=True):
    if not mastername:
      mastername=self.m.properties['mastername']
    if not buildername:
      buildername=self.m.properties['buildername']
    if use_goma:
      self.m.chromium.ensure_goma()
    self.m.chromium.runhooks()
    if self.m.chromium.c.project_generator.tool == 'gn': # pragma: no cover
      assert (self.m.chromium.c.HOST_PLATFORM == 'linux'
              and self.m.chromium.c.HOST_BITS == 64)
      gn_path = self.m.path['checkout'].join('buildtools', 'linux64', 'gn')
      if not self.m.path.exists(gn_path):
        gn_path = self.m.path['checkout'].join('third_party', 'gn', 'gn')
      self.m.chromium.run_gn(
          use_goma=use_goma,
          gn_path=gn_path)
    elif self.m.chromium.c.project_generator.tool == 'mb':
      self.m.chromium.mb_gen(
          mastername,
          buildername,
          use_goma=use_goma)
    self.m.chromium.compile(targets=targets, use_goma_module=use_goma)


  def get_version(self):
    version = self.m.chromium.get_version()
    return "%s.%s.%s.%s" % (version['MAJOR'], version['MINOR'],
                            version['BUILD'], version['PATCH'])


  def upload_package(self, build_config, cronetdir=None, platform='android'):
    cronetdir = cronetdir or self.m.path['checkout'].join(
        'out', self.m.chromium_android.c.BUILD_CONFIG, 'cronet')
    destdir = self.get_version() + '/' + build_config
    # Upload cronet version first to ensure that destdir is created.
    self.m.gsutil.upload(
        source=cronetdir.join('VERSION'),
        bucket='chromium-cronet/%s' % platform,
        dest=destdir + '/VERSION',
        name='upload_cronet_version',
        link_name='Cronet version')
    self.m.gsutil.upload(
        source=cronetdir,
        bucket='chromium-cronet/%s' % platform,
        dest=destdir,
        args=['-R'],
        name='upload_cronet_package',
        link_name='Cronet package')


  def sizes(self, perf_id):
    # Measures native .so size.
    self.m.chromium.sizes(results_url=self.DASHBOARD_UPLOAD_URL,
                          perf_id=perf_id, platform='android-cronet')
    if self.m.chromium.c.BUILD_CONFIG == 'Release':
      # Track apk metrics.
      self.m.chromium_android.resource_sizes(
              self.m.chromium.output_dir.join('apks', 'CronetSample.apk'),
              chartjson_file=True,
              perf_id=perf_id)


  def run_tests(
      self, unit_tests=None, instrumentation_tests=INSTRUMENTATION_TESTS):

    if unit_tests is None:
      # The Android-specific cronet unit test target was renamed from
      # 'cronet_unittests' to 'cronet_unittests_android' starting in M66.
      if int(self.m.chromium.get_version().get('MAJOR', sys.maxint)) > 65:
        unit_tests = self.UNIT_TESTS
      else:
        unit_tests = self.UNIT_TESTS_M65_AND_BELOW

    droid = self.m.chromium_android
    droid.common_tests_setup_steps()
    with self.m.step.defer_results():
      for suite in unit_tests:
        droid.run_test_suite(suite, shard_timeout=180)
      for suite in instrumentation_tests:
        droid.run_instrumentation_suite(
            name=suite['target'],
            verbose=True,
            wrapper_script_suite_name=suite['target'],
            num_retries=0,
            result_details=True,
            **suite.get('kwargs', {}))
      droid.common_tests_final_steps()

  def run_perf_tests(self, perf_id):
    # Before running the perf test, build quic_server and quic_client for this
    # host machine.
    self.m.chromium.set_config('chromium')

    # Make sure not to clobber all the Cronet binaries that were just built.
    # Landmines are very target dependent so they'll likely be different
    # between android and linux, so running runhooks now would make them go off.
    # Prevent clobbering by clearing landmines that would otherwise go off
    # when runhooks is run.It's safe to ignore landmines now because we just
    # did a clobber build.
    self.m.python.inline(
        'clear landmines',
        """
        import subprocess, sys
        proc = subprocess.Popen(
            sys.argv[1], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = proc.communicate()
        with open(sys.argv[2], 'w') as f:
          f.writelines(out)
        """,
        args=[self.m.path['checkout'].join('build', 'get_landmines.py'),
              self.m.path['checkout'].join('.landmines')])
    self.build(targets=['quic_server'],
               mastername='chromium.linux', buildername='Linux Builder')
    data_dir = self.m.path.mkdtemp('perf_data')
    args = ['--output-format', 'histograms', '--output-dir', data_dir]
    self.m.python('performance test',
                  self.m.path['checkout'].join('components', 'cronet',
                                               'android', 'test',
                                               'javaperftests', 'run.py'),
                  args=args)

    oauth_token = self.m.puppet_service_account.get_access_token(
          'cronet-perf')

    args = [
        '--results-file', data_dir.join('histograms.json'),
        # We are passing this in solely to have the output show up as a link
        # in the step log, it will not be used after the upload is complete.
        '--oauth-token-file', self.m.json.input(oauth_token),
        '--perf-id', perf_id,
        '--results-url', self.DASHBOARD_UPLOAD_URL,
        '--name', 'cronet_perf_tests',
        '--output-json-file', self.m.json.output(),
        '--buildername', self.m.properties['buildername'],
        '--buildnumber', self.m.properties['buildnumber'],
        '--chromium-checkout-dir', self.m.path['start_dir'],
        '--build-dir', self.m.chromium.c.build_dir,
        '--send-as-histograms',
    ]

    if 'got_revision_cp' in self.m.properties:
      args.extend(['--got-revision-cp', self.m.properties['got_revision_cp']])
    if 'git_revision' in self.m.properties:
      args.extend(['--git-revision', self.m.properties['git_revision']])

    self.m.build.python(
        'Perf Dashboard Upload',
        self.m.chromium.package_repo_resource(
            'scripts', 'slave', 'upload_perf_dashboard_results.py'),
        args,
        step_test_data=(
            lambda: self.m.json.test_api.output('chromeperf.appspot.com',
                                                name='dashboard_url') +
                    self.m.json.test_api.output({})))
