use of io.grpc.internal.ClientStream in project grpc-java by grpc.
the class AbstractTransportTest method earlyServerClose_serverFailure.
@Test
public void earlyServerClose_serverFailure() throws Exception {
server.start(serverListener);
client = newClientTransport(server);
runIfNotNull(client.start(mockClientTransportListener));
MockServerTransportListener serverTransportListener = serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
serverTransport = serverTransportListener.transport;
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata());
clientStream.start(mockClientStreamListener);
StreamCreation serverStreamCreation = serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
ServerStream serverStream = serverStreamCreation.stream;
ServerStreamListener mockServerStreamListener = serverStreamCreation.listener;
Status status = Status.INTERNAL.withDescription("I'm not listening").withCause(new Exception());
serverStream.close(status, new Metadata());
verify(mockServerStreamListener, timeout(TIMEOUT_MS)).closed(statusCaptor.capture());
assertCodeEquals(Status.OK, statusCaptor.getValue());
verify(mockClientStreamListener, timeout(TIMEOUT_MS)).closed(statusCaptor.capture(), any(Metadata.class));
assertEquals(status.getCode(), statusCaptor.getValue().getCode());
assertEquals(status.getDescription(), statusCaptor.getValue().getDescription());
assertNull(statusCaptor.getValue().getCause());
}
use of io.grpc.internal.ClientStream in project grpc-java by grpc.
the class AbstractTransportTest method frameAfterRstStreamShouldNotBreakClientChannel.
// TODO(ejona):
// multiple streams on same transport
// multiple client transports to same server
// halfClose to trigger flush (client and server)
// flow control pushes back (client and server)
// flow control provides precisely number of messages requested (client and server)
// onReady called when buffer drained (on server and client)
// test no start reentrancy (esp. during failure) (transport and call)
// multiple requests/responses (verifying contents received)
// server transport shutdown triggers client shutdown (via GOAWAY)
// queued message InputStreams are closed on stream cancel
// (and maybe exceptions handled)
/**
* Test for issue https://github.com/grpc/grpc-java/issues/1682
*/
@Test
public void frameAfterRstStreamShouldNotBreakClientChannel() throws Exception {
server.start(serverListener);
client = newClientTransport(server);
runIfNotNull(client.start(mockClientTransportListener));
MockServerTransportListener serverTransportListener = serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
serverTransport = serverTransportListener.transport;
// Try to create a sequence of frames so that the client receives a HEADERS or DATA frame
// after having sent a RST_STREAM to the server. Previously, this would have broken the
// Netty channel.
ClientStream stream = client.newStream(methodDescriptor, new Metadata());
stream.start(mockClientStreamListener);
StreamCreation serverStreamCreation = serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
stream.flush();
stream.writeMessage(methodDescriptor.streamRequest("foo"));
stream.flush();
stream.cancel(Status.CANCELLED);
stream.flush();
serverStreamCreation.stream.writeHeaders(new Metadata());
serverStreamCreation.stream.flush();
serverStreamCreation.stream.writeMessage(methodDescriptor.streamResponse("bar"));
serverStreamCreation.stream.flush();
verify(mockClientStreamListener, timeout(250)).closed(eq(Status.CANCELLED), any(Metadata.class));
ClientStreamListener mockClientStreamListener2 = mock(ClientStreamListener.class);
// Test that the channel is still usable i.e. we can receive headers from the server on a
// new stream.
stream = client.newStream(methodDescriptor, new Metadata());
stream.start(mockClientStreamListener2);
serverStreamCreation = serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
serverStreamCreation.stream.writeHeaders(new Metadata());
serverStreamCreation.stream.flush();
verify(mockClientStreamListener2, timeout(250)).headersRead(any(Metadata.class));
}
use of io.grpc.internal.ClientStream in project grpc-java by grpc.
the class AbstractTransportTest method newStream_afterTermination.
@Test
public void newStream_afterTermination() throws Exception {
// We expect the same general behavior as duringShutdown, but for some transports (e.g., Netty)
// dealing with afterTermination is harder than duringShutdown.
server.start(serverListener);
client = newClientTransport(server);
runIfNotNull(client.start(mockClientTransportListener));
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportReady();
client.shutdown();
verify(mockClientTransportListener, timeout(TIMEOUT_MS)).transportTerminated();
Thread.sleep(100);
ClientStream stream = client.newStream(methodDescriptor, new Metadata());
stream.start(mockClientStreamListener);
verify(mockClientStreamListener, timeout(TIMEOUT_MS)).closed(statusCaptor.capture(), any(Metadata.class));
verify(mockClientTransportListener, never()).transportInUse(anyBoolean());
assertCodeEquals(Status.UNAVAILABLE, statusCaptor.getValue());
}
use of io.grpc.internal.ClientStream in project grpc-java by grpc.
the class AbstractTransportTest method clientCancel.
@Test
public void clientCancel() throws Exception {
server.start(serverListener);
client = newClientTransport(server);
runIfNotNull(client.start(mockClientTransportListener));
MockServerTransportListener serverTransportListener = serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
serverTransport = serverTransportListener.transport;
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata());
clientStream.start(mockClientStreamListener);
StreamCreation serverStreamCreation = serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
ServerStreamListener mockServerStreamListener = serverStreamCreation.listener;
Status status = Status.CANCELLED.withDescription("Nevermind").withCause(new Exception());
clientStream.cancel(status);
verify(mockClientStreamListener, timeout(TIMEOUT_MS)).closed(Matchers.same(status), any(Metadata.class));
verify(mockServerStreamListener, timeout(TIMEOUT_MS)).closed(statusCaptor.capture());
assertNotEquals(Status.Code.OK, statusCaptor.getValue().getCode());
// Cause should not be transmitted between client and server
assertNull(statusCaptor.getValue().getCause());
reset(mockServerStreamListener);
reset(mockClientStreamListener);
clientStream.cancel(status);
verify(mockServerStreamListener, never()).closed(any(Status.class));
verify(mockClientStreamListener, never()).closed(any(Status.class), any(Metadata.class));
}
use of io.grpc.internal.ClientStream in project grpc-java by grpc.
the class AbstractTransportTest method flowControlPushBack.
@Test
public void flowControlPushBack() throws Exception {
server.start(serverListener);
client = newClientTransport(server);
runIfNotNull(client.start(mockClientTransportListener));
MockServerTransportListener serverTransportListener = serverListener.takeListenerOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
serverTransport = serverTransportListener.transport;
ClientStream clientStream = client.newStream(methodDescriptor, new Metadata());
clientStream.start(mockClientStreamListener);
StreamCreation serverStreamCreation = serverTransportListener.takeStreamOrFail(TIMEOUT_MS, TimeUnit.MILLISECONDS);
assertEquals(methodDescriptor.getFullMethodName(), serverStreamCreation.method);
ServerStream serverStream = serverStreamCreation.stream;
ServerStreamListener mockServerStreamListener = serverStreamCreation.listener;
serverStream.writeHeaders(new Metadata());
Answer<Void> closeStream = new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Exception {
Object[] args = invocation.getArguments();
((InputStream) args[0]).close();
return null;
}
};
String largeMessage;
{
int size = 1 * 1024;
StringBuffer sb = new StringBuffer(size);
for (int i = 0; i < size; i++) {
sb.append('a');
}
largeMessage = sb.toString();
}
doAnswer(closeStream).when(mockServerStreamListener).messageRead(any(InputStream.class));
serverStream.request(1);
verify(mockClientStreamListener, timeout(TIMEOUT_MS)).onReady();
assertTrue(clientStream.isReady());
final int maxToSend = 10 * 1024;
int clientSent;
// Verify that flow control will push back on client.
for (clientSent = 0; clientStream.isReady(); clientSent++) {
if (clientSent > maxToSend) {
// It seems like flow control isn't working. _Surely_ flow control would have pushed-back
// already. If this is normal, please configure the transport to buffer less.
fail("Too many messages sent before isReady() returned false");
}
clientStream.writeMessage(methodDescriptor.streamRequest(largeMessage));
clientStream.flush();
}
assertTrue(clientSent > 0);
// Make sure there are at least a few messages buffered.
for (; clientSent < 5; clientSent++) {
clientStream.writeMessage(methodDescriptor.streamResponse(largeMessage));
clientStream.flush();
}
doPingPong(serverListener);
verify(mockServerStreamListener, timeout(TIMEOUT_MS)).messageRead(any(InputStream.class));
doAnswer(closeStream).when(mockClientStreamListener).messageRead(any(InputStream.class));
clientStream.request(1);
verify(mockServerStreamListener, timeout(TIMEOUT_MS)).onReady();
assertTrue(serverStream.isReady());
int serverSent;
// Verify that flow control will push back on server.
for (serverSent = 0; serverStream.isReady(); serverSent++) {
if (serverSent > maxToSend) {
// It seems like flow control isn't working. _Surely_ flow control would have pushed-back
// already. If this is normal, please configure the transport to buffer less.
fail("Too many messages sent before isReady() returned false");
}
serverStream.writeMessage(methodDescriptor.streamResponse(largeMessage));
serverStream.flush();
}
assertTrue(serverSent > 0);
// Make sure there are at least a few messages buffered.
for (; serverSent < 5; serverSent++) {
serverStream.writeMessage(methodDescriptor.streamResponse(largeMessage));
serverStream.flush();
}
doPingPong(serverListener);
verify(mockClientStreamListener, timeout(TIMEOUT_MS)).messageRead(any(InputStream.class));
serverStream.request(3);
clientStream.request(3);
doPingPong(serverListener);
// times() is total number throughout the entire test
verify(mockClientStreamListener, timeout(TIMEOUT_MS).times(4)).messageRead(any(InputStream.class));
verify(mockServerStreamListener, timeout(TIMEOUT_MS).times(4)).messageRead(any(InputStream.class));
// Request the rest
serverStream.request(clientSent);
clientStream.request(serverSent);
verify(mockClientStreamListener, timeout(TIMEOUT_MS).times(clientSent)).messageRead(any(InputStream.class));
verify(mockServerStreamListener, timeout(TIMEOUT_MS).times(serverSent)).messageRead(any(InputStream.class));
verify(mockClientStreamListener, timeout(TIMEOUT_MS).times(2)).onReady();
assertTrue(clientStream.isReady());
verify(mockServerStreamListener, timeout(TIMEOUT_MS).times(2)).onReady();
assertTrue(serverStream.isReady());
// Request four more
for (int i = 0; i < 5; i++) {
clientStream.writeMessage(methodDescriptor.streamRequest(largeMessage));
clientStream.flush();
serverStream.writeMessage(methodDescriptor.streamResponse(largeMessage));
serverStream.flush();
}
doPingPong(serverListener);
verify(mockClientStreamListener, timeout(TIMEOUT_MS).times(clientSent + 4)).messageRead(any(InputStream.class));
verify(mockServerStreamListener, timeout(TIMEOUT_MS).times(serverSent + 4)).messageRead(any(InputStream.class));
// Drain exactly how many messages are left
serverStream.request(1);
clientStream.request(1);
verify(mockServerStreamListener, timeout(TIMEOUT_MS).times(serverSent + 5)).messageRead(any(InputStream.class));
verify(mockClientStreamListener, timeout(TIMEOUT_MS).times(clientSent + 5)).messageRead(any(InputStream.class));
// And now check that the streams can still complete gracefully
clientStream.writeMessage(methodDescriptor.streamRequest(largeMessage));
clientStream.flush();
clientStream.halfClose();
doPingPong(serverListener);
verify(mockServerStreamListener, never()).halfClosed();
serverStream.request(1);
verify(mockServerStreamListener, timeout(TIMEOUT_MS).times(serverSent + 6)).messageRead(any(InputStream.class));
verify(mockServerStreamListener, timeout(TIMEOUT_MS)).halfClosed();
serverStream.writeMessage(methodDescriptor.streamResponse(largeMessage));
serverStream.flush();
Status status = Status.OK.withDescription("... quite a lengthy discussion");
serverStream.close(status, new Metadata());
doPingPong(serverListener);
verify(mockClientStreamListener, never()).closed(any(Status.class), any(Metadata.class));
clientStream.request(1);
verify(mockClientStreamListener, timeout(TIMEOUT_MS).times(clientSent + 6)).messageRead(any(InputStream.class));
verify(mockServerStreamListener, timeout(TIMEOUT_MS)).closed(statusCaptor.capture());
assertCodeEquals(Status.OK, statusCaptor.getValue());
verify(mockClientStreamListener, timeout(TIMEOUT_MS)).closed(statusCaptor.capture(), any(Metadata.class));
assertEquals(status.getCode(), statusCaptor.getValue().getCode());
assertEquals(status.getDescription(), statusCaptor.getValue().getDescription());
}
Aggregations