content: // Protocol Buffers - Google's data interchange format
  // Copyright 2008 Google Inc.  All rights reserved.
  // http://code.google.com/p/protobuf/
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  //     * Neither the name of Google Inc. nor the names of its
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  package com.google.protobuf.test;
  import com.google.protobuf.*;
  
  import junit.framework.TestCase;
  
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.util.List;
  
  import protobuf_unittest.UnittestProto;
  import protobuf_unittest.UnittestProto.TestAllExtensions;
  import protobuf_unittest.UnittestProto.TestAllTypes;
  import protobuf_unittest.UnittestProto.TestFieldOrderings;
  import protobuf_unittest.UnittestProto.TestPackedExtensions;
  import protobuf_unittest.UnittestProto.TestPackedTypes;
  import protobuf_unittest.UnittestMset.TestMessageSet;
  import protobuf_unittest.UnittestMset.RawMessageSet;
  import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
  import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
  
  /**
   * Tests related to parsing and serialization.
   *
   * @author kenton@google.com (Kenton Varda)
   */
  public class WireFormatTest extends TestCase {
    public void testSerialization() throws Exception {
      TestAllTypes message = TestUtil.getAllSet();
  
      ByteString rawBytes = message.toByteString();
      assertEquals(rawBytes.size(), message.getSerializedSize());
  
      TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
  
      TestUtil.assertAllFieldsSet(message2);
    }
  
    public void testSerializationPacked() throws Exception {
      TestPackedTypes message = TestUtil.getPackedSet();
  
      ByteString rawBytes = message.toByteString();
      assertEquals(rawBytes.size(), message.getSerializedSize());
  
      TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
  
      TestUtil.assertPackedFieldsSet(message2);
    }
  
    public void testSerializeExtensions() throws Exception {
      // TestAllTypes and TestAllExtensions should have compatible wire formats,
      // so if we serialize a TestAllExtensions then parse it as TestAllTypes
      // it should work.
  
      TestAllExtensions message = TestUtil.getAllExtensionsSet();
      ByteString rawBytes = message.toByteString();
      assertEquals(rawBytes.size(), message.getSerializedSize());
  
      TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
  
      TestUtil.assertAllFieldsSet(message2);
    }
  
    public void testSerializePackedExtensions() throws Exception {
      // TestPackedTypes and TestPackedExtensions should have compatible wire
      // formats; check that they serialize to the same string.
      TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
      ByteString rawBytes = message.toByteString();
  
      TestPackedTypes message2 = TestUtil.getPackedSet();
      ByteString rawBytes2 = message2.toByteString();
  
      assertEquals(rawBytes, rawBytes2);
    }
  
    public void testSerializationPackedWithoutGetSerializedSize()
        throws Exception {
      // Write directly to an OutputStream, without invoking getSerializedSize()
      // This used to be a bug where the size of a packed field was incorrect,
      // since getSerializedSize() was never invoked.
      TestPackedTypes message = TestUtil.getPackedSet();
  
      // Directly construct a CodedOutputStream around the actual OutputStream,
      // in case writeTo(OutputStream output) invokes getSerializedSize();
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
  
      message.writeTo(codedOutput);
  
      codedOutput.flush();
  
      TestPackedTypes message2 = TestPackedTypes.parseFrom(
          outputStream.toByteArray());
  
      TestUtil.assertPackedFieldsSet(message2);
    }
  
    public void testParseExtensions() throws Exception {
      // TestAllTypes and TestAllExtensions should have compatible wire formats,
      // so if we serialize a TestAllTypes then parse it as TestAllExtensions
      // it should work.
  
      TestAllTypes message = TestUtil.getAllSet();
      ByteString rawBytes = message.toByteString();
  
      ExtensionRegistry registry = TestUtil.getExtensionRegistry();
  
      TestAllExtensions message2 =
        TestAllExtensions.parseFrom(rawBytes, registry);
  
      TestUtil.assertAllExtensionsSet(message2);
    }
  
    public void testParsePackedExtensions() throws Exception {
      // Ensure that packed extensions can be properly parsed.
      TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
      ByteString rawBytes = message.toByteString();
  
      ExtensionRegistry registry = TestUtil.getExtensionRegistry();
  
      TestPackedExtensions message2 =
          TestPackedExtensions.parseFrom(rawBytes, registry);
  
      TestUtil.assertPackedExtensionsSet(message2);
    }
  
    public void testExtensionsSerializedSize() throws Exception {
      assertEquals(TestUtil.getAllSet().getSerializedSize(),
                   TestUtil.getAllExtensionsSet().getSerializedSize());
    }
  
    public void testSerializeDelimited() throws Exception {
      ByteArrayOutputStream output = new ByteArrayOutputStream();
      TestUtil.getAllSet().writeDelimitedTo(output);
      output.write(12);
      TestUtil.getPackedSet().writeDelimitedTo(output);
      output.write(34);
  
      ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
  
      TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
      assertEquals(12, input.read());
      TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
      assertEquals(34, input.read());
      assertEquals(-1, input.read());
  
      // We're at EOF, so parsing again should return null.
      assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
    }
  
    private void assertFieldsInOrder(ByteString data) throws Exception {
      CodedInputStream input = data.newCodedInput();
      int previousTag = 0;
  
      while (true) {
        int tag = input.readTag();
        if (tag == 0) {
          break;
        }
  
        assertTrue(tag > previousTag);
        previousTag = tag;
        input.skipField(tag);
      }
    }
  
    public void testInterleavedFieldsAndExtensions() throws Exception {
      // Tests that fields are written in order even when extension ranges
      // are interleaved with field numbers.
      ByteString data =
        TestFieldOrderings.newBuilder()
          .setMyInt(1)
          .setMyString("foo")
          .setMyFloat(1.0F)
          .setExtension(UnittestProto.myExtensionInt, 23)
          .setExtension(UnittestProto.myExtensionString, "bar")
          .build().toByteString();
      assertFieldsInOrder(data);
  
      Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
      ByteString dynamic_data =
        DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
          .setField(descriptor.findFieldByName("my_int"), 1L)
          .setField(descriptor.findFieldByName("my_string"), "foo")
          .setField(descriptor.findFieldByName("my_float"), 1.0F)
          .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
          .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
          .build().toByteString();
      assertFieldsInOrder(dynamic_data);
    }
  
    private ExtensionRegistry getTestFieldOrderingsRegistry() {
      ExtensionRegistry result = ExtensionRegistry.newInstance();
      result.add(UnittestProto.myExtensionInt);
      result.add(UnittestProto.myExtensionString);
      return result;
    }
  
    public void testParseMultipleExtensionRanges() throws Exception {
      // Make sure we can parse a message that contains multiple extensions
      // ranges.
      TestFieldOrderings source =
        TestFieldOrderings.newBuilder()
          .setMyInt(1)
          .setMyString("foo")
          .setMyFloat(1.0F)
          .setExtension(UnittestProto.myExtensionInt, 23)
          .setExtension(UnittestProto.myExtensionString, "bar")
          .build();
      TestFieldOrderings dest =
        TestFieldOrderings.parseFrom(source.toByteString(),
                                     getTestFieldOrderingsRegistry());
      assertEquals(source, dest);
    }
  
    public void testParseMultipleExtensionRangesDynamic() throws Exception {
      // Same as above except with DynamicMessage.
      Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
      DynamicMessage source =
        DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
          .setField(descriptor.findFieldByName("my_int"), 1L)
          .setField(descriptor.findFieldByName("my_string"), "foo")
          .setField(descriptor.findFieldByName("my_float"), 1.0F)
          .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
          .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
          .build();
      DynamicMessage dest =
        DynamicMessage.parseFrom(descriptor, source.toByteString(),
                                 getTestFieldOrderingsRegistry());
      assertEquals(source, dest);
    }
  
    private static final int UNKNOWN_TYPE_ID = 1550055;
    private static final int TYPE_ID_1 =
      TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
    private static final int TYPE_ID_2 =
      TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
  
    public void testSerializeMessageSetEagerly() throws Exception {
      testSerializeMessageSetWithFlag(true);
    }
  
    public void testSerializeMessageSetNotEagerly() throws Exception {
      testSerializeMessageSetWithFlag(false);
    }
  
    private void testSerializeMessageSetWithFlag(boolean eagerParsing)
        throws Exception {
      ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
      // Set up a TestMessageSet with two known messages and an unknown one.
      TestMessageSet messageSet =
        TestMessageSet.newBuilder()
          .setExtension(
            TestMessageSetExtension1.messageSetExtension,
            TestMessageSetExtension1.newBuilder().setI(123).build())
          .setExtension(
            TestMessageSetExtension2.messageSetExtension,
            TestMessageSetExtension2.newBuilder().setStr("foo").build())
          .setUnknownFields(
            UnknownFieldSet.newBuilder()
              .addField(UNKNOWN_TYPE_ID,
                UnknownFieldSet.Field.newBuilder()
                  .addLengthDelimited(ByteString.copyFromUtf8("bar"))
                  .build())
              .build())
          .build();
  
      ByteString data = messageSet.toByteString();
  
      // Parse back using RawMessageSet and check the contents.
      RawMessageSet raw = RawMessageSet.parseFrom(data);
  
      assertTrue(raw.getUnknownFields().asMap().isEmpty());
  
      assertEquals(3, raw.getItemCount());
      assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
      assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
      assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
  
      TestMessageSetExtension1 message1 =
        TestMessageSetExtension1.parseFrom(
          raw.getItem(0).getMessage().toByteArray());
      assertEquals(123, message1.getI());
  
      TestMessageSetExtension2 message2 =
        TestMessageSetExtension2.parseFrom(
          raw.getItem(1).getMessage().toByteArray());
      assertEquals("foo", message2.getStr());
  
      assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
    }
  
    public void testParseMessageSetEagerly() throws Exception {
      testParseMessageSetWithFlag(true);
    }
  
    public void testParseMessageSetNotEagerly()throws Exception {
      testParseMessageSetWithFlag(false);
    }
  
    private void testParseMessageSetWithFlag(boolean eagerParsing)
        throws Exception {
      ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
      ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
      extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
      extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
  
      // Set up a RawMessageSet with two known messages and an unknown one.
      RawMessageSet raw =
        RawMessageSet.newBuilder()
          .addItem(
            RawMessageSet.Item.newBuilder()
              .setTypeId(TYPE_ID_1)
              .setMessage(
                TestMessageSetExtension1.newBuilder()
                  .setI(123)
                  .build().toByteString())
              .build())
          .addItem(
            RawMessageSet.Item.newBuilder()
              .setTypeId(TYPE_ID_2)
              .setMessage(
                TestMessageSetExtension2.newBuilder()
                  .setStr("foo")
                  .build().toByteString())
              .build())
          .addItem(
            RawMessageSet.Item.newBuilder()
              .setTypeId(UNKNOWN_TYPE_ID)
              .setMessage(ByteString.copyFromUtf8("bar"))
              .build())
          .build();
  
      ByteString data = raw.toByteString();
  
      // Parse as a TestMessageSet and check the contents.
      TestMessageSet messageSet =
        TestMessageSet.parseFrom(data, extensionRegistry);
  
      assertEquals(123, messageSet.getExtension(
        TestMessageSetExtension1.messageSetExtension).getI());
      assertEquals("foo", messageSet.getExtension(
        TestMessageSetExtension2.messageSetExtension).getStr());
  
      // Check for unknown field with type LENGTH_DELIMITED,
      //   number UNKNOWN_TYPE_ID, and contents "bar".
      UnknownFieldSet unknownFields = messageSet.getUnknownFields();
      assertEquals(1, unknownFields.asMap().size());
      assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
  
      UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
      assertEquals(1, field.getLengthDelimitedList().size());
      assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
    }
  
    public void testParseMessageSetExtensionEagerly() throws Exception {
      testParseMessageSetExtensionWithFlag(true);
    }
  
    public void testParseMessageSetExtensionNotEagerly() throws Exception {
      testParseMessageSetExtensionWithFlag(false);
    }
  
    private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
        throws Exception {
      ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
      ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
      extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
  
      // Set up a RawMessageSet with a known messages.
      int TYPE_ID_1 =
          TestMessageSetExtension1
              .getDescriptor().getExtensions().get(0).getNumber();
      RawMessageSet raw =
        RawMessageSet.newBuilder()
          .addItem(
            RawMessageSet.Item.newBuilder()
              .setTypeId(TYPE_ID_1)
              .setMessage(
                TestMessageSetExtension1.newBuilder()
                  .setI(123)
                  .build().toByteString())
              .build())
          .build();
  
      ByteString data = raw.toByteString();
  
      // Parse as a TestMessageSet and check the contents.
      TestMessageSet messageSet =
          TestMessageSet.parseFrom(data, extensionRegistry);
      assertEquals(123, messageSet.getExtension(
          TestMessageSetExtension1.messageSetExtension).getI());
    }
  
    public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
      testMergeLazyMessageSetExtensionWithFlag(true);
    }
  
    public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
      testMergeLazyMessageSetExtensionWithFlag(false);
    }
  
    private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
        throws Exception {
      ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
      ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
      extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
  
      // Set up a RawMessageSet with a known messages.
      int TYPE_ID_1 =
          TestMessageSetExtension1
              .getDescriptor().getExtensions().get(0).getNumber();
      RawMessageSet raw =
        RawMessageSet.newBuilder()
          .addItem(
            RawMessageSet.Item.newBuilder()
              .setTypeId(TYPE_ID_1)
              .setMessage(
                TestMessageSetExtension1.newBuilder()
                  .setI(123)
                  .build().toByteString())
              .build())
          .build();
  
      ByteString data = raw.toByteString();
  
      // Parse as a TestMessageSet and store value into lazy field
      TestMessageSet messageSet =
          TestMessageSet.parseFrom(data, extensionRegistry);
      // Merge lazy field check the contents.
      messageSet =
          messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
      assertEquals(123, messageSet.getExtension(
          TestMessageSetExtension1.messageSetExtension).getI());
    }
  }
  