diff options
author | Stas Negara <snegara@google.com> | 2015-05-01 15:57:10 -0700 |
---|---|---|
committer | Stas Negara <snegara@google.com> | 2015-05-05 15:55:32 -0700 |
commit | d15ea558d770bd733f2b9b8431199f5ef862bafa (patch) | |
tree | 3f9784cb071bd919aa9e8a2412c14b50cbd17ab2 | |
parent | be9df783298c3d80fe31aaebe25f34862cc014d2 (diff) | |
download | testing-d15ea558d770bd733f2b9b8431199f5ef862bafa.tar.gz |
Cancel cloud matrix tests if user terminates the execution.
Change-Id: I7952f93e033520fa701b197cd0dbd1aac9c2280c
4 files changed, 129 insertions, 25 deletions
diff --git a/src/com/google/gct/testing/CloudConfigurationProviderImpl.java b/src/com/google/gct/testing/CloudConfigurationProviderImpl.java index 5b0f92d..c935e53 100644 --- a/src/com/google/gct/testing/CloudConfigurationProviderImpl.java +++ b/src/com/google/gct/testing/CloudConfigurationProviderImpl.java @@ -427,10 +427,10 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { lastCloudProjectId = cloudProjectId; AndroidTestRunConfiguration testRunConfiguration = (AndroidTestRunConfiguration) runningState.getConfiguration(); - AndroidTestConsoleProperties properties = - new AndroidTestConsoleProperties(testRunConfiguration, executor); - ConsoleView console = GoogleCloudTestResultsConnectionUtil - .createAndAttachConsole("Cloud Testing", runningState.getProcessHandler(), properties, runningState.getEnvironment()); + AndroidTestConsoleProperties properties = new AndroidTestConsoleProperties(testRunConfiguration, executor); + CloudMatrixExecutionCancellator matrixExecutionCancellator = new CloudMatrixExecutionCancellator(); + ConsoleView console = GoogleCloudTestResultsConnectionUtil.createAndAttachConsole( + "Cloud Testing", runningState.getProcessHandler(), properties, runningState.getEnvironment(), matrixExecutionCancellator); Disposer.register(project, console); GoogleCloudTestingResultParser @@ -444,13 +444,13 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { GoogleCloudTestingDeveloperConfigurable.GoogleCloudTestingDeveloperState googleCloudTestingDeveloperState = GoogleCloudTestingDeveloperSettings.getInstance(project).getState(); if (!googleCloudTestingDeveloperState.shouldUseFakeBucket) { - performTestsInCloud(cloudConfiguration, cloudProjectId, runningState, cloudResultParser); + performTestsInCloud(cloudConfiguration, cloudProjectId, runningState, cloudResultParser, matrixExecutionCancellator); } else { String testRunId = TEST_RUN_ID_PREFIX + googleCloudTestingDeveloperState.fakeBucketName + System.currentTimeMillis(); CloudResultsAdapter cloudResultsAdapter = new CloudResultsAdapter(cloudProjectId, googleCloudTestingDeveloperState.fakeBucketName, cloudResultParser, - expectedConfigurationInstances, testRunId, null); + expectedConfigurationInstances, testRunId, null, null); addCloudConfiguration(testRunId, cloudConfiguration); addCloudResultsAdapter(testRunId, cloudResultsAdapter); cloudResultsAdapter.startPolling(); @@ -459,7 +459,8 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { } private void performTestsInCloud(final CloudConfigurationImpl cloudTestingConfiguration, final String cloudProjectId, - final AndroidRunningState runningState, final GoogleCloudTestingResultParser cloudResultParser) { + final AndroidRunningState runningState, final GoogleCloudTestingResultParser cloudResultParser, + final CloudMatrixExecutionCancellator matrixExecutionCancellator) { if (cloudTestingConfiguration != null && cloudTestingConfiguration.getDeviceConfigurationCount() > 0) { final List<String> expectedConfigurationInstances = cloudTestingConfiguration.computeConfigurationInstances(ConfigurationInstance.DISPLAY_NAME_DELIMITER); @@ -472,10 +473,16 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { String appPackage = runningState.getFacet().getAndroidModuleInfo().getPackage(); String testPackage = appPackage + ".test"; + if (matrixExecutionCancellator.isCancelled()) { + return; + } runningState.getProcessHandler().notifyTextAvailable( prepareProgressString("Creating Cloud Storage bucket " + bucketName + "...", ""), ProcessOutputTypes.STDOUT); CloudTestsLauncher.createBucket(cloudProjectId, bucketName); + if (matrixExecutionCancellator.isCancelled()) { + return; + } List<String> apkPaths = getApkPaths(runningState); runningState.getProcessHandler().notifyTextAvailable(prepareProgressString("Uploading app APK...", ""), ProcessOutputTypes.STDOUT); @@ -488,6 +495,9 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { } String appApkName = CloudTestsLauncher.uploadFile(bucketName, appApk).getName(); + if (matrixExecutionCancellator.isCancelled()) { + return; + } runningState.getProcessHandler().notifyTextAvailable(prepareProgressString("Uploading test APK...", ""), ProcessOutputTypes.STDOUT); File testApk = findAppropriateApk(apkPaths, true); @@ -499,6 +509,9 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { } String testApkName = CloudTestsLauncher.uploadFile(bucketName, testApk).getName(); + if (matrixExecutionCancellator.isCancelled()) { + return; + } runningState.getProcessHandler().notifyTextAvailable(prepareProgressString("Invoking cloud test API...", "\n"), ProcessOutputTypes.STDOUT); String testSpecification = CloudTestingUtils.prepareTestSpecification(testRunConfiguration); @@ -509,9 +522,12 @@ public class CloudConfigurationProviderImpl extends CloudConfigurationProvider { cloudTestingConfiguration, appPackage, testPackage); if (testMatrix != null) { + matrixExecutionCancellator.setCloudProjectId(cloudProjectId); + matrixExecutionCancellator.setTestMatrixId(testMatrix.getTestMatrixId()); String testRunId = TEST_RUN_ID_PREFIX + bucketName; CloudResultsAdapter cloudResultsAdapter = - new CloudResultsAdapter(cloudProjectId, bucketName, cloudResultParser, expectedConfigurationInstances, testRunId, testMatrix); + new CloudResultsAdapter(cloudProjectId, bucketName, cloudResultParser, expectedConfigurationInstances, testRunId, testMatrix, + matrixExecutionCancellator); addCloudConfiguration(testRunId, cloudTestingConfiguration); addCloudResultsAdapter(testRunId, cloudResultsAdapter); cloudResultsAdapter.startPolling(); diff --git a/src/com/google/gct/testing/CloudMatrixExecutionCancellator.java b/src/com/google/gct/testing/CloudMatrixExecutionCancellator.java new file mode 100644 index 0000000..c59bfcc --- /dev/null +++ b/src/com/google/gct/testing/CloudMatrixExecutionCancellator.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.gct.testing; + +import java.io.IOException; + +import static com.google.gct.testing.launcher.CloudAuthenticator.getTest; + +public class CloudMatrixExecutionCancellator { + + private volatile boolean isCancelled = false; + private volatile String cloudProjectId = null; + private volatile String testMatrixId = null; + + + public synchronized void cancel() { + if (isCancelled) { + return; + } + + if (cloudProjectId != null && testMatrixId != null) { + try { + doCancel(); + } catch (Exception e1) { + // Retry + try { + doCancel(); + } catch (Exception e2) { + // Give up + } + } + } + isCancelled = true; + } + + private void doCancel() throws IOException { + getTest().projects().testMatrices().cancel(cloudProjectId, testMatrixId); + } + + public synchronized boolean isCancelled() { + return isCancelled; + } + + public synchronized void setCloudProjectId(String cloudProjectId) { + this.cloudProjectId = cloudProjectId; + } + + public synchronized void setTestMatrixId(String testMatrixId) { + this.testMatrixId = testMatrixId; + } +} diff --git a/src/com/google/gct/testing/CloudResultsAdapter.java b/src/com/google/gct/testing/CloudResultsAdapter.java index 8b804fd..99b27c3 100644 --- a/src/com/google/gct/testing/CloudResultsAdapter.java +++ b/src/com/google/gct/testing/CloudResultsAdapter.java @@ -20,6 +20,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.gct.testing.results.GoogleCloudTestingResultParser; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -39,15 +40,17 @@ public class CloudResultsAdapter { private final Set<ConfigurationResult> markedAsPendingConfigurations = new HashSet<ConfigurationResult>(); // The set of configurations that were marked as finished in the test results tree. private final Set<ConfigurationResult> markedAsFinishedConfigurations = new HashSet<ConfigurationResult>(); - private final PollingTicker pollingTicker = new PollingTicker(); + private final PollingTicker pollingTicker; public CloudResultsAdapter(String cloudProjectId, String bucketName, GoogleCloudTestingResultParser resultParser, - List<String> expectedConfigurationInstances, String testRunId, TestMatrix testMatrix) { + List<String> expectedConfigurationInstances, String testRunId, @Nullable TestMatrix testMatrix, + @Nullable CloudMatrixExecutionCancellator matrixExecutionCancellator) { this.cloudProjectId = cloudProjectId; loader = new CloudResultsLoader(cloudProjectId, resultParser.getTestRunListener(), bucketName, testMatrix); this.resultParser = resultParser; this.expectedConfigurationInstances = expectedConfigurationInstances; + pollingTicker = new PollingTicker(matrixExecutionCancellator); // Update the tree's root node with the index of the adapter that communicates with the tree through this parser. resultParser.getTestRunListener().setTestRunId(testRunId); } @@ -153,6 +156,11 @@ public class CloudResultsAdapter { private static final int POLLING_INTERVAL = 3 * 1000; // 3 seconds private long stopTime; + private final CloudMatrixExecutionCancellator matrixExecutionCancellator; + + public PollingTicker(@Nullable CloudMatrixExecutionCancellator matrixExecutionCancellator) { + this.matrixExecutionCancellator = matrixExecutionCancellator; + } public void resetTimeout() { long newStopTime = System.currentTimeMillis() + DYNAMIC_TIMEOUT; @@ -166,6 +174,9 @@ public class CloudResultsAdapter { boolean allResultsArrived = false; stopTime = System.currentTimeMillis() + INITIAL_TIMEOUT; while (System.currentTimeMillis() < stopTime) { + if (matrixExecutionCancellator != null && matrixExecutionCancellator.isCancelled()) { + break; + } allResultsArrived = poll(); if (allResultsArrived) { break; diff --git a/src/com/google/gct/testing/results/GoogleCloudTestResultsConnectionUtil.java b/src/com/google/gct/testing/results/GoogleCloudTestResultsConnectionUtil.java index 495b207..7924a46 100644 --- a/src/com/google/gct/testing/results/GoogleCloudTestResultsConnectionUtil.java +++ b/src/com/google/gct/testing/results/GoogleCloudTestResultsConnectionUtil.java @@ -15,6 +15,7 @@ */ package com.google.gct.testing.results; +import com.google.gct.testing.CloudMatrixExecutionCancellator; import com.intellij.execution.ExecutionException; import com.intellij.execution.Executor; import com.intellij.execution.configurations.CommandLineState; @@ -67,9 +68,10 @@ public class GoogleCloudTestResultsConnectionUtil { public static BaseTestsOutputConsoleView createAndAttachConsole(@NotNull final String testFrameworkName, @NotNull final ProcessHandler processHandler, @NotNull final TestConsoleProperties consoleProperties, - ExecutionEnvironment environment + ExecutionEnvironment environment, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator ) throws ExecutionException { - BaseTestsOutputConsoleView console = createConsole(testFrameworkName, consoleProperties, environment); + BaseTestsOutputConsoleView console = createConsole(testFrameworkName, consoleProperties, environment, matrixExecutionCancellator); console.attachToProcess(processHandler); return console; } @@ -77,13 +79,15 @@ public class GoogleCloudTestResultsConnectionUtil { public static BaseTestsOutputConsoleView createConsoleWithCustomLocator(@NotNull final String testFrameworkName, @NotNull final TestConsoleProperties consoleProperties, ExecutionEnvironment environment, - @Nullable final TestLocationProvider locator) { + @Nullable final TestLocationProvider locator, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator) { return createConsoleWithCustomLocator(testFrameworkName, consoleProperties, environment, new CompositeTestLocationProvider(locator), false, - null); + null, + matrixExecutionCancellator); } public static GoogleCloudTestingConsoleView createConsoleWithCustomLocator(@NotNull final String testFrameworkName, @@ -91,12 +95,13 @@ public class GoogleCloudTestResultsConnectionUtil { ExecutionEnvironment environment, @Nullable final TestLocationProvider locator, final boolean idBasedTreeConstruction, - @Nullable final TestProxyFilterProvider filterProvider) { + @Nullable final TestProxyFilterProvider filterProvider, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator) { String splitterPropertyName = getSplitterPropertyName(testFrameworkName); GoogleCloudTestingConsoleView consoleView = new GoogleCloudTestingConsoleView(consoleProperties, environment, splitterPropertyName); - initConsoleView(consoleView, testFrameworkName, locator, idBasedTreeConstruction, filterProvider); + initConsoleView(consoleView, testFrameworkName, locator, idBasedTreeConstruction, filterProvider, matrixExecutionCancellator); return consoleView; } @@ -109,7 +114,8 @@ public class GoogleCloudTestResultsConnectionUtil { @NotNull final String testFrameworkName, @Nullable final TestLocationProvider locator, final boolean idBasedTreeConstruction, - @Nullable final TestProxyFilterProvider filterProvider) { + @Nullable final TestProxyFilterProvider filterProvider, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator) { consoleView.addAttachToProcessListener(new AttachToProcessListener() { @Override public void onAttachToProcess(@NotNull ProcessHandler processHandler) { @@ -125,7 +131,8 @@ public class GoogleCloudTestResultsConnectionUtil { testFrameworkName, locator, idBasedTreeConstruction, - printerProvider); + printerProvider, + matrixExecutionCancellator); } }); consoleView.setHelpId("reference.runToolWindow.testResultsTab"); @@ -134,9 +141,10 @@ public class GoogleCloudTestResultsConnectionUtil { public static BaseTestsOutputConsoleView createConsole(@NotNull final String testFrameworkName, @NotNull final TestConsoleProperties consoleProperties, - ExecutionEnvironment environment) { + ExecutionEnvironment environment, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator) { - return createConsoleWithCustomLocator(testFrameworkName, consoleProperties, environment, null); + return createConsoleWithCustomLocator(testFrameworkName, consoleProperties, environment, null, matrixExecutionCancellator); } /** @@ -188,26 +196,29 @@ public class GoogleCloudTestResultsConnectionUtil { public static ConsoleView createAndAttachConsole(@NotNull final String testFrameworkName, @NotNull final ProcessHandler processHandler, @NotNull final CommandLineState commandLineState, @NotNull final ModuleRunConfiguration config, - @NotNull final Executor executor + @NotNull final Executor executor, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator ) throws ExecutionException { // final String testFrameworkName final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config, testFrameworkName, executor); return createAndAttachConsole(testFrameworkName, processHandler, consoleProperties, - commandLineState.getEnvironment()); + commandLineState.getEnvironment(), matrixExecutionCancellator); } public static ConsoleView createConsole(@NotNull final String testFrameworkName, @NotNull final CommandLineState commandLineState, @NotNull final ModuleRunConfiguration config, - @NotNull final Executor executor + @NotNull final Executor executor, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator ) throws ExecutionException { // final String testFrameworkName final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config, testFrameworkName, executor); return createConsole(testFrameworkName, consoleProperties, - commandLineState.getEnvironment()); + commandLineState.getEnvironment(), + matrixExecutionCancellator); } /** @@ -227,7 +238,8 @@ public class GoogleCloudTestResultsConnectionUtil { @NotNull final String testFrameworkName, @Nullable final TestLocationProvider locator, boolean idBasedTreeConstruction, - @Nullable TestProxyPrinterProvider printerProvider) { + @Nullable TestProxyPrinterProvider printerProvider, + @NotNull final CloudMatrixExecutionCancellator matrixExecutionCancellator) { //build messages consumer final OutputToGoogleCloudTestEventsConverter outputConsumer = new OutputToGoogleCloudTestEventsConverter(testFrameworkName, consoleProperties); @@ -268,6 +280,7 @@ public class GoogleCloudTestResultsConnectionUtil { processHandler.addProcessListener(new ProcessAdapter() { @Override public void processTerminated(final ProcessEvent event) { + matrixExecutionCancellator.cancel(); outputConsumer.flushBufferBeforeTerminating(); eventsProcessor.onFinishTesting(); |