blob: a09271619804204c262ba1cc575065136aa2dd5a [file] [log] [blame]
// Copyright 2022 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.bazel.commands;
import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.AugmentedModuleBuilder.buildAugmentedModule;
import static com.google.devtools.build.lib.bazel.bzlmod.BzlmodTestUtil.createModuleKey;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.bazel.bzlmod.BazelModuleInspectorValue.AugmentedModule;
import com.google.devtools.build.lib.bazel.bzlmod.ModuleKey;
import com.google.devtools.build.lib.bazel.bzlmod.Version;
import com.google.devtools.build.lib.bazel.bzlmod.Version.ParseException;
import com.google.devtools.build.lib.bazel.commands.ModqueryExecutor.ResultNode;
import com.google.devtools.build.lib.bazel.commands.ModqueryExecutor.ResultNode.IsExpanded;
import java.io.StringWriter;
import java.io.Writer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for {@link ModqueryExecutor}. */
@RunWith(JUnit4.class)
public class ModqueryExecutorTest {
private final Writer writer = new StringWriter();
// Tests for the ModqueryExecutor::expandAndPrune core function.
//
// (* In the ASCII graph hints "__>" or "-->" mean a direct edge, while "..>" means an indirect
// edge. "aaa ..." means module "aaa" is unexpanded.)
@Test
public void testExpandFromTargetsFirst() throws ParseException {
// aaa -> bbb -> ccc -> ddd
ImmutableMap<ModuleKey, AugmentedModule> depGraph =
new ImmutableMap.Builder<ModuleKey, AugmentedModule>()
.put(
buildAugmentedModule(ModuleKey.ROOT, "aaa", Version.parse("1.0"), true)
.addDep("bbb", "1.0")
.buildEntry())
.put(
buildAugmentedModule("bbb", "1.0")
.addStillDependant(ModuleKey.ROOT)
.addDep("ccc", "1.0")
.buildEntry())
.put(
buildAugmentedModule("ccc", "1.0")
.addStillDependant("bbb", "1.0")
.addDep("ddd", "1.0")
.buildEntry())
.put(buildAugmentedModule("ddd", "1.0").addStillDependant("ccc", "1.0").buildEntry())
.buildOrThrow();
ModqueryOptions options = ModqueryOptions.getDefaultOptions();
ModqueryExecutor executor = new ModqueryExecutor(depGraph, options, writer);
// RESULT:
// <root> ...> ccc -> ddd
// \___> bbb -> ccc ...
assertThat(
executor.expandAndPrune(
ImmutableSet.of(ModuleKey.ROOT, createModuleKey("ccc", "1.0")),
ImmutableSet.of(),
false))
.containsExactly(
ModuleKey.ROOT,
ResultNode.builder()
.addChild(createModuleKey("bbb", "1.0"), IsExpanded.TRUE)
.addIndirectChild(createModuleKey("ccc", "1.0"), IsExpanded.TRUE)
.build(),
createModuleKey("bbb", "1.0"),
ResultNode.builder().addChild(createModuleKey("ccc", "1.0"), IsExpanded.FALSE).build(),
createModuleKey("ccc", "1.0"),
ResultNode.builder().addChild(createModuleKey("ddd", "1.0"), IsExpanded.TRUE).build(),
createModuleKey("ddd", "1.0"),
ResultNode.builder().build());
}
@Test
public void testPathsDepth1_containsAllTargetsWithNestedIndirect() throws ParseException {
// <root> -> bbb -> ccc -> ddd -> eee -> fff -> ggg -> hhh
// ^ /
// \___/
ImmutableMap<ModuleKey, AugmentedModule> depGraph =
new ImmutableMap.Builder<ModuleKey, AugmentedModule>()
.put(
buildAugmentedModule(ModuleKey.ROOT, "aaa", Version.parse("1.0"), true)
.addDep("bbb", "1.0")
.buildEntry())
.put(
buildAugmentedModule("bbb", "1.0")
.addStillDependant(ModuleKey.ROOT)
.addDep("ccc", "1.0")
.buildEntry())
.put(
buildAugmentedModule("ccc", "1.0")
.addStillDependant("bbb", "1.0")
.addDep("ddd", "1.0")
.buildEntry())
.put(
buildAugmentedModule("ddd", "1.0")
.addStillDependant("ccc", "1.0")
.addStillDependant("eee", "1.0")
.addDep("eee", "1.0")
.buildEntry())
.put(
buildAugmentedModule("eee", "1.0")
.addStillDependant("ddd", "1.0")
.addDep("fff", "1.0")
.addDep("ddd", "1.0")
.buildEntry())
.put(
buildAugmentedModule("fff", "1.0")
.addStillDependant("eee", "1.0")
.addDep("ggg", "1.0")
.buildEntry())
.put(
buildAugmentedModule("ggg", "1.0")
.addStillDependant("fff", "1.0")
.addDep("hhh", "1.0")
.buildEntry())
.put(buildAugmentedModule("hhh", "1.0").addStillDependant("ggg", "1.0").buildEntry())
.buildOrThrow();
ModqueryOptions options = ModqueryOptions.getDefaultOptions();
options.cycles = true;
options.depth = 1;
ModqueryExecutor executor = new ModqueryExecutor(depGraph, options, writer);
ImmutableSet<ModuleKey> targets =
ImmutableSet.of(createModuleKey("eee", "1.0"), createModuleKey("hhh", "1.0"));
// RESULT:
// <root> --> bbb ..> ddd --> eee --> ddd (cycle)
// \..> ggg --> hhh
assertThat(executor.expandAndPrune(ImmutableSet.of(ModuleKey.ROOT), targets, false))
.containsExactly(
ModuleKey.ROOT,
ResultNode.builder().addChild(createModuleKey("bbb", "1.0"), IsExpanded.TRUE).build(),
createModuleKey("bbb", "1.0"),
ResultNode.builder()
.addIndirectChild(createModuleKey("ddd", "1.0"), IsExpanded.TRUE)
.build(),
createModuleKey("ddd", "1.0"),
ResultNode.builder().addChild(createModuleKey("eee", "1.0"), IsExpanded.TRUE).build(),
createModuleKey("eee", "1.0"),
ResultNode.builder()
.setTarget(true)
.addIndirectChild(createModuleKey("ggg", "1.0"), IsExpanded.TRUE)
.addChild(createModuleKey("ddd", "1.0"), IsExpanded.FALSE)
.build(),
createModuleKey("ggg", "1.0"),
ResultNode.builder().addChild(createModuleKey("hhh", "1.0"), IsExpanded.TRUE).build(),
createModuleKey("hhh", "1.0"),
ResultNode.builder().setTarget(true).build());
}
@Test
public void testPathsDepth1_targetParentIsDirectAndIndirectChild() throws ParseException {
// <root> --> bbb --> ccc
// \ |________
// \ V |
// \__> ddd --> eee
ImmutableMap<ModuleKey, AugmentedModule> depGraph =
new ImmutableMap.Builder<ModuleKey, AugmentedModule>()
.put(
buildAugmentedModule(ModuleKey.ROOT, "aaa", Version.parse("1.0"), true)
.addDep("bbb", "1.0")
.buildEntry())
.put(
buildAugmentedModule("bbb", "1.0")
.addStillDependant(ModuleKey.ROOT)
.addDep("ccc", "1.0")
.addDep("ddd", "1.0")
.buildEntry())
.put(
buildAugmentedModule("ccc", "1.0")
.addStillDependant("bbb", "1.0")
.addDep("ddd", "1.0")
.buildEntry())
.put(
buildAugmentedModule("ddd", "1.0")
.addStillDependant("bbb", "1.0")
.addStillDependant("ccc", "1.0")
.addStillDependant("eee", "1.0")
.addDep("eee", "1.0")
.buildEntry())
.put(
buildAugmentedModule("eee", "1.0")
.addStillDependant("ddd", "1.0")
.addStillDependant("eee", "1.0")
.addDep("ddd", "1.0")
.buildEntry())
.buildOrThrow();
ModqueryOptions options = ModqueryOptions.getDefaultOptions();
options.cycles = true;
options.depth = 1;
ModqueryExecutor executor = new ModqueryExecutor(depGraph, options, writer);
ImmutableSet<ModuleKey> targets = ImmutableSet.of(createModuleKey("eee", "1.0"));
// RESULT:
// <root> --> bbb --- ddd --> eee --> ddd (c)
// \
// \..> ddd ...
assertThat(executor.expandAndPrune(ImmutableSet.of(ModuleKey.ROOT), targets, false))
.containsExactly(
ModuleKey.ROOT,
ResultNode.builder().addChild(createModuleKey("bbb", "1.0"), IsExpanded.TRUE).build(),
createModuleKey("bbb", "1.0"),
ResultNode.builder()
.addChild(createModuleKey("ddd", "1.0"), IsExpanded.TRUE)
.addIndirectChild(createModuleKey("ddd", "1.0"), IsExpanded.FALSE)
.build(),
createModuleKey("ddd", "1.0"),
ResultNode.builder().addChild(createModuleKey("eee", "1.0"), IsExpanded.TRUE).build(),
createModuleKey("eee", "1.0"),
ResultNode.builder()
.setTarget(true)
.addChild(createModuleKey("ddd", "1.0"), IsExpanded.FALSE)
.build());
}
// TODO(andreisolo): Add more eventual edge-case tests for the #expandAndPrune core method
}