From 0eea0b7bda2bef1e88cc93e8b912f59443634ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Sodja?= Date: Fri, 8 Mar 2024 17:00:05 +0100 Subject: [PATCH 1/2] Start on IDEStarter --- gradle/libs.versions.toml | 2 +- subprojects/ide-provisioning/build.gradle.kts | 5 +- .../ide/studio/AndroidStudioProvider.java | 3 + .../kotlin/org/gradle/profiler/ide/RunIde.kt | 55 +++++++++++++++++++ .../kotlin/org/gradle/profiler/ide/Starter.kt | 15 +++++ 5 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt create mode 100644 subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/Starter.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 333ccb45..23fc2644 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ spock = "2.1-groovy-3.0" [libraries] commonIo = "commons-io:commons-io:2.11.0" -ideStarter = "com.jetbrains.intellij.tools:ide-starter-squashed:233.13135.103" +ideStarter = "com.jetbrains.intellij.tools:ide-starter-squashed:233.14475.28" toolingApi = "org.gradle:gradle-tooling-api:7.2" spock-core = { module = "org.spockframework:spock-core", version.ref = "spock" } diff --git a/subprojects/ide-provisioning/build.gradle.kts b/subprojects/ide-provisioning/build.gradle.kts index cc1388e4..7f8e99ef 100644 --- a/subprojects/ide-provisioning/build.gradle.kts +++ b/subprojects/ide-provisioning/build.gradle.kts @@ -1,15 +1,16 @@ plugins { id("profiler.embedded-library") id("profiler.publication") + kotlin("jvm") version "1.9.22" } description = "IDE provisioning capabilities for Gradle profiler" +repositories { } + dependencies { implementation(libs.ideStarter) { exclude(group = "io.ktor") - exclude(group = "com.jetbrains.infra") - exclude(group = "com.jetbrains.intellij.remoteDev") } testImplementation(libs.bundles.testDependencies) testImplementation(libs.commonIo) diff --git a/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java b/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java index 89a192db..058f5583 100644 --- a/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java +++ b/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java @@ -12,12 +12,15 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import static com.intellij.ide.starter.di.DiContainerKt.getDi; + public class AndroidStudioProvider implements IdeProvider { private final IdeArchiveExtractor ideArchiveExtractor = IdeArchiveExtractor.INSTANCE; private final HttpClient httpClient = HttpClient.INSTANCE; @Override public File provideIde(AndroidStudio ide, Path homeDir, Path downloadsDir) { + var v = getDi(); if (ide.getVersion().isEmpty()) { throw new IllegalArgumentException("Android Studio version must be specified"); } diff --git a/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt b/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt new file mode 100644 index 00000000..3a3fb5f0 --- /dev/null +++ b/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt @@ -0,0 +1,55 @@ +package org.gradle.profiler.ide + +import com.intellij.ide.starter.di.di +import com.intellij.ide.starter.ide.IdeDistributionFactory +import com.intellij.ide.starter.ide.IdeInstaller +import com.intellij.ide.starter.ide.IdeProductProvider +import com.intellij.ide.starter.ide.InstalledIde +import com.intellij.ide.starter.ide.installer.IdeInstallerFile +import com.intellij.ide.starter.models.IdeInfo +import com.intellij.ide.starter.models.TestCase +import com.intellij.ide.starter.path.GlobalPaths +import com.intellij.ide.starter.path.InstallerGlobalPaths +import com.intellij.ide.starter.project.LocalProjectInfo +import com.intellij.tools.ide.performanceTesting.commands.CommandChain +import com.intellij.tools.ide.performanceTesting.commands.exitApp +import com.intellij.tools.ide.performanceTesting.commands.importGradleProject +import java.nio.file.Path +import java.nio.file.Paths + +class RunIde { + + fun runIde(projectLocation: String, ideLocation: String) { + val testCase = TestCase( + IdeProductProvider.IC, + LocalProjectInfo(Paths.get(projectLocation)) + ) + val ideInfo = IdeInfo( + productCode = "IC", + version = "2021.2.2", + buildNumber = "212.5284.40", + executableFileName = "idea", + fullName = "IntelliJ IDEA Community", + platformPrefix = "idea", + getInstaller = { _ -> IdeLocalInstaller(Paths.get(ideLocation)) } + ) + val context = Starter.newContext("test", testCase) + .prepareProjectCleanImport() + + context.runIDE(commands = CommandChain().importGradleProject().exitApp()) + } + + class IdeLocalInstaller(private val installer: Path) : IdeInstaller { + override fun install(ideInfo: IdeInfo, includeRuntimeModuleRepository: Boolean): Pair { + val ideInstaller = IdeInstallerFile(installer, "locally-installed-ide") + val installDir = InstallerGlobalPaths() + .getCacheDirectoryFor("builds") / "${ideInfo.productCode}-${ideInstaller.buildNumber}" + FileUtils.deleteDirectory(installDir.toFile()) + FileUtils.copyDirectory(installer.toFile(), installDir.toFile()) + return Pair( + ideInstaller.buildNumber, + IdeDistributionFactory.installIDE(installDir.toFile(), ideInfo.executableFileName) + ) + } + } +} diff --git a/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/Starter.kt b/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/Starter.kt new file mode 100644 index 00000000..a7a1bcbe --- /dev/null +++ b/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/Starter.kt @@ -0,0 +1,15 @@ +package org.gradle.profiler.ide + +import com.intellij.ide.starter.ide.IDETestContext +import com.intellij.ide.starter.models.TestCase +import com.intellij.ide.starter.runner.TestContainer +import com.intellij.ide.starter.runner.TestContainerImpl + +object Starter { + fun newTestContainer(): TestContainer<*> { + return TestContainerImpl() + } + + fun newContext(testName: String, testCase: TestCase<*>, preserveSystemDir: Boolean = false): IDETestContext = + newTestContainer().initializeTestContext(testName = testName, testCase = testCase, preserveSystemDir = preserveSystemDir) +} From 495d0f3b4242094ebe4498c16bb2880042d6248c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Sodja?= Date: Fri, 8 Mar 2024 21:27:49 +0100 Subject: [PATCH 2/2] More progress --- .../profiler/studio/StudioGradleClient.java | 13 +++++- .../ide/studio/AndroidStudioProvider.java | 3 -- .../kotlin/org/gradle/profiler/ide/RunIde.kt | 42 +++++++++---------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/gradle/profiler/studio/StudioGradleClient.java b/src/main/java/org/gradle/profiler/studio/StudioGradleClient.java index 57fc69a3..b5bdd70b 100644 --- a/src/main/java/org/gradle/profiler/studio/StudioGradleClient.java +++ b/src/main/java/org/gradle/profiler/studio/StudioGradleClient.java @@ -5,6 +5,7 @@ import org.gradle.profiler.InvocationSettings; import org.gradle.profiler.client.protocol.ServerConnection; import org.gradle.profiler.client.protocol.messages.*; +import org.gradle.profiler.ide.RunIde; import org.gradle.profiler.instrument.GradleInstrumentation; import org.gradle.profiler.result.BuildActionResult; import org.gradle.profiler.studio.invoker.StudioBuildActionResult; @@ -33,6 +34,9 @@ public class StudioGradleClient implements GradleClient { + + private final InvocationSettings invocationSettings; + public enum CleanCacheMode { BEFORE_SCENARIO, BEFORE_BUILD, @@ -43,6 +47,7 @@ public enum CleanCacheMode { private static final Duration GRADLE_INVOCATION_STARTED_TIMEOUT = Duration.ofMillis(100); private static final Duration GRADLE_INVOCATION_COMPLETED_TIMEOUT = Duration.ofMinutes(60); private static final Duration SYNC_REQUEST_COMPLETED_TIMEOUT = Duration.ofMinutes(90); + private final StudioInstallDirSupplier studioInstallDirSupplier; private final StudioProcessController processController; private final StudioPluginInstaller studioPluginInstaller; @@ -58,18 +63,24 @@ public StudioGradleClient( ) { this.isFirstRun = true; this.cleanCacheMode = cleanCacheMode; - Supplier studioInstallDirSupplier = new StudioInstallDirSupplier(invocationSettings, buildConfiguration); + this.studioInstallDirSupplier = new StudioInstallDirSupplier(invocationSettings, buildConfiguration); Optional studioSandboxDir = invocationSettings.getStudioSandboxDir(); this.sandbox = StudioSandboxCreator.createSandbox(studioSandboxDir.map(File::toPath).orElse(null)); Path protocolJar = GradleInstrumentation.unpackPlugin("client-protocol").toPath(); Path studioPlugin = GradleInstrumentation.unpackPlugin("studio-plugin").toPath(); this.studioPluginInstaller = new StudioPluginInstaller(sandbox.getPluginsDir()); studioPluginInstaller.installPlugin(Arrays.asList(studioPlugin, protocolJar)); + this.invocationSettings = invocationSettings; this.processController = new StudioProcessController(studioInstallDirSupplier, sandbox, invocationSettings, buildConfiguration); this.executor = Executors.newSingleThreadExecutor(); } public BuildActionResult sync(List gradleArgs, List jvmArgs) { + new RunIde().runIde( + invocationSettings.getProjectDir().getAbsolutePath(), + "2023.2.3", + studioInstallDirSupplier.get().toString() + ); if (shouldCleanCache()) { processController.runAndWaitToStop((connections) -> { System.out.println("* Cleaning Android Studio cache, this will require a restart..."); diff --git a/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java b/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java index 058f5583..89a192db 100644 --- a/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java +++ b/subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/studio/AndroidStudioProvider.java @@ -12,15 +12,12 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import static com.intellij.ide.starter.di.DiContainerKt.getDi; - public class AndroidStudioProvider implements IdeProvider { private final IdeArchiveExtractor ideArchiveExtractor = IdeArchiveExtractor.INSTANCE; private final HttpClient httpClient = HttpClient.INSTANCE; @Override public File provideIde(AndroidStudio ide, Path homeDir, Path downloadsDir) { - var v = getDi(); if (ide.getVersion().isEmpty()) { throw new IllegalArgumentException("Android Studio version must be specified"); } diff --git a/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt b/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt index 3a3fb5f0..b2438c4c 100644 --- a/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt +++ b/subprojects/ide-provisioning/src/main/kotlin/org/gradle/profiler/ide/RunIde.kt @@ -1,55 +1,51 @@ package org.gradle.profiler.ide -import com.intellij.ide.starter.di.di import com.intellij.ide.starter.ide.IdeDistributionFactory import com.intellij.ide.starter.ide.IdeInstaller import com.intellij.ide.starter.ide.IdeProductProvider import com.intellij.ide.starter.ide.InstalledIde -import com.intellij.ide.starter.ide.installer.IdeInstallerFile import com.intellij.ide.starter.models.IdeInfo import com.intellij.ide.starter.models.TestCase -import com.intellij.ide.starter.path.GlobalPaths -import com.intellij.ide.starter.path.InstallerGlobalPaths import com.intellij.ide.starter.project.LocalProjectInfo import com.intellij.tools.ide.performanceTesting.commands.CommandChain import com.intellij.tools.ide.performanceTesting.commands.exitApp import com.intellij.tools.ide.performanceTesting.commands.importGradleProject +import com.intellij.tools.ide.performanceTesting.commands.waitForSmartMode import java.nio.file.Path import java.nio.file.Paths class RunIde { - fun runIde(projectLocation: String, ideLocation: String) { - val testCase = TestCase( - IdeProductProvider.IC, - LocalProjectInfo(Paths.get(projectLocation)) - ) + fun runIde(projectLocation: String, buildVersion: String, ideLocation: String) { + val testVersion = "2021.2.2" val ideInfo = IdeInfo( productCode = "IC", - version = "2021.2.2", - buildNumber = "212.5284.40", + version = "2023.2.3", + buildNumber = buildVersion, executableFileName = "idea", fullName = "IntelliJ IDEA Community", platformPrefix = "idea", getInstaller = { _ -> IdeLocalInstaller(Paths.get(ideLocation)) } ) + val testCase = TestCase( + ideInfo, + LocalProjectInfo(Paths.get(projectLocation)), + ) val context = Starter.newContext("test", testCase) - .prepareProjectCleanImport() + .applyVMOptionsPatch { + removeProfilerAgents() + + } - context.runIDE(commands = CommandChain().importGradleProject().exitApp()) + context.runIDE(commands = CommandChain().importGradleProject().waitForSmartMode().importGradleProject()) + println("Waiting for 10 seconds") + Thread.sleep(10_000) + context.runIDE(commands = CommandChain().importGradleProject().waitForSmartMode().exitApp()) } - class IdeLocalInstaller(private val installer: Path) : IdeInstaller { + class IdeLocalInstaller(private val installedLocation: Path) : IdeInstaller { override fun install(ideInfo: IdeInfo, includeRuntimeModuleRepository: Boolean): Pair { - val ideInstaller = IdeInstallerFile(installer, "locally-installed-ide") - val installDir = InstallerGlobalPaths() - .getCacheDirectoryFor("builds") / "${ideInfo.productCode}-${ideInstaller.buildNumber}" - FileUtils.deleteDirectory(installDir.toFile()) - FileUtils.copyDirectory(installer.toFile(), installDir.toFile()) - return Pair( - ideInstaller.buildNumber, - IdeDistributionFactory.installIDE(installDir.toFile(), ideInfo.executableFileName) - ) + return ideInfo.buildNumber to IdeDistributionFactory.installIDE(installedLocation.toFile().parentFile, ideInfo.executableFileName) } } }