// 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 com.google.protobuf.UnittestLite.TestAllTypesLite;
import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
import com.google.protobuf.UnittestLite.TestParsingMergeLite;
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.TestParsingMerge;
import protobuf_unittest.UnittestProto.TestRequired;
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));
  }

  @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)));
  }

  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());
    assertRoundTripEquals(TestUtil.getAllLiteExtensionsSet(),
                          TestUtil.getExtensionRegistryLite());
  }

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

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

    // Write MessageLite with packed extension fields.
    TestPackedExtensionsLite packedMessage =
        TestUtil.getLitePackedExtensionsSet();
    packedMessage.writeDelimitedTo(output);

    InputStream input = new ByteArrayInputStream(output.toByteArray());
    assertMessageEquals(
        normalMessage,
        normalMessage.getParserForType().parseDelimitedFrom(input));
    assertMessageEquals(
        packedMessage,
        packedMessage.getParserForType().parseDelimitedFrom(
            input, TestUtil.getExtensionRegistryLite()));
  }

  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());
  }

  /** Helper method for {@link #testParsingMergeLite()}.*/
  private void assertMessageMerged(TestAllTypesLite 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 testParsingMergeLite() throws Exception {
    // Build messages.
    TestAllTypesLite.Builder builder =
        TestAllTypesLite.newBuilder();
    TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
    builder.clear();
    TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
    builder.clear();
    TestAllTypesLite msg3 = builder.setOptionalInt32(3)
        .setOptionalString("hello").build();

    // Build groups.
    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
        .setField1(msg1).build();
    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
        .setField1(msg2).build();
    TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
        TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
        .setField1(msg3).build();
    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
        .setField1(msg1).build();
    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
        .setField1(msg2).build();
    TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
        TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
        .setField1(msg3).build();

    // Assign and serialize RepeatedFieldsGenerator.
    ByteString data = TestParsingMergeLite.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 TestParsingMergeLite.
    ExtensionRegistry registry = ExtensionRegistry.newInstance();
    UnittestLite.registerAllExtensions(registry);
    TestParsingMergeLite parsingMerge =
        TestParsingMergeLite.PARSER.parseFrom(data, registry);

    // Required and optional fields should be merged.
    assertMessageMerged(parsingMerge.getRequiredAllTypes());
    assertMessageMerged(parsingMerge.getOptionalAllTypes());
    assertMessageMerged(
        parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
    assertMessageMerged(parsingMerge.getExtension(
        TestParsingMergeLite.optionalExt));

    // Repeated fields should not be merged.
    assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
    assertEquals(3, parsingMerge.getRepeatedGroupCount());
    assertEquals(3, parsingMerge.getExtensionCount(
        TestParsingMergeLite.repeatedExt));
  }
}
