/* * Copyright 2016-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.versions; import static org.hamcrest.junit.MatcherAssert.assertThat; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.rules.TargetGraphAndBuildTargets; import com.facebook.buck.rules.TargetNode; import com.facebook.buck.rules.coercer.DefaultTypeCoercerFactory; import com.facebook.buck.testutil.TargetGraphFactory; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Maps; import java.lang.reflect.Field; import java.util.Map; import java.util.concurrent.ForkJoinPool; import org.hamcrest.Matchers; import org.junit.Test; public class VersionedTargetGraphBuilderTest { private static final ForkJoinPool POOL = new ForkJoinPool(1); private static String getVersionedTarget( BuildTarget target, ImmutableSortedMap<BuildTarget, Version> versions) { return target .withAppendedFlavors(VersionedTargetGraphBuilder.getVersionedFlavor(versions)) .toString(); } private static String getVersionedTarget(String target, String dep, String version) { return getVersionedTarget( BuildTargetFactory.newInstance(target), ImmutableSortedMap.of(BuildTargetFactory.newInstance(dep), Version.of(version))); } private static void assertEquals(TargetNode<?, ?> expected, TargetNode<?, ?> actual) { assertThat(actual.getBuildTarget(), Matchers.equalTo(expected.getBuildTarget())); assertThat( String.format("%s: declared deps: ", expected.getBuildTarget()), actual.getDeclaredDeps(), Matchers.equalTo(expected.getDeclaredDeps())); assertThat( String.format("%s: extra deps: ", expected.getBuildTarget()), actual.getExtraDeps(), Matchers.equalTo(expected.getExtraDeps())); assertThat( String.format("%s: inputs: ", expected.getBuildTarget()), actual.getInputs(), Matchers.equalTo(expected.getInputs())); for (Field field : actual.getConstructorArg().getClass().getFields()) { if (!field.getName().equals("selectedVersions")) { try { assertThat( field.get(actual.getConstructorArg()), Matchers.equalTo(field.get(expected.getConstructorArg()))); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } } private static void assertEquals(TargetGraph expected, TargetGraph actual) { ImmutableMap<BuildTarget, TargetNode<?, ?>> expectedNodes = Maps.uniqueIndex(expected.getNodes(), TargetNode::getBuildTarget); ImmutableMap<BuildTarget, TargetNode<?, ?>> actualNodes = Maps.uniqueIndex(actual.getNodes(), TargetNode::getBuildTarget); assertThat(actualNodes.keySet(), Matchers.equalTo(expectedNodes.keySet())); for (Map.Entry<BuildTarget, TargetNode<?, ?>> ent : expectedNodes.entrySet()) { assertEquals(ent.getValue(), actualNodes.get(ent.getKey())); } } @Test public void singleRootNode() throws Exception { TargetNode<?, ?> root = new VersionRootBuilder("//:root").build(); TargetGraph graph = TargetGraphFactory.newInstance(root); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of(graph, ImmutableSet.of(root.getBuildTarget())), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); assertEquals(graph, versionedGraph); } @Test public void rootWithDepOnRoot() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionRootBuilder("//:root2").build(), new VersionRootBuilder("//:root1").setDeps("//:root2").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of( BuildTargetFactory.newInstance("//:root1"), BuildTargetFactory.newInstance("//:root2"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); assertEquals(graph, versionedGraph); } @Test public void versionedSubGraph() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep").build(), new VersionedAliasBuilder("//:versioned").setVersions("1.0", "//:dep").build(), new VersionRootBuilder("//:root").setDeps("//:versioned").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of(BuildTargetFactory.newInstance("//:root"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); TargetGraph expectedTargetGraph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep").build(), new VersionRootBuilder("//:root").setDeps("//:dep").build()); assertEquals(expectedTargetGraph, versionedGraph); } @Test public void versionedSubGraphWithDepOnRoot() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionRootBuilder("//:dep_root").build(), new VersionPropagatorBuilder("//:dep").setDeps("//:dep_root").build(), new VersionedAliasBuilder("//:versioned").setVersions("1.0", "//:dep").build(), new VersionRootBuilder("//:root").setDeps("//:versioned").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of(BuildTargetFactory.newInstance("//:root"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); TargetGraph expectedTargetGraph = TargetGraphFactory.newInstance( new VersionRootBuilder("//:dep_root").build(), new VersionPropagatorBuilder("//:dep").setDeps("//:dep_root").build(), new VersionRootBuilder("//:root").setDeps("//:dep").build()); assertEquals(expectedTargetGraph, versionedGraph); } @Test public void versionedSubGraphWithDepAnotherVersionedSubGraph() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep2").build(), new VersionedAliasBuilder("//:versioned2").setVersions("1.0", "//:dep2").build(), new VersionRootBuilder("//:root2").setDeps("//:versioned2").build(), new VersionPropagatorBuilder("//:dep1").setDeps("//:root2").build(), new VersionedAliasBuilder("//:versioned1").setVersions("1.0", "//:dep1").build(), new VersionRootBuilder("//:root1").setDeps("//:versioned1").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of(BuildTargetFactory.newInstance("//:root1"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); TargetGraph expectedTargetGraph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep2").build(), new VersionRootBuilder("//:root2").setDeps("//:dep2").build(), new VersionPropagatorBuilder("//:dep1").setDeps("//:root2").build(), new VersionRootBuilder("//:root1").setDeps("//:dep1").build()); assertEquals(expectedTargetGraph, versionedGraph); } @Test public void versionedSubGraphWithVersionedFlavor() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep").build(), new VersionedAliasBuilder("//:versioned").setVersions("1.0", "//:dep").build(), new VersionPropagatorBuilder("//:a").setDeps("//:versioned").build(), new VersionRootBuilder("//:root").setDeps("//:a").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of(BuildTargetFactory.newInstance("//:root"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); TargetGraph expectedTargetGraph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep").build(), new VersionPropagatorBuilder(getVersionedTarget("//:a", "//:versioned", "1.0")) .setDeps("//:dep") .build(), new VersionRootBuilder("//:root") .setDeps(getVersionedTarget("//:a", "//:versioned", "1.0")) .build()); assertEquals(expectedTargetGraph, versionedGraph); } @Test public void versionedSubGraphWithConstraints() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:v2").build(), new VersionPropagatorBuilder("//:v1").build(), new VersionedAliasBuilder("//:dep").setVersions("1.0", "//:v1", "2.0", "//:v2").build(), new VersionPropagatorBuilder("//:lib").setDeps("//:dep").build(), new VersionRootBuilder("//:a") .setDeps("//:lib") .setVersionedDeps("//:dep", ExactConstraint.of(Version.of("1.0"))) .build(), new VersionRootBuilder("//:b") .setDeps("//:lib") .setVersionedDeps("//:dep", ExactConstraint.of(Version.of("2.0"))) .build()); BuildTarget a = BuildTargetFactory.newInstance("//:a"); BuildTarget b = BuildTargetFactory.newInstance("//:b"); BuildTarget dep = BuildTargetFactory.newInstance("//:dep"); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new FixedVersionSelector( ImmutableMap.of( a, ImmutableMap.of(dep, Version.of("1.0")), b, ImmutableMap.of(dep, Version.of("2.0")))), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of( BuildTargetFactory.newInstance("//:a"), BuildTargetFactory.newInstance("//:b"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); TargetGraph expectedTargetGraph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:v1").build(), new VersionPropagatorBuilder(getVersionedTarget("//:lib", "//:dep", "1.0")) .setDeps("//:v1") .build(), new VersionRootBuilder("//:a") .setDeps(getVersionedTarget("//:lib", "//:dep", "1.0")) .setVersionedDeps("//:v1", ExactConstraint.of(Version.of("1.0"))) .build(), new VersionPropagatorBuilder("//:v2").build(), new VersionPropagatorBuilder(getVersionedTarget("//:lib", "//:dep", "2.0")) .setDeps("//:v2") .build(), new VersionRootBuilder("//:b") .setDeps(getVersionedTarget("//:lib", "//:dep", "2.0")) .setVersionedDeps("//:v2", ExactConstraint.of(Version.of("2.0"))) .build()); assertEquals(expectedTargetGraph, versionedGraph); } @Test public void explicitNonRootTreatedAsRoot() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep").build(), new VersionedAliasBuilder("//:versioned").setVersions("1.0", "//:dep").build(), new VersionPropagatorBuilder("//:root").setDeps("//:versioned").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of(BuildTargetFactory.newInstance("//:root"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); TargetGraph expectedTargetGraph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:dep").build(), new VersionPropagatorBuilder("//:root").setDeps("//:dep").build()); assertEquals(expectedTargetGraph, versionedGraph); } @Test public void nodeWithTestParameterReferringToNonExistentTarget() throws Exception { TargetGraph graph = TargetGraphFactory.newInstance( new VersionPropagatorBuilder("//:root2") .setTests(ImmutableSortedSet.of(BuildTargetFactory.newInstance("//:test"))) .build(), new VersionRootBuilder("//:root1").setDeps("//:root2").build()); VersionedTargetGraphBuilder builder = new VersionedTargetGraphBuilder( POOL, new NaiveVersionSelector(), TargetGraphAndBuildTargets.of( graph, ImmutableSet.of( BuildTargetFactory.newInstance("//:root1"), BuildTargetFactory.newInstance("//:root2"))), new DefaultTypeCoercerFactory()); TargetGraph versionedGraph = builder.build(); assertEquals(graph, versionedGraph); } }