Merge remote-tracking branch 'upstream/master' into log_format_check

pull/6871/head
Yuchen Zeng 9 years ago
commit ed81a88c3e
  1. 4
      examples/cpp/helloworld/greeter_async_client.cc
  2. 4
      examples/cpp/helloworld/greeter_async_server.cc
  3. 26
      examples/php/greeter_client.php
  4. 160
      examples/php/helloworld.php
  5. 768
      examples/php/route_guide/route_guide.php
  6. 266
      examples/php/route_guide/route_guide_client.php
  7. 3
      setup.py
  8. 42
      src/compiler/objective_c_generator.cc
  9. 71
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  10. 3
      src/core/ext/transport/chttp2/transport/internal.h
  11. 2
      src/core/lib/channel/channel_stack.c
  12. 3
      src/core/lib/channel/channel_stack.h
  13. 4
      src/core/lib/channel/channel_stack_builder.c
  14. 13
      src/core/lib/channel/http_client_filter.c
  15. 2
      src/core/lib/channel/http_client_filter.h
  16. 15
      src/csharp/Grpc.Core.Tests/ServerTest.cs
  17. 3
      src/csharp/Grpc.Core/Server.cs
  18. 3
      src/php/tests/interop/interop_client.php
  19. 6
      src/php/tests/interop/metrics_client.php
  20. 103
      src/php/tests/interop/stress_client.php
  21. 6
      src/python/grpcio/grpc/_channel.py
  22. 284
      src/python/grpcio/tests/unit/_cython/cygrpc_test.py
  23. 34
      src/python/grpcio/tests/unit/_cython/test_utilities.py
  24. 2
      test/core/channel/channel_stack_test.c
  25. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/23f261e44d54a2736f6e288128d98db9e5015206
  26. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/552199651d942e7220141a93ec33dd8256210a18
  27. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/7a946bf3cd91b63001f2cf3f40c515c747f2ecde
  28. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/7d25c28298fb4d0fe41209d0d14307e4aa67c59e
  29. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/8138b18a9a743659befc2f2b23d23cb9c3086a09
  30. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/925011abb99fd56bb0f425ae5e0d92e6d341f804
  31. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/crash-c1f66840627e3bfdedf2e4c225bc4de0c267ed37
  32. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/d6bed9cc3c10338a8c5f41064ff8bec0bbc267ce
  33. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/dda9643679f8c8b796e64232a7d153e447d64991
  34. BIN
      test/core/end2end/fuzzers/server_fuzzer_corpus/e7b08e36420fa107f0aee652e62158af85a4ef15
  35. 10
      test/cpp/end2end/end2end_test.cc
  36. 2
      tools/distrib/python/check_grpcio_tools.py
  37. 10
      tools/distrib/python/grpcio_tools/README.rst
  38. 5
      tools/distrib/python/grpcio_tools/grpc/tools/protoc.py
  39. 4
      tools/distrib/python/grpcio_tools/protoc_lib_deps.py
  40. 36
      tools/distrib/python/grpcio_tools/setup.py
  41. 35
      tools/distrib/python/make_grpcio_tools.py
  42. 7
      tools/dockerfile/grpc_artifact_python_manylinux_x64/Dockerfile
  43. 7
      tools/dockerfile/grpc_artifact_python_manylinux_x86/Dockerfile
  44. 4
      tools/run_tests/build_artifact_python.sh
  45. 170
      tools/run_tests/tests.json

@ -87,7 +87,9 @@ class GreeterClient {
void* got_tag; void* got_tag;
bool ok = false; bool ok = false;
// Block until the next result is available in the completion queue "cq". // Block until the next result is available in the completion queue "cq".
cq.Next(&got_tag, &ok); // The return value of Next should always be checked. This return value
// tells us whether there is any kind of event or the cq_ is shutting down.
GPR_ASSERT(cq.Next(&got_tag, &ok));
// Verify that the result from "cq" corresponds, by its tag, our previous // Verify that the result from "cq" corresponds, by its tag, our previous
// request. // request.

@ -160,7 +160,9 @@ class ServerImpl final {
// Block waiting to read the next event from the completion queue. The // Block waiting to read the next event from the completion queue. The
// event is uniquely identified by its tag, which in this case is the // event is uniquely identified by its tag, which in this case is the
// memory address of a CallData instance. // memory address of a CallData instance.
cq_->Next(&tag, &ok); // The return value of Next should always be checked. This return value
// tells us whether there is any kind of event or cq_ is shutting down.
GPR_ASSERT(cq_->Next(&tag, &ok));
GPR_ASSERT(ok); GPR_ASSERT(ok);
static_cast<CallData*>(tag)->Proceed(); static_cast<CallData*>(tag)->Proceed();
} }

@ -32,19 +32,21 @@
* *
*/ */
require dirname(__FILE__) . '/vendor/autoload.php'; require dirname(__FILE__).'/vendor/autoload.php';
require dirname(__FILE__) . '/helloworld.php'; require dirname(__FILE__).'/helloworld.php';
function greet($name) { function greet($name)
$client = new helloworld\GreeterClient('localhost:50051', [ {
'credentials' => Grpc\ChannelCredentials::createInsecure() $client = new helloworld\GreeterClient('localhost:50051', [
]); 'credentials' => Grpc\ChannelCredentials::createInsecure(),
$request = new helloworld\HelloRequest(); ]);
$request->setName($name); $request = new helloworld\HelloRequest();
list($reply, $status) = $client->SayHello($request)->wait(); $request->setName($name);
$message = $reply->getMessage(); list($reply, $status) = $client->SayHello($request)->wait();
return $message; $message = $reply->getMessage();
return $message;
} }
$name = !empty($argv[1]) ? $argv[1] : 'world'; $name = !empty($argv[1]) ? $argv[1] : 'world';
print(greet($name)."\n"); echo greet($name)."\n";

@ -5,154 +5,164 @@
namespace helloworld { namespace helloworld {
class HelloRequest extends \DrSlump\Protobuf\Message { class HelloRequest extends \DrSlump\Protobuf\Message
{
/** @var string */ /** @var string */
public $name = null; public $name = null;
/** @var \Closure[] */ /** @var \Closure[] */
protected static $__extensions = array(); protected static $__extensions = array();
public static function descriptor() public static function descriptor()
{ {
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloRequest'); $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloRequest');
// OPTIONAL STRING name = 1 // OPTIONAL STRING name = 1
$f = new \DrSlump\Protobuf\Field(); $f = new \DrSlump\Protobuf\Field();
$f->number = 1; $f->number = 1;
$f->name = "name"; $f->name = 'name';
$f->type = \DrSlump\Protobuf::TYPE_STRING; $f->type = \DrSlump\Protobuf::TYPE_STRING;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$descriptor->addField($f); $descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor; foreach (self::$__extensions as $cb) {
} $descriptor->addField($cb(), true);
}
return $descriptor;
}
/** /**
* Check if <name> has a value * Check if <name> has a value.
* *
* @return boolean * @return bool
*/ */
public function hasName(){ public function hasName()
return $this->_has(1); {
return $this->_has(1);
} }
/** /**
* Clear <name> value * Clear <name> value.
* *
* @return \helloworld\HelloRequest * @return \helloworld\HelloRequest
*/ */
public function clearName(){ public function clearName()
return $this->_clear(1); {
return $this->_clear(1);
} }
/** /**
* Get <name> value * Get <name> value.
* *
* @return string * @return string
*/ */
public function getName(){ public function getName()
return $this->_get(1); {
return $this->_get(1);
} }
/** /**
* Set <name> value * Set <name> value.
* *
* @param string $value * @param string $value
*
* @return \helloworld\HelloRequest * @return \helloworld\HelloRequest
*/ */
public function setName( $value){ public function setName($value)
return $this->_set(1, $value); {
return $this->_set(1, $value);
} }
} }
} }
namespace helloworld { namespace helloworld {
class HelloReply extends \DrSlump\Protobuf\Message { class HelloReply extends \DrSlump\Protobuf\Message
{
/** @var string */ /** @var string */
public $message = null; public $message = null;
/** @var \Closure[] */ /** @var \Closure[] */
protected static $__extensions = array(); protected static $__extensions = array();
public static function descriptor() public static function descriptor()
{ {
$descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloReply'); $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloReply');
// OPTIONAL STRING message = 1 // OPTIONAL STRING message = 1
$f = new \DrSlump\Protobuf\Field(); $f = new \DrSlump\Protobuf\Field();
$f->number = 1; $f->number = 1;
$f->name = "message"; $f->name = 'message';
$f->type = \DrSlump\Protobuf::TYPE_STRING; $f->type = \DrSlump\Protobuf::TYPE_STRING;
$f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL;
$descriptor->addField($f); $descriptor->addField($f);
foreach (self::$__extensions as $cb) {
$descriptor->addField($cb(), true);
}
return $descriptor; foreach (self::$__extensions as $cb) {
} $descriptor->addField($cb(), true);
}
return $descriptor;
}
/** /**
* Check if <message> has a value * Check if <message> has a value.
* *
* @return boolean * @return bool
*/ */
public function hasMessage(){ public function hasMessage()
return $this->_has(1); {
return $this->_has(1);
} }
/** /**
* Clear <message> value * Clear <message> value.
* *
* @return \helloworld\HelloReply * @return \helloworld\HelloReply
*/ */
public function clearMessage(){ public function clearMessage()
return $this->_clear(1); {
return $this->_clear(1);
} }
/** /**
* Get <message> value * Get <message> value.
* *
* @return string * @return string
*/ */
public function getMessage(){ public function getMessage()
return $this->_get(1); {
return $this->_get(1);
} }
/** /**
* Set <message> value * Set <message> value.
* *
* @param string $value * @param string $value
*
* @return \helloworld\HelloReply * @return \helloworld\HelloReply
*/ */
public function setMessage( $value){ public function setMessage($value)
return $this->_set(1, $value); {
return $this->_set(1, $value);
} }
} }
} }
namespace helloworld { namespace helloworld {
class GreeterClient extends \Grpc\BaseStub { class GreeterClient extends \Grpc\BaseStub
{
public function __construct($hostname, $opts) { public function __construct($hostname, $opts)
parent::__construct($hostname, $opts); {
} parent::__construct($hostname, $opts);
}
/** /**
* @param helloworld\HelloRequest $input * @param helloworld\HelloRequest $input
*/ */
public function SayHello(\helloworld\HelloRequest $argument, $metadata = array(), $options = array()) { public function SayHello(\helloworld\HelloRequest $argument, $metadata = array(), $options = array())
return $this->_simpleRequest('/helloworld.Greeter/SayHello', $argument, '\helloworld\HelloReply::deserialize', $metadata, $options); {
return $this->_simpleRequest('/helloworld.Greeter/SayHello', $argument, '\helloworld\HelloReply::deserialize', $metadata, $options);
} }
} }
} }

