Merge branch 'master' of github.com:google/grpc into go-auth-tests

pull/884/head
Donna Dionne 10 years ago
commit 71d764b0b3
  1. 36
      Makefile
  2. 14
      build.json
  3. 367
      src/compiler/python_generator.cc
  4. 3
      src/compiler/python_generator.h
  5. 16
      src/compiler/python_plugin.cc
  6. 4
      src/core/iomgr/fd_posix.c
  7. 5
      src/core/iomgr/pollset.h
  8. 155
      src/core/iomgr/pollset_posix.c
  9. 4
      src/core/iomgr/pollset_posix.h
  10. 6
      src/core/iomgr/pollset_windows.c
  11. 33
      src/core/security/security_context.c
  12. 3
      src/core/support/cpu_posix.c
  13. 9
      src/core/surface/completion_queue.c
  14. 20
      src/core/transport/chttp2_transport.c
  15. 106
      src/core/tsi/ssl_transport_security.c
  16. 7
      src/core/tsi/ssl_transport_security.h
  17. 11
      src/csharp/Grpc.Core.Tests/ClientServerTest.cs
  18. 1
      src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
  19. 9
      src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
  20. 145
      src/csharp/Grpc.Core.Tests/PInvokeTest.cs
  21. 15
      src/csharp/Grpc.Core/Calls.cs
  22. 21
      src/csharp/Grpc.Core/Grpc.Core.csproj
  23. 1
      src/csharp/Grpc.Core/GrpcEnvironment.cs
  24. 31
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  25. 10
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  26. 94
      src/csharp/Grpc.Core/Internal/GrpcLog.cs
  27. 3
      src/csharp/Grpc.Core/RpcException.cs
  28. 2
      src/csharp/Grpc.Core/ServerCallHandler.cs
  29. 68
      src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
  30. 57
      src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
  31. 11
      src/csharp/Grpc.IntegrationTesting/Client.cs
  32. 49
      src/csharp/ext/grpc_csharp_ext.c
  33. 2
      src/node/test/interop_sanity_test.js
  34. 2
      src/php/tests/interop/interop_client.php
  35. 2
      src/php/tests/unit_tests/SecureEndToEndTest.php
  36. 35
      src/ruby/bin/apis/pubsub_demo.rb
  37. 33
      src/ruby/bin/interop/interop_client.rb
  38. 2
      src/ruby/bin/math_client.rb
  39. 2
      src/ruby/bin/noproto_client.rb
  40. 1
      src/ruby/grpc.gemspec
  41. 2
      src/ruby/lib/grpc.rb
  42. 67
      src/ruby/lib/grpc/auth/compute_engine.rb
  43. 66
      src/ruby/lib/grpc/auth/service_account.rb
  44. 67
      src/ruby/lib/grpc/auth/signet.rb
  45. 163
      src/ruby/spec/auth/apply_auth_examples.rb
  46. 108
      src/ruby/spec/auth/compute_engine_spec.rb
  47. 75
      src/ruby/spec/auth/service_account_spec.rb
  48. 70
      src/ruby/spec/auth/signet_spec.rb
  49. 2
      src/ruby/spec/client_server_spec.rb
  50. 2
      src/ruby/spec/generic/client_stub_spec.rb
  51. 395
      test/compiler/python_plugin_test.py
  52. 3
      test/compiler/test.proto
  53. 4
      test/core/end2end/dualstack_socket_test.c
  54. 2
      test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
  55. 2
      test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
  56. 2
      test/core/end2end/tests/cancel_after_accept.c
  57. 4
      test/core/end2end/tests/cancel_after_accept_and_writes_closed.c
  58. 4
      test/core/end2end/tests/cancel_after_accept_and_writes_closed_legacy.c
  59. 4
      test/core/end2end/tests/cancel_after_accept_legacy.c
  60. 2
      test/core/end2end/tests/cancel_after_invoke.c
  61. 2
      test/core/end2end/tests/cancel_after_invoke_legacy.c
  62. 2
      test/core/end2end/tests/cancel_before_invoke.c
  63. 2
      test/core/end2end/tests/cancel_before_invoke_legacy.c
  64. 2
      test/core/end2end/tests/cancel_in_a_vacuum.c
  65. 2
      test/core/end2end/tests/cancel_in_a_vacuum_legacy.c
  66. 4
      test/core/end2end/tests/census_simple_request.c
  67. 4
      test/core/end2end/tests/census_simple_request_legacy.c
  68. 4
      test/core/end2end/tests/disappearing_server.c
  69. 4
      test/core/end2end/tests/disappearing_server_legacy.c
  70. 4
      test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c
  71. 4
      test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls_legacy.c
  72. 2
      test/core/end2end/tests/empty_batch.c
  73. 4
      test/core/end2end/tests/graceful_server_shutdown.c
  74. 4
      test/core/end2end/tests/graceful_server_shutdown_legacy.c
  75. 4
      test/core/end2end/tests/invoke_large_request.c
  76. 4
      test/core/end2end/tests/invoke_large_request_legacy.c
  77. 12
      test/core/end2end/tests/max_concurrent_streams.c
  78. 12
      test/core/end2end/tests/max_concurrent_streams_legacy.c
  79. 4
      test/core/end2end/tests/ping_pong_streaming.c
  80. 4
      test/core/end2end/tests/ping_pong_streaming_legacy.c
  81. 4
      test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c
  82. 4
      test/core/end2end/tests/request_response_with_binary_metadata_and_payload_legacy.c
  83. 4
      test/core/end2end/tests/request_response_with_metadata_and_payload.c
  84. 4
      test/core/end2end/tests/request_response_with_metadata_and_payload_legacy.c
  85. 4
      test/core/end2end/tests/request_response_with_payload.c
  86. 4
      test/core/end2end/tests/request_response_with_payload_legacy.c
  87. 4
      test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c
  88. 4
      test/core/end2end/tests/request_response_with_trailing_metadata_and_payload_legacy.c
  89. 4
      test/core/end2end/tests/request_with_large_metadata.c
  90. 4
      test/core/end2end/tests/request_with_large_metadata_legacy.c
  91. 4
      test/core/end2end/tests/request_with_payload.c
  92. 4
      test/core/end2end/tests/request_with_payload_legacy.c
  93. 4
      test/core/end2end/tests/simple_delayed_request.c
  94. 4
      test/core/end2end/tests/simple_delayed_request_legacy.c
  95. 4
      test/core/end2end/tests/simple_request.c
  96. 8
      test/core/end2end/tests/simple_request_legacy.c
  97. 2
      test/core/end2end/tests/thread_stress.c
  98. 2
      test/core/end2end/tests/thread_stress_legacy.c
  99. 4
      test/core/end2end/tests/writes_done_hangs_with_pending_read.c
  100. 4
      test/core/end2end/tests/writes_done_hangs_with_pending_read_legacy.c
  101. Some files were not shown because too many files have changed in this diff Show More

File diff suppressed because one or more lines are too long

@ -1579,6 +1579,20 @@
"gpr" "gpr"
] ]
}, },
{
"name": "transport_security_test",
"build": "test",
"language": "c",
"src": [
"test/core/tsi/transport_security_test.c"
],
"deps": [
"grpc_test_util",
"grpc",
"gpr_test_util",
"gpr"
]
},
{ {
"name": "async_end2end_test", "name": "async_end2end_test",
"build": "test", "build": "test",

@ -33,9 +33,11 @@
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
#include <cstring>
#include <map> #include <map>
#include <ostream> #include <ostream>
#include <sstream> #include <sstream>
#include <vector>
#include "src/compiler/python_generator.h" #include "src/compiler/python_generator.h"
#include <google/protobuf/io/printer.h> #include <google/protobuf/io/printer.h>
@ -43,14 +45,19 @@
#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
using google::protobuf::Descriptor;
using google::protobuf::FileDescriptor; using google::protobuf::FileDescriptor;
using google::protobuf::ServiceDescriptor; using google::protobuf::ServiceDescriptor;
using google::protobuf::MethodDescriptor; using google::protobuf::MethodDescriptor;
using google::protobuf::io::Printer; using google::protobuf::io::Printer;
using google::protobuf::io::StringOutputStream; using google::protobuf::io::StringOutputStream;
using std::initializer_list; using std::initializer_list;
using std::make_pair;
using std::map; using std::map;
using std::pair;
using std::string; using std::string;
using std::strlen;
using std::vector;
namespace grpc_python_generator { namespace grpc_python_generator {
namespace { namespace {
@ -99,62 +106,81 @@ class IndentScope {
// END FORMATTING BOILERPLATE // // END FORMATTING BOILERPLATE //
//////////////////////////////// ////////////////////////////////
void PrintService(const ServiceDescriptor* service, bool PrintServicer(const ServiceDescriptor* service,
Printer* out) { Printer* out) {
string doc = "<fill me in later!>"; string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({ map<string, string> dict = ListToDict({
"Service", service->name(), "Service", service->name(),
"Documentation", doc, "Documentation", doc,
}); });
out->Print(dict, "class $Service$Service(object):\n"); out->Print(dict, "class EarlyAdopter$Service$Servicer(object):\n");
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
out->Print("def __init__(self):\n"); out->Print("__metaclass__ = abc.ABCMeta\n");
{ for (int i = 0; i < service->method_count(); ++i) {
IndentScope raii_method_indent(out); auto meth = service->method(i);
out->Print("pass\n"); string arg_name = meth->client_streaming() ?
"request_iterator" : "request";
out->Print("@abc.abstractmethod\n");
out->Print("def $Method$(self, $ArgName$):\n",
"Method", meth->name(), "ArgName", arg_name);
{
IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n");
}
} }
} }
return true;
} }
void PrintServicer(const ServiceDescriptor* service, bool PrintServer(const ServiceDescriptor* service, Printer* out) {
Printer* out) {
string doc = "<fill me in later!>"; string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({ map<string, string> dict = ListToDict({
"Service", service->name(), "Service", service->name(),
"Documentation", doc, "Documentation", doc,
}); });
out->Print(dict, "class $Service$Servicer(object):\n"); out->Print(dict, "class EarlyAdopter$Service$Server(object):\n");
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) { out->Print("__metaclass__ = abc.ABCMeta\n");
auto meth = service->method(i); out->Print("@abc.abstractmethod\n");
out->Print("def $Method$(self, arg):\n", "Method", meth->name()); out->Print("def start(self):\n");
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n"); out->Print("raise NotImplementedError()\n");
} }
out->Print("@abc.abstractmethod\n");
out->Print("def stop(self):\n");
{
IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n");
} }
} }
return true;
} }
void PrintStub(const ServiceDescriptor* service, bool PrintStub(const ServiceDescriptor* service,
Printer* out) { Printer* out) {
string doc = "<fill me in later!>"; string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({ map<string, string> dict = ListToDict({
"Service", service->name(), "Service", service->name(),
"Documentation", doc, "Documentation", doc,
}); });
out->Print(dict, "class $Service$Stub(object):\n"); out->Print(dict, "class EarlyAdopter$Service$Stub(object):\n");
{ {
IndentScope raii_class_indent(out); IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
out->Print("__metaclass__ = abc.ABCMeta\n");
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i); const MethodDescriptor* meth = service->method(i);
auto methdict = ListToDict({"Method", meth->name()}); string arg_name = meth->client_streaming() ?
out->Print(methdict, "def $Method$(self, arg):\n"); "request_iterator" : "request";
auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
out->Print("@abc.abstractmethod\n");
out->Print(methdict, "def $Method$(self, $ArgName$):\n");
{ {
IndentScope raii_method_indent(out); IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n"); out->Print("raise NotImplementedError()\n");
@ -162,169 +188,190 @@ void PrintStub(const ServiceDescriptor* service,
out->Print(methdict, "$Method$.async = None\n"); out->Print(methdict, "$Method$.async = None\n");
} }
} }
return true;
} }
void PrintStubImpl(const ServiceDescriptor* service, bool GetModuleAndMessagePath(const Descriptor* type,
Printer* out) { pair<string, string>* out) {
map<string, string> dict = ListToDict({ const Descriptor* path_elem_type = type;
"Service", service->name(), vector<const Descriptor*> message_path;
}); do {
out->Print(dict, "class _$Service$Stub($Service$Stub):\n"); message_path.push_back(path_elem_type);
{ path_elem_type = path_elem_type->containing_type();
IndentScope raii_class_indent(out); } while (path_elem_type != nullptr);
out->Print("def __init__(self, face_stub, default_timeout):\n"); string file_name = type->file()->name();
{ string module_name;
IndentScope raii_method_indent(out); static const int proto_suffix_length = strlen(".proto");
out->Print("self._face_stub = face_stub\n" if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
"self._default_timeout = default_timeout\n" file_name.find_last_of(".proto") == file_name.size() - 1)) {
"stub_self = self\n"); return false;
}
module_name = file_name.substr(
0, file_name.size() - proto_suffix_length) + "_pb2";
string package = type->file()->package();
string module = (package.empty() ? "" : package + ".") +
module_name;
string message_type;
for (auto path_iter = message_path.rbegin();
path_iter != message_path.rend(); ++path_iter) {
message_type += (*path_iter)->name() + ".";
}
message_type.pop_back();
*out = make_pair(module, message_type);
return true;
}
for (int i = 0; i < service->method_count(); ++i) { bool PrintServerFactory(const ServiceDescriptor* service, Printer* out) {
const MethodDescriptor* meth = service->method(i); out->Print("def early_adopter_create_$Service$_server(servicer, port, "
bool server_streaming = meth->server_streaming(); "root_certificates, key_chain_pairs):\n",
bool client_streaming = meth->client_streaming(); "Service", service->name());
std::string blocking_call, future_call; {
if (server_streaming) { IndentScope raii_create_server_indent(out);
if (client_streaming) { map<string, pair<string, string>> method_to_module_and_message;
blocking_call = "stub_self._face_stub.inline_stream_in_stream_out"; out->Print("method_implementations = {\n");
future_call = blocking_call; for (int i = 0; i < service->method_count(); ++i) {
} else { IndentScope raii_implementations_indent(out);
blocking_call = "stub_self._face_stub.inline_value_in_stream_out"; const MethodDescriptor* meth = service->method(i);
future_call = blocking_call; string meth_type =
} string(meth->client_streaming() ? "stream" : "unary") +
} else { string(meth->server_streaming() ? "_stream" : "_unary") + "_inline";
if (client_streaming) { out->Print("\"$Method$\": utilities.$Type$(servicer.$Method$),\n",
blocking_call = "stub_self._face_stub.blocking_stream_in_value_out"; "Method", meth->name(),
future_call = "stub_self._face_stub.future_stream_in_value_out"; "Type", meth_type);
} else { // Maintain information on the input type of the service method for later
blocking_call = "stub_self._face_stub.blocking_value_in_value_out"; // use in constructing the service assembly's activated fore link.
future_call = "stub_self._face_stub.future_value_in_value_out"; const Descriptor* input_type = meth->input_type();
} pair<string, string> module_and_message;
} if (!GetModuleAndMessagePath(input_type, &module_and_message)) {
// TODO(atash): use the solution described at return false;
// http://stackoverflow.com/a/2982 to bind 'async' attribute
// functions to def'd functions instead of using callable attributes.
auto methdict = ListToDict({
"Method", meth->name(),
"BlockingCall", blocking_call,
"FutureCall", future_call
});
out->Print(methdict, "class $Method$(object):\n");
{
IndentScope raii_callable_indent(out);
out->Print("def __call__(self, arg):\n");
{
IndentScope raii_callable_call_indent(out);
out->Print(methdict,
"return $BlockingCall$(\"$Method$\", arg, "
"stub_self._default_timeout)\n");
}
out->Print("def async(self, arg):\n");
{
IndentScope raii_callable_async_indent(out);
out->Print(methdict,
"return $FutureCall$(\"$Method$\", arg, "
"stub_self._default_timeout)\n");
}
}
out->Print(methdict, "self.$Method$ = $Method$()\n");
} }
method_to_module_and_message.emplace(
meth->name(), module_and_message);
}
out->Print("}\n");
// Ensure that we've imported all of the relevant messages.
for (auto& meth_vals : method_to_module_and_message) {
out->Print("import $Module$\n",
"Module", meth_vals.second.first);
} }
out->Print("request_deserializers = {\n");
for (auto& meth_vals : method_to_module_and_message) {
IndentScope raii_serializers_indent(out);
string full_input_type_path = meth_vals.second.first + "." +
meth_vals.second.second;
out->Print("\"$Method$\": $Type$.FromString,\n",
"Method", meth_vals.first,
"Type", full_input_type_path);
}
out->Print("}\n");
out->Print("response_serializers = {\n");
for (auto& meth_vals : method_to_module_and_message) {
IndentScope raii_serializers_indent(out);
out->Print("\"$Method$\": lambda x: x.SerializeToString(),\n",
"Method", meth_vals.first);
}
out->Print("}\n");
out->Print("link = fore.activated_fore_link(port, request_deserializers, "
"response_serializers, root_certificates, key_chain_pairs)\n");
out->Print("return implementations.assemble_service("
"method_implementations, link)\n");
} }
return true;
} }
void PrintStubGenerators(const ServiceDescriptor* service, Printer* out) { bool PrintStubFactory(const ServiceDescriptor* service, Printer* out) {
map<string, string> dict = ListToDict({ map<string, string> dict = ListToDict({
"Service", service->name(), "Service", service->name(),
}); });
// Write out a generator of linked pairs of Server/Stub out->Print(dict, "def early_adopter_create_$Service$_stub(host, port):\n");
out->Print(dict, "def mock_$Service$(servicer, default_timeout):\n");
{ {
IndentScope raii_mock_indent(out); IndentScope raii_create_server_indent(out);
out->Print("value_in_value_out = {}\n" map<string, pair<string, string>> method_to_module_and_message;
"value_in_stream_out = {}\n" out->Print("method_implementations = {\n");
"stream_in_value_out = {}\n"
"stream_in_stream_out = {}\n");
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
IndentScope raii_implementations_indent(out);
const MethodDescriptor* meth = service->method(i); const MethodDescriptor* meth = service->method(i);
std::string super_interface, meth_dict; string meth_type =
bool server_streaming = meth->server_streaming(); string(meth->client_streaming() ? "stream" : "unary") +
bool client_streaming = meth->client_streaming(); string(meth->server_streaming() ? "_stream" : "_unary") + "_inline";
if (server_streaming) { // TODO(atash): once the expected input to assemble_dynamic_inline_stub is
if (client_streaming) { // cleaned up, change this to the expected argument's dictionary values.
super_interface = "InlineStreamInStreamOutMethod"; out->Print("\"$Method$\": utilities.$Type$(None),\n",
meth_dict = "stream_in_stream_out"; "Method", meth->name(),
} else { "Type", meth_type);
super_interface = "InlineValueInStreamOutMethod"; // Maintain information on the input type of the service method for later
meth_dict = "value_in_stream_out"; // use in constructing the service assembly's activated fore link.
} const Descriptor* output_type = meth->output_type();
} else { pair<string, string> module_and_message;
if (client_streaming) { if (!GetModuleAndMessagePath(output_type, &module_and_message)) {
super_interface = "InlineStreamInValueOutMethod"; return false;
meth_dict = "stream_in_value_out";
} else {
super_interface = "InlineValueInValueOutMethod";
meth_dict = "value_in_value_out";
}
}
map<string, string> methdict = ListToDict({
"Method", meth->name(),
"SuperInterface", super_interface,
"MethodDict", meth_dict
});
out->Print(
methdict, "class $Method$(_face_interfaces.$SuperInterface$):\n");
{
IndentScope raii_inline_class_indent(out);
out->Print("def service(self, request, context):\n");
{
IndentScope raii_inline_class_fn_indent(out);
out->Print(methdict, "return servicer.$Method$(request)\n");
}
} }
out->Print(methdict, "$MethodDict$['$Method$'] = $Method$()\n"); method_to_module_and_message.emplace(
meth->name(), module_and_message);
} }
out->Print( out->Print("}\n");
"face_linked_pair = _face_testing.server_and_stub(default_timeout," // Ensure that we've imported all of the relevant messages.
"inline_value_in_value_out_methods=value_in_value_out," for (auto& meth_vals : method_to_module_and_message) {
"inline_value_in_stream_out_methods=value_in_stream_out," out->Print("import $Module$\n",
"inline_stream_in_value_out_methods=stream_in_value_out," "Module", meth_vals.second.first);
"inline_stream_in_stream_out_methods=stream_in_stream_out)\n");
out->Print("class LinkedPair(object):\n");
{
IndentScope raii_linked_pair(out);
out->Print("def __init__(self, server, stub):\n");
{
IndentScope raii_linked_pair_init(out);
out->Print("self.server = server\n"
"self.stub = stub\n");
}
} }
out->Print( out->Print("response_deserializers = {\n");
dict, for (auto& meth_vals : method_to_module_and_message) {
"stub = _$Service$Stub(face_linked_pair.stub, default_timeout)\n"); IndentScope raii_serializers_indent(out);
out->Print("return LinkedPair(None, stub)\n"); string full_output_type_path = meth_vals.second.first + "." +
meth_vals.second.second;
out->Print("\"$Method$\": $Type$.FromString,\n",
"Method", meth_vals.first,
"Type", full_output_type_path);
}
out->Print("}\n");
out->Print("request_serializers = {\n");
for (auto& meth_vals : method_to_module_and_message) {
IndentScope raii_serializers_indent(out);
out->Print("\"$Method$\": lambda x: x.SerializeToString(),\n",
"Method", meth_vals.first);
}
out->Print("}\n");
out->Print("link = rear.activated_rear_link("
"host, port, request_serializers, response_deserializers)\n");
out->Print("return implementations.assemble_dynamic_inline_stub("
"method_implementations, link)\n");
} }
return true;
}
bool PrintPreamble(const FileDescriptor* file, Printer* out) {
out->Print("import abc\n");
out->Print("from grpc._adapter import fore\n");
out->Print("from grpc._adapter import rear\n");
out->Print("from grpc.framework.assembly import implementations\n");
out->Print("from grpc.framework.assembly import utilities\n");
return true;
} }
} // namespace } // namespace
string GetServices(const FileDescriptor* file) { pair<bool, string> GetServices(const FileDescriptor* file) {
string output; string output;
StringOutputStream output_stream(&output); {
Printer out(&output_stream, '$'); // Scope the output stream so it closes and finalizes output to the string.
out.Print("from grpc.framework.face import demonstration as _face_testing\n"); StringOutputStream output_stream(&output);
out.Print("from grpc.framework.face import interfaces as _face_interfaces\n"); Printer out(&output_stream, '$');
if (!PrintPreamble(file, &out)) {
for (int i = 0; i < file->service_count(); ++i) { return make_pair(false, "");
auto service = file->service(i); }
PrintService(service, &out); for (int i = 0; i < file->service_count(); ++i) {
PrintServicer(service, &out); auto service = file->service(i);
PrintStub(service, &out); if (!(PrintServicer(service, &out) &&
PrintStubImpl(service, &out); PrintServer(service, &out) &&
PrintStubGenerators(service, &out); PrintStub(service, &out) &&
PrintServerFactory(service, &out) &&
PrintStubFactory(service, &out))) {
return make_pair(false, "");
}
}
} }
return output; return make_pair(true, std::move(output));
} }
} // namespace grpc_python_generator } // namespace grpc_python_generator

