Add converter for Change protobuf messages
The use of ProtobufCodec requires that value classes need to be annotated with @Column, which won't be possible as soon as we have removed gwtorm. Hence, provide a hand-written converter for Change protobuf messages. As protobuf Changes are currently used in indices and we don't want to invalidate those, we have to ensure binary compatibility. Prove that the new converter generates binary compatible results via dedicated tests. Those tests will be removed after this change. Change-Id: Ie1dcd3dd28c628cb8c20d0f95147417e8b2fd260
This commit is contained in:
committed by
Dave Borowitz
parent
8bd35ec888
commit
921d9d67f9
@@ -99,7 +99,7 @@ abstract class AbstractElasticIndex<K, V> implements Index<K, V> {
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
private static <P extends MessageLite, T> T parseProtoFrom(
|
||||
protected static <P extends MessageLite, T> T parseProtoFrom(
|
||||
byte[] bytes, ProtoConverter<P, T> converter) {
|
||||
P message = Protos.parseUnchecked(converter.getParser(), bytes);
|
||||
return converter.fromProto(message);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package com.google.gerrit.elasticsearch;
|
||||
|
||||
import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
|
||||
import static com.google.gerrit.server.index.change.ChangeIndexRewriter.CLOSED_STATUSES;
|
||||
import static com.google.gerrit.server.index.change.ChangeIndexRewriter.OPEN_STATUSES;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
@@ -43,6 +42,7 @@ import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.Change.Id;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.converter.ChangeProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
|
||||
import com.google.gerrit.server.ReviewerByEmailSet;
|
||||
@@ -218,7 +218,8 @@ class ElasticChangeIndex extends AbstractElasticIndex<Change.Id, ChangeData>
|
||||
}
|
||||
|
||||
ChangeData cd =
|
||||
changeDataFactory.create(CHANGE_CODEC.decode(Base64.decodeBase64(c.getAsString())));
|
||||
changeDataFactory.create(
|
||||
parseProtoFrom(Base64.decodeBase64(c.getAsString()), ChangeProtoConverter.INSTANCE));
|
||||
|
||||
// Any decoding that is done here must also be done in {@link LuceneChangeIndex}.
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ package com.google.gerrit.lucene;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.gerrit.lucene.AbstractLuceneIndex.sortFieldName;
|
||||
import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
|
||||
import static com.google.gerrit.server.git.QueueProvider.QueueType.INTERACTIVE;
|
||||
import static com.google.gerrit.server.index.change.ChangeField.LEGACY_ID;
|
||||
import static com.google.gerrit.server.index.change.ChangeField.PROJECT;
|
||||
@@ -46,6 +45,7 @@ import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.converter.ChangeProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.ProtoConverter;
|
||||
@@ -445,7 +445,7 @@ public class LuceneChangeIndex implements ChangeIndex {
|
||||
IndexableField cb = Iterables.getFirst(doc.get(CHANGE_FIELD), null);
|
||||
if (cb != null) {
|
||||
BytesRef proto = cb.binaryValue();
|
||||
cd = changeDataFactory.create(CHANGE_CODEC.decode(proto.bytes, proto.offset, proto.length));
|
||||
cd = changeDataFactory.create(parseProtoFrom(proto, ChangeProtoConverter.INSTANCE));
|
||||
} else {
|
||||
IndexableField f = Iterables.getFirst(doc.get(idFieldName), null);
|
||||
Change.Id id = new Change.Id(f.numericValue().intValue());
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.reviewdb.client.Branch;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.protobuf.Parser;
|
||||
|
||||
public enum BranchNameKeyProtoConverter
|
||||
implements ProtoConverter<Reviewdb.Branch_NameKey, Branch.NameKey> {
|
||||
INSTANCE;
|
||||
|
||||
private final ProtoConverter<Reviewdb.Project_NameKey, Project.NameKey> projectNameConverter =
|
||||
ProjectNameKeyProtoConverter.INSTANCE;
|
||||
|
||||
@Override
|
||||
public Reviewdb.Branch_NameKey toProto(Branch.NameKey nameKey) {
|
||||
return Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(projectNameConverter.toProto(nameKey.getParentKey()))
|
||||
.setBranchName(nameKey.get())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Branch.NameKey fromProto(Reviewdb.Branch_NameKey proto) {
|
||||
return new Branch.NameKey(
|
||||
projectNameConverter.fromProto(proto.getProjectName()), proto.getBranchName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser<Reviewdb.Branch_NameKey> getParser() {
|
||||
return Reviewdb.Branch_NameKey.parser();
|
||||
}
|
||||
}
|
||||
@@ -12,15 +12,27 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.reviewdb.server;
|
||||
package com.google.gerrit.reviewdb.converter;
|
||||
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gwtorm.protobuf.CodecFactory;
|
||||
import com.google.gwtorm.protobuf.ProtobufCodec;
|
||||
import com.google.protobuf.Parser;
|
||||
|
||||
/** {@link ProtobufCodec} instances for ReviewDb types. */
|
||||
public class ReviewDbCodecs {
|
||||
public static final ProtobufCodec<Change> CHANGE_CODEC = CodecFactory.encoder(Change.class);
|
||||
public enum ChangeKeyProtoConverter implements ProtoConverter<Reviewdb.Change_Key, Change.Key> {
|
||||
INSTANCE;
|
||||
|
||||
private ReviewDbCodecs() {}
|
||||
@Override
|
||||
public Reviewdb.Change_Key toProto(Change.Key key) {
|
||||
return Reviewdb.Change_Key.newBuilder().setId(key.get()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Change.Key fromProto(Reviewdb.Change_Key proto) {
|
||||
return new Change.Key(proto.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser<Reviewdb.Change_Key> getParser() {
|
||||
return Reviewdb.Change_Key.parser();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
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.PatchSet;
|
||||
import com.google.protobuf.Parser;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public enum ChangeProtoConverter implements ProtoConverter<Reviewdb.Change, Change> {
|
||||
INSTANCE;
|
||||
|
||||
private final ProtoConverter<Reviewdb.Change_Id, Change.Id> changeIdConverter =
|
||||
ChangeIdProtoConverter.INSTANCE;
|
||||
private final ProtoConverter<Reviewdb.Change_Key, Change.Key> changeKeyConverter =
|
||||
ChangeKeyProtoConverter.INSTANCE;
|
||||
private final ProtoConverter<Reviewdb.Account_Id, Account.Id> accountIdConverter =
|
||||
AccountIdProtoConverter.INSTANCE;
|
||||
private final ProtoConverter<Reviewdb.Branch_NameKey, Branch.NameKey> branchNameConverter =
|
||||
BranchNameKeyProtoConverter.INSTANCE;
|
||||
|
||||
@Override
|
||||
public Reviewdb.Change toProto(Change change) {
|
||||
Reviewdb.Change.Builder builder =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(changeIdConverter.toProto(change.getId()))
|
||||
.setRowVersion(change.getRowVersion())
|
||||
.setChangeKey(changeKeyConverter.toProto(change.getKey()))
|
||||
.setCreatedOn(change.getCreatedOn().getTime())
|
||||
.setLastUpdatedOn(change.getLastUpdatedOn().getTime())
|
||||
.setOwnerAccountId(accountIdConverter.toProto(change.getOwner()))
|
||||
.setDest(branchNameConverter.toProto(change.getDest()))
|
||||
.setStatus(change.getStatus().getCode())
|
||||
.setIsPrivate(change.isPrivate())
|
||||
.setWorkInProgress(change.isWorkInProgress())
|
||||
.setReviewStarted(change.hasReviewStarted());
|
||||
PatchSet.Id currentPatchSetId = change.currentPatchSetId();
|
||||
// Special behavior necessary to ensure binary compatibility.
|
||||
builder.setCurrentPatchSetId(currentPatchSetId == null ? 0 : currentPatchSetId.get());
|
||||
String subject = change.getSubject();
|
||||
if (subject != null) {
|
||||
builder.setSubject(subject);
|
||||
}
|
||||
String topic = change.getTopic();
|
||||
if (topic != null) {
|
||||
builder.setTopic(topic);
|
||||
}
|
||||
String originalSubject = change.getOriginalSubjectOrNull();
|
||||
if (originalSubject != null) {
|
||||
builder.setOriginalSubject(originalSubject);
|
||||
}
|
||||
String submissionId = change.getSubmissionId();
|
||||
if (submissionId != null) {
|
||||
builder.setSubmissionId(submissionId);
|
||||
}
|
||||
Account.Id assignee = change.getAssignee();
|
||||
if (assignee != null) {
|
||||
builder.setAssignee(accountIdConverter.toProto(assignee));
|
||||
}
|
||||
Change.Id revertOf = change.getRevertOf();
|
||||
if (revertOf != null) {
|
||||
builder.setRevertOf(changeIdConverter.toProto(revertOf));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Change fromProto(Reviewdb.Change proto) {
|
||||
Change.Id changeId = changeIdConverter.fromProto(proto.getChangeId());
|
||||
Change.Key key =
|
||||
proto.hasChangeKey() ? changeKeyConverter.fromProto(proto.getChangeKey()) : null;
|
||||
Account.Id owner =
|
||||
proto.hasOwnerAccountId() ? accountIdConverter.fromProto(proto.getOwnerAccountId()) : null;
|
||||
Branch.NameKey destination =
|
||||
proto.hasDest() ? branchNameConverter.fromProto(proto.getDest()) : null;
|
||||
Change change =
|
||||
new Change(key, changeId, owner, destination, new Timestamp(proto.getCreatedOn()));
|
||||
if (proto.hasLastUpdatedOn()) {
|
||||
change.setLastUpdatedOn(new Timestamp(proto.getLastUpdatedOn()));
|
||||
}
|
||||
Change.Status status = Change.Status.forCode((char) proto.getStatus());
|
||||
if (status != null) {
|
||||
change.setStatus(status);
|
||||
}
|
||||
String subject = proto.hasSubject() ? proto.getSubject() : null;
|
||||
String originalSubject = proto.hasOriginalSubject() ? proto.getOriginalSubject() : null;
|
||||
change.setCurrentPatchSet(
|
||||
new PatchSet.Id(changeId, proto.getCurrentPatchSetId()), subject, originalSubject);
|
||||
if (proto.hasTopic()) {
|
||||
change.setTopic(proto.getTopic());
|
||||
}
|
||||
if (proto.hasSubmissionId()) {
|
||||
change.setSubmissionId(proto.getSubmissionId());
|
||||
}
|
||||
if (proto.hasAssignee()) {
|
||||
change.setAssignee(accountIdConverter.fromProto(proto.getAssignee()));
|
||||
}
|
||||
change.setPrivate(proto.getIsPrivate());
|
||||
change.setWorkInProgress(proto.getWorkInProgress());
|
||||
change.setReviewStarted(proto.getReviewStarted());
|
||||
if (proto.hasRevertOf()) {
|
||||
change.setRevertOf(changeIdConverter.fromProto(proto.getRevertOf()));
|
||||
}
|
||||
return change;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser<Reviewdb.Change> getParser() {
|
||||
return Reviewdb.Change.parser();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.protobuf.Parser;
|
||||
|
||||
public enum ProjectNameKeyProtoConverter
|
||||
implements ProtoConverter<Reviewdb.Project_NameKey, Project.NameKey> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Reviewdb.Project_NameKey toProto(Project.NameKey nameKey) {
|
||||
return Reviewdb.Project_NameKey.newBuilder().setName(nameKey.get()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project.NameKey fromProto(Reviewdb.Project_NameKey proto) {
|
||||
return new Project.NameKey(proto.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parser<Reviewdb.Project_NameKey> getParser() {
|
||||
return Reviewdb.Project_NameKey.parser();
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import static com.google.gerrit.index.FieldDef.integer;
|
||||
import static com.google.gerrit.index.FieldDef.prefix;
|
||||
import static com.google.gerrit.index.FieldDef.storedOnly;
|
||||
import static com.google.gerrit.index.FieldDef.timestamp;
|
||||
import static com.google.gerrit.reviewdb.server.ReviewDbCodecs.CHANGE_CODEC;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
@@ -53,6 +52,7 @@ import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.PatchSetApproval;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.client.RefNames;
|
||||
import com.google.gerrit.reviewdb.converter.ChangeProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.PatchSetApprovalProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.PatchSetProtoConverter;
|
||||
import com.google.gerrit.reviewdb.converter.ProtoConverter;
|
||||
@@ -468,7 +468,8 @@ public class ChangeField {
|
||||
|
||||
/** Serialized change object, used for pre-populating results. */
|
||||
public static final FieldDef<ChangeData, byte[]> CHANGE =
|
||||
storedOnly("_change").build(changeGetter(CHANGE_CODEC::encodeToByteArray));
|
||||
storedOnly("_change")
|
||||
.build(changeGetter(change -> toProto(ChangeProtoConverter.INSTANCE, change)));
|
||||
|
||||
/** Serialized approvals for the current patch set, used for pre-populating results. */
|
||||
public static final FieldDef<ChangeData, Iterable<byte[]>> APPROVAL =
|
||||
@@ -854,11 +855,11 @@ public class ChangeField {
|
||||
}
|
||||
|
||||
private static <T> List<byte[]> toProtos(ProtoConverter<?, T> converter, Collection<T> objects) {
|
||||
return objects
|
||||
.stream()
|
||||
.map(converter::toProto)
|
||||
.map(Protos::toByteArray)
|
||||
.collect(toImmutableList());
|
||||
return objects.stream().map(object -> toProto(converter, object)).collect(toImmutableList());
|
||||
}
|
||||
|
||||
private static <T> byte[] toProto(ProtoConverter<?, T> converter, T object) {
|
||||
return Protos.toByteArray(converter.toProto(object));
|
||||
}
|
||||
|
||||
private static <T> FieldDef.Getter<ChangeData, T> changeGetter(Function<Change, T> func) {
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
|
||||
import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.proto.testing.SerializedClassSubject;
|
||||
import com.google.gerrit.reviewdb.client.Branch;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.protobuf.Parser;
|
||||
import java.lang.reflect.Type;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BranchNameKeyProtoConverterTest {
|
||||
private final BranchNameKeyProtoConverter branchNameKeyProtoConverter =
|
||||
BranchNameKeyProtoConverter.INSTANCE;
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProto() {
|
||||
Branch.NameKey nameKey = new Branch.NameKey(new Project.NameKey("project-13"), "branch-72");
|
||||
|
||||
Reviewdb.Branch_NameKey proto = branchNameKeyProtoConverter.toProto(nameKey);
|
||||
|
||||
Reviewdb.Branch_NameKey expectedProto =
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project-13"))
|
||||
.setBranchName("refs/heads/branch-72")
|
||||
.build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProtoAndBackAgain() {
|
||||
Branch.NameKey nameKey = new Branch.NameKey(new Project.NameKey("project-52"), "branch 14");
|
||||
|
||||
Branch.NameKey convertedNameKey =
|
||||
branchNameKeyProtoConverter.fromProto(branchNameKeyProtoConverter.toProto(nameKey));
|
||||
|
||||
assertThat(convertedNameKey).isEqualTo(nameKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void protoCanBeParsedFromBytes() throws Exception {
|
||||
Reviewdb.Branch_NameKey proto =
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 1"))
|
||||
.setBranchName("branch 36")
|
||||
.build();
|
||||
byte[] bytes = proto.toByteArray();
|
||||
|
||||
Parser<Reviewdb.Branch_NameKey> parser = branchNameKeyProtoConverter.getParser();
|
||||
Reviewdb.Branch_NameKey parsedProto = parser.parseFrom(bytes);
|
||||
|
||||
assertThat(parsedProto).isEqualTo(proto);
|
||||
}
|
||||
|
||||
/** See {@link SerializedClassSubject} for background and what to do if this test fails. */
|
||||
@Test
|
||||
public void fieldsExistAsExpected() {
|
||||
assertThatSerializedClass(Branch.NameKey.class)
|
||||
.hasFields(
|
||||
ImmutableMap.<String, Type>builder()
|
||||
.put("projectName", Project.NameKey.class)
|
||||
.put("branchName", String.class)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.gerrit.proto.Protos;
|
||||
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.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gwtorm.protobuf.CodecFactory;
|
||||
import com.google.gwtorm.protobuf.ProtobufCodec;
|
||||
import java.sql.Timestamp;
|
||||
import org.junit.Test;
|
||||
|
||||
// TODO(aliceks): Delete after proving binary compatibility.
|
||||
public class ChangeConverterCompatibilityTest {
|
||||
|
||||
private final ProtobufCodec<Change> changeCodec = CodecFactory.encoder(Change.class);
|
||||
private final ChangeProtoConverter changeProtoConverter = ChangeProtoConverter.INSTANCE;
|
||||
|
||||
@Test
|
||||
public void changeIndexFieldWithAllValuesIsBinaryCompatible() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
change.setLastUpdatedOn(new Timestamp(1234567L));
|
||||
change.setStatus(Change.Status.MERGED);
|
||||
change.setCurrentPatchSet(
|
||||
new PatchSet.Id(new Change.Id(14), 23), "subject XYZ", "original subject ABC");
|
||||
change.setTopic("my topic");
|
||||
change.setSubmissionId("submission ID 234");
|
||||
change.setAssignee(new Account.Id(100001));
|
||||
change.setPrivate(true);
|
||||
change.setWorkInProgress(true);
|
||||
change.setReviewStarted(true);
|
||||
change.setRevertOf(new Change.Id(180));
|
||||
|
||||
byte[] resultOfOldConverter = convertToProto_old(changeCodec, change);
|
||||
byte[] resultOfNewConverter = convertToProto_new(changeProtoConverter, change);
|
||||
|
||||
assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeIndexFieldWithMandatoryValuesIsBinaryCompatible() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
|
||||
byte[] resultOfOldConverter = convertToProto_old(changeCodec, change);
|
||||
byte[] resultOfNewConverter = convertToProto_new(changeProtoConverter, change);
|
||||
|
||||
assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeIndexFieldWithSubjectButNotOriginalSubjectIsBinaryCompatible() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
change.setCurrentPatchSet(new PatchSet.Id(new Change.Id(14), 23), "subject XYZ", null);
|
||||
|
||||
byte[] resultOfOldConverter = convertToProto_old(changeCodec, change);
|
||||
byte[] resultOfNewConverter = convertToProto_new(changeProtoConverter, change);
|
||||
|
||||
assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeIndexFieldWithoutPatchSetIsBinaryCompatible() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
// O for patch set ID means that there isn't any current patch set.
|
||||
change.setCurrentPatchSet(new PatchSet.Id(new Change.Id(14), 0), null, null);
|
||||
|
||||
byte[] resultOfOldConverter = convertToProto_old(changeCodec, change);
|
||||
byte[] resultOfNewConverter = convertToProto_new(changeProtoConverter, change);
|
||||
|
||||
assertThat(resultOfNewConverter).isEqualTo(resultOfOldConverter);
|
||||
}
|
||||
|
||||
// Copied from ChangeField.
|
||||
private static <T> byte[] convertToProto_old(ProtobufCodec<T> codec, T object) {
|
||||
return codec.encodeToByteArray(object);
|
||||
}
|
||||
|
||||
// Copied from ChangeField.
|
||||
private static <T> byte[] convertToProto_new(ProtoConverter<?, T> converter, T object) {
|
||||
return Protos.toByteArray(converter.toProto(object));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
|
||||
import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.proto.testing.SerializedClassSubject;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.protobuf.Parser;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ChangeKeyProtoConverterTest {
|
||||
private final ChangeKeyProtoConverter changeKeyProtoConverter = ChangeKeyProtoConverter.INSTANCE;
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProto() {
|
||||
Change.Key changeKey = new Change.Key("change-1");
|
||||
|
||||
Reviewdb.Change_Key proto = changeKeyProtoConverter.toProto(changeKey);
|
||||
|
||||
Reviewdb.Change_Key expectedProto = Reviewdb.Change_Key.newBuilder().setId("change-1").build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProtoAndBackAgain() {
|
||||
Change.Key changeKey = new Change.Key("change-52");
|
||||
|
||||
Change.Key convertedChangeKey =
|
||||
changeKeyProtoConverter.fromProto(changeKeyProtoConverter.toProto(changeKey));
|
||||
|
||||
assertThat(convertedChangeKey).isEqualTo(changeKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void protoCanBeParsedFromBytes() throws Exception {
|
||||
Reviewdb.Change_Key proto = Reviewdb.Change_Key.newBuilder().setId("change 36").build();
|
||||
byte[] bytes = proto.toByteArray();
|
||||
|
||||
Parser<Reviewdb.Change_Key> parser = changeKeyProtoConverter.getParser();
|
||||
Reviewdb.Change_Key parsedProto = parser.parseFrom(bytes);
|
||||
|
||||
assertThat(parsedProto).isEqualTo(proto);
|
||||
}
|
||||
|
||||
/** See {@link SerializedClassSubject} for background and what to do if this test fails. */
|
||||
@Test
|
||||
public void fieldsExistAsExpected() {
|
||||
assertThatSerializedClass(Change.Key.class).hasFields(ImmutableMap.of("id", String.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
|
||||
import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.proto.testing.SerializedClassSubject;
|
||||
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.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.protobuf.Parser;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.Timestamp;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ChangeProtoConverterTest {
|
||||
private final ChangeProtoConverter changeProtoConverter = ChangeProtoConverter.INSTANCE;
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProto() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch 74"),
|
||||
new Timestamp(987654L));
|
||||
change.setLastUpdatedOn(new Timestamp(1234567L));
|
||||
change.setStatus(Change.Status.MERGED);
|
||||
change.setCurrentPatchSet(
|
||||
new PatchSet.Id(new Change.Id(14), 23), "subject XYZ", "original subject ABC");
|
||||
change.setTopic("my topic");
|
||||
change.setSubmissionId("submission ID 234");
|
||||
change.setAssignee(new Account.Id(100001));
|
||||
change.setPrivate(true);
|
||||
change.setWorkInProgress(true);
|
||||
change.setReviewStarted(true);
|
||||
change.setRevertOf(new Change.Id(180));
|
||||
|
||||
Reviewdb.Change proto = changeProtoConverter.toProto(change);
|
||||
|
||||
Reviewdb.Change expectedProto =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(Reviewdb.Change_Id.newBuilder().setId(14))
|
||||
.setChangeKey(Reviewdb.Change_Key.newBuilder().setId("change 1"))
|
||||
.setRowVersion(0)
|
||||
.setCreatedOn(987654L)
|
||||
.setLastUpdatedOn(1234567L)
|
||||
.setOwnerAccountId(Reviewdb.Account_Id.newBuilder().setId(35))
|
||||
.setDest(
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 67"))
|
||||
.setBranchName("refs/heads/branch 74"))
|
||||
.setStatus(Change.STATUS_MERGED)
|
||||
.setCurrentPatchSetId(23)
|
||||
.setSubject("subject XYZ")
|
||||
.setTopic("my topic")
|
||||
.setOriginalSubject("original subject ABC")
|
||||
.setSubmissionId("submission ID 234")
|
||||
.setAssignee(Reviewdb.Account_Id.newBuilder().setId(100001))
|
||||
.setIsPrivate(true)
|
||||
.setWorkInProgress(true)
|
||||
.setReviewStarted(true)
|
||||
.setRevertOf(Reviewdb.Change_Id.newBuilder().setId(180))
|
||||
.build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mandatoryValuesConvertedToProto() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
|
||||
Reviewdb.Change proto = changeProtoConverter.toProto(change);
|
||||
|
||||
Reviewdb.Change expectedProto =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(Reviewdb.Change_Id.newBuilder().setId(14))
|
||||
.setChangeKey(Reviewdb.Change_Key.newBuilder().setId("change 1"))
|
||||
.setCreatedOn(987654L)
|
||||
// Defaults to createdOn if not set.
|
||||
.setLastUpdatedOn(987654L)
|
||||
.setOwnerAccountId(Reviewdb.Account_Id.newBuilder().setId(35))
|
||||
.setDest(
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 67"))
|
||||
.setBranchName("refs/heads/branch-74"))
|
||||
// Default values which can't be unset.
|
||||
.setCurrentPatchSetId(0)
|
||||
.setRowVersion(0)
|
||||
.setStatus(Change.STATUS_NEW)
|
||||
.setIsPrivate(false)
|
||||
.setWorkInProgress(false)
|
||||
.setReviewStarted(false)
|
||||
.build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
// This test documents a special behavior which is necessary to ensure binary compatibility.
|
||||
@Test
|
||||
public void currentPatchSetIsAlwaysSetWhenConvertedToProto() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
// O as ID actually means that no current patch set is present.
|
||||
change.setCurrentPatchSet(new PatchSet.Id(new Change.Id(14), 0), null, null);
|
||||
|
||||
Reviewdb.Change proto = changeProtoConverter.toProto(change);
|
||||
|
||||
Reviewdb.Change expectedProto =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(Reviewdb.Change_Id.newBuilder().setId(14))
|
||||
.setChangeKey(Reviewdb.Change_Key.newBuilder().setId("change 1"))
|
||||
.setCreatedOn(987654L)
|
||||
// Defaults to createdOn if not set.
|
||||
.setLastUpdatedOn(987654L)
|
||||
.setOwnerAccountId(Reviewdb.Account_Id.newBuilder().setId(35))
|
||||
.setDest(
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 67"))
|
||||
.setBranchName("refs/heads/branch-74"))
|
||||
.setCurrentPatchSetId(0)
|
||||
// Default values which can't be unset.
|
||||
.setRowVersion(0)
|
||||
.setStatus(Change.STATUS_NEW)
|
||||
.setIsPrivate(false)
|
||||
.setWorkInProgress(false)
|
||||
.setReviewStarted(false)
|
||||
.build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
// This test documents a special behavior which is necessary to ensure binary compatibility.
|
||||
@Test
|
||||
public void originalSubjectIsNotAutomaticallySetToSubjectWhenConvertedToProto() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
change.setCurrentPatchSet(new PatchSet.Id(new Change.Id(14), 23), "subject ABC", null);
|
||||
|
||||
Reviewdb.Change proto = changeProtoConverter.toProto(change);
|
||||
|
||||
Reviewdb.Change expectedProto =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(Reviewdb.Change_Id.newBuilder().setId(14))
|
||||
.setChangeKey(Reviewdb.Change_Key.newBuilder().setId("change 1"))
|
||||
.setCreatedOn(987654L)
|
||||
// Defaults to createdOn if not set.
|
||||
.setLastUpdatedOn(987654L)
|
||||
.setOwnerAccountId(Reviewdb.Account_Id.newBuilder().setId(35))
|
||||
.setDest(
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 67"))
|
||||
.setBranchName("refs/heads/branch-74"))
|
||||
.setCurrentPatchSetId(23)
|
||||
.setSubject("subject ABC")
|
||||
// Default values which can't be unset.
|
||||
.setRowVersion(0)
|
||||
.setStatus(Change.STATUS_NEW)
|
||||
.setIsPrivate(false)
|
||||
.setWorkInProgress(false)
|
||||
.setReviewStarted(false)
|
||||
.build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProtoAndBackAgain() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
change.setLastUpdatedOn(new Timestamp(1234567L));
|
||||
change.setStatus(Change.Status.MERGED);
|
||||
change.setCurrentPatchSet(
|
||||
new PatchSet.Id(new Change.Id(14), 23), "subject XYZ", "original subject ABC");
|
||||
change.setTopic("my topic");
|
||||
change.setSubmissionId("submission ID 234");
|
||||
change.setAssignee(new Account.Id(100001));
|
||||
change.setPrivate(true);
|
||||
change.setWorkInProgress(true);
|
||||
change.setReviewStarted(true);
|
||||
change.setRevertOf(new Change.Id(180));
|
||||
|
||||
Change convertedChange = changeProtoConverter.fromProto(changeProtoConverter.toProto(change));
|
||||
assertEqualChange(convertedChange, change);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mandatoryValuesConvertedToProtoAndBackAgain() {
|
||||
Change change =
|
||||
new Change(
|
||||
new Change.Key("change 1"),
|
||||
new Change.Id(14),
|
||||
new Account.Id(35),
|
||||
new Branch.NameKey(new Project.NameKey("project 67"), "branch-74"),
|
||||
new Timestamp(987654L));
|
||||
|
||||
Change convertedChange = changeProtoConverter.fromProto(changeProtoConverter.toProto(change));
|
||||
assertEqualChange(convertedChange, change);
|
||||
}
|
||||
|
||||
// We need this special test as some values are only optional in the protobuf definition but can
|
||||
// never be unset in our entity object.
|
||||
@Test
|
||||
public void protoWithOnlyRequiredValuesCanBeConvertedBack() {
|
||||
Reviewdb.Change proto =
|
||||
Reviewdb.Change.newBuilder().setChangeId(Reviewdb.Change_Id.newBuilder().setId(14)).build();
|
||||
Change change = changeProtoConverter.fromProto(proto);
|
||||
|
||||
assertThat(change.getChangeId()).isEqualTo(14);
|
||||
// Values which can't be null according to ReviewDb's column definition but which are optional.
|
||||
assertThat(change.getKey()).isNull();
|
||||
assertThat(change.getOwner()).isNull();
|
||||
assertThat(change.getDest()).isNull();
|
||||
assertThat(change.getCreatedOn()).isEqualTo(new Timestamp(0));
|
||||
assertThat(change.getLastUpdatedOn()).isEqualTo(new Timestamp(0));
|
||||
assertThat(change.getSubject()).isNull();
|
||||
assertThat(change.currentPatchSetId()).isNull();
|
||||
// Default values for unset protobuf fields which can't be unset in the entity object.
|
||||
assertThat(change.getRowVersion()).isEqualTo(0);
|
||||
assertThat(change.getStatus()).isEqualTo(Change.Status.NEW);
|
||||
assertThat(change.isPrivate()).isFalse();
|
||||
assertThat(change.isWorkInProgress()).isFalse();
|
||||
assertThat(change.hasReviewStarted()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsetLastUpdatedOnIsAutomaticallySetToCreatedOnWhenConvertedBack() {
|
||||
Reviewdb.Change proto =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(Reviewdb.Change_Id.newBuilder().setId(14))
|
||||
.setChangeKey(Reviewdb.Change_Key.newBuilder().setId("change 1"))
|
||||
.setCreatedOn(987654L)
|
||||
.setOwnerAccountId(Reviewdb.Account_Id.newBuilder().setId(35))
|
||||
.setDest(
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 67"))
|
||||
.setBranchName("branch 74"))
|
||||
.build();
|
||||
Change change = changeProtoConverter.fromProto(proto);
|
||||
|
||||
assertThat(change.getLastUpdatedOn()).isEqualTo(new Timestamp(987654L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void protoCanBeParsedFromBytes() throws Exception {
|
||||
Reviewdb.Change proto =
|
||||
Reviewdb.Change.newBuilder()
|
||||
.setChangeId(Reviewdb.Change_Id.newBuilder().setId(14))
|
||||
.setChangeKey(Reviewdb.Change_Key.newBuilder().setId("change 1"))
|
||||
.setRowVersion(0)
|
||||
.setCreatedOn(987654L)
|
||||
.setLastUpdatedOn(1234567L)
|
||||
.setOwnerAccountId(Reviewdb.Account_Id.newBuilder().setId(35))
|
||||
.setDest(
|
||||
Reviewdb.Branch_NameKey.newBuilder()
|
||||
.setProjectName(Reviewdb.Project_NameKey.newBuilder().setName("project 67"))
|
||||
.setBranchName("branch 74"))
|
||||
.setStatus(Change.STATUS_MERGED)
|
||||
.setCurrentPatchSetId(23)
|
||||
.setSubject("subject XYZ")
|
||||
.setTopic("my topic")
|
||||
.setOriginalSubject("original subject ABC")
|
||||
.setSubmissionId("submission ID 234")
|
||||
.setAssignee(Reviewdb.Account_Id.newBuilder().setId(100001))
|
||||
.setIsPrivate(true)
|
||||
.setWorkInProgress(true)
|
||||
.setReviewStarted(true)
|
||||
.setRevertOf(Reviewdb.Change_Id.newBuilder().setId(180))
|
||||
.build();
|
||||
byte[] bytes = proto.toByteArray();
|
||||
|
||||
Parser<Reviewdb.Change> parser = changeProtoConverter.getParser();
|
||||
Reviewdb.Change parsedProto = parser.parseFrom(bytes);
|
||||
|
||||
assertThat(parsedProto).isEqualTo(proto);
|
||||
}
|
||||
|
||||
/** See {@link SerializedClassSubject} for background and what to do if this test fails. */
|
||||
@Test
|
||||
public void fieldsExistAsExpected() {
|
||||
assertThatSerializedClass(Change.class)
|
||||
.hasFields(
|
||||
ImmutableMap.<String, Type>builder()
|
||||
.put("changeId", Change.Id.class)
|
||||
.put("changeKey", Change.Key.class)
|
||||
.put("rowVersion", int.class)
|
||||
.put("createdOn", Timestamp.class)
|
||||
.put("lastUpdatedOn", Timestamp.class)
|
||||
.put("owner", Account.Id.class)
|
||||
.put("dest", Branch.NameKey.class)
|
||||
.put("status", char.class)
|
||||
.put("currentPatchSetId", int.class)
|
||||
.put("subject", String.class)
|
||||
.put("topic", String.class)
|
||||
.put("originalSubject", String.class)
|
||||
.put("submissionId", String.class)
|
||||
.put("assignee", Account.Id.class)
|
||||
.put("isPrivate", boolean.class)
|
||||
.put("workInProgress", boolean.class)
|
||||
.put("reviewStarted", boolean.class)
|
||||
.put("revertOf", Change.Id.class)
|
||||
.build());
|
||||
}
|
||||
|
||||
// Unfortunately, Change doesn't implement equals(). Remove this method when we switch Change to
|
||||
// an AutoValue.
|
||||
private static void assertEqualChange(Change change, Change expectedChange) {
|
||||
assertThat(change.getChangeId()).isEqualTo(expectedChange.getChangeId());
|
||||
assertThat(change.getKey()).isEqualTo(expectedChange.getKey());
|
||||
assertThat(change.getRowVersion()).isEqualTo(expectedChange.getRowVersion());
|
||||
assertThat(change.getCreatedOn()).isEqualTo(expectedChange.getCreatedOn());
|
||||
assertThat(change.getLastUpdatedOn()).isEqualTo(expectedChange.getLastUpdatedOn());
|
||||
assertThat(change.getOwner()).isEqualTo(expectedChange.getOwner());
|
||||
assertThat(change.getDest()).isEqualTo(expectedChange.getDest());
|
||||
assertThat(change.getStatus()).isEqualTo(expectedChange.getStatus());
|
||||
assertThat(change.currentPatchSetId()).isEqualTo(expectedChange.currentPatchSetId());
|
||||
assertThat(change.getSubject()).isEqualTo(expectedChange.getSubject());
|
||||
assertThat(change.getTopic()).isEqualTo(expectedChange.getTopic());
|
||||
assertThat(change.getOriginalSubject()).isEqualTo(expectedChange.getOriginalSubject());
|
||||
assertThat(change.getSubmissionId()).isEqualTo(expectedChange.getSubmissionId());
|
||||
assertThat(change.getAssignee()).isEqualTo(expectedChange.getAssignee());
|
||||
assertThat(change.isPrivate()).isEqualTo(expectedChange.isPrivate());
|
||||
assertThat(change.isWorkInProgress()).isEqualTo(expectedChange.isWorkInProgress());
|
||||
assertThat(change.hasReviewStarted()).isEqualTo(expectedChange.hasReviewStarted());
|
||||
assertThat(change.getRevertOf()).isEqualTo(expectedChange.getRevertOf());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2018 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.reviewdb.converter;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
|
||||
import static com.google.gerrit.proto.testing.SerializedClassSubject.assertThatSerializedClass;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.proto.reviewdb.Reviewdb;
|
||||
import com.google.gerrit.proto.testing.SerializedClassSubject;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.protobuf.Parser;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ProjectNameKeyProtoConverterTest {
|
||||
private final ProjectNameKeyProtoConverter projectNameKeyProtoConverter =
|
||||
ProjectNameKeyProtoConverter.INSTANCE;
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProto() {
|
||||
Project.NameKey nameKey = new Project.NameKey("project-72");
|
||||
|
||||
Reviewdb.Project_NameKey proto = projectNameKeyProtoConverter.toProto(nameKey);
|
||||
|
||||
Reviewdb.Project_NameKey expectedProto =
|
||||
Reviewdb.Project_NameKey.newBuilder().setName("project-72").build();
|
||||
assertThat(proto).isEqualTo(expectedProto);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allValuesConvertedToProtoAndBackAgain() {
|
||||
Project.NameKey nameKey = new Project.NameKey("project-52");
|
||||
|
||||
Project.NameKey convertedNameKey =
|
||||
projectNameKeyProtoConverter.fromProto(projectNameKeyProtoConverter.toProto(nameKey));
|
||||
|
||||
assertThat(convertedNameKey).isEqualTo(nameKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void protoCanBeParsedFromBytes() throws Exception {
|
||||
Reviewdb.Project_NameKey proto =
|
||||
Reviewdb.Project_NameKey.newBuilder().setName("project 36").build();
|
||||
byte[] bytes = proto.toByteArray();
|
||||
|
||||
Parser<Reviewdb.Project_NameKey> parser = projectNameKeyProtoConverter.getParser();
|
||||
Reviewdb.Project_NameKey parsedProto = parser.parseFrom(bytes);
|
||||
|
||||
assertThat(parsedProto).isEqualTo(proto);
|
||||
}
|
||||
|
||||
/** See {@link SerializedClassSubject} for background and what to do if this test fails. */
|
||||
@Test
|
||||
public void fieldsExistAsExpected() {
|
||||
assertThatSerializedClass(Project.NameKey.class)
|
||||
.hasFields(ImmutableMap.of("name", String.class));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user