View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.internal.expectations;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import java.util.ArrayList;
12  import java.util.List;
13  
14  import mockit.internal.expectations.invocation.ExpectedInvocation;
15  
16  class UnorderedVerificationPhase extends BaseVerificationPhase {
17      @NonNull
18      private final List<VerifiedExpectation> verifiedExpectations;
19  
20      UnorderedVerificationPhase(@NonNull ReplayPhase replayPhase) {
21          super(replayPhase);
22          verifiedExpectations = new ArrayList<>();
23      }
24  
25      @NonNull
26      @Override
27      final List<ExpectedInvocation> findExpectation(@Nullable Object mock, @NonNull String mockClassDesc,
28              @NonNull String mockNameAndDesc, @NonNull Object[] args) {
29          if (!matchInstance && executionState.isToBeMatchedOnInstance(mock, mockNameAndDesc)) {
30              matchInstance = true;
31          }
32  
33          replayIndex = -1;
34          List<Expectation> expectationsInReplayOrder = replayPhase.invocations;
35          Expectation verification = currentVerification;
36          List<ExpectedInvocation> matchingInvocationsWithDifferentArgs = new ArrayList<>();
37  
38          for (int i = 0, n = expectationsInReplayOrder.size(); i < n; i++) {
39              Expectation replayExpectation = expectationsInReplayOrder.get(i);
40              Object replayInstance = replayPhase.invocationInstances.get(i);
41              Object[] replayArgs = replayPhase.invocationArguments.get(i);
42  
43              if (matches(mock, mockClassDesc, mockNameAndDesc, args, replayExpectation, replayInstance, replayArgs)) {
44                  replayIndex = i;
45  
46                  if (verification != null) {
47                      verification.constraints.invocationCount++;
48                  }
49  
50                  currentExpectation = replayExpectation;
51              } else if (matchingInvocationWithDifferentArgs != null) {
52                  matchingInvocationsWithDifferentArgs.add(matchingInvocationWithDifferentArgs);
53              }
54          }
55  
56          if (verification != null && replayIndex >= 0) {
57              pendingError = verifyConstraints(verification);
58          }
59  
60          return matchingInvocationsWithDifferentArgs;
61      }
62  
63      @Nullable
64      private Error verifyConstraints(@NonNull Expectation verification) {
65          ExpectedInvocation lastInvocation = replayPhase.invocations.get(replayIndex).invocation;
66          Object[] lastArgs = replayPhase.invocationArguments.get(replayIndex);
67          return verification.verifyConstraints(lastInvocation, lastArgs, 1, -1);
68      }
69  
70      @Override
71      final void addVerifiedExpectation(@NonNull Expectation expectation, @NonNull Object[] args) {
72          VerifiedExpectation verifiedExpectation = new VerifiedExpectation(expectation, args, argMatchers, -1);
73          addVerifiedExpectation(verifiedExpectation);
74          verifiedExpectations.add(verifiedExpectation);
75      }
76  
77      @Override
78      final void handleInvocationCountConstraint(int minInvocations, int maxInvocations) {
79          pendingError = null;
80  
81          Expectation verifying = currentVerification;
82  
83          if (verifying == null) {
84              return;
85          }
86  
87          Error errorThrown;
88  
89          if (replayIndex >= 0) {
90              ExpectedInvocation replayInvocation = replayPhase.invocations.get(replayIndex).invocation;
91              Object[] replayArgs = replayPhase.invocationArguments.get(replayIndex);
92              errorThrown = verifying.verifyConstraints(replayInvocation, replayArgs, minInvocations, maxInvocations);
93          } else {
94              errorThrown = verifying.verifyConstraints(minInvocations);
95          }
96  
97          if (errorThrown != null) {
98              throw errorThrown;
99          }
100     }
101 }