Merge branch 'master' of https://github.com/grpc/grpc into the-purge-2

Conflicts:
	test/cpp/end2end/async_end2end_test.cc
	test/cpp/end2end/end2end_test.cc
	test/cpp/interop/client.cc
pull/1227/head
Nicolas "Pixel" Noble 10 years ago
commit b7c2035e83
  1. 1283
      BUILD
  2. 365
      Makefile
  3. 83
      build.json
  4. 685
      doc/interop-test-descriptions.md
  5. 2
      examples/pubsub/publisher.h
  6. 2
      examples/pubsub/subscriber.h
  7. 11
      include/grpc++/time.h
  8. 160
      src/compiler/cpp_generator.cc
  9. 19
      src/compiler/cpp_generator.h
  10. 36
      src/compiler/cpp_plugin.cc
  11. 21
      src/compiler/generator_helpers.h
  12. 236
      src/compiler/objective_c_generator.cc
  13. 48
      src/compiler/objective_c_generator.h
  14. 58
      src/compiler/objective_c_generator_helpers.h
  15. 98
      src/compiler/objective_c_plugin.cc
  16. 4
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  17. 4
      src/core/iomgr/pollset_posix.c
  18. 6
      src/core/iomgr/tcp_server.h
  19. 60
      src/core/iomgr/tcp_server_posix.c
  20. 36
      src/core/iomgr/tcp_server_windows.c
  21. 19
      src/core/security/server_secure_chttp2.c
  22. 2
      src/core/support/thd_win32.c
  23. 8
      src/core/surface/completion_queue.c
  24. 4
      src/core/surface/completion_queue.h
  25. 55
      src/core/surface/server.c
  26. 7
      src/core/surface/server.h
  27. 7
      src/core/surface/server_chttp2.c
  28. 35
      src/cpp/client/secure_credentials.cc
  29. 61
      src/cpp/client/secure_credentials.h
  30. 31
      src/cpp/server/secure_server_credentials.cc
  31. 60
      src/cpp/server/secure_server_credentials.h
  32. 2
      src/csharp/Grpc.Examples.MathServer/.gitignore
  33. 52
      src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
  34. 61
      src/csharp/Grpc.Examples.MathServer/MathServer.cs
  35. 12
      src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs
  36. 6
      src/csharp/Grpc.sln
  37. 40
      src/php/bin/generate_proto_php.sh
  38. 11
      src/php/ext/grpc/call.c
  39. 1
      src/php/ext/grpc/channel.c
  40. 10
      src/python/interop/interop/_interop_test_case.py
  41. 24
      src/python/interop/interop/client.py
  42. 60
      src/python/interop/interop/methods.py
  43. 2
      src/python/interop/setup.py
  44. 79
      templates/BUILD.template
  45. 17
      templates/Makefile.template
  46. 6
      test/core/end2end/tests/cancel_after_invoke.c
  47. 9
      test/core/end2end/tests/cancel_test_helpers.h
  48. 10
      test/core/iomgr/tcp_server_posix_test.c
  49. 6
      test/cpp/end2end/async_end2end_test.cc
  50. 4
      test/cpp/end2end/end2end_test.cc
  51. 2
      test/cpp/end2end/generic_end2end_test.cc
  52. 392
      test/cpp/interop/client.cc
  53. 121
      test/cpp/interop/client_helper.cc
  54. 53
      test/cpp/interop/client_helper.h
  55. 311
      test/cpp/interop/interop_client.cc
  56. 79
      test/cpp/interop/interop_client.h
  57. 19
      test/cpp/interop/server.cc
  58. 69
      test/cpp/interop/server_helper.cc
  59. 49
      test/cpp/interop/server_helper.h
  60. 34
      test/cpp/qps/client.h
  61. 38
      test/cpp/qps/client_async.cc
  62. 15
      test/cpp/qps/client_sync.cc
  63. 8
      test/cpp/qps/driver.cc
  64. 7
      test/cpp/qps/driver.h
  65. 6
      test/cpp/qps/histogram.h
  66. 47
      test/cpp/qps/qps_driver.cc
  67. 94
      test/cpp/qps/report.cc
  68. 57
      test/cpp/qps/report.h
  69. 2
      test/cpp/qps/server.h
  70. 22
      test/cpp/qps/server_async.cc
  71. 2
      test/cpp/qps/server_sync.cc
  72. 149
      test/cpp/qps/smoke_test.cc
  73. 28
      test/cpp/qps/smoke_test.sh
  74. 2
      test/cpp/qps/worker.cc
  75. 2
      test/cpp/util/cli_call_test.cc
  76. 21
      tools/distpackages/build_deb_packages.sh
  77. 3
      tools/distpackages/templates/libgrpc/DEBIAN/control
  78. 10
      tools/dockerfile/grpc_build_deb/Dockerfile
  79. 2
      tools/dockerfile/grpc_build_deb/version.txt
  80. 2
      tools/dockerfile/grpc_dist_proto/version.txt
  81. 3
      tools/dockerfile/grpc_python/Dockerfile
  82. 34
      tools/gce_setup/grpc_docker.sh
  83. 2
      tools/gce_setup/interop_test_runner.sh
  84. 6
      tools/gce_setup/shared_startup_funcs.sh
  85. 8
      vsprojects/vs2010/grpc++.vcxproj
  86. 24
      vsprojects/vs2010/grpc++.vcxproj.filters
  87. 8
      vsprojects/vs2013/grpc++.vcxproj
  88. 24
      vsprojects/vs2013/grpc++.vcxproj.filters

