@Test
  public void testEmptySave() throws Exception {
    Log.info(Log.FAC_TEST, "Starting testEmptySave");

    boolean caught = false;
    NDNHandle handle = NDNHandle.open();
    try {
      ContentName testName =
          new ContentName(testHelper.getTestNamespace("testEmptySave"), collectionObjName);
      CollectionObject emptycoll =
          new CollectionObject(testName, (Collection) null, SaveType.REPOSITORY, handle);
      setupNamespace(testName);
      try {
        emptycoll.setData(small1); // set temporarily to non-null
        saveAndLog("Empty", emptycoll, null, null);
        TestUtils.checkObject(handle, emptycoll);
      } catch (InvalidObjectException iox) {
        // this is what we expect to happen
        caught = true;
      }
      Assert.assertTrue("Failed to produce expected exception.", caught);
    } finally {
      handle.close();
      KeyManager.closeDefaultKeyManager();
    }

    Log.info(Log.FAC_TEST, "Completed testEmptySave");
  }
  @Test
  public void testVersionOrdering() throws Exception {
    Log.info(Log.FAC_TEST, "Starting testVersionOrdering");

    NDNHandle tHandle = NDNHandle.open();
    NDNHandle rHandle = NDNHandle.open();
    try {
      ContentName testName =
          new ContentName(
              testHelper.getTestNamespace("testVersionOrdering"), collectionObjName, "name1");
      ContentName testName2 =
          new ContentName(
              testHelper.getTestNamespace("testVersionOrdering"), collectionObjName, "name2");

      CollectionObject c0 = new CollectionObject(testName, empty, SaveType.REPOSITORY, rHandle);
      setupNamespace(testName);
      NDNTime t0 = saveAndLog("Empty", c0, null, empty);
      TestUtils.checkObject(rHandle, c0);

      CollectionObject c1 = new CollectionObject(testName2, small1, SaveType.REPOSITORY, tHandle);
      CollectionObject c2 = new CollectionObject(testName2, small1, SaveType.REPOSITORY, null);
      setupNamespace(testName2);
      NDNTime t1 = saveAndLog("Small", c1, null, small1);
      TestUtils.checkObject(tHandle, c1);
      Assert.assertTrue("First version should come before second", t0.before(t1));

      NDNTime t2 = saveAndLog("Small2ndWrite", c2, null, small1);
      TestUtils.checkObject(c2.getHandle(), c2);
      Assert.assertTrue("Third version should come after second", t1.before(t2));
      Assert.assertTrue(c2.contentEquals(c1));
      Assert.assertFalse(c2.equals(c1));
      Assert.assertTrue(
          VersioningProfile.isLaterVersionOf(c2.getVersionedName(), c1.getVersionedName()));
    } finally {
      tHandle.close();
      rHandle.close();
      KeyManager.closeDefaultKeyManager();
    }

    Log.info(Log.FAC_TEST, "Completed testVersionOrdering");
  }
  @Test
  public void testSaveAsGone() throws Exception {
    Log.info(Log.FAC_TEST, "Starting testSaveAsGone");

    NDNHandle thandle = NDNHandle.open();
    NDNHandle rhandle = NDNHandle.open();
    NDNHandle shandle = NDNHandle.open();

    try {
      ContentName testName =
          new ContentName(testHelper.getTestNamespace("testSaveAsGone"), collectionObjName);
      CollectionObject c0 = new CollectionObject(testName, empty, SaveType.REPOSITORY, thandle);
      setupNamespace(testName);
      NDNTime t0 = saveAsGoneAndLog("Gone", c0);
      Assert.assertTrue("Should be gone", c0.isGone());
      ContentName goneVersionName = c0.getVersionedName();

      NDNTime t1 = saveAndLog("NotGone", c0, null, small1);
      TestUtils.checkObject(thandle, c0);
      Assert.assertFalse("Should not be gone", c0.isGone());
      Assert.assertTrue(t1.after(t0));

      CollectionObject c1 = new CollectionObject(testName, rhandle);
      NDNTime t2 = waitForDataAndLog(testName.toString(), c1);
      Assert.assertFalse("Read back should not be gone", c1.isGone());
      Assert.assertEquals(t2, t1);

      NDNTime t3 = updateAndLog(goneVersionName.toString(), c1, goneVersionName);
      Assert.assertTrue(VersioningProfile.isVersionOf(c1.getVersionedName(), testName));
      Assert.assertEquals(t3, t0);
      Assert.assertTrue("Read back should be gone.", c1.isGone());

      t0 = saveAsGoneAndLog("GoneAgain", c0);
      Assert.assertTrue("Should be gone", c0.isGone());

      CollectionObject c2 = new CollectionObject(testName, shandle);
      NDNTime t4 = waitForDataAndLog(testName.toString(), c2);
      Assert.assertTrue(
          "Read back of " + c0.getVersionedName() + " should be gone, got " + c2.getVersionedName(),
          c2.isGone());
      Assert.assertEquals(t4, t0);
    } finally {
      thandle.close();
      rhandle.close();
      shandle.close();
      KeyManager.closeDefaultKeyManager();
    }

    Log.info(Log.FAC_TEST, "Completed testSaveAsGone");
  }
  @Test
  public void testStreamUpdate() throws Exception {
    Log.info(Log.FAC_TEST, "Starting testStreamUpdate");

    NDNHandle tHandle = NDNHandle.open();
    try {
      ContentName testName =
          new ContentName(testHelper.getTestNamespace("testStreamUpdate"), collectionObjName);
      CollectionObject testCollectionObject =
          new CollectionObject(testName, small1, SaveType.REPOSITORY, tHandle);
      setupNamespace(testName);

      saveAndLog("testStreamUpdate", testCollectionObject, null, small1);
      TestUtils.checkObject(tHandle, testCollectionObject);
      Log.info(
          Log.FAC_TEST, "testCollectionObject name: " + testCollectionObject.getVersionedName());

      NDNVersionedInputStream vis =
          new NDNVersionedInputStream(testCollectionObject.getVersionedName());
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      byte[] buf = new byte[128];
      // Will incur a timeout
      while (!vis.eof()) {
        int read = vis.read(buf);
        if (read > 0) baos.write(buf, 0, read);
      }
      Log.info(
          Log.FAC_TEST,
          "Read "
              + baos.toByteArray().length
              + " bytes, digest: "
              + DigestHelper.printBytes(DigestHelper.digest(baos.toByteArray()), 16));

      Collection decodedData = new Collection();
      decodedData.decode(baos.toByteArray());
      Log.info(Log.FAC_TEST, "Decoded collection data: " + decodedData);
      Assert.assertEquals(
          "Decoding via stream fails to give expected result!", decodedData, small1);

      NDNVersionedInputStream vis2 =
          new NDNVersionedInputStream(testCollectionObject.getVersionedName());
      ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
      // Will incur a timeout
      while (!vis2.eof()) {
        int val = vis2.read();
        if (val < 0) break;
        baos2.write((byte) val);
      }
      Log.info(
          Log.FAC_TEST,
          "Read "
              + baos2.toByteArray().length
              + " bytes, digest: "
              + DigestHelper.printBytes(DigestHelper.digest(baos2.toByteArray()), 16));
      Assert.assertArrayEquals(
          "Reading same object twice gets different results!",
          baos.toByteArray(),
          baos2.toByteArray());

      Collection decodedData2 = new Collection();
      decodedData2.decode(baos2.toByteArray());
      Assert.assertEquals(
          "Decoding via stream byte read fails to give expected result!", decodedData2, small1);

      NDNVersionedInputStream vis3 =
          new NDNVersionedInputStream(testCollectionObject.getVersionedName());
      Collection decodedData3 = new Collection();
      decodedData3.decode(vis3);
      Assert.assertEquals(
          "Decoding via stream full read fails to give expected result!", decodedData3, small1);
    } finally {
      tHandle.close();
      KeyManager.closeDefaultKeyManager();
    }

    Log.info(Log.FAC_TEST, "Completed testStreamUpdate");
  }