/* * 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 com.betfair.cougar.api.ExecutionContext; import com.betfair.cougar.core.api.ev.*; import com.betfair.cougar.core.api.exception.CougarException; import com.betfair.cougar.core.api.exception.CougarFrameworkException; import com.betfair.cougar.core.api.exception.ServerFaultCode; import com.betfair.cougar.core.impl.DefaultTimeConstraints; import org.slf4j.LoggerFactory; import org.junit.*; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; /** * Unit test for InterceptingExecutableWrapper */ public class InterceptingExecutableWrapperTest { private List<ExecutionPreProcessor> preExecutionInterceptorList = new ArrayList<ExecutionPreProcessor>(); private List<ExecutionPostProcessor> postExecutionInterceptorList = new ArrayList<ExecutionPostProcessor>(); private final InterceptorResult SUCCESS = new InterceptorResult(InterceptorState.CONTINUE); private final InterceptorResult FAILURE_UNCHECKED = new InterceptorResult(InterceptorState.FORCE_ON_EXCEPTION, new CougarFrameworkException(ServerFaultCode.ServiceRuntimeException, "Broken")); private final InterceptorResult FAILURE_CHECKED = new InterceptorResult(InterceptorState.FORCE_ON_EXCEPTION, new CougarFrameworkException(ServerFaultCode.ServiceCheckedException, "Broken")); private Executable executable; private ExecutionContext ctx; private ExecutionObserver observer; private ExecutionVenue ev; private OperationKey key; @Before public void before() { preExecutionInterceptorList.clear(); postExecutionInterceptorList.clear(); executable = Mockito.mock(Executable.class); ctx = Mockito.mock(ExecutionContext.class); observer = Mockito.mock(ExecutionObserver.class); ev = Mockito.mock(ExecutionVenue.class); key = Mockito.mock(OperationKey.class); } @Test public void testPreInterceptorHappyCase() { ExecutionPreProcessor preIntercerptor = Mockito.mock(ExecutionPreProcessor.class); when(preIntercerptor.getExecutionRequirement()).thenReturn(ExecutionRequirement.EXACTLY_ONCE); when(preIntercerptor.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(SUCCESS); preExecutionInterceptorList.add(preIntercerptor); InterceptingExecutableWrapper executableWrapper = new InterceptingExecutableWrapper(executable, preExecutionInterceptorList, postExecutionInterceptorList); executableWrapper.execute(ctx, key, new Object[]{}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS); verify(preIntercerptor).invoke(eq(ctx), eq(key), any(Object[].class)); verify(executable).execute(eq(ctx), eq(key), any(Object[].class), any(ExecutionObserver.class), eq(ev), eq(DefaultTimeConstraints.NO_CONSTRAINTS)); } @Test public void testPreInterceptorsOneGoodOneBadUnchecked() { ExecutionPreProcessor preIntercerptorGood = Mockito.mock(ExecutionPreProcessor.class); when(preIntercerptorGood.getExecutionRequirement()).thenReturn(ExecutionRequirement.EXACTLY_ONCE); when(preIntercerptorGood.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(SUCCESS); ExecutionPreProcessor preIntercerptorBad = Mockito.mock(ExecutionPreProcessor.class); when(preIntercerptorBad.getExecutionRequirement()).thenReturn(ExecutionRequirement.EXACTLY_ONCE); when(preIntercerptorBad.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(FAILURE_UNCHECKED); preExecutionInterceptorList.add(preIntercerptorGood); preExecutionInterceptorList.add(preIntercerptorBad); InterceptingExecutableWrapper executableWrapper = new InterceptingExecutableWrapper(executable, preExecutionInterceptorList, postExecutionInterceptorList); executableWrapper.execute(ctx, key, new Object[]{}, observer, ev,DefaultTimeConstraints.NO_CONSTRAINTS); //Firstly check that the first good one worked correctly verify(preIntercerptorGood).invoke(eq(ctx), eq(key), any(Object[].class)); //For the second failing interceptor ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class); verify(observer).onResult(executionResultArgumentCaptor.capture()); ExecutionResult result = executionResultArgumentCaptor.getValue(); assertTrue(result.isFault()); CougarException ex = result.getFault(); assertNotNull(ex); assertEquals(ex.getServerFaultCode(), ServerFaultCode.ServiceRuntimeException); //Check that the ev WAS NOT called - should never happen verify(ev, never()).execute(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class), any(ExecutionObserver.class), eq(DefaultTimeConstraints.NO_CONSTRAINTS)); } @Test public void testPreInterceptorsOneBadCheckedOneGood() { ExecutionPreProcessor preIntercerptorBad = Mockito.mock(ExecutionPreProcessor.class); when(preIntercerptorBad.getExecutionRequirement()).thenReturn(ExecutionRequirement.EXACTLY_ONCE); when(preIntercerptorBad.invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class))).thenReturn(FAILURE_CHECKED); ExecutionPreProcessor preIntercerptorGood = Mockito.mock(ExecutionPreProcessor.class); when(preIntercerptorGood.getExecutionRequirement()).thenReturn(ExecutionRequirement.EXACTLY_ONCE); preExecutionInterceptorList.add(preIntercerptorBad); preExecutionInterceptorList.add(preIntercerptorGood); InterceptingExecutableWrapper executableWrapper = new InterceptingExecutableWrapper(executable, preExecutionInterceptorList, postExecutionInterceptorList); executableWrapper.execute(ctx, key, new Object[]{}, observer, ev,DefaultTimeConstraints.NO_CONSTRAINTS); //For the second failing interceptor ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class); verify(observer).onResult(executionResultArgumentCaptor.capture()); ExecutionResult result = executionResultArgumentCaptor.getValue(); assertTrue(result.isFault()); CougarException ex = result.getFault(); assertNotNull(ex); assertEquals(ex.getServerFaultCode(), ServerFaultCode.ServiceCheckedException); //Confirm also that the second interceptor WAS NOT called verify(preIntercerptorGood, never()).invoke(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class)); //Check that the ev WAS NOT called - should never happen verify(ev, never()).execute(any(ExecutionContext.class), any(OperationKey.class), any(Object[].class), any(ExecutionObserver.class), eq(DefaultTimeConstraints.NO_CONSTRAINTS)); } @Test public void testPostInterceptorHappyCase() { postExecutionInterceptorList.add(epp); InterceptingExecutableWrapper executableWrapper = new InterceptingExecutableWrapper(new Executable() { @Override public void execute(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionObserver observer, ExecutionVenue executionVenue, TimeConstraints timeConstraints) { assertTrue("Observer should be wrapped by PostProcessorInterceptorWrapper", observer instanceof PostProcessingInterceptorWrapper); PostProcessingInterceptorWrapper ppiw = (PostProcessingInterceptorWrapper) observer; ppiw.onResult(new ExecutionResult()); } }, preExecutionInterceptorList, postExecutionInterceptorList); executableWrapper.execute(ctx, key, new Object[]{Boolean.TRUE}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS); ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class); verify(observer).onResult(executionResultArgumentCaptor.capture()); ExecutionResult executionResult = executionResultArgumentCaptor.getValue(); assertNotNull(executionResult); assertFalse(executionResult.isFault()); } @Test public void testPostInterceptorOnException() { postExecutionInterceptorList.add(epp); InterceptingExecutableWrapper executableWrapper = new InterceptingExecutableWrapper(new Executable() { @Override public void execute(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionObserver observer, ExecutionVenue executionVenue, TimeConstraints timeConstraints) { assertTrue("Observer should be wrapped by PostProcessorInterceptorWrapper", observer instanceof PostProcessingInterceptorWrapper); PostProcessingInterceptorWrapper ppiw = (PostProcessingInterceptorWrapper) observer; ppiw.onResult(new ExecutionResult()); } }, preExecutionInterceptorList, postExecutionInterceptorList); executableWrapper.execute(ctx, key, new Object[]{Boolean.FALSE}, observer, ev, DefaultTimeConstraints.NO_CONSTRAINTS); ArgumentCaptor<ExecutionResult> executionResultArgumentCaptor = ArgumentCaptor.forClass(ExecutionResult.class); verify(observer).onResult(executionResultArgumentCaptor.capture()); ExecutionResult executionResult = executionResultArgumentCaptor.getValue(); assertNotNull(executionResult); assertTrue(executionResult.isFault()); CougarException ce = executionResult.getFault(); assertNotNull(ce); assertEquals(ce.getServerFaultCode(), ServerFaultCode.ServiceRuntimeException); } private ExecutionPostProcessor epp = new ExecutionPostProcessor() { @Override public InterceptorResult invoke(ExecutionContext ctx, OperationKey key, Object[] args, ExecutionResult result) { Boolean b = (Boolean)args[0]; if (b) { return SUCCESS; } else { return FAILURE_UNCHECKED; } } @Override public String getName() { return "epp-test"; } }; }