/* * Copyright 2015-present Facebook, Inc. * * 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.facebook.buck.android.aapt; import static org.junit.Assert.assertThat; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.rules.BuildRuleParams; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.FakeBuildContext; import com.facebook.buck.rules.FakeBuildRuleParamsBuilder; import com.facebook.buck.rules.FakeBuildableContext; import com.facebook.buck.rules.FakeSourcePath; import com.facebook.buck.rules.SourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.step.ExecutionContext; import com.facebook.buck.step.Step; import com.facebook.buck.step.TestExecutionContext; import com.facebook.buck.step.fs.MkdirStep; import com.facebook.buck.step.fs.RmStep; import com.google.common.base.Function; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; public class MergeAndroidResourcesSourcesTest { private static final String RESOURCES_XML_HEADER = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n"; private static final String RESOURCES_XML_FOOTER = "</resources>"; @Rule public TemporaryFolder tmp = new TemporaryFolder(); private final Function<Step, String> stepDescriptionFunction = new Function<Step, String>() { @Override public String apply(Step input) { return input.getDescription(context); } }; private ExecutionContext context; private ProjectFilesystem filesystem; @Before public void setUp() throws Exception { filesystem = new ProjectFilesystem(tmp.getRoot().toPath()); context = TestExecutionContext.newInstance(); tmp.newFolder("res_in_1"); tmp.newFolder("res_in_1", "values"); tmp.newFolder("res_in_1", "drawable"); tmp.newFile("res_in_1/drawable/one.png"); tmp.newFolder("res_in_2"); tmp.newFolder("res_in_2", "values"); tmp.newFolder("res_in_2", "drawable"); tmp.newFile("res_in_2/drawable/two.png"); filesystem.writeContentsToPath( RESOURCES_XML_HEADER + "<string name=\"override_me\">one</string>\n" + "<string name=\"only_in_first\">first</string>\n" + RESOURCES_XML_FOOTER, Paths.get("res_in_1/values/strings.xml")); filesystem.writeContentsToPath( RESOURCES_XML_HEADER + "<string name=\"override_me\">two</string>\n" + "<string name=\"only_in_second\">second</string>\n" + RESOURCES_XML_FOOTER, Paths.get("res_in_2/values/strings.xml")); filesystem.writeContentsToPath("png, trust me", Paths.get("res_in_1/drawable/one.png")); filesystem.writeContentsToPath("png, trust me", Paths.get("res_in_2/drawable/two.png")); } @Test @SuppressWarnings("unchecked") public void testRuleStepCreation() throws IOException, InterruptedException { BuildRuleParams buildRuleParams = new FakeBuildRuleParamsBuilder("//:output_folder").setProjectFilesystem(filesystem).build(); ImmutableList<SourcePath> directories = ImmutableList.of( new FakeSourcePath(filesystem, "res_in_1"), new FakeSourcePath(filesystem, "res_in_2")); SourcePathResolver pathResolver = new SourcePathResolver( new SourcePathRuleFinder( new BuildRuleResolver( TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))); MergeAndroidResourceSources mergeAndroidResourceSourcesStep = new MergeAndroidResourceSources(buildRuleParams, directories); ImmutableList<Step> steps = mergeAndroidResourceSourcesStep.getBuildSteps( FakeBuildContext.withSourcePathResolver(pathResolver), new FakeBuildableContext()); assertThat( steps, Matchers.contains( Matchers.instanceOf(RmStep.class), Matchers.instanceOf(MkdirStep.class), Matchers.instanceOf(MergeAndroidResourceSourcesStep.class))); String resIn1 = filesystem.getRootPath().resolve("res_in_1").toString(); String resIn2 = filesystem.getRootPath().resolve("res_in_2").toString(); assertThat( FluentIterable.from(steps).transform(stepDescriptionFunction), Matchers.contains( Matchers.containsString("rm"), Matchers.containsString("mkdir"), Matchers.startsWith(String.format("merge-resources %s,%s -> ", resIn1, resIn2)))); } @Test public void testStepExecution() throws IOException, InterruptedException { Path rootPath = tmp.getRoot().toPath(); File outFolder = tmp.newFolder("out"); File tmpFolder = tmp.newFolder("tmp"); MergeAndroidResourceSourcesStep step = MergeAndroidResourceSourcesStep.builder() .setResPaths( ImmutableList.of(rootPath.resolve("res_in_1"), rootPath.resolve("res_in_2"))) .setOutFolderPath(outFolder.toPath()) .setTmpFolderPath(tmpFolder.toPath()) .build(); step.execute(context); assertThat( filesystem.getFilesUnderPath(outFolder.toPath()), Matchers.containsInAnyOrder( Paths.get("out", "drawable", "one.png"), Paths.get("out", "drawable", "two.png"), Paths.get("out", "values", "values.xml"))); assertThat( filesystem.readFileIfItExists(outFolder.toPath().resolve("values/values.xml")).get(), Matchers.equalTo( RESOURCES_XML_HEADER + " <string name=\"only_in_first\">first</string>\n" + " <string name=\"only_in_second\">second</string>\n" + " <string name=\"override_me\">two</string>\n" + RESOURCES_XML_FOOTER)); } }