/* * A CCNx library test. * * Copyright (C) 2008, 2009, 2011 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.repo; import java.io.IOException; import java.util.ArrayList; import org.ccnx.ccn.impl.repo.RepositoryException; import org.ccnx.ccn.impl.support.DataUtils; import org.ccnx.ccn.impl.support.Log; import org.ccnx.ccn.io.CCNReader; import org.ccnx.ccn.protocol.ContentName; import org.ccnx.ccn.protocol.ContentObject; import org.ccnx.ccn.protocol.Exclude; import org.ccnx.ccn.protocol.Interest; import org.ccnx.ccn.protocol.PublisherID; import org.ccnx.ccn.protocol.PublisherPublicKeyDigest; import org.junit.Assert; import org.junit.Test; /** * Part of repository test infrastructure. This test must be run after RFSTest and can be * run only once correctly after running RFSTest. * * This test tests reading of unusual objects which can't be written to a running repo * via the current repo writing algorithms. The data needed for this test can only be created * by something like RFSTest which creates and saves a repo file structure without a running * repo by calling saveContent methods directly with different kinds of data. * * It is normally desirable that tests such as this can be run repeatedly and achieve the same * results. But since we can't write the data to be tested via the repo, and once we have read the * data once, it may be cached by ccnd, a correct running of the test after the first time can't be * guaranteed and is in fact unlikely with this test. Possibly this test should just be eliminated but * since it is part of the historic repo test suite I am leaving it in for the time being. */ public class RepoInitialReadTest extends RepoTestBase { public static final long TIMEOUT = 5000; @Test public void testReadViaRepo() throws Throwable { Log.info(Log.FAC_TEST, "Starting testReadViaRepo"); ContentName name = ContentName.fromNative("/repoTest/data1"); // Since we have 2 pieces of data with the name /repoTest/data1 we need to compute both // digests to make sure we get the right data. ContentName name1 = findFullName(name, "Here's my data!"); ContentName digestName = findFullName(name, "Testing2"); String tooLongName = "0123456789"; for (int i = 0; i < 30; i++) tooLongName += "0123456789"; // Have 2 pieces of data with the same name here too. ContentName longName = findFullName(ContentName.fromNative("/repoTest/" + tooLongName), "Long name!"); ContentName badCharName = ContentName.fromNative("/repoTest/" + "*x?y<z>u"); ContentName badCharLongName = ContentName.fromNative("/repoTest/" + tooLongName + "*x?y<z>u"); checkDataWithDigest(name1, "Here's my data!"); checkDataWithDigest(digestName, "Testing2"); checkDataWithDigest(longName, "Long name!"); checkData(badCharName, "Funny characters!"); checkData(badCharLongName, "Long and funny"); CCNReader reader = new CCNReader(getHandle); ArrayList<ContentObject>keys = reader.enumerate(new Interest(keyprefix), 4000); for (ContentObject keyObject : keys) { checkDataAndPublisher(name, "Testing2", new PublisherPublicKeyDigest(keyObject.content())); } Log.info(Log.FAC_TEST, "Completed testReadViaRepo"); } /** * Find a content object by name (without digest) and content, and return the full name (with digest) * @param name ContentName without digest component * @param str The content * @return ContentName with implicit digest * @throws IOException */ private ContentName findFullName(ContentName name, String str) throws IOException { byte[] content = str.getBytes(); Exclude e = null; for(;;) { Interest i = Interest.constructInterest(name, e, Interest.CHILD_SELECTOR_LEFT, null, null, null); Log.info("searching for {0} content {1}, exclude {2}", name, str, e); ContentObject co = getHandle.get(i, TIMEOUT); Assert.assertTrue(null != co); Log.info("got result {0} digest={1}", co, DataUtils.printHexBytes(co.digest())); if (DataUtils.arrayEquals(co.content(), content)) return co.fullName(); byte [][]omissions = { co.digest() }; if (e == null) e = new Exclude(omissions); else e.add(omissions); } } private void checkDataWithDigest(ContentName name, String data) throws RepositoryException, IOException, InterruptedException { // When generating an Interest for the exact name with content digest, need to set maxSuffixComponents // to 0, signifying that name ends with explicit digest Interest interest = new Interest(name); interest.maxSuffixComponents(0); checkData(interest, data.getBytes()); } private void checkDataAndPublisher(ContentName name, String data, PublisherPublicKeyDigest publisher) throws IOException, InterruptedException { Interest interest = new Interest(name, new PublisherID(publisher)); ContentObject testContent = getHandle.get(interest, 10000); Assert.assertFalse(testContent == null); Assert.assertEquals(data, new String(testContent.content())); Assert.assertTrue(testContent.signedInfo().getPublisherKeyID().equals(publisher)); } }