com.google.gerrit.acceptance.api.change.ChangeIT.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.acceptance.api.change.ChangeIT.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.api.change;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.Util.blockLabel;
import static com.google.gerrit.server.project.Util.category;
import static com.google.gerrit.server.project.Util.value;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.AddReviewerInput;
import com.google.gerrit.extensions.api.changes.RebaseInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.LabelInfo;
import com.google.gerrit.extensions.common.RevisionInfo;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.Util;

import org.eclipse.jgit.lib.Constants;
import org.junit.Test;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

@NoHttpd
public class ChangeIT extends AbstractDaemonTest {

    @Test
    public void get() throws Exception {
        PushOneCommit.Result r = createChange();
        String triplet = project.get() + "~master~" + r.getChangeId();
        ChangeInfo c = info(triplet);
        assertThat(c.id).isEqualTo(triplet);
        assertThat(c.project).isEqualTo(project.get());
        assertThat(c.branch).isEqualTo("master");
        assertThat(c.status).isEqualTo(ChangeStatus.NEW);
        assertThat(c.subject).isEqualTo("test commit");
        assertThat(c.mergeable).isTrue();
        assertThat(c.changeId).isEqualTo(r.getChangeId());
        assertThat(c.created).isEqualTo(c.updated);
        assertThat(c._number).isEqualTo(r.getChange().getId().get());

        assertThat(c.owner._accountId).isEqualTo(admin.getId().get());
        assertThat(c.owner.name).isNull();
        assertThat(c.owner.email).isNull();
        assertThat(c.owner.username).isNull();
        assertThat(c.owner.avatars).isNull();
    }

    @Test
    public void abandon() throws Exception {
        PushOneCommit.Result r = createChange();
        gApi.changes().id(r.getChangeId()).abandon();
    }

    @Test
    public void restore() throws Exception {
        PushOneCommit.Result r = createChange();
        gApi.changes().id(r.getChangeId()).abandon();
        gApi.changes().id(r.getChangeId()).restore();
    }

