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