mirror of https://github.com/grpc/grpc.git
commit
c34cac2891
430 changed files with 7855 additions and 3980 deletions
@ -0,0 +1,194 @@ |
||||
Negative HTTP/2 Interop Test Case Descriptions |
||||
======================================= |
||||
|
||||
Client and server use |
||||
[test.proto](../src/proto/grpc/testing/test.proto). |
||||
|
||||
Server |
||||
------ |
||||
The code for the custom http2 server can be found |
||||
[here](https://github.com/grpc/grpc/tree/master/test/http2_test). |
||||
It is responsible for handling requests and sending responses, and also for |
||||
fulfilling the behavior of each particular test case. |
||||
|
||||
Server should accept these arguments: |
||||
* --port=PORT |
||||
* The port the server will run on. For example, "8080" |
||||
* --test_case=TESTCASE |
||||
* The name of the test case to execute. For example, "goaway" |
||||
|
||||
Client |
||||
------ |
||||
|
||||
Clients implement test cases that test certain functionality. Each client is |
||||
provided the test case it is expected to run as a command-line parameter. Names |
||||
should be lowercase and without spaces. |
||||
|
||||
Clients should accept these arguments: |
||||
* --server_host=HOSTNAME |
||||
* The server host to connect to. For example, "localhost" or "127.0.0.1" |
||||
* --server_port=PORT |
||||
* The server port to connect to. For example, "8080" |
||||
* --test_case=TESTCASE |
||||
* The name of the test case to execute. For example, "goaway" |
||||
|
||||
Note |
||||
----- |
||||
|
||||
Note that the server and client must be invoked with the same test case or else |
||||
the test will be meaningless. For convenience, we provide a shell script wrapper |
||||
that invokes both server and client at the same time, with the same test_case. |
||||
This is the preferred way to run these tests. |
||||
|
||||
## Test Cases |
||||
|
||||
### goaway |
||||
|
||||
This test verifies that the client correctly responds to a goaway sent by the |
||||
server. The client should handle the goaway by switching to a new stream without |
||||
the user application having to do a thing. |
||||
|
||||
Client Procedure: |
||||
1. Client sends two UnaryCall requests with: |
||||
|
||||
``` |
||||
{ |
||||
response_size: 314159 |
||||
payload:{ |
||||
body: 271828 bytes of zeros |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Client asserts: |
||||
* Call was successful. |
||||
* Response payload body is 314159 bytes in size. |
||||
|
||||
Server Procedure: |
||||
1. Server sends a GOAWAY after receiving the first UnaryCall. |
||||
|
||||
Server asserts: |
||||
* The second UnaryCall has a different stream_id than the first one. |
||||
|
||||
### rst_after_header |
||||
|
||||
This test verifies that the client fails correctly when the server sends a |
||||
RST_STREAM immediately after sending headers to the client. |
||||
|
||||
Procedure: |
||||
1. Client sends UnaryCall with: |
||||
|
||||
``` |
||||
{ |
||||
response_size: 314159 |
||||
payload:{ |
||||
body: 271828 bytes of zeros |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Client asserts: |
||||
* Call was not successful. |
||||
|
||||
Server Procedure: |
||||
1. Server sends a RST_STREAM with error code 0 after sending headers to the client. |
||||
|
||||
*At the moment the error code and message returned are not standardized throughout all |
||||
languages. Those checks will be added once all client languages behave the same way. [#9142](https://github.com/grpc/grpc/issues/9142) is in flight.* |
||||
|
||||
### rst_during_data |
||||
|
||||
This test verifies that the client fails "correctly" when the server sends a |
||||
RST_STREAM halfway through sending data to the client. |
||||
|
||||
Procedure: |
||||
1. Client sends UnaryCall with: |
||||
|
||||
``` |
||||
{ |
||||
response_size: 314159 |
||||
payload:{ |
||||
body: 271828 bytes of zeros |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Client asserts: |
||||
* Call was not successful. |
||||
|
||||
Server Procedure: |
||||
1. Server sends a RST_STREAM with error code 0 after sending half of |
||||
the requested data to the client. |
||||
|
||||
### rst_after_data |
||||
|
||||
This test verifies that the client fails "correctly" when the server sends a |
||||
RST_STREAM after sending all of the data to the client. |
||||
|
||||
Procedure: |
||||
1. Client sends UnaryCall with: |
||||
|
||||
``` |
||||
{ |
||||
response_size: 314159 |
||||
payload:{ |
||||
body: 271828 bytes of zeros |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Client asserts: |
||||
* Call was not successful. |
||||
|
||||
Server Procedure: |
||||
1. Server sends a RST_STREAM with error code 0 after sending all of the |
||||
data to the client. |
||||
|
||||
*Certain client languages allow the data to be accessed even though a RST_STREAM |
||||
was encountered. Once all client languages behave this way, checks will be added on |
||||
the incoming data.* |
||||
|
||||
### ping |
||||
|
||||
This test verifies that the client correctly acknowledges all pings it gets from the |
||||
server. |
||||
|
||||
Procedure: |
||||
1. Client sends UnaryCall with: |
||||
|
||||
``` |
||||
{ |
||||
response_size: 314159 |
||||
payload:{ |
||||
body: 271828 bytes of zeros |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Client asserts: |
||||
* call was successful. |
||||
* response payload body is 314159 bytes in size. |
||||
|
||||
Server Procedure: |
||||
1. Server tracks the number of outstanding pings (i.e. +1 when it sends a ping, and -1 |
||||
when it receives an ack from the client). |
||||
2. Server sends pings before and after sending headers, also before and after sending data. |
||||
|
||||
Server Asserts: |
||||
* Number of outstanding pings is 0 when the connection is lost. |
||||
|
||||
### max_streams |
||||
|
||||
This test verifies that the client observes the MAX_CONCURRENT_STREAMS limit set by the server. |
||||
|
||||
Client Procedure: |
||||
1. Client sends initial UnaryCall to allow the server to update its MAX_CONCURRENT_STREAMS settings. |
||||
2. Client concurrently sends 10 UnaryCalls. |
||||
|
||||
Client Asserts: |
||||
* All UnaryCalls were successful, and had the correct type and payload size. |
||||
|
||||
Server Procedure: |
||||
1. Sets MAX_CONCURRENT_STREAMS to one after the connection is made. |
||||
|
||||
*The assertion that the MAX_CONCURRENT_STREAMS limit is upheld occurs in the http2 library we used.* |
@ -0,0 +1,47 @@ |
||||
import grpc |
||||
from grpc.framework.common import cardinality |
||||
from grpc.framework.interfaces.face import utilities as face_utilities |
||||
|
||||
import helloworld_pb2 as helloworld__pb2 |
||||
|
||||
|
||||
class GreeterStub(object): |
||||
"""The greeting service definition. |
||||
""" |
||||
|
||||
def __init__(self, channel): |
||||
"""Constructor. |
||||
|
||||
Args: |
||||
channel: A grpc.Channel. |
||||
""" |
||||
self.SayHello = channel.unary_unary( |
||||
'/helloworld.Greeter/SayHello', |
||||
request_serializer=helloworld__pb2.HelloRequest.SerializeToString, |
||||
response_deserializer=helloworld__pb2.HelloReply.FromString, |
||||
) |
||||
|
||||
|
||||
class GreeterServicer(object): |
||||
"""The greeting service definition. |
||||
""" |
||||
|
||||
def SayHello(self, request, context): |
||||
"""Sends a greeting |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
|
||||
def add_GreeterServicer_to_server(servicer, server): |
||||
rpc_method_handlers = { |
||||
'SayHello': grpc.unary_unary_rpc_method_handler( |
||||
servicer.SayHello, |
||||
request_deserializer=helloworld__pb2.HelloRequest.FromString, |
||||
response_serializer=helloworld__pb2.HelloReply.SerializeToString, |
||||
), |
||||
} |
||||
generic_handler = grpc.method_handlers_generic_handler( |
||||
'helloworld.Greeter', rpc_method_handlers) |
||||
server.add_generic_rpc_handlers((generic_handler,)) |
@ -0,0 +1,47 @@ |
||||
import grpc |
||||
from grpc.framework.common import cardinality |
||||
from grpc.framework.interfaces.face import utilities as face_utilities |
||||
|
||||
import helloworld_pb2 as helloworld__pb2 |
||||
|
||||
|
||||
class GreeterStub(object): |
||||
"""The greeting service definition. |
||||
""" |
||||
|
||||
def __init__(self, channel): |
||||
"""Constructor. |
||||
|
||||
Args: |
||||
channel: A grpc.Channel. |
||||
""" |
||||
self.SayHello = channel.unary_unary( |
||||
'/helloworld.Greeter/SayHello', |
||||
request_serializer=helloworld__pb2.HelloRequest.SerializeToString, |
||||
response_deserializer=helloworld__pb2.HelloReply.FromString, |
||||
) |
||||
|
||||
|
||||
class GreeterServicer(object): |
||||
"""The greeting service definition. |
||||
""" |
||||
|
||||
def SayHello(self, request, context): |
||||
"""Sends a greeting |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
|
||||
def add_GreeterServicer_to_server(servicer, server): |
||||
rpc_method_handlers = { |
||||
'SayHello': grpc.unary_unary_rpc_method_handler( |
||||
servicer.SayHello, |
||||
request_deserializer=helloworld__pb2.HelloRequest.FromString, |
||||
response_serializer=helloworld__pb2.HelloReply.SerializeToString, |
||||
), |
||||
} |
||||
generic_handler = grpc.method_handlers_generic_handler( |
||||
'helloworld.Greeter', rpc_method_handlers) |
||||
server.add_generic_rpc_handlers((generic_handler,)) |
@ -0,0 +1,114 @@ |
||||
import grpc |
||||
from grpc.framework.common import cardinality |
||||
from grpc.framework.interfaces.face import utilities as face_utilities |
||||
|
||||
import route_guide_pb2 as route__guide__pb2 |
||||
|
||||
|
||||
class RouteGuideStub(object): |
||||
"""Interface exported by the server. |
||||
""" |
||||
|
||||
def __init__(self, channel): |
||||
"""Constructor. |
||||
|
||||
Args: |
||||
channel: A grpc.Channel. |
||||
""" |
||||
self.GetFeature = channel.unary_unary( |
||||
'/routeguide.RouteGuide/GetFeature', |
||||
request_serializer=route__guide__pb2.Point.SerializeToString, |
||||
response_deserializer=route__guide__pb2.Feature.FromString, |
||||
) |
||||
self.ListFeatures = channel.unary_stream( |
||||
'/routeguide.RouteGuide/ListFeatures', |
||||
request_serializer=route__guide__pb2.Rectangle.SerializeToString, |
||||
response_deserializer=route__guide__pb2.Feature.FromString, |
||||
) |
||||
self.RecordRoute = channel.stream_unary( |
||||
'/routeguide.RouteGuide/RecordRoute', |
||||
request_serializer=route__guide__pb2.Point.SerializeToString, |
||||
response_deserializer=route__guide__pb2.RouteSummary.FromString, |
||||
) |
||||
self.RouteChat = channel.stream_stream( |
||||
'/routeguide.RouteGuide/RouteChat', |
||||
request_serializer=route__guide__pb2.RouteNote.SerializeToString, |
||||
response_deserializer=route__guide__pb2.RouteNote.FromString, |
||||
) |
||||
|
||||
|
||||
class RouteGuideServicer(object): |
||||
"""Interface exported by the server. |
||||
""" |
||||
|
||||
def GetFeature(self, request, context): |
||||
"""A simple RPC. |
||||
|
||||
Obtains the feature at a given position. |
||||
|
||||
A feature with an empty name is returned if there's no feature at the given |
||||
position. |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def ListFeatures(self, request, context): |
||||
"""A server-to-client streaming RPC. |
||||
|
||||
Obtains the Features available within the given Rectangle. Results are |
||||
streamed rather than returned at once (e.g. in a response message with a |
||||
repeated field), as the rectangle may cover a large area and contain a |
||||
huge number of features. |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def RecordRoute(self, request_iterator, context): |
||||
"""A client-to-server streaming RPC. |
||||
|
||||
Accepts a stream of Points on a route being traversed, returning a |
||||
RouteSummary when traversal is completed. |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def RouteChat(self, request_iterator, context): |
||||
"""A Bidirectional streaming RPC. |
||||
|
||||
Accepts a stream of RouteNotes sent while a route is being traversed, |
||||
while receiving other RouteNotes (e.g. from other users). |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
|
||||
def add_RouteGuideServicer_to_server(servicer, server): |
||||
rpc_method_handlers = { |
||||
'GetFeature': grpc.unary_unary_rpc_method_handler( |
||||
servicer.GetFeature, |
||||
request_deserializer=route__guide__pb2.Point.FromString, |
||||
response_serializer=route__guide__pb2.Feature.SerializeToString, |
||||
), |
||||
'ListFeatures': grpc.unary_stream_rpc_method_handler( |
||||
servicer.ListFeatures, |
||||
request_deserializer=route__guide__pb2.Rectangle.FromString, |
||||
response_serializer=route__guide__pb2.Feature.SerializeToString, |
||||
), |
||||
'RecordRoute': grpc.stream_unary_rpc_method_handler( |
||||
servicer.RecordRoute, |
||||
request_deserializer=route__guide__pb2.Point.FromString, |
||||
response_serializer=route__guide__pb2.RouteSummary.SerializeToString, |
||||
), |
||||
'RouteChat': grpc.stream_stream_rpc_method_handler( |
||||
servicer.RouteChat, |
||||
request_deserializer=route__guide__pb2.RouteNote.FromString, |
||||
response_serializer=route__guide__pb2.RouteNote.SerializeToString, |
||||
), |
||||
} |
||||
generic_handler = grpc.method_handlers_generic_handler( |
||||
'routeguide.RouteGuide', rpc_method_handlers) |
||||
server.add_generic_rpc_handlers((generic_handler,)) |
@ -0,0 +1,114 @@ |
||||
import grpc |
||||
from grpc.framework.common import cardinality |
||||
from grpc.framework.interfaces.face import utilities as face_utilities |
||||
|
||||
import route_guide_pb2 as route__guide__pb2 |
||||
|
||||
|
||||
class RouteGuideStub(object): |
||||
"""Interface exported by the server. |
||||
""" |
||||
|
||||
def __init__(self, channel): |
||||
"""Constructor. |
||||
|
||||
Args: |
||||
channel: A grpc.Channel. |
||||
""" |
||||
self.GetFeature = channel.unary_unary( |
||||
'/routeguide.RouteGuide/GetFeature', |
||||
request_serializer=route__guide__pb2.Point.SerializeToString, |
||||
response_deserializer=route__guide__pb2.Feature.FromString, |
||||
) |
||||
self.ListFeatures = channel.unary_stream( |
||||
'/routeguide.RouteGuide/ListFeatures', |
||||
request_serializer=route__guide__pb2.Rectangle.SerializeToString, |
||||
response_deserializer=route__guide__pb2.Feature.FromString, |
||||
) |
||||
self.RecordRoute = channel.stream_unary( |
||||
'/routeguide.RouteGuide/RecordRoute', |
||||
request_serializer=route__guide__pb2.Point.SerializeToString, |
||||
response_deserializer=route__guide__pb2.RouteSummary.FromString, |
||||
) |
||||
self.RouteChat = channel.stream_stream( |
||||
'/routeguide.RouteGuide/RouteChat', |
||||
request_serializer=route__guide__pb2.RouteNote.SerializeToString, |
||||
response_deserializer=route__guide__pb2.RouteNote.FromString, |
||||
) |
||||
|
||||
|
||||
class RouteGuideServicer(object): |
||||
"""Interface exported by the server. |
||||
""" |
||||
|
||||
def GetFeature(self, request, context): |
||||
"""A simple RPC. |
||||
|
||||
Obtains the feature at a given position. |
||||
|
||||
A feature with an empty name is returned if there's no feature at the given |
||||
position. |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def ListFeatures(self, request, context): |
||||
"""A server-to-client streaming RPC. |
||||
|
||||
Obtains the Features available within the given Rectangle. Results are |
||||
streamed rather than returned at once (e.g. in a response message with a |
||||
repeated field), as the rectangle may cover a large area and contain a |
||||
huge number of features. |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def RecordRoute(self, request_iterator, context): |
||||
"""A client-to-server streaming RPC. |
||||
|
||||
Accepts a stream of Points on a route being traversed, returning a |
||||
RouteSummary when traversal is completed. |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def RouteChat(self, request_iterator, context): |
||||
"""A Bidirectional streaming RPC. |
||||
|
||||
Accepts a stream of RouteNotes sent while a route is being traversed, |
||||
while receiving other RouteNotes (e.g. from other users). |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
|
||||
def add_RouteGuideServicer_to_server(servicer, server): |
||||
rpc_method_handlers = { |
||||
'GetFeature': grpc.unary_unary_rpc_method_handler( |
||||
servicer.GetFeature, |
||||
request_deserializer=route__guide__pb2.Point.FromString, |
||||
response_serializer=route__guide__pb2.Feature.SerializeToString, |
||||
), |
||||
'ListFeatures': grpc.unary_stream_rpc_method_handler( |
||||
servicer.ListFeatures, |
||||
request_deserializer=route__guide__pb2.Rectangle.FromString, |
||||
response_serializer=route__guide__pb2.Feature.SerializeToString, |
||||
), |
||||
'RecordRoute': grpc.stream_unary_rpc_method_handler( |
||||
servicer.RecordRoute, |
||||
request_deserializer=route__guide__pb2.Point.FromString, |
||||
response_serializer=route__guide__pb2.RouteSummary.SerializeToString, |
||||
), |
||||
'RouteChat': grpc.stream_stream_rpc_method_handler( |
||||
servicer.RouteChat, |
||||
request_deserializer=route__guide__pb2.RouteNote.FromString, |
||||
response_serializer=route__guide__pb2.RouteNote.SerializeToString, |
||||
), |
||||
} |
||||
generic_handler = grpc.method_handlers_generic_handler( |
||||
'routeguide.RouteGuide', rpc_method_handlers) |
||||
server.add_generic_rpc_handlers((generic_handler,)) |
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue