/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
* This library 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
* Lesser General Public License for more details. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.test.profiles.versioning;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Random;
import java.util.TreeSet;
import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.impl.CCNFlowControl.SaveType;
import org.ccnx.ccn.io.content.CCNStringObject;
import org.ccnx.ccn.profiles.VersioningProfile;
import org.ccnx.ccn.profiles.versioning.InterestData;
import org.ccnx.ccn.profiles.versioning.VersionNumber;
import org.ccnx.ccn.profiles.versioning.VersioningInterestManager;
import org.ccnx.ccn.protocol.CCNTime;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.ContentObject;
import org.ccnx.ccn.protocol.Interest;
import org.ccnx.ccn.protocol.MalformedContentNameStringException;
import org.ccnx.ccn.test.profiles.versioning.VersioningHelper.TestListener;
import org.junit.Assert;
import org.junit.Test;
public class InterestDataTestRepo {
protected final Random _rnd = new Random();
protected final static long TIMEOUT=30000;
protected final ContentName prefix;
protected final VersionNumber vn_411000000000L = new VersionNumber(411000000000L);
protected final VersionNumber vn_411111000000L = new VersionNumber(411111000000L);
protected final VersionNumber vn_411222000000L = new VersionNumber(411222000000L);
protected final VersionNumber vn_411333000000L = new VersionNumber(411333000000L);
public InterestDataTestRepo() throws MalformedContentNameStringException {
prefix = ContentName.fromNative(String.format("/repotest/test_%016X", _rnd.nextLong()));
}
@Test
public void testVersionNumberInTree() throws Exception {
// make sure the sortable work
long [] values = new long [] {1111110000000L, 1110000000000L, 1113330000000L, 1112220000000L};
VersionNumber [] vns = new VersionNumber[values.length];
TreeSet<VersionNumber> tree = new TreeSet<VersionNumber>();
for(int i = 0; i < values.length; i++) {
vns[i] = new VersionNumber(values[i]);
tree.add(vns[i]);
}
// they should be in the same order as the sorted values
Arrays.sort(values);
Iterator<VersionNumber> iter = tree.iterator();
int index = 0;
while( iter.hasNext() ) {
VersionNumber v = iter.next();
Assert.assertEquals(values[index], v.getAsMillis());
index++;
}
}
@Test
public void testVersionNumberCompare() throws Exception {
// make sure the sortable work
VersionNumber a = new VersionNumber(new CCNTime(111111000000L));
VersionNumber aa = new VersionNumber(new CCNTime(111111000000L));
VersionNumber b = new VersionNumber(new CCNTime(111222000000L));
VersionNumber c = new VersionNumber(new CCNTime(111333000000L));
Assert.assertTrue(a.compareTo(b) < 0);
Assert.assertTrue(b.compareTo(a) > 0);
Assert.assertTrue(a.compareTo(aa) == 0);
Assert.assertTrue(a.compareTo(c) < 0);
Assert.assertTrue(b.compareTo(c) < 0);
Assert.assertTrue(c.compareTo(a) > 0);
Assert.assertTrue(c.compareTo(b) > 0);
}
@Test
public void testInterestDataStartTimeCompare() throws Exception {
ContentName basename = new ContentName(prefix, String.format("content_%016X", _rnd.nextLong()));
InterestData id1 = new InterestData(basename, vn_411000000000L, new VersionNumber(411110000010L));
InterestData id1a = new InterestData(basename, vn_411000000000L, new VersionNumber(411110000020L));
InterestData id2 = new InterestData(basename, vn_411222000000L, new VersionNumber(411330000000L));
InterestData.StartTimeComparator stc = new InterestData.StartTimeComparator();
Assert.assertTrue(stc.compare(id1, id1a) == 0);
Assert.assertTrue(stc.compare(id1a, id1) == 0);
Assert.assertTrue(stc.compare(id1, id2) < 0);
Assert.assertTrue(stc.compare(id2, id1) > 0);
}
/**
* Create one object then create an InterestData for it and make sure we get the object.
* @throws Exception
*/
@Test
public void testInterestDataInterest() throws Exception {
CCNHandle handle = CCNHandle.getHandle();
ContentName basename = new ContentName(prefix, String.format("content_%016X", _rnd.nextLong()));
TestListener listener = new TestListener();
InterestData id = new InterestData(basename);
// Save content
CCNStringObject so = new CCNStringObject(basename, "hello, world!", SaveType.LOCALREPOSITORY, handle);
so.save();
CCNTime version = so.getVersion();
so.close();
// Now use the interest to retrive it
Interest interest = id.buildInterest();
System.out.println("Expressing interest " + interest);
handle.expressInterest(interest, listener);
Assert.assertTrue( listener.cl.waitForValue(1L, TIMEOUT) );
// now make sure what we got is what we expected
ContentObject co = listener.received.get(0).object;
CCNTime received_version = VersioningProfile.getLastVersionAsTimestamp(co.name());
Assert.assertTrue(version.equals(received_version));
CCNStringObject received_so = new CCNStringObject(co, handle);
Assert.assertTrue(so.string().equals(received_so.string()));
}
/**
* Test an InterestData when retrieving many versions
* @throws Exception
*/
@Test
public void testInterestDataInterestStream() throws Exception {
CCNHandle handle = CCNHandle.getHandle();
ContentName basename = new ContentName(prefix, String.format("content_%016X", _rnd.nextLong()));
int tosend = 200;
// Send a stream of string objects
ArrayList<CCNStringObject> sent = VersioningHelper.sendEventStream(handle, basename, tosend);
// Now read them back
TestListener listener = new TestListener();
InterestData id = new InterestData(basename);
listener.setInterestData(id);
Assert.assertTrue( listener.run(handle, tosend, TIMEOUT) );
// now make sure what we got is what we sent
VersioningHelper.compareReceived(handle, sent, listener);
}
/**
* Test an InterestData when retrieving many versions, uses a start time between two streams.
* @throws Exception
*/
@Test
public void testInterestDataInterestStreamWithStartTime() throws Exception {
CCNHandle handle = CCNHandle.getHandle();
ContentName basename = new ContentName(prefix, String.format("content_%016X", _rnd.nextLong()));
int tosend = 100;
// Send a stream of string objects
ArrayList<CCNStringObject> sent1 = VersioningHelper.sendEventStream(handle, basename, tosend);
VersionNumber cutoff_version = new VersionNumber(sent1.get(sent1.size()-1).getVersion());
// now send another stream
ArrayList<CCNStringObject> sent2 = VersioningHelper.sendEventStream(handle, basename, tosend);
// Now read them back
TestListener listener = new TestListener();
InterestData id = new InterestData(basename, cutoff_version.addAndReturn(1), VersionNumber.getMaximumVersion());
listener.setInterestData(id);
Assert.assertTrue( listener.run(handle, tosend, TIMEOUT) );
// now make sure what we got is what we sent
VersioningHelper.compareReceived(handle, sent2, listener);
}
/**
* Test an InterestData when retrieving many versions, uses a start & stop time
* in the middle of three streams.
* @throws Exception
*/
@Test
public void testInterestDataInterestStreamWithStartAndStopTime() throws Exception {
CCNHandle handle = CCNHandle.getHandle();
ContentName basename = new ContentName(prefix, String.format("content_%016X", _rnd.nextLong()));
int tosend = 50;
// Send a stream of string objects
ArrayList<CCNStringObject> sent1 = VersioningHelper.sendEventStream(handle, basename, tosend);
VersionNumber start_version = new VersionNumber(sent1.get(sent1.size()-1).getVersion()).addAndReturn(1);
// now send another stream
ArrayList<CCNStringObject> sent2 = VersioningHelper.sendEventStream(handle, basename, tosend);
VersionNumber stop_version = new VersionNumber(sent2.get(sent2.size()-1).getVersion()).addAndReturn(1);
// Make sure everything in sent2 is between the start and stop versions
for(CCNStringObject so : sent2) {
Assert.assertTrue(start_version.before(so.getVersion()));
Assert.assertTrue(stop_version.after(so.getVersion()));
}
// now final stream
VersioningHelper.sendEventStream(handle, basename, tosend);
System.out.println(String.format("Start/stop versions %s to %s",
start_version.printAsVersionComponent(),
stop_version.printAsVersionComponent()));
// Now read them back
TestListener listener = new TestListener();
InterestData id = new InterestData(basename, start_version, stop_version);
listener.setInterestData(id);
Assert.assertTrue( listener.run(handle, tosend, TIMEOUT) );
// now make sure what we got is what we sent
VersioningHelper.compareReceived(handle, sent2, listener);
}
@Test
public void testSplitLeft() throws Exception {
// put a bunch of exclusions in an INterestData, then split it and check results.
ContentName basename = new ContentName(prefix, String.format("content_%016X", _rnd.nextLong()));
VersionNumber starttime = new VersionNumber();
VersionNumber stoptime = null;
int count = VersioningInterestManager.MAX_FILL;
InterestData data = new InterestData(basename, starttime, VersionNumber.getMaximumVersion());
VersionNumber t = starttime;
for(int i = 0; i < count; i++) {
// walk up to 100 seconds, converted to nanos, with minimum 1 msec
long walk = _rnd.nextInt(100000) * 1000000L + 1000000L;
t = t.addAndReturn(walk);
data.addExclude(t);
stoptime = t.addAndReturn(100);
data.setStopTime(stoptime);
}
// now split it, so MIN_FILL will stay in data, and the rest will go to left
InterestData left = data.splitLeft(data.size() - VersioningInterestManager.MIN_FILL);
Assert.assertTrue(left.getStartVersion().equals(starttime));
Assert.assertTrue(data.getStopVersion().equals(stoptime));
Assert.assertEquals(VersioningInterestManager.MIN_FILL, data.size());
Assert.assertEquals(count - VersioningInterestManager.MIN_FILL, left.size());
Assert.assertTrue(left.getStopVersion().addAndReturn(1).equals(data.getStartVersion()));
// Ensure data consistency
Assert.assertTrue(left.validate());
Assert.assertTrue(data.validate());
}
}