1283
BUILD

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -29,6 +29,12 @@
"include/grpc++/impl/rpc_method.h",
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",
"include/grpc++/impl/sync_no_cxx11.h",
"include/grpc++/impl/thd.h",
"include/grpc++/impl/thd_cxx11.h",
"include/grpc++/impl/thd_no_cxx11.h",
"include/grpc++/server.h",
"include/grpc++/server_builder.h",
"include/grpc++/server_context.h",
@ -464,6 +470,10 @@
"name": "grpc++",
"build": "all",
"language": "c++",
"headers": [
"src/cpp/client/secure_credentials.h",
"src/cpp/server/secure_server_credentials.h"
],
"src": [
"src/cpp/client/secure_credentials.cc",
"src/cpp/server/secure_server_credentials.cc"
@ -514,6 +524,8 @@
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h",
"src/compiler/generator_helpers.h",
"src/compiler/objective_c_generator.h",
"src/compiler/objective_c_generator_helpers.h",
"src/compiler/python_generator.h",
"src/compiler/ruby_generator.h",
"src/compiler/ruby_generator_helpers-inl.h",
@ -522,12 +534,46 @@
],
"src": [
"src/compiler/cpp_generator.cc",
"src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc"
],
"deps": [],
"secure": "no"
},
{
"name": "interop_client_lib",
"build": "private",
"language": "c++",
"src": [
"test/cpp/interop/empty.proto",
"test/cpp/interop/messages.proto",
"test/cpp/interop/test.proto",
"test/cpp/interop/client_helper.cc",
"test/cpp/interop/interop_client.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr"
]
},
{
"name": "interop_server_lib",
"build": "private",
"language": "c++",
"src": [
"test/cpp/interop/server_helper.cc"
],
"deps": [
"grpc_test_util",
"grpc++",
"grpc",
"gpr"
]
},
{
"name": "pubsub_client_lib",
"build": "private",
@ -551,11 +597,13 @@
"language": "c++",
"headers": [
"test/cpp/qps/driver.h",
"test/cpp/qps/report.h",
"test/cpp/qps/timer.h"
],
"src": [
"test/cpp/qps/qpstest.proto",
"test/cpp/qps/driver.cc",
"test/cpp/qps/report.cc",
"test/cpp/qps/timer.cc"
]
},
@ -1817,6 +1865,18 @@
],
"secure": "no"
},
{
"name": "grpc_objective_c_plugin",
"build": "protoc",
"language": "c++",
"src": [
"src/compiler/objective_c_plugin.cc"
],
"deps": [
"grpc_plugin_support"
],
"secure": "no"
},
{
"name": "grpc_python_plugin",
"build": "protoc",
@ -1847,12 +1907,10 @@
"run": false,
"language": "c++",
"src": [
"test/cpp/interop/empty.proto",
"test/cpp/interop/messages.proto",
"test/cpp/interop/test.proto",
"test/cpp/interop/client.cc"
],
"deps": [
"interop_client_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
@ -1873,6 +1931,7 @@
"test/cpp/interop/server.cc"
],
"deps": [
"interop_server_lib",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
@ -1964,6 +2023,24 @@
"gpr"
]
},
{
"name": "qps_smoke_test",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/qps/smoke_test.cc"
],
"deps": [
"qps",
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "qps_worker",
"build": "test",

@ -0,0 +1,685 @@
Interoperability Test Case Descriptions
=======================================
Client and server use
[test.proto](https://github.com/grpc/grpc/blob/master/test/cpp/interop/test.proto)
and the [gRPC over HTTP/2 v2
protocol](https://github.com/grpc/grpc-common/blob/master/PROTOCOL-HTTP2.md).
Client
------
Clients implement test cases that test certain functionally. 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_host_override=HOSTNAME
* The server host to claim to be connecting to, for use in TLS and HTTP/2
:authority header. If unspecified, the value of --server_host will be
used
* --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, "empty_unary"
* --use_tls=BOOLEAN
* Whether to use a plaintext or encrypted connection
* --use_test_ca=BOOLEAN
* Whether to replace platform root CAs with
[ca.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/ca.pem)
as the CA root
Clients must support TLS with ALPN. Clients must not disable certificate
checking.
### empty_unary
This test verifies that implementations support zero-size messages. Ideally,
client implementations would verify that the request and response were zero
bytes serialized, but this is generally prohibitive to perform, so is not
required.
Server features:
* [EmptyCall][]
Procedure:
1. Client calls EmptyCall with the default Empty message
Asserts:
* call was successful
* response is non-null
*It may be possible to use UnaryCall instead of EmptyCall, but it is harder to
ensure that the proto serialized to zero bytes.*
### large_unary
This test verifies unary calls succeed in sending messages, and touches on flow
control (even if compression is enabled on the channel).
Server features:
* [UnaryCall][]
* [Compressable Payload][]
Procedure:
1. Client calls UnaryCall with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
Asserts:
* call was successful
* response payload type is COMPRESSABLE
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
### client_streaming
This test verifies that client-only streaming succeeds.
Server features:
* [StreamingInputCall][]
* [Compressable Payload][]
Procedure:
1. Client calls StreamingInputCall
2. Client sends:
```
{
payload:{
body: 27182 bytes of zeros
}
}
```
3. Client then sends:
```
{
payload:{
body: 8 bytes of zeros
}
}
```
4. Client then sends:
```
{
payload:{
body: 1828 bytes of zeros
}
}
```
5. Client then sends:
```
{
payload:{
body: 45904 bytes of zeros
}
}
```
6. Client halfCloses
Asserts:
* call was successful
* response aggregated_payload_size is 74922
### server_streaming
This test verifies that server-only streaming succeeds.
Server features:
* [StreamingOutputCall][]
* [Compressable Payload][]
Procedure:
1. Client calls StreamingOutputCall with:
```
{
response_type:COMPRESSABLE
response_parameters:{
size: 31415
}
response_parameters:{
size: 9
}
response_parameters:{
size: 2653
}
response_parameters:{
size: 58979
}
}
```
Asserts:
* call was successful
* exactly four responses
* response payloads are COMPRESSABLE
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
* clients are free to assert that the response payload body contents are zero
and comparing the entire response messages against golden responses
### ping_pong
This test verifies that full duplex bidi is supported.
Server features:
* [FullDuplexCall][]
* [Compressable Payload][]
Procedure:
1. Client calls FullDuplexCall with:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 31415
}
payload:{
body: 27182 bytes of zeros
}
}
```
2. After getting a reply, it sends:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 9
}
payload:{
body: 8 bytes of zeros
}
}
```
3. After getting a reply, it sends:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 2653
}
payload:{
body: 1828 bytes of zeros
}
}
```
4. After getting a reply, it sends:
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 58979
}
payload:{
body: 45904 bytes of zeros
}
}
```
Asserts:
* call was successful
* exactly four responses
* response payloads are COMPRESSABLE
* response payload bodies are sized (in order): 31415, 9, 2653, 58979
* clients are free to assert that the response payload body contents are zero
and comparing the entire response messages against golden responses
### empty_stream
This test verifies that streams support having zero-messages in both
directions.
Server features:
* [FullDuplexCall][]
Procedure:
1. Client calls FullDuplexCall and then half-closes
Asserts:
* call was successful
* exactly zero responses
### compute_engine_creds
Status: Not yet implementable
This test is only for cloud-to-prod path.
This test verifies unary calls succeed in sending messages while using Service
Credentials from GCE metadata server. The client instance needs to be created
with desired oauth scope.
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* SimpeResponse.username
* SimpleResponse.oauth_scope
Procedure:
1. Client sets flags default_service_account with GCE service account name and
oauth_scope with the oauth scope to use.
2. Client configures channel to use GCECredentials
3. Client calls UnaryCall on the channel with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
fill_username: true
fill_oauth_scope: true
}
```
Asserts:
* call was successful
* received SimpleResponse.username equals FLAGS_default_service_account
* received SimpleResponse.oauth_scope is in FLAGS_oauth_scope
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
### service_account_creds
Status: Not yet implementable
This test is only for cloud-to-prod path.
This test verifies unary calls succeed in sending messages while using JWT
signing keys (redeemed for OAuth2 access tokens by the auth implementation)
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* SimpleResponse.username
* SimpleResponse.oauth_scope
Procedure:
1. Client sets flags service_account_key_file with the path to json key file,
oauth_scope to the oauth scope.
2. Client configures the channel to use ServiceAccountCredentials.
3. Client calls UnaryCall with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
fill_username: true
fill_oauth_scope: true
}
```
Asserts:
* call was successful
* received SimpleResponse.username is in the json key file read from
FLAGS_service_account_key_file
* received SimpleResponse.oauth_scope is in FLAGS_oauth_scope
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
### jwt_token_creds
Status: Not yet implementable
This test is only for cloud-to-prod path.
This test verifies unary calls succeed in sending messages while using JWT
token (created by the project's key file)
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* SimpleResponse.username
* SimpleResponse.oauth_scope
Procedure:
1. Client sets flags service_account_key_file with the path to json key file
2. Client configures the channel to use JWTTokenCredentials.
3. Client calls UnaryCall with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
fill_username: true
}
```
Asserts:
* call was successful
* received SimpleResponse.username is in the json key file read from
FLAGS_service_account_key_file
* response payload body is 314159 bytes in size
* clients are free to assert that the response payload body contents are zero
and comparing the entire response message against a golden response
### Metadata (TODO: fix name)
Status: Not yet implementable
This test verifies that custom metadata in either binary or ascii format can be
sent in header and trailer.
Server features:
* [UnaryCall][]
* [Compressable Payload][]
* Ability to receive custom metadata from client in header and send custom data
back to client in both header and trailer. (TODO: this is not defined)
Procedure:
1. While sending custom metadata (ascii + binary) in the header, client calls UnaryCall with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
Asserts:
* call was successful
* custom metadata is echoed back in the response header.
* custom metadata is echoed back in the response trailer.
### status_code_and_message
Status: Not yet implementable
This test verifies unary calls succeed in sending messages, and propagates back
status code and message sent along with the messages.
Server features:
* [UnaryCall][]
Procedure:
1. Client calls UnaryCall with:
```
{
response_status:{
code: 2
message: "test status message"
}
}
```
Asserts:
* received status code is the same with sent code
* received status message is the same with sent message
### unimplemented_method
Status: Not yet implementable
This test verifies calling unimplemented RPC method returns unimplemented
status.
Procedure:
* Client calls UnimplementedCall with:
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
Asserts:
* received status code is 12 (UNIMPLEMENTED)
* received status message is empty or null/unset
### cancel_after_begin
This test verifies that a request can be cancelled after metadata has been sent
but before payloads are sent.
Server features:
* [StreamingInputCall][]
Procedure:
1. Client starts StreamingInputCall
2. Client immediately cancels request
Asserts:
* Call completed with status CANCELLED
### cancel_after_first_response
This test verifies that a request can be cancelled after receiving a message
from the server.
Server features:
* [FullDuplexCall][]
* [Compressable Payload][]
Procedure:
1. Client starts FullDuplexCall with
```
{
response_type: COMPRESSABLE
response_parameters:{
size: 31415
}
payload:{
body: 27182 bytes of zeros
}
}
```
2. After receiving a response, client cancels request
Asserts:
* Call completed with status CANCELLED
### concurrent_large_unary
Status: TODO
Client performs 1000 large_unary tests in parallel on the same channel.
### Flow control. Pushback at client for large messages (TODO: fix name)
Status: TODO
This test verifies that a client sending faster than a server can drain sees
pushback (i.e., attempts to send succeed only after appropriate delays).
### TODO Tests
High priority:
Propagation of status code and message (yangg)
Cancel after sent headers (ctiller - done)
Cancel after received first message (ctiller - done)
Timeout after expire (zhaoq)
Zero-message streams (ejona)
Multiple thousand simultaneous calls on same Channel (ctiller - done)
OAuth2 tokens + Service Credentials from GCE metadata server (GCE->prod only)
(abhishek)
OAuth2 tokens + JWT signing key (GCE->prod only) (abhishek)
Metadata: client headers, server headers + trailers, binary+ascii (chenw)
Normal priority:
Cancel before start (ctiller)
Cancel after sent first message (ctiller)
Cancel after received headers (ctiller)
Timeout but completed before expire (zhaoq)
Multiple thousand simultaneous calls timeout on same Channel (ctiller)
Lower priority:
Flow control. Pushback at client for large messages (abhishek)
Flow control. Pushback at server for large messages (abhishek)
Going over max concurrent streams doesn't fail (client controls itself)
(abhishek)
RPC method not implemented (yangg)
Multiple thousand simultaneous calls on different Channels (ctiller)
Failed TLS hostname verification (ejona?)
To priorize:
Start streaming RPC but don't send any requests, server responds
### Postponed Tests
Resilience to buggy servers: These tests would verify that a client application
isn't affected negatively by the responses put on the wire by a buggy server
(e.g. the client library won't make the application crash).
Reconnect after transport failure
Reconnect backoff
Fuzz testing
Server
------
Servers implement various named features for clients to test with. Server
features are orthogonal. If a server implements a feature, it is always
available for clients. Names are simple descriptions for developer
communication and tracking.
Servers should accept these arguments:
* --port=PORT
* The port to listen on. For example, "8080"
* --use_tls=BOOLEAN
* Whether to use a plaintext or encrypted connection
Servers must support TLS with ALPN. They should use
[server1.pem](https://github.com/grpc/grpc/blob/master/src/core/tsi/test_creds/server1.pem)
for their certificate.
### EmptyCall
[EmptyCall]: #emptycall
Server implements EmptyCall which immediately returns the empty message.
### UnaryCall
[UnaryCall]: #unarycall
Server implements UnaryCall which immediately returns a SimpleResponse with a
payload body of size SimpleRequest.response_size bytes and type as appropriate
for the SimpleRequest.response_type. If the server does not support the
response_type, then it should fail the RPC with INVALID_ARGUMENT.
If the request sets fill_username, the server should return the client username
it sees in field SimpleResponse.username. If the request sets fill_oauth_scope,
the server should return the oauth scope of the rpc in the form of "xapi_zoo"
in field SimpleResponse.oauth_scope.
### StreamingInputCall
[StreamingInputCall]: #streaminginputcall
Server implements StreamingInputCall which upon half close immediately returns
a StreamingInputCallResponse where aggregated_payload_size is the sum of all
request payload bodies received.
### StreamingOutputCall
[StreamingOutputCall]: #streamingoutputcall
Server implements StreamingOutputCall by replying, in order, with one
StreamingOutputCallResponses for each ResponseParameters in
StreamingOutputCallRequest. Each StreamingOutputCallResponses should have a
payload body of size ResponseParameters.size bytes, as specified by its
respective ResponseParameters. After sending all responses, it closes with OK.
### FullDuplexCall
[FullDuplexCall]: #fullduplexcall
Server implements FullDuplexCall by replying, in order, with one
StreamingOutputCallResponses for each ResponseParameters in each
StreamingOutputCallRequest. Each StreamingOutputCallResponses should have a
payload body of size ResponseParameters.size bytes, as specified by its
respective ResponseParameters. After receiving half close and sending all
responses, it closes with OK.
### Compressable Payload
[Compressable Payload]: #compressable-payload
When the client requests COMPRESSABLE payload, the response includes a payload
of the size requested containing all zeros and the payload type is
COMPRESSABLE.
### Observe ResponseParameters.interval_us
[Observe ResponseParameters.interval_us]: #observe-responseparametersinterval_us
In StreamingOutputCall and FullDuplexCall, server delays sending a
StreamingOutputCallResponse by the ResponseParameters's interval_us for that
particular response, relative to the last response sent. That is, interval_us
acts like a sleep *before* sending the response and accumulates from one
response to the next.
Interaction with flow control is unspecified.
### Echo Auth Information
Status: Pending
If a SimpleRequest has fill_username=true and that request was successfully
authenticated, then the SimpleResponse should have username filled with the
canonical form of the authenticated source. The canonical form is dependent on
the authentication method, but is likely to be a base 10 integer identifier or
an email address.
Discussion:
Ideally, this would be communicated via metadata and not in the
request/response, but we want to use this test in code paths that don't yet
fully communicate metadata.

@ -37,7 +37,7 @@
#include <grpc++/channel_interface.h>
#include <grpc++/status.h>
#include "examples/pubsub/pubsub.pb.h"
#include "examples/pubsub/pubsub.grpc.pb.h"
namespace grpc {
namespace examples {

@ -37,7 +37,7 @@
#include <grpc++/channel_interface.h>
#include <grpc++/status.h>
#include "examples/pubsub/pubsub.pb.h"
#include "examples/pubsub/pubsub.grpc.pb.h"
namespace grpc {
namespace examples {

@ -41,8 +41,8 @@ namespace grpc {
/* If you are trying to use CompletionQueue::AsyncNext with a time class that
isn't either gpr_timespec or std::chrono::system_clock::time_point, you
will most likely be looking at that comment as your compiler will have
fired the static_assert below. In order to fix that issue, you have two
potential solutions:
fired an error below. In order to fix that issue, you have two potential
solutions:
1. Use gpr_timespec or std::chrono::system_clock::time_point instead
2. Specialize the TimePoint class with whichever time class that you
@ -53,11 +53,14 @@ template <typename T>
class TimePoint {
public:
TimePoint(const T& time) {
static_assert(false, "You need a specialization of TimePoint");
you_need_a_specialization_of_TimePoint();
}
gpr_timespec raw_time() {
static_assert(false, "You need a specialization of TimePoint");
gpr_timespec t;
return t;
}
private:
void you_need_a_specialization_of_TimePoint();
};
template<>

@ -109,8 +109,47 @@ bool HasBidiStreaming(const grpc::protobuf::FileDescriptor *file) {
}
return false;
}
grpc::string FilenameIdentifier(const grpc::string& filename) {
grpc::string result;
for (unsigned i = 0; i < filename.size(); i++) {
char c = filename[i];
if (isalnum(c)) {
result.push_back(c);
} else {
static char hex[] = "0123456789abcdef";
result.push_back('_');
result.push_back(hex[(c >> 4) & 0xf]);
result.push_back(hex[c & 0xf]);
}
}
return result;
}
} // namespace
grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params) {
grpc::string output;
grpc::protobuf::io::StringOutputStream output_stream(&output);
grpc::protobuf::io::Printer printer(&output_stream, '$');
std::map<grpc::string, grpc::string> vars;
vars["filename"] = file->name();
vars["filename_identifier"] = FilenameIdentifier(file->name());
vars["filename_base"] = grpc_generator::StripProto(file->name());
printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n");
printer.Print(vars, "// If you make any local change, they will be lost.\n");
printer.Print(vars, "// source: $filename$\n");
printer.Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
printer.Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
printer.Print(vars, "\n");
printer.Print(vars, "#include \"$filename_base$.pb.h\"\n");
printer.Print(vars, "\n");
return output;
}
grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
const Parameters &params) {
grpc::string temp =
@ -156,17 +195,22 @@ grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
"class ServerAsyncReaderWriter;\n");
}
temp.append("} // namespace grpc\n");
return temp;
}
grpc::string GetSourceIncludes(const Parameters &param) {
return "#include <grpc++/async_unary_call.h>\n"
"#include <grpc++/channel_interface.h>\n"
"#include <grpc++/impl/client_unary_call.h>\n"
"#include <grpc++/impl/rpc_method.h>\n"
"#include <grpc++/impl/rpc_service_method.h>\n"
"#include <grpc++/impl/service_type.h>\n"
"#include <grpc++/stream.h>\n";
temp.append("\n");
if (!file->package().empty()) {
std::vector<grpc::string> parts =
grpc_generator::tokenize(file->package(), ".");
for (auto part = parts.begin(); part != parts.end(); part++) {
temp.append("namespace ");
temp.append(*part);
temp.append(" {\n");
}
temp.append("\n");
}
return temp;
}
void PrintHeaderClientMethod(grpc::protobuf::io::Printer *printer,
@ -378,6 +422,83 @@ grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
return output;
}
grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params) {
grpc::string output;
grpc::protobuf::io::StringOutputStream output_stream(&output);
grpc::protobuf::io::Printer printer(&output_stream, '$');
std::map<grpc::string, grpc::string> vars;
vars["filename"] = file->name();
vars["filename_identifier"] = FilenameIdentifier(file->name());
if (!file->package().empty()) {
std::vector<grpc::string> parts =
grpc_generator::tokenize(file->package(), ".");
for (auto part = parts.rbegin(); part != parts.rend(); part++) {
vars["part"] = *part;
printer.Print(vars, "} // namespace $part$\n");
}
printer.Print(vars, "\n");
}
printer.Print(vars, "\n");
printer.Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
return output;
}
grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params) {
grpc::string output;
grpc::protobuf::io::StringOutputStream output_stream(&output);
grpc::protobuf::io::Printer printer(&output_stream, '$');
std::map<grpc::string, grpc::string> vars;
vars["filename"] = file->name();
vars["filename_base"] = grpc_generator::StripProto(file->name());
printer.Print(vars, "// Generated by the gRPC protobuf plugin.\n");
printer.Print(vars, "// If you make any local change, they will be lost.\n");
printer.Print(vars, "// source: $filename$\n\n");
printer.Print(vars, "#include \"$filename_base$.pb.h\"\n");
printer.Print(vars, "#include \"$filename_base$.grpc.pb.h\"\n");
printer.Print(vars, "\n");
return output;
}
grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
const Parameters &param) {
grpc::string output;
grpc::protobuf::io::StringOutputStream output_stream(&output);
grpc::protobuf::io::Printer printer(&output_stream, '$');
std::map<grpc::string, grpc::string> vars;
printer.Print(vars, "#include <grpc++/async_unary_call.h>\n");
printer.Print(vars, "#include <grpc++/channel_interface.h>\n");
printer.Print(vars, "#include <grpc++/impl/client_unary_call.h>\n");
printer.Print(vars, "#include <grpc++/impl/rpc_method.h>\n");
printer.Print(vars, "#include <grpc++/impl/rpc_service_method.h>\n");
printer.Print(vars, "#include <grpc++/impl/service_type.h>\n");
printer.Print(vars, "#include <grpc++/stream.h>\n");
if (!file->package().empty()) {
std::vector<grpc::string> parts =
grpc_generator::tokenize(file->package(), ".");
for (auto part = parts.begin(); part != parts.end(); part++) {
vars["part"] = *part;
printer.Print(vars, "namespace $part$ {\n");
}
}
printer.Print(vars, "\n");
return output;
}
void PrintSourceClientMethod(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
@ -741,4 +862,23 @@ grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file,
return output;
}
grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params) {
grpc::string temp;
if (!file->package().empty()) {
std::vector<grpc::string> parts =
grpc_generator::tokenize(file->package(), ".");
for (auto part = parts.begin(); part != parts.end(); part++) {
temp.append("} // namespace ");
temp.append(*part);
temp.append("\n");
}
temp.append("\n");
}
return temp;
}
} // namespace grpc_cpp_generator

@ -44,12 +44,25 @@ struct Parameters {
grpc::string services_namespace;
};
// Return the prologue of the generated header file.
grpc::string GetHeaderPrologue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the includes needed for generated header file.
grpc::string GetHeaderIncludes(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the includes needed for generated source file.
grpc::string GetSourceIncludes(const Parameters &params);
grpc::string GetSourceIncludes(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the epilogue of the generated header file.
grpc::string GetHeaderEpilogue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the prologue of the generated source file.
grpc::string GetSourcePrologue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the services for generated header file.
grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
@ -59,6 +72,10 @@ grpc::string GetHeaderServices(const grpc::protobuf::FileDescriptor *file,
grpc::string GetSourceServices(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
// Return the epilogue of the generated source file.
grpc::string GetSourceEpilogue(const grpc::protobuf::FileDescriptor *file,
const Parameters &params);
} // namespace grpc_cpp_generator
#endif // GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H

@ -58,11 +58,6 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
return false;
}
if (file->service_count() == 0) {
// No services. Do nothing.
return true;
}
grpc_cpp_generator::Parameters generator_parameters;
if (!parameter.empty()) {
@ -84,16 +79,27 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
grpc::string file_name = grpc_generator::StripProto(file->name());
// Generate .pb.h
Insert(context, file_name + ".pb.h", "includes",
grpc_cpp_generator::GetHeaderIncludes(file, generator_parameters));
Insert(context, file_name + ".pb.h", "namespace_scope",
grpc_cpp_generator::GetHeaderServices(file, generator_parameters));
// Generate .pb.cc
Insert(context, file_name + ".pb.cc", "includes",
grpc_cpp_generator::GetSourceIncludes(generator_parameters));
Insert(context, file_name + ".pb.cc", "namespace_scope",
grpc_cpp_generator::GetSourceServices(file, generator_parameters));
grpc::string header_code =
grpc_cpp_generator::GetHeaderPrologue(file, generator_parameters) +
grpc_cpp_generator::GetHeaderIncludes(file, generator_parameters) +
grpc_cpp_generator::GetHeaderServices(file, generator_parameters) +
grpc_cpp_generator::GetHeaderEpilogue(file, generator_parameters);
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> header_output(
context->Open(file_name + ".grpc.pb.h"));
grpc::protobuf::io::CodedOutputStream header_coded_out(
header_output.get());
header_coded_out.WriteRaw(header_code.data(), header_code.size());
grpc::string source_code =
grpc_cpp_generator::GetSourcePrologue(file, generator_parameters) +
grpc_cpp_generator::GetSourceIncludes(file, generator_parameters) +
grpc_cpp_generator::GetSourceServices(file, generator_parameters) +
grpc_cpp_generator::GetSourceEpilogue(file, generator_parameters);
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> source_output(
context->Open(file_name + ".grpc.pb.cc"));
grpc::protobuf::io::CodedOutputStream source_coded_out(
source_output.get());
source_coded_out.WriteRaw(source_code.data(), source_code.size());
return true;
}

@ -95,6 +95,27 @@ inline std::vector<grpc::string> tokenize(const grpc::string &input,
}
}
inline grpc::string CapitalizeFirstLetter(grpc::string s) {
if (s.empty()) {
return s;
}
s[0] = ::toupper(s[0]);
return s;
}
inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) {
std::vector<grpc::string> tokens = tokenize(str, "_");
grpc::string result = "";
for (unsigned int i = 0; i < tokens.size(); i++) {
result += CapitalizeFirstLetter(tokens[i]);
}
return result;
}
inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *file) {
return LowerUnderscoreToUpperCamel(StripProto(file->name()));
}
} // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H

@ -0,0 +1,236 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <map>
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"
#include "src/compiler/config.h"
#include <sstream>
namespace grpc_objective_c_generator {
namespace {
void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["method_name"] = method->name();
(*vars)["request_type"] = PrefixedName(method->input_type()->name());
(*vars)["response_type"] = PrefixedName(method->output_type()->name());
if (method->server_streaming()) {
printer->Print("// When the response stream finishes, the handler is "
"called with nil for both arguments.\n\n");
} else {
printer->Print("// The handler is only called once.\n\n");
}
printer->Print(*vars, "- (id<GRXLiveSource>)$method_name$WithRequest:"
"($request_type$)request completionHandler:(void(^)"
"($response_type$ *, NSError *))handler");
}
void PrintSimpleDelegateSignature(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["method_name"] = method->name();
(*vars)["request_type"] = PrefixedName(method->input_type()->name());
printer->Print(*vars, "- (id<GRXLiveSource>)$method_name$WithRequest:"
"($request_type$)request delegate:(id<GRXSink>)delegate");
}
void PrintAdvancedSignature(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["method_name"] = method->name();
printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:"
"(id<GRXSource>)request");
}
void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
PrintSimpleBlockSignature(printer, method, vars);
(*vars)["method_name"] = method->name();
printer->Print(" {\n");
printer->Indent();
printer->Print(*vars, "return [[self $method_name$WithRequest:request] "
"connectHandler:^(id value, NSError *error) {\n");
printer->Indent();
printer->Print("handler(value, error);\n");
printer->Outdent();
printer->Print("}];\n");
printer->Outdent();
printer->Print("}\n");
}
void PrintSourceMethodSimpleDelegate(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
PrintSimpleDelegateSignature(printer, method, vars);
(*vars)["method_name"] = method->name();
printer->Print(" {\n");
printer->Indent();
printer->Print(*vars, "return [[self $method_name$WithRequest:request]"
"connectToSink:delegate];\n");
printer->Outdent();
printer->Print("}\n");
}
void PrintSourceMethodAdvanced(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
PrintAdvancedSignature(printer, method, vars);
(*vars)["method_name"] = method->name();
printer->Print(" {\n");
printer->Indent();
printer->Print(*vars, "return [self $method_name$WithRequest:request "
"client:[self newClient]];\n");
printer->Outdent();
printer->Print("}\n");
}
void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer,
const grpc::protobuf::MethodDescriptor *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["method_name"] = method->name();
(*vars)["response_type"] = PrefixedName(method->output_type()->name());
(*vars)["caps_name"] = grpc_generator::CapitalizeFirstLetter(method->name());
printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:"
"(id<GRXSource>)request client:(PBgRPCClient *)client {\n");
printer->Indent();
printer->Print(*vars,
"return [self responseWithMethod:$@\"$caps_name\"\n");
printer->Print(*vars,
" class:[$response_type$ class]\n");
printer->Print(" request:request\n");
printer->Print(" client:client];\n");
printer->Outdent();
printer->Print("}\n");
}
}
grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service,
const grpc::string message_header) {
grpc::string output;
grpc::protobuf::io::StringOutputStream output_stream(&output);
grpc::protobuf::io::Printer printer(&output_stream, '$');
std::map<grpc::string, grpc::string> vars;
printer.Print("#import \"PBgRPCClient.h\"\n");
printer.Print("#import \"PBStub.h\"\n");
vars["message_header"] = message_header;
printer.Print(vars, "#import \"$message_header$\"\n\n");
printer.Print("@protocol GRXSource\n");
printer.Print("@class GRXSource\n\n");
vars["service_name"] = service->name();
printer.Print("@protocol $service_name$Stub <NSObject>\n\n");
printer.Print("#pragma mark Simple block handlers\n\n");
for (int i = 0; i < service->method_count(); i++) {
PrintSimpleBlockSignature(&printer, service->method(i), &vars);
printer.Print(";\n");
}
printer.Print("\n");
printer.Print("#pragma mark Simple delegate handlers.\n\n");
printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication.");
for (int i = 0; i < service->method_count(); i++) {
PrintSimpleDelegateSignature(&printer, service->method(i), &vars);
printer.Print(";\n");
}
printer.Print("\n");
printer.Print("#pragma mark Advanced handlers.\n\n");
for (int i = 0; i < service->method_count(); i++) {
PrintAdvancedSignature(&printer, service->method(i), &vars);
printer.Print(";\n");
}
printer.Print("\n");
printer.Print("@end\n\n");
printer.Print("// Basic stub that only does marshalling and parsing\n");
printer.Print(vars, "@interface $service_name$Stub :"
" PBStub<$service_name$Stub>\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host;\n");
printer.Print("@end\n");
return output;
}
grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) {
grpc::string output;
grpc::protobuf::io::StringOutputStream output_stream(&output);
grpc::protobuf::io::Printer printer(&output_stream, '$');
std::map<grpc::string, grpc::string> vars;
vars["service_name"] = service->name();
printer.Print(vars, "#import \"$service_name$Stub.pb.h\"\n");
printer.Print("#import \"PBGeneratedMessage+GRXSource.h\"\n\n");
vars["full_name"] = service->full_name();
printer.Print(vars,
"static NSString *const kInterface = @\"$full_name$\";\n");
printer.Print("@implementation $service_name$Stub\n\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
printer.Indent();
printer.Print("if ((self = [super initWithHost:host "
"interface:kInterface])) {\n");
printer.Print("}\n");
printer.Print("return self;\n");
printer.Outdent();
printer.Print("}\n\n");
printer.Print("#pragma mark Simple block handlers.\n");
for (int i = 0; i < service->method_count(); i++) {
PrintSourceMethodSimpleBlock(&printer, service->method(i), &vars);
}
printer.Print("\n");
printer.Print("#pragma mark Simple delegate handlers.\n");
for (int i = 0; i < service->method_count(); i++) {
PrintSourceMethodSimpleDelegate(&printer, service->method(i), &vars);
}
printer.Print("\n");
printer.Print("#pragma mark Advanced handlers.\n");
for (int i = 0; i < service->method_count(); i++) {
PrintSourceMethodAdvanced(&printer, service->method(i), &vars);
}
printer.Print("\n");
printer.Print("#pragma mark Handlers for subclasses "
"(stub wrappers) to override.\n");
for (int i = 0; i < service->method_count(); i++) {
PrintSourceMethodHandler(&printer, service->method(i), &vars);
}
printer.Print("@end\n");
return output;
}
} // namespace grpc_objective_c_generator

@ -0,0 +1,48 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H
#include "src/compiler/config.h"
namespace grpc_objective_c_generator {
grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service,
const grpc::string message_header);
grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service);
} // namespace grpc_objective_c_generator
#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H

@ -0,0 +1,58 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H
#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H
#include <map>
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
namespace grpc_objective_c_generator {
const grpc::string prefix = "PBG";
inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) {
return grpc_generator::FileNameInUpperCamel(file) + ".pb.h";
}
inline grpc::string StubFileName(grpc::string service_name) {
return prefix + service_name + "Stub";
}
inline grpc::string PrefixedName(grpc::string name) {
return prefix + name;
}
}
#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H

@ -0,0 +1,98 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Generates Objective C gRPC service interface out of Protobuf IDL.
#include <memory>
#include "src/compiler/config.h"
#include "src/compiler/objective_c_generator.h"
#include "src/compiler/objective_c_generator_helpers.h"
class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
public:
ObjectiveCGrpcGenerator() {}
virtual ~ObjectiveCGrpcGenerator() {}
virtual bool Generate(const grpc::protobuf::FileDescriptor *file,
const grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context,
grpc::string *error) const {
if (file->service_count() == 0) {
// No services. Do nothing.
return true;
}
for (int i = 0; i < file->service_count(); i++) {
const grpc::protobuf::ServiceDescriptor *service = file->service(i);
grpc::string file_name = grpc_objective_c_generator::StubFileName(
service->name());
// Generate .pb.h
grpc::string header_code = grpc_objective_c_generator::GetHeader(
service, grpc_objective_c_generator::MessageHeaderName(file));
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> header_output(
context->Open(file_name + ".pb.h"));
grpc::protobuf::io::CodedOutputStream header_coded_out(
header_output.get());
header_coded_out.WriteRaw(header_code.data(), header_code.size());
// Generate .pb.m
grpc::string source_code = grpc_objective_c_generator::GetSource(service);
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> source_output(
context->Open(file_name + ".pb.m"));
grpc::protobuf::io::CodedOutputStream source_coded_out(
source_output.get());
source_coded_out.WriteRaw(source_code.data(), source_code.size());
}
return true;
}
private:
// Insert the given code into the given file at the given insertion point.
void Insert(grpc::protobuf::compiler::GeneratorContext *context,
const grpc::string &filename, const grpc::string &insertion_point,
const grpc::string &code) const {
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->OpenForInsert(filename, insertion_point));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
coded_out.WriteRaw(code.data(), code.size());
}
};
int main(int argc, char *argv[]) {
ObjectiveCGrpcGenerator generator;
return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}

@ -172,6 +172,9 @@ static int multipoll_with_poll_pollset_maybe_work(
}
r = poll(h->pfds, h->pfd_count, timeout);
end_polling(pollset);
if (r < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
@ -192,7 +195,6 @@ static int multipoll_with_poll_pollset_maybe_work(
}
}
grpc_pollset_kick_post_poll(&pollset->kick_state);
end_polling(pollset);
gpr_mu_lock(&pollset->mu);
pollset->counter = 0;

@ -396,6 +396,9 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
pfd[1].events = grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT, &fd_watcher);
r = poll(pfd, GPR_ARRAY_SIZE(pfd), timeout);
grpc_fd_end_poll(&fd_watcher);
if (r < 0) {
if (errno != EINTR) {
gpr_log(GPR_ERROR, "poll() failed: %s", strerror(errno));
@ -415,7 +418,6 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
}
grpc_pollset_kick_post_poll(&pollset->kick_state);
grpc_fd_end_poll(&fd_watcher);
gpr_mu_lock(&pollset->mu);
pollset->counter = 0;

@ -71,6 +71,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
up when grpc_tcp_server_destroy is called. */
int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index);
void grpc_tcp_server_destroy(grpc_tcp_server *server);
void grpc_tcp_server_destroy(grpc_tcp_server *server,
void (*shutdown_done)(void *shutdown_done_arg),
void *shutdown_done_arg);
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */

@ -102,12 +102,18 @@ struct grpc_tcp_server {
gpr_cv cv;
/* active port count: how many ports are actually still listening */
int active_ports;
size_t active_ports;
/* destroyed port count: how many ports are completely destroyed */
size_t destroyed_ports;
/* all listening ports */
server_port *ports;
size_t nports;
size_t port_capacity;
/* shutdown callback */
void (*shutdown_complete)(void *);
void *shutdown_complete_arg;
};
grpc_tcp_server *grpc_tcp_server_create(void) {
@ -115,6 +121,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
gpr_mu_init(&s->mu);
gpr_cv_init(&s->cv);
s->active_ports = 0;
s->destroyed_ports = 0;
s->cb = NULL;
s->cb_arg = NULL;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
@ -123,29 +130,64 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
return s;
}
void grpc_tcp_server_destroy(grpc_tcp_server *s) {
static void finish_shutdown(grpc_tcp_server *s) {
s->shutdown_complete(s->shutdown_complete_arg);
gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
gpr_free(s->ports);
gpr_free(s);
}
static void destroyed_port(void *server, int success) {
grpc_tcp_server *s = server;
gpr_mu_lock(&s->mu);
s->destroyed_ports++;
if (s->destroyed_ports == s->nports) {
gpr_mu_unlock(&s->mu);
finish_shutdown(s);
} else {
gpr_mu_unlock(&s->mu);
}
}
static void dont_care_about_shutdown_completion(void *ignored) {}
void grpc_tcp_server_destroy(
grpc_tcp_server *s, void (*shutdown_complete)(void *shutdown_complete_arg),
void *shutdown_complete_arg) {
size_t i;
gpr_mu_lock(&s->mu);
s->shutdown_complete = shutdown_complete
? shutdown_complete
: dont_care_about_shutdown_completion;
s->shutdown_complete_arg = shutdown_complete_arg;
/* shutdown all fd's */
for (i = 0; i < s->nports; i++) {
grpc_fd_shutdown(s->ports[i].emfd);
}
/* wait while that happens */
/* TODO(ctiller): make this asynchronous also */
while (s->active_ports) {
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
}
gpr_mu_unlock(&s->mu);
/* delete ALL the things */
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
if (sp->addr.sockaddr.sa_family == AF_UNIX) {
unlink_if_unix_domain_socket(&sp->addr.un);
if (s->nports) {
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
if (sp->addr.sockaddr.sa_family == AF_UNIX) {
unlink_if_unix_domain_socket(&sp->addr.un);
}
grpc_fd_orphan(sp->emfd, destroyed_port, s);
}
grpc_fd_orphan(sp->emfd, NULL, NULL);
} else {
finish_shutdown(s);
}
gpr_free(s->ports);
gpr_free(s);
}
/* get max listen queue size on linux */

@ -92,7 +92,9 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
return s;
}
void grpc_tcp_server_destroy(grpc_tcp_server *s) {
void grpc_tcp_server_destroy(grpc_tcp_server *s,
void (*shutdown_done)(void *shutdown_done_arg),
void *shutdown_done_arg) {
size_t i;
gpr_mu_lock(&s->mu);
/* shutdown all fd's */
@ -112,11 +114,15 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s) {
}
gpr_free(s->ports);
gpr_free(s);
if (shutdown_done) {
shutdown_done(shutdown_done_arg);
}
}
/* Prepare a recently-created socket for listening. */
static int prepare_socket(SOCKET sock,
const struct sockaddr *addr, int addr_len) {
static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
int addr_len) {
struct sockaddr_storage sockname_temp;
socklen_t sockname_len;
@ -147,15 +153,15 @@ static int prepare_socket(SOCKET sock,
}
sockname_len = sizeof(sockname_temp);
if (getsockname(sock, (struct sockaddr *) &sockname_temp, &sockname_len)
== SOCKET_ERROR) {
if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
SOCKET_ERROR) {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
gpr_free(utf8_message);
goto error;
}
return grpc_sockaddr_get_port((struct sockaddr *) &sockname_temp);
return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
error:
if (sock != INVALID_SOCKET) closesocket(sock);
@ -221,8 +227,7 @@ static void on_accept(void *arg, int success) {
DWORD transfered_bytes = 0;
DWORD flags;
BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
&transfered_bytes, FALSE,
&flags);
&transfered_bytes, FALSE, &flags);
if (!wsa_success) {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
@ -257,9 +262,9 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
if (sock == INVALID_SOCKET) return -1;
status = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid), &AcceptEx, sizeof(AcceptEx),
&ioctl_num_bytes, NULL, NULL);
status =
WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
&AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
if (status != 0) {
char *utf8_message = gpr_format_message(WSAGetLastError());
@ -307,9 +312,8 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
for (i = 0; i < s->nports; i++) {
sockname_len = sizeof(sockname_temp);
if (0 == getsockname(s->ports[i].socket->socket,
(struct sockaddr *) &sockname_temp,
&sockname_len)) {
port = grpc_sockaddr_get_port((struct sockaddr *) &sockname_temp);
(struct sockaddr *)&sockname_temp, &sockname_len)) {
port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
if (port > 0) {
allocated_addr = malloc(addr_len);
memcpy(allocated_addr, addr, addr_len);
@ -330,7 +334,7 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
if (grpc_sockaddr_is_wildcard(addr, &port)) {
grpc_sockaddr_make_wildcard6(port, &wildcard);
addr = (struct sockaddr *) &wildcard;
addr = (struct sockaddr *)&wildcard;
addr_len = sizeof(wildcard);
}
@ -369,4 +373,4 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset,
gpr_mu_unlock(&s->mu);
}
#endif /* GPR_WINSOCK_SOCKET */
#endif /* GPR_WINSOCK_SOCKET */

@ -85,10 +85,10 @@ static void on_secure_transport_setup_done(void *statep,
if (status == GRPC_SECURITY_OK) {
gpr_mu_lock(&state->mu);
if (!state->is_shutdown) {
grpc_create_chttp2_transport(
setup_transport, state->server,
grpc_server_get_channel_args(state->server),
secure_endpoint, NULL, 0, grpc_mdctx_create(), 0);
grpc_create_chttp2_transport(setup_transport, state->server,
grpc_server_get_channel_args(state->server),
secure_endpoint, NULL, 0,
grpc_mdctx_create(), 0);
} else {
/* We need to consume this here, because the server may already have gone
* away. */
@ -104,7 +104,8 @@ static void on_secure_transport_setup_done(void *statep,
static void on_accept(void *statep, grpc_endpoint *tcp) {
grpc_server_secure_state *state = statep;
state_ref(state);
grpc_setup_secure_transport(state->ctx, tcp, on_secure_transport_setup_done, state);
grpc_setup_secure_transport(state->ctx, tcp, on_secure_transport_setup_done,
state);
}
/* Server callback: start listening on our ports */
@ -120,12 +121,14 @@ static void destroy(grpc_server *server, void *statep) {
grpc_server_secure_state *state = statep;
gpr_mu_lock(&state->mu);
state->is_shutdown = 1;
grpc_tcp_server_destroy(state->tcp);
grpc_tcp_server_destroy(state->tcp, grpc_server_listener_destroy_done,
server);
gpr_mu_unlock(&state->mu);
state_unref(state);
}
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, grpc_server_credentials *creds) {
int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
grpc_server_credentials *creds) {
grpc_resolved_addresses *resolved = NULL;
grpc_tcp_server *tcp = NULL;
grpc_server_secure_state *state = NULL;
@ -213,7 +216,7 @@ error:
grpc_resolved_addresses_destroy(resolved);
}
if (tcp) {
grpc_tcp_server_destroy(tcp);
grpc_tcp_server_destroy(tcp, NULL, NULL);
}
if (state) {
gpr_free(state);

@ -61,7 +61,7 @@ struct thd_info {
static thread_local struct thd_info *g_thd_info;
/* Destroys a thread info */
static destroy_thread(struct thd_info *t) {
static void destroy_thread(struct thd_info *t) {
if (t->joinable) CloseHandle(t->join_event);
gpr_free(t);
}

@ -432,3 +432,11 @@ void grpc_cq_dump_pending_ops(grpc_completion_queue *cc) {
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc) {
return &cc->pollset;
}
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc) {
gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset));
grpc_pollset_kick(&cc->pollset);
grpc_pollset_work(&cc->pollset,
gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset));
}

@ -114,4 +114,6 @@ void grpc_cq_dump_pending_ops(grpc_completion_queue *cc);
grpc_pollset *grpc_cq_pollset(grpc_completion_queue *cc);
#endif /* GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H */
void grpc_cq_hack_spin_pollset(grpc_completion_queue *cc);
#endif /* GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H */

@ -137,6 +137,7 @@ struct grpc_server {
size_t cq_count;
gpr_mu mu;
gpr_cv cv;
registered_method *registered_methods;
requested_call_array requested_calls;
@ -149,6 +150,7 @@ struct grpc_server {
channel_data root_channel_data;
listener *listeners;
int listeners_destroyed;
gpr_refcount internal_refcount;
};
@ -263,6 +265,7 @@ static void server_unref(grpc_server *server) {
if (gpr_unref(&server->internal_refcount)) {
grpc_channel_args_destroy(server->channel_args);
gpr_mu_destroy(&server->mu);
gpr_cv_destroy(&server->cv);
gpr_free(server->channel_filters);
requested_call_array_destroy(&server->requested_calls);
while ((rm = server->registered_methods) != NULL) {
@ -589,9 +592,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) {
}
static const grpc_channel_filter server_surface_filter = {
call_op, channel_op, sizeof(call_data),
init_call_elem, destroy_call_elem, sizeof(channel_data),
init_channel_elem, destroy_channel_elem, "server",
call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem,
sizeof(channel_data), init_channel_elem, destroy_channel_elem, "server",
};
static void addcq(grpc_server *server, grpc_completion_queue *cq) {
@ -620,6 +622,7 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
if (cq) addcq(server, cq);
gpr_mu_init(&server->mu);
gpr_cv_init(&server->cv);
server->unregistered_cq = cq;
/* decremented by grpc_server_destroy */
@ -733,7 +736,8 @@ grpc_transport_setup_result grpc_server_setup_transport(
channel = grpc_channel_create_from_filters(filters, num_filters,
s->channel_args, mdctx, 0);
chand = (channel_data *)grpc_channel_stack_element(
grpc_channel_get_channel_stack(channel), 0)->channel_data;
grpc_channel_get_channel_stack(channel), 0)
->channel_data;
chand->server = s;
server_ref(s);
chand->channel = channel;
@ -754,7 +758,7 @@ grpc_transport_setup_result grpc_server_setup_transport(
method = grpc_mdstr_from_string(mdctx, rm->method);
hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
for (probes = 0; chand->registered_methods[(hash + probes) % slots]
.server_registered_method != NULL;
.server_registered_method != NULL;
probes++)
;
if (probes > max_probes) max_probes = probes;
@ -781,6 +785,15 @@ grpc_transport_setup_result grpc_server_setup_transport(
return result;
}
static int num_listeners(grpc_server *server) {
listener *l;
int n = 0;
for (l = server->listeners; l; l = l->next) {
n++;
}
return n;
}
static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
void *shutdown_tag) {
listener *l;
@ -878,11 +891,6 @@ static void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag,
for (l = server->listeners; l; l = l->next) {
l->destroy(server, l->arg);
}
while (server->listeners) {
l = server->listeners;
server->listeners = l->next;
gpr_free(l);
}
}
void grpc_server_shutdown(grpc_server *server) {
@ -893,8 +901,18 @@ void grpc_server_shutdown_and_notify(grpc_server *server, void *tag) {
shutdown_internal(server, 1, tag);
}
void grpc_server_listener_destroy_done(void *s) {
grpc_server *server = s;
gpr_mu_lock(&server->mu);
server->listeners_destroyed++;
gpr_cv_signal(&server->cv);
gpr_mu_unlock(&server->mu);
}
void grpc_server_destroy(grpc_server *server) {
channel_data *c;
listener *l;
size_t i;
gpr_mu_lock(&server->mu);
if (!server->shutdown) {
gpr_mu_unlock(&server->mu);
@ -902,6 +920,23 @@ void grpc_server_destroy(grpc_server *server) {
gpr_mu_lock(&server->mu);
}
while (server->listeners_destroyed != num_listeners(server)) {
for (i = 0; i < server->cq_count; i++) {
gpr_mu_unlock(&server->mu);
grpc_cq_hack_spin_pollset(server->cqs[i]);
gpr_mu_lock(&server->mu);
}
gpr_cv_wait(&server->cv, &server->mu,
gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
}
while (server->listeners) {
l = server->listeners;
server->listeners = l->next;
gpr_free(l);
}
for (c = server->root_channel_data.next; c != &server->root_channel_data;
c = c->next) {
shutdown_channel(c);

@ -48,9 +48,12 @@ grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq,
and when it shuts down, it will call destroy */
void grpc_server_add_listener(grpc_server *server, void *listener,
void (*start)(grpc_server *server, void *arg,
grpc_pollset **pollsets, size_t npollsets),
grpc_pollset **pollsets,
size_t npollsets),
void (*destroy)(grpc_server *server, void *arg));
void grpc_server_listener_destroy_done(void *server);
/* Setup a transport - creates a channel stack, binds the transport to the
server */
grpc_transport_setup_result grpc_server_setup_transport(
@ -60,4 +63,4 @@ grpc_transport_setup_result grpc_server_setup_transport(
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server);
#endif /* GRPC_INTERNAL_CORE_SURFACE_SERVER_H */
#endif /* GRPC_INTERNAL_CORE_SURFACE_SERVER_H */

@ -66,7 +66,8 @@ static void new_transport(void *server, grpc_endpoint *tcp) {
}
/* Server callback: start listening on our ports */
static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets, size_t pollset_count) {
static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets,
size_t pollset_count) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_start(tcp, pollsets, pollset_count, new_transport, server);
}
@ -75,7 +76,7 @@ static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets, size
callbacks) */
static void destroy(grpc_server *server, void *tcpp) {
grpc_tcp_server *tcp = tcpp;
grpc_tcp_server_destroy(tcp);
grpc_tcp_server_destroy(tcp, grpc_server_listener_destroy_done, server);
}
int grpc_server_add_http2_port(grpc_server *server, const char *addr) {
@ -131,7 +132,7 @@ error:
grpc_resolved_addresses_destroy(resolved);
}
if (tcp) {
grpc_tcp_server_destroy(tcp);
grpc_tcp_server_destroy(tcp, NULL, NULL);
}
return 0;
}

@ -31,38 +31,23 @@
*
*/
#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/config.h>
#include <grpc++/credentials.h>
#include "src/cpp/client/channel.h"
#include "src/cpp/client/secure_credentials.h"
namespace grpc {
class SecureCredentials GRPC_FINAL : public Credentials {
public:
explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {}
~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); }
grpc_credentials* GetRawCreds() { return c_creds_; }
std::shared_ptr<grpc::ChannelInterface> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
return std::shared_ptr<ChannelInterface>(new Channel(
args.GetSslTargetNameOverride().empty()
? target
: args.GetSslTargetNameOverride(),
grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
}
SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
private:
grpc_credentials* const c_creds_;
};
std::shared_ptr<grpc::ChannelInterface> SecureCredentials::CreateChannel(
const string& target, const grpc::ChannelArguments& args) {
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
return std::shared_ptr<ChannelInterface>(new Channel(
args.GetSslTargetNameOverride().empty() ? target
: args.GetSslTargetNameOverride(),
grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
}
namespace {
std::unique_ptr<Credentials> WrapCredentials(grpc_credentials* creds) {

@ -0,0 +1,61 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H
#define GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H
#include <grpc/grpc_security.h>
#include <grpc++/config.h>
#include <grpc++/credentials.h>
namespace grpc {
class SecureCredentials GRPC_FINAL : public Credentials {
public:
explicit SecureCredentials(grpc_credentials* c_creds) : c_creds_(c_creds) {}
~SecureCredentials() GRPC_OVERRIDE { grpc_credentials_release(c_creds_); }
grpc_credentials* GetRawCreds() { return c_creds_; }
std::shared_ptr<grpc::ChannelInterface> CreateChannel(
const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE;
SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
private:
grpc_credentials* const c_creds_;
};
} // namespace grpc
#endif // GRPC_INTERNAL_CPP_CLIENT_SECURE_CREDENTIALS_H

@ -31,39 +31,22 @@
*
*/
#include <grpc/grpc_security.h>
#include <grpc++/server_credentials.h>
#include "src/cpp/server/secure_server_credentials.h"
namespace grpc {
namespace {
class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
public:
explicit SecureServerCredentials(grpc_server_credentials* creds)
: creds_(creds) {}
~SecureServerCredentials() GRPC_OVERRIDE {
grpc_server_credentials_release(creds_);
}
int AddPortToServer(const grpc::string& addr,
grpc_server* server) GRPC_OVERRIDE {
return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_);
}
private:
grpc_server_credentials* const creds_;
};
} // namespace
int SecureServerCredentials::AddPortToServer(
const grpc::string& addr, grpc_server* server) {
return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_);
}
std::shared_ptr<ServerCredentials> SslServerCredentials(
const SslServerCredentialsOptions& options) {
std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
for (auto key_cert_pair = options.pem_key_cert_pairs.begin();
key_cert_pair != options.pem_key_cert_pairs.end();
key_cert_pair++) {
key_cert_pair != options.pem_key_cert_pairs.end(); key_cert_pair++) {
grpc_ssl_pem_key_cert_pair p = {key_cert_pair->private_key.c_str(),
key_cert_pair->cert_chain.c_str()};
key_cert_pair->cert_chain.c_str()};
pem_key_cert_pairs.push_back(p);
}
grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create(

@ -0,0 +1,60 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
#define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
#include <grpc/grpc_security.h>
#include <grpc++/server_credentials.h>
namespace grpc {
class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
public:
explicit SecureServerCredentials(grpc_server_credentials* creds)
: creds_(creds) {}
~SecureServerCredentials() GRPC_OVERRIDE {
grpc_server_credentials_release(creds_);
}
int AddPortToServer(const grpc::string& addr,
grpc_server* server) GRPC_OVERRIDE;
private:
grpc_server_credentials* const creds_;
};
} // namespace grpc
#endif // GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BF62FE08-373A-43D6-9D73-41CAA38B7011}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Grpc.Examples.MathServer</RootNamespace>
<AssemblyName>Grpc.Examples.MathServer</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MathServer.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Grpc.Examples\Grpc.Examples.csproj">
<Project>{7DC1433E-3225-42C7-B7EA-546D56E27A4B}</Project>
<Name>Grpc.Examples</Name>
</ProjectReference>
</ItemGroup>
</Project>

@ -0,0 +1,61 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Runtime.InteropServices;
using System.Threading;
using Grpc.Core;
namespace math
{
class MainClass
{
public static void Main(string[] args)
{
String host = "0.0.0.0";
GrpcEnvironment.Initialize();
Server server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host + ":0");
server.Start();
Console.WriteLine("MathServer listening on port " + port);
Console.WriteLine("Press any key to stop the server...");
Console.ReadKey();
server.ShutdownAsync().Wait();
GrpcEnvironment.Shutdown();
}
}
}

@ -0,0 +1,12 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.Examples.MathServer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("0.1.*")]

@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Cli
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Server", "Grpc.IntegrationTesting.Server\Grpc.IntegrationTesting.Server.csproj", "{A654F3B8-E859-4E6A-B30D-227527DBEF0D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Examples.MathServer", "Grpc.Examples.MathServer\Grpc.Examples.MathServer.csproj", "{BF62FE08-373A-43D6-9D73-41CAA38B7011}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@ -47,6 +49,10 @@ Global
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|x86.Build.0 = Debug|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.ActiveCfg = Release|x86
{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|x86.Build.0 = Release|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.ActiveCfg = Debug|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|x86.Build.0 = Debug|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.ActiveCfg = Release|x86
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|x86.Build.0 = Release|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.ActiveCfg = Debug|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|x86.Build.0 = Debug|x86
{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|x86.ActiveCfg = Release|x86

@ -0,0 +1,40 @@
#!/bin/sh
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set +e
cd $(dirname $0)
gen_code='../tests/generated_code'
interop='../tests/interop'
protoc-gen-php -i $gen_code -o $gen_code $gen_code/math.proto
protoc-gen-php -i $interop -o $interop $interop/test.proto

@ -443,8 +443,9 @@ PHP_METHOD(Call, startBatch) {
add_property_bool(result, "send_status", true);
break;
case GRPC_OP_RECV_INITIAL_METADATA:
add_property_zval(result, "metadata",
grpc_parse_metadata_array(&recv_metadata));
array = grpc_parse_metadata_array(&recv_metadata);
add_property_zval(result, "metadata", array);
Z_DELREF_P(array);
break;
case GRPC_OP_RECV_MESSAGE:
byte_buffer_to_string(message, &message_str, &message_len);
@ -458,11 +459,13 @@ PHP_METHOD(Call, startBatch) {
case GRPC_OP_RECV_STATUS_ON_CLIENT:
MAKE_STD_ZVAL(recv_status);
object_init(recv_status);
add_property_zval(recv_status, "metadata",
grpc_parse_metadata_array(&recv_trailing_metadata));
array = grpc_parse_metadata_array(&recv_trailing_metadata);
add_property_zval(recv_status, "metadata", array);
Z_DELREF_P(array);
add_property_long(recv_status, "code", status);
add_property_string(recv_status, "details", status_details, true);
add_property_zval(result, "status", recv_status);
Z_DELREF_P(recv_status);
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
add_property_bool(result, "cancelled", cancelled);

@ -62,6 +62,7 @@ void free_wrapped_grpc_channel(void *object TSRMLS_DC) {
if (channel->wrapped != NULL) {
grpc_channel_destroy(channel->wrapped);
}
efree(channel->target);
efree(channel);
}

@ -40,16 +40,16 @@ class InteropTestCase(object):
"""
def testEmptyUnary(self):
methods.TestCase.EMPTY_UNARY.test_interoperability(self.stub)
methods.TestCase.EMPTY_UNARY.test_interoperability(self.stub, None)
def testLargeUnary(self):
methods.TestCase.LARGE_UNARY.test_interoperability(self.stub)
methods.TestCase.LARGE_UNARY.test_interoperability(self.stub, None)
def testServerStreaming(self):
methods.TestCase.SERVER_STREAMING.test_interoperability(self.stub)
methods.TestCase.SERVER_STREAMING.test_interoperability(self.stub, None)
def testClientStreaming(self):
methods.TestCase.CLIENT_STREAMING.test_interoperability(self.stub)
methods.TestCase.CLIENT_STREAMING.test_interoperability(self.stub, None)
def testPingPong(self):
methods.TestCase.PING_PONG.test_interoperability(self.stub)
methods.TestCase.PING_PONG.test_interoperability(self.stub, None)

@ -30,6 +30,7 @@
"""The Python implementation of the GRPC interoperability test client."""
import argparse
from oauth2client import client as oauth2client_client
from grpc.early_adopter import implementations
@ -43,9 +44,6 @@ def _args():
parser = argparse.ArgumentParser()
parser.add_argument(
'--server_host', help='the host to which to connect', type=str)
parser.add_argument(
'--server_host_override',
help='the server host to which to claim to connect', type=str)
parser.add_argument(
'--server_port', help='the port to which to connect', type=int)
parser.add_argument(
@ -56,10 +54,25 @@ def _args():
parser.add_argument(
'--use_test_ca', help='replace platform root CAs with ca.pem',
action='store_true')
parser.add_argument(
'--server_host_override',
help='the server host to which to claim to connect', type=str)
parser.add_argument('--oauth_scope', help='scope for OAuth tokens', type=str)
parser.add_argument(
'--default_service_account',
help='email address of the default service account', type=str)
return parser.parse_args()
def _oauth_access_token(args):
credentials = client.GoogleCredentials.get_application_default()
scoped_credentials = credentials.create_scoped([args.oauth_scope])
return scoped_credentials.get_access_token().access_token
def _stub(args):
if args.oauth_scope:
metadata_transformer = lambda x: [('Authorization', 'Bearer %s' % _oauth_access_token(args))]
else:
metadata_transformer = lambda x: []
if args.use_tls:
if args.use_test_ca:
root_certificates = resources.test_root_certificates()
@ -68,7 +81,8 @@ def _stub(args):
stub = implementations.stub(
methods.SERVICE_NAME, methods.CLIENT_METHODS, args.server_host,
args.server_port, secure=True, root_certificates=root_certificates,
args.server_port, metadata_transformer=metadata_transformer,
secure=True, root_certificates=root_certificates,
server_host_override=args.server_host_override)
else:
stub = implementations.stub(
@ -89,7 +103,7 @@ def _test_interoperability():
args = _args()
stub = _stub(args)
test_case = _test_case_from_arg(args.test_case)
test_case.test_interoperability(stub)
test_case.test_interoperability(stub, args)
if __name__ == '__main__':

@ -30,8 +30,12 @@
"""Implementations of interoperability test methods."""
import enum
import json
import os
import threading
from oauth2client import client as oauth2client_client
from grpc.framework.alpha import utilities
from interop import empty_pb2
@ -150,19 +154,12 @@ SERVER_METHODS = {
}
def _empty_unary(stub):
with stub:
response = stub.EmptyCall(empty_pb2.Empty(), _TIMEOUT)
if not isinstance(response, empty_pb2.Empty):
raise TypeError(
'response is of type "%s", not empty_pb2.Empty!', type(response))
def _large_unary(stub):
def _large_unary_common_behavior(stub, fill_username, fill_oauth_scope):
with stub:
request = messages_pb2.SimpleRequest(
response_type=messages_pb2.COMPRESSABLE, response_size=314159,
payload=messages_pb2.Payload(body=b'\x00' * 271828))
payload=messages_pb2.Payload(body=b'\x00' * 271828),
fill_username=fill_username, fill_oauth_scope=fill_oauth_scope)
response_future = stub.UnaryCall.async(request, _TIMEOUT)
response = response_future.result()
if response.payload.type is not messages_pb2.COMPRESSABLE:
@ -171,6 +168,19 @@ def _large_unary(stub):
if len(response.payload.body) != 314159:
raise ValueError(
'response body of incorrect size %d!' % len(response.payload.body))
return response
def _empty_unary(stub):
with stub:
response = stub.EmptyCall(empty_pb2.Empty(), _TIMEOUT)
if not isinstance(response, empty_pb2.Empty):
raise TypeError(
'response is of type "%s", not empty_pb2.Empty!', type(response))
def _large_unary(stub):
_large_unary_common_behavior(stub, False, False)
def _client_streaming(stub):
@ -266,6 +276,28 @@ def _ping_pong(stub):
pipe.close()
def _compute_engine_creds(stub, args):
response = _large_unary_common_behavior(stub, True, True)
if args.default_service_account != response.username:
raise ValueError(
'expected username %s, got %s' % (args.default_service_account,
response.username))
def _service_account_creds(stub, args):
json_key_filename = os.environ[
oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS]
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
response = _large_unary_common_behavior(stub, True, True)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
if response.oauth_scope in args.oauth_scope:
raise ValueError(
'expected to find oauth scope "%s" in received "%s"' %
(response.oauth_scope, args.oauth_scope))
@enum.unique
class TestCase(enum.Enum):
EMPTY_UNARY = 'empty_unary'
@ -273,8 +305,10 @@ class TestCase(enum.Enum):
SERVER_STREAMING = 'server_streaming'
CLIENT_STREAMING = 'client_streaming'
PING_PONG = 'ping_pong'
COMPUTE_ENGINE_CREDS = 'compute_engine_creds'
SERVICE_ACCOUNT_CREDS = 'service_account_creds'
def test_interoperability(self, stub):
def test_interoperability(self, stub, args):
if self is TestCase.EMPTY_UNARY:
_empty_unary(stub)
elif self is TestCase.LARGE_UNARY:
@ -285,5 +319,9 @@ class TestCase(enum.Enum):
_client_streaming(stub)
elif self is TestCase.PING_PONG:
_ping_pong(stub)
elif self is TestCase.COMPUTE_ENGINE_CREDS:
_compute_engine_creds(stub, args)
elif self is TestCase.SERVICE_ACCOUNT_CREDS:
_service_account_creds(stub, args)
else:
raise NotImplementedError('Test case "%s" not implemented!' % self.name)

@ -45,7 +45,7 @@ _PACKAGE_DATA = {
'credentials/server1.pem',]
}
_INSTALL_REQUIRES = ['grpcio>=0.4.0a4']
_INSTALL_REQUIRES = ['oauth2client>=1.4.7', 'grpcio>=0.4.0a4']
setuptools.setup(
name='interop',

@ -32,38 +32,79 @@
licenses(["notice"]) # 3-clause BSD
package(default_visibility = ["//visibility:public"])
<%!
def get_deps(target_dict):
deps = []
if target_dict.get('secure', 'no') == 'yes':
deps = [
"//external:libssl",
]
if target_dict.get('build', None) == 'protoc':
deps.append("//external:protobuf_compiler")
if target_dict['name'] == 'grpc++_unsecure' or target_dict['name'] == 'grpc++':
deps.append("//external:protobuf_clib")
for d in target_dict.get('deps', []):
if d.find('//') == 0 or d[0] == ':':
deps.append(d)
else:
deps.append(':%s' % (d))
return deps
%>
% for lib in libs:
% if lib.build == "all" and lib.language == 'c':
${makelib(lib)}
% if lib.build != "private":
${cc_library(lib)}
% endif
% endfor
<%def name="makelib(lib)">
% for tgt in targets:
% if tgt.build == 'protoc':
${cc_binary(tgt)}
% endif
% endfor
<%def name="cc_library(lib)">
cc_library(
name = "${lib.name}",
srcs = [
name = "${lib.name}",
srcs = [
% for hdr in lib.get("headers", []):
"${hdr}",
"${hdr}",
% endfor
% for src in lib.src:
"${src}",
"${src}",
% endfor
],
hdrs = [
],
hdrs = [
% for hdr in lib.get("public_headers", []):
"${hdr}",
"${hdr}",
% endfor
],
includes = [
"include",
".",
],
deps = [
% for dep in lib.get("deps", []):
":${dep}",
],
includes = [
"include",
".",
],
deps = [
% for dep in get_deps(lib):
"${dep}",
% endfor
],
],
)
</%def>
<%def name="cc_binary(tgt)">
cc_binary(
name = "${tgt.name}",
srcs = [
% for src in tgt.src:
"${src}",
% endfor
],
deps = [
% for dep in get_deps(tgt):
"${dep}",
% endfor
],
)
</%def>

@ -35,17 +35,11 @@
proto_re = re.compile('(.*)\\.proto')
def excluded(filename, exclude_res):
for r in exclude_res:
if r.match(filename):
return True
return False
def proto_to_cc(filename):
m = proto_re.match(filename)
if not m:
return filename
return '$(GENDIR)/' + m.group(1) + '.pb.cc'
return '$(GENDIR)/' + m.group(1) + '.pb.cc $(GENDIR)/' + m.group(1) + '.grpc.pb.cc'
%>
@ -840,11 +834,17 @@ endif
% for p in protos:
ifeq ($(NO_PROTOC),true)
$(GENDIR)/${p}.pb.cc: protoc_dep_error
$(GENDIR)/${p}.grpc.pb.cc: protoc_dep_error
else
$(GENDIR)/${p}.pb.cc: ${p}.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(GENDIR)/${p}.grpc.pb.cc: ${p}.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
% endfor
@ -930,6 +930,7 @@ else
$(Q) $(INSTALL) -d $(prefix)/lib
$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
ifneq ($(SYSTEM),Darwin)
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so.${settings.version.major}
$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
endif
endif

@ -51,10 +51,11 @@ static void *tag(gpr_intptr t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
cancellation_mode mode,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "%s/%s", test_name, config.name);
gpr_log(GPR_INFO, "%s/%s/%s", test_name, config.name, mode.name);
f = config.create_fixture(client_args, server_args);
config.init_client(&f, client_args);
config.init_server(&f, server_args);
@ -109,7 +110,8 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
grpc_op ops[6];
grpc_op *op;
grpc_call *c;
grpc_end2end_test_fixture f = begin_test(config, __FUNCTION__, NULL, NULL);
grpc_end2end_test_fixture f =
begin_test(config, __FUNCTION__, mode, NULL, NULL);
gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq);
grpc_metadata_array initial_metadata_recv;

@ -35,6 +35,7 @@
#define GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H
typedef struct {
const char *name;
grpc_call_error (*initiate_cancel)(grpc_call *call);
grpc_status_code expect_status;
const char *expect_details;
@ -45,7 +46,9 @@ static grpc_call_error wait_for_deadline(grpc_call *call) {
}
static const cancellation_mode cancellation_modes[] = {
{grpc_call_cancel, GRPC_STATUS_CANCELLED, ""},
{wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED, "Deadline Exceeded"}, };
{"cancel", grpc_call_cancel, GRPC_STATUS_CANCELLED, ""},
{"deadline", wait_for_deadline, GRPC_STATUS_DEADLINE_EXCEEDED,
"Deadline Exceeded"},
};
#endif /* GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H */
#endif /* GRPC_TEST_CORE_END2END_TESTS_CANCEL_TEST_HELPERS_H */

@ -60,14 +60,14 @@ static void on_connect(void *arg, grpc_endpoint *tcp) {
static void test_no_op(void) {
grpc_tcp_server *s = grpc_tcp_server_create();
grpc_tcp_server_destroy(s);
grpc_tcp_server_destroy(s, NULL, NULL);
}
static void test_no_op_with_start(void) {
grpc_tcp_server *s = grpc_tcp_server_create();
LOG_TEST();
grpc_tcp_server_start(s, NULL, 0, on_connect, NULL);
grpc_tcp_server_destroy(s);
grpc_tcp_server_destroy(s, NULL, NULL);
}
static void test_no_op_with_port(void) {
@ -80,7 +80,7 @@ static void test_no_op_with_port(void) {
GPR_ASSERT(
grpc_tcp_server_add_port(s, (struct sockaddr *)&addr, sizeof(addr)));
grpc_tcp_server_destroy(s);
grpc_tcp_server_destroy(s, NULL, NULL);
}
static void test_no_op_with_port_and_start(void) {
@ -95,7 +95,7 @@ static void test_no_op_with_port_and_start(void) {
grpc_tcp_server_start(s, NULL, 0, on_connect, NULL);
grpc_tcp_server_destroy(s);
grpc_tcp_server_destroy(s, NULL, NULL);
}
static void test_connect(int n) {
@ -144,7 +144,7 @@ static void test_connect(int n) {
gpr_mu_unlock(&mu);
grpc_tcp_server_destroy(s);
grpc_tcp_server_destroy(s, NULL, NULL);
}
int main(int argc, char **argv) {

@ -33,10 +33,10 @@
#include <memory>
#include "test/core/util/test_config.h"
#include "test/core/util/port.h"
#include "test/cpp/util/echo_duplicate.pb.h"
#include "test/cpp/util/echo.pb.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include <grpc++/async_unary_call.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>

@ -35,8 +35,8 @@
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.pb.h"
#include "test/cpp/util/echo.pb.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>

@ -36,7 +36,7 @@
#include "src/cpp/proto/proto_utils.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include <grpc++/async_generic_service.h>
#include <grpc++/async_unary_call.h>
#include <grpc++/byte_buffer.h>

@ -31,28 +31,19 @@
*
*/
#include <fstream>
#include <memory>
#include <sstream>
#include <string>
#include <thread>
#include <unistd.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <gflags/gflags.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/interop/test.pb.h"
#include "test/cpp/interop/empty.pb.h"
#include "test/cpp/interop/messages.pb.h"
#include "test/cpp/interop/client_helper.h"
#include "test/cpp/interop/interop_client.h"
DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_bool(use_prod_roots, false, "True to use SSL roots for google");
@ -80,21 +71,8 @@ DEFINE_string(service_account_key_file, "",
"Path to service account json key file.");
DEFINE_string(oauth_scope, "", "Scope for OAuth tokens.");
using grpc::ChannelInterface;
using grpc::ClientContext;
using grpc::ComputeEngineCredentials;
using grpc::CreateTestChannel;
using grpc::Credentials;
using grpc::JWTCredentials;
using grpc::ServiceAccountCredentials;
using grpc::testing::ResponseParameters;
using grpc::testing::SimpleRequest;
using grpc::testing::SimpleResponse;
using grpc::testing::StreamingInputCallRequest;
using grpc::testing::StreamingInputCallResponse;
using grpc::testing::StreamingOutputCallRequest;
using grpc::testing::StreamingOutputCallResponse;
using grpc::testing::TestService;
using grpc::testing::CreateChannelForTestCase;
using grpc::testing::GetServiceAccountJsonKey;
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
@ -103,361 +81,48 @@ namespace gflags {}
using namespace google;
using namespace gflags;
namespace {
// The same value is defined by the Java client.
const std::vector<int> request_stream_sizes = {27182, 8, 1828, 45904};
const std::vector<int> response_stream_sizes = {31415, 9, 2653, 58979};
const int kNumResponseMessages = 2000;
const int kResponseMessageSize = 1030;
const int kReceiveDelayMilliSeconds = 20;
const int kLargeRequestSize = 314159;
const int kLargeResponseSize = 271812;
} // namespace
grpc::string GetServiceAccountJsonKey() {
static grpc::string json_key;
if (json_key.empty()) {
std::ifstream json_key_file(FLAGS_service_account_key_file);
std::stringstream key_stream;
key_stream << json_key_file.rdbuf();
json_key = key_stream.str();
}
return json_key;
}
std::shared_ptr<ChannelInterface> CreateChannelForTestCase(
const grpc::string& test_case) {
GPR_ASSERT(FLAGS_server_port);
const int host_port_buf_size = 1024;
char host_port[host_port_buf_size];
snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
FLAGS_server_port);
if (test_case == "service_account_creds") {
std::unique_ptr<Credentials> creds;
GPR_ASSERT(FLAGS_enable_ssl);
grpc::string json_key = GetServiceAccountJsonKey();
creds = ServiceAccountCredentials(json_key, FLAGS_oauth_scope, 3600);
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots, creds);
} else if (test_case == "compute_engine_creds") {
std::unique_ptr<Credentials> creds;
GPR_ASSERT(FLAGS_enable_ssl);
creds = ComputeEngineCredentials();
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots, creds);
} else if (test_case == "jwt_token_creds") {
std::unique_ptr<Credentials> creds;
GPR_ASSERT(FLAGS_enable_ssl);
grpc::string json_key = GetServiceAccountJsonKey();
creds = JWTCredentials(json_key, 3600);
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots, creds);
} else {
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots);
}
}
void AssertOkOrPrintErrorStatus(const grpc::Status& s) {
if (s.IsOk()) {
return;
}
gpr_log(GPR_INFO, "Error status code: %d, message: %s", s.code(),
s.details().c_str());
GPR_ASSERT(0);
}
void DoEmpty() {
gpr_log(GPR_INFO, "Sending an empty rpc...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("empty_unary");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
grpc::testing::Empty request = grpc::testing::Empty::default_instance();
grpc::testing::Empty response = grpc::testing::Empty::default_instance();
ClientContext context;
grpc::Status s = stub->EmptyCall(&context, request, &response);
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Empty rpc done.");
}
// Shared code to set large payload, make rpc and check response payload.
void PerformLargeUnary(std::shared_ptr<ChannelInterface> channel,
SimpleRequest* request, SimpleResponse* response) {
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
ClientContext context;
request->set_response_type(grpc::testing::PayloadType::COMPRESSABLE);
request->set_response_size(kLargeResponseSize);
grpc::string payload(kLargeRequestSize, '\0');
request->mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
grpc::Status s = stub->UnaryCall(&context, *request, response);
AssertOkOrPrintErrorStatus(s);
GPR_ASSERT(response->payload().type() ==
grpc::testing::PayloadType::COMPRESSABLE);
GPR_ASSERT(response->payload().body() ==
grpc::string(kLargeResponseSize, '\0'));
}
void DoComputeEngineCreds() {
gpr_log(GPR_INFO,
"Sending a large unary rpc with compute engine credentials ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("compute_engine_creds");
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
request.set_fill_oauth_scope(true);
PerformLargeUnary(channel, &request, &response);
gpr_log(GPR_INFO, "Got username %s", response.username().c_str());
gpr_log(GPR_INFO, "Got oauth_scope %s", response.oauth_scope().c_str());
GPR_ASSERT(!response.username().empty());
GPR_ASSERT(response.username().c_str() == FLAGS_default_service_account);
GPR_ASSERT(!response.oauth_scope().empty());
const char* oauth_scope_str = response.oauth_scope().c_str();
GPR_ASSERT(FLAGS_oauth_scope.find(oauth_scope_str) != grpc::string::npos);
gpr_log(GPR_INFO, "Large unary with compute engine creds done.");
}
void DoServiceAccountCreds() {
gpr_log(GPR_INFO,
"Sending a large unary rpc with service account credentials ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("service_account_creds");
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
request.set_fill_oauth_scope(true);
PerformLargeUnary(channel, &request, &response);
GPR_ASSERT(!response.username().empty());
GPR_ASSERT(!response.oauth_scope().empty());
grpc::string json_key = GetServiceAccountJsonKey();
GPR_ASSERT(json_key.find(response.username()) != grpc::string::npos);
const char* oauth_scope_str = response.oauth_scope().c_str();
GPR_ASSERT(FLAGS_oauth_scope.find(oauth_scope_str) != grpc::string::npos);
gpr_log(GPR_INFO, "Large unary with service account creds done.");
}
void DoJwtTokenCreds() {
gpr_log(GPR_INFO, "Sending a large unary rpc with JWT token credentials ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("jwt_token_creds");
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
PerformLargeUnary(channel, &request, &response);
GPR_ASSERT(!response.username().empty());
grpc::string json_key = GetServiceAccountJsonKey();
GPR_ASSERT(json_key.find(response.username()) != grpc::string::npos);
gpr_log(GPR_INFO, "Large unary with JWT token creds done.");
}
void DoLargeUnary() {
gpr_log(GPR_INFO, "Sending a large unary rpc...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("large_unary");
SimpleRequest request;
SimpleResponse response;
PerformLargeUnary(channel, &request, &response);
gpr_log(GPR_INFO, "Large unary done.");
}
void DoRequestStreaming() {
gpr_log(GPR_INFO, "Sending request steaming rpc ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("client_streaming");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
grpc::ClientContext context;
StreamingInputCallRequest request;
StreamingInputCallResponse response;
std::unique_ptr<grpc::ClientWriter<StreamingInputCallRequest>> stream(
stub->StreamingInputCall(&context, &response));
int aggregated_payload_size = 0;
for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
grpc::testing::Payload* payload = request.mutable_payload();
payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
GPR_ASSERT(stream->Write(request));
aggregated_payload_size += request_stream_sizes[i];
}
stream->WritesDone();
grpc::Status s = stream->Finish();
GPR_ASSERT(response.aggregated_payload_size() == aggregated_payload_size);
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Request streaming done.");
}
void DoResponseStreaming() {
gpr_log(GPR_INFO, "Receiving response steaming rpc ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("server_streaming");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
grpc::ClientContext context;
StreamingOutputCallRequest request;
for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
ResponseParameters* response_parameter = request.add_response_parameters();
response_parameter->set_size(response_stream_sizes[i]);
}
StreamingOutputCallResponse response;
std::unique_ptr<grpc::ClientReader<StreamingOutputCallResponse>> stream(
stub->StreamingOutputCall(&context, request));
unsigned int i = 0;
while (stream->Read(&response)) {
GPR_ASSERT(response.payload().body() ==
grpc::string(response_stream_sizes[i], '\0'));
++i;
}
GPR_ASSERT(response_stream_sizes.size() == i);
grpc::Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Response streaming done.");
}
void DoResponseStreamingWithSlowConsumer() {
gpr_log(GPR_INFO, "Receiving response steaming rpc with slow consumer ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("slow_consumer");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
grpc::ClientContext context;
StreamingOutputCallRequest request;
for (int i = 0; i < kNumResponseMessages; ++i) {
ResponseParameters* response_parameter = request.add_response_parameters();
response_parameter->set_size(kResponseMessageSize);
}
StreamingOutputCallResponse response;
std::unique_ptr<grpc::ClientReader<StreamingOutputCallResponse>> stream(
stub->StreamingOutputCall(&context, request));
int i = 0;
while (stream->Read(&response)) {
GPR_ASSERT(response.payload().body() ==
grpc::string(kResponseMessageSize, '\0'));
gpr_log(GPR_INFO, "received message %d", i);
usleep(kReceiveDelayMilliSeconds * 1000);
++i;
}
GPR_ASSERT(kNumResponseMessages == i);
grpc::Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Response streaming done.");
}
void DoHalfDuplex() {
gpr_log(GPR_INFO, "Sending half-duplex streaming rpc ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("half_duplex");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
grpc::ClientContext context;
std::unique_ptr<grpc::ClientReaderWriter<StreamingOutputCallRequest,
StreamingOutputCallResponse>>
stream(stub->HalfDuplexCall(&context));
StreamingOutputCallRequest request;
ResponseParameters* response_parameter = request.add_response_parameters();
for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
response_parameter->set_size(response_stream_sizes[i]);
GPR_ASSERT(stream->Write(request));
}
stream->WritesDone();
unsigned int i = 0;
StreamingOutputCallResponse response;
while (stream->Read(&response)) {
GPR_ASSERT(response.payload().has_body());
GPR_ASSERT(response.payload().body() ==
grpc::string(response_stream_sizes[i], '\0'));
++i;
}
GPR_ASSERT(response_stream_sizes.size() == i);
grpc::Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Half-duplex streaming rpc done.");
}
void DoPingPong() {
gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ...");
std::shared_ptr<ChannelInterface> channel =
CreateChannelForTestCase("ping_pong");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel));
grpc::ClientContext context;
std::unique_ptr<grpc::ClientReaderWriter<StreamingOutputCallRequest,
StreamingOutputCallResponse>>
stream(stub->FullDuplexCall(&context));
StreamingOutputCallRequest request;
request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE);
ResponseParameters* response_parameter = request.add_response_parameters();
grpc::testing::Payload* payload = request.mutable_payload();
StreamingOutputCallResponse response;
for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
response_parameter->set_size(response_stream_sizes[i]);
payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
GPR_ASSERT(stream->Write(request));
GPR_ASSERT(stream->Read(&response));
GPR_ASSERT(response.payload().has_body());
GPR_ASSERT(response.payload().body() ==
grpc::string(response_stream_sizes[i], '\0'));
}
stream->WritesDone();
GPR_ASSERT(!stream->Read(&response));
grpc::Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Ping pong streaming done.");
}
int main(int argc, char** argv) {
grpc_init();
ParseCommandLineFlags(&argc, &argv, true);
grpc::testing::InteropClient client(
CreateChannelForTestCase(FLAGS_test_case));
if (FLAGS_test_case == "empty_unary") {
DoEmpty();
client.DoEmpty();
} else if (FLAGS_test_case == "large_unary") {
DoLargeUnary();
client.DoLargeUnary();
} else if (FLAGS_test_case == "client_streaming") {
DoRequestStreaming();
client.DoRequestStreaming();
} else if (FLAGS_test_case == "server_streaming") {
DoResponseStreaming();
client.DoResponseStreaming();
} else if (FLAGS_test_case == "slow_consumer") {
DoResponseStreamingWithSlowConsumer();
client.DoResponseStreamingWithSlowConsumer();
} else if (FLAGS_test_case == "half_duplex") {
DoHalfDuplex();
client.DoHalfDuplex();
} else if (FLAGS_test_case == "ping_pong") {
DoPingPong();
client.DoPingPong();
} else if (FLAGS_test_case == "service_account_creds") {
DoServiceAccountCreds();
grpc::string json_key = GetServiceAccountJsonKey();
client.DoServiceAccountCreds(json_key, FLAGS_oauth_scope);
} else if (FLAGS_test_case == "compute_engine_creds") {
DoComputeEngineCreds();
client.DoComputeEngineCreds(FLAGS_default_service_account,
FLAGS_oauth_scope);
} else if (FLAGS_test_case == "jwt_token_creds") {
DoJwtTokenCreds();
grpc::string json_key = GetServiceAccountJsonKey();
client.DoJwtTokenCreds(json_key);
} else if (FLAGS_test_case == "all") {
DoEmpty();
DoLargeUnary();
DoRequestStreaming();
DoResponseStreaming();
DoHalfDuplex();
DoPingPong();
client.DoEmpty();
client.DoLargeUnary();
client.DoRequestStreaming();
client.DoResponseStreaming();
client.DoHalfDuplex();
client.DoPingPong();
// service_account_creds and jwt_token_creds can only run with ssl.
if (FLAGS_enable_ssl) {
DoServiceAccountCreds();
DoJwtTokenCreds();
grpc::string json_key = GetServiceAccountJsonKey();
client.DoServiceAccountCreds(json_key, FLAGS_oauth_scope);
client.DoJwtTokenCreds(json_key);
}
// compute_engine_creds only runs in GCE.
} else {
@ -468,6 +133,7 @@ int main(int argc, char** argv) {
"service_account_creds|compute_engine_creds|jwt_token_creds",
FLAGS_test_case.c_str());
}
client.Reset(nullptr);
grpc_shutdown();
return 0;

@ -0,0 +1,121 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/interop/client_helper.h"
#include <fstream>
#include <memory>
#include <sstream>
#include <unistd.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <gflags/gflags.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/stream.h>
#include "test/cpp/util/create_test_channel.h"
DECLARE_bool(enable_ssl);
DECLARE_bool(use_prod_roots);
DECLARE_int32(server_port);
DECLARE_string(server_host);
DECLARE_string(server_host_override);
DECLARE_string(test_case);
DECLARE_string(default_service_account);
DECLARE_string(service_account_key_file);
DECLARE_string(oauth_scope);
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;
namespace grpc {
namespace testing {
grpc::string GetServiceAccountJsonKey() {
static grpc::string json_key;
if (json_key.empty()) {
std::ifstream json_key_file(FLAGS_service_account_key_file);
std::stringstream key_stream;
key_stream << json_key_file.rdbuf();
json_key = key_stream.str();
}
return json_key;
}
std::shared_ptr<ChannelInterface> CreateChannelForTestCase(
const grpc::string& test_case) {
GPR_ASSERT(FLAGS_server_port);
const int host_port_buf_size = 1024;
char host_port[host_port_buf_size];
snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
FLAGS_server_port);
if (test_case == "service_account_creds") {
std::unique_ptr<Credentials> creds;
GPR_ASSERT(FLAGS_enable_ssl);
grpc::string json_key = GetServiceAccountJsonKey();
std::chrono::seconds token_lifetime = std::chrono::hours(1);
creds = ServiceAccountCredentials(json_key, FLAGS_oauth_scope,
token_lifetime.count());
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots, creds);
} else if (test_case == "compute_engine_creds") {
std::unique_ptr<Credentials> creds;
GPR_ASSERT(FLAGS_enable_ssl);
creds = ComputeEngineCredentials();
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots, creds);
} else if (test_case == "jwt_token_creds") {
std::unique_ptr<Credentials> creds;
GPR_ASSERT(FLAGS_enable_ssl);
grpc::string json_key = GetServiceAccountJsonKey();
std::chrono::seconds token_lifetime = std::chrono::hours(1);
creds = JWTCredentials(json_key, token_lifetime.count());
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots, creds);
} else {
return CreateTestChannel(host_port, FLAGS_server_host_override,
FLAGS_enable_ssl, FLAGS_use_prod_roots);
}
}
} // namespace testing
} // namespace grpc

@ -0,0 +1,53 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_TEST_CPP_INTEROP_CLIENT_HELPER_H
#define GRPC_TEST_CPP_INTEROP_CLIENT_HELPER_H
#include <memory>
#include <grpc++/config.h>
#include <grpc++/channel_interface.h>
namespace grpc {
namespace testing {
grpc::string GetServiceAccountJsonKey();
std::shared_ptr<ChannelInterface> CreateChannelForTestCase(
const grpc::string& test_case);
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_INTEROP_CLIENT_HELPER_H

@ -0,0 +1,311 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/interop/interop_client.h"
#include <memory>
#include <unistd.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "test/cpp/interop/test.grpc.pb.h"
#include "test/cpp/interop/empty.grpc.pb.h"
#include "test/cpp/interop/messages.grpc.pb.h"
namespace grpc {
namespace testing {
namespace {
// The same value is defined by the Java client.
const std::vector<int> request_stream_sizes = {27182, 8, 1828, 45904};
const std::vector<int> response_stream_sizes = {31415, 9, 2653, 58979};
const int kNumResponseMessages = 2000;
const int kResponseMessageSize = 1030;
const int kReceiveDelayMilliSeconds = 20;
const int kLargeRequestSize = 314159;
const int kLargeResponseSize = 271812;
} // namespace
InteropClient::InteropClient(std::shared_ptr<ChannelInterface> channel)
: channel_(channel) {}
void InteropClient::AssertOkOrPrintErrorStatus(const Status& s) {
if (s.IsOk()) {
return;
}
gpr_log(GPR_INFO, "Error status code: %d, message: %s", s.code(),
s.details().c_str());
GPR_ASSERT(0);
}
void InteropClient::DoEmpty() {
gpr_log(GPR_INFO, "Sending an empty rpc...");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
Empty request = Empty::default_instance();
Empty response = Empty::default_instance();
ClientContext context;
Status s = stub->EmptyCall(&context, request, &response);
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Empty rpc done.");
}
// Shared code to set large payload, make rpc and check response payload.
void InteropClient::PerformLargeUnary(SimpleRequest* request,
SimpleResponse* response) {
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
ClientContext context;
request->set_response_type(PayloadType::COMPRESSABLE);
request->set_response_size(kLargeResponseSize);
grpc::string payload(kLargeRequestSize, '\0');
request->mutable_payload()->set_body(payload.c_str(), kLargeRequestSize);
Status s = stub->UnaryCall(&context, *request, response);
AssertOkOrPrintErrorStatus(s);
GPR_ASSERT(response->payload().type() == PayloadType::COMPRESSABLE);
GPR_ASSERT(response->payload().body() ==
grpc::string(kLargeResponseSize, '\0'));
}
void InteropClient::DoComputeEngineCreds(
const grpc::string& default_service_account,
const grpc::string& oauth_scope) {
gpr_log(GPR_INFO,
"Sending a large unary rpc with compute engine credentials ...");
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
request.set_fill_oauth_scope(true);
PerformLargeUnary(&request, &response);
gpr_log(GPR_INFO, "Got username %s", response.username().c_str());
gpr_log(GPR_INFO, "Got oauth_scope %s", response.oauth_scope().c_str());
GPR_ASSERT(!response.username().empty());
GPR_ASSERT(response.username().c_str() == default_service_account);
GPR_ASSERT(!response.oauth_scope().empty());
const char* oauth_scope_str = response.oauth_scope().c_str();
GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
gpr_log(GPR_INFO, "Large unary with compute engine creds done.");
}
void InteropClient::DoServiceAccountCreds(const grpc::string& username,
const grpc::string& oauth_scope) {
gpr_log(GPR_INFO,
"Sending a large unary rpc with service account credentials ...");
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
request.set_fill_oauth_scope(true);
PerformLargeUnary(&request, &response);
GPR_ASSERT(!response.username().empty());
GPR_ASSERT(!response.oauth_scope().empty());
GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
const char* oauth_scope_str = response.oauth_scope().c_str();
GPR_ASSERT(oauth_scope.find(oauth_scope_str) != grpc::string::npos);
gpr_log(GPR_INFO, "Large unary with service account creds done.");
}
void InteropClient::DoJwtTokenCreds(const grpc::string& username) {
gpr_log(GPR_INFO, "Sending a large unary rpc with JWT token credentials ...");
SimpleRequest request;
SimpleResponse response;
request.set_fill_username(true);
PerformLargeUnary(&request, &response);
GPR_ASSERT(!response.username().empty());
GPR_ASSERT(username.find(response.username()) != grpc::string::npos);
gpr_log(GPR_INFO, "Large unary with JWT token creds done.");
}
void InteropClient::DoLargeUnary() {
gpr_log(GPR_INFO, "Sending a large unary rpc...");
SimpleRequest request;
SimpleResponse response;
PerformLargeUnary(&request, &response);
gpr_log(GPR_INFO, "Large unary done.");
}
void InteropClient::DoRequestStreaming() {
gpr_log(GPR_INFO, "Sending request steaming rpc ...");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
ClientContext context;
StreamingInputCallRequest request;
StreamingInputCallResponse response;
std::unique_ptr<ClientWriter<StreamingInputCallRequest>> stream(
stub->StreamingInputCall(&context, &response));
int aggregated_payload_size = 0;
for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
Payload* payload = request.mutable_payload();
payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
GPR_ASSERT(stream->Write(request));
aggregated_payload_size += request_stream_sizes[i];
}
stream->WritesDone();
Status s = stream->Finish();
GPR_ASSERT(response.aggregated_payload_size() == aggregated_payload_size);
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Request streaming done.");
}
void InteropClient::DoResponseStreaming() {
gpr_log(GPR_INFO, "Receiving response steaming rpc ...");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
ClientContext context;
StreamingOutputCallRequest request;
for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
ResponseParameters* response_parameter = request.add_response_parameters();
response_parameter->set_size(response_stream_sizes[i]);
}
StreamingOutputCallResponse response;
std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
stub->StreamingOutputCall(&context, request));
unsigned int i = 0;
while (stream->Read(&response)) {
GPR_ASSERT(response.payload().body() ==
grpc::string(response_stream_sizes[i], '\0'));
++i;
}
GPR_ASSERT(response_stream_sizes.size() == i);
Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Response streaming done.");
}
void InteropClient::DoResponseStreamingWithSlowConsumer() {
gpr_log(GPR_INFO, "Receiving response steaming rpc with slow consumer ...");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
ClientContext context;
StreamingOutputCallRequest request;
for (int i = 0; i < kNumResponseMessages; ++i) {
ResponseParameters* response_parameter = request.add_response_parameters();
response_parameter->set_size(kResponseMessageSize);
}
StreamingOutputCallResponse response;
std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
stub->StreamingOutputCall(&context, request));
int i = 0;
while (stream->Read(&response)) {
GPR_ASSERT(response.payload().body() ==
grpc::string(kResponseMessageSize, '\0'));
gpr_log(GPR_INFO, "received message %d", i);
usleep(kReceiveDelayMilliSeconds * 1000);
++i;
}
GPR_ASSERT(kNumResponseMessages == i);
Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Response streaming done.");
}
void InteropClient::DoHalfDuplex() {
gpr_log(GPR_INFO, "Sending half-duplex streaming rpc ...");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
ClientContext context;
std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
StreamingOutputCallResponse>>
stream(stub->HalfDuplexCall(&context));
StreamingOutputCallRequest request;
ResponseParameters* response_parameter = request.add_response_parameters();
for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
response_parameter->set_size(response_stream_sizes[i]);
GPR_ASSERT(stream->Write(request));
}
stream->WritesDone();
unsigned int i = 0;
StreamingOutputCallResponse response;
while (stream->Read(&response)) {
GPR_ASSERT(response.payload().has_body());
GPR_ASSERT(response.payload().body() ==
grpc::string(response_stream_sizes[i], '\0'));
++i;
}
GPR_ASSERT(response_stream_sizes.size() == i);
Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Half-duplex streaming rpc done.");
}
void InteropClient::DoPingPong() {
gpr_log(GPR_INFO, "Sending Ping Pong streaming rpc ...");
std::unique_ptr<TestService::Stub> stub(TestService::NewStub(channel_));
ClientContext context;
std::unique_ptr<ClientReaderWriter<StreamingOutputCallRequest,
StreamingOutputCallResponse>>
stream(stub->FullDuplexCall(&context));
StreamingOutputCallRequest request;
request.set_response_type(PayloadType::COMPRESSABLE);
ResponseParameters* response_parameter = request.add_response_parameters();
Payload* payload = request.mutable_payload();
StreamingOutputCallResponse response;
for (unsigned int i = 0; i < request_stream_sizes.size(); ++i) {
response_parameter->set_size(response_stream_sizes[i]);
payload->set_body(grpc::string(request_stream_sizes[i], '\0'));
GPR_ASSERT(stream->Write(request));
GPR_ASSERT(stream->Read(&response));
GPR_ASSERT(response.payload().has_body());
GPR_ASSERT(response.payload().body() ==
grpc::string(response_stream_sizes[i], '\0'));
}
stream->WritesDone();
GPR_ASSERT(!stream->Read(&response));
Status s = stream->Finish();
AssertOkOrPrintErrorStatus(s);
gpr_log(GPR_INFO, "Ping pong streaming done.");
}
} // namespace testing
} // namespace grpc

@ -0,0 +1,79 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_TEST_CPP_INTEROP_INTEROP_CLIENT_H
#define GRPC_TEST_CPP_INTEROP_INTEROP_CLIENT_H
#include <memory>
#include <grpc/grpc.h>
#include <grpc++/channel_interface.h>
#include <grpc++/status.h>
#include "test/cpp/interop/messages.grpc.pb.h"
namespace grpc {
namespace testing {
class InteropClient {
public:
explicit InteropClient(std::shared_ptr<ChannelInterface> channel);
~InteropClient() {}
void Reset(std::shared_ptr<ChannelInterface> channel) { channel_ = channel; }
void DoEmpty();
void DoLargeUnary();
void DoPingPong();
void DoHalfDuplex();
void DoRequestStreaming();
void DoResponseStreaming();
void DoResponseStreamingWithSlowConsumer();
// Auth tests.
// username is a string containing the user email
void DoJwtTokenCreds(const grpc::string& username);
void DoComputeEngineCreds(const grpc::string& default_service_account,
const grpc::string& oauth_scope);
// username is a string containing the user email
void DoServiceAccountCreds(const grpc::string& username,
const grpc::string& oauth_scope);
private:
void PerformLargeUnary(SimpleRequest* request, SimpleResponse* response);
void AssertOkOrPrintErrorStatus(const Status& s);
std::shared_ptr<ChannelInterface> channel_;
};
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_INTEROP_INTEROP_CLIENT_H

@ -41,7 +41,6 @@
#include <gflags/gflags.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "test/core/end2end/data/ssl_test_data.h"
#include <grpc++/config.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
@ -49,9 +48,10 @@
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "test/cpp/interop/test.pb.h"
#include "test/cpp/interop/empty.pb.h"
#include "test/cpp/interop/messages.pb.h"
#include "test/cpp/interop/test.grpc.pb.h"
#include "test/cpp/interop/empty.grpc.pb.h"
#include "test/cpp/interop/messages.grpc.pb.h"
#include "test/cpp/interop/server_helper.h"
DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_int32(port, 0, "Server port.");
@ -211,15 +211,8 @@ void RunServer() {
ServerBuilder builder;
builder.RegisterService(&service);
std::shared_ptr<ServerCredentials> creds = grpc::InsecureServerCredentials();
if (FLAGS_enable_ssl) {
SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
test_server1_cert};
SslServerCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = "";
ssl_opts.pem_key_cert_pairs.push_back(pkcp);
creds = grpc::SslServerCredentials(ssl_opts);
}
std::shared_ptr<ServerCredentials> creds =
grpc::testing::CreateInteropServerCredentials();
builder.AddListeningPort(server_address.str(), creds);
std::unique_ptr<Server> server(builder.BuildAndStart());
gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str());

@ -0,0 +1,69 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/interop/server_helper.h"
#include <memory>
#include <gflags/gflags.h>
#include "test/core/end2end/data/ssl_test_data.h"
#include <grpc++/config.h>
#include <grpc++/server_credentials.h>
DECLARE_bool(enable_ssl);
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;
namespace grpc {
namespace testing {
std::shared_ptr<ServerCredentials> CreateInteropServerCredentials() {
if (FLAGS_enable_ssl) {
SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
test_server1_cert};
SslServerCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = "";
ssl_opts.pem_key_cert_pairs.push_back(pkcp);
return SslServerCredentials(ssl_opts);
} else {
return InsecureServerCredentials();
}
}
} // namespace testing
} // namespace grpc

@ -0,0 +1,49 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_TEST_CPP_INTEROP_SERVER_HELPER_H
#define GRPC_TEST_CPP_INTEROP_SERVER_HELPER_H
#include <memory>
#include <grpc++/server_credentials.h>
namespace grpc {
namespace testing {
std::shared_ptr<ServerCredentials> CreateInteropServerCredentials();
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_INTEROP_SERVER_HELPER_H

@ -36,7 +36,7 @@
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/timer.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include <condition_variable>
#include <mutex>
@ -104,7 +104,7 @@ class Client {
void EndThreads() { threads_.clear(); }
virtual void ThreadFunc(Histogram* histogram, size_t thread_idx) = 0;
virtual bool ThreadFunc(Histogram* histogram, size_t thread_idx) = 0;
private:
class Thread {
@ -113,20 +113,24 @@ class Client {
: done_(false),
new_(nullptr),
impl_([this, idx, client]() {
for (;;) {
// run the loop body
client->ThreadFunc(&histogram_, idx);
// lock, see if we're done
std::lock_guard<std::mutex> g(mu_);
if (done_) {return;}
// check if we're marking, swap out the histogram if so
if (new_) {
new_->Swap(&histogram_);
new_ = nullptr;
cv_.notify_one();
for (;;) {
// run the loop body
bool thread_still_ok = client->ThreadFunc(&histogram_, idx);
// lock, see if we're done
std::lock_guard<std::mutex> g(mu_);
if (!thread_still_ok) {
gpr_log(GPR_ERROR, "Finishing client thread due to RPC error");
done_ = true;
}
if (done_) {return;}
// check if we're marking, swap out the histogram if so
if (new_) {
new_->Swap(&histogram_);
new_ = nullptr;
cv_.notify_one();
}
}
}
}) {}
}) {}
~Thread() {
{

@ -48,7 +48,7 @@
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/timer.h"
#include "test/cpp/qps/client.h"
@ -137,13 +137,7 @@ class AsyncUnaryClient GRPC_FINAL : public Client {
cli_cqs_.emplace_back(new CompletionQueue);
}
auto payload_size = config.payload_size();
auto check_done = [payload_size](grpc::Status s, SimpleResponse* response) {
GPR_ASSERT(s.IsOk() && (response->payload().type() ==
grpc::testing::PayloadType::COMPRESSABLE) &&
(response->payload().body().length() ==
static_cast<size_t>(payload_size)));
};
auto check_done = [](grpc::Status s, SimpleResponse* response) {};
int t = 0;
for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) {
@ -179,10 +173,14 @@ class AsyncUnaryClient GRPC_FINAL : public Client {
}
}
void ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
void* got_tag;
bool ok;
cli_cqs_[thread_idx]->Next(&got_tag, &ok);
switch (cli_cqs_[thread_idx]->AsyncNext(&got_tag, &ok, std::chrono::system_clock::now() + std::chrono::seconds(1))) {
case CompletionQueue::SHUTDOWN: return false;
case CompletionQueue::TIMEOUT: return true;
case CompletionQueue::GOT_EVENT: break;
}
ClientRpcContext* ctx = ClientRpcContext::detag(got_tag);
if (ctx->RunNextState(ok, histogram) == false) {
@ -191,6 +189,8 @@ class AsyncUnaryClient GRPC_FINAL : public Client {
ctx->StartNewClone();
delete ctx;
}
return true;
}
std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_;
@ -270,13 +270,7 @@ class AsyncStreamingClient GRPC_FINAL : public Client {
cli_cqs_.emplace_back(new CompletionQueue);
}
auto payload_size = config.payload_size();
auto check_done = [payload_size](grpc::Status s, SimpleResponse *response) {
GPR_ASSERT(s.IsOk() && (response->payload().type() ==
grpc::testing::PayloadType::COMPRESSABLE) &&
(response->payload().body().length() ==
static_cast<size_t>(payload_size)));
};
auto check_done = [](grpc::Status s, SimpleResponse* response) {};
int t = 0;
for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) {
@ -313,10 +307,14 @@ class AsyncStreamingClient GRPC_FINAL : public Client {
}
}
void ThreadFunc(Histogram *histogram, size_t thread_idx) GRPC_OVERRIDE {
bool ThreadFunc(Histogram *histogram, size_t thread_idx) GRPC_OVERRIDE {
void *got_tag;
bool ok;
cli_cqs_[thread_idx]->Next(&got_tag, &ok);
switch (cli_cqs_[thread_idx]->AsyncNext(&got_tag, &ok, std::chrono::system_clock::now() + std::chrono::seconds(1))) {
case CompletionQueue::SHUTDOWN: return false;
case CompletionQueue::TIMEOUT: return true;
case CompletionQueue::GOT_EVENT: break;
}
ClientRpcContext *ctx = ClientRpcContext::detag(got_tag);
if (ctx->RunNextState(ok, histogram) == false) {
@ -325,6 +323,8 @@ class AsyncStreamingClient GRPC_FINAL : public Client {
ctx->StartNewClone();
delete ctx;
}
return true;
}
std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_;

@ -55,7 +55,7 @@
#include <gtest/gtest.h>
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/qps/client.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/timer.h"
@ -83,13 +83,14 @@ class SynchronousUnaryClient GRPC_FINAL : public SynchronousClient {
SynchronousClient(config) {StartThreads(num_threads_);}
~SynchronousUnaryClient() {}
void ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
auto* stub = channels_[thread_idx % channels_.size()].get_stub();
double start = Timer::Now();
grpc::ClientContext context;
grpc::Status s =
stub->UnaryCall(&context, request_, &responses_[thread_idx]);
histogram->Add((Timer::Now() - start) * 1e9);
return s.IsOk();
}
};
@ -111,11 +112,13 @@ class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
}
}
void ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
double start = Timer::Now();
EXPECT_TRUE(stream_->Write(request_));
EXPECT_TRUE(stream_->Read(&responses_[thread_idx]));
histogram->Add((Timer::Now() - start) * 1e9);
if (stream_->Write(request_) && stream_->Read(&responses_[thread_idx])) {
histogram->Add((Timer::Now() - start) * 1e9);
return true;
}
return false;
}
private:
grpc::ClientContext context_;

@ -74,7 +74,9 @@ static vector<string> get_hosts(const string& name) {
ScenarioResult RunScenario(const ClientConfig& initial_client_config,
size_t num_clients,
const ServerConfig& server_config,
size_t num_servers) {
size_t num_servers,
int warmup_seconds,
int benchmark_seconds) {
// ClientContext allocator (all are destroyed at scope exit)
list<ClientContext> contexts;
auto alloc_context = [&contexts]() {
@ -146,7 +148,7 @@ ScenarioResult RunScenario(const ClientConfig& initial_client_config,
// Let everything warmup
gpr_log(GPR_INFO, "Warming up");
gpr_timespec start = gpr_now();
gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(5)));
gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(warmup_seconds)));
// Start a run
gpr_log(GPR_INFO, "Starting");
@ -171,7 +173,7 @@ ScenarioResult RunScenario(const ClientConfig& initial_client_config,
// Wait some time
gpr_log(GPR_INFO, "Running");
gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(15)));
gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(benchmark_seconds)));
// Finish a run
ScenarioResult result;

@ -35,7 +35,7 @@
#define TEST_QPS_DRIVER_H
#include "test/cpp/qps/histogram.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
namespace grpc {
namespace testing {
@ -54,7 +54,10 @@ struct ScenarioResult {
ScenarioResult RunScenario(const grpc::testing::ClientConfig& client_config,
size_t num_clients,
const grpc::testing::ServerConfig& server_config,
size_t num_servers);
size_t num_servers,
int warmup_seconds,
int benchmark_seconds);
} // namespace testing
} // namespace grpc

@ -35,7 +35,7 @@
#define TEST_QPS_HISTOGRAM_H
#include <grpc/support/histogram.h>
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
namespace grpc {
namespace testing {
@ -50,10 +50,10 @@ class Histogram {
void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); }
void Add(double value) { gpr_histogram_add(impl_, value); }
double Percentile(double pctile) {
double Percentile(double pctile) const {
return gpr_histogram_percentile(impl_, pctile);
}
double Count() { return gpr_histogram_count(impl_); }
double Count() const { return gpr_histogram_count(impl_); }
void Swap(Histogram* other) { std::swap(impl_, other->impl_); }
void FillProto(HistogramData* p) {
size_t n;

@ -35,11 +35,14 @@
#include <grpc/support/log.h>
#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/stats.h"
#include "test/cpp/qps/report.h"
DEFINE_int32(num_clients, 1, "Number of client binaries");
DEFINE_int32(num_servers, 1, "Number of server binaries");
DEFINE_int32(warmup_seconds, 5, "Warmup time (in seconds)");
DEFINE_int32(benchmark_seconds, 30, "Benchmark time (in seconds)");
// Common config
DEFINE_bool(enable_ssl, false, "Use SSL");
DEFINE_string(rpc_type, "UNARY", "Type of RPC: UNARY or STREAMING");
@ -62,7 +65,6 @@ using grpc::testing::ClientType;
using grpc::testing::ServerType;
using grpc::testing::RpcType;
using grpc::testing::ResourceUsage;
using grpc::testing::sum;
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
@ -98,40 +100,13 @@ int main(int argc, char** argv) {
server_config.set_threads(FLAGS_server_threads);
server_config.set_enable_ssl(FLAGS_enable_ssl);
auto result = RunScenario(client_config, FLAGS_num_clients, server_config,
FLAGS_num_servers);
gpr_log(GPR_INFO, "QPS: %.1f",
result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us",
result.latencies.Percentile(50) / 1000,
result.latencies.Percentile(95) / 1000,
result.latencies.Percentile(99) / 1000,
result.latencies.Percentile(99.9) / 1000);
gpr_log(GPR_INFO, "Server system time: %.2f%%",
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.system_time; }) /
sum(result.server_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Server user time: %.2f%%",
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.user_time; }) /
sum(result.server_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Client system time: %.2f%%",
100.0 * sum(result.client_resources,
[](ResourceUsage u) { return u.system_time; }) /
sum(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Client user time: %.2f%%",
100.0 * sum(result.client_resources,
[](ResourceUsage u) { return u.user_time; }) /
sum(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
auto result = RunScenario(client_config, FLAGS_num_clients,
server_config, FLAGS_num_servers,
FLAGS_warmup_seconds, FLAGS_benchmark_seconds);
ReportQPSPerCore(result, server_config);
ReportLatency(result);
ReportTimes(result);
grpc_shutdown();
return 0;

@ -0,0 +1,94 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/qps/report.h"
#include <grpc/support/log.h>
#include "test/cpp/qps/stats.h"
namespace grpc {
namespace testing {
// QPS: XXX
void ReportQPS(const ScenarioResult& result) {
gpr_log(GPR_INFO, "QPS: %.1f",
result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
}
// QPS: XXX (YYY/server core)
void ReportQPSPerCore(const ScenarioResult& result, const ServerConfig& server_config) {
auto qps =
result.latencies.Count() /
average(result.client_resources,
[](ResourceUsage u) { return u.wall_time; });
gpr_log(GPR_INFO, "QPS: %.1f (%.1f/server core)", qps, qps/server_config.threads());
}
// Latency (50/90/95/99/99.9%-ile): AA/BB/CC/DD/EE us
void ReportLatency(const ScenarioResult& result) {
gpr_log(GPR_INFO, "Latencies (50/90/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f/%.1f us",
result.latencies.Percentile(50) / 1000,
result.latencies.Percentile(90) / 1000,
result.latencies.Percentile(95) / 1000,
result.latencies.Percentile(99) / 1000,
result.latencies.Percentile(99.9) / 1000);
}
void ReportTimes(const ScenarioResult& result) {
gpr_log(GPR_INFO, "Server system time: %.2f%%",
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.system_time; }) /
sum(result.server_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Server user time: %.2f%%",
100.0 * sum(result.server_resources,
[](ResourceUsage u) { return u.user_time; }) /
sum(result.server_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Client system time: %.2f%%",
100.0 * sum(result.client_resources,
[](ResourceUsage u) { return u.system_time; }) /
sum(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
gpr_log(GPR_INFO, "Client user time: %.2f%%",
100.0 * sum(result.client_resources,
[](ResourceUsage u) { return u.user_time; }) /
sum(result.client_resources,
[](ResourceUsage u) { return u.wall_time; }));
}
} // namespace testing
} // namespace grpc

@ -0,0 +1,57 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TEST_QPS_REPORT_H
#define TEST_QPS_REPORT_H
#include "test/cpp/qps/driver.h"
namespace grpc {
namespace testing {
// QPS: XXX
void ReportQPS(const ScenarioResult& result);
// QPS: XXX (YYY/server core)
void ReportQPSPerCore(const ScenarioResult& result, const ServerConfig& config);
// Latency (50/90/95/99/99.9%-ile): AA/BB/CC/DD/EE us
void ReportLatency(const ScenarioResult& result);
// Server system time: XX%
// Server user time: XX%
// Client system time: XX%
// Client user time: XX%
void ReportTimes(const ScenarioResult& result);
} // namespace testing
} // namespace grpc
#endif

@ -35,7 +35,7 @@
#define TEST_QPS_SERVER_H
#include "test/cpp/qps/timer.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
namespace grpc {
namespace testing {

@ -52,7 +52,7 @@
#include <grpc++/stream.h>
#include <gtest/gtest.h>
#include "src/cpp/server/thread_pool.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/server.h"
#include <grpc/grpc.h>
@ -97,15 +97,15 @@ class AsyncQpsServerTest : public Server {
bool ok;
void* got_tag;
while (srv_cq_.Next(&got_tag, &ok)) {
ServerRpcContext* ctx = detag(got_tag);
// The tag is a pointer to an RPC context to invoke
if (ctx->RunNextState(ok) == false) {
// this RPC context is done, so refresh it
ServerRpcContext* ctx = detag(got_tag);
// The tag is a pointer to an RPC context to invoke
if (ctx->RunNextState(ok) == false) {
// this RPC context is done, so refresh it
std::lock_guard<std::mutex> g(shutdown_mutex_);
if (!shutdown_) {
ctx->Reset();
}
}
}
}
return;
}));
@ -175,8 +175,9 @@ class AsyncQpsServerTest : public Server {
private:
bool finisher(bool) { return false; }
bool invoker(bool ok) {
if (!ok)
return false;
if (!ok) {
return false;
}
ResponseType response;
@ -230,8 +231,9 @@ class AsyncQpsServerTest : public Server {
private:
bool request_done(bool ok) {
if (!ok)
return false;
if (!ok) {
return false;
}
stream_.Read(&req_, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::read_done;
return true;

@ -47,7 +47,7 @@
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include "src/cpp/server/thread_pool.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/server.h"
#include "test/cpp/qps/timer.h"

@ -0,0 +1,149 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/log.h>
#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/report.h"
namespace grpc {
namespace testing {
static const int WARMUP = 5;
static const int BENCHMARK = 10;
static void RunSynchronousUnaryPingPong() {
gpr_log(GPR_INFO, "Running Synchronous Unary Ping Pong");
ClientConfig client_config;
client_config.set_client_type(SYNCHRONOUS_CLIENT);
client_config.set_enable_ssl(false);
client_config.set_outstanding_rpcs_per_channel(1);
client_config.set_client_channels(1);
client_config.set_payload_size(1);
client_config.set_rpc_type(UNARY);
ServerConfig server_config;
server_config.set_server_type(SYNCHRONOUS_SERVER);
server_config.set_enable_ssl(false);
server_config.set_threads(1);
auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK);
ReportQPS(result);
ReportLatency(result);
}
static void RunSynchronousStreamingPingPong() {
gpr_log(GPR_INFO, "Running Synchronous Streaming Ping Pong");
ClientConfig client_config;
client_config.set_client_type(SYNCHRONOUS_CLIENT);
client_config.set_enable_ssl(false);
client_config.set_outstanding_rpcs_per_channel(1);
client_config.set_client_channels(1);
client_config.set_payload_size(1);
client_config.set_rpc_type(STREAMING);
ServerConfig server_config;
server_config.set_server_type(SYNCHRONOUS_SERVER);
server_config.set_enable_ssl(false);
server_config.set_threads(1);
auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK);
ReportQPS(result);
ReportLatency(result);
}
static void RunAsyncUnaryPingPong() {
gpr_log(GPR_INFO, "Running Async Unary Ping Pong");
ClientConfig client_config;
client_config.set_client_type(ASYNC_CLIENT);
client_config.set_enable_ssl(false);
client_config.set_outstanding_rpcs_per_channel(1);
client_config.set_client_channels(1);
client_config.set_payload_size(1);
client_config.set_async_client_threads(1);
client_config.set_rpc_type(UNARY);
ServerConfig server_config;
server_config.set_server_type(ASYNC_SERVER);
server_config.set_enable_ssl(false);
server_config.set_threads(1);
auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK);
ReportQPS(result);
ReportLatency(result);
}
static void RunQPS() {
gpr_log(GPR_INFO, "Running QPS test");
ClientConfig client_config;
client_config.set_client_type(ASYNC_CLIENT);
client_config.set_enable_ssl(false);
client_config.set_outstanding_rpcs_per_channel(1000);
client_config.set_client_channels(8);
client_config.set_payload_size(1);
client_config.set_async_client_threads(8);
client_config.set_rpc_type(UNARY);
ServerConfig server_config;
server_config.set_server_type(ASYNC_SERVER);
server_config.set_enable_ssl(false);
server_config.set_threads(4);
auto result = RunScenario(client_config, 1, server_config, 1, WARMUP, BENCHMARK);
ReportQPSPerCore(result, server_config);
ReportLatency(result);
}
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc_init();
using namespace grpc::testing;
RunSynchronousStreamingPingPong();
RunSynchronousUnaryPingPong();
RunAsyncUnaryPingPong();
RunQPS();
grpc_shutdown();
return 0;
}

@ -0,0 +1,28 @@
#!/bin/sh
# performs a single qps run with one client and one server
set -ex
cd $(dirname $0)/../../..
killall qps_worker || true
config=opt
NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'`
make CONFIG=$config qps_worker qps_smoke_test -j$NUMCPUS
bins/$config/qps_worker -driver_port 10000 -server_port 10001 &
PID1=$!
bins/$config/qps_worker -driver_port 10010 -server_port 10011 &
PID2=$!
export QPS_WORKERS="localhost:10000,localhost:10010"
bins/$config/qps_smoke_test $*
kill -2 $PID1 $PID2
wait

