public void serverStreamingShouldBeFlowControlled() throws Exception { final StreamingOutputCallRequest request = new StreamingOutputCallRequest(); request.responseType = Messages.COMPRESSABLE; request.responseParameters = new ResponseParameters[2]; request.responseParameters[0] = new ResponseParameters(); request.responseParameters[0].size = 100000; request.responseParameters[1] = new ResponseParameters(); request.responseParameters[1].size = 100001; final StreamingOutputCallResponse[] goldenResponses = new StreamingOutputCallResponse[2]; goldenResponses[0] = new StreamingOutputCallResponse(); goldenResponses[0].payload = new Payload(); goldenResponses[0].payload.type = Messages.COMPRESSABLE; goldenResponses[0].payload.body = new byte[100000]; goldenResponses[1] = new StreamingOutputCallResponse(); goldenResponses[1].payload = new Payload(); goldenResponses[1].payload.type = Messages.COMPRESSABLE; goldenResponses[1].payload.body = new byte[100001]; long start = System.nanoTime(); final ArrayBlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(10); ClientCall<StreamingOutputCallRequest, StreamingOutputCallResponse> call = channel.newCall(TestServiceGrpc.METHOD_STREAMING_OUTPUT_CALL, CallOptions.DEFAULT); call.start( new ClientCall.Listener<StreamingOutputCallResponse>() { @Override public void onHeaders(Metadata headers) {} @Override public void onMessage(final StreamingOutputCallResponse message) { queue.add(message); } @Override public void onClose(io.grpc.Status status, Metadata trailers) { queue.add(status); } }, new Metadata()); call.sendMessage(request); call.halfClose(); // Time how long it takes to get the first response. call.request(1); assertMessageEquals( goldenResponses[0], (StreamingOutputCallResponse) queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); long firstCallDuration = System.nanoTime() - start; // Without giving additional flow control, make sure that we don't get another response. We wait // until we are comfortable the next message isn't coming. We may have very low nanoTime // resolution (like on Windows) or be using a testing, in-process transport where message // handling is instantaneous. In both cases, firstCallDuration may be 0, so round up sleep time // to at least 1ms. assertNull(queue.poll(Math.max(firstCallDuration * 4, 1 * 1000 * 1000), TimeUnit.NANOSECONDS)); // Make sure that everything still completes. call.request(1); assertMessageEquals( goldenResponses[1], (StreamingOutputCallResponse) queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); assertCodeEquals( io.grpc.Status.OK, (io.grpc.Status) queue.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); }