state machine unit test
This commit is contained in:
parent
a14ca74a69
commit
5462caf3f1
2 changed files with 178 additions and 166 deletions
|
|
@ -8,8 +8,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.config.StateMachineFactory;
|
||||
import ru.spcex.clearing.session.teststate.config.Event;
|
||||
import ru.spcex.clearing.session.teststate.config.State;
|
||||
import ru.spcex.clearing.session.stage.TaskType;
|
||||
import ru.spcex.clearing.session.state.SsnEvent;
|
||||
import ru.spcex.clearing.session.teststate.config.TestStateMachineConfig;
|
||||
import ru.spcex.clearing.session.teststate.config.TestStateMachineExecutorsConfig;
|
||||
|
||||
|
|
@ -21,9 +21,9 @@ class StateMachineTest {
|
|||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Autowired
|
||||
private StateMachineFactory<State, Event> stateMachineFactory;
|
||||
private StateMachineFactory<TaskType, SsnEvent> stateMachineFactory;
|
||||
|
||||
private StateMachine<State, Event> stateMachine;
|
||||
private StateMachine<TaskType, SsnEvent> stateMachine;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
|
|
@ -35,7 +35,7 @@ class StateMachineTest {
|
|||
|
||||
@Test
|
||||
void test() {
|
||||
log.debug("test???");
|
||||
log.debug("test started");
|
||||
// stateMachine
|
||||
// .getStateMachineAccessor()
|
||||
// .doWithRegion(function -> function.addStateMachineInterceptor(
|
||||
|
|
@ -84,20 +84,20 @@ class StateMachineTest {
|
|||
// }
|
||||
// }));
|
||||
|
||||
stateMachine.sendEvent(Event.startSession);
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
stateMachine.sendEvent(Event.SDF_01);
|
||||
stateMachine.sendEvent(Event.SDF_04);
|
||||
stateMachine.sendEvent(Event.SDF_57);
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// stateMachine.sendEvent(SsnEvent.);
|
||||
// try {
|
||||
// Thread.sleep(5000);
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// stateMachine.sendEvent(Event.SDF_01);
|
||||
// stateMachine.sendEvent(Event.SDF_04);
|
||||
// stateMachine.sendEvent(Event.SDF_57);
|
||||
// try {
|
||||
// Thread.sleep(10000);
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// stateMachine.sendEvent(Event.continueRevise);
|
||||
// log.info("'ve send a continueRevise");
|
||||
// try {
|
||||
|
|
@ -109,7 +109,20 @@ class StateMachineTest {
|
|||
// stateMachine.stop();
|
||||
// log.info("SECOND STOP");
|
||||
// stateMachine.stop();
|
||||
sleepForNSec(5);
|
||||
stateMachine.sendEvent(SsnEvent.SDF_57);
|
||||
sleepForNSec(5);
|
||||
stateMachine.sendEvent(SsnEvent.CONTINUE);
|
||||
sleepForNSec(5);
|
||||
log.info("So. We end with SM in state: {}", stateMachine.getState().getId());;
|
||||
}
|
||||
|
||||
public static void sleepForNSec(int i) {
|
||||
try {
|
||||
Thread.sleep((i * 1000L));
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("***** INTERRUPTED");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
package ru.spcex.clearing.session.teststate.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
|
|
@ -19,17 +18,18 @@ import org.springframework.statemachine.config.builders.StateMachineStateConfigu
|
|||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
import org.springframework.statemachine.transition.Transition;
|
||||
import ru.spcex.clearing.session.teststate.config.action.ContinueReviseTestAction;
|
||||
import ru.spcex.clearing.session.teststate.config.action.InitialAction;
|
||||
import ru.spcex.clearing.session.teststate.config.action.SelfAction;
|
||||
import ru.spcex.clearing.session.teststate.config.action.Send56TestAction;
|
||||
import ru.spcex.clearing.session.teststate.config.guard.NoActiveSessionGuard;
|
||||
import ru.spcex.clearing.util.StateMachineUtil;
|
||||
import ru.spcex.clearing.session.stage.TaskType;
|
||||
import ru.spcex.clearing.session.state.SsnEvent;
|
||||
import ru.spcex.clearing.session.state.action.SdfReceivedAction;
|
||||
import ru.spcex.clearing.session.state.guard.PaymentsWereCreatedGuard;
|
||||
import ru.spcex.clearing.session.state.guard.SdfGuard;
|
||||
import ru.spcex.clearing.session.state.guard.SdfGuardExtractorAfterAssets;
|
||||
import static ru.spcex.clearing.util.StateMachineUtil.chain;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachineFactory
|
||||
public class TestStateMachineConfig extends EnumStateMachineConfigurerAdapter<State, Event> {
|
||||
public class TestStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Autowired
|
||||
|
|
@ -38,179 +38,178 @@ public class TestStateMachineConfig extends EnumStateMachineConfigurerAdapter<St
|
|||
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineStateConfigurer<State, Event> states) throws Exception {
|
||||
public void configure(StateMachineStateConfigurer<TaskType, SsnEvent> states) throws Exception {
|
||||
states
|
||||
.withStates()
|
||||
.initial(State.initial, StateMachineUtil.chain(new InitialAction(), new SelfAction()))
|
||||
.state(State.initial)
|
||||
.state(State.startRevise)
|
||||
.state(State.continueRevise, Event.triggerInternal)
|
||||
.state(State.stateWithInternalTransition)
|
||||
.state(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||
.state(State.stateWaitingForSdf)
|
||||
.state(State.stateAfterSdfReceived)
|
||||
;
|
||||
.initial(TaskType.StartRevise, chain(
|
||||
context -> log.info("create session action"),
|
||||
context -> log.info("send sdf56 action")))
|
||||
.states(new HashSet<>(Arrays.asList(
|
||||
TaskType.StartRevise,
|
||||
TaskType.StartRevisePart1,
|
||||
TaskType.DealsPrepare,
|
||||
TaskType.RequirementsAndObligationsCreate,
|
||||
TaskType.ObligationsAdmission,
|
||||
TaskType.InclusionToPool,
|
||||
TaskType.InspectionObligations,
|
||||
TaskType.FormingRegistersOnOS,
|
||||
TaskType.FormingPaymentInstruction,
|
||||
TaskType.FinishingSession,
|
||||
TaskType.EndStageNotification,
|
||||
TaskType.PSEUDO_waitingForSdf,
|
||||
TaskType.PSEUDO_waitingForObligationAdmission
|
||||
)))
|
||||
.end(TaskType.EndStageNotification);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineTransitionConfigurer<State, Event> transitions) throws Exception {
|
||||
public void configure(StateMachineTransitionConfigurer<TaskType, SsnEvent> transitions) throws Exception {
|
||||
transitions
|
||||
.withExternal()
|
||||
.source(State.initial)
|
||||
.target(State.startRevise)
|
||||
.event(Event.startSession)
|
||||
.guard(new NoActiveSessionGuard())
|
||||
.action(new Send56TestAction())
|
||||
.and()
|
||||
.event(SsnEvent.SDF_57)
|
||||
.source(TaskType.StartRevise).target(TaskType.StartRevisePart1)
|
||||
.action(context -> log.info("reviseStage1Action"))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(State.startRevise)
|
||||
.target(State.continueRevise)
|
||||
.action(new ContinueReviseTestAction())
|
||||
|
||||
//.and()
|
||||
//.withExternal()
|
||||
// .source(State.continueRevise)
|
||||
// .target(State.newState)
|
||||
// .action(context -> log.info("action without an event"))
|
||||
.and()
|
||||
.source(TaskType.StartRevisePart1).target(TaskType.DealsPrepare)
|
||||
.action(context -> log.info("dealsPrepareAction"))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(State.continueRevise)
|
||||
.target(State.stateWithInternalTransition)
|
||||
.action(context -> {
|
||||
log.info("ACTION without an event");
|
||||
// context.getStateMachine().sendEvent(Event.triggerInternal);
|
||||
})
|
||||
.and()
|
||||
.withInternal()
|
||||
.source(State.stateWithInternalTransition)
|
||||
.action(context -> {
|
||||
log.info("ACTION INTERNAL without an event");
|
||||
})
|
||||
.action(context -> {
|
||||
log.info("ACTION INTERNAL second without an event");
|
||||
})
|
||||
.and()
|
||||
.source(TaskType.DealsPrepare).target(TaskType.RequirementsAndObligationsCreate)
|
||||
.action(context -> log.info("reqAndOblAction"))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(State.stateWithInternalTransition)
|
||||
.timerOnce(1)
|
||||
.target(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||
.action(ctx -> {
|
||||
log.info("ACTION after internal transition");
|
||||
List<Object> list = new ArrayList<>();
|
||||
list.add("fasdfasdf");
|
||||
ctx.getExtendedState().getVariables().put("payments", list);
|
||||
})
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||
.target(State.stateAfterSdfReceived)
|
||||
.action(ctx -> log.info("ACTION stateAutoTransitionAfterInternalAutoTransition to stateAfterSdfReceived without waiting"))
|
||||
.guard(ctx -> {
|
||||
List list = ctx.getExtendedState().get("payments", List.class);
|
||||
return list != null && list.isEmpty();
|
||||
})
|
||||
.and()
|
||||
.source(TaskType.RequirementsAndObligationsCreate).target(TaskType.ObligationsAdmission)
|
||||
.action(context -> log.info("obligationAdmissionAction"))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||
.target(State.stateWaitingForSdf)
|
||||
.action(ctx -> log.info("ACTION stateAutoTransitionAfterInternalAutoTransition to stateWaitingForSdf"))
|
||||
.guard(ctx -> {
|
||||
List list = ctx.getExtendedState().get("payments", List.class);
|
||||
return list != null && !list.isEmpty();
|
||||
})
|
||||
.and()
|
||||
.source(TaskType.ObligationsAdmission)
|
||||
.target(TaskType.PSEUDO_waitingForObligationAdmission)
|
||||
.guard(context -> true)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(State.stateWaitingForSdf)
|
||||
.target(State.stateAfterSdfReceived)
|
||||
.guard(ctx -> {
|
||||
Boolean sdf01Received = ctx.getExtendedState().get(Event.SDF_01.name(), Boolean.class);
|
||||
Boolean sdf04Received = ctx.getExtendedState().get(Event.SDF_04.name(), Boolean.class);
|
||||
Boolean sdf57Received = ctx.getExtendedState().get(Event.SDF_57.name(), Boolean.class);
|
||||
log.info("GUARD received sdfs: sdf01={}, sdf04={}, sdf57={}",
|
||||
sdf01Received, sdf04Received, sdf57Received);
|
||||
return Boolean.TRUE.equals(sdf01Received)
|
||||
&& Boolean.TRUE.equals(sdf04Received)
|
||||
&& Boolean.TRUE.equals(sdf57Received);
|
||||
});
|
||||
|
||||
for (var event : EnumSet.of(Event.SDF_01, Event.SDF_04, Event.SDF_57)) {
|
||||
.source(TaskType.PSEUDO_waitingForObligationAdmission).target(TaskType.InclusionToPool)
|
||||
.action(chain(ctx -> log.info("obligationAdmissionContinueAction"), ctx -> log.info("inclusionToPoolAction")))
|
||||
.event(SsnEvent.CONTINUE)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TaskType.PSEUDO_waitingForObligationAdmission).target(TaskType.ObligationsAdmission)
|
||||
.action(chain(act("discardOblAdmStash"), act("obligationAdmissionAction")))
|
||||
.event(SsnEvent.REPEAT)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TaskType.ObligationsAdmission).target(TaskType.InclusionToPool)
|
||||
.guard(context -> false) //invert(oblAdmGuard)
|
||||
.action(chain(act("obligationAdmissionContinueAction"), act("inclusionToPoolAction")))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TaskType.InclusionToPool).target(TaskType.InspectionObligations)
|
||||
.action(act("inspOblDepositReturnAction"))
|
||||
.action(act("inspectionObligationsV2Action"))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TaskType.InspectionObligations).target(TaskType.FormingPaymentInstruction)
|
||||
.action(act("formingPaymentInstructionReturnMkrAction"))
|
||||
.action(act("formingPaymentInstructionAssetsAction"))
|
||||
.and()
|
||||
//если не создалось paymentInstruction'ов
|
||||
.withExternal()
|
||||
.source(TaskType.FormingPaymentInstruction)
|
||||
.target(TaskType.FinishingSession)
|
||||
.guard(ctx -> true) //PaymentsWereNotCreatedGuard.instance
|
||||
.action(act("finishingSessionAction"))
|
||||
.and()
|
||||
//если создались paymentInstruction, переходим в режим ожидания
|
||||
.withExternal()
|
||||
.source(TaskType.FormingPaymentInstruction)
|
||||
.target(TaskType.PSEUDO_waitingForSdf)
|
||||
.guard(PaymentsWereCreatedGuard.instance)
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TaskType.PSEUDO_waitingForSdf)
|
||||
.target(TaskType.FinishingSession)
|
||||
.guard(new SdfGuard(SdfGuardExtractorAfterAssets.instance))
|
||||
.action(act("finishingSessionAction"))
|
||||
.and()
|
||||
.withExternal()
|
||||
.source(TaskType.FinishingSession)
|
||||
.target(TaskType.EndStageNotification)
|
||||
.action(act("endStageNotificationAction"));
|
||||
for (var event: EnumSet.of(SsnEvent.SDF_01, SsnEvent.SDF_57, SsnEvent.SDF_04)) {
|
||||
transitions
|
||||
.withInternal()
|
||||
.source(State.stateWaitingForSdf)
|
||||
.source(TaskType.PSEUDO_waitingForSdf)
|
||||
.event(event)
|
||||
.action(eventReceivedAction());
|
||||
.action(SdfReceivedAction.instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Action<State, Event> eventReceivedAction() {
|
||||
return ctx -> {
|
||||
log.info("event {} flag saving received", ctx.getEvent().name());
|
||||
ctx.getExtendedState().getVariables().put(ctx.getEvent().name(), true);
|
||||
};
|
||||
private Action<TaskType, SsnEvent> act(String actionName) {
|
||||
return ctx -> log.info(actionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<State, Event> config) throws Exception {
|
||||
StateMachineListenerAdapter<State, Event> loggingChangeStateListener = new StateMachineListenerAdapter<>() {
|
||||
@Override
|
||||
public void stateEntered(org.springframework.statemachine.state.State<State, Event> state) {
|
||||
State enteredState = state != null ? state.getId() : null;
|
||||
log.info(String.format("LISTENER stateEntered: %s", enteredState));
|
||||
}
|
||||
public void configure(StateMachineConfigurationConfigurer<TaskType, SsnEvent> config) throws Exception {
|
||||
StateMachineListenerAdapter<TaskType, SsnEvent> loggingChangeStateListener = new StateMachineListenerAdapter<>() {
|
||||
// @Override
|
||||
// public void stateEntered(org.springframework.statemachine.state.State<TaskType, SsnEvent> state) {
|
||||
// TaskType enteredState = state != null ? state.getId() : null;
|
||||
// log.info(String.format("LISTENER stateEntered: %s", enteredState));
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public void eventNotAccepted(Message<SsnEvent> event) {
|
||||
// SsnEvent payload = event != null ? event.getPayload() : null;
|
||||
// log.info(String.format("LISTENER eventNotAccepted: %s", payload));
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void eventNotAccepted(Message<Event> event) {
|
||||
Event payload = event != null ? event.getPayload() : null;
|
||||
log.info(String.format("LISTENER eventNotAccepted: %s", payload));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transition(Transition<State, Event> transition) {
|
||||
State source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||
State target = transition.getTarget().getId();
|
||||
public void transition(Transition<TaskType, SsnEvent> transition) {
|
||||
TaskType source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||
TaskType target = transition.getTarget().getId();
|
||||
log.info("LISTENER transition: source {} target {}",
|
||||
source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(org.springframework.statemachine.state.State<State, Event> from, org.springframework.statemachine.state.State<State, Event> to) {
|
||||
State source = from != null ? from.getId() : null;
|
||||
State target = to.getId();
|
||||
log.info("LISTENER stateChanged: source {} target {}",
|
||||
source, target);
|
||||
}
|
||||
// @Override
|
||||
// public void stateChanged(org.springframework.statemachine.state.State<TaskType, SsnEvent> from, org.springframework.statemachine.state.State<TaskType, SsnEvent> to) {
|
||||
// TaskType source = from != null ? from.getId() : null;
|
||||
// TaskType target = to.getId();
|
||||
// log.info("LISTENER stateChanged: source {} target {}",
|
||||
// source, target);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public void stateExited(org.springframework.statemachine.state.State<TaskType, SsnEvent> state) {
|
||||
// TaskType whichOne = state != null ? state.getId() : null;
|
||||
// log.info("LISTENER stateExited: {}", whichOne);
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public void transitionEnded(Transition<TaskType, SsnEvent> transition) {
|
||||
// TaskType source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||
// TaskType target = transition.getTarget().getId();
|
||||
// log.info("LISTENER transitionEnded: source {} target {}",
|
||||
// source, target);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void stateExited(org.springframework.statemachine.state.State<State, Event> state) {
|
||||
State whichOne = state != null ? state.getId() : null;
|
||||
log.info("LISTENER stateExited: {}", whichOne);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transitionEnded(Transition<State, Event> transition) {
|
||||
State source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||
State target = transition.getTarget().getId();
|
||||
log.info("LISTENER transitionEnded: source {} target {}",
|
||||
source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateMachineError(StateMachine<State, Event> stateMachine, Exception exception) {
|
||||
public void stateMachineError(StateMachine<TaskType, SsnEvent> stateMachine, Exception exception) {
|
||||
log.info("LISTENER stateMachineError: {}", (ExceptionUtils.getStackTrace(exception)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transitionStarted(Transition<State, Event> transition) {
|
||||
State source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||
State target = transition.getTarget().getId();
|
||||
log.info("LISTENER transitionStarted: source {} target {}",
|
||||
source, target);
|
||||
}
|
||||
// @Override
|
||||
// public void transitionStarted(Transition<TaskType, SsnEvent> transition) {
|
||||
// TaskType source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||
// TaskType target = transition.getTarget().getId();
|
||||
// log.info("LISTENER transitionStarted: source {} target {}",
|
||||
// source, target);
|
||||
// }
|
||||
};
|
||||
config
|
||||
.withConfiguration()
|
||||
.machineId("test-machine")
|
||||
.listener(loggingChangeStateListener)
|
||||
// .taskExecutor(taskExecutor)
|
||||
;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue