[rdct-tests]: allow running from background

GitOrigin-RevId: dee7a5efa21ed8ffef92f4483007fac2d67302cf
This commit is contained in:
Anastasia Katsman
2023-08-01 13:50:26 +00:00
committed by intellij-monorepo-bot
parent 60f8208092
commit 8204569932
3 changed files with 60 additions and 35 deletions
@@ -30,6 +30,7 @@ import com.jetbrains.rd.util.lifetime.EternalLifetime
import com.jetbrains.rd.util.lifetime.Lifetime
import com.jetbrains.rd.util.measureTimeMillis
import com.jetbrains.rd.util.reactive.viewNotNull
import com.jetbrains.rd.util.threading.SynchronousScheduler
import org.jetbrains.annotations.ApiStatus
import java.awt.Component
import java.awt.image.BufferedImage
@@ -128,65 +129,80 @@ open class DistributedTestHost {
testClassObject.performInit(testMethod)
testMethod.invoke(testClassObject)
// Advice for processing events
session.runNextAction.set { _, _ ->
var actionTitle: String? = null
fun runAction(agentAction: AgentAction, expectIsDispatchThread: Boolean): RdTask<String?> {
val actionTitle = agentAction.title
try {
assert(ClientId.current.isLocal) { "ClientId '${ClientId.current}' should be local when test method starts" }
assert(application.isDispatchThread == expectIsDispatchThread) {
"Expected to be started on EDT: $expectIsDispatchThread, actual: ${Thread.currentThread()}"
}
val action = queue.remove()
actionTitle = action.title
if (expectIsDispatchThread) {
logger.info("'$actionTitle': preparing to start action")
logger.info("'$actionTitle': preparing to start action")
val isNotRdHost = !(session.agentInfo.productTypeType == RdProductType.REMOTE_DEVELOPMENT && session.agentInfo.agentType == RdAgentType.HOST)
if (!application.isHeadlessEnvironment && isNotRdHost) {
IdeEventQueue.getInstance().flushQueue()
requestFocus(actionTitle)
val isNotRdHost = !(session.agentInfo.productTypeType == RdProductType.REMOTE_DEVELOPMENT && session.agentInfo.agentType == RdAgentType.HOST)
if (!application.isHeadlessEnvironment && isNotRdHost) {
IdeEventQueue.getInstance().flushQueue()
requestFocus(actionTitle)
}
}
showNotification("${session.agentInfo.id}: $actionTitle")
// Flush all events to process pending protocol events and other things
// before actual test method execution
IdeEventQueue.getInstance().flushQueue()
if (expectIsDispatchThread) {
// Flush all events to process pending protocol events and other things
// before actual test method execution
IdeEventQueue.getInstance().flushQueue()
}
// Execute test method
lateinit var result: RdTask<String?>
val context = when (session.agentInfo.agentType) {
val agentContext = when (session.agentInfo.agentType) {
RdAgentType.HOST -> HostAgentContextImpl(session.agentInfo, application, projectOrNull, protocol)
RdAgentType.CLIENT -> ClientAgentContextImpl(session.agentInfo, application, projectOrNull, protocol)
RdAgentType.GATEWAY -> GatewayAgentContextImpl(session.agentInfo, application, projectOrNull, protocol)
}
// Execute test method
lateinit var result: RdTask<String?>
logger.info("'$actionTitle': starting action")
val elapsedAction = measureTimeMillis {
result = action.action.invoke(context)
result = agentAction.action.invoke(agentContext)
}
logger.info("'$actionTitle': completed action in ${elapsedAction}ms")
projectOrNull?.let {
// Sync state across all IDE agents to maintain proper order in protocol events
logger.info("'$actionTitle': Sync protocol events after execution...")
val elapsedSync = measureTimeMillis {
DistributedTestBridge.getInstance(it).syncProtocolEvents()
IdeEventQueue.getInstance().flushQueue()
if (expectIsDispatchThread) {
projectOrNull?.let {
// Sync state across all IDE agents to maintain proper order in protocol events
logger.info("'$actionTitle': Sync protocol events after execution...")
val elapsedSync = measureTimeMillis {
DistributedTestBridge.getInstance(it).syncProtocolEvents()
IdeEventQueue.getInstance().flushQueue()
}
logger.info("'$actionTitle': Protocol state sync completed in ${elapsedSync}ms")
}
logger.info("'$actionTitle': Protocol state sync completed in ${elapsedSync}ms")
}
// Assert state
assertLoggerFactory()
return@set result
return result
}
catch (ex: Throwable) {
val msg = "${session.agentInfo.id}: ${actionTitle?.let { "'$it' " }.orEmpty()}hasn't finished successfully"
val msg = "${session.agentInfo.id}: ${actionTitle.let { "'$it' " }.orEmpty()}hasn't finished successfully"
logger.warn(msg, ex)
if (!application.isHeadlessEnvironment)
actionTitle?.let { makeScreenshot("${it}_$screenshotOnFailureFileName") }
return@set RdTask.faulted(AssertionError(msg, ex))
makeScreenshot("${actionTitle}_$screenshotOnFailureFileName")
return RdTask.faulted(AssertionError(msg, ex))
}
}
// Advice for processing events
session.runNextAction.set { _, _ ->
runAction(queue.remove(), true)
}
// Special handler to be used in
session.runNextActionBackground.set(SynchronousScheduler, SynchronousScheduler) { _, _ ->
runAction(queue.remove(), false)
}
}
session.isResponding.set { _, _ ->
@@ -238,9 +254,9 @@ open class DistributedTestHost {
// Initialize loggers
DebugLogManager.getInstance().applyCategories(
session.traceCategories.map { DebugLogManager.Category(it, DebugLogManager.DebugLogLevel.TRACE)} +
session.debugCategories.map { DebugLogManager.Category(it, DebugLogManager.DebugLogLevel.DEBUG) }
)
session.traceCategories.map { DebugLogManager.Category(it, DebugLogManager.DebugLogLevel.TRACE) } +
session.debugCategories.map { DebugLogManager.Category(it, DebugLogManager.DebugLogLevel.DEBUG) }
)
logger.info("Test session ready!")
session.ready.value = true
}
@@ -54,7 +54,7 @@ class DistributedTestModel private constructor(
private val __RdTestSessionNullableSerializer = RdTestSession.nullable()
const val serializationHash = -4063022036171224345L
const val serializationHash = -195273050868380088L
}
override val serializersOwner: ISerializersOwner get() = DistributedTestModel
@@ -218,6 +218,7 @@ class RdTestSession private constructor(
private val _closeProject: RdCall<Unit, Boolean>,
private val _closeProjectIfOpened: RdCall<Unit, Boolean>,
private val _runNextAction: RdCall<Unit, String?>,
private val _runNextActionBackground: RdCall<Unit, String?>,
private val _makeScreenshot: RdCall<String, Boolean>,
private val _isResponding: RdCall<Unit, Boolean>
) : RdBindableBase() {
@@ -240,9 +241,10 @@ class RdTestSession private constructor(
val _closeProject = RdCall.read(ctx, buffer, FrameworkMarshallers.Void, FrameworkMarshallers.Bool)
val _closeProjectIfOpened = RdCall.read(ctx, buffer, FrameworkMarshallers.Void, FrameworkMarshallers.Bool)
val _runNextAction = RdCall.read(ctx, buffer, FrameworkMarshallers.Void, __StringNullableSerializer)
val _runNextActionBackground = RdCall.read(ctx, buffer, FrameworkMarshallers.Void, __StringNullableSerializer)
val _makeScreenshot = RdCall.read(ctx, buffer, FrameworkMarshallers.String, FrameworkMarshallers.Bool)
val _isResponding = RdCall.read(ctx, buffer, FrameworkMarshallers.Void, FrameworkMarshallers.Bool)
return RdTestSession(agentInfo, testClassName, testMethodName, traceCategories, debugCategories, _ready, _sendException, _shutdown, _closeProject, _closeProjectIfOpened, _runNextAction, _makeScreenshot, _isResponding).withId(_id)
return RdTestSession(agentInfo, testClassName, testMethodName, traceCategories, debugCategories, _ready, _sendException, _shutdown, _closeProject, _closeProjectIfOpened, _runNextAction, _runNextActionBackground, _makeScreenshot, _isResponding).withId(_id)
}
override fun write(ctx: SerializationCtx, buffer: AbstractBuffer, value: RdTestSession) {
@@ -258,6 +260,7 @@ class RdTestSession private constructor(
RdCall.write(ctx, buffer, value._closeProject)
RdCall.write(ctx, buffer, value._closeProjectIfOpened)
RdCall.write(ctx, buffer, value._runNextAction)
RdCall.write(ctx, buffer, value._runNextActionBackground)
RdCall.write(ctx, buffer, value._makeScreenshot)
RdCall.write(ctx, buffer, value._isResponding)
}
@@ -273,6 +276,7 @@ class RdTestSession private constructor(
val closeProject: RdCall<Unit, Boolean> get() = _closeProject
val closeProjectIfOpened: RdCall<Unit, Boolean> get() = _closeProjectIfOpened
val runNextAction: RdCall<Unit, String?> get() = _runNextAction
val runNextActionBackground: RdCall<Unit, String?> get() = _runNextActionBackground
val makeScreenshot: RdCall<String, Boolean> get() = _makeScreenshot
val isResponding: RdCall<Unit, Boolean> get() = _isResponding
//methods
@@ -292,6 +296,7 @@ class RdTestSession private constructor(
bindableChildren.add("closeProject" to _closeProject)
bindableChildren.add("closeProjectIfOpened" to _closeProjectIfOpened)
bindableChildren.add("runNextAction" to _runNextAction)
bindableChildren.add("runNextActionBackground" to _runNextActionBackground)
bindableChildren.add("makeScreenshot" to _makeScreenshot)
bindableChildren.add("isResponding" to _isResponding)
}
@@ -315,6 +320,7 @@ class RdTestSession private constructor(
RdCall<Unit, Boolean>(FrameworkMarshallers.Void, FrameworkMarshallers.Bool),
RdCall<Unit, Boolean>(FrameworkMarshallers.Void, FrameworkMarshallers.Bool),
RdCall<Unit, String?>(FrameworkMarshallers.Void, __StringNullableSerializer),
RdCall<Unit, String?>(FrameworkMarshallers.Void, __StringNullableSerializer),
RdCall<String, Boolean>(FrameworkMarshallers.String, FrameworkMarshallers.Bool),
RdCall<Unit, Boolean>(FrameworkMarshallers.Void, FrameworkMarshallers.Bool)
)
@@ -336,6 +342,7 @@ class RdTestSession private constructor(
print("closeProject = "); _closeProject.print(printer); println()
print("closeProjectIfOpened = "); _closeProjectIfOpened.print(printer); println()
print("runNextAction = "); _runNextAction.print(printer); println()
print("runNextActionBackground = "); _runNextActionBackground.print(printer); println()
print("makeScreenshot = "); _makeScreenshot.print(printer); println()
print("isResponding = "); _isResponding.print(printer); println()
}
@@ -355,6 +362,7 @@ class RdTestSession private constructor(
_closeProject.deepClonePolymorphic(),
_closeProjectIfOpened.deepClonePolymorphic(),
_runNextAction.deepClonePolymorphic(),
_runNextActionBackground.deepClonePolymorphic(),
_makeScreenshot.deepClonePolymorphic(),
_isResponding.deepClonePolymorphic()
)
@@ -62,6 +62,7 @@ object DistributedTestModel : Ext(TestRoot) {
call("closeProject", void, bool)
call("closeProjectIfOpened", void, bool)
call("runNextAction", void, string.nullable)
call("runNextActionBackground", void, string.nullable)
call("makeScreenshot", string, bool)
call("isResponding", void, bool)
}