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

from contextlib import ExitStack

DEPS = [
    'flutter/android_virtual_device',
    'flutter/flutter_deps',
    'flutter/logs_util',
    'flutter/os_utils',
    'flutter/osx_sdk',
    'flutter/repo_util',
    'flutter/yaml',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/step',
    'recipe_engine/runtime',
    'recipe_engine/raw_io',
]


def RunSteps(api):
  """Recipe to run flutter package tests."""
  # Collect memory/cpu/process before task execution.
  api.os_utils.collect_os_info()

  packages_checkout_path = api.path['start_dir'].join('packages')
  flutter_checkout_path = api.path['start_dir'].join('flutter')
  channel = api.properties.get('channel')
  version_file_name = api.properties.get('version_file', '')
  with api.step.nest('checkout source code'):
    api.repo_util.checkout(
        'packages',
        checkout_path=packages_checkout_path,
        url=api.properties.get('git_url'),
        ref=api.properties.get('git_ref')
    )
    # Check out the specified version of Flutter.
    flutter_ref = 'refs/heads/%s' % channel
    # When specified, use a pinned version instead of latest.
    if version_file_name:
      version_file = packages_checkout_path.join('.ci', version_file_name)
      flutter_ref = api.file.read_text(
          'read pinned version', version_file, flutter_ref
      ).strip()
    api.repo_util.checkout(
        'flutter',
        checkout_path=flutter_checkout_path,
        ref=flutter_ref,
        url='https://github.com/flutter/flutter',
    )

  env, env_prefixes = api.repo_util.flutter_environment(flutter_checkout_path)

  # Join labels with ',' and do no perform any char escaping.
  env['PR_OVERRIDE_LABELS'] = ','.join(api.properties.get('overrides', ''))

  env['USE_EMULATOR'] = False
  with api.step.nest('Dependencies'):
    deps = api.properties.get('dependencies', [])
    api.flutter_deps.required_deps(env, env_prefixes, deps)
    dep_list = {d['dependency']: d.get('version') for d in deps}
    # If the emulator dependency is present then we assume it is wanted for testing.
    if 'android_virtual_device' in dep_list.keys():
      env['USE_EMULATOR'] = True
      env['EMULATOR_VERSION'] = dep_list.get('android_virtual_device')

  with api.context(env=env, env_prefixes=env_prefixes,
                   cwd=flutter_checkout_path):
    with api.step.nest('prepare environment'):
      api.step('flutter doctor', ['flutter', 'doctor', '-v'])
      # Fail fast on dependencies problem.
      timeout_secs = 300
      api.step(
          'download dependencies', ['flutter', 'update-packages', '-v'],
          infra_step=True,
          timeout=timeout_secs
      )
  tests_yaml_path = packages_checkout_path.join(
      '.ci', 'targets', api.properties.get('target_file', 'tests.yaml')
  )
  result = api.yaml.read('read yaml', tests_yaml_path, api.json.output())
  with api.context(env=env, env_prefixes=env_prefixes,
                   cwd=packages_checkout_path):
    with api.step.nest('Run package tests'):
      if api.properties.get('$flutter/osx_sdk'):
        with api.osx_sdk('ios'):
          api.flutter_deps.gems(
              env, env_prefixes, flutter_checkout_path.join('dev', 'ci', 'mac')
          )
          with api.context(env=env, env_prefixes=env_prefixes):
            run_test(api, result, packages_checkout_path, env, env_prefixes)
      else:
        with ExitStack() as stack:
          if env['USE_EMULATOR']:
            stack.enter_context(
                api.android_virtual_device(
                    env=env,
                    env_prefixes=env_prefixes,
                    version=env['EMULATOR_VERSION']
                )
            )
          run_test(api, result, packages_checkout_path, env, env_prefixes)

  # 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 run_test(api, result, packages_checkout_path, env, env_prefixes):
  """Run tests sequentially following the script"""
  failed_tasks = []
  for task in result.json.output['tasks']:
    script_path = packages_checkout_path.join(task['script'])
    cmd = ['bash', script_path]
    if 'args' in task:
      args = task['args']
      cmd.extend(args)
    api.logs_util.initialize_logs_collection(env)

    # Flag showing whether the task should always run regardless of previous failures.
    always_run_task = task['always'] if 'always' in task else False
    # Flag showing whether the task should be considered and infra failure or test failure.
    is_infra_step = task['infra_step'] if 'infra_step' in task else False
    with api.context(env=env, env_prefixes=env_prefixes):
      # Runs the task in two scenarios:
      #   1) all earlier tasks pass
      #   2) there are earlier task failures, but the current task is marked as `always: True`.
      #   Note that infra tasks fail and do not run the rest of the tasks including `always`.
      if not failed_tasks or always_run_task:
        step = api.step(
            task['name'],
            cmd,
            raise_on_failure=is_infra_step,
            infra_step=is_infra_step
        )
        if step.retcode != 0:
          failed_tasks.append(task['name'])
    api.logs_util.upload_logs(task['name'])
  if failed_tasks:
    raise api.step.StepFailure('Tasks failed: %s' % ','.join(failed_tasks))


def GenTests(api):
  flutter_path = api.path['start_dir'].join('flutter')
  tasks_dict = {
      'tasks': [{'name': 'one', 'script': 'myscript', 'args': ['arg1', 'arg2']}]
  }
  yield api.test(
      'master_channel', api.repo_util.flutter_environment_data(flutter_path),
      api.properties(
          channel='master',
          version_file='flutter_master.version',
      ), api.step_data('read yaml.parse', api.json.output(tasks_dict))
  )
  yield api.test(
      'stable_channel', api.repo_util.flutter_environment_data(flutter_path),
      api.properties(channel='stable',),
      api.step_data('read yaml.parse', api.json.output(tasks_dict))
  )
  yield api.test(
      'mac', api.repo_util.flutter_environment_data(flutter_path),
      api.properties(
          channel='master',
          version_file='flutter_master.version',
          **{'$flutter/osx_sdk': {'sdk_version': 'deadbeef',}},
      ), api.step_data('read yaml.parse', api.json.output(tasks_dict))
  )
  checkout_path = api.path['cleanup'].join('tmp_tmp_1', 'flutter sdk')
  yield api.test(
      "emulator-test", api.repo_util.flutter_environment_data(flutter_path),
      api.properties(
          channel='master',
          version_file='flutter_master.version',
          git_branch='master',
          dependencies=[{
              "dependency": "android_virtual_device", "version": "31"
          }],
      ), api.step_data('read yaml.parse', api.json.output(tasks_dict)),
      api.step_data(
          'Run package tests.start avd.Start Android emulator (API level 31)',
          stdout=api.raw_io.output_text(
              'android_31_google_apis_x86|emulator-5554 started (pid: 17687)'
          )
      ), api.runtime(is_experimental=True)
  )
  multiple_tasks_dict = {
      'tasks': [{'name': 'one', 'script': 'myscript', 'args': ['arg1', 'arg2']},
                {
                    'name': 'two', 'script': 'myscript',
                    'args': ['arg1', 'arg2'], 'always': True
                }]
  }
  yield api.test(
      'multiple_tests_with_always',
      api.repo_util.flutter_environment_data(flutter_path),
      api.properties(
          channel='master',
          version_file='flutter_master.version',
      ),
      api.step_data('read yaml.parse', api.json.output(multiple_tasks_dict)),
      api.step_data('Run package tests.one', retcode=1),
      status='FAILURE'
  )
