com.google.gerrit.acceptance.server.change.GetRelatedIT.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.acceptance.server.change.GetRelatedIT.java

Source

// Copyright (C) 2013 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.acceptance.server.change;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.GitUtil.pushHead;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.RestSession;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.change.GetRelated.ChangeAndCommit;
import com.google.gerrit.server.change.GetRelated.RelatedInfo;
import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

public class GetRelatedIT extends AbstractDaemonTest {
    @ConfigSuite.Default
    public static Config byGroup() {
        Config cfg = new Config();
        cfg.setBoolean("change", null, "getRelatedByAncestors", false);
        return cfg;
    }

    @ConfigSuite.Config
    public static Config byAncestors() {
        Config cfg = new Config();
        cfg.setBoolean("change", null, "getRelatedByAncestors", true);
        return cfg;
    }

    @Inject
    private ChangeEditUtil editUtil;

    @Inject
    private ChangeEditModifier editModifier;

    @Inject
    private ChangeData.Factory changeDataFactory;

    @Test
    public void getRelatedNoResult() throws Exception {
        PushOneCommit push = pushFactory.create(db, admin.getIdent(), testRepo);
        assertRelated(push.to("refs/for/master").getPatchSetId());
    }

    @Test
    public void getRelatedLinear() throws Exception {
        RevCommit c1_1 = commitBuilder().add("a.txt", "1").message("subject: 1").create();
        String id1 = getChangeId(c1_1);
        RevCommit c2_2 = commitBuilder().add("b.txt", "2").message("subject: 2").create();
        String id2 = getChangeId(c2_2);
        pushHead(testRepo, "refs/for/master", false);

        for (RevCommit c : ImmutableList.of(c2_2, c1_1)) {
            assertRelated(getPatchSetId(c), changeAndCommit(id2, c2_2, 1, 1), changeAndCommit(id1, c1_1, 1, 1));
        }
    }

    @Test
    public void getRelatedReorder() throws Exception {
        // Create two commits and push.
        RevCommit c1_1 = commitBuilder().add("a.txt", "1").message("subject: 1").create();
        String id1 = getChangeId(c1_1);
        RevCommit c2_1 = commitBuilder().add("b.txt", "2").message("subject: 2").create();
        String id2 = getChangeId(c2_1);
        pushHead(testRepo, "refs/for/master", false);
        PatchSet.Id ps1_1 = getPatchSetId(c1_1);
        PatchSet.Id ps2_1 = getPatchSetId(c2_1);

        // Swap the order of commits and push again.
        testRepo.reset("HEAD~2");
        RevCommit c2_2 = testRepo.cherryPick(c2_1);
        RevCommit c1_2 = testRepo.cherryPick(c1_1);
        pushHead(testRepo, "refs/for/master", false);
        PatchSet.Id ps1_2 = getPatchSetId(c1_1);
        PatchSet.Id ps2_2 = getPatchSetId(c2_1);

        for (PatchSet.Id ps : ImmutableList.of(ps2_2, ps1_2)) {
            assertRelated(ps, changeAndCommit(id1, c1_2, 2, 2), changeAndCommit(id2, c2_2, 2, 2));
        }

        for (PatchSet.Id ps : ImmutableList.of(ps2_1, ps1_1)) {
            assertRelated(ps, changeAndCommit(id2, c2_1, 1, 2), changeAndCommit(id1, c1_1, 1, 2));
        }
    }

    @Test
    public void getRelatedReorderAndExtend() throws Exception {
        // Create two commits and push.
        ObjectId initial = repo().getRef("HEAD").getObjectId();
        RevCommit c1_1 = commitBuilder().add("a.txt", "1").message("subject: 1").create();
        String id1 = getChangeId(c1_1);
        RevCommit c2_1 = commitBuilder().add("b.txt", "2").message("subject: 2").create();
        String id2 = getChangeId(c2_1);
        pushHead(testRepo, "refs/for/master", false);
        PatchSet.Id ps1_1 = getPatchSetId(c1_1);
        PatchSet.Id ps2_1 = getPatchSetId(c2_1);

        // Swap the order of commits, create a new commit on top, and push again.
        testRepo.reset(initial);
        RevCommit c2_2 = testRepo.cherryPick(c2_1);
        RevCommit c1_2 = testRepo.cherryPick(c1_1);
        RevCommit c3_1 = commitBuilder().add("c.txt", "3").message("subject: 3").create();
        String id3 = getChangeId(c3_1);
        pushHead(testRepo, "refs/for/master", false);
        PatchSet.Id ps1_2 = getPatchSetId(c1_1);
        PatchSet.Id ps2_2 = getPatchSetId(c2_1);
        PatchSet.Id ps3_1 = getPatchSetId(c3_1);

        for (PatchSet.Id ps : ImmutableList.of(ps3_1, ps2_2, ps1_2)) {
            assertRelated(ps, changeAndCommit(id3, c3_1, 1, 1), changeAndCommit(id1, c1_2, 2, 2),
                    changeAndCommit(id2, c2_2, 2, 2));
        }

        for (PatchSet.Id ps : ImmutableList.of(ps2_1, ps1_1)) {
            assertRelated(ps, changeAndCommit(id3, c3_1, 1, 1), changeAndCommit(id2, c2_1, 1, 2),
                    changeAndCommit(id1, c1_1, 1, 2));
        }
    }

