aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/firrtlTests/options/phases/WriteOutputAnnotationsSpec.scala
blob: 176362cc95ad5aaf815618c603fe5c70acaf0b10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// See LICENSE for license details.

package firrtlTests.options.phases

import org.scalatest.{FlatSpec, Matchers}

import java.io.File

import firrtl.AnnotationSeq
import firrtl.annotations.{DeletedAnnotation, NoTargetAnnotation}
import firrtl.options.{InputAnnotationFileAnnotation, OutputAnnotationFileAnnotation, Phase, WriteDeletedAnnotation}
import firrtl.options.phases.{GetIncludes, WriteOutputAnnotations}

class WriteOutputAnnotationsSpec extends FlatSpec with Matchers with firrtl.testutils.Utils {

  val dir = "test_run_dir/WriteOutputAnnotationSpec"

  /** Check if the annotations contained by a [[File]] and the same, and in the same order, as a reference
    * [[AnnotationSeq]]. This uses [[GetIncludes]] as that already knows how to read annotation files.
    * @param f a file to read
    * @param a the expected annotations
    */
  private def fileContainsAnnotations(f: File, a: AnnotationSeq): Unit = {
    info(s"output file '$f' exists")
    f should (exist)

    info(s"reading '$f' works")
    val read = (new GetIncludes)
      .transform(Seq(InputAnnotationFileAnnotation(f.toString)))
      .filterNot{
        case a @ DeletedAnnotation(_, _: InputAnnotationFileAnnotation) => true
        case _                                                          => false }

    info(s"annotations in file are expected size")
    read.size should be (a.size)

    read
      .zip(a)
      .foreach{ case (read, expected) =>
        info(s"$read matches")
        read should be (expected) }

    f.delete()
  }

  class Fixture { val phase: Phase = new WriteOutputAnnotations }

  behavior of classOf[WriteOutputAnnotations].toString

  it should "write annotations to a file (excluding DeletedAnnotations)" in new Fixture {
    val file = new File(dir + "/should-write-annotations-to-a-file.anno.json")
    val annotations = Seq( OutputAnnotationFileAnnotation(file.toString),
                           WriteOutputAnnotationsSpec.FooAnnotation,
                           WriteOutputAnnotationsSpec.BarAnnotation(0),
                           WriteOutputAnnotationsSpec.BarAnnotation(1),
                           DeletedAnnotation("foo", WriteOutputAnnotationsSpec.FooAnnotation) )
    val expected = annotations.filter {
      case a: DeletedAnnotation => false
      case a => true
    }
    val out = phase.transform(annotations)

    info("annotations are unmodified")
    out.toSeq should be (annotations)

    fileContainsAnnotations(file, expected)
  }

  it should "include DeletedAnnotations if a WriteDeletedAnnotation is present" in new Fixture {
    val file = new File(dir + "should-include-deleted.anno.json")
    val annotations = Seq( OutputAnnotationFileAnnotation(file.toString),
                           WriteOutputAnnotationsSpec.FooAnnotation,
                           WriteOutputAnnotationsSpec.BarAnnotation(0),
                           WriteOutputAnnotationsSpec.BarAnnotation(1),
                           DeletedAnnotation("foo", WriteOutputAnnotationsSpec.FooAnnotation),
                           WriteDeletedAnnotation )
    val out = phase.transform(annotations)

    info("annotations are unmodified")
    out.toSeq should be (annotations)

    fileContainsAnnotations(file, annotations)
  }

  it should "do nothing if no output annotation file is specified" in new Fixture {
    val annotations = Seq( WriteOutputAnnotationsSpec.FooAnnotation,
                           WriteOutputAnnotationsSpec.BarAnnotation(0),
                           WriteOutputAnnotationsSpec.BarAnnotation(1) )

    val out = catchWrites { phase.transform(annotations) } match {
      case Right(a) =>
        info("no file writes occurred")
        a
      case Left(a) =>
        fail(s"No file writes expected, but a write to '$a' ocurred!")
    }

    info("annotations are unmodified")
    out.toSeq should be (annotations)
  }

}

private object WriteOutputAnnotationsSpec {
  case object FooAnnotation extends NoTargetAnnotation
  case class BarAnnotation(x: Int) extends NoTargetAnnotation
}