@ -35,6 +35,7 @@
#define __GRPC_COMPILER_PYTHON_GENERATOR_H__ #define __GRPC_COMPILER_PYTHON_GENERATOR_H__
#include <string> #include <string>
#include <utility>
namespace google { namespace google {
namespace protobuf { namespace protobuf {
@ -44,7 +45,7 @@ class FileDescriptor;
namespace grpc_python_generator { namespace grpc_python_generator {
std::string GetServices(const google::protobuf::FileDescriptor* file); std::pair<bool, std::string> GetServices(const google::protobuf::FileDescriptor* file);
} // namespace grpc_python_generator } // namespace grpc_python_generator

@ -33,6 +33,7 @@
// Generates a Python gRPC service interface out of Protobuf IDL. // Generates a Python gRPC service interface out of Protobuf IDL.
#include <cstring>
#include <memory> #include <memory>
#include <string> #include <string>
@ -50,6 +51,7 @@ using google::protobuf::compiler::PluginMain;
using google::protobuf::io::CodedOutputStream; using google::protobuf::io::CodedOutputStream;
using google::protobuf::io::ZeroCopyOutputStream; using google::protobuf::io::ZeroCopyOutputStream;
using std::string; using std::string;
using std::strlen;
class PythonGrpcGenerator : public CodeGenerator { class PythonGrpcGenerator : public CodeGenerator {
public: public:
@ -62,7 +64,7 @@ class PythonGrpcGenerator : public CodeGenerator {
string* error) const override { string* error) const override {
// Get output file name. // Get output file name.
string file_name; string file_name;
static const int proto_suffix_length = 6; // length of ".proto" static const int proto_suffix_length = strlen(".proto");
if (file->name().size() > static_cast<size_t>(proto_suffix_length) && if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
file->name().find_last_of(".proto") == file->name().size() - 1) { file->name().find_last_of(".proto") == file->name().size() - 1) {
file_name = file->name().substr( file_name = file->name().substr(
@ -75,9 +77,15 @@ class PythonGrpcGenerator : public CodeGenerator {
std::unique_ptr<ZeroCopyOutputStream> output( std::unique_ptr<ZeroCopyOutputStream> output(
context->OpenForInsert(file_name, "module_scope")); context->OpenForInsert(file_name, "module_scope"));
CodedOutputStream coded_out(output.get()); CodedOutputStream coded_out(output.get());
string code = grpc_python_generator::GetServices(file); bool success = false;
coded_out.WriteRaw(code.data(), code.size()); string code = "";
return true; tie(success, code) = grpc_python_generator::GetServices(file);
if (success) {
coded_out.WriteRaw(code.data(), code.size());
return true;
} else {
return false;
}
} }
}; };

@ -38,6 +38,7 @@
#include "src/core/iomgr/fd_posix.h" #include "src/core/iomgr/fd_posix.h"
#include <assert.h> #include <assert.h>
#include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include "src/core/iomgr/iomgr_internal.h" #include "src/core/iomgr/iomgr_internal.h"
@ -113,6 +114,7 @@ static void ref_by(grpc_fd *fd, int n) {
static void unref_by(grpc_fd *fd, int n) { static void unref_by(grpc_fd *fd, int n) {
gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n);
if (old == n) { if (old == n) {
close(fd->fd);
grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data);
freelist_fd(fd); freelist_fd(fd);
grpc_iomgr_unref(); grpc_iomgr_unref();
@ -158,9 +160,9 @@ static void wake_watchers(grpc_fd *fd) {
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) { void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_cb_func on_done, void *user_data) {
fd->on_done = on_done ? on_done : do_nothing; fd->on_done = on_done ? on_done : do_nothing;
fd->on_done_user_data = user_data; fd->on_done_user_data = user_data;
shutdown(fd->fd, SHUT_RDWR);
ref_by(fd, 1); /* remove active status, but keep referenced */ ref_by(fd, 1); /* remove active status, but keep referenced */
wake_watchers(fd); wake_watchers(fd);
close(fd->fd);
unref_by(fd, 2); /* drop the reference */ unref_by(fd, 2); /* drop the reference */
} }

@ -52,9 +52,14 @@
#include "src/core/iomgr/pollset_windows.h" #include "src/core/iomgr/pollset_windows.h"
#endif #endif
void grpc_pollset_init(grpc_pollset *pollset); void grpc_pollset_init(grpc_pollset *pollset);
void grpc_pollset_shutdown(grpc_pollset *pollset,
void (*shutdown_done)(void *arg),
void *shutdown_done_arg);
void grpc_pollset_destroy(grpc_pollset *pollset); void grpc_pollset_destroy(grpc_pollset *pollset);
/* Do some work on a pollset. /* Do some work on a pollset.
May involve invoking asynchronous callbacks, or actually polling file May involve invoking asynchronous callbacks, or actually polling file
descriptors. descriptors.

@ -55,6 +55,7 @@
static grpc_pollset g_backup_pollset; static grpc_pollset g_backup_pollset;
static int g_shutdown_backup_poller; static int g_shutdown_backup_poller;
static gpr_event g_backup_poller_done; static gpr_event g_backup_poller_done;
static gpr_event g_backup_pollset_shutdown_done;
static void backup_poller(void *p) { static void backup_poller(void *p) {
gpr_timespec delta = gpr_time_from_millis(100); gpr_timespec delta = gpr_time_from_millis(100);
@ -104,9 +105,14 @@ void grpc_pollset_global_init(void) {
/* start the backup poller thread */ /* start the backup poller thread */
g_shutdown_backup_poller = 0; g_shutdown_backup_poller = 0;
gpr_event_init(&g_backup_poller_done); gpr_event_init(&g_backup_poller_done);
gpr_event_init(&g_backup_pollset_shutdown_done);
gpr_thd_new(&id, backup_poller, NULL, NULL); gpr_thd_new(&id, backup_poller, NULL, NULL);
} }
static void on_backup_pollset_shutdown_done(void *arg) {
gpr_event_set(&g_backup_pollset_shutdown_done, (void *)1);
}
void grpc_pollset_global_shutdown(void) { void grpc_pollset_global_shutdown(void) {
/* terminate the backup poller thread */ /* terminate the backup poller thread */
gpr_mu_lock(&g_backup_pollset.mu); gpr_mu_lock(&g_backup_pollset.mu);
@ -114,6 +120,10 @@ void grpc_pollset_global_shutdown(void) {
gpr_mu_unlock(&g_backup_pollset.mu); gpr_mu_unlock(&g_backup_pollset.mu);
gpr_event_wait(&g_backup_poller_done, gpr_inf_future); gpr_event_wait(&g_backup_poller_done, gpr_inf_future);
grpc_pollset_shutdown(&g_backup_pollset, on_backup_pollset_shutdown_done,
NULL);
gpr_event_wait(&g_backup_pollset_shutdown_done, gpr_inf_future);
/* destroy the backup pollset */ /* destroy the backup pollset */
grpc_pollset_destroy(&g_backup_pollset); grpc_pollset_destroy(&g_backup_pollset);
@ -130,6 +140,8 @@ void grpc_pollset_init(grpc_pollset *pollset) {
gpr_mu_init(&pollset->mu); gpr_mu_init(&pollset->mu);
gpr_cv_init(&pollset->cv); gpr_cv_init(&pollset->cv);
grpc_pollset_kick_init(&pollset->kick_state); grpc_pollset_kick_init(&pollset->kick_state);
pollset->in_flight_cbs = 0;
pollset->shutting_down = 0;
become_empty_pollset(pollset); become_empty_pollset(pollset);
} }
@ -163,7 +175,24 @@ int grpc_pollset_work(grpc_pollset *pollset, gpr_timespec deadline) {
return pollset->vtable->maybe_work(pollset, deadline, now, 1); return pollset->vtable->maybe_work(pollset, deadline, now, 1);
} }
void grpc_pollset_shutdown(grpc_pollset *pollset,
void (*shutdown_done)(void *arg),
void *shutdown_done_arg) {
int in_flight_cbs;
gpr_mu_lock(&pollset->mu);
pollset->shutting_down = 1;
in_flight_cbs = pollset->in_flight_cbs;
pollset->shutdown_done_cb = shutdown_done;
pollset->shutdown_done_arg = shutdown_done_arg;
gpr_mu_unlock(&pollset->mu);
if (in_flight_cbs == 0) {
shutdown_done(shutdown_done_arg);
}
}
void grpc_pollset_destroy(grpc_pollset *pollset) { void grpc_pollset_destroy(grpc_pollset *pollset) {
GPR_ASSERT(pollset->shutting_down);
GPR_ASSERT(pollset->in_flight_cbs == 0);
pollset->vtable->destroy(pollset); pollset->vtable->destroy(pollset);
grpc_pollset_kick_destroy(&pollset->kick_state); grpc_pollset_kick_destroy(&pollset->kick_state);
gpr_mu_destroy(&pollset->mu); gpr_mu_destroy(&pollset->mu);
@ -201,21 +230,119 @@ static void become_empty_pollset(grpc_pollset *pollset) {
* via poll() * via poll()
*/ */
typedef struct grpc_unary_promote_args {
const grpc_pollset_vtable *original_vtable;
grpc_pollset *pollset;
grpc_fd *fd;
} grpc_unary_promote_args;
static void unary_poll_do_promote(void *args, int success) {
grpc_unary_promote_args *up_args = args;
const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
grpc_pollset *pollset = up_args->pollset;
grpc_fd *fd = up_args->fd;
int do_shutdown_cb = 0;
gpr_free(up_args);
/*
* This is quite tricky. There are a number of cases to keep in mind here:
* 1. fd may have been orphaned
* 2. The pollset may no longer be a unary poller (and we can't let case #1
* leak to other pollset types!)
* 3. pollset's fd (which may have changed) may have been orphaned
* 4. The pollset may be shutting down.
*/
gpr_mu_lock(&pollset->mu);
/* First we need to ensure that nobody is polling concurrently */
while (pollset->counter != 0) {
grpc_pollset_kick(pollset);
gpr_cv_wait(&pollset->cv, &pollset->mu, gpr_inf_future);
}
/* At this point the pollset may no longer be a unary poller. In that case
* we should just call the right add function and be done. */
/* TODO(klempner): If we're not careful this could cause infinite recursion.
* That's not a problem for now because empty_pollset has a trivial poller
* and we don't have any mechanism to unbecome multipoller. */
pollset->in_flight_cbs--;
if (pollset->shutting_down) {
gpr_log(GPR_INFO, "Shutting down");
/* We don't care about this pollset anymore. */
if (pollset->in_flight_cbs == 0) {
do_shutdown_cb = 1;
}
} else if (grpc_fd_is_orphaned(fd)) {
/* Don't try to add it to anything, we'll drop our ref on it below */
} else if (pollset->vtable != original_vtable) {
gpr_log(GPR_INFO, "Not original vtable");
pollset->vtable->add_fd(pollset, fd);
} else if (fd != pollset->data.ptr) {
grpc_fd *fds[2];
fds[0] = pollset->data.ptr;
fds[1] = fd;
if (!grpc_fd_is_orphaned(fds[0])) {
grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
grpc_fd_unref(fds[0]);
} else {
/* old fd is orphaned and we haven't cleaned it up until now, so remain a
* unary poller */
/* Note that it is possible that fds[1] is also orphaned at this point.
* That's okay, we'll correct it at the next add or poll. */
grpc_fd_unref(fds[0]);
pollset->data.ptr = fd;
grpc_fd_ref(fd);
}
}
gpr_cv_broadcast(&pollset->cv);
gpr_mu_unlock(&pollset->mu);
if (do_shutdown_cb) {
pollset->shutdown_done_cb(pollset->shutdown_done_arg);
}
/* Matching ref in unary_poll_pollset_add_fd */
grpc_fd_unref(fd);
}
static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
grpc_fd *fds[2]; grpc_unary_promote_args *up_args;
if (fd == pollset->data.ptr) return; if (fd == pollset->data.ptr) return;
fds[0] = pollset->data.ptr;
fds[1] = fd; if (!pollset->counter) {
if (!grpc_fd_is_orphaned(fds[0])) { /* Fast path -- no in flight cbs */
grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds)); /* TODO(klempner): Comment this out and fix any test failures or establish
grpc_fd_unref(fds[0]); * they are due to timing issues */
} else { grpc_fd *fds[2];
/* old fd is orphaned and we haven't cleaned it up until now, so remain a fds[0] = pollset->data.ptr;
* unary poller */ fds[1] = fd;
grpc_fd_unref(fds[0]);
pollset->data.ptr = fd; if (!grpc_fd_is_orphaned(fds[0])) {
grpc_fd_ref(fd); grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
grpc_fd_unref(fds[0]);
} else {
/* old fd is orphaned and we haven't cleaned it up until now, so remain a
* unary poller */
grpc_fd_unref(fds[0]);
pollset->data.ptr = fd;
grpc_fd_ref(fd);
}
return;
} }
/* Now we need to promote. This needs to happen when we're not polling. Since
* this may be called from poll, the wait needs to happen asynchronously. */
grpc_fd_ref(fd);
pollset->in_flight_cbs++;
up_args = gpr_malloc(sizeof(*up_args));
up_args->pollset = pollset;
up_args->fd = fd;
up_args->original_vtable = pollset->vtable;
grpc_iomgr_add_callback(unary_poll_do_promote, up_args);
grpc_pollset_kick(pollset);
} }
static void unary_poll_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) { static void unary_poll_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) {
@ -238,6 +365,10 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset,
if (pollset->counter) { if (pollset->counter) {
return 0; return 0;
} }
if (pollset->in_flight_cbs) {
/* Give do_promote priority so we don't starve it out */
return 0;
}
fd = pollset->data.ptr; fd = pollset->data.ptr;
if (grpc_fd_is_orphaned(fd)) { if (grpc_fd_is_orphaned(fd)) {
grpc_fd_unref(fd); grpc_fd_unref(fd);

@ -55,6 +55,10 @@ typedef struct grpc_pollset {
gpr_cv cv; gpr_cv cv;
grpc_pollset_kick_state kick_state; grpc_pollset_kick_state kick_state;
int counter; int counter;
int in_flight_cbs;
int shutting_down;
void (*shutdown_done_cb)(void *arg);
void *shutdown_done_arg;
union { union {
int fd; int fd;
void *ptr; void *ptr;

@ -46,6 +46,12 @@ void grpc_pollset_init(grpc_pollset *pollset) {
gpr_cv_init(&pollset->cv); gpr_cv_init(&pollset->cv);
} }
void grpc_pollset_shutdown(grpc_pollset *pollset,
void (*shutdown_done)(void *arg),
void *shutdown_done_arg) {
shutdown_done(shutdown_done_arg);
}
void grpc_pollset_destroy(grpc_pollset *pollset) { void grpc_pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu); gpr_mu_destroy(&pollset->mu);
gpr_cv_destroy(&pollset->cv); gpr_cv_destroy(&pollset->cv);

@ -54,20 +54,33 @@
/* -- Constants. -- */ /* -- Constants. -- */
/* Defines the cipher suites that we accept. All these cipher suites are
compliant with TLS 1.2 and use an RSA public key. We prefer GCM over CBC
and ECDHE-RSA over just RSA. */
#define GRPC_SSL_CIPHER_SUITES \
"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:AES128-GCM-SHA256:" \
"AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-" \
"SHA256:AES256-SHA256"
#ifndef INSTALL_PREFIX #ifndef INSTALL_PREFIX
static const char *installed_roots_path = "/usr/share/grpc/roots.pem"; static const char *installed_roots_path = "/usr/share/grpc/roots.pem";
#else #else
static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem"; static const char *installed_roots_path = INSTALL_PREFIX "/share/grpc/roots.pem";
#endif #endif
/* -- Cipher suites. -- */
/* Defines the cipher suites that we accept by default. All these cipher suites
are compliant with HTTP2. */
#define GRPC_SSL_CIPHER_SUITES \
"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" \
"SHA384:ECDHE-RSA-AES256-GCM-SHA384"
static gpr_once cipher_suites_once = GPR_ONCE_INIT;
static const char *cipher_suites = NULL;
static void init_cipher_suites(void) {
char *overridden = gpr_getenv("GRPC_SSL_CIPHER_SUITES");
cipher_suites = overridden != NULL ? overridden : GRPC_SSL_CIPHER_SUITES;
}
static const char *ssl_cipher_suites(void) {
gpr_once_init(&cipher_suites_once, init_cipher_suites);
return cipher_suites;
}
/* -- Common methods. -- */ /* -- Common methods. -- */
grpc_security_status grpc_security_context_create_handshaker( grpc_security_status grpc_security_context_create_handshaker(
@ -489,7 +502,7 @@ grpc_security_status grpc_ssl_channel_security_context_create(
result = tsi_create_ssl_client_handshaker_factory( result = tsi_create_ssl_client_handshaker_factory(
config->pem_private_key, config->pem_private_key_size, config->pem_private_key, config->pem_private_key_size,
config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs, config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
pem_root_certs_size, GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings, pem_root_certs_size, ssl_cipher_suites(), alpn_protocol_strings,
alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory); alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) { if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
@ -543,7 +556,7 @@ grpc_security_status grpc_ssl_server_security_context_create(
(const unsigned char **)config->pem_cert_chains, (const unsigned char **)config->pem_cert_chains,
config->pem_cert_chains_sizes, config->num_key_cert_pairs, config->pem_cert_chains_sizes, config->num_key_cert_pairs,
config->pem_root_certs, config->pem_root_certs_size, config->pem_root_certs, config->pem_root_certs_size,
GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings, ssl_cipher_suites(), alpn_protocol_strings,
alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory); alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) { if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.", gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",

@ -40,6 +40,7 @@
#include <string.h> #include <string.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/sync.h>
static __thread char magic_thread_local; static __thread char magic_thread_local;
@ -55,7 +56,7 @@ static void init_ncpus() {
unsigned gpr_cpu_num_cores(void) { unsigned gpr_cpu_num_cores(void) {
static gpr_once once = GPR_ONCE_INIT; static gpr_once once = GPR_ONCE_INIT;
gpr_once_init(&once, init_num_cpus); gpr_once_init(&once, init_ncpus);
return ncpus; return ncpus;
} }

@ -389,12 +389,17 @@ void grpc_completion_queue_shutdown(grpc_completion_queue *cc) {
} }
} }
void grpc_completion_queue_destroy(grpc_completion_queue *cc) { static void on_pollset_destroy_done(void *arg) {
GPR_ASSERT(cc->queue == NULL); grpc_completion_queue *cc = arg;
grpc_pollset_destroy(&cc->pollset); grpc_pollset_destroy(&cc->pollset);
gpr_free(cc); gpr_free(cc);
} }
void grpc_completion_queue_destroy(grpc_completion_queue *cc) {
GPR_ASSERT(cc->queue == NULL);
grpc_pollset_shutdown(&cc->pollset, on_pollset_destroy_done, cc);
}
void grpc_event_finish(grpc_event *base) { void grpc_event_finish(grpc_event *base) {
event *ev = (event *)base; event *ev = (event *)base;
ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK);

@ -308,7 +308,7 @@ static void push_setting(transport *t, grpc_chttp2_setting_id id,
gpr_uint32 value); gpr_uint32 value);
static int prepare_callbacks(transport *t); static int prepare_callbacks(transport *t);
static void run_callbacks(transport *t); static void run_callbacks(transport *t, const grpc_transport_callbacks *cb);
static int prepare_write(transport *t); static int prepare_write(transport *t);
static void perform_write(transport *t, grpc_endpoint *ep); static void perform_write(transport *t, grpc_endpoint *ep);
@ -713,6 +713,7 @@ static void unlock(transport *t) {
pending_goaway *goaways = NULL; pending_goaway *goaways = NULL;
grpc_endpoint *ep = t->ep; grpc_endpoint *ep = t->ep;
grpc_stream_op_buffer nuke_now; grpc_stream_op_buffer nuke_now;
const grpc_transport_callbacks *cb = t->cb;
grpc_sopb_init(&nuke_now); grpc_sopb_init(&nuke_now);
if (t->nuke_later_sopb.nops) { if (t->nuke_later_sopb.nops) {
@ -732,7 +733,7 @@ static void unlock(transport *t) {
} }
/* gather any callbacks that need to be made */ /* gather any callbacks that need to be made */
if (!t->calling_back && t->cb) { if (!t->calling_back && cb) {
perform_callbacks = prepare_callbacks(t); perform_callbacks = prepare_callbacks(t);
if (perform_callbacks) { if (perform_callbacks) {
t->calling_back = 1; t->calling_back = 1;
@ -740,6 +741,7 @@ static void unlock(transport *t) {
if (t->error_state == ERROR_STATE_SEEN) { if (t->error_state == ERROR_STATE_SEEN) {
call_closed = 1; call_closed = 1;
t->calling_back = 1; t->calling_back = 1;
t->cb = NULL; /* no more callbacks */
t->error_state = ERROR_STATE_NOTIFIED; t->error_state = ERROR_STATE_NOTIFIED;
} }
if (t->num_pending_goaways) { if (t->num_pending_goaways) {
@ -761,16 +763,16 @@ static void unlock(transport *t) {
/* perform some callbacks if necessary */ /* perform some callbacks if necessary */
for (i = 0; i < num_goaways; i++) { for (i = 0; i < num_goaways; i++) {
t->cb->goaway(t->cb_user_data, &t->base, goaways[i].status, cb->goaway(t->cb_user_data, &t->base, goaways[i].status,
goaways[i].debug); goaways[i].debug);
} }
if (perform_callbacks) { if (perform_callbacks) {
run_callbacks(t); run_callbacks(t, cb);
} }
if (call_closed) { if (call_closed) {
t->cb->closed(t->cb_user_data, &t->base); cb->closed(t->cb_user_data, &t->base);
} }
/* write some bytes if necessary */ /* write some bytes if necessary */
@ -1753,13 +1755,13 @@ static int prepare_callbacks(transport *t) {
return n; return n;
} }
static void run_callbacks(transport *t) { static void run_callbacks(transport *t, const grpc_transport_callbacks *cb) {
stream *s; stream *s;
while ((s = stream_list_remove_head(t, EXECUTING_CALLBACKS))) { while ((s = stream_list_remove_head(t, EXECUTING_CALLBACKS))) {
size_t nops = s->callback_sopb.nops; size_t nops = s->callback_sopb.nops;
s->callback_sopb.nops = 0; s->callback_sopb.nops = 0;
t->cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s, cb->recv_batch(t->cb_user_data, &t->base, (grpc_stream *)s,
s->callback_sopb.ops, nops, s->callback_state); s->callback_sopb.ops, nops, s->callback_state);
} }
} }

@ -180,6 +180,30 @@ static void ssl_info_callback(const SSL* ssl, int where, int ret) {
ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE"); ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
} }
/* Returns 1 if name looks like an IP address, 0 otherwise.
This is a very rough heuristic as it does not handle IPV6 or things like:
0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
static int looks_like_ip_address(const char *name) {
size_t i;
size_t dot_count = 0;
size_t num_size = 0;
for (i = 0; i < strlen(name); i++) {
if (name[i] >= '0' && name[i] <= '9') {
if (num_size > 3) return 0;
num_size++;
} else if (name[i] == '.') {
if (dot_count > 3 || num_size == 0) return 0;
dot_count++;
num_size = 0;
} else {
return 0;
}
}
if (dot_count < 3 || num_size == 0) return 0;
return 1;
}
/* Gets the subject CN from an X509 cert. */ /* Gets the subject CN from an X509 cert. */
static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8, static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
size_t* utf8_size) { size_t* utf8_size) {
@ -226,10 +250,18 @@ static tsi_result peer_property_from_x509_common_name(
size_t common_name_size; size_t common_name_size;
tsi_result result = tsi_result result =
ssl_get_x509_common_name(cert, &common_name, &common_name_size); ssl_get_x509_common_name(cert, &common_name, &common_name_size);
if (result != TSI_OK) return result; if (result != TSI_OK) {
if (result == TSI_NOT_FOUND) {
common_name = NULL;
common_name_size = 0;
} else {
return result;
}
}
result = tsi_construct_string_peer_property( result = tsi_construct_string_peer_property(
TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, (const char*)common_name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
common_name_size, property); common_name == NULL ? "" : (const char*)common_name, common_name_size,
property);
OPENSSL_free(common_name); OPENSSL_free(common_name);
return result; return result;
} }
@ -1036,9 +1068,22 @@ static void ssl_server_handshaker_factory_destroy(
static int does_entry_match_name(const char* entry, size_t entry_length, static int does_entry_match_name(const char* entry, size_t entry_length,
const char* name) { const char* name) {
const char *dot;
const char* name_subdomain = NULL; const char* name_subdomain = NULL;
size_t name_length = strlen(name);
size_t name_subdomain_length;
if (entry_length == 0) return 0; if (entry_length == 0) return 0;
if (!strncmp(name, entry, entry_length) && (strlen(name) == entry_length)) {
/* Take care of '.' terminations. */
if (name[name_length - 1] == '.') {
name_length--;
}
if (entry[entry_length - 1] == '.') {
entry_length--;
if (entry_length == 0) return 0;
}
if ((name_length == entry_length) && !strncmp(name, entry, entry_length)) {
return 1; /* Perfect match. */ return 1; /* Perfect match. */
} }
if (entry[0] != '*') return 0; if (entry[0] != '*') return 0;
@ -1049,18 +1094,29 @@ static int does_entry_match_name(const char* entry, size_t entry_length,
return 0; return 0;
} }
name_subdomain = strchr(name, '.'); name_subdomain = strchr(name, '.');
if (name_subdomain == NULL || strlen(name_subdomain) < 2) return 0; if (name_subdomain == NULL) return 0;
name_subdomain_length = strlen(name_subdomain);
if (name_subdomain_length < 2) return 0;
name_subdomain++; /* Starts after the dot. */ name_subdomain++; /* Starts after the dot. */
name_subdomain_length--;
entry += 2; /* Remove *. */ entry += 2; /* Remove *. */
entry_length -= 2; entry_length -= 2;
return (!strncmp(entry, name_subdomain, entry_length) && dot = strchr(name_subdomain, '.');
(strlen(name_subdomain) == entry_length)); if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
return 0;
}
if (name_subdomain[name_subdomain_length - 1] == '.') {
name_subdomain_length--;
}
return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
!strncmp(entry, name_subdomain, entry_length));
} }
static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap, static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap,
void* arg) { void* arg) {
tsi_ssl_server_handshaker_factory* impl = tsi_ssl_server_handshaker_factory* impl =
(tsi_ssl_server_handshaker_factory*)arg; (tsi_ssl_server_handshaker_factory*)arg;
size_t i = 0; size_t i = 0;
const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (servername == NULL || strlen(servername) == 0) { if (servername == NULL || strlen(servername) == 0) {
@ -1283,17 +1339,13 @@ tsi_result tsi_create_ssl_server_handshaker_factory(
int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) { int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
size_t i = 0; size_t i = 0;
const tsi_peer_property* property = tsi_peer_get_property_by_name( size_t san_count = 0;
peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY); const tsi_peer_property* property = NULL;
if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_STRING) {
gpr_log(GPR_ERROR, "Invalid x509 subject common name property.");
return 0;
}
if (does_entry_match_name(property->value.string.data,
property->value.string.length, name)) {
return 1;
}
/* For now reject what looks like an IP address. */
if (looks_like_ip_address(name)) return 0;
/* Check the SAN first. */
property = tsi_peer_get_property_by_name( property = tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_ALTERNATIVE_NAMES_PEER_PROPERTY); peer, TSI_X509_SUBJECT_ALTERNATIVE_NAMES_PEER_PROPERTY);
if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_LIST) { if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_LIST) {
@ -1301,7 +1353,8 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
return 0; return 0;
} }
for (i = 0; i < property->value.list.child_count; i++) { san_count = property->value.list.child_count;
for (i = 0; i < san_count; i++) {
const tsi_peer_property* alt_name_property = const tsi_peer_property* alt_name_property =
&property->value.list.children[i]; &property->value.list.children[i];
if (alt_name_property->type != TSI_PEER_PROPERTY_TYPE_STRING) { if (alt_name_property->type != TSI_PEER_PROPERTY_TYPE_STRING) {
@ -1313,5 +1366,20 @@ int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
return 1; return 1;
} }
} }
/* If there's no SAN, try the CN. */
if (san_count == 0) {
property = tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
if (property == NULL || property->type != TSI_PEER_PROPERTY_TYPE_STRING) {
gpr_log(GPR_ERROR, "Invalid x509 subject common name property.");
return 0;
}
if (does_entry_match_name(property->value.string.data,
property->value.string.length, name)) {
return 1;
}
}
return 0; /* Not found. */ return 0; /* Not found. */
} }

@ -158,7 +158,12 @@ tsi_result tsi_ssl_handshaker_factory_create_handshaker(
while handshakers created with this factory are still in use. */ while handshakers created with this factory are still in use. */
void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory* self); void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory* self);
/* Util that checks that an ssl peer matches a specific name. */ /* Util that checks that an ssl peer matches a specific name.
Still TODO(jboeuf):
- handle mixed case.
- handle %encoded chars.
- handle public suffix wildchar more strictly (e.g. *.co.uk)
- handle IP addresses in SAN. */
int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name); int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name);
#ifdef __cplusplus #ifdef __cplusplus

@ -101,15 +101,8 @@ namespace Grpc.Core.Tests
using (Channel channel = new Channel(host + ":" + port)) using (Channel channel = new Channel(host + ":" + port))
{ {
var call = new Call<string, string>(unaryEchoStringMethod, channel); var call = new Call<string, string>(unaryEchoStringMethod, channel);
BenchmarkUtil.RunBenchmark(100, 1000,
var stopwatch = new Stopwatch(); () => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); });
stopwatch.Start();
for (int i = 0; i < 1000; i++)
{
Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken));
}
stopwatch.Stop();
Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms");
} }
server.ShutdownAsync().Wait(); server.ShutdownAsync().Wait();

@ -41,6 +41,7 @@
<Compile Include="ServerTest.cs" /> <Compile Include="ServerTest.cs" />
<Compile Include="GrpcEnvironmentTest.cs" /> <Compile Include="GrpcEnvironmentTest.cs" />
<Compile Include="TimespecTest.cs" /> <Compile Include="TimespecTest.cs" />
<Compile Include="PInvokeTest.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>

@ -41,14 +41,16 @@ namespace Grpc.Core.Tests
public class GrpcEnvironmentTest public class GrpcEnvironmentTest
{ {
[Test] [Test]
public void InitializeAndShutdownGrpcEnvironment() { public void InitializeAndShutdownGrpcEnvironment()
{
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
Assert.IsNotNull(GrpcEnvironment.ThreadPool.CompletionQueue); Assert.IsNotNull(GrpcEnvironment.ThreadPool.CompletionQueue);
GrpcEnvironment.Shutdown(); GrpcEnvironment.Shutdown();
} }
[Test] [Test]
public void SubsequentInvocations() { public void SubsequentInvocations()
{
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
GrpcEnvironment.Shutdown(); GrpcEnvironment.Shutdown();
@ -56,7 +58,8 @@ namespace Grpc.Core.Tests
} }
[Test] [Test]
public void InitializeAfterShutdown() { public void InitializeAfterShutdown()
{
GrpcEnvironment.Initialize(); GrpcEnvironment.Initialize();
var tp1 = GrpcEnvironment.ThreadPool; var tp1 = GrpcEnvironment.ThreadPool;
GrpcEnvironment.Shutdown(); GrpcEnvironment.Shutdown();

@ -0,0 +1,145 @@
#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.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
using System.Runtime.InteropServices;
namespace Grpc.Core.Tests
{
public class PInvokeTest
{
int counter;
[DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
[DllImport("grpc_csharp_ext.dll")]
static extern IntPtr grpcsharp_test_nop(IntPtr ptr);
[TestFixtureSetUp]
public void Init()
{
GrpcEnvironment.Initialize();
}
[TestFixtureTearDown]
public void Cleanup()
{
GrpcEnvironment.Shutdown();
}
/// <summary>
/// (~1.26us .NET Windows)
/// </summary>
[Test]
public void CompletionQueueCreateDestroyBenchmark()
{
BenchmarkUtil.RunBenchmark(
100000, 1000000,
() => {
CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create();
cq.Dispose();
}
);
}
/// <summary>
/// Approximate results:
/// (~80ns Mono Linux)
/// (~110ns .NET Windows)
/// </summary>
[Test]
public void NativeCallbackBenchmark()
{
CompletionCallbackDelegate handler = Handler;
counter = 0;
BenchmarkUtil.RunBenchmark(
1000000, 10000000,
() => {
grpcsharp_test_callback(handler);
}
);
Assert.AreNotEqual(0, counter);
}
/// <summary>
/// Creating a new native-to-managed callback has significant overhead
/// compared to using an existing one. We need to be aware of this.
/// (~50us on Mono Linux!!!)
/// (~1.1us on .NET Windows)
/// </summary>
[Test]
public void NewNativeCallbackBenchmark()
{
counter = 0;
BenchmarkUtil.RunBenchmark(
10000, 10000,
() => {
grpcsharp_test_callback(new CompletionCallbackDelegate(Handler));
}
);
Assert.AreNotEqual(0, counter);
}
/// <summary>
/// Tests overhead of a simple PInvoke call.
/// (~46ns .NET Windows)
/// </summary>
[Test]
public void NopPInvokeBenchmark()
{
CompletionCallbackDelegate handler = Handler;
BenchmarkUtil.RunBenchmark(
1000000, 100000000,
() => {
grpcsharp_test_nop(IntPtr.Zero);
}
);
}
private void Handler(GRPCOpError op, IntPtr ptr) {
counter ++;
}
}
}

@ -47,19 +47,8 @@ namespace Grpc.Core
{ {
public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token) public static TResponse BlockingUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)
{ {
//TODO: implement this in real synchronous style. var asyncCall = new AsyncCall<TRequest, TResponse>(call.RequestSerializer, call.ResponseDeserializer);
try { return asyncCall.UnaryCall(call.Channel, call.MethodName, req);
return AsyncUnaryCall(call, req, token).Result;
} catch(AggregateException ae) {
foreach (var e in ae.InnerExceptions)
{
if (e is RpcException)
{
throw e;
}
}
throw;
}
} }
public static async Task<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token) public static async Task<TResponse> AsyncUnaryCall<TRequest, TResponse>(Call<TRequest, TResponse> call, TRequest req, CancellationToken token)

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -33,6 +33,7 @@
<Reference Include="System" /> <Reference Include="System" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Internal\GrpcLog.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcException.cs" /> <Compile Include="RpcException.cs" />
<Compile Include="Calls.cs" /> <Compile Include="Calls.cs" />
@ -62,10 +63,20 @@
<Compile Include="Internal\ClientStreamingInputObserver.cs" /> <Compile Include="Internal\ClientStreamingInputObserver.cs" />
<Compile Include="Internal\ServerStreamingOutputObserver.cs" /> <Compile Include="Internal\ServerStreamingOutputObserver.cs" />
<Compile Include="Internal\BatchContextSafeHandleNotOwned.cs" /> <Compile Include="Internal\BatchContextSafeHandleNotOwned.cs" />
<Compile Include="Utils\BenchmarkUtil.cs" />
<Compile Include="Utils\ExceptionHelper.cs" />
</ItemGroup> </ItemGroup>
<Choose>
<!-- Under Windows, automatically copy the C core library to output dir.
Under Monodevelop it's not supported so it has no effect. -->
<When Condition=" '$(Platform)' == 'AnyCPU' ">
<ItemGroup>
<Content Include="..\..\..\vsprojects\vs2013\Debug\grpc_csharp_ext.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</When>
<Otherwise/>
</Choose>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Folder Include="Internal\" />
<Folder Include="Utils\" />
</ItemGroup>
</Project> </Project>

@ -107,6 +107,7 @@ namespace Grpc.Core
/// </summary> /// </summary>
private GrpcEnvironment() private GrpcEnvironment()
{ {
GrpcLog.RedirectNativeLogs(Console.Error);
grpcsharp_init(); grpcsharp_init();
threadPool = new GrpcThreadPool(THREAD_POOL_SIZE); threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
threadPool.Start(); threadPool.Start();

@ -38,6 +38,7 @@ using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Grpc.Core.Internal; using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal namespace Grpc.Core.Internal
{ {
@ -112,6 +113,36 @@ namespace Grpc.Core.Internal
InitializeInternal(call, true); InitializeInternal(call, true);
} }
public TRead UnaryCall(Channel channel, String methodName, TWrite msg)
{
using(CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
{
// TODO: handle serialization error...
byte[] payload = serializer(msg);
unaryResponseTcs = new TaskCompletionSource<TRead>();
lock (myLock)
{
Initialize(channel, cq, methodName);
started = true;
halfcloseRequested = true;
readingDone = true;
}
call.BlockingUnary(cq, payload, unaryResponseHandler);
try
{
// Once the blocking call returns, the result should be available synchronously.
return unaryResponseTcs.Task.Result;
}
catch (AggregateException ae)
{
throw ExceptionHelper.UnwrapRpcException(ae);
}
}
}
public Task<TRead> UnaryCallAsync(TWrite msg) public Task<TRead> UnaryCallAsync(TWrite msg)
{ {
lock (myLock) lock (myLock)

@ -62,6 +62,11 @@ namespace Grpc.Core.Internal
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len); byte[] send_buffer, UIntPtr send_buffer_len);
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback,
byte[] send_buffer, UIntPtr send_buffer_len);
[DllImport("grpc_csharp_ext.dll")] [DllImport("grpc_csharp_ext.dll")]
static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call,
[MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback);
@ -113,6 +118,11 @@ namespace Grpc.Core.Internal
AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong) payload.Length))); AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong) payload.Length)));
} }
public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback)
{
grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong) payload.Length));
}
public void StartClientStreaming(CompletionCallbackDelegate callback) public void StartClientStreaming(CompletionCallbackDelegate callback)
{ {
AssertCallOk(grpcsharp_call_start_client_streaming(this, callback)); AssertCallOk(grpcsharp_call_start_client_streaming(this, callback));

@ -0,0 +1,94 @@
#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.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
namespace Grpc.Core.Internal
{
internal delegate void GprLogDelegate(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr);
/// <summary>
/// Logs from gRPC C core library can get lost if your application is not a console app.
/// This class allows redirection of logs to arbitrary destination.
/// </summary>
internal static class GrpcLog
{
static object staticLock = new object();
static GprLogDelegate writeCallback;
static TextWriter dest;
[DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_redirect_log(GprLogDelegate callback);
/// <summary>
/// Sets text writer as destination for logs from native gRPC C core library.
/// Only first invocation has effect.
/// </summary>
/// <param name="textWriter"></param>
public static void RedirectNativeLogs(TextWriter textWriter)
{
lock (staticLock)
{
if (writeCallback == null)
{
writeCallback = new GprLogDelegate(HandleWrite);
dest = textWriter;
grpcsharp_redirect_log(writeCallback);
}
}
}
private static void HandleWrite(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr)
{
try
{
// TODO: DateTime format used here is different than in C core.
dest.WriteLine(string.Format("{0}{1} {2} {3}:{4}: {5}",
Marshal.PtrToStringAnsi(severityStringPtr), DateTime.Now,
threadId,
Marshal.PtrToStringAnsi(fileStringPtr),
line,
Marshal.PtrToStringAnsi(msgPtr)));
}
catch (Exception e)
{
Console.WriteLine("Caught exception in native callback " + e);
}
}
}
}

@ -49,7 +49,8 @@ namespace Grpc.Core
this.status = status; this.status = status;
} }
public Status Status { public Status Status
{
get get
{ {
return status; return status;

@ -111,6 +111,8 @@ namespace Grpc.Core
var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>()); var finishedTask = asyncCall.ServerSideStreamingRequestCallAsync(new NullObserver<byte[]>());
// TODO: this makes the call finish before all reads can be done which causes trouble
// in AsyncCall.HandleReadFinished callback. Revisit this.
asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait(); asyncCall.SendStatusFromServerAsync(new Status(StatusCode.Unimplemented, "No such method.")).Wait();
finishedTask.Wait(); finishedTask.Wait();

@ -0,0 +1,68 @@
#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.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace Grpc.Core.Utils
{
public static class BenchmarkUtil
{
/// <summary>
/// Runs a simple benchmark preceded by warmup phase.
/// </summary>
public static void RunBenchmark(int warmupIterations, int benchmarkIterations, Action action)
{
Console.WriteLine("Warmup iterations: " + warmupIterations);
for (int i = 0; i < warmupIterations; i++)
{
action();
}
Console.WriteLine("Benchmark iterations: " + benchmarkIterations);
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < benchmarkIterations; i++)
{
action();
}
stopwatch.Stop();
Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms");
Console.WriteLine("Ops per second: " + (int) ((double) benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds));
}
}
}

@ -0,0 +1,57 @@
#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;
namespace Grpc.Core.Utils
{
public static class ExceptionHelper
{
/// <summary>
/// If inner exceptions contain RpcException, rethrows it.
/// Otherwise, rethrows the original aggregate exception.
/// Always throws, the exception return type is here only to make the.
/// </summary>
public static Exception UnwrapRpcException(AggregateException ae) {
foreach (var e in ae.InnerExceptions)
{
if (e is RpcException)
{
throw e;
}
}
throw ae;
}
}
}

@ -33,7 +33,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Google.ProtocolBuffers; using Google.ProtocolBuffers;
using Grpc.Core; using Grpc.Core;
using Grpc.Core.Utils; using Grpc.Core.Utils;
@ -128,6 +130,9 @@ namespace Grpc.IntegrationTesting
case "empty_stream": case "empty_stream":
RunEmptyStream(client); RunEmptyStream(client);
break; break;
case "benchmark_empty_unary":
RunBenchmarkEmptyUnary(client);
break;
default: default:
throw new ArgumentException("Unknown test case " + testCase); throw new ArgumentException("Unknown test case " + testCase);
} }
@ -267,6 +272,12 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }
// This is not an official interop test, but it's useful.
private void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client)
{
BenchmarkUtil.RunBenchmark(10000, 10000,
() => { client.EmptyCall(Empty.DefaultInstance);});
}
private Payload CreateZerosPayload(int size) { private Payload CreateZerosPayload(int size) {
return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build(); return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build();

@ -35,9 +35,10 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/slice.h> #include <grpc/support/slice.h>
#include <grpc/support/thd.h>
#include <grpc/grpc.h>
#include <string.h> #include <string.h>
@ -343,6 +344,23 @@ grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback,
return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx); return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
} }
/* Synchronous unary call */
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_call_blocking_unary(grpc_call *call,
grpc_completion_queue *dedicated_cq,
callback_funcptr callback,
const char *send_buffer, size_t send_buffer_len) {
GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer,
send_buffer_len) == GRPC_CALL_OK);
/* TODO: we would like to use pluck, but we don't know the tag */
GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) ==
GRPC_OP_COMPLETE);
grpc_completion_queue_shutdown(dedicated_cq);
GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) ==
GRPC_QUEUE_SHUTDOWN);
}
GPR_EXPORT grpc_call_error GPR_CALLTYPE GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_client_streaming(grpc_call *call, grpcsharp_call_start_client_streaming(grpc_call *call,
callback_funcptr callback) { callback_funcptr callback) {
@ -566,3 +584,32 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
server, &(ctx->server_rpc_new.call), &(ctx->server_rpc_new.call_details), server, &(ctx->server_rpc_new.call), &(ctx->server_rpc_new.call_details),
&(ctx->server_rpc_new.request_metadata), cq, ctx); &(ctx->server_rpc_new.request_metadata), cq, ctx);
} }
/* Logging */
typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line,
gpr_uint64 thd_id,
const char *severity_string,
const char *msg);
static grpcsharp_log_func log_func = NULL;
/* Redirects gpr_log to log_func callback */
static void grpcsharp_log_handler(gpr_log_func_args *args) {
log_func(args->file, args->line, gpr_thd_currentid(),
gpr_log_severity_string(args->severity), args->message);
}
GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
GPR_ASSERT(func);
log_func = func;
gpr_set_log_function(grpcsharp_log_handler);
}
/* For testing */
GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_callback(callback_funcptr callback) {
callback(GRPC_OP_OK, NULL);
}
/* For testing */
GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; }

