All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ru.fix.corounit.allure.StepMethodWrapper.kt Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
package ru.fix.corounit.allure

import java.lang.reflect.Method
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.reflect.KParameter
import kotlin.reflect.jvm.kotlinFunction

class StepMethodWrapper(
        private val originMethod: Method,
        private val originArgs: Array) {

    private val newArgs: Array
    private val methodAllureStep: AllureStep?
    private val originContinuation: Continuation?

    init {
        originContinuation = originArgs.findLast { it is Continuation<*> } as? Continuation
        if (originContinuation == null){
            newArgs = originArgs
            methodAllureStep = null

        } else {
            val parentStep = AllureStep.tryFromCoroutineContext(originContinuation.context)
            if(parentStep == null){
                newArgs = originArgs
                methodAllureStep = null

            } else {
                val parameterNames = originMethod.kotlinFunction?.parameters
                        ?.filter { it.kind == KParameter.Kind.VALUE }
                        ?.map { it.name }
                        ?: originMethod.parameters.map { it.name }

                val title = "" +
                        originMethod.name + " " +
                        parameterNames
                                .zip(originArgs)
                                .map { (name, arg) -> "$name: $arg" }
                                .joinToString(prefix = "(", separator = ", ", postfix = ")")

                val childCoroutineContext = parentStep.startChildStepWithCoroutineContext(title, originContinuation.context)
                methodAllureStep = AllureStep.fromCoroutineContext(childCoroutineContext)
                newArgs = originArgs.copyOf()

                if (!isMethodInvokedRecursivelyWithItsInnerContinuation()) {
                    newArgs[newArgs.lastIndex] = object : Continuation {
                        override val context: CoroutineContext
                            get() = childCoroutineContext

                        override fun resumeWith(result: Result) {
                            methodAllureStep.stop()
                            originContinuation.resumeWith(result)
                        }
                    }
                }
            }
        }
    }

    private fun isMethodInvokedRecursivelyWithItsInnerContinuation() =
            originContinuation?.javaClass?.enclosingClass?.name ==
            originMethod.declaringClass.name

    fun wrappedInvoke(originalMethodInvocation: (newArgs: Array) -> Any?): Any? {
        try {
            val result = originalMethodInvocation(newArgs)
            if (result != kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED) {
                methodAllureStep?.stop()
            }
            return result
        } catch (thr: Throwable) {
            methodAllureStep?.stop(thr)
            throw thr
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy