diff options
Diffstat (limited to 'src/test/scala/firrtlTests/options/OptionParserSpec.scala')
| -rw-r--r-- | src/test/scala/firrtlTests/options/OptionParserSpec.scala | 92 |
1 files changed, 92 insertions, 0 deletions
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") + } + +} |
