Skip to content

Commit a7fbd20

Browse files
committed
Fixed multiple race conditions in shared buffer tests
1 parent 3da93e1 commit a7fbd20

File tree

1 file changed

+30
-47
lines changed

1 file changed

+30
-47
lines changed

httpcore5/src/test/java/org/apache/hc/core5/http/nio/support/classic/TestSharedOutputBuffer.java

Lines changed: 30 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
import java.util.concurrent.ExecutorService;
3838
import java.util.concurrent.Executors;
3939
import java.util.concurrent.Future;
40-
import java.util.concurrent.locks.Condition;
4140
import java.util.concurrent.locks.ReentrantLock;
4241

4342
import org.apache.hc.core5.http.Header;
4443
import org.apache.hc.core5.http.WritableByteChannelMock;
4544
import org.apache.hc.core5.http.nio.DataStreamChannel;
4645
import org.apache.hc.core5.util.Timeout;
4746
import org.junit.jupiter.api.Assertions;
47+
import org.junit.jupiter.api.RepeatedTest;
4848
import org.junit.jupiter.api.Test;
4949
import org.mockito.Mockito;
5050

@@ -57,12 +57,10 @@ static class DataStreamChannelMock implements DataStreamChannel {
5757
private final WritableByteChannelMock channel;
5858

5959
private final ReentrantLock lock;
60-
private final Condition condition;
6160

6261
DataStreamChannelMock(final WritableByteChannelMock channel) {
6362
this.channel = channel;
6463
this.lock = new ReentrantLock();
65-
this.condition = lock.newCondition();
6664
}
6765

6866
@Override
@@ -77,20 +75,13 @@ public int write(final ByteBuffer src) throws IOException {
7775

7876
@Override
7977
public void requestOutput() {
80-
lock.lock();
81-
try {
82-
condition.signalAll();
83-
} finally {
84-
lock.unlock();
85-
}
8678
}
8779

8880
@Override
8981
public void endStream(final List<? extends Header> trailers) throws IOException {
9082
lock.lock();
9183
try {
9284
channel.close();
93-
condition.signalAll();
9485
} finally {
9586
lock.unlock();
9687
}
@@ -101,15 +92,6 @@ public void endStream() throws IOException {
10192
endStream(null);
10293
}
10394

104-
public void awaitOutputRequest() throws InterruptedException {
105-
lock.lock();
106-
try {
107-
condition.await();
108-
} finally {
109-
lock.unlock();
110-
}
111-
}
112-
11395
}
11496

11597
@Test
@@ -164,7 +146,7 @@ void testFlush() throws Exception {
164146
Assertions.assertEquals(30, outputBuffer.capacity());
165147
}
166148

167-
@Test
149+
@RepeatedTest(20)
168150
void testMultithreadingWriteStream() throws Exception {
169151

170152
final Charset charset = StandardCharsets.US_ASCII;
@@ -174,36 +156,37 @@ void testMultithreadingWriteStream() throws Exception {
174156
final DataStreamChannelMock dataStreamChannel = new DataStreamChannelMock(channel);
175157

176158
final ExecutorService executorService = Executors.newFixedThreadPool(2);
177-
final Future<Boolean> task1 = executorService.submit(() -> {
178-
final byte[] tmp = "1234567890".getBytes(charset);
179-
outputBuffer.write(tmp, 0, tmp.length);
180-
outputBuffer.write(tmp, 0, tmp.length);
181-
outputBuffer.write('1');
182-
outputBuffer.write('2');
183-
outputBuffer.write(tmp, 0, tmp.length);
184-
outputBuffer.write(tmp, 0, tmp.length);
185-
outputBuffer.write(tmp, 0, tmp.length);
186-
outputBuffer.writeCompleted();
187-
outputBuffer.writeCompleted();
188-
return Boolean.TRUE;
189-
});
190-
final Future<Boolean> task2 = executorService.submit(() -> {
191-
for (;;) {
192-
outputBuffer.flush(dataStreamChannel);
193-
if (outputBuffer.isEndStream()) {
194-
break;
195-
}
196-
if (!outputBuffer.hasData()) {
197-
dataStreamChannel.awaitOutputRequest();
159+
try {
160+
final Future<Boolean> task1 = executorService.submit(() -> {
161+
final byte[] tmp = "1234567890".getBytes(charset);
162+
outputBuffer.write(tmp, 0, tmp.length);
163+
outputBuffer.write(tmp, 0, tmp.length);
164+
outputBuffer.write('1');
165+
outputBuffer.write('2');
166+
outputBuffer.write(tmp, 0, tmp.length);
167+
outputBuffer.write(tmp, 0, tmp.length);
168+
outputBuffer.write(tmp, 0, tmp.length);
169+
outputBuffer.writeCompleted();
170+
outputBuffer.writeCompleted();
171+
return Boolean.TRUE;
172+
});
173+
final Future<Boolean> task2 = executorService.submit(() -> {
174+
for (;;) {
175+
outputBuffer.flush(dataStreamChannel);
176+
if (outputBuffer.isEndStream()) {
177+
break;
178+
}
198179
}
199-
}
200-
return Boolean.TRUE;
201-
});
180+
return Boolean.TRUE;
181+
});
202182

203-
Assertions.assertEquals(Boolean.TRUE, task1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()));
204-
Assertions.assertEquals(Boolean.TRUE, task2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()));
183+
Assertions.assertEquals(Boolean.TRUE, task1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()));
184+
Assertions.assertEquals(Boolean.TRUE, task2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()));
205185

206-
Assertions.assertEquals("1234567890123456789012123456789012345678901234567890", new String(channel.toByteArray(), charset));
186+
Assertions.assertEquals("1234567890123456789012123456789012345678901234567890", new String(channel.toByteArray(), charset));
187+
} finally {
188+
executorService.shutdownNow();
189+
}
207190
}
208191

209192
@Test

0 commit comments

Comments
 (0)