Skip to content

Commit

Permalink
Closes #3: Should not reinitialize Resources parameter for beforeAll …
Browse files Browse the repository at this point in the history
…or for static method
  • Loading branch information
asarkar authored and Abhijit Sarkar committed Aug 11, 2020
2 parents c2e128d + d92255d commit 60a8a3c
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 34 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ dependencies {
implementation("org.junit.jupiter:junit-jupiter-api")
implementation("io.grpc:grpc-api")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("io.grpc:grpc-core")
testImplementation("org.mockito:mockito-core:$mockitoVersion")
testImplementation("org.mockito:mockito-junit-jupiter:$mockitoVersion")
testImplementation("org.junit.platform:junit-platform-testkit:$jUnitTestkitVersion")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ ktlintVersion=9.3.0
bintrayPluginVersion=1.8.5

projectGroup=com.asarkar.grpc
projectVersion=1.0.1
projectVersion=1.0.2
projectDescription=JUnit5 Extension that can automatically release gRPC resources at the end of the test
licenseName=Apache-2.0
licenseUrl=http://www.apache.org/licenses/LICENSE-2.0.txt
Expand Down
31 changes: 21 additions & 10 deletions src/main/kotlin/com/asarkar/grpc/test/GrpcCleanupExtension.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.asarkar.grpc.test

import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.AfterAllCallback
import org.junit.jupiter.api.extension.AfterEachCallback
Expand Down Expand Up @@ -29,7 +30,7 @@ import kotlin.reflect.KFunction1
*/
class GrpcCleanupExtension :
BeforeEachCallback, AfterEachCallback, ParameterResolver, BeforeAllCallback, AfterAllCallback {
private var resources: Resources? = null
private val resources = mutableMapOf<Boolean, MutableList<Resources>>()
private var resourcesField: Field? = null

override fun beforeEach(ctx: ExtensionContext) {
Expand All @@ -51,30 +52,34 @@ class GrpcCleanupExtension :

override fun afterEach(ctx: ExtensionContext) {
var successful = true
this.resources?.also {
this.resources[false]?.forEach {
getCleanUpMethod(ctx)(it)
successful = it.awaitReleased()
}

if (shouldAccessResourcesField(ctx)) {
tryGet(ctx.requiredTestInstance)?.also {
getCleanUpMethod(ctx)(it)
if (!it.awaitReleased()) {
if (!successful) throw PostconditionViolationException("$resources and $it couldn't be released")
else throw PostconditionViolationException("$it couldn't be released")
}
successful = it.awaitReleased()

trySet(ctx.requiredTestInstance, null)
}
}
if (!successful) throw PostconditionViolationException("$resources couldn't be released")
if (!successful) throw PostconditionViolationException("One or more Resources couldn't be released")
}

override fun supportsParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Boolean {
return parameterContext.parameter.type == Resources::class.java
}

override fun resolveParameter(parameterContext: ParameterContext, extensionContext: ExtensionContext): Any {
return Resources().also { resources = it }
override fun resolveParameter(parameterCtx: ParameterContext, extensionCtx: ExtensionContext): Any {
val once = !parameterCtx.target.isPresent ||
(
extensionCtx.testInstanceLifecycle.orElse(null) == TestInstance.Lifecycle.PER_CLASS &&
parameterCtx.declaringExecutable.isAnnotationPresent(BeforeAll::class.java)
)

return Resources().also { resources.getOrPut(once, { mutableListOf() }).add(it) }
}

override fun beforeAll(ctx: ExtensionContext) {
Expand All @@ -94,10 +99,16 @@ class GrpcCleanupExtension :
}

override fun afterAll(ctx: ExtensionContext) {
var successful = true
tryGet(ctx.testInstance.orElse(null))?.also {
getCleanUpMethod(ctx)(it)
if (!it.awaitReleased()) throw PostconditionViolationException("$it couldn't be released")
successful = it.awaitReleased()
}
this.resources[true]?.forEach {
getCleanUpMethod(ctx)(it)
successful = it.awaitReleased()
}
if (!successful) throw PostconditionViolationException("One or more Resources couldn't be released")
}

private fun shouldAccessResourcesField(ctx: ExtensionContext): Boolean {
Expand Down
18 changes: 14 additions & 4 deletions src/test/kotlin/com/asarkar/grpc/test/ExampleTestCase2.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
package com.asarkar.grpc.test

import io.grpc.inprocess.InProcessChannelBuilder
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
import kotlin.random.Random

@ExtendWith(GrpcCleanupExtension::class)
class ExampleTestCase2 {
private lateinit var resources: Resources
private val setOfResources: Set<Resources?> = mutableSetOf()
private val setOfResources: MutableSet<Resources?> = mutableSetOf()
private val set = Mockito.spy(setOfResources)

@Test
fun test1() {
setOfResources.plus(resources)
resources.register(randomChannel())
assertThat(setOfResources.add(resources)).isTrue()
}

@Test
fun test2() {
setOfResources.plus(resources)
resources.register(randomChannel())
assertThat(setOfResources.add(resources)).isTrue()
}

@Test
fun test3() {
setOfResources.plus(resources)
resources.register(randomChannel())
assertThat(setOfResources.add(resources)).isTrue()
}

private fun randomChannel() = InProcessChannelBuilder
.forName((1..4).map { ('a' + Random.nextInt(0, 26)) }.joinToString(""))
.build()
}
6 changes: 3 additions & 3 deletions src/test/kotlin/com/asarkar/grpc/test/ExampleTestCase3.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import org.mockito.Mockito
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ExampleTestCase3 {
private var resources: Resources? = null
private val setOfResources: Set<Resources?> = mutableSetOf()
private val setOfResources: MutableSet<Resources?> = mutableSetOf()
private val set = Mockito.spy(setOfResources)

@Test
fun test1() {
setOfResources.plus(resources)
setOfResources.add(resources)
}

@Test
fun test2() {
setOfResources.plus(resources)
setOfResources.add(resources)
}
}
5 changes: 3 additions & 2 deletions src/test/kotlin/com/asarkar/grpc/test/ExampleTestCase5.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.asarkar.grpc.test

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
Expand All @@ -10,11 +11,11 @@ open class BaseTestCase {

@ExtendWith(GrpcCleanupExtension::class)
class ExampleTestCase5 : BaseTestCase() {
private val setOfResources: Set<Resources?> = mutableSetOf()
private val setOfResources: MutableSet<Resources?> = mutableSetOf()
private val set = Mockito.spy(setOfResources)

@Test
fun testInheritResource() {
setOfResources.plus(super.resources)
assertThat(setOfResources.add(super.resources)).isTrue()
}
}
6 changes: 3 additions & 3 deletions src/test/kotlin/com/asarkar/grpc/test/ExampleTestCase7.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import org.mockito.Mockito
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ExampleTestCase7 {
private var resources = Resources()
private val setOfResources: Set<Resources?> = mutableSetOf()
private val setOfResources: MutableSet<Resources?> = mutableSetOf()
private val set = Mockito.spy(setOfResources)

@Test
fun test1() {
setOfResources.plus(resources)
setOfResources.add(resources)
}

@Test
fun test2() {
setOfResources.plus(resources)
setOfResources.add(resources)
}
}
46 changes: 46 additions & 0 deletions src/test/kotlin/com/asarkar/grpc/test/ExampleTestCase9.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.asarkar.grpc.test

import io.grpc.ManagedChannel
import io.grpc.inprocess.InProcessChannelBuilder
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
import kotlin.random.Random

@ExtendWith(GrpcCleanupExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ExampleTestCase9 {
private lateinit var channel: ManagedChannel
private val setOfResources: MutableSet<Resources?> = mutableSetOf()
private val set = Mockito.spy(setOfResources)

@BeforeAll
fun beforeAll(resources: Resources) {
channel = randomChannel()
resources.register(channel)
assertThat(setOfResources.add(resources)).isTrue()
}

@Test
fun test1(resources: Resources) {
assertThat(channel.isShutdown).isFalse()
assertThat(channel.isTerminated).isFalse()
resources.register(randomChannel())
assertThat(setOfResources.add(resources)).isTrue()
}

@Test
fun test2(resources: Resources) {
assertThat(channel.isShutdown).isFalse()
assertThat(channel.isTerminated).isFalse()
resources.register(randomChannel())
assertThat(setOfResources.add(resources)).isTrue()
}

private fun randomChannel() = InProcessChannelBuilder
.forName((1..4).map { ('a' + Random.nextInt(0, 26)) }.joinToString(""))
.build()
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class GrpcCleanupExtensionIntegrationTests {
}

@Test
fun testReinitializeInstanceVariableForEachTest() {
fun testReinitializeInstanceField() {
val mocks = mutableListOf<Any>()
val listener = MockCreationListener { mock, _ -> mocks.add(mock) }
Mockito.framework().addListener(listener)
Expand All @@ -171,11 +171,11 @@ class GrpcCleanupExtensionIntegrationTests {
)

assertThat(mocks).allMatch { it is Set<*> }
assertThat(mocks.map { it as Set<*> }.toSet()).hasSize(3)
assertThat(mocks.flatMap { it as Set<*> }.toSet()).hasSize(3)
}

@Test
fun testInitializeInstanceVariableOnlyOnce() {
fun testInitializeInstanceFieldOnlyOnce() {
val mocks = mutableListOf<Any>()
val listener = MockCreationListener { mock, _ -> mocks.add(mock) }
Mockito.framework().addListener(listener)
Expand All @@ -192,11 +192,11 @@ class GrpcCleanupExtensionIntegrationTests {
)

assertThat(mocks).allMatch { it is Set<*> }
assertThat(mocks.map { it as Set<*> }.toSet()).hasSize(1)
assertThat(mocks.flatMap { it as Set<*> }.toSet()).hasSize(1)
}

@Test
fun testInitializeStaticVariableOnlyOnce() {
fun testInitializeStaticFieldOnlyOnce() {
EngineTestKit.engine("junit-jupiter")
.selectors(
selectClass(ExampleTestCase4::class.java)
Expand Down Expand Up @@ -230,11 +230,11 @@ class GrpcCleanupExtensionIntegrationTests {
)

assertThat(mocks).allMatch { it is Set<*> }
assertThat(mocks.map { it as Set<*> }.toSet()).hasSize(1)
assertThat(mocks.flatMap { it as Set<*> }.toSet()).hasSize(1)
}

@Test
fun testMultipleParameters() {
fun testMultipleParametersError() {
EngineTestKit.engine("junit-jupiter")
.selectors(
selectMethod(
Expand All @@ -254,7 +254,7 @@ class GrpcCleanupExtensionIntegrationTests {
}

@Test
fun testMultipleInstances() {
fun testMultipleInstanceFieldsError() {
EngineTestKit.engine("junit-jupiter")
.selectors(
selectClass(
Expand All @@ -271,7 +271,7 @@ class GrpcCleanupExtensionIntegrationTests {
}

@Test
fun testAlreadyInitialized() {
fun testAlreadyInitializedField() {
val mocks = mutableListOf<Any>()
val listener = MockCreationListener { mock, _ -> mocks.add(mock) }
Mockito.framework().addListener(listener)
Expand All @@ -288,11 +288,11 @@ class GrpcCleanupExtensionIntegrationTests {
)

assertThat(mocks).allMatch { it is Set<*> }
assertThat(mocks.map { it as Set<*> }.toSet()).hasSize(1)
assertThat(mocks.flatMap { it as Set<*> }.toSet()).hasSize(1)
}

@Test
fun testCannotRetainAlreadyInitialized() {
fun testAlreadyInitializedFieldError() {
EngineTestKit.engine("junit-jupiter")
.selectors(
selectClass(ExampleTestCase8::class.java)
Expand All @@ -305,4 +305,27 @@ class GrpcCleanupExtensionIntegrationTests {
event(finishedWithFailure(instanceOf(PreconditionViolationException::class.java)))
)
}

@Test
fun testInitializeParameterOnlyOnce() {
val mocks = mutableListOf<Any>()
val listener = MockCreationListener { mock, _ -> mocks.add(mock) }
Mockito.framework().addListener(listener)
EngineTestKit.engine("junit-jupiter")
.selectors(
selectClass(ExampleTestCase9::class.java)
)
.execute()
.testEvents()
.assertThatEvents()
.haveExactly(
2,
event(
finishedSuccessfully()
)
)

assertThat(mocks).allMatch { it is Set<*> }
assertThat(mocks.flatMap { it as Set<*> }.toSet()).hasSize(3)
}
}

0 comments on commit 60a8a3c

Please sign in to comment.