# 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)


  # TODO(perezju): Remove venv option once also removed from callers.
  def run_tests(
      self, venv=False, 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(venv=venv)
    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({})))
