#!/usr/bin/env python3
# Copyright 2026 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Tool to check if a test suite is barred by ci_only = True configuration."""

import argparse
import json
import pathlib
import subprocess
import sys
from typing import Any, Callable, NamedTuple


class TrybotEntry(NamedTuple):
  """Holds trybot name and target group name.

  Attributes:
    trybot: Name of the trybot.
    group: Target group name (e.g. chromium.coverage).
  """

  trybot: str
  group: str


class BuilderConfig(NamedTuple):
  """Holds builder name and its ci_only status.

  Attributes:
    builder: Name of the builder.
    ci_only: Boolean status indicating if the builder is ci_only.
  """

  builder: str
  ci_only: bool


def discover_trybots_for_test_suite(
  src_root: pathlib.Path,
  test_suite: str,
  revision: str | None = None,
) -> list[TrybotEntry]:
  """Discovers all trybots and target groups configuring the test suite.

  Args:
    src_root: The root directory of the chromium source checkout.
    test_suite: Name of the test suite to search for.
    revision: Optional git revision (commit hash/branch) to search at.

  Returns:
    A list of TrybotEntry NamedTuples.
  """
  # Match exact JSON pattern for the test suite name.
  pattern = f'\\"name\\": \\"{test_suite}\\"'
  cmd = [
    'git',
    'grep',
    '-l',
    pattern,
  ]
  if revision:
    cmd.append(revision)
  cmd.extend(['--', 'infra/config/generated/builders/try/*/targets/*.json'])

  result = subprocess.run(
    cmd, cwd=src_root, capture_output=True, text=True, check=False
  )
  if result.returncode != 0:
    return []

  trybots_and_groups = []
  for line in result.stdout.splitlines():
    line = line.strip()
    if not line:
      continue
    if revision and ':' in line:
      line = line.split(':', 1)[1]

    path = pathlib.Path(line)
    parts = path.parts
    trybot = parts[5]
    group = path.stem
    trybots_and_groups.append(TrybotEntry(trybot=trybot, group=group))

  return trybots_and_groups


def read_local(src_root: pathlib.Path, rel_path: str) -> str | None:
  """Reads a configuration file from the local disk.

  Args:
    src_root: The root directory of the chromium source checkout.
    rel_path: Relative path to the file from the source root.

  Returns:
    The file contents as a string, or None if the file was missing/unread.
  """
  file_path = src_root / rel_path
  if not file_path.exists():
    return None
  try:
    return file_path.read_text(encoding='utf-8')
  except OSError as e:
    print(f'Error reading local file {file_path}: {e}', file=sys.stderr)
    return None


def read_git(
  src_root: pathlib.Path, revision: str, rel_path: str
) -> str | None:
  """Reads a configuration file from a git revision.

  Args:
    src_root: The root directory of the chromium source checkout.
    revision: The git revision (commit hash/branch) to query.
    rel_path: Relative path to the file from the source root.

  Returns:
    The file contents as a string, or None if the git command failed.
  """
  cmd = ['git', 'show', f'{revision}:{rel_path}']
  result = subprocess.run(
    cmd, cwd=src_root, capture_output=True, text=True, check=False
  )
  if result.returncode != 0:
    return None
  return result.stdout


def check_coverage_enabled(
  read_fn: Callable[[str], str | None], trybot: str
) -> bool:
  """Checks if coverage is enabled in the trybot's GN args.

  Args:
    read_fn: Callable that takes a relative path and returns file content.
    trybot: Name of the trybot to inspect.

  Returns:
    True if code coverage is enabled for Clang or JaCoCo, False otherwise.
  """
  gn_args_path = f'infra/config/generated/builders/try/{trybot}/gn-args.json'
  gn_args_content = read_fn(gn_args_path)
  if not gn_args_content:
    return False
  try:
    gn_args = json.loads(gn_args_content).get('gn_args', {})
    return bool(
      gn_args.get('use_clang_coverage', False)
      or gn_args.get('use_jacoco_coverage', False)
    )
  except json.JSONDecodeError:
    return False


