From daa2f6713ab7c6c367805f9c9547032b91d7f803 Mon Sep 17 00:00:00 2001 From: Patrick Woodworth Date: Thu, 22 Aug 2013 11:12:42 -0700 Subject: [PATCH] Remove changes unrelated to new tests and reformat for code style --- .../com/turn/ttorrent/common/Torrent.java | 25 +- .../com/turn/ttorrent/tracker/Tracker.java | 33 +- src/test/java/com/turn/ttorrent/FileUtil.java | 84 ++-- .../java/com/turn/ttorrent/TempFiles.java | 272 +++++----- src/test/java/com/turn/ttorrent/WaitFor.java | 49 +- .../com/turn/ttorrent/common/TorrentTest.java | 35 +- .../turn/ttorrent/tracker/TrackerTest.java | 471 +++++++++--------- src/test/resources/log4j.properties | 9 + 8 files changed, 494 insertions(+), 484 deletions(-) create mode 100644 src/test/resources/log4j.properties diff --git a/src/main/java/com/turn/ttorrent/common/Torrent.java b/src/main/java/com/turn/ttorrent/common/Torrent.java index 1f698e074..40e8a0c95 100644 --- a/src/main/java/com/turn/ttorrent/common/Torrent.java +++ b/src/main/java/com/turn/ttorrent/common/Torrent.java @@ -133,6 +133,7 @@ public TorrentFile(File file, long size) { * BitTorrent specification) and create a Torrent object from it. * * @param torrent The meta-info byte data. + * @param parent The parent directory or location of the torrent files. * @param seeder Whether we'll be seeding for this torrent or not. * @throws IOException When the info dictionary can't be read or * encoded and hashed back to create the torrent's SHA-1 hash. @@ -401,22 +402,22 @@ public boolean isSeeder() { return this.seeder; } - /** + /** * Save this torrent meta-info structure into a .torrent file. * * @param file The file to write to. * @throws IOException If an I/O error occurs while writing the file. */ public void save(File file) throws IOException { - FileOutputStream fOut = null; - try { - fOut = new FileOutputStream(file); - fOut.write(this.getEncoded()); - } finally { - if (fOut != null){ - fOut.close(); - } - } + FileOutputStream fOut = null; + try { + fOut = new FileOutputStream(file); + fOut.write(this.getEncoded()); + } finally { + if (fOut != null) { + fOut.close(); + } + } } public static byte[] hash(byte[] data) throws NoSuchAlgorithmException { @@ -961,8 +962,8 @@ public static void main(String[] args) { torrent = Torrent.create(source, announceURI, creator); } - fos.write(torrent.getEncoded()); - } else { + fos.write(torrent.getEncoded()); + } else { Torrent.load(new File(filenameValue), true); } } catch (Exception e) { diff --git a/src/main/java/com/turn/ttorrent/tracker/Tracker.java b/src/main/java/com/turn/ttorrent/tracker/Tracker.java index 94174697d..f9edd2148 100644 --- a/src/main/java/com/turn/ttorrent/tracker/Tracker.java +++ b/src/main/java/com/turn/ttorrent/tracker/Tracker.java @@ -183,15 +183,15 @@ public void stop() { } } - public ConcurrentMap getTorrentsMap() { - return torrents; - } - - public Collection getTrackedTorrents(){ - return torrents.values(); - } + /** + * + * @return list of tracker's torrents + */ + public Collection getTrackedTorrents() { + return torrents.values(); + } - /** + /** * Announce a new torrent on this tracker. * *

@@ -206,7 +206,8 @@ public Collection getTrackedTorrents(){ * different from the supplied Torrent object if the tracker already * contained a torrent with the same hash. */ - public synchronized TrackedTorrent announce(Torrent torrent) throws IOException, NoSuchAlgorithmException { + public synchronized TrackedTorrent announce(Torrent torrent) + throws IOException, NoSuchAlgorithmException { TrackedTorrent existing = this.torrents.get(torrent.getHexInfoHash()); if (existing != null) { @@ -215,13 +216,13 @@ public synchronized TrackedTorrent announce(Torrent torrent) throws IOException, return existing; } - final TrackedTorrent result; - if (torrent instanceof TrackedTorrent) { - result = (TrackedTorrent) torrent; - } else { - result = new TrackedTorrent(torrent); - } - this.torrents.put(torrent.getHexInfoHash(), result); + final TrackedTorrent result; + if (torrent instanceof TrackedTorrent) { + result = (TrackedTorrent)torrent; + } else { + result = new TrackedTorrent(torrent); + } + this.torrents.put(torrent.getHexInfoHash(), result); logger.info("Registered new torrent for '{}' with hash {}.", torrent.getName(), torrent.getHexInfoHash()); return result; diff --git a/src/test/java/com/turn/ttorrent/FileUtil.java b/src/test/java/com/turn/ttorrent/FileUtil.java index 3abff5e1d..05ce87adc 100644 --- a/src/test/java/com/turn/ttorrent/FileUtil.java +++ b/src/test/java/com/turn/ttorrent/FileUtil.java @@ -7,50 +7,50 @@ public class FileUtil { - public static File getTempDirectory() { - return new File(System.getProperty("java.io.tmpdir")); - } + public static File getTempDirectory() { + return new File(System.getProperty("java.io.tmpdir")); + } - public static void delete(File file) { - if (file.isDirectory()) { - File[] files = file.listFiles(); - for (File f: files) { - delete(f); - } - } - deleteFile(file); - } + public static void delete(File file) { + if (file.isDirectory()) { + File[] files = file.listFiles(); + for (File f : files) { + delete(f); + } + } + deleteFile(file); + } - private static boolean deleteFile(File file) { - if (!file.exists()) return false; - for (int i=0; i<10; i++) { - if (file.delete()) return true; - try { - Thread.sleep(1); - } catch (InterruptedException e) { - // - } - } - return false; - } + private static boolean deleteFile(File file) { + if (!file.exists()) return false; + for (int i = 0; i < 10; i++) { + if (file.delete()) return true; + try { + Thread.sleep(1); + } catch (InterruptedException e) { + // + } + } + return false; + } - public static void writeFile(File file, String content) throws IOException { - FileWriter fw = null; - try { - fw = new FileWriter(file); - fw.write(content); - } finally { - close(fw); - } - } + public static void writeFile(File file, String content) throws IOException { + FileWriter fw = null; + try { + fw = new FileWriter(file); + fw.write(content); + } finally { + close(fw); + } + } - public static void close(Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (IOException e) { - // - } - } - } + public static void close(Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (IOException e) { + // + } + } + } } diff --git a/src/test/java/com/turn/ttorrent/TempFiles.java b/src/test/java/com/turn/ttorrent/TempFiles.java index bf0953d1a..6f497654a 100644 --- a/src/test/java/com/turn/ttorrent/TempFiles.java +++ b/src/test/java/com/turn/ttorrent/TempFiles.java @@ -1,136 +1,146 @@ package com.turn.ttorrent; -import java.io.*; -import java.util.*; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; public class TempFiles { - private static final File ourCurrentTempDir = FileUtil.getTempDirectory(); - private final File myCurrentTempDir; - - private static Random ourRandom; - - static { - ourRandom = new Random(); - ourRandom.setSeed(System.currentTimeMillis()); - } - - private final List myFilesToDelete = new ArrayList(); - private final Thread myShutdownHook; - private volatile boolean myInsideShutdownHook; - - public TempFiles() { - myCurrentTempDir = ourCurrentTempDir; - if (!myCurrentTempDir.isDirectory()) { - - throw new IllegalStateException("Temp directory is not a directory, was deleted by some process: " + myCurrentTempDir.getAbsolutePath() + - "\njava.io.tmpdir: " + FileUtil.getTempDirectory()); - } - - myShutdownHook = new Thread(new Runnable() { - public void run() { - myInsideShutdownHook = true; - cleanup(); - } - }); - Runtime.getRuntime().addShutdownHook(myShutdownHook); - } - - private File doCreateTempDir(String prefix, String suffix) throws IOException { - prefix = prefix == null ? "" : prefix; - suffix = suffix == null ? ".tmp" : suffix; - - do { - int count = ourRandom.nextInt(); - final File f = new File(myCurrentTempDir, prefix + count + suffix); - if (!f.exists() && f.mkdirs()) { - return f.getCanonicalFile(); - } - } while (true); - - } - private File doCreateTempFile(String prefix, String suffix) throws IOException { - final File file = doCreateTempDir(prefix, suffix); - file.delete(); - file.createNewFile(); - return file; - } - - public final File createTempFile(String content) throws IOException { - File tempFile = createTempFile(); - FileUtil.writeFile(tempFile, content); - return tempFile; - } - - public final File createTempFile() throws IOException { - File tempFile = doCreateTempFile("test", null); - registerAsTempFile(tempFile); - return tempFile; - } - - public void registerAsTempFile(final File tempFile) { - myFilesToDelete.add(tempFile); - } - - public final File createTempFile(int size) throws IOException { - File tempFile = createTempFile(); - int bufLen = Math.min(8 * 1024, size); - if (bufLen == 0) return tempFile; - final OutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile)); - try { - byte[] buf = new byte[bufLen]; - for (int i=0; i < buf.length; i++) { - buf[i] = (byte)Math.round(Math.random()*128); - } - - int numWritten = 0; - for (int i=0; i numWritten) { - fos.write(buf, 0, size - numWritten); - } - } finally { - fos.close(); - } - - return tempFile; - } - - /** - * Returns a File object for created temp directory. - * Also stores the value into this object accessed with {@link #getCurrentTempDir()} - * - * @return a File object for created temp directory - * @throws IOException if directory creation fails. - */ - public final File createTempDir() throws IOException { - File f = doCreateTempDir("test", ""); - registerAsTempFile(f); - return f; - } - - /** - * Returns the current directory used by the test or null if no test is running or no directory is created yet. - * - * @return see above - */ - public File getCurrentTempDir() { - return myCurrentTempDir; - } - - public void cleanup() { - try { - for (File file : myFilesToDelete) { - FileUtil.delete(file); - } - - myFilesToDelete.clear(); - } finally { - if (!myInsideShutdownHook) { - Runtime.getRuntime().removeShutdownHook(myShutdownHook); - } - } - } + + private static final File ourCurrentTempDir = FileUtil.getTempDirectory(); + private final File myCurrentTempDir; + + private static Random ourRandom; + + static { + ourRandom = new Random(); + ourRandom.setSeed(System.currentTimeMillis()); + } + + private final List myFilesToDelete = new ArrayList(); + private final Thread myShutdownHook; + private volatile boolean myInsideShutdownHook; + + public TempFiles() { + myCurrentTempDir = ourCurrentTempDir; + if (!myCurrentTempDir.isDirectory()) { + + throw new IllegalStateException("Temp directory is not a directory, was deleted by some process: " + myCurrentTempDir.getAbsolutePath() + + "\njava.io.tmpdir: " + FileUtil.getTempDirectory()); + } + + myShutdownHook = new Thread(new Runnable() { + public void run() { + myInsideShutdownHook = true; + cleanup(); + } + }); + Runtime.getRuntime().addShutdownHook(myShutdownHook); + } + + private File doCreateTempDir(String prefix, String suffix) + throws IOException { + prefix = prefix == null ? "" : prefix; + suffix = suffix == null ? ".tmp" : suffix; + + do { + int count = ourRandom.nextInt(); + final File f = new File(myCurrentTempDir, prefix + count + suffix); + if (!f.exists() && f.mkdirs()) { + return f.getCanonicalFile(); + } + } while (true); + + } + + private File doCreateTempFile(String prefix, String suffix) + throws IOException { + final File file = doCreateTempDir(prefix, suffix); + file.delete(); + file.createNewFile(); + return file; + } + + public final File createTempFile(String content) throws IOException { + File tempFile = createTempFile(); + FileUtil.writeFile(tempFile, content); + return tempFile; + } + + public final File createTempFile() throws IOException { + File tempFile = doCreateTempFile("test", null); + registerAsTempFile(tempFile); + return tempFile; + } + + public void registerAsTempFile(final File tempFile) { + myFilesToDelete.add(tempFile); + } + + public final File createTempFile(int size) throws IOException { + File tempFile = createTempFile(); + int bufLen = Math.min(8 * 1024, size); + if (bufLen == 0) return tempFile; + final OutputStream fos = new BufferedOutputStream(new FileOutputStream(tempFile)); + try { + byte[] buf = new byte[bufLen]; + for (int i = 0; i < buf.length; i++) { + buf[i] = (byte)Math.round(Math.random() * 128); + } + + int numWritten = 0; + for (int i = 0; i < size / buf.length; i++) { + fos.write(buf); + numWritten += buf.length; + } + + if (size > numWritten) { + fos.write(buf, 0, size - numWritten); + } + } finally { + fos.close(); + } + + return tempFile; + } + + /** + * Returns a File object for created temp directory. + * Also stores the value into this object accessed with {@link #getCurrentTempDir()} + * + * @return a File object for created temp directory + * @throws IOException if directory creation fails. + */ + public final File createTempDir() throws IOException { + File f = doCreateTempDir("test", ""); + registerAsTempFile(f); + return f; + } + + /** + * Returns the current directory used by the test or null if no test is running or no directory is created yet. + * + * @return see above + */ + public File getCurrentTempDir() { + return myCurrentTempDir; + } + + public void cleanup() { + try { + for (File file : myFilesToDelete) { + FileUtil.delete(file); + } + + myFilesToDelete.clear(); + } finally { + if (!myInsideShutdownHook) { + Runtime.getRuntime().removeShutdownHook(myShutdownHook); + } + } + } } \ No newline at end of file diff --git a/src/test/java/com/turn/ttorrent/WaitFor.java b/src/test/java/com/turn/ttorrent/WaitFor.java index 41ab425ed..2551a3ed7 100644 --- a/src/test/java/com/turn/ttorrent/WaitFor.java +++ b/src/test/java/com/turn/ttorrent/WaitFor.java @@ -1,33 +1,34 @@ package com.turn.ttorrent; public abstract class WaitFor { - private long myPollInterval = 100; - protected WaitFor() { - this(40 * 1000); - } + private long myPollInterval = 100; - protected WaitFor(long timeout) { - long started = System.currentTimeMillis(); - try { - while(true) { - if (condition()) return; - if (System.currentTimeMillis() - started < timeout) { - Thread.sleep(myPollInterval); - } else { - break; - } - } + protected WaitFor() { + this(40 * 1000); + } - } catch (InterruptedException e) { - //NOP - } - } + protected WaitFor(long timeout) { + long started = System.currentTimeMillis(); + try { + while (true) { + if (condition()) return; + if (System.currentTimeMillis() - started < timeout) { + Thread.sleep(myPollInterval); + } else { + break; + } + } - protected WaitFor(long timeout, long pollInterval) { - this(timeout); - myPollInterval = pollInterval; - } + } catch (InterruptedException e) { + //NOP + } + } - protected abstract boolean condition(); + protected WaitFor(long timeout, long pollInterval) { + this(timeout); + myPollInterval = pollInterval; + } + + protected abstract boolean condition(); } diff --git a/src/test/java/com/turn/ttorrent/common/TorrentTest.java b/src/test/java/com/turn/ttorrent/common/TorrentTest.java index 666fde629..cfbaf19a5 100644 --- a/src/test/java/com/turn/ttorrent/common/TorrentTest.java +++ b/src/test/java/com/turn/ttorrent/common/TorrentTest.java @@ -1,30 +1,27 @@ package com.turn.ttorrent.common; -import org.testng.annotations.Test; - import java.io.File; -import java.io.IOException; import java.net.URI; -import java.net.URISyntaxException; -import java.security.NoSuchAlgorithmException; + +import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; @Test -public class TorrentTest { +public class TorrentTest { - public void test_create_torrent() throws URISyntaxException, IOException, NoSuchAlgorithmException, InterruptedException { - URI announceURI = new URI("http://localhost:6969/announce"); - String createdBy = "Test"; - Torrent t = Torrent.create(new File("src/test/resources/parentFiles/file1.jar"), announceURI, createdBy); - assertEquals(createdBy, t.getCreatedBy()); - assertEquals(announceURI, t.getAnnounceList().get(0).get(0)); - } + public void test_create_torrent() throws Exception { + URI announceURI = new URI("http://localhost:6969/announce"); + String createdBy = "Test"; + Torrent t = Torrent.create(new File("src/test/resources/parentFiles/file1.jar"), announceURI, createdBy); + assertEquals(createdBy, t.getCreatedBy()); + assertEquals(announceURI, t.getAnnounceList().get(0).get(0)); + } - public void load_torrent_created_by_utorrent() throws IOException, NoSuchAlgorithmException, URISyntaxException { - Torrent t = Torrent.load(new File("src/test/resources/torrents/file1.jar.torrent")); - assertEquals(new URI("http://localhost:6969/announce"), t.getAnnounceList().get(0).get(0)); - assertEquals("B92D38046C76D73948E14C42DF992CAF25489D08", t.getHexInfoHash()); - assertEquals("uTorrent/3130", t.getCreatedBy()); - } + public void load_torrent_created_by_utorrent() throws Exception { + Torrent t = Torrent.load(new File("src/test/resources/torrents/file1.jar.torrent")); + assertEquals(new URI("http://localhost:6969/announce"), t.getAnnounceList().get(0).get(0)); + assertEquals("B92D38046C76D73948E14C42DF992CAF25489D08", t.getHexInfoHash()); + assertEquals("uTorrent/3130", t.getCreatedBy()); + } } diff --git a/src/test/java/com/turn/ttorrent/tracker/TrackerTest.java b/src/test/java/com/turn/ttorrent/tracker/TrackerTest.java index 7742ea48a..590dacc07 100644 --- a/src/test/java/com/turn/ttorrent/tracker/TrackerTest.java +++ b/src/test/java/com/turn/ttorrent/tracker/TrackerTest.java @@ -5,256 +5,247 @@ import com.turn.ttorrent.client.Client; import com.turn.ttorrent.client.SharedTorrent; import com.turn.ttorrent.common.Torrent; -import org.apache.commons.io.FileUtils; -import org.apache.log4j.BasicConfigurator; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.URISyntaxException; import java.security.NoSuchAlgorithmException; -import java.util.*; +import java.util.Collection; +import java.util.Map; import java.util.zip.CRC32; import java.util.zip.Checksum; +import org.apache.commons.io.FileUtils; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + import static org.testng.Assert.*; @Test -public class TrackerTest { - private static final String TEST_RESOURCES = "src/test/resources"; - private Tracker tracker; - private TempFiles tempFiles; - - @BeforeMethod - protected void setUp() throws Exception { - BasicConfigurator.configure(); - tempFiles = new TempFiles(); - startTracker(); - } - - public void test_share_and_download() throws IOException, NoSuchAlgorithmException, InterruptedException { - final TrackedTorrent tt = this.tracker.announce(loadTorrent("file1.jar.torrent")); - assertEquals(0, tt.getPeers().size()); - - Client seeder = createClient(completeTorrent("file1.jar.torrent")); - - assertEquals(tt.getHexInfoHash(), seeder.getTorrent().getHexInfoHash()); - - final File downloadDir = tempFiles.createTempDir(); - Client leech = createClient(incompleteTorrent("file1.jar.torrent", downloadDir)); - - try { - seeder.share(); - - leech.download(); - - waitForFileInDir(downloadDir, "file1.jar"); - assertFilesEqual(new File(TEST_RESOURCES + "/parentFiles/file1.jar"), new File(downloadDir, "file1.jar")); - } finally { - leech.stop(true); - seeder.stop(true); - } - } - - public void tracker_accepts_torrent_from_seeder() throws IOException, NoSuchAlgorithmException, InterruptedException { - final SharedTorrent torrent = completeTorrent("file1.jar.torrent"); - tracker.announce(torrent); - Client seeder = createClient(torrent); - - try { - seeder.share(); - - waitForSeeder(seeder.getTorrent().getInfoHash()); - - Collection trackedTorrents = this.tracker.getTrackedTorrents(); - assertEquals(1, trackedTorrents.size()); - - TrackedTorrent trackedTorrent = trackedTorrents.iterator().next(); - Map peers = trackedTorrent.getPeers(); - assertEquals(1, peers.size()); - assertTrue(peers.values().iterator().next().isCompleted()); // seed - assertEquals(1, trackedTorrent.seeders()); - assertEquals(0, trackedTorrent.leechers()); - } finally { - seeder.stop(true); - } - } - - public void tracker_accepts_torrent_from_leech() throws IOException, NoSuchAlgorithmException, InterruptedException { - - final File downloadDir = tempFiles.createTempDir(); - final SharedTorrent torrent = incompleteTorrent("file1.jar.torrent", downloadDir); - tracker.announce(torrent); - Client leech = createClient(torrent); - - try { - leech.download(); - - waitForPeers(1); - - Collection trackedTorrents = this.tracker.getTrackedTorrents(); - assertEquals(1, trackedTorrents.size()); - - TrackedTorrent trackedTorrent = trackedTorrents.iterator().next(); - Map peers = trackedTorrent.getPeers(); - assertEquals(1, peers.size()); - assertFalse(peers.values().iterator().next().isCompleted()); // leech - assertEquals(0, trackedTorrent.seeders()); - assertEquals(1, trackedTorrent.leechers()); - } finally { - leech.stop(true); - } - } - - public void tracker_accepts_torrent_from_seeder_plus_leech() throws IOException, NoSuchAlgorithmException, InterruptedException { - assertEquals(0, this.tracker.getTrackedTorrents().size()); - - final SharedTorrent completeTorrent = completeTorrent("file1.jar.torrent"); - tracker.announce(completeTorrent); - Client seeder = createClient(completeTorrent); - - final File downloadDir = tempFiles.createTempDir(); - final SharedTorrent incompleteTorrent = incompleteTorrent("file1.jar.torrent", downloadDir); - Client leech = createClient(incompleteTorrent); - - try { - seeder.share(); - leech.download(); - - waitForFileInDir(downloadDir, "file1.jar"); - } finally { - seeder.stop(true); - leech.stop(true); - } - } - - private Set listFileNames(File downloadDir) { - if (downloadDir == null) return Collections.emptySet(); - Set names = new HashSet(); - File[] files = downloadDir.listFiles(); - if (files == null) return Collections.emptySet(); - for (File f: files) { - names.add(f.getName()); - } - return names; - } - - - public void large_file_download() throws IOException, URISyntaxException, NoSuchAlgorithmException, InterruptedException { - - - File tempFile = tempFiles.createTempFile(201 * 1024 * 1024); - - Torrent torrent = Torrent.create(tempFile, this.tracker.getAnnounceUrl().toURI(), "Test"); - File torrentFile = new File(tempFile.getParentFile(), tempFile.getName() + ".torrent"); - torrent.save(torrentFile); - tracker.announce(torrent); - - Client seeder = createClient(SharedTorrent.fromFile(torrentFile, tempFile.getParentFile())); - - final File downloadDir = tempFiles.createTempDir(); - Client leech = createClient(SharedTorrent.fromFile(torrentFile, downloadDir)); - - try { - seeder.share(); - leech.download(); - - waitForFileInDir(downloadDir, tempFile.getName()); - assertFilesEqual(tempFile, new File(downloadDir, tempFile.getName())); - } finally { - seeder.stop(true); - leech.stop(true); - } - } - - public void test_announce() throws IOException, NoSuchAlgorithmException { - assertEquals(0, this.tracker.getTrackedTorrents().size()); - - this.tracker.announce(loadTorrent("file1.jar.torrent")); - - assertEquals(1, this.tracker.getTrackedTorrents().size()); - } - - private void waitForSeeder(final byte[] torrentHash) { - new WaitFor() { - @Override - protected boolean condition() { - for (TrackedTorrent tt: TrackerTest.this.tracker.getTrackedTorrents()) { - if (tt.seeders() == 1 && tt.getHexInfoHash().equals(Torrent.byteArrayToHexString(torrentHash))) return true; - } - - return false; - } - }; - } - - private void waitForPeers(final int numPeers) { - new WaitFor() { - @Override - protected boolean condition() { - for (TrackedTorrent tt: TrackerTest.this.tracker.getTrackedTorrents()) { - if (tt.getPeers().size() == numPeers) return true; - } - - return false; - } - }; - } - - private void waitForFileInDir(final File downloadDir, final String fileName) { - new WaitFor() { - @Override - protected boolean condition() { - return new File(downloadDir, fileName).isFile(); - } - }; - - assertTrue(new File(downloadDir, fileName).isFile()); - } - - private TrackedTorrent loadTorrent(String name) throws IOException, NoSuchAlgorithmException { - return new TrackedTorrent(Torrent.load(new File(TEST_RESOURCES + "/torrents", name), true)); - } - - - @AfterMethod - protected void tearDown() throws Exception { - stopTracker(); - tempFiles.cleanup(); - } - - private void startTracker() throws IOException { - this.tracker = new Tracker(new InetSocketAddress(6969)); - this.tracker.start(); - } - - private Client createClient(SharedTorrent torrent) throws IOException, NoSuchAlgorithmException, InterruptedException { - return new Client(InetAddress.getLocalHost(), torrent); - } - - private SharedTorrent completeTorrent(String name) throws IOException, NoSuchAlgorithmException { - File torrentFile = new File(TEST_RESOURCES + "/torrents", name); - File parentFiles = new File(TEST_RESOURCES + "/parentFiles"); - return SharedTorrent.fromFile(torrentFile, parentFiles); - } - - private SharedTorrent incompleteTorrent(String name, File destDir) throws IOException, NoSuchAlgorithmException { - File torrentFile = new File(TEST_RESOURCES + "/torrents", name); - return SharedTorrent.fromFile(torrentFile, destDir); - } - - private void stopTracker() { - this.tracker.stop(); - } - - private void assertFilesEqual(File f1, File f2) throws IOException { - assertEquals(f1.length(), f2.length(), "Files size differs"); - Checksum c1 = FileUtils.checksum(f1, new CRC32()); - Checksum c2 = FileUtils.checksum(f2, new CRC32()); - assertEquals(c1.getValue(), c2.getValue()); - } +public class TrackerTest { + + private static final String TEST_RESOURCES = "src/test/resources"; + private Tracker tracker; + private TempFiles tempFiles; + + @BeforeMethod(alwaysRun = true) + protected void setUp() throws Exception { + tempFiles = new TempFiles(); + startTracker(); + } + + @AfterMethod(alwaysRun = true) + protected void tearDown() throws Exception { + stopTracker(); + tempFiles.cleanup(); + } + + public void test_share_and_download() throws Exception { + final TrackedTorrent tt = this.tracker.announce(loadTorrent("file1.jar.torrent")); + assertEquals(0, tt.getPeers().size()); + + Client seeder = createClient(completeTorrent("file1.jar.torrent")); + + assertEquals(tt.getHexInfoHash(), seeder.getTorrent().getHexInfoHash()); + + final File downloadDir = tempFiles.createTempDir(); + Client leech = createClient(incompleteTorrent("file1.jar.torrent", downloadDir)); + + try { + seeder.share(); + + leech.download(); + + waitForFileInDir(downloadDir, "file1.jar"); + assertFilesEqual(new File(TEST_RESOURCES + "/parentFiles/file1.jar"), new File(downloadDir, "file1.jar")); + } finally { + leech.stop(true); + seeder.stop(true); + } + } + + public void tracker_accepts_torrent_from_seeder() throws Exception { + final SharedTorrent torrent = completeTorrent("file1.jar.torrent"); + tracker.announce(torrent); + Client seeder = createClient(torrent); + + try { + seeder.share(); + + waitForSeeder(seeder.getTorrent().getInfoHash()); + + Collection trackedTorrents = this.tracker.getTrackedTorrents(); + assertEquals(1, trackedTorrents.size()); + + TrackedTorrent trackedTorrent = trackedTorrents.iterator().next(); + Map peers = trackedTorrent.getPeers(); + assertEquals(1, peers.size()); + assertTrue(peers.values().iterator().next().isCompleted()); // seed + assertEquals(1, trackedTorrent.seeders()); + assertEquals(0, trackedTorrent.leechers()); + } finally { + seeder.stop(true); + } + } + + public void tracker_accepts_torrent_from_leech() throws Exception { + + final File downloadDir = tempFiles.createTempDir(); + final SharedTorrent torrent = incompleteTorrent("file1.jar.torrent", downloadDir); + tracker.announce(torrent); + Client leech = createClient(torrent); + + try { + leech.download(); + + waitForPeers(1); + + Collection trackedTorrents = this.tracker.getTrackedTorrents(); + assertEquals(1, trackedTorrents.size()); + + TrackedTorrent trackedTorrent = trackedTorrents.iterator().next(); + Map peers = trackedTorrent.getPeers(); + assertEquals(1, peers.size()); + assertFalse(peers.values().iterator().next().isCompleted()); // leech + assertEquals(0, trackedTorrent.seeders()); + assertEquals(1, trackedTorrent.leechers()); + } finally { + leech.stop(true); + } + } + + public void tracker_accepts_torrent_from_seeder_plus_leech() throws Exception { + assertEquals(0, this.tracker.getTrackedTorrents().size()); + + final SharedTorrent completeTorrent = completeTorrent("file1.jar.torrent"); + tracker.announce(completeTorrent); + Client seeder = createClient(completeTorrent); + + final File downloadDir = tempFiles.createTempDir(); + final SharedTorrent incompleteTorrent = incompleteTorrent("file1.jar.torrent", downloadDir); + Client leech = createClient(incompleteTorrent); + + try { + seeder.share(); + leech.download(); + + waitForFileInDir(downloadDir, "file1.jar"); + } finally { + seeder.stop(true); + leech.stop(true); + } + } + + public void large_file_download() throws Exception { + + File tempFile = tempFiles.createTempFile(201 * 1024 * 1024); + + Torrent torrent = Torrent.create(tempFile, this.tracker.getAnnounceUrl().toURI(), "Test"); + File torrentFile = new File(tempFile.getParentFile(), tempFile.getName() + ".torrent"); + torrent.save(torrentFile); + tracker.announce(torrent); + + Client seeder = createClient(SharedTorrent.fromFile(torrentFile, tempFile.getParentFile())); + + final File downloadDir = tempFiles.createTempDir(); + Client leech = createClient(SharedTorrent.fromFile(torrentFile, downloadDir)); + + try { + seeder.share(); + leech.download(); + + waitForFileInDir(downloadDir, tempFile.getName()); + assertFilesEqual(tempFile, new File(downloadDir, tempFile.getName())); + } finally { + seeder.stop(true); + leech.stop(true); + } + } + + public void test_announce() throws Exception { + assertEquals(0, this.tracker.getTrackedTorrents().size()); + + this.tracker.announce(loadTorrent("file1.jar.torrent")); + + assertEquals(1, this.tracker.getTrackedTorrents().size()); + } + + private void waitForSeeder(final byte[] torrentHash) { + new WaitFor() { + @Override + protected boolean condition() { + for (TrackedTorrent tt : TrackerTest.this.tracker.getTrackedTorrents()) { + if (tt.seeders() == 1 && tt.getHexInfoHash().equals(Torrent.byteArrayToHexString(torrentHash))) + return true; + } + + return false; + } + }; + } + + private void waitForPeers(final int numPeers) { + new WaitFor() { + @Override + protected boolean condition() { + for (TrackedTorrent tt : TrackerTest.this.tracker.getTrackedTorrents()) { + if (tt.getPeers().size() == numPeers) return true; + } + + return false; + } + }; + } + + private void waitForFileInDir(final File downloadDir, final String fileName) { + new WaitFor(120 * 1000) { + @Override + protected boolean condition() { + return new File(downloadDir, fileName).isFile(); + } + }; + + assertTrue(new File(downloadDir, fileName).isFile()); + } + + private TrackedTorrent loadTorrent(String name) + throws IOException, NoSuchAlgorithmException { + return new TrackedTorrent(Torrent.load(new File(TEST_RESOURCES + "/torrents", name), true)); + } + + private void startTracker() throws IOException { + this.tracker = new Tracker(new InetSocketAddress(6969)); + this.tracker.start(); + } + + private Client createClient(SharedTorrent torrent) + throws IOException, NoSuchAlgorithmException, InterruptedException { + return new Client(InetAddress.getLocalHost(), torrent); + } + + private SharedTorrent completeTorrent(String name) + throws IOException, NoSuchAlgorithmException { + File torrentFile = new File(TEST_RESOURCES + "/torrents", name); + File parentFiles = new File(TEST_RESOURCES + "/parentFiles"); + return SharedTorrent.fromFile(torrentFile, parentFiles); + } + + private SharedTorrent incompleteTorrent(String name, File destDir) + throws IOException, NoSuchAlgorithmException { + File torrentFile = new File(TEST_RESOURCES + "/torrents", name); + return SharedTorrent.fromFile(torrentFile, destDir); + } + + private void stopTracker() { + this.tracker.stop(); + } + + private void assertFilesEqual(File f1, File f2) throws IOException { + assertEquals(f1.length(), f2.length(), "Files size differs"); + Checksum c1 = FileUtils.checksum(f1, new CRC32()); + Checksum c2 = FileUtils.checksum(f2, new CRC32()); + assertEquals(c1.getValue(), c2.getValue()); + } } diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 000000000..5fe42d854 --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,9 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=DEBUG, A1 + +# A1 is set to be a ConsoleAppender. +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n