@ -40,7 +40,7 @@ var server;
var port; var port;
var name_override = 'foo.test.google.com'; var name_override = 'foo.test.google.fr';
describe('Interop tests', function() { describe('Interop tests', function() {
before(function(done) { before(function(done) {

@ -215,7 +215,7 @@ $stub = new grpc\testing\TestServiceClient(
new Grpc\BaseStub( new Grpc\BaseStub(
$server_address, $server_address,
[ [
'grpc.ssl_target_name_override' => 'foo.test.google.com', 'grpc.ssl_target_name_override' => 'foo.test.google.fr',
'credentials' => $credentials 'credentials' => $credentials
])); ]));

@ -47,7 +47,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase{
$this->channel = new Grpc\Channel( $this->channel = new Grpc\Channel(
'localhost:' . $port, 'localhost:' . $port,
[ [
'grpc.ssl_target_name_override' => 'foo.test.google.com', 'grpc.ssl_target_name_override' => 'foo.test.google.fr',
'credentials' => $credentials 'credentials' => $credentials
]); ]);
} }

@ -31,10 +31,9 @@
# pubsub_demo demos accesses the Google PubSub API via its gRPC interface # pubsub_demo demos accesses the Google PubSub API via its gRPC interface
# #
# TODO: update the Usage once the usable auth gem is available # $ GOOGLE_APPLICATION_CREDENTIALS=<path_to_service_account_key_file> \
# $ SSL_CERT_FILE=<path/to/ssl/certs> \ # SSL_CERT_FILE=<path/to/ssl/certs> \
# path/to/pubsub_demo.rb \ # path/to/pubsub_demo.rb \
# --service_account_key_file=<path_to_service_account> \
# [--action=<chosen_demo_action> ] # [--action=<chosen_demo_action> ]
# #
# There are options related to the chosen action, see #parse_args below. # There are options related to the chosen action, see #parse_args below.
@ -49,6 +48,7 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'optparse' require 'optparse'
require 'grpc' require 'grpc'
require 'googleauth'
require 'google/protobuf' require 'google/protobuf'
require 'google/protobuf/empty' require 'google/protobuf/empty'
@ -59,7 +59,9 @@ require 'tech/pubsub/proto/pubsub_services'
def load_prod_cert def load_prod_cert
fail 'could not find a production cert' if ENV['SSL_CERT_FILE'].nil? fail 'could not find a production cert' if ENV['SSL_CERT_FILE'].nil?
p "loading prod certs from #{ENV['SSL_CERT_FILE']}" p "loading prod certs from #{ENV['SSL_CERT_FILE']}"
File.open(ENV['SSL_CERT_FILE']).read File.open(ENV['SSL_CERT_FILE']) do |f|
return f.read
end
end end
# creates a SSL Credentials from the production certificates. # creates a SSL Credentials from the production certificates.
@ -68,14 +70,9 @@ def ssl_creds
end end
# Builds the metadata authentication update proc. # Builds the metadata authentication update proc.
#
# TODO: replace this once the ruby usable auth repo is available.
def auth_proc(opts) def auth_proc(opts)
if GRPC::Auth::GCECredentials.on_gce? auth_creds = Google::Auth.get_application_default(opts.oauth_scope)
return GRPC::Auth::GCECredentials.new.updater_proc return auth_creds.updater_proc
end
fd = StringIO.new(File.read(opts.oauth_key_file))
GRPC::Auth::ServiceAccountCredentials.new(opts.oauth_scope, fd).updater_proc
end end
# Creates a stub for accessing the publisher service. # Creates a stub for accessing the publisher service.
@ -216,14 +213,14 @@ class NamedActions
end end
# Args is used to hold the command line info. # Args is used to hold the command line info.
Args = Struct.new(:host, :oauth_scope, :oauth_key_file, :port, :action, Args = Struct.new(:host, :oauth_scope, :port, :action, :project_id, :topic_name,
:project_id, :topic_name, :sub_name) :sub_name)
# validates the the command line options, returning them as an Arg. # validates the the command line options, returning them as an Arg.
def parse_args def parse_args
args = Args.new('pubsub-staging.googleapis.com', args = Args.new('pubsub-staging.googleapis.com',
'https://www.googleapis.com/auth/pubsub', 'https://www.googleapis.com/auth/pubsub',
nil, 443, 'list_some_topics', 'stoked-keyword-656') 443, 'list_some_topics', 'stoked-keyword-656')
OptionParser.new do |opts| OptionParser.new do |opts|
opts.on('--oauth_scope scope', opts.on('--oauth_scope scope',
'Scope for OAuth tokens') { |v| args['oauth_scope'] = v } 'Scope for OAuth tokens') { |v| args['oauth_scope'] = v }
@ -233,10 +230,6 @@ def parse_args
opts.on('--server_port SERVER_PORT', 'server port') do |v| opts.on('--server_port SERVER_PORT', 'server port') do |v|
args.port = v args.port = v
end end
opts.on('--service_account_key_file PATH',
'Path to the service account json key file') do |v|
args.oauth_key_file = v
end
# instance_methods(false) gives only the methods defined in that class. # instance_methods(false) gives only the methods defined in that class.
scenes = NamedActions.instance_methods(false).map { |t| t.to_s } scenes = NamedActions.instance_methods(false).map { |t| t.to_s }
@ -257,15 +250,11 @@ def parse_args
end end
def _check_args(args) def _check_args(args)
%w(host port action).each do |a| %w(host port action oauth_scope).each do |a|
if args[a].nil? if args[a].nil?
raise OptionParser::MissingArgument.new("please specify --#{a}") raise OptionParser::MissingArgument.new("please specify --#{a}")
end end
end end
if args['oauth_key_file'].nil? || args['oauth_scope'].nil?
fail(OptionParser::MissingArgument,
'please specify both of --service_account_key_file and --oauth_scope')
end
args args
end end

@ -48,6 +48,7 @@ require 'minitest'
require 'minitest/assertions' require 'minitest/assertions'
require 'grpc' require 'grpc'
require 'googleauth'
require 'google/protobuf' require 'google/protobuf'
require 'test/cpp/interop/test_services' require 'test/cpp/interop/test_services'
@ -56,7 +57,7 @@ require 'test/cpp/interop/empty'
require 'signet/ssl_config' require 'signet/ssl_config'
include GRPC::Auth AUTH_ENV = Google::Auth::ServiceAccountCredentials::ENV_VAR
# loads the certificates used to access the test server securely. # loads the certificates used to access the test server securely.
def load_test_certs def load_test_certs
@ -101,22 +102,14 @@ def create_stub(opts)
} }
# Add service account creds if specified # Add service account creds if specified
if %w(all service_account_creds).include?(opts.test_case) wants_creds = %w(all compute_engine_creds service_account_creds)
if wants_creds.include?(opts.test_case)
unless opts.oauth_scope.nil? unless opts.oauth_scope.nil?
fd = StringIO.new(File.read(opts.oauth_key_file)) auth_creds = Google::Auth.get_application_default(opts.oauth_scope)
logger.info("loading oauth certs from #{opts.oauth_key_file}")
auth_creds = ServiceAccountCredentials.new(opts.oauth_scope, fd)
stub_opts[:update_metadata] = auth_creds.updater_proc stub_opts[:update_metadata] = auth_creds.updater_proc
end end
end end
# Add compute engine creds if specified
if %w(all compute_engine_creds).include?(opts.test_case)
unless opts.oauth_scope.nil?
stub_opts[:update_metadata] = GCECredentials.new.update_proc
end
end
logger.info("... connecting securely to #{address}") logger.info("... connecting securely to #{address}")
Grpc::Testing::TestService::Stub.new(address, **stub_opts) Grpc::Testing::TestService::Stub.new(address, **stub_opts)
else else
@ -193,11 +186,11 @@ class NamedTests
def service_account_creds def service_account_creds
# ignore this test if the oauth options are not set # ignore this test if the oauth options are not set
if @args.oauth_scope.nil? || @args.oauth_key_file.nil? if @args.oauth_scope.nil?
p 'NOT RUN: service_account_creds; no service_account settings' p 'NOT RUN: service_account_creds; no service_account settings'
return return
end end
json_key = File.read(@args.oauth_key_file) json_key = File.read(ENV[AUTH_ENV])
wanted_email = MultiJson.load(json_key)['client_email'] wanted_email = MultiJson.load(json_key)['client_email']
resp = perform_large_unary(fill_username: true, resp = perform_large_unary(fill_username: true,
fill_oauth_scope: true) fill_oauth_scope: true)
@ -285,13 +278,13 @@ end
# Args is used to hold the command line info. # Args is used to hold the command line info.
Args = Struct.new(:default_service_account, :host, :host_override, Args = Struct.new(:default_service_account, :host, :host_override,
:oauth_scope, :oauth_key_file, :port, :secure, :test_case, :oauth_scope, :port, :secure, :test_case,
:use_test_ca) :use_test_ca)
# validates the the command line options, returning them as a Hash. # validates the the command line options, returning them as a Hash.
def parse_args def parse_args
args = Args.new args = Args.new
args.host_override = 'foo.test.google.com' args.host_override = 'foo.test.google.fr'
OptionParser.new do |opts| OptionParser.new do |opts|
opts.on('--oauth_scope scope', opts.on('--oauth_scope scope',
'Scope for OAuth tokens') { |v| args['oauth_scope'] = v } 'Scope for OAuth tokens') { |v| args['oauth_scope'] = v }
@ -302,10 +295,6 @@ def parse_args
'email address of the default service account') do |v| 'email address of the default service account') do |v|
args['default_service_account'] = v args['default_service_account'] = v
end end
opts.on('--service_account_key_file PATH',
'Path to the service account json key file') do |v|
args['oauth_key_file'] = v
end
opts.on('--server_host_override HOST_OVERRIDE', opts.on('--server_host_override HOST_OVERRIDE',
'override host via a HTTP header') do |v| 'override host via a HTTP header') do |v|
args['host_override'] = v args['host_override'] = v
@ -333,10 +322,6 @@ def _check_args(args)
fail(OptionParser::MissingArgument, "please specify --#{arg}") fail(OptionParser::MissingArgument, "please specify --#{arg}")
end end
end end
if args['oauth_key_file'].nil? ^ args['oauth_scope'].nil?
fail(OptionParser::MissingArgument,
'please specify both of --service_account_key_file and --oauth_scope')
end
args args
end end

@ -127,7 +127,7 @@ def main
if options['secure'] if options['secure']
stub_opts = { stub_opts = {
:creds => test_creds, :creds => test_creds,
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com' GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr'
} }
p stub_opts p stub_opts
p options['host'] p options['host']

@ -89,7 +89,7 @@ def main
if options['secure'] if options['secure']
stub_opts = { stub_opts = {
:creds => test_creds, :creds => test_creds,
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com' GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr'
} }
p stub_opts p stub_opts
p options['host'] p options['host']

@ -22,6 +22,7 @@ Gem::Specification.new do |s|
s.add_dependency 'faraday', '~> 0.9' s.add_dependency 'faraday', '~> 0.9'
s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1' s.add_dependency 'google-protobuf', '~> 3.0.0alpha.1.1'
s.add_dependency 'googleauth', '~> 0.1'
s.add_dependency 'logging', '~> 1.8' s.add_dependency 'logging', '~> 1.8'
s.add_dependency 'jwt', '~> 1.2.1' s.add_dependency 'jwt', '~> 1.2.1'
s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests s.add_dependency 'minitest', '~> 5.4' # reqd for interop tests

@ -27,8 +27,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
require 'grpc/auth/compute_engine.rb'
require 'grpc/auth/service_account.rb'
require 'grpc/errors' require 'grpc/errors'
require 'grpc/grpc' require 'grpc/grpc'
require 'grpc/logconfig' require 'grpc/logconfig'

@ -1,67 +0,0 @@
# 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.
require 'faraday'
require 'grpc/auth/signet'
module GRPC
# Module Auth provides classes that provide Google-specific authentication
# used to access Google gRPC services.
module Auth
# Extends Signet::OAuth2::Client so that the auth token is obtained from
# the GCE metadata server.
class GCECredentials < Signet::OAuth2::Client
COMPUTE_AUTH_TOKEN_URI = 'http://metadata/computeMetadata/v1/'\
'instance/service-accounts/default/token'
COMPUTE_CHECK_URI = 'http://metadata.google.internal'
# Detect if this appear to be a GCE instance, by checking if metadata
# is available
def self.on_gce?(options = {})
c = options[:connection] || Faraday.default_connection
resp = c.get(COMPUTE_CHECK_URI)
return false unless resp.status == 200
return false unless resp.headers.key?('Metadata-Flavor')
return resp.headers['Metadata-Flavor'] == 'Google'
rescue Faraday::ConnectionFailed
return false
end
# Overrides the super class method to change how access tokens are
# fetched.
def fetch_access_token(options = {})
c = options[:connection] || Faraday.default_connection
c.headers = { 'Metadata-Flavor' => 'Google' }
resp = c.get(COMPUTE_AUTH_TOKEN_URI)
Signet::OAuth2.parse_credentials(resp.body,
resp.headers['content-type'])
end
end
end
end

@ -1,66 +0,0 @@
# 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.
require 'grpc/auth/signet'
require 'multi_json'
require 'openssl'
# Reads the private key and client email fields from service account JSON key.
def read_json_key(json_key_io)
json_key = MultiJson.load(json_key_io.read)
fail 'missing client_email' unless json_key.key?('client_email')
fail 'missing private_key' unless json_key.key?('private_key')
[json_key['private_key'], json_key['client_email']]
end
module GRPC
# Module Auth provides classes that provide Google-specific authentication
# used to access Google gRPC services.
module Auth
# Authenticates requests using Google's Service Account credentials.
# (cf https://developers.google.com/accounts/docs/OAuth2ServiceAccount)
class ServiceAccountCredentials < Signet::OAuth2::Client
TOKEN_CRED_URI = 'https://www.googleapis.com/oauth2/v3/token'
AUDIENCE = TOKEN_CRED_URI
# Initializes a ServiceAccountCredentials.
#
# @param scope [string|array] the scope(s) to access
# @param json_key_io [IO] an IO from which the JSON key can be read
def initialize(scope, json_key_io)
private_key, client_email = read_json_key(json_key_io)
super(token_credential_uri: TOKEN_CRED_URI,
audience: AUDIENCE,
scope: scope,
issuer: client_email,
signing_key: OpenSSL::PKey::RSA.new(private_key))
end
end
end
end

@ -1,67 +0,0 @@
# 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.
require 'signet/oauth_2/client'
module Signet
# Signet::OAuth2 supports OAuth2 authentication.
module OAuth2
AUTH_METADATA_KEY = :Authorization
# Signet::OAuth2::Client creates an OAuth2 client
#
# Here client is re-opened to add the #apply and #apply! methods which
# update a hash map with the fetched authentication token
#
# Eventually, this change may be merged into signet itself, or some other
# package that provides Google-specific auth via signet, and this extension
# will be unnecessary.
class Client
# Updates a_hash updated with the authentication token
def apply!(a_hash, opts = {})
# fetch the access token there is currently not one, or if the client
# has expired
fetch_access_token!(opts) if access_token.nil? || expired?
a_hash[AUTH_METADATA_KEY] = "Bearer #{access_token}"
end
# Returns a clone of a_hash updated with the authentication token
def apply(a_hash, opts = {})
a_copy = a_hash.clone
apply!(a_copy, opts)
a_copy
end
# Returns a reference to the #apply method, suitable for passing as
# a closure
def updater_proc
lambda(&method(:apply))
end
end
end
end

@ -1,163 +0,0 @@
# 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.
spec_dir = File.expand_path(File.join(File.dirname(__FILE__)))
$LOAD_PATH.unshift(spec_dir)
$LOAD_PATH.uniq!
require 'faraday'
require 'spec_helper'
def build_json_response(payload)
[200,
{ 'Content-Type' => 'application/json; charset=utf-8' },
MultiJson.dump(payload)]
end
WANTED_AUTH_KEY = :Authorization
shared_examples 'apply/apply! are OK' do
# tests that use these examples need to define
#
# @client which should be an auth client
#
# @make_auth_stubs, which should stub out the expected http behaviour of the
# auth client
describe '#fetch_access_token' do
it 'should set access_token to the fetched value' do
token = '1/abcdef1234567890'
stubs = make_auth_stubs with_access_token: token
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
@client.fetch_access_token!(connection: c)
expect(@client.access_token).to eq(token)
stubs.verify_stubbed_calls
end
end
describe '#apply!' do
it 'should update the target hash with fetched access token' do
token = '1/abcdef1234567890'
stubs = make_auth_stubs with_access_token: token
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
md = { foo: 'bar' }
@client.apply!(md, connection: c)
want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" }
expect(md).to eq(want)
stubs.verify_stubbed_calls
end
end
describe 'updater_proc' do
it 'should provide a proc that updates a hash with the access token' do
token = '1/abcdef1234567890'
stubs = make_auth_stubs with_access_token: token
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
md = { foo: 'bar' }
the_proc = @client.updater_proc
got = the_proc.call(md, connection: c)
want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" }
expect(got).to eq(want)
stubs.verify_stubbed_calls
end
end
describe '#apply' do
it 'should not update the original hash with the access token' do
token = '1/abcdef1234567890'
stubs = make_auth_stubs with_access_token: token
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
md = { foo: 'bar' }
@client.apply(md, connection: c)
want = { foo: 'bar' }
expect(md).to eq(want)
stubs.verify_stubbed_calls
end
it 'should add the token to the returned hash' do
token = '1/abcdef1234567890'
stubs = make_auth_stubs with_access_token: token
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
md = { foo: 'bar' }
got = @client.apply(md, connection: c)
want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" }
expect(got).to eq(want)
stubs.verify_stubbed_calls
end
it 'should not fetch a new token if the current is not expired' do
token = '1/abcdef1234567890'
stubs = make_auth_stubs with_access_token: token
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
n = 5 # arbitrary
n.times do |_t|
md = { foo: 'bar' }
got = @client.apply(md, connection: c)
want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{token}" }
expect(got).to eq(want)
end
stubs.verify_stubbed_calls
end
it 'should fetch a new token if the current one is expired' do
token_1 = '1/abcdef1234567890'
token_2 = '2/abcdef1234567890'
[token_1, token_2].each do |t|
stubs = make_auth_stubs with_access_token: t
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
md = { foo: 'bar' }
got = @client.apply(md, connection: c)
want = { :foo => 'bar', WANTED_AUTH_KEY => "Bearer #{t}" }
expect(got).to eq(want)
stubs.verify_stubbed_calls
@client.expires_at -= 3601 # default is to expire in 1hr
end
end
end
end

@ -1,108 +0,0 @@
# 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.
spec_dir = File.expand_path(File.join(File.dirname(__FILE__)))
$LOAD_PATH.unshift(spec_dir)
$LOAD_PATH.uniq!
require 'apply_auth_examples'
require 'faraday'
require 'grpc/auth/compute_engine'
require 'spec_helper'
describe GRPC::Auth::GCECredentials do
MD_URI = '/computeMetadata/v1/instance/service-accounts/default/token'
GCECredentials = GRPC::Auth::GCECredentials
before(:example) do
@client = GCECredentials.new
end
def make_auth_stubs(with_access_token: '')
Faraday::Adapter::Test::Stubs.new do |stub|
stub.get(MD_URI) do |env|
headers = env[:request_headers]
expect(headers['Metadata-Flavor']).to eq('Google')
build_json_response(
'access_token' => with_access_token,
'token_type' => 'Bearer',
'expires_in' => 3600)
end
end
end
it_behaves_like 'apply/apply! are OK'
describe '#on_gce?' do
it 'should be true when Metadata-Flavor is Google' do
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
stub.get('/') do |_env|
[200,
{ 'Metadata-Flavor' => 'Google' },
'']
end
end
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
expect(GCECredentials.on_gce?(connection: c)).to eq(true)
stubs.verify_stubbed_calls
end
it 'should be false when Metadata-Flavor is not Google' do
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
stub.get('/') do |_env|
[200,
{ 'Metadata-Flavor' => 'NotGoogle' },
'']
end
end
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
expect(GCECredentials.on_gce?(connection: c)).to eq(false)
stubs.verify_stubbed_calls
end
it 'should be false if the response is not 200' do
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
stub.get('/') do |_env|
[404,
{ 'Metadata-Flavor' => 'Google' },
'']
end
end
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
expect(GCECredentials.on_gce?(connection: c)).to eq(false)
stubs.verify_stubbed_calls
end
end
end

@ -1,75 +0,0 @@
# 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.
spec_dir = File.expand_path(File.join(File.dirname(__FILE__)))
$LOAD_PATH.unshift(spec_dir)
$LOAD_PATH.uniq!
require 'apply_auth_examples'
require 'grpc/auth/service_account'
require 'jwt'
require 'multi_json'
require 'openssl'
require 'spec_helper'
describe GRPC::Auth::ServiceAccountCredentials do
before(:example) do
@key = OpenSSL::PKey::RSA.new(2048)
cred_json = {
private_key_id: 'a_private_key_id',
private_key: @key.to_pem,
client_email: 'app@developer.gserviceaccount.com',
client_id: 'app.apps.googleusercontent.com',
type: 'service_account'
}
cred_json_text = MultiJson.dump(cred_json)
@client = GRPC::Auth::ServiceAccountCredentials.new(
'https://www.googleapis.com/auth/userinfo.profile',
StringIO.new(cred_json_text))
end
def make_auth_stubs(with_access_token: '')
Faraday::Adapter::Test::Stubs.new do |stub|
stub.post('/oauth2/v3/token') do |env|
params = Addressable::URI.form_unencode(env[:body])
_claim, _header = JWT.decode(params.assoc('assertion').last,
@key.public_key)
want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer']
expect(params.assoc('grant_type')).to eq(want)
build_json_response(
'access_token' => with_access_token,
'token_type' => 'Bearer',
'expires_in' => 3600
)
end
end
end
it_behaves_like 'apply/apply! are OK'
end

@ -1,70 +0,0 @@
# 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.
spec_dir = File.expand_path(File.join(File.dirname(__FILE__)))
$LOAD_PATH.unshift(spec_dir)
$LOAD_PATH.uniq!
require 'apply_auth_examples'
require 'grpc/auth/signet'
require 'jwt'
require 'openssl'
require 'spec_helper'
describe Signet::OAuth2::Client do
before(:example) do
@key = OpenSSL::PKey::RSA.new(2048)
@client = Signet::OAuth2::Client.new(
token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
scope: 'https://www.googleapis.com/auth/userinfo.profile',
issuer: 'app@example.com',
audience: 'https://accounts.google.com/o/oauth2/token',
signing_key: @key
)
end
def make_auth_stubs(with_access_token: '')
Faraday::Adapter::Test::Stubs.new do |stub|
stub.post('/o/oauth2/token') do |env|
params = Addressable::URI.form_unencode(env[:body])
_claim, _header = JWT.decode(params.assoc('assertion').last,
@key.public_key)
want = ['grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer']
expect(params.assoc('grant_type')).to eq(want)
build_json_response(
'access_token' => with_access_token,
'token_type' => 'Bearer',
'expires_in' => 3600
)
end
end
end
it_behaves_like 'apply/apply! are OK'
end

@ -353,7 +353,7 @@ describe 'the secure http client/server' do
@server = GRPC::Core::Server.new(@server_queue, nil, server_creds) @server = GRPC::Core::Server.new(@server_queue, nil, server_creds)
server_port = @server.add_http2_port(server_host, true) server_port = @server.add_http2_port(server_host, true)
@server.start @server.start
args = { Channel::SSL_TARGET => 'foo.test.google.com' } args = { Channel::SSL_TARGET => 'foo.test.google.fr' }
@ch = Channel.new("0.0.0.0:#{server_port}", args, @ch = Channel.new("0.0.0.0:#{server_port}", args,
GRPC::Core::Credentials.new(certs[0], nil, nil)) GRPC::Core::Credentials.new(certs[0], nil, nil))
end end

@ -116,7 +116,7 @@ describe 'ClientStub' do
host = FAKE_HOST host = FAKE_HOST
blk = proc do blk = proc do
opts = { opts = {
GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com', GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr',
a_channel_arg: 'an_arg', a_channel_arg: 'an_arg',
creds: GRPC::Core::Credentials.new(certs[0], nil, nil) creds: GRPC::Core::Credentials.new(certs[0], nil, nil)
} }

@ -40,8 +40,24 @@ import unittest
from grpc.framework.face import exceptions from grpc.framework.face import exceptions
from grpc.framework.foundation import future from grpc.framework.foundation import future
# Identifiers of entities we expect to find in the generated module.
SERVICER_IDENTIFIER = 'EarlyAdopterTestServiceServicer'
SERVER_IDENTIFIER = 'EarlyAdopterTestServiceServer'
STUB_IDENTIFIER = 'EarlyAdopterTestServiceStub'
SERVER_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_server'
STUB_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_stub'
# Timeouts and delays.
SHORT_TIMEOUT = 0.1
NORMAL_TIMEOUT = 1
LONG_TIMEOUT = 2
DOES_NOT_MATTER_DELAY = 0
NO_DELAY = 0
LONG_DELAY = 1
# Assigned in __main__. # Assigned in __main__.
_build_mode = None _build_mode = None
_port = None
class _ServicerMethods(object): class _ServicerMethods(object):
@ -71,14 +87,14 @@ class _ServicerMethods(object):
while self._paused: while self._paused:
time.sleep(0) time.sleep(0)
def UnaryCall(self, request): def UnaryCall(self, request, context):
response = self.test_pb2.SimpleResponse() response = self.test_pb2.SimpleResponse()
response.payload.payload_type = self.test_pb2.COMPRESSABLE response.payload.payload_type = self.test_pb2.COMPRESSABLE
response.payload.payload_compressable = 'a' * request.response_size response.payload.payload_compressable = 'a' * request.response_size
self._control() self._control()
return response return response
def StreamingOutputCall(self, request): def StreamingOutputCall(self, request, context):
for parameter in request.response_parameters: for parameter in request.response_parameters:
response = self.test_pb2.StreamingOutputCallResponse() response = self.test_pb2.StreamingOutputCallResponse()
response.payload.payload_type = self.test_pb2.COMPRESSABLE response.payload.payload_type = self.test_pb2.COMPRESSABLE
@ -86,7 +102,7 @@ class _ServicerMethods(object):
self._control() self._control()
yield response yield response
def StreamingInputCall(self, request_iter): def StreamingInputCall(self, request_iter, context):
response = self.test_pb2.StreamingInputCallResponse() response = self.test_pb2.StreamingInputCallResponse()
aggregated_payload_size = 0 aggregated_payload_size = 0
for request in request_iter: for request in request_iter:
@ -95,7 +111,7 @@ class _ServicerMethods(object):
self._control() self._control()
return response return response
def FullDuplexCall(self, request_iter): def FullDuplexCall(self, request_iter, context):
for request in request_iter: for request in request_iter:
for parameter in request.response_parameters: for parameter in request.response_parameters:
response = self.test_pb2.StreamingOutputCallResponse() response = self.test_pb2.StreamingOutputCallResponse()
@ -104,7 +120,7 @@ class _ServicerMethods(object):
self._control() self._control()
yield response yield response
def HalfDuplexCall(self, request_iter): def HalfDuplexCall(self, request_iter, context):
responses = [] responses = []
for request in request_iter: for request in request_iter:
for parameter in request.response_parameters: for parameter in request.response_parameters:
@ -117,7 +133,7 @@ class _ServicerMethods(object):
yield response yield response
def CreateService(test_pb2, delay=0, timeout=1): def _CreateService(test_pb2, delay):
"""Provides a servicer backend and a stub. """Provides a servicer backend and a stub.
The servicer is just the implementation The servicer is just the implementation
@ -136,28 +152,30 @@ def CreateService(test_pb2, delay=0, timeout=1):
A two-tuple (servicer, stub), where the servicer is the back-end of the A two-tuple (servicer, stub), where the servicer is the back-end of the
service bound to the stub. service bound to the stub.
""" """
class Servicer(test_pb2.TestServiceServicer): servicer_methods = _ServicerMethods(test_pb2, delay)
def UnaryCall(self, request): class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)):
return servicer_methods.UnaryCall(request)
def StreamingOutputCall(self, request): def UnaryCall(self, request, context):
return servicer_methods.StreamingOutputCall(request) return servicer_methods.UnaryCall(request, context)
def StreamingInputCall(self, request_iter): def StreamingOutputCall(self, request, context):
return servicer_methods.StreamingInputCall(request_iter) return servicer_methods.StreamingOutputCall(request, context)
def FullDuplexCall(self, request_iter): def StreamingInputCall(self, request_iter, context):
return servicer_methods.FullDuplexCall(request_iter) return servicer_methods.StreamingInputCall(request_iter, context)
def HalfDuplexCall(self, request_iter): def FullDuplexCall(self, request_iter, context):
return servicer_methods.HalfDuplexCall(request_iter) return servicer_methods.FullDuplexCall(request_iter, context)
def HalfDuplexCall(self, request_iter, context):
return servicer_methods.HalfDuplexCall(request_iter, context)
servicer_methods = _ServicerMethods(test_pb2, delay)
servicer = Servicer() servicer = Servicer()
linked_pair = test_pb2.mock_TestService(servicer, timeout) server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer, _port,
stub = linked_pair.stub None, None)
return servicer_methods, stub stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)('localhost', _port)
return servicer_methods, stub, server
def StreamingInputRequest(test_pb2): def StreamingInputRequest(test_pb2):
@ -198,19 +216,20 @@ class PythonPluginTest(unittest.TestCase):
def setUp(self): def setUp(self):
protoc_command = '../../bins/%s/protobuf/protoc' % _build_mode protoc_command = '../../bins/%s/protobuf/protoc' % _build_mode
protoc_plugin_filename = '../../bins/%s/grpc_python_plugin' % _build_mode protoc_plugin_filename = '../../bins/%s/grpc_python_plugin' % _build_mode
test_proto_filename = '../cpp/interop/test.proto' test_proto_filename = './test.proto'
if not os.path.isfile(protoc_command): if not os.path.isfile(protoc_command):
# Assume that if we haven't built protoc that it's on the system. # Assume that if we haven't built protoc that it's on the system.
protoc_command = 'protoc' protoc_command = 'protoc'
# ensure that the output directory exists # Ensure that the output directory exists.
outdir = '../../gens/test/compiler/python/' outdir = '../../gens/test/compiler/python'
try: try:
os.makedirs(outdir) os.makedirs(outdir)
except OSError as exception: except OSError as exception:
if exception.errno != errno.EEXIST: if exception.errno != errno.EEXIST:
raise raise
# Invoke protoc with the plugin.
cmd = [ cmd = [
protoc_command, protoc_command,
'--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename,
@ -222,215 +241,231 @@ class PythonPluginTest(unittest.TestCase):
subprocess.call(' '.join(cmd), shell=True) subprocess.call(' '.join(cmd), shell=True)
sys.path.append(outdir) sys.path.append(outdir)
self.delay = 1 # seconds # TODO(atash): Figure out which of theses tests is hanging flakily with small
self.timeout = 2 # seconds # probability.
def testImportAttributes(self): def testImportAttributes(self):
# check that we can access the members # check that we can access the generated module and its members.
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
self.assertIsNotNone(getattr(test_pb2, 'TestServiceServicer', None)) self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None))
self.assertIsNotNone(getattr(test_pb2, 'TestServiceService', None)) self.assertIsNotNone(getattr(test_pb2, SERVER_IDENTIFIER, None))
self.assertIsNotNone(getattr(test_pb2, 'TestServiceStub', None)) self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None))
self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None))
self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None))
def testUpDown(self):
import test_pb2
servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
request = test_pb2.SimpleRequest(response_size=13)
with server, stub:
pass
def testUnaryCall(self): def testUnaryCall(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, NO_DELAY)
request = test_pb2.SimpleRequest(response_size=13) request = test_pb2.SimpleRequest(response_size=13)
response = stub.UnaryCall(request) with server, stub:
expected_response = servicer.UnaryCall(request) response = stub.UnaryCall(request, NORMAL_TIMEOUT)
expected_response = servicer.UnaryCall(request, None)
self.assertEqual(expected_response, response) self.assertEqual(expected_response, response)
def testUnaryCallAsync(self): def testUnaryCallAsync(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService( servicer, stub, server = _CreateService(test_pb2, LONG_DELAY)
test_pb2, delay=self.delay, timeout=self.timeout)
request = test_pb2.SimpleRequest(response_size=13) request = test_pb2.SimpleRequest(response_size=13)
# TODO(atash): consider using the 'profile' module? Does it even work here? with server, stub:
start_time = time.clock() start_time = time.clock()
response_future = stub.UnaryCall.async(request) response_future = stub.UnaryCall.async(request, LONG_TIMEOUT)
self.assertGreater(self.delay, time.clock() - start_time) # Check that we didn't block on the asynchronous call.
response = response_future.result() self.assertGreater(LONG_DELAY, time.clock() - start_time)
expected_response = servicer.UnaryCall(request) response = response_future.result()
expected_response = servicer.UnaryCall(request, None)
self.assertEqual(expected_response, response) self.assertEqual(expected_response, response)
def testUnaryCallAsyncExpired(self): def testUnaryCallAsyncExpired(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
# set the timeout super low... # set the timeout super low...
servicer, stub = CreateService(test_pb2, delay=1, timeout=0.1) servicer, stub, server = _CreateService(test_pb2,
delay=DOES_NOT_MATTER_DELAY)
request = test_pb2.SimpleRequest(response_size=13) request = test_pb2.SimpleRequest(response_size=13)
with servicer.pause(): with server, stub:
response_future = stub.UnaryCall.async(request) with servicer.pause():
with self.assertRaises(exceptions.ExpirationError): response_future = stub.UnaryCall.async(request, SHORT_TIMEOUT)
response_future.result() with self.assertRaises(exceptions.ExpirationError):
response_future.result()
def testUnaryCallAsyncCancelled(self): def testUnaryCallAsyncCancelled(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
request = test_pb2.SimpleRequest(response_size=13) request = test_pb2.SimpleRequest(response_size=13)
with servicer.pause(): with server, stub:
response_future = stub.UnaryCall.async(request) with servicer.pause():
response_future.cancel() response_future = stub.UnaryCall.async(request, 1)
self.assertTrue(response_future.cancelled()) response_future.cancel()
self.assertTrue(response_future.cancelled())
def testUnaryCallAsyncFailed(self): def testUnaryCallAsyncFailed(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
request = test_pb2.SimpleRequest(response_size=13) request = test_pb2.SimpleRequest(response_size=13)
with servicer.fail(): with server, stub:
response_future = stub.UnaryCall.async(request) with servicer.fail():
self.assertIsNotNone(response_future.exception()) response_future = stub.UnaryCall.async(request, NORMAL_TIMEOUT)
self.assertIsNotNone(response_future.exception())
def testStreamingOutputCall(self): def testStreamingOutputCall(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, NO_DELAY)
request = StreamingOutputRequest(test_pb2) request = StreamingOutputRequest(test_pb2)
responses = stub.StreamingOutputCall(request) with server, stub:
expected_responses = servicer.StreamingOutputCall(request) responses = stub.StreamingOutputCall(request, NORMAL_TIMEOUT)
for check in itertools.izip_longest(expected_responses, responses): expected_responses = servicer.StreamingOutputCall(request, None)
expected_response, response = check for check in itertools.izip_longest(expected_responses, responses):
self.assertEqual(expected_response, response) expected_response, response = check
self.assertEqual(expected_response, response)
def testStreamingOutputCallAsync(self):
import test_pb2 # pylint: disable=g-import-not-at-top def testStreamingOutputCallExpired(self):
servicer, stub = CreateService(test_pb2, timeout=self.timeout)
request = StreamingOutputRequest(test_pb2)
responses = stub.StreamingOutputCall.async(request)
expected_responses = servicer.StreamingOutputCall(request)
for check in itertools.izip_longest(expected_responses, responses):
expected_response, response = check
self.assertEqual(expected_response, response)
def testStreamingOutputCallAsyncExpired(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2, timeout=0.1) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
request = StreamingOutputRequest(test_pb2) request = StreamingOutputRequest(test_pb2)
with servicer.pause(): with server, stub:
responses = stub.StreamingOutputCall.async(request) with servicer.pause():
with self.assertRaises(exceptions.ExpirationError): responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT)
list(responses) with self.assertRaises(exceptions.ExpirationError):
list(responses)
def testStreamingOutputCallAsyncCancelled(self): def testStreamingOutputCallCancelled(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
_, stub = CreateService(test_pb2, timeout=0.1) unused_servicer, stub, server = _CreateService(test_pb2,
DOES_NOT_MATTER_DELAY)
request = StreamingOutputRequest(test_pb2) request = StreamingOutputRequest(test_pb2)
responses = stub.StreamingOutputCall.async(request) with server, stub:
next(responses) responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT)
responses.cancel()
with self.assertRaises(future.CancelledError):
next(responses) next(responses)
responses.cancel()
with self.assertRaises(future.CancelledError):
next(responses)
def testStreamingOutputCallAsyncFailed(self): @unittest.skip('TODO(atash,nathaniel): figure out why this times out '
'instead of raising the proper error.')
def testStreamingOutputCallFailed(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2, timeout=0.1) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
request = StreamingOutputRequest(test_pb2) request = StreamingOutputRequest(test_pb2)
with servicer.fail(): with server, stub:
responses = stub.StreamingOutputCall.async(request) with servicer.fail():
self.assertIsNotNone(responses) responses = stub.StreamingOutputCall(request, 1)
with self.assertRaises(exceptions.ServicerError): self.assertIsNotNone(responses)
next(responses) with self.assertRaises(exceptions.ServicerError):
next(responses)
def testStreamingInputCall(self): def testStreamingInputCall(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, NO_DELAY)
response = stub.StreamingInputCall(StreamingInputRequest(test_pb2)) with server, stub:
response = stub.StreamingInputCall(StreamingInputRequest(test_pb2),
NORMAL_TIMEOUT)
expected_response = servicer.StreamingInputCall( expected_response = servicer.StreamingInputCall(
StreamingInputRequest(test_pb2)) StreamingInputRequest(test_pb2), None)
self.assertEqual(expected_response, response) self.assertEqual(expected_response, response)
def testStreamingInputCallAsync(self): def testStreamingInputCallAsync(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService( servicer, stub, server = _CreateService(
test_pb2, delay=self.delay, timeout=self.timeout) test_pb2, LONG_DELAY)
start_time = time.clock() with server, stub:
response_future = stub.StreamingInputCall.async( start_time = time.clock()
StreamingInputRequest(test_pb2)) response_future = stub.StreamingInputCall.async(
self.assertGreater(self.delay, time.clock() - start_time) StreamingInputRequest(test_pb2), LONG_TIMEOUT)
response = response_future.result() self.assertGreater(LONG_DELAY, time.clock() - start_time)
response = response_future.result()
expected_response = servicer.StreamingInputCall( expected_response = servicer.StreamingInputCall(
StreamingInputRequest(test_pb2)) StreamingInputRequest(test_pb2), None)
self.assertEqual(expected_response, response) self.assertEqual(expected_response, response)
def testStreamingInputCallAsyncExpired(self): def testStreamingInputCallAsyncExpired(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
# set the timeout super low... # set the timeout super low...
servicer, stub = CreateService(test_pb2, delay=1, timeout=0.1) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
with servicer.pause(): with server, stub:
response_future = stub.StreamingInputCall.async( with servicer.pause():
StreamingInputRequest(test_pb2)) response_future = stub.StreamingInputCall.async(
with self.assertRaises(exceptions.ExpirationError): StreamingInputRequest(test_pb2), SHORT_TIMEOUT)
response_future.result() with self.assertRaises(exceptions.ExpirationError):
self.assertIsInstance( response_future.result()
response_future.exception(), exceptions.ExpirationError) self.assertIsInstance(
response_future.exception(), exceptions.ExpirationError)
def testStreamingInputCallAsyncCancelled(self): def testStreamingInputCallAsyncCancelled(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
with servicer.pause(): with server, stub:
response_future = stub.StreamingInputCall.async( with servicer.pause():
StreamingInputRequest(test_pb2)) response_future = stub.StreamingInputCall.async(
response_future.cancel() StreamingInputRequest(test_pb2), NORMAL_TIMEOUT)
self.assertTrue(response_future.cancelled()) response_future.cancel()
with self.assertRaises(future.CancelledError): self.assertTrue(response_future.cancelled())
response_future.result() with self.assertRaises(future.CancelledError):
response_future.result()
def testStreamingInputCallAsyncFailed(self): def testStreamingInputCallAsyncFailed(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
with servicer.fail(): with server, stub:
response_future = stub.StreamingInputCall.async( with servicer.fail():
StreamingInputRequest(test_pb2)) response_future = stub.StreamingInputCall.async(
self.assertIsNotNone(response_future.exception()) StreamingInputRequest(test_pb2), SHORT_TIMEOUT)
self.assertIsNotNone(response_future.exception())
def testFullDuplexCall(self): def testFullDuplexCall(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, NO_DELAY)
responses = stub.FullDuplexCall(FullDuplexRequest(test_pb2)) with server, stub:
expected_responses = servicer.FullDuplexCall(FullDuplexRequest(test_pb2)) responses = stub.FullDuplexCall(FullDuplexRequest(test_pb2),
for check in itertools.izip_longest(expected_responses, responses): NORMAL_TIMEOUT)
expected_response, response = check expected_responses = servicer.FullDuplexCall(FullDuplexRequest(test_pb2),
self.assertEqual(expected_response, response) None)
for check in itertools.izip_longest(expected_responses, responses):
def testFullDuplexCallAsync(self): expected_response, response = check
self.assertEqual(expected_response, response)
def testFullDuplexCallExpired(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2, timeout=self.timeout) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
responses = stub.FullDuplexCall.async(FullDuplexRequest(test_pb2))
expected_responses = servicer.FullDuplexCall(FullDuplexRequest(test_pb2))
for check in itertools.izip_longest(expected_responses, responses):
expected_response, response = check
self.assertEqual(expected_response, response)
def testFullDuplexCallAsyncExpired(self):
import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2, timeout=0.1)
request = FullDuplexRequest(test_pb2) request = FullDuplexRequest(test_pb2)
with servicer.pause(): with server, stub:
responses = stub.FullDuplexCall.async(request) with servicer.pause():
with self.assertRaises(exceptions.ExpirationError): responses = stub.FullDuplexCall(request, SHORT_TIMEOUT)
list(responses) with self.assertRaises(exceptions.ExpirationError):
list(responses)
def testFullDuplexCallAsyncCancelled(self): def testFullDuplexCallCancelled(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
_, stub = CreateService(test_pb2, timeout=0.1) unused_servicer, stub, server = _CreateService(test_pb2, NO_DELAY)
request = FullDuplexRequest(test_pb2) with server, stub:
responses = stub.FullDuplexCall.async(request) request = FullDuplexRequest(test_pb2)
next(responses) responses = stub.FullDuplexCall(request, NORMAL_TIMEOUT)
responses.cancel()
with self.assertRaises(future.CancelledError):
next(responses) next(responses)
responses.cancel()
with self.assertRaises(future.CancelledError):
next(responses)
def testFullDuplexCallAsyncFailed(self): @unittest.skip('TODO(atash,nathaniel): figure out why this hangs forever '
'and fix.')
def testFullDuplexCallFailed(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2, timeout=0.1) servicer, stub, server = _CreateService(test_pb2, DOES_NOT_MATTER_DELAY)
request = FullDuplexRequest(test_pb2) request = FullDuplexRequest(test_pb2)
with servicer.fail(): with server, stub:
responses = stub.FullDuplexCall.async(request) with servicer.fail():
self.assertIsNotNone(responses) responses = stub.FullDuplexCall(request, NORMAL_TIMEOUT)
with self.assertRaises(exceptions.ServicerError): self.assertIsNotNone(responses)
next(responses) with self.assertRaises(exceptions.ServicerError):
next(responses)
def testHalfDuplexCall(self): def testHalfDuplexCall(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
servicer, stub = CreateService(test_pb2) servicer, stub, server = _CreateService(test_pb2, NO_DELAY)
def HalfDuplexRequest(): def HalfDuplexRequest():
request = test_pb2.StreamingOutputCallRequest() request = test_pb2.StreamingOutputCallRequest()
request.response_parameters.add(size=1, interval_us=0) request.response_parameters.add(size=1, interval_us=0)
@ -439,15 +474,16 @@ class PythonPluginTest(unittest.TestCase):
request.response_parameters.add(size=2, interval_us=0) request.response_parameters.add(size=2, interval_us=0)
request.response_parameters.add(size=3, interval_us=0) request.response_parameters.add(size=3, interval_us=0)
yield request yield request
responses = stub.HalfDuplexCall(HalfDuplexRequest()) with server, stub:
expected_responses = servicer.HalfDuplexCall(HalfDuplexRequest()) responses = stub.HalfDuplexCall(HalfDuplexRequest(), NORMAL_TIMEOUT)
for check in itertools.izip_longest(expected_responses, responses): expected_responses = servicer.HalfDuplexCall(HalfDuplexRequest(), None)
expected_response, response = check for check in itertools.izip_longest(expected_responses, responses):
self.assertEqual(expected_response, response) expected_response, response = check
self.assertEqual(expected_response, response)
def testHalfDuplexCallAsyncWedged(self):
def testHalfDuplexCallWedged(self):
import test_pb2 # pylint: disable=g-import-not-at-top import test_pb2 # pylint: disable=g-import-not-at-top
_, stub = CreateService(test_pb2, timeout=1) _, stub, server = _CreateService(test_pb2, NO_DELAY)
wait_flag = [False] wait_flag = [False]
@contextlib.contextmanager @contextlib.contextmanager
def wait(): # pylint: disable=invalid-name def wait(): # pylint: disable=invalid-name
@ -461,20 +497,25 @@ class PythonPluginTest(unittest.TestCase):
yield request yield request
while wait_flag[0]: while wait_flag[0]:
time.sleep(0.1) time.sleep(0.1)
with wait(): with server, stub:
responses = stub.HalfDuplexCall.async(HalfDuplexRequest()) with wait():
# half-duplex waits for the client to send all info responses = stub.HalfDuplexCall(HalfDuplexRequest(), NORMAL_TIMEOUT)
with self.assertRaises(exceptions.ExpirationError): # half-duplex waits for the client to send all info
next(responses) with self.assertRaises(exceptions.ExpirationError):
next(responses)
if __name__ == '__main__': if __name__ == '__main__':
os.chdir(os.path.dirname(sys.argv[0])) os.chdir(os.path.dirname(sys.argv[0]))
parser = argparse.ArgumentParser(description='Run Python compiler plugin test.') parser = argparse.ArgumentParser(
parser.add_argument('--build_mode', dest='build_mode', type=str, default='dbg', description='Run Python compiler plugin test.')
help='The build mode of the targets to test, e.g. ' parser.add_argument(
'"dbg", "opt", "asan", etc.') '--build_mode', dest='build_mode', type=str, default='dbg',
help='The build mode of the targets to test, e.g. "dbg", "opt", "asan", '
'etc.')
parser.add_argument('--port', dest='port', type=int, default=0)
args, remainder = parser.parse_known_args() args, remainder = parser.parse_known_args()
_build_mode = args.build_mode _build_mode = args.build_mode
_port = args.port
sys.argv[1:] = remainder sys.argv[1:] = remainder
unittest.main() unittest.main()

@ -32,7 +32,8 @@
// This file is duplicated around the code base. See GitHub issue #526. // This file is duplicated around the code base. See GitHub issue #526.
syntax = "proto2"; syntax = "proto2";
package grpc.testing; // TODO(atash): Investigate this statement's utility.
// package grpc.testing;
enum PayloadType { enum PayloadType {
// Compressable text format. // Compressable text format.

@ -112,7 +112,7 @@ void test_connect(const char *server_host, const char *client_host, int port,
} }
/* Send a trivial request. */ /* Send a trivial request. */
c = grpc_channel_create_call_old(client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -126,7 +126,7 @@ void test_connect(const char *server_host, const char *client_host, int port,
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -105,7 +105,7 @@ static void chttp2_init_client_simple_ssl_secure_fullstack(
grpc_ssl_credentials_create(NULL, NULL); grpc_ssl_credentials_create(NULL, NULL);
grpc_arg ssl_name_override = {GRPC_ARG_STRING, grpc_arg ssl_name_override = {GRPC_ARG_STRING,
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
{"foo.test.google.com"}}; {"foo.test.google.fr"}};
grpc_channel_args *new_client_args = grpc_channel_args *new_client_args =
grpc_channel_args_copy_and_add(client_args, &ssl_name_override); grpc_channel_args_copy_and_add(client_args, &ssl_name_override);
chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds); chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);

@ -107,7 +107,7 @@ static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack(
grpc_composite_credentials_create(ssl_creds, oauth2_creds); grpc_composite_credentials_create(ssl_creds, oauth2_creds);
grpc_arg ssl_name_override = {GRPC_ARG_STRING, grpc_arg ssl_name_override = {GRPC_ARG_STRING,
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
{"foo.test.google.com"}}; {"foo.test.google.fr"}};
grpc_channel_args *new_client_args = grpc_channel_args *new_client_args =
grpc_channel_args_copy_and_add(client_args, &ssl_name_override); grpc_channel_args_copy_and_add(client_args, &ssl_name_override);
chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds); chttp2_init_client_secure_fullstack(f, new_client_args, ssl_oauth2_creds);

@ -132,7 +132,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);

@ -113,7 +113,7 @@ static void test_cancel_after_accept_and_writes_closed(
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -122,7 +122,7 @@ static void test_cancel_after_accept_and_writes_closed(
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -113,7 +113,7 @@ static void test_cancel_after_accept_and_writes_closed(
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -121,7 +121,7 @@ static void test_cancel_after_accept_and_writes_closed(
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -113,7 +113,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -121,7 +121,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config,
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -125,7 +125,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
grpc_byte_buffer_create(&request_payload_slice, 1); grpc_byte_buffer_create(&request_payload_slice, 1);
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);

@ -111,7 +111,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config,
gpr_timespec deadline = five_seconds_time(); gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);

@ -123,7 +123,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config, int test_
grpc_byte_buffer_create(&request_payload_slice, 1); grpc_byte_buffer_create(&request_payload_slice, 1);
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c)); GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c));

@ -109,7 +109,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config) {
gpr_timespec deadline = five_seconds_time(); gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);

@ -110,7 +110,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c)); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c));

@ -109,7 +109,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config,
gpr_timespec deadline = five_seconds_time(); gpr_timespec deadline = five_seconds_time();
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);

@ -106,7 +106,7 @@ static void test_body(grpc_end2end_test_fixture f) {
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
tag(1); tag(1);
@ -118,7 +118,7 @@ static void test_body(grpc_end2end_test_fixture f) {
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -106,7 +106,7 @@ static void test_body(grpc_end2end_test_fixture f) {
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
tag(1); tag(1);
@ -118,7 +118,7 @@ static void test_body(grpc_end2end_test_fixture f) {
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -97,7 +97,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f,
grpc_call *s; grpc_call *s;
gpr_timespec deadline = five_seconds_time(); gpr_timespec deadline = five_seconds_time();
c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -110,7 +110,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f,
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -97,7 +97,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f,
grpc_call *s; grpc_call *s;
gpr_timespec deadline = five_seconds_time(); gpr_timespec deadline = five_seconds_time();
c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -109,7 +109,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f,
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -111,7 +111,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -124,7 +124,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -111,7 +111,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -123,7 +123,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -111,7 +111,7 @@ static void empty_batch_body(grpc_end2end_test_fixture f) {
grpc_op *op = NULL; grpc_op *op = NULL;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, op, 0, tag(1))); GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, op, 0, tag(1)));

@ -110,7 +110,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -123,7 +123,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -110,7 +110,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -122,7 +122,7 @@ static void test_early_server_shutdown_finishes_inflight_calls(
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -122,7 +122,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -139,7 +139,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) {
cq_verify_empty(v_client); cq_verify_empty(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -122,7 +122,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -138,7 +138,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) {
request (as this request is very large) */ request (as this request is very large) */
cq_verify_empty(v_client); cq_verify_empty(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -109,7 +109,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -122,7 +122,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==
@ -182,10 +182,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
/* start two requests - ensuring that the second is not accepted until /* start two requests - ensuring that the second is not accepted until
the first completes */ the first completes */
deadline = five_seconds_time(); deadline = five_seconds_time();
c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.com", c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c1); GPR_ASSERT(c1);
c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.com", c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c1); GPR_ASSERT(c1);
@ -211,7 +211,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
cq_expect_server_rpc_new(v_server, &s1, tag(100), cq_expect_server_rpc_new(v_server, &s1, tag(100),
live_call == 300 ? "/alpha" : "/beta", live_call == 300 ? "/alpha" : "/beta",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==
@ -237,7 +237,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200)));
cq_expect_server_rpc_new(v_server, &s2, tag(200), cq_expect_server_rpc_new(v_server, &s2, tag(200),
live_call == 300 ? "/alpha" : "/beta", live_call == 300 ? "/alpha" : "/beta",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -109,7 +109,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -121,7 +121,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
@ -182,10 +182,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
/* start two requests - ensuring that the second is not accepted until /* start two requests - ensuring that the second is not accepted until
the first completes */ the first completes */
deadline = five_seconds_time(); deadline = five_seconds_time();
c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.com", c1 = grpc_channel_create_call_old(f.client, "/alpha", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c1); GPR_ASSERT(c1);
c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.com", c2 = grpc_channel_create_call_old(f.client, "/beta", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c1); GPR_ASSERT(c1);
@ -211,7 +211,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
cq_expect_server_rpc_new(v_server, &s1, tag(100), cq_expect_server_rpc_new(v_server, &s1, tag(100),
live_call == 300 ? "/alpha" : "/beta", live_call == 300 ? "/alpha" : "/beta",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==
@ -237,7 +237,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200)));
cq_expect_server_rpc_new(v_server, &s2, tag(200), cq_expect_server_rpc_new(v_server, &s2, tag(200),
live_call == 300 ? "/alpha" : "/beta", live_call == 300 ? "/alpha" : "/beta",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -118,7 +118,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
gpr_log(GPR_INFO, "testing with %d message pairs.", messages); gpr_log(GPR_INFO, "testing with %d message pairs.", messages);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -128,7 +128,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_server_accept_old(s, f.server_cq, tag(102))); grpc_call_server_accept_old(s, f.server_cq, tag(102)));

@ -118,7 +118,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
gpr_log(GPR_INFO, "testing with %d message pairs.", messages); gpr_log(GPR_INFO, "testing with %d message pairs.", messages);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -127,7 +127,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config,
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -140,7 +140,7 @@ static void test_request_response_with_metadata_and_payload(
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -210,7 +210,7 @@ static void test_request_response_with_metadata_and_payload(
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));

@ -137,7 +137,7 @@ static void test_request_response_with_metadata_and_payload(
gpr_slice_unref(request_payload_slice); gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice); gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -157,7 +157,7 @@ static void test_request_response_with_metadata_and_payload(
cq_verify(v_client); cq_verify(v_client);
cq_expect_server_rpc_new( cq_expect_server_rpc_new(
v_server, &s, tag(100), "/foo", "foo.test.google.com", deadline, "key1-bin", v_server, &s, tag(100), "/foo", "foo.test.google.fr", deadline, "key1-bin",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", "key2-bin", "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc", "key2-bin",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", NULL); "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", NULL);
cq_verify(v_server); cq_verify(v_server);

@ -133,7 +133,7 @@ static void test_request_response_with_metadata_and_payload(
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -203,7 +203,7 @@ static void test_request_response_with_metadata_and_payload(
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));

@ -128,7 +128,7 @@ static void test_request_response_with_metadata_and_payload(
gpr_slice_unref(request_payload_slice); gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice); gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -147,7 +147,7 @@ static void test_request_response_with_metadata_and_payload(
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client); cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, "key1", "val1", "key2", "val2", NULL); deadline, "key1", "val1", "key2", "val2", NULL);
cq_verify(v_server); cq_verify(v_server);

@ -128,7 +128,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -196,7 +196,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));

@ -121,7 +121,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -136,7 +136,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) {
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client); cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -134,7 +134,7 @@ static void test_request_response_with_metadata_and_payload(
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -205,7 +205,7 @@ static void test_request_response_with_metadata_and_payload(
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 1); GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));

