Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 6e8a4779cedc046d1343c9067f5fd15fcbeee80a
Author: Tim van der Lippe <tvanderlippe@gmail.com>
Date:   Tue Jul 5 16:55:04 2016 +0200

    Add two tests to verify subclass extension for generic type retrieval

commit e39c2bc
Author: Christian Schwarz <chriss.dev@github>
Date:   Fri Jul 1 22:16:24 2016 +0200

    Fixes mockito#457 added type compability checks to CompareTo and
    ArgumentsComparator

    Added tests to HashCodeAndEqualsSafeSetTest to satisfy codecov
  • Loading branch information
TimvdLippe authored and Christian Schwarz committed Jul 7, 2016
1 parent 6cd29fd commit 85ff234
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 48 deletions.
10 changes: 5 additions & 5 deletions src/main/java/org/mockito/AdditionalMatchers.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class AdditionalMatchers {
* the given value.
* @return <code>null</code>.
*/
public static <T extends Comparable<T>> T geq(Comparable<T> value) {
public static <T extends Comparable<T>> T geq(T value) {
reportMatcher(new GreaterOrEqual<T>(value));
return null;
}
Expand Down Expand Up @@ -147,7 +147,7 @@ public static short geq(short value) {
* the given value.
* @return <code>null</code>.
*/
public static <T extends Comparable<T>> T leq(Comparable<T> value) {
public static <T extends Comparable<T>> T leq(T value) {
reportMatcher(new LessOrEqual<T>(value));
return null;
}
Expand Down Expand Up @@ -245,7 +245,7 @@ public static short leq(short value) {
* the given value.
* @return <code>null</code>.
*/
public static <T extends Comparable<T>> T gt(Comparable<T> value) {
public static <T extends Comparable<T>> T gt(T value) {
reportMatcher(new GreaterThan<T>(value));
return null;
}
Expand Down Expand Up @@ -343,7 +343,7 @@ public static short gt(short value) {
* the given value.
* @return <code>null</code>.
*/
public static <T extends Comparable<T>> T lt(Comparable<T> value) {
public static <T extends Comparable<T>> T lt(T value) {
reportMatcher(new LessThan<T>(value));
return null;
}
Expand Down Expand Up @@ -442,7 +442,7 @@ public static short lt(short value) {
* the given value.
* @return <code>null</code>.
*/
public static <T extends Comparable<T>> T cmpEq(Comparable<T> value) {
public static <T extends Comparable<T>> T cmpEq(T value) {
reportMatcher(new CompareEqual<T>(value));
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
*/
package org.mockito.internal.invocation;

import java.lang.reflect.Method;
import java.util.List;
import org.mockito.ArgumentMatcher;
import org.mockito.internal.matchers.VarargMatcher;
import org.mockito.invocation.Invocation;

import java.util.List;

@SuppressWarnings("unchecked")
public class ArgumentsComparator {
public boolean argumentsMatch(InvocationMatcher invocationMatcher, Invocation actual) {
Expand All @@ -22,21 +22,24 @@ public boolean argumentsMatch(InvocationMatcher invocationMatcher, Object[] actu
return false;
}
for (int i = 0; i < actualArgs.length; i++) {
if (!invocationMatcher.getMatchers().get(i).matches(actualArgs[i])) {
ArgumentMatcher<Object> argumentMatcher = invocationMatcher.getMatchers().get(i);
Object argument = actualArgs[i];

if (!matches(argumentMatcher, argument)) {
return false;
}
}
return true;
}

//ok, this method is a little bit messy but the vararg business unfortunately is messy...
private boolean varArgsMatch(InvocationMatcher invocationMatcher, Invocation actual) {
// ok, this method is a little bit messy but the vararg business unfortunately is messy...
private static boolean varArgsMatch(InvocationMatcher invocationMatcher, Invocation actual) {
if (!actual.getMethod().isVarArgs()) {
//if the method is not vararg forget about it
// if the method is not vararg forget about it
return false;
}

//we must use raw arguments, not arguments...
// we must use raw arguments, not arguments...
Object[] rawArgs = actual.getRawArguments();
List<ArgumentMatcher> matchers = invocationMatcher.getMatchers();

Expand All @@ -46,18 +49,66 @@ private boolean varArgsMatch(InvocationMatcher invocationMatcher, Invocation act

for (int i = 0; i < rawArgs.length; i++) {
ArgumentMatcher m = matchers.get(i);
//it's a vararg because it's the last array in the arg list
if (rawArgs[i] != null && rawArgs[i].getClass().isArray() && i == rawArgs.length-1) {
//this is very important to only allow VarargMatchers here. If you're not sure why remove it and run all tests.
// it's a vararg because it's the last array in the arg list
if (rawArgs[i] != null && rawArgs[i].getClass().isArray() && i == rawArgs.length - 1) {
// this is very important to only allow VarargMatchers here. If
// you're not sure why remove it and run all tests.
if (!(m instanceof VarargMatcher) || !m.matches(rawArgs[i])) {
return false;
}
//it's not a vararg (i.e. some ordinary argument before varargs), just do the ordinary check
} else if (!m.matches(rawArgs[i])){
// it's not a vararg (i.e. some ordinary argument before
// varargs), just do the ordinary check
} else if (!m.matches(rawArgs[i])) {
return false;
}
}

return true;
}
}

private static boolean matches(ArgumentMatcher<Object> argumentMatcher, Object argument) {
return isCompatible(argumentMatcher, argument) && argumentMatcher.matches(argument);
}

/**
* Returns <code>true</code> if the given <b>argument</b> can be passed to
* the given <code>argumentMatcher</code> without causing a
* {@link ClassCastException}.
*/
private static boolean isCompatible(ArgumentMatcher<?> argumentMatcher, Object argument) {
if (argument == null)
return true;

Class<?> expectedArgumentType = getArgumentType(argumentMatcher);

return expectedArgumentType.isInstance(argument);
}

/**
* Returns the type of {@link ArgumentMatcher#matches(Object)} of the given
* {@link ArgumentMatcher} implementation.
*/
private static Class<?> getArgumentType(ArgumentMatcher<?> argumentMatcher) {
Method[] methods = argumentMatcher.getClass().getMethods();
for (Method method : methods) {
if (isMatchesMethod(method)) {
return method.getParameterTypes()[0];
}
}
throw new NoSuchMethodError("Method 'matches(T)' not found in ArgumentMatcher: " + argumentMatcher + " !\r\n Please file a bug with this stack trace at: https://github.com/mockito/mockito/issues/new ");
}

/**
* Returns <code>true</code> if the given method is
* {@link ArgumentMatcher#matches(Object)}
*/
private static boolean isMatchesMethod(Method method) {
if (method.getParameterTypes().length != 1) {
return false;
}
if (method.isBridge()) {
return false;
}
return method.getName().equals("matches");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public class CompareEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {

public CompareEqual(Comparable<T> value) {
public CompareEqual(T value) {
super(value);
}

Expand Down
26 changes: 17 additions & 9 deletions src/main/java/org/mockito/internal/matchers/CompareTo.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,32 @@

import java.io.Serializable;


public abstract class CompareTo<T extends Comparable<T>> implements ArgumentMatcher<T>, Serializable {
private final Comparable<T> wanted;
private final T wanted;

public CompareTo(Comparable<T> value) {
public CompareTo(T value) {
this.wanted = value;
}

@SuppressWarnings("unchecked")
public boolean matches(T actual) {
return matchResult(((Comparable)actual).compareTo(wanted));
@Override
public final boolean matches(T actual) {
if (actual == null) {
return false;
}
if (!actual.getClass().isInstance(wanted)){
return false;
}

int result = actual.compareTo(wanted);
return matchResult(result);
}

public String toString() {
@Override
public final String toString() {
return getName() + "(" + wanted + ")";
}

protected abstract String getName();

protected abstract boolean matchResult(int result);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public class GreaterOrEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {

public GreaterOrEqual(Comparable<T> value) {
public GreaterOrEqual(T value) {
super(value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public class GreaterThan<T extends Comparable<T>> extends CompareTo<T> implements Serializable {

public GreaterThan(Comparable<T> value) {
public GreaterThan(T value) {
super(value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public class LessOrEqual<T extends Comparable<T>> extends CompareTo<T> implements Serializable {

public LessOrEqual(Comparable<T> value) {
public LessOrEqual(T value) {
super(value);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/mockito/internal/matchers/LessThan.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

public class LessThan<T extends Comparable<T>> extends CompareTo<T> implements Serializable {

public LessThan(Comparable<T> value) {
public LessThan(T value) {
super(value);
}

Expand Down
Loading

0 comments on commit 85ff234

Please sign in to comment.