File diff suppressed because it is too large Load Diff

@ -32,48 +32,50 @@
* *
*/ */
require dirname(__FILE__) . '/../vendor/autoload.php'; require dirname(__FILE__).'/../vendor/autoload.php';
require dirname(__FILE__) . '/route_guide.php'; require dirname(__FILE__).'/route_guide.php';
define('COORD_FACTOR', 1e7); define('COORD_FACTOR', 1e7);
$client = new routeguide\RouteGuideClient('localhost:50051', [ $client = new routeguide\RouteGuideClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure() 'credentials' => Grpc\ChannelCredentials::createInsecure(),
]); ]);
function printFeature($feature) { function printFeature($feature)
$name = $feature->getName(); {
if (!$name) { $name = $feature->getName();
$name_str = "no feature"; if (!$name) {
} else { $name_str = 'no feature';
$name_str = "feature called $name"; } else {
} $name_str = "feature called $name";
print sprintf("Found %s \n at %f, %f\n", $name_str, }
$feature->getLocation()->getLatitude() / COORD_FACTOR, echo sprintf("Found %s \n at %f, %f\n", $name_str,
$feature->getLocation()->getLongitude() / COORD_FACTOR); $feature->getLocation()->getLatitude() / COORD_FACTOR,
$feature->getLocation()->getLongitude() / COORD_FACTOR);
} }
/** /**
* Run the getFeature demo. Calls getFeature with a point known to have a * Run the getFeature demo. Calls getFeature with a point known to have a
* feature and a point known not to have a feature. * feature and a point known not to have a feature.
*/ */
function runGetFeature() { function runGetFeature()
print "Running GetFeature...\n"; {
global $client; echo "Running GetFeature...\n";
global $client;
$point = new routeguide\Point();
$points = array( $point = new routeguide\Point();
array(409146138, -746188906), $points = array(
array(0, 0), array(409146138, -746188906),
); array(0, 0),
);
foreach ($points as $p) {
$point->setLatitude($p[0]); foreach ($points as $p) {
$point->setLongitude($p[1]); $point->setLatitude($p[0]);
// make a unary grpc call $point->setLongitude($p[1]);
list($feature, $status) = $client->GetFeature($point)->wait(); // make a unary grpc call
printFeature($feature); list($feature, $status) = $client->GetFeature($point)->wait();
} printFeature($feature);
}
} }
/** /**
@ -81,29 +83,30 @@ function runGetFeature() {
* containing all of the features in the pre-generated * containing all of the features in the pre-generated
* database. Prints each response as it comes in. * database. Prints each response as it comes in.
*/ */
function runListFeatures() { function runListFeatures()
print "Running ListFeatures...\n"; {
global $client; echo "Running ListFeatures...\n";
global $client;
$lo_point = new routeguide\Point();
$hi_point = new routeguide\Point(); $lo_point = new routeguide\Point();
$hi_point = new routeguide\Point();
$lo_point->setLatitude(400000000);
$lo_point->setLongitude(-750000000); $lo_point->setLatitude(400000000);
$hi_point->setLatitude(420000000); $lo_point->setLongitude(-750000000);
$hi_point->setLongitude(-730000000); $hi_point->setLatitude(420000000);
$hi_point->setLongitude(-730000000);
$rectangle = new routeguide\Rectangle();
$rectangle->setLo($lo_point); $rectangle = new routeguide\Rectangle();
$rectangle->setHi($hi_point); $rectangle->setLo($lo_point);
$rectangle->setHi($hi_point);
// start the server streaming call
$call = $client->ListFeatures($rectangle); // start the server streaming call
// an iterator over the server streaming responses $call = $client->ListFeatures($rectangle);
$features = $call->responses(); // an iterator over the server streaming responses
foreach ($features as $feature) { $features = $call->responses();
printFeature($feature); foreach ($features as $feature) {
} printFeature($feature);
}
} }
/** /**
@ -111,96 +114,99 @@ function runListFeatures() {
* pre-generated feature database with a variable delay in between. Prints * pre-generated feature database with a variable delay in between. Prints
* the statistics when they are sent from the server. * the statistics when they are sent from the server.
*/ */
function runRecordRoute() { function runRecordRoute()
print "Running RecordRoute...\n"; {
global $client, $argv; echo "Running RecordRoute...\n";
global $client, $argv;
// start the client streaming call
$call = $client->RecordRoute(); // start the client streaming call
$call = $client->RecordRoute();
$db = json_decode(file_get_contents($argv[1]), true);
$num_points_in_db = count($db); $db = json_decode(file_get_contents($argv[1]), true);
$num_points = 10; $num_points_in_db = count($db);
for ($i = 0; $i < $num_points; $i++) { $num_points = 10;
$point = new routeguide\Point(); for ($i = 0; $i < $num_points; ++$i) {
$index = rand(0, $num_points_in_db - 1); $point = new routeguide\Point();
$lat = $db[$index]['location']['latitude']; $index = rand(0, $num_points_in_db - 1);
$long = $db[$index]['location']['longitude']; $lat = $db[$index]['location']['latitude'];
$feature_name = $db[$index]['name']; $long = $db[$index]['location']['longitude'];
$point->setLatitude($lat); $feature_name = $db[$index]['name'];
$point->setLongitude($long); $point->setLatitude($lat);
print sprintf("Visiting point %f, %f,\n with feature name: %s\n", $point->setLongitude($long);
$lat / COORD_FACTOR, $long / COORD_FACTOR, echo sprintf("Visiting point %f, %f,\n with feature name: %s\n",
$feature_name ? $feature_name : '<empty>'); $lat / COORD_FACTOR, $long / COORD_FACTOR,
usleep(rand(300000, 800000)); $feature_name ? $feature_name : '<empty>');
$call->write($point); usleep(rand(300000, 800000));
} $call->write($point);
list($route_summary, $status) = $call->wait(); }
print sprintf("Finished trip with %d points\nPassed %d features\n". list($route_summary, $status) = $call->wait();
"Travelled %d meters\nIt took %d seconds\n", echo sprintf("Finished trip with %d points\nPassed %d features\n".
$route_summary->getPointCount(), "Travelled %d meters\nIt took %d seconds\n",
$route_summary->getFeatureCount(), $route_summary->getPointCount(),
$route_summary->getDistance(), $route_summary->getFeatureCount(),
$route_summary->getElapsedTime()); $route_summary->getDistance(),
$route_summary->getElapsedTime());
} }
/** /**
* Run the routeChat demo. Send some chat messages, and print any chat * Run the routeChat demo. Send some chat messages, and print any chat
* messages that are sent from the server. * messages that are sent from the server.
*/ */
function runRouteChat() { function runRouteChat()
print "Running RouteChat...\n"; {
global $client; echo "Running RouteChat...\n";
global $client;
// start the bidirectional streaming call
$call = $client->RouteChat(); // start the bidirectional streaming call
$call = $client->RouteChat();
$notes = array(
array(1, 1, 'first message'), $notes = array(
array(1, 2, 'second message'), array(1, 1, 'first message'),
array(2, 1, 'third message'), array(1, 2, 'second message'),
array(1, 1, 'fourth message'), array(2, 1, 'third message'),
array(1, 1, 'fifth message'), array(1, 1, 'fourth message'),
); array(1, 1, 'fifth message'),
);
foreach ($notes as $n) {
$point = new routeguide\Point(); foreach ($notes as $n) {
$point->setLatitude($lat = $n[0]); $point = new routeguide\Point();
$point->setLongitude($long = $n[1]); $point->setLatitude($lat = $n[0]);
$point->setLongitude($long = $n[1]);
$route_note = new routeguide\RouteNote();
$route_note->setLocation($point); $route_note = new routeguide\RouteNote();
$route_note->setMessage($message = $n[2]); $route_note->setLocation($point);
$route_note->setMessage($message = $n[2]);
print sprintf("Sending message: '%s' at (%d, %d)\n",
$message, $lat, $long); echo sprintf("Sending message: '%s' at (%d, %d)\n",
// send a bunch of messages to the server $message, $lat, $long);
$call->write($route_note); // send a bunch of messages to the server
} $call->write($route_note);
$call->writesDone(); }
$call->writesDone();
// read from the server until there's no more
while ($route_note_reply = $call->read()) { // read from the server until there's no more
print sprintf("Previous left message at (%d, %d): '%s'\n", while ($route_note_reply = $call->read()) {
$route_note_reply->getLocation()->getLatitude(), echo sprintf("Previous left message at (%d, %d): '%s'\n",
$route_note_reply->getLocation()->getLongitude(), $route_note_reply->getLocation()->getLatitude(),
$route_note_reply->getMessage()); $route_note_reply->getLocation()->getLongitude(),
} $route_note_reply->getMessage());
}
} }
/** /**
* Run all of the demos in order * Run all of the demos in order.
*/ */
function main() { function main()
runGetFeature(); {
runListFeatures(); runGetFeature();
runRecordRoute(); runListFeatures();
runRouteChat(); runRecordRoute();
runRouteChat();
} }
if (empty($argv[1])) { if (empty($argv[1])) {
print "Usage: php -d extension=grpc.so route_guide_client.php " . echo 'Usage: php -d extension=grpc.so route_guide_client.php '.
"<path to route_guide_db.json>\n"; "<path to route_guide_db.json>\n";
exit(1); exit(1);
} }
main(); main();

@ -234,8 +234,7 @@ setuptools.setup(
ext_modules=CYTHON_EXTENSION_MODULES, ext_modules=CYTHON_EXTENSION_MODULES,
packages=list(PACKAGES), packages=list(PACKAGES),
package_dir=PACKAGE_DIRECTORIES, package_dir=PACKAGE_DIRECTORIES,
# TODO(atash): Figure out why auditwheel doesn't like namespace packages. namespace_packages=['grpc'],
#namespace_packages=['grpc'],
package_data=PACKAGE_DATA, package_data=PACKAGE_DATA,
install_requires=INSTALL_REQUIRES, install_requires=INSTALL_REQUIRES,
setup_requires=SETUP_REQUIRES, setup_requires=SETUP_REQUIRES,

@ -60,9 +60,34 @@ void PrintProtoRpcDeclarationAsPragma(Printer *printer,
" returns ($server_stream$$response_type$)\n\n"); " returns ($server_stream$$response_type$)\n\n");
} }
template <typename DescriptorType>
static void PrintAllComments(const DescriptorType* desc, Printer* printer) {
std::vector<grpc::string> comments;
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED,
&comments);
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING,
&comments);
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING,
&comments);
if (comments.empty()) {
return;
}
printer->Print("/**\n");
for (auto it = comments.begin(); it != comments.end(); ++it) {
printer->Print(" * ");
size_t start_pos = it->find_first_not_of(' ');
if (start_pos != grpc::string::npos) {
printer->Print(it->c_str() + start_pos);
}
printer->Print("\n");
}
printer->Print(" */\n");
}
void PrintMethodSignature(Printer *printer, const MethodDescriptor *method, void PrintMethodSignature(Printer *printer, const MethodDescriptor *method,
const map< ::grpc::string, ::grpc::string> &vars) { const map< ::grpc::string, ::grpc::string> &vars) {
// TODO(jcanizales): Print method comments. // Print comment
PrintAllComments(method, printer);
printer->Print(vars, "- ($return_type$)$method_name$With"); printer->Print(vars, "- ($return_type$)$method_name$With");
if (method->client_streaming()) { if (method->client_streaming()) {
@ -195,8 +220,10 @@ void PrintMethodImplementations(Printer *printer,
printer.Print("@end\n\n"); printer.Print("@end\n\n");
printer.Print( printer.Print(
"// Basic service implementation, over gRPC, that only does" "/**\n"
" marshalling and parsing.\n"); " * Basic service implementation, over gRPC, that only does\n"
" * marshalling and parsing.\n"
" */\n");
printer.Print(vars, printer.Print(vars,
"@interface $service_class$ :" "@interface $service_class$ :"
" GRPCProtoService<$service_class$>\n"); " GRPCProtoService<$service_class$>\n");
@ -220,18 +247,13 @@ void PrintMethodImplementations(Printer *printer,
{"service_class", ServiceClassName(service)}, {"service_class", ServiceClassName(service)},
{"package", service->file()->package()}}; {"package", service->file()->package()}};
printer.Print(vars,
"static NSString *const kPackageName = @\"$package$\";\n");
printer.Print(
vars, "static NSString *const kServiceName = @\"$service_name$\";\n\n");
printer.Print(vars, "@implementation $service_class$\n\n"); printer.Print(vars, "@implementation $service_class$\n\n");
printer.Print("// Designated initializer\n"); printer.Print("// Designated initializer\n");
printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); printer.Print("- (instancetype)initWithHost:(NSString *)host {\n");
printer.Print( printer.Print(vars,
" return (self = [super initWithHost:host" " return (self = [super initWithHost:host"
" packageName:kPackageName serviceName:kServiceName]);\n"); " packageName:@\"$package$\" serviceName:@\"$service_name$\"]);\n");
printer.Print("}\n\n"); printer.Print("}\n\n");
printer.Print( printer.Print(
"// Override superclass initializer to disallow different" "// Override superclass initializer to disallow different"

@ -47,6 +47,7 @@
#include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h" #include "src/core/ext/transport/chttp2/transport/status_conversion.h"
#include "src/core/ext/transport/chttp2/transport/timeout_encoding.h" #include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
@ -107,7 +108,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
static void cancel_from_api(grpc_exec_ctx *exec_ctx, static void cancel_from_api(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_chttp2_stream_global *stream_global,
grpc_status_code status); grpc_status_code status,
gpr_slice *optional_message);
static void close_from_api(grpc_exec_ctx *exec_ctx, static void close_from_api(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
@ -161,6 +163,8 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(t->ep == NULL); GPR_ASSERT(t->ep == NULL);
gpr_slice_unref(t->optional_drop_message);
gpr_slice_buffer_destroy(&t->global.qbuf); gpr_slice_buffer_destroy(&t->global.qbuf);
gpr_slice_buffer_destroy(&t->writing.outbuf); gpr_slice_buffer_destroy(&t->writing.outbuf);
@ -260,6 +264,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
t->parsing.deframe_state = t->parsing.deframe_state =
is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0; is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
t->writing.is_client = is_client; t->writing.is_client = is_client;
t->optional_drop_message = gpr_empty_slice();
grpc_connectivity_state_init( grpc_connectivity_state_init(
&t->channel_callback.state_tracker, GRPC_CHANNEL_READY, &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
is_client ? "client_transport" : "server_transport"); is_client ? "client_transport" : "server_transport");
@ -804,8 +809,10 @@ void grpc_chttp2_add_incoming_goaway(
gpr_free(msg); gpr_free(msg);
gpr_slice_unref(goaway_text); gpr_slice_unref(goaway_text);
transport_global->seen_goaway = 1; transport_global->seen_goaway = 1;
connectivity_state_set(exec_ctx, transport_global, GRPC_CHANNEL_SHUTDOWN, /* lie: use transient failure from the transport to indicate goaway has been
"got_goaway"); * received */
connectivity_state_set(exec_ctx, transport_global,
GRPC_CHANNEL_TRANSIENT_FAILURE, "got_goaway");
} }
static void maybe_start_some_streams( static void maybe_start_some_streams(
@ -859,7 +866,7 @@ static void maybe_start_some_streams(
grpc_chttp2_list_pop_waiting_for_concurrency(transport_global, grpc_chttp2_list_pop_waiting_for_concurrency(transport_global,
&stream_global)) { &stream_global)) {
cancel_from_api(exec_ctx, transport_global, stream_global, cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_UNAVAILABLE); GRPC_STATUS_UNAVAILABLE, NULL);
} }
} }
@ -936,7 +943,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
if (op->cancel_with_status != GRPC_STATUS_OK) { if (op->cancel_with_status != GRPC_STATUS_OK) {
cancel_from_api(exec_ctx, transport_global, stream_global, cancel_from_api(exec_ctx, transport_global, stream_global,
op->cancel_with_status); op->cancel_with_status, op->optional_close_message);
} }
if (op->close_with_status != GRPC_STATUS_OK) { if (op->close_with_status != GRPC_STATUS_OK) {
@ -960,7 +967,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
"(%" PRIuPTR " vs. %" PRIuPTR ")", "(%" PRIuPTR " vs. %" PRIuPTR ")",
metadata_size, metadata_peer_limit); metadata_size, metadata_peer_limit);
cancel_from_api(exec_ctx, transport_global, stream_global, cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_RESOURCE_EXHAUSTED); GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
} else { } else {
if (contains_non_ok_status(transport_global, op->send_initial_metadata)) { if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
stream_global->seen_error = true; stream_global->seen_error = true;
@ -1015,7 +1022,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx,
"(%" PRIuPTR " vs. %" PRIuPTR ")", "(%" PRIuPTR " vs. %" PRIuPTR ")",
metadata_size, metadata_peer_limit); metadata_size, metadata_peer_limit);
cancel_from_api(exec_ctx, transport_global, stream_global, cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_RESOURCE_EXHAUSTED); GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
} else { } else {
if (contains_non_ok_status(transport_global, if (contains_non_ok_status(transport_global,
op->send_trailing_metadata)) { op->send_trailing_metadata)) {
@ -1201,7 +1208,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
} }
if (stream_global->exceeded_metadata_size) { if (stream_global->exceeded_metadata_size) {
cancel_from_api(exec_ctx, transport_global, stream_global, cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_RESOURCE_EXHAUSTED); GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
} }
} }
grpc_chttp2_incoming_metadata_buffer_publish( grpc_chttp2_incoming_metadata_buffer_publish(
@ -1240,7 +1247,7 @@ static void check_read_ops(grpc_exec_ctx *exec_ctx,
} }
if (stream_global->exceeded_metadata_size) { if (stream_global->exceeded_metadata_size) {
cancel_from_api(exec_ctx, transport_global, stream_global, cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_RESOURCE_EXHAUSTED); GRPC_STATUS_RESOURCE_EXHAUSTED, NULL);
} }
} }
if (stream_global->all_incoming_byte_streams_finished) { if (stream_global->all_incoming_byte_streams_finished) {
@ -1303,7 +1310,8 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
static void cancel_from_api(grpc_exec_ctx *exec_ctx, static void cancel_from_api(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global, grpc_chttp2_stream_global *stream_global,
grpc_status_code status) { grpc_status_code status,
gpr_slice *optional_message) {
if (!stream_global->read_closed || !stream_global->write_closed) { if (!stream_global->read_closed || !stream_global->write_closed) {
if (stream_global->id != 0) { if (stream_global->id != 0) {
gpr_slice_buffer_add( gpr_slice_buffer_add(
@ -1313,8 +1321,12 @@ static void cancel_from_api(grpc_exec_ctx *exec_ctx,
(uint32_t)grpc_chttp2_grpc_status_to_http2_error(status), (uint32_t)grpc_chttp2_grpc_status_to_http2_error(status),
&stream_global->stats.outgoing)); &stream_global->stats.outgoing));
} }
if (optional_message) {
gpr_slice_ref(*optional_message);
}
grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status, grpc_chttp2_fake_status(exec_ctx, transport_global, stream_global, status,
NULL); optional_message);
} }
if (status != GRPC_STATUS_OK && !stream_global->seen_error) { if (status != GRPC_STATUS_OK && !stream_global->seen_error) {
stream_global->seen_error = true; stream_global->seen_error = true;
@ -1524,8 +1536,12 @@ static void close_from_api(grpc_exec_ctx *exec_ctx,
static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global, static void cancel_stream_cb(grpc_chttp2_transport_global *transport_global,
void *user_data, void *user_data,
grpc_chttp2_stream_global *stream_global) { grpc_chttp2_stream_global *stream_global) {
grpc_chttp2_transport *transport = TRANSPORT_FROM_GLOBAL(transport_global);
cancel_from_api(user_data, transport_global, stream_global, cancel_from_api(user_data, transport_global, stream_global,
GRPC_STATUS_UNAVAILABLE); GRPC_STATUS_UNAVAILABLE,
GPR_SLICE_IS_EMPTY(transport->optional_drop_message)
? NULL
: &transport->optional_drop_message);
} }
static void end_all_the_calls(grpc_exec_ctx *exec_ctx, static void end_all_the_calls(grpc_exec_ctx *exec_ctx,
@ -1601,6 +1617,29 @@ static void reading_action_locked(grpc_exec_ctx *exec_ctx,
} }
} }
static bool try_http_parsing(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t) {
grpc_http_parser parser;
size_t i = 0;
bool success = false;
grpc_http_parser_init(&parser);
for (; i < t->read_buffer.count &&
grpc_http_parser_parse(&parser, t->read_buffer.slices[i]);
i++)
;
if (grpc_http_parser_eof(&parser) && parser.type == GRPC_HTTP_RESPONSE) {
success = true;
GRPC_CHTTP2_IF_TRACING(gpr_log(
GPR_DEBUG, "Trying to connect an http1.x server, received status:%d",
parser.http.response.status));
}
grpc_http_parser_destroy(&parser);
return success;
}
static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) { static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
grpc_chttp2_transport *t = arg; grpc_chttp2_transport *t = arg;
GPR_TIMER_BEGIN("reading_action.parse", 0); GPR_TIMER_BEGIN("reading_action.parse", 0);
@ -1612,6 +1651,14 @@ static void parsing_action(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
; ;
if (i != t->read_buffer.count) { if (i != t->read_buffer.count) {
success = false; success = false;
gpr_slice_unref(t->optional_drop_message);
if (try_http_parsing(exec_ctx, t)) {
t->optional_drop_message = gpr_slice_from_copied_string(
"Connection dropped: received http1.x response");
} else {
t->optional_drop_message = gpr_slice_from_copied_string(
"Connection dropped: received unparseable response");
}
} }
GPR_TIMER_END("reading_action.parse", 0); GPR_TIMER_END("reading_action.parse", 0);
grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked, grpc_chttp2_run_with_global_lock(exec_ctx, t, NULL, post_parse_locked,

@ -383,6 +383,9 @@ struct grpc_chttp2_transport {
/** Transport op to be applied post-parsing */ /** Transport op to be applied post-parsing */
grpc_transport_op *post_parsing_op; grpc_transport_op *post_parsing_op;
/** Message explaining the reason of dropping connection */
gpr_slice optional_drop_message;
}; };
typedef struct { typedef struct {

@ -106,6 +106,7 @@ void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
const grpc_channel_filter **filters, const grpc_channel_filter **filters,
size_t filter_count, size_t filter_count,
const grpc_channel_args *channel_args, const grpc_channel_args *channel_args,
grpc_transport *optional_transport,
const char *name, grpc_channel_stack *stack) { const char *name, grpc_channel_stack *stack) {
size_t call_size = size_t call_size =
ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) + ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
@ -127,6 +128,7 @@ void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
for (i = 0; i < filter_count; i++) { for (i = 0; i < filter_count; i++) {
args.channel_stack = stack; args.channel_stack = stack;
args.channel_args = channel_args; args.channel_args = channel_args;
args.optional_transport = optional_transport;
args.is_first = i == 0; args.is_first = i == 0;
args.is_last = i == (filter_count - 1); args.is_last = i == (filter_count - 1);
elems[i].filter = filters[i]; elems[i].filter = filters[i];

@ -60,6 +60,8 @@ typedef struct grpc_call_stack grpc_call_stack;
typedef struct { typedef struct {
grpc_channel_stack *channel_stack; grpc_channel_stack *channel_stack;
const grpc_channel_args *channel_args; const grpc_channel_args *channel_args;
/** Transport, iff it is known */
grpc_transport *optional_transport;
int is_first; int is_first;
int is_last; int is_last;
} grpc_channel_element_args; } grpc_channel_element_args;
@ -198,6 +200,7 @@ void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx, int initial_refs,
grpc_iomgr_cb_func destroy, void *destroy_arg, grpc_iomgr_cb_func destroy, void *destroy_arg,
const grpc_channel_filter **filters, const grpc_channel_filter **filters,
size_t filter_count, const grpc_channel_args *args, size_t filter_count, const grpc_channel_args *args,
grpc_transport *optional_transport,
const char *name, grpc_channel_stack *stack); const char *name, grpc_channel_stack *stack);
/* Destroy a channel stack */ /* Destroy a channel stack */
void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx, void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,

@ -257,8 +257,8 @@ void *grpc_channel_stack_builder_finish(grpc_exec_ctx *exec_ctx,
// and initialize it // and initialize it
grpc_channel_stack_init(exec_ctx, initial_refs, destroy, grpc_channel_stack_init(exec_ctx, initial_refs, destroy,
destroy_arg == NULL ? result : destroy_arg, filters, destroy_arg == NULL ? result : destroy_arg, filters,
num_filters, builder->args, builder->name, num_filters, builder->args, builder->transport,
channel_stack); builder->name, channel_stack);
// run post-initialization functions // run post-initialization functions
i = 0; i = 0;

@ -38,6 +38,7 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport_impl.h"
#define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE "application/grpc"
#define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1
@ -199,7 +200,8 @@ static grpc_mdelem *scheme_from_args(const grpc_channel_args *args) {
return GRPC_MDELEM_SCHEME_HTTP; return GRPC_MDELEM_SCHEME_HTTP;
} }
static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args) { static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args,
const char *transport_name) {
gpr_strvec v; gpr_strvec v;
size_t i; size_t i;
int is_first = 1; int is_first = 1;
@ -221,8 +223,8 @@ static grpc_mdstr *user_agent_from_args(const grpc_channel_args *args) {
} }
} }
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s)", is_first ? "" : " ", gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s)", is_first ? "" : " ",
grpc_version_string(), GPR_PLATFORM_STRING); grpc_version_string(), GPR_PLATFORM_STRING, transport_name);
is_first = 0; is_first = 0;
gpr_strvec_add(&v, tmp); gpr_strvec_add(&v, tmp);
@ -253,9 +255,12 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element_args *args) { grpc_channel_element_args *args) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
GPR_ASSERT(args->optional_transport != NULL);
chand->static_scheme = scheme_from_args(args->channel_args); chand->static_scheme = scheme_from_args(args->channel_args);
chand->user_agent = grpc_mdelem_from_metadata_strings( chand->user_agent = grpc_mdelem_from_metadata_strings(
GRPC_MDSTR_USER_AGENT, user_agent_from_args(args->channel_args)); GRPC_MDSTR_USER_AGENT,
user_agent_from_args(args->channel_args,
args->optional_transport->vtable->name));
} }
/* Destructor for channel data */ /* Destructor for channel data */

@ -1,5 +1,4 @@
/* /*
*
* Copyright 2015, Google Inc. * Copyright 2015, Google Inc.
* All rights reserved. * All rights reserved.
* *
@ -39,6 +38,7 @@
/* Processes metadata on the client side for HTTP2 transports */ /* Processes metadata on the client side for HTTP2 transports */
extern const grpc_channel_filter grpc_http_client_filter; extern const grpc_channel_filter grpc_http_client_filter;
/* Channel arg to override the http2 :scheme header */
#define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme" #define GRPC_ARG_HTTP2_SCHEME "grpc.http2_scheme"
#endif /* GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H */ #endif /* GRPC_CORE_LIB_CHANNEL_HTTP_CLIENT_FILTER_H */

@ -93,5 +93,20 @@ namespace Grpc.Core.Tests
server.ShutdownAsync().Wait(); server.ShutdownAsync().Wait();
} }
[Test]
public void UnstartedServerCanBeShutdown()
{
var server = new Server();
server.ShutdownAsync().Wait();
Assert.Throws(typeof(InvalidOperationException), () => server.Start());
}
[Test]
public void UnstartedServerDoesNotPreventShutdown()
{
// just create a server, don't start it, and make sure it doesn't prevent shutdown.
var server = new Server();
}
} }
} }

