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

    NDNHandle thandle = NDNHandle.open();
    NDNHandle rhandle = NDNHandle.open();
    try {
      ContentName testName =
          new ContentName(testHelper.getTestNamespace("testUpdateDoesNotExist"), collectionObjName);
      NDNStringObject so = new NDNStringObject(testName, rhandle);

      // so should catch exception thrown by underlying stream when it times out.
      Assert.assertFalse(so.available());

      // ask for it in background
      so.updateInBackground();

      NDNStringObject sowrite =
          new NDNStringObject(testName, "Now we write something.", SaveType.REPOSITORY, thandle);
      setupNamespace(testName);
      saveAndLog("Delayed write", sowrite, null, "Now we write something.");
      TestUtils.checkObject(thandle, sowrite);
      so.waitForData();
      Assert.assertTrue(so.available());
      Assert.assertEquals(so.string(), sowrite.string());
      Assert.assertEquals(so.getVersionedName(), sowrite.getVersionedName());
    } finally {
      thandle.close();
      rhandle.close();
      KeyManager.closeDefaultKeyManager();
    }

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

    NDNHandle rhandle = NDNHandle.open();
    try {
      // The local copy wrapper API isn't applicable in very many situations. Try this instead.
      ContentName testName =
          new ContentName(testHelper.getTestNamespace("testLocalCopyListener"), collectionObjName);

      LocalCopyListener copyListener = new LocalCopyListener();

      // Would like to test functionality that arranges for existing version to get written
      // to the repo, but can't do that without a flosser or using a flow server.
      NDNStringObject so = new NDNStringObject(testName, rhandle);
      so.addListener(copyListener);

      Assert.assertFalse(so.available());

      class Record {
        boolean callback = false;
      }
      Record record = new Record();

      class Listener implements UpdateListener {
        Record _rec;

        public Listener(Record r) {
          _rec = r;
        }

        public void newVersionAvailable(NDNNetworkObject<?> newVersion, boolean wasSave) {
          synchronized (_rec) {
            _rec.callback = true;
            _rec.notifyAll();
          }
        }
      };

      // ask for it in background
      so.updateInBackground(false, new Listener(record));

      NDNHandle thandle = NDNHandle.open();
      try {
        NDNStringObject sowrite =
            new NDNStringObject(testName, "Now we write", SaveType.RAW, thandle);
        setupNamespace(testName);
        saveAndLog("Delayed write", sowrite, null, "Now we write");
        TestUtils.checkObject(thandle, sowrite);
        so.waitForData();
        Assert.assertTrue(so.available());
        Assert.assertEquals(so.string(), sowrite.string());
        Assert.assertEquals(so.getVersionedName(), sowrite.getVersionedName());

        new Waiter(UPDATE_TIMEOUT) {
          @Override
          protected boolean check(Object o, Object check) throws Exception {
            return ((Record) o).callback;
          }
        }.wait(record, record);
        Assert.assertEquals(true, record.callback);
        if (!RepositoryControl.localRepoSync(rhandle, so)) {
          Thread.sleep(SystemConfiguration.MEDIUM_TIMEOUT);
          // Should be in the repo by now
          Assert.assertTrue(RepositoryControl.localRepoSync(rhandle, so));
        }
      } finally {
        thandle.close();
      }
    } finally {
      rhandle.close();
      KeyManager.closeDefaultKeyManager();
    }

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

    NDNHandle thandle = NDNHandle.open();
    NDNHandle thandle2 = NDNHandle.open();
    NDNHandle thandle3 = NDNHandle.open();

    try {
      ContentName testName =
          new ContentName(
              testHelper.getTestNamespace("testUpdateInBackground"), stringObjName, "name1");
      // Make writer first, so it picks up readers first interests even before it writes.
      NDNStringObject c2 =
          new NDNStringObject(testName, (String) null, SaveType.REPOSITORY, thandle);

      NDNStringObject c0 =
          new NDNStringObject(testName, (String) null, SaveType.REPOSITORY, thandle2);
      c0.updateInBackground();

      NDNStringObject c1 =
          new NDNStringObject(testName, (String) null, SaveType.REPOSITORY, thandle3);
      c1.updateInBackground(true);

      Assert.assertFalse(c0.available());
      Assert.assertFalse(c0.isSaved());
      Assert.assertFalse(c1.available());
      Assert.assertFalse(c1.isSaved());

      NDNTime t1 = saveAndLog("First string", c2, null, "Here is the first string.");
      TestUtils.checkObject(thandle, c2);
      Log.info(
          Log.FAC_TEST,
          "Saved c2: "
              + c2.getVersionedName()
              + " c0 available? "
              + c0.available()
              + " c1 available? "
              + c1.available());
      c0.waitForData();
      Assert.assertEquals("c0 update", c0.getVersion(), c2.getVersion());
      c1.waitForData();
      Assert.assertEquals("c1 update", c1.getVersion(), c2.getVersion());

      NDNTime t2 = saveAndLog("Second string", c2, null, "Here is the second string.");
      TestUtils.checkObject(thandle, c2);
      doWait(c1, t2);
      Assert.assertEquals("c1 update 2", c1.getVersion(), c2.getVersion());
      Assert.assertEquals("c0 unchanged", c0.getVersion(), t1);

      // Sleep for a while and see how fast the interests come. Should be only 2 interests.
      Log.info(Log.FAC_TEST, "Sleeping, count background interests.");
      long time = System.currentTimeMillis();
      Thread.sleep(2000);
      long elapsed = System.currentTimeMillis() - time;
      long count = (elapsed / 4000) + 1;
      Log.info(
          Log.FAC_TEST,
          "Slept " + elapsed / 1000.0 + " seconds, should have been " + count + " interests.");

      NDNTime t3 = saveAndLog("Third string", c2, null, "Here is the third string.");
      TestUtils.checkObject(thandle, c2);
      doWait(c1, t3);
      Assert.assertEquals("c1 update 3", c1.getVersion(), c2.getVersion());
      Assert.assertEquals("c0 unchanged", c0.getVersion(), t1);

      c1.cancelInterest();
    } finally {
      thandle.close();
      thandle2.close();
      thandle3.close();
      KeyManager.closeDefaultKeyManager();
    }

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