GtestRunner.kt
/*
* Copyright 2022 The Android Open Source Project
*
* 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 androidx.test.ext.junitgtest
import org.junit.runner.Description
import org.junit.runner.Runner
import org.junit.runner.manipulation.Filter
import org.junit.runner.manipulation.Filterable
import org.junit.runner.manipulation.NoTestsRemainException
import org.junit.runner.notification.RunNotifier
/**
* Custom Runner that implements a bridge between JUnit and GTest.
*
* Use this Runner in a `@RunWith` annotation together with a `@TargetLibrary`
* annotation on an empty class to create a connected test that consists of native
* tests written against the Google Test Framework.
*/
class GtestRunner(testClass: Class<*>) : Runner(),
Filterable {
private val targetClass: Class<*>
private var description: Description
override fun getDescription(): Description {
return description
}
@Throws(NoTestsRemainException::class)
override fun filter(filter: Filter) {
val children: List<Description> = description.children
description = Description.createSuiteDescription(targetClass)
val iter = children.iterator()
while (iter.hasNext()) {
val testDescription = iter.next()
if (filter.shouldRun(testDescription)) {
description.addChild(testDescription)
}
}
if (description.children.isEmpty()) {
throw NoTestsRemainException()
}
}
override fun run(notifier: RunNotifier) {
for (description in description.children) {
addTest(description.methodName)
}
run(targetClass.name, notifier)
}
private companion object {
private var onceFlag = false
}
init {
synchronized(GtestRunner::class.java) {
check(!onceFlag) { "Error multiple GtestRunners defined" }
onceFlag = true
}
targetClass = testClass
val library = testClass.getAnnotation(TargetLibrary::class.java)
?: throw IllegalStateException("Missing required @TargetLibrary annotation")
System.loadLibrary(library.libraryName)
description = Description.createSuiteDescription(testClass)
// The nInitialize native method will populate the description based on
// GTest test data.
initialize(testClass.name, description)
}
private external fun initialize(className: String, description: Description)
private external fun addTest(testName: String)
private external fun run(className: String, notifier: RunNotifier): Boolean
}