// 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.NestedExtension;
import protobuf_unittest.NonNestedExtension;
import com.google.protobuf.DescriptorProtos.DescriptorProto;
import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.google.protobuf.Descriptors.EnumDescriptor;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.MethodDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Descriptors.ServiceDescriptor;
import com.google.protobuf.test.UnittestImport;
import com.google.protobuf.test.UnittestImport.ImportEnum;
import com.google.protobuf.test.UnittestImport.ImportEnumForMap;
import protobuf_unittest.TestCustomOptions;
import protobuf_unittest.UnittestCustomOptions;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
import protobuf_unittest.UnittestProto.TestJsonName;
import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestReservedFields;
import protobuf_unittest.UnittestProto.TestService;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;

/**
 * Unit test for {@link Descriptors}.
 *
 * @author kenton@google.com Kenton Varda
 */
public class DescriptorsTest extends TestCase {

  // Regression test for bug where referencing a FieldDescriptor.Type value
  // before a FieldDescriptorProto.Type value would yield a
  // ExceptionInInitializerError.
  @SuppressWarnings("unused")
  private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;

  public void testFieldTypeEnumMapping() throws Exception {
    assertEquals(FieldDescriptor.Type.values().length, FieldDescriptorProto.Type.values().length);
    for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
      FieldDescriptorProto.Type protoType = type.toProto();
      assertEquals("TYPE_" + type.name(), protoType.name());
      assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
    }
  }

  public void testFileDescriptor() throws Exception {
    FileDescriptor file = UnittestProto.getDescriptor();

    assertEquals("google/protobuf/unittest.proto", file.getName());
    assertEquals("protobuf_unittest", file.getPackage());

    assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
    assertEquals("google/protobuf/unittest.proto", file.toProto().getName());

    assertEquals(Arrays.asList(UnittestImport.getDescriptor()), file.getDependencies());

    Descriptor messageType = TestAllTypes.getDescriptor();
    assertEquals(messageType, file.getMessageTypes().get(0));
    assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
    assertNull(file.findMessageTypeByName("NoSuchType"));
    assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
    for (int i = 0; i < file.getMessageTypes().size(); i++) {
      assertEquals(i, file.getMessageTypes().get(i).getIndex());
    }

    EnumDescriptor enumType = ForeignEnum.getDescriptor();
    assertEquals(enumType, file.getEnumTypes().get(0));
    assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
    assertNull(file.findEnumTypeByName("NoSuchType"));
    assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
    assertEquals(
        Arrays.asList(ImportEnum.getDescriptor(), ImportEnumForMap.getDescriptor()),
        UnittestImport.getDescriptor().getEnumTypes());
    for (int i = 0; i < file.getEnumTypes().size(); i++) {
      assertEquals(i, file.getEnumTypes().get(i).getIndex());
    }

    ServiceDescriptor service = TestService.getDescriptor();
    assertEquals(service, file.getServices().get(0));
    assertEquals(service, file.findServiceByName("TestService"));
    assertNull(file.findServiceByName("NoSuchType"));
    assertNull(file.findServiceByName("protobuf_unittest.TestService"));
    assertEquals(Collections.emptyList(), UnittestImport.getDescriptor().getServices());
    for (int i = 0; i < file.getServices().size(); i++) {
      assertEquals(i, file.getServices().get(i).getIndex());
    }

    FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor();
    assertEquals(extension, file.getExtensions().get(0));
    assertEquals(extension, file.findExtensionByName("optional_int32_extension"));
    assertNull(file.findExtensionByName("no_such_ext"));
    assertNull(file.findExtensionByName("protobuf_unittest.optional_int32_extension"));
    assertEquals(Collections.emptyList(), UnittestImport.getDescriptor().getExtensions());
    for (int i = 0; i < file.getExtensions().size(); i++) {
      assertEquals(i, file.getExtensions().get(i).getIndex());
    }
  }

  public void testDescriptor() throws Exception {
    Descriptor messageType = TestAllTypes.getDescriptor();
    Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();

    assertEquals("TestAllTypes", messageType.getName());
    assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
    assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
    assertNull(messageType.getContainingType());
    assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(), messageType.getOptions());
    assertEquals("TestAllTypes", messageType.toProto().getName());

    assertEquals("NestedMessage", nestedType.getName());
    assertEquals("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.getFullName());
    assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
    assertEquals(messageType, nestedType.getContainingType());

    FieldDescriptor field = messageType.getFields().get(0);
    assertEquals("optional_int32", field.getName());
    assertEquals(field, messageType.findFieldByName("optional_int32"));
    assertNull(messageType.findFieldByName("no_such_field"));
    assertEquals(field, messageType.findFieldByNumber(1));
    assertNull(messageType.findFieldByNumber(571283));
    for (int i = 0; i < messageType.getFields().size(); i++) {
      assertEquals(i, messageType.getFields().get(i).getIndex());
    }

    assertEquals(nestedType, messageType.getNestedTypes().get(0));
    assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
    assertNull(messageType.findNestedTypeByName("NoSuchType"));
    for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
      assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
    }

    EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
    assertEquals(enumType, messageType.getEnumTypes().get(0));
    assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
    assertNull(messageType.findEnumTypeByName("NoSuchType"));
    for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
      assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
    }
  }

  public void testFieldDescriptor() throws Exception {
    Descriptor messageType = TestAllTypes.getDescriptor();
    FieldDescriptor primitiveField = messageType.findFieldByName("optional_int32");
    FieldDescriptor enumField = messageType.findFieldByName("optional_nested_enum");
    FieldDescriptor messageField = messageType.findFieldByName("optional_foreign_message");
    FieldDescriptor cordField = messageType.findFieldByName("optional_cord");
    FieldDescriptor extension = UnittestProto.optionalInt32Extension.getDescriptor();
    FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();

    assertEquals("optional_int32", primitiveField.getName());
    assertEquals("protobuf_unittest.TestAllTypes.optional_int32", primitiveField.getFullName());
    assertEquals(1, primitiveField.getNumber());
    assertEquals(messageType, primitiveField.getContainingType());
    assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
    assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
    assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), primitiveField.getOptions());
    assertFalse(primitiveField.isExtension());
    assertEquals("optional_int32", primitiveField.toProto().getName());

    assertEquals("optional_nested_enum", enumField.getName());
    assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
    assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
    assertEquals(TestAllTypes.NestedEnum.getDescriptor(), enumField.getEnumType());

    assertEquals("optional_foreign_message", messageField.getName());
    assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
    assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
    assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());

    assertEquals("optional_cord", cordField.getName());
    assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
    assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
    assertEquals(DescriptorProtos.FieldOptions.CType.CORD, cordField.getOptions().getCtype());

    assertEquals("optional_int32_extension", extension.getName());
    assertEquals("protobuf_unittest.optional_int32_extension", extension.getFullName());
    assertEquals(1, extension.getNumber());
    assertEquals(TestAllExtensions.getDescriptor(), extension.getContainingType());
    assertEquals(UnittestProto.getDescriptor(), extension.getFile());
    assertEquals(FieldDescriptor.Type.INT32, extension.getType());
    assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
    assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(), extension.getOptions());
    assertTrue(extension.isExtension());
    assertEquals(null, extension.getExtensionScope());
    assertEquals("optional_int32_extension", extension.toProto().getName());

    assertEquals("single", nestedExtension.getName());
    assertEquals("protobuf_unittest.TestRequired.single", nestedExtension.getFullName());
    assertEquals(TestRequired.getDescriptor(), nestedExtension.getExtensionScope());
  }

  public void testFieldDescriptorLabel() throws Exception {
    FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
    FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
    FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32");

    assertTrue(requiredField.isRequired());
    assertFalse(requiredField.isRepeated());
    assertFalse(optionalField.isRequired());
    assertFalse(optionalField.isRepeated());
    assertFalse(repeatedField.isRequired());
    assertTrue(repeatedField.isRepeated());
  }

  public void testFieldDescriptorJsonName() throws Exception {
    FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
    FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
    FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
    assertEquals("a", requiredField.getJsonName());
    assertEquals("optionalInt32", optionalField.getJsonName());
    assertEquals("repeatedInt32", repeatedField.getJsonName());
  }

  public void testFieldDescriptorDefault() throws Exception {
    Descriptor d = TestAllTypes.getDescriptor();
    assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
    assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
    assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
    assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());

    d = TestExtremeDefaultValues.getDescriptor();
    assertEquals(
        ByteString.copyFrom("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)),
        d.findFieldByName("escaped_bytes").getDefaultValue());
    assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
    assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
  }

  public void testEnumDescriptor() throws Exception {
    EnumDescriptor enumType = ForeignEnum.getDescriptor();
    EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();

    assertEquals("ForeignEnum", enumType.getName());
    assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
    assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
    assertNull(enumType.getContainingType());
    assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(), enumType.getOptions());

    assertEquals("NestedEnum", nestedType.getName());
    assertEquals("protobuf_unittest.TestAllTypes.NestedEnum", nestedType.getFullName());
    assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
    assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());

    EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
    assertEquals(value, enumType.getValues().get(0));
    assertEquals("FOREIGN_FOO", value.getName());
    assertEquals("FOREIGN_FOO", value.toString());
    assertEquals(4, value.getNumber());
    assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
    assertEquals(value, enumType.findValueByNumber(4));
    assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
    for (int i = 0; i < enumType.getValues().size(); i++) {
      assertEquals(i, enumType.getValues().get(i).getIndex());
    }
  }

  public void testServiceDescriptor() throws Exception {
    ServiceDescriptor service = TestService.getDescriptor();

    assertEquals("TestService", service.getName());
    assertEquals("protobuf_unittest.TestService", service.getFullName());
    assertEquals(UnittestProto.getDescriptor(), service.getFile());


    MethodDescriptor fooMethod = service.getMethods().get(0);
    assertEquals("Foo", fooMethod.getName());
    assertEquals(UnittestProto.FooRequest.getDescriptor(), fooMethod.getInputType());
    assertEquals(UnittestProto.FooResponse.getDescriptor(), fooMethod.getOutputType());
    assertEquals(fooMethod, service.findMethodByName("Foo"));

    MethodDescriptor barMethod = service.getMethods().get(1);
    assertEquals("Bar", barMethod.getName());
    assertEquals(UnittestProto.BarRequest.getDescriptor(), barMethod.getInputType());
    assertEquals(UnittestProto.BarResponse.getDescriptor(), barMethod.getOutputType());
    assertEquals(barMethod, service.findMethodByName("Bar"));

    assertNull(service.findMethodByName("NoSuchMethod"));

    for (int i = 0; i < service.getMethods().size(); i++) {
      assertEquals(i, service.getMethods().get(i).getIndex());
    }
  }


  public void testCustomOptions() throws Exception {
    // Get the descriptor indirectly from a dependent proto class. This is to
    // ensure that when a proto class is loaded, custom options defined in its
    // dependencies are also properly initialized.
    Descriptor descriptor =
        TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor()
            .findFieldByName("field")
            .getMessageType();

    assertTrue(descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
    assertEquals(
        Integer.valueOf(-56),
        descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));

    FieldDescriptor field = descriptor.findFieldByName("field1");
    assertNotNull(field);

    assertTrue(field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
    assertEquals(
        Long.valueOf(8765432109L),
        field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));

    OneofDescriptor oneof = descriptor.getOneofs().get(0);
    assertNotNull(oneof);

    assertTrue(oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1));
    assertEquals(
        Integer.valueOf(-99), oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1));

    EnumDescriptor enumType =
        UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();

    assertTrue(enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
    assertEquals(
        Integer.valueOf(-789), enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));

    ServiceDescriptor service = UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();

    assertTrue(service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
    assertEquals(
        Long.valueOf(-9876543210L),
        service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));

    MethodDescriptor method = service.findMethodByName("Foo");
    assertNotNull(method);

    assertTrue(method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
    assertEquals(
        UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
        method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
  }

  /** Test that the FieldDescriptor.Type enum is the same as the WireFormat.FieldType enum. */
  public void testFieldTypeTablesMatch() throws Exception {
    FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
    WireFormat.FieldType[] values2 = WireFormat.FieldType.values();

    assertEquals(values1.length, values2.length);

    for (int i = 0; i < values1.length; i++) {
      assertEquals(values1[i].toString(), values2[i].toString());
    }
  }

  /** Test that the FieldDescriptor.JavaType enum is the same as the WireFormat.JavaType enum. */
  public void testJavaTypeTablesMatch() throws Exception {
    FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
    WireFormat.JavaType[] values2 = WireFormat.JavaType.values();

    assertEquals(values1.length, values2.length);

    for (int i = 0; i < values1.length; i++) {
      assertEquals(values1[i].toString(), values2[i].toString());
    }
  }

  public void testEnormousDescriptor() throws Exception {
    // The descriptor for this file is larger than 64k, yet it did not cause
    // a compiler error due to an over-long string literal.
    assertTrue(UnittestEnormousDescriptor.getDescriptor().toProto().getSerializedSize() > 65536);
  }

  /** Tests that the DescriptorValidationException works as intended. */
  public void testDescriptorValidatorException() throws Exception {
    FileDescriptorProto fileDescriptorProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Foo")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setType(FieldDescriptorProto.Type.TYPE_INT32)
                            .setName("foo")
                            .setNumber(1)
                            .setDefaultValue("invalid")
                            .build())
                    .build())
            .build();
    try {
      Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
      fail("DescriptorValidationException expected");
    } catch (DescriptorValidationException e) {
      // Expected; check that the error message contains some useful hints
      assertTrue(e.getMessage().indexOf("foo") != -1);
      assertTrue(e.getMessage().indexOf("Foo") != -1);
      assertTrue(e.getMessage().indexOf("invalid") != -1);
      assertTrue(e.getCause() instanceof NumberFormatException);
      assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
    }
  }

  /**
   * Tests the translate/crosslink for an example where a message field's name and type name are the
   * same.
   */
  public void testDescriptorComplexCrosslink() throws Exception {
    FileDescriptorProto fileDescriptorProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Foo")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setType(FieldDescriptorProto.Type.TYPE_INT32)
                            .setName("foo")
                            .setNumber(1)
                            .build())
                    .build())
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Bar")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setTypeName("Foo")
                            .setName("Foo")
                            .setNumber(1)
                            .build())
                    .build())
            .build();
    // translate and crosslink
    FileDescriptor file =
        Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
    // verify resulting descriptors
    assertNotNull(file);
    List<Descriptor> msglist = file.getMessageTypes();
    assertNotNull(msglist);
    assertTrue(msglist.size() == 2);
    boolean barFound = false;
    for (Descriptor desc : msglist) {
      if (desc.getName().equals("Bar")) {
        barFound = true;
        assertNotNull(desc.getFields());
        List<FieldDescriptor> fieldlist = desc.getFields();
        assertNotNull(fieldlist);
        assertTrue(fieldlist.size() == 1);
        assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
        assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
      }
    }
    assertTrue(barFound);
  }

  public void testDependencyOrder() throws Exception {
    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build();
    FileDescriptorProto barProto =
        FileDescriptorProto.newBuilder().setName("bar.proto").addDependency("foo.proto").build();
    FileDescriptorProto bazProto =
        FileDescriptorProto.newBuilder()
            .setName("baz.proto")
            .addDependency("foo.proto")
            .addDependency("bar.proto")
            .addPublicDependency(0)
            .addPublicDependency(1)
            .build();
    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
    FileDescriptor barFile =
        Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});

    // Items in the FileDescriptor array can be in any order.
    Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {fooFile, barFile});
    Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {barFile, fooFile});
  }

  public void testInvalidPublicDependency() throws Exception {
    FileDescriptorProto fooProto = FileDescriptorProto.newBuilder().setName("foo.proto").build();
    FileDescriptorProto barProto =
        FileDescriptorProto.newBuilder()
            .setName("boo.proto")
            .addDependency("foo.proto")
            .addPublicDependency(1) // Error, should be 0.
            .build();
    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
    try {
      Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});
      fail("DescriptorValidationException expected");
    } catch (DescriptorValidationException e) {
      assertTrue(e.getMessage().indexOf("Invalid public dependency index.") != -1);
    }
  }

  public void testUnknownFieldsDenied() throws Exception {
    FileDescriptorProto fooProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Foo")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setTypeName("Bar")
                            .setName("bar")
                            .setNumber(1)))
            .build();

    try {
      Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
      fail("DescriptorValidationException expected");
    } catch (DescriptorValidationException e) {
      assertTrue(e.getMessage().indexOf("Bar") != -1);
      assertTrue(e.getMessage().indexOf("is not defined") != -1);
    }
  }

  public void testUnknownFieldsAllowed() throws Exception {
    FileDescriptorProto fooProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addDependency("bar.proto")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Foo")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setTypeName("Bar")
                            .setName("bar")
                            .setNumber(1)))
            .build();
    Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true);
  }

  public void testHiddenDependency() throws Exception {
    FileDescriptorProto barProto =
        FileDescriptorProto.newBuilder()
            .setName("bar.proto")
            .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
            .build();
    FileDescriptorProto forwardProto =
        FileDescriptorProto.newBuilder()
            .setName("forward.proto")
            .addDependency("bar.proto")
            .build();
    FileDescriptorProto fooProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addDependency("forward.proto")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Foo")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setTypeName("Bar")
                            .setName("bar")
                            .setNumber(1)))
            .build();
    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]);
    FileDescriptor forwardFile =
        Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile});

    try {
      Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
      fail("DescriptorValidationException expected");
    } catch (DescriptorValidationException e) {
      assertTrue(e.getMessage().indexOf("Bar") != -1);
      assertTrue(e.getMessage().indexOf("is not defined") != -1);
    }
  }

  public void testPublicDependency() throws Exception {
    FileDescriptorProto barProto =
        FileDescriptorProto.newBuilder()
            .setName("bar.proto")
            .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
            .build();
    FileDescriptorProto forwardProto =
        FileDescriptorProto.newBuilder()
            .setName("forward.proto")
            .addDependency("bar.proto")
            .addPublicDependency(0)
            .build();
    FileDescriptorProto fooProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addDependency("forward.proto")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Foo")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
                            .setTypeName("Bar")
                            .setName("bar")
                            .setNumber(1)))
            .build();
    FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[0]);
    FileDescriptor forwardFile =
        Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile});
    Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
  }

  /** Tests the translate/crosslink for an example with a more complex namespace referencing. */
  public void testComplexNamespacePublicDependency() throws Exception {
    FileDescriptorProto fooProto =
        FileDescriptorProto.newBuilder()
            .setName("bar.proto")
            .setPackage("a.b.c.d.bar.shared")
            .addEnumType(
                EnumDescriptorProto.newBuilder()
                    .setName("MyEnum")
                    .addValue(EnumValueDescriptorProto.newBuilder().setName("BLAH").setNumber(1)))
            .build();
    FileDescriptorProto barProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addDependency("bar.proto")
            .setPackage("a.b.c.d.foo.shared")
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("MyMessage")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
                            .setTypeName("bar.shared.MyEnum")
                            .setName("MyField")
                            .setNumber(1)))
            .build();
    // translate and crosslink
    FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
    FileDescriptor barFile =
        Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});
    // verify resulting descriptors
    assertNotNull(barFile);
    List<Descriptor> msglist = barFile.getMessageTypes();
    assertNotNull(msglist);
    assertTrue(msglist.size() == 1);
    Descriptor desc = msglist.get(0);
    if (desc.getName().equals("MyMessage")) {
      assertNotNull(desc.getFields());
      List<FieldDescriptor> fieldlist = desc.getFields();
      assertNotNull(fieldlist);
      assertTrue(fieldlist.size() == 1);
      FieldDescriptor field = fieldlist.get(0);
      assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
      assertTrue(field.getEnumType().getName().equals("MyEnum"));
      assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
      assertTrue(field.getEnumType().getFile().getPackage().equals("a.b.c.d.bar.shared"));
    }
  }

  public void testOneofDescriptor() throws Exception {
    Descriptor messageType = TestAllTypes.getDescriptor();
    FieldDescriptor field = messageType.findFieldByName("oneof_nested_message");
    OneofDescriptor oneofDescriptor = field.getContainingOneof();
    assertNotNull(oneofDescriptor);
    assertSame(oneofDescriptor, messageType.getOneofs().get(0));
    assertEquals("oneof_field", oneofDescriptor.getName());

    assertEquals(4, oneofDescriptor.getFieldCount());
    assertSame(oneofDescriptor.getField(1), field);

    assertEquals(4, oneofDescriptor.getFields().size());
    assertEquals(oneofDescriptor.getFields().get(1), field);
  }

  public void testMessageDescriptorExtensions() throws Exception {
    assertFalse(TestAllTypes.getDescriptor().isExtendable());
    assertTrue(TestAllExtensions.getDescriptor().isExtendable());
    assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable());

    assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3));
    assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3));
    assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42));
    assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43));
    assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142));
    assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
  }

  public void testReservedFields() {
    Descriptor d = TestReservedFields.getDescriptor();
    assertTrue(d.isReservedNumber(2));
    assertFalse(d.isReservedNumber(8));
    assertTrue(d.isReservedNumber(9));
    assertTrue(d.isReservedNumber(10));
    assertTrue(d.isReservedNumber(11));
    assertFalse(d.isReservedNumber(12));
    assertFalse(d.isReservedName("foo"));
    assertTrue(d.isReservedName("bar"));
    assertTrue(d.isReservedName("baz"));
  }

  public void testToString() {
    assertEquals(
        "protobuf_unittest.TestAllTypes.optional_uint64",
        UnittestProto.TestAllTypes.getDescriptor()
            .findFieldByNumber(UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER)
            .toString());
  }

  public void testPackedEnumField() throws Exception {
    FileDescriptorProto fileDescriptorProto =
        FileDescriptorProto.newBuilder()
            .setName("foo.proto")
            .addEnumType(
                EnumDescriptorProto.newBuilder()
                    .setName("Enum")
                    .addValue(
                        EnumValueDescriptorProto.newBuilder().setName("FOO").setNumber(1).build())
                    .build())
            .addMessageType(
                DescriptorProto.newBuilder()
                    .setName("Message")
                    .addField(
                        FieldDescriptorProto.newBuilder()
                            .setName("foo")
                            .setTypeName("Enum")
                            .setNumber(1)
                            .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
                            .setOptions(
                                DescriptorProtos.FieldOptions.newBuilder().setPacked(true).build())
                            .build())
                    .build())
            .build();
    Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
  }

  public void testFieldJsonName() throws Exception {
    Descriptor d = TestJsonName.getDescriptor();
    assertEquals(6, d.getFields().size());
    assertEquals("fieldName1", d.getFields().get(0).getJsonName());
    assertEquals("fieldName2", d.getFields().get(1).getJsonName());
    assertEquals("FieldName3", d.getFields().get(2).getJsonName());
    assertEquals("FieldName4", d.getFields().get(3).getJsonName());
    assertEquals("FIELDNAME5", d.getFields().get(4).getJsonName());
    assertEquals("@type", d.getFields().get(5).getJsonName());
  }

  public void testExtensionRenamesKeywords() {
    assertTrue(NonNestedExtension.if_ instanceof GeneratedMessage.GeneratedExtension);
    assertTrue(
        NestedExtension.MyNestedExtension.default_
            instanceof GeneratedMessage.GeneratedExtension);

    NonNestedExtension.MessageToBeExtended msg =
        NonNestedExtension.MessageToBeExtended.newBuilder()
            .setExtension(NonNestedExtension.if_, "!fi")
            .build();
    assertEquals("!fi", msg.getExtension(NonNestedExtension.if_));

    msg =
        NonNestedExtension.MessageToBeExtended.newBuilder()
            .setExtension(NestedExtension.MyNestedExtension.default_, 8)
            .build();
    assertEquals(8, msg.getExtension(NestedExtension.MyNestedExtension.default_).intValue());
  }
}
