Skip to content

Commit

Permalink
Verify early OK behavior
Browse files Browse the repository at this point in the history
Looks like early OK support was implemented in
grpc#14080 but
grpc#7032 was not marked fixed at the
time.

Good thing it was just an idea on our Google Summer of Code ideas
page...
  • Loading branch information
nathanielmanistaatgoogle committed Mar 13, 2018
1 parent 44fd655 commit 7726c30
Show file tree
Hide file tree
Showing 7 changed files with 374 additions and 28 deletions.
162 changes: 162 additions & 0 deletions src/python/grpcio_tests/tests/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,168 @@
"unit._cython.cygrpc_test.InsecureServerInsecureClient",
"unit._cython.cygrpc_test.SecureServerSecureClient",
"unit._cython.cygrpc_test.TypeSmokeTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyEmptyRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManyLargeRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ManySmallRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoEmptyRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoLargeRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.TwoSmallRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroEmptyRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroLargeRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsTwoReadZeroSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadManyEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadManyLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadManySmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadTwoEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadTwoLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadTwoSmallResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadZeroEmptyResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadZeroLargeResponsesEarlyOKTest",
"unit._early_ok_test.ZeroSmallRequestsZeroReadZeroSmallResponsesEarlyOKTest",
"unit._empty_message_test.EmptyMessageTest",
"unit._exit_test.ExitTest",
"unit._interceptor_test.InterceptorTest",
Expand Down
6 changes: 2 additions & 4 deletions src/python/grpcio_tests/tests/unit/_compression_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@ def handle_unary(request, servicer_context):


def handle_stream(request_iterator, servicer_context):
# TODO(issue:#6891) We should be able to remove this loop,
# and replace with return; yield
servicer_context.send_initial_metadata([('grpc-internal-encoding-request',
'gzip')])
for request in request_iterator:
yield request
return
yield


class _MethodHandler(grpc.RpcMethodHandler):
Expand Down
206 changes: 206 additions & 0 deletions src/python/grpcio_tests/tests/unit/_early_ok_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# Copyright 2018 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests servicers sending OK status without having read all requests.
This is a regression test of https://github.com/grpc/grpc/issues/6891.
"""

import enum
import unittest

import six

import grpc

from tests.unit import test_common
from tests.unit.framework.common import test_constants

_RPC_METHOD = '/serffice/Meffod'


@enum.unique
class _MessageCount(enum.Enum):

ZERO = (
0,
'Zero',
)
TWO = (
1,
'Two',
)
MANY = (
test_constants.STREAM_LENGTH,
'Many',
)


@enum.unique
class _MessageSize(enum.Enum):
EMPTY = (
0,
'Empty',
)
SMALL = (
32,
'Small',
) # Smaller than any flow control window.
LARGE = (
3 * 1024 * 1024,
'Large',
) # Larger than any flow control window.


_ZERO_MESSAGE = b''
_SMALL_MESSAGE = b'\x07' * _MessageSize.SMALL.value[0]
_LARGE_MESSAGE = b'abc' * (_MessageSize.LARGE.value[0] // 3)


@enum.unique
class _ReadRequests(enum.Enum):

ZERO = (
0,
'Zero',
)
TWO = (
2,
'Two',
)


class _Case(object):

def __init__(self, request_count, request_size, request_reading,
response_count, response_size):
self.request_count = request_count
self.request_size = request_size
self.request_reading = request_reading
self.response_count = response_count
self.response_size = response_size

def create_test_case_name(self):
return '{}{}Requests{}Read{}{}ResponsesEarlyOKTest'.format(
self.request_count.value[1], self.request_size.value[1],
self.request_reading.value[1], self.response_count.value[1],
self.response_size.value[1])


def _message(message_size):
if message_size is _MessageSize.EMPTY:
return _ZERO_MESSAGE
elif message_size is _MessageSize.SMALL:
return _SMALL_MESSAGE
elif message_size is _MessageSize.LARGE:
return _LARGE_MESSAGE


def _messages_to_send(count, size):
for _ in range(count.value[0]):
yield _message(size)


def _draw_requests(case, request_iterator):
for _ in range(
min(case.request_count.value[0], case.request_reading.value[0])):
next(request_iterator)


def _draw_responses(case, response_iterator):
for _ in range(case.response_count.value[0]):
next(response_iterator)


class _MethodHandler(grpc.RpcMethodHandler):

def __init__(self, case):
self.request_streaming = True
self.response_streaming = True
self.request_deserializer = None
self.response_serializer = None
self.unary_unary = None
self.unary_stream = None
self.stream_unary = None
self._case = case

def stream_stream(self, request_iterator, servicer_context):
_draw_requests(self._case, request_iterator)

for response in _messages_to_send(self._case.response_count,
self._case.response_size):
yield response


class _GenericHandler(grpc.GenericRpcHandler):

def __init__(self, case):
self._case = case

def service(self, handler_call_details):
return _MethodHandler(self._case)


class _EarlyOkTest(unittest.TestCase):

def setUp(self):
self._server = test_common.test_server()
port = self._server.add_insecure_port('[::]:0')
self._server.add_generic_rpc_handlers((_GenericHandler(self.case),))
self._server.start()

self._channel = grpc.insecure_channel('localhost:%d' % port)
self._multi_callable = self._channel.stream_stream(_RPC_METHOD)

def tearDown(self):
self._server.stop(None)

def test_early_ok(self):
requests = _messages_to_send(self.case.request_count,
self.case.request_size)

response_iterator_call = self._multi_callable(requests)

_draw_responses(self.case, response_iterator_call)

self.assertIs(grpc.StatusCode.OK, response_iterator_call.code())


def _cases():
for request_count in _MessageCount:
for request_size in _MessageSize:
for request_reading in _ReadRequests:
for response_count in _MessageCount:
for response_size in _MessageSize:
yield _Case(request_count, request_size,
request_reading, response_count,
response_size)


def _test_case_classes():
for case in _cases():
yield type(case.create_test_case_name(), (_EarlyOkTest,), {
'case': case,
'__module__': _EarlyOkTest.__module__,
})


def load_tests(loader, tests, pattern):
return unittest.TestSuite(
tests=tuple(
loader.loadTestsFromTestCase(test_case_class)
for test_case_class in _test_case_classes()))


if __name__ == '__main__':
unittest.main(verbosity=2)
Loading

0 comments on commit 7726c30

Please sign in to comment.