package com.limegroup.gnutella.downloader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashSet; import java.util.Set; import junit.framework.Test; import com.limegroup.gnutella.DownloadManager; import com.limegroup.gnutella.Downloader; import com.limegroup.gnutella.RemoteFileDesc; import com.limegroup.gnutella.RouterService; import com.limegroup.gnutella.URN; import com.limegroup.gnutella.messages.QueryRequest; import com.limegroup.gnutella.stubs.ActivityCallbackStub; import com.limegroup.gnutella.stubs.DownloadManagerStub; import com.limegroup.gnutella.stubs.FileManagerStub; import com.limegroup.gnutella.util.CommonUtils; import com.limegroup.gnutella.util.ConverterObjectInputStream; import com.limegroup.gnutella.util.PrivilegedAccessor; /** * Unit tests small parts of ResumeDownloader. See RequeryDownloadTest for * larger integration tests. * @see RequeryDownloadTest */ public class ResumeDownloaderTest extends com.limegroup.gnutella.util.BaseTestCase { static final String filePath="com/limegroup/gnutella/downloader/"; static final String queryName = "filename"; static final String name="filename.txt"; static final URN hash=TestFile.hash(); static final int size=1111; static final int amountDownloaded=500; static final RemoteFileDesc rfd=newRFD(name, size, hash); static final IncompleteFileManager ifm=new IncompleteFileManager(); static File incompleteFile; public static void globalSetUp() throws Exception { new RouterService(new ActivityCallbackStub()); incompleteFile=ifm.getFile(rfd); VerifyingFile vf=new VerifyingFile(size); vf.addInterval(new Interval(0, amountDownloaded-1)); //inclusive ifm.addEntry(incompleteFile, vf); // Make sure that we don't wait for network on requery ManagedDownloader.NO_DELAY = true; } public ResumeDownloaderTest(String name) { super(name); } public static Test suite() { return buildTestSuite(ResumeDownloaderTest.class); } /** Returns a new ResumeDownloader with stubbed-out DownloadManager, etc. */ private static ResumeDownloader newResumeDownloader() { // this ResumeDownloader is started from the library, not from restart, // that is why the last param to init is false ResumeDownloader ret=new ResumeDownloader(ifm,incompleteFile,name,size); DownloadManagerStub dm = new DownloadManagerStub(); dm.initialize(); dm.scheduleWaitingPump(); ret.initialize(dm, new FileManagerStub(), new ActivityCallbackStub()); ret.startDownload(); return ret; } private static RemoteFileDesc newRFD(String name, int size, URN hash) { Set urns=new HashSet(1); if (hash!=null) urns.add(hash); return new RemoteFileDesc("1.2.3.4", 6346, 13l, name, size, new byte[16], 56, false, 4, true, null, urns, false, false,"",0,null, -1); } //////////////////////////////////////////////////////////////////////////// /** Tests that the progress is not 0% while requerying. * This issue was reported by Sam Berlin. */ public void testRequeryProgress() throws Exception { ResumeDownloader downloader=newResumeDownloader(); while (downloader.getState()!=Downloader.WAITING_FOR_RESULTS) { if ( downloader.getState() != Downloader.QUEUED ) assertEquals(Downloader.GAVE_UP, downloader.getState()); Thread.sleep(200); } // give the downloader time to change its state Thread.sleep(1000); assertEquals(Downloader.WAITING_FOR_RESULTS, downloader.getState()); assertEquals(amountDownloaded, downloader.getAmountRead()); //Serialize it! ByteArrayOutputStream baos=new ByteArrayOutputStream(); ObjectOutputStream out=new ObjectOutputStream(baos); out.writeObject(downloader); out.flush(); out.close(); downloader.stop(); //Deserialize it as a different instance. Initialize. ObjectInputStream in=new ObjectInputStream( new ByteArrayInputStream(baos.toByteArray())); downloader=(ResumeDownloader)in.readObject(); in.close(); DownloadManager dm = new DownloadManagerStub(); dm.initialize(); dm.scheduleWaitingPump(); downloader.initialize(dm, new FileManagerStub(), new ActivityCallbackStub()); downloader.startDownload(); //Check same state as before serialization. try { Thread.sleep(200); } catch (InterruptedException e) { } assertEquals(Downloader.WAITING_FOR_USER, downloader.getState()); assertEquals(amountDownloaded, downloader.getAmountRead()); downloader.stop(); } /** Tests serialization of version 1.2 of ResumeDownloader. * (LimeWire 2.7.0/2.7.1 beta.) */ public void testSerialization12() throws Exception { tSerialization("ResumeDownloader.1_2.dat", false); } /** Tests serialization of version 1.3 of ResumeDownloader. * (LimeWire 2.7.3) */ public void testSerialization13() throws Exception { tSerialization("ResumeDownloader.1_3.dat", true); } /** Generic serialization testing routing. * @param file the serialized ResumeDownloader to read * @param expectHash true iff there should be a hash in the downloader */ private void tSerialization(String file, boolean expectHash) throws Exception { ObjectInputStream in=new ConverterObjectInputStream( new FileInputStream( CommonUtils.getResourceFile(filePath + file) ) ); ResumeDownloader rd=(ResumeDownloader)in.readObject(); QueryRequest qr = rd.newRequery(0); URN _hash = (URN) PrivilegedAccessor.getValue(rd, "_hash"); if (expectHash) { assertEquals("unexpected hash", hash, _hash); // filenames were put in hash queries since everyone drops // assertEquals("hash query should have name", queryName, qr.getQuery()); } // we never send URNs assertEquals("unexpected amount of urns", 0, qr.getQueryUrns().size()); assertEquals("unexpected query name", "filename", qr.getQuery()); assertEquals("unexpected filename", "filename.txt", rd.getSaveFile().getName()); } /** Writes the ResumeDownloader.dat file generated for testSerialization. * This should be run to generate a new version when ResumeDownloader * changes. */ public static void main(String args[]) { try { ResumeDownloader rd=newResumeDownloader(); ObjectOutputStream out=new ObjectOutputStream( new FileOutputStream( CommonUtils.getResourceFile( filePath + "ResumeDownloader.dat" ) ) ); out.writeObject(rd); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } }