1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/*
2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Copyright (c) 2007 Mockito contributors
3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This program is made available under the terms of the MIT License.
4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */
5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpackage org.mockito.internal.verification.argumentmatching;
6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.LinkedList;
8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.List;
9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.hamcrest.Matcher;
11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.hamcrest.StringDescription;
12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.matchers.ContainsExtraTypeInformation;
13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson@SuppressWarnings("unchecked")
15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpublic class ArgumentMatchingTool {
16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    /**
18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * Suspiciously not matching arguments are those that don't match, the toString() representation is the same but types are different.
19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     */
20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public Integer[] getSuspiciouslyNotMatchingArgsIndexes(List<Matcher> matchers, Object[] arguments) {
21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if (matchers.size() != arguments.length) {
22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return new Integer[0];
23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        List<Integer> suspicious = new LinkedList<Integer>();
26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        int i = 0;
27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        for (Matcher m : matchers) {
28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            if (m instanceof ContainsExtraTypeInformation
29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    && !safelyMatches(m, arguments[i])
30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    && toStringEquals(m, arguments[i])
31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    && !((ContainsExtraTypeInformation) m).typeMatches(arguments[i])) {
32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                suspicious.add(i);
33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            }
34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            i++;
35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return suspicious.toArray(new Integer[0]);
37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    private boolean safelyMatches(Matcher m, Object arg) {
40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        try {
41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return m.matches(arg);
42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        } catch (Throwable t) {
43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            return false;
44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    private boolean toStringEquals(Matcher m, Object arg) {
48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return StringDescription.toString(m).equals(arg == null? "null" : arg.toString());
49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson}
51