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

"""Recipe for engine shards.

   web_engine.py will call these shards. It will build the Flutter Web Engine,
   and will archive it to the CAS server.

   These shards will be called with required dependencies, felt commands, and
   with a CAS digest of the Flutter Web Engine.
"""

import contextlib
import copy

from recipe_engine import recipe_api

from PB.recipes.flutter.engine.engine import InputProperties
from PB.recipes.flutter.engine.engine import EnvProperties

DEPS = [
    'depot_tools/depot_tools',
    'flutter/flutter_deps',
    'flutter/os_utils',
    'flutter/osx_sdk',
    'flutter/repo_util',
    'flutter/retry',
    'flutter/web_util',
    'fuchsia/goma',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/runtime',
    'recipe_engine/step',
]

GIT_REPO = 'https://flutter.googlesource.com/mirrors/engine'

PROPERTIES = InputProperties
ENV_PROPERTIES = EnvProperties


def GetCheckoutPath(api):
  """Path to checkout the flutter/engine repo."""
  return api.path['cleanup'].join('builder', 'src')


def RunSteps(api, properties, env_properties):
  """Steps to checkout flutter engine and execute web test shard.

  The test shard to run will be determined by `command_args` send as part of
  properties.
  """
  cache_root = api.path['cleanup'].join('builder')
  checkout = GetCheckoutPath(api)
  platform = api.platform.name.capitalize()
  if properties.clobber:
    api.file.rmtree('Clobber cache', cache_root)
  api.file.rmtree('Clobber build output: %s' % platform, checkout.join('out'))

  api.file.ensure_directory('Ensure checkout cache', cache_root)
  api.goma.ensure()
  env = {}
  env_prefixes = {}

  # Checkout source code and build
  api.repo_util.engine_checkout(cache_root, env, env_prefixes)

  # Ensure required deps are installed
  api.flutter_deps.required_deps(
      env, env_prefixes, api.properties.get('inherited_dependencies', [])
  )

  # Prepare the web dependencies that web tests need.
  # These can be browsers, web drivers or other repositories.
  api.web_util.prepare_web_dependencies(checkout)

  with api.context(cwd=cache_root, env=env,
                   env_prefixes=env_prefixes), api.depot_tools.on_path():

    target_name = 'host_debug_unopt'

    # Load local engine information if available.
    api.flutter_deps.flutter_engine(env, env_prefixes)

    android_home = checkout.join('third_party', 'android_tools', 'sdk')
    env['GOMA_DIR'] = api.goma.goma_dir
    env['ANDROID_HOME'] = str(android_home)
    env['CHROME_NO_SANDBOX'] = 'true'
    env['ENGINE_PATH'] = cache_root
    # flutter_engine deps adds dart dependency as out/host_debug_unopt/dart-sdk
    # We are changing it with src/third_party/dart/tools/sdks/dart-sdk
    dart_bin = checkout.join(
        'third_party', 'dart', 'tools', 'sdks', 'dart-sdk', 'bin'
    )
    paths = env_prefixes.get('PATH', [])
    paths.insert(0, dart_bin)
    env_prefixes['PATH'] = paths

    command_args = api.properties.get('command_args', ['test'])
    command_name = api.properties.get('command_name', 'test')
    felt_cmd = [
        checkout.join('out', target_name, 'dart-sdk', 'bin', 'dart'),
        'dev/felt.dart'
    ]
    felt_cmd.extend(command_args)

    with api.context(cwd=cache_root, env=env,
                     env_prefixes=env_prefixes), api.depot_tools.on_path():
      # Update dart packages and run tests.
      local_engine_path = env.get('LOCAL_ENGINE')
      local_dart = local_engine_path.join('dart-sdk', 'bin', 'dart')
      with api.context(
          cwd=checkout.join('flutter', 'web_sdk', 'web_engine_tester')):
        api.retry.step(
            'dart pub get in web_engine_tester', [local_dart, 'pub', 'get'], infra_step=True
        )
      with api.context(cwd=checkout.join('flutter', 'lib', 'web_ui')):
        api.retry.step('pub get in web_ui', [local_dart, 'pub', 'get'], infra_step=True)
        web_dependencies = api.web_util.get_web_dependencies()
        if api.platform.is_mac:
          with api.osx_sdk('ios'):
            with recipe_api.defer_results():
              api.step('felt test: %s' % command_name, felt_cmd)
              # This is to clean up leaked processes.
              api.os_utils.kill_processes()
              # Collect memory/cpu/process after task execution.
              api.os_utils.collect_os_info()
        else:
          with recipe_api.defer_results():
            api.step('felt test: %s' % command_name, felt_cmd)
            # This is to clean up leaked processes.
            api.os_utils.kill_processes()
            # Collect memory/cpu/process after task execution.
            api.os_utils.collect_os_info()


def GenTests(api):
  browser_yaml_file = {
      'required_driver_version': {'chrome': 84},
      'chrome': {'Linux': '768968', 'Mac': '768985', 'Win': '768975'}
  }
  yield api.test(
      'linux-post-submit',
      api.step_data(
          'read browser lock yaml.parse', api.json.output(browser_yaml_file)
      ),
      api.step_data(
          'read browser lock yaml (2).parse',
          api.json.output(browser_yaml_file)
      ),
      api.properties(
          goma_jobs='200',
          web_dependencies=['chrome_driver', 'chrome'],
          command_args=['test', '--browser=chrome'],
          command_name='chrome-tests',
          local_engine_cas_hash='abceqwe'
      ), api.platform('linux', 64)
  ) + api.runtime(is_experimental=False) + api.platform.name('linux')
  yield api.test(
      'linux-firefox-integration',
      api.properties(
          goma_jobs='200',
          web_dependencies=['firefox_driver'],
          command_args=['test', '--browser=firefox'],
          command_name='firefox-tests',
          local_engine_cas_hash='abceqwe'
      ), api.platform.name('linux'), api.platform('linux', 64)
  ) + api.runtime(is_experimental=False)
  yield api.test('windows-post-submit') + api.properties(
      goma_jobs='200', local_engine_cas_hash='abceqwe'
  ) + api.platform('win', 32) + api.runtime(is_experimental=False)
  yield api.test(
      'mac-post-submit',
      api.properties(
          goma_jobs='200',
          web_dependencies=[],
          command_args=['test', '--browser=ios-safari', '--require-skia-gold'],
          command_name='ios-safari-unit-tests',
          local_engine_cas_hash='abceqwe'
      ), api.platform('mac', 64)
  ) + api.runtime(is_experimental=False)
  yield api.test(
      'linux-experimental',
      api.repo_util.flutter_environment_data(),
      api.properties(
          goma_jobs='200',
          git_url='https://mygitrepo',
          git_ref='refs/pull/1/head',
          web_dependencies=[],
          clobber=True,
          local_engine_cas_hash='abceqwe'
      ), api.platform('linux', 64)
  ) + api.runtime(is_experimental=True)
  yield api.test(
      'linux-error',
      api.properties(
          goma_jobs='200',
          git_url='https://mygitrepo',
          git_ref='refs/pull/1/head',
          web_dependencies=['invalid_dependency'],
          clobber=True,
          local_engine_cas_hash='abceqwe'
      ), api.platform('linux', 64), api.expect_exception('ValueError')
  ) + api.runtime(is_experimental=True)
