All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.internal.expectations.invocation.ArgumentValuesAndMatchers Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for automated developer testing. It contains mocking/faking APIs and a code coverage tool, supporting both JUnit and TestNG. The mocking APIs allow all kinds of Java code, without testability restrictions, to be tested in isolation from selected dependencies.

There is a newer version: 1.49
Show newest version
/*
 * Copyright (c) 2006 JMockit developers
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.internal.expectations.invocation;

import java.util.*;
import javax.annotation.*;

import mockit.internal.expectations.argumentMatching.*;

abstract class ArgumentValuesAndMatchers
{
   @Nonnull final InvocationArguments signature;
   @Nonnull Object[] values;
   @Nullable List> matchers;

   ArgumentValuesAndMatchers(@Nonnull InvocationArguments signature, @Nonnull Object[] values) {
      this.signature = signature;
      this.values = values;
   }

   final void setValuesWithNoMatchers(@Nonnull Object[] argsToVerify) { setValuesAndMatchers(argsToVerify, null); }

   @Nonnull
   final Object[] prepareForVerification(@Nonnull Object[] argsToVerify, @Nullable List> matchersToUse) {
      Object[] replayArgs = values;
      setValuesAndMatchers(argsToVerify, matchersToUse);
      return replayArgs;
   }

   final void setValuesAndMatchers(@Nonnull Object[] argsToVerify, @Nullable List> matchersToUse) {
      values = argsToVerify;
      matchers = matchersToUse;
   }

   @Nullable
   final ArgumentMatcher getArgumentMatcher(@Nonnegative int parameterIndex) {
      if (matchers == null) {
         return null;
      }

      ArgumentMatcher matcher = parameterIndex < matchers.size() ? matchers.get(parameterIndex) : null;

      if (matcher == null && parameterIndex < values.length && values[parameterIndex] == null) {
         matcher = AlwaysTrueMatcher.ANY_VALUE;
      }

      return matcher;
   }

   abstract boolean isMatch(@Nonnull Object[] replayArgs, @Nonnull Map instanceMap);

   static boolean areEqual(
      @Nonnull Object[] expectedValues, @Nonnull Object[] actualValues, @Nonnegative int count, @Nonnull Map instanceMap
   ) {
      for (int i = 0; i < count; i++) {
         if (isNotEqual(expectedValues[i], actualValues[i], instanceMap)) {
            return false;
         }
      }

      return true;
   }

   private static boolean isNotEqual(@Nullable Object expected, @Nullable Object actual, @Nonnull Map instanceMap) {
      return
         actual == null && expected != null ||
         actual != null && expected == null ||
         actual != null && actual != expected && expected != instanceMap.get(actual) &&
         !EqualityMatcher.areEqualWhenNonNull(actual, expected);
   }

   @Nullable
   abstract Error assertMatch(@Nonnull Object[] replayArgs, @Nonnull Map instanceMap);

   @Nullable
   final Error assertEquals(
      @Nonnull Object[] expectedValues, @Nonnull Object[] actualValues, @Nonnegative int count, @Nonnull Map instanceMap
   ) {
      for (int i = 0; i < count; i++) {
         Object expected = expectedValues[i];
         Object actual = actualValues[i];

         if (isNotEqual(expected, actual, instanceMap)) {
            return signature.argumentMismatchMessage(i, expected, actual);
         }
      }

      return null;
   }

   abstract boolean hasEquivalentMatchers(@Nonnull ArgumentValuesAndMatchers other);

   private static boolean equivalentMatches(
      @Nonnull ArgumentMatcher matcher1, @Nullable Object arg1, @Nonnull ArgumentMatcher matcher2, @Nullable Object arg2
   ) {
      boolean matcher1MatchesArg2 = matcher1.matches(arg2);
      boolean matcher2MatchesArg1 = matcher2.matches(arg1);

      if (arg1 != null && arg2 != null && matcher1MatchesArg2 && matcher2MatchesArg1) {
         return true;
      }

      if (arg1 == arg2 && matcher1MatchesArg2 == matcher2MatchesArg1) { // both matchers fail
         ArgumentMismatch desc1 = new ArgumentMismatch();
         matcher1.writeMismatchPhrase(desc1);
         ArgumentMismatch desc2 = new ArgumentMismatch();
         matcher2.writeMismatchPhrase(desc2);
         return desc1.toString().equals(desc2.toString());
      }

      return false;
   }

   @SuppressWarnings("unchecked")
   final , M2 extends ArgumentMatcher> int indexOfFirstValueAfterEquivalentMatchers(
      @Nonnull ArgumentValuesAndMatchers other
   ) {
      List> otherMatchers = other.matchers;

      if (hasDifferentAmountOfMatchers(otherMatchers)) {
         return -1;
      }

      //noinspection ConstantConditions
      int m = matchers.size();
      int i;

      for (i = 0; i < m; i++) {
         M1 matcher1 = (M1) matchers.get(i);
         M2 matcher2 = (M2) otherMatchers.get(i);

         if (matcher1 == null || matcher2 == null) {
            if (!EqualityMatcher.areEqual(values[i], other.values[i])) {
               return -1;
            }
         }
         else if (matcher1 != matcher2) {
            if (matcher1.getClass() != matcher2.getClass()) {
               return -1;
            }

            if (!matcher1.same((M1) matcher2) && areNonEquivalentMatches(other, matcher1, matcher2, i)) {
               return -1;
            }
         }
      }

      return i;
   }

   private boolean hasDifferentAmountOfMatchers(@Nullable List> otherMatchers) {
      return otherMatchers == null || matchers == null || otherMatchers.size() != matchers.size();
   }

   private boolean areNonEquivalentMatches(
      @Nonnull ArgumentValuesAndMatchers other, @Nonnull ArgumentMatcher matcher1, @Nonnull ArgumentMatcher matcher2,
      @Nonnegative int matcherIndex
   ) {
      Class matcherClass = matcher1.getClass();
      return
         matcherClass == ReflectiveMatcher.class || matcherClass == HamcrestAdapter.class ||
         !equivalentMatches(matcher1, values[matcherIndex], matcher2, other.values[matcherIndex]);
   }

   @Nonnull
   final String toString(@Nonnull List parameterTypes) {
      ArgumentMismatch desc = new ArgumentMismatch();
      int parameterCount = values.length;

      if (parameterCount > 0) {
         if (matchers == null) {
            desc.appendFormatted(values);
         }
         else {
            String sep = "";

            for (int i = 0; i < parameterCount; i++) {
               ArgumentMatcher matcher = getArgumentMatcher(i);
               String parameterType = parameterTypes.get(i);
               desc.append(sep).appendFormatted(parameterType, values[i], matcher);
               sep = ", ";
            }
         }

         desc.append(')');
      }

      return desc.toString();
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy