/* * 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. */ import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; import com.google.protobuf.ExtensionRegistry; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.List; import protos.OneofFoo; import protos.OneofMsg; import protos.OneofMsg.OneofGroupCase; import protos.OneofMsgOrBuilder; /** * Tests for correct serialization and deserialization of oneof fields. */ public class OneofTest extends ProtobufTest { public void testParseFromByteArray() throws Exception { ExtensionRegistry registry = ExtensionRegistry.newInstance(); OneofMsg msg = OneofMsg.parseFrom(ONEOF_STRING_BYTES, registry); checkFields(msg, OneofGroupCase.ONEOF_STRING); msg = OneofMsg.parseFrom(ONEOF_INT_BYTES, registry); checkFields(msg, OneofGroupCase.ONEOF_INT); msg = OneofMsg.parseFrom(ONEOF_MESSAGE_BYTES, registry); checkFields(msg, OneofGroupCase.ONEOF_MESSAGE); } public void testMergeFromInputStream(OneofGroupCase groupCase) throws Exception { ExtensionRegistry registry = ExtensionRegistry.newInstance(); ByteArrayInputStream in = new ByteArrayInputStream(getBytes(groupCase)); OneofMsg.Builder builder = OneofMsg.newBuilder().mergeFrom(in, registry); checkFields(builder, groupCase); checkFields(builder.build(), groupCase); } public void testMergeFromInputStream() throws Exception { testMergeFromInputStream(OneofGroupCase.ONEOF_STRING); testMergeFromInputStream(OneofGroupCase.ONEOF_INT); testMergeFromInputStream(OneofGroupCase.ONEOF_MESSAGE); } public void testMergeFromOtherMessage() throws Exception { OneofMsg filledMsg = getFilledMessage(OneofGroupCase.ONEOF_STRING); OneofMsg.Builder builder = OneofMsg.newBuilder(); builder.mergeFrom(filledMsg); checkFields(builder, OneofGroupCase.ONEOF_STRING); checkFields(builder.build(), OneofGroupCase.ONEOF_STRING); } public void testSerialization(OneofGroupCase groupCase) throws Exception { OneofMsg msg = getFilledMessage(groupCase); byte[] expectedBytes = getBytes(groupCase); assertEquals(expectedBytes.length, msg.getSerializedSize()); byte[] bytes1 = msg.toByteArray(); checkBytes(expectedBytes, bytes1); ByteArrayOutputStream out = new ByteArrayOutputStream(); msg.writeTo(out); byte[] bytes2 = out.toByteArray(); checkBytes(expectedBytes, bytes2); } public void testSerialization() throws Exception { testSerialization(OneofGroupCase.ONEOF_STRING); testSerialization(OneofGroupCase.ONEOF_INT); testSerialization(OneofGroupCase.ONEOF_MESSAGE); } public void testReflection() throws Exception { Descriptor descriptor = OneofMsg.getDescriptor(); FieldDescriptor stringField = descriptor.findFieldByNumber(6); FieldDescriptor intField = descriptor.findFieldByNumber(4); FieldDescriptor messageField = descriptor.findFieldByNumber(1); OneofMsg msg = getFilledMessage(OneofGroupCase.ONEOF_STRING); assertEquals("goodbye", msg.getField(stringField)); assertFalse(msg.hasField(intField)); assertFalse(msg.hasField(messageField)); OneofMsg.Builder builder = msg.toBuilder(); builder.setField(messageField, OneofFoo.newBuilder().setFoo("baz").build()); assertEquals("baz", builder.getOneofMessage().getFoo()); assertFalse(builder.hasOneofString()); assertFalse(builder.hasOneofInt()); } public void testOneofDescriptor() throws Exception { Descriptor descriptor = OneofMsg.getDescriptor(); List<OneofDescriptor> oneofs = descriptor.getOneofs(); assertEquals(1, oneofs.size()); OneofDescriptor oneof = oneofs.get(0); assertEquals("oneof_group", oneof.getName()); assertEquals(descriptor, oneof.getContainingType()); } public void testFieldOrder() throws Exception { Descriptor descriptor = OneofMsg.getDescriptor(); List<FieldDescriptor> fields = descriptor.getFields(); assertEquals(3, fields.get(0).getNumber()); assertEquals(2, fields.get(1).getNumber()); assertEquals(5, fields.get(2).getNumber()); assertEquals(6, fields.get(3).getNumber()); assertEquals(4, fields.get(4).getNumber()); assertEquals(1, fields.get(5).getNumber()); OneofDescriptor oneof = descriptor.getOneofs().get(0); List<FieldDescriptor> oneofFields = oneof.getFields(); assertEquals(6, oneofFields.get(0).getNumber()); assertEquals(4, oneofFields.get(1).getNumber()); assertEquals(1, oneofFields.get(2).getNumber()); assertEquals(oneof, fields.get(3).getContainingOneof()); assertEquals(oneof, fields.get(4).getContainingOneof()); assertEquals(oneof, fields.get(5).getContainingOneof()); } public void testCaseForNumber() throws Exception { assertEquals(OneofGroupCase.ONEOF_STRING, OneofGroupCase.forNumber(6)); assertEquals(OneofGroupCase.ONEOF_INT, OneofGroupCase.forNumber(4)); assertEquals(OneofGroupCase.ONEOF_MESSAGE, OneofGroupCase.forNumber(1)); assertEquals(OneofGroupCase.ONEOFGROUP_NOT_SET, OneofGroupCase.forNumber(0)); assertNull(OneofGroupCase.forNumber(100)); assertNull(OneofGroupCase.forNumber(-1)); } private void checkFields(OneofMsgOrBuilder msg, OneofGroupCase fieldToCheck) { assertEquals("hello", msg.getRegularString()); assertEquals(42, msg.getRegularInt()); assertEquals("foo", msg.getRegularMessage().getFoo()); assertEquals(fieldToCheck, msg.getOneofGroupCase()); switch (fieldToCheck) { case ONEOF_STRING: assertEquals("goodbye", msg.getOneofString()); break; case ONEOF_INT: assertEquals(24, msg.getOneofInt()); break; case ONEOF_MESSAGE: assertEquals("bar", msg.getOneofMessage().getFoo()); break; } if (!fieldToCheck.equals(OneofGroupCase.ONEOF_STRING)) { assertFalse(msg.hasOneofString()); } if (!fieldToCheck.equals(OneofGroupCase.ONEOF_INT)) { assertFalse(msg.hasOneofInt()); } if (!fieldToCheck.equals(OneofGroupCase.ONEOF_MESSAGE)) { assertFalse(msg.hasOneofMessage()); } } private OneofMsg getFilledMessage(OneofGroupCase fieldToSet) { OneofMsg.Builder builder = OneofMsg.newBuilder() .setRegularString("hello") .setRegularInt(42) .setRegularMessage(OneofFoo.newBuilder().setFoo("foo").build()); switch (fieldToSet) { case ONEOF_STRING: builder.setOneofString("goodbye"); break; case ONEOF_INT: builder.setOneofInt(24); break; case ONEOF_MESSAGE: builder.setOneofMessage(OneofFoo.newBuilder().setFoo("bar").build()); break; default: // Add nothing. } return builder.build(); } private static byte[] getBytes(OneofGroupCase groupCase) { switch (groupCase) { case ONEOF_STRING: return ONEOF_STRING_BYTES; case ONEOF_INT: return ONEOF_INT_BYTES; case ONEOF_MESSAGE: return ONEOF_MESSAGE_BYTES; default: return null; } } private static final byte[] ONEOF_STRING_BYTES = asBytes(new int[] { 0x10, 0x2A, 0x1A, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x2A, 0x05, 0x0A, 0x03, 0x66, 0x6F, 0x6F, 0x32, 0x07, 0x67, 0x6F, 0x6F, 0x64, 0x62, 0x79, 0x65 }); private static final byte[] ONEOF_INT_BYTES = asBytes(new int[] { 0x10, 0x2A, 0x1A, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x18, 0x2A, 0x05, 0x0A, 0x03, 0x66, 0x6F, 0x6F }); private static final byte[] ONEOF_MESSAGE_BYTES = asBytes(new int[] { 0x0A, 0x05, 0x0A, 0x03, 0x62, 0x61, 0x72, 0x10, 0x2A, 0x1A, 0x05, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x2A, 0x05, 0x0A, 0x03, 0x66, 0x6F, 0x6F }); }