blob: 9e711295bb335bb304ba75a9ea7716f35b5076d5 [file] [log] [blame]
// Copyright 2019 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.execlog;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.exec.Protos.File;
import com.google.devtools.build.lib.exec.Protos.SpawnExec;
import com.google.devtools.build.lib.util.io.MessageOutputStream;
import com.google.protobuf.Message;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for {@link StableSort}. */
@RunWith(JUnit4.class)
public final class StableSortTest {
private static class ListOutput implements MessageOutputStream {
public ArrayList<SpawnExec> list;
ListOutput() {
list = new ArrayList<>();
}
@Override
public void write(Message m) throws IOException {
Preconditions.checkNotNull(m);
Preconditions.checkArgument(m instanceof SpawnExec);
list.add((SpawnExec) m);
}
@Override
public void close() throws IOException {}
}
ArrayList<SpawnExec> testStableSort(List<SpawnExec> list) throws Exception {
ListOutput o = new ListOutput();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (SpawnExec spawn : list) {
spawn.writeDelimitedTo(baos);
}
InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
StableSort.stableSort(inputStream, o);
return o.list;
}
private static SpawnExec.Builder createSpawnExecBuilder(
List<String> inputs, List<String> outputs) {
SpawnExec.Builder e = SpawnExec.newBuilder();
for (String output : outputs) {
e.addActualOutputsBuilder().setPath(output).build();
e.addListedOutputs(output);
}
for (String s : inputs) {
e.addInputs(File.newBuilder().setPath(s).build());
}
return e;
}
private static SpawnExec createSpawnExec(List<String> inputs, List<String> outputs) {
return createSpawnExecBuilder(inputs, outputs).build();
}
@Test
public void stableSortEmpty() throws Exception {
List<SpawnExec> l = testStableSort(ImmutableList.of());
assertThat(l).isEmpty();
}
@Test
public void stableSortOne() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of(), ImmutableList.of("output"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e1));
assertThat(l).containsExactly(e1).inOrder();
}
@Test
public void stableSortTwo_unlinkedLexicographic() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("a"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("leaf2"), ImmutableList.of("b"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e1, e2));
assertThat(l).containsExactly(e1, e2).inOrder();
}
@Test
public void stableSortTwo_unlinkedLexicographic_reverse() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("b"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("leaf2"), ImmutableList.of("a"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e1, e2));
assertThat(l).containsExactly(e2, e1).inOrder();
}
@Test
public void stableSortTwo_linked() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("b"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("b"), ImmutableList.of("a"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e1, e2));
assertThat(l).containsExactly(e1, e2).inOrder();
}
@Test
public void stableSortTwo_linked_inputOrderDoesNotMatter() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("b"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("b"), ImmutableList.of("a"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e2, e1));
assertThat(l).containsExactly(e1, e2).inOrder();
}
@Test
public void stableSortTwo_oneOfMultipleInputs() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("b1", "b2", "b3"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("b2"), ImmutableList.of("a"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e2, e1));
assertThat(l).containsExactly(e1, e2).inOrder();
}
@Test
public void stableSortTwo_manyOfMultipleInputs() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("b1", "b2", "b3"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("b2", "b3"), ImmutableList.of("a"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e2, e1));
assertThat(l).containsExactly(e1, e2).inOrder();
}
@Test
public void stableSortTwo_IrrelevantInputs() throws Exception {
SpawnExec e1 = createSpawnExec(ImmutableList.of("leaf1"), ImmutableList.of("b1", "b2", "b3"));
SpawnExec e2 = createSpawnExec(ImmutableList.of("z", "b2", "1"), ImmutableList.of("a"));
List<SpawnExec> l = testStableSort(ImmutableList.of(e2, e1));
assertThat(l).containsExactly(e1, e2).inOrder();
}
@Test
public void stableSortTwo_ABC() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of(""), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of(""), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c));
assertThat(l).containsExactly(a, b, c).inOrder();
}
@Test
public void stableSortTwo_CBA() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("b"), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of("c"), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c));
assertThat(l).containsExactly(c, b, a).inOrder();
}
@Test
public void stableSortTwo_ACB() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of(""), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of("a", "c"), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c));
assertThat(l).containsExactly(a, c, b).inOrder();
}
@Test
public void stableSortTwo_CAB() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("c"), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of("c"), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c));
assertThat(l).containsExactly(c, a, b).inOrder();
}
@Test
public void stableSortTwo_CAB2() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("c1"), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of("c2"), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c1", "c2"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c));
assertThat(l).containsExactly(c, a, b).inOrder();
}
@Test
public void stableSortTwo_CBAFED() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("b"), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of("c"), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c"));
SpawnExec d = createSpawnExec(ImmutableList.of("e"), ImmutableList.of("d"));
SpawnExec e = createSpawnExec(ImmutableList.of("f"), ImmutableList.of("e"));
SpawnExec f = createSpawnExec(ImmutableList.of(""), ImmutableList.of("f"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c, d, e, f));
assertThat(l).containsExactly(c, b, a, f, e, d).inOrder();
}
@Test
public void stableSortTwo_InterleavedPaths() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("c"), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of(""), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of(""), ImmutableList.of("c"));
SpawnExec d = createSpawnExec(ImmutableList.of("a"), ImmutableList.of("d"));
SpawnExec e = createSpawnExec(ImmutableList.of("f"), ImmutableList.of("e"));
SpawnExec f = createSpawnExec(ImmutableList.of("b"), ImmutableList.of("f"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c, d, e, f));
assertThat(l).containsExactly(b, c, a, d, f, e).inOrder();
}
@Test
public void stableSortTwo_ManyDependencies() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("b", "c", "f"), ImmutableList.of("a"));
SpawnExec b = createSpawnExec(ImmutableList.of("d", "e"), ImmutableList.of("b"));
SpawnExec c = createSpawnExec(ImmutableList.of("e", "d", "f"), ImmutableList.of("c"));
SpawnExec d = createSpawnExec(ImmutableList.of(""), ImmutableList.of("d"));
SpawnExec e = createSpawnExec(ImmutableList.of("f"), ImmutableList.of("e"));
SpawnExec f = createSpawnExec(ImmutableList.of(""), ImmutableList.of("f"));
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c, d, e, f));
assertThat(l).containsExactly(d, f, e, b, c, a).inOrder();
}
@Test
public void stableSort_NoOutputs() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("a"), ImmutableList.of());
SpawnExec b = createSpawnExec(ImmutableList.of("b"), ImmutableList.of());
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b));
assertThat(l).containsExactly(a, b).inOrder();
}
@Test
public void stableSort_NoOutputs_reversed() throws Exception {
SpawnExec a = createSpawnExec(ImmutableList.of("a"), ImmutableList.of());
SpawnExec b = createSpawnExec(ImmutableList.of("b"), ImmutableList.of());
List<SpawnExec> l = testStableSort(ImmutableList.of(b, a));
assertThat(l).containsExactly(a, b).inOrder();
}
@Test
public void stableSort_ListedOutputs() throws Exception {
SpawnExec a =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("a"))
.addCommandArgs("a")
.build();
SpawnExec b =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("b").build();
SpawnExec c =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("c"))
.addCommandArgs("c")
.build();
SpawnExec d =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("d"))
.addCommandArgs("d")
.build();
SpawnExec e =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("e").build();
SpawnExec f =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("f").build();
List<SpawnExec> l = testStableSort(ImmutableList.of(a, b, c, d, e, f));
assertThat(l)
.containsExactly(
// sorted elements with actual outputs
a,
c,
d,
// sorted elements without listed outputs
b,
e,
f)
.inOrder();
}
@Test
public void stableSort_ListedOutputs_reordered() throws Exception {
SpawnExec a =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("a"))
.addCommandArgs("a")
.build();
SpawnExec b =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("b").build();
SpawnExec c =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("c"))
.addCommandArgs("c")
.build();
SpawnExec d =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("d"))
.addCommandArgs("d")
.build();
SpawnExec e =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("e").build();
SpawnExec f =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("f").build();
// Reordering the input from the previous test does not change the resulting order
List<SpawnExec> l = testStableSort(ImmutableList.of(f, e, d, c, b, a));
assertThat(l)
.containsExactly(
// sorted elements with actual outputs
a,
c,
d,
// sorted elements without listed outputs
b,
e,
f)
.inOrder();
}
@Test
public void stableSort_ListedOutputs_dependencies() throws Exception {
// Dependencies are respected
SpawnExec a =
createSpawnExecBuilder(ImmutableList.of("d"), ImmutableList.of("a"))
.addCommandArgs("a")
.build();
SpawnExec b =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("b").build();
SpawnExec c =
createSpawnExecBuilder(ImmutableList.of("d"), ImmutableList.of("c"))
.addCommandArgs("c")
.build();
SpawnExec d =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of("d"))
.addCommandArgs("d")
.build();
SpawnExec e =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("e").build();
SpawnExec f =
createSpawnExecBuilder(ImmutableList.of(), ImmutableList.of()).addCommandArgs("f").build();
List<SpawnExec> l = testStableSort(ImmutableList.of(f, e, d, c, b, a));
assertThat(l).containsExactly(d, a, c, b, e, f).inOrder();
}
}