package com.limegroup.bittorrent.swarm; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import org.jmock.Expectations; import org.jmock.Mockery; import org.limewire.swarm.SwarmContent; import org.limewire.swarm.SwarmWriteJobControl; import com.limegroup.bittorrent.BTInterval; import com.limegroup.bittorrent.disk.TorrentDiskManager; import com.limegroup.gnutella.util.LimeTestCase; public class BTSwarmWriteJobTest extends LimeTestCase { public BTSwarmWriteJobTest(String name) { super(name); } public static Test suite() { return buildTestSuite(BTSwarmWriteJobTest.class); } public void testWriteOnePartialPieces() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(0, 9, 0); pieces.add(piece1); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(10); final byte[] data1 = { 0, 1, 2, 3, 4 }; contentBuffer.put(data1); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 0, 4, data1)); one(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } public void testWriteOnePiece() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(0, 9, 0); pieces.add(piece1); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(10); final byte[] data1 = { 0, 1, 2, 3, 4 }; final byte[] data2 = { 5, 6, 7, 8, 9 }; contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 0, 4, data1)); one(tdm).writeBlock(new BTNECallable(0, 5, 9, data2)); atLeast(2).of(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } public void testWriteTwoPieces() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(0, 9, 0); final BTInterval piece2 = new BTInterval(0, 9, 1); pieces.add(piece1); pieces.add(piece2); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(20); final byte[] data1 = { 0, 1, 2, 3, 4 }; final byte[] data2 = { 5, 6, 7, 8, 9 }; contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.put(data2); contentBuffer.put(data1); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 0, 4, data1)); one(tdm).writeBlock(new BTNECallable(0, 5, 9, data2)); one(tdm).writeBlock(new BTNECallable(1, 0, 4, data2)); one(tdm).writeBlock(new BTNECallable(1, 5, 9, data1)); atLeast(4).of(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } public void testWriteTwoPartialPieces() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(3, 6, 0); final BTInterval piece2 = new BTInterval(6, 9, 1); pieces.add(piece1); pieces.add(piece2); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(8); final byte[] data1 = { 0, 1, 2, 3 }; final byte[] data2 = { 6, 7, 8, 9 }; contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 3, 6, data1)); one(tdm).writeBlock(new BTNECallable(1, 6, 9, data2)); atLeast(2).of(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } public void testWriteThreePieces() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(0, 9, 0); final BTInterval piece2 = new BTInterval(0, 9, 1); final BTInterval piece3 = new BTInterval(0, 9, 2); pieces.add(piece1); pieces.add(piece2); pieces.add(piece3); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(30); final byte[] data1 = { 0, 1, 2, 3, 4 }; final byte[] data2 = { 5, 6, 7, 8, 9 }; contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.put(data2); contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.put(data2); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 0, 4, data1)); one(tdm).writeBlock(new BTNECallable(0, 5, 9, data2)); one(tdm).writeBlock(new BTNECallable(1, 0, 4, data2)); one(tdm).writeBlock(new BTNECallable(1, 5, 9, data1)); one(tdm).writeBlock(new BTNECallable(2, 0, 4, data2)); one(tdm).writeBlock(new BTNECallable(2, 5, 9, data2)); atLeast(4).of(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } public void testWriteThreePartialPieces() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(1, 9, 0); final BTInterval piece2 = new BTInterval(5, 9, 1); final BTInterval piece3 = new BTInterval(0, 2, 2); pieces.add(piece1); pieces.add(piece2); pieces.add(piece3); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(17); final byte[] data1 = { 0, 1, 2, 3, 4 }; final byte[] data2 = { 5, 6, 7, 8 }; final byte[] data3 = { 9, 10, 11, 12, 13 }; final byte[] data4 = { 14, 15, 16 }; contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.put(data3); contentBuffer.put(data4); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 1, 5, data1)); one(tdm).writeBlock(new BTNECallable(0, 6, 9, data2)); one(tdm).writeBlock(new BTNECallable(1, 5, 9, data3)); one(tdm).writeBlock(new BTNECallable(2, 0, 2, data4)); atLeast(4).of(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } public void testWriteThreePartialPiecesWriteCalledExtraTime() throws Exception { List<BTInterval> pieces = new ArrayList<BTInterval>(); final BTInterval piece1 = new BTInterval(1, 9, 0); final BTInterval piece2 = new BTInterval(5, 9, 1); final BTInterval piece3 = new BTInterval(0, 2, 2); pieces.add(piece1); pieces.add(piece2); pieces.add(piece3); Mockery mockery = new Mockery(); final TorrentDiskManager tdm = mockery.mock(TorrentDiskManager.class); final SwarmWriteJobControl callback = mockery.mock(SwarmWriteJobControl.class); final ByteBuffer contentBuffer = ByteBuffer.allocate(17); final byte[] data1 = { 0, 1, 2, 3, 4 }; final byte[] data2 = { 5, 6, 7, 8 }; final byte[] data3 = { 9, 10, 11, 12, 13 }; final byte[] data4 = { 14, 15, 16 }; contentBuffer.put(data1); contentBuffer.put(data2); contentBuffer.put(data3); contentBuffer.put(data4); contentBuffer.clear(); mockery.checking(new Expectations() { { one(tdm).writeBlock(new BTNECallable(0, 1, 5, data1)); one(tdm).writeBlock(new BTNECallable(0, 6, 9, data2)); one(tdm).writeBlock(new BTNECallable(1, 5, 9, data3)); one(tdm).writeBlock(new BTNECallable(2, 0, 2, data4)); atLeast(4).of(callback).resume(); } }); BTSwarmWriteJob swarmWriteJob = new BTSwarmWriteJob(pieces, tdm, callback, 5); SwarmContent content = new SwarmContentTester(contentBuffer); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); swarmWriteJob.write(content); mockery.assertIsSatisfied(); } private final class SwarmContentTester implements SwarmContent { private final ByteBuffer contentBuffer; private SwarmContentTester(ByteBuffer contentBuffer) { this.contentBuffer = contentBuffer; } public int read(ByteBuffer byteBuffer) throws IOException { int oldRemaining = byteBuffer.remaining(); if (contentBuffer.remaining() == 0) { return 0; } int oldLimit = contentBuffer.limit(); int remainingOffset = contentBuffer.remaining() - byteBuffer.remaining(); int newLimit = oldLimit - remainingOffset; if (newLimit < oldLimit) { contentBuffer.limit(newLimit); } byteBuffer.put(contentBuffer); contentBuffer.limit(oldLimit); int read = oldRemaining - byteBuffer.remaining(); return read; } } }