Open pdalfarr opened 4 months ago
Adding the unit test in this ticket.
So the last assertion does fail:
assertThat(transitionsOfRegion2InStateMachine).isEqualTo(transitionsOfRegion2InStateMachineModel);
Unit test to add in UmlStateMachineModelFactoryTests.java :
public void testStateMachineVsStateMachineModelConsistency() {
context.refresh();
Resource model1 = new ClassPathResource("org/springframework/statemachine/uml/simple-root-regions.uml");
UmlStateMachineModelFactory builder = new UmlStateMachineModelFactory(model1);
builder.setBeanFactory(context);
assertThat(model1.exists()).isTrue();
StateMachineModel<String, String> stateMachineModel = builder.build();
try {
// build statemachine from model
UmlStateMachineModelFactory umlStateMachineModelFactory = new UmlStateMachineModelFactory(("classpath:org/springframework/statemachine/uml/simple-root-regions.uml"));
StateMachineBuilder.Builder<String, String> stateMachineBuilder = StateMachineBuilder.builder();
stateMachineBuilder.configureModel().withModel().factory(umlStateMachineModelFactory);
stateMachineBuilder.configureConfiguration().withConfiguration();
StateMachine<String, String> stateMachine = stateMachineBuilder.build();
// get the "root" state of this state machines
State<String, String> rootState = stateMachine.getStates().stream().findFirst().get();
assertThat(rootState).isInstanceOf(RegionState.class);
RegionState<String, String> rootRegionState = ((RegionState<String, String>) rootState);
// compare statemachine and stateMachineModel
// states in Region1
AbstractStateMachine region1InStatemachine = (AbstractStateMachine)
((List) rootRegionState.getRegions()).stream()
.filter(region -> ((AbstractStateMachine) region).getId().contains("Region1"))
.findFirst().get();
List statesOfRegion1InStateMachine = region1InStatemachine.getStates().stream()
.map(o -> ((State) o).getId().toString())
.sorted().toList();
List<String> statesOfRegion1InStateMachineModel = stateMachineModel.getStatesData().getStateData().stream()
.filter(stateData -> "Region1".equals(stateData.getRegion().toString()))
.map(stateData -> stateData.getState().toString())
.sorted().toList();
assertThat(statesOfRegion1InStateMachine).isEqualTo(statesOfRegion1InStateMachineModel);
// states in Region2
AbstractStateMachine region2InStatemachine = (AbstractStateMachine)
((List) rootRegionState.getRegions()).stream()
.filter(region -> ((AbstractStateMachine) region).getId().contains("Region2"))
.findFirst().get();
List statesOfRegion2InStateMachine = region2InStatemachine.getStates().stream()
.map(o -> ((State) o).getId().toString())
.sorted().toList();
List<String> statesOfRegion2InStateMachineModel = stateMachineModel.getStatesData().getStateData().stream()
.filter(stateData -> "Region2".equals(stateData.getRegion().toString()))
.map(stateData -> stateData.getState().toString())
.sorted().toList();
assertThat(statesOfRegion2InStateMachine).isEqualTo(statesOfRegion2InStateMachineModel);
// transitions in Region1
List transitionsOfRegion1InStateMachine = region1InStatemachine.getTransitions().stream()
.map(o -> ((Transition) o).getSource().getId().toString() + "->" + ((Transition) o).getTarget().getId().toString())
.sorted().toList();
List<String> transitionsOfRegion1InStateMachineModel = stateMachineModel.getTransitionsData().getTransitions().stream()
// let's exclude "initial" transition
.filter(transitionData -> !transitionData.getSource().startsWith("initial"))
.filter(transitionData -> statesOfRegion1InStateMachine.contains(transitionData.getSource())
|| statesOfRegion1InStateMachine.contains(transitionData.getTarget()))
.map(transitionData -> transitionData.getSource() + "->" + transitionData.getTarget())
.sorted().toList();
assertThat(transitionsOfRegion1InStateMachine).isEqualTo(transitionsOfRegion1InStateMachineModel);
// transitions in Region2
List transitionsOfRegion2InStateMachine = region2InStatemachine.getTransitions().stream()
.map(o -> ((Transition) o).getSource().getId().toString() + "->" + ((Transition) o).getTarget().getId().toString())
.sorted().toList();
List<String> transitionsOfRegion2InStateMachineModel = stateMachineModel.getTransitionsData().getTransitions().stream()
// let's exclude "initial" transition
.filter(transitionData -> !transitionData.getSource().startsWith("initial"))
.filter(transitionData -> statesOfRegion2InStateMachine.contains(transitionData.getSource())
|| statesOfRegion2InStateMachine.contains(transitionData.getTarget()))
.map(transitionData -> transitionData.getSource() + "->" + transitionData.getTarget())
.sorted().toList();
// WOW! this is failing! Why is transition "S1->S2" present in both Region1 AND Region2 ?!?
// Does this indicates an issue in UmlStateMachineModelFactory ???
// Expected :["S1->S2"]
// Actual :["S1->S2", "S3->S4"]
assertThat(transitionsOfRegion2InStateMachine).isEqualTo(transitionsOfRegion2InStateMachineModel);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Using simple-root-regions.uml to perform some tests, I encountered an unexpected situation where the 'transitions per regions' are not consistent between StateMachineModel and StateMachine.
I am using the simple-root-regions.uml file from this repository to create a StateMachineModel.
This StateMachineModel contains:
When I create a StateMachine based on this StateMachineModel, I end up with a StateMachine containing:
So it seems the "S1->S2" from Region1 has been duplicated in Regon2 as illustrated below.
Unit test available :-)
I created a unit test avalable here to help you troubleshot the issue. This unit test does compare a StateMachineModel and a StateMachine regarding: