[test] Introduce DeserializedIrBackend backend kind
We have `BackendKinds.IrBackend` for IR emitted by the frontend. We need a different backend kind for IR deserialized from klibs. We cannot use `BackendKinds.IrBackend` for that purpose, because we cannot have two different `IrBackendInput` subclasses with the same kind. We need a different `IrBackendInput` subclass for deserialized IR because the `IrBackendInput` for frontend-emitted IR contains some properties like `sourceFiles` which don't make sense for deserialized IR. Since we now have two backend kinds for IR artifacts, we need to make certain functions and classes in the test infrastructure generic over backend kinds. Note: the JsIrDeserializedFromKlibBackendInput class is not used anywhere yet. We will use it in the coming commits.
This commit is contained in:
committed by
Space Team
parent
0521b63cb1
commit
2727163a63
@@ -16,7 +16,11 @@ import org.jetbrains.kotlin.test.services.ModuleStructureExtractor
|
||||
import org.jetbrains.kotlin.test.services.PreAnalysisHandler
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
typealias Constructor<T> = (TestServices) -> T
|
||||
typealias Constructor<R> = (TestServices) -> R
|
||||
|
||||
typealias Constructor2<T, R> = (TestServices, T) -> R
|
||||
|
||||
typealias Constructor3<T1, T2, R> = (TestServices, T1, T2) -> R
|
||||
|
||||
abstract class TestConfiguration {
|
||||
abstract val rootDisposable: Disposable
|
||||
@@ -44,11 +48,11 @@ abstract class TestConfiguration {
|
||||
|
||||
// ---------------------------- Utils ----------------------------
|
||||
|
||||
fun <T, R> ((TestServices, T) -> R).bind(value: T): Constructor<R> {
|
||||
fun <T, R> Constructor2<T, R>.bind(value: T): Constructor<R> {
|
||||
return { this.invoke(it, value) }
|
||||
}
|
||||
|
||||
fun <T1, T2, R> ((TestServices, T1, T2) -> R).bind(value1: T1, value2: T2): Constructor<R> {
|
||||
fun <T1, T2, R> Constructor3<T1, T2, R>.bind(value1: T1, value2: T2): Constructor<R> {
|
||||
return { this.invoke(it, value1, value2) }
|
||||
}
|
||||
|
||||
|
||||
@@ -8,27 +8,41 @@ package org.jetbrains.kotlin.test
|
||||
import org.jetbrains.kotlin.test.TestRunner.Companion.shouldRun
|
||||
import org.jetbrains.kotlin.test.model.*
|
||||
|
||||
sealed class TestStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>> {
|
||||
abstract val inputArtifactKind: TestArtifactKind<I>
|
||||
sealed class TestStep<InputArtifact, OutputArtifact>
|
||||
where InputArtifact : ResultingArtifact<InputArtifact>,
|
||||
OutputArtifact : ResultingArtifact<OutputArtifact> {
|
||||
abstract val inputArtifactKind: TestArtifactKind<InputArtifact>
|
||||
|
||||
open fun shouldProcessModule(module: TestModule, inputArtifact: ResultingArtifact<*>): Boolean {
|
||||
return inputArtifact.kind == inputArtifactKind
|
||||
}
|
||||
|
||||
abstract fun processModule(module: TestModule, inputArtifact: I, thereWereExceptionsOnPreviousSteps: Boolean): StepResult<out O>
|
||||
abstract fun processModule(
|
||||
module: TestModule,
|
||||
inputArtifact: InputArtifact,
|
||||
thereWereExceptionsOnPreviousSteps: Boolean,
|
||||
): StepResult<out OutputArtifact>
|
||||
|
||||
class FacadeStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>>(val facade: AbstractTestFacade<I, O>) : TestStep<I, O>() {
|
||||
override val inputArtifactKind: TestArtifactKind<I>
|
||||
class FacadeStep<InputArtifact, OutputArtifact>(
|
||||
val facade: AbstractTestFacade<InputArtifact, OutputArtifact>,
|
||||
) : TestStep<InputArtifact, OutputArtifact>()
|
||||
where InputArtifact : ResultingArtifact<InputArtifact>,
|
||||
OutputArtifact : ResultingArtifact<OutputArtifact> {
|
||||
override val inputArtifactKind: TestArtifactKind<InputArtifact>
|
||||
get() = facade.inputKind
|
||||
|
||||
val outputArtifactKind: TestArtifactKind<O>
|
||||
val outputArtifactKind: TestArtifactKind<OutputArtifact>
|
||||
get() = facade.outputKind
|
||||
|
||||
override fun shouldProcessModule(module: TestModule, inputArtifact: ResultingArtifact<*>): Boolean {
|
||||
return super.shouldProcessModule(module, inputArtifact) && facade.shouldRunAnalysis(module)
|
||||
}
|
||||
|
||||
override fun processModule(module: TestModule, inputArtifact: I, thereWereExceptionsOnPreviousSteps: Boolean): StepResult<out O> {
|
||||
override fun processModule(
|
||||
module: TestModule,
|
||||
inputArtifact: InputArtifact,
|
||||
thereWereExceptionsOnPreviousSteps: Boolean,
|
||||
): StepResult<out OutputArtifact> {
|
||||
val outputArtifact = try {
|
||||
facade.transform(module, inputArtifact) ?: return StepResult.NoArtifactFromFacade
|
||||
} catch (e: Throwable) {
|
||||
@@ -39,17 +53,22 @@ sealed class TestStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>> {
|
||||
}
|
||||
}
|
||||
|
||||
class HandlersStep<I : ResultingArtifact<I>>(
|
||||
override val inputArtifactKind: TestArtifactKind<I>,
|
||||
val handlers: List<AnalysisHandler<I>>
|
||||
) : TestStep<I, Nothing>() {
|
||||
class HandlersStep<InputArtifact : ResultingArtifact<InputArtifact>>(
|
||||
override val inputArtifactKind: TestArtifactKind<InputArtifact>,
|
||||
val handlers: List<AnalysisHandler<InputArtifact>>
|
||||
) : TestStep<InputArtifact, Nothing>() {
|
||||
init {
|
||||
require(handlers.all { it.artifactKind == inputArtifactKind })
|
||||
for (handler in handlers) {
|
||||
require(handler.artifactKind == inputArtifactKind) {
|
||||
"Artifact kind mismatch. Artifact kind of each handler must match input artifact kind ($inputArtifactKind). " +
|
||||
"In handler $handler artifact kind is ${handler.artifactKind}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun processModule(
|
||||
module: TestModule,
|
||||
inputArtifact: I,
|
||||
inputArtifact: InputArtifact,
|
||||
thereWereExceptionsOnPreviousSteps: Boolean
|
||||
): StepResult.HandlersResult {
|
||||
val exceptions = mutableListOf<WrappedException>()
|
||||
@@ -69,15 +88,20 @@ sealed class TestStep<I : ResultingArtifact<I>, O : ResultingArtifact<O>> {
|
||||
}
|
||||
}
|
||||
|
||||
sealed class StepResult<O : ResultingArtifact<O>> {
|
||||
class Artifact<O : ResultingArtifact<O>>(val outputArtifact: O) : StepResult<O>()
|
||||
class ErrorFromFacade<O : ResultingArtifact<O>>(val exception: WrappedException) : StepResult<O>()
|
||||
sealed class StepResult<OutputArtifact : ResultingArtifact<OutputArtifact>> {
|
||||
|
||||
class Artifact<OutputArtifact : ResultingArtifact<OutputArtifact>>(val outputArtifact: OutputArtifact) :
|
||||
StepResult<OutputArtifact>()
|
||||
|
||||
class ErrorFromFacade<OutputArtifact : ResultingArtifact<OutputArtifact>>(val exception: WrappedException) :
|
||||
StepResult<OutputArtifact>()
|
||||
|
||||
data class HandlersResult(
|
||||
val exceptionsFromHandlers: Collection<WrappedException>,
|
||||
val shouldRunNextSteps: Boolean
|
||||
) : StepResult<Nothing>()
|
||||
|
||||
object NoArtifactFromFacade : StepResult<Nothing>()
|
||||
data object NoArtifactFromFacade : StepResult<Nothing>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,38 +8,49 @@ package org.jetbrains.kotlin.test
|
||||
import org.jetbrains.kotlin.test.model.*
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
sealed class TestStepBuilder<I : ResultingArtifact<I>, O : ResultingArtifact<O>> {
|
||||
sealed class TestStepBuilder<InputArtifact, OutputArtifact>
|
||||
where InputArtifact : ResultingArtifact<InputArtifact>,
|
||||
OutputArtifact : ResultingArtifact<OutputArtifact> {
|
||||
@TestInfrastructureInternals
|
||||
abstract fun createTestStep(testServices: TestServices): TestStep<I, O>
|
||||
abstract fun createTestStep(testServices: TestServices): TestStep<InputArtifact, OutputArtifact>
|
||||
}
|
||||
|
||||
|
||||
class FacadeStepBuilder<I : ResultingArtifact<I>, O : ResultingArtifact<O>>(
|
||||
val facade: Constructor<AbstractTestFacade<I, O>>
|
||||
) : TestStepBuilder<I, O>() {
|
||||
class FacadeStepBuilder<InputArtifact, OutputArtifact>(
|
||||
val facade: Constructor<AbstractTestFacade<InputArtifact, OutputArtifact>>,
|
||||
) : TestStepBuilder<InputArtifact, OutputArtifact>()
|
||||
where InputArtifact : ResultingArtifact<InputArtifact>,
|
||||
OutputArtifact : ResultingArtifact<OutputArtifact> {
|
||||
@TestInfrastructureInternals
|
||||
override fun createTestStep(testServices: TestServices): TestStep.FacadeStep<I, O> {
|
||||
override fun createTestStep(testServices: TestServices): TestStep.FacadeStep<InputArtifact, OutputArtifact> {
|
||||
return TestStep.FacadeStep(facade.invoke(testServices))
|
||||
}
|
||||
}
|
||||
|
||||
class HandlersStepBuilder<I : ResultingArtifact<I>>(val artifactKind: TestArtifactKind<I>) : TestStepBuilder<I, Nothing>() {
|
||||
private val handlers: MutableList<Constructor<AnalysisHandler<I>>> = mutableListOf()
|
||||
class HandlersStepBuilder<InputArtifact, InputArtifactKind>(val artifactKind: InputArtifactKind) :
|
||||
TestStepBuilder<InputArtifact, Nothing>()
|
||||
where InputArtifact : ResultingArtifact<InputArtifact>,
|
||||
InputArtifactKind : TestArtifactKind<InputArtifact> {
|
||||
private val handlers: MutableList<Constructor<AnalysisHandler<InputArtifact>>> = mutableListOf()
|
||||
|
||||
fun useHandlers(vararg constructor: Constructor<AnalysisHandler<I>>) {
|
||||
fun useHandlers(vararg constructor: Constructor<AnalysisHandler<InputArtifact>>) {
|
||||
handlers += constructor
|
||||
}
|
||||
|
||||
fun useHandlersAtFirst(vararg constructor: Constructor<AnalysisHandler<I>>) {
|
||||
fun useHandlers(vararg constructor: Constructor2<InputArtifactKind, AnalysisHandler<InputArtifact>>) {
|
||||
constructor.mapTo(handlers) { it.bind(artifactKind) }
|
||||
}
|
||||
|
||||
fun useHandlersAtFirst(vararg constructor: Constructor<AnalysisHandler<InputArtifact>>) {
|
||||
handlers.addAll(0, constructor.toList())
|
||||
}
|
||||
|
||||
fun useHandlers(constructors: List<Constructor<AnalysisHandler<I>>>) {
|
||||
fun useHandlers(constructors: List<Constructor<AnalysisHandler<InputArtifact>>>) {
|
||||
handlers += constructors
|
||||
}
|
||||
|
||||
@TestInfrastructureInternals
|
||||
override fun createTestStep(testServices: TestServices): TestStep.HandlersStep<I> {
|
||||
override fun createTestStep(testServices: TestServices): TestStep.HandlersStep<InputArtifact> {
|
||||
return TestStep.HandlersStep(artifactKind, handlers.map { it.invoke(testServices) })
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -35,16 +35,22 @@ class DependencyProviderImpl(
|
||||
return testModulesByName[name] ?: assertions.fail { "Module $name is not defined" }
|
||||
}
|
||||
|
||||
override fun <A : ResultingArtifact<A>> getArtifactSafe(module: TestModule, kind: TestArtifactKind<A>): A? {
|
||||
override fun <OutputArtifact : ResultingArtifact<OutputArtifact>> getArtifactSafe(
|
||||
module: TestModule,
|
||||
kind: TestArtifactKind<OutputArtifact>,
|
||||
): OutputArtifact? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return artifactsByModule.getMap(module)[kind] as A?
|
||||
return artifactsByModule.getMap(module)[kind] as OutputArtifact?
|
||||
}
|
||||
|
||||
override fun <A : ResultingArtifact<A>> getArtifact(module: TestModule, kind: TestArtifactKind<A>): A {
|
||||
return getArtifactSafe(module, kind) ?: error("Artifact with kind $kind is not registered for module ${module.name}")
|
||||
}
|
||||
|
||||
fun <A : ResultingArtifact<A>> registerArtifact(module: TestModule, artifact: ResultingArtifact<A>) {
|
||||
fun <OutputArtifact : ResultingArtifact<OutputArtifact>> registerArtifact(
|
||||
module: TestModule,
|
||||
artifact: ResultingArtifact<OutputArtifact>,
|
||||
) {
|
||||
val kind = artifact.kind
|
||||
val previousValue = artifactsByModule.getMap(module).put(kind, artifact)
|
||||
if (previousValue != null) error("Artifact with kind $kind already registered for module ${module.name}")
|
||||
|
||||
Reference in New Issue
Block a user