Generate tests be test data for sequence traces

This commit is contained in:
Vitaliy.Bibaev
2018-06-07 20:26:36 +03:00
committed by Yan Zhulanow
parent c0c344210a
commit 44b736e846
14 changed files with 753 additions and 213 deletions
@@ -78,6 +78,7 @@ import org.jetbrains.kotlin.idea.conversion.copy.AbstractTextJavaToKotlinCopyPas
import org.jetbrains.kotlin.idea.coverage.AbstractKotlinCoverageOutputFilesTest
import org.jetbrains.kotlin.idea.debugger.*
import org.jetbrains.kotlin.idea.debugger.evaluate.*
import org.jetbrains.kotlin.idea.debugger.sequence.exec.AbstractSequenceTraceTestCase
import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToDecompiledLibraryTest
import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest
@@ -645,6 +646,17 @@ fun main(args: Array<String>) {
model("debugger/fileRanking")
}
testClass<AbstractSequenceTraceTestCase> {
model("debugger/tinyApp/src/sequence/append", testMethod = "doTest")
model("debugger/tinyApp/src/sequence/distinct", testMethod = "doTest")
model("debugger/tinyApp/src/sequence/filter", testMethod = "doTest")
model("debugger/tinyApp/src/sequence/flatMap", testMethod = "doTest")
model("debugger/tinyApp/src/sequence/map", testMethod = "doTest")
model("debugger/tinyApp/src/sequence/misc", testMethod = "doTest")
model("debugger/tinyApp/src/sequence/sort", testMethod = "doTest")
// model("debugger/tinyApp/src/sequence/terminal", testMethod = "doTest") We need to implement mapping logic
}
testClass<AbstractStubBuilderTest> {
model("stubs", extension = "kt")
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.debugger.sequence.exec
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import org.jetbrains.kotlin.idea.debugger.sequence.lib.sequence.KotlinSequenceSupportProvider
/**
* @author Vitaliy.Bibaev
*/
abstract class AbstractSequenceTraceTestCase : KotlinTraceTestCase() {
override val librarySupportProvider: LibrarySupportProvider = KotlinSequenceSupportProvider()
}
@@ -0,0 +1,199 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.debugger.sequence.exec
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.impl.OutputChecker
import com.intellij.debugger.streams.lib.LibrarySupportProvider
import com.intellij.debugger.streams.psi.DebuggerPositionResolver
import com.intellij.debugger.streams.psi.impl.DebuggerPositionResolverImpl
import com.intellij.debugger.streams.trace.*
import com.intellij.debugger.streams.trace.impl.TraceResultInterpreterImpl
import com.intellij.debugger.streams.wrapper.StreamChain
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import com.intellij.execution.ExecutionException
import com.intellij.execution.process.ProcessOutputTypes
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Computable
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.util.indexing.FileBasedIndex
import com.intellij.xdebugger.XDebugSessionListener
import com.sun.jdi.Value
import junit.framework.TestCase
import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerTestBase
import java.nio.file.Paths
import java.util.concurrent.atomic.AtomicBoolean
/**
* @author Vitaliy.Bibaev
*/
abstract class KotlinTraceTestCase : KotlinDebuggerTestBase() {
private companion object {
val DEFAULT_CHAIN_SELECTOR = ChainSelector.byIndex(0)
}
private lateinit var traceChecker: StreamTraceChecker
override fun initOutputChecker(): OutputChecker {
traceChecker = StreamTraceChecker(this)
return super.initOutputChecker()
}
abstract val librarySupportProvider: LibrarySupportProvider
fun doTest(filePath: String) = doTestImpl(filePath)
override fun createDebugProcess(path: String) {
val filePath = Paths.get(path);
FileBasedIndex.getInstance().requestReindex(VfsUtil.findFileByIoFile(filePath.toFile(), true)!!)
val fileName = filePath.getName(filePath.nameCount - 1).toString()
val packageName = filePath.getName(filePath.nameCount - 2).toString()
createLocalProcess("$packageName.${fileName.replace(".kt", "Kt")}")
}
@Throws(ExecutionException::class)
private fun doTestImpl(path: String, chainSelector: ChainSelector = DEFAULT_CHAIN_SELECTOR) {
createDebugProcess(path)
val session = debuggerSession.xDebugSession ?: kotlin.test.fail("XDebugSession is null")
TestCase.assertNotNull(session)
val completed = AtomicBoolean(false)
val positionResolver = getPositionResolver()
val chainBuilder = getChainBuilder()
val resultInterpreter = getResultInterpreter()
val expressionBuilder = getExpressionBuilder()
session.addSessionListener(object : XDebugSessionListener {
override fun sessionPaused() {
if (completed.getAndSet(true)) {
resume()
return
}
try {
sessionPausedImpl()
} catch (t: Throwable) {
println("Exception caught: " + t + ", " + t.message, ProcessOutputTypes.SYSTEM)
t.printStackTrace()
resume()
}
}
private fun sessionPausedImpl() {
printContext(debugProcess.debuggerContext)
val chain = ApplicationManager.getApplication().runReadAction(
Computable<StreamChain> {
val elementAtBreakpoint = positionResolver.getNearestElementToBreakpoint(session)
val chains = if (elementAtBreakpoint == null) null else chainBuilder.build(elementAtBreakpoint)
if (chains == null || chains.isEmpty()) null else chainSelector.select(chains)
})
if (chain == null) {
complete(null, null, null, FailureReason.CHAIN_CONSTRUCTION)
return
}
EvaluateExpressionTracer(session, expressionBuilder, resultInterpreter).trace(chain, object : TracingCallback {
override fun evaluated(result: TracingResult, context: EvaluationContextImpl) {
complete(chain, result, null, null)
}
override fun evaluationFailed(traceExpression: String, message: String) {
complete(chain, null, message, FailureReason.EVALUATION)
}
override fun compilationFailed(traceExpression: String, message: String) {
complete(chain, null, message, FailureReason.COMPILATION)
}
})
}
private fun complete(
chain: StreamChain?,
result: TracingResult?,
error: String?,
errorReason: FailureReason?
) {
try {
if (error != null) {
TestCase.assertNotNull(errorReason)
TestCase.assertNotNull(chain)
handleError(chain!!, error, errorReason!!)
} else {
TestCase.assertNull(errorReason)
handleSuccess(chain, result)
}
} catch (t: Throwable) {
println("Exception caught: " + t + ", " + t.message, ProcessOutputTypes.SYSTEM)
} finally {
resume()
}
}
private fun resume() {
ApplicationManager.getApplication().invokeLater { session.resume() }
}
}, testRootDisposable)
}
protected fun getPositionResolver(): DebuggerPositionResolver {
return DebuggerPositionResolverImpl()
}
protected fun handleError(chain: StreamChain, error: String, reason: FailureReason) {
TestCase.fail(error)
}
protected fun handleSuccess(chain: StreamChain?, result: TracingResult?) {
TestCase.assertNotNull(chain)
TestCase.assertNotNull(result)
println(chain!!.text, ProcessOutputTypes.SYSTEM)
val resultValue = result!!.result
handleResultValue(resultValue.value)
val trace = result.trace
traceChecker.checkChain(trace)
val resolvedTrace = result.resolve(librarySupportProvider.librarySupport.resolverFactory)
traceChecker.checkResolvedChain(resolvedTrace)
}
protected fun handleResultValue(result: Value?) {
}
private fun getResultInterpreter(): TraceResultInterpreter {
return TraceResultInterpreterImpl(librarySupportProvider.librarySupport.interpreterFactory)
}
private fun getChainBuilder(): StreamChainBuilder {
return librarySupportProvider.chainBuilder
}
private fun getExpressionBuilder(): TraceExpressionBuilder {
return librarySupportProvider.getExpressionBuilder(project)
}
protected enum class FailureReason {
COMPILATION, EVALUATION, CHAIN_CONSTRUCTION
}
@FunctionalInterface
protected interface ChainSelector {
fun select(chains: List<StreamChain>): StreamChain
companion object {
fun byIndex(index: Int): ChainSelector {
return object : ChainSelector {
override fun select(chains: List<StreamChain>): StreamChain = chains.get(index)
}
}
}
}
}
@@ -0,0 +1,347 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.debugger.sequence.exec;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class SequenceTraceTestCaseGenerated extends AbstractSequenceTraceTestCase {
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/append")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Append extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInAppend() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/append"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("PlusArray.kt")
public void testPlusArray() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/append/PlusArray.kt");
}
@TestMetadata("PlusElement.kt")
public void testPlusElement() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/append/PlusElement.kt");
}
@TestMetadata("PlusSequence.kt")
public void testPlusSequence() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/append/PlusSequence.kt");
}
@TestMetadata("PlusSingle.kt")
public void testPlusSingle() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/append/PlusSingle.kt");
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/distinct")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Distinct extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInDistinct() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/distinct"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Distinct.kt")
public void testDistinct() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/Distinct.kt");
}
@TestMetadata("DistinctBy.kt")
public void testDistinctBy() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/DistinctBy.kt");
}
@TestMetadata("DistinctByBigPrimitives.kt")
public void testDistinctByBigPrimitives() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/DistinctByBigPrimitives.kt");
}
@TestMetadata("DistinctByNullableElement.kt")
public void testDistinctByNullableElement() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/DistinctByNullableElement.kt");
}
@TestMetadata("DistinctByNullableKey.kt")
public void testDistinctByNullableKey() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/DistinctByNullableKey.kt");
}
@TestMetadata("DistinctByNullableKeyAndElement.kt")
public void testDistinctByNullableKeyAndElement() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/DistinctByNullableKeyAndElement.kt");
}
@TestMetadata("DistinctObjects.kt")
public void testDistinctObjects() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/distinct/DistinctObjects.kt");
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/filter")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Filter extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFilter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/filter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Drop.kt")
public void testDrop() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/Drop.kt");
}
@TestMetadata("DropWhile.kt")
public void testDropWhile() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/DropWhile.kt");
}
@TestMetadata("Filter.kt")
public void testFilter() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/Filter.kt");
}
@TestMetadata("FilterIndexed.kt")
public void testFilterIndexed() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/FilterIndexed.kt");
}
@TestMetadata("FilterIsInstance.kt")
public void testFilterIsInstance() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/FilterIsInstance.kt");
}
@TestMetadata("FilterNot.kt")
public void testFilterNot() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/FilterNot.kt");
}
@TestMetadata("Minus.kt")
public void testMinus() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/Minus.kt");
}
@TestMetadata("MinusElement.kt")
public void testMinusElement() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/MinusElement.kt");
}
@TestMetadata("Take.kt")
public void testTake() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/Take.kt");
}
@TestMetadata("TakeWhile.kt")
public void testTakeWhile() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/filter/TakeWhile.kt");
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/flatMap")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class FlatMap extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFlatMap() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/flatMap"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("FlatMap.kt")
public void testFlatMap() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/flatMap/FlatMap.kt");
}
@TestMetadata("Flatten.kt")
public void testFlatten() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/flatMap/Flatten.kt");
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/map")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Map extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInMap() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/map"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Map.kt")
public void testMap() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/map/Map.kt");
}
@TestMetadata("MapIndexed.kt")
public void testMapIndexed() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/map/MapIndexed.kt");
}
@TestMetadata("MapNotNull.kt")
public void testMapNotNull() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/map/MapNotNull.kt");
}
@TestMetadata("WithIndex.kt")
public void testWithIndex() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/map/WithIndex.kt");
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/misc")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Misc extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInMisc() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/misc"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("AsSequence.kt")
public void testAsSequence() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/AsSequence.kt");
}
@TestMetadata("Chunked.kt")
public void testChunked() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/Chunked.kt");
}
@TestMetadata("ChunkedWithTransform.kt")
public void testChunkedWithTransform() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ChunkedWithTransform.kt");
}
@TestMetadata("ConstrainOnce.kt")
public void testConstrainOnce() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ConstrainOnce.kt");
}
@TestMetadata("OnEach.kt")
public void testOnEach() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/OnEach.kt");
}
@TestMetadata("RequireNoNulls.kt")
public void testRequireNoNulls() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/RequireNoNulls.kt");
}
@TestMetadata("Windowed.kt")
public void testWindowed() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/Windowed.kt");
}
@TestMetadata("WindowedWithBigStep.kt")
public void testWindowedWithBigStep() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/WindowedWithBigStep.kt");
}
@TestMetadata("WindowedWithPartial.kt")
public void testWindowedWithPartial() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/WindowedWithPartial.kt");
}
@TestMetadata("WindowedWithStep.kt")
public void testWindowedWithStep() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/WindowedWithStep.kt");
}
@TestMetadata("ZipWithGreater.kt")
public void testZipWithGreater() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ZipWithGreater.kt");
}
@TestMetadata("ZipWithLesser.kt")
public void testZipWithLesser() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ZipWithLesser.kt");
}
@TestMetadata("ZipWithNextMany.kt")
public void testZipWithNextMany() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ZipWithNextMany.kt");
}
@TestMetadata("ZipWithNextSingle.kt")
public void testZipWithNextSingle() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ZipWithNextSingle.kt");
}
@TestMetadata("ZipWithSame.kt")
public void testZipWithSame() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/misc/ZipWithSame.kt");
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/sequence/sort")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Sort extends AbstractSequenceTraceTestCase {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInSort() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/sequence/sort"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("Sorted.kt")
public void testSorted() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/sort/Sorted.kt");
}
@TestMetadata("SortedBy.kt")
public void testSortedBy() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/sort/SortedBy.kt");
}
@TestMetadata("SortedByDescending.kt")
public void testSortedByDescending() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/sort/SortedByDescending.kt");
}
@TestMetadata("SortedDescending.kt")
public void testSortedDescending() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/sort/SortedDescending.kt");
}
@TestMetadata("SortedWith.kt")
public void testSortedWith() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/sequence/sort/SortedWith.kt");
}
}
}
@@ -0,0 +1,179 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.debugger.sequence.exec
import com.intellij.debugger.streams.resolve.ResolvedStreamCall
import com.intellij.debugger.streams.resolve.ResolvedStreamChain
import com.intellij.debugger.streams.trace.*
import com.intellij.execution.ExecutionTestCase
import com.intellij.execution.process.ProcessOutputTypes
import com.intellij.testFramework.UsefulTestCase
import junit.framework.TestCase
import one.util.streamex.StreamEx
import java.util.*
/**
* @author Vitaliy.Bibaev
*/
class StreamTraceChecker(private val testCase: ExecutionTestCase) {
fun checkChain(trace: List<TraceInfo>) {
for (info in trace) {
val name = info.call.name
println(name)
print(" before: ")
val before = info.valuesOrderBefore
println(traceToString(before.values))
print(" after: ")
val after = info.valuesOrderAfter
println(traceToString(after.values))
}
}
fun checkResolvedChain(result: ResolvedTracingResult) {
val resolvedChain = result.resolvedChain
checkChain(resolvedChain)
checkTracesIsCorrectInBothDirections(resolvedChain)
val terminator = resolvedChain.terminator
resolvedChain.intermediateCalls.forEach { x -> printBeforeAndAfterValues(x.stateBefore, x.stateAfter) }
printBeforeAndAfterValues(terminator.stateBefore, terminator.stateAfter)
}
private fun printBeforeAndAfterValues(before: NextAwareState?, after: PrevAwareState?) {
TestCase.assertFalse(before == null && after == null)
val call = before?.nextCall ?: after!!.prevCall
TestCase.assertNotNull(call)
println("mappings for " + call!!.name)
println(" direct:")
if (before != null) {
printMapping(before.trace, { before.getNextValues(it) }, Direction.FORWARD)
} else {
println(" no")
}
println(" reverse:")
if (after != null) {
printMapping(after.trace, { after.getPrevValues(it) }, Direction.BACKWARD)
} else {
println(" not found")
}
}
private fun printMapping(
values: List<TraceElement>,
mapper: (TraceElement) -> List<TraceElement>,
direction: Direction
) {
if (values.isEmpty()) {
println(" empty")
}
for (element in values) {
val mappedValues = mapper(element)
val mapped = traceToString(mappedValues)
val line = if (Direction.FORWARD == direction) element.time.toString() + " -> " + mapped else mapped + " <- " + element.time
println(" $line")
}
}
private enum class Direction {
FORWARD, BACKWARD
}
private fun checkChain(chain: ResolvedStreamChain) {
val intermediates = chain.intermediateCalls
val terminator = chain.terminator
if (intermediates.isEmpty()) {
TestCase.assertFalse(terminator.stateBefore is PrevAwareState)
}
checkIntermediates(chain.intermediateCalls)
TestCase.assertEquals(terminator.call.name, terminator.stateBefore.nextCall.name)
val after = terminator.stateAfter
if (after != null) {
val terminatorCall = after.prevCall
TestCase.assertNotNull(terminatorCall)
TestCase.assertEquals(terminator.call.name, terminatorCall!!.name)
}
if (!intermediates.isEmpty()) {
val lastIntermediate = intermediates[intermediates.size - 1]
val stateAfterIntermediates = lastIntermediate.stateAfter
UsefulTestCase.assertInstanceOf(stateAfterIntermediates, NextAwareState::class.java)
TestCase.assertEquals(terminator.call.name, (stateAfterIntermediates as NextAwareState).nextCall.name)
}
}
private fun checkIntermediates(intermediates: List<ResolvedStreamCall.Intermediate>) {
for (i in 0 until intermediates.size - 1) {
val prev = intermediates[i]
val next = intermediates[i + 1]
TestCase.assertSame(prev.stateAfter, next.stateBefore)
val prevCall = prev.stateAfter.prevCall
TestCase.assertNotNull(prevCall)
TestCase.assertEquals(prev.call.name, prevCall!!.name)
TestCase.assertEquals(next.call.name, next.stateBefore.nextCall.name)
}
}
private fun checkTracesIsCorrectInBothDirections(resolvedChain: ResolvedStreamChain) {
for (intermediate in resolvedChain.intermediateCalls) {
checkNeighborTraces(intermediate.stateBefore, intermediate.stateAfter)
}
val terminator = resolvedChain.terminator
val after = terminator.stateAfter
if (after != null) {
checkNeighborTraces(terminator.stateBefore, after)
}
}
private fun checkNeighborTraces(left: NextAwareState, right: PrevAwareState) {
val leftValues = HashSet(left.trace)
val rightValues = HashSet(right.trace)
checkThatMappingsIsCorrect(
leftValues,
rightValues,
{ left.getNextValues(it) },
{ right.getPrevValues(it) })
checkThatMappingsIsCorrect(
rightValues,
leftValues,
{ right.getPrevValues(it) },
{ left.getNextValues(it) })
}
private fun checkThatMappingsIsCorrect(
prev: Set<TraceElement>,
next: Set<TraceElement>,
toNext: (TraceElement) -> List<TraceElement>,
toPrev: (TraceElement) -> List<TraceElement>
) {
for (leftElement in prev) {
val mapToRight = toNext.invoke(leftElement)
for (rightElement in mapToRight) {
TestCase.assertTrue(next.contains(rightElement))
TestCase.assertTrue(toPrev.invoke(rightElement).contains(leftElement))
}
}
}
private fun traceToString(trace: Collection<TraceElement>): String {
return replaceIfEmpty(StreamEx.of(trace).map<Int>({ it.time }).sorted().joining(","))
}
private fun replaceIfEmpty(str: String): String {
return if (str.isEmpty()) "nothing" else str
}
private fun println(msg: String) = testCase.println(msg, ProcessOutputTypes.SYSTEM)
private fun print(msg: String) = testCase.print(msg, ProcessOutputTypes.SYSTEM)
}
@@ -1,13 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
/**
* @author Vitaliy.Bibaev
*/
class AppendOperationsTest : OperationsTestCase("append") {
fun testPlusSingle() = doTestWithResult()
fun testPlusArray() = doTestWithResult()
fun testPlusSequence() = doTestWithResult()
fun testPlusElement() = doTestWithResult()
}
@@ -1,16 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
/**
* @author Vitaliy.Bibaev
*/
class DistinctOperationsTest : OperationsTestCase("distinct") {
fun testDistinct() = doTestWithResult()
fun testDistinctObjects() = doTestWithResult()
fun testDistinctBy() = doTestWithResult()
fun testDistinctByNullableElement() = doTestWithResult()
fun testDistinctByNullableKey() = doTestWithResult()
fun testDistinctByNullableKeyAndElement() = doTestWithResult()
fun testDistinctByBigPrimitives() = doTestWithResult()
}
@@ -1,18 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
class FilterOperationsTest : OperationsTestCase("filter") {
fun testFilter() = doTestWithResult()
fun testFilterNot() = doTestWithResult()
fun testFilterIndexed() = doTestWithResult()
fun testFilterIsInstance() = doTestWithoutResult()
fun testDrop() = doTestWithResult()
fun testDropWhile() = doTestWithoutResult()
fun testMinus() = doTestWithResult()
fun testMinusElement() = doTestWithResult()
fun testTake() = doTestWithResult()
fun testTakeWhile() = doTestWithoutResult()
}
@@ -1,10 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
/**
* @author Vitaliy.Bibaev
*/
class FlatMapOperationsTest : OperationsTestCase("flatMap") {
fun testFlatMap() = doTestWithResult()
fun testFlatten() = doTestWithResult()
}
@@ -1,12 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
/**
* @author Vitaliy.Bibaev
*/
class MappingOperationsTest : OperationsTestCase("map") {
fun testMap() = doTestWithResult()
fun testMapNotNull() = doTestWithResult()
fun testMapIndexed() = doTestWithResult()
fun testWithIndex() = doTestWithoutResult()
}
@@ -1,30 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
/**
* @author Vitaliy.Bibaev
*/
class MiscOperationsTest : OperationsTestCase("misc") {
fun testConstrainOnce() = doTestWithResult()
fun testRequireNoNulls() = doTestWithResult()
fun testOnEach() = doTestWithResult()
fun testZipWithSame() = doTestWithResult()
fun testZipWithGreater() = doTestWithResult()
fun testZipWithLesser() = doTestWithResult()
fun testZipWithNextSingle() = doTestWithResult()
fun testZipWithNextMany() = doTestWithResult()
fun testChunked() = doTestWithResult()
fun testChunkedWithTransform() = doTestWithResult()
fun testWindowed() = doTestWithResult()
fun testWindowedWithPartial() = doTestWithResult()
fun testWindowedWithBigStep() = doTestWithResult()
fun testWindowedWithStep() = doTestWithResult()
fun testAsSequence() = doTestWithResult()
}
@@ -1,16 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.exec.KotlinTraceEvaluationTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.lib.sequence.KotlinSequenceSupportProvider
import com.intellij.debugger.streams.lib.LibrarySupportProvider
abstract class OperationsTestCase(private val packageName: String) : KotlinTraceEvaluationTestCase() {
override val appName: String = "sequence"
override val librarySupport: LibrarySupportProvider = KotlinSequenceSupportProvider()
protected fun doTestWithResult() = doTest(false, fullyQualifiedClassName())
protected fun doTestWithoutResult() = doTest(true, fullyQualifiedClassName())
private fun fullyQualifiedClassName() = "$packageName.${getTestName(false)}"
}
@@ -1,15 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence.OperationsTestCase
/**
* @author Vitaliy.Bibaev
*/
class SortingOperationsTest : OperationsTestCase("sort") {
fun testSorted() = doTestWithResult()
fun testSortedBy() = doTestWithResult()
fun testSortedDescending() = doTestWithResult()
fun testSortedByDescending() = doTestWithResult()
fun testSortedWith() = doTestWithResult()
}
@@ -1,83 +0,0 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence
import org.jetbrains.kotlin.idea.debugger.sequence.exec.sequence.OperationsTestCase
/**
* @author Vitaliy.Bibaev
*/
class TerminalOperationsTest : OperationsTestCase("terminal") {
fun testAllTrue() = doTestWithResult()
fun testAllFalse() = doTestWithResult()
fun testAnyTrue() = doTestWithResult()
fun testAnyFalse() = doTestWithResult()
fun testAsIterable() = doTestWithResult()
fun testAssociate() = doTestWithResult()
fun testAssociateBy() = doTestWithResult()
fun testAverage() = doTestWithResult()
fun testCount() = doTestWithResult()
fun testElementAt() = doTestWithResult()
fun testElementAtOrElsePresent() = doTestWithResult()
fun testElementAtOrElseAbsent() = doTestWithResult()
fun testElementAtOrNull() = doTestWithResult()
fun testFindPresent() = doTestWithResult()
fun testFindAbsent() = doTestWithResult()
fun testFindLastPresent() = doTestWithResult()
fun testFindLastAbsent() = doTestWithResult()
fun testFirst() = doTestWithResult()
fun testFirstOrNullPresent() = doTestWithResult()
fun testFirstOrNullAbsent() = doTestWithResult()
fun testGroupingBy() = doTestWithResult()
fun testIndexOfPresent() = doTestWithResult()
fun testIndexOfAbsent() = doTestWithResult()
fun testIndexOfFirstPresent() = doTestWithResult()
fun testIndexOfFirstAbsent() = doTestWithResult()
fun testIndexOfLastPresent() = doTestWithResult()
fun testIndexOfLastAbsent() = doTestWithResult()
fun testLast() = doTestWithResult()
fun testLastIndexOf() = doTestWithResult()
fun testLastOrNullPresent() = doTestWithResult()
fun testLastOrNullAbsent() = doTestWithResult()
fun testMaxPresent() = doTestWithResult()
fun testMaxAbsent() = doTestWithResult()
fun testMaxBy() = doTestWithResult()
fun testMaxWith() = doTestWithResult()
fun testMinPresent() = doTestWithResult()
fun testMinAbsent() = doTestWithResult()
fun testMinBy() = doTestWithResult()
fun testMinWith() = doTestWithResult()
fun testNonePresent() = doTestWithResult()
fun testNoneAbsent() = doTestWithResult()
fun testPartition() = doTestWithResult()
fun testSingle() = doTestWithResult()
fun testSingleOrNullPresent() = doTestWithResult()
fun testSingleOrNullAbsent() = doTestWithResult()
fun testToCollection() = doTestWithResult()
fun testToHashSet() = doTestWithResult()
fun testToMutableSet() = doTestWithResult()
fun testToList() = doTestWithResult()
fun testToMutableList() = doTestWithResult()
fun testToSet() = doTestWithResult()
fun testToSortedSet() = doTestWithResult()
}