diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 3af2fb0c9df..02eb1567219 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -1281,6 +1281,10 @@ fun main(args: Array) { model("copyPaste/conversion", testMethod = "doPerfTest", pattern = """^([^\.]+)\.java$""") } + testClass { + model("copyPaste/literal", testMethod = "doPerfTest", pattern = """^([^\.]+)\.kt$""") + } + testClass { model("highlighter", testMethod = "doPerfTest") } diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 index 1f4d76382ce..b6d0b8c601a 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.183 @@ -111,6 +111,7 @@ import org.jetbrains.kotlin.idea.maven.AbstractKotlinMavenInspectionTest import org.jetbrains.kotlin.idea.maven.configuration.AbstractMavenConfigureProjectByChangingFileTest import org.jetbrains.kotlin.idea.navigation.* import org.jetbrains.kotlin.idea.parameterInfo.AbstractParameterInfoTest +import org.jetbrains.kotlin.idea.perf.* import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiFileTest import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixMultiModuleTest import org.jetbrains.kotlin.idea.quickfix.AbstractQuickFixTest @@ -1210,6 +1211,52 @@ fun main(args: Array) { } } + testGroup("idea/performanceTests", "idea/testData") { + testClass { + model("copyPaste/conversion", testMethod = "doPerfTest", pattern = """^([^\.]+)\.java$""") + } + + testClass { + model("copyPaste/conversion", testMethod = "doPerfTest", pattern = """^([^\.]+)\.java$""") + } + + testClass { + model("copyPaste/literal", testMethod = "doPerfTest", pattern = """^([^\.]+)\.kt$""") + } + + testClass { + model("highlighter", testMethod = "doPerfTest") + } + + testClass { + model("addImport", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME) + } + + + } + + testGroup("idea/performanceTests", "idea/idea-completion/testData") { + testClass { + model("incrementalResolve", testMethod = "doPerfTest") + } + + testClass { + model("handlers/basic", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME) + } + + testClass { + model("handlers/smart", testMethod = "doPerfTest") + } + + testClass { + model("handlers/keywords", testMethod = "doPerfTest") + } + + testClass { + model("handlers/charFilter", testMethod = "doPerfTest", pattern = KT_WITHOUT_DOTS_IN_NAME) + } + } +/* testGroup("plugins/android-extensions/android-extensions-idea/tests", "plugins/android-extensions/android-extensions-idea/testData") { testClass { model("android/completion", recursive = false, extension = null) diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceCompletionIncrementalResolveTest.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceCompletionIncrementalResolveTest.kt index b66d730a927..826d5a168f6 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceCompletionIncrementalResolveTest.kt +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceCompletionIncrementalResolveTest.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.util.text.StringUtil import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.completion.CompletionBindingContextProvider +import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments @@ -56,7 +57,7 @@ abstract class AbstractPerformanceCompletionIncrementalResolveTest : KotlinLight } private fun doWarmUpPerfTest() { - innerPerfTest("warm-up") { + innerPerfTest(WARM_UP) { myFixture.configureByText( KotlinFileType.INSTANCE, "class Foo {\n private val value: String? = n\n}" diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceHighlightingTest.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceHighlightingTest.kt index 8156a8bfcc1..32b4300a0d9 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceHighlightingTest.kt +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceHighlightingTest.kt @@ -9,6 +9,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.openapi.application.runWriteAction import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl.ensureIndexesUpToDate import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments @@ -45,7 +46,7 @@ abstract class AbstractPerformanceHighlightingTest : KotlinLightCodeInsightFixtu } private fun doWarmUpPerfTest() { - innerPerfTest("warm-up") { + innerPerfTest(WARM_UP) { myFixture.configureByText( KotlinFileType.INSTANCE, "class Foo {\n private val value: String? = null\n}" diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceJavaToKotlinCopyPasteConversionTest.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceJavaToKotlinCopyPasteConversionTest.kt index 857584c2661..c69ed1ee0ee 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceJavaToKotlinCopyPasteConversionTest.kt +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceJavaToKotlinCopyPasteConversionTest.kt @@ -12,6 +12,7 @@ import com.intellij.psi.PsiDocumentManager import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.conversion.copy.AbstractJavaToKotlinCopyPasteConversionTest import org.jetbrains.kotlin.idea.conversion.copy.ConvertJavaCopyPasteProcessor +import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP import org.jetbrains.kotlin.idea.testFramework.commitAllDocuments import org.jetbrains.kotlin.j2k.J2kConverterExtension import org.jetbrains.kotlin.test.InTextDirectivesUtils @@ -47,7 +48,7 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va private fun doWarmUpPerfTest() { stats().perfTest( - testName = "warm-up", + testName = WARM_UP, setUp = { with(myFixture) { configureByText(JavaFileType.INSTANCE, "public class Foo {\nprivate String value;\n}") @@ -105,6 +106,7 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va commitAllDocuments() validate(path, noConversionExpected) + // to avoid VFS refresh myFixture.performEditorAction(IdeActions.ACTION_UNDO) } ) diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest.kt new file mode 100644 index 00000000000..5375f9cb17a --- /dev/null +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.perf + +import com.intellij.openapi.actionSystem.IdeActions +import com.intellij.openapi.application.runWriteAction +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.idea.AbstractCopyPasteTest +import org.jetbrains.kotlin.idea.perf.Stats.Companion.WARM_UP +import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +/** + * Inspired by AbstractLiteralKotlinToKotlinCopyPasteTest + */ +abstract class AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest : AbstractCopyPasteTest() { + + companion object { + val BASE_PATH = PluginTestCaseBase.getTestDataPathBase() + "/copyPaste/literal" + + @JvmStatic + var warmedUp: Boolean = false + + @JvmStatic + val stats: Stats = Stats("Literal-k2k-CopyPaste") + + init { + // there is no @AfterClass for junit3.8 + Runtime.getRuntime().addShutdownHook(Thread(Runnable { stats.close() })) + } + } + + override fun getTestDataPath() = BASE_PATH + + override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE + + override fun setUp() { + super.setUp() + + if (!warmedUp) { + doWarmUpPerfTest() + warmedUp = true + } + } + + private fun doWarmUpPerfTest() { + val fileEditorManager = FileEditorManagerEx.getInstance(project) + stats.perfTest, Unit>( + testName = WARM_UP, + iterations = 1, + setUp = { + val file1 = myFixture.configureByText( + "src.kt", + "class Foo {\n private val value: String? = n\n}" + ) + val file2 = myFixture.configureByText("target.kt", "") + it.setUpValue = Pair(file1, file2) + }, + test = { + fileEditorManager.setSelectedEditor(it.setUpValue!!.first.virtualFile, "") + myFixture.performEditorAction(IdeActions.ACTION_COPY) + + fileEditorManager.setSelectedEditor(it.setUpValue!!.second.virtualFile, "") + myFixture.performEditorAction(IdeActions.ACTION_PASTE) + }, + tearDown = { + assertEquals("private val value: String? = n", it.setUpValue!!.second.text) + + // to avoid VFS refresh + myFixture.performEditorAction(IdeActions.ACTION_UNDO) + + runWriteAction { + it.setUpValue!!.first.delete() + it.setUpValue!!.second.delete() + } + } + ) + } + + fun doPerfTest(path: String) { + val testName = getTestName(false) + + val fileEditorManager = FileEditorManagerEx.getInstance(project) + stats.perfTest, Unit>( + testName = testName, + setUp = { + it.setUpValue = myFixture.configureByFiles("$testName.kt", "$testName.to.kt") + }, + test = { + fileEditorManager.setSelectedEditor(it.setUpValue!![0].virtualFile, "") + myFixture.performEditorAction(IdeActions.ACTION_COPY) + + fileEditorManager.setSelectedEditor(it.setUpValue!![1].virtualFile, "") + myFixture.performEditorAction(IdeActions.ACTION_PASTE) + }, + tearDown = { + KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".expected.kt")), it.setUpValue!![1].text) + + // to avoid VFS refresh + myFixture.performEditorAction(IdeActions.ACTION_UNDO) + + runWriteAction { + it.setUpValue!!.forEach { f -> f.delete() } + } + } + ) + } +} \ No newline at end of file diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceLiteralKotlinToKotlinCopyPasteTestGenerated.java b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceLiteralKotlinToKotlinCopyPasteTestGenerated.java new file mode 100644 index 00000000000..a835ee77839 --- /dev/null +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/PerformanceLiteralKotlinToKotlinCopyPasteTestGenerated.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.perf; + +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") +@TestMetadata("idea/testData/copyPaste/literal") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class PerformanceLiteralKotlinToKotlinCopyPasteTestGenerated extends AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doPerfTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInLiteral() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/copyPaste/literal"), Pattern.compile("^([^\\.]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("CollectionLiteralReference.kt") + public void testCollectionLiteralReference() throws Exception { + runTest("idea/testData/copyPaste/literal/CollectionLiteralReference.kt"); + } + + @TestMetadata("DontEscapeEntries.kt") + public void testDontEscapeEntries() throws Exception { + runTest("idea/testData/copyPaste/literal/DontEscapeEntries.kt"); + } + + @TestMetadata("DontEscapeEntries2.kt") + public void testDontEscapeEntries2() throws Exception { + runTest("idea/testData/copyPaste/literal/DontEscapeEntries2.kt"); + } + + @TestMetadata("DontEscapeThis.kt") + public void testDontEscapeThis() throws Exception { + runTest("idea/testData/copyPaste/literal/DontEscapeThis.kt"); + } + + @TestMetadata("DontUnescapeLiteralWIthCode.kt") + public void testDontUnescapeLiteralWIthCode() throws Exception { + runTest("idea/testData/copyPaste/literal/DontUnescapeLiteralWIthCode.kt"); + } + + @TestMetadata("UnescapeFullSelection.kt") + public void testUnescapeFullSelection() throws Exception { + runTest("idea/testData/copyPaste/literal/UnescapeFullSelection.kt"); + } +} diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/Stats.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/Stats.kt index 16edb6e7409..d77ba78636c 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/Stats.kt +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/Stats.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.perf import org.jetbrains.kotlin.idea.perf.WholeProjectPerformanceTest.Companion.nsToMs +import org.jetbrains.kotlin.idea.perf.profilers.async.DummyProfilerHandler import org.jetbrains.kotlin.idea.perf.profilers.async.ProfilerHandler import org.jetbrains.kotlin.idea.testFramework.logMessage import org.jetbrains.kotlin.util.PerformanceCounter @@ -26,8 +27,6 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " private val statsOutput: BufferedWriter - private val profilerHandler = ProfilerHandler.getInstance() - init { statsOutput = statsFile.bufferedWriter() @@ -121,15 +120,40 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " iterations: Int = 20, setUp: (TestData) -> Unit = { }, test: (TestData) -> Unit, - tearDown: (TestData) -> Unit = { } + tearDown: (TestData) -> Unit = { }, + profileEnabled: Boolean = false ) { - tcSuite(testName) { - warmUpPhase(warmUpIterations, testName, setUp, test, tearDown) - val statInfoArray = mainPhase(iterations, testName, setUp, test, tearDown) + val warmPhaseData = PhaseData( + iterations = warmUpIterations, + testName = testName, + setUp = setUp, + test = test, + tearDown = tearDown, + profileEnabled = profileEnabled + ) + val mainPhaseData = PhaseData( + iterations = iterations, + testName = testName, + setUp = setUp, + test = test, + tearDown = tearDown, + profileEnabled = profileEnabled + ) + val block = { + warmUpPhase(warmPhaseData) + val statInfoArray = mainPhase(mainPhaseData) assertEquals(iterations, statInfoArray.size) - appendTimings(testName, statInfoArray) + if (testName != WARM_UP) { + appendTimings(testName, statInfoArray) + } + } + + if (testName != WARM_UP) { + tcSuite(testName, block) + } else { + block() } } @@ -140,7 +164,7 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " ) { for (statInfoIndex in statInfoArray.withIndex()) { val attempt = statInfoIndex.index - val statInfo = statInfoIndex.value!! + val statInfo = statInfoIndex.value ?: continue val n = "$name: $prefix ${attemptFn(attempt)}" printTestStarted(n) val t = statInfo[ERROR_KEY] as? Throwable @@ -168,83 +192,67 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " append("$name: $prefix", statInfosArray) } - private fun mainPhase( - iterations: Int, - testName: String, - setUp: (TestData) -> Unit, - test: (TestData) -> Unit, - tearDown: (TestData) -> Unit - ): Array { - val statInfosArray = phase(testName, "", iterations, setUp, test, tearDown) + private fun warmUpPhase(phaseData: PhaseData) { + val warmUpStatInfosArray = phase(phaseData, WARM_UP) + + if (phaseData.testName != WARM_UP) { + printWarmUpTimings(phaseData.testName, warmUpStatInfosArray) + } + + warmUpStatInfosArray.filterNotNull().map { it[ERROR_KEY] as? Exception }.firstOrNull()?.let { throw it } + } + + private fun mainPhase(phaseData: PhaseData): Array { + val statInfosArray = phase(phaseData, "") // do not estimate stability for warm-up - if (!testName.contains(WARM_UP)) { + if (!phaseData.testName.contains(WARM_UP)) { val calcMean = calcMean(statInfosArray) val stabilityPercentage = round(calcMean.stdDev * 100.0 / calcMean.mean).toInt() - logMessage { "$testName stability is $stabilityPercentage %" } - check(stabilityPercentage <= 10) { "$testName is not stable: stability above $stabilityPercentage %" } + logMessage { "${phaseData.testName} stability is $stabilityPercentage %" } + check(stabilityPercentage <= 10) { "${phaseData.testName} is not stable: stability above $stabilityPercentage %" } } return statInfosArray } - private fun warmUpPhase( - warmUpIterations: Int, - testName: String, - setUp: (TestData) -> Unit, - test: (TestData) -> Unit, - tearDown: (TestData) -> Unit - ) { - val warmUpStatInfosArray = phase(testName, "warm-up", warmUpIterations, setUp, test, tearDown) + private fun phase(phaseData: PhaseData, phaseName: String): Array { + val statInfosArray = Array(phaseData.iterations) { null } + val testData = TestData(null, null) - printWarmUpTimings(testName, warmUpStatInfosArray) - - warmUpStatInfosArray.filterNotNull().map { it[ERROR_KEY] as? Exception }.firstOrNull()?.let { throw it } - } - - private fun phase( - namePrefix: String, - phaseName: String, - iterations: Int, - setUp: (TestData) -> Unit, - test: (TestData) -> Unit, - tearDown: (TestData) -> Unit - ): Array { - val statInfosArray = Array(iterations) { null } - val testData = TestData(null, null) - val profilerPath = pathToResource("profile/${plainname()}/") - check(with(File(profilerPath)) { exists() || mkdirs() }) { "unable to mkdirs $profilerPath for $namePrefix" } try { - for (attempt in 0 until iterations) { + for (attempt in 0 until phaseData.iterations) { testData.reset() triggerGC(attempt) - val setUpMillis = measureTimeMillis { - setUp(testData) - } + val phaseProfiler = createPhaseProfiler(phaseData, phaseName, attempt) + + val setUpMillis = measureTimeMillis { phaseData.setUp(testData) } logMessage { "setup took $setUpMillis ms" } + val valueMap = HashMap(2 * PerformanceCounter.numberOfCounters + 1) statInfosArray[attempt] = valueMap try { - val activityName = "$namePrefix-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt" - profilerHandler.startProfiling(activityName) + + phaseProfiler.start() valueMap[TEST_KEY] = measureNanoTime { - test(testData) + phaseData.test(testData) } - profilerHandler.stopProfiling(profilerPath, activityName) + phaseProfiler.stop() + PerformanceCounter.report { name, counter, nanos -> valueMap["counter \"$name\": count"] = counter.toLong() valueMap["counter \"$name\": time"] = nanos.nsToMs } } catch (t: Throwable) { - println("# error at $namePrefix #$attempt:") + println("# error at ${phaseData.testName} #$attempt:") t.printStackTrace() valueMap[ERROR_KEY] = t } finally { try { val tearDownMillis = measureTimeMillis { - tearDown(testData) + phaseData.tearDown(testData) } logMessage { "tearDown took $tearDownMillis ms" } } finally { @@ -253,12 +261,30 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " } } } catch (t: Throwable) { - println("error at $namePrefix:") - tcPrintErrors(namePrefix, listOf(t)) + println("error at ${phaseData.testName}:") + tcPrintErrors(phaseData.testName, listOf(t)) } return statInfosArray } + private fun createPhaseProfiler( + phaseData: PhaseData, + phaseName: String, + attempt: Int + ): PhaseProfiler { + val profilerHandler = if (phaseData.profileEnabled) ProfilerHandler.getInstance() else DummyProfilerHandler + + return if (profilerHandler != DummyProfilerHandler) { + val profilerPath = pathToResource("profile/${plainname()}/") + check(with(File(profilerPath)) { exists() || mkdirs() }) { "unable to mkdirs $profilerPath for ${phaseData.testName}" } + val activityName = "${phaseData.testName}-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt" + + ActualPhaseProfiler(activityName, profilerPath, profilerHandler) + } else { + dummyPhaseProfiler + } + } + private fun triggerGC(attempt: Int) { if (attempt > 0) { val ref = WeakReference(IntArray(32 * 1024)) @@ -287,6 +313,11 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " const val WARM_UP = "warm-up" + private val dummyPhaseProfiler = object : PhaseProfiler { + override fun start() {} + override fun stop() {} + } + inline fun runAndMeasure(note: String, block: () -> Unit) { val openProjectMillis = measureTimeMillis { block() @@ -354,8 +385,34 @@ class Stats(val name: String = "", val header: Array = arrayOf("Name", " } } } + + private interface PhaseProfiler { + fun start() + + fun stop() + } + + private class ActualPhaseProfiler(val activityName: String, val profilerPath: String, val profilerHandler: ProfilerHandler) : + PhaseProfiler { + override fun start() { + profilerHandler.startProfiling(activityName) + } + + override fun stop() { + profilerHandler.stopProfiling(profilerPath, activityName) + } + } } +data class PhaseData( + val iterations: Int, + val testName: String, + val setUp: (TestData) -> Unit, + val test: (TestData) -> Unit, + val tearDown: (TestData) -> Unit, + val profileEnabled: Boolean = false +) + data class TestData(var setUpValue: SV?, var value: TV?) { fun reset() { setUpValue = null