All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sntb.TestProvider.scala Maven / Gradle / Ivy

package sntb

import language.experimental.macros
import language.implicitConversions
import reflect.ClassTag
import reflect.macros.blackbox.Context
import reflect.macros.{ParseException, TypecheckException}
import util.{Failure, Success, Try}

trait TestProvider {

  private var runList: List[Block] = Nil

  private val className = this.getClass.getSimpleName()

  def assertCompiles(str: String): Unit = macro TestProvider.assertCompilesImpl

  def assertTypeError(str: String): Unit = macro TestProvider.assertTypeErrorImpl

  object it {
    def should(name: String): BlockBuilder = BlockBuilder(name)
  }

  def intercept[T <: RuntimeException](arg: => Any)(implicit ct: ClassTag[T]): T =
    try {
      arg
      throw new RuntimeException("Value was not an error")
    } catch {
      case x: T => x
      case _: Throwable => throw new RuntimeException(s"Error was not an instance of the expected type")
    }

  def run: Unit = {
    println(s"${Console.GREEN}$className: ${Console.RESET}")
    runList.reverse foreach {
      case Block(name, exec) =>
        print(s"- $name...")
        exec()
        println("done")
    }
  }

  case class BlockBuilder(name: String) {
    def in(exec: => Unit): Unit = runList = new Block(name, () => exec) :: runList
  }

  private case class Block(name: String, exec: Function0[Unit])

  final class TSEQ[T](lhs: T) {
    def ===(rhs: T): Boolean = lhs == rhs
  }

  implicit def tseqBuilder[T](lhs: T): TSEQ[T] = new TSEQ(lhs)

}

object TestProvider {

  def assertCompilesImpl(c: Context)(str: c.Tree): c.Tree = {
    import c.universe._
    str match {
      case q"${ y: String }" =>
        util.Try {
          val parsed = c.parse(y)
          val typechecked = c.typecheck(parsed)
          true
        } match {
          case util.Success(_) => q"assert(true)"
          case util.Failure(TypecheckException(_, msg)) => q"""assert(false, "typecheck failure: " + $msg)"""
          case util.Failure(ParseException(_, msg)) => q"""assert(false, "parse failure: " + $msg)"""
          case util.Failure(err) => q"assert(false, error: ${err.toString})"
        }
      case _ => c.abort(c.enclosingPosition, "Supplied Literal must be a string")
    }
  }

  def assertTypeErrorImpl(c: Context)(str: c.Tree): c.Tree = {
    import c.universe._
    str match {
      case q"${ y: String }" =>
        util.Try {
          val parsed = c.parse(y)
          val typechecked = c.typecheck(parsed)
        } match {
          case util.Failure(TypecheckException(_, _)) => q"assert(true)"
          case util.Failure(ParseException(_, msg)) => q"""assert(false, "parse failure: " + $msg)"""
          case util.Success(_) => q"""assert(false, "code compiles")"""
          case util.Failure(err) => q"assert(false, error: ${err.toString})"
        }
      case _ => c.abort(c.enclosingPosition, "Supplied Literal must be a string")
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy