// SPDX-License-Identifier: Apache-2.0 package firrtlTests.options.phases import java.io.{File, PrintWriter} import firrtl.AnnotationSeq import firrtl.annotations.{AnnotationFileNotFoundException, JsonProtocol, NoTargetAnnotation} import firrtl.options.phases.GetIncludes import firrtl.options.{InputAnnotationFileAnnotation, Phase} import firrtl.util.BackendCompilationUtilities import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers case object A extends NoTargetAnnotation case object B extends NoTargetAnnotation case object C extends NoTargetAnnotation case object D extends NoTargetAnnotation case object E extends NoTargetAnnotation class GetIncludesSpec extends AnyFlatSpec with Matchers with firrtl.testutils.Utils { val dir = new File("test_run_dir/GetIncludesSpec") dir.mkdirs() def ref(filename: String): InputAnnotationFileAnnotation = InputAnnotationFileAnnotation(s"$dir/$filename.anno.json") def checkAnnos(a: AnnotationSeq, b: AnnotationSeq): Unit = { info("read the expected number of annotations") a.size should be(b.size) info("annotations match exact order") a.zip(b).foreach { case (ax, bx) => ax should be(bx) } } val files = Seq( new File(dir + "/a.anno.json") -> Seq(A, ref("b")), new File(dir + "/b.anno.json") -> Seq(B, ref("c"), ref("a")), new File(dir + "/c.anno.json") -> Seq(C, ref("d"), ref("e")), new File(dir + "/d.anno.json") -> Seq(D), new File(dir + "/e.anno.json") -> Seq(E) ) files.foreach { case (file, annotations) => val pw = new PrintWriter(file) pw.write(JsonProtocol.serialize(annotations)) pw.close() } class Fixture { val phase: Phase = new GetIncludes } behavior.of(classOf[GetIncludes].toString) it should "throw an exception if the annotation file doesn't exit" in new Fixture { intercept[AnnotationFileNotFoundException] { phase.transform(Seq(ref("f"))) }.getMessage should startWith( "Annotation file" ) } it should "read annotations from a file" in new Fixture { val e = ref("e") val in = Seq(e) val expect = Seq(E) val out = phase.transform(in) checkAnnos(out, expect) } it should "read annotations from multiple files, but not reading duplicates" in new Fixture { val Seq(d, e) = Seq("d", "e").map(ref) val in = Seq(d, e, e, d) val expect = Seq(D, E) val (stdout, _, out) = grabStdOutErr { phase.transform(in) } checkAnnos(out, expect) Seq("d", "e").foreach { x => info(s"a warning about '$x.anno.json' was printed") stdout should include(s"Warning: Annotation file ($dir/$x.anno.json) already included!") } } it should "handle recursive references gracefully, but show a warning" in new Fixture { val Seq(a, b, c, d, e) = Seq("a", "b", "c", "d", "e").map(ref) val in = Seq(a) val expect = Seq(A, B, C, D, E) val (stdout, _, out) = grabStdOutErr { phase.transform(in) } checkAnnos(out, expect) info("a warning about 'a.anno.json' was printed") stdout should include(s"Warning: Annotation file ($dir/a.anno.json)") } }