@ -130,7 +130,7 @@ static void test_request_response_with_metadata_and_payload(
gpr_slice_unref(request_payload_slice); gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice); gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -149,7 +149,7 @@ static void test_request_response_with_metadata_and_payload(
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client); cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, "key1", "val1", "key2", "val2", NULL); deadline, "key1", "val1", "key2", "val2", NULL);
cq_verify(v_server); cq_verify(v_server);

@ -128,7 +128,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
const int large_size = 64 * 1024; const int large_size = 64 * 1024;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
meta.key = "key"; meta.key = "key";
@ -197,7 +197,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value)); GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));

@ -121,7 +121,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
((char*)meta.value)[large_size] = 0; ((char*)meta.value)[large_size] = 0;
meta.value_length = large_size; meta.value_length = large_size;
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -131,7 +131,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) {
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==
grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, "key", meta.value, NULL); deadline, "key", meta.value, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -126,7 +126,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -188,7 +188,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));

@ -116,7 +116,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
/* byte buffer holds the slice, we can unref it already */ /* byte buffer holds the slice, we can unref it already */
gpr_slice_unref(payload_slice); gpr_slice_unref(payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -132,7 +132,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) {
cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK);
cq_verify(v_client); cq_verify(v_client);
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -114,7 +114,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
config.init_client(f, client_args); config.init_client(f, client_args);
c = grpc_channel_create_call(f->client, f->client_cq, "/foo", c = grpc_channel_create_call(f->client, f->client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -172,7 +172,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
gpr_free(details); gpr_free(details);

@ -103,7 +103,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
config.init_client(f, client_args); config.init_client(f, client_args);
c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f->client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -119,7 +119,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config,
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -122,7 +122,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
int was_cancelled = 2; int was_cancelled = 2;
c = grpc_channel_create_call(f.client, f.client_cq, "/foo", c = grpc_channel_create_call(f.client, f.client_cq, "/foo",
"foo.test.google.com", deadline); "foo.test.google.fr", deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&initial_metadata_recv);
@ -178,7 +178,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.com")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(was_cancelled == 0);
gpr_free(details); gpr_free(details);

@ -110,7 +110,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -122,7 +122,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) {
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
@ -157,7 +157,7 @@ static void simple_request_body2(grpc_end2end_test_fixture f) {
cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_client = cq_verifier_create(f.client_cq);
cq_verifier *v_server = cq_verifier_create(f.server_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -169,7 +169,7 @@ static void simple_request_body2(grpc_end2end_test_fixture f) {
cq_verify(v_client); cq_verify(v_client);
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.com", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "foo.test.google.fr",
deadline, NULL); deadline, NULL);
cq_verify(v_server); cq_verify(v_server);

@ -109,7 +109,7 @@ static void start_request(void) {
gpr_slice slice = gpr_slice_malloc(100); gpr_slice slice = gpr_slice_malloc(100);
grpc_byte_buffer *buf; grpc_byte_buffer *buf;
grpc_call *call = grpc_channel_create_call_old( grpc_call *call = grpc_channel_create_call_old(
g_fixture.client, "/Foo", "foo.test.google.com", g_test_end_time); g_fixture.client, "/Foo", "foo.test.google.fr", g_test_end_time);
memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice));
buf = grpc_byte_buffer_create(&slice, 1); buf = grpc_byte_buffer_create(&slice, 1);

@ -109,7 +109,7 @@ static void start_request(void) {
gpr_slice slice = gpr_slice_malloc(100); gpr_slice slice = gpr_slice_malloc(100);
grpc_byte_buffer *buf; grpc_byte_buffer *buf;
grpc_call *call = grpc_channel_create_call_old( grpc_call *call = grpc_channel_create_call_old(
g_fixture.client, "/Foo", "foo.test.google.com", g_test_end_time); g_fixture.client, "/Foo", "foo.test.google.fr", g_test_end_time);
memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice));
buf = grpc_byte_buffer_create(&slice, 1); buf = grpc_byte_buffer_create(&slice, 1);

@ -124,7 +124,7 @@ static void test_writes_done_hangs_with_pending_read(
gpr_slice_unref(request_payload_slice); gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice); gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -141,7 +141,7 @@ static void test_writes_done_hangs_with_pending_read(
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

@ -124,7 +124,7 @@ static void test_writes_done_hangs_with_pending_read(
gpr_slice_unref(request_payload_slice); gpr_slice_unref(request_payload_slice);
gpr_slice_unref(response_payload_slice); gpr_slice_unref(response_payload_slice);
c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.com", c = grpc_channel_create_call_old(f.client, "/foo", "foo.test.google.fr",
deadline); deadline);
GPR_ASSERT(c); GPR_ASSERT(c);
@ -141,7 +141,7 @@ static void test_writes_done_hangs_with_pending_read(
GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100)));
cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo",
"foo.test.google.com", deadline, NULL); "foo.test.google.fr", deadline, NULL);
cq_verify(v_server); cq_verify(v_server);
GPR_ASSERT(GRPC_CALL_OK == GPR_ASSERT(GRPC_CALL_OK ==

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save