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