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