blob: 70542d3272da4644ecfa8d42356403767ff3d5f6 [file] [log] [blame]
/*
* 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.android.tools.idea.tests.gui.gradle;
import com.android.tools.idea.gradle.dsl.parser.DependenciesElement;
import com.android.tools.idea.gradle.dsl.parser.ExternalDependencyElement;
import com.android.tools.idea.gradle.dsl.parser.GradleBuildFile;
import com.android.tools.idea.tests.gui.framework.BelongsToTestGroups;
import com.android.tools.idea.tests.gui.framework.GuiTestCase;
import com.android.tools.idea.tests.gui.framework.IdeGuiTest;
import com.android.tools.idea.tests.gui.framework.IdeGuiTestSetup;
import com.android.tools.idea.tests.gui.framework.fixture.IdeFrameFixture;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.vfs.VirtualFile;
import org.fest.assertions.AssertExtension;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.edt.GuiTask;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
import static com.android.tools.idea.tests.gui.framework.TestGroup.PROJECT_SUPPORT;
import static com.intellij.openapi.vfs.VfsUtil.saveText;
import static com.intellij.openapi.vfs.VfsUtilCore.loadText;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.swing.edt.GuiActionRunner.execute;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@BelongsToTestGroups({PROJECT_SUPPORT})
@IdeGuiTestSetup(skipSourceGenerationOnSync = true)
public class GradleDslExternalDependenciesParsingTest extends GuiTestCase {
@NonNls private static final String APP_BUILD_GRADLE_RELATIVE_PATH = "app/build.gradle";
@NonNls private static final String DEPENDENCIES_BLOCK_START = "dependencies {";
@Test @IdeGuiTest
public void testParseExternalDependenciesWithCompactNotation() throws IOException {
IdeFrameFixture projectFrame = importSimpleApplication();
GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(2);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("compile")
.hasGroup("com.android.support")
.hasName("appcompat-v7")
.hasVersion("22.1.1");
assertThat(dependency(dependencies.get(1))).hasConfigurationName("compile")
.hasGroup("com.google.guava")
.hasName("guava")
.hasVersion("18.0");
}
@Test @IdeGuiTest
public void testAddExternalDependencyWithCompactNotation() throws IOException {
final IdeFrameFixture projectFrame = importSimpleApplication();
final GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
final Ref<DependenciesElement> dependenciesBlockRef = new Ref<DependenciesElement>(dependenciesBlocks.get(0));
List<ExternalDependencyElement> dependencies = dependenciesBlockRef.get().getExternalDependenciesView();
assertThat(dependencies).hasSize(2);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
WriteCommandAction.runWriteCommandAction(projectFrame.getProject(), new Runnable() {
@Override
public void run() {
dependenciesBlockRef.get().addExternalDependency("compile", "joda-time:joda-time:2.3");
}
});
parsedBuildFile.reparse();
}
});
dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(3);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("compile")
.hasGroup("com.android.support")
.hasName("appcompat-v7")
.hasVersion("22.1.1");
assertThat(dependency(dependencies.get(1))).hasConfigurationName("compile")
.hasGroup("com.google.guava")
.hasName("guava")
.hasVersion("18.0");
assertThat(dependency(dependencies.get(2))).hasConfigurationName("compile")
.hasGroup("joda-time")
.hasName("joda-time")
.hasVersion("2.3");
}
@Test @IdeGuiTest
public void testSetVersionOnExternalDependencyWithCompactNotation() throws IOException {
final IdeFrameFixture projectFrame = importSimpleApplication();
final GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(2);
final ExternalDependencyElement appCompat = dependencies.get(0);
assertThat(dependency(appCompat)).hasConfigurationName("compile")
.hasGroup("com.android.support")
.hasName("appcompat-v7").hasVersion("22.1.1");
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
WriteCommandAction.runWriteCommandAction(projectFrame.getProject(), new Runnable() {
@Override
public void run() {
appCompat.setVersion("1.2.3");
}
});
parsedBuildFile.reparse();
}
});
dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
dependenciesBlock = dependenciesBlocks.get(0);
dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(2);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("compile")
.hasGroup("com.android.support")
.hasName("appcompat-v7")
.hasVersion("1.2.3");
}
@Test @IdeGuiTest
public void testParseDependenciesWithMapNotation() throws IOException {
IdeFrameFixture projectFrame = importSimpleApplication();
replaceDependenciesInAppBuildFile(projectFrame, "compile group: 'com.google.code.guice', name: 'guice', version: '1.0'");
GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(1);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("compile")
.hasGroup("com.google.code.guice")
.hasName("guice")
.hasVersion("1.0");
}
@Test @IdeGuiTest
public void testSetVersionOnExternalDependencyWithMapNotation() throws IOException {
final IdeFrameFixture projectFrame = importSimpleApplication();
replaceDependenciesInAppBuildFile(projectFrame, "compile group: 'com.google.code.guice', name: 'guice', version: '1.0'");
final GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(1);
final ExternalDependencyElement guice = dependencies.get(0);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
WriteCommandAction.runWriteCommandAction(projectFrame.getProject(), new Runnable() {
@Override
public void run() {
guice.setVersion("1.2.3");
}
});
parsedBuildFile.reparse();
}
});
dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
dependenciesBlock = dependenciesBlocks.get(0);
dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(1);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("compile")
.hasGroup("com.google.code.guice")
.hasName("guice")
.hasVersion("1.2.3");
}
@Test @IdeGuiTest
public void testAddDependencyWhenBuildFileDoesNotHaveDependenciesBlock() throws IOException {
final IdeFrameFixture projectFrame = importSimpleApplication();
// Remove "dependencies" block.
final VirtualFile appBuildFile = projectFrame.findFileByRelativePath(APP_BUILD_GRADLE_RELATIVE_PATH, true);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
String text = loadText(appBuildFile);
int indexOfDependenciesBlock = text.indexOf(DEPENDENCIES_BLOCK_START);
if (indexOfDependenciesBlock != -1) {
final String newText = text.substring(0, indexOfDependenciesBlock);
ApplicationManager.getApplication().runWriteAction(new ThrowableComputable<Void, IOException>() {
@Override
public Void compute() throws IOException {
saveText(appBuildFile, newText);
return null;
}
});
}
}
});
final GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
WriteCommandAction.runWriteCommandAction(projectFrame.getProject(), new Runnable() {
@Override
public void run() {
parsedBuildFile.addExternalDependency("compile", "joda-time:joda-time:2.3");
}
});
parsedBuildFile.reparse();
}
});
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(1);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("compile")
.hasGroup("joda-time")
.hasName("joda-time")
.hasVersion("2.3");
}
@Test @IdeGuiTest
public void testParseExternalDependenciesWithCompactNotationDeclaredInSingleLine() throws IOException {
IdeFrameFixture projectFrame = importSimpleApplication();
// Added comments to dependency declarations just ensure parsing works.
replaceDependenciesInAppBuildFile(projectFrame,
"runtime /* Hey */ 'org.springframework:spring-core:2.5', /* Hey */ 'org.springframework:spring-aop:2.5'");
GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(2);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("runtime")
.hasGroup("org.springframework")
.hasName("spring-core")
.hasVersion("2.5");
assertThat(dependency(dependencies.get(1))).hasConfigurationName("runtime")
.hasGroup("org.springframework")
.hasName("spring-aop")
.hasVersion("2.5");
}
@Test @IdeGuiTest
public void testParseExternalDependenciesWithMapNotationUsingSingleConfigurationName() throws IOException {
IdeFrameFixture projectFrame = importSimpleApplication();
replaceDependenciesInAppBuildFile(projectFrame,
"runtime(\n" +
" [group: 'org.springframework', name: 'spring-core', version: '2.5'],\n" +
" [group: 'org.springframework', name: 'spring-aop', version: '2.5']\n" +
" )");
GradleBuildFile parsedBuildFile = openAndParseAppBuildFile(projectFrame);
List<DependenciesElement> dependenciesBlocks = parsedBuildFile.getDependenciesBlocksView();
assertThat(dependenciesBlocks).hasSize(1);
DependenciesElement dependenciesBlock = dependenciesBlocks.get(0);
List<ExternalDependencyElement> dependencies = dependenciesBlock.getExternalDependenciesView();
assertThat(dependencies).hasSize(2);
assertThat(dependency(dependencies.get(0))).hasConfigurationName("runtime")
.hasGroup("org.springframework")
.hasName("spring-core")
.hasVersion("2.5");
assertThat(dependency(dependencies.get(1))).hasConfigurationName("runtime")
.hasGroup("org.springframework")
.hasName("spring-aop")
.hasVersion("2.5");
}
private static void replaceDependenciesInAppBuildFile(@NotNull IdeFrameFixture projectFrame, @NotNull final String...dependencies) {
final VirtualFile appBuildFile = projectFrame.findFileByRelativePath(APP_BUILD_GRADLE_RELATIVE_PATH, true);
execute(new GuiTask() {
@Override
protected void executeInEDT() throws Throwable {
String text = loadText(appBuildFile);
int indexOfDependenciesBlock = text.indexOf(DEPENDENCIES_BLOCK_START);
if (indexOfDependenciesBlock != -1) {
final StringBuilder newText = new StringBuilder();
newText.append(text.substring(0, indexOfDependenciesBlock));
newText.append("dependencies {\n");
for (String dependency : dependencies) {
newText.append(" ").append(dependency).append('\n');
}
newText.append("}");
ApplicationManager.getApplication().runWriteAction(new ThrowableComputable<Void, IOException>() {
@Override
public Void compute() throws IOException {
saveText(appBuildFile, newText.toString());
return null;
}
});
}
}
});
}
@NotNull
private static GradleBuildFile openAndParseAppBuildFile(@NotNull final IdeFrameFixture projectFrame) {
String relativePath = APP_BUILD_GRADLE_RELATIVE_PATH;
projectFrame.getEditor().open(relativePath).getCurrentFile();
final VirtualFile appBuildFile = projectFrame.findFileByRelativePath(relativePath, true);
GradleBuildFile parsed = execute(new GuiQuery<GradleBuildFile>() {
@Override
@NotNull
protected GradleBuildFile executeInEDT() throws Throwable {
return GradleBuildFile.parseFile(appBuildFile, projectFrame.getProject());
}
});
assertNotNull(parsed);
return parsed;
}
@NotNull
private static ExternalDependencyAssertion dependency(@NotNull ExternalDependencyElement target) {
return new ExternalDependencyAssertion(target);
}
private static class ExternalDependencyAssertion implements AssertExtension {
@NotNull private final ExternalDependencyElement myTarget;
ExternalDependencyAssertion(@NotNull ExternalDependencyElement target) {
myTarget = target;
}
@NotNull
ExternalDependencyAssertion hasConfigurationName(@NotNull String expected) {
assertEquals("configurationName", expected, myTarget.getConfigurationName());
return this;
}
@NotNull
ExternalDependencyAssertion hasGroup(@Nullable String expected) {
assertEquals("groupId", expected, myTarget.getGroup());
return this;
}
@NotNull
ExternalDependencyAssertion hasName(@Nullable String expected) {
assertEquals("artifactId", expected, myTarget.getName());
return this;
}
@NotNull
ExternalDependencyAssertion hasVersion(@Nullable String expected) {
assertEquals("fullRevision", expected, myTarget.getVersion());
return this;
}
}
}