public MessageType union(MessageType toMerge) {
    return union(toMerge, true);
  }
@Test
  public void testMergeSchema() {
    MessageType t1 = new MessageType(
        "root1", new PrimitiveType(REPEATED, BINARY, "a"), new PrimitiveType(OPTIONAL, BINARY, "b"));
    MessageType t2 = new MessageType("root2", new PrimitiveType(REQUIRED, BINARY, "c"));

    assertEquals(
        t1.union(t2),
        new MessageType(
            "root1",
            new PrimitiveType(REPEATED, BINARY, "a"),
            new PrimitiveType(OPTIONAL, BINARY, "b"),
            new PrimitiveType(REQUIRED, BINARY, "c")));

    assertEquals(
        t2.union(t1),
        new MessageType(
            "root2",
            new PrimitiveType(REQUIRED, BINARY, "c"),
            new PrimitiveType(REPEATED, BINARY, "a"),
            new PrimitiveType(OPTIONAL, BINARY, "b")));

    MessageType t3 = new MessageType("root1", new PrimitiveType(OPTIONAL, BINARY, "a"));
    MessageType t4 = new MessageType("root2", new PrimitiveType(REQUIRED, BINARY, "a"));

    assertEquals(t3.union(t4), new MessageType("root1", new PrimitiveType(OPTIONAL, BINARY, "a")));

    assertEquals(t4.union(t3), new MessageType("root2", new PrimitiveType(OPTIONAL, BINARY, "a")));

    MessageType t5 = new MessageType(
        "root1",
        new GroupType(REQUIRED, "g1", new PrimitiveType(OPTIONAL, BINARY, "a")),
        new GroupType(REQUIRED, "g2", new PrimitiveType(OPTIONAL, BINARY, "b")));
    MessageType t6 = new MessageType(
        "root1",
        new GroupType(REQUIRED, "g1", new PrimitiveType(OPTIONAL, BINARY, "a")),
        new GroupType(
            REQUIRED,
            "g2",
            new GroupType(REQUIRED, "g3", new PrimitiveType(OPTIONAL, BINARY, "c")),
            new PrimitiveType(OPTIONAL, BINARY, "b")));

    assertEquals(
        t5.union(t6),
        new MessageType(
            "root1",
            new GroupType(REQUIRED, "g1", new PrimitiveType(OPTIONAL, BINARY, "a")),
            new GroupType(
                REQUIRED,
                "g2",
                new PrimitiveType(OPTIONAL, BINARY, "b"),
                new GroupType(REQUIRED, "g3", new PrimitiveType(OPTIONAL, BINARY, "c")))));

    MessageType t7 = new MessageType("root1", new PrimitiveType(OPTIONAL, BINARY, "a"));
    MessageType t8 = new MessageType("root2", new PrimitiveType(OPTIONAL, INT32, "a"));
    try {
      t7.union(t8);
      fail("moving from BINARY to INT32");
    } catch (IncompatibleSchemaModificationException e) {
      assertEquals("can not merge type optional int32 a into optional binary a", e.getMessage());
    }

    MessageType t9 = Types.buildMessage()
        .addField(Types.optional(BINARY).as(OriginalType.UTF8).named("a"))
        .named("root1");
    MessageType t10 =
        Types.buildMessage().addField(Types.optional(BINARY).named("a")).named("root1");
    assertEquals(t9.union(t9), t9);
    try {
      t9.union(t10);
      fail("moving from BINARY (UTF8) to BINARY");
    } catch (IncompatibleSchemaModificationException e) {
      assertEquals("cannot merge logical type null into STRING", e.getMessage());
    }

    MessageType t11 = Types.buildMessage()
        .addField(Types.optional(FIXED_LEN_BYTE_ARRAY).length(10).named("a"))
        .named("root1");
    MessageType t12 = Types.buildMessage()
        .addField(Types.optional(FIXED_LEN_BYTE_ARRAY).length(20).named("a"))
        .named("root2");
    try {
      t11.union(t12);
      fail("moving from FIXED_LEN_BYTE_ARRAY(10) to FIXED_LEN_BYTE_ARRAY(20)");
    } catch (IncompatibleSchemaModificationException e) {
      assertEquals(
          "can not merge type optional fixed_len_byte_array(20) a into optional fixed_len_byte_array(10) a",
          e.getMessage());
    }
  }