// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.
package com.google.devtools.build.lib.testutil;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.fail;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.io.RecordingOutErr;
import java.lang.ref.Reference;
import java.lang.reflect.Field;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.regex.Pattern;

/** A helper class for tests providing a simple interface for asserts. */
public class MoreAsserts {

  /**
   * Scans if an instance of given class is strongly reachable from a given object.
   *
   * <p>Runs breadth-first search in object reachability graph to check if an instance of <code>clz
   * </code> can be reached. <strong>Note:</strong> This method can take a long time if analyzed
   * data structure spans across large part of heap and may need a lot of memory.
   *
   * @param start object to start the search from
   * @param clazz class to look for
   */
  public static void assertInstanceOfNotReachable(Object start, final Class<?> clazz) {
    Predicate<Object> p = obj -> clazz.isAssignableFrom(obj.getClass());
    if (isRetained(p, start)) {
      fail("Found an instance of " + clazz.getCanonicalName() + " reachable from " + start);
    }
  }

  private static final Field NON_STRONG_REF;

  static {
    try {
      NON_STRONG_REF = Reference.class.getDeclaredField("referent");
    } catch (SecurityException | NoSuchFieldException e) {
      throw new RuntimeException(e);
    }
  }

  static final Predicate<Field> ALL_STRONG_REFS = Predicates.equalTo(NON_STRONG_REF);

  private static boolean isRetained(Predicate<Object> predicate, Object start) {
    IdentityHashMap<Object, Object> visited = Maps.newIdentityHashMap();
    visited.put(start, start);
    Queue<Object> toScan = new ArrayDeque<>();
    toScan.add(start);

    while (!toScan.isEmpty()) {
      Object current = toScan.poll();
      if (current.getClass().isArray()) {
        if (current.getClass().getComponentType().isPrimitive()) {
          continue;
        }

        for (Object ref : (Object[]) current) {
          if (ref != null) {
            if (predicate.apply(ref)) {
              return true;
            }
            if (visited.put(ref, ref) == null) {
              toScan.add(ref);
            }
          }
        }
      } else {
        // iterate *all* fields (getFields() returns only accessible ones)
        for (Class<?> clazz = current.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
          for (Field f : clazz.getDeclaredFields()) {
            if (f.getType().isPrimitive() || ALL_STRONG_REFS.apply(f)) {
              continue;
            }

            try {
              f.setAccessible(true);
            } catch (RuntimeException e) {
              // JDK9 can throw InaccessibleObjectException when internal modules are accessed.
              // This isn't available in JDK8, so catch RuntimeException
              // We can use a JVM arg --add_opens to suppress that, but that involves every
              // test adding every JVM module to the target.
              continue;
            }
            try {
              Object ref = f.get(current);
              if (ref != null) {
                if (predicate.apply(ref)) {
                  return true;
                }
                if (visited.put(ref, ref) == null) {
                  toScan.add(ref);
                }
              }
            } catch (IllegalArgumentException | IllegalAccessException e) {
              throw new IllegalStateException("Error when scanning the heap", e);
            }
          }
        }
      }
    }
    return false;
  }

  public static void assertEqualsUnifyingLineEnds(String expected, String actual) {
    if (actual != null) {
      actual = actual.replaceAll(System.getProperty("line.separator"), "\n");
    }
    assertThat(actual).isEqualTo(expected);
  }

  public static void assertContainsWordsWithQuotes(String message, String... strings) {
    for (String string : strings) {
      assertWithMessage(message + " should contain '" + string + "' (with quotes)")
          .that(message.contains("'" + string + "'"))
          .isTrue();
    }
  }

  public static void assertNonZeroExitCode(int exitCode, String stdout, String stderr) {
    if (exitCode == 0) {
      fail(
          "expected non-zero exit code but exit code was 0 and stdout was <"
              + stdout
              + "> and stderr was <"
              + stderr
              + ">");
    }
  }

