/*
* 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.apple.project_generator;
import static org.junit.Assert.assertEquals;
import com.facebook.buck.apple.AppleBinaryBuilder;
import com.facebook.buck.apple.AppleBundleBuilder;
import com.facebook.buck.apple.AppleBundleExtension;
import com.facebook.buck.apple.AppleLibraryBuilder;
import com.facebook.buck.apple.AppleTestBuilder;
import com.facebook.buck.apple.XcodeWorkspaceConfigBuilder;
import com.facebook.buck.apple.XcodeWorkspaceConfigDescription;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.event.BuckEventBusFactory;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.Either;
import com.facebook.buck.rules.Cell;
import com.facebook.buck.rules.FakeSourcePath;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetGraphAndTargets;
import com.facebook.buck.rules.TargetNode;
import com.facebook.buck.rules.TestCellBuilder;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.TargetGraphFactory;
import com.facebook.buck.timing.SettableFakeClock;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
public class XCodeProjectCommandHelperTest {
private TargetNode<?, ?> barLibNode;
private TargetNode<?, ?> fooLibNode;
private TargetNode<?, ?> fooBinBinaryNode;
private TargetNode<?, ?> fooBinNode;
private TargetNode<?, ?> bazLibNode;
private TargetNode<?, ?> bazTestNode;
private TargetNode<?, ?> fooTestNode;
private TargetNode<?, ?> fooBinTestNode;
private TargetNode<?, ?> quxBinNode;
private TargetNode<?, ?> workspaceNode;
private TargetNode<?, ?> workspaceExtraTestNode;
private TargetNode<?, ?> smallWorkspaceNode;
private TargetGraph targetGraph;
@Before
public void buildGraph() {
// Create the following dep tree:
//
// FooBin -has-test-> FooBinTest
// |
// V
// FooLib -has-test-> FooLibTest
// | |
// V V
// BarLib BazLib -has-test-> BazLibTest
// ^
// |
// QuxBin
//
// FooBin and BazLib and FooLibTest use "tests" to specify their tests.
BuildTarget bazTestTarget = BuildTargetFactory.newInstance("//baz:xctest");
BuildTarget fooBinTestTarget = BuildTargetFactory.newInstance("//foo:bin-xctest");
BuildTarget barLibTarget = BuildTargetFactory.newInstance("//bar:lib");
barLibNode = AppleLibraryBuilder.createBuilder(barLibTarget).build();
BuildTarget bazLibTarget = BuildTargetFactory.newInstance("//baz:lib");
bazLibNode =
AppleLibraryBuilder.createBuilder(bazLibTarget)
.setTests(ImmutableSortedSet.of(bazTestTarget))
.build();
BuildTarget fooTestTarget = BuildTargetFactory.newInstance("//foo:lib-xctest");
fooTestNode =
AppleTestBuilder.createBuilder(fooTestTarget)
.setDeps(ImmutableSortedSet.of(bazLibTarget))
.setInfoPlist(new FakeSourcePath("Info.plist"))
.build();
BuildTarget fooLibTarget = BuildTargetFactory.newInstance("//foo:lib");
fooLibNode =
AppleLibraryBuilder.createBuilder(fooLibTarget)
.setDeps(ImmutableSortedSet.of(barLibTarget))
.setTests(ImmutableSortedSet.of(fooTestTarget))
.build();
BuildTarget fooBinBinaryTarget = BuildTargetFactory.newInstance("//foo:binbinary");
fooBinBinaryNode =
AppleBinaryBuilder.createBuilder(fooBinBinaryTarget)
.setDeps(ImmutableSortedSet.of(fooLibTarget))
.build();
BuildTarget fooBinTarget = BuildTargetFactory.newInstance("//foo:bin");
fooBinNode =
AppleBundleBuilder.createBuilder(fooBinTarget)
.setExtension(Either.ofLeft(AppleBundleExtension.APP))
.setBinary(fooBinBinaryTarget)
.setTests(ImmutableSortedSet.of(fooBinTestTarget))
.setInfoPlist(new FakeSourcePath("Info.plist"))
.build();
bazTestNode =
AppleTestBuilder.createBuilder(bazTestTarget)
.setDeps(ImmutableSortedSet.of(bazLibTarget))
.setInfoPlist(new FakeSourcePath("Info.plist"))
.build();
fooBinTestNode =
AppleTestBuilder.createBuilder(fooBinTestTarget)
.setDeps(ImmutableSortedSet.of(fooBinTarget))
.setInfoPlist(new FakeSourcePath("Info.plist"))
.build();
BuildTarget quxBinTarget = BuildTargetFactory.newInstance("//qux:bin");
quxBinNode =
AppleBinaryBuilder.createBuilder(quxBinTarget)
.setDeps(ImmutableSortedSet.of(barLibTarget))
.build();
BuildTarget workspaceExtraTestTarget = BuildTargetFactory.newInstance("//foo:extra-xctest");
workspaceExtraTestNode =
AppleTestBuilder.createBuilder(workspaceExtraTestTarget)
.setInfoPlist(new FakeSourcePath("Info.plist"))
.build();
BuildTarget workspaceTarget = BuildTargetFactory.newInstance("//foo:workspace");
workspaceNode =
XcodeWorkspaceConfigBuilder.createBuilder(workspaceTarget)
.setWorkspaceName(Optional.of("workspace"))
.setSrcTarget(Optional.of(fooBinTarget))
.setExtraTests(ImmutableSortedSet.of(workspaceExtraTestTarget))
.build();
BuildTarget smallWorkspaceTarget = BuildTargetFactory.newInstance("//baz:small-workspace");
smallWorkspaceNode =
XcodeWorkspaceConfigBuilder.createBuilder(smallWorkspaceTarget)
.setWorkspaceName(Optional.of("small-workspace"))
.setSrcTarget(Optional.of(bazLibTarget))
.build();
targetGraph =
TargetGraphFactory.newInstance(
barLibNode,
fooLibNode,
fooBinBinaryNode,
fooBinNode,
bazLibNode,
bazTestNode,
fooTestNode,
fooBinTestNode,
quxBinNode,
workspaceExtraTestNode,
workspaceNode,
smallWorkspaceNode);
}
@Test
public void testCreateTargetGraphWithoutTests() {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(
targetGraph,
ImmutableSet.of(),
/* withTests = */ false,
/* withDependenciesTests = */ false);
assertEquals(
ImmutableSortedSet.<TargetNode<?, ?>>of(
workspaceNode,
fooBinNode,
fooBinBinaryNode,
fooLibNode,
barLibNode,
smallWorkspaceNode,
bazLibNode,
workspaceExtraTestNode),
ImmutableSortedSet.copyOf(targetGraphAndTargets.getTargetGraph().getNodes()));
}
@Test
public void testCreateTargetGraphWithTests() {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(
targetGraph,
ImmutableSet.of(),
/* withTests = */ true,
/* withDependenciesTests */ true);
assertEquals(
ImmutableSortedSet.<TargetNode<?, ?>>of(
workspaceNode,
fooBinNode,
fooBinBinaryNode,
fooLibNode,
fooBinTestNode,
fooTestNode,
barLibNode,
smallWorkspaceNode,
bazLibNode,
bazTestNode,
workspaceExtraTestNode),
ImmutableSortedSet.copyOf(targetGraphAndTargets.getTargetGraph().getNodes()));
}
@Test
public void testCreateTargetGraphForSliceWithoutTests() {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(
targetGraph,
ImmutableSet.of(workspaceNode.getBuildTarget()),
/* withTests = */ false,
/* withDependenciesTests */ false);
assertEquals(
ImmutableSortedSet.<TargetNode<?, ?>>of(
workspaceNode,
fooBinNode,
fooBinBinaryNode,
fooLibNode,
barLibNode,
workspaceExtraTestNode),
ImmutableSortedSet.copyOf(targetGraphAndTargets.getTargetGraph().getNodes()));
}
@Test
public void testCreateTargetGraphForSliceWithTests() {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(
targetGraph,
ImmutableSet.of(workspaceNode.getBuildTarget()),
/* withTests = */ true,
/* withDependenciesTests */ true);
assertEquals(
ImmutableSortedSet.<TargetNode<?, ?>>of(
workspaceNode,
fooBinNode,
fooBinBinaryNode,
fooLibNode,
fooBinTestNode,
fooTestNode,
barLibNode,
bazLibNode,
workspaceExtraTestNode),
ImmutableSortedSet.copyOf(targetGraphAndTargets.getTargetGraph().getNodes()));
}
@Test
public void testCreateTargetGraphForSmallSliceWithoutTests() {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(
targetGraph,
ImmutableSet.of(smallWorkspaceNode.getBuildTarget()),
/* withTests = */ false,
/* withDependenciesTests */ false);
assertEquals(
ImmutableSortedSet.of(smallWorkspaceNode, bazLibNode),
ImmutableSortedSet.copyOf(targetGraphAndTargets.getTargetGraph().getNodes()));
}
@Test
public void testCreateTargetGraphForSmallSliceWithTests() {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(
targetGraph,
ImmutableSet.of(smallWorkspaceNode.getBuildTarget()),
/* withTests = */ true,
/* withDependenciesTests */ true);
assertEquals(
ImmutableSortedSet.of(smallWorkspaceNode, bazLibNode, bazTestNode),
ImmutableSortedSet.copyOf(targetGraphAndTargets.getTargetGraph().getNodes()));
}
@Test
public void testTargetWithTests() throws IOException, InterruptedException {
Map<Path, ProjectGenerator> projectGenerators =
generateProjectsForTests(
ImmutableSet.of(fooBinNode.getBuildTarget()),
/* withTests = */ true,
/* withDependenciesTests */ true);
ProjectGeneratorTestUtils.assertTargetExists(
projectGenerators.get(Paths.get("foo")), "bin-xctest");
ProjectGeneratorTestUtils.assertTargetExists(
projectGenerators.get(Paths.get("foo")), "lib-xctest");
}
private Map<Path, ProjectGenerator> generateProjectsForTests(
ImmutableSet<BuildTarget> passedInTargetsSet,
boolean isWithTests,
boolean isWithDependenciesTests)
throws IOException, InterruptedException {
return generateWorkspacesForTargets(
targetGraph, passedInTargetsSet, isWithTests, isWithDependenciesTests);
}
@Test
public void testTargetWithoutDependenciesTests() throws IOException, InterruptedException {
Map<Path, ProjectGenerator> projectGenerators =
generateProjectsForTests(
ImmutableSet.of(fooBinNode.getBuildTarget()),
/* withTests = */ true,
/* withDependenciesTests */ false);
ProjectGeneratorTestUtils.assertTargetExists(
projectGenerators.get(Paths.get("foo")), "bin-xctest");
ProjectGeneratorTestUtils.assertTargetDoesNotExists(
projectGenerators.get(Paths.get("foo")), "lib-xctest");
}
@Test
public void testTargetWithoutTests() throws IOException, InterruptedException {
Map<Path, ProjectGenerator> projectGenerators =
generateProjectsForTests(
ImmutableSet.of(fooBinNode.getBuildTarget()),
/* withTests = */ false,
/* withDependenciesTests */ false);
ProjectGeneratorTestUtils.assertTargetDoesNotExists(
projectGenerators.get(Paths.get("foo")), "bin-xctest");
ProjectGeneratorTestUtils.assertTargetDoesNotExists(
projectGenerators.get(Paths.get("foo")), "lib-xctest");
}
@Test
public void testWorkspaceWithoutDependenciesTests() throws IOException, InterruptedException {
Map<Path, ProjectGenerator> projectGenerators =
generateProjectsForTests(
ImmutableSet.of(workspaceNode.getBuildTarget()),
/* withTests = */ true,
/* withDependenciesTests */ false);
ProjectGeneratorTestUtils.assertTargetExists(
projectGenerators.get(Paths.get("foo")), "bin-xctest");
ProjectGeneratorTestUtils.assertTargetDoesNotExists(
projectGenerators.get(Paths.get("foo")), "lib-xctest");
ProjectGeneratorTestUtils.assertTargetExists(
projectGenerators.get(Paths.get("foo")), "extra-xctest");
}
@Test
public void testWorkspaceWithoutExtraTestsWithoutDependenciesTests()
throws IOException, InterruptedException {
Map<Path, ProjectGenerator> projectGenerators =
generateProjectsForTests(
ImmutableSet.of(smallWorkspaceNode.getBuildTarget()),
/* withTests = */ true,
/* withDependenciesTests */ false);
ProjectGeneratorTestUtils.assertTargetExists(projectGenerators.get(Paths.get("baz")), "lib");
ProjectGeneratorTestUtils.assertTargetExists(projectGenerators.get(Paths.get("baz")), "xctest");
}
private static TargetGraphAndTargets createTargetGraph(
TargetGraph projectGraph,
ImmutableSet<BuildTarget> passedInTargetsSet,
boolean withTests,
boolean withDependenciesTests) {
ImmutableSet<BuildTarget> graphRoots;
if (!passedInTargetsSet.isEmpty()) {
graphRoots = passedInTargetsSet;
} else {
graphRoots =
XCodeProjectCommandHelper.getRootsFromPredicate(
projectGraph,
node -> node.getDescription() instanceof XcodeWorkspaceConfigDescription);
}
ImmutableSet<BuildTarget> graphRootsOrSourceTargets =
XCodeProjectCommandHelper.replaceWorkspacesWithSourceTargetsIfPossible(
graphRoots, projectGraph);
ImmutableSet<BuildTarget> explicitTests;
if (withTests) {
explicitTests =
XCodeProjectCommandHelper.getExplicitTestTargets(
graphRootsOrSourceTargets,
projectGraph,
withDependenciesTests,
FocusedModuleTargetMatcher.noFocus());
} else {
explicitTests = ImmutableSet.of();
}
return TargetGraphAndTargets.create(graphRoots, projectGraph, withTests, explicitTests);
}
private static Map<Path, ProjectGenerator> generateWorkspacesForTargets(
TargetGraph targetGraph,
ImmutableSet<BuildTarget> passedInTargetsSet,
boolean isWithTests,
boolean isWithDependenciesTests)
throws IOException, InterruptedException {
TargetGraphAndTargets targetGraphAndTargets =
createTargetGraph(targetGraph, passedInTargetsSet, isWithTests, isWithDependenciesTests);
Map<Path, ProjectGenerator> projectGenerators = new HashMap<>();
Cell cell =
new TestCellBuilder()
.setFilesystem(new FakeProjectFilesystem(new SettableFakeClock(0, 0)))
.build();
XCodeProjectCommandHelper.generateWorkspacesForTargets(
BuckEventBusFactory.newInstance(),
cell,
FakeBuckConfig.builder().build(),
MoreExecutors.newDirectExecutorService(),
targetGraphAndTargets,
passedInTargetsSet,
XCodeProjectCommandHelper.buildWorkspaceGeneratorOptions(
false,
isWithTests,
isWithDependenciesTests,
false,
true /* shouldUseHeaderMaps */,
false /* shouldMergeHeaderMaps */,
false /* shouldGenerateHeaderSymlinkTreeOnly */),
FocusedModuleTargetMatcher.noFocus(),
projectGenerators,
false);
return projectGenerators;
}
}