/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit.internal.expectations; import java.util.*; import javax.annotation.*; import mockit.internal.expectations.invocation.*; import mockit.internal.util.*; final class Expectation { @Nullable final RecordPhase recordPhase; @Nonnull final ExpectedInvocation invocation; @Nonnull final InvocationConstraints constraints; @Nullable private InvocationResults results; boolean executedRealImplementation; Expectation(@Nonnull ExpectedInvocation invocation) { recordPhase = null; this.invocation = invocation; constraints = new InvocationConstraints(false, true); } Expectation( @Nullable RecordPhase recordPhase, @Nonnull ExpectedInvocation invocation, boolean strict, boolean nonStrict) { this.recordPhase = recordPhase; this.invocation = invocation; constraints = new InvocationConstraints(strict, nonStrict); } @Nonnull InvocationResults getResults() { if (results == null) { results = new InvocationResults(invocation, constraints); } return results; } @Nullable Object produceResult(@Nullable Object invokedObject, @Nonnull Object[] invocationArgs) throws Throwable { if (results == null) { return invocation.getDefaultValueForReturnType(); } return results.produceResult(invokedObject, invocationArgs); } @Nonnull Class<?> getReturnType() { String resolvedReturnType = invocation.getSignatureWithResolvedReturnType(); return TypeDescriptor.getReturnType(resolvedReturnType); } void addSequenceOfReturnValues(@Nonnull Object[] values) { int n = values.length - 1; Object firstValue = values[0]; Object[] remainingValues = new Object[n]; System.arraycopy(values, 1, remainingValues, 0, n); InvocationResults sequence = getResults(); if (!new SequenceOfReturnValues(this, firstValue, remainingValues).addResultWithSequenceOfValues()) { sequence.addReturnValue(firstValue); sequence.addReturnValues(remainingValues); } } @SuppressWarnings("UnnecessaryFullyQualifiedName") void addResult(@Nullable Object value) { if (value == null) { getResults().addReturnValueResult(null); } else if (isReplacementInstance(value)) { if (recordPhase != null) { Map<Object, Object> replacementMap = recordPhase.getReplacementMap(); replacementMap.put(invocation.instance, value); } invocation.replacementInstance = value; } else if (value instanceof Throwable) { getResults().addThrowable((Throwable) value); } else if (value instanceof mockit.Delegate) { getResults().addDelegatedResult((mockit.Delegate<?>) value); } else { Class<?> rt = getReturnType(); if (rt.isInstance(value)) { getResults().addReturnValueResult(value); } else { new ReturnTypeConversion(this, rt, value).addConvertedValue(); } } } private boolean isReplacementInstance(@Nonnull Object value) { return invocation.isConstructor() && value.getClass().isInstance(invocation.instance); } @Nullable Error verifyConstraints( @Nonnull ExpectedInvocation replayInvocation, @Nonnull Object[] replayArgs, int minInvocations, int maxInvocations) { Error error = verifyConstraints(minInvocations); if (error != null) { return error; } return constraints.verifyUpperLimit(replayInvocation, replayArgs, maxInvocations); } @Nullable Error verifyConstraints(int minInvocations) { return constraints.verifyLowerLimit(invocation, minInvocations); } @Nullable Object executeRealImplementation(@Nonnull Object replacementInstance, @Nonnull Object[] args) throws Throwable { return getResults().executeRealImplementation(replacementInstance, args); } }