Skip to content

Commit a54b719

Browse files
committed
[test] stabilize SSLSocketTest data-integrity check
1 parent 1f1fc01 commit a54b719

File tree

1 file changed

+44
-19
lines changed

1 file changed

+44
-19
lines changed

src/test/java/org/jruby/ext/openssl/SSLSocketTest.java

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import java.nio.ByteBuffer;
55
import java.nio.channels.SelectionKey;
66
import java.nio.channels.Selector;
7+
import java.util.concurrent.CountDownLatch;
8+
import java.util.concurrent.TimeUnit;
79
import javax.net.ssl.SSLEngine;
810

911
import org.jruby.Ruby;
@@ -58,9 +60,12 @@ public void syswriteNonblockDataIntegrity() throws Exception {
5860
SSLSocket server = (SSLSocket) pair.entry(1).toJava(SSLSocket.class);
5961

6062
try {
61-
// Server: read all data in a background thread, counting bytes
62-
final long[] serverReceived = { 0 };
63-
Thread serverReader = startServerReader(server, serverReceived);
63+
final int expectedBytes = 64 * 4096;
64+
65+
// Server: read an exact payload size in the background so the assertion
66+
// does not depend on EOF timing or close-path behavior
67+
final ServerReadResult serverResult = new ServerReadResult();
68+
Thread serverReader = startServerReader(server, expectedBytes, serverResult);
6469

6570
// Client: write 256KB in 4KB chunks via syswrite_nonblock
6671
byte[] chunk = new byte[4096];
@@ -85,42 +90,62 @@ public void syswriteNonblockDataIntegrity() throws Exception {
8590
}
8691
}
8792
assertTrue(totalSent > 0, "should have sent data");
93+
assertEquals(expectedBytes, totalSent, "test must send the full payload");
8894

89-
// Close client to signal EOF, let server finish reading
90-
client.callMethod(currentContext(), "close");
91-
serverReader.join(10_000);
95+
assertTrue(serverResult.await(10, TimeUnit.SECONDS),
96+
"server must finish reading the expected payload"
97+
);
98+
serverReader.join(1_000);
99+
assertFalse(serverReader.isAlive(), "server reader must exit after reading expected bytes");
100+
if (serverResult.failure != null) {
101+
throw new AssertionError("server reader failed unexpectedly", serverResult.failure);
102+
}
92103

93-
assertEquals(totalSent, serverReceived[0],
104+
assertEquals(totalSent, serverResult.bytesRead,
94105
"server must receive exactly what client sent — mismatch means encrypted bytes were lost!"
95106
);
96107
} finally {
97108
closeQuietly(pair);
98109
}
99110
}
100111

101-
private Thread startServerReader(final SSLSocket server, final long[] serverReceived) {
112+
private Thread startServerReader(final SSLSocket server, final long expectedBytes,
113+
final ServerReadResult serverResult) {
102114
Thread serverReader = new Thread(() -> {
103115
try {
104116
RubyFixnum len = RubyFixnum.newFixnum(runtime, 8192);
105-
while (true) {
117+
while (serverResult.bytesRead < expectedBytes) {
106118
IRubyObject data = server.sysread(currentContext(), len);
107-
serverReceived[0] += ((RubyString) data).getByteList().getRealSize();
119+
serverResult.bytesRead += ((RubyString) data).getByteList().getRealSize();
108120
}
109-
} catch (RaiseException e) {
110-
String errorName = e.getException().getMetaClass().getName();
111-
if ("EOFError".equals(errorName) || "IOError".equals(errorName)) { // client closes connection
112-
System.out.println("server-reader expected: " + e.getMessage());
113-
} else {
114-
System.err.println("server-reader unexpected: " + e.getMessage());
115-
e.printStackTrace(System.err);
116-
throw e;
121+
if (serverResult.bytesRead != expectedBytes) {
122+
throw new AssertionError("server read " + serverResult.bytesRead +
123+
" bytes, expected " + expectedBytes);
117124
}
125+
} catch (Throwable t) {
126+
serverResult.failure = t;
127+
} finally {
128+
serverResult.finish();
118129
}
119-
});
130+
}, "ssl-server-reader");
120131
serverReader.start();
121132
return serverReader;
122133
}
123134

135+
private static final class ServerReadResult {
136+
private final CountDownLatch done = new CountDownLatch(1);
137+
private volatile long bytesRead;
138+
private volatile Throwable failure;
139+
140+
private boolean await(final long timeout, final TimeUnit unit) throws InterruptedException {
141+
return done.await(timeout, unit);
142+
}
143+
144+
private void finish() {
145+
done.countDown();
146+
}
147+
}
148+
124149
/**
125150
* After saturating the TCP send buffer with {@code syswrite_nonblock},
126151
* inspect {@code netWriteData} to verify the buffer is consistent.

0 commit comments

Comments
 (0)