# Copyright 2018 The Fuchsia 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 recipe_engine import recipe_test_api


class FuchsiaBuildTestApi(recipe_test_api.RecipeTestApi):

  def test(self,
           name,
           target='x64',
           variants=(),
           build_type='debug',
           product='products/core.gni',
           board='boards/x64.gni',
           tryjob=False,
           properties=None,
           create_shards=True,
           status='success',
           test_deps=()):
    """Returns a test case appropriate for yielding from GenTests().

    Provides default property values for the common cases.

    Args:
      name: Test name.
      target (str): A build target (e.g., 'x64' or 'arm64').
      build_type (str): A build type (e.g., 'debug' or 'release')
      variants (sequence[str]): Variant selectors to pass to GN.
      packages (sequence[str]): A sequence of packages to pass to GN to build
      product (str): A product to pass to GN to build.
      board (str): A board to pass to GN to build.
      properties (dict): A dict of properties to override for this test.
      status (str): One of 'success' (default), 'failure', or
        'infra_failure'. The result of the test case will be required to
        match this.
      test_deps (sequence[str] or None): Test dependency paths.

    Returns:
      TestData object.
    """

    final_properties = {
        'target': target,
        'variants': variants,
        'build_type': build_type,
        'product': product,
        'board': board,
    }
    # Provided properties override the defaults.
    properties = properties or {}
    final_properties.update(properties)

    # Assemble the return value.
    ret = self.m.status_check.test(name, status=status)

    # Add buildbucket properties
    if tryjob:
      ret += self.m.buildbucket.try_build(
          project='fuchsia',
          git_repo='https://fuchsia.googlesource.com/fuchsia',
      )
    else:
      final_properties['gcs_bucket'] = '###fuchsia-build###'
      ret += self.m.buildbucket.ci_build(
          project='fuchsia',
          git_repo='https://fuchsia.googlesource.com/fuchsia',
      )

    ret += self.m.properties(**final_properties)

    if create_shards:
      ret += self.create_shards_step_data(shards=[
          self.m.testsharder.shard(
              name='Vim2',
              tests=[
                  self.m.testsharder.test(
                      name='test',
                      label='//path/to/test:test(//toolchain)',
                      os='linux',
                      path='/path/to/test',
                      deps=test_deps,
                  )
              ],
              dimensions=dict(device_type='Khadas Vim2 Max'),
          ),
      ])
    return ret

  def mock_image_manifest(self):
    """Returns a mock image manifest.

    Args:
      arch (str): The target architecture of the build.
    """
    return self.m.json.output([{
        'name': 'zircon-a',
        'type': 'zbi',
        'path': 'fuchsia.zbi',
        'bootserver_pave': ['--boot', '--zircona'],
    }, {
        'name': 'storage-full',
        'type': 'blk',
        'path': 'fvm.blk',
    }, {
        'name': 'storage-sparse',
        'type': 'blk',
        'path': 'fvm.sparse.blk',
        'bootserver_pave': ['--fvm'],
    }, {
        'name': 'efi',
        'type': 'blk',
        'path': 'fuchsia.esp.blk',
        'bootserver_pave': ['--efi'],
    }, {
        'name': 'netboot',
        'type': 'zbi',
        'path': 'netboot.zbi',
        'bootserver_netboot': ['--boot'],
    }, {
        'name': 'archive',
        'path': 'build-archive.tgz',
        'type': 'tgz',
    }, {
        'name': 'archive',
        'path': 'build-archive.zip',
        'type': 'zip',
    }, {
        'name': 'qemu-kernel',
        'path': 'multiboot.bin',
        'type': 'kernel'
    }, {
        'name': 'symbol-archive',
        'path': 'symbol-archive.tgz',
        'type': 'tgz',
    }, {
        'name': 'zircon-r',
        'type': 'zbi',
        'path': 'zircon-r.zbi',
        'bootserver_pave': ['--zircon-r'],
    }, {
        'name': 'zircon-r',
        'type': 'zbi',
        'path': 'zedboot.zbi',
        'bootserver_pave_zedboot': ['--zircona'],
    }])

  def mock_test_spec_manifest(self):
    """Returns a mock manifest of test specs in a build."""
    return self.m.json.output([
        {
            'test': {
                'name': 'foo_tests',
                'label': '//public/lib/foo:foo_tests(//some/toolchain)',
                'os': 'linux',
                'path': 'path/on/disk/to/test',
            }
        },
        {
            'test': {
                'name': 'bar_unittests',
                'label': '//lib/bar:bar_unittests(//some/toolchain)',
                'os': 'fuchsia',
                'path': 'path/on/fuchsia/to/test',
            }
        },
    ])

  def mock_tool_paths_manifest(self):
    prebuilt_tools = [
        'bazel', 'cargo', 'clang-doc', 'clang-format-diff', 'clang-format',
        'clang-tidy-diff', 'clang-tidy', 'dart', 'dartfmt', 'gn', 'go', 'gofmt',
        'llvm-cov', 'llvm-profdata', 'llvm-symbolizer', 'ninja', 'rustc',
        'rustdoc', 'rustfmt', 'yapf'
    ]
    built_zircon_tools = [
        'bootserver', 'fidl-format', 'fidl-lint', 'fvm', 'minfs', 'zbi'
    ]
    built_tools = [
        'artifactory', 'bootserver_new', 'botanist', 'covargs', 'debroot',
        'ninjatrace', 'seriallistener', 'size_checker', 'symbolize',
        'testrunner', 'testsharder', 'upload_debug_symbols'
    ]

    def tool_entry(tool_name, os, cpu, path):
      return {
          'cpu': cpu,
          'label': '//tools/%s' % tool_name,
          'name': tool_name,
          'os': os,
          'path': path
      }

    entries = []
    for os in ['linux', 'mac']:
      for cpu in ['x64', 'arm64']:
        for tool in prebuilt_tools:
          entries.append(
              tool_entry(
                  tool, os, cpu, '../../prebuilt/third_party/%s/%s_%s/%s' %
                  (tool, os, cpu, tool)))
        for tool in built_zircon_tools:
          entries.append(
              tool_entry(tool, os, cpu,
                         '../default.zircon/host-%s-%s/%s' % (os, cpu, tool)))
        for tool in built_tools:
          entries.append(
              tool_entry(tool, os, cpu, '%s_%s/%s' % (os, cpu, tool)))
    return self.m.json.output(entries)

  def mock_zircon_instructions(self):
    """Returns a mock zircon.json file."""
    return self.m.json.output({
        'dir': '../default.zircon',
        'targets': ['legacy-host_tests', 'manifest-$cpu'],
    })

  def create_shards_step_data(self, shards):
    """Returns mock step data for test shards.

    This should be used by any test which calls api.fuchsia.test*() and expects
    to shard tests.

    Args:
      shards (seq[api.testsharder.Shard]): A set of example shards which should
        be used as step data for the result of invoking the testsharder.

    Returns:
      RecipeTestApi.step_data for the extract_results step.
    """
    return self.m.testsharder.execute(
        step_name='create test shards', shards=shards)

  def mock_zbi_test(self, target):
    return {
        'cpu': target,
        'name': 'zbi-test-{}'.format(target),
        'type': 'zbi',
        'success_string': 'purple monkey dishwasher',
        'path': '../default.zircon/zbi-test-{}.zbi'.format(target),
        'device_types': ['QEMU', 'AEMU', 'DEVICE_TYPE'],
    }