  public static void assertZeroExitCode(int exitCode, String stdout, String stderr) {
    assertExitCode(0, exitCode, stdout, stderr);
  }

  public static void assertZeroExitCode(int exitCode, RecordingOutErr recordingOutErr) {
    assertExitCode(0, exitCode, recordingOutErr.outAsLatin1(), recordingOutErr.errAsLatin1());
  }

  public static void assertExitCode(
      int expectedExitCode, int exitCode, String stdout, String stderr) {
    if (exitCode != expectedExitCode) {
      fail(
          String.format(
              "expected exit code <%d> but exit code was <%d> and stdout was <%s> "
                  + "and stderr was <%s>",
              expectedExitCode, exitCode, stdout, stderr));
    }
  }

  public static void assertExitCode(
      int expectedExitCode, int exitCode, RecordingOutErr recordingOutErr) {
    assertExitCode(
        expectedExitCode, exitCode, recordingOutErr.outAsLatin1(), recordingOutErr.errAsLatin1());
  }

  public static void assertEqualWithStdoutAndErr(
      Object expected, Object actual, String stdout, String stderr) {
    if (!expected.equals(actual)) {
      fail(
          String.format(
              "expected <%s> but was <%s> and stdout was <%s> and stderr was <%s>",
              expected, actual, stdout, stderr));
    }
  }

  public static void assertStderrContainsString(String expected, String stdout, String stderr) {
    if (!stderr.contains(expected)) {
      fail(
          "expected stderr to contain string <"
              + expected
              + "> but stdout was <"
              + stdout
              + "> and stderr was <"
              + stderr
              + ">");
    }
  }

  public static void assertStdoutContainsRegex(String expectedRegex, String stdout, String stderr) {
    if (!Pattern.compile(expectedRegex).matcher(stdout).find()) {
      fail(
          "expected stdout to contain regex <"
              + expectedRegex
              + "> but stdout was <"
              + stdout
              + "> and stderr was <"
              + stderr
              + ">");
    }
  }

  public static void assertStderrContainsRegex(String expectedRegex, String stdout, String stderr) {
    if (!Pattern.compile(expectedRegex).matcher(stderr).find()) {
      fail(
          "expected stderr to contain regex <"
              + expectedRegex
              + "> but stdout was <"
              + stdout
              + "> and stderr was <"
              + stderr
              + ">");
    }
  }

  /**
   * If the specified EventCollector contains any events, an informative assertion fails in the
   * context of the specified TestCase.
   */
  public static void assertNoEvents(Iterable<Event> eventCollector) {
    String eventsString = eventsToString(eventCollector);
    assertThat(eventsString).isEmpty();
  }

  /**
   * If the specified EventCollector contains an unexpected number of events, an informative
   * assertion fails in the context of the specified TestCase.
   */
  public static void assertEventCount(int expectedCount, EventCollector eventCollector) {
    assertWithMessage(eventsToString(eventCollector))
        .that(eventCollector.count())
        .isEqualTo(expectedCount);
  }

  /**
   * If the specified EventCollector contains an unexpected number of events, an informative
   * assertion fails in the context of the specified TestCase.
   */
  public static void assertEventCountAtLeast(int minCount, EventCollector eventCollector) {
    assertWithMessage(eventsToString(eventCollector))
        .that(eventCollector.count())
        .isAtLeast(minCount);
  }

  /**
   * If the specified EventCollector does not contain an event which has 'expectedEvent' as a
   * substring, an informative assertion fails. Otherwise the matching event is returned.
   */
  public static Event assertContainsEvent(Iterable<Event> eventCollector, String expectedEvent) {
    return assertContainsEvent(eventCollector, expectedEvent, EventKind.ALL_EVENTS);
  }

