/*
* Copyright 2016 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.statemachine.config.model;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.ObjectStateMachineFactory;
import org.springframework.statemachine.config.model.verifier.DefaultStateMachineModelVerifier;
import org.springframework.statemachine.config.model.verifier.StateMachineModelVerifier;
import org.springframework.statemachine.ensemble.StateMachineEnsemble;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.security.SecurityRule;
import org.springframework.statemachine.transition.TransitionKind;
import java.util.*;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
public class StateMachineModelTests {
@Test
public void testMachineManuallyViaModel() {
BeanFactory beanFactory = null;
TaskExecutor taskExecutor = new SyncTaskExecutor();
TaskScheduler taskScheduler = null;
boolean autoStart = false;
StateMachineEnsemble<String, String> ensemble = null;
List<StateMachineListener<String, String>> listeners = new ArrayList<>();
boolean securityEnabled = false;
AccessDecisionManager transitionSecurityAccessDecisionManager = null;
AccessDecisionManager eventSecurityAccessDecisionManager = null;
SecurityRule eventSecurityRule = null;
SecurityRule transitionSecurityRule = null;
boolean verifierEnabled = true;
StateMachineModelVerifier<String, String> verifier = new DefaultStateMachineModelVerifier<>();
ConfigurationData<String, String> configurationData = new ConfigurationData<>(beanFactory, taskExecutor, taskScheduler, autoStart,
ensemble, listeners, securityEnabled, transitionSecurityAccessDecisionManager, eventSecurityAccessDecisionManager,
eventSecurityRule, transitionSecurityRule, verifierEnabled, verifier, null, null);
Collection<StateData<String, String>> stateData = new ArrayList<>();
StateData<String, String> stateData1 = new StateData<String, String>(null, null, "S1", null, null, null);
stateData1.setInitial(true);
stateData.add(stateData1);
StateData<String, String> stateData2 = new StateData<String, String>(null, null, "S2", null, null, null);
stateData.add(stateData2);
StatesData<String, String> statesData = new StatesData<>(stateData);
Collection<TransitionData<String, String>> transitions = new ArrayList<>();
TransitionData<String, String> transitionData1 = new TransitionData<String, String>("S1", "S2", null, "E1", null, null, null, null, TransitionKind.EXTERNAL, null);
transitions.add(transitionData1);
Map<String, List<ChoiceData<String, String>>> choices = new HashMap<>();
Map<String, List<JunctionData<String, String>>> junctions = new HashMap<>();
Map<String, List<String>> forks = new HashMap<>();
Map<String, List<String>> joins = new HashMap<>();
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitions, choices, junctions, forks, joins, null, null, null);
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData, transitionsData);
ObjectStateMachineFactory<String, String> factory = new ObjectStateMachineFactory<>(stateMachineModel);
StateMachine<String,String> stateMachine = factory.getStateMachine();
stateMachine.start();
assertThat(stateMachine.getState().getIds(), contains("S1"));
stateMachine.sendEvent("E1");
assertThat(stateMachine.getState().getIds(), contains("S2"));
}
@Test
public void testMinimalConfig() {
ConfigurationData<String, String> configurationData = new ConfigurationData<>();
Collection<StateData<String, String>> stateData = new ArrayList<>();
stateData.add(new StateData<String, String>("S1", true));
stateData.add(new StateData<String, String>("S2"));
StatesData<String, String> statesData = new StatesData<>(stateData);
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
transitionData.add(new TransitionData<String, String>("S1", "S2", "E1"));
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData, transitionsData);
ObjectStateMachineFactory<String, String> factory = new ObjectStateMachineFactory<>(stateMachineModel);
StateMachine<String,String> stateMachine = factory.getStateMachine();
stateMachine.start();
assertThat(stateMachine.getState().getIds(), contains("S1"));
stateMachine.sendEvent("E1");
assertThat(stateMachine.getState().getIds(), contains("S2"));
}
@Test
public void testSubmachineRefConfig() {
// *S1 S2
// / \
// *S20 S21
// / \
// *S30 S31
ConfigurationData<String, String> configurationData = new ConfigurationData<>();
Collection<StateData<String, String>> stateData2 = new ArrayList<>();
stateData2.add(new StateData<String, String>("S2", null, "S20", true));
stateData2.add(new StateData<String, String>("S2", null, "S21", false));
stateData2.add(new StateData<String, String>("S21", null, "S30", true));
stateData2.add(new StateData<String, String>("S21", null, "S31", false));
Collection<StateData<String, String>> stateData1 = new ArrayList<>();
stateData1.add(new StateData<String, String>("S1", true));
StateData<String, String> stateDataS2 = new StateData<String, String>("S2");
stateDataS2.setSubmachineStateData(stateData2);
stateData1.add(stateDataS2);
StatesData<String, String> statesData = new StatesData<>(stateData1);
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
transitionData.add(new TransitionData<String, String>("S1", "S2", "E1"));
transitionData.add(new TransitionData<String, String>("S20", "S21", "E2"));
transitionData.add(new TransitionData<String, String>("S30", "S31", "E3"));
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData, transitionsData);
ObjectStateMachineFactory<String, String> factory = new ObjectStateMachineFactory<>(stateMachineModel);
StateMachine<String,String> stateMachine = factory.getStateMachine();
stateMachine.start();
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S1"));
stateMachine.sendEvent("E1");
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2", "S20"));
stateMachine.sendEvent("E2");
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2", "S21", "S30"));
stateMachine.sendEvent("E3");
assertThat(stateMachine.getState().getIds(), containsInAnyOrder("S2", "S21", "S31"));
}
}