aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorSchuyler Eldridge2018-09-28 12:39:01 -0400
committerSchuyler Eldridge2018-11-07 13:26:09 -0500
commit27c1b366ce58e93434e77e964365474f5e7aa8d7 (patch)
treee54301b8019d17cce4448ce9d09589815a7315d5 /src/test
parente0951fef346c4e3e2d19a57b396012e9800b69b6 (diff)
Add firrtl.options tests
Signed-off-by: Schuyler Eldridge <schuyler.eldridge@ibm.com>
Diffstat (limited to 'src/test')
-rw-r--r--src/test/resources/META-INF/services/firrtl.options.RegisteredLibrary1
-rw-r--r--src/test/resources/META-INF/services/firrtl.options.RegisteredTransform1
-rw-r--r--src/test/scala/firrtlTests/options/OptionParserSpec.scala92
-rw-r--r--src/test/scala/firrtlTests/options/OptionsViewSpec.scala75
-rw-r--r--src/test/scala/firrtlTests/options/RegistrationSpec.scala54
-rw-r--r--src/test/scala/firrtlTests/options/ShellSpec.scala22
6 files changed, 245 insertions, 0 deletions
diff --git a/src/test/resources/META-INF/services/firrtl.options.RegisteredLibrary b/src/test/resources/META-INF/services/firrtl.options.RegisteredLibrary
new file mode 100644
index 00000000..f28a6850
--- /dev/null
+++ b/src/test/resources/META-INF/services/firrtl.options.RegisteredLibrary
@@ -0,0 +1 @@
+firrtlTests.options.BarLibrary \ No newline at end of file
diff --git a/src/test/resources/META-INF/services/firrtl.options.RegisteredTransform b/src/test/resources/META-INF/services/firrtl.options.RegisteredTransform
new file mode 100644
index 00000000..a9fd3bc5
--- /dev/null
+++ b/src/test/resources/META-INF/services/firrtl.options.RegisteredTransform
@@ -0,0 +1 @@
+firrtlTests.options.FooTransform \ No newline at end of file
diff --git a/src/test/scala/firrtlTests/options/OptionParserSpec.scala b/src/test/scala/firrtlTests/options/OptionParserSpec.scala
new file mode 100644
index 00000000..ae4899d4
--- /dev/null
+++ b/src/test/scala/firrtlTests/options/OptionParserSpec.scala
@@ -0,0 +1,92 @@
+// See LICENSE for license details
+
+package firrtlTests.options
+
+import firrtl.{AnnotationSeq, FIRRTLException}
+import firrtl.annotations.{Annotation, NoTargetAnnotation}
+import firrtl.options.{DoNotTerminateOnExit, DuplicateHandling, OptionsException}
+
+import scopt.OptionParser
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import java.security.Permission
+
+class OptionParserSpec extends FlatSpec with Matchers {
+
+ case class IntAnnotation(x: Int) extends NoTargetAnnotation {
+ def extract: Int = x
+ }
+
+ /* An option parser that prepends to a Seq[Int] */
+ class IntParser extends OptionParser[AnnotationSeq]("Int Parser") {
+ opt[Int]("integer").abbr("n").unbounded.action( (x, c) => IntAnnotation(x) +: c )
+ help("help")
+ }
+
+ trait DuplicateShortOption { this: OptionParser[AnnotationSeq] =>
+ opt[Int]("not-an-integer").abbr("n").unbounded.action( (x, c) => IntAnnotation(x) +: c )
+ }
+
+ trait DuplicateLongOption { this: OptionParser[AnnotationSeq] =>
+ opt[Int]("integer").abbr("m").unbounded.action( (x, c) => IntAnnotation(x) +: c )
+ }
+
+ case class ExitException(status: Option[Int]) extends SecurityException("Found a sys.exit")
+
+ /* Security manager that disallows calls to sys.exit */
+ class ExceptOnExit extends SecurityManager {
+ override def checkPermission(perm: Permission): Unit = {}
+ override def checkPermission(perm: Permission, context: Object): Unit = {}
+ override def checkExit(status: Int): Unit = {
+ super.checkExit(status)
+ throw ExitException(Some(status))
+ }
+ }
+
+ /* Tell a parser to terminate in an environment where sys.exit throws an exception */
+ def catchStatus(parser: OptionParser[_], exitState: Either[String, Unit]): Option[Int] = {
+ System.setSecurityManager(new ExceptOnExit())
+ val status = try {
+ parser.terminate(exitState)
+ throw new ExitException(None)
+ } catch {
+ case ExitException(s) => s
+ }
+ System.setSecurityManager(null)
+ status
+ }
+
+ behavior of "default OptionsParser"
+
+ it should "terminate on exit" in {
+ val parser = new IntParser
+
+ info("By default, exit statuses are reported")
+ catchStatus(parser, Left("some message")) should be (Some(1))
+ catchStatus(parser, Right(Unit)) should be (Some(0))
+ }
+
+ behavior of "DoNotTerminateOnExit"
+
+ it should "disable sys.exit for terminate method" in {
+ val parser = new IntParser with DoNotTerminateOnExit
+ catchStatus(parser, Left("some message")) should be (None)
+ catchStatus(parser, Right(Unit)) should be (None)
+ }
+
+ behavior of "DuplicateHandling"
+
+ it should "detect short duplicates" in {
+ val parser = new IntParser with DuplicateHandling with DuplicateShortOption
+ intercept[OptionsException] { parser.parse(Array[String](), Seq[Annotation]()) }
+ .getMessage should startWith ("Duplicate short option")
+ }
+
+ it should "detect long duplicates" in {
+ val parser = new IntParser with DuplicateHandling with DuplicateLongOption
+ intercept[OptionsException] { parser.parse(Array[String](), Seq[Annotation]()) }
+ .getMessage should startWith ("Duplicate long option")
+ }
+
+}
diff --git a/src/test/scala/firrtlTests/options/OptionsViewSpec.scala b/src/test/scala/firrtlTests/options/OptionsViewSpec.scala
new file mode 100644
index 00000000..dec6a99f
--- /dev/null
+++ b/src/test/scala/firrtlTests/options/OptionsViewSpec.scala
@@ -0,0 +1,75 @@
+// See LICENSE for license details
+
+package firrtlTests.options
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import firrtl.options.OptionsView
+import firrtl.AnnotationSeq
+import firrtl.annotations.{Annotation,NoTargetAnnotation}
+
+class OptionsViewSpec extends FlatSpec with Matchers {
+
+ /* Annotations */
+ case class NameAnnotation(name: String) extends NoTargetAnnotation
+ case class ValueAnnotation(value: Int) extends NoTargetAnnotation
+
+ /* The type we want to view the annotations as */
+ case class Foo(name: Option[String] = None, value: Option[Int] = None)
+ case class Bar(name: String = "bar")
+
+ /* An OptionsView that converts an AnnotationSeq to Option[Foo] */
+ implicit object FooView extends OptionsView[Foo] {
+ private def append(foo: Foo, anno: Annotation): Foo = anno match {
+ case NameAnnotation(n) => foo.copy(name = Some(n))
+ case ValueAnnotation(v) => foo.copy(value = Some(v))
+ case _ => foo
+ }
+
+ def view(options: AnnotationSeq): Option[Foo] = {
+ val annoSeq = options.foldLeft(Foo())(append)
+ Some(annoSeq)
+ }
+ }
+
+ /* An OptionsView that converts an AnnotationSeq to Option[Bar] */
+ implicit object BarView extends OptionsView[Bar] {
+ private def append(bar: Bar, anno: Annotation): Bar = anno match {
+ case NameAnnotation(n) => bar.copy(name = n)
+ case _ => bar
+ }
+
+ def view(options: AnnotationSeq): Option[Bar] = {
+ val annoSeq = options.foldLeft(Bar())(append)
+ Some(annoSeq)
+ }
+ }
+
+ behavior of "OptionsView"
+
+ it should "convert annotations to one of two types" in {
+ /* Some default annotations */
+ val annos = Seq(NameAnnotation("foo"), ValueAnnotation(42))
+
+ info("Foo conversion okay")
+ FooView.view(annos) should be (Some(Foo(Some("foo"), Some(42))))
+
+ info("Bar conversion okay")
+ BarView.view(annos) should be (Some(Bar("foo")))
+ }
+
+ behavior of "Viewer"
+
+ it should "implicitly view annotations as the specified type" in {
+ import firrtl.options.Viewer._
+
+ /* Some empty annotations */
+ val annos = Seq[Annotation]()
+
+ info("Foo view okay")
+ view[Foo](annos) should be (Some(Foo(None, None)))
+
+ info("Bar view okay")
+ view[Bar](annos) should be (Some(Bar()))
+ }
+}
diff --git a/src/test/scala/firrtlTests/options/RegistrationSpec.scala b/src/test/scala/firrtlTests/options/RegistrationSpec.scala
new file mode 100644
index 00000000..c060341d
--- /dev/null
+++ b/src/test/scala/firrtlTests/options/RegistrationSpec.scala
@@ -0,0 +1,54 @@
+// See LICENSE for license details.
+
+package firrtlTests.options
+
+import org.scalatest.{FlatSpec, Matchers}
+import scopt.OptionParser
+import java.util.ServiceLoader
+
+import firrtl.options.{RegisteredTransform, RegisteredLibrary}
+import firrtl.passes.Pass
+import firrtl.ir.Circuit
+import firrtl.annotations.NoTargetAnnotation
+import firrtl.AnnotationSeq
+
+case object HelloAnnotation extends NoTargetAnnotation
+
+class FooTransform extends Pass with RegisteredTransform {
+ def run(c: Circuit): Circuit = c
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit =
+ p.opt[Unit]("hello")
+ .action( (_, c) => HelloAnnotation +: c )
+}
+
+class BarLibrary extends RegisteredLibrary {
+ def name: String = "Bar"
+ def addOptions(p: OptionParser[AnnotationSeq]): Unit =
+ p.opt[Unit]("world")
+ .action( (_, c) => HelloAnnotation +: c )
+}
+
+class RegistrationSpec extends FlatSpec with Matchers {
+
+ behavior of "RegisteredTransform"
+
+ it should "FooTransform should be discovered by Java.util.ServiceLoader" in {
+ val iter = ServiceLoader.load(classOf[RegisteredTransform]).iterator()
+ val transforms = scala.collection.mutable.ArrayBuffer[RegisteredTransform]()
+ while (iter.hasNext) {
+ transforms += iter.next()
+ }
+ transforms.map(_.getClass.getName) should contain ("firrtlTests.options.FooTransform")
+ }
+
+ behavior of "RegisteredLibrary"
+
+ it should "BarLibrary be discovered by Java.util.ServiceLoader" in {
+ val iter = ServiceLoader.load(classOf[RegisteredLibrary]).iterator()
+ val transforms = scala.collection.mutable.ArrayBuffer[RegisteredLibrary]()
+ while (iter.hasNext) {
+ transforms += iter.next()
+ }
+ transforms.map(_.getClass.getName) should contain ("firrtlTests.options.BarLibrary")
+ }
+}
diff --git a/src/test/scala/firrtlTests/options/ShellSpec.scala b/src/test/scala/firrtlTests/options/ShellSpec.scala
new file mode 100644
index 00000000..d87a9a30
--- /dev/null
+++ b/src/test/scala/firrtlTests/options/ShellSpec.scala
@@ -0,0 +1,22 @@
+// See LICENSE for license details.
+
+package firrtlTests.options
+
+import org.scalatest._
+
+import firrtl.options.Shell
+
+class ShellSpec extends FlatSpec with Matchers {
+
+ behavior of "Shell"
+
+ it should "detect all registered libraries and transforms" in {
+ val shell = new Shell("foo")
+
+ info("Found FooTransform")
+ shell.registeredTransforms.map(_.getClass.getName) should contain ("firrtlTests.options.FooTransform")
+
+ info("Found BarLibrary")
+ shell.registeredLibraries.map(_.getClass.getName) should contain ("firrtlTests.options.BarLibrary")
+ }
+}