1/* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5package org.mockito.internal.invocation; 6 7import org.hamcrest.Matcher; 8import org.mockito.internal.matchers.MatcherDecorator; 9import org.mockito.internal.matchers.VarargMatcher; 10import org.mockito.invocation.Invocation; 11 12import java.util.List; 13 14@SuppressWarnings("unchecked") 15public class ArgumentsComparator { 16 public boolean argumentsMatch(InvocationMatcher invocationMatcher, Invocation actual) { 17 Object[] actualArgs = actual.getArguments(); 18 return argumentsMatch(invocationMatcher, actualArgs) || varArgsMatch(invocationMatcher, actual); 19 } 20 21 public boolean argumentsMatch(InvocationMatcher invocationMatcher, Object[] actualArgs) { 22 if (actualArgs.length != invocationMatcher.getMatchers().size()) { 23 return false; 24 } 25 for (int i = 0; i < actualArgs.length; i++) { 26 if (!invocationMatcher.getMatchers().get(i).matches(actualArgs[i])) { 27 return false; 28 } 29 } 30 return true; 31 } 32 33 //ok, this method is a little bit messy but the vararg business unfortunately is messy... 34 private boolean varArgsMatch(InvocationMatcher invocationMatcher, Invocation actual) { 35 if (!actual.getMethod().isVarArgs()) { 36 //if the method is not vararg forget about it 37 return false; 38 } 39 40 //we must use raw arguments, not arguments... 41 Object[] rawArgs = actual.getRawArguments(); 42 List<Matcher> matchers = invocationMatcher.getMatchers(); 43 44 if (rawArgs.length != matchers.size()) { 45 return false; 46 } 47 48 for (int i = 0; i < rawArgs.length; i++) { 49 Matcher m = matchers.get(i); 50 //it's a vararg because it's the last array in the arg list 51 if (rawArgs[i] != null && rawArgs[i].getClass().isArray() && i == rawArgs.length-1) { 52 Matcher actualMatcher; 53 //this is necessary as the framework often decorates matchers 54 if (m instanceof MatcherDecorator) { 55 actualMatcher = ((MatcherDecorator)m).getActualMatcher(); 56 } else { 57 actualMatcher = m; 58 } 59 //this is very important to only allow VarargMatchers here. If you're not sure why remove it and run all tests. 60 if (!(actualMatcher instanceof VarargMatcher) || !actualMatcher.matches(rawArgs[i])) { 61 return false; 62 } 63 //it's not a vararg (i.e. some ordinary argument before varargs), just do the ordinary check 64 } else if (!m.matches(rawArgs[i])){ 65 return false; 66 } 67 } 68 69 return true; 70 } 71}