// 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.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestEmptyMessage;
import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
import protobuf_unittest.UnittestProto.TestPackedExtensions;
import protobuf_unittest.UnittestProto.TestPackedTypes;

import junit.framework.TestCase;

import java.util.Arrays;
import java.util.Map;

/**
 * Tests related to unknown field handling.
 *
 * @author kenton@google.com (Kenton Varda)
 */
public class UnknownFieldSetTest extends TestCase {
  @Override
  public void setUp() throws Exception {
    descriptor = TestAllTypes.getDescriptor();
    allFields = TestUtil.getAllSet();
    allFieldsData = allFields.toByteString();
    emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
    unknownFields = emptyMessage.getUnknownFields();
  }

  UnknownFieldSet.Field getField(String name) {
    Descriptors.FieldDescriptor field = descriptor.findFieldByName(name);
    assertNotNull(field);
    return unknownFields.getField(field.getNumber());
  }

  // Constructs a protocol buffer which contains fields with all the same
  // numbers as allFieldsData except that each field is some other wire
  // type.
  ByteString getBizarroData() throws Exception {
    UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder();

    UnknownFieldSet.Field varintField =
      UnknownFieldSet.Field.newBuilder().addVarint(1).build();
    UnknownFieldSet.Field fixed32Field =
      UnknownFieldSet.Field.newBuilder().addFixed32(1).build();

    for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
         unknownFields.asMap().entrySet()) {
      if (entry.getValue().getVarintList().isEmpty()) {
        // Original field is not a varint, so use a varint.
        bizarroFields.addField(entry.getKey(), varintField);
      } else {
        // Original field *is* a varint, so use something else.
        bizarroFields.addField(entry.getKey(), fixed32Field);
      }
    }

    return bizarroFields.build().toByteString();
  }

  Descriptors.Descriptor descriptor;
  TestAllTypes allFields;
  ByteString allFieldsData;

  // An empty message that has been parsed from allFieldsData.  So, it has
  // unknown fields of every type.
  TestEmptyMessage emptyMessage;
  UnknownFieldSet unknownFields;

  // =================================================================

  public void testVarint() throws Exception {
    UnknownFieldSet.Field field = getField("optional_int32");
    assertEquals(1, field.getVarintList().size());
    assertEquals(allFields.getOptionalInt32(),
                 (long) field.getVarintList().get(0));
  }

  public void testFixed32() throws Exception {
    UnknownFieldSet.Field field = getField("optional_fixed32");
    assertEquals(1, field.getFixed32List().size());
    assertEquals(allFields.getOptionalFixed32(),
                 (int) field.getFixed32List().get(0));
  }

  public void testFixed64() throws Exception {
    UnknownFieldSet.Field field = getField("optional_fixed64");
    assertEquals(1, field.getFixed64List().size());
    assertEquals(allFields.getOptionalFixed64(),
                 (long) field.getFixed64List().get(0));
  }

  public void testLengthDelimited() throws Exception {
    UnknownFieldSet.Field field = getField("optional_bytes");
    assertEquals(1, field.getLengthDelimitedList().size());
    assertEquals(allFields.getOptionalBytes(),
                 field.getLengthDelimitedList().get(0));
  }

  public void testGroup() throws Exception {
    Descriptors.FieldDescriptor nestedFieldDescriptor =
      TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a");
    assertNotNull(nestedFieldDescriptor);

    UnknownFieldSet.Field field = getField("optionalgroup");
    assertEquals(1, field.getGroupList().size());

    UnknownFieldSet group = field.getGroupList().get(0);
    assertEquals(1, group.asMap().size());
    assertTrue(group.hasField(nestedFieldDescriptor.getNumber()));

    UnknownFieldSet.Field nestedField =
      group.getField(nestedFieldDescriptor.getNumber());
    assertEquals(1, nestedField.getVarintList().size());
    assertEquals(allFields.getOptionalGroup().getA(),
                 (long) nestedField.getVarintList().get(0));
  }

  public void testSerialize() throws Exception {
    // Check that serializing the UnknownFieldSet produces the original data
    // again.
    ByteString data = emptyMessage.toByteString();
    assertEquals(allFieldsData, data);
  }

  public void testCopyFrom() throws Exception {
    TestEmptyMessage message =
      TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build();

    assertEquals(emptyMessage.toString(), message.toString());
  }

  public void testMergeFrom() throws Exception {
    TestEmptyMessage source =
      TestEmptyMessage.newBuilder()
        .setUnknownFields(
          UnknownFieldSet.newBuilder()
            .addField(2,
              UnknownFieldSet.Field.newBuilder()
                .addVarint(2).build())
            .addField(3,
              UnknownFieldSet.Field.newBuilder()
                .addVarint(4).build())
            .build())
        .build();
    TestEmptyMessage destination =
      TestEmptyMessage.newBuilder()
        .setUnknownFields(
          UnknownFieldSet.newBuilder()
            .addField(1,
              UnknownFieldSet.Field.newBuilder()
                .addVarint(1).build())
            .addField(3,
              UnknownFieldSet.Field.newBuilder()
                .addVarint(3).build())
            .build())
        .mergeFrom(source)
        .build();

    assertEquals(
      "1: 1\n" +
      "2: 2\n" +
      "3: 3\n" +
      "3: 4\n",
      destination.toString());
  }

  public void testClear() throws Exception {
    UnknownFieldSet fields =
      UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build();
    assertTrue(fields.asMap().isEmpty());
  }

  public void testClearMessage() throws Exception {
    TestEmptyMessage message =
      TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build();
    assertEquals(0, message.getSerializedSize());
  }
  
  public void testClearField() throws Exception {
    int fieldNumber = unknownFields.asMap().keySet().iterator().next();
    UnknownFieldSet fields =
        UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clearField(fieldNumber).build();
    assertFalse(fields.hasField(fieldNumber));
  }

  public void testParseKnownAndUnknown() throws Exception {
    // Test mixing known and unknown fields when parsing.

    UnknownFieldSet fields =
      UnknownFieldSet.newBuilder(unknownFields)
        .addField(123456,
          UnknownFieldSet.Field.newBuilder().addVarint(654321).build())
        .build();

    ByteString data = fields.toByteString();
    TestAllTypes destination = TestAllTypes.parseFrom(data);

    TestUtil.assertAllFieldsSet(destination);
    assertEquals(1, destination.getUnknownFields().asMap().size());

    UnknownFieldSet.Field field =
      destination.getUnknownFields().getField(123456);
    assertEquals(1, field.getVarintList().size());
    assertEquals(654321, (long) field.getVarintList().get(0));
  }

  public void testWrongTypeTreatedAsUnknown() throws Exception {
    // Test that fields of the wrong wire type are treated like unknown fields
    // when parsing.

    ByteString bizarroData = getBizarroData();
    TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
    TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);

    // All fields should have been interpreted as unknown, so the debug strings
    // should be the same.
    assertEquals(emptyMessage.toString(), allTypesMessage.toString());
  }

  public void testUnknownExtensions() throws Exception {
    // Make sure fields are properly parsed to the UnknownFieldSet even when
    // they are declared as extension numbers.

    TestEmptyMessageWithExtensions message =
      TestEmptyMessageWithExtensions.parseFrom(allFieldsData);

    assertEquals(unknownFields.asMap().size(),
                 message.getUnknownFields().asMap().size());
    assertEquals(allFieldsData, message.toByteString());
  }

  public void testWrongExtensionTypeTreatedAsUnknown() throws Exception {
    // Test that fields of the wrong wire type are treated like unknown fields
    // when parsing extensions.

    ByteString bizarroData = getBizarroData();
    TestAllExtensions allExtensionsMessage =
      TestAllExtensions.parseFrom(bizarroData);
    TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);

    // All fields should have been interpreted as unknown, so the debug strings
    // should be the same.
    assertEquals(emptyMessage.toString(),
                 allExtensionsMessage.toString());
  }

  public void testParseUnknownEnumValue() throws Exception {
    Descriptors.FieldDescriptor singularField =
      TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
    Descriptors.FieldDescriptor repeatedField =
      TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
    assertNotNull(singularField);
    assertNotNull(repeatedField);

    ByteString data =
      UnknownFieldSet.newBuilder()
        .addField(singularField.getNumber(),
          UnknownFieldSet.Field.newBuilder()
            .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
            .addVarint(5)   // not valid
            .build())
        .addField(repeatedField.getNumber(),
          UnknownFieldSet.Field.newBuilder()
            .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
            .addVarint(4)   // not valid
            .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
            .addVarint(6)   // not valid
            .build())
        .build()
        .toByteString();

    {
      TestAllTypes message = TestAllTypes.parseFrom(data);
      assertEquals(TestAllTypes.NestedEnum.BAR,
                   message.getOptionalNestedEnum());
      assertEquals(
        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
        message.getRepeatedNestedEnumList());
      assertEquals(Arrays.asList(5L),
                   message.getUnknownFields()
                          .getField(singularField.getNumber())
                          .getVarintList());
      assertEquals(Arrays.asList(4L, 6L),
                   message.getUnknownFields()
                          .getField(repeatedField.getNumber())
                          .getVarintList());
    }

    {
      TestAllExtensions message =
        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
      assertEquals(TestAllTypes.NestedEnum.BAR,
        message.getExtension(UnittestProto.optionalNestedEnumExtension));
      assertEquals(
        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
        message.getExtension(UnittestProto.repeatedNestedEnumExtension));
      assertEquals(Arrays.asList(5L),
                   message.getUnknownFields()
                          .getField(singularField.getNumber())
                          .getVarintList());
      assertEquals(Arrays.asList(4L, 6L),
                   message.getUnknownFields()
                          .getField(repeatedField.getNumber())
                          .getVarintList());
    }
  }

  public void testLargeVarint() throws Exception {
    ByteString data =
      UnknownFieldSet.newBuilder()
        .addField(1,
          UnknownFieldSet.Field.newBuilder()
            .addVarint(0x7FFFFFFFFFFFFFFFL)
            .build())
        .build()
        .toByteString();
    UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data);
    UnknownFieldSet.Field field = parsed.getField(1);
    assertEquals(1, field.getVarintList().size());
    assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
  }

  public void testEqualsAndHashCode() {
    UnknownFieldSet.Field fixed32Field =
        UnknownFieldSet.Field.newBuilder()
            .addFixed32(1)
            .build();
    UnknownFieldSet.Field fixed64Field =
        UnknownFieldSet.Field.newBuilder()
            .addFixed64(1)
            .build();
    UnknownFieldSet.Field varIntField =
        UnknownFieldSet.Field.newBuilder()
            .addVarint(1)
            .build();
    UnknownFieldSet.Field lengthDelimitedField =
        UnknownFieldSet.Field.newBuilder()
            .addLengthDelimited(ByteString.EMPTY)
            .build();
    UnknownFieldSet.Field groupField =
        UnknownFieldSet.Field.newBuilder()
            .addGroup(unknownFields)
            .build();

    UnknownFieldSet a =
        UnknownFieldSet.newBuilder()
            .addField(1, fixed32Field)
            .build();
    UnknownFieldSet b =
        UnknownFieldSet.newBuilder()
            .addField(1, fixed64Field)
            .build();
    UnknownFieldSet c =
        UnknownFieldSet.newBuilder()
            .addField(1, varIntField)
            .build();
    UnknownFieldSet d =
        UnknownFieldSet.newBuilder()
            .addField(1, lengthDelimitedField)
            .build();
    UnknownFieldSet e =
        UnknownFieldSet.newBuilder()
            .addField(1, groupField)
            .build();

    checkEqualsIsConsistent(a);
    checkEqualsIsConsistent(b);
    checkEqualsIsConsistent(c);
    checkEqualsIsConsistent(d);
    checkEqualsIsConsistent(e);

    checkNotEqual(a, b);
    checkNotEqual(a, c);
    checkNotEqual(a, d);
    checkNotEqual(a, e);
    checkNotEqual(b, c);
    checkNotEqual(b, d);
    checkNotEqual(b, e);
    checkNotEqual(c, d);
    checkNotEqual(c, e);
    checkNotEqual(d, e);
  }

  /**
   * Asserts that the given field sets are not equal and have different
   * hash codes.
   *
   * @warning It's valid for non-equal objects to have the same hash code, so
   *   this test is stricter than it needs to be. However, this should happen
   *   relatively rarely.
   */
  private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
    String equalsError = String.format("%s should not be equal to %s", s1, s2);
    assertFalse(equalsError, s1.equals(s2));
    assertFalse(equalsError, s2.equals(s1));

    assertFalse(
        String.format("%s should have a different hash code from %s", s1, s2),
        s1.hashCode() == s2.hashCode());
  }

  /**
   * Asserts that the given field sets are equal and have identical hash codes.
   */
  private void checkEqualsIsConsistent(UnknownFieldSet set) {
    // Object should be equal to itself.
    assertEquals(set, set);

    // Object should be equal to a copy of itself.
    UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
    assertEquals(set, copy);
    assertEquals(copy, set);
    assertEquals(set.hashCode(), copy.hashCode());
  }

  // =================================================================

  public void testSerializeLite() throws Exception {
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
    assertEquals(allFieldsData.size(), emptyMessageLite.getSerializedSize());
    ByteString data = emptyMessageLite.toByteString();
    TestAllTypes message = TestAllTypes.parseFrom(data);
    TestUtil.assertAllFieldsSet(message);
    assertEquals(allFieldsData, data);
  }

  public void testAllExtensionsLite() throws Exception {
    TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet();
    ByteString allExtensionsData = allExtensions.toByteString();
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData);
    ByteString data = emptyMessageLite.toByteString();
    TestAllExtensions message =
        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
    TestUtil.assertAllExtensionsSet(message);
    assertEquals(allExtensionsData, data);
  }

  public void testAllPackedFieldsLite() throws Exception {
    TestPackedTypes allPackedFields = TestUtil.getPackedSet();
    ByteString allPackedData = allPackedFields.toByteString();
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(allPackedData);
    ByteString data = emptyMessageLite.toByteString();
    TestPackedTypes message =
        TestPackedTypes.parseFrom(data, TestUtil.getExtensionRegistry());
    TestUtil.assertPackedFieldsSet(message);
    assertEquals(allPackedData, data);
  }

  public void testAllPackedExtensionsLite() throws Exception {
    TestPackedExtensions allPackedExtensions = TestUtil.getPackedExtensionsSet();
    ByteString allPackedExtensionsData = allPackedExtensions.toByteString();
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(allPackedExtensionsData);
    ByteString data = emptyMessageLite.toByteString();
    TestPackedExtensions message =
        TestPackedExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
    TestUtil.assertPackedExtensionsSet(message);
    assertEquals(allPackedExtensionsData, data);
  }

  public void testCopyFromLite() throws Exception {
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
    UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
        UnittestLite.TestEmptyMessageLite.newBuilder()
        .mergeFrom(emptyMessageLite).build();
    assertEquals(emptyMessageLite.toByteString(), emptyMessageLite2.toByteString());
  }

  public void testMergeFromLite() throws Exception {
    TestAllTypes message1 = TestAllTypes.newBuilder()
        .setOptionalInt32(1)
        .setOptionalString("foo")
        .addRepeatedString("bar")
        .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ)
        .build();

    TestAllTypes message2 = TestAllTypes.newBuilder()
        .setOptionalInt64(2)
        .setOptionalString("baz")
        .addRepeatedString("qux")
        .setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ)
        .build();

    ByteString data1 = message1.toByteString();
    UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
        UnittestLite.TestEmptyMessageLite.parseFrom(data1);
    ByteString data2 = message2.toByteString();
    UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
        UnittestLite.TestEmptyMessageLite.parseFrom(data2);

    message1 = TestAllTypes.newBuilder(message1).mergeFrom(message2).build();
    emptyMessageLite1 = UnittestLite.TestEmptyMessageLite.newBuilder(emptyMessageLite1)
                        .mergeFrom(emptyMessageLite2).build();

    data1 = emptyMessageLite1.toByteString();
    message2 = TestAllTypes.parseFrom(data1);

    assertEquals(message1, message2);
  }

  public void testWrongTypeTreatedAsUnknownLite() throws Exception {
    // Test that fields of the wrong wire type are treated like unknown fields
    // when parsing.

    ByteString bizarroData = getBizarroData();
    TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
    ByteString data = emptyMessageLite.toByteString();
    TestAllTypes allTypesMessage2 = TestAllTypes.parseFrom(data);

    assertEquals(allTypesMessage.toString(), allTypesMessage2.toString());
  }

  public void testUnknownExtensionsLite() throws Exception {
    // Make sure fields are properly parsed to the UnknownFieldSet even when
    // they are declared as extension numbers.

    UnittestLite.TestEmptyMessageWithExtensionsLite message =
      UnittestLite.TestEmptyMessageWithExtensionsLite.parseFrom(allFieldsData);

    assertEquals(allFieldsData, message.toByteString());
  }

  public void testWrongExtensionTypeTreatedAsUnknownLite() throws Exception {
    // Test that fields of the wrong wire type are treated like unknown fields
    // when parsing extensions.

    ByteString bizarroData = getBizarroData();
    TestAllExtensions allExtensionsMessage =
      TestAllExtensions.parseFrom(bizarroData);
    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);

    // All fields should have been interpreted as unknown, so the byte strings
    // should be the same.
    assertEquals(emptyMessageLite.toByteString(),
                 allExtensionsMessage.toByteString());
  }

  public void testParseUnknownEnumValueLite() throws Exception {
    Descriptors.FieldDescriptor singularField =
      TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
    Descriptors.FieldDescriptor repeatedField =
      TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
    assertNotNull(singularField);
    assertNotNull(repeatedField);

    ByteString data =
      UnknownFieldSet.newBuilder()
        .addField(singularField.getNumber(),
          UnknownFieldSet.Field.newBuilder()
            .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
            .addVarint(5)   // not valid
            .build())
        .addField(repeatedField.getNumber(),
          UnknownFieldSet.Field.newBuilder()
            .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
            .addVarint(4)   // not valid
            .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
            .addVarint(6)   // not valid
            .build())
        .build()
        .toByteString();

    UnittestLite.TestEmptyMessageLite emptyMessageLite =
        UnittestLite.TestEmptyMessageLite.parseFrom(data);
    data = emptyMessageLite.toByteString();

    {
      TestAllTypes message = TestAllTypes.parseFrom(data);
      assertEquals(TestAllTypes.NestedEnum.BAR,
                   message.getOptionalNestedEnum());
      assertEquals(
        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
        message.getRepeatedNestedEnumList());
      assertEquals(Arrays.asList(5L),
                   message.getUnknownFields()
                          .getField(singularField.getNumber())
                          .getVarintList());
      assertEquals(Arrays.asList(4L, 6L),
                   message.getUnknownFields()
                          .getField(repeatedField.getNumber())
                          .getVarintList());
    }

    {
      TestAllExtensions message =
        TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
      assertEquals(TestAllTypes.NestedEnum.BAR,
        message.getExtension(UnittestProto.optionalNestedEnumExtension));
      assertEquals(
        Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
        message.getExtension(UnittestProto.repeatedNestedEnumExtension));
      assertEquals(Arrays.asList(5L),
                   message.getUnknownFields()
                          .getField(singularField.getNumber())
                          .getVarintList());
      assertEquals(Arrays.asList(4L, 6L),
                   message.getUnknownFields()
                          .getField(repeatedField.getNumber())
                          .getVarintList());
    }
  }

  public void testClearLite() throws Exception {
    UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
        UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
    UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
        UnittestLite.TestEmptyMessageLite.newBuilder()
        .mergeFrom(emptyMessageLite1).clear().build();
    assertEquals(0, emptyMessageLite2.getSerializedSize());
    ByteString data = emptyMessageLite2.toByteString();
    assertEquals(0, data.size());
  }

}