    @Test
    public void getRelatedEdit() throws Exception {
        RevCommit c1_1 = commitBuilder().add("a.txt", "1").message("subject: 1").create();
        String id1 = getChangeId(c1_1);
        RevCommit c2_1 = commitBuilder().add("b.txt", "2").message("subject: 2").create();
        String id2 = getChangeId(c2_1);
        RevCommit c3_1 = commitBuilder().add("c.txt", "3").message("subject: 3").create();
        String id3 = getChangeId(c3_1);
        pushHead(testRepo, "refs/for/master", false);

        Change ch2 = getChange(c2_1).change();
        editModifier.createEdit(ch2, getPatchSet(ch2));
        editModifier.modifyFile(editUtil.byChange(ch2).get(), "a.txt", RestSession.newRawInput(new byte[] { 'a' }));
        ObjectId editRev = ObjectId.fromString(editUtil.byChange(ch2).get().getRevision().get());

        PatchSet.Id ps1_1 = getPatchSetId(c1_1);
        PatchSet.Id ps2_1 = getPatchSetId(c2_1);
        PatchSet.Id ps2_edit = new PatchSet.Id(ch2.getId(), 0);
        PatchSet.Id ps3_1 = getPatchSetId(c3_1);

        for (PatchSet.Id ps : ImmutableList.of(ps1_1, ps2_1, ps3_1)) {
            assertRelated(ps, changeAndCommit(id3, c3_1, 1, 1), changeAndCommit(id2, c2_1, 1, 1),
                    changeAndCommit(id1, c1_1, 1, 1));
        }

        assertRelated(ps2_edit, changeAndCommit(id3, c3_1, 1, 1), changeAndCommit(id2, editRev, 0, 1),
                changeAndCommit(id1, c1_1, 1, 1));
    }

    @Test
    public void pushNewPatchSetWhenParentHasNullGroup() throws Exception {
        RevCommit c1_1 = commitBuilder().add("a.txt", "1").message("subject: 1").create();
        String id1 = getChangeId(c1_1);
        RevCommit c2_1 = commitBuilder().add("b.txt", "2").message("subject: 2").create();
        String id2 = getChangeId(c2_1);
        pushHead(testRepo, "refs/for/master", false);
        PatchSet.Id psId1_1 = getPatchSetId(c1_1);
        PatchSet.Id psId2_1 = getPatchSetId(c2_1);

        for (PatchSet.Id psId : ImmutableList.of(psId1_1, psId2_1)) {
            assertRelated(psId, changeAndCommit(id2, c2_1, 1, 1), changeAndCommit(id1, c1_1, 1, 1));
        }

        // Pretend PS1,1 was pushed before the groups field was added.
        PatchSet ps1_1 = db.patchSets().get(psId1_1);
        ps1_1.setGroups(null);
        db.patchSets().update(ImmutableList.of(ps1_1));
        indexer.index(changeDataFactory.create(db, psId1_1.getParentKey()));

        if (!cfg.getBoolean("change", null, "getRelatedByAncestors", false)) {
            // PS1,1 has no groups, so disappeared from related changes.
            assertRelated(psId2_1);
        }

        RevCommit c2_2 = testRepo.amend(c2_1).add("c.txt", "2").create();
        testRepo.reset(c2_2);
        pushHead(testRepo, "refs/for/master", false);
        PatchSet.Id psId2_2 = getPatchSetId(c2_2);

        // Push updated the group for PS1,1, so it shows up in related changes even
        // though a new patch set was not pushed.
        assertRelated(psId2_2, changeAndCommit(id2, c2_2, 2, 2), changeAndCommit(id1, c1_1, 1, 1));
    }

    private List<ChangeAndCommit> getRelated(PatchSet.Id ps) throws IOException {
        return getRelated(ps.getParentKey(), ps.get());
    }

    private List<ChangeAndCommit> getRelated(Change.Id changeId, int ps) throws IOException {
        String url = String.format("/changes/%d/revisions/%d/related", changeId.get(), ps);
        return newGson().fromJson(adminSession.get(url).getReader(), RelatedInfo.class).changes;
    }

    private String getChangeId(RevCommit c) throws Exception {
        return GitUtil.getChangeId(testRepo, c).get();
    }

    private PatchSet.Id getPatchSetId(ObjectId c) throws OrmException {
        return getChange(c).change().currentPatchSetId();
    }

    private PatchSet getPatchSet(Change c) throws OrmException {
        return db.patchSets().get(c.currentPatchSetId());
    }

    private ChangeData getChange(ObjectId c) throws OrmException {
        return Iterables.getOnlyElement(queryProvider.get().byCommit(c));
    }

    private static ChangeAndCommit changeAndCommit(String changeId, ObjectId commitId, int revisionNum,
            int currentRevisionNum) {
        ChangeAndCommit result = new ChangeAndCommit();
        result.changeId = changeId;
        result.commit = new CommitInfo();
        result.commit.commit = commitId.name();
        result._revisionNumber = revisionNum;
        result._currentRevisionNumber = currentRevisionNum;
        result.status = "NEW";
        return result;
    }

    private void assertRelated(PatchSet.Id psId, ChangeAndCommit... expected) throws Exception {
        List<ChangeAndCommit> actual = getRelated(psId);
        assertThat(actual).hasSize(expected.length);
        for (int i = 0; i < actual.size(); i++) {
            String name = "index " + i + " related to " + psId;
            ChangeAndCommit a = actual.get(i);
            ChangeAndCommit e = expected[i];
            assertThat(a.changeId).named("Change-Id of " + name).isEqualTo(e.changeId);
            assertThat(a.commit.commit).named("commit of " + name).isEqualTo(e.commit.commit);
            // Don't bother checking _changeNumber; assume changeId is sufficient.
            assertThat(a._revisionNumber).named("revision of " + name).isEqualTo(e._revisionNumber);
            assertThat(a._currentRevisionNumber).named("current revision of " + name)
                    .isEqualTo(e._currentRevisionNumber);
        }
    }
}