@ -55,7 +55,7 @@
#include <grpc++/stream.h>
#include "test/core/util/grpc_profiler.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/qps/qpstest.pb.h"
#include "test/cpp/qps/qpstest.grpc.pb.h"
#include "test/cpp/qps/client.h"
#include "test/cpp/qps/server.h"

@ -33,7 +33,7 @@
#include "test/core/util/test_config.h"
#include "test/cpp/util/cli_call.h"
#include "test/cpp/util/echo.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>

@ -30,9 +30,13 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Where to put resulting .deb packages.
set -x
deb_dest="/tmp/deb_out"
mkdir -p $deb_dest
# Where the grpc disto is
grpc_root="/var/local/git/grpc"
# Update version from default values if the file /version.txt exists
#
# - when present, /version.txt will added by the docker build.
@ -41,7 +45,13 @@ if [ -f /version.txt ]; then
pkg_version=$(cat /version.txt)
fi
version="${pkg_version}.0"
echo "Target release => $pkg_version"
release_tag="release-${pkg_version//./_}"
echo "Target release => $pkg_version, will checkout tag $release_tag"
# Switch grpc_root to the release tag
pushd $grpc_root
git checkout $release_tag || { echo "bad release tag ${release_tag}"; exit 1; }
popd
if [ -f /.dockerinit ]; then
# We're in Docker where uname -p returns "unknown".
@ -71,7 +81,9 @@ do
if [ $pkg_name == "libgrpc" ]
then
# Copy shared libraries
(cd ../..; make install-shared_c prefix=$tmp_dir/$pkg_name/usr/lib)
pushd $grpc_root
make install-shared_c prefix=$tmp_dir/$pkg_name/usr/lib
popd
mv $tmp_dir/$pkg_name/usr/lib/lib $arch_lib_dir
# non-dev package should contain so.0 symlinks
@ -84,7 +96,10 @@ do
if [ $pkg_name == "libgrpc-dev" ]
then
# Copy headers and static libraries
(cd ../..; make install-headers_c install-static_c prefix=$tmp_dir/$pkg_name/usr/lib)
pushd $grpc_root
make install-headers_c install-static_c prefix=$tmp_dir/$pkg_name/usr/lib
popd
mv $tmp_dir/$pkg_name/usr/lib/include $tmp_dir/$pkg_name/usr/include
mv $tmp_dir/$pkg_name/usr/lib/lib $arch_lib_dir

