Example: Reuse EUnit tests with model and data bindings

operation hasLoop(n) : Boolean {
  for (n in Node.all) {
    n.~status = 0; // not visited yet
  }
  return hasLoopAux(n);
}

operation hasLoopAux(n) : Boolean {
  if (n.~status == 2) {
    // We already visited this node and did not find any loops
    return false;
  }
  else if (n.~status == 1) {
    // We have returned to a node through its outgoing edges: we found a loop
    return true;
  }

  n.~status = 1;
  for (e in n.outgoing) {
    if (hasLoopAux(e.target)) {
      return true;
    } 
  }
  n.~status = 2;
  return false;
}
import "loops.eol";

@data numNodes
operation nodes() {
  return 1.to(3);
}

@data cycleLength
operation cycLength() {
  return 0.to(numNodes - 1);
}

@model
operation populateGraph() {
 // Here we populate the empty graph model with a sequence of nodes.
 var g = new Graph;
 for (i in 1.to(numNodes)) {
   var n = new Node;
   n.name = "n" + i;
   if (i > 1) {
     var e = new Edge;
     e.source = g.nodes.get(n.size - 1);
     e.target = n;
   }
   g.nodes.add(n);
 }
}

@test
operation originalHasNoLoops() {
  assertFalse(hasLoop(Node.all.first));
}

@test
operation loopIsDetected() {
  var e = new Edge;
  e.source = Node.all.select(n|n.name == "n" + (1 + cycleLength)).first;
  e.target = Node.all.first;
  assertTrue(hasLoop(Node.all.first));
}
import "loops.eol";

$with Map {"" = "LoopingA"}
$with Map {"" = "LoopingB"}
@test
operation looping() {
  assertTrue(hasLoop(Node.all.first));
}

$with Map {"" = "NonLooping"}
@test
operation nonLooping() {
  assertFalse(hasLoop(Node.all.first));
}
<project>
  <target name="run-tests">
    <epsilon.emf.loadModel name="LoopingA"
      modelfile="graph-with-loops-1.model"
      metamodelfile="graph.ecore"
      read="true" store="false" />
    <epsilon.emf.loadModel name="LoopingB"
      modelfile="graph-with-loops-2.model"
      metamodelfile="graph.ecore"
      read="true" store="false" />
    <epsilon.emf.loadModel name="NonLooping"
      modelfile="graph-without-loops.model"
      metamodelfile="graph.ecore"
      read="true" store="false" />
    <epsilon.emf.loadModel name="Empty"
      metamodelfile="graph.ecore"
      read="false" store="false" />

    <epsilon.eunit src="bind-model.eunit" package="loops">
      <model ref="LoopingA" />
      <model ref="LoopingB" />
      <model ref="NonLooping" />
    </epsilon.eunit>
    <epsilon.eunit src="bind-data.eunit" package="loops">
      <model ref="Empty" />
    </epsilon.eunit>
  </target>
</project>

Check out the code from the SVN:

  • go to the SVN repository
  • navigate to trunk/examples
  • check out the org.eclipse.epsilon.eunit.examples.bindings project

Once you have checked out/imported the code, to run the example you need to go through the following steps:

  1. register any .ecore metamodels in the org.eclipse.epsilon.eunit.examples.bindings project
  2. right click the .launch file in the org.eclipse.epsilon.eunit.examples.bindings project
  3. select Run as... and click the first item in the menu that pops up

What's this?

In this example we show how the same EUnit test can be reused for several models, and how EUnit supports several levels of parametric tests.

What are .emf files?

.emf files are Ecore metamodels expressed using the Emfatic textual syntax.

More examples...

Epsilon Object Language
Epsilon Transformation Language
Epsilon Generation Language
Epsilon Validation Language
Epsilon Merging Language
Epsilon Flock
Combining the Epsilon Languages
EuGENia
EUnit

Even more examples...

More examples are available in the examples folder of the SVN repository.