  /**
   * If the specified EventCollector does not contain an event which has 'expectedEvent' as a
   * substring, an informative assertion fails. Otherwise the matching event is returned.
   */
  public static Event assertContainsEvent(
      Iterable<Event> eventCollector, String expectedEvent, EventKind kind) {
    return assertContainsEvent(eventCollector, expectedEvent, ImmutableSet.of(kind));
  }

  /**
   * If the specified EventCollector does not contain an event of a kind of 'kinds' which has
   * 'expectedEvent' as a substring, an informative assertion fails. Otherwise the matching event is
   * returned.
   */
  public static Event assertContainsEvent(
      Iterable<Event> eventCollector, String expectedEvent, Set<EventKind> kinds) {
    for (Event event : eventCollector) {
      // We want to be able to check for the location and the message type (error / warning).
      // Consequently, we use toString() instead of getMessage().
      if (event.toString().contains(expectedEvent) && kinds.contains(event.getKind())) {
        return event;
      }
    }
    String eventsString = eventsToString(eventCollector);
    assertWithMessage(
            "Event '"
                + expectedEvent
                + "' not found"
                + (eventsString.length() == 0 ? "" : ("; found these though:" + eventsString)))
        .that(false)
        .isTrue();
    return null; // unreachable
  }

  /**
   * If {@code eventCollector} does not contain an event which matches {@code expectedEventPattern},
   * fails with an informative assertion.
   */
  public static Event assertContainsEvent(
      Iterable<Event> eventCollector, Pattern expectedEventPattern, EventKind... kinds) {
    return assertContainsEvent(eventCollector, expectedEventPattern, ImmutableSet.copyOf(kinds));
  }

  /**
   * If {@code eventCollector} does not contain an event which matches {@code expectedEventPattern},
   * fails with an informative assertion.
   */
  public static Event assertContainsEvent(
      Iterable<Event> eventCollector, Pattern expectedEventPattern, Set<EventKind> kinds) {
    for (Event event : eventCollector) {
      // Does the event message match the expected regex?
      if (!expectedEventPattern.matcher(event.toString()).find()) {
        continue;
      }
      // Was an expected kind given, and does the event match?
      if (!kinds.isEmpty() && !kinds.contains(event.getKind())) {
        continue;
      }
      // Return the event, assertion successful
      return event;
    }
    String eventsString = eventsToString(eventCollector);
    String failureMessage = "Event matching '" + expectedEventPattern + "' not found";
    if (!eventsString.isEmpty()) {
      failureMessage += "; found these though: " + eventsString;
    }
    fail(failureMessage);
    return null; // unreachable
  }

  public static void assertNotContainsEvent(
      Iterable<Event> eventCollector, Pattern unexpectedEventPattern) {
    for (Event event : eventCollector) {
      assertThat(event.toString()).doesNotMatch(unexpectedEventPattern);
    }
  }

  /**
   * If the specified EventCollector contains an event which has 'unexpectedEvent' as a substring,
   * an informative assertion fails.
   */
  public static void assertDoesNotContainEvent(
      Iterable<Event> eventCollector, String unexpectedEvent) {
    assertDoesNotContainEvents(eventCollector, unexpectedEvent);
  }

  /**
   * If the specified EventCollector contains an event which has any of 'unexpectedEvents' as a
   * substring, an informative assertion fails.
   */
  public static void assertDoesNotContainEvents(
      Iterable<Event> eventCollector, String... unexpectedEvents) {
    for (Event event : eventCollector) {
      for (String unexpectedEvent : unexpectedEvents) {
        assertWithMessage(
                "Unexpected string '"
                    + unexpectedEvent
                    + "' matched following event:\n"
                    + event.getMessage())
            .that(event.getMessage())
            .doesNotContain(unexpectedEvent);
      }
    }
  }

