/* * Copyright 2012 Jason Miller * * 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 jj.script; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; import java.util.HashMap; import java.util.Map; import jj.event.Publisher; import jj.jjmessage.JJMessage; import jj.script.module.RequiredModule; import jj.util.Closer; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.mozilla.javascript.Callable; import org.mozilla.javascript.ConstProperties; import org.mozilla.javascript.ContinuationPending; import org.mozilla.javascript.Script; import org.mozilla.javascript.Scriptable; /** * this class is hard to test because it mainly * exercises rhino * * @author jason * */ @RunWith(MockitoJUnitRunner.class) public class ContinuationCoordinatorTest { final String sha1 = "scriptsha1"; PendingKey pendingKey; @Mock(extraInterfaces = {ConstProperties.class}) Scriptable scope; RhinoContext context; @Mock Script script; @Mock AbstractScriptEnvironment<?> scriptEnvironment; CurrentScriptEnvironment env = new CurrentScriptEnvironment(new MockRhinoContextProvider()); @Mock ContinuationPending continuation; ContinuationState continuationState; @Mock Publisher publisher; @Mock Callable function; @Mock Script executedScript; ContinuationCoordinator continuationCoordinator; final Object[] args = { new Object(), new Object() }; final String unexpectedExceptionString = "unexpected problem during script execution {}"; @Mock ContinuationProcessor continuationProcessor1; @Mock ContinuationProcessor continuationProcessor2; @Mock ContinuationProcessor continuationProcessor3; @Mock ContinuationPendingCache cache; @Mock IsThread is; @Mock Closer closer; @Before public void before() { pendingKey = new PendingKey(); MockRhinoContextProvider contextProvider = new MockRhinoContextProvider(); given(scriptEnvironment.script()).willReturn(script); given(scriptEnvironment.scope()).willReturn(scope); given(scriptEnvironment.sha1()).willReturn(sha1); continuationState = new ContinuationState(JJMessage.makeRetrieve("")); given(continuation.getApplicationState()).willReturn(continuationState); Map<Class<? extends Continuation>, ContinuationProcessor> continuationProcessors = new HashMap<>(); //continuationProcessors.put(RestRequest.class, continuationProcessor1); continuationProcessors.put(JJMessage.class, continuationProcessor2); continuationProcessors.put(RequiredModule.class, continuationProcessor3); context = contextProvider.get(); continuationCoordinator = new ContinuationCoordinator(contextProvider, env, publisher, continuationProcessors, cache, is); given(is.forScriptEnvironment(any(ScriptEnvironment.class))).willReturn(true); } @Test public void testFunctionExecutionNoContinuation() { PendingKey result = continuationCoordinator.execute(scriptEnvironment, function, args[0], args[1]); assertThat(result, is(nullValue())); } @Test public void testFunctionExecutionWithContinuation() { given(context.callFunctionWithContinuations(eq(function), eq(scope), any(Object[].class))).willThrow(continuation); continuationState.continuationAs(JJMessage.class).pendingKey(pendingKey); PendingKey result = continuationCoordinator.execute(scriptEnvironment, function, args); assertThat(result, is(notNullValue())); verify(continuationProcessor2).process(continuationState); } @Test public void testFunctionExecutionWithUnexpectedException() { final RuntimeException e = new RuntimeException(); given(context.callFunctionWithContinuations(eq(function), eq(scope), any(Object[].class))).willThrow(e); try { continuationCoordinator.execute(scriptEnvironment, function); fail(); } catch (RuntimeException re) { assertThat(re, is(sameInstance(e))); } verify(publisher).publish(isA(ScriptExecutionError.class)); } @Test public void testScriptExecutionNoContinuation() { PendingKey result = continuationCoordinator.execute(scriptEnvironment, executedScript); assertThat(result, is(nullValue())); } @Test public void testScriptExecutionWithContinuation() { given(context.executeScriptWithContinuations(executedScript, scope)).willThrow(continuation); continuationState.continuationAs(JJMessage.class).pendingKey(pendingKey); PendingKey result = continuationCoordinator.execute(scriptEnvironment, executedScript); assertThat(result, is(notNullValue())); verify(continuationProcessor2).process(continuationState); } @Test public void testScriptExecutionWithUnexpectedException() { final RuntimeException e = new RuntimeException(); given(context.executeScriptWithContinuations(executedScript, scope)).willThrow(e); try { continuationCoordinator.execute(scriptEnvironment, executedScript); fail(); } catch (RuntimeException re) { assertThat(re, is(sameInstance(e))); } verify(publisher).publish(isA(ScriptExecutionError.class)); } @Test public void testContinuationResumptionNoContinuation() { given(scriptEnvironment.continuationPending(pendingKey)).willReturn(continuation); given(scriptEnvironment.restoreContextForKey(pendingKey)).willReturn(closer); PendingKey result = continuationCoordinator.resumeContinuation(scriptEnvironment, pendingKey, args); assertThat(result, is(nullValue())); } @Test public void testContinuationResumptionWithContinuation() { given(scriptEnvironment.continuationPending(pendingKey)).willReturn(continuation); given(context.resumeContinuation(any(), eq(scope), eq(args))).willThrow(continuation); continuationState.continuationAs(JJMessage.class).pendingKey(pendingKey); PendingKey result = continuationCoordinator.resumeContinuation(scriptEnvironment, pendingKey, args); assertThat(result, is(notNullValue())); verify(continuationProcessor2).process(continuationState); } @Test public void testContinuationResumptionWithUnexpectedException() { given(scriptEnvironment.continuationPending(pendingKey)).willReturn(continuation); given(scriptEnvironment.restoreContextForKey(pendingKey)).willReturn(closer); final RuntimeException e = new RuntimeException(); given(context.resumeContinuation(any(), eq(scope), eq(args))).willThrow(e); try { continuationCoordinator.resumeContinuation(scriptEnvironment, pendingKey, args); fail(); } catch (RuntimeException re) { assertThat(re, is(sameInstance(e))); } verify(publisher).publish(isA(ScriptExecutionError.class)); } }