1
2
3
4
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 }