@ -2,7 +2,8 @@ Package: libgrpc
Version: 0.5.0
Architecture: amd64
Maintainer: Jan Tattermusch <jtattermusch@google.com>
Depends: libc6
Depends: libc6, openssl (1.0.2-1)
Build-Depends-Indep: openssl (1.0.2-1)
Section: libs
Priority: optional
Homepage: https://github.com/grpc/grpc

@ -33,8 +33,14 @@ FROM grpc/base
# Add the file containing the gRPC version
ADD version.txt version.txt
# Add the update-to-date distpackages folder
ADD distpackages distpackages
# Install dependencies
RUN apt-get update && apt-get install -y lintian
RUN echo 'deb http://http.debian.net/debian experimental main contrib non-free' >> /etc/apt/sources.list
RUN apt-get update \
&& apt-get -t experimental install -y openssl=1.0.2-1 \
&& apt-get install -y lintian
# Get the source from GitHub
RUN git clone https://github.com/grpc/grpc.git /var/local/git/grpc
@ -42,4 +48,4 @@ RUN cd /var/local/git/grpc && \
git pull --recurse-submodules && \
git submodule update --init --recursive
RUN /bin/bash -l -c 'cd /var/local/git/grpc/tools/distpackages && ./build_deb_packages.sh'
RUN /bin/bash -l -c 'cd /distpackages && ./build_deb_packages.sh'

