diff --git a/README.md b/README.md index 8e24686..4e8d52d 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ val currentState = stateMachine.createState(currentSutState, 1) val action = new NavigateToAction("http://google.com") val nextSutState = new SutState(nextDescriptors) val nextState = stateMachine.createState(nextSutState, 1) -stateMachine.executeAction(currentState, action, nextState) +stateMachine.executeAction(currentState, action, nextState, true) GuiStateMachineSerializer.javaObjectStream(stateMachine).save("mystatemachine.ser") GuiStateMachineSerializer.gml(stateMachine).save("mystatemachine.gml") diff --git a/src/main/scala/de/retest/guistatemachine/api/GuiStateMachine.scala b/src/main/scala/de/retest/guistatemachine/api/GuiStateMachine.scala index b50a293..6d1216c 100644 --- a/src/main/scala/de/retest/guistatemachine/api/GuiStateMachine.scala +++ b/src/main/scala/de/retest/guistatemachine/api/GuiStateMachine.scala @@ -44,8 +44,9 @@ trait GuiStateMachine { * @param to The state which the execution leads to. * @return The number of times the action has been executed. */ - def executeAction(from: State, a: ActionIdentifier, to: State): Int = from.addTransition(a, to) - def executeAction(from: State, a: Action, to: State): Int = executeAction(from, new ActionIdentifier(a), to) + def executeAction(from: State, a: ActionIdentifier, to: State, isUnexploredActionType: Boolean): Int = from.addTransition(a, to, isUnexploredActionType) + def executeAction(from: State, a: Action, to: State, isUnexploredActionType: Boolean): Int = + executeAction(from, new ActionIdentifier(a), to, isUnexploredActionType) def getAllStates: Map[SutStateIdentifier, State] diff --git a/src/main/scala/de/retest/guistatemachine/api/State.scala b/src/main/scala/de/retest/guistatemachine/api/State.scala index 7fd4e5b..7f3197c 100644 --- a/src/main/scala/de/retest/guistatemachine/api/State.scala +++ b/src/main/scala/de/retest/guistatemachine/api/State.scala @@ -55,7 +55,8 @@ trait State { * * @param a The action which represents the transition's consumed symbol. * @param to The state which the transition leads t o. + * @param isUnexploredActionType If this flag is true, the never explored action types counter is decreased. * @return The number of times the action has been executed from this state. The target state does not matter for this number. */ - private[api] def addTransition(a: ActionIdentifier, to: State): Int + private[api] def addTransition(a: ActionIdentifier, to: State, isUnexploredActionType: Boolean): Int } diff --git a/src/main/scala/de/retest/guistatemachine/api/impl/StateImpl.scala b/src/main/scala/de/retest/guistatemachine/api/impl/StateImpl.scala index 452e21a..25e909a 100644 --- a/src/main/scala/de/retest/guistatemachine/api/impl/StateImpl.scala +++ b/src/main/scala/de/retest/guistatemachine/api/impl/StateImpl.scala @@ -5,9 +5,7 @@ import de.retest.guistatemachine.api.{ActionIdentifier, ActionTransitions, State import scala.collection.immutable.HashMap @SerialVersionUID(1L) -case class StateImpl(sutState: SutStateIdentifier, var neverExploredActionTypesCounter: Int) - extends State - with Serializable { +case class StateImpl(sutState: SutStateIdentifier, var neverExploredActionTypesCounter: Int) extends State with Serializable { /** * Currently, there is no MultiMap trait for immutable maps in the Scala standard library. @@ -29,8 +27,12 @@ case class StateImpl(sutState: SutStateIdentifier, var neverExploredActionTypesC } override def getNeverExploredActionTypesCounter: Int = this.synchronized { neverExploredActionTypesCounter } - private[api] override def addTransition(a: ActionIdentifier, to: State): Int = { + private[api] override def addTransition(a: ActionIdentifier, to: State, isUnexploredActionType: Boolean): Int = { val executionCounter = this.synchronized { + if (isUnexploredActionType) { + neverExploredActionTypesCounter = neverExploredActionTypesCounter - 1 + } + outgoingActionTransitions.get(a) match { case Some(oldTransitions) => val updatedTransitions = ActionTransitions(oldTransitions.states + to, oldTransitions.executionCounter + 1) @@ -39,7 +41,6 @@ case class StateImpl(sutState: SutStateIdentifier, var neverExploredActionTypesC case None => outgoingActionTransitions += (a -> ActionTransitions(Set(to), 1)) - neverExploredActionTypesCounter = neverExploredActionTypesCounter - 1 1 } } diff --git a/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GraphicsProvider.scala b/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GraphicsProvider.scala index 77c1011..c283108 100644 --- a/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GraphicsProvider.scala +++ b/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GraphicsProvider.scala @@ -7,7 +7,11 @@ import de.retest.guistatemachine.api.SutStateIdentifier class GraphicsProvider extends YedGmlGraphicsProvider[SutStateIdentifier, GraphActionEdge, AnyRef] { override def getVertexGraphics(vertex: SutStateIdentifier): NodeGraphicDefinition = - new NodeGraphicDefinition.Builder().setFill(Color.LIGHT_GRAY).setLineColor(Color.black).setFontStyle(GraphicDefinition.FontStyle.ITALIC).build + new NodeGraphicDefinition.Builder() + .setFill(Color.LIGHT_GRAY) + .setLineColor(Color.black) + .setFontStyle(GraphicDefinition.FontStyle.ITALIC) + .build override def getEdgeGraphics(edge: GraphActionEdge, edgeSource: SutStateIdentifier, edgeTarget: SutStateIdentifier): EdgeGraphicDefinition = new EdgeGraphicDefinition.Builder() .setTargetArrow(EdgeGraphicDefinition.ArrowType.SHORT_ARROW) diff --git a/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachinGMLSerializer.scala b/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachinGMLSerializer.scala index 25a56dd..215ef4a 100644 --- a/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachinGMLSerializer.scala +++ b/src/main/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachinGMLSerializer.scala @@ -47,7 +47,8 @@ class GuiStateMachinGMLSerializer(guiStateMachine: GuiStateMachine) extends GuiS allStatesSorted.foreach { x => val fromVertex = x._1 - val allOutgoingActionTransitionsSorted = x._2.getOutgoingActionTransitions.toSeq.sortWith(hashCodeComparisonOfTuples) + val allOutgoingActionTransitionsSorted = + x._2.getOutgoingActionTransitions.toSeq.sortWith(hashCodeComparisonOfTuples) allOutgoingActionTransitionsSorted foreach { transition => val actionTransitions = transition._2 diff --git a/src/test/scala/de/retest/guistatemachine/api/impl/GuiStateMachineImplSpec.scala b/src/test/scala/de/retest/guistatemachine/api/impl/GuiStateMachineImplSpec.scala index bcc874d..fc3128a 100644 --- a/src/test/scala/de/retest/guistatemachine/api/impl/GuiStateMachineImplSpec.scala +++ b/src/test/scala/de/retest/guistatemachine/api/impl/GuiStateMachineImplSpec.scala @@ -44,7 +44,7 @@ class GuiStateMachineImplSpec extends AbstractApiSpec with BeforeAndAfterEach { // execute action0 for the first time val s0SutState = createSutState(rootElementA) val s0 = sut.createState(s0SutState, 2) - sut.executeAction(initial, action0, s0) shouldEqual 1 + sut.executeAction(initial, action0, s0, true) shouldEqual 1 initial.getOutgoingActionTransitions.size shouldEqual 1 initial.getOutgoingActionTransitions(action0Identifier).states.size shouldEqual 1 initial.getOutgoingActionTransitions(action0Identifier).executionCounter shouldEqual 1 @@ -59,7 +59,7 @@ class GuiStateMachineImplSpec extends AbstractApiSpec with BeforeAndAfterEach { // execute action0 for the second time val s1SutState = createSutState(rootElementB) val s1 = sut.createState(s1SutState, 2) - sut.executeAction(initial, action0, s1) shouldEqual 2 + sut.executeAction(initial, action0, s1, true) shouldEqual 2 initial.getOutgoingActionTransitions.size shouldEqual 1 initial.getOutgoingActionTransitions(action0Identifier).states.size shouldEqual 2 initial.getOutgoingActionTransitions(action0Identifier).executionCounter shouldEqual 2 @@ -74,7 +74,7 @@ class GuiStateMachineImplSpec extends AbstractApiSpec with BeforeAndAfterEach { // execute action1 for the first time val s2SutState = createSutState(rootElementC) val s2 = sut.createState(s2SutState, 2) - sut.executeAction(initial, action1, s2) shouldEqual 1 + sut.executeAction(initial, action1, s2, true) shouldEqual 1 initial.getOutgoingActionTransitions.size shouldEqual 2 initial.getOutgoingActionTransitions(action1Identifier).states.size shouldEqual 1 initial.getOutgoingActionTransitions(action1Identifier).executionCounter shouldEqual 1 @@ -87,7 +87,7 @@ class GuiStateMachineImplSpec extends AbstractApiSpec with BeforeAndAfterEach { s2.getNeverExploredActionTypesCounter shouldEqual 2 // execute action1 for the second time but from s1SutState to create one incoming action from two different states - sut.executeAction(s1, action1, s2) shouldEqual 1 + sut.executeAction(s1, action1, s2, true) shouldEqual 1 s1.getOutgoingActionTransitions.size shouldEqual 1 s1.getOutgoingActionTransitions(action1Identifier).states.size shouldEqual 1 s1.getOutgoingActionTransitions(action1Identifier).executionCounter shouldEqual 1 diff --git a/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineGMLSerializerSpec.scala b/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineGMLSerializerSpec.scala index d11ebe4..2faa029 100644 --- a/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineGMLSerializerSpec.scala +++ b/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineGMLSerializerSpec.scala @@ -28,10 +28,10 @@ class GuiStateMachineGMLSerializerSpec extends AbstractApiSpec with BeforeAndAft // Create the whole state machine: val initialState = guiStateMachine.createState(initialSutState, 2) val finalState = guiStateMachine.createState(finalSutState, 2) - guiStateMachine.executeAction(initialState, action0, finalState) - guiStateMachine.executeAction(initialState, action1, finalState) - guiStateMachine.executeAction(finalState, action0, initialState) - guiStateMachine.executeAction(finalState, action1, initialState) + guiStateMachine.executeAction(initialState, action0, finalState, true) + guiStateMachine.executeAction(initialState, action1, finalState, true) + guiStateMachine.executeAction(finalState, action0, initialState, true) + guiStateMachine.executeAction(finalState, action1, initialState, true) val filePath = "./target/test_state_machine.gml" val oldFile = new File(filePath) diff --git a/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineJavaObjectStreamSerializerSpec.scala b/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineJavaObjectStreamSerializerSpec.scala index e1c4e7a..9b2a18e 100644 --- a/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineJavaObjectStreamSerializerSpec.scala +++ b/src/test/scala/de/retest/guistatemachine/api/impl/serialization/GuiStateMachineJavaObjectStreamSerializerSpec.scala @@ -37,7 +37,7 @@ class GuiStateMachineJavaObjectStreamSerializerSpec extends AbstractApiSpec with // Create the whole state machine: val initialState = guiStateMachine.createState(initialSutStateIdentifier, 1) val finalState = guiStateMachine.createState(finalSutStateIdentifier, 1) - guiStateMachine.executeAction(initialState, action0, finalState) + guiStateMachine.executeAction(initialState, action0, finalState, true) // Save the state machine: GuiStateMachineSerializer.javaObjectStream(guiStateMachine).save(filePath)