@Test
public void badMessage() throws Exception {

    // Bring up an actual network connection and feed it bogus data.
    final SettableFuture<Void> result = SettableFuture.create();
    Threading.uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread thread, Throwable throwable) {
            result.setException(throwable);
        }
    };
    connect(); // Writes out a verack+version.
    final SettableFuture<Void> peerDisconnected = SettableFuture.create();
    writeTarget.peer.addDisconnectedEventListener(new PeerDisconnectedEventListener() {
        @Override
        public void onPeerDisconnected(Peer p, int peerCount) {
            peerDisconnected.set(null);
        }
    });
    final NetworkParameters params = TestNet3Params.get();
    MessageSerializer serializer = params.getDefaultSerializer();
    // Now write some bogus truncated message.
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    serializer.serialize("inv", new InventoryMessage(PARAMS) {
        @Override
        public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
            // Add some hashes.
            addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.of(new byte[]{1})));
            addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.of(new byte[]{2})));
            addItem(new InventoryItem(InventoryItem.Type.Transaction, Sha256Hash.of(new byte[]{3})));

            // Write out a copy that's truncated in the middle.
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            super.bitcoinSerializeToStream(bos);
            byte[] bits = bos.toByteArray();
            bits = Arrays.copyOf(bits, bits.length / 2);
            stream.write(bits);
        }
    }.bitcoinSerialize(), out);
    writeTarget.writeTarget.writeBytes(out.toByteArray());
    try {
        result.get(1, TimeUnit.SECONDS);
        fail();
    } catch (ExecutionException e) {
        assertTrue(e.getCause() instanceof ProtocolException);
    }
    peerDisconnected.get();
    try {
        peer.writeTarget.writeBytes(new byte[1]);
        fail();
    } catch (IOException e) {
        assertTrue((e.getCause() != null && e.getCause() instanceof CancelledKeyException)
                || (e instanceof SocketException && e.getMessage().equals("Socket is closed")));
    }
}