1
2
3
4
5
6 package mockit.internal.expectations.invocation;
7
8 import edu.umd.cs.findbugs.annotations.NonNull;
9 import edu.umd.cs.findbugs.annotations.Nullable;
10
11 import java.lang.reflect.Array;
12 import java.util.Iterator;
13
14 import mockit.Delegate;
15 import mockit.internal.expectations.invocation.InvocationResult.DeferredResults;
16 import mockit.internal.expectations.invocation.InvocationResult.ReturnValueResult;
17 import mockit.internal.expectations.invocation.InvocationResult.ThrowableResult;
18
19 import org.checkerframework.checker.index.qual.NonNegative;
20
21 public final class InvocationResults {
22 @NonNull
23 private final ExpectedInvocation invocation;
24 @NonNull
25 private final InvocationConstraints constraints;
26 @Nullable
27 private InvocationResult currentResult;
28 @Nullable
29 private InvocationResult lastResult;
30 @NonNegative
31 private int resultCount;
32
33 public InvocationResults(@NonNull ExpectedInvocation invocation, @NonNull InvocationConstraints constraints) {
34 this.invocation = invocation;
35 this.constraints = constraints;
36 }
37
38 public void addReturnValue(@Nullable Object value) {
39 if (value instanceof Delegate) {
40 addDelegatedResult((Delegate<?>) value);
41 } else {
42 addNewReturnValueResult(value);
43 }
44 }
45
46 public void addDelegatedResult(@NonNull Delegate<?> delegate) {
47 InvocationResult result = new DelegatedResult(invocation, delegate);
48 addResult(result);
49 }
50
51 private void addNewReturnValueResult(@Nullable Object value) {
52 InvocationResult result = new ReturnValueResult(value);
53 addResult(result);
54 }
55
56 public void addReturnValueResult(@Nullable Object value) {
57 addNewReturnValueResult(value);
58 }
59
60 public void addReturnValues(@NonNull Object... values) {
61 for (Object value : values) {
62 addReturnValue(value);
63 }
64 }
65
66 void addResults(@NonNull Object array) {
67 int n = Array.getLength(array);
68
69 for (int i = 0; i < n; i++) {
70 Object value = Array.get(array, i);
71 addConsecutiveResult(value);
72 }
73 }
74
75 private void addConsecutiveResult(@Nullable Object result) {
76 if (result instanceof Throwable) {
77 addThrowable((Throwable) result);
78 } else {
79 addReturnValue(result);
80 }
81 }
82
83 void addResults(@NonNull Iterable<?> values) {
84 for (Object value : values) {
85 addConsecutiveResult(value);
86 }
87 }
88
89 void addDeferredResults(@NonNull Iterator<?> values) {
90 InvocationResult result = new DeferredResults(values);
91 addResult(result);
92 constraints.setUnlimitedMaxInvocations();
93 }
94
95 public void addThrowable(@NonNull Throwable t) {
96 addResult(new ThrowableResult(t));
97 }
98
99 private void addResult(@NonNull InvocationResult result) {
100 resultCount++;
101 constraints.adjustMaxInvocations(resultCount);
102
103 if (currentResult == null) {
104 currentResult = result;
105 } else {
106 assert lastResult != null;
107 lastResult.next = result;
108 }
109
110 lastResult = result;
111 }
112
113 @Nullable
114 public Object produceResult(@Nullable Object invokedObject, @NonNull Object[] invocationArgs) throws Throwable {
115 InvocationResult resultToBeProduced = currentResult;
116
117 if (resultToBeProduced == null) {
118 return null;
119 }
120
121 InvocationResult nextResult = resultToBeProduced.next;
122
123 if (nextResult != null) {
124 currentResult = nextResult;
125 }
126
127 return resultToBeProduced.produceResult(invokedObject, invocation, constraints, invocationArgs);
128 }
129 }