View Javadoc
1   /*
2    * Copyright (c) 2006 JMockit developers
3    * This file is subject to the terms of the MIT license (see LICENSE.txt).
4    */
5   package mockit.internal.expectations;
6   
7   import edu.umd.cs.findbugs.annotations.NonNull;
8   import edu.umd.cs.findbugs.annotations.Nullable;
9   
10  import java.util.ArrayList;
11  import java.util.List;
12  
13  import mockit.internal.expectations.invocation.ExpectedInvocation;
14  import mockit.internal.expectations.invocation.InvocationArguments;
15  import mockit.internal.util.ClassLoad;
16  
17  import org.checkerframework.checker.index.qual.NonNegative;
18  
19  final class FullVerificationPhase extends UnorderedVerificationPhase {
20      @NonNull
21      private final Object[] mockedTypesAndInstancesToVerify;
22  
23      FullVerificationPhase(@NonNull ReplayPhase replayPhase, @NonNull Object[] mockedTypesAndInstancesToVerify) {
24          super(replayPhase);
25          this.mockedTypesAndInstancesToVerify = mockedTypesAndInstancesToVerify;
26      }
27  
28      @Nullable
29      @Override
30      Error endVerification() {
31          if (pendingError != null) {
32              return pendingError;
33          }
34  
35          List<Expectation> expectationsInReplayOrder = replayPhase.invocations;
36          List<Expectation> notVerified = new ArrayList<>();
37  
38          for (int i = 0, n = expectationsInReplayOrder.size(); i < n; i++) {
39              Expectation replayExpectation = expectationsInReplayOrder.get(i);
40  
41              if (replayExpectation != null && isEligibleForFullVerification(replayExpectation)) {
42                  Object[] replayArgs = replayPhase.invocationArguments.get(i);
43  
44                  if (!wasVerified(replayExpectation, replayArgs, i)) {
45                      notVerified.add(replayExpectation);
46                  }
47              }
48          }
49  
50          if (!notVerified.isEmpty()) {
51              if (mockedTypesAndInstancesToVerify.length == 0) {
52                  Expectation firstUnexpected = notVerified.get(0);
53                  return firstUnexpected.invocation.errorForUnexpectedInvocation();
54              }
55  
56              return validateThatUnverifiedInvocationsAreAllowed(notVerified);
57          }
58  
59          return null;
60      }
61  
62      private static boolean isEligibleForFullVerification(@NonNull Expectation replayExpectation) {
63          return !replayExpectation.executedRealImplementation && replayExpectation.constraints.minInvocations <= 0;
64      }
65  
66      private boolean wasVerified(@NonNull Expectation replayExpectation, @NonNull Object[] replayArgs,
67              @NonNegative int expectationIndex) {
68          InvocationArguments invokedArgs = replayExpectation.invocation.arguments;
69          List<VerifiedExpectation> verifiedExpectations = executionState.verifiedExpectations;
70  
71          for (VerifiedExpectation verified : verifiedExpectations) {
72              if (verified.expectation == replayExpectation) {
73                  Object[] storedArgs = invokedArgs.prepareForVerification(verified.arguments, verified.argMatchers);
74                  boolean argumentsMatch = invokedArgs.isMatch(replayArgs, getInstanceMap());
75                  invokedArgs.setValuesWithNoMatchers(storedArgs);
76  
77                  if (argumentsMatch && verified.matchesReplayIndex(expectationIndex)) {
78                      return true;
79                  }
80              }
81          }
82  
83          invokedArgs.setValuesWithNoMatchers(replayArgs);
84          return false;
85      }
86  
87      @Nullable
88      private Error validateThatUnverifiedInvocationsAreAllowed(@NonNull List<Expectation> unverified) {
89          for (Expectation expectation : unverified) {
90              ExpectedInvocation invocation = expectation.invocation;
91  
92              if (isInvocationToBeVerified(invocation)) {
93                  return invocation.errorForUnexpectedInvocation();
94              }
95          }
96  
97          return null;
98      }
99  
100     private boolean isInvocationToBeVerified(@NonNull ExpectedInvocation unverifiedInvocation) {
101         String invokedClassName = unverifiedInvocation.getClassName();
102         Object invokedInstance = unverifiedInvocation.instance;
103 
104         for (Object mockedTypeOrInstance : mockedTypesAndInstancesToVerify) {
105             if (mockedTypeOrInstance instanceof Class) {
106                 Class<?> mockedType = (Class<?>) mockedTypeOrInstance;
107 
108                 if (invokedClassName.equals(mockedType.getName())) {
109                     return true;
110                 }
111             } else if (invokedInstance == null) {
112                 ClassLoader loader = mockedTypeOrInstance.getClass().getClassLoader();
113                 Class<?> invokedClass = ClassLoad.loadFromLoader(loader, invokedClassName);
114 
115                 if (invokedClass.isInstance(mockedTypeOrInstance)) {
116                     return true;
117                 }
118             } else if (unverifiedInvocation.matchInstance) {
119                 if (mockedTypeOrInstance == invokedInstance) {
120                     return true;
121                 }
122             } else if (invokedInstance.getClass().isInstance(mockedTypeOrInstance)) {
123                 return true;
124             }
125         }
126 
127         return false;
128     }
129 }