// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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;

import protobuf_unittest.UnittestOptimizeFor;
import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestEmptyMessage;
import protobuf_unittest.UnittestProto.TestParsingMerge;
import protobuf_unittest.UnittestProto.TestRequired;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import junit.framework.TestCase;

/**
 * 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));
    assertMessageEquals(
        message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer(), registry));
  }

  @SuppressWarnings("unchecked")
  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<MessageLite> parser =
        (Parser<MessageLite>) 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)));
    assertMessageEquals(message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer()));
  }

  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 {
    assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
  }

  private <T extends MessageLite> void assertParsePartial(
      Parser<T> parser, T partialMessage) throws Exception {
    final String errorString =
        "Should throw exceptions when the parsed message isn't initialized.";

    // 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 testParseExtensions() throws Exception {
    assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
                          TestUtil.getExtensionRegistry());
  }

  public void testParsePacked() throws Exception {
    assertRoundTripEquals(TestUtil.getPackedSet());
    assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
                          TestUtil.getExtensionRegistry());
  }

  public void testParseDelimitedTo() throws Exception {
    // Write normal Message.
    TestAllTypes normalMessage = TestUtil.getAllSet();
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    normalMessage.writeDelimitedTo(output);
    normalMessage.writeDelimitedTo(output);

    InputStream input = new ByteArrayInputStream(output.toByteArray());
    assertMessageEquals(normalMessage, normalMessage.getParserForType().parseDelimitedFrom(input));
    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));
  }

  public void testParseDelimitedFrom_firstByteInterrupted_preservesCause() {
    try {
      TestUtil.getAllSet().parseDelimitedFrom(
          new InputStream() {
            @Override
            public int read() throws IOException {
              throw new InterruptedIOException();
            }
          });
      fail("Expected InterruptedIOException");
    } catch (Exception e) {
      assertEquals(InterruptedIOException.class, e.getClass());
    }
  }

  public void testParseDelimitedFrom_secondByteInterrupted_preservesCause() {
    try {
      TestUtil.getAllSet().parseDelimitedFrom(
          new InputStream() {
            private int i;

            @Override
            public int read() throws IOException {
              switch (i++) {
                case 0:
                  return 1;
                case 1:
                  throw new InterruptedIOException();
                default:
                  throw new AssertionError();
              }
            }
          });
      fail("Expected InterruptedIOException");
    } catch (Exception e) {
      assertEquals(InterruptedIOException.class, e.getClass());
    }
  }
}
