Select the asserter based on test framework presence in classpath
Simplify asserter lookup: enumerate all AsserterContributors when the file class with lookupAsserter function is initialized. It's assumed that AsserterContributor initialization should be fast. #KT-21154 Fixed
This commit is contained in:
@@ -3,21 +3,25 @@ package kotlin.test.junit
|
|||||||
import org.junit.*
|
import org.junit.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides [JUnitAsserter] if `org.junit.Assert` is found in the classpath.
|
||||||
|
*/
|
||||||
class JUnitContributor : AsserterContributor {
|
class JUnitContributor : AsserterContributor {
|
||||||
override fun contribute(): Asserter? {
|
override fun contribute(): Asserter? {
|
||||||
for (stackFrame in currentStackTrace()) {
|
return if (hasJUnitInClassPath) JUnitAsserter else null
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
}
|
||||||
val className = stackFrame.className as java.lang.String
|
|
||||||
|
|
||||||
if (className.startsWith("org.junit.") || className.startsWith("junit.")) {
|
private val hasJUnitInClassPath = try {
|
||||||
return JUnitAsserter
|
Class.forName("org.junit.Assert")
|
||||||
}
|
true
|
||||||
}
|
} catch (_: ClassNotFoundException) {
|
||||||
|
false
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements `kotlin.test` assertions by delegating them to `org.junit.Assert` class.
|
||||||
|
*/
|
||||||
object JUnitAsserter : Asserter {
|
object JUnitAsserter : Asserter {
|
||||||
override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
|
override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
|
||||||
Assert.assertEquals(message, expected, actual)
|
Assert.assertEquals(message, expected, actual)
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
package kotlin.test.junit.tests
|
package kotlin.test.junit.tests
|
||||||
|
|
||||||
import org.junit.*
|
import org.junit.Assert
|
||||||
|
import kotlin.test.*
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
|
import kotlin.test.junit.JUnitAsserter
|
||||||
|
|
||||||
class JUnitContributorTest {
|
class JUnitContributorTest {
|
||||||
@Test
|
@Test
|
||||||
fun smokeTest() {
|
fun smokeTest() {
|
||||||
Assert.assertEquals("JUnitAsserter", asserter.`class`.simpleName)
|
assertSame(JUnitAsserter, kotlin.test.asserter)
|
||||||
|
Assert.assertEquals(JUnitAsserter::class.java.simpleName, kotlin.test.asserter.javaClass.simpleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should fail to contribute if it was run outside of junit`() {
|
fun parallelThreadGetsTheSameAsserter() {
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
val q = ArrayBlockingQueue<Any>(1)
|
||||||
val q = ArrayBlockingQueue<java.lang.Object>(1)
|
|
||||||
|
|
||||||
Thread {
|
Thread {
|
||||||
q.put(asserter)
|
q.put(asserter)
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
Assert.assertEquals("DefaultAsserter", q.take().`class`.simpleName)
|
assertSame(kotlin.test.asserter, q.take())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
|
||||||
private val asserter: java.lang.Object
|
|
||||||
get() = Class.forName("kotlin.test.AssertionsKt").getMethod("getAsserter").invoke(null) as java.lang.Object
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,15 @@
|
|||||||
package kotlin.test
|
package kotlin.test
|
||||||
|
|
||||||
import java.util.*
|
import java.util.ServiceLoader
|
||||||
import java.util.concurrent.atomic.*
|
|
||||||
import java.util.concurrent.locks.*
|
|
||||||
import kotlin.concurrent.withLock
|
|
||||||
|
|
||||||
private val inited = AtomicBoolean()
|
private val contributors = ServiceLoader.load(AsserterContributor::class.java).toList()
|
||||||
private val lock = ReentrantLock()
|
|
||||||
private val contributors = ArrayList<AsserterContributor>()
|
|
||||||
|
|
||||||
internal actual fun lookupAsserter(): Asserter = lookup()
|
|
||||||
|
|
||||||
private val defaultAsserter = DefaultAsserter()
|
private val defaultAsserter = DefaultAsserter()
|
||||||
|
|
||||||
internal fun lookup(): Asserter {
|
internal actual fun lookupAsserter(): Asserter {
|
||||||
initContributorsIfNeeded()
|
|
||||||
|
|
||||||
for (contributor in contributors) {
|
for (contributor in contributors) {
|
||||||
val asserter = contributor.contribute()
|
val asserter = contributor.contribute()
|
||||||
if (asserter != null) {
|
if (asserter != null) return asserter
|
||||||
return asserter
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultAsserter
|
return defaultAsserter
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initContributors() {
|
|
||||||
contributors.clear()
|
|
||||||
val loader = ServiceLoader.load(AsserterContributor::class.java)
|
|
||||||
|
|
||||||
for (contributor in loader) {
|
|
||||||
if (contributor != null) {
|
|
||||||
contributors.add(contributor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initContributorsIfNeeded() {
|
|
||||||
if (!inited.get()) {
|
|
||||||
lock.withLock {
|
|
||||||
if (inited.compareAndSet(false, true)) {
|
|
||||||
initContributors()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,20 +8,25 @@ package kotlin.test.testng
|
|||||||
import org.testng.*
|
import org.testng.*
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides [TestNGAsserter] if `org.testng.Assert` is found in the classpath.
|
||||||
|
*/
|
||||||
class TestNGContributor : AsserterContributor {
|
class TestNGContributor : AsserterContributor {
|
||||||
override fun contribute(): Asserter? {
|
override fun contribute(): Asserter? {
|
||||||
for (stackFrame in currentStackTrace()) {
|
return if (hasTestNGInClassPath) TestNGAsserter else null
|
||||||
val className = stackFrame.className
|
}
|
||||||
|
|
||||||
if (className.startsWith("org.testng.") || className.startsWith("testng.")) {
|
private val hasTestNGInClassPath = try {
|
||||||
return TestNGAsserter
|
Class.forName("org.testng.Assert")
|
||||||
}
|
true
|
||||||
}
|
} catch (_: ClassNotFoundException) {
|
||||||
|
false
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements `kotlin.test` assertions by delegating them to `org.testng.Assert` class.
|
||||||
|
*/
|
||||||
object TestNGAsserter : Asserter {
|
object TestNGAsserter : Asserter {
|
||||||
override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
|
override fun assertEquals(message: String?, expected: Any?, actual: Any?) {
|
||||||
Assert.assertEquals(expected, actual, message)
|
Assert.assertEquals(expected, actual, message)
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
package kotlin.test.testng.tests
|
package kotlin.test.testng.tests
|
||||||
|
|
||||||
import org.testng.annotations.*
|
import org.testng.Assert
|
||||||
import org.testng.*
|
import kotlin.test.*
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
|
import kotlin.test.testng.TestNGAsserter
|
||||||
|
|
||||||
class TestNGContributorTest {
|
class TestNGContributorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun smokeTest() {
|
fun smokeTest() {
|
||||||
Assert.assertEquals("TestNGAsserter", kotlin.test.asserter.javaClass.simpleName)
|
assertSame(TestNGAsserter, asserter)
|
||||||
|
Assert.assertEquals(TestNGAsserter::class.java.simpleName, kotlin.test.asserter.javaClass.simpleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should fail to contribute if it was run outside of testng`() {
|
fun parallelThreadGetsTheSameAsserter() {
|
||||||
val q = ArrayBlockingQueue<Any>(1)
|
val q = ArrayBlockingQueue<Any>(1)
|
||||||
|
|
||||||
Thread {
|
Thread {
|
||||||
q.put(kotlin.test.asserter)
|
q.put(asserter)
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
Assert.assertEquals("DefaultAsserter", q.take().javaClass.simpleName)
|
assertSame(asserter, q.take())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user