Program: 85836
Project: 85836
Buggy source:
@Test public void recursiveDownload() throws Exception {
  ECKey to=new ECKey();
  control.replay();
  connect();
  final Transaction[] onTx=new Transaction[1];
  peer.addEventListener(new AbstractPeerEventListener(){
    @Override public void onTransaction(    Peer peer1,    Transaction t){
      onTx[0]=t;
    }
  }
);
  Transaction t2=TestUtils.createFakeTx(unitTestParams,Utils.toNanoCoins(1,0),to);
  Sha256Hash t5=t2.getInput(0).getOutpoint().getHash();
  Transaction t4=TestUtils.createFakeTx(unitTestParams,Utils.toNanoCoins(1,0),new ECKey());
  Sha256Hash t6=t4.getInput(0).getOutpoint().getHash();
  t4.addOutput(Utils.toNanoCoins(1,0),new ECKey());
  Transaction t3=new Transaction(unitTestParams);
  t3.addInput(t4.getOutput(0));
  t3.addOutput(Utils.toNanoCoins(1,0),new ECKey());
  Transaction t1=new Transaction(unitTestParams);
  t1.addInput(t2.getOutput(0));
  t1.addInput(t3.getOutput(0));
  t1.addOutput(Utils.toNanoCoins(1,0),to);
  t1=TestUtils.roundTripTransaction(unitTestParams,t1);
  t2=TestUtils.roundTripTransaction(unitTestParams,t2);
  t3=TestUtils.roundTripTransaction(unitTestParams,t3);
  t4=TestUtils.roundTripTransaction(unitTestParams,t4);
  InventoryMessage inv=new InventoryMessage(unitTestParams);
  inv.addTransaction(t1);
  inbound(peer,inv);
  GetDataMessage getdata=(GetDataMessage)outbound();
  assertEquals(t1.getHash(),getdata.getItems().get(0).hash);
  inbound(peer,t1);
  assertEquals(t1,onTx[0]);
  ListenableFuture<List<Transaction>> futures=peer.downloadDependencies(t1);
  assertFalse(futures.isDone());
  getdata=(GetDataMessage)outbound();
  assertEquals(t2.getHash(),getdata.getItems().get(0).hash);
  assertEquals(t3.getHash(),getdata.getItems().get(1).hash);
  inbound(peer,t4);
  inbound(peer,t2);
  inbound(peer,t3);
  assertFalse(futures.isDone());
  getdata=(GetDataMessage)outbound();
  assertEquals(getdata.getItems().get(0).hash,t2.getInput(0).getOutpoint().getHash());
  NotFoundMessage notFound=new NotFoundMessage(unitTestParams);
  notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction,t5));
  inbound(peer,notFound);
  assertFalse(futures.isDone());
  getdata=(GetDataMessage)outbound();
  assertEquals(t6,getdata.getItems().get(0).hash);
  notFound=new NotFoundMessage(unitTestParams);
  notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction,t6));
  inbound(peer,notFound);
  assertTrue(futures.isDone());
  List<Transaction> results=futures.get();
  assertTrue(results.contains(t2));
  assertTrue(results.contains(t3));
  assertTrue(results.contains(t4));
}

Fixed version (ground truth):
public void recursiveDownload(boolean useNotFound) throws Exception {
  control.replay();
  connectWithVersion(useNotFound ? 70001 : 60001);
  ECKey to=new ECKey();
  final Transaction[] onTx=new Transaction[1];
  peer.addEventListener(new AbstractPeerEventListener(){
    @Override public void onTransaction(    Peer peer1,    Transaction t){
      onTx[0]=t;
    }
  }
);
  Transaction t2=TestUtils.createFakeTx(unitTestParams,Utils.toNanoCoins(1,0),to);
  Sha256Hash t5=t2.getInput(0).getOutpoint().getHash();
  Transaction t4=TestUtils.createFakeTx(unitTestParams,Utils.toNanoCoins(1,0),new ECKey());
  Sha256Hash t6=t4.getInput(0).getOutpoint().getHash();
  t4.addOutput(Utils.toNanoCoins(1,0),new ECKey());
  Transaction t3=new Transaction(unitTestParams);
  t3.addInput(t4.getOutput(0));
  t3.addOutput(Utils.toNanoCoins(1,0),new ECKey());
  Transaction t1=new Transaction(unitTestParams);
  t1.addInput(t2.getOutput(0));
  t1.addInput(t3.getOutput(0));
  Sha256Hash someHash=new Sha256Hash("String_Node_Str");
  t1.addInput(new TransactionInput(unitTestParams,t1,new byte[]{},new TransactionOutPoint(unitTestParams,0,someHash)));
  Sha256Hash anotherHash=new Sha256Hash("String_Node_Str");
  t1.addInput(new TransactionInput(unitTestParams,t1,new byte[]{},new TransactionOutPoint(unitTestParams,1,anotherHash)));
  t1.addOutput(Utils.toNanoCoins(1,0),to);
  t1=TestUtils.roundTripTransaction(unitTestParams,t1);
  t2=TestUtils.roundTripTransaction(unitTestParams,t2);
  t3=TestUtils.roundTripTransaction(unitTestParams,t3);
  t4=TestUtils.roundTripTransaction(unitTestParams,t4);
  InventoryMessage inv=new InventoryMessage(unitTestParams);
  inv.addTransaction(t1);
  inbound(peer,inv);
  GetDataMessage getdata=(GetDataMessage)outbound();
  assertEquals(t1.getHash(),getdata.getItems().get(0).hash);
  inbound(peer,t1);
  assertEquals(t1,onTx[0]);
  ListenableFuture<List<Transaction>> futures=peer.downloadDependencies(t1);
  assertFalse(futures.isDone());
  getdata=(GetDataMessage)outbound();
  assertEquals(4,getdata.getItems().size());
  assertEquals(t2.getHash(),getdata.getItems().get(0).hash);
  assertEquals(t3.getHash(),getdata.getItems().get(1).hash);
  assertEquals(someHash,getdata.getItems().get(2).hash);
  assertEquals(anotherHash,getdata.getItems().get(3).hash);
  long nonce=-1;
  if (!useNotFound)   nonce=((Ping)outbound()).getNonce();
  inbound(peer,t4);
  inbound(peer,t2);
  inbound(peer,t3);
  if (useNotFound) {
    NotFoundMessage notFound=new NotFoundMessage(unitTestParams);
    notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction,someHash));
    notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction,anotherHash));
    inbound(peer,notFound);
  }
 else {
    inbound(peer,new Pong(nonce));
  }
  assertFalse(futures.isDone());
  getdata=(GetDataMessage)outbound();
  assertEquals(getdata.getItems().get(0).hash,t2.getInput(0).getOutpoint().getHash());
  if (useNotFound) {
    NotFoundMessage notFound=new NotFoundMessage(unitTestParams);
    notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction,t5));
    inbound(peer,notFound);
  }
 else {
    bouncePing();
  }
  assertFalse(futures.isDone());
  getdata=(GetDataMessage)outbound();
  assertEquals(t6,getdata.getItems().get(0).hash);
  if (useNotFound) {
    NotFoundMessage notFound=new NotFoundMessage(unitTestParams);
    notFound.addItem(new InventoryItem(InventoryItem.Type.Transaction,t6));
    inbound(peer,notFound);
  }
 else {
    bouncePing();
  }
  assertTrue(futures.isDone());
  List<Transaction> results=futures.get();
  assertTrue(results.contains(t2));
  assertTrue(results.contains(t3));
  assertTrue(results.contains(t4));
}