/* * Copyright 2004-2012 the original author or authors. * * 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 org.springframework.webflow.engine.impl; import junit.framework.TestCase; import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.core.collection.MutableAttributeMap; import org.springframework.webflow.definition.FlowDefinition; import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException; import org.springframework.webflow.definition.registry.FlowDefinitionLocator; import org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException; import org.springframework.webflow.engine.EndState; import org.springframework.webflow.engine.Flow; import org.springframework.webflow.engine.RequestControlContext; import org.springframework.webflow.engine.State; import org.springframework.webflow.execution.FlowExecution; import org.springframework.webflow.execution.FlowExecutionException; import org.springframework.webflow.execution.FlowExecutionKey; import org.springframework.webflow.execution.FlowExecutionKeyFactory; import org.springframework.webflow.execution.FlowExecutionListener; import org.springframework.webflow.execution.FlowExecutionListenerAdapter; import org.springframework.webflow.execution.FlowSession; import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader; import org.springframework.webflow.test.MockExternalContext; import org.springframework.webflow.test.MockFlowExecutionKey; /** * Test case for {@link FlowExecutionImplFactory}. */ public class FlowExecutionImplFactoryTests extends TestCase { private FlowExecutionImplFactory factory = new FlowExecutionImplFactory(); private Flow flowDefinition; private boolean starting; private boolean getKeyCalled; private boolean updateSnapshotCalled; private boolean removeSnapshotCalled; private boolean removeAllSnapshotsCalled; public void setUp() { flowDefinition = new Flow("flow"); new EndState(flowDefinition, "end"); } public void testCreate() { FlowExecution execution = factory.createFlowExecution(flowDefinition); assertSame(flowDefinition, execution.getDefinition()); assertFalse(execution.hasStarted()); assertFalse(execution.isActive()); } public void testCreateNullArgument() { try { factory.createFlowExecution(null); fail("Should've failed"); } catch (IllegalArgumentException e) { } } public void testCreateWithExecutionAttributes() { MutableAttributeMap<Object> attributes = new LocalAttributeMap<Object>(); attributes.put("foo", "bar"); factory.setExecutionAttributes(attributes); FlowExecution execution = factory.createFlowExecution(flowDefinition); assertEquals(attributes, execution.getAttributes()); assertSame("Flow execution attributes are global", attributes.asMap(), execution.getAttributes().asMap()); } public void testCreateWithExecutionListener() { FlowExecutionListener listener1 = new FlowExecutionListenerAdapter() { public void sessionStarting(RequestContext context, FlowSession session, MutableAttributeMap<?> input) { starting = true; } }; factory.setExecutionListenerLoader(new StaticFlowExecutionListenerLoader(listener1)); FlowExecution execution = factory.createFlowExecution(flowDefinition); assertFalse(execution.isActive()); execution.start(null, new MockExternalContext()); assertTrue(starting); } public void testCreateWithExecutionKeyFactory() { State state = new State(flowDefinition, "state") { protected void doEnter(RequestControlContext context) throws FlowExecutionException { context.assignFlowExecutionKey(); context.updateCurrentFlowExecutionSnapshot(); context.removeCurrentFlowExecutionSnapshot(); context.removeAllFlowExecutionSnapshots(); } }; flowDefinition.setStartState(state); factory.setExecutionKeyFactory(new MockFlowExecutionKeyFactory()); FlowExecution execution = factory.createFlowExecution(flowDefinition); execution.start(null, new MockExternalContext()); assertTrue(getKeyCalled); assertTrue(removeAllSnapshotsCalled); assertTrue(removeSnapshotCalled); assertTrue(updateSnapshotCalled); assertNull(execution.getKey()); } public void testRestoreExecutionState() { FlowExecutionImpl flowExecution = (FlowExecutionImpl) factory.createFlowExecution(flowDefinition); LocalAttributeMap<Object> executionAttributes = new LocalAttributeMap<Object>(); factory.setExecutionAttributes(executionAttributes); FlowExecutionListener listener = new FlowExecutionListenerAdapter() { }; factory.setExecutionListenerLoader(new StaticFlowExecutionListenerLoader(listener)); MockFlowExecutionKeyFactory keyFactory = new MockFlowExecutionKeyFactory(); factory.setExecutionKeyFactory(keyFactory); FlowExecutionKey flowExecutionKey = new MockFlowExecutionKey("e1s1"); LocalAttributeMap<Object> conversationScope = new LocalAttributeMap<Object>(); SimpleFlowDefinitionLocator locator = new SimpleFlowDefinitionLocator(); FlowSessionImpl session1 = new FlowSessionImpl(); session1.setFlowId("flow"); session1.setStateId("end"); FlowSessionImpl session2 = new FlowSessionImpl(); session2.setFlowId("child"); session2.setStateId("state"); flowExecution.getFlowSessions().add(session1); flowExecution.getFlowSessions().add(session2); factory.restoreFlowExecution(flowExecution, flowDefinition, flowExecutionKey, conversationScope, locator); assertSame("Flow execution attributes are global", flowExecution.getAttributes().asMap(), executionAttributes.asMap()); assertEquals(1, flowExecution.getListeners().length); assertSame(listener, flowExecution.getListeners()[0]); assertSame(flowExecutionKey, flowExecution.getKey()); assertSame(keyFactory, flowExecution.getKeyFactory()); assertSame(conversationScope, flowExecution.getConversationScope()); assertSame(((FlowSession) flowExecution.getFlowSessions().get(0)).getDefinition(), flowDefinition); assertSame(((FlowSession) flowExecution.getFlowSessions().get(0)).getDefinition().getState("end"), flowDefinition.getState("end")); assertSame(((FlowSession) flowExecution.getFlowSessions().get(1)).getDefinition(), locator.child); assertSame(((FlowSession) flowExecution.getFlowSessions().get(1)).getDefinition().getState("state"), locator.child.getState("state")); } private class MockFlowExecutionKeyFactory implements FlowExecutionKeyFactory { public FlowExecutionKey getKey(FlowExecution execution) { getKeyCalled = true; return null; } public void removeAllFlowExecutionSnapshots(FlowExecution execution) { removeAllSnapshotsCalled = true; } public void removeFlowExecutionSnapshot(FlowExecution execution) { removeSnapshotCalled = true; } public void updateFlowExecutionSnapshot(FlowExecution execution) { updateSnapshotCalled = true; } } private class SimpleFlowDefinitionLocator implements FlowDefinitionLocator { Flow child = new Flow("child"); public SimpleFlowDefinitionLocator() { new EndState(child, "state"); } public FlowDefinition getFlowDefinition(String flowId) throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException { if (flowId.equals(child.getId())) { return child; } else { throw new IllegalArgumentException(flowId.toString()); } } } }