def check_trybot_coverage_config(
  read_fn: Callable[[str], str | None],
  trybot: str,
  group: str,
  test_suite: str,
) -> list[BuilderConfig]:
  """Checks target specs for a trybot to see if a test suite is ci_only.

  Args:
    read_fn: Callable that takes a relative path and returns file content.
    trybot: Name of the trybot to check.
    group: Target group name (e.g. chromium.coverage).
    test_suite: Name of the test suite to verify.

  Returns:
    A list of BuilderConfig NamedTuples.
  """
  target_spec_rel_path = (
    f'infra/config/generated/builders/try/{trybot}/targets/{group}.json'
  )
  target_spec_content = read_fn(target_spec_rel_path)
  if not target_spec_content:
    return []

  try:
    target_spec = json.loads(target_spec_content)
  except json.JSONDecodeError as e:
    print(
      f'Error parsing target spec {target_spec_rel_path}: {e}',
      file=sys.stderr,
    )
    return []

  results = []
  for builder_name, builder_specs in target_spec.items():
    suite_found = False
    is_ci_only = False
    for test_type in [
      'gtest_tests',
      'isolated_scripts',
      'junit_tests',
      'scripts',
    ]:
      tests = builder_specs.get(test_type, [])
      for test in tests:
        if test.get('name') == test_suite:
          suite_found = True
          is_ci_only = test.get('ci_only', False)
          break
      if suite_found:
        break

    if suite_found:
      results.append(BuilderConfig(builder=builder_name, ci_only=is_ci_only))
  return results


def main() -> None:
  parser = argparse.ArgumentParser(
    description=(
      'Check if a test suite is barred by ci_only = True on trybots.'
    )
  )
  parser.add_argument(
    'test_suite',
    help='Name of the test suite (e.g. chrome_junit_tests)',
  )
  parser.add_argument(
    '--revision',
    '-r',
    help=(
      'Git revision to check the configuration at (e.g., commit hash, branch).'
    ),
  )

  args = parser.parse_args()

  script_dir = pathlib.Path(__file__).resolve().parent
  src_root = script_dir.parents[1]

  if not src_root.exists():
    print(f'Error: Src path {src_root} does not exist', file=sys.stderr)
    sys.exit(1)

  if args.revision:
    # Check if the revision is valid
    res = subprocess.run(
      ['git', 'rev-parse', '--verify', args.revision],
      cwd=src_root,
      capture_output=True,
      text=True,
      check=False,
    )
    if res.returncode != 0:
      print(f'Error: Invalid revision: {args.revision}', file=sys.stderr)
      sys.exit(1)

  trybots_and_groups = discover_trybots_for_test_suite(
    src_root, args.test_suite, args.revision
  )
  if not trybots_and_groups:
    print(
      f"Warning: Test suite '{args.test_suite}' was not found on any trybots.",
      file=sys.stderr,
    )
    sys.exit(0)

  if args.revision:
    read_fn = lambda path: read_git(src_root, args.revision, path)
  else:
    read_fn = lambda path: read_local(src_root, path)

  revision_msg = f' at revision {args.revision}' if args.revision else ''
  print(
    f"Checking test suite '{args.test_suite}' across"
    f' {len(trybots_and_groups)} configured trybots{revision_msg}...'
  )

  for entry in sorted(trybots_and_groups, key=lambda e: e.trybot):
    trybot = entry.trybot
    group = entry.group
    configs = check_trybot_coverage_config(
      read_fn, trybot, group, args.test_suite
    )
    coverage_enabled = check_coverage_enabled(read_fn, trybot)

    for config in configs:
      status = 'ci_only = True' if config.ci_only else 'ci_only = False'
      coverage_status = (
        'Coverage: Enabled' if coverage_enabled else 'Coverage: Disabled'
      )
      print(
        f'  Trybot: {trybot:<30} | Builder: {group}:{config.builder:<30}'
        f' | {status:<15} | {coverage_status}'
      )


if __name__ == '__main__':
  main()