@ -140,6 +140,7 @@ namespace Grpc.Core
lock (myLock) lock (myLock)
{ {
GrpcPreconditions.CheckState(!startRequested); GrpcPreconditions.CheckState(!startRequested);
GrpcPreconditions.CheckState(!shutdownRequested);
startRequested = true; startRequested = true;
handle.Start(); handle.Start();
@ -203,7 +204,6 @@ namespace Grpc.Core
{ {
lock (myLock) lock (myLock)
{ {
GrpcPreconditions.CheckState(startRequested);
GrpcPreconditions.CheckState(!shutdownRequested); GrpcPreconditions.CheckState(!shutdownRequested);
shutdownRequested = true; shutdownRequested = true;
} }
@ -215,7 +215,6 @@ namespace Grpc.Core
{ {
handle.CancelAllCalls(); handle.CancelAllCalls();
} }
await ShutdownCompleteOrEnvironmentDeadAsync().ConfigureAwait(false); await ShutdownCompleteOrEnvironmentDeadAsync().ConfigureAwait(false);
DisposeHandle(); DisposeHandle();

@ -477,7 +477,8 @@ function _makeStub($args)
return $stub; return $stub;
} }
function interop_main($args, $stub = false) { function interop_main($args, $stub = false)
{
if (!$stub) { if (!$stub) {
$stub = _makeStub($args); $stub = _makeStub($args);
} }

@ -39,11 +39,11 @@ $server_port = (count($parts) == 2) ? $parts[1] : '';
$socket = socket_create(AF_INET, SOCK_STREAM, 0); $socket = socket_create(AF_INET, SOCK_STREAM, 0);
if (@!socket_connect($socket, $server_host, $server_port)) { if (@!socket_connect($socket, $server_host, $server_port)) {
echo "Cannot connect to merics server...\n"; echo "Cannot connect to merics server...\n";
exit(1); exit(1);
} }
socket_write($socket, 'qps'); socket_write($socket, 'qps');
while ($out = socket_read($socket, 1024)) { while ($out = socket_read($socket, 1024)) {
echo "$out\n"; echo "$out\n";
} }
socket_close($socket); socket_close($socket);

@ -32,50 +32,52 @@
* *
*/ */
include_once('interop_client.php'); include_once 'interop_client.php';
function stress_main($args) { function stress_main($args)
mt_srand(); {
set_time_limit(0); mt_srand();
set_time_limit(0);
// open socket to listen as metrics server // open socket to listen as metrics server
$socket = socket_create(AF_INET, SOCK_STREAM, 0); $socket = socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
if (@!socket_bind($socket, 'localhost', $args['metrics_port'])) { if (@!socket_bind($socket, 'localhost', $args['metrics_port'])) {
echo "Cannot create socket for metrics server...\n"; echo "Cannot create socket for metrics server...\n";
exit(1); exit(1);
} }
socket_listen($socket); socket_listen($socket);
socket_set_nonblock($socket); socket_set_nonblock($socket);
$start_time = microtime(true); $start_time = microtime(true);
$count = 0; $count = 0;
$deadline = $args['test_duration_secs'] ? $deadline = $args['test_duration_secs'] ?
($start_time + $args['test_duration_secs']) : false; ($start_time + $args['test_duration_secs']) : false;
$num_test_cases = count($args['test_cases']); $num_test_cases = count($args['test_cases']);
$stub = false; $stub = false;
while (true) { while (true) {
$current_time = microtime(true); $current_time = microtime(true);
if ($deadline && $current_time > $deadline) { if ($deadline && $current_time > $deadline) {
break; break;
} }
if ($client_connection = socket_accept($socket)) { if ($client_connection = socket_accept($socket)) {
// there is an incoming request, respond with qps metrics // there is an incoming request, respond with qps metrics
$input = socket_read($client_connection, 1024); $input = socket_read($client_connection, 1024);
$qps = round($count / ($current_time - $start_time)); $qps = round($count / ($current_time - $start_time));
socket_write($client_connection, "qps: $qps"); socket_write($client_connection, "qps: $qps");
socket_close($client_connection); socket_close($client_connection);
} else { } else {
// do actual work, run one interop test case // do actual work, run one interop test case
$args['test_case'] = $args['test_case'] =
$args['test_cases'][mt_rand(0, $num_test_cases - 1)]; $args['test_cases'][mt_rand(0, $num_test_cases - 1)];
$stub = @interop_main($args, $stub); $stub = @interop_main($args, $stub);
$count++; ++$count;
}
} }
} socket_close($socket);
socket_close($socket); echo "Number of interop tests run in $args[test_duration_secs] ".
echo "Number of interop tests run in $args[test_duration_secs] seconds: $count.\n"; "seconds: $count.\n";
} }
// process command line arguments // process command line arguments
@ -85,31 +87,32 @@ $raw_args = getopt('',
'metrics_port::', 'metrics_port::',
'test_duration_secs::', 'test_duration_secs::',
'num_channels_per_server::', 'num_channels_per_server::',
'num_stubs_per_channel::']); 'num_stubs_per_channel::',
]);
$args = []; $args = [];
if (empty($raw_args['server_addresses'])) { if (empty($raw_args['server_addresses'])) {
$args['server_host'] = 'localhost'; $args['server_host'] = 'localhost';
$args['server_port'] = '8080'; $args['server_port'] = '8080';
} else { } else {
$parts = explode(':', $raw_args['server_addresses']); $parts = explode(':', $raw_args['server_addresses']);
$args['server_host'] = $parts[0]; $args['server_host'] = $parts[0];
$args['server_port'] = (count($parts) == 2) ? $parts[1] : ''; $args['server_port'] = (count($parts) == 2) ? $parts[1] : '';
} }
$args['metrics_port'] = empty($raw_args['metrics_port']) ? $args['metrics_port'] = empty($raw_args['metrics_port']) ?
'8081' : $args['metrics_port']; '8081' : $args['metrics_port'];
$args['test_duration_secs'] = empty($raw_args['test_duration_secs']) || $args['test_duration_secs'] = empty($raw_args['test_duration_secs']) ||
$raw_args['test_duration_secs'] == -1 ? $raw_args['test_duration_secs'] == -1 ?
false : $raw_args['test_duration_secs']; false : $raw_args['test_duration_secs'];
$test_cases = []; $test_cases = [];
$test_case_strs = explode(',', $raw_args['test_cases']); $test_case_strs = explode(',', $raw_args['test_cases']);
foreach ($test_case_strs as $test_case_str) { foreach ($test_case_strs as $test_case_str) {
$parts = explode(':', $test_case_str); $parts = explode(':', $test_case_str);
$test_cases = array_merge($test_cases, array_fill(0, $parts[1], $parts[0])); $test_cases = array_merge($test_cases, array_fill(0, $parts[1], $parts[0]));
} }
$args['test_cases'] = $test_cases; $args['test_cases'] = $test_cases;

@ -134,9 +134,9 @@ def _handle_event(event, state, response_deserializer):
for batch_operation in event.batch_operations: for batch_operation in event.batch_operations:
operation_type = batch_operation.type operation_type = batch_operation.type
state.due.remove(operation_type) state.due.remove(operation_type)
if operation_type is cygrpc.OperationType.receive_initial_metadata: if operation_type == cygrpc.OperationType.receive_initial_metadata:
state.initial_metadata = batch_operation.received_metadata state.initial_metadata = batch_operation.received_metadata
elif operation_type is cygrpc.OperationType.receive_message: elif operation_type == cygrpc.OperationType.receive_message:
serialized_response = batch_operation.received_message.bytes() serialized_response = batch_operation.received_message.bytes()
if serialized_response is not None: if serialized_response is not None:
response = _common.deserialize( response = _common.deserialize(
@ -146,7 +146,7 @@ def _handle_event(event, state, response_deserializer):
_abort(state, grpc.StatusCode.INTERNAL, details) _abort(state, grpc.StatusCode.INTERNAL, details)
else: else:
state.response = response state.response = response
elif operation_type is cygrpc.OperationType.receive_status_on_client: elif operation_type == cygrpc.OperationType.receive_status_on_client:
state.trailing_metadata = batch_operation.received_metadata state.trailing_metadata = batch_operation.received_metadata
if state.code is None: if state.code is None:
code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get( code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get(

@ -143,22 +143,60 @@ class TypeSmokeTest(unittest.TestCase):
del completion_queue del completion_queue
class InsecureServerInsecureClient(unittest.TestCase): class ServerClientMixin(object):
def setUp(self): def setUpMixin(self, server_credentials, client_credentials, host_override):
self.server_completion_queue = cygrpc.CompletionQueue() self.server_completion_queue = cygrpc.CompletionQueue()
self.server = cygrpc.Server() self.server = cygrpc.Server()
self.server.register_completion_queue(self.server_completion_queue) self.server.register_completion_queue(self.server_completion_queue)
self.port = self.server.add_http2_port('[::]:0') if server_credentials:
self.port = self.server.add_http2_port('[::]:0', server_credentials)
else:
self.port = self.server.add_http2_port('[::]:0')
self.server.start() self.server.start()
self.client_completion_queue = cygrpc.CompletionQueue() self.client_completion_queue = cygrpc.CompletionQueue()
self.client_channel = cygrpc.Channel('localhost:{}'.format(self.port)) if client_credentials:
client_channel_arguments = cygrpc.ChannelArgs([
def tearDown(self): cygrpc.ChannelArg(cygrpc.ChannelArgKey.ssl_target_name_override,
host_override)])
self.client_channel = cygrpc.Channel(
'localhost:{}'.format(self.port), client_channel_arguments,
client_credentials)
else:
self.client_channel = cygrpc.Channel('localhost:{}'.format(self.port))
if host_override:
self.host_argument = None # default host
self.expected_host = host_override
else:
# arbitrary host name necessitating no further identification
self.host_argument = b'hostess'
self.expected_host = self.host_argument
def tearDownMixin(self):
del self.server del self.server
del self.client_completion_queue del self.client_completion_queue
del self.server_completion_queue del self.server_completion_queue
def _perform_operations(self, operations, call, queue, deadline, description):
"""Perform the list of operations with given call, queue, and deadline.
Invocation errors are reported with as an exception with `description` in
the message. Performs the operations asynchronously, returning a future.
"""
def performer():
tag = object()
try:
call_result = call.start_batch(cygrpc.Operations(operations), tag)
self.assertEqual(cygrpc.CallError.ok, call_result)
event = queue.poll(deadline)
self.assertEqual(cygrpc.CompletionType.operation_complete, event.type)
self.assertTrue(event.success)
self.assertIs(tag, event.tag)
except Exception as error:
raise Exception("Error in '{}': {}".format(description, error.message))
return event
return test_utilities.SimpleFuture(performer)
def testEcho(self): def testEcho(self):
DEADLINE = time.time()+5 DEADLINE = time.time()+5
DEADLINE_TOLERANCE = 0.25 DEADLINE_TOLERANCE = 0.25
@ -175,7 +213,6 @@ class InsecureServerInsecureClient(unittest.TestCase):
REQUEST = b'in death a member of project mayhem has a name' REQUEST = b'in death a member of project mayhem has a name'
RESPONSE = b'his name is robert paulson' RESPONSE = b'his name is robert paulson'
METHOD = b'twinkies' METHOD = b'twinkies'
HOST = b'hostess'
cygrpc_deadline = cygrpc.Timespec(DEADLINE) cygrpc_deadline = cygrpc.Timespec(DEADLINE)
@ -188,7 +225,8 @@ class InsecureServerInsecureClient(unittest.TestCase):
client_call_tag = object() client_call_tag = object()
client_call = self.client_channel.create_call( client_call = self.client_channel.create_call(
None, 0, self.client_completion_queue, METHOD, HOST, cygrpc_deadline) None, 0, self.client_completion_queue, METHOD, self.host_argument,
cygrpc_deadline)
client_initial_metadata = cygrpc.Metadata([ client_initial_metadata = cygrpc.Metadata([
cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY, cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY,
CLIENT_METADATA_ASCII_VALUE), CLIENT_METADATA_ASCII_VALUE),
@ -216,7 +254,8 @@ class InsecureServerInsecureClient(unittest.TestCase):
test_common.metadata_transmitted(client_initial_metadata, test_common.metadata_transmitted(client_initial_metadata,
request_event.request_metadata)) request_event.request_metadata))
self.assertEqual(METHOD, request_event.request_call_details.method) self.assertEqual(METHOD, request_event.request_call_details.method)
self.assertEqual(HOST, request_event.request_call_details.host) self.assertEqual(self.expected_host,
request_event.request_call_details.host)
self.assertLess( self.assertLess(
abs(DEADLINE - float(request_event.request_call_details.deadline)), abs(DEADLINE - float(request_event.request_call_details.deadline)),
DEADLINE_TOLERANCE) DEADLINE_TOLERANCE)
@ -292,172 +331,101 @@ class InsecureServerInsecureClient(unittest.TestCase):
del client_call del client_call
del server_call del server_call
def test6522(self):
class SecureServerSecureClient(unittest.TestCase):
def setUp(self):
server_credentials = cygrpc.server_credentials_ssl(
None, [cygrpc.SslPemKeyCertPair(resources.private_key(),
resources.certificate_chain())], False)
channel_credentials = cygrpc.channel_credentials_ssl(
resources.test_root_certificates(), None)
self.server_completion_queue = cygrpc.CompletionQueue()
self.server = cygrpc.Server()
self.server.register_completion_queue(self.server_completion_queue)
self.port = self.server.add_http2_port('[::]:0', server_credentials)
self.server.start()
self.client_completion_queue = cygrpc.CompletionQueue()
client_channel_arguments = cygrpc.ChannelArgs([
cygrpc.ChannelArg(cygrpc.ChannelArgKey.ssl_target_name_override,
_SSL_HOST_OVERRIDE)])
self.client_channel = cygrpc.Channel(
'localhost:{}'.format(self.port), client_channel_arguments,
channel_credentials)
def tearDown(self):
del self.server
del self.client_completion_queue
del self.server_completion_queue
def testEcho(self):
DEADLINE = time.time()+5 DEADLINE = time.time()+5
DEADLINE_TOLERANCE = 0.25 DEADLINE_TOLERANCE = 0.25
CLIENT_METADATA_ASCII_KEY = b'key' METHOD = b'twinkies'
CLIENT_METADATA_ASCII_VALUE = b'val'
CLIENT_METADATA_BIN_KEY = b'key-bin'
CLIENT_METADATA_BIN_VALUE = b'\0'*1000
SERVER_INITIAL_METADATA_KEY = b'init_me_me_me'
SERVER_INITIAL_METADATA_VALUE = b'whodawha?'
SERVER_TRAILING_METADATA_KEY = b'california_is_in_a_drought'
SERVER_TRAILING_METADATA_VALUE = b'zomg it is'
SERVER_STATUS_CODE = cygrpc.StatusCode.ok
SERVER_STATUS_DETAILS = b'our work is never over'
REQUEST = b'in death a member of project mayhem has a name'
RESPONSE = b'his name is robert paulson'
METHOD = b'/twinkies'
HOST = None # Default host
cygrpc_deadline = cygrpc.Timespec(DEADLINE) cygrpc_deadline = cygrpc.Timespec(DEADLINE)
empty_metadata = cygrpc.Metadata([])
server_request_tag = object() server_request_tag = object()
request_call_result = self.server.request_call( self.server.request_call(
self.server_completion_queue, self.server_completion_queue, self.server_completion_queue, self.server_completion_queue,
server_request_tag) server_request_tag)
client_call = self.client_channel.create_call(
None, 0, self.client_completion_queue, METHOD, self.host_argument,
cygrpc_deadline)
self.assertEqual(cygrpc.CallError.ok, request_call_result) # Prologue
def perform_client_operations(operations, description):
plugin = cygrpc.CredentialsMetadataPlugin(_metadata_plugin_callback, '') return self._perform_operations(
call_credentials = cygrpc.call_credentials_metadata_plugin(plugin) operations, client_call,
self.client_completion_queue, cygrpc_deadline, description)
client_call_tag = object() client_event_future = perform_client_operations([
client_call = self.client_channel.create_call( cygrpc.operation_send_initial_metadata(empty_metadata,
None, 0, self.client_completion_queue, METHOD, HOST, cygrpc_deadline) _EMPTY_FLAGS),
client_call.set_credentials(call_credentials) cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),
client_initial_metadata = cygrpc.Metadata([ ], "Client prologue")
cygrpc.Metadatum(CLIENT_METADATA_ASCII_KEY,
CLIENT_METADATA_ASCII_VALUE),
cygrpc.Metadatum(CLIENT_METADATA_BIN_KEY, CLIENT_METADATA_BIN_VALUE)])
client_start_batch_result = client_call.start_batch(cygrpc.Operations([
cygrpc.operation_send_initial_metadata(client_initial_metadata,
_EMPTY_FLAGS),
cygrpc.operation_send_message(REQUEST, _EMPTY_FLAGS),
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS)
]), client_call_tag)
self.assertEqual(cygrpc.CallError.ok, client_start_batch_result)
client_event_future = test_utilities.CompletionQueuePollFuture(
self.client_completion_queue, cygrpc_deadline)
request_event = self.server_completion_queue.poll(cygrpc_deadline) request_event = self.server_completion_queue.poll(cygrpc_deadline)
self.assertEqual(cygrpc.CompletionType.operation_complete,
request_event.type)
self.assertIsInstance(request_event.operation_call, cygrpc.Call)
self.assertIs(server_request_tag, request_event.tag)
self.assertEqual(0, len(request_event.batch_operations))
client_metadata_with_credentials = list(client_initial_metadata) + [
(_CALL_CREDENTIALS_METADATA_KEY, _CALL_CREDENTIALS_METADATA_VALUE)]
self.assertTrue(
test_common.metadata_transmitted(client_metadata_with_credentials,
request_event.request_metadata))
self.assertEqual(METHOD, request_event.request_call_details.method)
self.assertEqual(_SSL_HOST_OVERRIDE,
request_event.request_call_details.host)
self.assertLess(
abs(DEADLINE - float(request_event.request_call_details.deadline)),
DEADLINE_TOLERANCE)
server_call_tag = object()
server_call = request_event.operation_call server_call = request_event.operation_call
server_initial_metadata = cygrpc.Metadata([
cygrpc.Metadatum(SERVER_INITIAL_METADATA_KEY,
SERVER_INITIAL_METADATA_VALUE)])
server_trailing_metadata = cygrpc.Metadata([
cygrpc.Metadatum(SERVER_TRAILING_METADATA_KEY,
SERVER_TRAILING_METADATA_VALUE)])
server_start_batch_result = server_call.start_batch([
cygrpc.operation_send_initial_metadata(server_initial_metadata,
_EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS),
cygrpc.operation_send_message(RESPONSE, _EMPTY_FLAGS),
cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
cygrpc.operation_send_status_from_server(
server_trailing_metadata, SERVER_STATUS_CODE,
SERVER_STATUS_DETAILS, _EMPTY_FLAGS)
], server_call_tag)
self.assertEqual(cygrpc.CallError.ok, server_start_batch_result)
client_event = client_event_future.result() def perform_server_operations(operations, description):
server_event = self.server_completion_queue.poll(cygrpc_deadline) return self._perform_operations(
operations, server_call,
self.server_completion_queue, cygrpc_deadline, description)
self.assertEqual(6, len(client_event.batch_operations)) server_event_future = perform_server_operations([
found_client_op_types = set() cygrpc.operation_send_initial_metadata(empty_metadata,
for client_result in client_event.batch_operations: _EMPTY_FLAGS),
# we expect each op type to be unique ], "Server prologue")
self.assertNotIn(client_result.type, found_client_op_types)
found_client_op_types.add(client_result.type)
if client_result.type == cygrpc.OperationType.receive_initial_metadata:
self.assertTrue(
test_common.metadata_transmitted(server_initial_metadata,
client_result.received_metadata))
elif client_result.type == cygrpc.OperationType.receive_message:
self.assertEqual(RESPONSE, client_result.received_message.bytes())
elif client_result.type == cygrpc.OperationType.receive_status_on_client:
self.assertTrue(
test_common.metadata_transmitted(server_trailing_metadata,
client_result.received_metadata))
self.assertEqual(SERVER_STATUS_DETAILS,
client_result.received_status_details)
self.assertEqual(SERVER_STATUS_CODE, client_result.received_status_code)
self.assertEqual(set([
cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message,
cygrpc.OperationType.send_close_from_client,
cygrpc.OperationType.receive_initial_metadata,
cygrpc.OperationType.receive_message,
cygrpc.OperationType.receive_status_on_client
]), found_client_op_types)
self.assertEqual(5, len(server_event.batch_operations)) client_event_future.result() # force completion
found_server_op_types = set() server_event_future.result()
for server_result in server_event.batch_operations:
self.assertNotIn(client_result.type, found_server_op_types)
found_server_op_types.add(server_result.type)
if server_result.type == cygrpc.OperationType.receive_message:
self.assertEqual(REQUEST, server_result.received_message.bytes())
elif server_result.type == cygrpc.OperationType.receive_close_on_server:
self.assertFalse(server_result.received_cancelled)
self.assertEqual(set([
cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.receive_message,
cygrpc.OperationType.send_message,
cygrpc.OperationType.receive_close_on_server,
cygrpc.OperationType.send_status_from_server
]), found_server_op_types)
del client_call # Messaging
del server_call for _ in range(10):
client_event_future = perform_client_operations([
cygrpc.operation_send_message(b'', _EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS),
], "Client message")
server_event_future = perform_server_operations([
cygrpc.operation_send_message(b'', _EMPTY_FLAGS),
cygrpc.operation_receive_message(_EMPTY_FLAGS),
], "Server receive")
client_event_future.result() # force completion
server_event_future.result()
# Epilogue
client_event_future = perform_client_operations([
cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),
cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS)
], "Client epilogue")
server_event_future = perform_server_operations([
cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
cygrpc.operation_send_status_from_server(
empty_metadata, cygrpc.StatusCode.ok, b'', _EMPTY_FLAGS)
], "Server epilogue")
client_event_future.result() # force completion
server_event_future.result()
class InsecureServerInsecureClient(unittest.TestCase, ServerClientMixin):
def setUp(self):
self.setUpMixin(None, None, None)
def tearDown(self):
self.tearDownMixin()
class SecureServerSecureClient(unittest.TestCase, ServerClientMixin):
def setUp(self):
server_credentials = cygrpc.server_credentials_ssl(
None, [cygrpc.SslPemKeyCertPair(resources.private_key(),
resources.certificate_chain())], False)
client_credentials = cygrpc.channel_credentials_ssl(
resources.test_root_certificates(), None)
self.setUpMixin(server_credentials, client_credentials, _SSL_HOST_OVERRIDE)
def tearDown(self):
self.tearDownMixin()
if __name__ == '__main__': if __name__ == '__main__':

@ -32,15 +32,35 @@ import threading
from grpc._cython import cygrpc from grpc._cython import cygrpc
class CompletionQueuePollFuture: class SimpleFuture(object):
"""A simple future mechanism."""
def __init__(self, completion_queue, deadline): def __init__(self, function, *args, **kwargs):
def poller_function(): def wrapped_function():
self._event_result = completion_queue.poll(deadline) try:
self._event_result = None self._result = function(*args, **kwargs)
self._thread = threading.Thread(target=poller_function) except Exception as error:
self._error = error
self._result = None
self._error = None
self._thread = threading.Thread(target=wrapped_function)
self._thread.start() self._thread.start()
def result(self): def result(self):
"""The resulting value of this future.
Re-raises any exceptions.
"""
self._thread.join() self._thread.join()
return self._event_result if self._error:
# TODO(atash): re-raise exceptions in a way that preserves tracebacks
raise self._error
return self._result
class CompletionQueuePollFuture(SimpleFuture):
def __init__(self, completion_queue, deadline):
super(CompletionQueuePollFuture, self).__init__(
lambda: completion_queue.poll(deadline))

@ -124,7 +124,7 @@ static void test_create_channel_stack(void) {
channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1)); channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1));
grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters, grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters,
1, &chan_args, "test", channel_stack); 1, &chan_args, NULL, "test", channel_stack);
GPR_ASSERT(channel_stack->count == 1); GPR_ASSERT(channel_stack->count == 1);
channel_elem = grpc_channel_stack_element(channel_stack, 0); channel_elem = grpc_channel_stack_element(channel_stack, 0);
channel_data = (int *)channel_elem->channel_data; channel_data = (int *)channel_elem->channel_data;

