mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 11:51:10 +01:00
Add support for handling unknown protobuf fields.
This commit is contained in:
committed by
Alex Hart
parent
ffcb90da52
commit
2cf9eb69eb
@@ -0,0 +1,229 @@
|
||||
package org.whispersystems.signalservice.api.util;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestInnerMessage;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestInnerMessageWithNewString;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestPerson;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestPersonWithNewFieldOnMessage;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestPersonWithNewMessage;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestPersonWithNewRepeatedString;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestPersonWithNewString;
|
||||
import org.thoughtcrime.securesms.util.testprotos.TestPersonWithNewStringAndInt;
|
||||
import org.whispersystems.signalservice.api.util.ProtoUtil;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ProtoUtilTest {
|
||||
|
||||
@Test
|
||||
public void hasUnknownFields_noUnknowns() {
|
||||
TestPerson person = TestPerson.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
assertFalse(ProtoUtil.hasUnknownFields(person));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasUnknownFields_unknownString() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewString person = TestPersonWithNewString.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob("Reporter")
|
||||
.build();
|
||||
|
||||
TestPerson personWithUnknowns = TestPerson.parseFrom(person.toByteArray());
|
||||
|
||||
assertTrue(ProtoUtil.hasUnknownFields(personWithUnknowns));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasUnknownFields_multipleUnknowns() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewStringAndInt person = TestPersonWithNewStringAndInt.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob("Reporter")
|
||||
.setSalary(75_000)
|
||||
.build();
|
||||
|
||||
TestPerson personWithUnknowns = TestPerson.parseFrom(person.toByteArray());
|
||||
|
||||
assertTrue(ProtoUtil.hasUnknownFields(personWithUnknowns));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasUnknownFields_unknownMessage() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewMessage person = TestPersonWithNewMessage.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob(TestPersonWithNewMessage.Job.newBuilder()
|
||||
.setTitle("Reporter")
|
||||
.setSalary(75_000))
|
||||
.build();
|
||||
|
||||
TestPerson personWithUnknowns = TestPerson.parseFrom(person.toByteArray());
|
||||
|
||||
assertTrue(ProtoUtil.hasUnknownFields(personWithUnknowns));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasUnknownFields_unknownInsideMessage() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewFieldOnMessage person = TestPersonWithNewFieldOnMessage.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob(TestPersonWithNewFieldOnMessage.Job.newBuilder()
|
||||
.setTitle("Reporter")
|
||||
.setSalary(75_000)
|
||||
.setStartDate(100))
|
||||
.build();
|
||||
|
||||
TestPersonWithNewMessage personWithUnknowns = TestPersonWithNewMessage.parseFrom(person.toByteArray());
|
||||
|
||||
assertTrue(ProtoUtil.hasUnknownFields(personWithUnknowns));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithUnknownFields_noUnknowns() throws InvalidProtocolBufferException {
|
||||
TestPerson personWithUnknowns = TestPerson.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
TestPerson localRepresentation = TestPerson.newBuilder()
|
||||
.setName("Spider-Man")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
TestPerson combinedWithUnknowns = ProtoUtil.combineWithUnknownFields(localRepresentation, personWithUnknowns.toByteArray());
|
||||
TestPersonWithNewString reparsedPerson = TestPersonWithNewString.parseFrom(combinedWithUnknowns.toByteArray());
|
||||
|
||||
Assert.assertEquals("Spider-Man", reparsedPerson.getName());
|
||||
Assert.assertEquals(23, reparsedPerson.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithUnknownFields_appendedString() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewString personWithUnknowns = TestPersonWithNewString.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob("Reporter")
|
||||
.build();
|
||||
|
||||
TestPerson localRepresentation = TestPerson.newBuilder()
|
||||
.setName("Spider-Man")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
TestPerson combinedWithUnknowns = ProtoUtil.combineWithUnknownFields(localRepresentation, personWithUnknowns.toByteArray());
|
||||
TestPersonWithNewString reparsedPerson = TestPersonWithNewString.parseFrom(combinedWithUnknowns.toByteArray());
|
||||
|
||||
Assert.assertEquals("Spider-Man", reparsedPerson.getName());
|
||||
Assert.assertEquals(23, reparsedPerson.getAge());
|
||||
Assert.assertEquals("Reporter", reparsedPerson.getJob());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithUnknownFields_appendedRepeatedString() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewRepeatedString personWithUnknowns = TestPersonWithNewRepeatedString.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.addJobs("Reporter")
|
||||
.addJobs("Super Hero")
|
||||
.build();
|
||||
|
||||
TestPerson localRepresentation = TestPerson.newBuilder()
|
||||
.setName("Spider-Man")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
TestPerson combinedWithUnknowns = ProtoUtil.combineWithUnknownFields(localRepresentation, personWithUnknowns.toByteArray());
|
||||
TestPersonWithNewRepeatedString reparsedPerson = TestPersonWithNewRepeatedString.parseFrom(combinedWithUnknowns.toByteArray());
|
||||
|
||||
Assert.assertEquals("Spider-Man", reparsedPerson.getName());
|
||||
Assert.assertEquals(23, reparsedPerson.getAge());
|
||||
Assert.assertEquals(2, reparsedPerson.getJobsCount());
|
||||
Assert.assertEquals("Reporter", reparsedPerson.getJobs(0));
|
||||
Assert.assertEquals("Super Hero", reparsedPerson.getJobs(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithUnknownFields_appendedStringAndInt() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewStringAndInt personWithUnknowns = TestPersonWithNewStringAndInt.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob("Reporter")
|
||||
.setSalary(75_000)
|
||||
.build();
|
||||
|
||||
TestPerson localRepresentation = TestPerson.newBuilder()
|
||||
.setName("Spider-Man")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
TestPerson combinedWithUnknowns = ProtoUtil.combineWithUnknownFields(localRepresentation, personWithUnknowns.toByteArray());
|
||||
TestPersonWithNewStringAndInt reparsedPerson = TestPersonWithNewStringAndInt.parseFrom(combinedWithUnknowns.toByteArray());
|
||||
|
||||
Assert.assertEquals("Spider-Man", reparsedPerson.getName());
|
||||
Assert.assertEquals(23, reparsedPerson.getAge());
|
||||
Assert.assertEquals("Reporter", reparsedPerson.getJob());
|
||||
Assert.assertEquals(75_000, reparsedPerson.getSalary());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithUnknownFields_appendedMessage() throws InvalidProtocolBufferException {
|
||||
TestPersonWithNewMessage personWithUnknowns = TestPersonWithNewMessage.newBuilder()
|
||||
.setName("Peter Parker")
|
||||
.setAge(23)
|
||||
.setJob(TestPersonWithNewMessage.Job.newBuilder()
|
||||
.setTitle("Reporter")
|
||||
.setSalary(75_000))
|
||||
.build();
|
||||
|
||||
TestPerson localRepresentation = TestPerson.newBuilder()
|
||||
.setName("Spider-Man")
|
||||
.setAge(23)
|
||||
.build();
|
||||
|
||||
TestPerson combinedWithUnknowns = ProtoUtil.combineWithUnknownFields(localRepresentation, personWithUnknowns.toByteArray());
|
||||
TestPersonWithNewMessage reparsedPerson = TestPersonWithNewMessage.parseFrom(combinedWithUnknowns.toByteArray());
|
||||
|
||||
Assert.assertEquals("Spider-Man", reparsedPerson.getName());
|
||||
Assert.assertEquals(23, reparsedPerson.getAge());
|
||||
Assert.assertEquals("Reporter", reparsedPerson.getJob().getTitle());
|
||||
Assert.assertEquals(75_000, reparsedPerson.getJob().getSalary());
|
||||
}
|
||||
|
||||
/**
|
||||
* This isn't ideal behavior. This is more to show how something works. In the future, it'd be
|
||||
* nice to support inner unknown fields.
|
||||
*/
|
||||
@Test
|
||||
public void combineWithUnknownFields_innerMessagesUnknownsIgnored() throws InvalidProtocolBufferException {
|
||||
TestInnerMessageWithNewString test = TestInnerMessageWithNewString.newBuilder()
|
||||
.setInner(TestInnerMessageWithNewString.Inner.newBuilder()
|
||||
.setA("a1")
|
||||
.setB("b1")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
TestInnerMessage localRepresentation = TestInnerMessage.newBuilder()
|
||||
.setInner(TestInnerMessage.Inner.newBuilder()
|
||||
.setA("a2")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
TestInnerMessage combined = ProtoUtil.combineWithUnknownFields(localRepresentation, test.toByteArray());
|
||||
TestInnerMessageWithNewString reparsedTest = TestInnerMessageWithNewString.parseFrom(combined.toByteArray());
|
||||
|
||||
Assert.assertEquals("a2", reparsedTest.getInner().getA());
|
||||
Assert.assertEquals("", reparsedTest.getInner().getB());
|
||||
}
|
||||
}
|
||||
70
libsignal/service/src/test/proto/Test.proto
Normal file
70
libsignal/service/src/test/proto/Test.proto
Normal file
@@ -0,0 +1,70 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package signal;
|
||||
|
||||
option java_package = "org.thoughtcrime.securesms.util.testprotos";
|
||||
option java_multiple_files = true;
|
||||
|
||||
message TestPerson {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
}
|
||||
|
||||
message TestPersonWithNewString {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
string job = 3;
|
||||
}
|
||||
|
||||
message TestPersonWithNewRepeatedString {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
repeated string jobs = 3;
|
||||
}
|
||||
|
||||
message TestPersonWithNewStringAndInt {
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
string job = 3;
|
||||
int32 salary = 4;
|
||||
}
|
||||
|
||||
message TestPersonWithNewMessage {
|
||||
message Job {
|
||||
string title = 1;
|
||||
uint32 salary = 2;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
Job job = 3;
|
||||
}
|
||||
|
||||
message TestPersonWithNewFieldOnMessage {
|
||||
message Job {
|
||||
string title = 1;
|
||||
uint32 salary = 2;
|
||||
uint64 startDate = 3;
|
||||
}
|
||||
|
||||
string name = 1;
|
||||
int32 age = 2;
|
||||
Job job = 3;
|
||||
}
|
||||
|
||||
message TestInnerMessage {
|
||||
message Inner {
|
||||
string a = 1;
|
||||
}
|
||||
|
||||
Inner inner = 1;
|
||||
}
|
||||
|
||||
message TestInnerMessageWithNewString {
|
||||
message Inner {
|
||||
string a = 1;
|
||||
string b = 2;
|
||||
}
|
||||
|
||||
Inner inner = 1;
|
||||
}
|
||||
Reference in New Issue
Block a user