blob: 2c4c98fb5e3dbb158ced7ce19ddc0c1503d9e517 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// 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.gerrit.server.change;
import static com.google.common.collect.Collections2.permutations;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.change.WalkSorter.PatchSetData;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import com.google.gerrit.testing.InMemoryRepositoryManager.Repo;
import com.google.gerrit.testing.TestChanges;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;
public class WalkSorterTest {
private Account.Id userId;
private InMemoryRepositoryManager repoManager;
@Before
public void setUp() {
userId = Account.id(1);
repoManager = new InMemoryRepositoryManager();
}
@Test
public void seriesOfChanges() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c1_1 = p.commit().create();
RevCommit c2_1 = p.commit().parent(c1_1).create();
RevCommit c3_1 = p.commit().parent(c2_1).create();
ChangeData cd1 = newChange(p, c1_1);
ChangeData cd2 = newChange(p, c2_1);
ChangeData cd3 = newChange(p, c3_1);
List<ChangeData> changes = ImmutableList.of(cd1, cd2, cd3);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(
sorter,
changes,
ImmutableList.of(
patchSetData(cd3, c3_1), patchSetData(cd2, c2_1), patchSetData(cd1, c1_1)));
// Add new patch sets whose commits are in reverse order, so output is in
// reverse order.
RevCommit c3_2 = p.commit().create();
RevCommit c2_2 = p.commit().parent(c3_2).create();
RevCommit c1_2 = p.commit().parent(c2_2).create();
addPatchSet(cd1, c1_2);
addPatchSet(cd2, c2_2);
addPatchSet(cd3, c3_2);
assertSorted(
sorter,
changes,
ImmutableList.of(
patchSetData(cd1, c1_2), patchSetData(cd2, c2_2), patchSetData(cd3, c3_2)));
}
@Test
public void subsetOfSeriesOfChanges() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c1_1 = p.commit().create();
RevCommit c2_1 = p.commit().parent(c1_1).create();
RevCommit c3_1 = p.commit().parent(c2_1).create();
ChangeData cd1 = newChange(p, c1_1);
ChangeData cd3 = newChange(p, c3_1);
List<ChangeData> changes = ImmutableList.of(cd1, cd3);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(
sorter, changes, ImmutableList.of(patchSetData(cd3, c3_1), patchSetData(cd1, c1_1)));
}
@Test
public void seriesOfChangesAtSameTimestamp() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c0 = p.commit().tick(0).create();
RevCommit c1 = p.commit().tick(0).parent(c0).create();
RevCommit c2 = p.commit().tick(0).parent(c1).create();
RevCommit c3 = p.commit().tick(0).parent(c2).create();
RevCommit c4 = p.commit().tick(0).parent(c3).create();
RevWalk rw = p.getRevWalk();
rw.parseCommit(c1);
assertThat(rw.parseCommit(c2).getCommitTime()).isEqualTo(c1.getCommitTime());
assertThat(rw.parseCommit(c3).getCommitTime()).isEqualTo(c1.getCommitTime());
assertThat(rw.parseCommit(c4).getCommitTime()).isEqualTo(c1.getCommitTime());
ChangeData cd1 = newChange(p, c1);
ChangeData cd2 = newChange(p, c2);
ChangeData cd3 = newChange(p, c3);
ChangeData cd4 = newChange(p, c4);
List<ChangeData> changes = ImmutableList.of(cd1, cd2, cd3, cd4);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(
sorter,
changes,
ImmutableList.of(
patchSetData(cd4, c4),
patchSetData(cd3, c3),
patchSetData(cd2, c2),
patchSetData(cd1, c1)));
}
@Test
public void seriesOfChangesWithReverseTimestamps() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c0 = p.commit().tick(-1).create();
RevCommit c1 = p.commit().tick(-1).parent(c0).create();
RevCommit c2 = p.commit().tick(-1).parent(c1).create();
RevCommit c3 = p.commit().tick(-1).parent(c2).create();
RevCommit c4 = p.commit().tick(-1).parent(c3).create();
RevWalk rw = p.getRevWalk();
rw.parseCommit(c1);
assertThat(rw.parseCommit(c2).getCommitTime()).isLessThan(c1.getCommitTime());
assertThat(rw.parseCommit(c3).getCommitTime()).isLessThan(c2.getCommitTime());
assertThat(rw.parseCommit(c4).getCommitTime()).isLessThan(c3.getCommitTime());
ChangeData cd1 = newChange(p, c1);
ChangeData cd2 = newChange(p, c2);
ChangeData cd3 = newChange(p, c3);
ChangeData cd4 = newChange(p, c4);
List<ChangeData> changes = ImmutableList.of(cd1, cd2, cd3, cd4);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(
sorter,
changes,
ImmutableList.of(
patchSetData(cd4, c4),
patchSetData(cd3, c3),
patchSetData(cd2, c2),
patchSetData(cd1, c1)));
}
@Test
public void subsetOfSeriesOfChangesWithReverseTimestamps() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c0 = p.commit().tick(-1).create();
RevCommit c1 = p.commit().tick(-1).parent(c0).create();
RevCommit c2 = p.commit().tick(-1).parent(c1).create();
RevCommit c3 = p.commit().tick(-1).parent(c2).create();
RevCommit c4 = p.commit().tick(-1).parent(c3).create();
RevWalk rw = p.getRevWalk();
rw.parseCommit(c1);
assertThat(rw.parseCommit(c2).getCommitTime()).isLessThan(c1.getCommitTime());
assertThat(rw.parseCommit(c3).getCommitTime()).isLessThan(c2.getCommitTime());
assertThat(rw.parseCommit(c4).getCommitTime()).isLessThan(c3.getCommitTime());
ChangeData cd1 = newChange(p, c1);
ChangeData cd2 = newChange(p, c2);
ChangeData cd4 = newChange(p, c4);
List<ChangeData> changes = ImmutableList.of(cd1, cd2, cd4);
WalkSorter sorter = new WalkSorter(repoManager);
List<PatchSetData> expected =
ImmutableList.of(patchSetData(cd4, c4), patchSetData(cd2, c2), patchSetData(cd1, c1));
for (List<ChangeData> list : permutations(changes)) {
// Not inOrder(); since child of c2 is missing, partial topo sort isn't
// guaranteed to work.
assertThat(sorter.sort(list)).containsExactlyElementsIn(expected);
}
}
@Test
public void seriesOfChangesAtSameTimestampWithRootCommit() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c1 = p.commit().tick(0).create();
RevCommit c2 = p.commit().tick(0).parent(c1).create();
RevCommit c3 = p.commit().tick(0).parent(c2).create();
RevCommit c4 = p.commit().tick(0).parent(c3).create();
RevWalk rw = p.getRevWalk();
rw.parseCommit(c1);
assertThat(rw.parseCommit(c2).getCommitTime()).isEqualTo(c1.getCommitTime());
assertThat(rw.parseCommit(c3).getCommitTime()).isEqualTo(c1.getCommitTime());
assertThat(rw.parseCommit(c4).getCommitTime()).isEqualTo(c1.getCommitTime());
ChangeData cd1 = newChange(p, c1);
ChangeData cd2 = newChange(p, c2);
ChangeData cd3 = newChange(p, c3);
ChangeData cd4 = newChange(p, c4);
List<ChangeData> changes = ImmutableList.of(cd1, cd2, cd3, cd4);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(
sorter,
changes,
ImmutableList.of(
patchSetData(cd4, c4),
patchSetData(cd3, c3),
patchSetData(cd2, c2),
patchSetData(cd1, c1)));
}
@Test
public void projectsSortedByName() throws Exception {
TestRepository<Repo> pa = newRepo("a");
TestRepository<Repo> pb = newRepo("b");
RevCommit c1 = pa.commit().create();
RevCommit c2 = pb.commit().create();
RevCommit c3 = pa.commit().parent(c1).create();
RevCommit c4 = pb.commit().parent(c2).create();
ChangeData cd1 = newChange(pa, c1);
ChangeData cd2 = newChange(pb, c2);
ChangeData cd3 = newChange(pa, c3);
ChangeData cd4 = newChange(pb, c4);
assertSorted(
new WalkSorter(repoManager),
ImmutableList.of(cd1, cd2, cd3, cd4),
ImmutableList.of(
patchSetData(cd3, c3),
patchSetData(cd1, c1),
patchSetData(cd4, c4),
patchSetData(cd2, c2)));
}
@Test
public void restrictToPatchSets() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c1_1 = p.commit().create();
RevCommit c2_1 = p.commit().parent(c1_1).create();
ChangeData cd1 = newChange(p, c1_1);
ChangeData cd2 = newChange(p, c2_1);
// Add new patch sets whose commits are in reverse order.
RevCommit c2_2 = p.commit().create();
RevCommit c1_2 = p.commit().parent(c2_2).create();
addPatchSet(cd1, c1_2);
addPatchSet(cd2, c2_2);
List<ChangeData> changes = ImmutableList.of(cd1, cd2);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(
sorter, changes, ImmutableList.of(patchSetData(cd1, c1_2), patchSetData(cd2, c2_2)));
// If we restrict to PS1 of each change, the sorter uses that commit.
sorter.includePatchSets(
ImmutableSet.of(PatchSet.id(cd1.getId(), 1), PatchSet.id(cd2.getId(), 1)));
assertSorted(
sorter, changes, ImmutableList.of(patchSetData(cd2, 1, c2_1), patchSetData(cd1, 1, c1_1)));
}
@Test
public void restrictToPatchSetsOmittingWholeProject() throws Exception {
TestRepository<Repo> pa = newRepo("a");
TestRepository<Repo> pb = newRepo("b");
RevCommit c1 = pa.commit().create();
RevCommit c2 = pa.commit().create();
ChangeData cd1 = newChange(pa, c1);
ChangeData cd2 = newChange(pb, c2);
List<ChangeData> changes = ImmutableList.of(cd1, cd2);
WalkSorter sorter =
new WalkSorter(repoManager).includePatchSets(ImmutableSet.of(cd1.currentPatchSet().id()));
assertSorted(sorter, changes, ImmutableList.of(patchSetData(cd1, c1)));
}
@Test
public void retainBody() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c = p.commit().message("message").create();
ChangeData cd = newChange(p, c);
List<ChangeData> changes = ImmutableList.of(cd);
RevCommit actual =
new WalkSorter(repoManager).setRetainBody(true).sort(changes).iterator().next().commit();
assertThat(actual.getRawBuffer()).isNotNull();
assertThat(actual.getShortMessage()).isEqualTo("message");
actual =
new WalkSorter(repoManager).setRetainBody(false).sort(changes).iterator().next().commit();
assertThat(actual.getRawBuffer()).isNull();
}
@Test
public void oneChange() throws Exception {
TestRepository<Repo> p = newRepo("p");
RevCommit c = p.commit().create();
ChangeData cd = newChange(p, c);
List<ChangeData> changes = ImmutableList.of(cd);
WalkSorter sorter = new WalkSorter(repoManager);
assertSorted(sorter, changes, ImmutableList.of(patchSetData(cd, c)));
}
private ChangeData newChange(TestRepository<Repo> tr, ObjectId id) throws Exception {
Project.NameKey project = tr.getRepository().getDescription().getProject();
Change c = TestChanges.newChange(project, userId);
ChangeData cd = ChangeData.createForTest(project, c.getId(), 1, id);
cd.setChange(c);
cd.setPatchSets(ImmutableList.of(cd.currentPatchSet()));
return cd;
}
private PatchSet addPatchSet(ChangeData cd, ObjectId id) throws Exception {
TestChanges.incrementPatchSet(cd.change());
PatchSet ps = TestChanges.newPatchSet(cd.change().currentPatchSetId(), id.name(), userId);
List<PatchSet> patchSets = new ArrayList<>(cd.patchSets());
patchSets.add(ps);
cd.setPatchSets(patchSets);
return ps;
}
private TestRepository<Repo> newRepo(String name) throws Exception {
return new TestRepository<>(repoManager.createRepository(Project.nameKey(name)));
}
private static PatchSetData patchSetData(ChangeData cd, RevCommit commit) throws Exception {
return PatchSetData.create(cd, cd.currentPatchSet(), commit);
}
private static PatchSetData patchSetData(ChangeData cd, int psId, RevCommit commit)
throws Exception {
return PatchSetData.create(cd, cd.patchSet(PatchSet.id(cd.getId(), psId)), commit);
}
private static void assertSorted(
WalkSorter sorter, List<ChangeData> changes, List<PatchSetData> expected) throws Exception {
for (List<ChangeData> list : permutations(changes)) {
assertThat(sorter.sort(list)).containsExactlyElementsIn(expected).inOrder();
}
}
}