#!/usr/bin/env vpython3
#
# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
'''Implements Chrome-Fuchsia package binary size checks.'''

import argparse
import collections
import json
import math
import os
import re
import shutil
import subprocess
import sys
import tempfile
import time
import traceback
import uuid

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
                                             'test')))

from common import DIR_SRC_ROOT, SDK_ROOT, get_host_tool_path

PACKAGES_BLOBS_FILE = 'package_blobs.json'
PACKAGES_SIZES_FILE = 'package_sizes.json'

# Structure representing the compressed and uncompressed sizes for a Fuchsia
# package.
PackageSizes = collections.namedtuple('PackageSizes',
                                      ['compressed', 'uncompressed'])

# Structure representing a Fuchsia package blob and its compressed and
# uncompressed sizes.
Blob = collections.namedtuple(
    'Blob', ['name', 'hash', 'compressed', 'uncompressed', 'is_counted'])


def CreateSizesExternalDiagnostic(sizes_guid):
  """Creates a histogram external sizes diagnostic."""

  benchmark_diagnostic = {
      'type': 'GenericSet',
      'guid': str(sizes_guid),
      'values': ['sizes'],
  }

  return benchmark_diagnostic


def CreateSizesHistogramItem(name, size, sizes_guid):
  """Create a performance dashboard histogram from the histogram template and
  binary size data."""

  # Chromium performance dashboard histogram containing binary size data.
  histogram = {
      'name': name,
      'unit': 'sizeInBytes_smallerIsBetter',
      'diagnostics': {
          'benchmarks': str(sizes_guid),
      },
      'sampleValues': [size],
      'running': [1, size, math.log(size), size, size, size, 0],
      'description': 'chrome-fuchsia package binary sizes',
      'summaryOptions': {
          'avg': True,
          'count': False,
          'max': False,
          'min': False,
          'std': False,
          'sum': False,
      },
  }

  return histogram


def CreateSizesHistogram(package_sizes):
  """Create a performance dashboard histogram from binary size data."""

  sizes_guid = uuid.uuid1()
  histogram = [CreateSizesExternalDiagnostic(sizes_guid)]
  for name, size in package_sizes.items():
    histogram.append(
        CreateSizesHistogramItem('%s_%s' % (name, 'compressed'),
                                 size.compressed, sizes_guid))
    histogram.append(
        CreateSizesHistogramItem('%s_%s' % (name, 'uncompressed'),
                                 size.uncompressed, sizes_guid))
  return histogram


def CreateTestResults(test_status, timestamp):
  """Create test results data to write to JSON test results file.

  The JSON data format is defined in
  https://chromium.googlesource.com/chromium/src/+/main/docs/testing/json_test_results_format.md
  """

  results = {
      'tests': {},
      'interrupted': False,
      'metadata': {
          'test_name_prefix': 'build/fuchsia/'
      },
      'version': 3,
      'seconds_since_epoch': timestamp,
  }

  num_failures_by_type = {result: 0 for result in ['FAIL', 'PASS', 'CRASH']}
  for metric in test_status:
    actual_status = test_status[metric]
    num_failures_by_type[actual_status] += 1
    results['tests'][metric] = {
        'expected': 'PASS',
        'actual': actual_status,
    }
  results['num_failures_by_type'] = num_failures_by_type

  return results


def GetTestStatus(package_sizes, sizes_config, test_completed):
  """Checks package sizes against size limits.

  Returns a tuple of overall test pass/fail status and a dictionary mapping size
  limit checks to PASS/FAIL/CRASH status."""

  if not test_completed:
    test_status = {'binary_sizes': 'CRASH'}
  else:
    test_status = {}
    for metric, limit in sizes_config['size_limits'].items():
      # Strip the "_compressed" suffix from |metric| if it exists.
      match = re.match(r'(?P<name>\w+)_compressed', metric)
      package_name = match.group('name') if match else metric
      if package_name not in package_sizes:
        raise Exception('package "%s" not in sizes "%s"' %
                        (package_name, str(package_sizes)))
      if package_sizes[package_name].compressed <= limit:
        test_status[metric] = 'PASS'
      else:
        test_status[metric] = 'FAIL'

  all_tests_passed = all(status == 'PASS' for status in test_status.values())

  return all_tests_passed, test_status


