# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Module for dealing with fuzz targets affected by the change-under-test
(CUT)."""
import logging
import os
import sys

# pylint: disable=wrong-import-position,import-error
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import utils


def remove_unaffected_fuzz_targets(clusterfuzz_deployment, out_dir,
                                   files_changed, repo_path):
  """Removes all non affected fuzz targets in the out directory.

  Args:
    clusterfuzz_deployment: The ClusterFuzz deployment object.
    out_dir: The location of the fuzz target binaries.
    files_changed: A list of files changed compared to HEAD.
    repo_path: The location of the OSS-Fuzz repo in the docker image.

  This function will not delete fuzz targets unless it knows that the fuzz
  targets are unaffected. For example, this means that fuzz targets which don't
  have coverage data on will not be deleted.
  """
  if not files_changed:
    # Don't remove any fuzz targets if there is no difference from HEAD.
    logging.info('No files changed compared to HEAD.')
    return

  logging.info('Files changed in PR: %s', files_changed)

  fuzz_target_paths = utils.get_fuzz_targets(out_dir)
  if not fuzz_target_paths:
    # Nothing to remove.
    logging.error('No fuzz targets found in out dir.')
    return

  coverage = clusterfuzz_deployment.get_coverage(repo_path)
  if not coverage:
    # Don't remove any fuzz targets unless we have data.
    logging.error('Could not find latest coverage report.')
    return

  affected_fuzz_targets = get_affected_fuzz_targets(coverage, fuzz_target_paths,
                                                    files_changed)

  if not affected_fuzz_targets:
    logging.info('No affected fuzz targets detected, keeping all as fallback.')
    return

  logging.info('Using affected fuzz targets: %s.', affected_fuzz_targets)
  unaffected_fuzz_targets = set(fuzz_target_paths) - affected_fuzz_targets
  logging.info('Removing unaffected fuzz targets: %s.', unaffected_fuzz_targets)

  # Remove all the targets that are not affected.
  for fuzz_target_path in unaffected_fuzz_targets:
    try:
      os.remove(fuzz_target_path)
    except OSError as error:
      logging.error('%s occurred while removing file %s', error,
                    fuzz_target_path)


def is_fuzz_target_affected(coverage, fuzz_target_path, files_changed):
  """Returns True if a fuzz target (|fuzz_target_path|) is affected by
  |files_changed|."""
  fuzz_target = os.path.basename(fuzz_target_path)
  covered_files = coverage.get_files_covered_by_target(fuzz_target)
  if not covered_files:
    # Assume a fuzz target is affected if we can't get its coverage from
    # OSS-Fuzz.
    # TODO(metzman): Figure out what we should do if covered_files is [].
    # Should we act as if we couldn't get the coverage?
    logging.info('Could not get coverage for %s. Treating as affected.',
                 fuzz_target)
    return True

  logging.info('Fuzz target %s is affected by: %s', fuzz_target, covered_files)
  for filename in files_changed:
    if filename in covered_files:
      logging.info('Fuzz target %s is affected by changed file: %s',
                   fuzz_target, filename)
      return True

  logging.info('Fuzz target %s is not affected.', fuzz_target)
  return False


def get_affected_fuzz_targets(coverage, fuzz_target_paths, files_changed):
  """Returns a list of paths of affected targets."""
  affected_fuzz_targets = set()
  for fuzz_target_path in fuzz_target_paths:
    if is_fuzz_target_affected(coverage, fuzz_target_path, files_changed):
      affected_fuzz_targets.add(fuzz_target_path)

  return affected_fuzz_targets
