mirror of https://github.com/grpc/grpc-java.git
transports can send a msg larger than their flow control window (#10842)
This commit is contained in:
parent
c9db8fa4fe
commit
09acf2f6b7
|
|
@ -1354,8 +1354,8 @@ public abstract class AbstractTransportTest {
|
||||||
serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
serverTransport = serverTransportListener.transport;
|
serverTransport = serverTransportListener.transport;
|
||||||
|
|
||||||
ClientStream clientStream = client.newStream(
|
ClientStream clientStream =
|
||||||
methodDescriptor, new Metadata(), callOptions, tracers);
|
client.newStream(methodDescriptor, new Metadata(), callOptions, tracers);
|
||||||
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||||
clientStream.start(clientStreamListener);
|
clientStream.start(clientStreamListener);
|
||||||
StreamCreation serverStreamCreation =
|
StreamCreation serverStreamCreation =
|
||||||
|
|
@ -1366,15 +1366,7 @@ public abstract class AbstractTransportTest {
|
||||||
|
|
||||||
serverStream.writeHeaders(new Metadata(), true);
|
serverStream.writeHeaders(new Metadata(), true);
|
||||||
|
|
||||||
String largeMessage;
|
String largeMessage = newString(1024);
|
||||||
{
|
|
||||||
int size = 1 * 1024;
|
|
||||||
StringBuilder sb = new StringBuilder(size);
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
sb.append('a');
|
|
||||||
}
|
|
||||||
largeMessage = sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
serverStream.request(1);
|
serverStream.request(1);
|
||||||
assertTrue(clientStreamListener.awaitOnReadyAndDrain(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
assertTrue(clientStreamListener.awaitOnReadyAndDrain(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
|
@ -1494,6 +1486,64 @@ public abstract class AbstractTransportTest {
|
||||||
assertEquals(status.getDescription(), clientStreamStatus.getDescription());
|
assertEquals(status.getDescription(), clientStreamStatus.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void flowControlDoesNotDeadlockLargeMessage() throws Exception {
|
||||||
|
server.start(serverListener);
|
||||||
|
client = newClientTransport(server);
|
||||||
|
startTransport(client, mockClientTransportListener);
|
||||||
|
MockServerTransportListener serverTransportListener =
|
||||||
|
serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
|
serverTransport = serverTransportListener.transport;
|
||||||
|
|
||||||
|
ClientStream clientStream =
|
||||||
|
client.newStream(methodDescriptor, new Metadata(), callOptions, tracers);
|
||||||
|
ClientStreamListenerBase clientStreamListener = new ClientStreamListenerBase();
|
||||||
|
clientStream.start(clientStreamListener);
|
||||||
|
StreamCreation serverStreamCreation =
|
||||||
|
serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
|
assertEquals(methodDescriptor.getFullMethodName(), serverStreamCreation.method);
|
||||||
|
ServerStream serverStream = serverStreamCreation.stream;
|
||||||
|
ServerStreamListenerBase serverStreamListener = serverStreamCreation.listener;
|
||||||
|
|
||||||
|
serverStream.writeHeaders(new Metadata(), true);
|
||||||
|
|
||||||
|
String largeMessage = newString(TEST_FLOW_CONTROL_WINDOW + 1);
|
||||||
|
|
||||||
|
serverStream.request(1);
|
||||||
|
assertTrue(clientStreamListener.awaitOnReadyAndDrain(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
assertTrue(clientStream.isReady());
|
||||||
|
clientStream.writeMessage(methodDescriptor.streamRequest(largeMessage));
|
||||||
|
clientStream.flush();
|
||||||
|
doPingPong(serverListener);
|
||||||
|
|
||||||
|
verifyMessageCountAndClose(serverStreamListener.messageQueue, 1);
|
||||||
|
|
||||||
|
clientStream.request(1);
|
||||||
|
assertTrue(serverStreamListener.awaitOnReadyAndDrain(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
assertTrue(serverStream.isReady());
|
||||||
|
serverStream.writeMessage(methodDescriptor.streamResponse(largeMessage));
|
||||||
|
serverStream.flush();
|
||||||
|
doPingPong(serverListener);
|
||||||
|
|
||||||
|
verifyMessageCountAndClose(clientStreamListener.messageQueue, 1);
|
||||||
|
|
||||||
|
// And now check that the streams can still complete normally.
|
||||||
|
clientStream.halfClose();
|
||||||
|
doPingPong(serverListener);
|
||||||
|
serverStream.request(1);
|
||||||
|
assertTrue(serverStreamListener.awaitHalfClosed(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
|
||||||
|
Status status = Status.OK.withDescription("... quite a lengthy discussion");
|
||||||
|
serverStream.close(status, new Metadata());
|
||||||
|
doPingPong(serverListener);
|
||||||
|
clientStream.request(1);
|
||||||
|
assertCodeEquals(Status.OK, serverStreamListener.status.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
Status clientStreamStatus = clientStreamListener.status.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
|
assertNotNull(clientStreamListener.trailers.get(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||||
|
assertEquals(status.getCode(), clientStreamStatus.getCode());
|
||||||
|
assertEquals(status.getDescription(), clientStreamStatus.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
private int verifyMessageCountAndClose(BlockingQueue<InputStream> messageQueue, int count)
|
private int verifyMessageCountAndClose(BlockingQueue<InputStream> messageQueue, int count)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
InputStream message;
|
InputStream message;
|
||||||
|
|
@ -2399,4 +2449,12 @@ public abstract class AbstractTransportTest {
|
||||||
throws ExecutionException, InterruptedException {
|
throws ExecutionException, InterruptedException {
|
||||||
return socket.getStats().get().data;
|
return socket.getStats().get().data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String newString(int size) {
|
||||||
|
StringBuilder sb = new StringBuilder(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
sb.append('a');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,12 @@ public class JettyTransportTest extends AbstractTransportTest {
|
||||||
public void flowControlPushBack() {
|
public void flowControlPushBack() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Ignore("Servlet flow control not implemented yet")
|
||||||
|
@Test
|
||||||
|
public void flowControlDoesNotDeadlockLargeMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
@Override
|
@Override
|
||||||
@Ignore("Jetty is broken on client RST_STREAM")
|
@Ignore("Jetty is broken on client RST_STREAM")
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,13 @@ public class TomcatTransportTest extends AbstractTransportTest {
|
||||||
@Test
|
@Test
|
||||||
public void flowControlPushBack() {}
|
public void flowControlPushBack() {}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
@Override
|
||||||
|
@Ignore("Servlet flow control not implemented yet")
|
||||||
|
@Test
|
||||||
|
public void flowControlDoesNotDeadlockLargeMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Ignore("Server side sockets are managed by the servlet container")
|
@Ignore("Server side sockets are managed by the servlet container")
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,13 @@ public class UndertowTransportTest extends AbstractTransportTest {
|
||||||
@Test
|
@Test
|
||||||
public void flowControlPushBack() {}
|
public void flowControlPushBack() {}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
@Override
|
||||||
|
@Ignore("Servlet flow control not implemented yet")
|
||||||
|
@Test
|
||||||
|
public void flowControlDoesNotDeadlockLargeMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Ignore("Server side sockets are managed by the servlet container")
|
@Ignore("Server side sockets are managed by the servlet container")
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue