// 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 junit.framework.TestCase.assertEquals;

import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestAllTypesLite;
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.TestPackedExtensions;
import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import junit.framework.TestCase;

/**
 * Tests for {@link UnknownFieldSetLite}.
 *
 * @author dweis@google.com (Daniel Weis)
 */
public class UnknownFieldSetLiteTest extends TestCase {
  @Override
  public void setUp() throws Exception {
    allFields = TestUtil.getAllSet();
    allFieldsData = allFields.toByteString();
    emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
    unknownFields = emptyMessage.getUnknownFields();
  }

  TestAllTypes allFields;
  ByteString allFieldsData;

  // Constructs a protocol buffer which contains fields with all the same
  // numbers as allFieldsData except that each field is some other wire
  // type.
  private 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();
  }

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

  public void testDefaultInstance() {
    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();

    assertEquals(0, unknownFields.getSerializedSize());
    assertEquals(ByteString.EMPTY, toByteString(unknownFields));
  }

  public void testEmptyInstance() {
    UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();

    assertEquals(0, instance.getSerializedSize());
    assertEquals(ByteString.EMPTY, toByteString(instance));
    assertEquals(UnknownFieldSetLite.getDefaultInstance(), instance);
  }

  public void testMergeFieldFrom() throws IOException {
    Foo foo = Foo.newBuilder()
      .setValue(2)
      .build();

    CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());

    UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
    instance.mergeFieldFrom(input.readTag(), input);

    assertEquals(foo.toByteString(), toByteString(instance));
  }

  public void testSerializedSize() throws IOException {
    Foo foo = Foo.newBuilder()
      .setValue(2)
      .build();

    CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());

    UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
    instance.mergeFieldFrom(input.readTag(), input);

    assertEquals(foo.toByteString().size(), instance.getSerializedSize());
  }

  public void testHashCodeAfterDeserialization() throws IOException {
    Foo foo = Foo.newBuilder()
      .setValue(2)
      .build();

    Foo fooDeserialized = Foo.parseFrom(foo.toByteArray());

    assertEquals(fooDeserialized, foo);
    assertEquals(foo.hashCode(), fooDeserialized.hashCode());
  }

  public void testNewInstanceHashCode() {
    UnknownFieldSetLite emptyFieldSet = UnknownFieldSetLite.getDefaultInstance();
    UnknownFieldSetLite paddedFieldSet = UnknownFieldSetLite.newInstance();

    assertEquals(emptyFieldSet, paddedFieldSet);
    assertEquals(emptyFieldSet.hashCode(), paddedFieldSet.hashCode());
  }

  public void testMergeVarintField() throws IOException {
    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
    unknownFields.mergeVarintField(10, 2);

    CodedInputStream input =
        CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());

    int tag = input.readTag();
    assertEquals(10, WireFormat.getTagFieldNumber(tag));
    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
    assertEquals(2, input.readUInt64());
    assertTrue(input.isAtEnd());
  }

  public void testMergeVarintField_negative() throws IOException {
    UnknownFieldSetLite builder = UnknownFieldSetLite.newInstance();
    builder.mergeVarintField(10, -6);

    CodedInputStream input =
        CodedInputStream.newInstance(toByteString(builder).toByteArray());

    int tag = input.readTag();
    assertEquals(10, WireFormat.getTagFieldNumber(tag));
    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
    assertEquals(-6, input.readUInt64());
    assertTrue(input.isAtEnd());
  }

  public void testEqualsAndHashCode() {
    UnknownFieldSetLite unknownFields1 = UnknownFieldSetLite.newInstance();
    unknownFields1.mergeVarintField(10, 2);

    UnknownFieldSetLite unknownFields2 = UnknownFieldSetLite.newInstance();
    unknownFields2.mergeVarintField(10, 2);

    assertEquals(unknownFields1, unknownFields2);
    assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode());
    assertFalse(unknownFields1.equals(UnknownFieldSetLite.getDefaultInstance()));
    assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode());
  }

  public void testMutableCopyOf() throws IOException {
    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
    unknownFields.mergeVarintField(10, 2);
    unknownFields = UnknownFieldSetLite.mutableCopyOf(unknownFields, unknownFields);
    unknownFields.checkMutable();

    CodedInputStream input =
        CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());

    int tag = input.readTag();
    assertEquals(10, WireFormat.getTagFieldNumber(tag));
    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
    assertEquals(2, input.readUInt64());
    assertFalse(input.isAtEnd());
    input.readTag();
    assertEquals(10, WireFormat.getTagFieldNumber(tag));
    assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
    assertEquals(2, input.readUInt64());
    assertTrue(input.isAtEnd());
  }

  public void testMutableCopyOf_empty() {
    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.mutableCopyOf(
        UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance());
    unknownFields.checkMutable();

    assertEquals(0, unknownFields.getSerializedSize());
    assertEquals(ByteString.EMPTY, toByteString(unknownFields));
  }

  public void testRoundTrips() throws InvalidProtocolBufferException {
    Foo foo = Foo.newBuilder()
        .setValue(1)
        .setExtension(Bar.fooExt, Bar.newBuilder()
            .setName("name")
            .build())
        .setExtension(LiteEqualsAndHash.varint, 22)
        .setExtension(LiteEqualsAndHash.fixed32, 44)
        .setExtension(LiteEqualsAndHash.fixed64, 66L)
        .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
            .setGroupValue("value")
            .build())
        .build();

    Foo copy = Foo.parseFrom(foo.toByteArray());

    assertEquals(foo.getSerializedSize(), copy.getSerializedSize());
    assertFalse(foo.equals(copy));

    Foo secondCopy = Foo.parseFrom(foo.toByteArray());
    assertEquals(copy, secondCopy);

    ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
    LiteEqualsAndHash.registerAllExtensions(extensionRegistry);
    Foo copyOfCopy = Foo.parseFrom(copy.toByteArray(), extensionRegistry);

    assertEquals(foo, copyOfCopy);
  }

  public void testMalformedBytes() throws Exception {
    try {
      Foo.parseFrom("this is a malformed protocol buffer".getBytes(Internal.UTF_8));
      fail();
    } catch (InvalidProtocolBufferException e) {
      // Expected.
    }
  }

  public void testMissingStartGroupTag() throws IOException {
    ByteString.Output byteStringOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
    output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
    output.writeTag(100, WireFormat.WIRETYPE_END_GROUP);
    output.flush();

    try {
      Foo.parseFrom(byteStringOutput.toByteString());
      fail();
    } catch (InvalidProtocolBufferException e) {
      // Expected.
    }
  }

  public void testMissingEndGroupTag() throws IOException {
    ByteString.Output byteStringOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
    output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
    output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
    output.flush();

    try {
      Foo.parseFrom(byteStringOutput.toByteString());
      fail();
    } catch (InvalidProtocolBufferException e) {
      // Expected.
    }
  }

  public void testMismatchingGroupTags() throws IOException {
    ByteString.Output byteStringOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
    output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
    output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
    output.writeTag(101, WireFormat.WIRETYPE_END_GROUP);
    output.flush();

    try {
      Foo.parseFrom(byteStringOutput.toByteString());
      fail();
    } catch (InvalidProtocolBufferException e) {
      // Expected.
    }
  }

  public void testTruncatedInput() {
    Foo foo = Foo.newBuilder()
        .setValue(1)
        .setExtension(Bar.fooExt, Bar.newBuilder()
            .setName("name")
            .build())
        .setExtension(LiteEqualsAndHash.varint, 22)
        .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
            .setGroupValue("value")
            .build())
        .build();

    try {
      Foo.parseFrom(foo.toByteString().substring(0, foo.toByteString().size() - 10));
      fail();
    } catch (InvalidProtocolBufferException e) {
      // Expected.
    }
  }
  
  public void testMakeImmutable() throws Exception {
    UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
    unknownFields.makeImmutable();
    
    try {
      unknownFields.mergeVarintField(1, 1);
      fail();
    } catch (UnsupportedOperationException expected) {}
    
    try {
      unknownFields.mergeLengthDelimitedField(2, ByteString.copyFromUtf8("hello"));
      fail();
    } catch (UnsupportedOperationException expected) {}
    
    try {
      unknownFields.mergeFieldFrom(1, CodedInputStream.newInstance(new byte[0]));
      fail();
    } catch (UnsupportedOperationException expected) {}
  }
  
  public void testEndToEnd() throws Exception {
    TestAllTypesLite testAllTypes = TestAllTypesLite.getDefaultInstance();
    try {
      testAllTypes.unknownFields.checkMutable();
      fail();
    } catch (UnsupportedOperationException expected) {}
    
    testAllTypes = TestAllTypesLite.parseFrom(new byte[0]);
    try {
      testAllTypes.unknownFields.checkMutable();
      fail();
    } catch (UnsupportedOperationException expected) {}
    
    testAllTypes = TestAllTypesLite.newBuilder().build();
    try {
      testAllTypes.unknownFields.checkMutable();
      fail();
    } catch (UnsupportedOperationException expected) {}
    
    testAllTypes = TestAllTypesLite.newBuilder()
        .setDefaultBool(true)
        .build();
    try {
      testAllTypes.unknownFields.checkMutable();
      fail();
    } catch (UnsupportedOperationException expected) {}
    
    TestAllExtensionsLite testAllExtensions = TestAllExtensionsLite.newBuilder()
        .mergeFrom(TestAllExtensionsLite.newBuilder()
            .setExtension(UnittestLite.optionalInt32ExtensionLite, 2)
            .build().toByteArray())
        .build();
    try {
      testAllExtensions.unknownFields.checkMutable();
      fail();
    } catch (UnsupportedOperationException expected) {}
  }

  private ByteString toByteString(UnknownFieldSetLite unknownFields) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
    try {
      unknownFields.writeTo(output);
      output.flush();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return ByteString.copyFrom(byteArrayOutputStream.toByteArray());
  }

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