Skip to content

Commit

Permalink
Avoid race condition in LocalBitcoinNodeTests
Browse files Browse the repository at this point in the history
Previously, Travis CI was failing non-deterministically due to a race
condition in which a thread was started in order to call the blocking
ServerSocket.accept() method, and sometimes the subsequent attempt by
LocalBitcoinNode.detectAndRun() to connect to that socket's port would
occur before the thread had actually called the accept() method.

This commit simplifies the approach by removing the thread entirely. As
it turns out, calling accept() is not necessary; simply constructing a
new ServerSocket() binds to and listens on the given port, such that a
subsequent attempt to connect() will succeed.
  • Loading branch information
cbeams committed Jan 10, 2020
1 parent 63205d7 commit 83a2fc8
Showing 1 changed file with 8 additions and 18 deletions.
26 changes: 8 additions & 18 deletions core/src/test/java/bisq/core/btc/nodes/LocalBitcoinNodeTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.net.ServerSocket;

import java.io.IOException;
import java.io.UncheckedIOException;

import java.util.concurrent.atomic.AtomicBoolean;

Expand All @@ -17,37 +16,28 @@ public class LocalBitcoinNodeTests {

private AtomicBoolean called = new AtomicBoolean(false);
private Runnable callback = () -> called.set(true);
private int port;
private ServerSocket socket;
private LocalBitcoinNode localBitcoinNode;

@Before
public void setUp() throws IOException {
// Find an available port
try (ServerSocket socket = new ServerSocket(0)) {
port = socket.getLocalPort();
}
localBitcoinNode = new LocalBitcoinNode(port);
// Bind to and listen on an available port
socket = new ServerSocket(0);
localBitcoinNode = new LocalBitcoinNode(socket.getLocalPort());
}

@Test
public void whenLocalBitcoinNodeIsDetected_thenCallbackGetsRun_andIsDetectedReturnsTrue() {
// Listen on the port, indicating that the local bitcoin node is running
new Thread(() -> {
try (ServerSocket socket = new ServerSocket(port)){
socket.accept();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}).start();

// Continue listening on the port, indicating the local Bitcoin node is running
localBitcoinNode.detectAndRun(callback);
assertTrue(called.get());
assertTrue(localBitcoinNode.isDetected());
}

@Test
public void whenLocalBitcoinNodeIsNotDetected_thenCallbackGetsRun_andIsDetectedReturnsFalse() {
// Leave port unbound, indicating that no local Bitcoin node is running
public void whenLocalBitcoinNodeIsNotDetected_thenCallbackGetsRun_andIsDetectedReturnsFalse() throws IOException {
// Stop listening on the port, indicating the local Bitcoin node is not running
socket.close();
localBitcoinNode.detectAndRun(callback);
assertTrue(called.get());
assertFalse(localBitcoinNode.isDetected());
Expand Down

0 comments on commit 83a2fc8

Please sign in to comment.