diff --git a/core/src/test/java/com/google/bitcoin/core/TestWithPeerGroup.java b/core/src/test/java/com/google/bitcoin/core/TestWithPeerGroup.java index 0776397d..2cca1908 100644 --- a/core/src/test/java/com/google/bitcoin/core/TestWithPeerGroup.java +++ b/core/src/test/java/com/google/bitcoin/core/TestWithPeerGroup.java @@ -33,14 +33,18 @@ public class TestWithPeerGroup extends TestWithNetworkConnections { protected PeerGroup peerGroup; protected VersionMessage remoteVersionMessage; + private ClientBootstrap bootstrap; public void setUp(BlockStore blockStore) throws Exception { super.setUp(blockStore); remoteVersionMessage = new VersionMessage(unitTestParams, 1); remoteVersionMessage.clientVersion = FilteredBlock.MIN_PROTOCOL_VERSION; - - ClientBootstrap bootstrap = new ClientBootstrap(new ChannelFactory() { + initPeerGroup(); + } + + protected void initPeerGroup() { + bootstrap = new ClientBootstrap(new ChannelFactory() { public void releaseExternalResources() {} public Channel newChannel(ChannelPipeline pipeline) { ChannelSink sink = new FakeChannelSink(); @@ -52,7 +56,7 @@ public class TestWithPeerGroup extends TestWithNetworkConnections { public ChannelPipeline getPipeline() throws Exception { VersionMessage ver = new VersionMessage(unitTestParams, 1); ChannelPipeline p = Channels.pipeline(); - + Peer peer = new Peer(unitTestParams, blockChain, ver, peerGroup.getMemoryPool()); peer.addLifecycleListener(peerGroup.startupListener); p.addLast("peer", peer.getHandler()); @@ -63,7 +67,7 @@ public class TestWithPeerGroup extends TestWithNetworkConnections { peerGroup = new PeerGroup(unitTestParams, blockChain, bootstrap); peerGroup.setPingIntervalMsec(0); // Disable the pings as they just get in the way of most tests. } - + protected FakeChannel connectPeer(int id) { return connectPeer(id, remoteVersionMessage); } diff --git a/core/src/test/java/com/google/bitcoin/core/TransactionBroadcastTest.java b/core/src/test/java/com/google/bitcoin/core/TransactionBroadcastTest.java index d124c927..6e3e1a24 100644 --- a/core/src/test/java/com/google/bitcoin/core/TransactionBroadcastTest.java +++ b/core/src/test/java/com/google/bitcoin/core/TransactionBroadcastTest.java @@ -28,6 +28,7 @@ import java.util.Random; import static com.google.common.base.Preconditions.checkNotNull; import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class TransactionBroadcastTest extends TestWithPeerGroup { @Override @@ -67,6 +68,41 @@ public class TransactionBroadcastTest extends TestWithPeerGroup { assertTrue(future.isDone()); } + @Test + public void retryFailedBroadcast() throws Exception { + // If we create a spend, it's sent to a peer that swallows it, and the peergroup is removed/re-added then + // the tx should be broadcast again. + FakeChannel p1 = connectPeer(1, new VersionMessage(params, 2)); + connectPeer(2); + + // Send ourselves a bit of money. + Block b1 = TestUtils.makeSolvedTestBlock(blockStore, address); + inbound(p1, b1); + assertNull(outbound(p1)); + assertEquals(Utils.toNanoCoins(50, 0), wallet.getBalance()); + + // Now create a spend, and expect the announcement on p1. + Address dest = new ECKey().toAddress(params); + Wallet.SendResult sendResult = wallet.sendCoins(peerGroup, dest, Utils.toNanoCoins(1, 0)); + assertFalse(sendResult.broadcastComplete.isDone()); + Transaction t1 = (Transaction) outbound(p1); + assertFalse(sendResult.broadcastComplete.isDone()); + + // p1 eats it :( A bit later the PeerGroup is taken down. + peerGroup.removeWallet(wallet); + // ... and put back. + initPeerGroup(); + peerGroup.addWallet(wallet); + p1 = connectPeer(1, new VersionMessage(params, 2)); + connectPeer(2); + + // We want to hear about it again. Now, because we've disabled the randomness for the unit tests it will + // re-appear on p1 again. Of course in the real world it would end up with a different set of peers and + // select randomly so we get a second chance. + Transaction t2 = (Transaction) outbound(p1); + assertEquals(t1, t2); + } + @Test public void peerGroupWalletIntegration() throws Exception { // Make sure we can create spends, and that they are announced. Then do the same with offline mode. @@ -79,7 +115,6 @@ public class TransactionBroadcastTest extends TestWithPeerGroup { Block b1 = TestUtils.makeSolvedTestBlock(blockStore, address); inbound(p1, b1); assertNull(outbound(p1)); - assertEquals(Utils.toNanoCoins(50, 0), wallet.getBalance()); // Check that the wallet informs us of changes in confidence as the transaction ripples across the network. @@ -98,7 +133,7 @@ public class TransactionBroadcastTest extends TestWithPeerGroup { Threading.waitForUserCode(); assertFalse(sendResult.broadcastComplete.isDone()); assertEquals(transactions[0], sendResult.tx); - assertEquals(transactions[0].getConfidence().numBroadcastPeers(), 0); + assertEquals(0, transactions[0].getConfidence().numBroadcastPeers()); transactions[0] = null; Transaction t1 = (Transaction) outbound(p1); assertNotNull(t1);