summaryrefslogtreecommitdiffstats
path: root/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java')
-rw-r--r--gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java2917
1 files changed, 0 insertions, 2917 deletions
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
deleted file mode 100644
index 215089af64..0000000000
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ /dev/null
@@ -1,2917 +0,0 @@
-// 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.server.query.change;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
-import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
-import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWED;
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static com.google.gerrit.server.project.Util.category;
-import static com.google.gerrit.server.project.Util.value;
-import static java.util.concurrent.TimeUnit.HOURS;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.MINUTES;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.stream.Collectors.toList;
-import static org.junit.Assert.fail;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Streams;
-import com.google.common.truth.ThrowableSubject;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.TimeUtil;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.api.changes.AddReviewerInput;
-import com.google.gerrit.extensions.api.changes.AssigneeInput;
-import com.google.gerrit.extensions.api.changes.Changes.QueryRequest;
-import com.google.gerrit.extensions.api.changes.DraftInput;
-import com.google.gerrit.extensions.api.changes.HashtagsInput;
-import com.google.gerrit.extensions.api.changes.NotifyHandling;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
-import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
-import com.google.gerrit.extensions.api.changes.StarsInput;
-import com.google.gerrit.extensions.api.groups.GroupInput;
-import com.google.gerrit.extensions.api.projects.ConfigInput;
-import com.google.gerrit.extensions.api.projects.ProjectInput;
-import com.google.gerrit.extensions.client.InheritableBoolean;
-import com.google.gerrit.extensions.client.ProjectWatchInfo;
-import com.google.gerrit.extensions.client.ReviewerState;
-import com.google.gerrit.extensions.common.AccountInfo;
-import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.common.ChangeInput;
-import com.google.gerrit.extensions.common.ChangeMessageInfo;
-import com.google.gerrit.extensions.common.CommentInfo;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.index.FieldDef;
-import com.google.gerrit.index.IndexConfig;
-import com.google.gerrit.index.QueryOptions;
-import com.google.gerrit.index.Schema;
-import com.google.gerrit.lifecycle.LifecycleManager;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.PatchSetUtil;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.StarredChangesUtil;
-import com.google.gerrit.server.account.AccountCache;
-import com.google.gerrit.server.account.AccountManager;
-import com.google.gerrit.server.account.Accounts;
-import com.google.gerrit.server.account.AccountsUpdate;
-import com.google.gerrit.server.account.AuthRequest;
-import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.account.externalids.ExternalIdsUpdate;
-import com.google.gerrit.server.change.ChangeInserter;
-import com.google.gerrit.server.change.ChangeTriplet;
-import com.google.gerrit.server.change.PatchSetInserter;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.MetaDataUpdate;
-import com.google.gerrit.server.git.ProjectConfig;
-import com.google.gerrit.server.index.change.ChangeField;
-import com.google.gerrit.server.index.change.ChangeIndexCollection;
-import com.google.gerrit.server.index.change.ChangeIndexer;
-import com.google.gerrit.server.index.change.IndexedChangeQuery;
-import com.google.gerrit.server.index.change.StalenessChecker;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.project.Util;
-import com.google.gerrit.server.schema.SchemaCreator;
-import com.google.gerrit.server.update.BatchUpdate;
-import com.google.gerrit.server.util.ManualRequestContext;
-import com.google.gerrit.server.util.OneOffRequestContext;
-import com.google.gerrit.server.util.RequestContext;
-import com.google.gerrit.server.util.ThreadLocalRequestContext;
-import com.google.gerrit.testutil.ConfigSuite;
-import com.google.gerrit.testutil.DisabledReviewDb;
-import com.google.gerrit.testutil.GerritServerTests;
-import com.google.gerrit.testutil.InMemoryDatabase;
-import com.google.gerrit.testutil.InMemoryRepositoryManager;
-import com.google.gerrit.testutil.InMemoryRepositoryManager.Repo;
-import com.google.gerrit.testutil.TestTimeUtil;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Provider;
-import com.google.inject.util.Providers;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.util.SystemReader;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-@Ignore
-public abstract class AbstractQueryChangesTest extends GerritServerTests {
- @ConfigSuite.Default
- public static Config defaultConfig() {
- Config cfg = new Config();
- cfg.setInt("index", null, "maxPages", 10);
- cfg.setString("trackingid", "query-bug", "footer", "Bug:");
- cfg.setString("trackingid", "query-bug", "match", "QUERY\\d{2,8}");
- cfg.setString("trackingid", "query-bug", "system", "querytests");
- cfg.setString("trackingid", "query-feature", "footer", "Feature");
- cfg.setString("trackingid", "query-feature", "match", "QUERY\\d{2,8}");
- cfg.setString("trackingid", "query-feature", "system", "querytests");
- return cfg;
- }
-
- @Inject protected Accounts accounts;
- @Inject protected AccountCache accountCache;
- @Inject protected AccountsUpdate.Server accountsUpdate;
- @Inject protected AccountManager accountManager;
- @Inject protected AllUsersName allUsersName;
- @Inject protected BatchUpdate.Factory updateFactory;
- @Inject protected ChangeInserter.Factory changeFactory;
- @Inject protected ChangeQueryBuilder queryBuilder;
- @Inject protected GerritApi gApi;
- @Inject protected IdentifiedUser.GenericFactory userFactory;
- @Inject protected ChangeIndexCollection indexes;
- @Inject protected ChangeIndexer indexer;
- @Inject protected IndexConfig indexConfig;
- @Inject protected InMemoryRepositoryManager repoManager;
- @Inject protected Provider<InternalChangeQuery> queryProvider;
- @Inject protected ChangeNotes.Factory notesFactory;
- @Inject protected OneOffRequestContext oneOffRequestContext;
- @Inject protected PatchSetInserter.Factory patchSetFactory;
- @Inject protected PatchSetUtil psUtil;
- @Inject protected ChangeNotes.Factory changeNotesFactory;
- @Inject protected Provider<ChangeQueryProcessor> queryProcessorProvider;
- @Inject protected SchemaCreator schemaCreator;
- @Inject protected SchemaFactory<ReviewDb> schemaFactory;
- @Inject protected Sequences seq;
- @Inject protected ThreadLocalRequestContext requestContext;
- @Inject protected ProjectCache projectCache;
- @Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
- @Inject protected ExternalIdsUpdate.Server externalIdsUpdate;
- @Inject protected IdentifiedUser.GenericFactory identifiedUserFactory;
-
- // Only for use in setting up/tearing down injector; other users should use schemaFactory.
- @Inject private InMemoryDatabase inMemoryDatabase;
-
- protected Injector injector;
- protected LifecycleManager lifecycle;
- protected ReviewDb db;
- protected Account.Id userId;
- protected CurrentUser user;
-
- private String systemTimeZone;
-
- protected abstract Injector createInjector();
-
- @Before
- public void setUpInjector() throws Exception {
- lifecycle = new LifecycleManager();
- injector = createInjector();
- lifecycle.add(injector);
- injector.injectMembers(this);
- lifecycle.start();
- initAfterLifecycleStart();
- setUpDatabase();
- }
-
- @After
- public void cleanUp() {
- lifecycle.stop();
- db.close();
- }
-
- protected void initAfterLifecycleStart() throws Exception {}
-
- protected void setUpDatabase() throws Exception {
- try (ReviewDb underlyingDb = inMemoryDatabase.getDatabase().open()) {
- schemaCreator.create(underlyingDb);
- }
- db = schemaFactory.open();
-
- userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
- String email = "user@example.com";
- externalIdsUpdate.create().insert(ExternalId.createEmail(userId, email));
- accountsUpdate.create().update(userId, a -> a.setPreferredEmail(email));
- user = userFactory.create(userId);
- requestContext.setContext(newRequestContext(userId));
- }
-
- protected RequestContext newRequestContext(Account.Id requestUserId) {
- final CurrentUser requestUser = userFactory.create(requestUserId);
- return new RequestContext() {
- @Override
- public CurrentUser getUser() {
- return requestUser;
- }
-
- @Override
- public Provider<ReviewDb> getReviewDbProvider() {
- return Providers.of(db);
- }
- };
- }
-
- @After
- public void tearDownInjector() {
- if (lifecycle != null) {
- lifecycle.stop();
- }
- requestContext.setContext(null);
- if (db != null) {
- db.close();
- }
- InMemoryDatabase.drop(inMemoryDatabase);
- }
-
- @Before
- public void setTimeForTesting() {
- resetTimeWithClockStep(1, SECONDS);
- }
-
- private void resetTimeWithClockStep(long clockStep, TimeUnit clockStepUnit) {
- systemTimeZone = System.setProperty("user.timezone", "US/Eastern");
- // TODO(dborowitz): Figure out why tests fail when stubbing out
- // SystemReader.
- TestTimeUtil.resetWithClockStep(clockStep, clockStepUnit);
- SystemReader.setInstance(null);
- }
-
- @After
- public void resetTime() {
- TestTimeUtil.useSystemTime();
- System.setProperty("user.timezone", systemTimeZone);
- }
-
- @Test
- public void byId() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- assertQuery("12345");
- assertQuery(change1.getId().get(), change1);
- assertQuery(change2.getId().get(), change2);
- }
-
- @Test
- public void byKey() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
- String key = change.getKey().get();
-
- assertQuery("I0000000000000000000000000000000000000000");
- for (int i = 0; i <= 36; i++) {
- String q = key.substring(0, 41 - i);
- assertQuery(q, change);
- }
- }
-
- @Test
- public void byTriplet() throws Exception {
- TestRepository<Repo> repo = createProject("iabcde");
- Change change = insert(repo, newChangeForBranch(repo, "branch"));
- String k = change.getKey().get();
-
- assertQuery("iabcde~branch~" + k, change);
- assertQuery("change:iabcde~branch~" + k, change);
- assertQuery("iabcde~refs/heads/branch~" + k, change);
- assertQuery("change:iabcde~refs/heads/branch~" + k, change);
- assertQuery("iabcde~branch~" + k.substring(0, 10), change);
- assertQuery("change:iabcde~branch~" + k.substring(0, 10), change);
-
- assertQuery("foo~bar");
- assertThatQueryException("change:foo~bar").hasMessageThat().isEqualTo("Invalid change format");
- assertQuery("otherrepo~branch~" + k);
- assertQuery("change:otherrepo~branch~" + k);
- assertQuery("iabcde~otherbranch~" + k);
- assertQuery("change:iabcde~otherbranch~" + k);
- assertQuery("iabcde~branch~I0000000000000000000000000000000000000000");
- assertQuery("change:iabcde~branch~I0000000000000000000000000000000000000000");
- }
-
- @Test
- public void byStatus() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.NEW);
- Change change1 = insert(repo, ins1);
- ChangeInserter ins2 = newChangeWithStatus(repo, Change.Status.MERGED);
- Change change2 = insert(repo, ins2);
-
- assertQuery("status:new", change1);
- assertQuery("status:NEW", change1);
- assertQuery("is:new", change1);
- assertQuery("status:merged", change2);
- assertQuery("is:merged", change2);
- assertQuery("status:draft");
- assertQuery("is:draft");
- }
-
- @Test
- public void byStatusOpen() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.NEW);
- Change change1 = insert(repo, ins1);
- insert(repo, newChangeWithStatus(repo, Change.Status.MERGED));
-
- Change[] expected = new Change[] {change1};
- assertQuery("status:open", expected);
- assertQuery("status:OPEN", expected);
- assertQuery("status:o", expected);
- assertQuery("status:op", expected);
- assertQuery("status:ope", expected);
- assertQuery("status:pending", expected);
- assertQuery("status:PENDING", expected);
- assertQuery("status:p", expected);
- assertQuery("status:pe", expected);
- assertQuery("status:pen", expected);
- assertQuery("is:open", expected);
- assertQuery("is:pending", expected);
- }
-
- @Test
- public void byStatusClosed() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.MERGED);
- Change change1 = insert(repo, ins1);
- ChangeInserter ins2 = newChangeWithStatus(repo, Change.Status.ABANDONED);
- Change change2 = insert(repo, ins2);
- insert(repo, newChangeWithStatus(repo, Change.Status.NEW));
-
- Change[] expected = new Change[] {change2, change1};
- assertQuery("status:closed", expected);
- assertQuery("status:CLOSED", expected);
- assertQuery("status:c", expected);
- assertQuery("status:cl", expected);
- assertQuery("status:clo", expected);
- assertQuery("status:clos", expected);
- assertQuery("status:close", expected);
- assertQuery("status:closed", expected);
- assertQuery("is:closed", expected);
- }
-
- @Test
- public void byStatusAbandoned() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.MERGED);
- insert(repo, ins1);
- ChangeInserter ins2 = newChangeWithStatus(repo, Change.Status.ABANDONED);
- Change change1 = insert(repo, ins2);
- insert(repo, newChangeWithStatus(repo, Change.Status.NEW));
-
- assertQuery("status:abandoned", change1);
- assertQuery("status:ABANDONED", change1);
- assertQuery("is:abandoned", change1);
- }
-
- @Test
- public void byStatusPrefix() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.NEW);
- Change change1 = insert(repo, ins1);
- insert(repo, newChangeWithStatus(repo, Change.Status.MERGED));
-
- assertQuery("status:n", change1);
- assertQuery("status:ne", change1);
- assertQuery("status:new", change1);
- assertQuery("status:N", change1);
- assertQuery("status:nE", change1);
- assertQuery("status:neW", change1);
- assertQuery("status:nx");
- assertQuery("status:newx");
- }
-
- @Test
- public void byPrivate() throws Exception {
- if (getSchemaVersion() < 40) {
- assertMissingField(ChangeField.PRIVATE);
- assertFailingQuery(
- "is:private", "'is:private' operator is not supported by change index version");
- return;
- }
-
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo), userId);
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- Change change2 = insert(repo, newChange(repo), user2);
-
- // No private changes.
- assertQuery("is:open", change2, change1);
- assertQuery("is:private");
-
- gApi.changes().id(change1.getChangeId()).setPrivate(true, null);
-
- // Change1 is not private, but should be still visible to its owner.
- assertQuery("is:open", change1, change2);
- assertQuery("is:private", change1);
-
- // Switch request context to user2.
- requestContext.setContext(newRequestContext(user2));
- assertQuery("is:open", change2);
- assertQuery("is:private");
- }
-
- @Test
- public void byWip() throws Exception {
- if (getSchemaVersion() < 42) {
- assertMissingField(ChangeField.WIP);
- assertFailingQuery("is:wip", "'is:wip' operator is not supported by change index version");
- return;
- }
-
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo), userId);
-
- assertQuery("is:open", change1);
- assertQuery("is:wip");
-
- gApi.changes().id(change1.getChangeId()).setWorkInProgress();
-
- assertQuery("is:wip", change1);
-
- gApi.changes().id(change1.getChangeId()).setReadyForReview();
-
- assertQuery("is:wip");
- }
-
- @Test
- public void excludeWipChangeFromReviewersDashboardsBeforeSchema42() throws Exception {
- assume().that(getSchemaVersion()).isLessThan(42);
-
- assertMissingField(ChangeField.WIP);
- assertFailingQuery("is:wip", "'is:wip' operator is not supported by change index version");
-
- Account.Id user1 = createAccount("user1");
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChangeWorkInProgress(repo), userId);
- assertQuery("reviewer:" + user1, change1);
- gApi.changes().id(change1.getChangeId()).setWorkInProgress();
- assertQuery("reviewer:" + user1, change1);
- }
-
- @Test
- public void excludeWipChangeFromReviewersDashboards() throws Exception {
- assume().that(getSchemaVersion()).isAtLeast(42);
-
- Account.Id user1 = createAccount("user1");
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChangeWorkInProgress(repo), userId);
-
- assertQuery("is:wip", change1);
- assertQuery("reviewer:" + user1);
-
- gApi.changes().id(change1.getChangeId()).setReadyForReview();
- assertQuery("is:wip");
- assertQuery("reviewer:" + user1);
-
- gApi.changes().id(change1.getChangeId()).setWorkInProgress();
- assertQuery("is:wip", change1);
- assertQuery("reviewer:" + user1);
- }
-
- @Test
- public void byStartedBeforeSchema44() throws Exception {
- assume().that(getSchemaVersion()).isLessThan(44);
- assertMissingField(ChangeField.STARTED);
- assertFailingQuery(
- "is:started", "'is:started' operator is not supported by change index version");
- }
-
- @Test
- public void byStarted() throws Exception {
- assume().that(getSchemaVersion()).isAtLeast(44);
-
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChangeWorkInProgress(repo));
-
- assertQuery("is:started");
-
- gApi.changes().id(change1.getChangeId()).setReadyForReview();
- assertQuery("is:started", change1);
-
- gApi.changes().id(change1.getChangeId()).setWorkInProgress();
- assertQuery("is:started", change1);
- }
-
- private void assertReviewers(Collection<AccountInfo> reviewers, Object... expected)
- throws Exception {
- if (expected.length == 0) {
- assertThat(reviewers).isNull();
- return;
- }
-
- // Convert AccountInfos to strings, either account ID or email.
- List<String> reviewerIds =
- reviewers.stream()
- .map(
- ai -> {
- if (ai._accountId != null) {
- return ai._accountId.toString();
- }
- return ai.email;
- })
- .collect(toList());
- assertThat(reviewerIds).containsExactly(expected);
- }
-
- @Test
- public void restorePendingReviewers() throws Exception {
- assume().that(getSchemaVersion()).isAtLeast(44);
- assume().that(notesMigration.readChanges()).isTrue();
-
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- ConfigInput conf = new ConfigInput();
- conf.enableReviewerByEmail = InheritableBoolean.TRUE;
- gApi.projects().name(project.get()).config(conf);
- Change change1 = insert(repo, newChangeWorkInProgress(repo));
- Account.Id user1 = createAccount("user1");
- Account.Id user2 = createAccount("user2");
- String email1 = "email1@example.com";
- String email2 = "email2@example.com";
-
- ReviewInput in =
- ReviewInput.noScore()
- .reviewer(user1.toString())
- .reviewer(user2.toString(), ReviewerState.CC, false)
- .reviewer(email1)
- .reviewer(email2, ReviewerState.CC, false);
- gApi.changes().id(change1.getId().get()).revision("current").review(in);
-
- List<ChangeInfo> changeInfos =
- assertQuery(newQuery("is:wip").withOption(DETAILED_LABELS), change1);
- assertThat(changeInfos).isNotEmpty();
-
- Map<ReviewerState, Collection<AccountInfo>> pendingReviewers =
- changeInfos.get(0).pendingReviewers;
- assertThat(pendingReviewers).isNotNull();
-
- assertReviewers(
- pendingReviewers.get(ReviewerState.REVIEWER), userId.toString(), user1.toString(), email1);
- assertReviewers(pendingReviewers.get(ReviewerState.CC), user2.toString(), email2);
- assertReviewers(pendingReviewers.get(ReviewerState.REMOVED));
-
- // Pending reviewers may also be presented in the REMOVED state. Toggle the
- // change to ready and then back to WIP and remove reviewers to produce.
- assertThat(pendingReviewers.get(ReviewerState.REMOVED)).isNull();
- gApi.changes().id(change1.getId().get()).setReadyForReview();
- gApi.changes().id(change1.getId().get()).setWorkInProgress();
- gApi.changes().id(change1.getId().get()).reviewer(user1.toString()).remove();
- gApi.changes().id(change1.getId().get()).reviewer(user2.toString()).remove();
- gApi.changes().id(change1.getId().get()).reviewer(email1).remove();
- gApi.changes().id(change1.getId().get()).reviewer(email2).remove();
-
- changeInfos = assertQuery(newQuery("is:wip").withOption(DETAILED_LABELS), change1);
- assertThat(changeInfos).isNotEmpty();
-
- pendingReviewers = changeInfos.get(0).pendingReviewers;
- assertThat(pendingReviewers).isNotNull();
- assertReviewers(pendingReviewers.get(ReviewerState.REVIEWER));
- assertReviewers(pendingReviewers.get(ReviewerState.CC));
- assertReviewers(
- pendingReviewers.get(ReviewerState.REMOVED),
- user1.toString(),
- user2.toString(),
- email1,
- email2);
- }
-
- @Test
- public void byCommit() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins = newChange(repo);
- Change change = insert(repo, ins);
- String sha = ins.getCommitId().name();
-
- assertQuery("0000000000000000000000000000000000000000");
- assertQuery("commit:0000000000000000000000000000000000000000");
- for (int i = 0; i <= 36; i++) {
- String q = sha.substring(0, 40 - i);
- assertQuery(q, change);
- assertQuery("commit:" + q, change);
- }
- }
-
- @Test
- public void byOwner() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo), userId);
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- Change change2 = insert(repo, newChange(repo), user2);
-
- assertQuery("is:owner", change1);
- assertQuery("owner:" + userId.get(), change1);
- assertQuery("owner:" + user2, change2);
-
- String nameEmail = user.asIdentifiedUser().getNameEmail();
- assertQuery("owner: \"" + nameEmail + "\"", change1);
- }
-
- @Test
- public void byAuthorExact() throws Exception {
- assume().that(getSchema().hasField(ChangeField.EXACT_AUTHOR)).isTrue();
- byAuthorOrCommitterExact("author:");
- }
-
- @Test
- public void byAuthorFullText() throws Exception {
- byAuthorOrCommitterFullText("author:");
- }
-
- @Test
- public void byCommitterExact() throws Exception {
- assume().that(getSchema().hasField(ChangeField.EXACT_COMMITTER)).isTrue();
- byAuthorOrCommitterExact("committer:");
- }
-
- @Test
- public void byCommitterFullText() throws Exception {
- byAuthorOrCommitterFullText("committer:");
- }
-
- private void byAuthorOrCommitterExact(String searchOperator) throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- PersonIdent johnDoe = new PersonIdent("John Doe", "john.doe@example.com");
- PersonIdent john = new PersonIdent("John", "john@example.com");
- PersonIdent doeSmith = new PersonIdent("Doe Smith", "doe_smith@example.com");
- Change change1 = createChange(repo, johnDoe);
- Change change2 = createChange(repo, john);
- Change change3 = createChange(repo, doeSmith);
-
- // Only email address.
- assertQuery(searchOperator + "john.doe@example.com", change1);
- assertQuery(searchOperator + "john@example.com", change2);
- assertQuery(searchOperator + "Doe_SmIth@example.com", change3); // Case insensitive.
-
- // Right combination of email address and name.
- assertQuery(searchOperator + "\"John Doe <john.doe@example.com>\"", change1);
- assertQuery(searchOperator + "\" John <john@example.com> \"", change2);
- assertQuery(searchOperator + "\"doE SMITH <doe_smitH@example.com>\"", change3);
-
- // Wrong combination of email address and name.
- assertQuery(searchOperator + "\"John <john.doe@example.com>\"");
- assertQuery(searchOperator + "\"Doe John <john@example.com>\"");
- assertQuery(searchOperator + "\"Doe John <doe_smith@example.com>\"");
- }
-
- private void byAuthorOrCommitterFullText(String searchOperator) throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- PersonIdent johnDoe = new PersonIdent("John Doe", "john.doe@example.com");
- PersonIdent john = new PersonIdent("John", "john@example.com");
- PersonIdent doeSmith = new PersonIdent("Doe Smith", "doe_smith@example.com");
- Change change1 = createChange(repo, johnDoe);
- Change change2 = createChange(repo, john);
- Change change3 = createChange(repo, doeSmith);
-
- // By exact name.
- assertQuery(searchOperator + "\"John Doe\"", change1);
- assertQuery(searchOperator + "\"john\"", change2, change1);
- assertQuery(searchOperator + "\"Doe smith\"", change3);
-
- // By name part.
- assertQuery(searchOperator + "Doe", change3, change1);
- assertQuery(searchOperator + "smith", change3);
-
- // By wrong combination.
- assertQuery(searchOperator + "\"John Smith\"");
-
- // By invalid query.
- exception.expect(BadRequestException.class);
- exception.expectMessage("invalid value");
- // SchemaUtil.getNameParts will return an empty set for query only containing these characters.
- assertQuery(searchOperator + "@.- /_");
- }
-
- private Change createChange(TestRepository<Repo> repo, PersonIdent person) throws Exception {
- RevCommit commit =
- repo.parseBody(repo.commit().message("message").author(person).committer(person).create());
- return insert(repo, newChangeForCommit(repo, commit), null);
- }
-
- @Test
- public void byOwnerIn() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo), userId);
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- Change change2 = insert(repo, newChange(repo), user2);
- Change change3 = insert(repo, newChange(repo), user2);
- gApi.changes().id(change3.getId().get()).current().review(ReviewInput.approve());
- gApi.changes().id(change3.getId().get()).current().submit();
-
- assertQuery("ownerin:Administrators", change1);
- assertQuery("ownerin:\"Registered Users\"", change2, change1);
- assertQuery("ownerin:\"Registered Users\" project:repo", change3, change2, change1);
- assertQuery("ownerin:\"Registered Users\" status:merged", change3);
- }
-
- @Test
- public void byProject() throws Exception {
- TestRepository<Repo> repo1 = createProject("repo1");
- TestRepository<Repo> repo2 = createProject("repo2");
- Change change1 = insert(repo1, newChange(repo1));
- Change change2 = insert(repo2, newChange(repo2));
-
- assertQuery("project:foo");
- assertQuery("project:repo");
- assertQuery("project:repo1", change1);
- assertQuery("project:repo2", change2);
- }
-
- @Test
- public void byParentProject() throws Exception {
- TestRepository<Repo> repo1 = createProject("repo1");
- TestRepository<Repo> repo2 = createProject("repo2", "repo1");
- Change change1 = insert(repo1, newChange(repo1));
- Change change2 = insert(repo2, newChange(repo2));
-
- assertQuery("parentproject:repo1", change2, change1);
- assertQuery("parentproject:repo2", change2);
- }
-
- @Test
- public void byProjectPrefix() throws Exception {
- TestRepository<Repo> repo1 = createProject("repo1");
- TestRepository<Repo> repo2 = createProject("repo2");
- Change change1 = insert(repo1, newChange(repo1));
- Change change2 = insert(repo2, newChange(repo2));
-
- assertQuery("projects:foo");
- assertQuery("projects:repo1", change1);
- assertQuery("projects:repo2", change2);
- assertQuery("projects:repo", change2, change1);
- }
-
- @Test
- public void byBranchAndRef() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChangeForBranch(repo, "master"));
- Change change2 = insert(repo, newChangeForBranch(repo, "branch"));
-
- assertQuery("branch:foo");
- assertQuery("branch:master", change1);
- assertQuery("branch:refs/heads/master", change1);
- assertQuery("ref:master");
- assertQuery("ref:refs/heads/master", change1);
- assertQuery("branch:refs/heads/master", change1);
- assertQuery("branch:branch", change2);
- assertQuery("branch:refs/heads/branch", change2);
- assertQuery("ref:branch");
- assertQuery("ref:refs/heads/branch", change2);
- }
-
- @Test
- public void byTopic() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithTopic(repo, "feature1");
- Change change1 = insert(repo, ins1);
-
- ChangeInserter ins2 = newChangeWithTopic(repo, "feature2");
- Change change2 = insert(repo, ins2);
-
- ChangeInserter ins3 = newChangeWithTopic(repo, "Cherrypick-feature2");
- Change change3 = insert(repo, ins3);
-
- ChangeInserter ins4 = newChangeWithTopic(repo, "feature2-fixup");
- Change change4 = insert(repo, ins4);
-
- ChangeInserter ins5 = newChangeWithTopic(repo, "https://gerrit.local");
- Change change5 = insert(repo, ins5);
-
- ChangeInserter ins6 = newChangeWithTopic(repo, "git_gerrit_training");
- Change change6 = insert(repo, ins6);
-
- Change change_no_topic = insert(repo, newChange(repo));
-
- assertQuery("intopic:foo");
- assertQuery("intopic:feature1", change1);
- assertQuery("intopic:feature2", change4, change3, change2);
- assertQuery("topic:feature2", change2);
- assertQuery("intopic:feature2", change4, change3, change2);
- assertQuery("intopic:fixup", change4);
- assertQuery("intopic:gerrit", change6, change5);
- assertQuery("topic:\"\"", change_no_topic);
- assertQuery("intopic:\"\"", change_no_topic);
- }
-
- @Test
- public void byTopicRegex() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
-
- ChangeInserter ins1 = newChangeWithTopic(repo, "feature1");
- Change change1 = insert(repo, ins1);
-
- ChangeInserter ins2 = newChangeWithTopic(repo, "Cherrypick-feature1");
- Change change2 = insert(repo, ins2);
-
- ChangeInserter ins3 = newChangeWithTopic(repo, "feature1-fixup");
- Change change3 = insert(repo, ins3);
-
- assertQuery("intopic:^feature1.*", change3, change1);
- assertQuery("intopic:{^.*feature1$}", change2, change1);
- }
-
- @Test
- public void byMessageExact() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 = repo.parseBody(repo.commit().message("one").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- RevCommit commit2 = repo.parseBody(repo.commit().message("two").create());
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- assertQuery("message:foo");
- assertQuery("message:one", change1);
- assertQuery("message:two", change2);
- }
-
- @Test
- public void fullTextWithNumbers() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 = repo.parseBody(repo.commit().message("12345 67890").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- RevCommit commit2 = repo.parseBody(repo.commit().message("12346 67891").create());
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- assertQuery("message:1234");
- assertQuery("message:12345", change1);
- assertQuery("message:12346", change2);
- }
-
- @Test
- public void byMessageMixedCase() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 = repo.parseBody(repo.commit().message("Hello gerrit").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- RevCommit commit2 = repo.parseBody(repo.commit().message("Hello Gerrit").create());
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- assertQuery("message:gerrit", change2, change1);
- assertQuery("message:Gerrit", change2, change1);
- }
-
- @Test
- public void byMessageSubstring() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 = repo.parseBody(repo.commit().message("https://gerrit.local").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- assertQuery("message:gerrit", change1);
- }
-
- @Test
- public void byLabel() throws Exception {
- accountManager.authenticate(AuthRequest.forUser("anotheruser"));
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins = newChange(repo, null, null, null, null, false);
- ChangeInserter ins2 = newChange(repo, null, null, null, null, false);
- ChangeInserter ins3 = newChange(repo, null, null, null, null, false);
- ChangeInserter ins4 = newChange(repo, null, null, null, null, false);
- ChangeInserter ins5 = newChange(repo, null, null, null, null, false);
-
- Change reviewMinus2Change = insert(repo, ins);
- gApi.changes().id(reviewMinus2Change.getId().get()).current().review(ReviewInput.reject());
-
- Change reviewMinus1Change = insert(repo, ins2);
- gApi.changes().id(reviewMinus1Change.getId().get()).current().review(ReviewInput.dislike());
-
- Change noLabelChange = insert(repo, ins3);
-
- Change reviewPlus1Change = insert(repo, ins4);
- gApi.changes().id(reviewPlus1Change.getId().get()).current().review(ReviewInput.recommend());
-
- Change reviewPlus2Change = insert(repo, ins5);
- gApi.changes().id(reviewPlus2Change.getId().get()).current().review(ReviewInput.approve());
-
- Map<String, Short> m =
- gApi.changes()
- .id(reviewPlus1Change.getId().get())
- .reviewer(user.getAccountId().toString())
- .votes();
- assertThat(m).hasSize(1);
- assertThat(m).containsEntry("Code-Review", Short.valueOf((short) 1));
-
- Map<Integer, Change> changes = new LinkedHashMap<>(5);
- changes.put(2, reviewPlus2Change);
- changes.put(1, reviewPlus1Change);
- changes.put(0, noLabelChange);
- changes.put(-1, reviewMinus1Change);
- changes.put(-2, reviewMinus2Change);
-
- assertQuery("label:Code-Review=-2", reviewMinus2Change);
- assertQuery("label:Code-Review-2", reviewMinus2Change);
- assertQuery("label:Code-Review=-1", reviewMinus1Change);
- assertQuery("label:Code-Review-1", reviewMinus1Change);
- assertQuery("label:Code-Review=0", noLabelChange);
- assertQuery("label:Code-Review=+1", reviewPlus1Change);
- assertQuery("label:Code-Review=1", reviewPlus1Change);
- assertQuery("label:Code-Review+1", reviewPlus1Change);
- assertQuery("label:Code-Review=+2", reviewPlus2Change);
- assertQuery("label:Code-Review=2", reviewPlus2Change);
- assertQuery("label:Code-Review+2", reviewPlus2Change);
-
- assertQuery("label:Code-Review>-3", codeReviewInRange(changes, -2, 2));
- assertQuery("label:Code-Review>=-2", codeReviewInRange(changes, -2, 2));
- assertQuery("label:Code-Review>-2", codeReviewInRange(changes, -1, 2));
- assertQuery("label:Code-Review>=-1", codeReviewInRange(changes, -1, 2));
- assertQuery("label:Code-Review>-1", codeReviewInRange(changes, 0, 2));
- assertQuery("label:Code-Review>=0", codeReviewInRange(changes, 0, 2));
- assertQuery("label:Code-Review>0", codeReviewInRange(changes, 1, 2));
- assertQuery("label:Code-Review>=1", codeReviewInRange(changes, 1, 2));
- assertQuery("label:Code-Review>1", reviewPlus2Change);
- assertQuery("label:Code-Review>=2", reviewPlus2Change);
- assertQuery("label:Code-Review>2");
-
- assertQuery("label:Code-Review<=2", codeReviewInRange(changes, -2, 2));
- assertQuery("label:Code-Review<2", codeReviewInRange(changes, -2, 1));
- assertQuery("label:Code-Review<=1", codeReviewInRange(changes, -2, 1));
- assertQuery("label:Code-Review<1", codeReviewInRange(changes, -2, 0));
- assertQuery("label:Code-Review<=0", codeReviewInRange(changes, -2, 0));
- assertQuery("label:Code-Review<0", codeReviewInRange(changes, -2, -1));
- assertQuery("label:Code-Review<=-1", codeReviewInRange(changes, -2, -1));
- assertQuery("label:Code-Review<-1", reviewMinus2Change);
- assertQuery("label:Code-Review<=-2", reviewMinus2Change);
- assertQuery("label:Code-Review<-2");
-
- assertQuery("label:Code-Review=+1,anotheruser");
- assertQuery("label:Code-Review=+1,user", reviewPlus1Change);
- assertQuery("label:Code-Review=+1,user=user", reviewPlus1Change);
- assertQuery("label:Code-Review=+1,Administrators", reviewPlus1Change);
- assertQuery("label:Code-Review=+1,group=Administrators", reviewPlus1Change);
- assertQuery("label:Code-Review=+1,user=owner", reviewPlus1Change);
- assertQuery("label:Code-Review=+1,owner", reviewPlus1Change);
- assertQuery("label:Code-Review=+2,owner", reviewPlus2Change);
- assertQuery("label:Code-Review=-2,owner", reviewMinus2Change);
- }
-
- @Test
- public void byLabelMulti() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Project.NameKey project =
- new Project.NameKey(repo.getRepository().getDescription().getRepositoryName());
- ProjectConfig cfg = projectCache.checkedGet(project).getConfig();
-
- LabelType verified =
- category("Verified", value(1, "Passes"), value(0, "No score"), value(-1, "Failed"));
- cfg.getLabelSections().put(verified.getName(), verified);
-
- String heads = RefNames.REFS_HEADS + "*";
- Util.allow(cfg, Permission.forLabel(Util.verified().getName()), -1, 1, REGISTERED_USERS, heads);
-
- try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
- cfg.commit(md);
- }
- projectCache.evict(cfg.getProject());
-
- ReviewInput reviewVerified = new ReviewInput().label("Verified", 1);
- ChangeInserter ins = newChange(repo, null, null, null, null, false);
- ChangeInserter ins2 = newChange(repo, null, null, null, null, false);
- ChangeInserter ins3 = newChange(repo, null, null, null, null, false);
- ChangeInserter ins4 = newChange(repo, null, null, null, null, false);
- ChangeInserter ins5 = newChange(repo, null, null, null, null, false);
-
- // CR+1
- Change reviewCRplus1 = insert(repo, ins);
- gApi.changes().id(reviewCRplus1.getId().get()).current().review(ReviewInput.recommend());
-
- // CR+2
- Change reviewCRplus2 = insert(repo, ins2);
- gApi.changes().id(reviewCRplus2.getId().get()).current().review(ReviewInput.approve());
-
- // CR+1 VR+1
- Change reviewCRplus1VRplus1 = insert(repo, ins3);
- gApi.changes().id(reviewCRplus1VRplus1.getId().get()).current().review(ReviewInput.recommend());
- gApi.changes().id(reviewCRplus1VRplus1.getId().get()).current().review(reviewVerified);
-
- // CR+2 VR+1
- Change reviewCRplus2VRplus1 = insert(repo, ins4);
- gApi.changes().id(reviewCRplus2VRplus1.getId().get()).current().review(ReviewInput.approve());
- gApi.changes().id(reviewCRplus2VRplus1.getId().get()).current().review(reviewVerified);
-
- // VR+1
- Change reviewVRplus1 = insert(repo, ins5);
- gApi.changes().id(reviewVRplus1.getId().get()).current().review(reviewVerified);
-
- assertQuery("label:Code-Review=+1", reviewCRplus1VRplus1, reviewCRplus1);
- assertQuery(
- "label:Code-Review>=+1",
- reviewCRplus2VRplus1,
- reviewCRplus1VRplus1,
- reviewCRplus2,
- reviewCRplus1);
- assertQuery("label:Code-Review>=+2", reviewCRplus2VRplus1, reviewCRplus2);
-
- assertQuery(
- "label:Code-Review>=+1 label:Verified=+1", reviewCRplus2VRplus1, reviewCRplus1VRplus1);
- assertQuery("label:Code-Review>=+2 label:Verified=+1", reviewCRplus2VRplus1);
- }
-
- @Test
- public void byLabelNotOwner() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins = newChange(repo, null, null, null, null, false);
- Account.Id user1 = createAccount("user1");
-
- Change reviewPlus1Change = insert(repo, ins);
-
- // post a review with user1
- requestContext.setContext(newRequestContext(user1));
- gApi.changes().id(reviewPlus1Change.getId().get()).current().review(ReviewInput.recommend());
-
- assertQuery("label:Code-Review=+1,user=user1", reviewPlus1Change);
- assertQuery("label:Code-Review=+1,owner");
- }
-
- private Change[] codeReviewInRange(Map<Integer, Change> changes, int start, int end) {
- int size = 0;
- Change[] range = new Change[end - start + 1];
- for (int i : changes.keySet()) {
- if (i >= start && i <= end) {
- range[size] = changes.get(i);
- size++;
- }
- }
- return range;
- }
-
- private String createGroup(String name, String owner) throws Exception {
- GroupInput in = new GroupInput();
- in.name = name;
- in.ownerId = owner;
- gApi.groups().create(in);
- return name;
- }
-
- private Account.Id createAccount(String name) throws Exception {
- return accountManager.authenticate(AuthRequest.forUser(name)).getAccountId();
- }
-
- @Test
- public void byLabelGroup() throws Exception {
- Account.Id user1 = createAccount("user1");
- createAccount("user2");
- TestRepository<Repo> repo = createProject("repo");
-
- // create group and add users
- String g1 = createGroup("group1", "Administrators");
- String g2 = createGroup("group2", "Administrators");
- gApi.groups().id(g1).addMembers("user1");
- gApi.groups().id(g2).addMembers("user2");
-
- // create a change
- Change change1 = insert(repo, newChange(repo), user1);
-
- // post a review with user1
- requestContext.setContext(newRequestContext(user1));
- gApi.changes()
- .id(change1.getId().get())
- .current()
- .review(new ReviewInput().label("Code-Review", 1));
-
- // verify that query with user1 will return results.
- requestContext.setContext(newRequestContext(userId));
- assertQuery("label:Code-Review=+1,group1", change1);
- assertQuery("label:Code-Review=+1,group=group1", change1);
- assertQuery("label:Code-Review=+1,user=user1", change1);
- assertQuery("label:Code-Review=+1,user=user2");
- assertQuery("label:Code-Review=+1,group=group2");
- }
-
- @Test
- public void limit() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change last = null;
- int n = 5;
- for (int i = 0; i < n; i++) {
- last = insert(repo, newChange(repo));
- }
-
- for (int i = 1; i <= n + 2; i++) {
- int expectedSize;
- Boolean expectedMoreChanges;
- if (i < n) {
- expectedSize = i;
- expectedMoreChanges = true;
- } else {
- expectedSize = n;
- expectedMoreChanges = null;
- }
- String q = "status:new limit:" + i;
- List<ChangeInfo> results = newQuery(q).get();
- assertThat(results).named(q).hasSize(expectedSize);
- assertThat(results.get(results.size() - 1)._moreChanges)
- .named(q)
- .isEqualTo(expectedMoreChanges);
- assertThat(results.get(0)._number).isEqualTo(last.getId().get());
- }
- }
-
- @Test
- public void start() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- List<Change> changes = new ArrayList<>();
- for (int i = 0; i < 2; i++) {
- changes.add(insert(repo, newChange(repo)));
- }
-
- assertQuery("status:new", changes.get(1), changes.get(0));
- assertQuery(newQuery("status:new").withStart(1), changes.get(0));
- assertQuery(newQuery("status:new").withStart(2));
- assertQuery(newQuery("status:new").withStart(3));
- }
-
- @Test
- public void startWithLimit() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- List<Change> changes = new ArrayList<>();
- for (int i = 0; i < 3; i++) {
- changes.add(insert(repo, newChange(repo)));
- }
-
- assertQuery("status:new limit:2", changes.get(2), changes.get(1));
- assertQuery(newQuery("status:new limit:2").withStart(1), changes.get(1), changes.get(0));
- assertQuery(newQuery("status:new limit:2").withStart(2), changes.get(0));
- assertQuery(newQuery("status:new limit:2").withStart(3));
- }
-
- @Test
- public void maxPages() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
-
- QueryRequest query = newQuery("status:new").withLimit(10);
- assertQuery(query, change);
- assertQuery(query.withStart(1));
- assertQuery(query.withStart(99));
- assertThatQueryException(query.withStart(100))
- .hasMessageThat()
- .isEqualTo("Cannot go beyond page 10 of results");
- assertQuery(query.withLimit(100).withStart(100));
- }
-
- @Test
- public void updateOrder() throws Exception {
- resetTimeWithClockStep(2, MINUTES);
- TestRepository<Repo> repo = createProject("repo");
- List<ChangeInserter> inserters = new ArrayList<>();
- List<Change> changes = new ArrayList<>();
- for (int i = 0; i < 5; i++) {
- inserters.add(newChange(repo));
- changes.add(insert(repo, inserters.get(i)));
- }
-
- for (int i : ImmutableList.of(2, 0, 1, 4, 3)) {
- gApi.changes()
- .id(changes.get(i).getId().get())
- .current()
- .review(new ReviewInput().message("modifying " + i));
- }
-
- assertQuery(
- "status:new",
- changes.get(3),
- changes.get(4),
- changes.get(1),
- changes.get(0),
- changes.get(2));
- }
-
- @Test
- public void updatedOrder() throws Exception {
- resetTimeWithClockStep(1, SECONDS);
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChange(repo);
- Change change1 = insert(repo, ins1);
- Change change2 = insert(repo, newChange(repo));
-
- assertThat(lastUpdatedMs(change1)).isLessThan(lastUpdatedMs(change2));
- assertQuery("status:new", change2, change1);
-
- gApi.changes().id(change1.getId().get()).topic("new-topic");
- change1 = notesFactory.create(db, change1.getProject(), change1.getId()).getChange();
-
- assertThat(lastUpdatedMs(change1)).isGreaterThan(lastUpdatedMs(change2));
- assertThat(lastUpdatedMs(change1) - lastUpdatedMs(change2))
- .isAtLeast(MILLISECONDS.convert(1, SECONDS));
-
- // change1 moved to the top.
- assertQuery("status:new", change1, change2);
- }
-
- @Test
- public void filterOutMoreThanOnePageOfResults() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo), userId);
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- for (int i = 0; i < 5; i++) {
- insert(repo, newChange(repo), user2);
- }
-
- assertQuery("status:new ownerin:Administrators", change);
- assertQuery("status:new ownerin:Administrators limit:2", change);
- }
-
- @Test
- public void filterOutAllResults() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- for (int i = 0; i < 5; i++) {
- insert(repo, newChange(repo), user2);
- }
-
- assertQuery("status:new ownerin:Administrators");
- assertQuery("status:new ownerin:Administrators limit:2");
- }
-
- @Test
- public void byFileExact() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit =
- repo.parseBody(
- repo.commit()
- .message("one")
- .add("dir/file1", "contents1")
- .add("dir/file2", "contents2")
- .create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
-
- assertQuery("file:file");
- assertQuery("file:dir", change);
- assertQuery("file:file1", change);
- assertQuery("file:file2", change);
- assertQuery("file:dir/file1", change);
- assertQuery("file:dir/file2", change);
- }
-
- @Test
- public void byFileRegex() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit =
- repo.parseBody(
- repo.commit()
- .message("one")
- .add("dir/file1", "contents1")
- .add("dir/file2", "contents2")
- .create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
-
- assertQuery("file:.*file.*");
- assertQuery("file:^file.*"); // Whole path only.
- assertQuery("file:^dir.file.*", change);
- }
-
- @Test
- public void byPathExact() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit =
- repo.parseBody(
- repo.commit()
- .message("one")
- .add("dir/file1", "contents1")
- .add("dir/file2", "contents2")
- .create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
-
- assertQuery("path:file");
- assertQuery("path:dir");
- assertQuery("path:file1");
- assertQuery("path:file2");
- assertQuery("path:dir/file1", change);
- assertQuery("path:dir/file2", change);
- }
-
- @Test
- public void byPathRegex() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit =
- repo.parseBody(
- repo.commit()
- .message("one")
- .add("dir/file1", "contents1")
- .add("dir/file2", "contents2")
- .create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
-
- assertQuery("path:.*file.*");
- assertQuery("path:^dir.file.*", change);
- }
-
- @Test
- public void byComment() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins = newChange(repo);
- Change change = insert(repo, ins);
-
- ReviewInput input = new ReviewInput();
- input.message = "toplevel";
- ReviewInput.CommentInput commentInput = new ReviewInput.CommentInput();
- commentInput.line = 1;
- commentInput.message = "inline";
- input.comments =
- ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
- Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(commentInput));
- gApi.changes().id(change.getId().get()).current().review(input);
-
- Map<String, List<CommentInfo>> comments =
- gApi.changes().id(change.getId().get()).current().comments();
- assertThat(comments).hasSize(1);
- CommentInfo comment = Iterables.getOnlyElement(comments.get(Patch.COMMIT_MSG));
- assertThat(comment.message).isEqualTo(commentInput.message);
- ChangeMessageInfo lastMsg =
- Iterables.getLast(gApi.changes().id(change.getId().get()).get().messages, null);
- assertThat(lastMsg.message).isEqualTo("Patch Set 1:\n\n(1 comment)\n\n" + input.message);
-
- assertQuery("comment:foo");
- assertQuery("comment:toplevel", change);
- assertQuery("comment:inline", change);
- }
-
- @Test
- public void byAge() throws Exception {
- long thirtyHoursInMs = MILLISECONDS.convert(30, HOURS);
- resetTimeWithClockStep(thirtyHoursInMs, MILLISECONDS);
- TestRepository<Repo> repo = createProject("repo");
- long startMs = TestTimeUtil.START.getMillis();
- Change change1 = insert(repo, newChange(repo), null, new Timestamp(startMs));
- Change change2 = insert(repo, newChange(repo), null, new Timestamp(startMs + thirtyHoursInMs));
-
- // Stop time so age queries use the same endpoint.
- TestTimeUtil.setClockStep(0, MILLISECONDS);
- TestTimeUtil.setClock(new Timestamp(startMs + 2 * thirtyHoursInMs));
- long nowMs = TimeUtil.nowMs();
-
- assertThat(lastUpdatedMs(change2) - lastUpdatedMs(change1)).isEqualTo(thirtyHoursInMs);
- assertThat(nowMs - lastUpdatedMs(change2)).isEqualTo(thirtyHoursInMs);
- assertThat(TimeUtil.nowMs()).isEqualTo(nowMs);
-
- assertQuery("-age:1d");
- assertQuery("-age:" + (30 * 60 - 1) + "m");
- assertQuery("-age:2d", change2);
- assertQuery("-age:3d", change2, change1);
- assertQuery("age:3d");
- assertQuery("age:2d", change1);
- assertQuery("age:1d", change2, change1);
- }
-
- @Test
- public void byBeforeUntil() throws Exception {
- long thirtyHoursInMs = MILLISECONDS.convert(30, HOURS);
- resetTimeWithClockStep(thirtyHoursInMs, MILLISECONDS);
- TestRepository<Repo> repo = createProject("repo");
- long startMs = TestTimeUtil.START.getMillis();
- Change change1 = insert(repo, newChange(repo), null, new Timestamp(startMs));
- Change change2 = insert(repo, newChange(repo), null, new Timestamp(startMs + thirtyHoursInMs));
- TestTimeUtil.setClockStep(0, MILLISECONDS);
-
- for (String predicate : Lists.newArrayList("before:", "until:")) {
- assertQuery(predicate + "2009-09-29");
- assertQuery(predicate + "2009-09-30");
- assertQuery(predicate + "\"2009-09-30 16:59:00 -0400\"");
- assertQuery(predicate + "\"2009-09-30 20:59:00 -0000\"");
- assertQuery(predicate + "\"2009-09-30 20:59:00\"");
- assertQuery(predicate + "\"2009-09-30 17:02:00 -0400\"", change1);
- assertQuery(predicate + "\"2009-10-01 21:02:00 -0000\"", change1);
- assertQuery(predicate + "\"2009-10-01 21:02:00\"", change1);
- assertQuery(predicate + "2009-10-01", change1);
- assertQuery(predicate + "2009-10-03", change2, change1);
- }
- }
-
- @Test
- public void byAfterSince() throws Exception {
- long thirtyHoursInMs = MILLISECONDS.convert(30, HOURS);
- resetTimeWithClockStep(thirtyHoursInMs, MILLISECONDS);
- TestRepository<Repo> repo = createProject("repo");
- long startMs = TestTimeUtil.START.getMillis();
- Change change1 = insert(repo, newChange(repo), null, new Timestamp(startMs));
- Change change2 = insert(repo, newChange(repo), null, new Timestamp(startMs + thirtyHoursInMs));
- TestTimeUtil.setClockStep(0, MILLISECONDS);
-
- for (String predicate : Lists.newArrayList("after:", "since:")) {
- assertQuery(predicate + "2009-10-03");
- assertQuery(predicate + "\"2009-10-01 20:59:59 -0400\"", change2);
- assertQuery(predicate + "\"2009-10-01 20:59:59 -0000\"", change2);
- assertQuery(predicate + "2009-10-01", change2);
- assertQuery(predicate + "2009-09-30", change2, change1);
- }
- }
-
- @Test
- public void bySize() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
-
- // added = 3, deleted = 0, delta = 3
- RevCommit commit1 = repo.parseBody(repo.commit().add("file1", "foo\n\foo\nfoo").create());
- // added = 0, deleted = 2, delta = 2
- RevCommit commit2 = repo.parseBody(repo.commit().parent(commit1).add("file1", "foo").create());
-
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- assertQuery("added:>4");
- assertQuery("-added:<=4");
-
- assertQuery("added:3", change1);
- assertQuery("-(added:<3 OR added>3)", change1);
-
- assertQuery("added:>2", change1);
- assertQuery("-added:<=2", change1);
-
- assertQuery("added:>=3", change1);
- assertQuery("-added:<3", change1);
-
- assertQuery("added:<1", change2);
- assertQuery("-added:>=1", change2);
-
- assertQuery("added:<=0", change2);
- assertQuery("-added:>0", change2);
-
- assertQuery("deleted:>3");
- assertQuery("-deleted:<=3");
-
- assertQuery("deleted:2", change2);
- assertQuery("-(deleted:<2 OR deleted>2)", change2);
-
- assertQuery("deleted:>1", change2);
- assertQuery("-deleted:<=1", change2);
-
- assertQuery("deleted:>=2", change2);
- assertQuery("-deleted:<2", change2);
-
- assertQuery("deleted:<1", change1);
- assertQuery("-deleted:>=1", change1);
-
- assertQuery("deleted:<=0", change1);
-
- for (String str : Lists.newArrayList("delta:", "size:")) {
- assertQuery(str + "<2");
- assertQuery(str + "3", change1);
- assertQuery(str + ">2", change1);
- assertQuery(str + ">=3", change1);
- assertQuery(str + "<3", change2);
- assertQuery(str + "<=2", change2);
- }
- }
-
- private List<Change> setUpHashtagChanges() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- HashtagsInput in = new HashtagsInput();
- in.add = ImmutableSet.of("foo");
- gApi.changes().id(change1.getId().get()).setHashtags(in);
-
- in.add = ImmutableSet.of("foo", "bar", "a tag", "ACamelCaseTag");
- gApi.changes().id(change2.getId().get()).setHashtags(in);
-
- return ImmutableList.of(change1, change2);
- }
-
- @Test
- public void byHashtagWithNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
- List<Change> changes = setUpHashtagChanges();
- assertQuery("hashtag:foo", changes.get(1), changes.get(0));
- assertQuery("hashtag:bar", changes.get(1));
- assertQuery("hashtag:\"a tag\"", changes.get(1));
- assertQuery("hashtag:\"a tag \"", changes.get(1));
- assertQuery("hashtag:\" a tag \"", changes.get(1));
- assertQuery("hashtag:\"#a tag\"", changes.get(1));
- assertQuery("hashtag:\"# #a tag\"", changes.get(1));
- assertQuery("hashtag:acamelcasetag", changes.get(1));
- assertQuery("hashtag:ACamelCaseTAg", changes.get(1));
- }
-
- @Test
- public void byHashtagWithoutNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
-
- notesMigration.setWriteChanges(true);
- notesMigration.setReadChanges(true);
- db.close();
- db = schemaFactory.open();
- List<Change> changes;
- try {
- changes = setUpHashtagChanges();
- notesMigration.setWriteChanges(false);
- notesMigration.setReadChanges(false);
- } finally {
- db.close();
- }
- db = schemaFactory.open();
- for (Change c : changes) {
- indexer.index(db, c); // Reindex without hashtag field.
- }
- assertQuery("hashtag:foo");
- assertQuery("hashtag:bar");
- assertQuery("hashtag:\" bar \"");
- assertQuery("hashtag:\"a tag\"");
- assertQuery("hashtag:\" a tag \"");
- assertQuery("hashtag:#foo");
- assertQuery("hashtag:\"# #foo\"");
- }
-
- @Test
- public void byDefault() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
-
- Change change1 = insert(repo, newChange(repo));
-
- RevCommit commit2 = repo.parseBody(repo.commit().message("foosubject").create());
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- RevCommit commit3 = repo.parseBody(repo.commit().add("Foo.java", "foo contents").create());
- Change change3 = insert(repo, newChangeForCommit(repo, commit3));
-
- ChangeInserter ins4 = newChange(repo);
- Change change4 = insert(repo, ins4);
- ReviewInput ri4 = new ReviewInput();
- ri4.message = "toplevel";
- ri4.labels = ImmutableMap.<String, Short>of("Code-Review", (short) 1);
- gApi.changes().id(change4.getId().get()).current().review(ri4);
-
- ChangeInserter ins5 = newChangeWithTopic(repo, "feature5");
- Change change5 = insert(repo, ins5);
-
- Change change6 = insert(repo, newChangeForBranch(repo, "branch6"));
-
- assertQuery(change1.getId().get(), change1);
- assertQuery(ChangeTriplet.format(change1), change1);
- assertQuery("foosubject", change2);
- assertQuery("Foo.java", change3);
- assertQuery("Code-Review+1", change4);
- assertQuery("toplevel", change4);
- assertQuery("feature5", change5);
- assertQuery("branch6", change6);
- assertQuery("refs/heads/branch6", change6);
-
- Change[] expected = new Change[] {change6, change5, change4, change3, change2, change1};
- assertQuery("user@example.com", expected);
- assertQuery("repo", expected);
- }
-
- @Test
- public void byDefaultWithCommitPrefix() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit = repo.parseBody(repo.commit().message("message").create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
-
- assertQuery(commit.getId().getName().substring(0, 6), change);
- }
-
- @Test
- public void visible() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- gApi.changes().id(change2.getChangeId()).setPrivate(true, "private");
-
- String q = "project:repo";
- assertQuery(q, change2, change1);
-
- // Second user cannot see first user's private change.
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- assertQuery(q + " visibleto:" + user2.get(), change1);
-
- requestContext.setContext(
- newRequestContext(
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId()));
- assertQuery("is:visible", change1);
- }
-
- @Test
- public void byCommentBy() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- int user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId().get();
-
- ReviewInput input = new ReviewInput();
- input.message = "toplevel";
- ReviewInput.CommentInput comment = new ReviewInput.CommentInput();
- comment.line = 1;
- comment.message = "inline";
- input.comments =
- ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
- Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
- gApi.changes().id(change1.getId().get()).current().review(input);
-
- input = new ReviewInput();
- input.message = "toplevel";
- gApi.changes().id(change2.getId().get()).current().review(input);
-
- assertQuery("commentby:" + userId.get(), change2, change1);
- assertQuery("commentby:" + user2);
- }
-
- @Test
- public void byDraftBy() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- assertQuery("has:draft");
-
- DraftInput in = new DraftInput();
- in.line = 1;
- in.message = "nit: trailing whitespace";
- in.path = Patch.COMMIT_MSG;
- gApi.changes().id(change1.getId().get()).current().createDraft(in);
-
- in = new DraftInput();
- in.line = 2;
- in.message = "nit: point in the end of the statement";
- in.path = Patch.COMMIT_MSG;
- gApi.changes().id(change2.getId().get()).current().createDraft(in);
-
- int user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId().get();
-
- assertQuery("has:draft", change2, change1);
- assertQuery("draftby:" + userId.get(), change2, change1);
- assertQuery("draftby:" + user2);
- }
-
- @Test
- public void byDraftByExcludesZombieDrafts() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- Change change = insert(repo, newChange(repo));
- Change.Id id = change.getId();
-
- DraftInput in = new DraftInput();
- in.line = 1;
- in.message = "nit: trailing whitespace";
- in.path = Patch.COMMIT_MSG;
- gApi.changes().id(id.get()).current().createDraft(in);
-
- assertQuery("draftby:" + userId, change);
- assertQuery("commentby:" + userId);
-
- TestRepository<Repo> allUsers = new TestRepository<>(repoManager.openRepository(allUsersName));
-
- Ref draftsRef = allUsers.getRepository().exactRef(RefNames.refsDraftComments(id, userId));
- assertThat(draftsRef).isNotNull();
-
- ReviewInput rin = ReviewInput.dislike();
- rin.drafts = DraftHandling.PUBLISH_ALL_REVISIONS;
- gApi.changes().id(id.get()).current().review(rin);
-
- assertQuery("draftby:" + userId);
- assertQuery("commentby:" + userId, change);
- assertThat(allUsers.getRepository().exactRef(draftsRef.getName())).isNull();
-
- // Re-add drafts ref and ensure it gets filtered out during indexing.
- allUsers.update(draftsRef.getName(), draftsRef.getObjectId());
- assertThat(allUsers.getRepository().exactRef(draftsRef.getName())).isNotNull();
-
- if (PrimaryStorage.of(change) == PrimaryStorage.REVIEW_DB
- && !notesMigration.disableChangeReviewDb()) {
- // Record draft ref in noteDbState as well.
- ReviewDb db = ReviewDbUtil.unwrapDb(this.db);
- change = db.changes().get(id);
- NoteDbChangeState.applyDelta(
- change,
- NoteDbChangeState.Delta.create(
- id, Optional.empty(), ImmutableMap.of(userId, draftsRef.getObjectId())));
- db.changes().update(Collections.singleton(change));
- }
-
- indexer.index(db, project, id);
- assertQuery("draftby:" + userId);
- }
-
- @Test
- public void byStarredBy() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- insert(repo, newChange(repo));
-
- gApi.accounts().self().starChange(change1.getId().toString());
- gApi.accounts().self().starChange(change2.getId().toString());
-
- int user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId().get();
-
- assertQuery("starredby:self", change2, change1);
- assertQuery("starredby:" + user2);
- }
-
- @Test
- public void byStar() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChangeWithStatus(repo, Change.Status.MERGED));
- Change change3 = insert(repo, newChangeWithStatus(repo, Change.Status.MERGED));
- Change change4 = insert(repo, newChange(repo));
-
- gApi.accounts()
- .self()
- .setStars(
- change1.getId().toString(),
- new StarsInput(new HashSet<>(Arrays.asList("red", "blue"))));
- gApi.accounts()
- .self()
- .setStars(
- change2.getId().toString(),
- new StarsInput(
- new HashSet<>(Arrays.asList(StarredChangesUtil.DEFAULT_LABEL, "green", "blue"))));
-
- gApi.accounts()
- .self()
- .setStars(
- change4.getId().toString(), new StarsInput(new HashSet<>(Arrays.asList("ignore"))));
-
- // check labeled stars
- assertQuery("star:red", change1);
- assertQuery("star:blue", change2, change1);
- assertQuery("has:stars", change4, change2, change1);
-
- // check default star
- assertQuery("has:star", change2);
- assertQuery("is:starred", change2);
- assertQuery("starredby:self", change2);
- assertQuery("star:" + StarredChangesUtil.DEFAULT_LABEL, change2);
-
- // check ignored
- assertQuery("is:ignored", change4);
- assertQuery("-is:ignored", change3, change2, change1);
- }
-
- @Test
- public void byIgnore() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- Change change1 = insert(repo, newChange(repo), user2);
- Change change2 = insert(repo, newChange(repo), user2);
-
- gApi.changes().id(change1.getId().toString()).ignore(true);
- assertQuery("is:ignored", change1);
- assertQuery("-is:ignored", change2);
-
- gApi.changes().id(change1.getId().toString()).ignore(false);
- assertQuery("is:ignored");
- assertQuery("-is:ignored", change2, change1);
- }
-
- @Test
- public void byFrom() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
-
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- Change change2 = insert(repo, newChange(repo), user2);
-
- ReviewInput input = new ReviewInput();
- input.message = "toplevel";
- ReviewInput.CommentInput comment = new ReviewInput.CommentInput();
- comment.line = 1;
- comment.message = "inline";
- input.comments =
- ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
- Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
- gApi.changes().id(change2.getId().get()).current().review(input);
-
- assertQuery("from:" + userId.get(), change2, change1);
- assertQuery("from:" + user2, change2);
- }
-
- @Test
- public void conflicts() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 =
- repo.parseBody(
- repo.commit()
- .add("file1", "contents1")
- .add("dir/file2", "contents2")
- .add("dir/file3", "contents3")
- .create());
- RevCommit commit2 = repo.parseBody(repo.commit().add("file1", "contents1").create());
- RevCommit commit3 =
- repo.parseBody(repo.commit().add("dir/file2", "contents2 different").create());
- RevCommit commit4 = repo.parseBody(repo.commit().add("file4", "contents4").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
- Change change3 = insert(repo, newChangeForCommit(repo, commit3));
- Change change4 = insert(repo, newChangeForCommit(repo, commit4));
-
- assertQuery("conflicts:" + change1.getId().get(), change3);
- assertQuery("conflicts:" + change2.getId().get());
- assertQuery("conflicts:" + change3.getId().get(), change1);
- assertQuery("conflicts:" + change4.getId().get());
- }
-
- @Test
- public void mergeable() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 = repo.parseBody(repo.commit().add("file1", "contents1").create());
- RevCommit commit2 = repo.parseBody(repo.commit().add("file1", "contents2").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- assertQuery("conflicts:" + change1.getId().get(), change2);
- assertQuery("conflicts:" + change2.getId().get(), change1);
- assertQuery("is:mergeable", change2, change1);
-
- gApi.changes().id(change1.getChangeId()).revision("current").review(ReviewInput.approve());
- gApi.changes().id(change1.getChangeId()).revision("current").submit();
-
- assertQuery("status:open conflicts:" + change2.getId().get());
- assertQuery("status:open is:mergeable");
- assertQuery("status:open -is:mergeable", change2);
- }
-
- @Test
- public void reviewedBy() throws Exception {
- resetTimeWithClockStep(2, MINUTES);
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- Change change3 = insert(repo, newChange(repo));
-
- gApi.changes().id(change1.getId().get()).current().review(new ReviewInput().message("comment"));
-
- Account.Id user2 =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- requestContext.setContext(newRequestContext(user2));
-
- gApi.changes().id(change2.getId().get()).current().review(new ReviewInput().message("comment"));
-
- PatchSet.Id ps3_1 = change3.currentPatchSetId();
- change3 = newPatchSet(repo, change3);
- assertThat(change3.currentPatchSetId()).isNotEqualTo(ps3_1);
- // Response to previous patch set still counts as reviewing.
- gApi.changes()
- .id(change3.getId().get())
- .revision(ps3_1.get())
- .review(new ReviewInput().message("comment"));
-
- List<ChangeInfo> actual;
- actual = assertQuery(newQuery("is:reviewed").withOption(REVIEWED), change3, change2);
- assertThat(actual.get(0).reviewed).isTrue();
- assertThat(actual.get(1).reviewed).isTrue();
-
- actual = assertQuery(newQuery("-is:reviewed").withOption(REVIEWED), change1);
- assertThat(actual.get(0).reviewed).isNull();
-
- actual = assertQuery("reviewedby:" + userId.get());
-
- actual =
- assertQuery(newQuery("reviewedby:" + user2.get()).withOption(REVIEWED), change3, change2);
- assertThat(actual.get(0).reviewed).isTrue();
- assertThat(actual.get(1).reviewed).isTrue();
- }
-
- @Test
- public void reviewerAndCc() throws Exception {
- Account.Id user1 = createAccount("user1");
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- Change change3 = insert(repo, newChange(repo));
- insert(repo, newChange(repo));
-
- AddReviewerInput rin = new AddReviewerInput();
- rin.reviewer = user1.toString();
- rin.state = ReviewerState.REVIEWER;
- gApi.changes().id(change1.getId().get()).addReviewer(rin);
-
- rin = new AddReviewerInput();
- rin.reviewer = user1.toString();
- rin.state = ReviewerState.CC;
- gApi.changes().id(change2.getId().get()).addReviewer(rin);
-
- assertQuery("is:reviewer");
- assertQuery("reviewer:self");
- gApi.changes().id(change3.getChangeId()).revision("current").review(ReviewInput.recommend());
- assertQuery("is:reviewer", change3);
- assertQuery("reviewer:self", change3);
-
- requestContext.setContext(newRequestContext(user1));
- if (notesMigration.readChanges()) {
- assertQuery("reviewer:" + user1, change1);
- assertQuery("cc:" + user1, change2);
- assertQuery("is:cc", change2);
- assertQuery("cc:self", change2);
- } else {
- assertQuery("reviewer:" + user1, change2, change1);
- assertQuery("cc:" + user1);
- assertQuery("is:cc");
- assertQuery("cc:self");
- }
- }
-
- @Test
- public void byReviewed() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Account.Id otherUser =
- accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- assertQuery("is:reviewed");
- assertQuery("status:reviewed");
- assertQuery("-is:reviewed", change2, change1);
- assertQuery("-status:reviewed", change2, change1);
-
- requestContext.setContext(newRequestContext(otherUser));
- gApi.changes().id(change1.getChangeId()).current().review(ReviewInput.recommend());
-
- assertQuery("is:reviewed", change1);
- assertQuery("status:reviewed", change1);
- assertQuery("-is:reviewed", change2);
- assertQuery("-status:reviewed", change2);
- }
-
- @Test
- public void reviewerin() throws Exception {
- Account.Id user1 = accountManager.authenticate(AuthRequest.forUser("user1")).getAccountId();
- Account.Id user2 = accountManager.authenticate(AuthRequest.forUser("user2")).getAccountId();
- Account.Id user3 = accountManager.authenticate(AuthRequest.forUser("user3")).getAccountId();
- TestRepository<Repo> repo = createProject("repo");
-
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- Change change3 = insert(repo, newChange(repo));
-
- AddReviewerInput rin = new AddReviewerInput();
- rin.reviewer = user1.toString();
- rin.state = ReviewerState.REVIEWER;
- gApi.changes().id(change1.getId().get()).addReviewer(rin);
-
- rin = new AddReviewerInput();
- rin.reviewer = user2.toString();
- rin.state = ReviewerState.REVIEWER;
- gApi.changes().id(change2.getId().get()).addReviewer(rin);
-
- rin = new AddReviewerInput();
- rin.reviewer = user3.toString();
- rin.state = ReviewerState.CC;
- gApi.changes().id(change3.getId().get()).addReviewer(rin);
-
- String group = gApi.groups().create("foo").get().name;
- gApi.groups().id(group).addMembers(user2.toString(), user3.toString());
-
- List<String> members =
- gApi.groups().id(group).members().stream()
- .map(a -> a._accountId.toString())
- .collect(toList());
- assertThat(members).contains(user2.toString());
-
- if (notesMigration.readChanges()) {
- // CC and REVIEWER are separate in NoteDB
- assertQuery("reviewerin:\"Registered Users\"", change2, change1);
- assertQuery("reviewerin:" + group, change2);
- } else {
- // CC and REVIEWER are the same in ReviewDb
- assertQuery("reviewerin:\"Registered Users\"", change3, change2, change1);
- assertQuery("reviewerin:" + group, change3, change2);
- }
-
- gApi.changes().id(change2.getId().get()).current().review(ReviewInput.approve());
- gApi.changes().id(change2.getId().get()).current().submit();
-
- if (notesMigration.readChanges()) {
- // CC and REVIEWER are separate in NoteDB
- assertQuery("reviewerin:" + group);
- assertQuery("project:repo reviewerin:" + group, change2);
- assertQuery("status:merged reviewerin:" + group, change2);
- } else {
- // CC and REVIEWER are the same in ReviewDb
- assertQuery("reviewerin:" + group, change3);
- assertQuery("project:repo reviewerin:" + group, change2, change3);
- assertQuery("status:merged reviewerin:" + group, change2);
- }
- }
-
- @Test
- public void reviewerAndCcByEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- ConfigInput conf = new ConfigInput();
- conf.enableReviewerByEmail = InheritableBoolean.TRUE;
- gApi.projects().name(project.get()).config(conf);
-
- String userByEmail = "un.registered@reviewer.com";
- String userByEmailWithName = "John Doe <" + userByEmail + ">";
-
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- insert(repo, newChange(repo));
-
- AddReviewerInput rin = new AddReviewerInput();
- rin.reviewer = userByEmailWithName;
- rin.state = ReviewerState.REVIEWER;
- gApi.changes().id(change1.getId().get()).addReviewer(rin);
-
- rin = new AddReviewerInput();
- rin.reviewer = userByEmailWithName;
- rin.state = ReviewerState.CC;
- gApi.changes().id(change2.getId().get()).addReviewer(rin);
-
- if (getSchemaVersion() >= 41) {
- assertQuery("reviewer:\"" + userByEmailWithName + "\"", change1);
- assertQuery("cc:\"" + userByEmailWithName + "\"", change2);
-
- // Omitting the name:
- assertQuery("reviewer:\"" + userByEmail + "\"", change1);
- assertQuery("cc:\"" + userByEmail + "\"", change2);
- } else {
- assertMissingField(ChangeField.REVIEWER_BY_EMAIL);
-
- assertFailingQuery(
- "reviewer:\"" + userByEmailWithName + "\"", "User " + userByEmailWithName + " not found");
- assertFailingQuery(
- "cc:\"" + userByEmailWithName + "\"", "User " + userByEmailWithName + " not found");
-
- // Omitting the name:
- assertFailingQuery("reviewer:\"" + userByEmail + "\"", "User " + userByEmail + " not found");
- assertFailingQuery("cc:\"" + userByEmail + "\"", "User " + userByEmail + " not found");
- }
- }
-
- @Test
- public void reviewerAndCcByEmailWithQueryForDifferentUser() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- ConfigInput conf = new ConfigInput();
- conf.enableReviewerByEmail = InheritableBoolean.TRUE;
- gApi.projects().name(project.get()).config(conf);
-
- String userByEmail = "John Doe <un.registered@reviewer.com>";
-
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- insert(repo, newChange(repo));
-
- AddReviewerInput rin = new AddReviewerInput();
- rin.reviewer = userByEmail;
- rin.state = ReviewerState.REVIEWER;
- gApi.changes().id(change1.getId().get()).addReviewer(rin);
-
- rin = new AddReviewerInput();
- rin.reviewer = userByEmail;
- rin.state = ReviewerState.CC;
- gApi.changes().id(change2.getId().get()).addReviewer(rin);
-
- if (getSchemaVersion() >= 41) {
- assertQuery("reviewer:\"someone@example.com\"");
- assertQuery("cc:\"someone@example.com\"");
- } else {
- assertMissingField(ChangeField.REVIEWER_BY_EMAIL);
-
- String someoneEmail = "someone@example.com";
- assertFailingQuery(
- "reviewer:\"" + someoneEmail + "\"", "User " + someoneEmail + " not found");
- assertFailingQuery("cc:\"" + someoneEmail + "\"", "User " + someoneEmail + " not found");
- }
- }
-
- @Test
- public void submitRecords() throws Exception {
- Account.Id user1 = createAccount("user1");
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- gApi.changes().id(change1.getId().get()).current().review(ReviewInput.approve());
- requestContext.setContext(newRequestContext(user1));
- gApi.changes().id(change2.getId().get()).current().review(ReviewInput.recommend());
- requestContext.setContext(newRequestContext(user.getAccountId()));
-
- assertQuery("is:submittable", change1);
- assertQuery("-is:submittable", change2);
- assertQuery("submittable:ok", change1);
- assertQuery("submittable:not_ready", change2);
-
- assertQuery("label:CodE-RevieW=ok", change1);
- assertQuery("label:CodE-RevieW=ok,user=user", change1);
- assertQuery("label:CodE-RevieW=ok,Administrators", change1);
- assertQuery("label:CodE-RevieW=ok,group=Administrators", change1);
- assertQuery("label:CodE-RevieW=ok,owner", change1);
- assertQuery("label:CodE-RevieW=ok,user1");
- assertQuery("label:CodE-RevieW=need", change2);
- // NEED records don't have associated users.
- assertQuery("label:CodE-RevieW=need,user1");
- assertQuery("label:CodE-RevieW=need,user");
-
- gApi.changes().id(change1.getId().get()).current().submit();
- assertQuery("submittable:ok");
- assertQuery("submittable:closed", change1);
- }
-
- @Test
- public void hasEdit() throws Exception {
- Account.Id user1 = createAccount("user1");
- Account.Id user2 = createAccount("user2");
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- String changeId1 = change1.getKey().get();
- Change change2 = insert(repo, newChange(repo));
- String changeId2 = change2.getKey().get();
-
- requestContext.setContext(newRequestContext(user1));
- assertQuery("has:edit");
- gApi.changes().id(changeId1).edit().create();
- gApi.changes().id(changeId2).edit().create();
-
- requestContext.setContext(newRequestContext(user2));
- assertQuery("has:edit");
- gApi.changes().id(changeId2).edit().create();
-
- requestContext.setContext(newRequestContext(user1));
- assertQuery("has:edit", change2, change1);
-
- requestContext.setContext(newRequestContext(user2));
- assertQuery("has:edit", change2);
- }
-
- @Test
- public void byUnresolved() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
- Change change3 = insert(repo, newChange(repo));
-
- // Change1 has one resolved comment (unresolvedcount = 0)
- // Change2 has one unresolved comment (unresolvedcount = 1)
- // Change3 has one resolved comment and one unresolved comment (unresolvedcount = 1)
- addComment(change1.getChangeId(), "comment 1", false);
- addComment(change2.getChangeId(), "comment 2", true);
- addComment(change3.getChangeId(), "comment 3", false);
- addComment(change3.getChangeId(), "comment 4", true);
-
- assertQuery("has:unresolved", change3, change2);
-
- assertQuery("unresolved:0", change1);
- List<ChangeInfo> changeInfos = assertQuery("unresolved:>=0", change3, change2, change1);
- assertThat(changeInfos.get(0).unresolvedCommentCount).isEqualTo(1); // Change3
- assertThat(changeInfos.get(1).unresolvedCommentCount).isEqualTo(1); // Change2
- assertThat(changeInfos.get(2).unresolvedCommentCount).isEqualTo(0); // Change1
- assertQuery("unresolved:>0", change3, change2);
-
- assertQuery("unresolved:<1", change1);
- assertQuery("unresolved:<=1", change3, change2, change1);
- assertQuery("unresolved:1", change3, change2);
- assertQuery("unresolved:>1");
- assertQuery("unresolved:>=1", change3, change2);
- }
-
- @Test
- public void byCommitsOnBranchNotMerged() throws Exception {
- TestRepository<Repo> tr = createProject("repo");
- testByCommitsOnBranchNotMerged(tr, ImmutableSet.of());
- }
-
- @Test
- public void byCommitsOnBranchNotMergedSkipsMissingChanges() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ObjectId missing =
- repo.branch(new PatchSet.Id(new Change.Id(987654), 1).toRefName())
- .commit()
- .message("No change for this commit")
- .insertChangeId()
- .create()
- .copy();
- testByCommitsOnBranchNotMerged(repo, ImmutableSet.of(missing));
- }
-
- private void testByCommitsOnBranchNotMerged(TestRepository<Repo> repo, Collection<ObjectId> extra)
- throws Exception {
- int n = 10;
- List<String> shas = new ArrayList<>(n + extra.size());
- extra.forEach(i -> shas.add(i.name()));
- List<Integer> expectedIds = new ArrayList<>(n);
- Branch.NameKey dest = null;
- for (int i = 0; i < n; i++) {
- ChangeInserter ins = newChange(repo);
- insert(repo, ins);
- if (dest == null) {
- dest = ins.getChange().getDest();
- }
- shas.add(ins.getCommitId().name());
- expectedIds.add(ins.getChange().getId().get());
- }
-
- for (int i = 1; i <= 11; i++) {
- Iterable<ChangeData> cds =
- queryProvider.get().byCommitsOnBranchNotMerged(repo.getRepository(), db, dest, shas, i);
- Iterable<Integer> ids = FluentIterable.from(cds).transform(in -> in.getId().get());
- String name = "limit " + i;
- assertThat(ids).named(name).hasSize(n);
- assertThat(ids).named(name).containsExactlyElementsIn(expectedIds);
- }
- }
-
- @Test
- public void prepopulatedFields() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
-
- db = new DisabledReviewDb();
- requestContext.setContext(newRequestContext(userId));
- // Use QueryProcessor directly instead of API so we get ChangeDatas back.
- List<ChangeData> cds =
- queryProcessorProvider
- .get()
- .query(queryBuilder.parse(change.getId().toString()))
- .entities();
- assertThat(cds).hasSize(1);
-
- ChangeData cd = cds.get(0);
- cd.change();
- cd.patchSets();
- cd.currentApprovals();
- cd.changedLines();
- cd.reviewedBy();
- cd.reviewers();
- cd.unresolvedCommentCount();
-
- // TODO(dborowitz): Swap out GitRepositoryManager somehow? Will probably be
- // necessary for NoteDb anyway.
- cd.isMergeable();
-
- exception.expect(DisabledReviewDb.Disabled.class);
- cd.messages();
- }
-
- @Test
- public void prepopulateOnlyRequestedFields() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
-
- db = new DisabledReviewDb();
- requestContext.setContext(newRequestContext(userId));
- // Use QueryProcessor directly instead of API so we get ChangeDatas back.
- List<ChangeData> cds =
- queryProcessorProvider
- .get()
- .setRequestedFields(
- ImmutableSet.of(ChangeField.PATCH_SET.getName(), ChangeField.CHANGE.getName()))
- .query(queryBuilder.parse(change.getId().toString()))
- .entities();
- assertThat(cds).hasSize(1);
-
- ChangeData cd = cds.get(0);
- cd.change();
- cd.patchSets();
-
- exception.expect(DisabledReviewDb.Disabled.class);
- cd.currentApprovals();
- }
-
- @Test
- public void reindexIfStale() throws Exception {
- Account.Id user = createAccount("user");
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- Change change = insert(repo, newChange(repo));
- String changeId = change.getKey().get();
- ChangeNotes notes = notesFactory.create(db, change.getProject(), change.getId());
- PatchSet ps = psUtil.get(db, notes, change.currentPatchSetId());
-
- requestContext.setContext(newRequestContext(user));
- gApi.changes().id(changeId).edit().create();
- assertQuery("has:edit", change);
- assertThat(indexer.reindexIfStale(project, change.getId()).get()).isFalse();
-
- // Delete edit ref behind index's back.
- RefUpdate ru =
- repo.getRepository().updateRef(RefNames.refsEdit(user, change.getId(), ps.getId()));
- ru.setForceUpdate(true);
- assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
-
- // Index is stale.
- assertQuery("has:edit", change);
- assertThat(indexer.reindexIfStale(project, change.getId()).get()).isTrue();
- assertQuery("has:edit");
- }
-
- @Test
- public void refStateFields() throws Exception {
- // This test method manages primary storage manually.
- assume().that(notesMigration.changePrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- Account.Id user = createAccount("user");
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- String path = "file";
- RevCommit commit = repo.parseBody(repo.commit().message("one").add(path, "contents").create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
- Change.Id id = change.getId();
- int c = id.get();
- String changeId = change.getKey().get();
- requestContext.setContext(newRequestContext(user));
-
- // Ensure one of each type of supported ref is present for the change. If
- // any more refs are added, update this test to reflect them.
-
- // Edit
- gApi.changes().id(changeId).edit().create();
-
- // Star
- gApi.accounts().self().starChange(change.getId().toString());
-
- if (notesMigration.readChanges()) {
- // Robot comment.
- ReviewInput rin = new ReviewInput();
- RobotCommentInput rcin = new RobotCommentInput();
- rcin.robotId = "happyRobot";
- rcin.robotRunId = "1";
- rcin.line = 1;
- rcin.message = "nit: trailing whitespace";
- rcin.path = path;
- rin.robotComments = ImmutableMap.of(path, ImmutableList.of(rcin));
- gApi.changes().id(c).current().review(rin);
- }
-
- // Draft.
- DraftInput din = new DraftInput();
- din.path = path;
- din.line = 1;
- din.message = "draft";
- gApi.changes().id(c).current().createDraft(din);
-
- if (notesMigration.readChanges()) {
- // Force NoteDb primary.
- change = ReviewDbUtil.unwrapDb(db).changes().get(id);
- change.setNoteDbState(NoteDbChangeState.NOTE_DB_PRIMARY_STATE);
- ReviewDbUtil.unwrapDb(db).changes().update(Collections.singleton(change));
- indexer.index(db, change);
- }
-
- QueryOptions opts =
- IndexedChangeQuery.createOptions(indexConfig, 0, 1, StalenessChecker.FIELDS);
- ChangeData cd = indexes.getSearchIndex().get(id, opts).get();
-
- String cs = RefNames.shard(c);
- int u = user.get();
- String us = RefNames.shard(u);
-
- List<String> expectedStates =
- Lists.newArrayList(
- "repo:refs/users/" + us + "/edit-" + c + "/1",
- "All-Users:refs/starred-changes/" + cs + "/" + u);
- if (notesMigration.readChanges()) {
- expectedStates.add("repo:refs/changes/" + cs + "/meta");
- expectedStates.add("repo:refs/changes/" + cs + "/robot-comments");
- expectedStates.add("All-Users:refs/draft-comments/" + cs + "/" + u);
- }
- assertThat(
- cd.getRefStates().stream()
- .map(String::new)
- // Omit SHA-1, we're just concerned with the project/ref names.
- .map(s -> s.substring(0, s.lastIndexOf(':')))
- .collect(toList()))
- .containsExactlyElementsIn(expectedStates);
-
- List<String> expectedPatterns = Lists.newArrayList("repo:refs/users/*/edit-" + c + "/*");
- expectedPatterns.add("All-Users:refs/starred-changes/" + cs + "/*");
- if (notesMigration.readChanges()) {
- expectedPatterns.add("All-Users:refs/draft-comments/" + cs + "/*");
- }
- assertThat(cd.getRefStatePatterns().stream().map(String::new).collect(toList()))
- .containsExactlyElementsIn(expectedPatterns);
- }
-
- @Test
- public void watched() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.NEW);
- Change change1 = insert(repo, ins1);
-
- TestRepository<Repo> repo2 = createProject("repo2");
-
- ChangeInserter ins2 = newChangeWithStatus(repo2, Change.Status.NEW);
- insert(repo2, ins2);
-
- assertQuery("is:watched");
- assertQuery("watchedby:self");
-
- List<ProjectWatchInfo> projectsToWatch = new ArrayList<>();
- ProjectWatchInfo pwi = new ProjectWatchInfo();
- pwi.project = "repo";
- pwi.filter = null;
- pwi.notifyAbandonedChanges = true;
- pwi.notifyNewChanges = true;
- pwi.notifyAllComments = true;
- projectsToWatch.add(pwi);
- gApi.accounts().self().setWatchedProjects(projectsToWatch);
-
- assertQuery("is:watched", change1);
- assertQuery("watchedby:self", change1);
- }
-
- @Test
- public void trackingid() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- RevCommit commit1 =
- repo.parseBody(repo.commit().message("Change one\n\nBug:QUERY123").create());
- Change change1 = insert(repo, newChangeForCommit(repo, commit1));
- RevCommit commit2 =
- repo.parseBody(repo.commit().message("Change two\n\nFeature:QUERY456").create());
- Change change2 = insert(repo, newChangeForCommit(repo, commit2));
-
- assertQuery("tr:QUERY123", change1);
- assertQuery("bug:QUERY123", change1);
- assertQuery("tr:QUERY456", change2);
- assertQuery("bug:QUERY456", change2);
- assertQuery("tr:QUERY-123");
- assertQuery("bug:QUERY-123");
- assertQuery("tr:QUERY12");
- assertQuery("bug:QUERY12");
- assertQuery("tr:QUERY789");
- assertQuery("bug:QUERY789");
- }
-
- @Test
- public void selfAndMe() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo), userId);
- insert(repo, newChange(repo));
- gApi.accounts().self().starChange(change1.getId().toString());
- gApi.accounts().self().starChange(change2.getId().toString());
-
- assertQuery("starredby:self", change2, change1);
- assertQuery("starredby:me", change2, change1);
- }
-
- @Test
- public void defaultFieldWithManyUsers() throws Exception {
- for (int i = 0; i < ChangeQueryBuilder.MAX_ACCOUNTS_PER_DEFAULT_FIELD * 2; i++) {
- createAccount("user" + i, "User " + i, "user" + i + "@example.com", true);
- }
- assertQuery("us");
- }
-
- @Test
- public void revertOf() throws Exception {
- if (getSchemaVersion() < 45) {
- assertMissingField(ChangeField.REVERT_OF);
- assertFailingQuery(
- "revertof:1", "'revertof' operator is not supported by change index version");
- return;
- }
-
- TestRepository<Repo> repo = createProject("repo");
- // Create two commits and revert second commit (initial commit can't be reverted)
- Change initial = insert(repo, newChange(repo));
- gApi.changes().id(initial.getChangeId()).current().review(ReviewInput.approve());
- gApi.changes().id(initial.getChangeId()).current().submit();
-
- ChangeInfo changeToRevert =
- gApi.changes().create(new ChangeInput("repo", "master", "commit to revert")).get();
- gApi.changes().id(changeToRevert.id).current().review(ReviewInput.approve());
- gApi.changes().id(changeToRevert.id).current().submit();
-
- ChangeInfo changeThatReverts = gApi.changes().id(changeToRevert.id).revert().get();
- assertQueryByIds(
- "revertof:" + changeToRevert._number, new Change.Id(changeThatReverts._number));
- }
-
- @Test
- public void assignee() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChange(repo));
-
- AssigneeInput input = new AssigneeInput();
- input.assignee = user.getUserName();
- gApi.changes().id(change1.getChangeId()).setAssignee(input);
-
- assertQuery("is:assigned", change1);
- assertQuery("-is:assigned", change2);
- assertQuery("is:unassigned", change2);
- assertQuery("-is:unassigned", change1);
- assertQuery("assignee:" + user.getUserName(), change1);
- assertQuery("-assignee:" + user.getUserName(), change2);
- }
-
- @Test
- public void userDestination() throws Exception {
- TestRepository<Repo> repo1 = createProject("repo1");
- Change change1 = insert(repo1, newChange(repo1));
- TestRepository<Repo> repo2 = createProject("repo2");
- Change change2 = insert(repo2, newChange(repo2));
-
- assertThatQueryException("destination:foo")
- .hasMessageThat()
- .isEqualTo("Unknown named destination: foo");
-
- String destination1 = "refs/heads/master\trepo1";
- String destination2 = "refs/heads/master\trepo2";
- String destination3 = "refs/heads/master\trepo1\nrefs/heads/master\trepo2";
- String destination4 = "refs/heads/master\trepo3";
- String destination5 = "refs/heads/other\trepo1";
-
- TestRepository<Repo> allUsers = new TestRepository<>(repoManager.openRepository(allUsersName));
- String refsUsers = RefNames.refsUsers(userId);
- allUsers.branch(refsUsers).commit().add("destinations/destination1", destination1).create();
- allUsers.branch(refsUsers).commit().add("destinations/destination2", destination2).create();
- allUsers.branch(refsUsers).commit().add("destinations/destination3", destination3).create();
- allUsers.branch(refsUsers).commit().add("destinations/destination4", destination4).create();
- allUsers.branch(refsUsers).commit().add("destinations/destination5", destination5).create();
-
- Ref userRef = allUsers.getRepository().exactRef(refsUsers);
- assertThat(userRef).isNotNull();
-
- assertQuery("destination:destination1", change1);
- assertQuery("destination:destination2", change2);
- assertQuery("destination:destination3", change2, change1);
- assertQuery("destination:destination4");
- assertQuery("destination:destination5");
- }
-
- @Test
- public void userQuery() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change1 = insert(repo, newChange(repo));
- Change change2 = insert(repo, newChangeForBranch(repo, "stable"));
-
- String queries =
- "query1\tproject:repo\n"
- + "query2\tproject:repo status:open\n"
- + "query3\tproject:repo branch:stable\n"
- + "query4\tproject:repo branch:other";
-
- TestRepository<Repo> allUsers = new TestRepository<>(repoManager.openRepository(allUsersName));
- String refsUsers = RefNames.refsUsers(userId);
- allUsers.branch(refsUsers).commit().add("queries", queries).create();
-
- Ref userRef = allUsers.getRepository().exactRef(refsUsers);
- assertThat(userRef).isNotNull();
-
- assertThatQueryException("query:foo").hasMessageThat().isEqualTo("Unknown named query: foo");
-
- assertQuery("query:query1", change2, change1);
- assertQuery("query:query2", change2, change1);
- gApi.changes().id(change1.getChangeId()).revision("current").review(ReviewInput.approve());
- gApi.changes().id(change1.getChangeId()).revision("current").submit();
- assertQuery("query:query2", change2);
- assertQuery("query:query3", change2);
- assertQuery("query:query4");
- }
-
- @Test
- public void byOwnerInvalidQuery() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- insert(repo, newChange(repo), userId);
- String nameEmail = user.asIdentifiedUser().getNameEmail();
- assertQuery("owner: \"" + nameEmail + "\"\\");
- }
-
- @Test
- public void byDeletedChange() throws Exception {
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
-
- String query = "change:" + change.getId();
- assertQuery(query, change);
-
- gApi.changes().id(change.getChangeId()).delete();
- assertQuery(query);
- }
-
- @Test
- public void byUrlEncodedProject() throws Exception {
- TestRepository<Repo> repo = createProject("repo+foo");
- Change change = insert(repo, newChange(repo));
- assertQuery("project:repo+foo", change);
- }
-
- protected ChangeInserter newChange(TestRepository<Repo> repo) throws Exception {
- return newChange(repo, null, null, null, null, false);
- }
-
- protected ChangeInserter newChangeForCommit(TestRepository<Repo> repo, RevCommit commit)
- throws Exception {
- return newChange(repo, commit, null, null, null, false);
- }
-
- protected ChangeInserter newChangeForBranch(TestRepository<Repo> repo, String branch)
- throws Exception {
- return newChange(repo, null, branch, null, null, false);
- }
-
- protected ChangeInserter newChangeWithStatus(TestRepository<Repo> repo, Change.Status status)
- throws Exception {
- return newChange(repo, null, null, status, null, false);
- }
-
- protected ChangeInserter newChangeWithTopic(TestRepository<Repo> repo, String topic)
- throws Exception {
- return newChange(repo, null, null, null, topic, false);
- }
-
- protected ChangeInserter newChangeWorkInProgress(TestRepository<Repo> repo) throws Exception {
- return newChange(repo, null, null, null, null, true);
- }
-
- protected ChangeInserter newChange(
- TestRepository<Repo> repo,
- @Nullable RevCommit commit,
- @Nullable String branch,
- @Nullable Change.Status status,
- @Nullable String topic,
- boolean workInProgress)
- throws Exception {
- if (commit == null) {
- commit = repo.parseBody(repo.commit().message("message").create());
- }
-
- branch = MoreObjects.firstNonNull(branch, "refs/heads/master");
- if (!branch.startsWith("refs/heads/")) {
- branch = "refs/heads/" + branch;
- }
-
- Change.Id id = new Change.Id(seq.nextChangeId());
- ChangeInserter ins =
- changeFactory
- .create(id, commit, branch)
- .setValidate(false)
- .setStatus(status)
- .setTopic(topic)
- .setWorkInProgress(workInProgress);
- return ins;
- }
-
- protected Change insert(TestRepository<Repo> repo, ChangeInserter ins) throws Exception {
- return insert(repo, ins, null, TimeUtil.nowTs());
- }
-
- protected Change insert(TestRepository<Repo> repo, ChangeInserter ins, @Nullable Account.Id owner)
- throws Exception {
- return insert(repo, ins, owner, TimeUtil.nowTs());
- }
-
- protected Change insert(
- TestRepository<Repo> repo,
- ChangeInserter ins,
- @Nullable Account.Id owner,
- Timestamp createdOn)
- throws Exception {
- Project.NameKey project =
- new Project.NameKey(repo.getRepository().getDescription().getRepositoryName());
- Account.Id ownerId = owner != null ? owner : userId;
- IdentifiedUser user = userFactory.create(ownerId);
- try (BatchUpdate bu = updateFactory.create(db, project, user, createdOn)) {
- bu.insertChange(ins);
- bu.execute();
- return ins.getChange();
- }
- }
-
- protected Change newPatchSet(TestRepository<Repo> repo, Change c) throws Exception {
- // Add a new file so the patch set is not a trivial rebase, to avoid default
- // Code-Review label copying.
- int n = c.currentPatchSetId().get() + 1;
- RevCommit commit =
- repo.parseBody(repo.commit().message("message").add("file" + n, "contents " + n).create());
-
- PatchSetInserter inserter =
- patchSetFactory
- .create(changeNotesFactory.createChecked(db, c), new PatchSet.Id(c.getId(), n), commit)
- .setNotify(NotifyHandling.NONE)
- .setFireRevisionCreated(false)
- .setValidate(false);
- try (BatchUpdate bu = updateFactory.create(db, c.getProject(), user, TimeUtil.nowTs());
- ObjectInserter oi = repo.getRepository().newObjectInserter();
- ObjectReader reader = oi.newReader();
- RevWalk rw = new RevWalk(reader)) {
- bu.setRepository(repo.getRepository(), rw, oi);
- bu.addOp(c.getId(), inserter);
- bu.execute();
- }
-
- return inserter.getChange();
- }
-
- protected ThrowableSubject assertThatQueryException(Object query) throws Exception {
- return assertThatQueryException(newQuery(query));
- }
-
- protected ThrowableSubject assertThatQueryException(QueryRequest query) throws Exception {
- try {
- query.get();
- throw new AssertionError("expected BadRequestException for query: " + query);
- } catch (BadRequestException e) {
- return assertThat(e);
- }
- }
-
- protected TestRepository<Repo> createProject(String name) throws Exception {
- gApi.projects().create(name).get();
- return new TestRepository<>(repoManager.openRepository(new Project.NameKey(name)));
- }
-
- protected TestRepository<Repo> createProject(String name, String parent) throws Exception {
- ProjectInput input = new ProjectInput();
- input.name = name;
- input.parent = parent;
- gApi.projects().create(input).get();
- return new TestRepository<>(repoManager.openRepository(new Project.NameKey(name)));
- }
-
- protected QueryRequest newQuery(Object query) {
- return gApi.changes().query(query.toString());
- }
-
- protected List<ChangeInfo> assertQuery(Object query, Change... changes) throws Exception {
- return assertQuery(newQuery(query), changes);
- }
-
- protected List<ChangeInfo> assertQueryByIds(Object query, Change.Id... changes) throws Exception {
- return assertQueryByIds(newQuery(query), changes);
- }
-
- protected List<ChangeInfo> assertQuery(QueryRequest query, Change... changes) throws Exception {
- return assertQueryByIds(
- query, Arrays.stream(changes).map(Change::getId).toArray(Change.Id[]::new));
- }
-
- protected List<ChangeInfo> assertQueryByIds(QueryRequest query, Change.Id... changes)
- throws Exception {
- List<ChangeInfo> result = query.get();
- Iterable<Change.Id> ids = ids(result);
- assertThat(ids)
- .named(format(query, ids, changes))
- .containsExactlyElementsIn(Arrays.asList(changes))
- .inOrder();
- return result;
- }
-
- private String format(
- QueryRequest query, Iterable<Change.Id> actualIds, Change.Id... expectedChanges)
- throws RestApiException {
- StringBuilder b = new StringBuilder();
- b.append("query '").append(query.getQuery()).append("' with expected changes ");
- b.append(format(Arrays.asList(expectedChanges)));
- b.append(" and result ");
- b.append(format(actualIds));
- return b.toString();
- }
-
- private String format(Iterable<Change.Id> changeIds) throws RestApiException {
- return format(changeIds.iterator());
- }
-
- private String format(Iterator<Change.Id> changeIds) throws RestApiException {
- StringBuilder b = new StringBuilder();
- b.append("[");
- while (changeIds.hasNext()) {
- Change.Id id = changeIds.next();
- ChangeInfo c = gApi.changes().id(id.get()).get();
- b.append("{")
- .append(id)
- .append(" (")
- .append(c.changeId)
- .append("), ")
- .append("dest=")
- .append(new Branch.NameKey(new Project.NameKey(c.project), c.branch))
- .append(", ")
- .append("status=")
- .append(c.status)
- .append(", ")
- .append("lastUpdated=")
- .append(c.updated.getTime())
- .append("}");
- if (changeIds.hasNext()) {
- b.append(", ");
- }
- }
- b.append("]");
- return b.toString();
- }
-
- protected static Iterable<Change.Id> ids(Change... changes) {
- return Arrays.stream(changes).map(c -> c.getId()).collect(toList());
- }
-
- protected static Iterable<Change.Id> ids(Iterable<ChangeInfo> changes) {
- return Streams.stream(changes).map(c -> new Change.Id(c._number)).collect(toList());
- }
-
- protected static long lastUpdatedMs(Change c) {
- return c.getLastUpdatedOn().getTime();
- }
-
- private void addComment(int changeId, String message, Boolean unresolved) throws Exception {
- ReviewInput input = new ReviewInput();
- ReviewInput.CommentInput comment = new ReviewInput.CommentInput();
- comment.line = 1;
- comment.message = message;
- comment.unresolved = unresolved;
- input.comments =
- ImmutableMap.<String, List<ReviewInput.CommentInput>>of(
- Patch.COMMIT_MSG, ImmutableList.<ReviewInput.CommentInput>of(comment));
- gApi.changes().id(changeId).current().review(input);
- }
-
- private Account.Id createAccount(String username, String fullName, String email, boolean active)
- throws Exception {
- try (ManualRequestContext ctx = oneOffRequestContext.open()) {
- Account.Id id = accountManager.authenticate(AuthRequest.forUser(username)).getAccountId();
- if (email != null) {
- accountManager.link(id, AuthRequest.forEmail(email));
- }
- accountsUpdate
- .create()
- .update(
- id,
- a -> {
- a.setFullName(fullName);
- a.setPreferredEmail(email);
- a.setActive(active);
- });
- return id;
- }
- }
-
- protected void assertMissingField(FieldDef<ChangeData, ?> field) {
- assertThat(getSchema().hasField(field))
- .named("schema %s has field %s", getSchemaVersion(), field.getName())
- .isFalse();
- }
-
- protected void assertFailingQuery(String query, String expectedMessage) throws Exception {
- try {
- assertQuery(query);
- fail("expected BadRequestException for query '" + query + "'");
- } catch (BadRequestException e) {
- assertThat(e.getMessage()).isEqualTo(expectedMessage);
- }
- }
-
- protected int getSchemaVersion() {
- return getSchema().getVersion();
- }
-
- protected Schema<ChangeData> getSchema() {
- return indexes.getSearchIndex().getSchema();
- }
-}