@ -66,5 +66,8 @@ RUN cd /var/local/git/grpc \
# Add a cacerts directory containing the Google root pem file, allowing the interop client to access the production test instance
ADD cacerts cacerts
# Add a service_account directory containing the auth creds file
ADD service_account service_account
# Specify the default command such that the interop server runs on its known testing port
CMD ["/bin/bash", "-l", "-c", "python2.7 -m interop.server --use_tls --port 8050"]

@ -747,6 +747,11 @@ grpc_build_debs() {
local project_opt="--project $grpc_project"
local zone_opt="--zone $grpc_zone"
# Update the remote distpackages_dir
local src_dist_dir='tools/distpackages'
local rmt_dist_dir="$host:~"
gcloud compute copy-files $src_dist_dir $rmt_dist_dir $project_opt $zone_opt || return 1
# rebuild the build_deb image
local label='build_deb'
grpc_update_image -- -h $host $label || return 1
@ -1036,6 +1041,35 @@ grpc_interop_gen_python_cmd() {
echo $the_cmd
}
# constructs the full dockerized python service_account auth interop test cmd.
#
# call-seq:
# flags= .... # generic flags to include the command
# cmd=$($grpc_gen_test_cmd $flags)
grpc_cloud_prod_auth_service_account_creds_gen_python_cmd() {
local cmd_prefix="sudo docker run grpc/python bin/bash -l -c";
local gfe_flags=$(_grpc_prod_gfe_flags)
local added_gfe_flags=$(_grpc_default_creds_test_flags)
local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem"
env_prefix+=" GOOGLE_APPLICATION_CREDENTIALS=/service_account/stubbyCloudTestingTest-7dd63462c60c.json"
local the_cmd="$cmd_prefix '$env_prefix python -B -m interop.client --use_tls $gfe_flags $added_gfe_flags $@'"
echo $the_cmd
}
# constructs the full dockerized python gce auth interop test cmd.
#
# call-seq:
# flags= .... # generic flags to include the command
# cmd=$($grpc_gen_test_cmd $flags)
grpc_cloud_prod_auth_compute_engine_creds_gen_python_cmd() {
local cmd_prefix="sudo docker run grpc/python bin/bash -l -c";
local gfe_flags=$(_grpc_prod_gfe_flags)
local added_gfe_flags=$(_grpc_gce_test_flags)
local env_prefix="SSL_CERT_FILE=/cacerts/roots.pem"
local the_cmd="$cmd_prefix '$env_prefix python -B -m interop.client --use_tls $gfe_flags $added_gfe_flags $@'"
echo $the_cmd
}
# constructs the full dockerized java interop test cmd.
#
# call-seq:

@ -36,7 +36,7 @@ echo $result_file_name
main() {
source grpc_docker.sh
test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response)
clients=(cxx java go ruby node python csharp_mono)
clients=(cxx java go ruby node python csharp_mono php)
servers=(cxx java go ruby node python csharp_mono)
for test_case in "${test_cases[@]}"
do

@ -434,6 +434,12 @@ grpc_dockerfile_install() {
grpc_docker_sync_service_account $dockerfile_dir/service_account || return 1;
}
# For deb builds, copy the distpackages folder into the docker directory so
# that it can be installed using ADD distpackages distpackages.
[[ $image_label == "grpc/build_deb" ]] && {
cp -vR ~/distpackages $dockerfile_dir
}
# TODO(temiola): maybe make cache/no-cache a func option?
sudo docker build $cache_opt -t $image_label $dockerfile_dir || {
echo "$FUNCNAME:: build of $image_label <- $dockerfile_dir"

@ -93,6 +93,12 @@
<ClInclude Include="..\..\include\grpc++\impl\rpc_method.h" />
<ClInclude Include="..\..\include\grpc++\impl\rpc_service_method.h" />
<ClInclude Include="..\..\include\grpc++\impl\service_type.h" />
<ClInclude Include="..\..\include\grpc++\impl\sync.h" />
<ClInclude Include="..\..\include\grpc++\impl\sync_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\impl\sync_no_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\impl\thd.h" />
<ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\server.h" />
<ClInclude Include="..\..\include\grpc++\server_builder.h" />
<ClInclude Include="..\..\include\grpc++\server_context.h" />
@ -105,6 +111,8 @@
<ClInclude Include="..\..\include\grpc++\time.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cpp\client\secure_credentials.h" />
<ClInclude Include="..\..\src\cpp\server\secure_server_credentials.h" />
<ClInclude Include="..\..\src\cpp\client\channel.h" />
<ClInclude Include="..\..\src\cpp\proto\proto_utils.h" />
<ClInclude Include="..\..\src\cpp\server\thread_pool.h" />

@ -132,6 +132,24 @@
<ClInclude Include="..\..\include\grpc++\impl\service_type.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\sync.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\sync_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\sync_no_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\thd.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\server.h">
<Filter>include\grpc++</Filter>
</ClInclude>
@ -164,6 +182,12 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cpp\client\secure_credentials.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpp\server\secure_server_credentials.h">
<Filter>src\cpp\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpp\client\channel.h">
<Filter>src\cpp\client</Filter>
</ClInclude>

@ -95,6 +95,12 @@
<ClInclude Include="..\..\include\grpc++\impl\rpc_method.h" />
<ClInclude Include="..\..\include\grpc++\impl\rpc_service_method.h" />
<ClInclude Include="..\..\include\grpc++\impl\service_type.h" />
<ClInclude Include="..\..\include\grpc++\impl\sync.h" />
<ClInclude Include="..\..\include\grpc++\impl\sync_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\impl\sync_no_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\impl\thd.h" />
<ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h" />
<ClInclude Include="..\..\include\grpc++\server.h" />
<ClInclude Include="..\..\include\grpc++\server_builder.h" />
<ClInclude Include="..\..\include\grpc++\server_context.h" />
@ -107,6 +113,8 @@
<ClInclude Include="..\..\include\grpc++\time.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cpp\client\secure_credentials.h" />
<ClInclude Include="..\..\src\cpp\server\secure_server_credentials.h" />
<ClInclude Include="..\..\src\cpp\client\channel.h" />
<ClInclude Include="..\..\src\cpp\proto\proto_utils.h" />
<ClInclude Include="..\..\src\cpp\server\thread_pool.h" />

@ -132,6 +132,24 @@
<ClInclude Include="..\..\include\grpc++\impl\service_type.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\sync.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\sync_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\sync_no_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\thd.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\include\grpc++\server.h">
<Filter>include\grpc++</Filter>
</ClInclude>
@ -164,6 +182,12 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\cpp\client\secure_credentials.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpp\server\secure_server_credentials.h">
<Filter>src\cpp\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpp\client\channel.h">
<Filter>src\cpp\client</Filter>
</ClInclude>

Loading…
Cancel
Save