summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Ruiz <alruiz@google.com>2014-08-19 10:55:26 -0700
committerAlex Ruiz <alruiz@google.com>2014-08-19 10:58:17 -0700
commit9b66aa8a10a98bdcb020fc2b93fb064b3ea4059d (patch)
tree883d4615e337376f8b017c49a3bbcf915de20c6c
parent52c2b0a372c7b7f771df9f909ea8690980048991 (diff)
downloadidea-9b66aa8a10a98bdcb020fc2b93fb064b3ea4059d.tar.gz
Added infrastructure to UI testing to simulate Gradle sync failures.
There are bugs that happen during Gradle sync that are very difficult to reproduce. One example is https://code.google.com/p/android/issues/detail?id=74842 where apparently Gradle did not finish downloading artifacts and now project sync fails. In this CL adds a "execute before sync" task which can be used to simulate failures in Gradle. See CorruptedGradleDependencyTest for more details. This CL also introduces the concept of "isGuiTestingMode", similar to IDEA's "isUnitTestingMode". Change-Id: I27b42a68cbb012696b93b2745092e39458a7d15c
-rw-r--r--android/guiTestSrc/com/android/tools/idea/tests/gui/CorruptedGradleDependencyTest.java50
-rw-r--r--android/guiTestSrc/com/android/tools/idea/tests/gui/framework/GuiTests.java3
-rw-r--r--android/src/com/android/tools/idea/gradle/project/AndroidGradleProjectResolver.java25
-rw-r--r--android/src/com/android/tools/idea/gradle/service/notification/errors/UnsupportedModelVersionErrorHandler.java14
-rw-r--r--android/src/org/jetbrains/android/AndroidPlugin.java12
-rw-r--r--android/testData/guiTests/SimpleApplication/app/app.iml6
6 files changed, 92 insertions, 18 deletions
diff --git a/android/guiTestSrc/com/android/tools/idea/tests/gui/CorruptedGradleDependencyTest.java b/android/guiTestSrc/com/android/tools/idea/tests/gui/CorruptedGradleDependencyTest.java
new file mode 100644
index 00000000000..76de99c9031
--- /dev/null
+++ b/android/guiTestSrc/com/android/tools/idea/tests/gui/CorruptedGradleDependencyTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 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.android.tools.idea.tests.gui;
+
+import com.android.tools.idea.tests.gui.framework.GuiTestCase;
+import com.android.tools.idea.tests.gui.framework.annotation.IdeGuiTest;
+import com.android.tools.idea.tests.gui.framework.fixture.IdeFrameFixture;
+import com.android.tools.idea.tests.gui.framework.fixture.MessagesToolWindowFixture;
+import com.intellij.openapi.application.ApplicationManager;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static com.intellij.ide.errorTreeView.ErrorTreeElementKind.ERROR;
+import static org.jetbrains.android.AndroidPlugin.EXECUTE_BEFORE_PROJECT_SYNC_TASK_IN_GUI_TEST_KEY;
+
+public class CorruptedGradleDependencyTest extends GuiTestCase {
+ // See https://code.google.com/p/android/issues/detail?id=74842
+ @Test @IdeGuiTest
+ public void testPrematureEndOfContentLength() throws IOException {
+ IdeFrameFixture projectFrame = openProject("SimpleApplication");
+
+ final String failure = "Premature end of Content-Length delimited message body (expected: 171012; received: 50250.";
+ Runnable failTask = new Runnable() {
+ @Override
+ public void run() {
+ throw new RuntimeException(failure);
+ }
+ };
+ ApplicationManager.getApplication().putUserData(EXECUTE_BEFORE_PROJECT_SYNC_TASK_IN_GUI_TEST_KEY, failTask);
+
+ projectFrame.requestProjectSync();
+
+ MessagesToolWindowFixture messages = projectFrame.getMessagesToolWindow();
+ messages.getGradleSyncContent().requireMessage(ERROR, failure);
+ }
+}
diff --git a/android/guiTestSrc/com/android/tools/idea/tests/gui/framework/GuiTests.java b/android/guiTestSrc/com/android/tools/idea/tests/gui/framework/GuiTests.java
index eb4068d12fe..31bb595a2ef 100644
--- a/android/guiTestSrc/com/android/tools/idea/tests/gui/framework/GuiTests.java
+++ b/android/guiTestSrc/com/android/tools/idea/tests/gui/framework/GuiTests.java
@@ -32,6 +32,7 @@ import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiTask;
import org.fest.swing.timing.Condition;
import org.fest.swing.timing.Timeout;
+import org.jetbrains.android.AndroidPlugin;
import org.jetbrains.android.AndroidTestBase;
import org.jetbrains.annotations.NotNull;
@@ -58,6 +59,8 @@ public final class GuiTests {
// Called by IdeTestApplication via reflection.
@SuppressWarnings("UnusedDeclaration")
public static void setUpDefaultGeneralSettings() {
+ AndroidPlugin.setGuiTestingMode(true);
+
GeneralSettings.getInstance().setShowTipsOnStartup(false);
setUpDefaultProjectCreationLocationPath();
diff --git a/android/src/com/android/tools/idea/gradle/project/AndroidGradleProjectResolver.java b/android/src/com/android/tools/idea/gradle/project/AndroidGradleProjectResolver.java
index 4eea558a182..ae95886694e 100644
--- a/android/src/com/android/tools/idea/gradle/project/AndroidGradleProjectResolver.java
+++ b/android/src/com/android/tools/idea/gradle/project/AndroidGradleProjectResolver.java
@@ -24,6 +24,7 @@ import com.android.tools.idea.gradle.IdeaAndroidProject;
import com.android.tools.idea.gradle.IdeaGradleProject;
import com.android.tools.idea.gradle.IdeaJavaProject;
import com.android.tools.idea.gradle.facet.JavaGradleFacet;
+import com.android.tools.idea.gradle.service.notification.errors.UnsupportedModelVersionErrorHandler;
import com.android.tools.idea.gradle.util.AndroidGradleSettings;
import com.android.tools.idea.gradle.util.LocalProperties;
import com.android.tools.idea.sdk.DefaultSdks;
@@ -32,6 +33,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.execution.configurations.SimpleJavaParameters;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.externalSystem.model.project.ModuleData;
@@ -49,6 +51,7 @@ import org.gradle.tooling.model.GradleTask;
import org.gradle.tooling.model.gradle.GradleScript;
import org.gradle.tooling.model.idea.IdeaModule;
import org.gradle.util.GradleVersion;
+import org.jetbrains.android.AndroidPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
@@ -68,14 +71,6 @@ import static com.android.tools.idea.gradle.util.GradleBuilds.BUILD_SRC_FOLDER_N
*/
@Order(ExternalSystemConstants.UNORDERED)
public class AndroidGradleProjectResolver extends AbstractProjectResolverExtension {
- /**
- * These String constants are being used in {@link com.android.tools.idea.gradle.service.notification.GradleNotificationExtension} to add
- * "quick-fix"/"help" hyperlinks to error messages. Given that the contract between the consumer and producer of error messages is pretty
- * loose, please do not use these constants, to prevent any unexpected side effects during project sync.
- */
- @NotNull public static final String UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX =
- "The project is using an unsupported version of the Android Gradle plug-in";
- @NotNull public static final String READ_MIGRATION_GUIDE_MSG = "Please read the migration guide";
@NotNull private final ProjectImportErrorHandler myErrorHandler;
@@ -194,9 +189,15 @@ public class AndroidGradleProjectResolver extends AbstractProjectResolverExtensi
return Sets.<Class>newHashSet(AndroidProject.class);
}
-
@Override
public void preImportCheck() {
+ if (AndroidPlugin.isGuiTestingMode()) {
+ // We use this task in GUI tests to simulate errors coming from Gradle project sync.
+ Runnable task = ApplicationManager.getApplication().getUserData(AndroidPlugin.EXECUTE_BEFORE_PROJECT_SYNC_TASK_IN_GUI_TEST_KEY);
+ if (task != null) {
+ task.run();
+ }
+ }
if (AndroidStudioSpecificInitializer.isAndroidStudio()) {
LocalProperties localProperties = getLocalProperties();
// Ensure that Android Studio and the project (local.properties) point to the same Android SDK home. If they are not the same, we'll
@@ -254,7 +255,7 @@ public class AndroidGradleProjectResolver extends AbstractProjectResolverExtensi
@NotNull String projectPath,
@Nullable String buildFilePath) {
String msg = error.getMessage();
- if (msg != null && !msg.contains(UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX)) {
+ if (msg != null && !msg.contains(UnsupportedModelVersionErrorHandler.UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX)) {
Throwable rootCause = ExceptionUtil.getRootCause(error);
if (rootCause instanceof ClassNotFoundException) {
msg = rootCause.getMessage();
@@ -278,12 +279,12 @@ public class AndroidGradleProjectResolver extends AbstractProjectResolverExtensi
@NotNull
private static String getUnsupportedModelVersionErrorMsg(@Nullable FullRevision modelVersion) {
StringBuilder builder = new StringBuilder();
- builder.append(UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX);
+ builder.append(UnsupportedModelVersionErrorHandler.UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX);
if (modelVersion != null) {
builder.append(String.format(" (%1$s)", modelVersion.toString()));
if (modelVersion.getMajor() == 0 && modelVersion.getMinor() <= 8) {
builder.append(".\n\nStarting with version 0.9.0 incompatible changes were introduced in the build language.\n")
- .append(READ_MIGRATION_GUIDE_MSG)
+ .append(UnsupportedModelVersionErrorHandler.READ_MIGRATION_GUIDE_MSG)
.append(" to learn how to update your project.");
}
}
diff --git a/android/src/com/android/tools/idea/gradle/service/notification/errors/UnsupportedModelVersionErrorHandler.java b/android/src/com/android/tools/idea/gradle/service/notification/errors/UnsupportedModelVersionErrorHandler.java
index 925a6de02e6..655c982ad64 100644
--- a/android/src/com/android/tools/idea/gradle/service/notification/errors/UnsupportedModelVersionErrorHandler.java
+++ b/android/src/com/android/tools/idea/gradle/service/notification/errors/UnsupportedModelVersionErrorHandler.java
@@ -15,7 +15,6 @@
*/
package com.android.tools.idea.gradle.service.notification.errors;
-import com.android.tools.idea.gradle.project.AndroidGradleProjectResolver;
import com.android.tools.idea.gradle.service.notification.hyperlink.FixGradleModelVersionHyperlink;
import com.android.tools.idea.gradle.service.notification.hyperlink.NotificationHyperlink;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
@@ -26,15 +25,24 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
public class UnsupportedModelVersionErrorHandler extends AbstractSyncErrorHandler {
+ /**
+ * These String constants are being used in {@link com.android.tools.idea.gradle.service.notification.GradleNotificationExtension} to add
+ * "quick-fix"/"help" hyperlinks to error messages. Given that the contract between the consumer and producer of error messages is pretty
+ * loose, please do not use these constants, to prevent any unexpected side effects during project sync.
+ */
+ @NotNull public static final String UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX =
+ "The project is using an unsupported version of the Android Gradle plug-in";
+ @NotNull public static final String READ_MIGRATION_GUIDE_MSG = "Please read the migration guide";
+
@Override
public boolean handleError(@NotNull List<String> message,
@NotNull ExternalSystemException error,
@NotNull NotificationData notification,
@NotNull Project project) {
String msg = error.getMessage();
- if (msg.startsWith(AndroidGradleProjectResolver.UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX)) {
+ if (msg.startsWith(UNSUPPORTED_MODEL_VERSION_ERROR_PREFIX)) {
NotificationHyperlink fixGradleModelHyperlink;
- if (msg.contains(AndroidGradleProjectResolver.READ_MIGRATION_GUIDE_MSG)) {
+ if (msg.contains(READ_MIGRATION_GUIDE_MSG)) {
fixGradleModelHyperlink = new FixGradleModelVersionHyperlink();
}
else {
diff --git a/android/src/org/jetbrains/android/AndroidPlugin.java b/android/src/org/jetbrains/android/AndroidPlugin.java
index d2ae876839d..518c6935ad1 100644
--- a/android/src/org/jetbrains/android/AndroidPlugin.java
+++ b/android/src/org/jetbrains/android/AndroidPlugin.java
@@ -18,6 +18,7 @@ package org.jetbrains.android;
import com.android.tools.idea.templates.TemplateManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.util.Key;
import org.jetbrains.android.sdk.AndroidSdkData;
import org.jetbrains.annotations.NotNull;
@@ -25,6 +26,9 @@ import org.jetbrains.annotations.NotNull;
* @author coyote
*/
public class AndroidPlugin implements ApplicationComponent {
+ public static Key<Runnable> EXECUTE_BEFORE_PROJECT_SYNC_TASK_IN_GUI_TEST_KEY = Key.create("gui.test.execute.before.sync.task");
+
+ private static boolean ourGuiTestingMode;
@Override
@NotNull
@@ -51,4 +55,12 @@ public class AndroidPlugin implements ApplicationComponent {
public void disposeComponent() {
AndroidSdkData.terminateDdmlib();
}
+
+ public static boolean isGuiTestingMode() {
+ return ourGuiTestingMode;
+ }
+
+ public static void setGuiTestingMode(boolean guiTestingMode) {
+ ourGuiTestingMode = guiTestingMode;
+ }
}
diff --git a/android/testData/guiTests/SimpleApplication/app/app.iml b/android/testData/guiTests/SimpleApplication/app/app.iml
index 1f9b9e0e172..a2d942c2ba1 100644
--- a/android/testData/guiTests/SimpleApplication/app/app.iml
+++ b/android/testData/guiTests/SimpleApplication/app/app.iml
@@ -37,22 +37,22 @@
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/test/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/src/main/assets" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />