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