Skip to content

Commit 526a2ad

Browse files
committed
[test] align SSLSocketTest retries with net/http
1 parent a54b719 commit 526a2ad

File tree

1 file changed

+46
-21
lines changed

1 file changed

+46
-21
lines changed

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

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.nio.ByteBuffer;
55
import java.nio.channels.SelectionKey;
66
import java.nio.channels.Selector;
7+
import java.nio.channels.SocketChannel;
78
import java.util.concurrent.CountDownLatch;
89
import java.util.concurrent.TimeUnit;
910
import javax.net.ssl.SSLEngine;
@@ -67,28 +68,12 @@ public void syswriteNonblockDataIntegrity() throws Exception {
6768
final ServerReadResult serverResult = new ServerReadResult();
6869
Thread serverReader = startServerReader(server, expectedBytes, serverResult);
6970

70-
// Client: write 256KB in 4KB chunks via syswrite_nonblock
71-
byte[] chunk = new byte[4096];
72-
java.util.Arrays.fill(chunk, (byte) 'P'); // P for POST body
73-
RubyString payload = RubyString.newString(runtime, chunk);
71+
// Client: write a large POST body in one request; net/http ultimately
72+
// retries write_nonblock internally until the full body is flushed
73+
byte[] payload = new byte[expectedBytes];
74+
java.util.Arrays.fill(payload, (byte) 'P'); // P for POST body
7475

75-
long totalSent = 0;
76-
for (int i = 0; i < 64; i++) { // 64 * 4KB = 256KB
77-
try {
78-
IRubyObject written = client.syswrite_nonblock(currentContext(), payload);
79-
totalSent += ((RubyInteger) written).getLongValue();
80-
} catch (RaiseException e) {
81-
if ("OpenSSL::SSL::SSLErrorWaitWritable".equals(e.getException().getMetaClass().getName())) {
82-
System.out.println("syswrite_nonblock expected: " + e.getMessage());
83-
// Expected: non-blocking write would block — retry as blocking
84-
IRubyObject written = client.syswrite(currentContext(), payload);
85-
totalSent += ((RubyInteger) written).getLongValue();
86-
} else {
87-
System.err.println("syswrite_nonblock unexpected: " + e.getMessage());
88-
throw e;
89-
}
90-
}
91-
}
76+
long totalSent = writeNonblockWithRetry(client, payload);
9277
assertTrue(totalSent > 0, "should have sent data");
9378
assertEquals(expectedBytes, totalSent, "test must send the full payload");
9479

@@ -146,6 +131,46 @@ private void finish() {
146131
}
147132
}
148133

134+
private int writeNonblockWithRetry(final SSLSocket socket, final byte[] data) throws Exception {
135+
int offset = 0;
136+
while (offset < data.length) {
137+
final RubyString payload = RubyString.newString(runtime, data, offset, data.length - offset);
138+
try {
139+
IRubyObject written = socket.syswrite_nonblock(currentContext(), payload);
140+
final int len = ((RubyInteger) written).getIntValue();
141+
offset += len;
142+
} catch (RaiseException e) {
143+
final String errorName = e.getException().getMetaClass().getName();
144+
if ("OpenSSL::SSL::SSLErrorWaitWritable".equals(errorName)) {
145+
System.out.println("syswrite_nonblock expected: " + e.getMessage());
146+
waitUntilReady(socket, SelectionKey.OP_WRITE, 5_000);
147+
} else if ("OpenSSL::SSL::SSLErrorWaitReadable".equals(errorName)) {
148+
System.out.println("syswrite_nonblock expected: " + e.getMessage());
149+
waitUntilReady(socket, SelectionKey.OP_READ, 5_000);
150+
} else {
151+
System.err.println("syswrite_nonblock unexpected: " + e.getMessage());
152+
throw e;
153+
}
154+
}
155+
}
156+
return offset;
157+
}
158+
159+
private void waitUntilReady(final SSLSocket socket, final int operation, final long timeoutMillis)
160+
throws Exception {
161+
final SocketChannel channel = (SocketChannel) socket.io().getChannel();
162+
final boolean blocking = channel.isBlocking();
163+
164+
try (Selector selector = Selector.open()) {
165+
if (blocking) channel.configureBlocking(false);
166+
channel.register(selector, operation);
167+
final int ready = selector.select(timeoutMillis);
168+
assertTrue(ready > 0, "socket did not become ready in time");
169+
} finally {
170+
if (blocking) channel.configureBlocking(true);
171+
}
172+
}
173+
149174
/**
150175
* After saturating the TCP send buffer with {@code syswrite_nonblock},
151176
* inspect {@code netWriteData} to verify the buffer is consistent.

0 commit comments

Comments
 (0)