blob: d9005730041ecaa8e3024fb2b134ec5739d420e7 [file] [log] [blame]
/*
* Copyright (C) 2019 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.build.gradle;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.android.annotations.NonNull;
import com.android.build.api.artifact.BuildableArtifact;
import com.android.build.gradle.internal.api.artifact.BuildableArtifactImpl;
import com.android.build.gradle.internal.fixtures.FakeDeprecationReporter;
import com.android.build.gradle.internal.fixtures.FakeEvalIssueReporter;
import com.android.build.gradle.internal.fixtures.FakeFileCollection;
import com.android.build.gradle.internal.fixtures.FakeObjectFactory;
import com.android.build.gradle.internal.variant2.DslScopeImpl;
import com.android.builder.core.BuilderConstants;
import com.android.ide.common.rendering.api.ResourceNamespace;
import com.android.ide.common.resources.ResourceSet;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.gradle.api.artifacts.ArtifactCollection;
import org.gradle.api.artifacts.component.ComponentArtifactIdentifier;
import org.gradle.api.artifacts.component.ProjectComponentIdentifier;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import org.gradle.api.file.FileCollection;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class DependencyResourcesComputerTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private DependecyResourcesComputer computer;
private List<ResourceSet> folderSets;
private Map<String, BuildableArtifact> artifactMap;
@Before
public void setUp() throws IOException {
BuildableArtifactImpl.Companion.enableResolution();
computer = new DependecyResourcesComputer();
// set some default file collection on the required inputs
FileCollection empty = mock(FileCollection.class);
computer.setRenderscriptResOutputDir(empty);
computer.setGeneratedResOutputDir(empty);
folderSets = Lists.newArrayList();
artifactMap = new LinkedHashMap<>();
computer.setResources(artifactMap);
}
@After
public void tearDown() {
computer = null;
folderSets = null;
}
@Test
public void singleSetWithSingleFile() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
assertThat(computer.compute()).containsExactly(mainSet);
}
@Test
public void singleSetWithMultiFiles() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
File file2 = temporaryFolder.newFolder("src", "main2");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file, file2);
assertThat(computer.compute()).containsExactly(mainSet);
}
@Test
public void twoSetsWithSingleFile() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
File file2 = temporaryFolder.newFolder("src", "debug");
ResourceSet debugSet = createResourceSet(folderSets, artifactMap, "debug", file2);
assertThat(computer.compute()).containsExactly(mainSet, debugSet);
}
@Test
public void singleSetWithDependency() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
File file2 = temporaryFolder.newFolder("foo", "bar", "1.0");
List<ResourceSet> librarySets = setupLibraryDependencies(file2, ":path");
assertThat(computer.getLibraries().getArtifactFiles()).containsExactly(file2);
List<ResourceSet> computedSets = computer.compute();
assertThat(computedSets).containsExactly(librarySets.get(0), mainSet).inOrder();
}
@Test
public void singleSetWithRenderscript() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
File rsFile = temporaryFolder.newFolder("rs");
setFileCollection(computer::setRenderscriptResOutputDir, rsFile);
mainSet.addSource(rsFile);
assertThat(computer.compute()).containsExactly(mainSet);
// rs file should have been added to the main resource sets.
assertThat(mainSet.getSourceFiles()).containsExactly(file, rsFile);
}
@Test
public void singleSetWithGeneratedRes() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
File genFile = temporaryFolder.newFolder("generated");
setFileCollection(computer::setGeneratedResOutputDir, genFile);
mainSet.addSource(genFile);
assertThat(computer.compute()).containsExactly(mainSet);
// generated file should have been added to the main resource sets.
assertThat(mainSet.getSourceFiles()).containsExactly(file, genFile);
}
@Test
public void singleSetWithMicroApkRes() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
File microFile = temporaryFolder.newFolder("micro");
setFileCollection(computer::setMicroApkResDirectory, microFile);
mainSet.addSource(microFile);
assertThat(computer.compute()).containsExactly(mainSet);
// micro file should have been added to the main resource sets.
assertThat(mainSet.getSourceFiles()).containsExactly(file, microFile);
}
@Test
public void singleSetWithExtraRes() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file);
File extraFile = temporaryFolder.newFolder("extra");
setFileCollectionSupplier(computer::setExtraGeneratedResFolders, extraFile);
mainSet.addSource(extraFile);
assertThat(computer.compute()).containsExactly(mainSet);
// rs file should have been added to the main resource sets.
assertThat(mainSet.getSourceFiles()).containsExactly(file, extraFile);
}
@Test
public void everything() throws Exception {
File file = temporaryFolder.newFolder("src", "main");
File file2 = temporaryFolder.newFolder("src", "main2");
ResourceSet mainSet =
createResourceSet(folderSets, artifactMap, BuilderConstants.MAIN, file, file2);
File debugFile = temporaryFolder.newFolder("src", "debug");
ResourceSet debugSet = createResourceSet(folderSets, artifactMap, "debug", debugFile);
File libFile = temporaryFolder.newFolder("foo", "bar", "1.0");
File libFile2 = temporaryFolder.newFolder("foo", "bar", "2.0");
// the order returned by the dependency is meant to be in the wrong order (consumer first,
// when we want dependent first for the merger), so the order in the res set should be
// the opposite order.
List<ResourceSet> librarySets = setupLibraryDependencies(
libFile, ":path1",
libFile2, ":path2");
ResourceSet librarySet = librarySets.get(0);
ResourceSet librarySet2 = librarySets.get(1);
// Note: the order of files are added to mainSet matters.
File rsFile = temporaryFolder.newFolder("rs");
setFileCollection(computer::setRenderscriptResOutputDir, rsFile);
mainSet.addSource(rsFile);
File genFile = temporaryFolder.newFolder("generated");
setFileCollection(computer::setGeneratedResOutputDir, genFile);
mainSet.addSource(genFile);
File extraFile = temporaryFolder.newFolder("extra");
setFileCollectionSupplier(computer::setExtraGeneratedResFolders, extraFile);
mainSet.addSource(extraFile);
File microFile = temporaryFolder.newFolder("micro");
setFileCollection(computer::setMicroApkResDirectory, microFile);
mainSet.addSource(microFile);
assertThat(computer.getLibraries().getArtifactFiles()).containsExactly(libFile, libFile2);
assertThat(computer.compute())
.containsExactly(librarySet2, librarySet, mainSet, debugSet)
.inOrder();
// generated files should have been added to the main resource sets.
assertThat(mainSet.getSourceFiles())
.containsExactly(file, file2, rsFile, genFile, extraFile, microFile);
assertThat(computer.getLibraries().getArtifactFiles()).containsExactly(libFile, libFile2);
}
@NonNull
private ResourceSet createResourceSet(
List<ResourceSet> folderSets,
Map<String, BuildableArtifact> artifactMap,
String name,
File... files) {
ResourceSet mainSet = new ResourceSet(name, ResourceNamespace.RES_AUTO, null, false);
BuildableArtifact artifact =
new BuildableArtifactImpl(
new FakeFileCollection(Arrays.asList(files)),
new DslScopeImpl(
new FakeEvalIssueReporter(true),
new FakeDeprecationReporter(),
new FakeObjectFactory()));
artifactMap.put(name, artifact);
mainSet.addSources(artifact.getFiles());
folderSets.add(mainSet);
return mainSet;
}
private static void setFileCollection(Consumer<FileCollection> setter, File... files) {
FileCollection fileCollection = mock(FileCollection.class);
Set<File> fileSet = ImmutableSet.copyOf(Arrays.asList(files));
when(fileCollection.getFiles()).thenReturn(fileSet);
setter.accept(fileCollection);
}
private static void setFileCollectionSupplier(
Consumer<FileCollection> setter,
File... files) {
FileCollection fileCollection = mock(FileCollection.class);
Set<File> fileSet = ImmutableSet.copyOf(Arrays.asList(files));
when(fileCollection.getFiles()).thenReturn(fileSet);
setter.accept(fileCollection);
}
@NonNull
private List<ResourceSet> setupLibraryDependencies(Object... objects) {
ArtifactCollection libraries = mock(ArtifactCollection.class);
Set<ResolvedArtifactResult> artifacts = new LinkedHashSet<>();
Set<File> files = new HashSet<>();
List<ResourceSet> resourceSets = Lists.newArrayListWithCapacity(objects.length/2);
for (int i = 0, count = objects.length; i < count ; i+=2) {
assertThat(objects[i]).isInstanceOf(File.class);
assertThat(objects[i+1]).isInstanceOf(String.class);
File file = (File) objects[i];
String path = (String) objects[i+1];
files.add(file);
ResolvedArtifactResult artifact = mock(ResolvedArtifactResult.class);
artifacts.add(artifact);
ComponentArtifactIdentifier artifactId = mock(ComponentArtifactIdentifier.class);
ProjectComponentIdentifier id = mock(ProjectComponentIdentifier.class);
when(id.getProjectPath()).thenReturn(path);
when(artifactId.getComponentIdentifier()).thenReturn(id);
when(artifact.getFile()).thenReturn(file);
when(artifact.getId()).thenReturn(artifactId);
// create a resource set that must match the one returned by the computation
ResourceSet set = new ResourceSet(path, ResourceNamespace.RES_AUTO, null, false);
set.addSource(file);
set.setFromDependency(true);
resourceSets.add(set);
}
when(libraries.getArtifacts()).thenReturn(artifacts);
when(libraries.getArtifactFiles()).thenReturn(new FakeFileCollection(files));
computer.setLibraries(libraries);
return resourceSets;
}
}