def WriteSimpleTestResults(results_path, test_completed):
  """Writes simplified test results file.

  Used when test status is not available.
  """

  simple_isolated_script_output = {
      'valid': test_completed,
      'failures': [],
      'version': 'simplified',
  }
  with open(results_path, 'w') as output_file:
    json.dump(simple_isolated_script_output, output_file)


def WriteTestResults(results_path, test_completed, test_status, timestamp):
  """Writes test results file containing test PASS/FAIL/CRASH statuses."""

  if test_status:
    test_results = CreateTestResults(test_status, timestamp)
    with open(results_path, 'w') as results_file:
      json.dump(test_results, results_file)
  else:
    WriteSimpleTestResults(results_path, test_completed)


def WriteGerritPluginSizeData(output_path, package_sizes):
  """Writes a package size dictionary in json format for the Gerrit binary
  sizes plugin."""

  with open(output_path, 'w') as sizes_file:
    sizes_data = {name: size.compressed for name, size in package_sizes.items()}
    json.dump(sizes_data, sizes_file)


def ReadPackageBlobsJson(json_path):
  """Reads package blob info from json file.

  Opens json file of blob info written by WritePackageBlobsJson,
  and converts back into package blobs used in this script.
  """
  with open(json_path, 'rt') as json_file:
    formatted_blob_info = json.load(json_file)

  package_blobs = {}
  for package in formatted_blob_info:
    package_blobs[package] = {}
    for blob_info in formatted_blob_info[package]:
      blob = Blob(name=blob_info['path'],
                  hash=blob_info['merkle'],
                  uncompressed=blob_info['bytes'],
                  compressed=blob_info['size'],
                  is_counted=blob_info['is_counted'])
      package_blobs[package][blob.name] = blob

  return package_blobs


def WritePackageBlobsJson(json_path, package_blobs):
  """Writes package blob information in human-readable JSON format.

  The json data is an array of objects containing these keys:
    'path': string giving blob location in the local file system
    'merkle': the blob's Merkle hash
    'bytes': the number of uncompressed bytes in the blod
    'size': the size of the compressed blob in bytes.  A multiple of the blobfs
        block size (8192)
    'is_counted: true if the blob counts towards the package budget, or false
        if not (for ICU blobs or blobs distributed in the SDK)"""

  formatted_blob_stats_per_package = {}
  for package in package_blobs:
    blob_data = []
    for blob_name in package_blobs[package]:
      blob = package_blobs[package][blob_name]
      blob_data.append({
          'path': str(blob.name),
          'merkle': str(blob.hash),
          'bytes': blob.uncompressed,
          'size': blob.compressed,
          'is_counted': blob.is_counted
      })
    formatted_blob_stats_per_package[package] = blob_data

  with (open(json_path, 'w')) as json_file:
    json.dump(formatted_blob_stats_per_package, json_file, indent=2)


def WritePackageSizesJson(json_path, package_sizes):
  """Writes package sizes into a human-readable JSON format.

  JSON data is a dictionary of each package name being a key, with
  the following keys within the sub-object:
    'compressed': compressed size of the package in bytes.
    'uncompressed': uncompressed size of the package in bytes.
  """
  formatted_package_sizes = {}
  for package, size_info in package_sizes.items():
    formatted_package_sizes[package] = {
        'uncompressed': size_info.uncompressed,
        'compressed': size_info.compressed
    }
  with (open(json_path, 'w')) as json_file:
    json.dump(formatted_package_sizes, json_file, indent=2)


def ReadPackageSizesJson(json_path):
  """Reads package_sizes from a given JSON file.

  Opens json file of blob info written by WritePackageSizesJson,
  and converts back into package sizes used in this script.
  """
  with open(json_path, 'rt') as json_file:
    formatted_package_info = json.load(json_file)

  package_sizes = {}
  for package, size_info in formatted_package_info.items():
    package_sizes[package] = PackageSizes(
        compressed=size_info['compressed'],
        uncompressed=size_info['uncompressed'])
  return package_sizes


