@Test
  @SuppressWarnings("unchecked")
  public void testCustomEncoders() throws IOException {
    // If clearEncodingHooks isn't working the first test will fail.
    Transformer tf = new TestDateTransformer();
    BSON.addEncodingHook(TestDate.class, tf);
    BSON.clearEncodingHooks();
    TestDate td = new TestDate(2009, 01, 23, 10, 53, 42);
    BSONObject o = new BasicBSONObject("date", td);
    BSONEncoder e = new BasicBSONEncoder();
    BSONDecoder d = new BasicBSONDecoder();
    BSONCallback cb = new BasicBSONCallback();
    OutputBuffer buf = new BasicOutputBuffer();
    e.set(buf);
    boolean encodeFailed = false;
    try {
      e.putObject(o);
    } catch (IllegalArgumentException ieE) {
      encodeFailed = true;
    }
    assertTrue(encodeFailed);
    // Reset the buffer
    buf.seekStart();
    assertTrue(tf.transform(td) instanceof java.util.Date);

    BSON.addEncodingHook(TestDate.class, tf);
    e.putObject(o);
    e.done();

    d.decode(new ByteArrayInputStream(buf.toByteArray()), cb);
    Object result = cb.get();
    assertTrue(result instanceof BSONObject);
    BSONObject bson = (BSONObject) result;
    assertNotNull(bson.get("date"));
    assertTrue(bson.get("date") instanceof java.util.Date);

    // Check that the hooks registered
    assertNotNull(BSON.getEncodingHooks(TestDate.class));
    Vector expect = new Vector(1);
    expect.add(tf);
    assertEquals(BSON.getEncodingHooks(TestDate.class), expect);
    assertTrue(BSON.getEncodingHooks(TestDate.class).contains(tf));
    BSON.removeEncodingHook(TestDate.class, tf);
    assertFalse(BSON.getEncodingHooks(TestDate.class).contains(tf));
  }
  @Test
  @SuppressWarnings({"deprecation", "unchecked"})
  public void testCustomDecoders() throws IOException {
    // If clearDecodingHooks isn't working this whole test will fail.
    Transformer tf = new TestDateTransformer();
    BSON.addDecodingHook(Date.class, tf);
    BSON.clearDecodingHooks();
    TestDate td = new TestDate(2009, 01, 23, 10, 53, 42);
    Date dt = new Date(2009, 01, 23, 10, 53, 42);
    BSONObject o = new BasicBSONObject("date", dt);
    BSONDecoder d = new BasicBSONDecoder();
    BSONEncoder e = new BasicBSONEncoder();
    BSONCallback cb = new BasicBSONCallback();
    OutputBuffer buf = new BasicOutputBuffer();
    e.set(buf);
    e.putObject(o);
    e.done();

    d.decode(new ByteArrayInputStream(buf.toByteArray()), cb);
    Object result = cb.get();
    assertTrue(result instanceof BSONObject);
    BSONObject bson = (BSONObject) result;
    assertNotNull(bson.get("date"));
    assertTrue(bson.get("date") instanceof java.util.Date);

    BSON.addDecodingHook(Date.class, tf);

    d.decode(new ByteArrayInputStream(buf.toByteArray()), cb);
    bson = (BSONObject) cb.get();
    assertNotNull(bson.get("date"));
    assertTrue(bson.get("date") instanceof TestDate);
    assertEquals(bson.get("date"), td);

    // Check that the hooks registered
    assertNotNull(BSON.getDecodingHooks(Date.class));
    Vector expect = new Vector(1);
    expect.add(tf);
    assertEquals(BSON.getDecodingHooks(Date.class), expect);
    assertTrue(BSON.getDecodingHooks(Date.class).contains(tf));
    BSON.removeDecodingHook(Date.class, tf);
    assertFalse(BSON.getDecodingHooks(Date.class).contains(tf));
  }
  void _test(BSONObject o, int size, String hash) throws IOException {
    BSONEncoder e = new BasicBSONEncoder();
    OutputBuffer buf = new BasicOutputBuffer();
    e.set(buf);
    e.putObject(o);
    assertEquals(size, buf.size());
    assertEquals(hash, buf.md5());
    e.done();

    BSONDecoder d = new BasicBSONDecoder();
    BSONCallback cb = new BasicBSONCallback();
    int s = d.decode(new ByteArrayInputStream(buf.toByteArray()), cb);
    assertEquals(size, s);

    OutputBuffer buf2 = new BasicOutputBuffer();
    e.set(buf2);
    e.putObject((BSONObject) cb.get());
    assertEquals(size, buf2.size());
    assertEquals(hash, buf2.md5());
  }