Merge changes from topic 'notedb-primary'
* changes:
NoteDbChangeState: Add enum to indicate change's primary storage
NoteDbChangeState: Refactor to move ref state into nested class
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
index b9e4d7d..e1771ce 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
@@ -69,6 +69,7 @@
import com.google.gerrit.server.notedb.ChangeBundleReader;
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.notedb.NoteDbUpdateManager;
import com.google.gerrit.server.notedb.TestChangeRebuilderWrapper;
import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder.NoPatchSetsException;
@@ -100,6 +101,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
public class ChangeRebuilderIT extends AbstractDaemonTest {
@@ -593,11 +595,15 @@
ReviewDb db = getUnwrappedDb();
Change c = db.changes().get(id);
// Leave change meta ID alone so DraftCommentNotes does the rebuild.
+ ObjectId badSha =
+ ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
NoteDbChangeState bogusState = new NoteDbChangeState(
- id, NoteDbChangeState.parse(c).getChangeMetaId(),
- ImmutableMap.<Account.Id, ObjectId>of(
- user.getId(),
- ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")));
+ id,
+ PrimaryStorage.REVIEW_DB,
+ Optional.of(
+ NoteDbChangeState.RefState.create(
+ NoteDbChangeState.parse(c).getChangeMetaId(),
+ ImmutableMap.of(user.getId(), badSha))));
c.setNoteDbState(bogusState.toString());
db.changes().update(Collections.singleton(c));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java
index 61f6557..dc229b8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/BatchUpdate.java
@@ -44,7 +44,6 @@
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.reviewdb.server.ReviewDbWrapper;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
@@ -1014,7 +1013,7 @@
RevWalk rw, Change.Id id) throws Exception {
Change c = newChanges.get(id);
if (c == null) {
- c = ReviewDbUtil.unwrapDb(db).changes().get(id);
+ c = ChangeNotes.readOneReviewDbChange(db, id);
}
// Pass in preloaded change to controlFor, to avoid:
// - reading from a db that does not belong to this update
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
index 68be2c5..eda50d7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -52,6 +52,7 @@
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.git.RefCache;
import com.google.gerrit.server.git.RepoRefCache;
+import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectCache;
@@ -95,6 +96,20 @@
+ String.format(fmt, args));
}
+ public static Change readOneReviewDbChange(ReviewDb db, Change.Id id)
+ throws OrmException {
+ return checkNoteDbState(ReviewDbUtil.unwrapDb(db).changes().get(id));
+ }
+
+ private static Change checkNoteDbState(Change c) throws OrmException {
+ NoteDbChangeState s = NoteDbChangeState.parse(c);
+ if (s != null && s.getPrimaryStorage() != PrimaryStorage.REVIEW_DB) {
+ throw new OrmException(
+ "invalid NoteDbChangeState in " + c.getId() + ": " + s);
+ }
+ return c;
+ }
+
@Singleton
public static class Factory {
private final Args args;
@@ -118,7 +133,7 @@
public ChangeNotes createChecked(ReviewDb db, Project.NameKey project,
Change.Id changeId) throws OrmException, NoSuchChangeException {
- Change change = ReviewDbUtil.unwrapDb(db).changes().get(changeId);
+ Change change = readOneReviewDbChange(db, changeId);
if (change == null || !change.getProject().equals(project)) {
throw new NoSuchChangeException(changeId);
}
@@ -142,7 +157,7 @@
private Change loadChangeFromDb(ReviewDb db, Project.NameKey project,
Change.Id changeId) throws OrmException {
- Change change = ReviewDbUtil.unwrapDb(db).changes().get(changeId);
+ Change change = readOneReviewDbChange(db, changeId);
checkArgument(project != null, "project is required");
checkNotNull(change,
"change %s not found in ReviewDb", changeId);
@@ -261,6 +276,7 @@
}
} else {
for (Change change : ReviewDbUtil.unwrapDb(db).changes().all()) {
+ checkNoteDbState(change);
ChangeNotes notes = createFromChangeOnlyWhenNoteDbDisabled(change);
if (predicate.test(notes)) {
m.put(change.getProject(), notes);
@@ -297,9 +313,8 @@
Project.NameKey project) throws OrmException, IOException {
Set<Change.Id> ids = scan(repo);
List<ChangeNotes> changeNotes = new ArrayList<>(ids.size());
- db = ReviewDbUtil.unwrapDb(db);
for (Change.Id id : ids) {
- Change change = db.changes().get(id);
+ Change change = readOneReviewDbChange(db, id);
if (change == null) {
log.warn("skipping change {} found in project {} " +
"but not in ReviewDb",
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbChangeState.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbChangeState.java
index ad54f02..2fefd72 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbChangeState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/NoteDbChangeState.java
@@ -16,30 +16,30 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
import static com.google.gerrit.reviewdb.client.RefNames.refsDraftComments;
-import static java.util.Comparator.comparing;
+import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.NOTE_DB;
+import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.REVIEW_DB;
+import static org.eclipse.jgit.lib.ObjectId.zeroId;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.git.RefCache;
-
-import org.eclipse.jgit.lib.ObjectId;
-
import java.io.IOException;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import org.eclipse.jgit.lib.ObjectId;
/**
* The state of all relevant NoteDb refs across all repos corresponding to a
@@ -48,13 +48,35 @@
* Stored serialized in the {@code Change#noteDbState} field, and used to
* determine whether the state in NoteDb is out of date.
* <p>
- * Serialized in the form:
- * <pre>
- * [meta-sha],[account1]=[drafts-sha],[account2]=[drafts-sha]...
- * </pre>
+ * Serialized in one of the forms:
+ * <ul>
+ * <li>[meta-sha],[account1]=[drafts-sha],[account2]=[drafts-sha]...
+ * <li>R[meta-sha],[account1]=[drafts-sha],[account2]=[drafts-sha]...
+ * <li>N
+ * </ul>
+ *
* in numeric account ID order, with hex SHA-1s for human readability.
*/
public class NoteDbChangeState {
+ public static final String NOTE_DB_PRIMARY_STATE = "N";
+
+ public enum PrimaryStorage {
+ REVIEW_DB('R', true),
+ NOTE_DB('N', false);
+
+ private final char code;
+ private final boolean writeToReviewDb;
+
+ private PrimaryStorage(char code, boolean writeToReviewDb) {
+ this.code = code;
+ this.writeToReviewDb = writeToReviewDb;
+ }
+
+ public boolean writeToReviewDb() {
+ return writeToReviewDb;
+ }
+ }
+
@AutoValue
public abstract static class Delta {
static Delta create(Change.Id changeId, Optional<ObjectId> newChangeMetaId,
@@ -73,31 +95,89 @@
abstract ImmutableMap<Account.Id, ObjectId> newDraftIds();
}
+ @AutoValue
+ public abstract static class RefState {
+ @VisibleForTesting
+ public static RefState create(ObjectId changeMetaId,
+ Map<Account.Id, ObjectId> draftIds) {
+ return new AutoValue_NoteDbChangeState_RefState(
+ changeMetaId.copy(),
+ ImmutableMap.copyOf(
+ Maps.filterValues(draftIds, id -> !zeroId().equals(id))));
+ }
+
+ private static Optional<RefState> parse(Change.Id changeId,
+ List<String> parts) {
+ checkArgument(!parts.isEmpty(),
+ "missing state string for change %s", changeId);
+ ObjectId changeMetaId = ObjectId.fromString(parts.get(0));
+ Map<Account.Id, ObjectId> draftIds =
+ Maps.newHashMapWithExpectedSize(parts.size() - 1);
+ Splitter s = Splitter.on('=');
+ for (int i = 1; i < parts.size(); i++) {
+ String p = parts.get(i);
+ List<String> draftParts = s.splitToList(p);
+ checkArgument(draftParts.size() == 2,
+ "invalid draft state part for change %s: %s", changeId, p);
+ draftIds.put(Account.Id.parse(draftParts.get(0)),
+ ObjectId.fromString(draftParts.get(1)));
+ }
+ return Optional.of(create(changeMetaId, draftIds));
+ }
+
+ abstract ObjectId changeMetaId();
+ abstract ImmutableMap<Account.Id, ObjectId> draftIds();
+
+ @Override
+ public String toString() {
+ return appendTo(new StringBuilder()).toString();
+ }
+
+ StringBuilder appendTo(StringBuilder sb) {
+ sb.append(changeMetaId().name());
+ for (Account.Id id : ReviewDbUtil.intKeyOrdering()
+ .sortedCopy(draftIds().keySet())) {
+ sb.append(',')
+ .append(id.get())
+ .append('=')
+ .append(draftIds().get(id).name());
+ }
+ return sb;
+ }
+ }
+
public static NoteDbChangeState parse(Change c) {
- return parse(c.getId(), c.getNoteDbState());
+ return c != null ? parse(c.getId(), c.getNoteDbState()) : null;
}
@VisibleForTesting
public static NoteDbChangeState parse(Change.Id id, String str) {
- if (str == null) {
+ if (Strings.isNullOrEmpty(str)) {
+ // Return null rather than Optional as this is what goes in the field in
+ // ReviewDb.
return null;
}
List<String> parts = Splitter.on(',').splitToList(str);
- checkArgument(!parts.isEmpty(),
- "invalid state string for change %s: %s", id, str);
- ObjectId changeMetaId = ObjectId.fromString(parts.get(0));
- Map<Account.Id, ObjectId> draftIds =
- Maps.newHashMapWithExpectedSize(parts.size() - 1);
- Splitter s = Splitter.on('=');
- for (int i = 1; i < parts.size(); i++) {
- String p = parts.get(i);
- List<String> draftParts = s.splitToList(p);
- checkArgument(draftParts.size() == 2,
- "invalid draft state part for change %s: %s", id, p);
- draftIds.put(Account.Id.parse(draftParts.get(0)),
- ObjectId.fromString(draftParts.get(1)));
+
+ // Only valid NOTE_DB state is "N".
+ String first = parts.get(0);
+ if (parts.size() == 1 && first.charAt(0) == NOTE_DB.code) {
+ return new NoteDbChangeState(id, NOTE_DB, Optional.empty());
}
- return new NoteDbChangeState(id, changeMetaId, draftIds);
+
+ // Otherwise it must be REVIEW_DB, either "R,<RefState>" or just
+ // "<RefState>". Allow length > 0 for forward compatibility.
+ if (first.length() > 0) {
+ Optional<RefState> refState;
+ if (first.charAt(0) == REVIEW_DB.code) {
+ refState = RefState.parse(id, parts.subList(1, parts.size()));
+ } else {
+ refState = RefState.parse(id, parts);
+ }
+ return new NoteDbChangeState(id, REVIEW_DB, refState);
+ }
+ throw new IllegalArgumentException(
+ "invalid state string for change " + id + ": " + str);
}
public static NoteDbChangeState applyDelta(Change change, Delta delta) {
@@ -112,6 +192,10 @@
return null;
}
NoteDbChangeState oldState = parse(change.getId(), oldStr);
+ if (oldState != null && oldState.getPrimaryStorage() == NOTE_DB) {
+ // NOTE_DB state doesn't include RefState, so applying a delta is a no-op.
+ return oldState;
+ }
ObjectId changeMetaId;
if (delta.newChangeMetaId().isPresent()) {
@@ -121,12 +205,12 @@
return null;
}
} else {
- changeMetaId = oldState.changeMetaId;
+ changeMetaId = oldState.getChangeMetaId();
}
Map<Account.Id, ObjectId> draftIds = new HashMap<>();
if (oldState != null) {
- draftIds.putAll(oldState.draftIds);
+ draftIds.putAll(oldState.getDraftIds());
}
for (Map.Entry<Account.Id, ObjectId> e : delta.newDraftIds().entrySet()) {
if (e.getValue().equals(ObjectId.zeroId())) {
@@ -137,7 +221,11 @@
}
NoteDbChangeState state = new NoteDbChangeState(
- change.getId(), changeMetaId, draftIds);
+ change.getId(),
+ oldState != null
+ ? oldState.getPrimaryStorage()
+ : REVIEW_DB,
+ Optional.of(RefState.create(changeMetaId, draftIds)));
change.setNoteDbState(state.toString());
return state;
}
@@ -160,38 +248,47 @@
return state.areDraftsUpToDate(draftsRepoRefs, accountId);
}
- public static String toString(ObjectId changeMetaId,
- Map<Account.Id, ObjectId> draftIds) {
- List<Account.Id> accountIds = Lists.newArrayList(draftIds.keySet());
- Collections.sort(accountIds, comparing(Account.Id::get));
- StringBuilder sb = new StringBuilder(changeMetaId.name());
- for (Account.Id id : accountIds) {
- sb.append(',')
- .append(id.get())
- .append('=')
- .append(draftIds.get(id).name());
+ private final Change.Id changeId;
+ private final PrimaryStorage primaryStorage;
+ private final Optional<RefState> refState;
+
+ public NoteDbChangeState(
+ Change.Id changeId,
+ PrimaryStorage primaryStorage,
+ Optional<RefState> refState) {
+ this.changeId = checkNotNull(changeId);
+ this.primaryStorage = checkNotNull(primaryStorage);
+ this.refState = refState;
+
+ switch (primaryStorage) {
+ case REVIEW_DB:
+ checkArgument(
+ refState.isPresent(),
+ "expected RefState for change %s with primary storage %s",
+ changeId, primaryStorage);
+ break;
+ case NOTE_DB:
+ checkArgument(
+ !refState.isPresent(),
+ "expected no RefState for change %s with primary storage %s",
+ changeId, primaryStorage);
+ break;
+ default:
+ throw new IllegalStateException(
+ "invalid PrimaryStorage: " + primaryStorage);
}
- return sb.toString();
}
- private final Change.Id changeId;
- private final ObjectId changeMetaId;
- private final ImmutableMap<Account.Id, ObjectId> draftIds;
-
- public NoteDbChangeState(Change.Id changeId, ObjectId changeMetaId,
- Map<Account.Id, ObjectId> draftIds) {
- this.changeId = checkNotNull(changeId);
- this.changeMetaId = checkNotNull(changeMetaId);
- this.draftIds = ImmutableMap.copyOf(Maps.filterValues(
- draftIds, Predicates.not(Predicates.equalTo(ObjectId.zeroId()))));
+ public PrimaryStorage getPrimaryStorage() {
+ return primaryStorage;
}
public boolean isChangeUpToDate(RefCache changeRepoRefs) throws IOException {
Optional<ObjectId> id = changeRepoRefs.get(changeMetaRef(changeId));
if (!id.isPresent()) {
- return changeMetaId.equals(ObjectId.zeroId());
+ return getChangeMetaId().equals(ObjectId.zeroId());
}
- return id.get().equals(changeMetaId);
+ return id.get().equals(getChangeMetaId());
}
public boolean areDraftsUpToDate(RefCache draftsRepoRefs, Account.Id accountId)
@@ -199,9 +296,9 @@
Optional<ObjectId> id =
draftsRepoRefs.get(refsDraftComments(changeId, accountId));
if (!id.isPresent()) {
- return !draftIds.containsKey(accountId);
+ return !getDraftIds().containsKey(accountId);
}
- return id.get().equals(draftIds.get(accountId));
+ return id.get().equals(getDraftIds().get(accountId));
}
public boolean isUpToDate(RefCache changeRepoRefs, RefCache draftsRepoRefs)
@@ -209,7 +306,7 @@
if (!isChangeUpToDate(changeRepoRefs)) {
return false;
}
- for (Account.Id accountId : draftIds.keySet()) {
+ for (Account.Id accountId : getDraftIds().keySet()) {
if (!areDraftsUpToDate(draftsRepoRefs, accountId)) {
return false;
}
@@ -224,16 +321,36 @@
@VisibleForTesting
public ObjectId getChangeMetaId() {
- return changeMetaId;
+ return refState().changeMetaId();
}
@VisibleForTesting
ImmutableMap<Account.Id, ObjectId> getDraftIds() {
- return draftIds;
+ return refState().draftIds();
+ }
+
+ @VisibleForTesting
+ Optional<RefState> getRefState() {
+ return refState;
+ }
+
+ private RefState refState() {
+ checkState(refState.isPresent(),
+ "state for %s has no RefState: %s", changeId, this);
+ return refState.get();
}
@Override
public String toString() {
- return toString(changeMetaId, draftIds);
+ switch (primaryStorage) {
+ case REVIEW_DB:
+ // Don't include enum field, just IDs (though parse would accept it).
+ return refState().toString();
+ case NOTE_DB:
+ return NOTE_DB_PRIMARY_STATE;
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported PrimaryStorage: " + primaryStorage);
+ }
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java
index 2e8cca7..b3aa420 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java
@@ -54,6 +54,7 @@
import com.google.gerrit.server.notedb.ChangeBundleReader;
import com.google.gerrit.server.notedb.ChangeDraftUpdate;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
+import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NoteDbChangeState;
import com.google.gerrit.server.notedb.NoteDbUpdateManager;
@@ -184,7 +185,7 @@
public NoteDbUpdateManager stage(ReviewDb db, Change.Id changeId)
throws NoSuchChangeException, IOException, OrmException {
db = ReviewDbUtil.unwrapDb(db);
- Change change = db.changes().get(changeId);
+ Change change = ChangeNotes.readOneReviewDbChange(db, changeId);
if (change == null) {
throw new NoSuchChangeException(changeId);
}
@@ -200,7 +201,7 @@
NoteDbUpdateManager manager) throws NoSuchChangeException, OrmException,
IOException {
db = ReviewDbUtil.unwrapDb(db);
- Change change = db.changes().get(changeId);
+ Change change = ChangeNotes.readOneReviewDbChange(db, changeId);
if (change == null) {
throw new NoSuchChangeException(changeId);
}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/NoteDbChangeStateTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/NoteDbChangeStateTest.java
index f2bf2be..e3613e3 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/NoteDbChangeStateTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/NoteDbChangeStateTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.notedb.NoteDbChangeState.applyDelta;
import static com.google.gerrit.server.notedb.NoteDbChangeState.parse;
+import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.NOTE_DB;
+import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.REVIEW_DB;
import static org.eclipse.jgit.lib.ObjectId.zeroId;
import com.google.common.collect.ImmutableMap;
@@ -48,30 +50,44 @@
ObjectId.fromString("badc0feebadc0feebadc0feebadc0feebadc0fee");
@Test
- public void parseWithoutDrafts() {
+ public void parseReviewDbWithoutDrafts() {
NoteDbChangeState state = parse(new Change.Id(1), SHA1.name());
-
+ assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
assertThat(state.getDraftIds()).isEmpty();
+ assertThat(state.toString()).isEqualTo(SHA1.name());
+ state = parse(new Change.Id(1), "R," + SHA1.name());
+ assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
+ assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
+ assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
+ assertThat(state.getDraftIds()).isEmpty();
assertThat(state.toString()).isEqualTo(SHA1.name());
}
@Test
- public void parseWithDrafts() {
- NoteDbChangeState state = parse(
- new Change.Id(1),
- SHA1.name() + ",2003=" + SHA2.name() + ",1001=" + SHA3.name());
-
+ public void parseReviewDbWithDrafts() {
+ String str = SHA1.name() + ",2003=" + SHA2.name() + ",1001=" + SHA3.name();
+ String expected =
+ SHA1.name() + ",1001=" + SHA3.name() + ",2003=" + SHA2.name();
+ NoteDbChangeState state = parse(new Change.Id(1), str);
+ assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
assertThat(state.getDraftIds()).containsExactly(
new Account.Id(1001), SHA3,
new Account.Id(2003), SHA2);
+ assertThat(state.toString()).isEqualTo(expected);
- assertThat(state.toString()).isEqualTo(
- SHA1.name() + ",1001=" + SHA3.name() + ",2003=" + SHA2.name());
+ state = parse(new Change.Id(1), "R," + str);
+ assertThat(state.getPrimaryStorage()).isEqualTo(REVIEW_DB);
+ assertThat(state.getChangeId()).isEqualTo(new Change.Id(1));
+ assertThat(state.getChangeMetaId()).isEqualTo(SHA1);
+ assertThat(state.getDraftIds()).containsExactly(
+ new Account.Id(1001), SHA3,
+ new Account.Id(2003), SHA2);
+ assertThat(state.toString()).isEqualTo(expected);
}
@Test
@@ -127,6 +143,27 @@
SHA3.name() + ",1001=" + SHA2.name());
}
+ @Test
+ public void parseNoteDbPrimary() {
+ NoteDbChangeState state = parse(new Change.Id(1), "N");
+ assertThat(state.getPrimaryStorage()).isEqualTo(NOTE_DB);
+ assertThat(state.getRefState().isPresent()).isFalse();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void parseInvalidPrimaryStorage() {
+ parse(new Change.Id(1), "X");
+ }
+
+ @Test
+ public void applyDeltaToNoteDbPrimaryIsNoOp() {
+ Change c = newChange();
+ c.setNoteDbState("N");
+ applyDelta(c, Delta.create(c.getId(), metaId(SHA1),
+ drafts(new Account.Id(1001), SHA2)));
+ assertThat(c.getNoteDbState()).isEqualTo("N");
+ }
+
private static Change newChange() {
return TestChanges.newChange(
new Project.NameKey("project"), new Account.Id(12345));