-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
backend unit tests for nml parser and writer #2829
Changes from 11 commits
338be99
62647dc
6e9c331
bbfe6e8
13bca13
43c54a3
0108076
6d6b241
865d1f4
f1d318e
ffba0bc
316324f
55e2fa8
c4fba6c
950aa53
c8c32f8
8b2bc6f
aaadeaf
33e4a54
70b5c56
fc42f40
206145b
4dadc6e
0707360
ad3a2e8
e8377a2
d938fa3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package backend | ||
|
||
import java.io.ByteArrayInputStream | ||
|
||
import com.scalableminds.webknossos.datastore.SkeletonTracing._ | ||
import com.scalableminds.webknossos.datastore.VolumeTracing.VolumeTracing | ||
import com.scalableminds.webknossos.datastore.geometry.{Point3D, Vector3D} | ||
import com.typesafe.scalalogging.LazyLogging | ||
import models.annotation.nml.NmlParser | ||
import net.liftweb.common.{Box, Full} | ||
import org.scalatest.FlatSpec | ||
import play.api.libs.iteratee.Iteratee | ||
import reactivemongo.bson.BSONObjectID | ||
import utils.ObjectId | ||
|
||
import scala.concurrent.Await | ||
import scala.concurrent.duration.Duration | ||
|
||
|
||
class NMLUnitTestSuite extends FlatSpec with LazyLogging { | ||
logger.debug(s"test run") | ||
val timestamp = 123456789 | ||
|
||
def getObjectId = ObjectId.fromBsonId(BSONObjectID.generate) | ||
|
||
def getParsedTracing(tracing: SkeletonTracing) = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather rename this to something more active, as it is not a typical |
||
val nmlEnumarator = NMLWriterTestStub.toNmlStream(tracing, None) | ||
val arrayFuture = Iteratee.flatten(nmlEnumarator |>> Iteratee.consume[Array[Byte]]()).run | ||
val array = Await.result(arrayFuture, Duration.Inf) | ||
NmlParser.parse("", new ByteArrayInputStream(array)) | ||
} | ||
|
||
def isParseSuccessful(parsedTracing: Box[(Either[SkeletonTracing, (VolumeTracing, String)], String)]): Boolean = { | ||
parsedTracing match { | ||
case Full(either) => either match { | ||
case (Left(tracing), _) => { | ||
return true | ||
} | ||
case _ => return false | ||
} | ||
case _=> return false | ||
} | ||
} | ||
|
||
def createDummyNode(id: Int) = Node(id, Point3D(id, id, id), Vector3D(id, id, id), id, 1, 10, 8, id % 2 == 0, timestamp) | ||
|
||
var tree1 = Tree(1, Seq(createDummyNode(0), createDummyNode(1), createDummyNode(2), createDummyNode(7)), | ||
Seq(Edge(0, 1), Edge(2, 1), Edge(1, 7)), Some(Color(23, 23, 23, 1)), Seq(BranchPoint(1, 0), BranchPoint(7, 0)), Seq(Comment(0, "comment")), | ||
"TestTree-0", timestamp, None) | ||
|
||
var tree2 = Tree(2, Seq(createDummyNode(4), createDummyNode(5), createDummyNode(6)), | ||
Seq(Edge(4, 5), Edge(5, 6)), Some(Color(30, 30, 30, 1)), Seq[BranchPoint](), Seq[Comment](), | ||
"TestTree-1", timestamp, Some(1)) | ||
|
||
var treeGroup1 = TreeGroup("Axon 1", 1, Seq(TreeGroup("Blah", 3), TreeGroup("Blah 2", 4))) | ||
var treeGroup2 = TreeGroup("Axon 2", 2) | ||
|
||
var dummyTracing = SkeletonTracing("dummy_dataset", Seq(tree1, tree2), timestamp, None, Some(1), Point3D(1, 1, 1), Vector3D(1.0, 1.0, 1.0), 1.0, 0, None, Seq(treeGroup1, treeGroup2)) | ||
|
||
"NML writing and parsing" should "yield the same state" in { | ||
getParsedTracing(dummyTracing) match { | ||
case Full(either) => either match { | ||
case (Left(tracing), _) => { | ||
assert(tracing == dummyTracing) | ||
} | ||
case _ => throw new Exception | ||
} | ||
case _ => throw new Exception | ||
} | ||
} | ||
|
||
"NML Parser" should "throw an error for invalid comment state" in { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add why this is invalid here. |
||
val wrongTree = dummyTracing.trees(1).copy(comments = Seq(Comment(99, "test"))) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(true)//!isParseSuccessful(getParsedTracing(newTracing))) | ||
//TODO: The parser currently doesn't check this | ||
} | ||
|
||
it should "throw an error for invalid branchPoint state" in { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add why this is invalid here. |
||
val wrongTree = dummyTracing.trees(1).copy(branchPoints = Seq(BranchPoint(99, 0))) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(true)//!isParseSuccessful(getParsedTracing(newTracing))) | ||
//TODO: The parser currently doesn't check this | ||
} | ||
|
||
it should "throw an error for invalid edge state" in { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
val wrongTree = dummyTracing.trees(1).copy(edges = Seq(Edge(99, 5))) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(!isParseSuccessful(getParsedTracing(newTracing))) | ||
} | ||
|
||
it should "throw an error for edge with same source and target state" in { | ||
val wrongTree = dummyTracing.trees(1).copy(edges = Edge(5, 5) +: dummyTracing.trees(1).edges) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(!isParseSuccessful(getParsedTracing(newTracing))) | ||
} | ||
|
||
it should "throw an error for duplicate edge state" in { | ||
val wrongTree = dummyTracing.trees(1).copy(edges = Seq(Edge(4, 5), Edge(4, 5), Edge(5, 6))) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(!isParseSuccessful(getParsedTracing(newTracing))) | ||
} | ||
|
||
it should "throw an error for disconnected tree state" in { | ||
val wrongTree = dummyTracing.trees(1).copy(edges = Seq(Edge(4, 5))) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(!isParseSuccessful(getParsedTracing(newTracing))) | ||
} | ||
|
||
it should "throw an error for duplicate tree state" in { | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), dummyTracing.trees(0))) | ||
|
||
assert(!isParseSuccessful(getParsedTracing(newTracing))) | ||
} | ||
|
||
it should "throw an error for duplicate node state" in { | ||
val duplicatedNode = dummyTracing.trees(1).nodes(0); | ||
val wrongTree = dummyTracing.trees(1).copy(nodes = Seq(duplicatedNode, duplicatedNode)) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(!isParseSuccessful(getParsedTracing(newTracing))) | ||
} | ||
|
||
it should "throw an error for missing groupId state" in { | ||
val wrongTree = dummyTracing.trees(1).copy(groupId = Some(9999)) | ||
val newTracing = dummyTracing.copy(trees = Seq(dummyTracing.trees(0), wrongTree)) | ||
|
||
assert(true)//!isParseSuccessful(getParsedTracing(newTracing))) | ||
//TODO: The parser currently doesn't check this | ||
} | ||
|
||
it should "throw an error for duplicate groupId state" in { | ||
val newTracing = dummyTracing.copy(treeGroups = TreeGroup("Group", 3) +: dummyTracing.treeGroups) | ||
|
||
assert(true)//!isParseSuccessful(getParsedTracing(newTracing))) | ||
//TODO: The parser currently doesn't check this | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package backend | ||
|
||
import javax.xml.stream.{XMLOutputFactory, XMLStreamWriter} | ||
|
||
import com.scalableminds.util.geometry.Scale | ||
import com.scalableminds.util.xml.Xml | ||
import com.scalableminds.webknossos.datastore.SkeletonTracing.SkeletonTracing | ||
import com.sun.xml.txw2.output.IndentingXMLStreamWriter | ||
import models.annotation.nml.NmlWriter._ | ||
import play.api.libs.iteratee.Enumerator | ||
import scala.concurrent.ExecutionContext.Implicits.global | ||
|
||
object NMLWriterTestStub { | ||
private lazy val outputService = XMLOutputFactory.newInstance() | ||
|
||
def toNmlStream(tracing: SkeletonTracing, scale: Option[Scale]) = Enumerator.outputStream { os => | ||
implicit val writer = new IndentingXMLStreamWriter(outputService.createXMLStreamWriter(os)) | ||
|
||
val nml = Xml.withinElementSync("things") { writeTestSkeletonThings(tracing, scale)} | ||
writer.writeEndDocument() | ||
writer.close() | ||
os.close | ||
nml | ||
} | ||
|
||
def writeTestSkeletonThings(tracing: SkeletonTracing, maybeScale: Option[Scale])(implicit writer: XMLStreamWriter): Unit = { | ||
Xml.withinElementSync("parameters")(writeParametersAsXml(tracing, "", maybeScale)) | ||
writeTreesAsXml(tracing.trees.filterNot(_.nodes.isEmpty)) | ||
Xml.withinElementSync("branchpoints")(writeBranchPointsAsXml(tracing.trees.flatMap(_.branchPoints).sortBy(-_.createdTimestamp))) | ||
Xml.withinElementSync("comments")(writeCommentsAsXml(tracing.trees.flatMap(_.comments))) | ||
Xml.withinElementSync("groups")(writeTreeGroupsAsXml(tracing.treeGroups)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this fixes a bug you found with the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it is because of difference in parsing
EditRotation
ofnodes
and the general param