• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2007 Mockito contributors
3  * This program is made available under the terms of the MIT License.
4  */
5 
6 package org.mockito.internal.invocation;
7 
8 import java.util.LinkedList;
9 import java.util.List;
10 
11 import org.mockito.internal.util.collections.ListUtil;
12 import org.mockito.internal.util.collections.ListUtil.Filter;
13 import org.mockito.internal.verification.api.InOrderContext;
14 import org.mockito.invocation.Invocation;
15 import org.mockito.invocation.Location;
16 import org.mockito.invocation.MatchableInvocation;
17 
18 public class InvocationsFinder {
19 
InvocationsFinder()20     private InvocationsFinder() {
21     }
22 
findInvocations(List<Invocation> invocations, MatchableInvocation wanted)23     public static List<Invocation> findInvocations(List<Invocation> invocations, MatchableInvocation wanted) {
24         return ListUtil.filter(invocations, new RemoveNotMatching(wanted));
25     }
26 
findAllMatchingUnverifiedChunks(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext orderingContext)27     public static List<Invocation> findAllMatchingUnverifiedChunks(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext orderingContext) {
28         List<Invocation> unverified = removeVerifiedInOrder(invocations, orderingContext);
29         return ListUtil.filter(unverified, new RemoveNotMatching(wanted));
30     }
31 
32     /**
33      * some examples how it works:
34      *
35      * Given invocations sequence:
36      * 1,1,2,1
37      *
38      * if wanted is 1 and mode is times(2) then returns
39      * 1,1
40      *
41      * if wanted is 1 and mode is atLeast() then returns
42      * 1,1,1
43      *
44      * if wanted is 1 and mode is times(x), where x != 2 then returns
45      * 1,1,1
46      */
findMatchingChunk(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount, InOrderContext context)47     public static List<Invocation> findMatchingChunk(List<Invocation> invocations, MatchableInvocation wanted, int wantedCount, InOrderContext context) {
48         List<Invocation> unverified = removeVerifiedInOrder(invocations, context);
49         List<Invocation> firstChunk = getFirstMatchingChunk(wanted, unverified);
50 
51         if (wantedCount != firstChunk.size()) {
52             return findAllMatchingUnverifiedChunks(invocations, wanted, context);
53         } else {
54             return firstChunk;
55         }
56     }
57 
getFirstMatchingChunk(MatchableInvocation wanted, List<Invocation> unverified)58     private static List<Invocation> getFirstMatchingChunk(MatchableInvocation wanted, List<Invocation> unverified) {
59         List<Invocation> firstChunk = new LinkedList<Invocation>();
60         for (Invocation invocation : unverified) {
61             if (wanted.matches(invocation)) {
62                 firstChunk.add(invocation);
63             } else if (!firstChunk.isEmpty()) {
64                 break;
65             }
66         }
67         return firstChunk;
68     }
69 
findFirstMatchingUnverifiedInvocation(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext context )70     public static Invocation findFirstMatchingUnverifiedInvocation(List<Invocation> invocations, MatchableInvocation wanted, InOrderContext context ){
71         for( Invocation invocation : removeVerifiedInOrder( invocations, context )){
72             if( wanted.matches( invocation )){
73                 return invocation;
74             }
75         }
76         return null;
77     }
78 
findSimilarInvocation(List<Invocation> invocations, MatchableInvocation wanted)79     public static Invocation findSimilarInvocation(List<Invocation> invocations, MatchableInvocation wanted) {
80         Invocation firstSimilar = null;
81         for (Invocation invocation : invocations) {
82             if (!wanted.hasSimilarMethod(invocation)) {
83                 continue;
84             }
85             if (firstSimilar == null) {
86                 firstSimilar = invocation;
87             }
88             if (wanted.hasSameMethod(invocation)) {
89                 return invocation;
90             }
91         }
92 
93         return firstSimilar;
94     }
95 
findFirstUnverified(List<Invocation> invocations)96     public static Invocation findFirstUnverified(List<Invocation> invocations) {
97         return findFirstUnverified(invocations, null);
98     }
99 
findFirstUnverified(List<Invocation> invocations, Object mock)100     static Invocation findFirstUnverified(List<Invocation> invocations, Object mock) {
101         for (Invocation i : invocations) {
102             boolean mockIsValid = mock == null || mock == i.getMock();
103             if (!i.isVerified() && mockIsValid) {
104                 return i;
105             }
106         }
107         return null;
108     }
109 
getLastLocation(List<Invocation> invocations)110     public static Location getLastLocation(List<Invocation> invocations) {
111         if (invocations.isEmpty()) {
112             return null;
113         } else {
114             Invocation last = invocations.get(invocations.size() - 1);
115             return last.getLocation();
116         }
117     }
118 
findPreviousVerifiedInOrder(List<Invocation> invocations, InOrderContext context)119     public static Invocation findPreviousVerifiedInOrder(List<Invocation> invocations, InOrderContext context) {
120         LinkedList<Invocation> verifiedOnly = ListUtil.filter(invocations, new RemoveUnverifiedInOrder(context));
121 
122         if (verifiedOnly.isEmpty()) {
123             return null;
124         } else {
125             return verifiedOnly.getLast();
126         }
127     }
128 
removeVerifiedInOrder(List<Invocation> invocations, InOrderContext orderingContext)129     private static List<Invocation> removeVerifiedInOrder(List<Invocation> invocations, InOrderContext orderingContext) {
130         List<Invocation> unverified = new LinkedList<Invocation>();
131         for (Invocation i : invocations) {
132             if (orderingContext.isVerified(i)) {
133                 unverified.clear();
134             } else {
135                 unverified.add(i);
136             }
137         }
138         return unverified;
139     }
140 
141     private static class RemoveNotMatching implements Filter<Invocation> {
142         private final MatchableInvocation wanted;
143 
RemoveNotMatching(MatchableInvocation wanted)144         private RemoveNotMatching(MatchableInvocation wanted) {
145             this.wanted = wanted;
146         }
147 
isOut(Invocation invocation)148         public boolean isOut(Invocation invocation) {
149             return !wanted.matches(invocation);
150         }
151     }
152 
153     private static class RemoveUnverifiedInOrder implements Filter<Invocation> {
154         private final InOrderContext orderingContext;
155 
RemoveUnverifiedInOrder(InOrderContext orderingContext)156         public RemoveUnverifiedInOrder(InOrderContext orderingContext) {
157             this.orderingContext = orderingContext;
158         }
159 
isOut(Invocation invocation)160         public boolean isOut(Invocation invocation) {
161             return !orderingContext.isVerified(invocation);
162         }
163     }
164 
165     /**
166      * i3 is unverified here:
167      *
168      * i1, i2, i3
169      *     v
170      *
171      * all good here:
172      *
173      * i1, i2, i3
174      *     v   v
175      *
176      * @param context
177      * @param orderedInvocations
178      */
findFirstUnverifiedInOrder(InOrderContext context, List<Invocation> orderedInvocations)179     public static Invocation findFirstUnverifiedInOrder(InOrderContext context, List<Invocation> orderedInvocations) {
180         Invocation candidate = null;
181         for(Invocation i : orderedInvocations) {
182             if (!context.isVerified(i)) {
183                 candidate = candidate != null ? candidate : i;
184             } else {
185                 candidate = null;
186             }
187         }
188         return candidate;
189     }
190 }
191