summaryrefslogtreecommitdiff
path: root/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala
blob: 6a531071bfce341658920e6d2da3bd1b797cd21c (plain) (blame)
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
import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe.definitions._
import scala.reflect.runtime.universe.Flag._
import scala.reflect.runtime.currentMirror
import scala.reflect.api.{Liftable, Universe}
import scala.reflect.macros.TypecheckException
import scala.tools.reflect.{ToolBox, ToolBoxError}

import org.scalacheck._
import Prop._
import Gen._
import Arbitrary._

class QuasiquoteProperties(name: String) extends Properties(name) with ArbitraryTreesAndNames with Helpers

trait Helpers {
  /** Runs a code block and returns proof confirmation
   *  if no exception has been thrown while executing code
   *  block. This is useful for simple one-off tests.
   */
  def test[T](block: => T)=
    Prop { (params) =>
      block
      Result(Prop.Proof)
    }

  implicit class TestSimilarTree(tree1: Tree) {
    def (tree2: Tree) = tree1.equalsStructure(tree2)
  }

  implicit class TestSimilarListTree(lst: List[Tree]) {
    def (other: List[Tree]) = (lst.length == other.length) && lst.zip(other).forall { case (t1, t2) => t1  t2 }
  }

  implicit class TestSimilarListListTree(lst: List[List[Tree]]) {
    def (other: List[List[Tree]]) = (lst.length == other.length) && lst.zip(other).forall { case (l1, l2) => l1  l2 }
  }

  implicit class TestSimilarName(name: Name) {
    def (other: Name) = name == other
  }

  implicit class TestSimilarMods(mods: Modifiers) {
    def (other: Modifiers) = (mods.flags == other.flags) && (mods.privateWithin  other.privateWithin) && (mods.annotations  other.annotations)
  }

  def assertThrows[T <: AnyRef](f: => Any)(implicit manifest: Manifest[T]): Unit = {
    val clazz = manifest.erasure.asInstanceOf[Class[T]]
    val thrown =
      try {
        f
        false
      } catch {
        case u: Throwable =>
          if (!clazz.isAssignableFrom(u.getClass))
            assert(false, s"wrong exception: $u")
          true
      }
    if(!thrown)
      assert(false, "exception wasn't thrown")
  }

  def assertEqAst(tree: Tree, code: String) = assert(eqAst(tree, code))
  def eqAst(tree: Tree, code: String) = tree  parse(code)

  val toolbox = currentMirror.mkToolBox()
  val parse = toolbox.parse(_)
  val compile = toolbox.compile(_)
  val eval = toolbox.eval(_)

  def fails(msg: String, block: String) = {
    def result(ok: Boolean, description: String = "") = {
      val status = if (ok) Prop.Proof else Prop.False
      val labels = if (description != "") Set(description) else Set.empty[String]
      Prop { new Prop.Result(status, Nil, Set.empty, labels) }
    }
    try {
      compile(parse(s"""
        object Wrapper extends Helpers {
          import scala.reflect.runtime.universe._
          $block
        }
      """))
      result(false, "given code doesn't fail to typecheck")
    } catch {
      case ToolBoxError(emsg, _) =>
        if (!emsg.contains(msg))
          result(false, s"error message '${emsg}' is not the same as expected '$msg'")
        else
          result(true)
    }
  }

  def annot(name: String): Tree = annot(TypeName(name), Nil)
  def annot(name: TypeName): Tree = annot(name, Nil)
  def annot(name: String, args: List[Tree]): Tree = annot(TypeName(name), args)
  def annot(name: TypeName, args: List[Tree]): Tree = q"new $name(..$args)"
}