mirror of
https://github.com/corda/corda.git
synced 2025-02-20 17:33:15 +00:00
[CORDA-2326] Ensure right step is rendered by AnsiProgressRenderer (#4514)
* Add test to reproduce problem * Remap step indices when the step tree changes
This commit is contained in:
parent
7bbe4668d6
commit
5e32e718ae
@ -85,6 +85,7 @@ abstract class ANSIProgressRenderer {
|
||||
stepsTreeFeed?.apply {
|
||||
tree = snapshot
|
||||
subscriptionTree = updates.subscribe({
|
||||
remapIndices(it)
|
||||
tree = it
|
||||
draw(true)
|
||||
}, { done(it) }, { done(null) })
|
||||
@ -92,7 +93,15 @@ abstract class ANSIProgressRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun remapIndices(newTree: List<Pair<Int, String>>) {
|
||||
val newIndices = newTree.filter {
|
||||
treeIndexProcessed.contains(tree.indexOf(it))
|
||||
}.map {
|
||||
newTree.indexOf(it)
|
||||
}.toMutableSet()
|
||||
treeIndex = newIndices.max() ?: 0
|
||||
treeIndexProcessed = if (newIndices.isNotEmpty()) newIndices else mutableSetOf(0)
|
||||
}
|
||||
|
||||
@Synchronized protected fun draw(moveUp: Boolean, error: Throwable? = null) {
|
||||
if (!usingANSI) {
|
||||
|
@ -1,8 +1,6 @@
|
||||
package net.corda.tools.shell.utilities
|
||||
|
||||
import com.nhaarman.mockito_kotlin.argumentCaptor
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.nhaarman.mockito_kotlin.verify
|
||||
import com.nhaarman.mockito_kotlin.*
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.internal.concurrent.openFuture
|
||||
import net.corda.core.messaging.DataFeed
|
||||
@ -28,38 +26,68 @@ class ANSIProgressRendererTest {
|
||||
private const val STEP_1_LABEL = "Running step 1"
|
||||
private const val STEP_2_LABEL = "Running step 2"
|
||||
private const val STEP_3_LABEL = "Running step 3"
|
||||
private const val STEP_4_LABEL = "Running step 4"
|
||||
private const val STEP_5_LABEL = "Running step 5"
|
||||
|
||||
private val STEP_1_SUCCESS_OUTPUT = if (SystemUtils.IS_OS_WINDOWS) """DONE: $STEP_1_LABEL""" else """✓ $STEP_1_LABEL"""
|
||||
private const val STEP_2_SKIPPED_OUTPUT = """ $INTENSITY_FAINT_ON_ASCII$STEP_2_LABEL$INTENSITY_OFF_ASCII"""
|
||||
private val STEP_3_ACTIVE_OUTPUT = if (SystemUtils.IS_OS_WINDOWS) """CURRENT: $INTENSITY_BOLD_ON_ASCII$STEP_3_LABEL$INTENSITY_OFF_ASCII""" else """▶︎ $INTENSITY_BOLD_ON_ASCII$STEP_3_LABEL$INTENSITY_OFF_ASCII"""
|
||||
fun stepSuccess(stepLabel: String): String {
|
||||
return if (SystemUtils.IS_OS_WINDOWS) """DONE: $stepLabel""" else """✓ $stepLabel"""
|
||||
}
|
||||
|
||||
fun stepSkipped(stepLabel: String): String {
|
||||
return """ $INTENSITY_FAINT_ON_ASCII$stepLabel$INTENSITY_OFF_ASCII"""
|
||||
}
|
||||
|
||||
fun stepActive(stepLabel: String): String {
|
||||
return if (SystemUtils.IS_OS_WINDOWS) """CURRENT: $INTENSITY_BOLD_ON_ASCII$stepLabel$INTENSITY_OFF_ASCII""" else """▶︎ $INTENSITY_BOLD_ON_ASCII$stepLabel$INTENSITY_OFF_ASCII"""
|
||||
}
|
||||
}
|
||||
|
||||
lateinit var printWriter: RenderPrintWriter
|
||||
lateinit var progressRenderer: ANSIProgressRenderer
|
||||
lateinit var indexSubject: PublishSubject<Int>
|
||||
lateinit var feedSubject: PublishSubject<List<Pair<Int, String>>>
|
||||
lateinit var flowProgressHandle: FlowProgressHandleImpl<*>
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
printWriter = mock()
|
||||
progressRenderer = CRaSHANSIProgressRenderer(printWriter)
|
||||
indexSubject = PublishSubject.create<Int>()
|
||||
feedSubject = PublishSubject.create<List<Pair<Int, String>>>()
|
||||
val stepsTreeIndexFeed = DataFeed<Int, Int>(0, indexSubject)
|
||||
val stepsTreeFeed = DataFeed<List<Pair<Int, String>>, List<Pair<Int, String>>>(listOf(), feedSubject)
|
||||
flowProgressHandle = FlowProgressHandleImpl(StateMachineRunId.createRandom(), openFuture<String>(), Observable.empty(), stepsTreeIndexFeed, stepsTreeFeed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test that steps are rendered appropriately depending on their status`() {
|
||||
val indexSubject = PublishSubject.create<Int>()
|
||||
val feedSubject = PublishSubject.create<List<Pair<Int, String>>>()
|
||||
val stepsTreeIndexFeed = DataFeed<Int, Int>(0, indexSubject)
|
||||
val stepsTreeFeed = DataFeed<List<Pair<Int, String>>, List<Pair<Int, String>>>(listOf(), feedSubject)
|
||||
val flowProgressHandle = FlowProgressHandleImpl(StateMachineRunId.createRandom(), openFuture<String>(), Observable.empty(), stepsTreeIndexFeed, stepsTreeFeed)
|
||||
|
||||
progressRenderer.render(flowProgressHandle)
|
||||
feedSubject.onNext(listOf(Pair(0, STEP_1_LABEL), Pair(0, STEP_2_LABEL), Pair(0, STEP_3_LABEL)))
|
||||
// The flow is currently at step 3, while step 1 has been completed and step 2 has been skipped.
|
||||
indexSubject.onNext(2)
|
||||
feedSubject.onNext(listOf(Pair(0, STEP_1_LABEL), Pair(0, STEP_2_LABEL), Pair(0, STEP_3_LABEL)))
|
||||
|
||||
val captor = argumentCaptor<Ansi>()
|
||||
verify(printWriter).print(captor.capture())
|
||||
assertThat(captor.firstValue.toString()).containsSequence(STEP_1_SUCCESS_OUTPUT, STEP_2_SKIPPED_OUTPUT, STEP_3_ACTIVE_OUTPUT)
|
||||
verify(printWriter).flush()
|
||||
verify(printWriter, times(2)).print(captor.capture())
|
||||
assertThat(captor.secondValue.toString()).containsSequence(stepSuccess(STEP_1_LABEL), stepSkipped(STEP_2_LABEL), stepActive(STEP_3_LABEL))
|
||||
verify(printWriter, times(2)).flush()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `changing tree causes correct steps to be marked as done`() {
|
||||
progressRenderer.render(flowProgressHandle)
|
||||
feedSubject.onNext(listOf(Pair(0, STEP_1_LABEL), Pair(1, STEP_2_LABEL), Pair(1, STEP_3_LABEL), Pair(0, STEP_4_LABEL), Pair(0, STEP_5_LABEL)))
|
||||
indexSubject.onNext(1)
|
||||
indexSubject.onNext(2)
|
||||
|
||||
val captor = argumentCaptor<Ansi>()
|
||||
verify(printWriter, times(3)).print(captor.capture())
|
||||
assertThat(captor.lastValue.toString()).containsSequence(stepSuccess(STEP_1_LABEL), stepSuccess(STEP_2_LABEL), stepActive(STEP_3_LABEL))
|
||||
verify(printWriter, times(3)).flush()
|
||||
|
||||
feedSubject.onNext(listOf(Pair(0, STEP_1_LABEL), Pair(0, STEP_4_LABEL), Pair(0, STEP_5_LABEL)))
|
||||
verify(printWriter, times(4)).print(captor.capture())
|
||||
assertThat(captor.lastValue.toString()).containsSequence(stepActive(STEP_1_LABEL))
|
||||
assertThat(captor.lastValue.toString()).doesNotContain(stepActive(STEP_5_LABEL))
|
||||
verify(printWriter, times(4)).flush()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user