// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf;

import com.google.protobuf.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.DescriptorValidationException;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Descriptors.EnumDescriptor;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.ServiceDescriptor;
import com.google.protobuf.Descriptors.MethodDescriptor;

import com.google.protobuf.test.UnittestImport;
import com.google.protobuf.test.UnittestImport.ImportEnum;
import com.google.protobuf.test.UnittestImport.ImportMessage;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestService;
import protobuf_unittest.UnittestCustomOptions;

import protobuf_unittest.TestCustomOptions;


import junit.framework.TestCase;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 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()),
                 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 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("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));

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

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