Skip to content

Commit

Permalink
airspec: Support AirSpec.design, localDesign (#631)
Browse files Browse the repository at this point in the history
  • Loading branch information
xerial committed Aug 21, 2019
1 parent 779f80d commit dfd7a86
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 19 deletions.
Expand Up @@ -155,8 +155,12 @@ object ReflectSurfaceFactory extends LogSupport {
.filter(m => isOwnedByTargetClass(m, t))
}

private def nonObject(x: ru.Symbol): Boolean = {
!x.isImplementationArtifact && !x.isSynthetic && !x.isAbstract && x.fullName != "scala.Any" && x.fullName != "java.lang.Object"
}

private def isOwnedByTargetClass(m: MethodSymbol, t: ru.Type): Boolean = {
m.owner == t.typeSymbol
m.owner == t.typeSymbol || t.baseClasses.filter(nonObject).exists(_ == m.owner)
}

def createMethodSurfaceOf(targetType: ru.Type): Seq[MethodSurface] = {
Expand Down
Expand Up @@ -80,8 +80,12 @@ private[surface] object SurfaceMacros {
allMethodsOf(t).filter(m => isOwnedByTargetClass(m, t))
}

private def nonObject(x: c.Symbol): Boolean = {
!x.isImplementationArtifact && !x.isSynthetic && !x.isAbstract && x.fullName != "scala.Any" && x.fullName != "java.lang.Object"
}

private def isOwnedByTargetClass(m: MethodSymbol, t: c.Type): Boolean = {
m.owner == t.typeSymbol
m.owner == t.typeSymbol || t.baseClasses.filter(nonObject).exists(_ == m.owner)
}

private def createMethodCaller(t: c.Type, m: MethodSymbol, methodArgs: Seq[MethodArg]): c.Tree = {
Expand Down
Expand Up @@ -42,22 +42,22 @@ import HigherKindTypeTest._
class HigherKindTypeTest extends AirSpec {
scalaJsSupport

val design =
val d =
newSilentDesign
.bind[HolderInterpreted].toInstance(interpreted)
.bind[Holder[Task]].toInstance(interpreted2)
.bind[Holder[MyFuture]].toInstance(interpreted3)

def `support higher kind types`: Unit = {
design.build[HolderInterpreted] { repo =>
d.build[HolderInterpreted] { repo =>
repo.hello shouldBe "new interpretation"
}

design.build[Holder[Task]] { repo =>
d.build[Holder[Task]] { repo =>
repo.hello shouldBe "another interpretation"
}

design.build[Holder[MyFuture]] { repo =>
d.build[Holder[MyFuture]] { repo =>
repo.hello shouldBe "third interpretation"
}
}
Expand Down
6 changes: 3 additions & 3 deletions airframe/src/test/scala/wvlet/airframe/SingletonTest.scala
Expand Up @@ -69,12 +69,12 @@ object SingletonTest {
class SingletonTest extends AirSpec {
scalaJsSupport

val design =
val d =
newDesign
.bind[TraitCounter].toInstance(new AtomicInteger(0))

def `bind singleton with bind[X]` : Unit = {
val session = design.newSession
val session = d.newSession

val a = session.build[A]
val b = session.build[B]
Expand All @@ -84,7 +84,7 @@ class SingletonTest extends AirSpec {
}

def `bind singleton with bind[X] as a service`: Unit = {
val session = design.newSession
val session = d.newSession

val u1 = session.build[U1]
val u2 = session.build[U2]
Expand Down
Expand Up @@ -43,7 +43,7 @@ trait MyServer extends LogSupport {
trait CustomSpec extends AirSpec with LogSupport {
protected val serverLaunchCounter = new AtomicInteger(0)

override def configure(design: Design): Design = {
override protected def configure(design: Design): Design = {
design
.bind[MyServer].toSingleton
.bind[MyServerConfig].toInstance(MyServerConfig("A"))
Expand Down
20 changes: 18 additions & 2 deletions airspec/src/main/scala/wvlet/airspec/AirSpec.scala
Expand Up @@ -68,16 +68,32 @@ private[airspec] trait AirSpecSpi {
/**
* Configure a global design for this spec.
*
* @deprecated(message="Use design:Design instead", since="19.8.9")
*/
protected def configure(design: Design): Design = design
protected def configure(d: Design): Design = d + design

/**
* Provide a global design for this spec.
*/
protected def design: Design = Design.empty

/**
* Configure a test-case local design in the spec.
*
* Note that if you override a global design in this method,
* test cases will create test-case local instances (singletons)
*
* @deprecated(message="Use localDesign: Design instead", since="19.8.9")
*/
protected def configureLocal(design: Design): Design = design + localDesign

/**
* Provide a test-case local design in the spec.
*
* Note that if you override a global design in this method,
* test cases will create test-case local instances (singletons)
*/
protected def configureLocal(design: Design): Design = design
protected def localDesign: Design = Design.empty

protected def beforeAll: Unit = {}
protected def before: Unit = {}
Expand Down
10 changes: 5 additions & 5 deletions airspec/src/main/scala/wvlet/airspec/spi/PropertyCheck.scala
Expand Up @@ -46,7 +46,7 @@ trait PropertyCheck extends Asserts { this: AirSpecSpi =>
Prop(x)
}

def forAll[A1, U](checker: A1 => U)(
protected def forAll[A1, U](checker: A1 => U)(
implicit
a1: Arbitrary[A1],
s1: Shrink[A1],
Expand All @@ -56,12 +56,12 @@ trait PropertyCheck extends Asserts { this: AirSpecSpi =>
checkProperty(prop)
}

def forAll[A1, U](gen: Gen[A1])(checker: A1 => U)(implicit s1: Shrink[A1], pp1: A1 => Pretty): Unit = {
protected def forAll[A1, U](gen: Gen[A1])(checker: A1 => U)(implicit s1: Shrink[A1], pp1: A1 => Pretty): Unit = {
val prop = Prop.forAll(gen)(checker.andThen(OK))(booleanProp, s1, pp1)
checkProperty(prop)
}

def forAll[A1, A2, U](checker: (A1, A2) => U)(
protected def forAll[A1, A2, U](checker: (A1, A2) => U)(
implicit
a1: Arbitrary[A1],
s1: Shrink[A1],
Expand All @@ -77,7 +77,7 @@ trait PropertyCheck extends Asserts { this: AirSpecSpi =>
checkProperty(prop)
}

def forAll[A1, A2, U](g1: Gen[A1], g2: Gen[A2])(checker: (A1, A2) => U)(
protected def forAll[A1, A2, U](g1: Gen[A1], g2: Gen[A2])(checker: (A1, A2) => U)(
implicit
s1: Shrink[A1],
pp1: A1 => Pretty,
Expand All @@ -91,7 +91,7 @@ trait PropertyCheck extends Asserts { this: AirSpecSpi =>
checkProperty(prop)
}

def forAll[A1, A2, A3, U](checker: (A1, A2, A3) => U)(
protected def forAll[A1, A2, A3, U](checker: (A1, A2, A3) => U)(
implicit
a1: Arbitrary[A1],
s1: Shrink[A1],
Expand Down
42 changes: 42 additions & 0 deletions airspec/src/test/scala/examples/DITest.scala
@@ -0,0 +1,42 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package examples

import wvlet.airframe.{Design, newDesign}
import wvlet.airspec.AirSpec

/**
*
*/
class DITest extends AirSpec {

import wvlet.airframe._

protected val v: Int = 1000

override protected def design: Design = newDesign.bind[String].toInstance("hello airframe")
override protected def localDesign: Design = newDesign.bind[Int].toInstance(v)

def globalDesignTest(msg: String): Unit = {
msg shouldBe "hello airframe"
}

def localDesignTest(intValue: Int): Unit = {
intValue shouldBe v
}
}

class DIExtTest extends DITest {
override protected val v: Int = 2000
}
4 changes: 2 additions & 2 deletions build.sbt
Expand Up @@ -19,9 +19,9 @@ val JS_JAVA_LOGGING_VERSION = "0.1.5"
val airSpecFramework = new TestFramework("wvlet.airspec.Framework")

// Allow using Ctrl+C in sbt without exiting the prompt
cancelable in Global := true
// cancelable in Global := true

ThisBuild / turbo := true
//ThisBuild / turbo := true

// For using Scala 2.12 in sbt
scalaVersion in ThisBuild := SCALA_2_12
Expand Down

0 comments on commit dfd7a86

Please sign in to comment.