    @Test
    public void revert() throws Exception {
        PushOneCommit.Result r = createChange();
        gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(ReviewInput.approve());
        gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).submit();
        gApi.changes().id(r.getChangeId()).revert();
    }

    // Change is already up to date
    @Test(expected = ResourceConflictException.class)
    public void rebase() throws Exception {
        PushOneCommit.Result r = createChange();
        gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).rebase();
    }

    @Test
    public void rebaseChangeBase() throws Exception {
        PushOneCommit.Result r1 = createChange();
        PushOneCommit.Result r2 = createChange();
        PushOneCommit.Result r3 = createChange();
        RebaseInput ri = new RebaseInput();

        // rebase r3 directly onto master (break dep. towards r2)
        ri.base = "";
        gApi.changes().id(r3.getChangeId()).revision(r3.getCommit().name()).rebase(ri);
        PatchSet ps3 = r3.getPatchSet();
        assertThat(ps3.getId().get()).isEqualTo(2);

        // rebase r2 onto r3 (referenced by ref)
        ri.base = ps3.getId().toRefName();
        gApi.changes().id(r2.getChangeId()).revision(r2.getCommit().name()).rebase(ri);
        PatchSet ps2 = r2.getPatchSet();
        assertThat(ps2.getId().get()).isEqualTo(2);

        // rebase r1 onto r2 (referenced by commit)
        ri.base = ps2.getRevision().get();
        gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).rebase(ri);
        PatchSet ps1 = r1.getPatchSet();
        assertThat(ps1.getId().get()).isEqualTo(2);

        // rebase r1 onto r3 (referenced by change number)
        ri.base = String.valueOf(r3.getChange().getId().get());
        gApi.changes().id(r1.getChangeId()).revision(ps1.getRevision().get()).rebase(ri);
        assertThat(r1.getPatchSetId().get()).isEqualTo(3);
    }

    @Test(expected = ResourceConflictException.class)
    public void rebaseChangeBaseRecursion() throws Exception {
        PushOneCommit.Result r1 = createChange();
        PushOneCommit.Result r2 = createChange();

        RebaseInput ri = new RebaseInput();
        ri.base = r2.getCommit().name();
        gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).rebase(ri);
    }

    private Set<Account.Id> getReviewers(String changeId) throws Exception {
        ChangeInfo ci = gApi.changes().id(changeId).get();
        Set<Account.Id> result = Sets.newHashSet();
        for (LabelInfo li : ci.labels.values()) {
            for (ApprovalInfo ai : li.all) {
                result.add(new Account.Id(ai._accountId));
            }
        }
        return result;
    }

    @Test
    public void addReviewer() throws Exception {
        PushOneCommit.Result r = createChange();
        AddReviewerInput in = new AddReviewerInput();
        in.reviewer = user.email;
        gApi.changes().id(r.getChangeId()).addReviewer(in);

        assertThat(getReviewers(r.getChangeId())).containsExactlyElementsIn(ImmutableSet.of(user.id));
    }

    @Test
    public void addReviewerToClosedChange() throws Exception {
        PushOneCommit.Result r = createChange();
        gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(ReviewInput.approve());
        gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).submit();

        assertThat(getReviewers(r.getChangeId())).containsExactlyElementsIn(ImmutableSet.of(admin.getId()));

        AddReviewerInput in = new AddReviewerInput();
        in.reviewer = user.email;
        gApi.changes().id(r.getChangeId()).addReviewer(in);
        assertThat(getReviewers(r.getChangeId()))
                .containsExactlyElementsIn(ImmutableSet.of(admin.getId(), user.id));
    }

    @Test
    public void createEmptyChange() throws Exception {
        ChangeInfo in = new ChangeInfo();
        in.branch = Constants.MASTER;
        in.subject = "Create a change from the API";
        in.project = project.get();
        ChangeInfo info = gApi.changes().create(in).get();
        assertThat(info.project).isEqualTo(in.project);
        assertThat(info.branch).isEqualTo(in.branch);
        assertThat(info.subject).isEqualTo(in.subject);
        assertThat(Iterables.getOnlyElement(info.messages).message).isEqualTo("Uploaded patch set 1.");
    }

    @Test
    public void queryChangesNoQuery() throws Exception {
        PushOneCommit.Result r = createChange();
        List<ChangeInfo> results = gApi.changes().query().get();
        assertThat(results.size()).isAtLeast(1);
        List<Integer> ids = new ArrayList<>(results.size());
        for (int i = 0; i < results.size(); i++) {
            ChangeInfo info = results.get(i);
            if (i == 0) {
                assertThat(info._number).isEqualTo(r.getChange().getId().get());
            }
            assertThat(Change.Status.forChangeStatus(info.status).isOpen()).isTrue();
            ids.add(info._number);
        }
        assertThat(ids).contains(r.getChange().getId().get());
    }

    @Test
    public void queryChangesNoResults() throws Exception {
        createChange();
        assertThat(query("message:test")).isNotEmpty();
        assertThat(query("message:{" + getClass().getName() + "fhqwhgads}")).isEmpty();
    }

    @Test
    public void queryChanges() throws Exception {
        PushOneCommit.Result r1 = createChange();
        createChange();
        List<ChangeInfo> results = query("project:{" + project.get() + "} " + r1.getChangeId());
        assertThat(Iterables.getOnlyElement(results).changeId).isEqualTo(r1.getChangeId());
    }

    @Test
    public void queryChangesLimit() throws Exception {
        createChange();
        PushOneCommit.Result r2 = createChange();
        List<ChangeInfo> results = gApi.changes().query().withLimit(1).get();
        assertThat(results).hasSize(1);
        assertThat(Iterables.getOnlyElement(results).changeId).isEqualTo(r2.getChangeId());
    }

    @Test
    public void queryChangesStart() throws Exception {
        PushOneCommit.Result r1 = createChange();
        createChange();
        List<ChangeInfo> results = gApi.changes().query("project:{" + project.get() + "}").withStart(1).get();
        assertThat(Iterables.getOnlyElement(results).changeId).isEqualTo(r1.getChangeId());
    }

    @Test
    public void queryChangesNoOptions() throws Exception {
        PushOneCommit.Result r = createChange();
        ChangeInfo result = Iterables.getOnlyElement(query(r.getChangeId()));
        assertThat(result.labels).isNull();
        assertThat(result.messages).isNull();
        assertThat(result.revisions).isNull();
        assertThat(result.actions).isNull();
    }

    @Test
    public void queryChangesOptions() throws Exception {
        PushOneCommit.Result r = createChange();
        ChangeInfo result = Iterables.getOnlyElement(
                gApi.changes().query(r.getChangeId()).withOptions(EnumSet.allOf(ListChangesOption.class)).get());
        assertThat(Iterables.getOnlyElement(result.labels.keySet())).isEqualTo("Code-Review");
        assertThat(result.messages).hasSize(1);
        assertThat(result.actions).isNotEmpty();

        RevisionInfo rev = Iterables.getOnlyElement(result.revisions.values());
        assertThat(rev._number).isEqualTo(r.getPatchSetId().get());
        assertThat(rev.created).isNotNull();
        assertThat(rev.uploader._accountId).isEqualTo(admin.getId().get());
        assertThat(rev.ref).isEqualTo(r.getPatchSetId().toRefName());
        assertThat(rev.actions).isNotEmpty();
    }

    @Test
    public void queryChangesOwnerWithDifferentUsers() throws Exception {
        PushOneCommit.Result r = createChange();
        assertThat(Iterables.getOnlyElement(query("project:{" + project.get() + "} owner:self")).changeId)
                .isEqualTo(r.getChangeId());
        setApiUser(user);
        assertThat(query("owner:self")).isEmpty();
    }

    @Test
    public void checkReviewedFlagBeforeAndAfterReview() throws Exception {
        PushOneCommit.Result r = createChange();
        AddReviewerInput in = new AddReviewerInput();
        in.reviewer = user.email;
        gApi.changes().id(r.getChangeId()).addReviewer(in);

        setApiUser(user);
        assertThat(get(r.getChangeId()).reviewed).isNull();

        revision(r).review(ReviewInput.recommend());
        assertThat(get(r.getChangeId()).reviewed).isTrue();
    }

    @Test
    public void topic() throws Exception {
        PushOneCommit.Result r = createChange();
        assertThat(gApi.changes().id(r.getChangeId()).topic()).isEqualTo("");
        gApi.changes().id(r.getChangeId()).topic("mytopic");
        assertThat(gApi.changes().id(r.getChangeId()).topic()).isEqualTo("mytopic");
        gApi.changes().id(r.getChangeId()).topic("");
        assertThat(gApi.changes().id(r.getChangeId()).topic()).isEqualTo("");
    }

    @Test
    public void check() throws Exception {
        PushOneCommit.Result r = createChange();
        assertThat(gApi.changes().id(r.getChangeId()).get().problems).isNull();
        assertThat(gApi.changes().id(r.getChangeId()).get(EnumSet.of(ListChangesOption.CHECK)).problems).isEmpty();
    }

    @Test
    public void commitFooters() throws Exception {
        LabelType verified = category("Verified", value(1, "Failed"), value(0, "No score"), value(-1, "Passes"));
        LabelType custom1 = category("Custom1", value(1, "Positive"), value(0, "No score"), value(-1, "Negative"));
        LabelType custom2 = category("Custom2", value(1, "Positive"), value(0, "No score"), value(-1, "Negative"));
        ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
        cfg.getLabelSections().put(verified.getName(), verified);
        cfg.getLabelSections().put(custom1.getName(), verified);
        cfg.getLabelSections().put(custom2.getName(), verified);
        String heads = "refs/heads/*";
        AccountGroup.UUID anon = SystemGroupBackend.getGroup(ANONYMOUS_USERS).getUUID();
        Util.allow(cfg, Permission.forLabel("Verified"), -1, 1, anon, heads);
        Util.allow(cfg, Permission.forLabel("Custom1"), -1, 1, anon, heads);
        Util.allow(cfg, Permission.forLabel("Custom2"), -1, 1, anon, heads);
        saveProjectConfig(project, cfg);

        PushOneCommit.Result r1 = createChange();
        r1.assertOkStatus();
        PushOneCommit.Result r2 = pushFactory
                .create(db, admin.getIdent(), testRepo, SUBJECT, FILE_NAME, "new content", r1.getChangeId())
                .to("refs/for/master");
        r2.assertOkStatus();

        ReviewInput in = new ReviewInput();
        in.label("Code-Review", 1);
        in.label("Verified", 1);
        in.label("Custom1", -1);
        in.label("Custom2", 1);
        gApi.changes().id(r2.getChangeId()).current().review(in);

        EnumSet<ListChangesOption> options = EnumSet.of(ListChangesOption.ALL_REVISIONS,
                ListChangesOption.COMMIT_FOOTERS);
        ChangeInfo actual = gApi.changes().id(r2.getChangeId()).get(options);
        assertThat(actual.revisions).hasSize(2);

        // No footers except on latest patch set.
        assertThat(actual.revisions.get(r1.getCommit().getName()).commitWithFooters).isNull();

        String expected = SUBJECT + "\n" + "\n" + "Change-Id: " + r2.getChangeId() + "\n" + "Reviewed-on: "
                + canonicalWebUrl.get() + r2.getChange().getId() + "\n"
                + "Reviewed-by: Administrator <admin@example.com>\n"
                + "Custom2: Administrator <admin@example.com>\n" + "Tested-by: Administrator <admin@example.com>\n";
        assertThat(actual.revisions.get(r2.getCommit().getName()).commitWithFooters).isEqualTo(expected);
    }

    @Test
    public void defaultSearchDoesNotTouchDatabase() throws Exception {
        PushOneCommit.Result r1 = createChange();
        gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).review(ReviewInput.approve());
        gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).submit();

        createChange();

        setApiUserAnonymous(); // Identified user may async get stars from DB.
        atrScope.disableDb();
        assertThat(
                gApi.changes().query().withQuery("project:{" + project.get() + "} (status:open OR status:closed)")
                        // Options should match defaults in AccountDashboardScreen.
                        .withOption(ListChangesOption.LABELS).withOption(ListChangesOption.DETAILED_ACCOUNTS)
                        .withOption(ListChangesOption.REVIEWED).get()).hasSize(2);
    }

    @Test
    public void votable() throws Exception {
        PushOneCommit.Result r = createChange();
        String triplet = project.get() + "~master~" + r.getChangeId();
        gApi.changes().id(triplet).addReviewer(user.username);
        ChangeInfo c = gApi.changes().id(triplet).get(EnumSet.of(ListChangesOption.DETAILED_LABELS));
        LabelInfo codeReview = c.labels.get("Code-Review");
        assertThat(codeReview.all).hasSize(1);
        ApprovalInfo approval = codeReview.all.get(0);
        assertThat(approval._accountId).isEqualTo(user.id.get());
        assertThat(approval.value).isEqualTo(0);

        ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
        blockLabel(cfg, "Code-Review", REGISTERED_USERS, "refs/heads/*");
        saveProjectConfig(project, cfg);
        c = gApi.changes().id(triplet).get(EnumSet.of(ListChangesOption.DETAILED_LABELS));
        codeReview = c.labels.get("Code-Review");
        assertThat(codeReview.all).hasSize(1);
        approval = codeReview.all.get(0);
        assertThat(approval._accountId).isEqualTo(user.id.get());
        assertThat(approval.value).isNull();
    }
}