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 protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
  import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
  import protobuf_unittest.UnittestOptimizeFor;
  import protobuf_unittest.UnittestProto.ForeignMessage;
  import protobuf_unittest.UnittestProto.TestAllTypes;
  import protobuf_unittest.UnittestProto.TestEmptyMessage;
  import protobuf_unittest.UnittestProto.TestRequired;
  import protobuf_unittest.UnittestProto.TestParsingMerge;
  import protobuf_unittest.UnittestProto;
  
  import junit.framework.TestCase;
  
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  
  /**
   * Unit test for {@link Parser}.
   *
   * @author liujisi@google.com (Pherl Liu)
   */
  public class ParserTest extends TestCase {
    public void testGeneratedMessageParserSingleton() throws Exception {
      for (int i = 0; i < 10; i++) {
        assertEquals(TestAllTypes.PARSER,
                     TestUtil.getAllSet().getParserForType());
      }
    }
  
    private void assertRoundTripEquals(MessageLite message,
                                       ExtensionRegistryLite registry)
        throws Exception {
      final byte[] data = message.toByteArray();
      final int offset = 20;
      final int length = data.length;
      final int padding = 30;
      Parser<? extends MessageLite> parser = message.getParserForType();
      assertMessageEquals(message, parser.parseFrom(data, registry));
      assertMessageEquals(message, parser.parseFrom(
          generatePaddingArray(data, offset, padding),
          offset, length, registry));
      assertMessageEquals(message, parser.parseFrom(
          message.toByteString(), registry));
      assertMessageEquals(message, parser.parseFrom(
          new ByteArrayInputStream(data), registry));
      assertMessageEquals(message, parser.parseFrom(
          CodedInputStream.newInstance(data), registry));
    }
  
    private void assertRoundTripEquals(MessageLite message) throws Exception {
      final byte[] data = message.toByteArray();
      final int offset = 20;
      final int length = data.length;
      final int padding = 30;
      Parser<? extends MessageLite> parser = message.getParserForType();
      assertMessageEquals(message, parser.parseFrom(data));
      assertMessageEquals(message, parser.parseFrom(
          generatePaddingArray(data, offset, padding),
          offset, length));
      assertMessageEquals(message, parser.parseFrom(message.toByteString()));
      assertMessageEquals(message, parser.parseFrom(
          new ByteArrayInputStream(data)));
      assertMessageEquals(message, parser.parseFrom(
          CodedInputStream.newInstance(data)));
    }
  
    private void assertMessageEquals(MessageLite expected, MessageLite actual)
        throws Exception {
      if (expected instanceof Message) {
        assertEquals(expected, actual);
      } else {
        assertEquals(expected.toByteString(), actual.toByteString());
      }
    }
  
    private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
      byte[] result = new byte[offset + data.length + padding];
      System.arraycopy(data, 0, result, offset, data.length);
      return result;
    }
  
    public void testNormalMessage() throws Exception {
      assertRoundTripEquals(TestUtil.getAllSet());
    }
  
    public void testParsePartial() throws Exception {
      Parser<TestRequired> parser = TestRequired.PARSER;
      final String errorString =
          "Should throw exceptions when the parsed message isn't initialized.";
  
      // TestRequired.b and TestRequired.c are not set.
      TestRequired partialMessage = TestRequired.newBuilder()
          .setA(1).buildPartial();
  
      // parsePartialFrom should pass.
      byte[] data = partialMessage.toByteArray();
      assertEquals(partialMessage, parser.parsePartialFrom(data));
      assertEquals(partialMessage, parser.parsePartialFrom(
          partialMessage.toByteString()));
      assertEquals(partialMessage, parser.parsePartialFrom(
          new ByteArrayInputStream(data)));
      assertEquals(partialMessage, parser.parsePartialFrom(
          CodedInputStream.newInstance(data)));
  
      // parseFrom(ByteArray)
      try {
        parser.parseFrom(partialMessage.toByteArray());
        fail(errorString);
      } catch (InvalidProtocolBufferException e) {
        // pass.
      }
  
      // parseFrom(ByteString)
      try {
        parser.parseFrom(partialMessage.toByteString());
        fail(errorString);
      } catch (InvalidProtocolBufferException e) {
        // pass.
      }
  
      // parseFrom(InputStream)
      try {
        parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
        fail(errorString);
      } catch (IOException e) {
        // pass.
      }
  
      // parseFrom(CodedInputStream)
      try {
        parser.parseFrom(CodedInputStream.newInstance(
            partialMessage.toByteArray()));
        fail(errorString);
      } catch (IOException e) {
        // pass.
      }
    }
  
    public void testParseDelimitedTo() throws Exception {
      // Write normal Message.
      TestAllTypes normalMessage = TestUtil.getAllSet();
      ByteArrayOutputStream output = new ByteArrayOutputStream();
      normalMessage.writeDelimitedTo(output);
  
      InputStream input = new ByteArrayInputStream(output.toByteArray());
      assertMessageEquals(
          normalMessage,
          normalMessage.getParserForType().parseDelimitedFrom(input));
    }
  
    public void testParseUnknownFields() throws Exception {
      // All fields will be treated as unknown fields in emptyMessage.
      TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
          TestUtil.getAllSet().toByteString());
      assertEquals(
          TestUtil.getAllSet().toByteString(),
          emptyMessage.toByteString());
    }
  
    public void testOptimizeForSize() throws Exception {
      TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
      builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
      builder.setExtension(TestOptimizedForSize.testExtension, 56);
      builder.setExtension(TestOptimizedForSize.testExtension2,
          TestRequiredOptimizedForSize.newBuilder().setX(78).build());
  
      TestOptimizedForSize message = builder.build();
      ExtensionRegistry registry = ExtensionRegistry.newInstance();
      UnittestOptimizeFor.registerAllExtensions(registry);
  
      assertRoundTripEquals(message, registry);
    }
  
    /** Helper method for {@link #testParsingMerge()}.*/
    private void assertMessageMerged(TestAllTypes allTypes)
        throws Exception {
      assertEquals(3, allTypes.getOptionalInt32());
      assertEquals(2, allTypes.getOptionalInt64());
      assertEquals("hello", allTypes.getOptionalString());
    }
  
    public void testParsingMerge() throws Exception {
      // Build messages.
      TestAllTypes.Builder builder = TestAllTypes.newBuilder();
      TestAllTypes msg1 = builder.setOptionalInt32(1).build();
      builder.clear();
      TestAllTypes msg2 = builder.setOptionalInt64(2).build();
      builder.clear();
      TestAllTypes msg3 = builder.setOptionalInt32(3)
          .setOptionalString("hello").build();
  
      // Build groups.
      TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
          TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
          .setField1(msg1).build();
      TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
          TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
          .setField1(msg2).build();
      TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
          TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
          .setField1(msg3).build();
      TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
          TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
          .setField1(msg1).build();
      TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
          TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
          .setField1(msg2).build();
      TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
          TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
          .setField1(msg3).build();
  
      // Assign and serialize RepeatedFieldsGenerator.
      ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
          .addField1(msg1).addField1(msg2).addField1(msg3)
          .addField2(msg1).addField2(msg2).addField2(msg3)
          .addField3(msg1).addField3(msg2).addField3(msg3)
          .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
          .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
          .addExt1(msg1).addExt1(msg2).addExt1(msg3)
          .addExt2(msg1).addExt2(msg2).addExt2(msg3)
          .build().toByteString();
  
      // Parse TestParsingMerge.
      ExtensionRegistry registry = ExtensionRegistry.newInstance();
      UnittestProto.registerAllExtensions(registry);
      TestParsingMerge parsingMerge =
          TestParsingMerge.PARSER.parseFrom(data, registry);
  
      // Required and optional fields should be merged.
      assertMessageMerged(parsingMerge.getRequiredAllTypes());
      assertMessageMerged(parsingMerge.getOptionalAllTypes());
      assertMessageMerged(
          parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
      assertMessageMerged(parsingMerge.getExtension(
          TestParsingMerge.optionalExt));
  
      // Repeated fields should not be merged.
      assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
      assertEquals(3, parsingMerge.getRepeatedGroupCount());
      assertEquals(3, parsingMerge.getExtensionCount(
          TestParsingMerge.repeatedExt));
    }
  
  }
  