def GetCompressedSize(file_path):
  """Measures file size after blobfs compression."""

  compressor_path = get_host_tool_path('blobfs-compression')
  try:
    temp_dir = tempfile.mkdtemp()
    compressed_file_path = os.path.join(temp_dir, os.path.basename(file_path))
    compressor_cmd = [
        compressor_path,
        '--source_file=%s' % file_path,
        '--compressed_file=%s' % compressed_file_path
    ]
    proc = subprocess.Popen(compressor_cmd,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
    proc.wait()
    compressor_output = proc.stdout.read().decode('utf-8')
    if proc.returncode != 0:
      print(compressor_output, file=sys.stderr)
      raise Exception('Error while running %s' % compressor_path)
  finally:
    shutil.rmtree(temp_dir)

  # Match a compressed bytes total from blobfs-compression output like
  # Wrote 360830 bytes (40% compression)
  blobfs_compressed_bytes_re = r'Wrote\s+(?P<bytes>\d+)\s+bytes'

  match = re.search(blobfs_compressed_bytes_re, compressor_output)
  if not match:
    print(compressor_output, file=sys.stderr)
    raise Exception('Could not get compressed bytes for %s' % file_path)

  # Round the compressed file size up to an integer number of blobfs blocks.
  BLOBFS_BLOCK_SIZE = 8192  # Fuchsia's blobfs file system uses 8KiB blocks.
  blob_bytes = int(match.group('bytes'))
  return int(math.ceil(blob_bytes / BLOBFS_BLOCK_SIZE)) * BLOBFS_BLOCK_SIZE


def ExtractFarFile(file_path, extract_dir):
  """Extracts contents of a Fuchsia archive file to the specified directory."""

  far_tool = get_host_tool_path('far')

  if not os.path.isfile(far_tool):
    raise Exception('Could not find FAR host tool "%s".' % far_tool)
  if not os.path.isfile(file_path):
    raise Exception('Could not find FAR file "%s".' % file_path)

  subprocess.check_call([
      far_tool, 'extract',
      '--archive=%s' % file_path,
      '--output=%s' % extract_dir
  ])


def GetBlobNameHashes(meta_dir):
  """Returns mapping from Fuchsia pkgfs paths to blob hashes.  The mapping is
  read from the extracted meta.far archive contained in an extracted package
  archive."""

  blob_name_hashes = {}
  contents_path = os.path.join(meta_dir, 'meta', 'contents')
  with open(contents_path) as lines:
    for line in lines:
      (pkgfs_path, blob_hash) = line.strip().split('=')
      blob_name_hashes[pkgfs_path] = blob_hash
  return blob_name_hashes


# Compiled regular expression matching strings like *.so, *.so.1, *.so.2, ...
SO_FILENAME_REGEXP = re.compile(r'\.so(\.\d+)?$')


def GetSdkModules():
  """Finds shared objects (.so) under the Fuchsia SDK arch directory in dist or
  lib subdirectories.

  Returns a set of shared objects' filenames.
  """

  # Fuchsia SDK arch directory path (contains all shared object files).
  sdk_arch_dir = os.path.join(SDK_ROOT, 'arch')
  # Leaf subdirectories containing shared object files.
  sdk_so_leaf_dirs = ['dist', 'lib']
  # Match a shared object file name.
  sdk_so_filename_re = r'\.so(\.\d+)?$'

  lib_names = set()
  for dirpath, _, file_names in os.walk(sdk_arch_dir):
    if os.path.basename(dirpath) in sdk_so_leaf_dirs:
      for name in file_names:
        if SO_FILENAME_REGEXP.search(name):
          lib_names.add(name)
  return lib_names


def FarBaseName(name):
  _, name = os.path.split(name)
  name = re.sub(r'\.far$', '', name)
  return name


def GetPackageMerkleRoot(far_file_path):
  """Returns a package's Merkle digest."""

  # The digest is the first word on the first line of the merkle tool's output.
  merkle_tool = get_host_tool_path('merkleroot')
  output = subprocess.check_output([merkle_tool, far_file_path])
  return output.splitlines()[0].split()[0]


def GetBlobs(far_file, build_out_dir):
  """Calculates compressed and uncompressed blob sizes for specified FAR file.
  Marks ICU blobs and blobs from SDK libraries as not counted."""

  base_name = FarBaseName(far_file)

  extract_dir = tempfile.mkdtemp()

  # Extract files and blobs from the specified Fuchsia archive.
  far_file_path = os.path.join(build_out_dir, far_file)
  far_extract_dir = os.path.join(extract_dir, base_name)
  ExtractFarFile(far_file_path, far_extract_dir)

  # Extract the meta.far archive contained in the specified Fuchsia archive.
  meta_far_file_path = os.path.join(far_extract_dir, 'meta.far')
  meta_far_extract_dir = os.path.join(extract_dir, '%s_meta' % base_name)
  ExtractFarFile(meta_far_file_path, meta_far_extract_dir)

  # Map Linux filesystem blob names to blob hashes.
  blob_name_hashes = GetBlobNameHashes(meta_far_extract_dir)

  # "System" files whose sizes are not charged against component size budgets.
  # Fuchsia SDK modules and the ICU icudtl.dat file sizes are not counted.
  system_files = GetSdkModules() | set(['icudtl.dat'])

  # Add the meta.far file blob.
  blobs = {}
  meta_name = 'meta.far'
  meta_hash = GetPackageMerkleRoot(meta_far_file_path)
  compressed = GetCompressedSize(meta_far_file_path)
  uncompressed = os.path.getsize(meta_far_file_path)
  blobs[meta_name] = Blob(meta_name, meta_hash, compressed, uncompressed, True)

  # Add package blobs.
  for blob_name, blob_hash in blob_name_hashes.items():
    extracted_blob_path = os.path.join(far_extract_dir, blob_hash)
    compressed = GetCompressedSize(extracted_blob_path)
    uncompressed = os.path.getsize(extracted_blob_path)
    is_counted = os.path.basename(blob_name) not in system_files
    blobs[blob_name] = Blob(blob_name, blob_hash, compressed, uncompressed,
                            is_counted)

  shutil.rmtree(extract_dir)

  return blobs


def GetPackageBlobs(far_files, build_out_dir):
  """Returns dictionary mapping package names to blobs contained in the package.

  Prints package blob size statistics."""

  package_blobs = {}
  for far_file in far_files:
    package_name = FarBaseName(far_file)
    if package_name in package_blobs:
      raise Exception('Duplicate FAR file base name "%s".' % package_name)
    package_blobs[package_name] = GetBlobs(far_file, build_out_dir)

  # Print package blob sizes (does not count sharing).
  for package_name in sorted(package_blobs.keys()):
    print('Package blob sizes: %s' % package_name)
    print('%-64s %12s %12s %s' %
          ('blob hash', 'compressed', 'uncompressed', 'path'))
    print('%s %s %s %s' % (64 * '-', 12 * '-', 12 * '-', 20 * '-'))
    for blob_name in sorted(package_blobs[package_name].keys()):
      blob = package_blobs[package_name][blob_name]
      if blob.is_counted:
        print('%64s %12d %12d %s' %
              (blob.hash, blob.compressed, blob.uncompressed, blob.name))

  return package_blobs


def GetPackageSizes(package_blobs):
  """Calculates compressed and uncompressed package sizes from blob sizes."""

  # TODO(crbug.com/1126177): Use partial sizes for blobs shared by
  # non Chrome-Fuchsia packages.

  # Count number of packages sharing blobs (a count of 1 is not shared).
  blob_counts = collections.defaultdict(int)
  for package_name in package_blobs:
    for blob_name in package_blobs[package_name]:
      blob = package_blobs[package_name][blob_name]
      blob_counts[blob.hash] += 1

  # Package sizes are the sum of blob sizes divided by their share counts.
  package_sizes = {}
  for package_name in package_blobs:
    compressed_total = 0
    uncompressed_total = 0
    for blob_name in package_blobs[package_name]:
      blob = package_blobs[package_name][blob_name]
      if blob.is_counted:
        count = blob_counts[blob.hash]
        compressed_total += blob.compressed // count
        uncompressed_total += blob.uncompressed // count
    package_sizes[package_name] = PackageSizes(compressed_total,
                                               uncompressed_total)

  return package_sizes


def GetBinarySizesAndBlobs(args, sizes_config):
  """Get binary size data and contained blobs for packages specified in args.

  If "total_size_name" is set, then computes a synthetic package size which is
  the aggregated sizes across all packages."""

  # Calculate compressed and uncompressed package sizes.
  package_blobs = GetPackageBlobs(sizes_config['far_files'], args.build_out_dir)
  package_sizes = GetPackageSizes(package_blobs)

  # Optionally calculate total compressed and uncompressed package sizes.
  if 'far_total_name' in sizes_config:
    compressed = sum([a.compressed for a in package_sizes.values()])
    uncompressed = sum([a.uncompressed for a in package_sizes.values()])
    package_sizes[sizes_config['far_total_name']] = PackageSizes(
        compressed, uncompressed)

  for name, size in package_sizes.items():
    print('%s: compressed size %d, uncompressed size %d' %
          (name, size.compressed, size.uncompressed))

  return package_sizes, package_blobs


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--build-out-dir',
      '--output-directory',
      type=os.path.realpath,
      required=True,
      help='Location of the build artifacts.',
  )
  parser.add_argument(
      '--isolated-script-test-output',
      type=os.path.realpath,
      help='File to which simplified JSON results will be written.')
  parser.add_argument(
      '--size-plugin-json-path',
      help='Optional path for json size data for the Gerrit binary size plugin',
  )
  parser.add_argument(
      '--sizes-path',
      default=os.path.join('tools', 'fuchsia', 'size_tests', 'fyi_sizes.json'),
      help='path to package size limits json file.  The path is relative to '
      'the workspace src directory')
  parser.add_argument('--verbose',
                      '-v',
                      action='store_true',
                      help='Enable verbose output')
  # Accepted to conform to the isolated script interface, but ignored.
  parser.add_argument('--isolated-script-test-filter', help=argparse.SUPPRESS)
  parser.add_argument('--isolated-script-test-perf-output',
                      help=argparse.SUPPRESS)
  args = parser.parse_args()

  if args.verbose:
    print('Fuchsia binary sizes')
    print('Working directory', os.getcwd())
    print('Args:')
    for var in vars(args):
      print('  {}: {}'.format(var, getattr(args, var) or ''))

  if not os.path.isdir(args.build_out_dir):
    raise Exception('Could not find build output directory "%s".' %
                    args.build_out_dir)

  with open(os.path.join(DIR_SRC_ROOT, args.sizes_path)) as sizes_file:
    sizes_config = json.load(sizes_file)

  if args.verbose:
    print('Sizes Config:')
    print(json.dumps(sizes_config))

  for far_rel_path in sizes_config['far_files']:
    far_abs_path = os.path.join(args.build_out_dir, far_rel_path)
    if not os.path.isfile(far_abs_path):
      raise Exception('Could not find FAR file "%s".' % far_abs_path)

  test_name = 'sizes'
  timestamp = time.time()
  test_completed = False
  all_tests_passed = False
  test_status = {}
  package_sizes = {}
  package_blobs = {}
  sizes_histogram = []

  results_directory = None
  if args.isolated_script_test_output:
    results_directory = os.path.join(
        os.path.dirname(args.isolated_script_test_output), test_name)
    if not os.path.exists(results_directory):
      os.makedirs(results_directory)

  try:
    package_sizes, package_blobs = GetBinarySizesAndBlobs(args, sizes_config)
    sizes_histogram = CreateSizesHistogram(package_sizes)
    test_completed = True
  except:
    _, value, trace = sys.exc_info()
    traceback.print_tb(trace)
    print(str(value))
  finally:
    all_tests_passed, test_status = GetTestStatus(package_sizes, sizes_config,
                                                  test_completed)

    if results_directory:
      WriteTestResults(os.path.join(results_directory, 'test_results.json'),
                       test_completed, test_status, timestamp)
      with open(os.path.join(results_directory, 'perf_results.json'), 'w') as f:
        json.dump(sizes_histogram, f)
      WritePackageBlobsJson(
          os.path.join(results_directory, PACKAGES_BLOBS_FILE), package_blobs)
      WritePackageSizesJson(
          os.path.join(results_directory, PACKAGES_SIZES_FILE), package_sizes)

    if args.isolated_script_test_output:
      WriteTestResults(args.isolated_script_test_output, test_completed,
                       test_status, timestamp)

    if args.size_plugin_json_path:
      WriteGerritPluginSizeData(args.size_plugin_json_path, package_sizes)

    return 0 if all_tests_passed else 1


if __name__ == '__main__':
  sys.exit(main())
