// 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 static org.junit.Assert.assertEquals;

import protobuf_unittest.UnittestProto;
import proto3_unittest.UnittestProto3;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for discard or preserve unknown fields. */
@RunWith(JUnit4.class)
public class DiscardUnknownFieldsTest {
  @Test
  public void testProto2() throws Exception {
    testProto2Message(
          UnittestProto.TestEmptyMessage.getDefaultInstance());
    testProto2Message(
          UnittestProto.TestEmptyMessageWithExtensions.getDefaultInstance());
    testProto2Message(
          DynamicMessage.getDefaultInstance(UnittestProto.TestEmptyMessage.getDescriptor()));
    testProto2Message(
          DynamicMessage.getDefaultInstance(
              UnittestProto.TestEmptyMessageWithExtensions.getDescriptor()));
  }

  @Test
  public void testProto3() throws Exception {
    testProto3Message(UnittestProto3.TestEmptyMessage.getDefaultInstance());
    testProto3Message(
        DynamicMessage.getDefaultInstance(UnittestProto3.TestEmptyMessage.getDescriptor()));
  }

  private static void testProto2Message(Message message) throws Exception {
    assertUnknownFieldsDefaultPreserved(message);
    assertUnknownFieldsExplicitlyDiscarded(message);
    assertReuseCodedInputStreamPreserve(message);
    assertUnknownFieldsInUnknownFieldSetArePreserve(message);
  }

  private static void testProto3Message(Message message) throws Exception {
    CodedInputStream.setProto3KeepUnknownsByDefaultForTest();
    assertUnknownFieldsDefaultPreserved(message);
    assertUnknownFieldsExplicitlyDiscarded(message);
    assertReuseCodedInputStreamPreserve(message);
    assertUnknownFieldsInUnknownFieldSetArePreserve(message);
    CodedInputStream.setProto3DiscardUnknownsByDefaultForTest();
    assertUnknownFieldsDefaultDiscarded(message);
    assertUnknownFieldsExplicitlyDiscarded(message);
    assertUnknownFieldsInUnknownFieldSetAreDiscarded(message);
  }

  private static void assertReuseCodedInputStreamPreserve(Message message) throws Exception {
    final int messageSize = payload.size();
    byte[] copied = new byte[messageSize * 2];
    payload.copyTo(copied, 0);
    payload.copyTo(copied, messageSize);
    CodedInputStream input = CodedInputStream.newInstance(copied);
    {
      // Use DiscardUnknownFieldsParser to parse the first payload.
      int oldLimit = input.pushLimit(messageSize);
      Message parsed = DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(input);
      assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
      input.popLimit(oldLimit);
    }
    {
      // Use the normal parser to parse the remaining payload should have unknown fields preserved.
      Message parsed = message.getParserForType().parseFrom(input);
      assertEquals(message.getClass().getName(), payload, parsed.toByteString());
    }
  }

  /**
   * {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link
   * Message.Builder#mergeUnknownFields(UnknownFieldSet)} should preserve the unknown fields.
   */
  private static void assertUnknownFieldsInUnknownFieldSetArePreserve(Message message)
      throws Exception {
    UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build();
    Message built = message.newBuilderForType().setUnknownFields(unknownFields).build();
    assertEquals(message.getClass().getName(), payload, built.toByteString());

  }
  /**
   * {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link
   * Message.Builder#mergeUnknownFields(UnknownFieldSet)} should discard the unknown fields.
   */
  private static void assertUnknownFieldsInUnknownFieldSetAreDiscarded(Message message)
      throws Exception {
    UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build();
    Message built = message.newBuilderForType().setUnknownFields(unknownFields).build();
    assertEquals(message.getClass().getName(), 0, built.getSerializedSize());
  }

  private static void assertUnknownFieldsDefaultPreserved(MessageLite message) throws Exception {
    {
      MessageLite parsed = message.getParserForType().parseFrom(payload);
      assertEquals(message.getClass().getName(), payload, parsed.toByteString());
    }

    {
      MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
      assertEquals(message.getClass().getName(), payload, parsed.toByteString());
    }
  }

  private static void assertUnknownFieldsDefaultDiscarded(MessageLite message) throws Exception {
    {
      MessageLite parsed = message.getParserForType().parseFrom(payload);
      assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
    }

    {
      MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
      assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
    }
  }

  private static void assertUnknownFieldsExplicitlyDiscarded(Message message) throws Exception {
    Message parsed =
        DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(payload);
    assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
  }

  private static final ByteString payload =
      TestUtilLite.getAllLiteSetBuilder().build().toByteString();
}
