|
@@ -0,0 +1,241 @@
|
|
|
+import java.io.File
|
|
|
+
|
|
|
+import modbat.mbt.MBT
|
|
|
+import org.scalatest.FlatSpec
|
|
|
+import scalax.collection.Graph
|
|
|
+
|
|
|
+import scala.xml.XML
|
|
|
+import scalax.collection.edge.LkDiEdge
|
|
|
+
|
|
|
+class GraphMLTests extends FlatSpec{
|
|
|
+ "XMLParser" should "Work" in {
|
|
|
+ val graphml_file = getClass.getResource("/graphs/flat.graphml")
|
|
|
+ val contents = XML.load(graphml_file)
|
|
|
+// print(contents)
|
|
|
+ }
|
|
|
+
|
|
|
+ "Graph Lib" should "Allow for hierarchical graphs" in {
|
|
|
+ case class MyLabel(i: Int)
|
|
|
+
|
|
|
+ case class MyNode(l: String)
|
|
|
+
|
|
|
+ val outerEdge = LkDiEdge(MyNode("a"),MyNode("b"))(MyLabel(4))
|
|
|
+ outerEdge.label.i // all right: 4
|
|
|
+ val g = Graph(outerEdge)
|
|
|
+// print(g)
|
|
|
+ }
|
|
|
+
|
|
|
+ "Transform flat graph" should "work" in {
|
|
|
+ val f = getClass.getResourceAsStream("/graphs/flat.graphml")
|
|
|
+ val graph = GraphMLLoader.createGraph(f)
|
|
|
+ assert(graph.nodes.size == 3)
|
|
|
+ assert(graph.edges.size == 3)
|
|
|
+ val instantiated = findNodeData(graph, "instantiated")
|
|
|
+
|
|
|
+ val edge = findEdge(graph, "e_terminate")
|
|
|
+ edge.source.value match {
|
|
|
+ case FlatNodeData(_, label) => assert(label=="instantiated")
|
|
|
+ }
|
|
|
+ edge.target.value match {
|
|
|
+ case FlatNodeData(_, label) => assert(label=="terminated")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ def findEdge(graph: Graph[NodeData, LkDiEdge], lbl:String) = {
|
|
|
+ val res = graph.edges.find(n => n.label match {
|
|
|
+ case EdgeData(_,label,_) => label==lbl
|
|
|
+ case _ => false
|
|
|
+ })
|
|
|
+ assert(res.isDefined)
|
|
|
+ res.get
|
|
|
+ }
|
|
|
+
|
|
|
+ def findEdges(graph: Graph[NodeData, LkDiEdge], lbl:String) = {
|
|
|
+ val res = graph.edges.filter(n => n.label match {
|
|
|
+ case EdgeData(_,label,_) => label==lbl
|
|
|
+ case _ => false
|
|
|
+ })
|
|
|
+ assert(res.nonEmpty)
|
|
|
+ res
|
|
|
+ }
|
|
|
+
|
|
|
+ def findNodeData(graph: Graph[NodeData, LkDiEdge], lbl:String): NodeData = {
|
|
|
+ val res = graph.nodes.find(n => n.value match {
|
|
|
+ case FlatNodeData(_, label) => label==lbl
|
|
|
+ case HierarchicalNodeData(_, label, _) => label==lbl
|
|
|
+ case _ => false
|
|
|
+ })
|
|
|
+ assert(res.isDefined)
|
|
|
+ res.get
|
|
|
+ }
|
|
|
+
|
|
|
+ "Transform hierarchical graph" should "work" in {
|
|
|
+ val f = getClass.getResourceAsStream("/graphs/hierarchical.graphml")
|
|
|
+ val graph = GraphMLLoader.createGraph(f)
|
|
|
+ assert(graph.nodes.size == 3)
|
|
|
+ assert(graph.edges.size == 2)
|
|
|
+ val group1 = findNodeData(graph, "group1")
|
|
|
+ val subGraph = group1.asInstanceOf[HierarchicalNodeData].child
|
|
|
+
|
|
|
+ assert(subGraph.nodes.size == 2)
|
|
|
+ assert(subGraph.edges.size == 2)
|
|
|
+
|
|
|
+ val m2 = findEdge(subGraph, "m2")
|
|
|
+ assert(m2.source.value.asInstanceOf[FlatNodeData].label == "something")
|
|
|
+ assert(m2.target.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ }
|
|
|
+
|
|
|
+ "Syntactic sugar for edges" should "expand edges" in {
|
|
|
+ val f = getClass.getResourceAsStream("/graphs/sugar_edges.graphml")
|
|
|
+ val graph = GraphMLLoader.createGraph(f)
|
|
|
+ assert(graph.nodes.size == 3)
|
|
|
+ assert(graph.edges.size == 4)
|
|
|
+
|
|
|
+ val eTerminate = findEdge(graph, "e_terminate")
|
|
|
+ val eInterrupt = findEdge(graph, "e_Interrupt")
|
|
|
+ val eInstantiated = findEdge(graph, "e_instantiated")
|
|
|
+
|
|
|
+ assert(eTerminate.source.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eTerminate.target.value.asInstanceOf[FlatNodeData].label == "terminated")
|
|
|
+ assert(eInterrupt.source.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eInterrupt.target.value.asInstanceOf[FlatNodeData].label == "terminated")
|
|
|
+ assert(eInstantiated.source.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eInstantiated.target.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ }
|
|
|
+
|
|
|
+ def assertEdgeUpperBound(graph: Graph[NodeData, LkDiEdge], edge: String, n : Int) = {
|
|
|
+ assert(findEdge(graph, edge).label match {
|
|
|
+ case EdgeData(_,_,bound) => bound == n
|
|
|
+ case _ => false
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ def assertEdgeNoUpperBound(graph: Graph[NodeData, LkDiEdge], edge: String) = assertEdgeUpperBound(graph, edge, Int.MaxValue)
|
|
|
+
|
|
|
+ "Syntactic sugar for edges" should "extract upper bound if any" in {
|
|
|
+ val f = getClass.getResourceAsStream("/graphs/bound.graphml")
|
|
|
+ val graph = GraphMLLoader.createGraph(f)
|
|
|
+ assert(graph.nodes.size == 3)
|
|
|
+ assert(graph.edges.size == 3)
|
|
|
+
|
|
|
+ assertEdgeNoUpperBound(graph, "e_terminate")
|
|
|
+ assertEdgeUpperBound(graph, "e_instantiated", 1)
|
|
|
+ }
|
|
|
+
|
|
|
+ "Syntactic sugar for nodes" should "expand nodes" in {
|
|
|
+ val f = getClass.getResourceAsStream("/graphs/sugar_nodes.graphml")
|
|
|
+ val graph = GraphMLLoader.createGraph(f)
|
|
|
+ assert(graph.nodes.size == 3)
|
|
|
+ assert(graph.edges.size == 2)
|
|
|
+
|
|
|
+ findNodeData(graph, "instantiated")
|
|
|
+ findNodeData(graph, "something")
|
|
|
+ findNodeData(graph, "terminated")
|
|
|
+
|
|
|
+ val terminateEdges = findEdges(graph, "e_Interrupt")
|
|
|
+
|
|
|
+ terminateEdges.foreach(e => {
|
|
|
+ assert(e.target.value.asInstanceOf[FlatNodeData].label == "terminated")
|
|
|
+ })
|
|
|
+ assert(terminateEdges.map(_.source.value.asInstanceOf[FlatNodeData].label).toSet == Set("instantiated", "something"))
|
|
|
+ }
|
|
|
+
|
|
|
+ "Syntactic sugar" should "expand nodes and edges" in {
|
|
|
+ val f = getClass.getResourceAsStream("/graphs/sugar_all.graphml")
|
|
|
+ val graph = GraphMLLoader.createGraph(f)
|
|
|
+ assert(graph.nodes.size == 4)
|
|
|
+ assert(graph.edges.size == 8)
|
|
|
+
|
|
|
+ val a = findNodeData(graph, "aState")
|
|
|
+ val b = findNodeData(graph, "bState")
|
|
|
+ val c = findNodeData(graph, "cState")
|
|
|
+ val d = findNodeData(graph, "dState")
|
|
|
+
|
|
|
+ val e1 = findEdges(graph, "e_someEvent")
|
|
|
+ val e2 = findEdges(graph, "e_someOtherEvent")
|
|
|
+
|
|
|
+ assert(e1.map(_.source.value.asInstanceOf[FlatNodeData].label).toSet == Set("aState", "bState"))
|
|
|
+ assert(e1.map(_.target.value.asInstanceOf[FlatNodeData].label).toSet == Set("cState", "dState"))
|
|
|
+
|
|
|
+ assert(e2.map(_.source.value.asInstanceOf[FlatNodeData].label).toSet == Set("aState", "bState"))
|
|
|
+ assert(e2.map(_.target.value.asInstanceOf[FlatNodeData].label).toSet == Set("cState", "dState"))
|
|
|
+ }
|
|
|
+
|
|
|
+ "Multiple GraphMLs" should "be merge into one graph, regardless of order" in {
|
|
|
+ def graph_conditions(graphList: List[String]) = {
|
|
|
+ val graph = GraphMLLoader.createGraphFromPath(graphList).get
|
|
|
+
|
|
|
+ assert(graph.nodes.size == 5)
|
|
|
+ assert(graph.edges.size == 9)
|
|
|
+
|
|
|
+ findNodeData(graph, "start")
|
|
|
+ findNodeData(graph, "instantiated")
|
|
|
+ findNodeData(graph, "running")
|
|
|
+ findNodeData(graph, "terminated")
|
|
|
+ findNodeData(graph, "freed")
|
|
|
+
|
|
|
+ val eInit = findEdge(graph, "init")
|
|
|
+ val eInstantiated = findEdge(graph, "e_instantiated")
|
|
|
+ val eStart = findEdge(graph, "e_start")
|
|
|
+ val eGo = findEdge(graph, "e_go")
|
|
|
+ val eRestart = findEdge(graph, "e_restart")
|
|
|
+ val eCancel = findEdge(graph, "e_cancel")
|
|
|
+ val eFree = findEdge(graph, "e_free")
|
|
|
+ val eInterrupt = findEdges(graph, "e_Interrupt")
|
|
|
+
|
|
|
+ assert(eInit.source.value.asInstanceOf[FlatNodeData].label == "start")
|
|
|
+ assert(eInit.target.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+
|
|
|
+ assert(eInstantiated.source.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eInstantiated.target.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+
|
|
|
+ assert(eStart.source.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eStart.target.value.asInstanceOf[FlatNodeData].label == "running")
|
|
|
+ assert(eGo.source.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eGo.target.value.asInstanceOf[FlatNodeData].label == "running")
|
|
|
+ assert(eRestart.source.value.asInstanceOf[FlatNodeData].label == "running")
|
|
|
+ assert(eRestart.target.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+ assert(eCancel.source.value.asInstanceOf[FlatNodeData].label == "running")
|
|
|
+ assert(eCancel.target.value.asInstanceOf[FlatNodeData].label == "instantiated")
|
|
|
+
|
|
|
+ assert(eFree.source.value.asInstanceOf[FlatNodeData].label == "terminated")
|
|
|
+ assert(eFree.target.value.asInstanceOf[FlatNodeData].label == "freed")
|
|
|
+
|
|
|
+ assert(eInterrupt.map(_.source.value.asInstanceOf[FlatNodeData].label).toSet == Set("instantiated", "running"))
|
|
|
+ eInterrupt.foreach(_.target.value.asInstanceOf[FlatNodeData].label == "terminated")
|
|
|
+ }
|
|
|
+
|
|
|
+ val graphList = List("/graphs/splitted_graphs/1.graphml",
|
|
|
+ "/graphs/splitted_graphs/2.graphml",
|
|
|
+ "/graphs/splitted_graphs/3.graphml",
|
|
|
+ "/graphs/splitted_graphs/4.graphml")
|
|
|
+
|
|
|
+ graphList.permutations.foreach(permutation => graph_conditions(permutation))
|
|
|
+ }
|
|
|
+
|
|
|
+ "FMIGraphModel" should "have the correct initial state" in {
|
|
|
+ val m = new FMIGraphModel()
|
|
|
+ val mbt = MBT.launch(m)
|
|
|
+ assert(mbt.currentState.toString() == "start")
|
|
|
+ }
|
|
|
+
|
|
|
+ "FMIGraphModel" should "load the correct fmi states" in {
|
|
|
+ val graph = GraphMLLoader.createGraphFromPath(
|
|
|
+ List("/graphs/fmi/fmi.graphml",
|
|
|
+ "/graphs/fmi/free.graphml",
|
|
|
+ "/graphs/fmi/reset.graphml")).get
|
|
|
+ findNodeData(graph, "start")
|
|
|
+ findNodeData(graph, "instantiated")
|
|
|
+ findNodeData(graph, "terminated")
|
|
|
+ findNodeData(graph, "freed")
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ "FMIGraphModel" should "work in MBT" in {
|
|
|
+ val p = getClass.getResource("/fmus/20-sim/threewatertank1.fmu").getPath
|
|
|
+ val f = new File(p)
|
|
|
+ val conf = Config(nruns = 10, loopLimit = 5)
|
|
|
+ MBTRunner.run_mbt(f, conf, classOf[FMIGraphModel])
|
|
|
+ }
|
|
|
+
|
|
|
+}
|