@ -1014,6 +1014,16 @@ TEST_P(ProxyEnd2endTest, SimpleRpc) {
SendRpc(stub_.get(), 1, false); SendRpc(stub_.get(), 1, false);
} }
TEST_P(ProxyEnd2endTest, SimpleRpcWithEmptyMessages) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
Status s = stub_->Echo(&context, request, &response);
EXPECT_TRUE(s.ok());
}
TEST_P(ProxyEnd2endTest, MultipleRpcs) { TEST_P(ProxyEnd2endTest, MultipleRpcs) {
ResetStub(); ResetStub();
std::vector<std::thread*> threads; std::vector<std::thread*> threads;

@ -37,7 +37,7 @@ OUT_OF_DATE_MESSAGE = """file {} is out of date
Have you called tools/distrib/python/make_grpcio_tools.py since upgrading protobuf?""" Have you called tools/distrib/python/make_grpcio_tools.py since upgrading protobuf?"""
check_protoc_lib_deps_content = make.get_deps(make.BAZEL_DEPS_PROTOC_LIB_QUERY) check_protoc_lib_deps_content = make.get_deps()
with open(make.GRPC_PYTHON_PROTOC_LIB_DEPS, 'r') as protoc_lib_deps_file: with open(make.GRPC_PYTHON_PROTOC_LIB_DEPS, 'r') as protoc_lib_deps_file:
if protoc_lib_deps_file.read() != check_protoc_lib_deps_content: if protoc_lib_deps_file.read() != check_protoc_lib_deps_content:

@ -126,3 +126,13 @@ Help, I ...
GCC 6.0), this is probably a bug where GCC chokes on constant expressions GCC 6.0), this is probably a bug where GCC chokes on constant expressions
when the :code:`-fwrapv` flag is specified. You should consider setting your when the :code:`-fwrapv` flag is specified. You should consider setting your
environment with :code:`CFLAGS=-fno-wrapv` or using clang (:code:`CC=clang`). environment with :code:`CFLAGS=-fno-wrapv` or using clang (:code:`CC=clang`).
Usage
-----
Given protobuf include directories :code:`$INCLUDE`, an output directory
:code:`$OUTPUT`, and proto files :code:`$PROTO_FILES`, invoke as:
::
$ python -m grpc.tools.protoc -I$INCLUDE --python_out=$OUTPUT --grpc_python_out=$OUTPUT $PROTO_FILES

@ -29,10 +29,13 @@
# (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.
import pkg_resources
import sys import sys
from grpc.tools import protoc_compiler from grpc.tools import protoc_compiler
if __name__ == '__main__': if __name__ == '__main__':
protoc_compiler.run_main(sys.argv) proto_include = pkg_resources.resource_filename('grpc.tools', '_proto')
protoc_compiler.run_main(
sys.argv + ['-I{}'.format(proto_include)])

File diff suppressed because one or more lines are too long

@ -28,9 +28,11 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from distutils import extension from distutils import extension
import errno
import os import os
import os.path import os.path
import shlex import shlex
import shutil
import sys import sys
import setuptools import setuptools
@ -47,18 +49,41 @@ sys.path.insert(0, os.path.abspath('.'))
# ourselves in w.r.t. the multitude of operating systems this ought to build on. # ourselves in w.r.t. the multitude of operating systems this ought to build on.
# By default we assume a GCC-like compiler. # By default we assume a GCC-like compiler.
EXTRA_COMPILE_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_CFLAGS', EXTRA_COMPILE_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_CFLAGS',
'-frtti -std=c++11')) '-fno-wrapv -frtti -std=c++11'))
EXTRA_LINK_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_LDFLAGS', EXTRA_LINK_ARGS = shlex.split(os.environ.get('GRPC_PYTHON_LDFLAGS',
'-lpthread')) '-lpthread'))
GRPC_PYTHON_TOOLS_PACKAGE = 'grpc.tools'
GRPC_PYTHON_PROTO_RESOURCES_NAME = '_proto'
import protoc_lib_deps import protoc_lib_deps
import grpc_version import grpc_version
def package_data():
tools_path = GRPC_PYTHON_TOOLS_PACKAGE.replace('.', os.path.sep)
proto_resources_path = os.path.join(tools_path,
GRPC_PYTHON_PROTO_RESOURCES_NAME)
proto_files = []
for proto_file in protoc_lib_deps.PROTO_FILES:
source = os.path.join(protoc_lib_deps.PROTO_INCLUDE, proto_file)
target = os.path.join(proto_resources_path, proto_file)
relative_target = os.path.join(GRPC_PYTHON_PROTO_RESOURCES_NAME, proto_file)
try:
os.makedirs(os.path.dirname(target))
except OSError as error:
if error.errno == errno.EEXIST:
pass
else:
raise
shutil.copy(source, target)
proto_files.append(relative_target)
return {GRPC_PYTHON_TOOLS_PACKAGE: proto_files}
def protoc_ext_module(): def protoc_ext_module():
plugin_sources = [ plugin_sources = [
'grpc/tools/main.cc', 'grpc/tools/main.cc',
'grpc_root/src/compiler/python_generator.cc'] + [ 'grpc_root/src/compiler/python_generator.cc'] + [
os.path.join('third_party/protobuf/src', cc_file) os.path.join(protoc_lib_deps.CC_INCLUDE, cc_file)
for cc_file in protoc_lib_deps.CC_FILES] for cc_file in protoc_lib_deps.CC_FILES]
plugin_ext = extension.Extension( plugin_ext = extension.Extension(
name='grpc.tools.protoc_compiler', name='grpc.tools.protoc_compiler',
@ -67,7 +92,7 @@ def protoc_ext_module():
'.', '.',
'grpc_root', 'grpc_root',
'grpc_root/include', 'grpc_root/include',
'third_party/protobuf/src', protoc_lib_deps.CC_INCLUDE,
], ],
language='c++', language='c++',
define_macros=[('HAVE_PTHREAD', 1)], define_macros=[('HAVE_PTHREAD', 1)],
@ -88,9 +113,10 @@ setuptools.setup(
protoc_ext_module(), protoc_ext_module(),
]), ]),
packages=setuptools.find_packages('.'), packages=setuptools.find_packages('.'),
# TODO(atash): Figure out why auditwheel doesn't like namespace packages. namespace_packages=['grpc'],
#namespace_packages=['grpc'],
install_requires=[ install_requires=[
'protobuf>=3.0.0a3', 'protobuf>=3.0.0a3',
'grpcio>=0.14.0',
], ],
package_data=package_data(),
) )

@ -67,11 +67,16 @@ DEPS_FILE_CONTENT="""
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# AUTO-GENERATED BY make_grpcio_tools.py! # AUTO-GENERATED BY make_grpcio_tools.py!
CC_FILES={} CC_FILES={cc_files}
PROTO_FILES={proto_files}
CC_INCLUDE={cc_include}
PROTO_INCLUDE={proto_include}
""" """
# Bazel query result prefix for expected source files in protobuf. # Bazel query result prefix for expected source files in protobuf.
PROTOBUF_CC_PREFIX = '//:src/' PROTOBUF_CC_PREFIX = '//:src/'
PROTOBUF_PROTO_PREFIX = '//:src/'
GRPC_ROOT = os.path.abspath( GRPC_ROOT = os.path.abspath(
os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.join(os.path.dirname(os.path.abspath(__file__)),
@ -79,7 +84,8 @@ GRPC_ROOT = os.path.abspath(
GRPC_PYTHON_ROOT = os.path.join(GRPC_ROOT, 'tools/distrib/python/grpcio_tools') GRPC_PYTHON_ROOT = os.path.join(GRPC_ROOT, 'tools/distrib/python/grpcio_tools')
GRPC_PROTOBUF = os.path.join(GRPC_ROOT, 'third_party/protobuf/src') GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT = 'third_party/protobuf/src'
GRPC_PROTOBUF = os.path.join(GRPC_ROOT, GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT)
GRPC_PROTOC_PLUGINS = os.path.join(GRPC_ROOT, 'src/compiler') GRPC_PROTOC_PLUGINS = os.path.join(GRPC_ROOT, 'src/compiler')
GRPC_PYTHON_PROTOBUF = os.path.join(GRPC_PYTHON_ROOT, GRPC_PYTHON_PROTOBUF = os.path.join(GRPC_PYTHON_ROOT,
'third_party/protobuf/src') 'third_party/protobuf/src')
@ -93,18 +99,29 @@ GRPC_PYTHON_INCLUDE = os.path.join(GRPC_PYTHON_ROOT, 'grpc_root/include')
BAZEL_DEPS = os.path.join(GRPC_ROOT, 'tools/distrib/python/bazel_deps.sh') BAZEL_DEPS = os.path.join(GRPC_ROOT, 'tools/distrib/python/bazel_deps.sh')
BAZEL_DEPS_PROTOC_LIB_QUERY = '//:protoc_lib' BAZEL_DEPS_PROTOC_LIB_QUERY = '//:protoc_lib'
BAZEL_DEPS_COMMON_PROTOS_QUERY = '//:well_known_protos'
def bazel_query(query):
output = subprocess.check_output([BAZEL_DEPS, query])
return output.splitlines()
def get_deps(query): def get_deps():
"""Write the result of the bazel query `query` against protobuf to """Write the result of the bazel query `query` against protobuf to
`out_file`.""" `out_file`."""
output = subprocess.check_output([BAZEL_DEPS, query]) cc_files_output = bazel_query(BAZEL_DEPS_PROTOC_LIB_QUERY)
output = output.splitlines()
cc_files = [ cc_files = [
name for name in output name[len(PROTOBUF_CC_PREFIX):] for name in cc_files_output
if name.endswith('.cc') and name.startswith(PROTOBUF_CC_PREFIX)] if name.endswith('.cc') and name.startswith(PROTOBUF_CC_PREFIX)]
cc_files = [cc_file[len(PROTOBUF_CC_PREFIX):] for cc_file in cc_files] proto_files_output = bazel_query(BAZEL_DEPS_COMMON_PROTOS_QUERY)
deps_file_content = DEPS_FILE_CONTENT.format(cc_files) proto_files = [
name[len(PROTOBUF_PROTO_PREFIX):] for name in proto_files_output
if name.endswith('.proto') and name.startswith(PROTOBUF_PROTO_PREFIX)]
deps_file_content = DEPS_FILE_CONTENT.format(
cc_files=cc_files,
proto_files=proto_files,
cc_include=repr(GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT),
proto_include=repr(GRPC_PYTHON_PROTOBUF_RELATIVE_ROOT))
return deps_file_content return deps_file_content
@ -123,7 +140,7 @@ def main():
shutil.copytree(GRPC_INCLUDE, GRPC_PYTHON_INCLUDE) shutil.copytree(GRPC_INCLUDE, GRPC_PYTHON_INCLUDE)
try: try:
protoc_lib_deps_content = get_deps(BAZEL_DEPS_PROTOC_LIB_QUERY) protoc_lib_deps_content = get_deps()
except Exception as error: except Exception as error:
# We allow this script to succeed even if we couldn't get the dependencies, # We allow this script to succeed even if we couldn't get the dependencies,
# as then we can assume that even without a successful bazel run the # as then we can assume that even without a successful bazel run the

@ -41,3 +41,10 @@ RUN /opt/python/cp27-cp27mu/bin/pip install cython
RUN /opt/python/cp34-cp34m/bin/pip install cython RUN /opt/python/cp34-cp34m/bin/pip install cython
RUN /opt/python/cp35-cp35m/bin/pip install cython RUN /opt/python/cp35-cp35m/bin/pip install cython
####################################################
# Install auditwheel with fix for namespace packages
RUN git clone https://github.com/pypa/auditwheel /usr/local/src/auditwheel
RUN cd /usr/local/src/auditwheel && git checkout bf071b38c9fe78b025ea05c78b1cb61d7cb09939
RUN /opt/python/cp35-cp35m/bin/pip install /usr/local/src/auditwheel
RUN rm /usr/local/bin/auditwheel
RUN cd /usr/local/bin && ln -s /opt/python/cp35-cp35m/bin/auditwheel

@ -41,3 +41,10 @@ RUN /opt/python/cp27-cp27mu/bin/pip install cython
RUN /opt/python/cp34-cp34m/bin/pip install cython RUN /opt/python/cp34-cp34m/bin/pip install cython
RUN /opt/python/cp35-cp35m/bin/pip install cython RUN /opt/python/cp35-cp35m/bin/pip install cython
####################################################
# Install auditwheel with fix for namespace packages
RUN git clone https://github.com/pypa/auditwheel /usr/local/src/auditwheel
RUN cd /usr/local/src/auditwheel && git checkout bf071b38c9fe78b025ea05c78b1cb61d7cb09939
RUN /opt/python/cp35-cp35m/bin/pip install /usr/local/src/auditwheel
RUN rm /usr/local/bin/auditwheel
RUN cd /usr/local/bin && ln -s /opt/python/cp35-cp35m/bin/auditwheel

@ -59,12 +59,14 @@ ${SETARCH_CMD} ${PYTHON} setup.py \
${SETARCH_CMD} ${PYTHON} setup.py \ ${SETARCH_CMD} ${PYTHON} setup.py \
bdist_wheel bdist_wheel
# Build gRPC tools package distribution
${PYTHON} tools/distrib/python/make_grpcio_tools.py
# Build gRPC tools package source distribution # Build gRPC tools package source distribution
${SETARCH_CMD} ${PYTHON} tools/distrib/python/grpcio_tools/setup.py \ ${SETARCH_CMD} ${PYTHON} tools/distrib/python/grpcio_tools/setup.py \
sdist sdist
# Build gRPC tools package binary distribution # Build gRPC tools package binary distribution
${PYTHON} tools/distrib/python/make_grpcio_tools.py
CFLAGS="$CFLAGS -fno-wrapv" ${SETARCH_CMD} \ CFLAGS="$CFLAGS -fno-wrapv" ${SETARCH_CMD} \
${PYTHON} tools/distrib/python/grpcio_tools/setup.py bdist_wheel ${PYTHON} tools/distrib/python/grpcio_tools/setup.py bdist_wheel

@ -73463,6 +73463,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/23f261e44d54a2736f6e288128d98db9e5015206"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b" "test/core/end2end/fuzzers/server_fuzzer_corpus/2463aea879c5ab49f8409d0e5c062c7e086b034b"
@ -74891,6 +74908,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/552199651d942e7220141a93ec33dd8256210a18"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34" "test/core/end2end/fuzzers/server_fuzzer_corpus/55af20415ead0ddd417f37fa91a4c767b749ee34"
@ -75656,6 +75690,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/7a946bf3cd91b63001f2cf3f40c515c747f2ecde"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f" "test/core/end2end/fuzzers/server_fuzzer_corpus/7b453adcb9c4bf31dbc448ff32c2bc90ebcbdf0f"
@ -75673,6 +75724,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/7d25c28298fb4d0fe41209d0d14307e4aa67c59e"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b" "test/core/end2end/fuzzers/server_fuzzer_corpus/7ddfac7d7845b424bf670070781ca6ff8586c63b"
@ -75724,6 +75792,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/8138b18a9a743659befc2f2b23d23cb9c3086a09"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf" "test/core/end2end/fuzzers/server_fuzzer_corpus/8164d3c4af043c47cfd6966873bccd2353d072bf"
@ -76132,6 +76217,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/925011abb99fd56bb0f425ae5e0d92e6d341f804"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin" "test/core/end2end/fuzzers/server_fuzzer_corpus/93beeba2.bin"
@ -77543,6 +77645,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/crash-c1f66840627e3bfdedf2e4c225bc4de0c267ed37"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/crash-dae0f07934a527989f23f06e630710ff6ca8c809" "test/core/end2end/fuzzers/server_fuzzer_corpus/crash-dae0f07934a527989f23f06e630710ff6ca8c809"
@ -77645,6 +77764,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/d6bed9cc3c10338a8c5f41064ff8bec0bbc267ce"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397" "test/core/end2end/fuzzers/server_fuzzer_corpus/d8a1d141a9e3876b71c7decbe6e3affccf6de397"
@ -77798,6 +77934,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/dda9643679f8c8b796e64232a7d153e447d64991"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19" "test/core/end2end/fuzzers/server_fuzzer_corpus/df5d3cf5f05eab65ef9d385e263780ae73c42b19"
@ -77900,6 +78053,23 @@
], ],
"uses_polling": false "uses_polling": false
}, },
{
"args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/e7b08e36420fa107f0aee652e62158af85a4ef15"
],
"ci_platforms": [
"linux"
],
"cpu_cost": 0.1,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "server_fuzzer_one_entry",
"platforms": [
"linux"
],
"uses_polling": false
},
{ {
"args": [ "args": [
"test/core/end2end/fuzzers/server_fuzzer_corpus/e96ad9c17795e52edc810a08d4fc61fe8790002a" "test/core/end2end/fuzzers/server_fuzzer_corpus/e96ad9c17795e52edc810a08d4fc61fe8790002a"

Loading…
Cancel
Save