/**
   * @param builder Builder.
   * @param key Key field value.
   */
  private static void setBuilderFields(BinaryObjectBuilder builder, int key) {
    builder.setField("f1", 1);

    builder.setField("f2", "SomeString");

    builder.setField("f3", (long) key);
  }
  /** @throws Exception If failed. */
  public void testNullField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(42);

    builder.setField("objField", (Object) null);

    builder.setField("otherField", "value");

    BinaryObject obj = builder.build();

    assertNull(obj.field("objField"));
    assertEquals("value", obj.field("otherField"));
    assertEquals(42, obj.hashCode());

    builder = builder(obj);

    builder.setField("objField", "value", Object.class);
    builder.setField("otherField", (Object) null);

    obj = builder.build();

    assertNull(obj.field("otherField"));
    assertEquals("value", obj.field("objField"));
    assertEquals(42, obj.hashCode());
  }
  /** @throws Exception If failed. */
  public void testCollectionField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("collectionField", Arrays.asList(new Value(1), new Value(2)));
    builder.setField(
        "collectionField2", Arrays.asList(new Value(1), new Value(2)), Collection.class);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    List<Value> list = po.field("collectionField");

    assertEquals(2, list.size());
    assertEquals(1, list.get(0).i);
    assertEquals(2, list.get(1).i);

    List<BinaryObject> list2 = po.field("collectionField2");

    assertEquals(2, list2.size());
    assertEquals(1, list2.get(0).<Value>deserialize().i);
    assertEquals(2, list2.get(1).<Value>deserialize().i);
  }
  /** @throws Exception If failed. */
  public void testMapField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("mapField", F.asMap(new Key(1), new Value(1), new Key(2), new Value(2)));
    builder.setField(
        "mapField2", F.asMap(new Key(1), new Value(1), new Key(2), new Value(2)), Map.class);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    // Test non-standard map.
    Map<Key, Value> map = po.field("mapField");

    assertEquals(2, map.size());

    for (Map.Entry<Key, Value> e : map.entrySet()) assertEquals(e.getKey().i, e.getValue().i);

    // Test binary map
    Map<BinaryObject, BinaryObject> map2 = po.field("mapField2");

    assertEquals(2, map2.size());

    for (Map.Entry<BinaryObject, BinaryObject> e : map2.entrySet())
      assertEquals(e.getKey().<Key>deserialize().i, e.getValue().<Value>deserialize().i);
  }
  /** @throws Exception If failed. */
  public void testSeveralFields() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("i", 111);
    builder.setField("f", 111.111f);
    builder.setField("iArr", new int[] {1, 2, 3});
    builder.setField("obj", new Key(1));
    builder.setField("col", Arrays.asList(new Value(1), new Value(2)), Collection.class);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(111, po.<Integer>field("i").intValue());
    assertEquals(111.111f, po.<Float>field("f").floatValue(), 0);
    assertTrue(Arrays.equals(new int[] {1, 2, 3}, po.<int[]>field("iArr")));
    assertEquals(1, po.<BinaryObject>field("obj").<Key>deserialize().i);

    List<BinaryObject> list = po.field("col");

    assertEquals(2, list.size());

    assertEquals(1, list.get(0).<Value>deserialize().i);
    assertEquals(2, list.get(1).<Value>deserialize().i);
  }
  /** @throws Exception If failed. */
  public void testOffheapBinary() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("i", 111);
    builder.setField("f", 111.111f);
    builder.setField("iArr", new int[] {1, 2, 3});
    builder.setField("obj", new Key(1));
    builder.setField("col", Arrays.asList(new Value(1), new Value(2)), Collection.class);

    BinaryObject po = builder.build();

    byte[] arr = ((CacheObjectBinaryProcessorImpl) (grid(0)).context().cacheObjects()).marshal(po);

    long ptr = GridUnsafe.allocateMemory(arr.length + 5);

    try {
      long ptr0 = ptr;

      GridUnsafe.putBoolean(null, ptr0++, false);

      int len = arr.length;

      if (BIG_ENDIAN) GridUnsafe.putIntLE(ptr0, len);
      else GridUnsafe.putInt(ptr0, len);

      GridUnsafe.copyHeapOffheap(arr, GridUnsafe.BYTE_ARR_OFF, ptr0 + 4, arr.length);

      BinaryObject offheapObj =
          (BinaryObject)
              ((CacheObjectBinaryProcessorImpl) (grid(0)).context().cacheObjects())
                  .unmarshal(ptr, false);

      assertEquals(BinaryObjectOffheapImpl.class, offheapObj.getClass());

      assertEquals(expectedHashCode("Class"), offheapObj.type().typeId());
      assertEquals(100, offheapObj.hashCode());

      assertEquals(111, offheapObj.<Integer>field("i").intValue());
      assertEquals(111.111f, offheapObj.<Float>field("f").floatValue(), 0);
      assertTrue(Arrays.equals(new int[] {1, 2, 3}, offheapObj.<int[]>field("iArr")));
      assertEquals(1, offheapObj.<BinaryObject>field("obj").<Key>deserialize().i);

      List<BinaryObject> list = offheapObj.field("col");

      assertEquals(2, list.size());

      assertEquals(1, list.get(0).<Value>deserialize().i);
      assertEquals(2, list.get(1).<Value>deserialize().i);

      assertEquals(po, offheapObj);
      assertEquals(offheapObj, po);
    } finally {
      GridUnsafe.freeMemory(ptr);
    }
  }
  Object createPerson(int id, String name) {
    if (!isBinaryMarshaller()) {
      Person p = new Person(id);
      p.name = name;

      return p;
    } else {
      BinaryObjectBuilder o = grid(0).binary().builder("Person");
      o.setField("id", id);
      o.setField("name", name);

      return o.build();
    }
  }
  /** @throws Exception If failed. */
  public void testMetaData() throws Exception {
    BinaryObjectBuilder builder = builder("org.test.MetaTest");

    builder.hashCode(100);

    builder.setField("intField", 1);
    builder.setField("byteArrayField", new byte[] {1, 2, 3});

    BinaryObject po = builder.build();

    BinaryType meta = po.type();

    assertEquals(expectedTypeName("org.test.MetaTest"), meta.typeName());

    Collection<String> fields = meta.fieldNames();

    assertEquals(2, fields.size());

    assertTrue(fields.contains("intField"));
    assertTrue(fields.contains("byteArrayField"));

    assertEquals("int", meta.fieldTypeName("intField"));
    assertEquals("byte[]", meta.fieldTypeName("byteArrayField"));

    builder = builder("org.test.MetaTest");

    builder.hashCode(100);

    builder.setField("intField", 2);
    builder.setField("uuidField", UUID.randomUUID());

    po = builder.build();

    meta = po.type();

    assertEquals(expectedTypeName("org.test.MetaTest"), meta.typeName());

    fields = meta.fieldNames();

    assertEquals(3, fields.size());

    assertTrue(fields.contains("intField"));
    assertTrue(fields.contains("byteArrayField"));
    assertTrue(fields.contains("uuidField"));

    assertEquals("int", meta.fieldTypeName("intField"));
    assertEquals("byte[]", meta.fieldTypeName("byteArrayField"));
    assertEquals("UUID", meta.fieldTypeName("uuidField"));
  }
  Object createPerson2(int id, String name, int valFld) {
    if (!isBinaryMarshaller()) {
      Person2 p = new Person2(id);
      p.name = name;
      p.IntVal = valFld;

      return p;
    } else {
      BinaryObjectBuilder o = grid(0).binary().builder("Person2");
      o.setField("id", id);
      o.setField("name", name);
      o.setField("IntVal", valFld);

      return o.build();
    }
  }
  public void testRemoveFromNewObject() {
    BinaryObjectBuilder builder = builder(GridBinaryTestClasses.TestObjectAllTypes.class.getName());

    builder.setField("str", "a");

    builder.removeField("str");

    TestCase.assertNull(
        builder.build().<GridBinaryTestClasses.TestObjectAllTypes>deserialize().str);
  }
  /** @throws Exception If failed. */
  public void testMetaData2() throws Exception {
    BinaryObjectBuilder builder = builder("org.test.MetaTest2");

    builder.setField("objectField", "a", Object.class);

    BinaryObject bo = builder.build();

    BinaryType meta = bo.type();

    assertEquals(expectedTypeName("org.test.MetaTest2"), meta.typeName());
    assertEquals("Object", meta.fieldTypeName("objectField"));
  }
  /** @throws Exception If failed. */
  public void testCharArrayField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("charArrayField", new char[] {1, 2, 3});

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertTrue(Arrays.equals(new char[] {1, 2, 3}, po.<char[]>field("charArrayField")));
  }
  /** @throws Exception If failed. */
  public void testLongField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("longField", 1L);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(1L, po.<Long>field("longField").longValue());
  }
  /** @throws Exception If failed. */
  public void testFloatField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("floatField", 1.0f);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(1.0f, po.<Float>field("floatField").floatValue(), 0);
  }
  /** @throws Exception If failed. */
  public void testDoubleField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("doubleField", 1.0d);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(1.0d, po.<Double>field("doubleField").doubleValue(), 0);
  }
  /** @throws Exception If failed. */
  public void testIntField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("intField", 1);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(1, po.<Integer>field("intField").intValue());
  }
  /** @throws Exception If failed. */
  public void testByteField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("byteField", (byte) 1);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals((byte) 1, po.<Byte>field("byteField").byteValue());
  }
  /** @throws Exception If failed. */
  public void testCharField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("charField", (char) 1);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals((char) 1, po.<Character>field("charField").charValue());
  }
  /** @throws Exception If failed. */
  public void testBooleanField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("booleanField", true);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertTrue(po.<Boolean>field("booleanField"));
  }
  /** @throws Exception If failed. */
  public void testStringField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("stringField", "str");

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals("str", po.<String>field("stringField"));
  }
  /** @throws Exception If failed. */
  public void testDecimalField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("decimalField", BigDecimal.TEN);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(BigDecimal.TEN, po.<BigDecimal>field("decimalField"));
  }
  /** @throws Exception If failed. */
  public void testBuildAndDeserialize() throws Exception {
    BinaryObjectBuilder builder = builder(Value.class.getName());

    builder.hashCode(100);

    builder.setField("i", 1);

    BinaryObject bo = builder.build();

    assertEquals(expectedHashCode(Value.class.getName()), bo.type().typeId());
    assertEquals(100, bo.hashCode());

    assertEquals(1, bo.<Value>deserialize().i);
  }
  /** @throws Exception If failed. */
  public void testObjectField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("objectField", new Value(1));

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(1, po.<BinaryObject>field("objectField").<Value>deserialize().i);
  }
  /** @throws Exception If failed. */
  public void testShortField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("shortField", (short) 1);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals((short) 1, po.<Short>field("shortField").shortValue());
  }
  /** @throws IgniteCheckedException If any error occurs. */
  public void testDontBrokeCyclicDependency() throws IgniteCheckedException {
    GridBinaryTestClasses.TestObjectOuter outer = new GridBinaryTestClasses.TestObjectOuter();
    outer.inner = new GridBinaryTestClasses.TestObjectInner();
    outer.inner.outer = outer;
    outer.foo = "a";

    BinaryObjectBuilder builder = builder(toBinary(outer));

    builder.setField("foo", "b");

    GridBinaryTestClasses.TestObjectOuter res = builder.build().deserialize();

    assertEquals("b", res.foo);
    assertSame(res, res.inner.outer);
  }
  /** @throws Exception If failed. */
  public void testUuidArrayField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    UUID[] arr = new UUID[] {UUID.randomUUID(), UUID.randomUUID()};

    builder.setField("uuidArrayField", arr);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertTrue(Arrays.equals(arr, po.<UUID[]>field("uuidArrayField")));
  }
  /** @throws Exception If failed. */
  public void testUuidField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    UUID uuid = UUID.randomUUID();

    builder.setField("uuidField", uuid);

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertEquals(uuid, po.<UUID>field("uuidField"));
  }
  /** @throws Exception If failed. */
  public void testStringArrayField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("stringArrayField", new String[] {"str1", "str2", "str3"});

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertTrue(
        Arrays.equals(
            new String[] {"str1", "str2", "str3"}, po.<String[]>field("stringArrayField")));
  }
  /** @throws Exception If failed. */
  public void testDecimalArrayField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("decimalArrayField", new BigDecimal[] {BigDecimal.ONE, BigDecimal.TEN});

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    assertTrue(
        Arrays.equals(
            new BigDecimal[] {BigDecimal.ONE, BigDecimal.TEN},
            po.<String[]>field("decimalArrayField")));
  }
  /** @throws Exception If failed. */
  public void testObjectArrayField() throws Exception {
    BinaryObjectBuilder builder = builder("Class");

    builder.hashCode(100);

    builder.setField("objectArrayField", new Value[] {new Value(1), new Value(2)});

    BinaryObject po = builder.build();

    assertEquals(expectedHashCode("Class"), po.type().typeId());
    assertEquals(100, po.hashCode());

    Object[] arr = po.field("objectArrayField");

    assertEquals(2, arr.length);

    assertEquals(1, ((BinaryObject) arr[0]).<Value>deserialize().i);
    assertEquals(2, ((BinaryObject) arr[1]).<Value>deserialize().i);
  }