/*
* Copyright 2014, The Sporting Exchange Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.betfair.cougar.core.impl.ev;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executor;
import com.betfair.cougar.api.DehydratedExecutionContext;
import com.betfair.cougar.api.ExecutionContext;
import com.betfair.cougar.api.RequestUUID;
import com.betfair.cougar.api.ResponseCode;
import com.betfair.cougar.api.fault.CougarApplicationException;
import com.betfair.cougar.api.geolocation.GeoLocationDetails;
import com.betfair.cougar.api.security.IdentityResolver;
import com.betfair.cougar.api.security.CredentialFaultCode;
import com.betfair.cougar.api.security.IdentityChain;
import com.betfair.cougar.api.security.IdentityToken;
import com.betfair.cougar.api.security.InvalidCredentialsException;
import com.betfair.cougar.core.api.ServiceVersion;
import com.betfair.cougar.core.api.ev.*;
import com.betfair.cougar.core.api.exception.CougarFrameworkException;
import com.betfair.cougar.core.api.exception.ServerFaultCode;
import com.betfair.cougar.core.api.transcription.Parameter;
import com.betfair.cougar.core.api.transcription.ParameterType;
import com.betfair.cougar.core.impl.DefaultTimeConstraints;
import com.betfair.cougar.util.RequestUUIDImpl;
import com.betfair.cougar.util.UUIDGeneratorImpl;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class BaseExecutionVenueTest {
private static final InterceptorResult CONTINUE = new InterceptorResult(InterceptorState.CONTINUE, null);
private static final InterceptorResult FORCE_ON_RESULT = new InterceptorResult(InterceptorState.FORCE_ON_RESULT, "THIS IS A FORCED PASS");
private static final InterceptorResult FORCE_ON_EXCEPTION = new InterceptorResult(InterceptorState.FORCE_ON_EXCEPTION, new CougarFrameworkException(ServerFaultCode.SecurityException,"I EXPECT TO FAIL"));
@BeforeClass
public static void setupStatic() {
RequestUUIDImpl.setGenerator(new UUIDGeneratorImpl());
}
private class EVTestException extends CougarApplicationException {
public EVTestException(ResponseCode code, String exceptionCode) {
super(code, exceptionCode);
}
@Override
public List<String[]> getApplicationFaultMessages() {
return null;
}
@Override
public String getApplicationFaultNamespace() {
return null;
}
}
private ExecutionPreProcessor checkedExceptionThrowingPreProcessor = new ExecutionPreProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args) {
return new InterceptorResult(InterceptorState.FORCE_ON_EXCEPTION,
new EVTestException(ResponseCode.Forbidden, "This is what we wanted"));
}
@Override
public String getName() {
return "checkedExceptionThrowingPreProcessor";
}
@Override
public ExecutionRequirement getExecutionRequirement() {
return ExecutionRequirement.EXACTLY_ONCE;
}
};
/**
* PRE-PROCESSORS
*/
private ExecutionPreProcessor exceptionThrowingPreProcessor = new ExecutionPreProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args) {
throw new UnsupportedOperationException("This is expected");
}
@Override
public String getName() {
return "exceptionThrowingPreProcessor";
}
@Override
public ExecutionRequirement getExecutionRequirement() {
return ExecutionRequirement.EXACTLY_ONCE;
}
};
private ExecutionPreProcessor continuePreProcessor = new ExecutionPreProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args) {
return CONTINUE;
}
@Override
public String getName() {
return "continuePreProcessor";
}
@Override
public ExecutionRequirement getExecutionRequirement() {
return ExecutionRequirement.EXACTLY_ONCE;
}
};
private ExecutionPreProcessor forceOnResultPreProcessor = new ExecutionPreProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args) {
return FORCE_ON_RESULT;
}
@Override
public String getName() {
return "forceOnResultPreProcessor";
}
@Override
public ExecutionRequirement getExecutionRequirement() {
return ExecutionRequirement.EXACTLY_ONCE;
}
};
/**
* POST-PROCESSORS
*/
private ExecutionPostProcessor exceptionThrowingPostProcessor = new ExecutionPostProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionResult result) {
throw new UnsupportedOperationException("This is expected");
}
@Override
public String getName() {
return "exceptionThrowingPostProcessor";
}
};
private ExecutionPostProcessor checkedServiceExceptionThrowingPostProcessor = new ExecutionPostProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionResult result) {
return new InterceptorResult(InterceptorState.FORCE_ON_EXCEPTION,
new EVTestException(ResponseCode.Forbidden, "This is what we wanted"));
}
@Override
public String getName() {
return "checkedServiceExceptionThrowingPostProcessor";
}
};
private ExecutionPostProcessor forceOnResultPostProcessor = new ExecutionPostProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionResult result) {
return FORCE_ON_RESULT;
}
@Override
public String getName() {
return "forceOnResultPostProcessor";
}
};
private ExecutionPostProcessor forceOnExceptionMockPostProcessor = new ExecutionPostProcessor() {
@Override
public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionResult result) {
return FORCE_ON_EXCEPTION;
}
@Override
public String getName() {
return "forceOnExceptionMockPostProcessor";
}
};
/**
* EXECUTION-OBSERVERS
*/
private ExecutionObserver failOnResultExecutionObserver = new ExecutionObserver() {
public void onResult(ExecutionResult result) {
switch (result.getResultType()) {
case Success:
case Subscription:
fail("Expected ExecutionResult of Fault");
break;
case Fault:
break;
}
}
};
private ExecutionObserver cougarApplicationExceptionResultExecutionObserver = new ExecutionObserver() {
public void onResult(ExecutionResult result) {
switch (result.getResultType()) {
case Success:
case Subscription:
fail("Expected ExecutionResult of Fault");
break;
case Fault:
//This is what we want, but we must confirm that it is possible to correctly construct the CAE
String className = result.getFault().getFault().getDetail().getDetailMessage();
assertEquals("EVTestException", className);
break;
}
}
};
private ExecutionObserver failOnExceptionExecutionObserver = new ExecutionObserver() {
public void onResult(ExecutionResult result) {
switch (result.getResultType()) {
case Fault:
case Subscription:
fail("Expected ExecutionResult of Success");
break;
case Success:
break;
}
}
};
private Executable failingExecutable = new Executable() {
@Override
public void execute(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionObserver observer, ExecutionVenue executionVenue, TimeConstraints timeConstraints) {
throw new IllegalStateException("Failure can now be an option!");
}
};
private Executable succeedingExecutable = new Executable() {
@Override
public void execute(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionObserver observer, ExecutionVenue executionVenue, TimeConstraints timeConstraints) {
observer.onResult(new ExecutionResult(null));
}
};
private IdentityResolver newIdentityResolver = new IdentityResolver() {
@Override
public void resolve(IdentityChain chain, DehydratedExecutionContext ctx) throws InvalidCredentialsException {
}
@Override
public List<IdentityToken> tokenise(IdentityChain chain) {
return null;
}
};
private IdentityResolver newIdentityResolverWithToken = new IdentityResolver() {
@Override
public void resolve(IdentityChain chain, DehydratedExecutionContext ctx) throws InvalidCredentialsException {
}
@Override
public List<IdentityToken> tokenise(IdentityChain chain) {
return Arrays.asList(new IdentityToken("Key", "Value"));
}
};
private IdentityResolver failingGenericIdentityResolver(CredentialFaultCode cfc) {
final InvalidCredentialsException ice = cfc != null ? new InvalidCredentialsException("", cfc) : new InvalidCredentialsException("");
return new IdentityResolver() {
@Override
public void resolve(IdentityChain chain, DehydratedExecutionContext ctx) throws InvalidCredentialsException {
throw ice;
}
@Override
public List<IdentityToken> tokenise(IdentityChain chain) {
return null;
}
};
}
private BaseExecutionVenue bev;
private List<ExecutionPreProcessor> preProcessorList;
private List<ExecutionPostProcessor> postProcessorList;
private DehydratedExecutionContext mockExecutionContext;
private OperationKey mockOperationKey;
private Object[] args = new Object[0];
private OperationDefinition mockOperationDef;
private ExecutionTimingRecorder mockTimingRecorder;
private Executable mockExecutable;
private RequestUUID uuid = new RequestUUIDImpl();
@Before
public void setup() {
bev = new BaseExecutionVenue();
preProcessorList = new ArrayList<ExecutionPreProcessor>();
postProcessorList = new ArrayList<ExecutionPostProcessor>();
bev.setPreProcessors(preProcessorList);
bev.setPostProcessors(postProcessorList);
mockExecutionContext = mock(DehydratedExecutionContext.class);
mockOperationKey = new OperationKey(new ServiceVersion(1,0), "SomeService", "someOperation");
mockOperationDef = new SimpleOperationDefinition(mockOperationKey, new Parameter[0], new ParameterType(Void.class, new ParameterType[0]));
mockExecutable = mock(Executable.class);
mockTimingRecorder = mock(ExecutionTimingRecorder.class);
when(mockExecutionContext.getRequestUUID()).thenReturn(uuid);
}
@Test
public void testForceOnExceptionForPostProcessorWhenExecutablePasses() {
postProcessorList.add(forceOnExceptionMockPostProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver, DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testOnExceptionCalledWhenPreProcessorFails() {
preProcessorList.add(exceptionThrowingPreProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnResultExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testOnExceptionWithServiceCheckedException() {
preProcessorList.add(checkedExceptionThrowingPreProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, cougarApplicationExceptionResultExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testOnResultCalledWhenPreProcessorPasses() {
preProcessorList.add(continuePreProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testExecutableNotCalledWhenPreProcessorSaySo() {
preProcessorList.add(forceOnResultPreProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void onlyOncePreProcessorViaExecutorExecuteMethod() {
ExecutionPreProcessor preProcessor = mock(ExecutionPreProcessor.class);
when(preProcessor.getExecutionRequirement()).thenReturn(ExecutionRequirement.EXACTLY_ONCE);
when(preProcessor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(new InterceptorResult(InterceptorState.CONTINUE));
preProcessorList.add(preProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver, thisThreadExecutor(), DefaultTimeConstraints.NO_CONSTRAINTS);
verify(preProcessor, times(1)).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class));
}
@Test
public void everyPlacePreProcessorViaExecutorExecuteMethod() {
ExecutionPreProcessor preProcessor = mock(ExecutionPreProcessor.class);
when(preProcessor.getExecutionRequirement()).thenReturn(ExecutionRequirement.EVERY_OPPORTUNITY);
when(preProcessor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(new InterceptorResult(InterceptorState.CONTINUE));
preProcessorList.add(preProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver, thisThreadExecutor(), DefaultTimeConstraints.NO_CONSTRAINTS);
verify(preProcessor, times(2)).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class));
}
@Test
public void preQueueOnlyPreProcessorViaExecutorExecuteMethod() {
// processors are executed in order, so if the second is executed, but not the first then we're good
ExecutionPreProcessor preExecuteProcessor = mock(ExecutionPreProcessor.class);
when(preExecuteProcessor.getExecutionRequirement()).thenReturn(ExecutionRequirement.PRE_EXECUTE);
when(preExecuteProcessor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(new InterceptorResult(InterceptorState.CONTINUE));
preProcessorList.add(preExecuteProcessor);
// the second won't execute since we stopped things
ExecutionPreProcessor preQueueProcessor = mock(ExecutionPreProcessor.class);
when(preQueueProcessor.getExecutionRequirement()).thenReturn(ExecutionRequirement.PRE_QUEUE);
when(preQueueProcessor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(new InterceptorResult(InterceptorState.FORCE_ON_RESULT, null));
preProcessorList.add(preQueueProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver, thisThreadExecutor(), DefaultTimeConstraints.NO_CONSTRAINTS);
verify(preQueueProcessor, times(1)).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class));
verify(preExecuteProcessor, times(0)).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class));
}
@Test
public void preExecuteOnlyPreProcessorViaExecutorExecuteMethod() {
// we know from the previous test that if we bomb out at queue that the execute one isn't run
// so this time allow the execution through from the queue and we should get an execute
ExecutionPreProcessor preExecuteProcessor = mock(ExecutionPreProcessor.class);
when(preExecuteProcessor.getExecutionRequirement()).thenReturn(ExecutionRequirement.PRE_EXECUTE);
when(preExecuteProcessor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(new InterceptorResult(InterceptorState.CONTINUE));
preProcessorList.add(preExecuteProcessor);
ExecutionPreProcessor preQueueProcessor = mock(ExecutionPreProcessor.class);
when(preQueueProcessor.getExecutionRequirement()).thenReturn(ExecutionRequirement.PRE_QUEUE);
when(preQueueProcessor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(new InterceptorResult(InterceptorState.CONTINUE));
preProcessorList.add(preQueueProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver, thisThreadExecutor(), DefaultTimeConstraints.NO_CONSTRAINTS);
verify(preQueueProcessor, times(1)).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class));
verify(preExecuteProcessor, times(1)).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class));
}
@Test
public void testFailingPostProcessorCallsOnExceptionWhenExecutableCompletesOK() {
postProcessorList.add(exceptionThrowingPostProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnResultExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testFailingPostProcessorCallsOnServiceCheckedExceptionWhenExecutableCompletesOK() {
postProcessorList.add(checkedServiceExceptionThrowingPostProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, cougarApplicationExceptionResultExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testSucceedingPostProcessorCallsOnResultWhenExecutableCompletesOK() {
postProcessorList.add(forceOnResultPostProcessor);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testPostProcessorForcesOnResultWhenExcecutableFails() {
postProcessorList.add(forceOnResultPostProcessor);
bev.registerOperation(null, mockOperationDef, failingExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnExceptionExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testPostProcessorForcesOnExceptionWhenExcecutableFails() {
postProcessorList.add(forceOnExceptionMockPostProcessor);
bev.registerOperation(null, mockOperationDef, failingExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, failOnResultExecutionObserver,DefaultTimeConstraints.NO_CONSTRAINTS);
}
@Test
public void testNoOperation() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.execute(mockExecutionContext, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(executionResultArgumentCaptor.capture());
assertNotNull(executionResultArgumentCaptor.getValue());
assertEquals(executionResultArgumentCaptor.getValue().getResultType(), ExecutionResult.ResultType.Fault);
assertEquals(ServerFaultCode.NoSuchOperation, executionResultArgumentCaptor.getValue().getFault().getServerFaultCode());
}
@Test
public void testNamepacedServiceNotSpecifiedInCallFail() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation("MyNamespace", mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(executionResultArgumentCaptor.capture());
assertNotNull(executionResultArgumentCaptor.getValue());
assertEquals(executionResultArgumentCaptor.getValue().getResultType(), ExecutionResult.ResultType.Fault);
assertEquals(ServerFaultCode.NoSuchOperation, executionResultArgumentCaptor.getValue().getFault().getServerFaultCode());
}
@Test
public void testServiceNamespaceSpecifiedInCallFail() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.execute(mockExecutionContext, new OperationKey(mockOperationKey, "MyNamespace"), args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(executionResultArgumentCaptor.capture());
assertNotNull(executionResultArgumentCaptor.getValue());
assertEquals(executionResultArgumentCaptor.getValue().getResultType(), ExecutionResult.ResultType.Fault);
assertEquals(ServerFaultCode.NoSuchOperation, executionResultArgumentCaptor.getValue().getFault().getServerFaultCode());
}
@Test
public void testSameOperationMultiRegisteredWithDifferentNamspaces() {
ExecutionObserver observer = mock(ExecutionObserver.class);
final ExecutionTimingRecorder mockTimingRecorderFoo = mock(ExecutionTimingRecorder.class);
final Executable mockExecutableFoo = mock(Executable.class);
final ExecutionTimingRecorder mockTimingRecorderBar = mock(ExecutionTimingRecorder.class);
final Executable mockExecutableBar = mock(Executable.class);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.registerOperation("foo", mockOperationDef, mockExecutableFoo, mockTimingRecorderFoo, 0);
bev.registerOperation("bar", mockOperationDef, mockExecutableBar, mockTimingRecorderBar, 0);
// Test no namespace
bev.execute(mockExecutionContext, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
verify(mockExecutable).execute(any(ExecutionContext.class), eq(mockOperationKey), any(Object[].class), any(ExecutionObserver.class), eq(bev), eq(DefaultTimeConstraints.NO_CONSTRAINTS));
// Test foo
OperationKey key = new OperationKey(mockOperationKey, "foo");
bev.execute(mockExecutionContext, key, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
verify(mockExecutableFoo).execute(any(ExecutionContext.class), eq(key), any(Object[].class), any(ExecutionObserver.class), eq(bev), eq(DefaultTimeConstraints.NO_CONSTRAINTS));
// Test bar
OperationKey barKey = new OperationKey(mockOperationKey, "bar");
bev.execute(mockExecutionContext, barKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
verify(mockExecutableBar).execute(any(ExecutionContext.class), eq(barKey), any(Object[].class), any(ExecutionObserver.class), eq(bev), eq(DefaultTimeConstraints.NO_CONSTRAINTS));
}
@Test
public void testNewIdentityResolution() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation(null, mockOperationDef, succeedingExecutable, mockTimingRecorder, 0);
bev.setIdentityResolver(newIdentityResolver);
DehydratedExecutionContext context = new DehydratedExecutionContext() {
private List<IdentityToken> tokens = new ArrayList<IdentityToken>();
private IdentityChain chain;
@Override
public List<IdentityToken> getIdentityTokens() {
return tokens;
}
@Override
public void setIdentityChain(IdentityChain chain) {
this.chain = chain;
}
@Override
public GeoLocationDetails getLocation() {
return null;
}
@Override
public IdentityChain getIdentity() {
return chain;
}
@Override
public RequestUUID getRequestUUID() {
return null;
}
@Override
public Date getReceivedTime() {
return null;
}
@Override
public Date getRequestTime() {
return null;
}
@Override
public boolean traceLoggingEnabled() {
return false;
}
@Override
public int getTransportSecurityStrengthFactor() {
return 0;
}
@Override
public boolean isTransportSecure() {
return false;
}
};
bev.execute(context, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> observerCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(observerCaptor.capture());
assertNotNull(observerCaptor.getValue());
assertEquals(ExecutionResult.ResultType.Success, observerCaptor.getValue().getResultType());
assertEquals(0, context.getIdentityTokens().size());
}
@Test
public void testNewIdentityResolutionWithTokenWriteback() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation(null, mockOperationDef, succeedingExecutable, mockTimingRecorder, 0);
bev.setIdentityResolver(newIdentityResolverWithToken);
DehydratedExecutionContext context = new DehydratedExecutionContext() {
private List<IdentityToken> tokens = new ArrayList<IdentityToken>();
private IdentityChain chain;
@Override
public List<IdentityToken> getIdentityTokens() {
return tokens;
}
@Override
public void setIdentityChain(IdentityChain chain) {
this.chain = chain;
}
@Override
public GeoLocationDetails getLocation() {
return null;
}
@Override
public IdentityChain getIdentity() {
return chain;
}
@Override
public RequestUUID getRequestUUID() {
return null;
}
@Override
public Date getReceivedTime() {
return null;
}
@Override
public Date getRequestTime() {
return null;
}
@Override
public boolean traceLoggingEnabled() {
return false;
}
@Override
public int getTransportSecurityStrengthFactor() {
return 0;
}
@Override
public boolean isTransportSecure() {
return false;
}
};
bev.execute(context, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> observerCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(observerCaptor.capture());
assertNotNull(observerCaptor.getValue());
assertEquals(ExecutionResult.ResultType.Success, observerCaptor.getValue().getResultType());
assertEquals(1, context.getIdentityTokens().size());
}
@Test
public void testNewIdentityResolutionFailsInspecific() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.setIdentityResolver(failingGenericIdentityResolver(null));
bev.execute(mockExecutionContext, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> observerCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(observerCaptor.capture());
assertNotNull(observerCaptor.getValue());
assertEquals(ExecutionResult.ResultType.Fault, observerCaptor.getValue().getResultType());
assertEquals(ServerFaultCode.SecurityException, observerCaptor.getValue().getFault().getServerFaultCode());
}
@Test
public void testNewIdentityResolutionFailsSpecific() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation(null, mockOperationDef, mockExecutable, mockTimingRecorder, 0);
bev.setIdentityResolver(failingGenericIdentityResolver(CredentialFaultCode.BannedLocation));
bev.execute(mockExecutionContext, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> observerCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(observerCaptor.capture());
assertNotNull(observerCaptor.getValue());
assertEquals(ExecutionResult.ResultType.Fault, observerCaptor.getValue().getResultType());
assertEquals(ServerFaultCode.BannedLocation, observerCaptor.getValue().getFault().getServerFaultCode());
}
@Test
public void expiringExecutable() {
ExecutionObserver observer = mock(ExecutionObserver.class);
bev.registerOperation(null, mockOperationDef, new Executable() {
@Override
public void execute(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionObserver observer, ExecutionVenue executionVenue, TimeConstraints timeConstraints) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
}
}, mockTimingRecorder, 1000);
bev.start();
bev.execute(mockExecutionContext, mockOperationKey, args, observer, DefaultTimeConstraints.NO_CONSTRAINTS);
ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class);
verify(observer).onResult(executionResultArgumentCaptor.capture());
assertNotNull(executionResultArgumentCaptor.getValue());
assertEquals(executionResultArgumentCaptor.getValue().getResultType(), ExecutionResult.ResultType.Fault);
assertEquals(ServerFaultCode.Timeout, executionResultArgumentCaptor.getValue().getFault().getServerFaultCode());
}
private Executor thisThreadExecutor() {
return new Executor() {
@Override
public void execute(Runnable command) {
command.run();
}
};
}
}