public MessageType convert(Descriptors.Descriptor descriptor) {
    // Remember classes seen with depths to avoid cycles.
    int depth = 0;
    ImmutableSetMultimap<String, Integer> seen = ImmutableSetMultimap.of(descriptor.getFullName(), depth);
    LOG.trace("convert:\n{}", descriptor.toProto());
    MessageType messageType = convertFields(Types.buildMessage(), descriptor.getFields(), seen, depth)
        .named(descriptor.getFullName());
    LOG.debug("Converter info:\n{}\n  was converted to:\n{}", descriptor.toProto(), messageType);
    return messageType;
  }
@Test
  public void testDeepRecursion() {
    // The general idea is to test the fanout of the schema.
    // TODO: figured out closed forms of the binary tree and struct series.
    long expectedBinaryTreeSize = 4;
    long expectedStructSize = 7;
    for (int i = 0; i < 10; ++i) {
      MessageType deepSchema = new ProtoSchemaConverter(true, i, false).convert(Trees.WideTree.class);
      // 3, 5, 7, 9, 11, 13, 15, 17, 19, 21
      assertEquals(2 * i + 3, deepSchema.getPaths().size());

      deepSchema = new ProtoSchemaConverter(true, i, false).convert(Trees.BinaryTree.class);
      // 4, 10, 22, 46, 94, 190, 382, 766, 1534, 3070
      assertEquals(expectedBinaryTreeSize, deepSchema.getPaths().size());
      expectedBinaryTreeSize = 2 * expectedBinaryTreeSize + 2;

      deepSchema = new ProtoSchemaConverter(true, i, false).convert(Struct.class);
      // 7, 18, 40, 84, 172, 348, 700, 1404, 2812, 5628
      assertEquals(expectedStructSize, deepSchema.getPaths().size());
      expectedStructSize = 2 * expectedStructSize + 4;
    }
  }