  /**
   * Returns a string consisting of each event in the specified collector, preceded by a newline.
   */
  private static String eventsToString(Iterable<Event> eventCollector) {
    StringBuilder buf = new StringBuilder();
    eventLoop:
    for (Event event : eventCollector) {
      for (String ignoredPrefix : TestConstants.IGNORED_MESSAGE_PREFIXES) {
        if (event.getMessage().startsWith(ignoredPrefix)) {
          continue eventLoop;
        }
      }
      buf.append('\n').append(event);
    }
    return buf.toString();
  }

  /**
   * If "expectedSublist" is not a sublist of "arguments", an informative assertion is failed in the
   * context of the specified TestCase.
   *
   * <p>Argument order mnemonic: assert(X)ContainsSublist(Y).
   */
  @SuppressWarnings("varargs")
  public static <T> void assertContainsSublist(List<T> arguments, T... expectedSublist) {
    List<T> sublist = Arrays.asList(expectedSublist);
    try {
      assertThat(Collections.indexOfSubList(arguments, sublist)).isNotEqualTo(-1);
    } catch (AssertionError e) {
      throw new AssertionError("Did not find " + sublist + " as a sublist of " + arguments, e);
    }
  }

  /**
   * If "expectedSublist" is a sublist of "arguments", an informative assertion is failed in the
   * context of the specified TestCase.
   *
   * <p>Argument order mnemonic: assert(X)DoesNotContainSublist(Y).
   */
  @SuppressWarnings("varargs")
  public static <T> void assertDoesNotContainSublist(List<T> arguments, T... expectedSublist) {
    List<T> sublist = Arrays.asList(expectedSublist);
    try {
      assertThat(Collections.indexOfSubList(arguments, sublist)).isEqualTo(-1);
    } catch (AssertionError e) {
      throw new AssertionError("Found " + sublist + " as a sublist of " + arguments, e);
    }
  }

  /**
   * Check to see if each element of expectedMessages is the beginning of a message in
   * eventCollector, in order, as in {@link #containsSublistWithGapsAndEqualityChecker}. If not, an
   * informative assertion is failed
   */
  public static void assertContainsEventsInOrder(
      Iterable<Event> eventCollector, String... expectedMessages) {
    String failure =
        containsSublistWithGapsAndEqualityChecker(
            ImmutableList.copyOf(eventCollector),
            pair -> pair.first.getMessage().contains(pair.second),
            expectedMessages);

    String eventsString = eventsToString(eventCollector);
    assertWithMessage(
            "Event '"
                + failure
                + "' not found in proper order"
                + (eventsString.length() == 0 ? "" : ("; found these though:" + eventsString)))
        .that(failure)
        .isNull();
  }

  /**
   * Check to see if each element of expectedSublist is in arguments, according to the
   * equalityChecker, in the same order as in expectedSublist (although with other interspersed
   * elements in arguments allowed).
   *
   * @param equalityChecker function that takes a {@code Pair<S, T>} element and returns true if the
   *     elements of the pair are equal by its lights.
   * @return first element not in arguments in order, or null if success.
   */
  protected static <S, T> T containsSublistWithGapsAndEqualityChecker(
      List<S> arguments, Function<Pair<S, T>, Boolean> equalityChecker, T... expectedSublist) {
    Iterator<S> iter = arguments.iterator();
    outerLoop:
    for (T expected : expectedSublist) {
      while (iter.hasNext()) {
        S actual = iter.next();
        if (equalityChecker.apply(Pair.of(actual, expected))) {
          continue outerLoop;
        }
      }
      return expected;
    }
    return null;
  }

  public static List<Event> assertContainsEventWithFrequency(
      Iterable<Event> events, String expectedMessage, int expectedFrequency) {
    ImmutableList.Builder<Event> builder = ImmutableList.builder();
    for (Event event : events) {
      if (event.getMessage().contains(expectedMessage)) {
        builder.add(event);
      }
    }
    List<Event> foundEvents = builder.build();
    assertWithMessage(events.toString()).that(foundEvents).hasSize(expectedFrequency);
    return foundEvents;
  }
}
