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 mockit.internal.expectations.invocation.ExpectedInvocation;
12  import mockit.internal.expectations.invocation.InvocationConstraints;
13  import mockit.internal.expectations.invocation.InvocationResults;
14  import mockit.internal.expectations.invocation.ReturnTypeConversion;
15  import mockit.internal.util.TypeDescriptor;
16  
17  final class Expectation {
18      @Nullable
19      final RecordPhase recordPhase;
20      @NonNull
21      final ExpectedInvocation invocation;
22      @NonNull
23      final InvocationConstraints constraints;
24      @Nullable
25      private InvocationResults results;
26      boolean executedRealImplementation;
27  
28      Expectation(@NonNull ExpectedInvocation invocation) {
29          recordPhase = null;
30          this.invocation = invocation;
31          constraints = new InvocationConstraints(true);
32      }
33  
34      Expectation(@NonNull RecordPhase recordPhase, @NonNull ExpectedInvocation invocation, boolean nonStrict) {
35          this.recordPhase = recordPhase;
36          this.invocation = invocation;
37          constraints = new InvocationConstraints(nonStrict);
38      }
39  
40      @NonNull
41      InvocationResults getResults() {
42          if (results == null) {
43              results = new InvocationResults(invocation, constraints);
44          }
45  
46          return results;
47      }
48  
49      @Nullable
50      Object produceResult(@Nullable Object invokedObject, @NonNull Object[] invocationArgs) throws Throwable {
51          if (results == null) {
52              return invocation.getDefaultValueForReturnType();
53          }
54  
55          return results.produceResult(invokedObject, invocationArgs);
56      }
57  
58      @NonNull
59      Class<?> getReturnType() {
60          String resolvedReturnType = invocation.getSignatureWithResolvedReturnType();
61          return TypeDescriptor.getReturnType(resolvedReturnType);
62      }
63  
64      void addSequenceOfReturnValues(@NonNull Object[] values) {
65          int n = values.length - 1;
66          Object firstValue = values[0];
67          Object[] remainingValues = new Object[n];
68          System.arraycopy(values, 1, remainingValues, 0, n);
69  
70          InvocationResults sequence = getResults();
71  
72          if (!new SequenceOfReturnValues(this, firstValue, remainingValues).addResultWithSequenceOfValues()) {
73              sequence.addReturnValue(firstValue);
74              sequence.addReturnValues(remainingValues);
75          }
76      }
77  
78      @SuppressWarnings("UnnecessaryFullyQualifiedName")
79      void addResult(@Nullable Object value) {
80          InvocationResults invocationResults = getResults();
81  
82          if (value == null) {
83              invocationResults.addReturnValueResult(null);
84          } else if (value instanceof Throwable) {
85              invocationResults.addThrowable((Throwable) value);
86          } else if (value instanceof mockit.Delegate) {
87              invocationResults.addDelegatedResult((mockit.Delegate<?>) value);
88          } else if (invocation.isConstructor()) {
89              throw new IllegalArgumentException("Invalid assignment to result field for constructor expectation");
90          } else {
91              Class<?> rt = getReturnType();
92  
93              if (rt.isInstance(value)) {
94                  invocationResults.addReturnValueResult(value);
95              } else {
96                  new ReturnTypeConversion(invocation, invocationResults, rt, value).addConvertedValue();
97              }
98          }
99      }
100 
101     @Nullable
102     Error verifyConstraints(@NonNull ExpectedInvocation replayInvocation, @NonNull Object[] replayArgs,
103             int minInvocations, int maxInvocations) {
104         Error error = verifyConstraints(minInvocations);
105 
106         if (error != null) {
107             return error;
108         }
109 
110         return constraints.verifyUpperLimit(replayInvocation, replayArgs, maxInvocations);
111     }
112 
113     @Nullable
114     Error verifyConstraints(int minInvocations) {
115         return constraints.verifyLowerLimit(invocation, minInvocations);
116     }
117 }