// 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.Joiner;
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.common.collect.Sets;
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.Comparator;
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 {

  public static <T> void assertEquals(T expected, T actual, Comparator<T> comp) {
    assertThat(comp.compare(expected, actual)).isEqualTo(0);
  }

  /**
   * 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;
  }

  private static String getClassDescription(Object object) {
    return object == null
        ? "null"
        : ("instance of " + object.getClass().getName());
  }

  public static String chattyFormat(String message, Object expected, Object actual) {
    String expectedClass = getClassDescription(expected);
    String actualClass = getClassDescription(actual);

    return Joiner.on('\n').join((message != null) ? ("\n" + message) : "",
        "  expected " + expectedClass + ": <" + expected + ">",
        "  but was " + actualClass + ": <" + actual + ">");
  }

  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 assertStdoutContainsString(String expected, String stdout, String stderr) {
    if (!stdout.contains(expected)) {
      fail("expected stdout to contain string <" + expected + "> but stdout was <"
          + stdout + "> and stderr was <" + 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 + ">");
    }
  }

  public static Set<String> asStringSet(Iterable<?> collection) {
    Set<String> set = Sets.newTreeSet();
    for (Object o : collection) {
      set.add("\"" + o + "\"");
    }
    return set;
  }

  /**
   * 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
   * 'expectedEvent' as a substring, an informative assertion fails.
   */
  public static void assertDoesNotContainEvent(Iterable<Event> eventCollector,
                                          String expectedEvent) {
    for (Event event : eventCollector) {
      assertWithMessage("Unexpected string '" + expectedEvent + "' matched following event:\n"
          + event.getMessage()).that(event.getMessage()).doesNotContain(expectedEvent);
    }
  }

  /**
   * If the specified EventCollector does not contain an event which has
   * each of {@code words} surrounded by single quotes as a substring, an
   * informative assertion fails.  Otherwise the matching event is returned.
   */
  public static Event assertContainsEventWithWordsInQuotes(
      Iterable<Event> eventCollector,
      String... words) {
    for (Event event : eventCollector) {
      boolean found = true;
      for (String word : words) {
        if (!event.getMessage().contains("'" + word + "'")) {
          found = false;
          break;
        }
      }
      if (found) {
        return event;
      }
    }
    String eventsString = eventsToString(eventCollector);
    assertWithMessage("Event containing words " + Arrays.toString(words) + " in "
        + "single quotes not found"
        + (eventsString.length() == 0 ? "" : ("; found these though:" + eventsString)))
        .that(false).isTrue();
    return null; // unreachable
  }

  /**
   * 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 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;
  }
}
