/*
* A CCNx library test.
*
* Copyright (C) 2008-2013 Palo Alto Research Center, Inc.
*
* This work is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License version 2 as published by the
* Free Software Foundation.
* This work is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
package org.ccnx.ccn.test.io.content;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.util.logging.Level;
import org.bouncycastle.util.Arrays;
import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.impl.CCNFlowServer;
import org.ccnx.ccn.impl.CCNFlowControl.SaveType;
import org.ccnx.ccn.impl.security.crypto.util.DigestHelper;
import org.ccnx.ccn.impl.support.Log;
import org.ccnx.ccn.io.CCNVersionedInputStream;
import org.ccnx.ccn.io.content.CCNNetworkObject;
import org.ccnx.ccn.io.content.CCNStringObject;
import org.ccnx.ccn.io.content.Collection;
import org.ccnx.ccn.io.content.Link;
import org.ccnx.ccn.io.content.LinkAuthenticator;
import org.ccnx.ccn.io.content.UpdateListener;
import org.ccnx.ccn.io.content.Collection.CollectionObject;
import org.ccnx.ccn.profiles.SegmentationProfile;
import org.ccnx.ccn.profiles.VersioningProfile;
import org.ccnx.ccn.protocol.CCNTime;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.ContentObject;
import org.ccnx.ccn.protocol.PublisherID;
import org.ccnx.ccn.protocol.SignedInfo;
import org.ccnx.ccn.protocol.PublisherID.PublisherType;
import org.ccnx.ccn.test.CCNTestHelper;
import org.ccnx.ccn.test.Flosser;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Test basic network object functionality, writing objects to a Flosser.
* Much slower than it needs to be -- seems to hit some kind of ordering
* bug which requires waiting for interest reexpression before it can go
* forward (shows up as mysterious 4-second delays in the log). The corresponding
* repo-backed test, CCNNetorkObjectTestRepo runs much faster to do exactly
* the same work.
* TODO track down slowness
*/
public class CCNNetworkObjectTest extends CCNNetworkObjectTestBase {
/**
* Handle naming for the test
*/
static CCNTestHelper testHelper = new CCNTestHelper(CCNNetworkObjectTest.class);
static void setupNamespace(ContentName name) throws IOException {
flosser.handleNamespace(name);
}
static void removeNamespace(ContentName name) throws IOException {
flosser.stopMonitoringNamespace(name);
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
try {
Log.info(Log.FAC_TEST, "Tearing down CCNNetworkObjectTest, prefix {0}", testHelper.getClassNamespace());
Log.flush();
if (flosser != null) {
flosser.stop();
flosser = null;
}
Log.info(Log.FAC_TEST, "Finished tearing down CCNNetworkObjectTest, prefix {0}", testHelper.getClassNamespace());
Log.flush();
} catch (Exception e) {
Log.severe(Log.FAC_TEST, "Exception in tearDownAfterClass: type {0} msg {0}", e.getClass().getName(), e.getMessage());
Log.warningStackTrace(e);
}
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
Log.info(Log.FAC_TEST, "Setting up CCNNetworkObjectTest, prefix {0}", testHelper.getClassNamespace());
handle = CCNHandle.open();
ns = new ContentName[NUM_LINKS];
for (int i=0; i < NUM_LINKS; ++i) {
ns[i] = new ContentName(testHelper.getClassNamespace(), "Links", prefix+Integer.toString(i));
}
Arrays.fill(publisherid1, (byte)6);
Arrays.fill(publisherid2, (byte)3);
pubID1 = new PublisherID(publisherid1, PublisherType.KEY);
pubID2 = new PublisherID(publisherid2, PublisherType.ISSUER_KEY);
las[0] = new LinkAuthenticator(pubID1);
las[1] = null;
las[2] = new LinkAuthenticator(pubID2, null, null,
SignedInfo.ContentType.DATA, contenthash1);
las[3] = new LinkAuthenticator(pubID1, null, CCNTime.now(),
null, contenthash1);
for (int j=4; j < NUM_LINKS; ++j) {
las[j] = new LinkAuthenticator(pubID2, null, CCNTime.now(), null, null);
}
lrs = new Link[NUM_LINKS];
for (int i=0; i < lrs.length; ++i) {
lrs[i] = new Link(ns[i],las[i]);
}
empty = new Collection();
small1 = new Collection();
small2 = new Collection();
for (int i=0; i < 5; ++i) {
small1.add(lrs[i]);
small2.add(lrs[i+5]);
}
big = new Collection();
for (int i=0; i < NUM_LINKS; ++i) {
big.add(lrs[i]);
}
flosser = new Flosser();
Log.info(Log.FAC_TEST, "Finished setting up CCNNetworkObjectTest, prefix is: {0}.", testHelper.getClassNamespace());
}
@AfterClass
public static void cleanupAfterClass() {
handle.close();
}
@Test
public void testVersioning() throws Exception {
Log.info(Log.FAC_TEST, "Starting testVersioning");
// Testing problem of disappearing versions, inability to get latest. Use simpler
// object than a collection.
CCNHandle lput = CCNHandle.open();
CCNHandle lget = CCNHandle.open();
ContentName testName = new ContentName(testHelper.getTestNamespace("testVersioning"), stringObjName);
try {
CCNStringObject so = new CCNStringObject(testName, "First value", SaveType.RAW, lput);
setupNamespace(testName);
CCNStringObject ro = null;
CCNStringObject ro2 = null;
CCNStringObject ro3, ro4; // make each time, to get a new handle.
CCNTime soTime, srTime, sr2Time, sr3Time, sr4Time, so2Time;
for (int i=0; i < numbers.length; ++i) {
soTime = saveAndLog(numbers[i], so, null, numbers[i]);
if (null == ro) {
ro = new CCNStringObject(testName, lget);
srTime = waitForDataAndLog(numbers[i], ro);
} else {
srTime = updateAndLog(numbers[i], ro, null);
}
if (null == ro2) {
ro2 = new CCNStringObject(testName, null);
sr2Time = waitForDataAndLog(numbers[i], ro2);
} else {
sr2Time = updateAndLog(numbers[i], ro2, null);
}
ro3 = new CCNStringObject(ro.getVersionedName(), null); // read specific version
sr3Time = waitForDataAndLog("UpdateToROVersion", ro3);
// Save a new version and pull old
so2Time = saveAndLog(numbers[i] + "-Update", so, null, numbers[i] + "-Update");
ro4 = new CCNStringObject(ro.getVersionedName(), null); // read specific version
sr4Time = waitForDataAndLog("UpdateAnotherToROVersion", ro4);
Log.info(Log.FAC_TEST, "Update " + i + ": Times: " + soTime + " " + srTime + " " + sr2Time + " " + sr3Time + " different: " + so2Time);
Assert.assertEquals("SaveTime doesn't match first read", soTime, srTime);
Assert.assertEquals("SaveTime doesn't match second read", soTime, sr2Time);
Assert.assertEquals("SaveTime doesn't match specific version read", soTime, sr3Time);
Assert.assertFalse("UpdateTime isn't newer than read time", soTime.equals(so2Time));
Assert.assertEquals("SaveTime doesn't match specific version read", soTime, sr4Time);
}
} finally {
removeNamespace(testName);
lput.close();
lget.close();
}
Log.info(Log.FAC_TEST, "Completed testVersioning");
}
@Test
public void testSaveToVersion() throws Exception {
Log.info(Log.FAC_TEST, "Starting testSaveToVersion");
// Testing problem of disappearing versions, inability to get latest. Use simpler
// object than a collection.
CCNHandle lput = CCNHandle.open();
CCNHandle lget = CCNHandle.open();
ContentName testName = new ContentName(testHelper.getTestNamespace("testSaveToVersion"), stringObjName);
try {
CCNTime desiredVersion = CCNTime.now();
CCNStringObject so = new CCNStringObject(testName, "First value", SaveType.RAW, lput);
setupNamespace(testName);
saveAndLog("SpecifiedVersion", so, desiredVersion, "Time: " + desiredVersion);
Assert.assertEquals("Didn't write correct version", desiredVersion, so.getVersion());
CCNStringObject ro = new CCNStringObject(testName, lget);
ro.waitForData();
Assert.assertEquals("Didn't read correct version", desiredVersion, ro.getVersion());
ContentName versionName = ro.getVersionedName();
saveAndLog("UpdatedVersion", so, null, "ReplacementData");
updateAndLog("UpdatedData", ro, null);
Assert.assertTrue("New version " + so.getVersion() + " should be later than old version " + desiredVersion, (desiredVersion.before(so.getVersion())));
Assert.assertEquals("Didn't read correct version", so.getVersion(), ro.getVersion());
CCNStringObject ro2 = new CCNStringObject(versionName, null);
ro2.waitForData();
Assert.assertEquals("Didn't read correct version", desiredVersion, ro2.getVersion());
} finally {
removeNamespace(testName);
lput.close();
lget.close();
}
Log.info(Log.FAC_TEST, "Completed testSaveToVersion");
}
@Test
public void testEmptySave() throws Exception {
Log.info(Log.FAC_TEST, "Starting testEmptySave");
boolean caught = false;
ContentName testName = new ContentName(testHelper.getTestNamespace("testEmptySave"), collectionObjName);
try {
CollectionObject emptycoll =
new CollectionObject(testName, (Collection)null, SaveType.RAW, handle);
setupNamespace(testName);
try {
emptycoll.setData(small1); // set temporarily to non-null
saveAndLog("Empty", emptycoll, null, null);
} catch (InvalidObjectException iox) {
// this is what we expect to happen
caught = true;
}
Assert.assertTrue("Failed to produce expected exception.", caught);
} finally {
removeNamespace(testName);
}
Log.info(Log.FAC_TEST, "Completed testEmptySave");
}
@Test
public void testStreamUpdate() throws Exception {
Log.info(Log.FAC_TEST, "Starting testStreamUpdate");
ContentName testName = new ContentName(testHelper.getTestNamespace("testStreamUpdate"), collectionObjName);
CCNHandle tHandle = CCNHandle.open();
try {
CollectionObject testCollectionObject = new CollectionObject(testName, small1, SaveType.RAW, tHandle);
setupNamespace(testName);
saveAndLog("testStreamUpdate", testCollectionObject, null, small1);
Log.info(Log.FAC_TEST, "testCollectionObject name: " + testCollectionObject.getVersionedName());
CCNVersionedInputStream vis = new CCNVersionedInputStream(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);
CCNVersionedInputStream vis2 = new CCNVersionedInputStream(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);
CCNVersionedInputStream vis3 = new CCNVersionedInputStream(testCollectionObject.getVersionedName());
Collection decodedData3 = new Collection();
decodedData3.decode(vis3);
Assert.assertEquals("Decoding via stream full read fails to give expected result!", decodedData3, small1);
} finally {
removeNamespace(testName);
tHandle.close();
}
Log.info(Log.FAC_TEST, "Completed testStreamUpdate");
}
@Test
public void testVersionOrdering() throws Exception {
Log.info(Log.FAC_TEST, "Starting testVersionOrdering");
ContentName testName = new ContentName(testHelper.getTestNamespace("testVersionOrdering"), collectionObjName, "name1");
ContentName testName2 = new ContentName(testHelper.getTestNamespace("testVersionOrdering"), collectionObjName, "name2");
CCNHandle tHandle = CCNHandle.open();
try {
CollectionObject c0 = new CollectionObject(testName, empty, SaveType.RAW, handle);
setupNamespace(testName);
CCNTime t0 = saveAndLog("Empty", c0, null, empty);
CollectionObject c1 = new CollectionObject(testName2, small1, SaveType.RAW, tHandle);
CollectionObject c2 = new CollectionObject(testName2, small1, SaveType.RAW, null);
setupNamespace(testName2);
CCNTime t1 = saveAndLog("Small", c1, null, small1);
Assert.assertTrue("First version should come before second", t0.before(t1));
CCNTime t2 = saveAndLog("Small2ndWrite", c2, null, small1);
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 {
removeNamespace(testName);
removeNamespace(testName2);
tHandle.close();
}
Log.info(Log.FAC_TEST, "Completed testVersionOrdering");
}
@Test
public void testUpdateOtherName() throws Exception {
Log.info(Log.FAC_TEST, "Started testUpdateOtherName");
CCNHandle tHandle = CCNHandle.open();
ContentName testName = new ContentName(testHelper.getTestNamespace("testUpdateOtherName"), collectionObjName, "name1");
ContentName testName2 = new ContentName(testHelper.getTestNamespace("testUpdateOtherName"), collectionObjName, "name2");
try {
CollectionObject c0 = new CollectionObject(testName, empty, SaveType.RAW, handle);
setupNamespace(testName);
CCNTime t0 = saveAndLog("Empty", c0, null, empty);
CollectionObject c1 = new CollectionObject(testName2, small1, SaveType.RAW, tHandle);
// Cheat a little, make this one before the setupNamespace...
CollectionObject c2 = new CollectionObject(testName2, small1, SaveType.RAW, null);
setupNamespace(testName2);
CCNTime t1 = saveAndLog("Small", c1, null, small1);
Assert.assertTrue("First version should come before second", t0.before(t1));
CCNTime t2 = saveAndLog("Small2ndWrite", c2, null, small1);
Assert.assertTrue("Third version should come after second", t1.before(t2));
Assert.assertTrue(c2.contentEquals(c1));
Assert.assertFalse(c2.equals(c1));
CCNTime t3 = updateAndLog(c0.getVersionedName().toString(), c0, testName2);
Assert.assertTrue(VersioningProfile.isVersionOf(c0.getVersionedName(), testName2));
Assert.assertEquals(t3, t2);
Assert.assertTrue(c0.contentEquals(c2));
t3 = updateAndLog(c0.getVersionedName().toString(), c0, c1.getVersionedName());
Assert.assertTrue(VersioningProfile.isVersionOf(c0.getVersionedName(), testName2));
Assert.assertEquals(t3, t1);
Assert.assertTrue(c0.contentEquals(c1));
} finally {
removeNamespace(testName);
removeNamespace(testName2);
tHandle.close();
}
Log.info(Log.FAC_TEST, "Completed testUpdateOtherName");
}
@Test
public void testUpdateInBackground() throws Exception {
Log.info(Log.FAC_TEST, "Starting testUpdateInBackground");
CCNHandle tHandle = CCNHandle.open();
CCNHandle tHandle2 = CCNHandle.open();
CCNHandle tHandle3 = CCNHandle.open();
ContentName testName = new ContentName(testHelper.getTestNamespace("testUpdateInBackground"), stringObjName, "name1");
try {
CCNStringObject c0 = new CCNStringObject(testName, (String)null, SaveType.RAW, tHandle);
c0.updateInBackground();
CCNStringObject c1 = new CCNStringObject(testName, (String)null, SaveType.RAW, tHandle2);
c1.updateInBackground(true);
Assert.assertFalse(c0.available());
Assert.assertFalse(c0.isSaved());
Assert.assertFalse(c1.available());
Assert.assertFalse(c1.isSaved());
CCNStringObject c2 = new CCNStringObject(testName, (String)null, SaveType.RAW, tHandle3);
CCNTime t1 = saveAndLog("First string", c2, null, "Here is the first string.");
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());
CCNTime t2 = saveAndLog("Second string", c2, null, "Here is the second string.");
doWait(c1, t2);
Assert.assertEquals("c1 update 2", c1.getVersion(), c2.getVersion());
Assert.assertEquals("c0 unchanged", c0.getVersion(), t1);
} finally {
removeNamespace(testName);
tHandle.close();
tHandle2.close();
tHandle3.close();
}
Log.info(Log.FAC_TEST, "Completed testUpdateInBackground");
}
@Test
public void testBackgroundVerifier() throws Exception {
Log.info(Log.FAC_TEST, "Starting testBackgroundVerifier");
ContentName testName = new ContentName(testHelper.getTestNamespace("testBackgroundVerifier"), stringObjName, "name1");
try {
CCNStringObject c0 = new CCNStringObject(testName, (String)null, SaveType.RAW, CCNHandle.open());
c0.updateInBackground(true);
CCNStringObject c1 = new CCNStringObject(testName, (String)null, SaveType.RAW, CCNHandle.open());
c1.updateInBackground(true);
CCNTime t1 = saveAndLog("First string", c0, null, "Here is the first string.");
doWait(c0, t1);
c1.waitForData();
CCNTime c1Version = c1.getVersion();
Assert.assertTrue(c0.available());
Assert.assertTrue(c0.isSaved());
Assert.assertTrue(c1.available());
Assert.assertTrue(c1.isSaved());
Assert.assertEquals(t1, c1Version);
// Test background ability to throw away bogus data.
// change the version so a) it's later, and b) the signature won't verify
ContentName laterName = SegmentationProfile.segmentName(VersioningProfile.updateVersion(c1.getVersionedName()),
SegmentationProfile.baseSegment());
CCNFlowServer server = new CCNFlowServer(testName, null, false, CCNHandle.open());
server.addNameSpace(laterName);
ContentObject bogon =
new ContentObject(laterName, c0.getFirstSegment().signedInfo(),
c0.getFirstSegment().content(), c0.getFirstSegment().signature());
Log.info(Log.FAC_TEST, "Writing bogon: {0}", bogon.fullName());
server.put(bogon);
Thread.sleep(300);
// Should be no update
Assert.assertEquals(c0.getVersion(), c1Version);
Assert.assertEquals(c1.getVersion(), c1Version);
// Now write a newer one
CCNStringObject c2 = new CCNStringObject(testName, (String)null, SaveType.RAW, CCNHandle.open());
CCNTime t2 = saveAndLog("Second string", c2, null, "Here is the second string.");
Log.info(Log.FAC_TEST, "Saved c2: " + c2.getVersionedName() + " c0 available? " + c0.available() + " c1 available? " + c1.available());
doWait(c0, t2);
Assert.assertEquals("c0 update", c0.getVersion(), c2.getVersion());
doWait(c1, t2);
Assert.assertEquals("c1 update", c1.getVersion(), c2.getVersion());
Assert.assertFalse(c1Version.equals(c1.getVersion()));
} finally {
removeNamespace(testName);
}
Log.info(Log.FAC_TEST, "Completed testBackgroundVerifier");
}
@Test
public void testSaveAsGone() throws Exception {
Log.info(Log.FAC_TEST, "Starting testSaveAsGone");
ContentName testName = new ContentName(testHelper.getTestNamespace("testSaveAsGone"), collectionObjName);
CCNHandle tHandle = CCNHandle.open();
CCNHandle tHandle2 = CCNHandle.open();
try {
Log.info(Log.FAC_TEST, "TSAG: Entering testSaveAsGone");
CollectionObject c0 = new CollectionObject(testName, empty, SaveType.RAW, handle);
setupNamespace(testName); // this sends the interest, doing it after the object gives it
// a chance to catch it.
CCNTime t0 = saveAsGoneAndLog("FirstGoneSave", c0);
Assert.assertTrue("Should be gone", c0.isGone());
ContentName goneVersionName = c0.getVersionedName();
Log.info(Log.FAC_TEST, "T1");
CCNTime t1 = saveAndLog("NotGone", c0, null, small1);
Assert.assertFalse("Should not be gone", c0.isGone());
Assert.assertTrue(t1.after(t0));
Log.info(Log.FAC_TEST, "T2");
CollectionObject c1 = new CollectionObject(testName, tHandle);
CCNTime t2 = waitForDataAndLog(testName.toString(), c1);
Assert.assertFalse("Read back should not be gone", c1.isGone());
Assert.assertEquals(t2, t1);
Log.info(Log.FAC_TEST, "T3");
CCNTime 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());
Log.info(Log.FAC_TEST, "T4");
t0 = saveAsGoneAndLog("GoneAgain", c0);
Assert.assertTrue("Should be gone", c0.isGone());
Log.info(Log.FAC_TEST, "TSAG: Updating new object: {0}", testName);
CollectionObject c2 = new CollectionObject(testName, tHandle2);
Log.info(Log.FAC_TEST, "TSAG: Waiting for: {0}", testName);
CCNTime t4 = waitForDataAndLog(testName.toString(), c2);
Log.info(Log.FAC_TEST, "TSAG: Waited for: {0}", c2.getVersionedName());
Assert.assertTrue("Read back of " + c0.getVersionedName() + " should be gone, got " + c2.getVersionedName(), c2.isGone());
Assert.assertEquals(t4, t0);
Log.info(Log.FAC_TEST, "TSAG: Leaving testSaveAsGone.");
} finally {
removeNamespace(testName);
tHandle.close();
tHandle2.close();
}
Log.info(Log.FAC_TEST, "Completed testSaveAsGone");
}
@Test
public void testUpdateDoesNotExist() throws Exception {
Log.info(Log.FAC_TEST, "Starting testUpdateDoesNotExist");
ContentName testName = new ContentName(testHelper.getTestNamespace("testUpdateDoesNotExist"), collectionObjName);
CCNHandle tHandle = CCNHandle.open();
try {
Log.info(Log.FAC_TEST, "CCNNetworkObjectTest: Entering testUpdateDoesNotExist");
CCNStringObject so = new CCNStringObject(testName, handle);
// so should catch exception thrown by underlying stream when it times out.
Assert.assertFalse(so.available());
// try to pick up anything that happens to appear
so.updateInBackground();
CCNStringObject sowrite = new CCNStringObject(testName, "Now we write something.", SaveType.RAW, tHandle);
setupNamespace(testName);
saveAndLog("testUpdateDoesNotExist: Delayed write", sowrite, null, "Now we write something.");
Log.flush();
so.waitForData();
Assert.assertTrue(so.available());
Assert.assertEquals(so.string(), sowrite.string());
Assert.assertEquals(so.getVersionedName(), sowrite.getVersionedName());
Log.info(Log.FAC_TEST, "CCNNetworkObjectTest: Leaving testUpdateDoesNotExist");
Log.flush();
} finally {
removeNamespace(testName);
tHandle.close();
}
Log.info(Log.FAC_TEST, "Completed testUpdateDoesNotExist");
}
@Test
public void testFirstSegmentInfo() throws Exception {
Log.info(Log.FAC_TEST, "Starting testFirstSegmentInfo");
// Testing for matching info about first segment.
CCNHandle lput = CCNHandle.open();
CCNHandle lget = CCNHandle.open();
ContentName testName = new ContentName(testHelper.getTestNamespace("testFirstSegmentInfo"), stringObjName);
try {
CCNTime desiredVersion = CCNTime.now();
CCNStringObject so = new CCNStringObject(testName, "First value", SaveType.RAW, lput);
setupNamespace(testName);
saveAndLog("SpecifiedVersion", so, desiredVersion, "Time: " + desiredVersion);
Assert.assertEquals("Didn't write correct version", desiredVersion, so.getVersion());
CCNStringObject ro = new CCNStringObject(testName, lget);
ro.waitForData();
Assert.assertEquals("Didn't read correct version", desiredVersion, ro.getVersion());
Assert.assertEquals("Didn't match first segment number", so.firstSegmentNumber(), ro.firstSegmentNumber());
Assert.assertArrayEquals("Didn't match first segment digest", so.getFirstDigest(), ro.getFirstDigest());
} finally {
removeNamespace(testName);
lput.close();
lget.close();
}
Log.info(Log.FAC_TEST, "Completed testFirstSegmentInfo");
}
static class CounterListener implements UpdateListener {
protected Integer _callbackCounter = 0;
public int getCounter() { return _callbackCounter; }
public void newVersionAvailable(CCNNetworkObject<?> newVersion, boolean wasSave) {
synchronized (this) {
_callbackCounter++;
if (Log.isLoggable(Log.FAC_TEST, Level.INFO)) {
Log.info(Log.FAC_TEST, "UPDATE CALLBACK: counter is " + _callbackCounter + " was save? " + wasSave);
}
}
}
}
@Test
public void testUpdateListener() throws Exception {
Log.info(Log.FAC_TEST, "Starting testUpdateListener");
SaveType saveType = SaveType.RAW;
CCNHandle writeHandle = CCNHandle.open();
CCNHandle readHandle = CCNHandle.open();
ContentName testName = new ContentName(testHelper.getTestNamespace("testUpdateListener"),
stringObjName);
CounterListener ourListener = new CounterListener();
CCNStringObject readObject =
new CCNStringObject(testName, null, null, readHandle);
readObject.addListener(ourListener);
setupNamespace(testName);
CCNStringObject writeObject =
new CCNStringObject(testName, "Something to listen to.", saveType, writeHandle);
writeObject.save();
boolean result = readObject.update();
Assert.assertTrue(result);
Assert.assertTrue(ourListener.getCounter() == 1);
readObject.updateInBackground();
writeObject.save("New stuff! New stuff!");
synchronized(readObject) {
while (ourListener.getCounter() == 1)
readObject.wait();
}
// For some reason, we're getting two updates on our updateInBackground...
Assert.assertTrue(ourListener.getCounter() > 1);
writeHandle.close();
readHandle.close();
Log.info(Log.FAC_TEST, "Completed testUpdateListener");
}
@Test
public void testVeryLast() throws Exception {
Log.info("CCNNetworkObjectTest: Entering testVeryLast -- dummy test to help track down blowup. Prefix {0}", testHelper.getClassNamespace());
Thread.sleep(1000);
Log.info("CCNNetworkObjectTest: Leaving testVeryLast -- dummy test to help track down blowup. Prefix {0}", testHelper.getClassNamespace());
}
}