From ba2d5a678da64109e6e0d79d5fdceecd3ae2b7d3 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 27 Sep 2016 14:33:06 -0700 Subject: [PATCH 001/104] Remove deprecated V8 function call in Node library --- src/node/ext/call.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 9f023b58831..b585282d329 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -613,8 +613,8 @@ NAN_METHOD(Call::New) { return Nan::ThrowTypeError("Call's fourth argument must be a string"); } call = new Call(wrapped_call); - info.This()->SetHiddenValue(Nan::New("channel_").ToLocalChecked(), - channel_object); + Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(), + channel_object); } call->Wrap(info.This()); info.GetReturnValue().Set(info.This()); From dc23046b065493807f0ca0b09907d03d96baeb5c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 25 Oct 2016 14:12:42 -0700 Subject: [PATCH 002/104] Add electron support and build electron artifacts --- binding.gyp | 132 ++++++++++++++---------- templates/binding.gyp.template | 117 +++++++++++++++------ tools/run_tests/build_artifact_node.bat | 10 +- tools/run_tests/build_artifact_node.sh | 8 ++ 4 files changed, 185 insertions(+), 82 deletions(-) diff --git a/binding.gyp b/binding.gyp index 8b23cc2e7df..023a67533a6 100644 --- a/binding.gyp +++ b/binding.gyp @@ -37,15 +37,59 @@ # Some of this file is built with the help of # https://n8.io/converting-a-c-library-to-gyp/ { + 'variables': { + 'runtime%': 'node' + }, 'target_defaults': { 'include_dirs': [ '.', 'include' ], + 'defines': [ + 'GPR_BACKWARDS_COMPATIBILITY_MODE' + ], 'conditions': [ + # This is the condition for using boringssl + ['OS=="win" or runtime=="electron"', { + "include_dirs": [ + "third_party/boringssl/include" + ], + "defines": [ + 'OPENSSL_NO_ASM', + 'OPENSSL_NO_THREADS' + ] + }, { + # Based on logic above, we know that this must be a non-Windows system + 'variables': { + # The output of "node --version" is "v[version]". We use cut to + # remove the first character. + 'target%': '0. + # io.js always reports versions >0 and always exports ALPN symbols. + # Therefore, Node's major version will be truthy if and only if it + # supports ALPN. The target is "[major].[minor].[patch]". We split by + # periods and take the first field to get the major version. + 'defines': [ + 'TSI_OPENSSL_ALPN_SUPPORT=0. - # io.js always reports versions >0 and always exports ALPN symbols. - # Therefore, Node's major version will be truthy if and only if it - # supports ALPN. The target is "[major].[minor].[patch]". We split by - # periods and take the first field to get the major version. - 'defines': [ - 'TSI_OPENSSL_ALPN_SUPPORT=0. + # io.js always reports versions >0 and always exports ALPN symbols. + # Therefore, Node's major version will be truthy if and only if it + # supports ALPN. The target is "[major].[minor].[patch]". We split by + # periods and take the first field to get the major version. + 'defines': [ + 'TSI_OPENSSL_ALPN_SUPPORT=0. - # io.js always reports versions >0 and always exports ALPN symbols. - # Therefore, Node's major version will be truthy if and only if it - # supports ALPN. The target is "[major].[minor].[patch]". We split by - # periods and take the first field to get the major version. - 'defines': [ - 'TSI_OPENSSL_ALPN_SUPPORT= Date: Thu, 27 Oct 2016 11:30:50 -0700 Subject: [PATCH 003/104] libuv changes don't work with Electron --- binding.gyp | 8 ++++++-- templates/binding.gyp.template | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/binding.gyp b/binding.gyp index 92360a43637..141104ac7cf 100644 --- a/binding.gyp +++ b/binding.gyp @@ -46,10 +46,14 @@ 'include' ], 'defines': [ - 'GPR_BACKWARDS_COMPATIBILITY_MODE', - 'GRPC_UV' + 'GPR_BACKWARDS_COMPATIBILITY_MODE' ], 'conditions': [ + ['runtime=="node"', { + 'defines': [ + 'GRPC_UV' + ] + }], # This is the condition for using boringssl ['OS=="win" or runtime=="electron"', { "include_dirs": [ diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template index 2fc840daad1..9b9e4e116d0 100644 --- a/templates/binding.gyp.template +++ b/templates/binding.gyp.template @@ -48,10 +48,14 @@ 'include' ], 'defines': [ - 'GPR_BACKWARDS_COMPATIBILITY_MODE', - 'GRPC_UV' + 'GPR_BACKWARDS_COMPATIBILITY_MODE' ], 'conditions': [ + ['runtime=="node"', { + 'defines': [ + 'GRPC_UV' + ] + }], # This is the condition for using boringssl ['OS=="win" or runtime=="electron"', { "include_dirs": [ From eaf796400169786c33a438c56c41a46d8ed45b02 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 1 Nov 2016 11:05:02 -0700 Subject: [PATCH 004/104] Add test scripts for electron --- package.json | 2 + src/node/test/surface_test.js | 2 + templates/package.json.template | 2 + tools/run_tests/build_node_electron.sh | 45 ++++++++++++++++++++++ tools/run_tests/pre_build_node_electron.sh | 37 ++++++++++++++++++ tools/run_tests/run_node_electron.sh | 44 +++++++++++++++++++++ tools/run_tests/run_tests.py | 34 +++++++++++++--- 7 files changed, 160 insertions(+), 6 deletions(-) create mode 100755 tools/run_tests/build_node_electron.sh create mode 100755 tools/run_tests/pre_build_node_electron.sh create mode 100755 tools/run_tests/run_node_electron.sh diff --git a/package.json b/package.json index 9afba318162..a6081ba4850 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "scripts": { "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js --exclude-path=src/node/.jshintignore", "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint", + "electron-build": "./node_modules/.bin/node-pre-gyp configure build --runtime=electron --disturl=https://atom.io/download/atom-shell", "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json", "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test", "install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build" @@ -34,6 +35,7 @@ }, "devDependencies": { "async": "^1.5.0", + "electron-mocha": "^3.1.1", "google-auth-library": "^0.9.2", "google-protobuf": "^3.0.0", "istanbul": "^0.3.21", diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index d8b36dc55cb..17c62d5635e 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -183,6 +183,7 @@ describe('Server.prototype.addProtoService', function() { assert.strictEqual(status.code, grpc.status.UNIMPLEMENTED); done(); }); + call.on('error', function(status) { /* Do nothing */ }); }); it('should respond to a bidi call with UNIMPLEMENTED', function(done) { var call = client.divMany(); @@ -193,6 +194,7 @@ describe('Server.prototype.addProtoService', function() { assert.strictEqual(status.code, grpc.status.UNIMPLEMENTED); done(); }); + call.on('error', function(status) { /* Do nothing */ }); call.end(); }); }); diff --git a/templates/package.json.template b/templates/package.json.template index e9596d4d4cb..b8ce92eb7ac 100644 --- a/templates/package.json.template +++ b/templates/package.json.template @@ -23,6 +23,7 @@ "scripts": { "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js --exclude-path=src/node/.jshintignore", "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint", + "electron-build": "./node_modules/.bin/node-pre-gyp configure build --runtime=electron --disturl=https://atom.io/download/atom-shell", "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json", "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test", "install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build" @@ -36,6 +37,7 @@ }, "devDependencies": { "async": "^1.5.0", + "electron-mocha": "^3.1.1", "google-auth-library": "^0.9.2", "google-protobuf": "^3.0.0", "istanbul": "^0.3.21", diff --git a/tools/run_tests/build_node_electron.sh b/tools/run_tests/build_node_electron.sh new file mode 100755 index 00000000000..4e7c3e4789a --- /dev/null +++ b/tools/run_tests/build_node_electron.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Copyright 2016, 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. + +ELECTRON_VERSION=$1 +source ~/.nvm/nvm.sh + +nvm use 6 +set -ex + +# change to grpc repo root +cd $(dirname $0)/../.. + +export npm_config_target=$ELECTRON_VERSION +export npm_config_disturl=https://atom.io/download/atom-shell +export npm_config_runtime=electron +export npm_config_build_from_source=true +HOME=~/.electron-gyp npm install --unsafe-perm diff --git a/tools/run_tests/pre_build_node_electron.sh b/tools/run_tests/pre_build_node_electron.sh new file mode 100755 index 00000000000..d8d9df4ddbc --- /dev/null +++ b/tools/run_tests/pre_build_node_electron.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Copyright 2016, 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. + +ELECTRON_VERSION=$1 + +nvm install 6 +set -ex + +npm install electron@$ELECTRON_VERSION diff --git a/tools/run_tests/run_node_electron.sh b/tools/run_tests/run_node_electron.sh new file mode 100755 index 00000000000..7f8a824df27 --- /dev/null +++ b/tools/run_tests/run_node_electron.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# 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. + +source ~/.nvm/nvm.sh + +nvm use 6 +set -ex + +# change to grpc repo root +cd $(dirname $0)/../.. + +test_directory='src/node/test' +timeout=8000 + +JUNIT_REPORT_PATH=src/node/report.xml JUNIT_REPORT_STACK=1 \ + ./node_modules/.bin/electron-mocha --timeout $timeout \ + --reporter mocha-jenkins-reporter $test_directory diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index db261d98c29..70da0cc0e32 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -362,19 +362,31 @@ class NodeLanguage(object): def configure(self, config, args): self.config = config self.args = args + # Note: electron ABI only depends on major and minor version, so that's all + # we should specify in the compiler argument _check_compiler(self.args.compiler, ['default', 'node0.12', - 'node4', 'node5', 'node6']) + 'node4', 'node5', 'node6', + 'electron1.3']) if self.args.compiler == 'default': self.node_version = '4' else: - # Take off the word "node" - self.node_version = self.args.compiler[4:] + if self.args.compiler.startswith('electron'): + self.runtime = 'electron' + self.node_version = self.args.compiler[8:] + else: + self.runtime = 'node' + # Take off the word "node" + self.node_version = self.args.compiler[4:] def test_specs(self): if self.platform == 'windows': return [self.config.job_spec(['tools\\run_tests\\run_node.bat'], None)] else: - return [self.config.job_spec(['tools/run_tests/run_node.sh', self.node_version], + run_script = 'run_node' + if self.runtime == 'electron': + run_script += '_electron' + return [self.config.job_spec(['tools/run_tests/{}.sh'.format(run_script), + self.node_version], None, environ=_FORCE_ENVIRON_FOR_WRAPPERS)] @@ -382,7 +394,10 @@ class NodeLanguage(object): if self.platform == 'windows': return [['tools\\run_tests\\pre_build_node.bat']] else: - return [['tools/run_tests/pre_build_node.sh', self.node_version]] + build_script = 'pre_build_node' + if self.runtime == 'electron': + build_script += '_electron' + return [['tools/run_tests/{}.sh'.format(build_script), self.node_version]] def make_targets(self): return [] @@ -394,7 +409,12 @@ class NodeLanguage(object): if self.platform == 'windows': return [['tools\\run_tests\\build_node.bat']] else: - return [['tools/run_tests/build_node.sh', self.node_version]] + build_script = 'build_node' + if self.runtime == 'electron': + build_script += '_electron' + # building for electron requires a patch version + self.node_version += '.0' + return [['tools/run_tests/{}.sh'.format(build_script), self.node_version]] def post_tests_steps(self): return [] @@ -1016,6 +1036,8 @@ argp.add_argument('--compiler', 'clang3.4', 'clang3.5', 'clang3.6', 'clang3.7', 'vs2010', 'vs2013', 'vs2015', 'python2.7', 'python3.4', 'python3.5', 'python3.6', 'pypy', 'pypy3', + 'node0.12', 'node4', 'node5', 'node6', + 'electron1.3', 'coreclr'], default='default', help='Selects compiler to use. Allowed values depend on the platform and language.') From 013d203d5d53a1c8b6119c2c6bc535863e7b22e6 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 1 Nov 2016 13:05:24 -0700 Subject: [PATCH 005/104] Refactor uv/non-uv code in Node extension --- binding.gyp | 4 +- build.yaml | 5 +- src/node/ext/completion_queue.h | 1 + ...rker.cc => completion_queue_threadpool.cc} | 63 ++++++++++++++++++- ...letion_queue.cc => completion_queue_uv.cc} | 17 ++--- 5 files changed, 71 insertions(+), 19 deletions(-) rename src/node/ext/{completion_queue_async_worker.cc => completion_queue_threadpool.cc} (72%) rename src/node/ext/{completion_queue.cc => completion_queue_uv.cc} (93%) diff --git a/binding.gyp b/binding.gyp index 7dd32546d9e..5455becae10 100644 --- a/binding.gyp +++ b/binding.gyp @@ -859,8 +859,8 @@ "src/node/ext/call_credentials.cc", "src/node/ext/channel.cc", "src/node/ext/channel_credentials.cc", - "src/node/ext/completion_queue.cc", - "src/node/ext/completion_queue_async_worker.cc", + "src/node/ext/completion_queue_threadpool.cc", + "src/node/ext/completion_queue_uv.cc", "src/node/ext/node_grpc.cc", "src/node/ext/server.cc", "src/node/ext/server_credentials.cc", diff --git a/build.yaml b/build.yaml index f86d896f6e3..d552a290b29 100644 --- a/build.yaml +++ b/build.yaml @@ -3710,7 +3710,6 @@ node_modules: - src/node/ext/channel.h - src/node/ext/channel_credentials.h - src/node/ext/completion_queue.h - - src/node/ext/completion_queue_async_worker.h - src/node/ext/server.h - src/node/ext/server_credentials.h - src/node/ext/timeval.h @@ -3729,8 +3728,8 @@ node_modules: - src/node/ext/call_credentials.cc - src/node/ext/channel.cc - src/node/ext/channel_credentials.cc - - src/node/ext/completion_queue.cc - - src/node/ext/completion_queue_async_worker.cc + - src/node/ext/completion_queue_threadpool.cc + - src/node/ext/completion_queue_uv.cc - src/node/ext/node_grpc.cc - src/node/ext/server.cc - src/node/ext/server_credentials.cc diff --git a/src/node/ext/completion_queue.h b/src/node/ext/completion_queue.h index bf280f768b0..9b01028ef17 100644 --- a/src/node/ext/completion_queue.h +++ b/src/node/ext/completion_queue.h @@ -32,6 +32,7 @@ */ #include +#include namespace grpc { namespace node { diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_threadpool.cc similarity index 72% rename from src/node/ext/completion_queue_async_worker.cc rename to src/node/ext/completion_queue_threadpool.cc index f5e03b277b3..6302e7a103b 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_threadpool.cc @@ -31,18 +31,63 @@ * */ +/* I don't like using #ifndef, but I don't see a better way to do this */ +#ifndef GRPC_UV + #include #include #include "grpc/grpc.h" #include "grpc/support/log.h" #include "grpc/support/time.h" -#include "completion_queue_async_worker.h" +#include "completion_queue.h" #include "call.h" namespace grpc { namespace node { +namespace { + +/* A worker that asynchronously calls completion_queue_next, and queues onto the + node event loop a call to the function stored in the event's tag. */ +class CompletionQueueAsyncWorker : public Nan::AsyncWorker { + public: + CompletionQueueAsyncWorker(); + + ~CompletionQueueAsyncWorker(); + /* Calls completion_queue_next with the provided deadline, and stores the + event if there was one or sets an error message if there was not */ + void Execute(); + + /* Returns the completion queue attached to this class */ + static grpc_completion_queue *GetQueue(); + + /* Convenience function to create a worker with the given arguments and queue + it to run asynchronously */ + static void Next(); + + /* Initialize the CompletionQueueAsyncWorker class */ + static void Init(v8::Local exports); + + protected: + /* Called when Execute has succeeded (completed without setting an error + message). Calls the saved callback with the event that came from + completion_queue_next */ + void HandleOKCallback(); + + void HandleErrorCallback(); + + private: + grpc_event result; + + static grpc_completion_queue *queue; + + // Number of grpc_completion_queue_next calls in the thread pool + static int current_threads; + // Number of grpc_completion_queue_next calls waiting to enter the thread pool + static int waiting_next_calls; +}; + const int max_queue_threads = 2; using v8::Function; @@ -137,5 +182,21 @@ void CompletionQueueAsyncWorker::HandleErrorCallback() { DestroyTag(result.tag); } +} // namespace + +grpc_completion_queue *GetCompletionQueue() { + return CompletionQueueAsyncWorker::GetQueue(); +} + +void CompletionQueueNext() { + CompletionQueueAsyncWorker::Next(); +} + +void CompletionQueueInit(Local exports) { + CompletionQueueAsyncWorker::Init(exports); +} + } // namespace node } // namespace grpc + +#endif /* GRPC_UV */ diff --git a/src/node/ext/completion_queue.cc b/src/node/ext/completion_queue_uv.cc similarity index 93% rename from src/node/ext/completion_queue.cc rename to src/node/ext/completion_queue_uv.cc index fcfa77b39ce..615973a6c9b 100644 --- a/src/node/ext/completion_queue.cc +++ b/src/node/ext/completion_queue_uv.cc @@ -31,6 +31,8 @@ * */ +#ifdef GRPC_UV + #include #include #include @@ -38,7 +40,6 @@ #include "call.h" #include "completion_queue.h" -#include "completion_queue_async_worker.h" namespace grpc { namespace node { @@ -81,34 +82,24 @@ void drain_completion_queue(uv_prepare_t *handle) { } grpc_completion_queue *GetCompletionQueue() { -#ifdef GRPC_UV return queue; -#else - return CompletionQueueAsyncWorker::GetQueue(); -#endif } void CompletionQueueNext() { -#ifdef GRPC_UV if (pending_batches == 0) { GPR_ASSERT(!uv_is_active((uv_handle_t *)&prepare)); uv_prepare_start(&prepare, drain_completion_queue); } pending_batches++; -#else - CompletionQueueAsyncWorker::Next(); -#endif } void CompletionQueueInit(Local exports) { -#ifdef GRPC_UV queue = grpc_completion_queue_create(NULL); uv_prepare_init(uv_default_loop(), &prepare); pending_batches = 0; -#else - CompletionQueueAsyncWorker::Init(exports); -#endif } } // namespace node } // namespace grpc + +#endif /* GRPC_UV */ From 0d3ea83b69f15c37a8e46aad92bd453e2e63b173 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Thu, 17 Nov 2016 01:25:27 -0800 Subject: [PATCH 006/104] Update CronetFramework version number to 1.0.0 and use new URL --- src/objective-c/CronetFramework.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/CronetFramework.podspec b/src/objective-c/CronetFramework.podspec index 2f47b02c0c0..538479b96bc 100644 --- a/src/objective-c/CronetFramework.podspec +++ b/src/objective-c/CronetFramework.podspec @@ -30,7 +30,7 @@ Pod::Spec.new do |s| s.name = "CronetFramework" - s.version = "0.0.3" + s.version = "1.0.0" s.summary = "Cronet, precompiled and used as a framework." s.homepage = "http://chromium.org" s.license = { @@ -69,7 +69,7 @@ Pod::Spec.new do |s| s.vendored_framework = "Cronet.framework" s.author = "The Chromium Authors" s.ios.deployment_target = "8.0" - s.source = { :http => 'https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework.zip' } + s.source = { :http => 'https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework-1.0.0.zip' } s.preserve_paths = "Cronet.framework" s.public_header_files = "Cronet.framework/Headers/**/*{.h}" s.source_files = "Cronet.framework/Headers/**/*{.h}" From a0ed373d3cb6d93b55ebe753b276c2ddf1fc7b65 Mon Sep 17 00:00:00 2001 From: Garrett Casto Date: Mon, 7 Nov 2016 20:36:31 -0800 Subject: [PATCH 007/104] Change interface --- BUILD | 2 +- build.yaml | 2 +- .../client/secure/cronet_channel_create.c | 2 +- .../cronet/transport/cronet_api_dummy.c | 29 +-- .../cronet/transport/cronet_transport.c | 116 ++++----- src/objective-c/GRPCClient/GRPCCall+Cronet.h | 6 +- src/objective-c/GRPCClient/GRPCCall+Cronet.m | 6 +- .../GRPCClient/private/GRPCChannel.m | 4 +- third_party/Cronet/bidirectional_stream_c.h | 246 ++++++++++++++++++ .../objective_c/Cronet/cronet_c_for_grpc.h | 202 -------------- tools/run_tests/sources_and_headers.json | 2 +- 11 files changed, 330 insertions(+), 287 deletions(-) create mode 100644 third_party/Cronet/bidirectional_stream_c.h delete mode 100644 third_party/objective_c/Cronet/cronet_c_for_grpc.h diff --git a/BUILD b/BUILD index f80e5f06646..955cb73af5e 100644 --- a/BUILD +++ b/BUILD @@ -687,7 +687,7 @@ cc_library( "src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/transport.h", "src/core/lib/transport/transport_impl.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h", + "third_party/Cronet/bidirectional_stream_c.h", "src/core/ext/transport/chttp2/transport/bin_decoder.h", "src/core/ext/transport/chttp2/transport/bin_encoder.h", "src/core/ext/transport/chttp2/transport/chttp2_transport.h", diff --git a/build.yaml b/build.yaml index 407b50ca7b9..24f34ad77f8 100644 --- a/build.yaml +++ b/build.yaml @@ -657,7 +657,7 @@ filegroups: - include/grpc/grpc_security.h - include/grpc/grpc_security_constants.h headers: - - third_party/objective_c/Cronet/cronet_c_for_grpc.h + - third_party/Cronet/bidirectional_stream_c.h src: - src/core/ext/transport/cronet/client/secure/cronet_channel_create.c - src/core/ext/transport/cronet/transport/cronet_api_dummy.c diff --git a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c index df1acddcc08..477cf07f45d 100644 --- a/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c +++ b/src/core/ext/transport/cronet/client/secure/cronet_channel_create.c @@ -60,7 +60,7 @@ GRPCAPI grpc_channel *grpc_cronet_secure_channel_create( ct->host = gpr_malloc(strlen(target) + 1); strcpy(ct->host, target); gpr_log(GPR_DEBUG, - "grpc_create_cronet_transport: cronet_engine = %p, target=%s", engine, + "grpc_create_cronet_transport: stream_engine = %p, target=%s", engine, ct->host); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c index 687026c9fde..1c4253f43fe 100644 --- a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c +++ b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c @@ -38,48 +38,47 @@ library, so we can build it in all environments */ #include -#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" +#include "third_party/Cronet/bidirectional_stream_c.h" #ifdef GRPC_COMPILE_WITH_CRONET /* link with the real CRONET library in the build system */ #else /* Dummy implementation of cronet API just to test for build-ability */ -cronet_bidirectional_stream* cronet_bidirectional_stream_create( - cronet_engine* engine, void* annotation, - cronet_bidirectional_stream_callback* callback) { +bidirectional_stream* bidirectional_stream_create( + stream_engine* engine, void* annotation, + bidirectional_stream_callback* callback) { GPR_ASSERT(0); return NULL; } -int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream) { +int bidirectional_stream_destroy(bidirectional_stream* stream) { GPR_ASSERT(0); return 0; } -int cronet_bidirectional_stream_start( - cronet_bidirectional_stream* stream, const char* url, int priority, - const char* method, const cronet_bidirectional_stream_header_array* headers, +int bidirectional_stream_start( + bidirectional_stream* stream, const char* url, int priority, + const char* method, const bidirectional_stream_header_array* headers, bool end_of_stream) { GPR_ASSERT(0); return 0; } -int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, - char* buffer, int capacity) { +int bidirectional_stream_read(bidirectional_stream* stream, + char* buffer, int capacity) { GPR_ASSERT(0); return 0; } -int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, - const char* buffer, int count, - bool end_of_stream) { +int bidirectional_stream_write(bidirectional_stream* stream, + const char* buffer, int count, + bool end_of_stream) { GPR_ASSERT(0); return 0; } -int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream) { +void bidirectional_stream_cancel(bidirectional_stream* stream) { GPR_ASSERT(0); - return 0; } #endif /* GRPC_COMPILE_WITH_CRONET */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index a4c110101ec..28c4fbe9fe1 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -49,7 +49,7 @@ #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/transport_impl.h" -#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h" +#include "third_party/Cronet/bidirectional_stream_c.h" #define GRPC_HEADER_SIZE_IN_BYTES 5 @@ -86,19 +86,19 @@ enum e_op_id { /* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */ -static void on_request_headers_sent(cronet_bidirectional_stream *); +static void on_request_headers_sent(bidirectional_stream *); static void on_response_headers_received( - cronet_bidirectional_stream *, - const cronet_bidirectional_stream_header_array *, const char *); -static void on_write_completed(cronet_bidirectional_stream *, const char *); -static void on_read_completed(cronet_bidirectional_stream *, char *, int); + bidirectional_stream *, + const bidirectional_stream_header_array *, const char *); +static void on_write_completed(bidirectional_stream *, const char *); +static void on_read_completed(bidirectional_stream *, char *, int); static void on_response_trailers_received( - cronet_bidirectional_stream *, - const cronet_bidirectional_stream_header_array *); -static void on_succeeded(cronet_bidirectional_stream *); -static void on_failed(cronet_bidirectional_stream *, int); -static void on_canceled(cronet_bidirectional_stream *); -static cronet_bidirectional_stream_callback cronet_callbacks = { + bidirectional_stream *, + const bidirectional_stream_header_array *); +static void on_succeeded(bidirectional_stream *); +static void on_failed(bidirectional_stream *, int); +static void on_canceled(bidirectional_stream *); +static bidirectional_stream_callback cronet_callbacks = { on_request_headers_sent, on_response_headers_received, on_read_completed, @@ -111,7 +111,7 @@ static cronet_bidirectional_stream_callback cronet_callbacks = { /* Cronet transport object */ struct grpc_cronet_transport { grpc_transport base; /* must be first element in this structure */ - cronet_engine *engine; + stream_engine *engine; char *host; }; typedef struct grpc_cronet_transport grpc_cronet_transport; @@ -173,8 +173,8 @@ struct stream_obj { grpc_transport_stream_op *curr_op; grpc_cronet_transport curr_ct; grpc_stream *curr_gs; - cronet_bidirectional_stream *cbs; - cronet_bidirectional_stream_header_array header_array; + bidirectional_stream *cbs; + bidirectional_stream_header_array header_array; /* Stream level state. Some state will be tracked both at stream and stream_op * level */ @@ -335,11 +335,11 @@ static void execute_from_storage(stream_obj *s) { /* Cronet callback */ -static void on_failed(cronet_bidirectional_stream *stream, int net_error) { +static void on_failed(bidirectional_stream *stream, int net_error) { CRONET_LOG(GPR_DEBUG, "on_failed(%p, %d)", stream, net_error); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); - cronet_bidirectional_stream_destroy(s->cbs); + bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_FAILED] = true; s->cbs = NULL; if (s->header_array.headers) { @@ -358,11 +358,11 @@ static void on_failed(cronet_bidirectional_stream *stream, int net_error) { /* Cronet callback */ -static void on_canceled(cronet_bidirectional_stream *stream) { +static void on_canceled(bidirectional_stream *stream) { CRONET_LOG(GPR_DEBUG, "on_canceled(%p)", stream); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); - cronet_bidirectional_stream_destroy(s->cbs); + bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_CANCELED] = true; s->cbs = NULL; if (s->header_array.headers) { @@ -381,11 +381,11 @@ static void on_canceled(cronet_bidirectional_stream *stream) { /* Cronet callback */ -static void on_succeeded(cronet_bidirectional_stream *stream) { +static void on_succeeded(bidirectional_stream *stream) { CRONET_LOG(GPR_DEBUG, "on_succeeded(%p)", stream); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); - cronet_bidirectional_stream_destroy(s->cbs); + bidirectional_stream_destroy(s->cbs); s->state.state_callback_received[OP_SUCCEEDED] = true; s->cbs = NULL; free_read_buffer(s); @@ -396,7 +396,7 @@ static void on_succeeded(cronet_bidirectional_stream *stream) { /* Cronet callback */ -static void on_request_headers_sent(cronet_bidirectional_stream *stream) { +static void on_request_headers_sent(bidirectional_stream *stream) { CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream); stream_obj *s = (stream_obj *)stream->annotation; gpr_mu_lock(&s->mu); @@ -415,8 +415,8 @@ static void on_request_headers_sent(cronet_bidirectional_stream *stream) { Cronet callback */ static void on_response_headers_received( - cronet_bidirectional_stream *stream, - const cronet_bidirectional_stream_header_array *headers, + bidirectional_stream *stream, + const bidirectional_stream_header_array *headers, const char *negotiated_protocol) { CRONET_LOG(GPR_DEBUG, "R: on_response_headers_received(%p, %p, %s)", stream, headers, negotiated_protocol); @@ -440,7 +440,7 @@ static void on_response_headers_received( /* Cronet callback */ -static void on_write_completed(cronet_bidirectional_stream *stream, +static void on_write_completed(bidirectional_stream *stream, const char *data) { stream_obj *s = (stream_obj *)stream->annotation; CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data); @@ -457,7 +457,7 @@ static void on_write_completed(cronet_bidirectional_stream *stream, /* Cronet callback */ -static void on_read_completed(cronet_bidirectional_stream *stream, char *data, +static void on_read_completed(bidirectional_stream *stream, char *data, int count) { stream_obj *s = (stream_obj *)stream->annotation; CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data, @@ -468,9 +468,9 @@ static void on_read_completed(cronet_bidirectional_stream *stream, char *data, s->state.rs.received_bytes += count; s->state.rs.remaining_bytes -= count; if (s->state.rs.remaining_bytes > 0) { - CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs); + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); s->state.state_op_done[OP_READ_REQ_MADE] = true; - cronet_bidirectional_stream_read( + bidirectional_stream_read( s->cbs, s->state.rs.read_buffer + s->state.rs.received_bytes, s->state.rs.remaining_bytes); gpr_mu_unlock(&s->mu); @@ -489,8 +489,8 @@ static void on_read_completed(cronet_bidirectional_stream *stream, char *data, Cronet callback */ static void on_response_trailers_received( - cronet_bidirectional_stream *stream, - const cronet_bidirectional_stream_header_array *trailers) { + bidirectional_stream *stream, + const bidirectional_stream_header_array *trailers) { CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream, trailers); stream_obj *s = (stream_obj *)stream->annotation; @@ -543,7 +543,7 @@ static void create_grpc_frame(grpc_slice_buffer *write_slice_buffer, */ static void convert_metadata_to_cronet_headers( grpc_linked_mdelem *head, const char *host, char **pp_url, - cronet_bidirectional_stream_header **pp_headers, size_t *p_num_headers, + bidirectional_stream_header **pp_headers, size_t *p_num_headers, const char **method) { grpc_linked_mdelem *curr = head; /* Walk the linked list and get number of header fields */ @@ -554,9 +554,9 @@ static void convert_metadata_to_cronet_headers( } /* Allocate enough memory. It is freed in the on_request_headers_sent callback */ - cronet_bidirectional_stream_header *headers = - (cronet_bidirectional_stream_header *)gpr_malloc( - sizeof(cronet_bidirectional_stream_header) * num_headers_available); + bidirectional_stream_header *headers = + (bidirectional_stream_header *)gpr_malloc( + sizeof(bidirectional_stream_header) * num_headers_available); *pp_headers = headers; /* Walk the linked list again, this time copying the header fields. @@ -788,9 +788,9 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled, * on_failed */ GPR_ASSERT(s->cbs == NULL); - s->cbs = cronet_bidirectional_stream_create(s->curr_ct.engine, s->curr_gs, - &cronet_callbacks); - CRONET_LOG(GPR_DEBUG, "%p = cronet_bidirectional_stream_create()", s->cbs); + s->cbs = bidirectional_stream_create(s->curr_ct.engine, s->curr_gs, + &cronet_callbacks); + CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs); char *url = NULL; const char *method = "POST"; s->header_array.headers = NULL; @@ -798,10 +798,10 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url, &s->header_array.headers, &s->header_array.count, &method); s->header_array.capacity = s->header_array.count; - CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_start(%p, %s)", s->cbs, + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); - cronet_bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, - false); + bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, + false); stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; result = ACTION_TAKEN_WITH_CALLBACK; } else if (stream_op->recv_initial_metadata && @@ -849,11 +849,11 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, size_t write_buffer_size; create_grpc_frame(&write_slice_buffer, &stream_state->ws.write_buffer, &write_buffer_size); - CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, %p)", + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, %p)", s->cbs, stream_state->ws.write_buffer); stream_state->state_callback_received[OP_SEND_MESSAGE] = false; - cronet_bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer, - (int)write_buffer_size, false); + bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer, + (int)write_buffer_size, false); result = ACTION_TAKEN_WITH_CALLBACK; } else { result = NO_ACTION_POSSIBLE; @@ -893,11 +893,11 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, GPR_ASSERT(stream_state->rs.read_buffer); stream_state->rs.remaining_bytes = stream_state->rs.length_field; stream_state->rs.received_bytes = 0; - CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs); + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); stream_state->state_op_done[OP_READ_REQ_MADE] = true; /* Indicates that at least one read request has been made */ - cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, - stream_state->rs.remaining_bytes); + bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, + stream_state->rs.remaining_bytes); result = ACTION_TAKEN_WITH_CALLBACK; } else { stream_state->rs.remaining_bytes = 0; @@ -918,11 +918,11 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; stream_state->rs.received_bytes = 0; - CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs); + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); stream_state->state_op_done[OP_READ_REQ_MADE] = true; /* Indicates that at least one read request has been made */ - cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, - stream_state->rs.remaining_bytes); + bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, + stream_state->rs.remaining_bytes); result = ACTION_TAKEN_WITH_CALLBACK; } else { result = NO_ACTION_POSSIBLE; @@ -972,10 +972,10 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, result = NO_ACTION_POSSIBLE; CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); } else { - CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, 0)", + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); stream_state->state_callback_received[OP_SEND_MESSAGE] = false; - cronet_bidirectional_stream_write(s->cbs, "", 0, true); + bidirectional_stream_write(s->cbs, "", 0, true); result = ACTION_TAKEN_WITH_CALLBACK; } stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true; @@ -983,9 +983,9 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, op_can_be_run(stream_op, stream_state, &oas->state, OP_CANCEL_ERROR)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas); - CRONET_LOG(GPR_DEBUG, "W: cronet_bidirectional_stream_cancel(%p)", s->cbs); + CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs); if (s->cbs) { - cronet_bidirectional_stream_cancel(s->cbs); + bidirectional_stream_cancel(s->cbs); } stream_state->state_op_done[OP_CANCEL_ERROR] = true; result = ACTION_TAKEN_WITH_CALLBACK; @@ -1064,9 +1064,9 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, header_has_authority(op->send_initial_metadata->list.head)) { /* Cronet does not support :authority header field. We cancel the call when this field is present in metadata */ - cronet_bidirectional_stream_header_array header_array; - cronet_bidirectional_stream_header *header; - cronet_bidirectional_stream cbs; + bidirectional_stream_header_array header_array; + bidirectional_stream_header *header; + bidirectional_stream cbs; CRONET_LOG(GPR_DEBUG, ":authority header is provided but not supported;" " cancel operations"); @@ -1074,8 +1074,8 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, header_array.count = 1; header_array.capacity = 1; header_array.headers = - gpr_malloc(sizeof(cronet_bidirectional_stream_header)); - header = (cronet_bidirectional_stream_header *)header_array.headers; + gpr_malloc(sizeof(bidirectional_stream_header)); + header = (bidirectional_stream_header *)header_array.headers; header->key = "grpc-status"; header->value = "1"; /* Return status GRPC_STATUS_CANCELLED */ cbs.annotation = (void *)s; diff --git a/src/objective-c/GRPCClient/GRPCCall+Cronet.h b/src/objective-c/GRPCClient/GRPCCall+Cronet.h index 2d8f7ac8fb9..b9d286c929a 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Cronet.h +++ b/src/objective-c/GRPCClient/GRPCCall+Cronet.h @@ -43,13 +43,13 @@ /** * This method should be called before issuing the first RPC. It should be * called only once. Create an instance of Cronet engine in your app elsewhere - * and pass the instance pointer in the cronet_engine parameter. Once set, + * and pass the instance pointer in the stream_engine parameter. Once set, * all subsequent RPCs will use Cronet transport. The method is not thread * safe. */ -+(void)useCronetWithEngine:(cronet_engine *)engine; ++(void)useCronetWithEngine:(stream_engine *)engine; -+(cronet_engine *)cronetEngine; ++(stream_engine *)cronetEngine; +(BOOL)isUsingCronet; diff --git a/src/objective-c/GRPCClient/GRPCCall+Cronet.m b/src/objective-c/GRPCClient/GRPCCall+Cronet.m index 76ca1a2537c..0e3598fb87d 100644 --- a/src/objective-c/GRPCClient/GRPCCall+Cronet.m +++ b/src/objective-c/GRPCClient/GRPCCall+Cronet.m @@ -35,16 +35,16 @@ #ifdef GRPC_COMPILE_WITH_CRONET static BOOL useCronet = NO; -static cronet_engine *globalCronetEngine; +static stream_engine *globalCronetEngine; @implementation GRPCCall (Cronet) -+ (void)useCronetWithEngine:(cronet_engine *)engine { ++ (void)useCronetWithEngine:(stream_engine *)engine { useCronet = YES; globalCronetEngine = engine; } -+ (cronet_engine *)cronetEngine { ++ (stream_engine *)cronetEngine { return globalCronetEngine; } diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m index e49aceefe18..2397c929f70 100644 --- a/src/objective-c/GRPCClient/private/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCChannel.m @@ -108,7 +108,7 @@ static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { #ifdef GRPC_COMPILE_WITH_CRONET - (instancetype)initWithHost:(NSString *)host - cronetEngine:(cronet_engine *)cronetEngine + cronetEngine:(stream_engine *)cronetEngine channelArgs:(NSDictionary *)channelArgs { if (!host) { [NSException raise:NSInvalidArgumentException format:@"host argument missing"]; @@ -163,7 +163,7 @@ static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) { #ifdef GRPC_COMPILE_WITH_CRONET + (GRPCChannel *)secureCronetChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)channelArgs { - cronet_engine *engine = [GRPCCall cronetEngine]; + stream_engine *engine = [GRPCCall cronetEngine]; if (!engine) { [NSException raise:NSInvalidArgumentException format:@"cronet_engine is NULL. Set it first."]; diff --git a/third_party/Cronet/bidirectional_stream_c.h b/third_party/Cronet/bidirectional_stream_c.h new file mode 100644 index 00000000000..ffb235ae874 --- /dev/null +++ b/third_party/Cronet/bidirectional_stream_c.h @@ -0,0 +1,246 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GRPC_SUPPORT_INCLUDE_BIDIRECTIONAL_STREAM_C_H_ +#define COMPONENTS_GRPC_SUPPORT_INCLUDE_BIDIRECTIONAL_STREAM_C_H_ + +#if defined(WIN32) +#define GRPC_SUPPORT_EXPORT +#else +#define GRPC_SUPPORT_EXPORT __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Engine API. */ + +/* Opaque object representing a Bidirectional stream creating engine. Created + * and configured outside of this API to facilitate sharing with other + * components */ +typedef struct stream_engine { + void* obj; + void* annotation; +} stream_engine; + +/* Bidirectional Stream API */ + +/* Opaque object representing Bidirectional Stream. */ +typedef struct bidirectional_stream { + void* obj; + void* annotation; +} bidirectional_stream; + +/* A single request or response header element. */ +typedef struct bidirectional_stream_header { + const char* key; + const char* value; +} bidirectional_stream_header; + +/* Array of request or response headers or trailers. */ +typedef struct bidirectional_stream_header_array { + size_t count; + size_t capacity; + bidirectional_stream_header* headers; +} bidirectional_stream_header_array; + +/* Set of callbacks used to receive callbacks from bidirectional stream. */ +typedef struct bidirectional_stream_callback { + /* Invoked when the stream is ready for reading and writing. + * Consumer may call bidirectional_stream_read() to start reading data. + * Consumer may call bidirectional_stream_write() to start writing + * data. + */ + void (*on_stream_ready)(bidirectional_stream* stream); + + /* Invoked when initial response headers are received. + * Consumer must call bidirectional_stream_read() to start reading. + * Consumer may call bidirectional_stream_write() to start writing or + * close the stream. Contents of |headers| is valid for duration of the call. + */ + void (*on_response_headers_received)( + bidirectional_stream* stream, + const bidirectional_stream_header_array* headers, + const char* negotiated_protocol); + + /* Invoked when data is read into the buffer passed to + * bidirectional_stream_read(). Only part of the buffer may be + * populated. To continue reading, call bidirectional_stream_read(). + * It may be invoked after on_response_trailers_received()}, if there was + * pending read data before trailers were received. + * + * If |bytes_read| is 0, it means the remote side has signaled that it will + * send no more data; future calls to bidirectional_stream_read() + * will result in the on_data_read() callback or on_succeded() callback if + * bidirectional_stream_write() was invoked with end_of_stream set to + * true. + */ + void (*on_read_completed)(bidirectional_stream* stream, + char* data, + int bytes_read); + + /** + * Invoked when all data passed to bidirectional_stream_write() is + * sent. To continue writing, call bidirectional_stream_write(). + */ + void (*on_write_completed)(bidirectional_stream* stream, const char* data); + + /* Invoked when trailers are received before closing the stream. Only invoked + * when server sends trailers, which it may not. May be invoked while there is + * read data remaining in local buffer. Contents of |trailers| is valid for + * duration of the call. + */ + void (*on_response_trailers_received)( + bidirectional_stream* stream, + const bidirectional_stream_header_array* trailers); + + /** + * Invoked when there is no data to be read or written and the stream is + * closed successfully remotely and locally. Once invoked, no further callback + * methods will be invoked. + */ + void (*on_succeded)(bidirectional_stream* stream); + + /** + * Invoked if the stream failed for any reason after + * bidirectional_stream_start(). HTTP/2 error codes are + * mapped to chrome net error codes. Once invoked, no further callback methods + * will be invoked. + */ + void (*on_failed)(bidirectional_stream* stream, int net_error); + + /** + * Invoked if the stream was canceled via + * bidirectional_stream_cancel(). Once invoked, no further callback + * methods will be invoked. + */ + void (*on_canceled)(bidirectional_stream* stream); +} bidirectional_stream_callback; + +/* Creates a new stream object that uses |engine| and |callback|. All stream + * tasks are performed asynchronously on the |engine| network thread. |callback| + * methods are invoked synchronously on the |engine| network thread, but must + * not run tasks on the current thread to prevent blocking networking operations + * and causing exceptions during shutdown. The |annotation| is stored in + * bidirectional stream for arbitrary use by application. + * + * Returned |bidirectional_stream*| is owned by the caller, and must be + * destroyed using |bidirectional_stream_destroy|. + * + * Both |calback| and |engine| must remain valid until stream is destroyed. + */ +GRPC_SUPPORT_EXPORT +bidirectional_stream* bidirectional_stream_create( + stream_engine* engine, + void* annotation, + bidirectional_stream_callback* callback); + +/* TBD: The following methods return int. Should it be a custom type? */ + +/* Destroys stream object. Destroy could be called from any thread, including + * network thread, but is posted, so |stream| is valid until calling task is + * complete. + */ +GRPC_SUPPORT_EXPORT +int bidirectional_stream_destroy(bidirectional_stream* stream); + +/** + * Disables or enables auto flush. By default, data is flushed after + * every bidirectional_stream_write(). If the auto flush is disabled, + * the client should explicitly call bidirectional_stream_flush to flush + * the data. + */ +GRPC_SUPPORT_EXPORT void bidirectional_stream_disable_auto_flush( + bidirectional_stream* stream, + bool disable_auto_flush); + +/** + * Delays sending request headers until bidirectional_stream_flush() + * is called. This flag is currently only respected when QUIC is negotiated. + * When true, QUIC will send request header frame along with data frame(s) + * as a single packet when possible. + */ +GRPC_SUPPORT_EXPORT +void bidirectional_stream_delay_request_headers_until_flush( + bidirectional_stream* stream, + bool delay_headers_until_flush); + +/* Starts the stream by sending request to |url| using |method| and |headers|. + * If |end_of_stream| is true, then no data is expected to be written. The + * |method| is HTTP verb, with PUT having a special meaning to mark idempotent + * request, which could use QUIC 0-RTT. + */ +GRPC_SUPPORT_EXPORT +int bidirectional_stream_start(bidirectional_stream* stream, + const char* url, + int priority, + const char* method, + const bidirectional_stream_header_array* headers, + bool end_of_stream); + +/* Reads response data into |buffer| of |capacity| length. Must only be called + * at most once in response to each invocation of the + * on_stream_ready()/on_response_headers_received() and on_read_completed() + * methods of the bidirectional_stream_callback. + * Each call will result in an invocation of the callback's + * on_read_completed() method if data is read, or its on_failed() method if + * there's an error. The callback's on_succeeded() method is also invoked if + * there is no more data to read and |end_of_stream| was previously sent. + */ +GRPC_SUPPORT_EXPORT +int bidirectional_stream_read(bidirectional_stream* stream, + char* buffer, + int capacity); + +/* Writes request data from |buffer| of |buffer_length| length. If auto flush is + * disabled, data will be sent only after bidirectional_stream_flush() is + * called. + * Each call will result in an invocation the callback's on_write_completed() + * method if data is sent, or its on_failed() method if there's an error. + * The callback's on_succeeded() method is also invoked if |end_of_stream| is + * set and all response data has been read. + */ +GRPC_SUPPORT_EXPORT +int bidirectional_stream_write(bidirectional_stream* stream, + const char* buffer, + int buffer_length, + bool end_of_stream); + +/** + * Flushes pending writes. This method should not be called before invocation of + * on_stream_ready() method of the bidirectional_stream_callback. + * For each previously called bidirectional_stream_write() + * a corresponding on_write_completed() callback will be invoked when the buffer + * is sent. + */ +GRPC_SUPPORT_EXPORT +void bidirectional_stream_flush(bidirectional_stream* stream); + +/* Cancels the stream. Can be called at any time after + * bidirectional_stream_start(). The on_canceled() method of + * bidirectional_stream_callback will be invoked when cancelation + * is complete and no further callback methods will be invoked. If the + * stream has completed or has not started, calling + * bidirectional_stream_cancel() has no effect and on_canceled() will not + * be invoked. At most one callback method may be invoked after + * bidirectional_stream_cancel() has completed. + */ +GRPC_SUPPORT_EXPORT +void bidirectional_stream_cancel(bidirectional_stream* stream); + +/* Returns true if the |stream| was successfully started and is now done + * (succeeded, canceled, or failed). + * Returns false if the |stream| stream is not yet started or is in progress. + */ +GRPC_SUPPORT_EXPORT +bool bidirectional_stream_is_done(bidirectional_stream* stream); + +#ifdef __cplusplus +} +#endif + +#endif // COMPONENTS_GRPC_SUPPORT_INCLUDE_BIDIRECTIONAL_STREAM_H_ diff --git a/third_party/objective_c/Cronet/cronet_c_for_grpc.h b/third_party/objective_c/Cronet/cronet_c_for_grpc.h deleted file mode 100644 index 15a511aebd0..00000000000 --- a/third_party/objective_c/Cronet/cronet_c_for_grpc.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ -#define COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Cronet Engine API. */ - -/* Opaque object representing Cronet Engine. Created and configured outside - * of this API to facilitate sharing with other components */ -typedef struct cronet_engine { void* obj; } cronet_engine; - -void cronet_engine_add_quic_hint(cronet_engine* engine, - const char* host, - int port, - int alternate_port); - -/* Cronet Bidirectional Stream API */ - -/* Opaque object representing Cronet Bidirectional Stream. */ -typedef struct cronet_bidirectional_stream { - void* obj; - void* annotation; -} cronet_bidirectional_stream; - -/* A single request or response header element. */ -typedef struct cronet_bidirectional_stream_header { - const char* key; - const char* value; -} cronet_bidirectional_stream_header; - -/* Array of request or response headers or trailers. */ -typedef struct cronet_bidirectional_stream_header_array { - size_t count; - size_t capacity; - cronet_bidirectional_stream_header* headers; -} cronet_bidirectional_stream_header_array; - -/* Set of callbacks used to receive callbacks from bidirectional stream. */ -typedef struct cronet_bidirectional_stream_callback { - /* Invoked when request headers are sent. Indicates that stream has initiated - * the request. Consumer may call cronet_bidirectional_stream_write() to start - * writing data. - */ - void (*on_request_headers_sent)(cronet_bidirectional_stream* stream); - - /* Invoked when initial response headers are received. - * Consumer must call cronet_bidirectional_stream_read() to start reading. - * Consumer may call cronet_bidirectional_stream_write() to start writing or - * close the stream. Contents of |headers| is valid for duration of the call. - */ - void (*on_response_headers_received)( - cronet_bidirectional_stream* stream, - const cronet_bidirectional_stream_header_array* headers, - const char* negotiated_protocol); - - /* Invoked when data is read into the buffer passed to - * cronet_bidirectional_stream_read(). Only part of the buffer may be - * populated. To continue reading, call cronet_bidirectional_stream_read(). - * It may be invoked after on_response_trailers_received()}, if there was - * pending read data before trailers were received. - * - * If count is 0, it means the remote side has signaled that it will send no - * more data; future calls to cronet_bidirectional_stream_read() will result - * in the on_data_read() callback or on_succeded() callback if - * cronet_bidirectional_stream_write() was invoked with end_of_stream set to - * true. - */ - void (*on_read_completed)(cronet_bidirectional_stream* stream, - char* data, - int count); - - /** - * Invoked when all data passed to cronet_bidirectional_stream_write() is - * sent. - * To continue writing, call cronet_bidirectional_stream_write(). - */ - void (*on_write_completed)(cronet_bidirectional_stream* stream, - const char* data); - - /* Invoked when trailers are received before closing the stream. Only invoked - * when server sends trailers, which it may not. May be invoked while there is - * read data remaining in local buffer. Contents of |trailers| is valid for - * duration of the call. - */ - void (*on_response_trailers_received)( - cronet_bidirectional_stream* stream, - const cronet_bidirectional_stream_header_array* trailers); - - /** - * Invoked when there is no data to be read or written and the stream is - * closed successfully remotely and locally. Once invoked, no further callback - * methods will be invoked. - */ - void (*on_succeded)(cronet_bidirectional_stream* stream); - - /** - * Invoked if the stream failed for any reason after - * cronet_bidirectional_stream_start(). HTTP/2 error codes are - * mapped to chrome net error codes. Once invoked, no further callback methods - * will be invoked. - */ - void (*on_failed)(cronet_bidirectional_stream* stream, int net_error); - - /** - * Invoked if the stream was canceled via - * cronet_bidirectional_stream_cancel(). Once invoked, no further callback - * methods will be invoked. - */ - void (*on_canceled)(cronet_bidirectional_stream* stream); -} cronet_bidirectional_stream_callback; - -/* Create a new stream object that uses |engine| and |callback|. All stream - * tasks are performed asynchronously on the |engine| network thread. |callback| - * methods are invoked synchronously on the |engine| network thread, but must - * not run tasks on the current thread to prevent blocking networking operations - * and causing exceptions during shutdown. The |annotation| is stored in - * bidirectional stream for arbitrary use by application. - * - * Returned |cronet_bidirectional_stream*| is owned by the caller, and must be - * destroyed using |cronet_bidirectional_stream_destroy|. - * - * Both |calback| and |engine| must remain valid until stream is destroyed. - */ -cronet_bidirectional_stream* cronet_bidirectional_stream_create( - cronet_engine* engine, - void* annotation, - cronet_bidirectional_stream_callback* callback); - -/* TBD: The following methods return int. Should it be a custom type? */ - -/* Destroy stream object. Destroy could be called from any thread, including - * network thread, but is posted, so |stream| is valid until calling task is - * complete. - */ -int cronet_bidirectional_stream_destroy(cronet_bidirectional_stream* stream); - -/* Start the stream by sending request to |url| using |method| and |headers|. If - * |end_of_stream| is true, then no data is expected to be written. - */ -int cronet_bidirectional_stream_start( - cronet_bidirectional_stream* stream, - const char* url, - int priority, - const char* method, - const cronet_bidirectional_stream_header_array* headers, - bool end_of_stream); - -/* Read response data into |buffer| of |capacity| length. Must only be called at - * most once in response to each invocation of the - * on_response_headers_received() and on_read_completed() methods of the - * cronet_bidirectional_stream_callback. - * Each call will result in an invocation of one of the callback's - * on_read_completed method if data is read, its on_succeeded() method if - * the stream is closed, or its on_failed() method if there's an error. - */ -int cronet_bidirectional_stream_read(cronet_bidirectional_stream* stream, - char* buffer, - int capacity); - -/* Read response data into |buffer| of |capacity| length. Must only be called at - * most once in response to each invocation of the - * on_response_headers_received() and on_read_completed() methods of the - * cronet_bidirectional_stream_callback. - * Each call will result in an invocation of one of the callback's - * on_read_completed method if data is read, its on_succeeded() method if - * the stream is closed, or its on_failed() method if there's an error. - */ -int cronet_bidirectional_stream_write(cronet_bidirectional_stream* stream, - const char* buffer, - int count, - bool end_of_stream); - -/* Cancels the stream. Can be called at any time after - * cronet_bidirectional_stream_start(). The on_canceled() method of - * cronet_bidirectional_stream_callback will be invoked when cancelation - * is complete and no further callback methods will be invoked. If the - * stream has completed or has not started, calling - * cronet_bidirectional_stream_cancel() has no effect and on_canceled() will not - * be invoked. At most one callback method may be invoked after - * cronet_bidirectional_stream_cancel() has completed. - */ -int cronet_bidirectional_stream_cancel(cronet_bidirectional_stream* stream); - -/* Returns true if the |stream| was successfully started and is now done - * (succeeded, canceled, or failed). - * Returns false if the |stream| stream is not yet started or is in progress. - */ -bool cronet_bidirectional_stream_is_done(cronet_bidirectional_stream* stream); - -#ifdef __cplusplus -} -#endif - -#endif // COMPONENTS_CRONET_IOS_CRONET_C_FOR_GRPC_H_ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 9be07941d75..fc609102598 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -7504,7 +7504,7 @@ "include/grpc/grpc_cronet.h", "include/grpc/grpc_security.h", "include/grpc/grpc_security_constants.h", - "third_party/objective_c/Cronet/cronet_c_for_grpc.h" + "third_party/Cronet/bidirectional_stream_c.h" ], "is_filegroup": true, "language": "c", From 0c2fb6a2a428b76c931f3795ce53e0794dbfdccd Mon Sep 17 00:00:00 2001 From: Garrett Casto Date: Tue, 22 Nov 2016 11:14:39 -0800 Subject: [PATCH 008/104] Fix CoreCronetEnd2EndTests --- .../tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m index 4a92cc8e0d3..40a18a5aa54 100644 --- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m +++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m @@ -94,7 +94,7 @@ static void process_auth_failure(void *state, grpc_auth_context *ctx, static void cronet_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, - cronet_engine *cronetEngine) { + stream_engine *cronetEngine) { fullstack_secure_fixture_data *ffd = f->fixture_data; f->client = grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL); @@ -124,7 +124,7 @@ static void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { static void cronet_init_client_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - cronet_engine *cronetEngine = [Cronet getGlobalEngine]; + stream_engine *cronetEngine = [Cronet getGlobalEngine]; grpc_channel_args *new_client_args = grpc_channel_args_copy(client_args); cronet_init_client_secure_fullstack(f, new_client_args, cronetEngine); From 07639b972538dda9bebfad2e0da95d99da42b91f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 28 Nov 2016 14:26:11 -0800 Subject: [PATCH 009/104] Drop support for Node 0.12 and io.js 1.0 --- tools/run_tests/build_artifact_node.bat | 2 +- tools/run_tests/build_artifact_node.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/build_artifact_node.bat b/tools/run_tests/build_artifact_node.bat index 57d55ef19ec..833cb8171d9 100644 --- a/tools/run_tests/build_artifact_node.bat +++ b/tools/run_tests/build_artifact_node.bat @@ -27,7 +27,7 @@ @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set node_versions=0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 +set node_versions=1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 set PATH=%PATH%;C:\Program Files\nodejs\;%APPDATA%\npm diff --git a/tools/run_tests/build_artifact_node.sh b/tools/run_tests/build_artifact_node.sh index 9d06472aa49..6a9caa9ca9b 100755 --- a/tools/run_tests/build_artifact_node.sh +++ b/tools/run_tests/build_artifact_node.sh @@ -42,7 +42,7 @@ mkdir -p artifacts npm update -node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 ) +node_versions=( 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 6.0.0 ) for version in ${node_versions[@]} do From d6c93802fff2dc3db004828a6ea4ff5b25383ee4 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 29 Nov 2016 09:17:57 -0800 Subject: [PATCH 010/104] Update package.json with version compatibility changes --- package.json | 2 +- templates/package.json.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5506e9bbdf8..6fd799cbab0 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "poisson-process": "^0.2.1" }, "engines": { - "node": ">=0.12.0" + "node": ">=1.1.0" }, "binary": { "module_name": "grpc_node", diff --git a/templates/package.json.template b/templates/package.json.template index 81f39d27f51..eb85c06590e 100644 --- a/templates/package.json.template +++ b/templates/package.json.template @@ -52,7 +52,7 @@ "poisson-process": "^0.2.1" }, "engines": { - "node": ">=0.12.0" + "node": ">=1.1.0" }, "binary": { "module_name": "grpc_node", From 33fdafbf18bc3f80bfddf998facefc6c9dd9f456 Mon Sep 17 00:00:00 2001 From: Garrett Casto Date: Tue, 29 Nov 2016 11:32:03 -0800 Subject: [PATCH 011/104] clang-format --- .../cronet/transport/cronet_transport.c | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index 28c4fbe9fe1..084532ea836 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -88,13 +88,12 @@ enum e_op_id { static void on_request_headers_sent(bidirectional_stream *); static void on_response_headers_received( - bidirectional_stream *, - const bidirectional_stream_header_array *, const char *); + bidirectional_stream *, const bidirectional_stream_header_array *, + const char *); static void on_write_completed(bidirectional_stream *, const char *); static void on_read_completed(bidirectional_stream *, char *, int); static void on_response_trailers_received( - bidirectional_stream *, - const bidirectional_stream_header_array *); + bidirectional_stream *, const bidirectional_stream_header_array *); static void on_succeeded(bidirectional_stream *); static void on_failed(bidirectional_stream *, int); static void on_canceled(bidirectional_stream *); @@ -440,8 +439,7 @@ static void on_response_headers_received( /* Cronet callback */ -static void on_write_completed(bidirectional_stream *stream, - const char *data) { +static void on_write_completed(bidirectional_stream *stream, const char *data) { stream_obj *s = (stream_obj *)stream->annotation; CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data); gpr_mu_lock(&s->mu); @@ -798,10 +796,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url, &s->header_array.headers, &s->header_array.count, &method); s->header_array.capacity = s->header_array.count; - CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, - url); - bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, - false); + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); + bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false); stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; result = ACTION_TAKEN_WITH_CALLBACK; } else if (stream_op->recv_initial_metadata && @@ -849,8 +845,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, size_t write_buffer_size; create_grpc_frame(&write_slice_buffer, &stream_state->ws.write_buffer, &write_buffer_size); - CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, %p)", - s->cbs, stream_state->ws.write_buffer); + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, %p)", s->cbs, + stream_state->ws.write_buffer); stream_state->state_callback_received[OP_SEND_MESSAGE] = false; bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer, (int)write_buffer_size, false); @@ -972,8 +968,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, result = NO_ACTION_POSSIBLE; CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); } else { - CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", - s->cbs); + CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); stream_state->state_callback_received[OP_SEND_MESSAGE] = false; bidirectional_stream_write(s->cbs, "", 0, true); result = ACTION_TAKEN_WITH_CALLBACK; @@ -1073,8 +1068,7 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, /* Notify application that operation is cancelled by forging trailers */ header_array.count = 1; header_array.capacity = 1; - header_array.headers = - gpr_malloc(sizeof(bidirectional_stream_header)); + header_array.headers = gpr_malloc(sizeof(bidirectional_stream_header)); header = (bidirectional_stream_header *)header_array.headers; header->key = "grpc-status"; header->value = "1"; /* Return status GRPC_STATUS_CANCELLED */ From 72f8e14a8068140fcda53b537253792c4907de5a Mon Sep 17 00:00:00 2001 From: Garrett Casto Date: Wed, 30 Nov 2016 13:12:39 -0800 Subject: [PATCH 012/104] More clang-format --- .../cronet/transport/cronet_api_dummy.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c index 1c4253f43fe..74327a42142 100644 --- a/src/core/ext/transport/cronet/transport/cronet_api_dummy.c +++ b/src/core/ext/transport/cronet/transport/cronet_api_dummy.c @@ -56,23 +56,22 @@ int bidirectional_stream_destroy(bidirectional_stream* stream) { return 0; } -int bidirectional_stream_start( - bidirectional_stream* stream, const char* url, int priority, - const char* method, const bidirectional_stream_header_array* headers, - bool end_of_stream) { +int bidirectional_stream_start(bidirectional_stream* stream, const char* url, + int priority, const char* method, + const bidirectional_stream_header_array* headers, + bool end_of_stream) { GPR_ASSERT(0); return 0; } -int bidirectional_stream_read(bidirectional_stream* stream, - char* buffer, int capacity) { +int bidirectional_stream_read(bidirectional_stream* stream, char* buffer, + int capacity) { GPR_ASSERT(0); return 0; } -int bidirectional_stream_write(bidirectional_stream* stream, - const char* buffer, int count, - bool end_of_stream) { +int bidirectional_stream_write(bidirectional_stream* stream, const char* buffer, + int count, bool end_of_stream) { GPR_ASSERT(0); return 0; } From 4d01ceea2e471d46d98a02c40f4428d27f8c0ba6 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 30 Nov 2016 13:37:07 -0800 Subject: [PATCH 013/104] Change CronetFramework.podspec version number to 0.0.4 instead of 1.0.0 --- src/objective-c/CronetFramework.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/CronetFramework.podspec b/src/objective-c/CronetFramework.podspec index 538479b96bc..90c7892df14 100644 --- a/src/objective-c/CronetFramework.podspec +++ b/src/objective-c/CronetFramework.podspec @@ -30,7 +30,7 @@ Pod::Spec.new do |s| s.name = "CronetFramework" - s.version = "1.0.0" + s.version = "0.0.4" s.summary = "Cronet, precompiled and used as a framework." s.homepage = "http://chromium.org" s.license = { From ff27a7aa4a9322833dcd9c29cda7ab3f1ba84ff2 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 30 Nov 2016 15:34:10 -0800 Subject: [PATCH 014/104] Use version number in Cronet zip file name --- src/objective-c/CronetFramework.podspec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/objective-c/CronetFramework.podspec b/src/objective-c/CronetFramework.podspec index 90c7892df14..d45b8d8143b 100644 --- a/src/objective-c/CronetFramework.podspec +++ b/src/objective-c/CronetFramework.podspec @@ -30,7 +30,8 @@ Pod::Spec.new do |s| s.name = "CronetFramework" - s.version = "0.0.4" + v = '0.0.4' + s.version = v s.summary = "Cronet, precompiled and used as a framework." s.homepage = "http://chromium.org" s.license = { @@ -69,7 +70,8 @@ Pod::Spec.new do |s| s.vendored_framework = "Cronet.framework" s.author = "The Chromium Authors" s.ios.deployment_target = "8.0" - s.source = { :http => 'https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework-1.0.0.zip' } + file = + s.source = { :http => "https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework-v#{v}.zip"} s.preserve_paths = "Cronet.framework" s.public_header_files = "Cronet.framework/Headers/**/*{.h}" s.source_files = "Cronet.framework/Headers/**/*{.h}" From f0f787d117a20156eeda8dbd6e96398fe4d443a7 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 5 Dec 2016 09:41:18 -0800 Subject: [PATCH 015/104] Fix Ruby compilation problems on MinGW --- Makefile | 72 +++++++------- Rakefile | 2 +- src/core/ext/census/tracing.c | 19 ++-- src/core/lib/iomgr/tcp_server_windows.c | 6 +- templates/Makefile.template | 8 +- templates/Rakefile.template | 126 ++++++++++++++++++++++++ 6 files changed, 183 insertions(+), 50 deletions(-) create mode 100644 templates/Rakefile.template diff --git a/Makefile b/Makefile index 87b152514b9..248770673a6 100644 --- a/Makefile +++ b/Makefile @@ -2327,7 +2327,7 @@ install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx install-shared_c: shared_c strip-shared_c install-pkg-config_c $(E) "[INSTALL] Installing $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr-imp.a $(prefix)/lib/libgpr-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2336,7 +2336,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc-imp.a $(prefix)/lib/libgrpc-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2345,7 +2345,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet-imp.a $(prefix)/lib/libgrpc_cronet-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2354,7 +2354,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure-imp.a $(prefix)/lib/libgrpc_unsecure-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2371,7 +2371,7 @@ endif install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-config_cxx $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++-imp.a $(prefix)/lib/libgrpc++-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2380,7 +2380,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet-imp.a $(prefix)/lib/libgrpc++_cronet-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2389,7 +2389,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection-imp.a $(prefix)/lib/libgrpc++_reflection-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2398,7 +2398,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a $(prefix)/lib/libgrpc++_unsecure-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2415,7 +2415,7 @@ endif install-shared_csharp: shared_csharp strip-shared_csharp $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a $(prefix)/lib/libgrpc_csharp_ext-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2584,11 +2584,11 @@ $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OB $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.2 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so endif endif @@ -2902,11 +2902,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so endif endif @@ -3171,11 +3171,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(L $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so endif endif @@ -3663,11 +3663,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so endif endif @@ -3926,11 +3926,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC+ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc - $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so endif endif @@ -4296,11 +4296,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(L $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet - $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so endif endif @@ -4419,11 +4419,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ - $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so endif endif @@ -4809,11 +4809,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure - $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so endif endif @@ -5299,11 +5299,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHA $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so endif endif diff --git a/Rakefile b/Rakefile index cfd4181d7e0..8a88b4401f5 100755 --- a/Rakefile +++ b/Rakefile @@ -83,7 +83,7 @@ task 'dlls' do env += 'EMBED_ZLIB=true ' env += 'BUILDDIR=/tmp ' env += "V=#{verbose} " - out = '/tmp/libs/opt/grpc-1.dll' + out = '/tmp/libs/opt/grpc-2.dll' w64 = { cross: 'x86_64-w64-mingw32', out: 'grpc_c.64.ruby' } w32 = { cross: 'i686-w64-mingw32', out: 'grpc_c.32.ruby' } diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c index 8f0e12296dd..536ba98f64f 100644 --- a/src/core/ext/census/tracing.c +++ b/src/core/ext/census/tracing.c @@ -33,17 +33,24 @@ //#include "src/core/ext/census/tracing.h" +#include + #include /* TODO(aveitch): These are all placeholder implementations. */ -// int census_trace_mask(const census_context *context) { -// return CENSUS_TRACE_MASK_NONE; -// } +int census_trace_mask(const census_context *context) { + abort(); + return CENSUS_TRACE_MASK_NONE; +} -// void census_set_trace_mask(int trace_mask) {} +void census_set_trace_mask(int trace_mask) { + abort(); +} -// void census_trace_print(census_context *context, uint32_t type, -// const char *buffer, size_t n) {} +void census_trace_print(census_context *context, uint32_t type, + const char *buffer, size_t n) { + abort(); +} // void SetTracerParams(const Params& params); diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index b8a391c0590..40d1746730b 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -239,7 +239,7 @@ static grpc_error *prepare_socket(SOCKET sock, error = GRPC_WSA_ERROR(WSAGetLastError(), "getsockname"); goto failure; } - sockname_temp.len = sockname_temp_len; + sockname_temp.len = (size_t)sockname_temp_len; *port = grpc_sockaddr_get_port(&sockname_temp); return GRPC_ERROR_NONE; @@ -375,7 +375,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { int peer_name_len = (int)peer_name.len; err = getpeername(sock, (struct sockaddr *)peer_name.addr, &peer_name_len); - peer_name.len = peer_name_len; + peer_name.len = (size_t)peer_name_len; if (!err) { peer_name_string = grpc_sockaddr_to_uri(&peer_name); } else { @@ -493,7 +493,7 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, if (0 == getsockname(sp->socket->socket, (struct sockaddr *)sockname_temp.addr, &sockname_temp_len)) { - sockname_temp.len = sockname_temp_len; + sockname_temp.len = (size_t)sockname_temp_len; *port = grpc_sockaddr_get_port(&sockname_temp); if (*port > 0) { allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); diff --git a/templates/Makefile.template b/templates/Makefile.template index 109de33c31e..d58d4fce41e 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1293,7 +1293,7 @@ % if not lib.get('external_deps', None): $(E) "[INSTALL] Installing $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]})" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a else ifneq ($(SYSTEM),Darwin) @@ -1552,11 +1552,11 @@ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) -dynamiclib -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs} + $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) -dynamiclib -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs} else $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.core_version.major} -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs} - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major} - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major} + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so endif endif % endif diff --git a/templates/Rakefile.template b/templates/Rakefile.template new file mode 100644 index 00000000000..2ab505b7c10 --- /dev/null +++ b/templates/Rakefile.template @@ -0,0 +1,126 @@ +%YAML 1.2 +--- | + # -*- ruby -*- + require 'rake/extensiontask' + require 'rspec/core/rake_task' + require 'rubocop/rake_task' + require 'bundler/gem_tasks' + require 'fileutils' + + load 'tools/distrib/docker_for_windows.rb' + + # Add rubocop style checking tasks + RuboCop::RakeTask.new(:rubocop) do |task| + task.options = ['-c', 'src/ruby/.rubocop.yml'] + task.patterns = ['src/ruby/{lib,spec}/**/*.rb'] + end + + spec = Gem::Specification.load('grpc.gemspec') + + Gem::PackageTask.new(spec) do |pkg| + end + + # Add the extension compiler task + Rake::ExtensionTask.new('grpc_c', spec) do |ext| + ext.source_pattern = '**/*.{c,h}' + ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc') + ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc') + ext.cross_compile = true + ext.cross_platform = [ + 'x86-mingw32', 'x64-mingw32', + 'x86_64-linux', 'x86-linux', + 'universal-darwin' + ] + ext.cross_compiling do |spec| + spec.files = %w( etc/roots.pem grpc_c.32.ruby grpc_c.64.ruby ) + spec.files += Dir.glob('src/ruby/bin/**/*') + spec.files += Dir.glob('src/ruby/ext/**/*') + spec.files += Dir.glob('src/ruby/lib/**/*') + spec.files += Dir.glob('src/ruby/pb/**/*') + end + end + + # Define the test suites + SPEC_SUITES = [ + { id: :wrapper, title: 'wrapper layer', files: %w(src/ruby/spec/*.rb) }, + { id: :idiomatic, title: 'idiomatic layer', dir: %w(src/ruby/spec/generic), + tags: ['~bidi', '~server'] }, + { id: :bidi, title: 'bidi tests', dir: %w(src/ruby/spec/generic), + tag: 'bidi' }, + { id: :server, title: 'rpc server thread tests', dir: %w(src/ruby/spec/generic), + tag: 'server' }, + { id: :pb, title: 'protobuf service tests', dir: %w(src/ruby/spec/pb) } + ] + namespace :suite do + SPEC_SUITES.each do |suite| + desc "Run all specs in the #{suite[:title]} spec suite" + RSpec::Core::RakeTask.new(suite[:id]) do |t| + ENV['COVERAGE_NAME'] = suite[:id].to_s + spec_files = [] + suite[:files].each { |f| spec_files += Dir[f] } if suite[:files] + + if suite[:dir] + suite[:dir].each { |f| spec_files += Dir["#{f}/**/*_spec.rb"] } + end + helper = 'src/ruby/spec/spec_helper.rb' + spec_files << helper unless spec_files.include?(helper) + + t.pattern = spec_files + t.rspec_opts = "--tag #{suite[:tag]}" if suite[:tag] + if suite[:tags] + t.rspec_opts = suite[:tags].map { |x| "--tag #{x}" }.join(' ') + end + end + end + end + + desc 'Build the Windows gRPC DLLs for Ruby' + task 'dlls' do + grpc_config = ENV['GRPC_CONFIG'] || 'opt' + verbose = ENV['V'] || '0' + + env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result" ' + env += 'LDFLAGS=-static ' + env += 'SYSTEM=MINGW32 ' + env += 'EMBED_ZLIB=true ' + env += 'BUILDDIR=/tmp ' + env += "V=#{verbose} " + out = '/tmp/libs/opt/grpc-${settings.core_version.major}.dll' + + w64 = { cross: 'x86_64-w64-mingw32', out: 'grpc_c.64.ruby' } + w32 = { cross: 'i686-w64-mingw32', out: 'grpc_c.32.ruby' } + + [ w64, w32 ].each do |opt| + env_comp = "CC=#{opt[:cross]}-gcc " + env_comp += "LD=#{opt[:cross]}-gcc " + docker_for_windows "#{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}" + end + + end + + desc 'Build the native gem file under rake_compiler_dock' + task 'gem:native' do + verbose = ENV['V'] || '0' + + grpc_config = ENV['GRPC_CONFIG'] || 'opt' + + if RUBY_PLATFORM =~ /darwin/ + FileUtils.touch 'grpc_c.32.ruby' + FileUtils.touch 'grpc_c.64.ruby' + system "rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" + else + Rake::Task['dlls'].execute + docker_for_windows "bundle && rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" + end + end + + # Define dependencies between the suites. + task 'suite:wrapper' => [:compile, :rubocop] + task 'suite:idiomatic' => 'suite:wrapper' + task 'suite:bidi' => 'suite:wrapper' + task 'suite:server' => 'suite:wrapper' + task 'suite:pb' => 'suite:server' + + desc 'Compiles the gRPC extension then runs all the tests' + task all: ['suite:idiomatic', 'suite:bidi', 'suite:pb', 'suite:server'] + task default: :all From 116901598f05690168e18e6cd73c6422089006b8 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 5 Dec 2016 09:42:15 -0800 Subject: [PATCH 016/104] Clang format --- src/core/ext/census/tracing.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c index 536ba98f64f..51508b00efe 100644 --- a/src/core/ext/census/tracing.c +++ b/src/core/ext/census/tracing.c @@ -44,9 +44,7 @@ int census_trace_mask(const census_context *context) { return CENSUS_TRACE_MASK_NONE; } -void census_set_trace_mask(int trace_mask) { - abort(); -} +void census_set_trace_mask(int trace_mask) { abort(); } void census_trace_print(census_context *context, uint32_t type, const char *buffer, size_t n) { From 804c9e90fc4e7d11294fec69801ff7bc99134d3c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 5 Dec 2016 12:19:57 -0800 Subject: [PATCH 017/104] Add Electron tests to portability test matrix --- tools/dockerfile/test/node_jessie_x64/Dockerfile | 7 +++++++ tools/run_tests/build_node_electron.sh | 1 + tools/run_tests/pre_build_node_electron.sh | 2 ++ tools/run_tests/run_node_electron.sh | 1 + tools/run_tests/run_tests_matrix.py | 9 +++++++++ 5 files changed, 20 insertions(+) diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile index d9a75018295..120ea59ae27 100644 --- a/tools/dockerfile/test/node_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile @@ -42,12 +42,18 @@ RUN apt-get update && apt-get install -y \ git \ golang \ gyp \ + libasound2 \ lcov \ libc6 \ libc6-dbg \ libc6-dev \ + libgconf-2-4 \ libgtest-dev \ + libgtk2.0-0 \ + libnss3 \ libtool \ + libxss1\ + libxtst6 \ make \ perl \ strace \ @@ -57,6 +63,7 @@ RUN apt-get update && apt-get install -y \ telnet \ unzip \ wget \ + xvfb \ zip && apt-get clean #================ diff --git a/tools/run_tests/build_node_electron.sh b/tools/run_tests/build_node_electron.sh index 4e7c3e4789a..1c95c513b32 100755 --- a/tools/run_tests/build_node_electron.sh +++ b/tools/run_tests/build_node_electron.sh @@ -42,4 +42,5 @@ export npm_config_target=$ELECTRON_VERSION export npm_config_disturl=https://atom.io/download/atom-shell export npm_config_runtime=electron export npm_config_build_from_source=true +mkdir -p ~/.electron-gyp HOME=~/.electron-gyp npm install --unsafe-perm diff --git a/tools/run_tests/pre_build_node_electron.sh b/tools/run_tests/pre_build_node_electron.sh index d8d9df4ddbc..95c56aa5094 100755 --- a/tools/run_tests/pre_build_node_electron.sh +++ b/tools/run_tests/pre_build_node_electron.sh @@ -34,4 +34,6 @@ ELECTRON_VERSION=$1 nvm install 6 set -ex +npm install xvfb-maybe + npm install electron@$ELECTRON_VERSION diff --git a/tools/run_tests/run_node_electron.sh b/tools/run_tests/run_node_electron.sh index 7f8a824df27..1999ffb0fa8 100755 --- a/tools/run_tests/run_node_electron.sh +++ b/tools/run_tests/run_node_electron.sh @@ -40,5 +40,6 @@ test_directory='src/node/test' timeout=8000 JUNIT_REPORT_PATH=src/node/report.xml JUNIT_REPORT_STACK=1 \ + ./node_modules/.bin/xvfb-maybe \ ./node_modules/.bin/electron-mocha --timeout $timeout \ --reporter mocha-jenkins-reporter $test_directory diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index 989bc7eb218..d03e34766ee 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -230,6 +230,15 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS) labels=['portability'], extra_args=extra_args, inner_jobs=inner_jobs) + + test_jobs += _generate_jobs(languages=['node'], + configs=['dbg'], + platforms=['linux'], + arch='default', + compiler='electron1.3', + labels=['portability'], + extra_args=extra_args, + inner_jobs=inner_jobs) return test_jobs From 123d0dbd614f6d6626295dec93764549e0e650ff Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 7 Dec 2016 09:37:24 -0800 Subject: [PATCH 018/104] bug fix --- src/objective-c/CronetFramework.podspec | 1 - 1 file changed, 1 deletion(-) diff --git a/src/objective-c/CronetFramework.podspec b/src/objective-c/CronetFramework.podspec index d45b8d8143b..509358dada2 100644 --- a/src/objective-c/CronetFramework.podspec +++ b/src/objective-c/CronetFramework.podspec @@ -70,7 +70,6 @@ Pod::Spec.new do |s| s.vendored_framework = "Cronet.framework" s.author = "The Chromium Authors" s.ios.deployment_target = "8.0" - file = s.source = { :http => "https://storage.googleapis.com/grpc-precompiled-binaries/cronet/Cronet.framework-v#{v}.zip"} s.preserve_paths = "Cronet.framework" s.public_header_files = "Cronet.framework/Headers/**/*{.h}" From 4d2ea021296697ade62457386ab36bafa8e7c5c4 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 12 Dec 2016 07:12:27 -0800 Subject: [PATCH 019/104] Revert "Revert "Revert "Revert "Remove redundant includes from string.h and tmpfile.h"""" --- BUILD | 9 ++ CMakeLists.txt | 7 ++ Makefile | 9 ++ build.yaml | 1 + gRPC-Core.podspec | 2 + grpc.gemspec | 2 + include/grpc/impl/codegen/gpr_slice.h | 84 +++++++++++++++++++ include/grpc/impl/codegen/slice.h | 20 +++++ package.xml | 2 + src/core/lib/support/string.h | 2 - src/core/lib/support/tmpfile.h | 2 - .../core/surface/public_headers_must_be_c89.c | 1 + tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core | 2 + tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/sources_and_headers.json | 2 + vsprojects/vcxproj/gpr/gpr.vcxproj | 1 + vsprojects/vcxproj/gpr/gpr.vcxproj.filters | 3 + vsprojects/vcxproj/grpc++/grpc++.vcxproj | 1 + .../vcxproj/grpc++/grpc++.vcxproj.filters | 3 + .../grpc++_test_util/grpc++_test_util.vcxproj | 1 + .../grpc++_test_util.vcxproj.filters | 3 + .../grpc++_unsecure/grpc++_unsecure.vcxproj | 1 + .../grpc++_unsecure.vcxproj.filters | 3 + vsprojects/vcxproj/grpc/grpc.vcxproj | 1 + vsprojects/vcxproj/grpc/grpc.vcxproj.filters | 3 + .../grpc_test_util/grpc_test_util.vcxproj | 1 + .../grpc_test_util.vcxproj.filters | 3 + .../grpc_unsecure/grpc_unsecure.vcxproj | 1 + .../grpc_unsecure.vcxproj.filters | 3 + .../codegen_test_full.vcxproj | 1 + .../codegen_test_full.vcxproj.filters | 3 + .../codegen_test_minimal.vcxproj | 1 + .../codegen_test_minimal.vcxproj.filters | 3 + .../grpc_tool_test/grpc_tool_test.vcxproj | 1 + .../grpc_tool_test.vcxproj.filters | 3 + 37 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 include/grpc/impl/codegen/gpr_slice.h diff --git a/BUILD b/BUILD index ab0fc237b78..fb81cf65fc2 100644 --- a/BUILD +++ b/BUILD @@ -135,6 +135,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -564,6 +565,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -960,6 +962,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -1341,6 +1344,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -1496,6 +1500,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -1958,6 +1963,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2134,6 +2140,7 @@ cc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2296,6 +2303,7 @@ objc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -2562,6 +2570,7 @@ objc_library( "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index ff0927504aa..16e5d62de2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,6 +258,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -537,6 +538,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -788,6 +790,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1039,6 +1042,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1202,6 +1206,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1535,6 +1540,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h @@ -1741,6 +1747,7 @@ foreach(_hdr include/grpc/impl/codegen/atm_gcc_atomic.h include/grpc/impl/codegen/atm_gcc_sync.h include/grpc/impl/codegen/atm_windows.h + include/grpc/impl/codegen/gpr_slice.h include/grpc/impl/codegen/gpr_types.h include/grpc/impl/codegen/port_platform.h include/grpc/impl/codegen/slice.h diff --git a/Makefile b/Makefile index 8f7328ae285..eae4f46e701 100644 --- a/Makefile +++ b/Makefile @@ -2552,6 +2552,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -2859,6 +2860,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3129,6 +3131,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3345,6 +3348,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3635,6 +3639,7 @@ PUBLIC_HEADERS_C += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -3879,6 +3884,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -4241,6 +4247,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -4596,6 +4603,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -4774,6 +4782,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ + include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/build.yaml b/build.yaml index de9d253ef1c..2555abce0c6 100644 --- a/build.yaml +++ b/build.yaml @@ -144,6 +144,7 @@ filegroups: - include/grpc/impl/codegen/atm_gcc_atomic.h - include/grpc/impl/codegen/atm_gcc_sync.h - include/grpc/impl/codegen/atm_windows.h + - include/grpc/impl/codegen/gpr_slice.h - include/grpc/impl/codegen/gpr_types.h - include/grpc/impl/codegen/port_platform.h - include/grpc/impl/codegen/slice.h diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 04f7211d210..f9e0164bdca 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -146,6 +146,7 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/atm_gcc_atomic.h', 'include/grpc/impl/codegen/atm_gcc_sync.h', 'include/grpc/impl/codegen/atm_windows.h', + 'include/grpc/impl/codegen/gpr_slice.h', 'include/grpc/impl/codegen/gpr_types.h', 'include/grpc/impl/codegen/port_platform.h', 'include/grpc/impl/codegen/slice.h', @@ -172,6 +173,7 @@ Pod::Spec.new do |s| 'include/grpc/impl/codegen/atm_gcc_atomic.h', 'include/grpc/impl/codegen/atm_gcc_sync.h', 'include/grpc/impl/codegen/atm_windows.h', + 'include/grpc/impl/codegen/gpr_slice.h', 'include/grpc/impl/codegen/gpr_types.h', 'include/grpc/impl/codegen/port_platform.h', 'include/grpc/impl/codegen/slice.h', diff --git a/grpc.gemspec b/grpc.gemspec index 6019b97f672..9c9568ce64d 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -73,6 +73,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) + s.files += %w( include/grpc/impl/codegen/gpr_slice.h ) s.files += %w( include/grpc/impl/codegen/gpr_types.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) @@ -155,6 +156,7 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/impl/codegen/atm_gcc_atomic.h ) s.files += %w( include/grpc/impl/codegen/atm_gcc_sync.h ) s.files += %w( include/grpc/impl/codegen/atm_windows.h ) + s.files += %w( include/grpc/impl/codegen/gpr_slice.h ) s.files += %w( include/grpc/impl/codegen/gpr_types.h ) s.files += %w( include/grpc/impl/codegen/port_platform.h ) s.files += %w( include/grpc/impl/codegen/slice.h ) diff --git a/include/grpc/impl/codegen/gpr_slice.h b/include/grpc/impl/codegen/gpr_slice.h new file mode 100644 index 00000000000..c62e976b8f4 --- /dev/null +++ b/include/grpc/impl/codegen/gpr_slice.h @@ -0,0 +1,84 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef GRPC_IMPL_CODEGEN_GPR_SLICE_H +#define GRPC_IMPL_CODEGEN_GPR_SLICE_H + +/* WARNING: Please do not use this header. This was added as a temporary measure + * to not break some of the external projects that depend on gpr_slice_* + * functions. We are actively working on moving all the gpr_slice_* references + * to grpc_slice_* and this file will be removed + * */ + +/* TODO (sreek) - Allowed by default but will be very soon turned off */ +#define GRPC_ALLOW_GPR_SLICE_FUNCTIONS 1 + +#ifdef GRPC_ALLOW_GPR_SLICE_FUNCTIONS + +#define gpr_slice_refcount grpc_slice_refcount +#define gpr_slice grpc_slice +#define gpr_slice_buffer grpc_slice_buffer + +#define gpr_slice_ref grpc_slice_ref +#define gpr_slice_unref grpc_slice_unref +#define gpr_slice_new grpc_slice_new +#define gpr_slice_new_with_user_data grpc_slice_new_with_user_data +#define gpr_slice_new_with_len grpc_slice_new_with_len +#define gpr_slice_malloc grpc_slice_malloc +#define gpr_slice_from_copied_string grpc_slice_from_copied_string +#define gpr_slice_from_copied_buffer grpc_slice_from_copied_buffer +#define gpr_slice_from_static_string grpc_slice_from_static_string +#define gpr_slice_sub grpc_slice_sub +#define gpr_slice_sub_no_ref grpc_slice_sub_no_ref +#define gpr_slice_split_tail grpc_slice_split_tail +#define gpr_slice_split_head grpc_slice_split_head +#define gpr_slice_cmp grpc_slice_cmp +#define gpr_slice_str_cmp grpc_slice_str_cmp + +#define gpr_slice_buffer grpc_slice_buffer +#define gpr_slice_buffer_init grpc_slice_buffer_init +#define gpr_slice_buffer_destroy grpc_slice_buffer_destroy +#define gpr_slice_buffer_add grpc_slice_buffer_add +#define gpr_slice_buffer_add_indexed grpc_slice_buffer_add_indexed +#define gpr_slice_buffer_addn grpc_slice_buffer_addn +#define gpr_slice_buffer_tiny_add grpc_slice_buffer_tiny_add +#define gpr_slice_buffer_pop grpc_slice_buffer_pop +#define gpr_slice_buffer_reset_and_unref grpc_slice_buffer_reset_and_unref +#define gpr_slice_buffer_swap grpc_slice_buffer_swap +#define gpr_slice_buffer_move_into grpc_slice_buffer_move_into +#define gpr_slice_buffer_trim_end grpc_slice_buffer_trim_end +#define gpr_slice_buffer_move_first grpc_slice_buffer_move_first +#define gpr_slice_buffer_take_first grpc_slice_buffer_take_first + +#endif /* GRPC_ALLOW_GPR_SLICE_FUNCTIONS */ + +#endif /* GRPC_IMPL_CODEGEN_GPR_SLICE_H */ diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index 774ba0e95d4..50b5426e1a1 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -37,6 +37,8 @@ #include #include +#include + /* Slice API A slice represents a contiguous reference counted array of bytes. @@ -115,4 +117,22 @@ typedef struct { GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(slice) #define GRPC_SLICE_IS_EMPTY(slice) (GRPC_SLICE_LENGTH(slice) == 0) +#ifdef GRPC_ALLOW_GPR_SLICE_FUNCTIONS + +/* Duplicate GPR_* definitions */ +#define GPR_SLICE_START_PTR(slice) \ + ((slice).refcount ? (slice).data.refcounted.bytes \ + : (slice).data.inlined.bytes) +#define GPR_SLICE_LENGTH(slice) \ + ((slice).refcount ? (slice).data.refcounted.length \ + : (slice).data.inlined.length) +#define GPR_SLICE_SET_LENGTH(slice, newlen) \ + ((slice).refcount ? ((slice).data.refcounted.length = (size_t)(newlen)) \ + : ((slice).data.inlined.length = (uint8_t)(newlen))) +#define GPR_SLICE_END_PTR(slice) \ + GRPC_SLICE_START_PTR(slice) + GRPC_SLICE_LENGTH(slice) +#define GPR_SLICE_IS_EMPTY(slice) (GRPC_SLICE_LENGTH(slice) == 0) + +#endif /* GRPC_ALLOW_GPR_SLICE_FUNCTIONS */ + #endif /* GRPC_IMPL_CODEGEN_SLICE_H */ diff --git a/package.xml b/package.xml index 61668815a68..2106b8f666b 100644 --- a/package.xml +++ b/package.xml @@ -81,6 +81,7 @@ + @@ -163,6 +164,7 @@ + diff --git a/src/core/lib/support/string.h b/src/core/lib/support/string.h index e933e2eb468..db59308425d 100644 --- a/src/core/lib/support/string.h +++ b/src/core/lib/support/string.h @@ -36,8 +36,6 @@ #include -#include -#include #include #ifdef __cplusplus diff --git a/src/core/lib/support/tmpfile.h b/src/core/lib/support/tmpfile.h index 8952e5ec3da..f613cf9bc8d 100644 --- a/src/core/lib/support/tmpfile.h +++ b/src/core/lib/support/tmpfile.h @@ -36,8 +36,6 @@ #include -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index d4cfa25d44b..df6b7334932 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index ff3a0e381da..9e3fc62ebc6 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -840,6 +840,7 @@ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 04e8f4e7f20..074ba504fa6 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -840,6 +840,7 @@ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 1e748ba4a89..b83e710a2b7 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -779,6 +779,7 @@ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -818,6 +819,7 @@ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 6572bd4ddf9..533999b7655 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -779,6 +779,7 @@ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ @@ -1212,6 +1213,7 @@ include/grpc/impl/codegen/atm.h \ include/grpc/impl/codegen/atm_gcc_atomic.h \ include/grpc/impl/codegen/atm_gcc_sync.h \ include/grpc/impl/codegen/atm_windows.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/port_platform.h \ include/grpc/impl/codegen/slice.h \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 6ae269cc20d..449cc126e38 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -6631,6 +6631,7 @@ "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", @@ -6647,6 +6648,7 @@ "include/grpc/impl/codegen/atm_gcc_atomic.h", "include/grpc/impl/codegen/atm_gcc_sync.h", "include/grpc/impl/codegen/atm_windows.h", + "include/grpc/impl/codegen/gpr_slice.h", "include/grpc/impl/codegen/gpr_types.h", "include/grpc/impl/codegen/port_platform.h", "include/grpc/impl/codegen/slice.h", diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj b/vsprojects/vcxproj/gpr/gpr.vcxproj index ce593473c07..c4f9c55308e 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj @@ -177,6 +177,7 @@ + diff --git a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters index a50a9f42001..77a1ba64d64 100644 --- a/vsprojects/vcxproj/gpr/gpr.vcxproj.filters +++ b/vsprojects/vcxproj/gpr/gpr.vcxproj.filters @@ -225,6 +225,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index f281db72b66..14b3453b74e 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -338,6 +338,7 @@ + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index f359e4ef31a..53608196494 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -354,6 +354,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj index d2305b2e255..6a928e173f6 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj @@ -185,6 +185,7 @@ + diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters index d1aaba70926..bf8fab03bb3 100644 --- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters @@ -147,6 +147,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 1511a2cfe4c..39b01e6a4e1 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -338,6 +338,7 @@ + diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index bed77b25a44..9cafa1670ab 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -339,6 +339,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 558b5b0c66a..40f0f141b58 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -286,6 +286,7 @@ + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index a40a1b5f1c8..c0de28563e1 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -705,6 +705,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index 2acdd32cf3e..01b73ce1a2a 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -166,6 +166,7 @@ + diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 6c918f12546..40ff67671f3 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -456,6 +456,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 661192101c8..49c2d2db306 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -277,6 +277,7 @@ + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 466116e6043..5bca4fb9a5b 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -621,6 +621,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj index a2b2a1dfa0f..377d86fa5a9 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj @@ -198,6 +198,7 @@ + diff --git a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters index 94b6c2530ef..e9ba002e9b1 100644 --- a/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_full/codegen_test_full.vcxproj.filters @@ -135,6 +135,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj index 1a3c1579837..3254ad8d459 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj @@ -198,6 +198,7 @@ + diff --git a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters index 1f4b60ca4d9..6f32f65524b 100644 --- a/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters +++ b/vsprojects/vcxproj/test/codegen_test_minimal/codegen_test_minimal.vcxproj.filters @@ -138,6 +138,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj index 1e3cc3ca043..7fad9222333 100644 --- a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj +++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj @@ -199,6 +199,7 @@ + diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters index 1c308c58817..19cb1133412 100644 --- a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters +++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters @@ -129,6 +129,9 @@ include\grpc\impl\codegen + + include\grpc\impl\codegen + include\grpc\impl\codegen From 3cadfb152fee3160be689ee4545e15dfcf8ebd37 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 14 Dec 2016 07:52:47 -0800 Subject: [PATCH 020/104] Started updating docs. --- doc/images/load-balancing.svg | 4 + doc/images/load_balancing_design.png | Bin 40354 -> 0 bytes doc/load-balancing.md | 128 +++++++++-------- doc/naming.md | 49 +++++-- doc/service_config.md | 201 +++++++++++++++++++++++++++ 5 files changed, 317 insertions(+), 65 deletions(-) create mode 100644 doc/images/load-balancing.svg delete mode 100644 doc/images/load_balancing_design.png create mode 100644 doc/service_config.md diff --git a/doc/images/load-balancing.svg b/doc/images/load-balancing.svg new file mode 100644 index 00000000000..425a9d33aa7 --- /dev/null +++ b/doc/images/load-balancing.svg @@ -0,0 +1,4 @@ + + + + diff --git a/doc/images/load_balancing_design.png b/doc/images/load_balancing_design.png deleted file mode 100644 index 86183966fb88e24a5a86dbd4b62ae2a308d0a542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40354 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 in bytes. The size which is measured is + # the serialized, uncompressed payload in bytes. This applies both + # to streaming and non-streaming requests. + # + # The actual value used is the minimum of the value specified here and + # the value set by the application via the gRPC client API. + # If either one is not set, then the other will be used. + # If neither is set, then the built-in default is used. + # + # If a client attempts to send an object larger than this value, it + # will not be sent and the client will see an error. + # Note that 0 is a valid value, meaning that the request message must + # be empty. + # + # The format of the value is that of the 'uint64' type defined here: + # https://developers.google.com/protocol-buffers/docs/proto3#json + 'maxRequestMessageBytes': string, + + # The maximum allowed payload size for an individual response or object + # in a stream (server->client) in bytes. The size which is measured is + # the serialized, uncompressed payload in bytes. This applies both + # to streaming and non-streaming requests. + # + # The actual value used is the minimum of the value specified here and + # the value set by the application via the gRPC client API. + # If either one is not set, then the other will be used. + # If neither is set, then the built-in default is used. + # + # If a server attempts to send an object larger than this value, it + # will not be sent, and the client will see an error. + # Note that 0 is a valid value, meaning that the response message must + # be empty. + # + # The format of the value is that of the 'uint64' type defined here: + # https://developers.google.com/protocol-buffers/docs/proto3#json + 'maxResponseMessageBytes': string + } + ] +} +``` + +# Architecture + +A service config is associated with a server name. The [name +resolver](naming.md) plugin, when asked to resolve a particular server +name, will return both the resolved addresses and the service config. + +TODO(roth): Design how the service config will be encoded in DNS. + + + + +The gRPC load balancing implements the external load balancing server approach: +an external load balancer provides simple clients with an up-to-date list of +servers. + +![image](images/load_balancing_design.png) + +1. On startup, the gRPC client issues a name resolution request for the service. + The name will resolve to one or more IP addresses to gRPC servers, a hint on + whether the IP address(es) point to a load balancer or not, and also return a + client config. +2. The gRPC client connects to a gRPC Server. + 1. If the name resolution has hinted that the endpoint is a load balancer, + the client's gRPC LB policy will attempt to open a stream to the load + balancer service. The server may respond in only one of the following + ways. + 1. `status::UNIMPLEMENTED`. There is no loadbalancing in use. The client + call will fail. + 2. "I am a Load Balancer and here is the server list." (Goto Step 4.) + 3. "Please contact Load Balancer X" (See Step 3.) The client will close + this connection and cancel the stream. + 4. If the server fails to respond, the client will wait for some timeout + and then re-resolve the name (process to Step 1 above). + 2. If the name resolution has not hinted that the endpoint is a load + balancer, the client connects directly to the service it wants to talk to. +3. The gRPC client's gRPC LB policy opens a separate connection to the Load + Balancer. If this fails, it will go back to step 1 and try another address. + 1. During channel initialization to the Load Balancer, the client will + attempt to open a stream to the Load Balancer service. + 2. The Load Balancer will return a server list to the gRPC client. If the + server list is empty, the call will wait until a non-empty one is + received. Optional: The Load Balancer will also open channels to the gRPC + servers if load reporting is needed. +4. The gRPC client will send RPCs to the gRPC servers contained in the server + list from the Load Balancer. +5. Optional: The gRPC servers may periodically report load to the Load Balancer. + +## Client + +When establishing a gRPC _stream_ to the balancer, the client will send an initial +request to the load balancer (via a regular gRPC message). The load balancer +will respond with client config (including, for example, settings for flow +control, RPC deadlines, etc.) or a redirect to another load balancer. If the +balancer did not redirect the client, it will then send a list of servers to the +client. The client will contain simple load balancing logic for choosing the +next server when it needs to send a request. + +## Load Balancer + +The Load Balancer is responsible for providing the client with a list of servers +and client RPC parameters. The balancer chooses when to update the list of +servers and can decide whether to provide a complete list, a subset, or a +specific list of “picked” servers in a particular order. The balancer can +optionally provide an expiration interval after which the server list should no +longer be trusted and should be updated by the balancer. + +The load balancer may open reporting streams to each server contained in the +server list. These streams are primarily used for load reporting. For example, +Weighted Round Robin requires that the servers report utilization to the load +balancer in order to compute the next list of servers. + +## Server + +The gRPC Server is responsible for answering RPC requests and providing +responses to the client. The server will also report load to the load balancer +if a reporting stream was opened for this purpose. From 8fda5511cb8dea5cb7fcd163253893f3d89357a1 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 14 Dec 2016 08:05:55 -0800 Subject: [PATCH 021/104] Finish docs. --- doc/load-balancing.md | 44 ++++-------------------- doc/service_config.md | 78 +++++++------------------------------------ 2 files changed, 19 insertions(+), 103 deletions(-) diff --git a/doc/load-balancing.md b/doc/load-balancing.md index 03c9bd2cbad..4ed938c9903 100644 --- a/doc/load-balancing.md +++ b/doc/load-balancing.md @@ -11,7 +11,7 @@ instruct the client how to send load to multiple backend servers. Prior to any gRPC specifics, we explore some usual ways to approach load balancing. -### Proxy Model +## Proxy Model Using a proxy provides a solid trustable client that can report load to the load balancing system. Proxies typically require more resources to operate since they @@ -21,7 +21,7 @@ latency to the RPCs. The proxy model was deemed inefficient when considering request heavy services like storage. -### Balancing-aware Client +## Balancing-aware Client This thicker client places more of the load balancing logic in the client. For example, the client could contain many load balancing policies (Round Robin, @@ -41,7 +41,7 @@ It would also significantly complicate the client's code: the new design hides the load balancing complexity of multiple layers and presents it as a simple list of servers to the client. -### External Load Balancing Service +## External Load Balancing Service The client load balancing code is kept simple and portable, implementing well-known algorithms (e.g., Round Robin) for server selection. @@ -56,7 +56,7 @@ servers to collect load and health information. # Requirements -### Simple API and client +## Simple API and client The gRPC client load balancing code must be simple and portable. The client should only contain simple algorithms (e.g., Round Robin) for @@ -68,7 +68,7 @@ unavailability or health issues. The load balancer will make any necessary complex decisions and inform the client. The load balancer may communicate with the backend servers to collect load and health information. -### Security +## Security The load balancer may be separate from the actual server backends and a compromise of the load balancer should only lead to a compromise of the @@ -90,13 +90,13 @@ However, there are only a small number of these (one of which is the are discouraged from trying to extend gRPC by adding more. Instead, new load balancing policies should be implemented in external load balancers. -## Load Balancing Policies +## Workflow Load-balancing policies fit into the gRPC client workflow in between name resolution and the connection to the server. Here's how it all works: -![image](images/load_balancing_design.png) +![image](images/load-balancing.svg) 1. On startup, the gRPC client issues a [name resolution](naming.md) request for the server name. The name will resolve to one or more IP addresses, @@ -130,33 +130,3 @@ works: received. 6. The gRPC client will send RPCs to the gRPC servers contained in the server list from the Load Balancer. - -## Client - -When establishing a gRPC _stream_ to the balancer, the client will send an initial -request to the load balancer (via a regular gRPC message). The load balancer -will respond with client config (including, for example, settings for flow -control, RPC deadlines, etc.) or a redirect to another load balancer. If the -balancer did not redirect the client, it will then send a list of servers to the -client. The client will contain simple load balancing logic for choosing the -next server when it needs to send a request. - -## Load Balancer - -The Load Balancer is responsible for providing the client with a list of servers -and client RPC parameters. The balancer chooses when to update the list of -servers and can decide whether to provide a complete list, a subset, or a -specific list of “picked” servers in a particular order. The balancer can -optionally provide an expiration interval after which the server list should no -longer be trusted and should be updated by the balancer. - -The load balancer may open reporting streams to each server contained in the -server list. These streams are primarily used for load reporting. For example, -Weighted Round Robin requires that the servers report utilization to the load -balancer in order to compute the next list of servers. - -## Server - -The gRPC Server is responsible for answering RPC requests and providing -responses to the client. The server will also report load to the load balancer -if a reporting stream was opened for this purpose. diff --git a/doc/service_config.md b/doc/service_config.md index 6093fc34453..7318b69f214 100644 --- a/doc/service_config.md +++ b/doc/service_config.md @@ -123,6 +123,9 @@ The service config is a JSON string of the following form: } ``` +Note that new per-method parameters may be added in the future as new +functionality is introduced. + # Architecture A service config is associated with a server name. The [name @@ -131,71 +134,14 @@ name, will return both the resolved addresses and the service config. TODO(roth): Design how the service config will be encoded in DNS. +# APIs +The service config is used in the following APIs: - -The gRPC load balancing implements the external load balancing server approach: -an external load balancer provides simple clients with an up-to-date list of -servers. - -![image](images/load_balancing_design.png) - -1. On startup, the gRPC client issues a name resolution request for the service. - The name will resolve to one or more IP addresses to gRPC servers, a hint on - whether the IP address(es) point to a load balancer or not, and also return a - client config. -2. The gRPC client connects to a gRPC Server. - 1. If the name resolution has hinted that the endpoint is a load balancer, - the client's gRPC LB policy will attempt to open a stream to the load - balancer service. The server may respond in only one of the following - ways. - 1. `status::UNIMPLEMENTED`. There is no loadbalancing in use. The client - call will fail. - 2. "I am a Load Balancer and here is the server list." (Goto Step 4.) - 3. "Please contact Load Balancer X" (See Step 3.) The client will close - this connection and cancel the stream. - 4. If the server fails to respond, the client will wait for some timeout - and then re-resolve the name (process to Step 1 above). - 2. If the name resolution has not hinted that the endpoint is a load - balancer, the client connects directly to the service it wants to talk to. -3. The gRPC client's gRPC LB policy opens a separate connection to the Load - Balancer. If this fails, it will go back to step 1 and try another address. - 1. During channel initialization to the Load Balancer, the client will - attempt to open a stream to the Load Balancer service. - 2. The Load Balancer will return a server list to the gRPC client. If the - server list is empty, the call will wait until a non-empty one is - received. Optional: The Load Balancer will also open channels to the gRPC - servers if load reporting is needed. -4. The gRPC client will send RPCs to the gRPC servers contained in the server - list from the Load Balancer. -5. Optional: The gRPC servers may periodically report load to the Load Balancer. - -## Client - -When establishing a gRPC _stream_ to the balancer, the client will send an initial -request to the load balancer (via a regular gRPC message). The load balancer -will respond with client config (including, for example, settings for flow -control, RPC deadlines, etc.) or a redirect to another load balancer. If the -balancer did not redirect the client, it will then send a list of servers to the -client. The client will contain simple load balancing logic for choosing the -next server when it needs to send a request. - -## Load Balancer - -The Load Balancer is responsible for providing the client with a list of servers -and client RPC parameters. The balancer chooses when to update the list of -servers and can decide whether to provide a complete list, a subset, or a -specific list of “picked” servers in a particular order. The balancer can -optionally provide an expiration interval after which the server list should no -longer be trusted and should be updated by the balancer. - -The load balancer may open reporting streams to each server contained in the -server list. These streams are primarily used for load reporting. For example, -Weighted Round Robin requires that the servers report utilization to the load -balancer in order to compute the next list of servers. - -## Server - -The gRPC Server is responsible for answering RPC requests and providing -responses to the client. The server will also report load to the load balancer -if a reporting stream was opened for this purpose. +- In the resolver API, used by resolver plugins to return the service + config to the gRPC client. +- In the gRPC client API, where users can query the channel to obtain + the service config associated with the channel (for debugging + purposes). +- In the gRPC client API, where users can set the service config + explicitly. This is intended for use in unit tests. From b3f811c7397e06d5c80317bdbda900aed914cf4a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 14 Dec 2016 08:10:11 -0800 Subject: [PATCH 022/104] Add image in PNG format. --- doc/images/load-balancing.png | Bin 0 -> 27733 bytes doc/load-balancing.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 doc/images/load-balancing.png diff --git a/doc/images/load-balancing.png b/doc/images/load-balancing.png new file mode 100644 index 0000000000000000000000000000000000000000..18b68bfdad83d15b33f37eeeb98f582feb8ee0c0 GIT binary patch literal 27733 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≶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 Date: Wed, 14 Dec 2016 08:12:39 -0800 Subject: [PATCH 023/104] Fix link. --- doc/naming.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/naming.md b/doc/naming.md index 5d603061f8a..588f611f163 100644 --- a/doc/naming.md +++ b/doc/naming.md @@ -53,7 +53,7 @@ include: is in use). - The name of the balancer, if the address is a balancer address. This will be used to perform peer authorization. -- A [service config](service-config.md). +- A [service config](service_config.md). The plugin API allows the resolvers to continuously watch an endpoint and return updated resolutions as needed. From d803b805aef97a03bd5873c1a8c3e534bd22feb7 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Fri, 16 Dec 2016 13:59:04 -0800 Subject: [PATCH 024/104] Fix RST_STREAM(0) inconsistency --- src/core/ext/transport/chttp2/transport/frame_rst_stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c index b4c5ed769b9..20043f5fbf4 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.c @@ -109,7 +109,7 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx, (((uint32_t)p->reason_bytes[2]) << 8) | (((uint32_t)p->reason_bytes[3])); grpc_error *error = GRPC_ERROR_NONE; - if (reason != GRPC_CHTTP2_NO_ERROR) { + if (reason != GRPC_CHTTP2_NO_ERROR || s->header_frames_received < 2) { error = grpc_error_set_int(GRPC_ERROR_CREATE("RST_STREAM"), GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)reason); grpc_status_code status_code = grpc_chttp2_http2_error_to_grpc_status( From 66c67827517120b0cf2115e4c9c8af60a24bf252 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Fri, 9 Dec 2016 10:22:50 -0800 Subject: [PATCH 025/104] add --perf_args usage to jenkins performance runner scripts --- tools/jenkins/run_performance_flamegraphs.sh | 56 ++++++++++++++++++++ tools/jenkins/run_sweep_performance.sh | 1 + tools/run_tests/run_performance_tests.py | 15 +++--- 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100755 tools/jenkins/run_performance_flamegraphs.sh diff --git a/tools/jenkins/run_performance_flamegraphs.sh b/tools/jenkins/run_performance_flamegraphs.sh new file mode 100755 index 00000000000..22081e22487 --- /dev/null +++ b/tools/jenkins/run_performance_flamegraphs.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# 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. +# +# This script is invoked by Jenkins and runs full performance test suite. +set -ex + +# Enter the gRPC repo root +cd $(dirname $0)/../.. + +# scalability with 32cores c++ benchmarks +tools/run_tests/run_performance_tests.py \ + -l c++ \ + --category scalable \ + --remote_worker_host grpc-performance-server-32core grpc-performance-client-32core grpc-performance-client2-32core \ + --perf_args "record -F 97 --call-graph dwarf" \ + --flame_graph_reports cpp_flamegraphs \ + || EXIT_CODE=1 + +# scalability with 32cores go benchmarks +tools/run_tests/run_performance_tests.py \ + -l go \ + --category scalable \ + --remote_worker_host grpc-performance-server-32core grpc-performance-client-32core grpc-performance-client2-32core \ + --perf_args "record -F 97 -g" \ + --flame_graph_reports go_flamegraphs \ + || EXIT_CODE=1 + +exit $EXIT_CODE + diff --git a/tools/jenkins/run_sweep_performance.sh b/tools/jenkins/run_sweep_performance.sh index 3b22e25a451..12054dc3dc8 100755 --- a/tools/jenkins/run_sweep_performance.sh +++ b/tools/jenkins/run_sweep_performance.sh @@ -43,6 +43,7 @@ tools/run_tests/run_performance_tests.py \ --category sweep \ --bq_result_table performance_test.performance_experiment_32core \ --remote_worker_host ${SERVER_HOST} ${CLIENT_HOST1} ${CLIENT_HOST2} \ + --perf_args "record -F 97 --call-graph dwarf" \ || EXIT_CODE=1 exit $EXIT_CODE diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py index 69ccff85cf5..06aa42756ef 100755 --- a/tools/run_tests/run_performance_tests.py +++ b/tools/run_tests/run_performance_tests.py @@ -58,8 +58,6 @@ os.chdir(_ROOT) _REMOTE_HOST_USERNAME = 'jenkins' -_PERF_REPORT_OUTPUT_DIR = 'perf_reports' - class QpsWorkerJob: """Encapsulates a qps worker server job.""" @@ -300,11 +298,11 @@ def perf_report_processor_job(worker_host, perf_base_name, output_filename): user_at_host = "%s@%s" % (_REMOTE_HOST_USERNAME, worker_host) cmd = "USER_AT_HOST=%s OUTPUT_FILENAME=%s OUTPUT_DIR=%s PERF_BASE_NAME=%s\ tools/run_tests/performance/process_remote_perf_flamegraphs.sh" \ - % (user_at_host, output_filename, _PERF_REPORT_OUTPUT_DIR, perf_base_name) + % (user_at_host, output_filename, args.flame_graph_reports, perf_base_name) else: cmd = "OUTPUT_FILENAME=%s OUTPUT_DIR=%s PERF_BASE_NAME=%s\ tools/run_tests/performance/process_local_perf_flamegraphs.sh" \ - % (output_filename, _PERF_REPORT_OUTPUT_DIR, perf_base_name) + % (output_filename, args.flame_graph_reports, perf_base_name) return jobset.JobSpec(cmdline=cmd, timeout_seconds=3*60, @@ -469,7 +467,7 @@ argp.add_argument('--perf_args', 'with the arguments to perf specified here. ' '".svg" flame graph profiles will be ' 'created for each Qps Worker on each scenario. ' - 'Files will output to "/perf_reports" ' + 'Files will output to "/" ' 'directory. Output files from running the worker ' 'under perf are saved in the repo root where its ran. ' 'Note that the perf "-g" flag is necessary for ' @@ -489,6 +487,8 @@ argp.add_argument('--skip_generate_flamegraphs', help=('Turn flame graph generation off. ' 'May be useful if "perf_args" arguments do not make sense for ' 'generating flamegraphs (e.g., "--perf_args=stat ...")')) +argp.add_argument('-f', '--flame_graph_reports', default='perf_reports', type=str, + help='Name of directory to output flame graph profiles to, if any are created.') args = argp.parse_args() @@ -522,8 +522,9 @@ if not args.dry_run: perf_cmd = None if args.perf_args: + print('Running workers under perf profiler') # Expect /usr/bin/perf to be installed here, as is usual - perf_cmd = ['/usr/bin/perf'] + perf_cmd = ['/usr/bin/perf'] perf_cmd.extend(re.split('\s+', args.perf_args)) qpsworker_jobs = create_qpsworkers(languages, args.remote_worker_host, perf_cmd=perf_cmd) @@ -582,7 +583,7 @@ for scenario in scenarios: # 'profile_output_files' will only have names for scenarios that passed if perf_cmd and not args.skip_generate_flamegraphs: # write the index fil to the output dir, with all profiles from all scenarios/workers - report_utils.render_perf_profiling_results('%s/index.html' % _PERF_REPORT_OUTPUT_DIR, profile_output_files) + report_utils.render_perf_profiling_results('%s/index.html' % args.flame_graph_reports, profile_output_files) if total_scenario_failures > 0 or qps_workers_killed > 0: print('%s scenarios failed and %s qps worker jobs killed' % (total_scenario_failures, qps_workers_killed)) From 4e6247a23cf94bc363abb2e8eb0d2b03195b9c5d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 5 Jan 2017 10:17:01 -0800 Subject: [PATCH 026/104] Fix sequential write buffering --- Makefile | 2 + include/grpc/impl/codegen/grpc_types.h | 3 + .../chttp2/transport/chttp2_transport.c | 31 +- .../ext/transport/chttp2/transport/internal.h | 6 + test/core/end2end/end2end_nosec_tests.c | 8 + test/core/end2end/end2end_tests.c | 8 + test/core/end2end/gen_build_yaml.py | 1 + test/core/end2end/generate_tests.bzl | 1 + test/core/end2end/tests/write_buffering.c | 291 +++++++ .../generated/sources_and_headers.json | 6 +- tools/run_tests/generated/tests.json | 738 +++++++++++++++++- .../end2end_nosec_tests.vcxproj | 2 + .../end2end_nosec_tests.vcxproj.filters | 3 + .../tests/end2end_tests/end2end_tests.vcxproj | 2 + .../end2end_tests.vcxproj.filters | 3 + 15 files changed, 1085 insertions(+), 20 deletions(-) create mode 100644 test/core/end2end/tests/write_buffering.c diff --git a/Makefile b/Makefile index 8f7328ae285..edcf50ec71c 100644 --- a/Makefile +++ b/Makefile @@ -7215,6 +7215,7 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/simple_request.c \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ + test/core/end2end/tests/write_buffering.c \ PUBLIC_HEADERS_C += \ @@ -7301,6 +7302,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/simple_request.c \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ + test/core/end2end/tests/write_buffering.c \ PUBLIC_HEADERS_C += \ diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 4471ccf7456..4dfd8794992 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -179,6 +179,9 @@ typedef struct { Larger values give lower CPU usage for large messages, but more head of line blocking for small messages. */ #define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size" +/** How much data are we willing to queue up per stream if + GRPC_WRITE_BUFFER_HINT is set? This is an upper bound */ +#define GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE "grpc.http2.write_buffer_size" /** Default authority to pass if none specified on call construction. A string. * */ #define GRPC_ARG_DEFAULT_AUTHORITY "grpc.default_authority" diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 488c3b93ccd..30c66d89529 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -269,6 +269,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, window -- this should by rights be 0 */ t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; t->sent_local_settings = 0; + t->write_buffer_size = DEFAULT_WINDOW; if (is_client) { grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string( @@ -319,6 +320,11 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor, (uint32_t)value); } + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { + t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer( + &channel_args->args[i], + (grpc_integer_options){0, 0, 64 * 1024 * 1024}); } else { static const struct { const char *channel_arg_name; @@ -895,15 +901,22 @@ static bool contains_non_ok_status(grpc_metadata_batch *batch) { return false; } +static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx, + grpc_chttp2_transport *t, + grpc_chttp2_stream *s) { + if (s->id != 0 && (!s->write_buffering || + s->flow_controlled_buffer.length > t->write_buffer_size)) { + grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message"); + } +} + static void add_fetched_slice_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s) { s->fetched_send_message_length += (uint32_t)GRPC_SLICE_LENGTH(s->fetching_slice); grpc_slice_buffer_add(&s->flow_controlled_buffer, s->fetching_slice); - if (s->id != 0) { - grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message"); - } + maybe_become_writable_due_to_send_msg(exec_ctx, t, s); } static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx, @@ -1096,14 +1109,13 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, (int64_t)len; s->complete_fetch_covered_by_poller = op->covered_by_poller; if (flags & GRPC_WRITE_BUFFER_HINT) { - /* allow up to 64kb to be buffered */ - /* TODO(ctiller): make this configurable */ - s->next_message_end_offset -= 65536; + s->next_message_end_offset -= t->write_buffer_size; + s->write_buffering = true; + } else { + s->write_buffering = false; } continue_fetching_send_locked(exec_ctx, t, s); - if (s->id != 0) { - grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message"); - } + maybe_become_writable_due_to_send_msg(exec_ctx, t, s); } } @@ -1112,6 +1124,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; s->send_trailing_metadata_finished = add_closure_barrier(on_complete); s->send_trailing_metadata = op->send_trailing_metadata; + s->write_buffering = false; const size_t metadata_size = grpc_metadata_batch_size(op->send_trailing_metadata); const size_t metadata_peer_limit = diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index a52acbacdb3..ea7beb4c2b6 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -249,6 +249,9 @@ struct grpc_chttp2_transport { int64_t announce_incoming_window; /** how much window would we like to have for incoming_window */ uint32_t connection_window_target; + /** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set? + */ + uint32_t write_buffer_size; /** have we seen a goaway */ uint8_t seen_goaway; @@ -403,6 +406,9 @@ struct grpc_chttp2_stream { /** Has this stream seen an error. If true, then pending incoming frames can be thrown away. */ bool seen_error; + /** Are we buffering writes on this stream? If yes, we won't become writable + until there's enough queued up in the flow_controlled_buffer */ + bool write_buffering; /** the error that resulted in this stream being read-closed */ grpc_error *read_closed_error; diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index 663489082f9..03e98ee850d 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -135,6 +135,8 @@ extern void streaming_error_response(grpc_end2end_test_config config); extern void streaming_error_response_pre_init(void); extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); +extern void write_buffering(grpc_end2end_test_config config); +extern void write_buffering_pre_init(void); void grpc_end2end_tests_pre_init(void) { GPR_ASSERT(!g_pre_init_called); @@ -185,6 +187,7 @@ void grpc_end2end_tests_pre_init(void) { simple_request_pre_init(); streaming_error_response_pre_init(); trailing_metadata_pre_init(); + write_buffering_pre_init(); } void grpc_end2end_tests(int argc, char **argv, @@ -240,6 +243,7 @@ void grpc_end2end_tests(int argc, char **argv, simple_request(config); streaming_error_response(config); trailing_metadata(config); + write_buffering(config); return; } @@ -428,6 +432,10 @@ void grpc_end2end_tests(int argc, char **argv, trailing_metadata(config); continue; } + if (0 == strcmp("write_buffering", argv[i])) { + write_buffering(config); + continue; + } gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); abort(); } diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index 25c7c62fde5..f116dc0c70b 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -137,6 +137,8 @@ extern void streaming_error_response(grpc_end2end_test_config config); extern void streaming_error_response_pre_init(void); extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); +extern void write_buffering(grpc_end2end_test_config config); +extern void write_buffering_pre_init(void); void grpc_end2end_tests_pre_init(void) { GPR_ASSERT(!g_pre_init_called); @@ -188,6 +190,7 @@ void grpc_end2end_tests_pre_init(void) { simple_request_pre_init(); streaming_error_response_pre_init(); trailing_metadata_pre_init(); + write_buffering_pre_init(); } void grpc_end2end_tests(int argc, char **argv, @@ -244,6 +247,7 @@ void grpc_end2end_tests(int argc, char **argv, simple_request(config); streaming_error_response(config); trailing_metadata(config); + write_buffering(config); return; } @@ -436,6 +440,10 @@ void grpc_end2end_tests(int argc, char **argv, trailing_metadata(config); continue; } + if (0 == strcmp("write_buffering", argv[i])) { + write_buffering(config); + continue; + } gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); abort(); } diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 201a92a1fdc..52142c26407 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -143,6 +143,7 @@ END2END_TESTS = { 'streaming_error_response': default_test_options, 'trailing_metadata': default_test_options, 'authority_not_supported': default_test_options, + 'write_buffering': default_test_options, } diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index ed1ba3eea99..8195abab694 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -131,6 +131,7 @@ END2END_TESTS = { 'trailing_metadata': test_options(), 'authority_not_supported': test_options(), 'filter_latency': test_options(), + 'write_buffering': test_options(), } diff --git a/test/core/end2end/tests/write_buffering.c b/test/core/end2end/tests/write_buffering.c new file mode 100644 index 00000000000..856e9f0306f --- /dev/null +++ b/test/core/end2end/tests/write_buffering.c @@ -0,0 +1,291 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice1 = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload1 = + grpc_raw_byte_buffer_create(&request_payload_slice1, 1); + grpc_slice request_payload_slice2 = grpc_slice_from_copied_string("abc123"); + grpc_byte_buffer *request_payload2 = + grpc_raw_byte_buffer_create(&request_payload_slice2, 1); + gpr_timespec deadline = five_seconds_time(); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer *request_payload_recv1 = NULL; + grpc_byte_buffer *request_payload_recv2 = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = request_payload1; + op->flags = GRPC_WRITE_BUFFER_HINT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* recv message should not succeed yet - it's buffered at the client still */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv1; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + CQ_EXPECT_COMPLETION(cqv, tag(3), true); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + /* send another message, this time not buffered */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = request_payload2; + op->flags = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* now the first send should match up with the first recv */ + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + CQ_EXPECT_COMPLETION(cqv, tag(4), true); + cq_verify(cqv); + + /* and the next recv should be ready immediately also */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.status_details = "xyz"; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(105), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == strcmp(details, "xyz")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123")); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + grpc_call_destroy(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload1); + grpc_byte_buffer_destroy(request_payload_recv1); + grpc_byte_buffer_destroy(request_payload2); + grpc_byte_buffer_destroy(request_payload_recv2); + + end_test(&f); + config.tear_down_data(&f); +} + +void write_buffering(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void write_buffering_pre_init(void) {} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 6ae269cc20d..3755f242e0a 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6362,7 +6362,8 @@ "test/core/end2end/tests/simple_metadata.c", "test/core/end2end/tests/simple_request.c", "test/core/end2end/tests/streaming_error_response.c", - "test/core/end2end/tests/trailing_metadata.c" + "test/core/end2end/tests/trailing_metadata.c", + "test/core/end2end/tests/write_buffering.c" ], "third_party": false, "type": "lib" @@ -6431,7 +6432,8 @@ "test/core/end2end/tests/simple_metadata.c", "test/core/end2end/tests/simple_request.c", "test/core/end2end/tests/streaming_error_response.c", - "test/core/end2end/tests/trailing_metadata.c" + "test/core/end2end/tests/trailing_metadata.c", + "test/core/end2end/tests/write_buffering.c" ], "third_party": false, "type": "lib" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index b76263b8b98..50992aa436c 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -6080,6 +6080,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -7163,6 +7186,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -8199,6 +8245,28 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_fakesec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -9165,6 +9233,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -10248,6 +10339,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -11141,6 +11255,25 @@ "linux" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_test", + "platforms": [ + "linux" + ] + }, { "args": [ "authority_not_supported" @@ -12178,6 +12311,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -13306,6 +13462,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -14389,6 +14569,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -15517,6 +15720,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_oauth2_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -16477,6 +16704,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -17487,7 +17738,7 @@ }, { "args": [ - "authority_not_supported" + "write_buffering" ], "ci_platforms": [ "windows", @@ -17501,7 +17752,7 @@ ], "flaky": false, "language": "c", - "name": "h2_sockpair+trace_test", + "name": "h2_sockpair_test", "platforms": [ "windows", "linux", @@ -17511,7 +17762,7 @@ }, { "args": [ - "bad_hostname" + "authority_not_supported" ], "ci_platforms": [ "windows", @@ -17535,7 +17786,7 @@ }, { "args": [ - "binary_metadata" + "bad_hostname" ], "ci_platforms": [ "windows", @@ -17559,7 +17810,7 @@ }, { "args": [ - "call_creds" + "binary_metadata" ], "ci_platforms": [ "windows", @@ -17583,14 +17834,14 @@ }, { "args": [ - "cancel_after_accept" + "call_creds" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -17607,14 +17858,38 @@ }, { "args": [ - "cancel_after_client_done" + "cancel_after_accept" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_client_done" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -18421,6 +18696,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -19487,6 +19786,32 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -20570,6 +20895,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -21653,6 +22001,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_cert_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -22613,6 +22984,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_ssl_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -23671,6 +24066,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -24731,6 +25149,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -25791,6 +26232,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -26734,6 +27198,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -27794,6 +28281,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -28668,6 +29178,25 @@ "linux" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_nosec_test", + "platforms": [ + "linux" + ] + }, { "args": [ "authority_not_supported" @@ -29682,6 +30211,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -30786,6 +31338,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -31846,6 +32422,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -32782,6 +33381,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -33766,6 +34389,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -34678,6 +35325,30 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -35718,6 +36389,32 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -36753,6 +37450,29 @@ "posix" ] }, + { + "args": [ + "write_buffering" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "--scenarios_json", diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj index 4fb8f8f4a15..5f1ea5ed274 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj @@ -247,6 +247,8 @@ + + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters index ff82a4dd43c..5f38c36f78d 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters @@ -145,6 +145,9 @@ test\core\end2end\tests + + test\core\end2end\tests + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj index 0b7d7c2e752..83e57eff7d0 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj @@ -249,6 +249,8 @@ + + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters index e641930e64a..00587c05b82 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters @@ -148,6 +148,9 @@ test\core\end2end\tests + + test\core\end2end\tests + From 2ef5a647bfb2bc9390a14be843647c2fb7841b36 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 5 Jan 2017 10:33:47 -0800 Subject: [PATCH 027/104] Add a test of finishing buffering with EOS --- Makefile | 2 + test/core/end2end/end2end_nosec_tests.c | 8 + test/core/end2end/end2end_tests.c | 8 + test/core/end2end/gen_build_yaml.py | 1 + test/core/end2end/generate_tests.bzl | 1 + .../end2end/tests/write_buffering_at_end.c | 280 +++++++ .../generated/sources_and_headers.json | 6 +- tools/run_tests/generated/tests.json | 738 +++++++++++++++++- .../end2end_nosec_tests.vcxproj | 2 + .../end2end_nosec_tests.vcxproj.filters | 3 + .../tests/end2end_tests/end2end_tests.vcxproj | 2 + .../end2end_tests.vcxproj.filters | 3 + 12 files changed, 1043 insertions(+), 11 deletions(-) create mode 100644 test/core/end2end/tests/write_buffering_at_end.c diff --git a/Makefile b/Makefile index edcf50ec71c..da06d17547c 100644 --- a/Makefile +++ b/Makefile @@ -7216,6 +7216,7 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ test/core/end2end/tests/write_buffering.c \ + test/core/end2end/tests/write_buffering_at_end.c \ PUBLIC_HEADERS_C += \ @@ -7303,6 +7304,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ test/core/end2end/tests/write_buffering.c \ + test/core/end2end/tests/write_buffering_at_end.c \ PUBLIC_HEADERS_C += \ diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index 03e98ee850d..b162bf2f40f 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -137,6 +137,8 @@ extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); extern void write_buffering(grpc_end2end_test_config config); extern void write_buffering_pre_init(void); +extern void write_buffering_at_end(grpc_end2end_test_config config); +extern void write_buffering_at_end_pre_init(void); void grpc_end2end_tests_pre_init(void) { GPR_ASSERT(!g_pre_init_called); @@ -188,6 +190,7 @@ void grpc_end2end_tests_pre_init(void) { streaming_error_response_pre_init(); trailing_metadata_pre_init(); write_buffering_pre_init(); + write_buffering_at_end_pre_init(); } void grpc_end2end_tests(int argc, char **argv, @@ -244,6 +247,7 @@ void grpc_end2end_tests(int argc, char **argv, streaming_error_response(config); trailing_metadata(config); write_buffering(config); + write_buffering_at_end(config); return; } @@ -436,6 +440,10 @@ void grpc_end2end_tests(int argc, char **argv, write_buffering(config); continue; } + if (0 == strcmp("write_buffering_at_end", argv[i])) { + write_buffering_at_end(config); + continue; + } gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); abort(); } diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index f116dc0c70b..9bca0c81f67 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -139,6 +139,8 @@ extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); extern void write_buffering(grpc_end2end_test_config config); extern void write_buffering_pre_init(void); +extern void write_buffering_at_end(grpc_end2end_test_config config); +extern void write_buffering_at_end_pre_init(void); void grpc_end2end_tests_pre_init(void) { GPR_ASSERT(!g_pre_init_called); @@ -191,6 +193,7 @@ void grpc_end2end_tests_pre_init(void) { streaming_error_response_pre_init(); trailing_metadata_pre_init(); write_buffering_pre_init(); + write_buffering_at_end_pre_init(); } void grpc_end2end_tests(int argc, char **argv, @@ -248,6 +251,7 @@ void grpc_end2end_tests(int argc, char **argv, streaming_error_response(config); trailing_metadata(config); write_buffering(config); + write_buffering_at_end(config); return; } @@ -444,6 +448,10 @@ void grpc_end2end_tests(int argc, char **argv, write_buffering(config); continue; } + if (0 == strcmp("write_buffering_at_end", argv[i])) { + write_buffering_at_end(config); + continue; + } gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); abort(); } diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 52142c26407..bcb7136eaa2 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -144,6 +144,7 @@ END2END_TESTS = { 'trailing_metadata': default_test_options, 'authority_not_supported': default_test_options, 'write_buffering': default_test_options, + 'write_buffering_at_end': default_test_options, } diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 8195abab694..95c06de73f9 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -132,6 +132,7 @@ END2END_TESTS = { 'authority_not_supported': test_options(), 'filter_latency': test_options(), 'write_buffering': test_options(), + 'write_buffering_at_end': test_options(), } diff --git a/test/core/end2end/tests/write_buffering_at_end.c b/test/core/end2end/tests/write_buffering_at_end.c new file mode 100644 index 00000000000..43aefcbdbcc --- /dev/null +++ b/test/core/end2end/tests/write_buffering_at_end.c @@ -0,0 +1,280 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + gpr_timespec deadline = five_seconds_time(); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer *request_payload_recv1 = NULL; + grpc_byte_buffer *request_payload_recv2 = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = request_payload; + op->flags = GRPC_WRITE_BUFFER_HINT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* recv message should not succeed yet - it's buffered at the client still */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv1; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + CQ_EXPECT_COMPLETION(cqv, tag(3), true); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + /* send end of stream: should release the buffering */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* now the first send should match up with the first recv */ + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + CQ_EXPECT_COMPLETION(cqv, tag(4), true); + cq_verify(cqv); + + /* and the next recv should be ready immediately also (and empty) */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.status_details = "xyz"; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(105), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == strcmp(details, "xyz")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); + GPR_ASSERT(request_payload_recv2 == NULL); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + grpc_call_destroy(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv1); + + end_test(&f); + config.tear_down_data(&f); +} + +void write_buffering_at_end(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void write_buffering_at_end_pre_init(void) {} diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 3755f242e0a..9287c839745 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6363,7 +6363,8 @@ "test/core/end2end/tests/simple_request.c", "test/core/end2end/tests/streaming_error_response.c", "test/core/end2end/tests/trailing_metadata.c", - "test/core/end2end/tests/write_buffering.c" + "test/core/end2end/tests/write_buffering.c", + "test/core/end2end/tests/write_buffering_at_end.c" ], "third_party": false, "type": "lib" @@ -6433,7 +6434,8 @@ "test/core/end2end/tests/simple_request.c", "test/core/end2end/tests/streaming_error_response.c", "test/core/end2end/tests/trailing_metadata.c", - "test/core/end2end/tests/write_buffering.c" + "test/core/end2end/tests/write_buffering.c", + "test/core/end2end/tests/write_buffering_at_end.c" ], "third_party": false, "type": "lib" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 50992aa436c..9ac477c5cd4 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -6103,6 +6103,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -7209,6 +7232,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -8267,6 +8313,28 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_fakesec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -9256,6 +9324,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -10362,6 +10453,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -11274,6 +11388,25 @@ "linux" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_test", + "platforms": [ + "linux" + ] + }, { "args": [ "authority_not_supported" @@ -12334,6 +12467,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -13486,6 +13642,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -14592,6 +14772,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -15744,6 +15947,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_oauth2_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -16728,6 +16955,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -17762,7 +18013,7 @@ }, { "args": [ - "authority_not_supported" + "write_buffering_at_end" ], "ci_platforms": [ "windows", @@ -17776,7 +18027,7 @@ ], "flaky": false, "language": "c", - "name": "h2_sockpair+trace_test", + "name": "h2_sockpair_test", "platforms": [ "windows", "linux", @@ -17786,7 +18037,7 @@ }, { "args": [ - "bad_hostname" + "authority_not_supported" ], "ci_platforms": [ "windows", @@ -17810,7 +18061,7 @@ }, { "args": [ - "binary_metadata" + "bad_hostname" ], "ci_platforms": [ "windows", @@ -17834,7 +18085,7 @@ }, { "args": [ - "call_creds" + "binary_metadata" ], "ci_platforms": [ "windows", @@ -17858,14 +18109,14 @@ }, { "args": [ - "cancel_after_accept" + "call_creds" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -17882,14 +18133,38 @@ }, { "args": [ - "cancel_after_client_done" + "cancel_after_accept" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_client_done" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -18720,6 +18995,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -19812,6 +20111,32 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -20918,6 +21243,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -22024,6 +22372,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_cert_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -23008,6 +23379,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_ssl_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -24089,6 +24484,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -25172,6 +25590,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -26255,6 +26696,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -27221,6 +27685,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -28304,6 +28791,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -29197,6 +29707,25 @@ "linux" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_nosec_test", + "platforms": [ + "linux" + ] + }, { "args": [ "authority_not_supported" @@ -30234,6 +30763,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -31362,6 +31914,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -32445,6 +33021,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -33405,6 +34004,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -34413,6 +35036,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -35349,6 +35996,30 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -36415,6 +37086,32 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "authority_not_supported" @@ -37473,6 +38170,29 @@ "posix" ] }, + { + "args": [ + "write_buffering_at_end" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "--scenarios_json", diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj index 5f1ea5ed274..6506f24d1bb 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj @@ -249,6 +249,8 @@ + + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters index 5f38c36f78d..77e5ebf8b19 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters @@ -148,6 +148,9 @@ test\core\end2end\tests + + test\core\end2end\tests + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj index 83e57eff7d0..176e8f71976 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj @@ -251,6 +251,8 @@ + + diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters index 00587c05b82..fa702679338 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters @@ -151,6 +151,9 @@ test\core\end2end\tests + + test\core\end2end\tests + From fd9f53a20fc87d1ff70f38c850eb7f03296cfb60 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 6 Jan 2017 15:33:04 -0800 Subject: [PATCH 028/104] clang-format --- include/grpc/impl/codegen/slice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h index 9c226f78c47..00781bb76bd 100644 --- a/include/grpc/impl/codegen/slice.h +++ b/include/grpc/impl/codegen/slice.h @@ -37,8 +37,8 @@ #include #include -#include #include +#include /* Slice API From c17ed124eca8fc6bed31c6e0d192fde386bdb3c2 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Mon, 9 Jan 2017 09:37:43 -0800 Subject: [PATCH 029/104] Ran generate-projects.sh --- tools/doxygen/Doxyfile.c++ | 32 ++++++++--------- tools/doxygen/Doxyfile.c++.internal | 32 ++++++++--------- tools/doxygen/Doxyfile.core | 32 ++++++++--------- tools/doxygen/Doxyfile.core.internal | 52 ++++++++++++++-------------- 4 files changed, 74 insertions(+), 74 deletions(-) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 2cd59863b62..13f440441bc 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -850,31 +850,31 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ doc/fail_fast.md \ +doc/g_stands_for.md \ +doc/wait-for-ready.md \ +doc/binary-logging.md \ doc/compression.md \ -doc/environment_variables.md \ -doc/stress_test_framework.md \ +doc/c-style-guide.md \ doc/PROTOCOL-WEB.md \ doc/cpp-style-guide.md \ -doc/http-grpc-status-mapping.md \ -doc/wait-for-ready.md \ -doc/command_line_tool.md \ -doc/c-style-guide.md \ doc/server_reflection_tutorial.md \ -doc/health-checking.md \ -doc/connection-backoff-interop-test-description.md \ +doc/server-reflection.md \ +doc/interop-test-descriptions.md \ +doc/PROTOCOL-HTTP2.md \ +doc/compression_cookbook.md \ +doc/connection-backoff.md \ doc/epoll-polling-engine.md \ -doc/naming.md \ -doc/binary-logging.md \ doc/connectivity-semantics-and-api.md \ -doc/connection-backoff.md \ -doc/compression_cookbook.md \ -doc/PROTOCOL-HTTP2.md \ doc/load-balancing.md \ +doc/environment_variables.md \ +doc/naming.md \ +doc/stress_test_framework.md \ +doc/http-grpc-status-mapping.md \ +doc/health-checking.md \ +doc/connection-backoff-interop-test-description.md \ doc/negative-http2-interop-test-descriptions.md \ -doc/server-reflection.md \ -doc/interop-test-descriptions.md \ +doc/command_line_tool.md \ doc/statuscodes.md \ -doc/g_stands_for.md \ doc/cpp/perf_notes.md \ doc/cpp/pending_api_cleanups.md diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 6ab452eaba9..a86dfde1726 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -896,31 +896,31 @@ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ src/cpp/codegen/codegen_init.cc \ doc/fail_fast.md \ +doc/g_stands_for.md \ +doc/wait-for-ready.md \ +doc/binary-logging.md \ doc/compression.md \ -doc/environment_variables.md \ -doc/stress_test_framework.md \ +doc/c-style-guide.md \ doc/PROTOCOL-WEB.md \ doc/cpp-style-guide.md \ -doc/http-grpc-status-mapping.md \ -doc/wait-for-ready.md \ -doc/command_line_tool.md \ -doc/c-style-guide.md \ doc/server_reflection_tutorial.md \ -doc/health-checking.md \ -doc/connection-backoff-interop-test-description.md \ +doc/server-reflection.md \ +doc/interop-test-descriptions.md \ +doc/PROTOCOL-HTTP2.md \ +doc/compression_cookbook.md \ +doc/connection-backoff.md \ doc/epoll-polling-engine.md \ -doc/naming.md \ -doc/binary-logging.md \ doc/connectivity-semantics-and-api.md \ -doc/connection-backoff.md \ -doc/compression_cookbook.md \ -doc/PROTOCOL-HTTP2.md \ doc/load-balancing.md \ +doc/environment_variables.md \ +doc/naming.md \ +doc/stress_test_framework.md \ +doc/http-grpc-status-mapping.md \ +doc/health-checking.md \ +doc/connection-backoff-interop-test-description.md \ doc/negative-http2-interop-test-descriptions.md \ -doc/server-reflection.md \ -doc/interop-test-descriptions.md \ +doc/command_line_tool.md \ doc/statuscodes.md \ -doc/g_stands_for.md \ doc/cpp/perf_notes.md \ doc/cpp/pending_api_cleanups.md \ src/cpp/README.md diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 16f8dcc29e5..ec4d6813e83 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -829,31 +829,31 @@ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ doc/fail_fast.md \ +doc/g_stands_for.md \ +doc/wait-for-ready.md \ +doc/binary-logging.md \ doc/compression.md \ -doc/environment_variables.md \ -doc/stress_test_framework.md \ +doc/c-style-guide.md \ doc/PROTOCOL-WEB.md \ doc/cpp-style-guide.md \ -doc/http-grpc-status-mapping.md \ -doc/wait-for-ready.md \ -doc/command_line_tool.md \ -doc/c-style-guide.md \ doc/server_reflection_tutorial.md \ -doc/health-checking.md \ -doc/connection-backoff-interop-test-description.md \ +doc/server-reflection.md \ +doc/interop-test-descriptions.md \ +doc/PROTOCOL-HTTP2.md \ +doc/compression_cookbook.md \ +doc/connection-backoff.md \ doc/epoll-polling-engine.md \ -doc/naming.md \ -doc/binary-logging.md \ doc/connectivity-semantics-and-api.md \ -doc/connection-backoff.md \ -doc/compression_cookbook.md \ -doc/PROTOCOL-HTTP2.md \ doc/load-balancing.md \ +doc/environment_variables.md \ +doc/naming.md \ +doc/stress_test_framework.md \ +doc/http-grpc-status-mapping.md \ +doc/health-checking.md \ +doc/connection-backoff-interop-test-description.md \ doc/negative-http2-interop-test-descriptions.md \ -doc/server-reflection.md \ -doc/interop-test-descriptions.md \ +doc/command_line_tool.md \ doc/statuscodes.md \ -doc/g_stands_for.md \ doc/core/pending_api_cleanups.md # This tag can be used to specify the character encoding of the source files diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index d9f69427b1b..34e5304ce4e 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1280,53 +1280,53 @@ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_windows.c \ src/core/lib/support/wrap_memcpy.c \ doc/fail_fast.md \ +doc/g_stands_for.md \ +doc/wait-for-ready.md \ +doc/binary-logging.md \ doc/compression.md \ -doc/environment_variables.md \ -doc/stress_test_framework.md \ +doc/c-style-guide.md \ doc/PROTOCOL-WEB.md \ doc/cpp-style-guide.md \ -doc/http-grpc-status-mapping.md \ -doc/wait-for-ready.md \ -doc/command_line_tool.md \ -doc/c-style-guide.md \ doc/server_reflection_tutorial.md \ -doc/health-checking.md \ -doc/connection-backoff-interop-test-description.md \ +doc/server-reflection.md \ +doc/interop-test-descriptions.md \ +doc/PROTOCOL-HTTP2.md \ +doc/compression_cookbook.md \ +doc/connection-backoff.md \ doc/epoll-polling-engine.md \ -doc/naming.md \ -doc/binary-logging.md \ doc/connectivity-semantics-and-api.md \ -doc/connection-backoff.md \ -doc/compression_cookbook.md \ -doc/PROTOCOL-HTTP2.md \ doc/load-balancing.md \ +doc/environment_variables.md \ +doc/naming.md \ +doc/stress_test_framework.md \ +doc/http-grpc-status-mapping.md \ +doc/health-checking.md \ +doc/connection-backoff-interop-test-description.md \ doc/negative-http2-interop-test-descriptions.md \ -doc/server-reflection.md \ -doc/interop-test-descriptions.md \ +doc/command_line_tool.md \ doc/statuscodes.md \ -doc/g_stands_for.md \ doc/core/pending_api_cleanups.md \ src/core/README.md \ src/core/ext/README.md \ +src/core/ext/resolver/README.md \ +src/core/ext/resolver/dns/native/README.md \ +src/core/ext/resolver/sockaddr/README.md \ +src/core/ext/client_channel/README.md \ src/core/ext/transport/README.md \ src/core/ext/transport/chttp2/README.md \ -src/core/ext/transport/chttp2/client/secure/README.md \ src/core/ext/transport/chttp2/client/insecure/README.md \ -src/core/ext/transport/chttp2/transport/README.md \ -src/core/ext/transport/chttp2/server/secure/README.md \ +src/core/ext/transport/chttp2/client/secure/README.md \ src/core/ext/transport/chttp2/server/insecure/README.md \ -src/core/ext/client_channel/README.md \ -src/core/ext/resolver/README.md \ -src/core/ext/resolver/sockaddr/README.md \ -src/core/ext/resolver/dns/native/README.md \ +src/core/ext/transport/chttp2/server/secure/README.md \ +src/core/ext/transport/chttp2/transport/README.md \ src/core/ext/census/README.md \ src/core/ext/census/gen/README.md \ src/core/lib/README.md \ +src/core/lib/iomgr/README.md \ src/core/lib/tsi/README.md \ -src/core/lib/channel/README.md \ +src/core/lib/surface/README.md \ src/core/lib/transport/README.md \ -src/core/lib/iomgr/README.md \ -src/core/lib/surface/README.md +src/core/lib/channel/README.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses From 871626ff160b6431c3b20ba906d80f4aa7edc0c1 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 9 Jan 2017 18:06:49 -0800 Subject: [PATCH 030/104] clang-format --- src/core/ext/transport/cronet/transport/cronet_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index 099f50b4065..06c7e41dad7 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -1001,7 +1001,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, stream_state->rs.length_field_received = false; CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, - stream_state->rs.remaining_bytes); + stream_state->rs.remaining_bytes); result = ACTION_TAKEN_NO_CALLBACK; } } else if (stream_op->recv_trailing_metadata && From a52032ed09924f4e939ee4b87ad4e39854fe7a59 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 10 Jan 2017 03:35:41 +0000 Subject: [PATCH 031/104] Build fix --- Makefile | 13 ++ .../generated/sources_and_headers.json | 23 +++- .../vcxproj/benchmark/benchmark.vcxproj | 48 ++++++- .../benchmark/benchmark.vcxproj.filters | 118 ++++++++++++++++++ 4 files changed, 200 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6e690a46eb0..a26842e71b1 100644 --- a/Makefile +++ b/Makefile @@ -7017,6 +7017,19 @@ endif LIBBENCHMARK_SRC = \ + third_party/benchmark/src/benchmark.cc \ + third_party/benchmark/src/benchmark_register.cc \ + third_party/benchmark/src/colorprint.cc \ + third_party/benchmark/src/commandlineflags.cc \ + third_party/benchmark/src/complexity.cc \ + third_party/benchmark/src/console_reporter.cc \ + third_party/benchmark/src/csv_reporter.cc \ + third_party/benchmark/src/json_reporter.cc \ + third_party/benchmark/src/reporter.cc \ + third_party/benchmark/src/sleep.cc \ + third_party/benchmark/src/string_util.cc \ + third_party/benchmark/src/sysinfo.cc \ + third_party/benchmark/src/timers.cc \ PUBLIC_HEADERS_CXX += \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index bd5b76ec1da..e80937be17f 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6206,7 +6206,28 @@ }, { "deps": [], - "headers": [], + "headers": [ + "third_party/benchmark/include/benchmark/benchmark.h", + "third_party/benchmark/include/benchmark/benchmark_api.h", + "third_party/benchmark/include/benchmark/macros.h", + "third_party/benchmark/include/benchmark/reporter.h", + "third_party/benchmark/src/arraysize.h", + "third_party/benchmark/src/benchmark_api_internal.h", + "third_party/benchmark/src/check.h", + "third_party/benchmark/src/colorprint.h", + "third_party/benchmark/src/commandlineflags.h", + "third_party/benchmark/src/complexity.h", + "third_party/benchmark/src/cycleclock.h", + "third_party/benchmark/src/internal_macros.h", + "third_party/benchmark/src/log.h", + "third_party/benchmark/src/mutex.h", + "third_party/benchmark/src/re.h", + "third_party/benchmark/src/sleep.h", + "third_party/benchmark/src/stat.h", + "third_party/benchmark/src/string_util.h", + "third_party/benchmark/src/sysinfo.h", + "third_party/benchmark/src/timers.h" + ], "is_filegroup": false, "language": "c++", "name": "benchmark", diff --git a/vsprojects/vcxproj/benchmark/benchmark.vcxproj b/vsprojects/vcxproj/benchmark/benchmark.vcxproj index 811317595f4..9f262b3b00c 100644 --- a/vsprojects/vcxproj/benchmark/benchmark.vcxproj +++ b/vsprojects/vcxproj/benchmark/benchmark.vcxproj @@ -147,7 +147,53 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters b/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters index 00e4276f1d4..ccc9ca2cae7 100644 --- a/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters +++ b/vsprojects/vcxproj/benchmark/benchmark.vcxproj.filters @@ -1,7 +1,125 @@ + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + + + third_party\benchmark\include\benchmark + + + third_party\benchmark\include\benchmark + + + third_party\benchmark\include\benchmark + + + third_party\benchmark\include\benchmark + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + third_party\benchmark\src + + + + {7b593518-9fee-107e-6b64-24bdce73f939} + + + {f0d35de1-6b41-778d-0ba0-faad514fb0f4} + + + {cbc02dfa-face-8cc6-0efb-efacc0c3369c} + + + {4f2f03fc-b82d-df33-63ee-bedebeb2c0ee} + + + {f42a8e0a-5a76-0e6f-d708-f0306858f673} + From 8d770144c259abbd7a307e96f9aec5e9bda1c4ea Mon Sep 17 00:00:00 2001 From: thinkerou Date: Tue, 10 Jan 2017 13:26:42 +0800 Subject: [PATCH 032/104] attempt to fix mem leaks --- src/php/ext/grpc/call.c | 2 ++ src/php/ext/grpc/call_credentials.c | 10 +++--- src/php/ext/grpc/channel_credentials.c | 12 ++------ src/php/ext/grpc/php7_wrapper.h | 12 ++++++++ src/php/ext/grpc/php_grpc.h | 4 --- src/php/ext/grpc/server_credentials.c | 4 +-- src/php/ext/grpc/timeval.c | 42 +++++++++----------------- 7 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index 3a49ea87081..64b1137c2a4 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -478,6 +478,7 @@ PHP_METHOD(Call, startBatch) { true); add_property_zval(result, "status", recv_status); PHP_GRPC_DELREF(recv_status); + PHP_GRPC_FREE_STD_ZVAL(recv_status); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: add_property_bool(result, "cancelled", cancelled); @@ -501,6 +502,7 @@ cleanup: } if (ops[i].op == GRPC_OP_RECV_MESSAGE) { grpc_byte_buffer_destroy(message); + PHP_GRPC_FREE_STD_ZVAL(message_str); } } RETURN_DESTROY_ZVAL(result); diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c index 3aafc3a19b6..043817facd1 100644 --- a/src/php/ext/grpc/call_credentials.c +++ b/src/php/ext/grpc/call_credentials.c @@ -111,9 +111,7 @@ PHP_METHOD(CallCredentials, createComposite) { grpc_call_credentials *creds = grpc_composite_call_credentials_create(cred1->wrapped, cred2->wrapped, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -155,9 +153,7 @@ PHP_METHOD(CallCredentials, createFromPlugin) { grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin(plugin, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -211,6 +207,8 @@ void plugin_destroy_state(void *ptr) { plugin_state *state = (plugin_state *)ptr; efree(state->fci); efree(state->fci_cache); + PHP_GRPC_FREE_STD_ZVAL(state->fci->params); + PHP_GRPC_FREE_STD_ZVAL(state->fci->retval); efree(state); } diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c index a32c4a4ea24..36a8223b880 100644 --- a/src/php/ext/grpc/channel_credentials.c +++ b/src/php/ext/grpc/channel_credentials.c @@ -121,9 +121,7 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { */ PHP_METHOD(ChannelCredentials, createDefault) { grpc_channel_credentials *creds = grpc_google_default_credentials_create(); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -160,9 +158,7 @@ PHP_METHOD(ChannelCredentials, createSsl) { grpc_channel_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } @@ -191,9 +187,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { grpc_channel_credentials *creds = grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h index 1d7824113fa..72e982d6fc9 100644 --- a/src/php/ext/grpc/php7_wrapper.h +++ b/src/php/ext/grpc/php7_wrapper.h @@ -50,8 +50,13 @@ #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val, dup) #define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv) +#define PHP_GRPC_FREE_STD_ZVAL(pzv) #define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv) +#define RETURN_DESTROY_ZVAL(val) \ + RETURN_ZVAL(val, false /* Don't execute copy constructor */, \ + true /* Dealloc original before returning */) + #define PHP_GRPC_WRAP_OBJECT_START(name) \ typedef struct name { \ zend_object std; @@ -144,8 +149,15 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len, #define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val) #define PHP_GRPC_MAKE_STD_ZVAL(pzv) \ pzv = (zval *)emalloc(sizeof(zval)); +#define PHP_GRPC_FREE_STD_ZVAL(pzv) efree(pzv); #define PHP_GRPC_DELREF(zv) +#define RETURN_DESTROY_ZVAL(val) \ + RETVAL_ZVAL(val, false /* Don't execute copy constructor */, \ + true /* Dealloc original before returning */); \ + efree(val); \ + return + #define PHP_GRPC_WRAP_OBJECT_START(name) \ typedef struct name { #define PHP_GRPC_WRAP_OBJECT_END(name) \ diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h index e57a06545e6..13083b0bc71 100644 --- a/src/php/ext/grpc/php_grpc.h +++ b/src/php/ext/grpc/php_grpc.h @@ -61,10 +61,6 @@ extern zend_module_entry grpc_module_entry; #include "grpc/grpc.h" -#define RETURN_DESTROY_ZVAL(val) \ - RETURN_ZVAL(val, false /* Don't execute copy constructor */, \ - true /* Dealloc original before returning */) - /* These are all function declarations */ /* Code that runs at module initialization */ PHP_MINIT_FUNCTION(grpc); diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index 1610c8ebb09..3e39fee246c 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -113,9 +113,7 @@ PHP_METHOD(ServerCredentials, createSsl) { grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, &pem_key_cert_pair, 1, GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); - zval *creds_object; - PHP_GRPC_MAKE_STD_ZVAL(creds_object); - creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); + zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); } diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c index 945231b47fe..7ada915aadd 100644 --- a/src/php/ext/grpc/timeval.c +++ b/src/php/ext/grpc/timeval.c @@ -115,11 +115,9 @@ PHP_METHOD(Timeval, add) { } wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); - zval *sum; - PHP_GRPC_MAKE_STD_ZVAL(sum); - sum = - grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) - TSRMLS_CC); + zval *sum = + grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(sum); } @@ -141,11 +139,9 @@ PHP_METHOD(Timeval, subtract) { } wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); - zval *diff; - PHP_GRPC_MAKE_STD_ZVAL(diff); - diff = - grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) - TSRMLS_CC); + zval *diff = + grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(diff); } @@ -206,9 +202,7 @@ PHP_METHOD(Timeval, similar) { * @return Timeval The current time */ PHP_METHOD(Timeval, now) { - zval *now; - PHP_GRPC_MAKE_STD_ZVAL(now); - now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(now); } @@ -217,13 +211,9 @@ PHP_METHOD(Timeval, now) { * @return Timeval Zero length time interval */ PHP_METHOD(Timeval, zero) { - zval *grpc_php_timeval_zero; - PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_zero); - grpc_php_timeval_zero = - grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); - RETURN_ZVAL(grpc_php_timeval_zero, - false, /* Copy original before returning? */ - true /* Destroy original before returning */); + zval *grpc_php_timeval_zero = + grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); + RETURN_DESTROY_ZVAL(grpc_php_timeval_zero); } /** @@ -231,10 +221,8 @@ PHP_METHOD(Timeval, zero) { * @return Timeval Infinite future time value */ PHP_METHOD(Timeval, infFuture) { - zval *grpc_php_timeval_inf_future; - PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_future); - grpc_php_timeval_inf_future = - grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *grpc_php_timeval_inf_future = + grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future); } @@ -243,10 +231,8 @@ PHP_METHOD(Timeval, infFuture) { * @return Timeval Infinite past time value */ PHP_METHOD(Timeval, infPast) { - zval *grpc_php_timeval_inf_past; - PHP_GRPC_MAKE_STD_ZVAL(grpc_php_timeval_inf_past); - grpc_php_timeval_inf_past = - grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); + zval *grpc_php_timeval_inf_past = + grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past); } From 9d1cc8c94bca8483bd94496fd4f4c1e518a101d3 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 10 Jan 2017 13:57:25 -0800 Subject: [PATCH 033/104] Change interop test infra to run new Ruby tests --- tools/run_tests/run_interop_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 981e38b813d..08c4a878f09 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -350,10 +350,10 @@ class RubyLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_ADVANCED + _SKIP_SERVER_COMPRESSION + return _SKIP_SERVER_COMPRESSION def unimplemented_test_cases_server(self): - return _SKIP_ADVANCED + _SKIP_COMPRESSION + return _SKIP_COMPRESSION def __str__(self): return 'ruby' From d383e4aa886d6a8191b4f7be987eba57c82ec2b4 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 10 Jan 2017 13:58:07 -0800 Subject: [PATCH 034/104] added ability to run bad-server http2 tests --- tools/run_tests/run_interop_tests.py | 94 ++++++++++++++++++++++++---- 1 file changed, 82 insertions(+), 12 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 981e38b813d..02694c89228 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -169,6 +169,9 @@ class JavaLanguage: def client_cmd(self, args): return ['./run-test-client.sh'] + args + def client_cmd_http2interop(self, args): + return ['./run-http2-client.sh'] + args + def cloud_to_prod_env(self): return {} @@ -179,10 +182,10 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_COMPRESSION + return _SKIP_ADVANCED + _SKIP_COMPRESSION def unimplemented_test_cases_server(self): - return _SKIP_COMPRESSION + return _SKIP_ADVANCED + _SKIP_COMPRESSION def __str__(self): return 'java' @@ -226,11 +229,15 @@ class Http2Client: """ def __init__(self): self.client_cwd = None + self.server_cwd = None self.safename = str(self) def client_cmd(self, args): return ['tools/http2_interop/http2_interop.test', '-test.v'] + args + def server_cmd(self, args): + return ['python test/http2_test/http2_test_server.py'] + def cloud_to_prod_env(self): return {} @@ -375,6 +382,11 @@ class PythonLanguage: '--args="{}"'.format(' '.join(args)) ] + def client_cmd_http2interop(self, args): + return [ 'py27/bin/python', + 'src/python/grpcio_tests/tests/http2/_negative_http2_client.py', + ] + args + def cloud_to_prod_env(self): return {} @@ -429,7 +441,10 @@ _TEST_CASES = ['large_unary', 'empty_unary', 'ping_pong', _AUTH_TEST_CASES = ['compute_engine_creds', 'jwt_token_creds', 'oauth2_auth_token', 'per_rpc_creds'] -_HTTP2_TEST_CASES = ["tls", "framing"] +_HTTP2_TEST_CASES = ['tls', 'framing'] + +_HTTP2_BADSERVER_TEST_CASES = ['rst_after_header', 'rst_after_data', 'rst_during_data', + 'goaway', 'ping', 'max_streams'] DOCKER_WORKDIR_ROOT = '/var/local/git/grpc' @@ -550,13 +565,26 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name, def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, server_port, docker_image=None): """Creates jobspec for cloud-to-cloud interop test""" - cmdline = bash_cmdline(language.client_cmd([ + interop_only_options = [ '--server_host_override=foo.test.google.fr', '--use_tls=true', '--use_test_ca=true', + ] + common_options = [ '--test_case=%s' % test_case, '--server_host=%s' % server_host, - '--server_port=%s' % server_port])) + ] + if test_case in sorted(_HTTP2_BADSERVER_TEST_CASES): + # We are running the http2_badserver_interop test. Adjust command line accordingly. + offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case) + client_options = common_options + ['--server_port=%s' % + (int(server_port)+offset)] + cmdline = bash_cmdline(language.client_cmd_http2interop(client_options)) + else: + client_options = interop_only_options + common_options + ['--server_port=%s' % server_port] + cmdline = bash_cmdline(language.client_cmd(client_options)) + + print('Client_CMD = %s'%cmdline) cwd = language.client_cwd environ = language.global_env() if docker_image: @@ -590,13 +618,30 @@ def server_jobspec(language, docker_image): cmdline = bash_cmdline( language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT])) environ = language.global_env() + if language.safename == 'http2': + # we are running the http2 interop server. Open next N ports beginning + # with the server port. These ports are used for http2 interop test + # (one test case per port). We also attach the docker container running + # the server to local network, so we don't have to mess with port mapping + port_args = [ + '-p', str(_DEFAULT_SERVER_PORT+0), + '-p', str(_DEFAULT_SERVER_PORT+1), + '-p', str(_DEFAULT_SERVER_PORT+2), + '-p', str(_DEFAULT_SERVER_PORT+3), + '-p', str(_DEFAULT_SERVER_PORT+4), + '-p', str(_DEFAULT_SERVER_PORT+5), + '-p', str(_DEFAULT_SERVER_PORT+6), + '--net=host', + ] + else: + port_args = ['-p', str(_DEFAULT_SERVER_PORT)] + docker_cmdline = docker_run_cmdline(cmdline, image=docker_image, cwd=language.server_cwd, environ=environ, - docker_args=['-p', str(_DEFAULT_SERVER_PORT), - '--name', container_name]) - + docker_args=port_args + + ['--name', container_name]) server_job = jobset.JobSpec( cmdline=docker_cmdline, environ=environ, @@ -730,7 +775,12 @@ argp.add_argument('--http2_interop', default=False, action='store_const', const=True, - help='Enable HTTP/2 interop tests') + help='Enable HTTP/2 client edge case testing. (Bad client, good server)') +argp.add_argument('--http2_badserver_interop', + default=False, + action='store_const', + const=True, + help='Enable HTTP/2 server edge case testing. (Good client, bad server)') args = argp.parse_args() @@ -756,14 +806,15 @@ languages = set(_LANGUAGES[l] _LANGUAGES.iterkeys() if x == 'all' else [x] for x in args.language)) -http2Interop = Http2Client() if args.http2_interop else None +http2Interop = Http2Client() if (args.http2_badserver_interop + or args.http2_interop) else None docker_images={} if args.use_docker: # languages for which to build docker images languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] + [s for s in servers])) - if args.http2_interop: + if args.http2_interop or args.http2_badserver_interop: languages_to_build.add(http2Interop) build_jobs = [] @@ -797,6 +848,14 @@ try: server_jobs[lang] = job server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT)) + if args.http2_badserver_interop: + # launch a HTTP2 server emulator that creates edge cases + lang = str(http2Interop) + spec = server_jobspec(Http2Client(), docker_images.get(lang)) + job = dockerjob.DockerJob(spec) + server_jobs[lang] = job + server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT) + jobs = [] if args.cloud_to_prod: for server_host_name in args.prod_servers: @@ -843,7 +902,7 @@ try: for language in languages: for test_case in _TEST_CASES: if not test_case in language.unimplemented_test_cases(): - if not test_case in skip_server: + if not test_case in skip_server and not args.http2_badserver_interop: test_job = cloud_to_cloud_jobspec(language, test_case, server_name, @@ -865,6 +924,17 @@ try: docker_image=docker_images.get(str(http2Interop))) jobs.append(test_job) + if args.http2_badserver_interop: + for language in languages: + for test_case in _HTTP2_BADSERVER_TEST_CASES: + test_job = cloud_to_cloud_jobspec(language, + test_case, + server_name, + server_host, + server_port, + docker_image=docker_images.get(str(language))) + jobs.append(test_job) + if not jobs: print('No jobs to run.') for image in docker_images.itervalues(): From a0d639dae9b53f3adb2c722789948bbf32dacd8a Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Tue, 10 Jan 2017 14:46:10 -0800 Subject: [PATCH 035/104] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index 5ea3a96dff1..65ee2cd32d6 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -61,14 +61,14 @@ Client Procedure: ``` Client asserts: -* Call was successful. +* Both calls are successful. * Response payload body is 314159 bytes in size. Server Procedure: 1. Server sends a GOAWAY after receiving the first UnaryCall. Server asserts: -* The second UnaryCall has a different stream_id than the first one. +* Two different were used from the client. ### rst_after_header From 9fafc034659e0f218fcafd61a0b3e53d8b28991f Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Tue, 10 Jan 2017 14:47:02 -0800 Subject: [PATCH 036/104] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index 65ee2cd32d6..e4717888914 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -68,7 +68,7 @@ Server Procedure: 1. Server sends a GOAWAY after receiving the first UnaryCall. Server asserts: -* Two different were used from the client. +* Two different connections were used from the client. ### rst_after_header From 850ed9b5d0c8766a29cd795e48f5eed1337bf892 Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Tue, 10 Jan 2017 15:00:53 -0800 Subject: [PATCH 037/104] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index e4717888914..1ded97b5037 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -49,7 +49,7 @@ server. The client should handle the goaway by switching to a new stream without the user application having to do a thing. Client Procedure: - 1. Client sends two UnaryCall requests with: + 1. Client sends two UnaryCall requests (and sleeps for 1 second in-between). ``` { From 078e4210fdd3410581c38f449a527fd947dfcecc Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Tue, 10 Jan 2017 15:09:21 -0800 Subject: [PATCH 038/104] addressed feedback created separate class for Http2Server. --- tools/run_tests/run_interop_tests.py | 74 +++++++++++++++++++--------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 02694c89228..d25da0b2fa9 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -182,10 +182,10 @@ class JavaLanguage: return {} def unimplemented_test_cases(self): - return _SKIP_ADVANCED + _SKIP_COMPRESSION + return _SKIP_COMPRESSION def unimplemented_test_cases_server(self): - return _SKIP_ADVANCED + _SKIP_COMPRESSION + return _SKIP_COMPRESSION def __str__(self): return 'java' @@ -220,6 +220,33 @@ class GoLanguage: def __str__(self): return 'go' +class Http2Server: + """Represents the HTTP/2 Interop Test server + + This pretends to be a language in order to be built and run, but really it + isn't. + """ + def __init__(self): + self.server_cwd = None + self.safename = str(self) + + def server_cmd(self, args): + return ['python test/http2_test/http2_test_server.py'] + + def cloud_to_prod_env(self): + return {} + + def global_env(self): + return {} + + def unimplemented_test_cases(self): + return _TEST_CASES + + def unimplemented_test_cases_server(self): + return _TEST_CASES + + def __str__(self): + return 'http2' class Http2Client: """Represents the HTTP/2 Interop Test @@ -229,15 +256,11 @@ class Http2Client: """ def __init__(self): self.client_cwd = None - self.server_cwd = None self.safename = str(self) def client_cmd(self, args): return ['tools/http2_interop/http2_interop.test', '-test.v'] + args - def server_cmd(self, args): - return ['python test/http2_test/http2_test_server.py'] - def cloud_to_prod_env(self): return {} @@ -574,7 +597,7 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, '--test_case=%s' % test_case, '--server_host=%s' % server_host, ] - if test_case in sorted(_HTTP2_BADSERVER_TEST_CASES): + if test_case in _HTTP2_BADSERVER_TEST_CASES: # We are running the http2_badserver_interop test. Adjust command line accordingly. offset = sorted(_HTTP2_BADSERVER_TEST_CASES).index(test_case) client_options = common_options + ['--server_port=%s' % @@ -584,7 +607,6 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, client_options = interop_only_options + common_options + ['--server_port=%s' % server_port] cmdline = bash_cmdline(language.client_cmd(client_options)) - print('Client_CMD = %s'%cmdline) cwd = language.client_cwd environ = language.global_env() if docker_image: @@ -806,17 +828,20 @@ languages = set(_LANGUAGES[l] _LANGUAGES.iterkeys() if x == 'all' else [x] for x in args.language)) -http2Interop = Http2Client() if (args.http2_badserver_interop - or args.http2_interop) else None +http2Interop = Http2Client() if args.http2_interop else None +http2InteropServer = Http2Server() if args.http2_badserver_interop else None docker_images={} if args.use_docker: # languages for which to build docker images languages_to_build = set(_LANGUAGES[k] for k in set([str(l) for l in languages] + [s for s in servers])) - if args.http2_interop or args.http2_badserver_interop: + if args.http2_interop: languages_to_build.add(http2Interop) + if args.http2_badserver_interop: + languages_to_build.add(http2InteropServer) + build_jobs = [] for l in languages_to_build: job = build_interop_image_jobspec(l) @@ -850,8 +875,8 @@ try: if args.http2_badserver_interop: # launch a HTTP2 server emulator that creates edge cases - lang = str(http2Interop) - spec = server_jobspec(Http2Client(), docker_images.get(lang)) + lang = str(http2InteropServer) + spec = server_jobspec(Http2Server(), docker_images.get(lang)) job = dockerjob.DockerJob(spec) server_jobs[lang] = job server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT) @@ -899,17 +924,18 @@ try: skip_server = [] # test cases unimplemented by server if server_language: skip_server = server_language.unimplemented_test_cases_server() - for language in languages: - for test_case in _TEST_CASES: - if not test_case in language.unimplemented_test_cases(): - if not test_case in skip_server and not args.http2_badserver_interop: - test_job = cloud_to_cloud_jobspec(language, - test_case, - server_name, - server_host, - server_port, - docker_image=docker_images.get(str(language))) - jobs.append(test_job) + if not args.http2_badserver_interop: + for language in languages: + for test_case in _TEST_CASES: + if not test_case in language.unimplemented_test_cases(): + if not test_case in skip_server: + test_job = cloud_to_cloud_jobspec(language, + test_case, + server_name, + server_host, + server_port, + docker_image=docker_images.get(str(language))) + jobs.append(test_job) if args.http2_interop: for test_case in _HTTP2_TEST_CASES: From 39fe75eed3102bc000e467c374e25e904419d893 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 13 Dec 2016 22:35:01 +0100 Subject: [PATCH 039/104] include/grpc/impl/codegen/port_platform.h: disable warn_unused_result on MINGW32 platform --- include/grpc/impl/codegen/port_platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index cd989d664ca..4633fa12e84 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -361,7 +361,7 @@ typedef unsigned __int64 uint64_t; #define GPR_MAX_ALIGNMENT 16 #ifndef GRPC_MUST_USE_RESULT -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(__MINGW32__) #define GRPC_MUST_USE_RESULT __attribute__((warn_unused_result)) #else #define GRPC_MUST_USE_RESULT From d817c1b75bcdf21f8cae66f46b39dbb1f867dde9 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 13 Dec 2016 22:35:50 +0100 Subject: [PATCH 040/104] iocp_windows.c and tcp_server_windows.c: fixes for gcc on Windows (unused variables and type casts) --- src/core/lib/iomgr/iocp_windows.c | 1 - src/core/lib/iomgr/tcp_server_windows.c | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/core/lib/iomgr/iocp_windows.c b/src/core/lib/iomgr/iocp_windows.c index 60ebe43676d..f0f4a6ff390 100644 --- a/src/core/lib/iomgr/iocp_windows.c +++ b/src/core/lib/iomgr/iocp_windows.c @@ -80,7 +80,6 @@ grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, LPOVERLAPPED overlapped; grpc_winsocket *socket; grpc_winsocket_callback_info *info; - grpc_closure *closure = NULL; success = GetQueuedCompletionStatus( g_iocp, &bytes, &completion_key, &overlapped, deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index 97d78274614..11d570367e1 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -184,7 +184,6 @@ void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, } static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { - int immediately_done = 0; grpc_tcp_listener *sp; gpr_mu_lock(&s->mu); @@ -240,7 +239,7 @@ static grpc_error *prepare_socket(SOCKET sock, error = GRPC_WSA_ERROR(WSAGetLastError(), "getsockname"); goto failure; } - sockname_temp.len = sockname_temp_len; + sockname_temp.len = (size_t)sockname_temp_len; *port = grpc_sockaddr_get_port(&sockname_temp); return GRPC_ERROR_NONE; @@ -248,8 +247,7 @@ static grpc_error *prepare_socket(SOCKET sock, failure: GPR_ASSERT(error != GRPC_ERROR_NONE); char *tgtaddr = grpc_sockaddr_to_uri(addr); - grpc_error *final_error = grpc_error_set_int( - grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING( + grpc_error_set_int(grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING( "Failed to prepare server socket", &error, 1), GRPC_ERROR_STR_TARGET_ADDRESS, tgtaddr), GRPC_ERROR_INT_FD, (intptr_t)sock); @@ -261,7 +259,6 @@ failure: static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *sp) { - int notify = 0; sp->shutting_down = 0; GPR_ASSERT(sp->server->active_ports > 0); if (0 == --sp->server->active_ports) { @@ -375,7 +372,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { int peer_name_len = (int)peer_name.len; err = getpeername(sock, (struct sockaddr *)peer_name.addr, &peer_name_len); - peer_name.len = peer_name_len; + peer_name.len = (size_t)peer_name_len; if (!err) { peer_name_string = grpc_sockaddr_to_uri(&peer_name); } else { @@ -498,7 +495,7 @@ grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, if (0 == getsockname(sp->socket->socket, (struct sockaddr *)sockname_temp.addr, &sockname_temp_len)) { - sockname_temp.len = sockname_temp_len; + sockname_temp.len = (size_t)sockname_temp_len; *port = grpc_sockaddr_get_port(&sockname_temp); if (*port > 0) { allocated_addr = gpr_malloc(sizeof(grpc_resolved_address)); From 294dc2f003d8173108b7de645052d3cc3305d428 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 13 Dec 2016 00:07:12 +0100 Subject: [PATCH 041/104] Makefile.template and Makefile: avoid def-files on MSYS2 / MINGW32 platform --- Makefile | 18 +++++++++--------- templates/Makefile.template | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index a26842e71b1..0c13184a436 100644 --- a/Makefile +++ b/Makefile @@ -2578,7 +2578,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared gpr.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) else $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(E) "[LD] Linking $@" @@ -2901,7 +2901,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) else $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -3174,7 +3174,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc_cronet.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) else $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -3674,7 +3674,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc_unsecure.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) else $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" @@ -3938,7 +3938,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc-imp else $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4313,7 +4313,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_cronet.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp else $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4436,7 +4436,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_reflection.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++-imp else $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4828,7 +4828,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared grpc++_unsecure.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp else $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" @@ -5318,7 +5318,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared grpc_csharp_ext.def -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) else $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" diff --git a/templates/Makefile.template b/templates/Makefile.template index 109de33c31e..55fbe530bee 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1546,7 +1546,7 @@ ${out_mingbase}.$(SHARED_EXT_${lang_to_var[lib.language]}): $(LIB${lib.name.upper()}_OBJS) ${mingw_lib_deps} $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared ${lib.name}.def -Wl,--output-def=${out_mingbase}.def -Wl,--out-implib=${out_libbase}-dll.a -o ${out_mingbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${mingw_libs} + $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=${out_mingbase}.def -Wl,--out-implib=${out_libbase}-dll.a -o ${out_mingbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${mingw_libs} else ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}): $(LIB${lib.name.upper()}_OBJS) ${lib_deps} $(E) "[LD] Linking $@" From 121d289e28d0a791cbc144cd9c3696e706684f9b Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 12 Dec 2016 23:49:27 +0100 Subject: [PATCH 042/104] Makefile.template and Makefile: use .exe suffix for grpc_cpp_plugin on MSYS2 / MINGW32 platform --- Makefile | 31 +++++++++++++++++-------------- templates/Makefile.template | 5 ++++- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 0c13184a436..433c115e842 100644 --- a/Makefile +++ b/Makefile @@ -479,6 +479,7 @@ CPP_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix CSHARP_PC_TEMPLATE = prefix=$(prefix),exec_prefix=\$${prefix},includedir=\$${prefix}/include,libdir=\$${exec_prefix}/lib,,Name: $(PC_NAME),Description: $(PC_DESCRIPTION),Version: $(CSHARP_VERSION),Cflags: -I\$${includedir} $(PC_CFLAGS),Requires.private: $(PC_REQUIRES_PRIVATE),Libs: -L\$${libdir} $(PC_LIB),Libs.private: $(PC_LIBS_PRIVATE) ifeq ($(SYSTEM),MINGW32) +EXECUTABLE_SUFFIX = .exe SHARED_EXT_CORE = dll SHARED_EXT_CPP = dll SHARED_EXT_CSHARP = dll @@ -487,6 +488,7 @@ SHARED_VERSION_CORE = -2 SHARED_VERSION_CPP = -1 SHARED_VERSION_CSHARP = -1 else ifeq ($(SYSTEM),Darwin) +EXECUTABLE_SUFFIX = SHARED_EXT_CORE = dylib SHARED_EXT_CPP = dylib SHARED_EXT_CSHARP = dylib @@ -495,6 +497,7 @@ SHARED_VERSION_CORE = SHARED_VERSION_CPP = SHARED_VERSION_CSHARP = else +EXECUTABLE_SUFFIX = SHARED_EXT_CORE = so.$(CORE_VERSION) SHARED_EXT_CPP = so.$(CPP_VERSION) SHARED_EXT_CSHARP = so.$(CSHARP_VERSION) @@ -2039,7 +2042,7 @@ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc: src/proto/grpc/lb/v1/load_ba $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v1/load_balancer.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2054,7 +2057,7 @@ $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.pb.cc: src/proto/grpc/ref $(GENDIR)/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc: src/proto/grpc/reflection/v1alpha/reflection.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2069,7 +2072,7 @@ $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: src/proto/grpc/testing/com $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2084,7 +2087,7 @@ $(GENDIR)/src/proto/grpc/testing/control.pb.cc: src/proto/grpc/testing/control.p $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: src/proto/grpc/testing/control.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2099,7 +2102,7 @@ $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.pb.cc: src/proto/grpc/ $(GENDIR)/src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.cc: src/proto/grpc/testing/duplicate/echo_duplicate.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2114,7 +2117,7 @@ $(GENDIR)/src/proto/grpc/testing/echo.pb.cc: src/proto/grpc/testing/echo.proto $ $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc: src/proto/grpc/testing/echo.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2129,7 +2132,7 @@ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc: src/proto/grpc/testing/ech $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc: src/proto/grpc/testing/echo_messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2144,7 +2147,7 @@ $(GENDIR)/src/proto/grpc/testing/empty.pb.cc: src/proto/grpc/testing/empty.proto $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc: src/proto/grpc/testing/empty.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2159,7 +2162,7 @@ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc: src/proto/grpc/testing/messages $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc: src/proto/grpc/testing/messages.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2174,7 +2177,7 @@ $(GENDIR)/src/proto/grpc/testing/metrics.pb.cc: src/proto/grpc/testing/metrics.p $(GENDIR)/src/proto/grpc/testing/metrics.grpc.pb.cc: src/proto/grpc/testing/metrics.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2189,7 +2192,7 @@ $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc: src/proto/grpc/testing/payloads $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc: src/proto/grpc/testing/payloads.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2204,7 +2207,7 @@ $(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2219,7 +2222,7 @@ $(GENDIR)/src/proto/grpc/testing/stats.pb.cc: src/proto/grpc/testing/stats.proto $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc: src/proto/grpc/testing/stats.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif ifeq ($(NO_PROTOC),true) @@ -2234,7 +2237,7 @@ $(GENDIR)/src/proto/grpc/testing/test.pb.cc: src/proto/grpc/testing/test.proto $ $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc: src/proto/grpc/testing/test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif diff --git a/templates/Makefile.template b/templates/Makefile.template index 55fbe530bee..6364662d9ab 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -392,6 +392,7 @@ Libs.private: $(PC_LIBS_PRIVATE) ifeq ($(SYSTEM),MINGW32) + EXECUTABLE_SUFFIX = .exe SHARED_EXT_CORE = dll SHARED_EXT_CPP = dll SHARED_EXT_CSHARP = dll @@ -400,6 +401,7 @@ SHARED_VERSION_CPP = -${settings.cpp_version.major} SHARED_VERSION_CSHARP = -${settings.csharp_version.major} else ifeq ($(SYSTEM),Darwin) + EXECUTABLE_SUFFIX = SHARED_EXT_CORE = dylib SHARED_EXT_CPP = dylib SHARED_EXT_CSHARP = dylib @@ -408,6 +410,7 @@ SHARED_VERSION_CPP = SHARED_VERSION_CSHARP = else + EXECUTABLE_SUFFIX = SHARED_EXT_CORE = so.$(CORE_VERSION) SHARED_EXT_CPP = so.$(CPP_VERSION) SHARED_EXT_CSHARP = so.$(CSHARP_VERSION) @@ -1196,7 +1199,7 @@ $(GENDIR)/${p}.grpc.pb.cc: ${p}.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) ${' '.join('$(GENDIR)/%s.pb.cc $(GENDIR)/%s.grpc.pb.cc' % (q,q) for q in proto_deps.get(p, []))} $(E) "[GRPC] Generating gRPC's protobuf service CC file from $<" $(Q) mkdir -p `dirname $@` - $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin $< + $(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $< endif % endfor From 1643c045a03536bff3bcafed6c1b599cc47d508a Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 12 Dec 2016 23:12:47 +0100 Subject: [PATCH 043/104] Makefile.template and Makefile: avoid stripping too heavily on MSYS2 / MINGW32 platform --- Makefile | 7 +++++++ templates/Makefile.template | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/Makefile b/Makefile index 433c115e842..4f0d0017f3b 100644 --- a/Makefile +++ b/Makefile @@ -292,12 +292,19 @@ AR = libtool -no_warning_for_no_symbols -o endif STRIP ?= strip -x else +ifeq ($(SYSTEM),MINGW32) +ifeq ($(origin AR), default) +AR = ar rcs +endif +STRIP ?= strip --strip-unneeded +else ifeq ($(origin AR), default) AR = ar rcs endif STRIP ?= strip endif endif +endif INSTALL ?= install RM ?= rm -f PKG_CONFIG ?= pkg-config diff --git a/templates/Makefile.template b/templates/Makefile.template index 6364662d9ab..3844918de28 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -182,12 +182,19 @@ endif STRIP ?= strip -x else + ifeq ($(SYSTEM),MINGW32) + ifeq ($(origin AR), default) + AR = ar rcs + endif + STRIP ?= strip --strip-unneeded + else ifeq ($(origin AR), default) AR = ar rcs endif STRIP ?= strip endif endif + endif INSTALL ?= install RM ?= rm -f PKG_CONFIG ?= pkg-config From 13f6716d8578ecb5e7c20151b781ad0d18be9c92 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 12 Dec 2016 23:56:04 +0100 Subject: [PATCH 044/104] Makefile.template and Makefile: install plugins on MSYS2 / MINGW32 platform --- Makefile | 4 ---- templates/Makefile.template | 4 ---- 2 files changed, 8 deletions(-) diff --git a/Makefile b/Makefile index 4f0d0017f3b..024ca8f12af 100644 --- a/Makefile +++ b/Makefile @@ -2440,9 +2440,6 @@ endif install-plugins: $(PROTOC_PLUGINS) -ifeq ($(SYSTEM),MINGW32) - $(Q) false -else $(E) "[INSTALL] Installing grpc protoc plugins" $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin @@ -2458,7 +2455,6 @@ else $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin -endif install-pkg-config_c: pc_c pc_c_unsecure $(E) "[INSTALL] Installing C pkg-config files" diff --git a/templates/Makefile.template b/templates/Makefile.template index 3844918de28..1b6bc0e93de 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1332,9 +1332,6 @@ ${install_shared("csharp")} install-plugins: $(PROTOC_PLUGINS) - ifeq ($(SYSTEM),MINGW32) - $(Q) false - else $(E) "[INSTALL] Installing grpc protoc plugins" % for tgt in targets: % if tgt.build == 'protoc': @@ -1342,7 +1339,6 @@ $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/${tgt.name} $(prefix)/bin/${tgt.name} % endif % endfor - endif install-pkg-config_c: pc_c pc_c_unsecure $(E) "[INSTALL] Installing C pkg-config files" From 98c0bd7c829c4932ac12ebbe6687f0fc5380e866 Mon Sep 17 00:00:00 2001 From: Yuxuan Li Date: Tue, 15 Nov 2016 13:31:36 -0800 Subject: [PATCH 045/104] add setting channel args functionality to performance tesing setting channel args --draft clang-format --- src/proto/grpc/testing/control.proto | 10 ++++++++++ test/cpp/qps/client.h | 13 +++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/proto/grpc/testing/control.proto b/src/proto/grpc/testing/control.proto index be387cf7869..529313cfb1e 100644 --- a/src/proto/grpc/testing/control.proto +++ b/src/proto/grpc/testing/control.proto @@ -78,6 +78,14 @@ message SecurityParams { string server_host_override = 2; } +message ChannelArg { + string name = 1; + oneof value { + string str_value = 2; + int32 int_value = 3; + } +} + message ClientConfig { // List of targets to connect to. At least one target needs to be specified. repeated string server_targets = 1; @@ -103,6 +111,8 @@ message ClientConfig { // If we use an OTHER_CLIENT client_type, this string gives more detail string other_client_api = 15; + + repeated ChannelArg channel_args = 16; } message ClientStatus { ClientStats stats = 1; } diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index fdd78ebb899..18f9778fc6f 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -409,6 +409,7 @@ class ClientImpl : public Client { // old compilers happy with using this in std::vector ChannelArguments args; args.SetInt("shard_to_ensure_no_subchannel_merges", shard); + set_channel_args(config, &args); channel_ = CreateTestChannel( target, config.security_params().server_host_override(), config.has_security_params(), !config.security_params().use_test_ca(), @@ -423,6 +424,18 @@ class ClientImpl : public Client { StubType* get_stub() { return stub_.get(); } private: + void set_channel_args(const ClientConfig& config, ChannelArguments* args) { + for (auto channel_arg : config.channel_args()) { + if (channel_arg.value_case() == ChannelArg::kStrValue) { + args->SetString(channel_arg.name(), channel_arg.str_value()); + } else if (channel_arg.value_case() == ChannelArg::kIntValue) { + args->SetInt(channel_arg.name(), channel_arg.int_value()); + } else { + gpr_log(GPR_ERROR, "Empty channel arg value."); + } + } + } + std::shared_ptr channel_; std::unique_ptr stub_; }; From df71518e54dbc0ecf0f992f6d102314e8a6c03ff Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 11 Jan 2017 10:44:41 +0100 Subject: [PATCH 046/104] fix code formatting --- src/core/lib/iomgr/tcp_server_windows.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/tcp_server_windows.c b/src/core/lib/iomgr/tcp_server_windows.c index 11d570367e1..dafe851ce8b 100644 --- a/src/core/lib/iomgr/tcp_server_windows.c +++ b/src/core/lib/iomgr/tcp_server_windows.c @@ -247,7 +247,8 @@ static grpc_error *prepare_socket(SOCKET sock, failure: GPR_ASSERT(error != GRPC_ERROR_NONE); char *tgtaddr = grpc_sockaddr_to_uri(addr); - grpc_error_set_int(grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING( + grpc_error_set_int( + grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING( "Failed to prepare server socket", &error, 1), GRPC_ERROR_STR_TARGET_ADDRESS, tgtaddr), GRPC_ERROR_INT_FD, (intptr_t)sock); From ac87a46225128f2c92e9d2cb8522b4b88d5abde8 Mon Sep 17 00:00:00 2001 From: Yuxuan Li Date: Fri, 11 Nov 2016 12:05:11 -0800 Subject: [PATCH 047/104] enable uploading server cpu usage data from performance tests to big query --- test/cpp/qps/qps_json_driver.cc | 1 + .../run_tests/performance/bq_upload_result.py | 8 ++++--- .../performance/scenario_result_schema.json | 22 +++++++++++++++++++ tools/run_tests/run_performance_tests.py | 20 +++++++++++------ 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index da835b995ab..57ee5ef63cd 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -212,6 +212,7 @@ static bool QpsDriver() { SearchOfferedLoad(FLAGS_initial_search_value, FLAGS_targeted_cpu_load, scenario, &success); gpr_log(GPR_INFO, "targeted_offered_load %f", targeted_offered_load); + GetCpuLoad(scenario, targeted_offered_load, &success); } else { gpr_log(GPR_ERROR, "Unimplemented search param"); } diff --git a/tools/run_tests/performance/bq_upload_result.py b/tools/run_tests/performance/bq_upload_result.py index ddcf053ae5e..89d2a9b320f 100755 --- a/tools/run_tests/performance/bq_upload_result.py +++ b/tools/run_tests/performance/bq_upload_result.py @@ -115,9 +115,11 @@ def _flatten_result_inplace(scenario_result): scenario_result['scenario']['clientConfig'] = json.dumps(scenario_result['scenario']['clientConfig']) scenario_result['scenario']['serverConfig'] = json.dumps(scenario_result['scenario']['serverConfig']) scenario_result['latencies'] = json.dumps(scenario_result['latencies']) + scenario_result['serverCpuStats'] = [] for stats in scenario_result['serverStats']: - stats.pop('totalCpuTime', None) - stats.pop('idleCpuTime', None) + scenario_result['serverCpuStats'].append(dict()) + scenario_result['serverCpuStats'][-1]['totalCpuTime'] = stats.pop('totalCpuTime', None) + scenario_result['serverCpuStats'][-1]['idleCpuTime'] = stats.pop('idleCpuTime', None) for stats in scenario_result['clientStats']: stats['latencies'] = json.dumps(stats['latencies']) stats.pop('requestResults', None) @@ -125,7 +127,7 @@ def _flatten_result_inplace(scenario_result): scenario_result['clientSuccess'] = json.dumps(scenario_result['clientSuccess']) scenario_result['serverSuccess'] = json.dumps(scenario_result['serverSuccess']) scenario_result['requestResults'] = json.dumps(scenario_result.get('requestResults', [])) - scenario_result['summary'].pop('serverCpuUsage', None) + scenario_result['serverCpuUsage'] = scenario_result['summary'].pop('serverCpuUsage', None) scenario_result['summary'].pop('successfulRequestsPerSecond', None) scenario_result['summary'].pop('failedRequestsPerSecond', None) diff --git a/tools/run_tests/performance/scenario_result_schema.json b/tools/run_tests/performance/scenario_result_schema.json index 3285f212d77..8ec41c377c5 100644 --- a/tools/run_tests/performance/scenario_result_schema.json +++ b/tools/run_tests/performance/scenario_result_schema.json @@ -213,5 +213,27 @@ "name": "requestResults", "type": "STRING", "mode": "NULLABLE" + }, + { + "name": "serverCpuStats", + "type": "RECORD", + "mode": "REPEATED", + "fields": [ + { + "name": "totalCpuTime", + "type": "INTEGER", + "mode": "NULLABLE" + }, + { + "name": "idleCpuTime", + "type": "INTEGER", + "mode": "NULLABLE" + } + ] + }, + { + "name": "serverCpuUsage", + "type": "FLOAT", + "mode": "NULLABLE" } ] diff --git a/tools/run_tests/run_performance_tests.py b/tools/run_tests/run_performance_tests.py index b7b742d7af2..d6eed3f5bdd 100755 --- a/tools/run_tests/run_performance_tests.py +++ b/tools/run_tests/run_performance_tests.py @@ -113,7 +113,7 @@ def create_qpsworker_job(language, shortname=None, port=10000, remote_host=None, def create_scenario_jobspec(scenario_json, workers, remote_host=None, - bq_result_table=None): + bq_result_table=None, server_cpu_load=0): """Runs one scenario using QPS driver.""" # setting QPS_WORKERS env variable here makes sure it works with SSH too. cmd = 'QPS_WORKERS="%s" ' % ','.join(workers) @@ -121,7 +121,9 @@ def create_scenario_jobspec(scenario_json, workers, remote_host=None, cmd += 'BQ_RESULT_TABLE="%s" ' % bq_result_table cmd += 'tools/run_tests/performance/run_qps_driver.sh ' cmd += '--scenarios_json=%s ' % pipes.quote(json.dumps({'scenarios': [scenario_json]})) - cmd += '--scenario_result_file=scenario_result.json' + cmd += '--scenario_result_file=scenario_result.json ' + if server_cpu_load != 0: + cmd += '--search_param=offered_load --initial_search_value=1000 --targeted_cpu_load=%d --stride=500 --error_tolerance=0.01' % server_cpu_load if remote_host: user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, remote_host) cmd = 'ssh %s "cd ~/performance_workspace/grpc/ && "%s' % (user_at_host, pipes.quote(cmd)) @@ -129,7 +131,7 @@ def create_scenario_jobspec(scenario_json, workers, remote_host=None, return jobset.JobSpec( cmdline=[cmd], shortname='qps_json_driver.%s' % scenario_json['name'], - timeout_seconds=3*60, + timeout_seconds=12*60, shell=True, verbose_success=True) @@ -318,7 +320,7 @@ Scenario = collections.namedtuple('Scenario', 'jobspec workers name') def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*', category='all', bq_result_table=None, - netperf=False, netperf_hosts=[]): + netperf=False, netperf_hosts=[], server_cpu_load=0): """Create jobspecs for scenarios to run.""" all_workers = [worker for workers in workers_by_lang.values() @@ -379,7 +381,8 @@ def create_scenarios(languages, workers_by_lang, remote_host=None, regex='.*', create_scenario_jobspec(scenario_json, [w.host_and_port for w in workers], remote_host=remote_host, - bq_result_table=bq_result_table), + bq_result_table=bq_result_table, + server_cpu_load=server_cpu_load), workers, scenario_json['name']) scenarios.append(scenario) @@ -461,6 +464,9 @@ argp.add_argument('--netperf', action='store_const', const=True, help='Run netperf benchmark as one of the scenarios.') +argp.add_argument('--server_cpu_load', + default=0, type=int, + help='Select a targeted server cpu load to run. 0 means ignore this flag') argp.add_argument('-x', '--xml_report', default='report.xml', type=str, help='Name of XML report file to generate.') argp.add_argument('--perf_args', @@ -490,7 +496,6 @@ argp.add_argument('--skip_generate_flamegraphs', 'May be useful if "perf_args" arguments do not make sense for ' 'generating flamegraphs (e.g., "--perf_args=stat ...")')) - args = argp.parse_args() languages = set(scenario_config.LANGUAGES[l] @@ -540,7 +545,8 @@ scenarios = create_scenarios(languages, category=args.category, bq_result_table=args.bq_result_table, netperf=args.netperf, - netperf_hosts=args.remote_worker_host) + netperf_hosts=args.remote_worker_host, + server_cpu_load=args.server_cpu_load) if not scenarios: raise Exception('No scenarios to run') From c344e87449cb23fa03977c6a8dbdedfba8730296 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Mon, 9 Jan 2017 10:53:50 -0800 Subject: [PATCH 048/104] Adds HTTP/2 interop test client --- Makefile | 92 +++++- build.yaml | 32 +++ test/cpp/interop/http2_client.cc | 272 ++++++++++++++++++ test/cpp/interop/http2_client.h | 80 ++++++ .../generated/sources_and_headers.json | 44 +++ .../http2_client_main.vcxproj | 206 +++++++++++++ .../http2_client_main.vcxproj.filters | 47 +++ 7 files changed, 771 insertions(+), 2 deletions(-) create mode 100644 test/cpp/interop/http2_client.cc create mode 100644 test/cpp/interop/http2_client.h create mode 100644 vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj create mode 100644 vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters diff --git a/Makefile b/Makefile index 024ca8f12af..fdeb389a80c 100644 --- a/Makefile +++ b/Makefile @@ -1095,6 +1095,7 @@ grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test +http2_client: $(BINDIR)/$(CONFIG)/http2_client hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test interop_client: $(BINDIR)/$(CONFIG)/interop_client interop_server: $(BINDIR)/$(CONFIG)/interop_server @@ -1270,9 +1271,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc ifeq ($(EMBED_OPENSSL),true) -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a else -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a endif @@ -1477,6 +1478,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ + $(BINDIR)/$(CONFIG)/http2_client \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/interop_client \ $(BINDIR)/$(CONFIG)/interop_server \ @@ -1570,6 +1572,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ + $(BINDIR)/$(CONFIG)/http2_client \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/interop_client \ $(BINDIR)/$(CONFIG)/interop_server \ @@ -4958,6 +4961,59 @@ ifneq ($(NO_DEPS),true) endif +LIBHTTP2_CLIENT_MAIN_SRC = \ + $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \ + $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ + $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \ + test/cpp/interop/http2_client.cc \ + +PUBLIC_HEADERS_CXX += \ + +LIBHTTP2_CLIENT_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBHTTP2_CLIENT_MAIN_SRC)))) + + +ifeq ($(NO_SECURE),true) + +# You can't build secure libraries if you don't have OpenSSL. + +$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: openssl_dep_error + + +else + +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: protobuf_dep_error + + +else + +$(LIBDIR)/$(CONFIG)/libhttp2_client_main.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBHTTP2_CLIENT_MAIN_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a + $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBHTTP2_CLIENT_MAIN_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a +endif + + + + +endif + +endif + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(LIBHTTP2_CLIENT_MAIN_OBJS:.o=.dep) +endif +endif +$(OBJDIR)/$(CONFIG)/test/cpp/interop/http2_client.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc + + LIBINTEROP_CLIENT_HELPER_SRC = \ $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \ test/cpp/interop/client_helper.cc \ @@ -12912,6 +12968,37 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/http2_client: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/http2_client: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/http2_client: $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/http2_client + +endif + +endif + + + + HYBRID_END2END_TEST_SRC = \ test/cpp/end2end/hybrid_end2end_test.cc \ @@ -16829,6 +16916,7 @@ test/core/util/test_tcp_server.c: $(OPENSSL_DEP) test/cpp/end2end/test_service_impl.cc: $(OPENSSL_DEP) test/cpp/interop/client.cc: $(OPENSSL_DEP) test/cpp/interop/client_helper.cc: $(OPENSSL_DEP) +test/cpp/interop/http2_client.cc: $(OPENSSL_DEP) test/cpp/interop/interop_client.cc: $(OPENSSL_DEP) test/cpp/interop/interop_server.cc: $(OPENSSL_DEP) test/cpp/interop/interop_server_bootstrap.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index 55aca52f680..1f90d26804f 100644 --- a/build.yaml +++ b/build.yaml @@ -1217,6 +1217,22 @@ libs: vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}' vs_props: - protoc +- name: http2_client_main + build: private + language: c++ + headers: + - test/cpp/interop/http2_client.h + src: + - src/proto/grpc/testing/empty.proto + - src/proto/grpc/testing/messages.proto + - src/proto/grpc/testing/test.proto + - test/cpp/interop/http2_client.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - grpc++_test_config - name: interop_client_helper build: private language: c++ @@ -3191,6 +3207,22 @@ targets: - grpc++ - grpc++_test_util - grpc_test_util +- name: http2_client + build: test + run: false + language: c++ + src: [] + deps: + - http2_client_main + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - grpc++_test_config + platforms: + - mac + - linux + - posix - name: hybrid_end2end_test gtest: true build: test diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc new file mode 100644 index 00000000000..38aee43b26a --- /dev/null +++ b/test/cpp/interop/http2_client.cc @@ -0,0 +1,272 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/lib/transport/byte_stream.h" +#include "src/proto/grpc/testing/messages.grpc.pb.h" +#include "src/proto/grpc/testing/test.grpc.pb.h" +#include "test/cpp/interop/http2_client.h" + +#include "src/core/lib/support/string.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/util/test_config.h" + +namespace grpc { +namespace testing { + +namespace { +const int kLargeRequestSize = 271828; +const int kLargeResponseSize = 314159; +} // namespace + +Http2Client::ServiceStub::ServiceStub(std::shared_ptr channel) + : channel_(channel) { + stub_ = TestService::NewStub(channel); +} + +TestService::Stub* Http2Client::ServiceStub::Get() { return stub_.get(); } + +Http2Client::Http2Client(std::shared_ptr channel) + : serviceStub_(channel), channel_(channel) {} + +bool Http2Client::AssertStatusCode(const Status& s, StatusCode expected_code) { + if (s.error_code() == expected_code) { + return true; + } + + gpr_log(GPR_ERROR, "Error status code: %d (expected: %d), message: %s", + s.error_code(), expected_code, s.error_message().c_str()); + abort(); +} + +bool Http2Client::DoRstAfterHeader() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after header"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::UNKNOWN); + GPR_ASSERT(!response.has_payload()); // no data should be received + + gpr_log(GPR_DEBUG, "Done testing reset stream after header"); + return true; +} + +bool Http2Client::DoRstAfterData() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream after data"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::UNKNOWN); + GPR_ASSERT(response.has_payload()); // data should be received + + gpr_log(GPR_DEBUG, "Done testing reset stream after data"); + return true; +} + +bool Http2Client::DoRstDuringData() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting reset stream during data"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::UNKNOWN); + GPR_ASSERT(!response.has_payload()); // no data should be received + + gpr_log(GPR_DEBUG, "Done testing reset stream during data"); + return true; +} + +bool Http2Client::DoGoaway() { + gpr_log(GPR_DEBUG, "Sending two RPCs and expecting goaway"); + + int numCalls = 2; + for (int i = 0; i < numCalls; i++) { + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); + } + + gpr_log(GPR_DEBUG, "Done testing goaway"); + return true; +} + +bool Http2Client::DoPing() { + gpr_log(GPR_DEBUG, "Sending RPC and expecting ping"); + + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = serviceStub_.Get()->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); + + gpr_log(GPR_DEBUG, "Done testing ping"); + return true; +} + +void Http2Client::MaxStreamsWorker(std::shared_ptr channel) { + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + + Status s = + TestService::NewStub(channel)->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); +} + +bool Http2Client::DoMaxStreams() { + gpr_log(GPR_DEBUG, "Testing max streams"); + + // Make an initial call on the channel to ensure the server's max streams + // setting is received + ClientContext context; + SimpleRequest request; + SimpleResponse response; + request.set_response_size(kLargeResponseSize); + grpc::string payload(kLargeRequestSize, '\0'); + request.mutable_payload()->set_body(payload.c_str(), kLargeRequestSize); + Status s = + TestService::NewStub(channel_)->UnaryCall(&context, request, &response); + AssertStatusCode(s, grpc::StatusCode::OK); + GPR_ASSERT(response.payload().body() == + grpc::string(kLargeResponseSize, '\0')); + + std::vector test_threads; + + for (int i = 0; i < 10; i++) { + test_threads.emplace_back( + std::thread(&Http2Client::MaxStreamsWorker, this, channel_)); + } + + for (auto it = test_threads.begin(); it != test_threads.end(); it++) { + it->join(); + } + + gpr_log(GPR_DEBUG, "Done testing max streams"); + return true; +} + +} // namespace testing +} // namespace grpc + +DEFINE_int32(server_port, 0, "Server port."); +DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); +DEFINE_string(test_case, "rst_after_header", + "Configure different test cases. Valid options are:\n\n" + "goaway\n" + "max_streams\n" + "ping\n" + "rst_after_data\n" + "rst_after_header\n" + "rst_during_data\n"); + +int main(int argc, char** argv) { + grpc::testing::InitTest(&argc, &argv, true); + GPR_ASSERT(FLAGS_server_port); + const int host_port_buf_size = 1024; + char host_port[host_port_buf_size]; + snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(), + FLAGS_server_port); + grpc::testing::Http2Client client(grpc::CreateTestChannel(host_port, false)); + gpr_log(GPR_INFO, "Testing case: %s", FLAGS_test_case.c_str()); + int ret = 0; + if (FLAGS_test_case == "rst_after_header") { + client.DoRstAfterHeader(); + } else if (FLAGS_test_case == "rst_after_data") { + client.DoRstAfterData(); + } else if (FLAGS_test_case == "rst_during_data") { + client.DoRstDuringData(); + } else if (FLAGS_test_case == "goaway") { + client.DoGoaway(); + } else if (FLAGS_test_case == "ping") { + client.DoPing(); + } else if (FLAGS_test_case == "max_streams") { + client.DoMaxStreams(); + } else { + const char* testcases[] = { + "goaway", "max_streams", "ping", + "rst_after_data", "rst_after_header", "rst_during_data"}; + char* joined_testcases = + gpr_strjoin_sep(testcases, GPR_ARRAY_SIZE(testcases), "\n", NULL); + + gpr_log(GPR_ERROR, "Unsupported test case %s. Valid options are\n%s", + FLAGS_test_case.c_str(), joined_testcases); + gpr_free(joined_testcases); + ret = 1; + } + + return ret; +} diff --git a/test/cpp/interop/http2_client.h b/test/cpp/interop/http2_client.h new file mode 100644 index 00000000000..6a315f5abba --- /dev/null +++ b/test/cpp/interop/http2_client.h @@ -0,0 +1,80 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H +#define GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H + +#include + +#include +#include +#include "src/proto/grpc/testing/messages.grpc.pb.h" +#include "src/proto/grpc/testing/test.grpc.pb.h" + +namespace grpc { +namespace testing { + +class Http2Client { + public: + explicit Http2Client(std::shared_ptr channel); + ~Http2Client() {} + + bool DoRstAfterHeader(); + bool DoRstAfterData(); + bool DoRstDuringData(); + bool DoGoaway(); + bool DoPing(); + bool DoMaxStreams(); + + private: + class ServiceStub { + public: + ServiceStub(std::shared_ptr channel); + + TestService::Stub* Get(); + + private: + std::unique_ptr stub_; + std::shared_ptr channel_; + }; + + void MaxStreamsWorker(std::shared_ptr channel); + bool AssertStatusCode(const Status& s, StatusCode expected_code); + ServiceStub serviceStub_; + std::shared_ptr channel_; +}; + +} // namespace testing +} // namespace grpc + +#endif // GRPC_TEST_CPP_INTEROP_HTTP2_CLIENT_H diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8849dcc600c..0c007672000 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -2772,6 +2772,23 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "grpc", + "grpc++", + "grpc++_test_config", + "grpc++_test_util", + "grpc_test_util", + "http2_client_main" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "http2_client", + "src": [], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -5388,6 +5405,33 @@ "third_party": false, "type": "lib" }, + { + "deps": [ + "grpc", + "grpc++", + "grpc++_test_config", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [ + "src/proto/grpc/testing/empty.grpc.pb.h", + "src/proto/grpc/testing/empty.pb.h", + "src/proto/grpc/testing/messages.grpc.pb.h", + "src/proto/grpc/testing/messages.pb.h", + "src/proto/grpc/testing/test.grpc.pb.h", + "src/proto/grpc/testing/test.pb.h", + "test/cpp/interop/http2_client.h" + ], + "is_filegroup": false, + "language": "c++", + "name": "http2_client_main", + "src": [ + "test/cpp/interop/http2_client.cc", + "test/cpp/interop/http2_client.h" + ], + "third_party": false, + "type": "lib" + }, { "deps": [ "gpr", diff --git a/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj new file mode 100644 index 00000000000..c94c346ed99 --- /dev/null +++ b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj @@ -0,0 +1,206 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {8008C126-4B35-5A76-A795-39DA13DA57F4} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + http2_client_main + + + http2_client_main + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Windows + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Windows + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Windows + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Windows + true + false + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {0BE77741-552A-929B-A497-4EF7ECE17A64} + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {C187A093-A0FE-489D-A40A-6E33DE0F9FEB} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {3F7D093D-11F9-C4BC-BEB7-18EB28E3F290} + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + diff --git a/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters new file mode 100644 index 00000000000..40e41913451 --- /dev/null +++ b/vsprojects/vcxproj/http2_client_main/http2_client_main.vcxproj.filters @@ -0,0 +1,47 @@ + + + + + src\proto\grpc\testing + + + src\proto\grpc\testing + + + src\proto\grpc\testing + + + test\cpp\interop + + + + + test\cpp\interop + + + + + + {8f01743f-58cf-2127-20d1-21303c8e0e8e} + + + {219dd0bc-d605-d0fa-cca4-460276dd64cf} + + + {7ee50971-dbc6-3240-e6a2-a432dac43e90} + + + {66289b19-9541-151c-03a1-771101833b4e} + + + {18fdd193-31a2-a622-980e-df055c23af50} + + + {f6da8892-ac51-d835-468a-b3b093df4baa} + + + {e32cff29-3247-cece-56cf-8fd16a1a79fe} + + + + From 6bbd95e4a319495a7ad6c70b93b0f7984b6cc891 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Wed, 11 Jan 2017 09:35:09 -0800 Subject: [PATCH 049/104] minor fix --- tools/run_tests/run_interop_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index d25da0b2fa9..a33ff55ca35 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -876,7 +876,7 @@ try: if args.http2_badserver_interop: # launch a HTTP2 server emulator that creates edge cases lang = str(http2InteropServer) - spec = server_jobspec(Http2Server(), docker_images.get(lang)) + spec = server_jobspec(http2InteropServer, docker_images.get(lang)) job = dockerjob.DockerJob(spec) server_jobs[lang] = job server_addresses[lang] = ('localhost', _DEFAULT_SERVER_PORT) From b8c5fe1e621dd804b3aec1175b6a8c23637de0ef Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 10:47:35 -0800 Subject: [PATCH 050/104] Promote dns resolution failure message to INFO --- src/core/ext/resolver/dns/native/dns_resolver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c index bb2b0125072..655d9dc586c 100644 --- a/src/core/ext/resolver/dns/native/dns_resolver.c +++ b/src/core/ext/resolver/dns/native/dns_resolver.c @@ -189,7 +189,7 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now); gpr_timespec timeout = gpr_time_sub(next_try, now); const char *msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg); + gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", msg); grpc_error_free_string(msg); GPR_ASSERT(!r->have_retry_timer); r->have_retry_timer = true; From 1da20c10b0f56e83364045445be0fb4f0c44b4cd Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 10:50:26 -0800 Subject: [PATCH 051/104] Remove unused load --- test/core/support/BUILD | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/core/support/BUILD b/test/core/support/BUILD index 77f0a9a0480..dfe952eb373 100644 --- a/test/core/support/BUILD +++ b/test/core/support/BUILD @@ -27,8 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") - cc_test( name = "alloc_test", srcs = ["alloc_test.c"], From cc5910228d84561d40cd8f0513faddc1e0100275 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 11:10:43 -0800 Subject: [PATCH 052/104] manual revert of #8901 --- build.yaml | 1 + test/cpp/end2end/async_end2end_test.cc | 19 ++++-- test/cpp/end2end/end2end_test.cc | 20 ++++-- test/cpp/interop/client.cc | 1 + test/cpp/interop/client_helper.cc | 10 ++- test/cpp/interop/interop_server.cc | 1 + test/cpp/interop/server_helper.cc | 18 +++--- test/cpp/interop/stress_test.cc | 1 + test/cpp/util/create_test_channel.cc | 64 ++++++++++++++++--- test/cpp/util/create_test_channel.h | 4 ++ test/cpp/util/test_credentials_provider.cc | 52 +++------------ test/cpp/util/test_credentials_provider.h | 50 ++++++++++----- .../generated/sources_and_headers.json | 1 + .../interop_server_helper.vcxproj | 3 + 14 files changed, 153 insertions(+), 92 deletions(-) diff --git a/build.yaml b/build.yaml index 55aca52f680..64b2a6e01ce 100644 --- a/build.yaml +++ b/build.yaml @@ -1259,6 +1259,7 @@ libs: src: - test/cpp/interop/server_helper.cc deps: + - grpc++_test_util - grpc_test_util - grpc++ - grpc diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 8e385d100c1..2ce3f2f7bd9 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -254,7 +254,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { // Setup server ServerBuilder builder; - auto server_creds = GetServerCredentials(GetParam().credentials_type); + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); builder.AddListeningPort(server_address_.str(), server_creds); builder.RegisterService(&service_); cq_ = builder.AddCompletionQueue(); @@ -283,8 +284,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { void ResetStub() { ChannelArguments args; - auto channel_creds = - GetChannelCredentials(GetParam().credentials_type, &args); + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); std::shared_ptr channel = CreateCustomChannel(server_address_.str(), channel_creds, args); stub_ = grpc::testing::EchoTestService::NewStub(channel); @@ -892,8 +893,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) { TEST_P(AsyncEnd2endTest, UnimplementedRpc) { ChannelArguments args; - auto channel_creds = - GetChannelCredentials(GetParam().credentials_type, &args); + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); std::shared_ptr channel = CreateCustomChannel(server_address_.str(), channel_creds, args); std::unique_ptr stub; @@ -1404,11 +1405,15 @@ std::vector CreateTestScenarios(bool test_disable_blocking, std::vector credentials_types; std::vector messages; - credentials_types.push_back(kInsecureCredentialsType); - auto sec_list = GetSecureCredentialsTypeList(); + if (GetCredentialsProvider()->GetChannelCredentials(kInsecureCredentialsType, + nullptr) != nullptr) { + credentials_types.push_back(kInsecureCredentialsType); + } + auto sec_list = GetCredentialsProvider()->GetSecureCredentialsTypeList(); for (auto sec = sec_list.begin(); sec != sec_list.end(); sec++) { credentials_types.push_back(*sec); } + GPR_ASSERT(!credentials_types.empty()); messages.push_back("Hello"); for (int sz = 1; sz < test_big_limit; sz *= 2) { diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 9bb892c694b..1a1a94e87c7 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -242,7 +242,8 @@ class End2endTest : public ::testing::TestWithParam { // Setup server ServerBuilder builder; ConfigureServerBuilder(&builder); - auto server_creds = GetServerCredentials(GetParam().credentials_type); + auto server_creds = GetCredentialsProvider()->GetServerCredentials( + GetParam().credentials_type); if (GetParam().credentials_type != kInsecureCredentialsType) { server_creds->SetAuthMetadataProcessor(processor); } @@ -270,8 +271,8 @@ class End2endTest : public ::testing::TestWithParam { } EXPECT_TRUE(is_server_started_); ChannelArguments args; - auto channel_creds = - GetChannelCredentials(GetParam().credentials_type, &args); + auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( + GetParam().credentials_type, &args); if (!user_agent_prefix_.empty()) { args.SetUserAgentPrefix(user_agent_prefix_); } @@ -1520,11 +1521,18 @@ std::vector CreateTestScenarios(bool use_proxy, std::vector scenarios; std::vector credentials_types; if (test_secure) { - credentials_types = GetSecureCredentialsTypeList(); + credentials_types = + GetCredentialsProvider()->GetSecureCredentialsTypeList(); } if (test_insecure) { - credentials_types.push_back(kInsecureCredentialsType); + // Only add insecure credentials type when it is registered with the + // provider. User may create providers that do not have insecure. + if (GetCredentialsProvider()->GetChannelCredentials( + kInsecureCredentialsType, nullptr) != nullptr) { + credentials_types.push_back(kInsecureCredentialsType); + } } + GPR_ASSERT(!credentials_types.empty()); for (auto it = credentials_types.begin(); it != credentials_types.end(); ++it) { scenarios.emplace_back(false, *it); @@ -1541,7 +1549,7 @@ INSTANTIATE_TEST_CASE_P(End2end, End2endTest, INSTANTIATE_TEST_CASE_P(End2endServerTryCancel, End2endServerTryCancelTest, ::testing::ValuesIn(CreateTestScenarios(false, true, - false))); + true))); INSTANTIATE_TEST_CASE_P(ProxyEnd2end, ProxyEnd2endTest, ::testing::ValuesIn(CreateTestScenarios(true, true, diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc index c58910abc3f..3265554444b 100644 --- a/test/cpp/interop/client.cc +++ b/test/cpp/interop/client.cc @@ -49,6 +49,7 @@ #include "test/cpp/util/test_config.h" DEFINE_bool(use_tls, false, "Whether to use tls."); +DEFINE_string(custom_credentials_type, "", "User provided credentials type."); DEFINE_bool(use_test_ca, false, "False to use SSL roots for google"); DEFINE_int32(server_port, 0, "Server port."); DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc index c171969e147..91564e5dcef 100644 --- a/test/cpp/interop/client_helper.cc +++ b/test/cpp/interop/client_helper.cc @@ -50,8 +50,10 @@ #include "src/cpp/client/secure_credentials.h" #include "test/core/security/oauth2_utils.h" #include "test/cpp/util/create_test_channel.h" +#include "test/cpp/util/test_credentials_provider.h" DECLARE_bool(use_tls); +DECLARE_string(custom_credentials_type); DECLARE_bool(use_test_ca); DECLARE_int32(server_port); DECLARE_string(server_host); @@ -114,8 +116,12 @@ std::shared_ptr CreateChannelForTestCase( creds = AccessTokenCredentials(raw_token); GPR_ASSERT(creds); } - return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_use_tls, - !FLAGS_use_test_ca, creds); + if (FLAGS_custom_credentials_type.empty()) { + return CreateTestChannel(host_port, FLAGS_server_host_override, + FLAGS_use_tls, !FLAGS_use_test_ca, creds); + } else { + return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds); + } } } // namespace testing diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc index 67456ce18bb..956840ba709 100644 --- a/test/cpp/interop/interop_server.cc +++ b/test/cpp/interop/interop_server.cc @@ -56,6 +56,7 @@ #include "test/cpp/util/test_config.h" DEFINE_bool(use_tls, false, "Whether to use tls."); +DEFINE_string(custom_credentials_type, "", "User provided credentials type."); DEFINE_int32(port, 0, "Server port."); DEFINE_int32(max_send_message_size, -1, "The maximum send message size."); diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc index 8b0b511bcb8..d395f50fa59 100644 --- a/test/cpp/interop/server_helper.cc +++ b/test/cpp/interop/server_helper.cc @@ -39,23 +39,23 @@ #include #include "src/core/lib/surface/call_test_only.h" -#include "test/core/end2end/data/ssl_test_data.h" +#include "test/cpp/util/test_credentials_provider.h" DECLARE_bool(use_tls); +DECLARE_string(custom_credentials_type); namespace grpc { namespace testing { std::shared_ptr CreateInteropServerCredentials() { - if (FLAGS_use_tls) { - SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, - test_server1_cert}; - SslServerCredentialsOptions ssl_opts; - ssl_opts.pem_root_certs = ""; - ssl_opts.pem_key_cert_pairs.push_back(pkcp); - return SslServerCredentials(ssl_opts); + if (!FLAGS_custom_credentials_type.empty()) { + return GetCredentialsProvider()->GetServerCredentials( + FLAGS_custom_credentials_type); + } else if (FLAGS_use_tls) { + return GetCredentialsProvider()->GetServerCredentials(kTlsCredentialsType); } else { - return InsecureServerCredentials(); + return GetCredentialsProvider()->GetServerCredentials( + kInsecureCredentialsType); } } diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc index 97e658869fe..562522de779 100644 --- a/test/cpp/interop/stress_test.cc +++ b/test/cpp/interop/stress_test.cc @@ -147,6 +147,7 @@ DEFINE_bool(do_not_abort_on_transient_failures, true, // Options from client.cc (for compatibility with interop test). // TODO(sreek): Consolidate overlapping options DEFINE_bool(use_tls, false, "Whether to use tls."); +DEFINE_string(custom_credentials_type, "", "User provided credentials type."); DEFINE_bool(use_test_ca, false, "False to use SSL roots for google"); DEFINE_int32(server_port, 0, "Server port."); DEFINE_string(server_host, "127.0.0.1", "Server host to connect to"); diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index fe8b5d54235..ad62e03490e 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -35,11 +35,37 @@ #include #include +#include -#include "test/core/end2end/data/ssl_test_data.h" +#include "test/cpp/util/test_credentials_provider.h" namespace grpc { +namespace { + +const char kProdTlsCredentialsType[] = "prod_ssl"; + +class SslCredentialProvider : public testing::CredentialTypeProvider { + public: + std::shared_ptr GetChannelCredentials( + grpc::ChannelArguments* args) override { + return SslCredentials(SslCredentialsOptions()); + } + std::shared_ptr GetServerCredentials() override { + return nullptr; + } +}; + +gpr_once g_once_init_add_prod_ssl_provider = GPR_ONCE_INIT; +// Register ssl with non-test roots type to the credentials provider. +void AddProdSslType() { + testing::GetCredentialsProvider()->AddSecureType( + kProdTlsCredentialsType, std::unique_ptr( + new SslCredentialProvider)); +} + +} // namespace + // When ssl is enabled, if server is empty, override_hostname is used to // create channel. Otherwise, connect to server and override hostname if // override_hostname is provided. @@ -61,16 +87,22 @@ std::shared_ptr CreateTestChannel( const std::shared_ptr& creds, const ChannelArguments& args) { ChannelArguments channel_args(args); + std::shared_ptr channel_creds; if (enable_ssl) { - const char* roots_certs = use_prod_roots ? "" : test_root_cert; - SslCredentialsOptions ssl_opts = {roots_certs, "", ""}; - - std::shared_ptr channel_creds = - SslCredentials(ssl_opts); - - if (!server.empty() && !override_hostname.empty()) { - channel_args.SetSslTargetNameOverride(override_hostname); + if (use_prod_roots) { + gpr_once_init(&g_once_init_add_prod_ssl_provider, &AddProdSslType); + channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( + kProdTlsCredentialsType, &channel_args); + if (!server.empty() && !override_hostname.empty()) { + channel_args.SetSslTargetNameOverride(override_hostname); + } + } else { + // override_hostname is discarded as the provider handles it. + channel_creds = testing::GetCredentialsProvider()->GetChannelCredentials( + testing::kTlsCredentialsType, &channel_args); } + GPR_ASSERT(channel_creds != nullptr); + const grpc::string& connect_to = server.empty() ? override_hostname : server; if (creds.get()) { @@ -103,4 +135,18 @@ std::shared_ptr CreateTestChannel(const grpc::string& server, return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false); } +std::shared_ptr CreateTestChannel( + const grpc::string& server, const grpc::string& credential_type, + const std::shared_ptr& creds) { + ChannelArguments channel_args; + std::shared_ptr channel_creds = + testing::GetCredentialsProvider()->GetChannelCredentials(credential_type, + &channel_args); + GPR_ASSERT(channel_creds != nullptr); + if (creds.get()) { + channel_creds = CompositeChannelCredentials(channel_creds, creds); + } + return CreateCustomChannel(server, channel_creds, channel_args); +} + } // namespace grpc diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index 4ff666dc1bc..ce71a97edbb 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -59,6 +59,10 @@ std::shared_ptr CreateTestChannel( const std::shared_ptr& creds, const ChannelArguments& args); +std::shared_ptr CreateTestChannel( + const grpc::string& server, const grpc::string& credential_type, + const std::shared_ptr& creds); + } // namespace grpc #endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 0456b966671..909b02a7019 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -43,25 +43,9 @@ #include "test/core/end2end/data/ssl_test_data.h" namespace grpc { +namespace testing { namespace { -using grpc::testing::CredentialTypeProvider; - -// Provide test credentials. Thread-safe. -class CredentialsProvider { - public: - virtual ~CredentialsProvider() {} - - virtual void AddSecureType( - const grpc::string& type, - std::unique_ptr type_provider) = 0; - virtual std::shared_ptr GetChannelCredentials( - const grpc::string& type, ChannelArguments* args) = 0; - virtual std::shared_ptr GetServerCredentials( - const grpc::string& type) = 0; - virtual std::vector GetSecureCredentialsTypeList() = 0; -}; - class DefaultCredentialsProvider : public CredentialsProvider { public: ~DefaultCredentialsProvider() override {} @@ -145,37 +129,21 @@ class DefaultCredentialsProvider : public CredentialsProvider { added_secure_type_providers_; }; -gpr_once g_once_init_provider = GPR_ONCE_INIT; CredentialsProvider* g_provider = nullptr; -void CreateDefaultProvider() { g_provider = new DefaultCredentialsProvider; } - -CredentialsProvider* GetProvider() { - gpr_once_init(&g_once_init_provider, &CreateDefaultProvider); - return g_provider; -} - } // namespace -namespace testing { - -void AddSecureType(const grpc::string& type, - std::unique_ptr type_provider) { - GetProvider()->AddSecureType(type, std::move(type_provider)); -} - -std::shared_ptr GetChannelCredentials( - const grpc::string& type, ChannelArguments* args) { - return GetProvider()->GetChannelCredentials(type, args); -} - -std::shared_ptr GetServerCredentials( - const grpc::string& type) { - return GetProvider()->GetServerCredentials(type); +CredentialsProvider* GetCredentialsProvider() { + if (g_provider == nullptr) { + g_provider = new DefaultCredentialsProvider; + } + return g_provider; } -std::vector GetSecureCredentialsTypeList() { - return GetProvider()->GetSecureCredentialsTypeList(); +void SetCredentialsProvider(CredentialsProvider* provider) { + // For now, forbids overriding provider. + GPR_ASSERT(g_provider == nullptr); + g_provider = provider; } } // namespace testing diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h index 1fb311e556e..0bc52ebe4df 100644 --- a/test/cpp/util/test_credentials_provider.h +++ b/test/cpp/util/test_credentials_provider.h @@ -59,23 +59,39 @@ class CredentialTypeProvider { virtual std::shared_ptr GetServerCredentials() = 0; }; -// Add a secure type in addition to the defaults above -// (kInsecureCredentialsType, kTlsCredentialsType) that can be returned from the -// functions below. -void AddSecureType(const grpc::string& type, - std::unique_ptr type_provider); - -// Provide channel credentials according to the given type. Alter the channel -// arguments if needed. -std::shared_ptr GetChannelCredentials( - const grpc::string& type, ChannelArguments* args); - -// Provide server credentials according to the given type. -std::shared_ptr GetServerCredentials( - const grpc::string& type); - -// Provide a list of secure credentials type. -std::vector GetSecureCredentialsTypeList(); +// Provide test credentials. Thread-safe. +class CredentialsProvider { + public: + virtual ~CredentialsProvider() {} + + // Add a secure type in addition to the defaults. The default provider has + // (kInsecureCredentialsType, kTlsCredentialsType). + virtual void AddSecureType( + const grpc::string& type, + std::unique_ptr type_provider) = 0; + + // Provide channel credentials according to the given type. Alter the channel + // arguments if needed. Return nullptr if type is not registered. + virtual std::shared_ptr GetChannelCredentials( + const grpc::string& type, ChannelArguments* args) = 0; + + // Provide server credentials according to the given type. + // Return nullptr if type is not registered. + virtual std::shared_ptr GetServerCredentials( + const grpc::string& type) = 0; + + // Provide a list of secure credentials type. + virtual std::vector GetSecureCredentialsTypeList() = 0; +}; + +// Get the current provider. Create a default one if not set. +// Not thread-safe. +CredentialsProvider* GetCredentialsProvider(); + +// Set the global provider. Takes ownership. The previous set provider will be +// destroyed. +// Not thread-safe. +void SetCredentialsProvider(CredentialsProvider* provider); } // namespace testing } // namespace grpc diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8849dcc600c..72f0b08d9e4 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -5447,6 +5447,7 @@ "gpr", "grpc", "grpc++", + "grpc++_test_util", "grpc_test_util" ], "headers": [ diff --git a/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj b/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj index 4c99988a34c..377cadc1a1e 100644 --- a/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj +++ b/vsprojects/vcxproj/interop_server_helper/interop_server_helper.vcxproj @@ -154,6 +154,9 @@ + + {0BE77741-552A-929B-A497-4EF7ECE17A64} + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} From a6e796f58f691ae130fe6e3b8ed746d67e189d79 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 11 Jan 2017 13:49:43 -0800 Subject: [PATCH 053/104] ignore core counts and core lists in qps json driver --- test/cpp/qps/driver.cc | 91 +------------------ test/cpp/qps/driver.h | 3 +- test/cpp/qps/qps_json_driver.cc | 5 +- .../run_tests/performance/scenario_config.py | 24 +++-- 4 files changed, 18 insertions(+), 105 deletions(-) diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 93ef32db770..42722b7e9d1 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -76,30 +76,6 @@ static std::string get_host(const std::string& worker) { return s; } -static std::unordered_map> get_hosts_and_cores( - const deque& workers) { - std::unordered_map> hosts; - for (auto it = workers.begin(); it != workers.end(); it++) { - const string host = get_host(*it); - if (hosts.find(host) == hosts.end()) { - auto stub = WorkerService::NewStub( - CreateChannel(*it, InsecureChannelCredentials())); - grpc::ClientContext ctx; - ctx.set_wait_for_ready(true); - CoreRequest dummy; - CoreResponse cores; - grpc::Status s = stub->CoreCount(&ctx, dummy, &cores); - GPR_ASSERT(s.ok()); - std::deque dq; - for (int i = 0; i < cores.cores(); i++) { - dq.push_back(i); - } - hosts[host] = dq; - } - } - return hosts; -} - static deque get_workers(const string& env_name) { char* env = gpr_getenv(env_name.c_str()); if (!env) { @@ -210,7 +186,7 @@ std::unique_ptr RunScenario( const ClientConfig& initial_client_config, size_t num_clients, const ServerConfig& initial_server_config, size_t num_servers, int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count, - const char* qps_server_target_override, bool configure_core_lists) { + const char* qps_server_target_override) { // Log everything from the driver gpr_set_log_verbosity(GPR_LOG_SEVERITY_DEBUG); @@ -279,9 +255,6 @@ std::unique_ptr RunScenario( std::vector servers(num_servers); std::unordered_map> hosts_cores; - if (configure_core_lists) { - hosts_cores = get_hosts_and_cores(workers); - } for (size_t i = 0; i < num_servers; i++) { gpr_log(GPR_INFO, "Starting server on %s (worker #%" PRIuPTR ")", workers[i].c_str(), i); @@ -289,37 +262,8 @@ std::unique_ptr RunScenario( CreateChannel(workers[i], InsecureChannelCredentials())); ServerConfig server_config = initial_server_config; - int server_core_limit = initial_server_config.core_limit(); - int client_core_limit = initial_client_config.core_limit(); - - if (configure_core_lists) { - string host_str(get_host(workers[i])); - if (server_core_limit == 0 && client_core_limit > 0) { - // In this case, limit the server cores if it matches the - // same host as one or more clients - const auto& dq = hosts_cores.at(host_str); - bool match = false; - int limit = dq.size(); - for (size_t cli = 0; cli < num_clients; cli++) { - if (host_str == get_host(workers[cli + num_servers])) { - limit -= client_core_limit; - match = true; - } - } - if (match) { - GPR_ASSERT(limit > 0); - server_core_limit = limit; - } - } - if (server_core_limit > 0) { - auto& dq = hosts_cores.at(host_str); - GPR_ASSERT(dq.size() >= static_cast(server_core_limit)); - gpr_log(GPR_INFO, "Setting server core_list"); - for (int core = 0; core < server_core_limit; core++) { - server_config.add_core_list(dq.front()); - dq.pop_front(); - } - } + if(server_config.core_limit() != 0) { + gpr_log(GPR_WARN, "server config core limit is set but ignored by driver"); } ServerArgs args; @@ -364,33 +308,8 @@ std::unique_ptr RunScenario( CreateChannel(worker, InsecureChannelCredentials())); ClientConfig per_client_config = client_config; - int server_core_limit = initial_server_config.core_limit(); - int client_core_limit = initial_client_config.core_limit(); - if (configure_core_lists && - ((server_core_limit > 0) || (client_core_limit > 0))) { - auto& dq = hosts_cores.at(get_host(worker)); - if (client_core_limit == 0) { - // limit client cores if it matches a server host - bool match = false; - int limit = dq.size(); - for (size_t srv = 0; srv < num_servers; srv++) { - if (get_host(worker) == get_host(workers[srv])) { - match = true; - } - } - if (match) { - GPR_ASSERT(limit > 0); - client_core_limit = limit; - } - } - if (client_core_limit > 0) { - GPR_ASSERT(dq.size() >= static_cast(client_core_limit)); - gpr_log(GPR_INFO, "Setting client core_list"); - for (int core = 0; core < client_core_limit; core++) { - per_client_config.add_core_list(dq.front()); - dq.pop_front(); - } - } + if(initial_client_config.core_limit() != 0) { + gpr_log(GPR_WARN, "client config core limit set but ignored"); } // Reduce channel count so that total channels specified is held regardless diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index b5c8152e1bc..e72d30a4eff 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -46,8 +46,7 @@ std::unique_ptr RunScenario( const grpc::testing::ClientConfig& client_config, size_t num_clients, const grpc::testing::ServerConfig& server_config, size_t num_servers, int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count, - const char* qps_server_target_override = "", - bool configure_core_lists = true); + const char* qps_server_target_override = ""); bool RunQuit(); } // namespace testing diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index da835b995ab..ca4c6865784 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -70,9 +70,6 @@ DEFINE_double(error_tolerance, 0.01, DEFINE_string(qps_server_target_override, "", "Override QPS server target to configure in client configs." "Only applicable if there is a single benchmark server."); -DEFINE_bool(configure_core_lists, true, - "Provide 'core_list' parameters to workers. Value determined " - "by cores available and 'core_limit' parameters of the scenarios."); namespace grpc { namespace testing { @@ -85,7 +82,7 @@ static std::unique_ptr RunAndReport(const Scenario& scenario, scenario.server_config(), scenario.num_servers(), scenario.warmup_seconds(), scenario.benchmark_seconds(), scenario.spawn_local_worker_count(), - FLAGS_qps_server_target_override.c_str(), FLAGS_configure_core_lists); + FLAGS_qps_server_target_override.c_str()); // Amend the result with scenario config. Eventually we should adjust // RunScenario contract so we don't need to touch the result here. diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py index c3c5ece3628..b20bb40eb1b 100644 --- a/tools/run_tests/performance/scenario_config.py +++ b/tools/run_tests/performance/scenario_config.py @@ -109,7 +109,6 @@ def _ping_pong_scenario(name, rpc_type, unconstrained_client=None, client_language=None, server_language=None, - server_core_limit=0, async_server_threads=0, warmup_seconds=WARMUP_SECONDS, categories=DEFAULT_CATEGORIES, @@ -136,7 +135,6 @@ def _ping_pong_scenario(name, rpc_type, 'server_config': { 'server_type': server_type, 'security_params': _get_secargs(secure), - 'core_limit': server_core_limit, 'async_server_threads': async_server_threads, }, 'warmup_seconds': warmup_seconds, @@ -200,7 +198,7 @@ class CXXLanguage: rpc_type='STREAMING', client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', - use_generic_payload=True, server_core_limit=1, async_server_threads=1, + use_generic_payload=True, async_server_threads=1, secure=secure, categories=smoketest_categories) @@ -219,7 +217,7 @@ class CXXLanguage: client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', unconstrained_client='async', use_generic_payload=True, - server_core_limit=1, async_server_threads=1, + async_server_threads=1, secure=secure) yield _ping_pong_scenario( @@ -248,7 +246,7 @@ class CXXLanguage: rpc_type=rpc_type.upper(), client_type='%s_CLIENT' % synchronicity.upper(), server_type='%s_SERVER' % synchronicity.upper(), - server_core_limit=1, async_server_threads=1, + async_server_threads=1, secure=secure) yield _ping_pong_scenario( @@ -332,13 +330,13 @@ class CSharpLanguage: yield _ping_pong_scenario( 'csharp_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY', client_type='SYNC_CLIENT', server_type='SYNC_SERVER', - server_language='c++', server_core_limit=1, async_server_threads=1, + server_language='c++', async_server_threads=1, categories=[SMOKETEST, SCALABLE]) yield _ping_pong_scenario( 'csharp_to_cpp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING', client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', - server_language='c++', server_core_limit=1, async_server_threads=1) + server_language='c++', async_server_threads=1) yield _ping_pong_scenario( 'csharp_to_cpp_protobuf_async_unary_qps_unconstrained', rpc_type='UNARY', @@ -414,13 +412,13 @@ class NodeLanguage: #yield _ping_pong_scenario( # 'node_to_cpp_protobuf_async_unary_ping_pong', rpc_type='UNARY', # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', - # server_language='c++', server_core_limit=1, async_server_threads=1) + # server_language='c++', async_server_threads=1) # TODO(jtattermusch): make this scenario work #yield _ping_pong_scenario( # 'node_to_cpp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING', # client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', - # server_language='c++', server_core_limit=1, async_server_threads=1) + # server_language='c++', async_server_threads=1) def __str__(self): return 'node' @@ -469,13 +467,13 @@ class PythonLanguage: yield _ping_pong_scenario( 'python_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY', client_type='SYNC_CLIENT', server_type='ASYNC_SERVER', - server_language='c++', server_core_limit=1, async_server_threads=1, + server_language='c++', async_server_threads=1, categories=[SMOKETEST, SCALABLE]) yield _ping_pong_scenario( 'python_to_cpp_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING', client_type='SYNC_CLIENT', server_type='ASYNC_SERVER', - server_language='c++', server_core_limit=1, async_server_threads=1) + server_language='c++', async_server_threads=1) def __str__(self): return 'python' @@ -516,12 +514,12 @@ class RubyLanguage: yield _ping_pong_scenario( 'ruby_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY', client_type='SYNC_CLIENT', server_type='SYNC_SERVER', - server_language='c++', server_core_limit=1, async_server_threads=1) + server_language='c++', async_server_threads=1) yield _ping_pong_scenario( 'ruby_to_cpp_protobuf_sync_streaming_ping_pong', rpc_type='STREAMING', client_type='SYNC_CLIENT', server_type='SYNC_SERVER', - server_language='c++', server_core_limit=1, async_server_threads=1) + server_language='c++', async_server_threads=1) def __str__(self): return 'ruby' From 8a0ef63dea1546a04fd00c6be7f4f223e3e559f1 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 11 Jan 2017 13:52:01 -0800 Subject: [PATCH 054/104] remove LimitCores in c++ benchmark --- test/cpp/qps/client.h | 2 +- test/cpp/qps/limit_cores.cc | 87 ------------------------------------- test/cpp/qps/limit_cores.h | 49 --------------------- test/cpp/qps/server.h | 2 +- 4 files changed, 2 insertions(+), 138 deletions(-) delete mode 100644 test/cpp/qps/limit_cores.cc delete mode 100644 test/cpp/qps/limit_cores.h diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index fdd78ebb899..3018c21f326 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -374,7 +374,7 @@ class ClientImpl : public Client { ClientImpl(const ClientConfig& config, std::function(std::shared_ptr)> create_stub) - : cores_(LimitCores(config.core_list().data(), config.core_list_size())), + : cores_(gpr_cpu_num_cores()), channels_(config.client_channels()), create_stub_(create_stub) { for (int i = 0; i < config.client_channels(); i++) { diff --git a/test/cpp/qps/limit_cores.cc b/test/cpp/qps/limit_cores.cc deleted file mode 100644 index b5c222542be..00000000000 --- a/test/cpp/qps/limit_cores.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "test/cpp/qps/limit_cores.h" - -#include -#include -#include - -#ifdef GPR_CPU_LINUX -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include - -namespace grpc { -namespace testing { - -int LimitCores(const int* cores, int cores_size) { - const int num_cores = gpr_cpu_num_cores(); - int cores_set = 0; - - cpu_set_t* cpup = CPU_ALLOC(num_cores); - GPR_ASSERT(cpup); - const size_t size = CPU_ALLOC_SIZE(num_cores); - CPU_ZERO_S(size, cpup); - - if (cores_size > 0) { - for (int i = 0; i < cores_size; i++) { - if (cores[i] < num_cores) { - CPU_SET_S(cores[i], size, cpup); - cores_set++; - } - } - } else { - for (int i = 0; i < num_cores; i++) { - CPU_SET_S(i, size, cpup); - cores_set++; - } - } - bool affinity_set = (sched_setaffinity(0, size, cpup) == 0); - CPU_FREE(cpup); - return affinity_set ? cores_set : num_cores; -} - -} // namespace testing -} // namespace grpc -#else -namespace grpc { -namespace testing { - -// LimitCores is not currently supported for non-Linux platforms -int LimitCores(const int*, int) { return gpr_cpu_num_cores(); } - -} // namespace testing -} // namespace grpc -#endif diff --git a/test/cpp/qps/limit_cores.h b/test/cpp/qps/limit_cores.h deleted file mode 100644 index 5482904a3c4..00000000000 --- a/test/cpp/qps/limit_cores.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Copyright 2016, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef TEST_QPS_LIMIT_CORES_H -#define TEST_QPS_LIMIT_CORES_H - -namespace grpc { -namespace testing { -/// LimitCores: allow this worker to only run on the cores specified in the -/// array \a cores, which is of length \a cores_size. -/// -/// LimitCores takes array and size arguments (instead of vector) for direct -/// conversion from repeated field of protobuf. Use a cores_size of 0 to remove -/// existing limits (from an empty repeated field) -int LimitCores(const int *cores, int cores_size); -} // namespace testing -} // namespace grpc - -#endif // TEST_QPS_LIMIT_CORES_H diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index c3d18e57892..5f4c34c9ad2 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -51,7 +51,7 @@ namespace testing { class Server { public: explicit Server(const ServerConfig& config) : timer_(new UsageTimer) { - cores_ = LimitCores(config.core_list().data(), config.core_list_size()); + cores_ = gpr_cpu_num_cores(); if (config.port()) { port_ = config.port(); From 6ff1ca4871d73dd018e33bfca0df896570c0d429 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 11 Jan 2017 14:25:55 -0800 Subject: [PATCH 055/104] re-run generate project to build qps json driver --- Makefile | 3 - build.yaml | 1 - test/cpp/qps/client.h | 1 - test/cpp/qps/driver.cc | 4 +- test/cpp/qps/server.h | 1 - .../generated/sources_and_headers.json | 1 - tools/run_tests/generated/tests.json | 136 +++++++++--------- vsprojects/vcxproj/qps/qps.vcxproj | 2 - vsprojects/vcxproj/qps/qps.vcxproj.filters | 3 - 9 files changed, 70 insertions(+), 82 deletions(-) diff --git a/Makefile b/Makefile index 8f7328ae285..314db9f4c1b 100644 --- a/Makefile +++ b/Makefile @@ -5200,7 +5200,6 @@ LIBQPS_SRC = \ test/cpp/qps/client_async.cc \ test/cpp/qps/client_sync.cc \ test/cpp/qps/driver.cc \ - test/cpp/qps/limit_cores.cc \ test/cpp/qps/parse_json.cc \ test/cpp/qps/qps_worker.cc \ test/cpp/qps/report.cc \ @@ -5256,7 +5255,6 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc -$(OBJDIR)/$(CONFIG)/test/cpp/qps/limit_cores.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/parse_json.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc @@ -16812,7 +16810,6 @@ test/cpp/interop/server_helper.cc: $(OPENSSL_DEP) test/cpp/qps/client_async.cc: $(OPENSSL_DEP) test/cpp/qps/client_sync.cc: $(OPENSSL_DEP) test/cpp/qps/driver.cc: $(OPENSSL_DEP) -test/cpp/qps/limit_cores.cc: $(OPENSSL_DEP) test/cpp/qps/parse_json.cc: $(OPENSSL_DEP) test/cpp/qps/qps_worker.cc: $(OPENSSL_DEP) test/cpp/qps/report.cc: $(OPENSSL_DEP) diff --git a/build.yaml b/build.yaml index de9d253ef1c..8f217682c2a 100644 --- a/build.yaml +++ b/build.yaml @@ -1306,7 +1306,6 @@ libs: - test/cpp/qps/client_async.cc - test/cpp/qps/client_sync.cc - test/cpp/qps/driver.cc - - test/cpp/qps/limit_cores.cc - test/cpp/qps/parse_json.cc - test/cpp/qps/qps_worker.cc - test/cpp/qps/report.cc diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 3018c21f326..ae7264c9c16 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -51,7 +51,6 @@ #include "test/cpp/qps/histogram.h" #include "test/cpp/qps/interarrival.h" -#include "test/cpp/qps/limit_cores.h" #include "test/cpp/qps/usage_timer.h" #include "test/cpp/util/create_test_channel.h" diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 42722b7e9d1..7494ced460e 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -263,7 +263,7 @@ std::unique_ptr RunScenario( ServerConfig server_config = initial_server_config; if(server_config.core_limit() != 0) { - gpr_log(GPR_WARN, "server config core limit is set but ignored by driver"); + gpr_log(GPR_ERROR, "server config core limit is set but ignored by driver"); } ServerArgs args; @@ -309,7 +309,7 @@ std::unique_ptr RunScenario( ClientConfig per_client_config = client_config; if(initial_client_config.core_limit() != 0) { - gpr_log(GPR_WARN, "client config core limit set but ignored"); + gpr_log(GPR_ERROR, "client config core limit set but ignored"); } // Reduce channel count so that total channels specified is held regardless diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 5f4c34c9ad2..821d5935beb 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -42,7 +42,6 @@ #include "src/proto/grpc/testing/messages.grpc.pb.h" #include "test/core/end2end/data/ssl_test_data.h" #include "test/core/util/port.h" -#include "test/cpp/qps/limit_cores.h" #include "test/cpp/qps/usage_timer.h" namespace grpc { diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 6ae269cc20d..deadec29a44 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -5545,7 +5545,6 @@ "test/cpp/qps/driver.h", "test/cpp/qps/histogram.h", "test/cpp/qps/interarrival.h", - "test/cpp/qps/limit_cores.cc", "test/cpp/qps/limit_cores.h", "test/cpp/qps/parse_json.cc", "test/cpp/qps/parse_json.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index b76263b8b98..7b46e8256c7 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -36756,7 +36756,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36780,7 +36780,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36804,7 +36804,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36828,7 +36828,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36852,7 +36852,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36876,7 +36876,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36900,7 +36900,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36924,7 +36924,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36948,7 +36948,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36972,7 +36972,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -36996,7 +36996,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37020,7 +37020,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37044,7 +37044,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37068,7 +37068,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37092,7 +37092,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37116,7 +37116,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37140,7 +37140,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37164,7 +37164,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37188,7 +37188,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37212,7 +37212,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37236,7 +37236,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37260,7 +37260,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37284,7 +37284,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37308,7 +37308,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37332,7 +37332,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37356,7 +37356,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37380,7 +37380,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37404,7 +37404,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37428,7 +37428,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37452,7 +37452,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37476,7 +37476,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 16, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37500,7 +37500,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37524,7 +37524,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37548,7 +37548,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37572,7 +37572,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37609,7 +37609,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37646,7 +37646,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37683,7 +37683,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37720,7 +37720,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37757,7 +37757,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37794,7 +37794,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37831,7 +37831,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37868,7 +37868,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37905,7 +37905,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37942,7 +37942,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -37979,7 +37979,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38016,7 +38016,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38053,7 +38053,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38090,7 +38090,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38127,7 +38127,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38164,7 +38164,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_secure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38201,7 +38201,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38238,7 +38238,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38275,7 +38275,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38312,7 +38312,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38349,7 +38349,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_client_sync_server_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 10, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38386,7 +38386,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38423,7 +38423,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38460,7 +38460,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38497,7 +38497,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38534,7 +38534,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38571,7 +38571,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38608,7 +38608,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38645,7 +38645,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38682,7 +38682,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_sync_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"SYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"SYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38719,7 +38719,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"core_limit\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_ping_pong_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38756,7 +38756,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -38793,7 +38793,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"core_limit\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_qps_unconstrained_insecure_500kib_resource_quota\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"resource_quota_size\": 512000, \"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ diff --git a/vsprojects/vcxproj/qps/qps.vcxproj b/vsprojects/vcxproj/qps/qps.vcxproj index 004cf7c9f0e..8b98b5e67c5 100644 --- a/vsprojects/vcxproj/qps/qps.vcxproj +++ b/vsprojects/vcxproj/qps/qps.vcxproj @@ -207,8 +207,6 @@ - - diff --git a/vsprojects/vcxproj/qps/qps.vcxproj.filters b/vsprojects/vcxproj/qps/qps.vcxproj.filters index d3a440ba730..111b133d719 100644 --- a/vsprojects/vcxproj/qps/qps.vcxproj.filters +++ b/vsprojects/vcxproj/qps/qps.vcxproj.filters @@ -25,9 +25,6 @@ test\cpp\qps - - test\cpp\qps - test\cpp\qps From 8ad258a450cd7800984be3da48e21bd1484c9673 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 15:22:29 -0800 Subject: [PATCH 056/104] Add missing include for GPRAPI --- include/grpc/support/log_windows.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/grpc/support/log_windows.h b/include/grpc/support/log_windows.h index 12bf8cc1f5e..943a8e908b3 100644 --- a/include/grpc/support/log_windows.h +++ b/include/grpc/support/log_windows.h @@ -34,6 +34,8 @@ #ifndef GRPC_SUPPORT_LOG_WINDOWS_H #define GRPC_SUPPORT_LOG_WINDOWS_H +#include + #ifdef __cplusplus extern "C" { #endif From 20ce39a4fe664b73cd271044e59377ee4d91d950 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Wed, 11 Jan 2017 15:44:13 -0800 Subject: [PATCH 057/104] remove limit_cores.h from build.yaml --- build.yaml | 1 - tools/run_tests/generated/sources_and_headers.json | 2 -- vsprojects/vcxproj/qps/qps.vcxproj | 1 - vsprojects/vcxproj/qps/qps.vcxproj.filters | 3 --- 4 files changed, 7 deletions(-) diff --git a/build.yaml b/build.yaml index 8f217682c2a..8f478066f76 100644 --- a/build.yaml +++ b/build.yaml @@ -1289,7 +1289,6 @@ libs: - test/cpp/qps/driver.h - test/cpp/qps/histogram.h - test/cpp/qps/interarrival.h - - test/cpp/qps/limit_cores.h - test/cpp/qps/parse_json.h - test/cpp/qps/qps_worker.h - test/cpp/qps/report.h diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index deadec29a44..8bf9dfd617a 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -5525,7 +5525,6 @@ "test/cpp/qps/driver.h", "test/cpp/qps/histogram.h", "test/cpp/qps/interarrival.h", - "test/cpp/qps/limit_cores.h", "test/cpp/qps/parse_json.h", "test/cpp/qps/qps_worker.h", "test/cpp/qps/report.h", @@ -5545,7 +5544,6 @@ "test/cpp/qps/driver.h", "test/cpp/qps/histogram.h", "test/cpp/qps/interarrival.h", - "test/cpp/qps/limit_cores.h", "test/cpp/qps/parse_json.cc", "test/cpp/qps/parse_json.h", "test/cpp/qps/qps_worker.cc", diff --git a/vsprojects/vcxproj/qps/qps.vcxproj b/vsprojects/vcxproj/qps/qps.vcxproj index 8b98b5e67c5..2d7892683a8 100644 --- a/vsprojects/vcxproj/qps/qps.vcxproj +++ b/vsprojects/vcxproj/qps/qps.vcxproj @@ -151,7 +151,6 @@ - diff --git a/vsprojects/vcxproj/qps/qps.vcxproj.filters b/vsprojects/vcxproj/qps/qps.vcxproj.filters index 111b133d719..f25be9af191 100644 --- a/vsprojects/vcxproj/qps/qps.vcxproj.filters +++ b/vsprojects/vcxproj/qps/qps.vcxproj.filters @@ -60,9 +60,6 @@ test\cpp\qps - - test\cpp\qps - test\cpp\qps From 4314043e407763918de6696366919d0fa8afac83 Mon Sep 17 00:00:00 2001 From: Noah Eisen Date: Wed, 11 Jan 2017 15:59:33 -0800 Subject: [PATCH 058/104] Update negative-http2-interop-test-descriptions.md --- doc/negative-http2-interop-test-descriptions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/negative-http2-interop-test-descriptions.md b/doc/negative-http2-interop-test-descriptions.md index 1ded97b5037..b64fe6a024d 100644 --- a/doc/negative-http2-interop-test-descriptions.md +++ b/doc/negative-http2-interop-test-descriptions.md @@ -50,6 +50,7 @@ the user application having to do a thing. Client Procedure: 1. Client sends two UnaryCall requests (and sleeps for 1 second in-between). + TODO: resolve [9300](https://github.com/grpc/grpc/issues/9300) and remove the 1 second sleep ``` { From 43dc9ed3b7faf24c02896b2307739630a3c92154 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 16:05:25 -0800 Subject: [PATCH 059/104] Add licenses to all BUILD files and missing copyright --- bazel/BUILD | 31 ++++++++++++++++++++++++++ src/proto/grpc/testing/BUILD | 30 +++++++++++++++++++++++++ src/proto/grpc/testing/duplicate/BUILD | 30 +++++++++++++++++++++++++ test/core/bad_client/BUILD | 2 ++ test/core/bad_ssl/BUILD | 2 ++ test/core/end2end/BUILD | 2 ++ test/core/end2end/fuzzers/BUILD | 2 ++ test/core/http/BUILD | 2 ++ test/core/json/BUILD | 2 ++ test/core/nanopb/BUILD | 2 ++ test/core/transport/chttp2/BUILD | 2 ++ test/core/util/BUILD | 29 ++++++++++++++++++++++++ 12 files changed, 136 insertions(+) diff --git a/bazel/BUILD b/bazel/BUILD index 940a379404f..2d3c576aa0e 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -1,3 +1,34 @@ +# Copyright 2016, 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. + +licenses(["notice"]) # 3-clause BSD + package(default_visibility = ["//:__subpackages__"]) load(":cc_grpc_library.bzl", "cc_grpc_library") diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD index f9f9cbceaf3..8d5c32d35cb 100644 --- a/src/proto/grpc/testing/BUILD +++ b/src/proto/grpc/testing/BUILD @@ -1,3 +1,33 @@ +# Copyright 2016, 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. + +licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) diff --git a/src/proto/grpc/testing/duplicate/BUILD b/src/proto/grpc/testing/duplicate/BUILD index 255e699bec0..f58de9bec69 100644 --- a/src/proto/grpc/testing/duplicate/BUILD +++ b/src/proto/grpc/testing/duplicate/BUILD @@ -1,3 +1,33 @@ +# Copyright 2016, 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. + +licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) diff --git a/test/core/bad_client/BUILD b/test/core/bad_client/BUILD index 5406eb9a4b0..6b06955efe7 100644 --- a/test/core/bad_client/BUILD +++ b/test/core/bad_client/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load(":generate_tests.bzl", "grpc_bad_client_tests") grpc_bad_client_tests() diff --git a/test/core/bad_ssl/BUILD b/test/core/bad_ssl/BUILD index 630733dd4d7..288788a52d3 100644 --- a/test/core/bad_ssl/BUILD +++ b/test/core/bad_ssl/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load(":generate_tests.bzl", "grpc_bad_ssl_tests") grpc_bad_ssl_tests() diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD index 681cea1de74..a40fb8e083f 100644 --- a/test/core/end2end/BUILD +++ b/test/core/end2end/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load(":generate_tests.bzl", "grpc_end2end_tests") cc_library( diff --git a/test/core/end2end/fuzzers/BUILD b/test/core/end2end/fuzzers/BUILD index 2adda560b40..4d98aa0725c 100644 --- a/test/core/end2end/fuzzers/BUILD +++ b/test/core/end2end/fuzzers/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") grpc_fuzzer( diff --git a/test/core/http/BUILD b/test/core/http/BUILD index 58d265bd8fb..037ede3cd1c 100644 --- a/test/core/http/BUILD +++ b/test/core/http/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") grpc_fuzzer( diff --git a/test/core/json/BUILD b/test/core/json/BUILD index 4b3fbd60768..05d4c6e0c5e 100644 --- a/test/core/json/BUILD +++ b/test/core/json/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") grpc_fuzzer( diff --git a/test/core/nanopb/BUILD b/test/core/nanopb/BUILD index bdf79b7fefa..b02d750f325 100644 --- a/test/core/nanopb/BUILD +++ b/test/core/nanopb/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") grpc_fuzzer( diff --git a/test/core/transport/chttp2/BUILD b/test/core/transport/chttp2/BUILD index 5dd205174f9..94b48301386 100644 --- a/test/core/transport/chttp2/BUILD +++ b/test/core/transport/chttp2/BUILD @@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +licenses(["notice"]) # 3-clause BSD + load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer") grpc_fuzzer( diff --git a/test/core/util/BUILD b/test/core/util/BUILD index e50e595d039..e7ed5ea2f59 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -1,4 +1,33 @@ +# Copyright 2016, 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. +licenses(["notice"]) # 3-clause BSD cc_library( name = "gpr_test_util", From d36a53156c9591cd68e5ea17d7579cda896e2840 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 16:14:44 -0800 Subject: [PATCH 060/104] Add missing include for size_t --- test/core/util/memory_counters.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/core/util/memory_counters.h b/test/core/util/memory_counters.h index f3328165014..b9b2b3adda5 100644 --- a/test/core/util/memory_counters.h +++ b/test/core/util/memory_counters.h @@ -34,6 +34,8 @@ #ifndef GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H #define GRPC_TEST_CORE_UTIL_MEMORY_COUNTERS_H +#include + struct grpc_memory_counters { size_t total_size_relative; size_t total_size_absolute; From 015998f7708843ead6379ac5e6d6963603d200ea Mon Sep 17 00:00:00 2001 From: Adele Zhou Date: Tue, 6 Dec 2016 16:05:07 -0800 Subject: [PATCH 061/104] Add perf link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 70cf9fcc30e..174e861f594 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ See [INSTALL](INSTALL.md) for installation instructions for various platforms. See [tools/run_tests](tools/run_tests) for more guidance on how to run various test suites (e.g. unit tests, interop tests, benchmarks) +See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5712453606309888) for the performance numbers for v1.0.x. + #Repository Structure & Status This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core] (src/core). From 122c687d61aac26d228da9bb6ed2a6237be55d93 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Wed, 11 Jan 2017 19:35:17 -0800 Subject: [PATCH 062/104] Fix various PHP bugs --- src/php/bin/generate_proto_php.sh | 21 +++++++++++++-------- src/php/lib/Grpc/BaseStub.php | 6 +++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/php/bin/generate_proto_php.sh b/src/php/bin/generate_proto_php.sh index c558bc57698..06cd7693304 100755 --- a/src/php/bin/generate_proto_php.sh +++ b/src/php/bin/generate_proto_php.sh @@ -39,10 +39,12 @@ protoc --proto_path=src/proto/math \ # replace the Empty message with EmptyMessage # because Empty is a PHP reserved word -sed -i 's/message Empty/message EmptyMessage/g' \ - src/proto/grpc/testing/empty.proto -sed -i 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \ - src/proto/grpc/testing/test.proto +sed 's/message Empty/message EmptyMessage/g' \ + src/proto/grpc/testing/empty.proto > empty.proto +mv empty.proto ./src/proto/grpc/testing +sed 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \ + src/proto/grpc/testing/test.proto > test.proto +mv test.proto ./src/proto/grpc/testing protoc --proto_path=. \ --php_out=src/php/tests/interop \ @@ -53,7 +55,10 @@ protoc --proto_path=. \ src/proto/grpc/testing/test.proto # change it back -sed -i 's/message EmptyMessage/message Empty/g' \ - src/proto/grpc/testing/empty.proto -sed -i 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \ - src/proto/grpc/testing/test.proto +sed 's/message EmptyMessage/message Empty/g' \ + src/proto/grpc/testing/empty.proto > empty.proto +mv empty.proto ./src/proto/grpc/testing +sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \ + src/proto/grpc/testing/test.proto > test.proto +mv test.proto ./src/proto/grpc/testing + diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php index aec60af094f..a9e77b9396a 100644 --- a/src/php/lib/Grpc/BaseStub.php +++ b/src/php/lib/Grpc/BaseStub.php @@ -271,7 +271,7 @@ class BaseStub * @return ClientStreamingSurfaceActiveCall The active call object */ public function _clientStreamRequest($method, - callable $deserialize, + $deserialize, array $metadata = [], array $options = []) { @@ -307,7 +307,7 @@ class BaseStub */ public function _serverStreamRequest($method, $argument, - callable $deserialize, + $deserialize, array $metadata = [], array $options = []) { @@ -340,7 +340,7 @@ class BaseStub * @return BidiStreamingSurfaceActiveCall The active call object */ public function _bidiRequest($method, - callable $deserialize, + $deserialize, array $metadata = [], array $options = []) { From 90cd2789457a466c208a46bbaf413cfe2af57bd8 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Wed, 11 Jan 2017 21:38:33 -0800 Subject: [PATCH 063/104] PHP: use a macro to specify extension src dir --- config.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index 12b10578e89..85549e5f427 100644 --- a/config.m4 +++ b/config.m4 @@ -5,9 +5,9 @@ if test "$PHP_GRPC" != "no"; then dnl Write more examples of tests here... dnl # --with-grpc -> add include path - PHP_ADD_INCLUDE(../../grpc/include) - PHP_ADD_INCLUDE(../../grpc/src/php/ext/grpc) - PHP_ADD_INCLUDE(../../grpc/third_party/boringssl/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include) LIBS="-lpthread $LIBS" From a2341eaed05cb5713dc95ff52fe59730a006f389 Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 11 Jan 2017 23:01:24 -0800 Subject: [PATCH 064/104] omg it is 2017 --- bazel/BUILD | 2 +- src/proto/grpc/testing/BUILD | 2 +- src/proto/grpc/testing/duplicate/BUILD | 2 +- test/core/util/BUILD | 2 +- tools/distrib/check_copyright.py | 1 + 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bazel/BUILD b/bazel/BUILD index 2d3c576aa0e..fe776b20ef2 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -1,4 +1,4 @@ -# Copyright 2016, Google Inc. +# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD index 8d5c32d35cb..283740839d9 100644 --- a/src/proto/grpc/testing/BUILD +++ b/src/proto/grpc/testing/BUILD @@ -1,4 +1,4 @@ -# Copyright 2016, Google Inc. +# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/src/proto/grpc/testing/duplicate/BUILD b/src/proto/grpc/testing/duplicate/BUILD index f58de9bec69..8fc5a96af40 100644 --- a/src/proto/grpc/testing/duplicate/BUILD +++ b/src/proto/grpc/testing/duplicate/BUILD @@ -1,4 +1,4 @@ -# Copyright 2016, Google Inc. +# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/test/core/util/BUILD b/test/core/util/BUILD index e7ed5ea2f59..8769683b23a 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -1,4 +1,4 @@ -# Copyright 2016, Google Inc. +# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/distrib/check_copyright.py b/tools/distrib/check_copyright.py index 718bb563f3a..c993407eb24 100755 --- a/tools/distrib/check_copyright.py +++ b/tools/distrib/check_copyright.py @@ -90,6 +90,7 @@ LICENSE_PREFIX = { 'Makefile': r'#\s*', 'Dockerfile': r'#\s*', 'LICENSE': '', + 'BUILD': r'#\s*', } _EXEMPT = frozenset(( From 3aab96f56c7de370070e9966cf3728fbcd1018dd Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 11 Jan 2017 16:12:46 +0100 Subject: [PATCH 065/104] successfuly compile gRPC with cmake+Ninja --- CMakeLists.txt | 8 +++++++- templates/CMakeLists.txt.template | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd271d472db..9e6b5f6bee0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,13 @@ set_property(CACHE gRPC_PROTOBUF_PROVIDER PROPERTY STRINGS "module" "package") set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library") if (MSVC) - add_definitions( -D_WIN32_WINNT=0x600 ) + add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS) + # needed to compile boringssl + add_definitions(/wd4464 /wd4623 /wd4668 /wd4701 /wd4702 /wd4777 /wd5027) + # needed to compile protobuf + add_definitions(/wd4065 /wd4506) + # TODO(jtattermusch): revisit C4267 occurrences throughout the code + add_definitions(/wd4267) endif() if (gRPC_USE_PROTO_LITE) diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template index c3c636c6af7..8d49abeffd4 100644 --- a/templates/CMakeLists.txt.template +++ b/templates/CMakeLists.txt.template @@ -84,7 +84,13 @@ set(gRPC_USE_PROTO_LITE OFF CACHE BOOL "Use the protobuf-lite library") if (MSVC) - add_definitions( -D_WIN32_WINNT=0x600 ) + add_definitions(-D_WIN32_WINNT=0x600 -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_WINSOCK_DEPRECATED_NO_WARNINGS) + # needed to compile boringssl + add_definitions(/wd4464 /wd4623 /wd4668 /wd4701 /wd4702 /wd4777 /wd5027) + # needed to compile protobuf + add_definitions(/wd4065 /wd4506) + # TODO(jtattermusch): revisit C4267 occurrences throughout the code + add_definitions(/wd4267) endif() if (gRPC_USE_PROTO_LITE) From af7b87f8eba17ec4ea4e87e19ebdb6935aadedc7 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 12 Jan 2017 09:41:03 +0100 Subject: [PATCH 066/104] remove unneeded/broken targets from CMakeLists.exe --- CMakeLists.txt | 68 ------------------------------- templates/CMakeLists.txt.template | 9 +++- 2 files changed, 7 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e6b5f6bee0..4627c10e2e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1589,45 +1589,6 @@ if (gRPC_INSTALL) endif() -add_library(grpc++_reflection - src/cpp/ext/proto_server_reflection.cc - src/cpp/ext/proto_server_reflection_plugin.cc - src/proto/grpc/reflection/v1alpha/reflection.proto -) - -target_include_directories(grpc++_reflection - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include - PRIVATE ${BORINGSSL_ROOT_DIR}/include - PRIVATE ${PROTOBUF_ROOT_DIR}/src - PRIVATE ${ZLIB_INCLUDE_DIR} - PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib -) - -target_link_libraries(grpc++_reflection - grpc++ -) - -foreach(_hdr - include/grpc++/ext/proto_server_reflection_plugin.h -) - string(REPLACE "include/" "" _path ${_hdr}) - get_filename_component(_path ${_path} PATH) - install(FILES ${_hdr} - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" - ) -endforeach() - - -if (gRPC_INSTALL) - install(TARGETS grpc++_reflection EXPORT gRPCTargets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) -endif() - - add_library(grpc++_unsecure src/cpp/client/insecure_credentials.cc src/cpp/common/insecure_create_auth_context.cc @@ -1828,35 +1789,6 @@ if (gRPC_INSTALL) ) endif() - -add_library(grpc_csharp_ext - src/csharp/ext/grpc_csharp_ext.c -) - -target_include_directories(grpc_csharp_ext - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include - PRIVATE ${BORINGSSL_ROOT_DIR}/include - PRIVATE ${PROTOBUF_ROOT_DIR}/src - PRIVATE ${ZLIB_INCLUDE_DIR} - PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib -) - -target_link_libraries(grpc_csharp_ext - grpc - gpr -) - - - -if (gRPC_INSTALL) - install(TARGETS grpc_csharp_ext EXPORT gRPCTargets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) -endif() - add_executable(gen_hpack_tables diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template index 8d49abeffd4..028c1b8c328 100644 --- a/templates/CMakeLists.txt.template +++ b/templates/CMakeLists.txt.template @@ -194,14 +194,19 @@ endif() % for lib in libs: - % if lib.build in ["all", "protoc", "tool"]: + % if lib.build in ["all", "protoc", "tool"] and lib.language in ['c', 'c++']: + ## TODO(jtattermusch): grpc++_reflection includes .proto files + ## which is not yet supported and thus fails the entire build. + ## Re-enable once fixed. + % if lib.name != 'grpc++_reflection': ${cc_library(lib)} ${cc_install(lib)} % endif + % endif % endfor % for tgt in targets: - % if tgt.build in ["all", "protoc", "tool"]: + % if tgt.build in ["all", "protoc", "tool"] and tgt.language in ['c', 'c++']: ${cc_binary(tgt)} ${cc_install(tgt)} % endif From 8e883b23bae2d2dd3367d3d1bcbe0d95c1d7c31d Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Thu, 12 Jan 2017 11:45:52 +0100 Subject: [PATCH 067/104] Makefile.template: fixed a few variables names, and added a missing variable on dll name --- templates/Makefile.template | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/Makefile.template b/templates/Makefile.template index 1b6bc0e93de..230f16c0c89 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1303,7 +1303,7 @@ % if not lib.get('external_deps', None): $(E) "[INSTALL] Installing $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]})" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a else ifneq ($(SYSTEM),Darwin) @@ -1520,7 +1520,7 @@ link_libs = link_libs + ' -l' + dep lib_deps = lib_deps + ' $(LIBDIR)/$(CONFIG)/lib' + dep + '.$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' mingw_libs = mingw_libs + ' -l' + dep + '-imp' - mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '.$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' + mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '$(SHARED_VERSION_' + lang_to_var[dep_lib.language] + ').$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' security = lib.get('secure', 'check') if security == True: @@ -1558,11 +1558,11 @@ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) -dynamiclib -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs} + $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) -dynamiclib -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs} else $(Q) ${ld} ${ldflags} -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,lib${lib.name}.so.${settings.core_version.major} -o ${out_libbase}.$(SHARED_EXT_${lang_to_var[lib.language]}) ${common}${link_libs} - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major} - $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major} + $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ${out_libbase}.so endif endif % endif From 34f58fe42c0ede74555ccaa54e9769ec10bb9fca Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 12 Jan 2017 14:14:05 +0100 Subject: [PATCH 068/104] remove not-yet-useful projects from grpc.sln --- templates/vsprojects/grpc.sln.template | 2 +- vsprojects/grpc.sln | 66 -------------------------- 2 files changed, 1 insertion(+), 67 deletions(-) diff --git a/templates/vsprojects/grpc.sln.template b/templates/vsprojects/grpc.sln.template index ded98383dad..0b28e936be2 100644 --- a/templates/vsprojects/grpc.sln.template +++ b/templates/vsprojects/grpc.sln.template @@ -2,6 +2,6 @@ --- | <%namespace file="sln_defs.include" import="gen_solution"/>\ <% - solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'test', 'fuzzer'] and p.language in ['c', 'c++'] and p.vs_proj_dir == '.' and not (p.build == 'private' and p.language == 'c++')] + solution_projects = [p for p in vsprojects if p.build not in ['protoc', 'test', 'fuzzer'] and p.language in ['c', 'c++'] and p.vs_proj_dir == '.' and not (p.build == 'private' and p.language == 'c++') and not p.name in ['z', 'boringssl', 'grpc++_reflection']] %>\ ${gen_solution(solution_projects, use_dlls='yes')} diff --git a/vsprojects/grpc.sln b/vsprojects/grpc.sln index 63be171c6ef..591d3b5edb2 100644 --- a/vsprojects/grpc.sln +++ b/vsprojects/grpc.sln @@ -3,11 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "boringssl", "vcxproj\.\boringssl\boringssl.vcxproj", "{9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}" - ProjectSection(myProperties) = preProject - lib = "True" - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_hpack_tables", "vcxproj\.\gen_hpack_tables\gen_hpack_tables.vcxproj", "{FCDEA4C7-7F26-05DB-D08F-A08F499026E6}" ProjectSection(myProperties) = preProject lib = "False" @@ -56,14 +51,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++", "vcxproj\.\grpc++\ {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++_reflection", "vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj", "{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}" - ProjectSection(myProperties) = preProject - lib = "True" - EndProjectSection - ProjectSection(ProjectDependencies) = postProject - {C187A093-A0FE-489D-A40A-6E33DE0F9FEB} = {C187A093-A0FE-489D-A40A-6E33DE0F9FEB} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc++_unsecure", "vcxproj\.\grpc++_unsecure\grpc++_unsecure.vcxproj", "{6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}" ProjectSection(myProperties) = preProject lib = "True" @@ -161,11 +148,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_tcp_server", "vcxproj\ {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "z", "vcxproj\.\z\z.vcxproj", "{FBADE9E3-6A3F-36D3-D676-C1B808451DD7}" - ProjectSection(myProperties) = preProject - lib = "True" - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -178,22 +160,6 @@ Global Release-DLL|x64 = Release-DLL|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|Win32.ActiveCfg = Debug|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|x64.ActiveCfg = Debug|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|Win32.ActiveCfg = Release|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|x64.ActiveCfg = Release|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|Win32.Build.0 = Debug|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug|x64.Build.0 = Debug|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|Win32.Build.0 = Release|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release|x64.Build.0 = Release|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|Win32.Build.0 = Debug|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|x64.ActiveCfg = Debug|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Debug-DLL|x64.Build.0 = Debug|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|Win32.ActiveCfg = Release|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|Win32.Build.0 = Release|Win32 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|x64.ActiveCfg = Release|x64 - {9FD9A3EF-C4A3-8390-D8F4-6F86C22A58CE}.Release-DLL|x64.Build.0 = Release|x64 {FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Debug|Win32.ActiveCfg = Debug|Win32 {FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Debug|x64.ActiveCfg = Debug|x64 {FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Release|Win32.ActiveCfg = Release|Win32 @@ -306,22 +272,6 @@ Global {C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release-DLL|Win32.Build.0 = Release-DLL|Win32 {C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release-DLL|x64.ActiveCfg = Release-DLL|x64 {C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release-DLL|x64.Build.0 = Release-DLL|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|Win32.ActiveCfg = Debug|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|x64.ActiveCfg = Debug|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|Win32.ActiveCfg = Release|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|x64.ActiveCfg = Release|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|Win32.Build.0 = Debug|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug|x64.Build.0 = Debug|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|Win32.Build.0 = Release|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release|x64.Build.0 = Release|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|Win32.Build.0 = Debug|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|x64.ActiveCfg = Debug|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Debug-DLL|x64.Build.0 = Debug|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|Win32.ActiveCfg = Release|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|Win32.Build.0 = Release|Win32 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|x64.ActiveCfg = Release|x64 - {5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}.Release-DLL|x64.Build.0 = Release|x64 {6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}.Debug|Win32.ActiveCfg = Debug|Win32 {6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}.Debug|x64.ActiveCfg = Debug|x64 {6EE56155-DF7C-4F6E-BFC4-F6F776BEB211}.Release|Win32.ActiveCfg = Release|Win32 @@ -482,22 +432,6 @@ Global {E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|Win32.Build.0 = Release|Win32 {E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.ActiveCfg = Release|x64 {E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.Build.0 = Release|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|Win32.ActiveCfg = Debug|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|x64.ActiveCfg = Debug|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|Win32.ActiveCfg = Release|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|x64.ActiveCfg = Release|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|Win32.Build.0 = Debug|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug|x64.Build.0 = Debug|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|Win32.Build.0 = Release|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release|x64.Build.0 = Release|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|Win32.Build.0 = Debug|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|x64.ActiveCfg = Debug|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Debug-DLL|x64.Build.0 = Debug|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|Win32.ActiveCfg = Release|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|Win32.Build.0 = Release|Win32 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|x64.ActiveCfg = Release|x64 - {FBADE9E3-6A3F-36D3-D676-C1B808451DD7}.Release-DLL|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From c79da7b383b2e927c2fc03860fcf641e76d694a4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 12 Jan 2017 14:57:24 +0100 Subject: [PATCH 069/104] fix compilation of grpc_dll project --- src/core/ext/census/tracing.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c index 8f0e12296dd..3b5d6dab2b8 100644 --- a/src/core/ext/census/tracing.c +++ b/src/core/ext/census/tracing.c @@ -31,19 +31,15 @@ * */ -//#include "src/core/ext/census/tracing.h" - #include /* TODO(aveitch): These are all placeholder implementations. */ -// int census_trace_mask(const census_context *context) { -// return CENSUS_TRACE_MASK_NONE; -// } - -// void census_set_trace_mask(int trace_mask) {} +int census_trace_mask(const census_context *context) { + return CENSUS_TRACE_MASK_NONE; +} -// void census_trace_print(census_context *context, uint32_t type, -// const char *buffer, size_t n) {} +void census_set_trace_mask(int trace_mask) {} -// void SetTracerParams(const Params& params); +void census_trace_print(census_context *context, uint32_t type, + const char *buffer, size_t n) {} From fe71d7fc5fb9d730cda1579baba65da7389ecb49 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 12 Jan 2017 11:13:23 -0800 Subject: [PATCH 070/104] Fix the template as well --- templates/config.m4.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/config.m4.template b/templates/config.m4.template index 5847d456f51..f5f1d23088d 100644 --- a/templates/config.m4.template +++ b/templates/config.m4.template @@ -7,9 +7,9 @@ dnl Write more examples of tests here... dnl # --with-grpc -> add include path - PHP_ADD_INCLUDE(../../grpc/include) - PHP_ADD_INCLUDE(../../grpc/src/php/ext/grpc) - PHP_ADD_INCLUDE(../../grpc/third_party/boringssl/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include) LIBS="-lpthread $LIBS" From 62a7ca8c9516b071593e7cea63d3466678589085 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Thu, 12 Jan 2017 11:32:15 -0800 Subject: [PATCH 071/104] re-run clang-format.sh --- test/cpp/qps/driver.cc | 7 ++++--- test/cpp/qps/qps_json_driver.cc | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 7494ced460e..74fe3662c1c 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -262,8 +262,9 @@ std::unique_ptr RunScenario( CreateChannel(workers[i], InsecureChannelCredentials())); ServerConfig server_config = initial_server_config; - if(server_config.core_limit() != 0) { - gpr_log(GPR_ERROR, "server config core limit is set but ignored by driver"); + if (server_config.core_limit() != 0) { + gpr_log(GPR_ERROR, + "server config core limit is set but ignored by driver"); } ServerArgs args; @@ -308,7 +309,7 @@ std::unique_ptr RunScenario( CreateChannel(worker, InsecureChannelCredentials())); ClientConfig per_client_config = client_config; - if(initial_client_config.core_limit() != 0) { + if (initial_client_config.core_limit() != 0) { gpr_log(GPR_ERROR, "client config core limit set but ignored"); } diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index ca4c6865784..db77a827468 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -77,12 +77,12 @@ namespace testing { static std::unique_ptr RunAndReport(const Scenario& scenario, bool* success) { std::cerr << "RUNNING SCENARIO: " << scenario.name() << "\n"; - auto result = RunScenario( - scenario.client_config(), scenario.num_clients(), - scenario.server_config(), scenario.num_servers(), - scenario.warmup_seconds(), scenario.benchmark_seconds(), - scenario.spawn_local_worker_count(), - FLAGS_qps_server_target_override.c_str()); + auto result = + RunScenario(scenario.client_config(), scenario.num_clients(), + scenario.server_config(), scenario.num_servers(), + scenario.warmup_seconds(), scenario.benchmark_seconds(), + scenario.spawn_local_worker_count(), + FLAGS_qps_server_target_override.c_str()); // Amend the result with scenario config. Eventually we should adjust // RunScenario contract so we don't need to touch the result here. From c518198d9adc423442082130dace7230b5df6e50 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Jan 2017 12:40:11 -0800 Subject: [PATCH 072/104] run_tests: set Node runtime variable when using default compiler --- tools/run_tests/run_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index ab719a6727e..5aae3432e16 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -377,6 +377,7 @@ class NodeLanguage(object): 'node4', 'node5', 'node6', 'node7', 'electron1.3']) if self.args.compiler == 'default': + self.runtime = 'node' self.node_version = '4' else: if self.args.compiler.startswith('electron'): From abe9757da1cda736db7305823aa3269454949cb5 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Thu, 12 Jan 2017 22:06:04 +0100 Subject: [PATCH 073/104] Makefile: fixed a few variables names, and added a missing variable on dll name --- Makefile | 80 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index 024ca8f12af..932f6068319 100644 --- a/Makefile +++ b/Makefile @@ -2337,7 +2337,7 @@ install-static_cxx: static_cxx strip-static_cxx install-pkg-config_cxx install-shared_c: shared_c strip-shared_c install-pkg-config_c $(E) "[INSTALL] Installing $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr-imp.a $(prefix)/lib/libgpr-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2346,7 +2346,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc-imp.a $(prefix)/lib/libgrpc-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2355,7 +2355,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet-imp.a $(prefix)/lib/libgrpc_cronet-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2364,7 +2364,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure-imp.a $(prefix)/lib/libgrpc_unsecure-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2381,7 +2381,7 @@ endif install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-config_cxx $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++-imp.a $(prefix)/lib/libgrpc++-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2390,7 +2390,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet-imp.a $(prefix)/lib/libgrpc++_cronet-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2399,7 +2399,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection-imp.a $(prefix)/lib/libgrpc++_reflection-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2408,7 +2408,7 @@ else ifneq ($(SYSTEM),Darwin) endif $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a $(prefix)/lib/libgrpc++_unsecure-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2425,7 +2425,7 @@ endif install-shared_csharp: shared_csharp strip-shared_csharp $(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP)" $(Q) $(INSTALL) -d $(prefix)/lib - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) ifeq ($(SYSTEM),MINGW32) $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a $(prefix)/lib/libgrpc_csharp_ext-imp.a else ifneq ($(SYSTEM),Darwin) @@ -2590,11 +2590,11 @@ $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OB $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.2 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so endif endif @@ -2913,11 +2913,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so endif endif @@ -3186,11 +3186,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(L $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so endif endif @@ -3686,11 +3686,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2 - $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so + $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.2 + $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so endif endif @@ -3941,7 +3941,7 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc-imp @@ -3950,11 +3950,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC+ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc - $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so endif endif @@ -4316,7 +4316,7 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp @@ -4325,11 +4325,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(L $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet - $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so endif endif @@ -4439,7 +4439,7 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++-imp @@ -4448,11 +4448,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ - $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so endif endif @@ -4831,7 +4831,7 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT_CORE) +$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp @@ -4840,11 +4840,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $ $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure else $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure - $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so endif endif @@ -5330,11 +5330,11 @@ $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHA $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) + $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) else $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.2 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1 - $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so + $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1 + $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so endif endif From 4dd97f901939c75ad9b77dc490cc642b2bc52161 Mon Sep 17 00:00:00 2001 From: Makarand Dharmapurikar Date: Thu, 12 Jan 2017 15:04:31 -0800 Subject: [PATCH 074/104] dockerfile update for http2_badserver_interop added h2 and twisted python modules --- tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile index 05e963d1e67..03ff179f718 100644 --- a/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile @@ -46,6 +46,7 @@ RUN apt-get update && apt-get install -y \ RUN pip install pip --upgrade RUN pip install virtualenv RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2 six==1.10.0 +RUN pip install twisted h2 # Define the default command. CMD ["bash"] From 50c878088a0aa43208609dce30ec578cf10296c0 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 12 Jan 2017 15:49:56 -0800 Subject: [PATCH 075/104] Use tmp file instead of writing to current directory --- src/php/bin/generate_proto_php.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/php/bin/generate_proto_php.sh b/src/php/bin/generate_proto_php.sh index 06cd7693304..416fa9df97b 100755 --- a/src/php/bin/generate_proto_php.sh +++ b/src/php/bin/generate_proto_php.sh @@ -39,12 +39,13 @@ protoc --proto_path=src/proto/math \ # replace the Empty message with EmptyMessage # because Empty is a PHP reserved word +output_file=$(mktemp) sed 's/message Empty/message EmptyMessage/g' \ - src/proto/grpc/testing/empty.proto > empty.proto -mv empty.proto ./src/proto/grpc/testing + src/proto/grpc/testing/empty.proto > $output_file +mv $output_file ./src/proto/grpc/testing/empty.proto sed 's/grpc\.testing\.Empty/grpc\.testing\.EmptyMessage/g' \ - src/proto/grpc/testing/test.proto > test.proto -mv test.proto ./src/proto/grpc/testing + src/proto/grpc/testing/test.proto > $output_file +mv $output_file ./src/proto/grpc/testing/test.proto protoc --proto_path=. \ --php_out=src/php/tests/interop \ @@ -56,9 +57,9 @@ protoc --proto_path=. \ # change it back sed 's/message EmptyMessage/message Empty/g' \ - src/proto/grpc/testing/empty.proto > empty.proto -mv empty.proto ./src/proto/grpc/testing + src/proto/grpc/testing/empty.proto > $output_file +mv $output_file ./src/proto/grpc/testing/empty.proto sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \ - src/proto/grpc/testing/test.proto > test.proto -mv test.proto ./src/proto/grpc/testing + src/proto/grpc/testing/test.proto > $output_file +mv $output_file ./src/proto/grpc/testing/test.proto From 88162f82c407e3025d3e157705b3aade63da675f Mon Sep 17 00:00:00 2001 From: Michael Lumish Date: Thu, 12 Jan 2017 17:37:58 -0800 Subject: [PATCH 076/104] Do not use OPENSSL_NO_THREAD normally for Node on Windows --- binding.gyp | 8 ++++++-- templates/binding.gyp.template | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/binding.gyp b/binding.gyp index bb1c7f0a3a1..fd48da875a8 100644 --- a/binding.gyp +++ b/binding.gyp @@ -54,14 +54,18 @@ 'GRPC_UV' ] }], + ['runtime=="electron"', { + "defines": [ + 'OPENSSL_NO_THREADS' + ] + }], # This is the condition for using boringssl ['OS=="win" or runtime=="electron"', { "include_dirs": [ "third_party/boringssl/include" ], "defines": [ - 'OPENSSL_NO_ASM', - 'OPENSSL_NO_THREADS' + 'OPENSSL_NO_ASM' ] }, { # Based on logic above, we know that this must be a non-Windows system diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template index 9b9e4e116d0..7570aa5e7ee 100644 --- a/templates/binding.gyp.template +++ b/templates/binding.gyp.template @@ -56,14 +56,18 @@ 'GRPC_UV' ] }], + ['runtime=="electron"', { + "defines": [ + 'OPENSSL_NO_THREADS' + ] + }], # This is the condition for using boringssl ['OS=="win" or runtime=="electron"', { "include_dirs": [ "third_party/boringssl/include" ], "defines": [ - 'OPENSSL_NO_ASM', - 'OPENSSL_NO_THREADS' + 'OPENSSL_NO_ASM' ] }, { # Based on logic above, we know that this must be a non-Windows system From 24263c3f7a3b04f073712e40376829e47772d7db Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 11 Jan 2017 01:03:09 +0100 Subject: [PATCH 077/104] Fixing a few items with the new Bazel BUILD system: -) Fixing Bazel 0.4.x breakage -) Adding helloworld BUILD examples -) Fixing grpc++ missing files. -) Adding helloworld example as a test for Bazel basic. --- BUILD | 2 + bazel/BUILD | 8 +++- bazel/cc_grpc_library.bzl | 1 - bazel/generate_cc.bzl | 4 +- examples/cpp/helloworld/BUILD | 42 +++++++++++++++++ examples/cpp/helloworld/greeter_client.cc | 4 ++ examples/cpp/helloworld/greeter_server.cc | 4 ++ examples/protos/BUILD | 52 ++++++++++++++++++++++ tools/jenkins/run_bazel_basic_in_docker.sh | 2 +- 9 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 examples/cpp/helloworld/BUILD create mode 100644 examples/protos/BUILD diff --git a/BUILD b/BUILD index 3122dc0a321..2c9a6f35a17 100644 --- a/BUILD +++ b/BUILD @@ -1078,6 +1078,7 @@ grpc_cc_library( "src/cpp/common/completion_queue_cc.cc", "src/cpp/common/core_codegen.cc", "src/cpp/common/rpc_method.cc", + "src/cpp/common/version_cc.cc", "src/cpp/server/async_generic_service.cc", "src/cpp/server/create_default_thread_pool.cc", "src/cpp/server/dynamic_thread_pool.cc", @@ -1086,6 +1087,7 @@ grpc_cc_library( "src/cpp/server/server_context.cc", "src/cpp/server/server_credentials.cc", "src/cpp/server/server_posix.cc", + "src/cpp/thread_manager/thread_manager.cc", "src/cpp/util/byte_buffer_cc.cc", "src/cpp/util/slice_cc.cc", "src/cpp/util/status.cc", diff --git a/bazel/BUILD b/bazel/BUILD index 940a379404f..44a1673212e 100644 --- a/bazel/BUILD +++ b/bazel/BUILD @@ -2,8 +2,14 @@ package(default_visibility = ["//:__subpackages__"]) load(":cc_grpc_library.bzl", "cc_grpc_library") +proto_library( + name = "well_known_protos_list", + srcs = ["@submodule_protobuf//:well_known_protos"], +) + cc_grpc_library( name = "well_known_protos", - srcs = "@submodule_protobuf//:well_known_protos", + srcs = "well_known_protos_list", + deps = [], proto_only = True, ) diff --git a/bazel/cc_grpc_library.bzl b/bazel/cc_grpc_library.bzl index e1dd27b0c3f..9020eacb740 100644 --- a/bazel/cc_grpc_library.bzl +++ b/bazel/cc_grpc_library.bzl @@ -44,7 +44,6 @@ def cc_grpc_library(name, srcs, deps, proto_only, **kwargs): **kwargs ) - if not proto_only: native.cc_library( name = name, srcs = [":" + codegen_grpc_target, ":" + codegen_target], diff --git a/bazel/generate_cc.bzl b/bazel/generate_cc.bzl index 3665733681e..d49cbe8d728 100644 --- a/bazel/generate_cc.bzl +++ b/bazel/generate_cc.bzl @@ -24,13 +24,15 @@ def generate_cc_impl(ctx): if ctx.executable.plugin: arguments += ["--plugin=protoc-gen-PLUGIN=" + ctx.executable.plugin.path] arguments += ["--PLUGIN_out=" + ",".join(ctx.attr.flags) + ":" + dir_out] + additional_input = [ctx.executable.plugin] else: arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out] + additional_input = [] arguments += ["-I{0}={0}".format(include.path) for include in includes] arguments += [proto.path for proto in protos] ctx.action( - inputs = protos + includes, + inputs = protos + includes + additional_input, outputs = out_files, executable = ctx.executable._protoc, arguments = arguments, diff --git a/examples/cpp/helloworld/BUILD b/examples/cpp/helloworld/BUILD new file mode 100644 index 00000000000..b9c3f5dfbed --- /dev/null +++ b/examples/cpp/helloworld/BUILD @@ -0,0 +1,42 @@ +# Copyright 2017, 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. + +cc_binary( + name = "greeter_client", + srcs = ["greeter_client.cc"], + deps = ["//examples/protos:helloworld"], + defines = ["BAZEL_BUILD"], +) + +cc_binary( + name = "greeter_server", + srcs = ["greeter_server.cc"], + deps = ["//examples/protos:helloworld"], + defines = ["BAZEL_BUILD"], +) diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc index 61f3953056a..8ee33b1383b 100644 --- a/examples/cpp/helloworld/greeter_client.cc +++ b/examples/cpp/helloworld/greeter_client.cc @@ -37,7 +37,11 @@ #include +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else #include "helloworld.grpc.pb.h" +#endif using grpc::Channel; using grpc::ClientContext; diff --git a/examples/cpp/helloworld/greeter_server.cc b/examples/cpp/helloworld/greeter_server.cc index 9eab32c62b4..c8a6d8ae86a 100644 --- a/examples/cpp/helloworld/greeter_server.cc +++ b/examples/cpp/helloworld/greeter_server.cc @@ -37,7 +37,11 @@ #include +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else #include "helloworld.grpc.pb.h" +#endif using grpc::Server; using grpc::ServerBuilder; diff --git a/examples/protos/BUILD b/examples/protos/BUILD new file mode 100644 index 00000000000..2ffdf64f9af --- /dev/null +++ b/examples/protos/BUILD @@ -0,0 +1,52 @@ +# Copyright 2017, 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. + +package(default_visibility = ["//visibility:public"]) + +load("//bazel:grpc_build_system.bzl", "grpc_proto_library") + +grpc_proto_library( + name = "auth_sample", + srcs = ["auth_sample.proto"], +) + +grpc_proto_library( + name = "hellostreamingworld", + srcs = ["hellostreamingworld.proto"], +) + +grpc_proto_library( + name = "helloworld", + srcs = ["helloworld.proto"], +) + +grpc_proto_library( + name = "route_guide", + srcs = ["route_guide.proto"], +) diff --git a/tools/jenkins/run_bazel_basic_in_docker.sh b/tools/jenkins/run_bazel_basic_in_docker.sh index 51aaa90ff82..b1d498a07d3 100755 --- a/tools/jenkins/run_bazel_basic_in_docker.sh +++ b/tools/jenkins/run_bazel_basic_in_docker.sh @@ -39,4 +39,4 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc && git submodule update --init --reference /var/local/jenkins/grpc/${name} \ ${name}') cd /var/local/git/grpc -bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... +bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... examples/cpp/... From 93d0b580a51af6e9c099164424040dfd4d6a71f3 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Jan 2017 17:57:36 -0800 Subject: [PATCH 078/104] Properly generate electron dependencies in test Dockerfile from template --- .../test/node_jessie_x64/Dockerfile.template | 15 +++++++++++++-- .../dockerfile/test/node_jessie_x64/Dockerfile | 18 +++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template index 72b098f0c20..fa5c8c3816b 100644 --- a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template @@ -28,10 +28,21 @@ # 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. - + FROM debian:jessie - + <%include file="../../apt_get_basic.include"/> + + # Install Electron apt dependencies + RUN apt-get update && apt-get install -y ${'\\'} + libasound ${'\\'} + libgconf-2-4 ${'\\'} + libgtk2.0-0 ${'\\'} + libnss3 ${'\\'} + libxss1 ${'\\'} + libxtst6 ${'\\'} + xvfb + <%include file="../../python_deps.include"/> <%include file="../../node_deps.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile index 120ea59ae27..184298f9138 100644 --- a/tools/dockerfile/test/node_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile @@ -42,18 +42,12 @@ RUN apt-get update && apt-get install -y \ git \ golang \ gyp \ - libasound2 \ lcov \ libc6 \ libc6-dbg \ libc6-dev \ - libgconf-2-4 \ libgtest-dev \ - libgtk2.0-0 \ - libnss3 \ libtool \ - libxss1\ - libxtst6 \ make \ perl \ strace \ @@ -63,13 +57,23 @@ RUN apt-get update && apt-get install -y \ telnet \ unzip \ wget \ - xvfb \ zip && apt-get clean #================ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean + +# Install Electron apt dependencies +RUN apt-get update && apt-get install -y \ + libasound \ + libgconf-2-4 \ + libgtk2.0-0 \ + libnss3 \ + libxss1 \ + libxtst6 \ + xvfb + #==================== # Python dependencies From 06d3d4ad387a4fde43edafb8a8c218c3e5fc7fb1 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 13 Jan 2017 12:22:24 +0100 Subject: [PATCH 079/104] Makefile.template: remove the 'imp' suffix from MINGW library names --- Makefile | 26 +++++++++++++------------- templates/Makefile.template | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 1f25c3859f3..bec4f3172ce 100644 --- a/Makefile +++ b/Makefile @@ -2342,7 +2342,7 @@ install-shared_c: shared_c strip-shared_c install-pkg-config_c $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr-imp.a $(prefix)/lib/libgpr-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr.a $(prefix)/lib/libgpr.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.2 $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so @@ -2351,7 +2351,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc-imp.a $(prefix)/lib/libgrpc-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc.a $(prefix)/lib/libgrpc.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so @@ -2360,7 +2360,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet-imp.a $(prefix)/lib/libgrpc_cronet-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(prefix)/lib/libgrpc_cronet.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so @@ -2369,7 +2369,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure-imp.a $(prefix)/lib/libgrpc_unsecure-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(prefix)/lib/libgrpc_unsecure.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so @@ -2386,7 +2386,7 @@ install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-con $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++-imp.a $(prefix)/lib/libgrpc++-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so @@ -2395,7 +2395,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet-imp.a $(prefix)/lib/libgrpc++_cronet-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(prefix)/lib/libgrpc++_cronet.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so @@ -2404,7 +2404,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection-imp.a $(prefix)/lib/libgrpc++_reflection-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(prefix)/lib/libgrpc++_reflection.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so @@ -2413,7 +2413,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a $(prefix)/lib/libgrpc++_unsecure-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(prefix)/lib/libgrpc++_unsecure.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so @@ -2430,7 +2430,7 @@ install-shared_csharp: shared_csharp strip-shared_csharp $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a $(prefix)/lib/libgrpc_csharp_ext-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a $(prefix)/lib/libgrpc_csharp_ext.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so @@ -3947,7 +3947,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc else $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4322,7 +4322,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_cronet-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet else $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4445,7 +4445,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ else $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4837,7 +4837,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr-imp -lgrpc_unsecure-imp + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure else $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" diff --git a/templates/Makefile.template b/templates/Makefile.template index 230f16c0c89..6f4a2ed6440 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1305,7 +1305,7 @@ $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so.${settings.core_version.major} $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so @@ -1519,7 +1519,7 @@ assert dep_lib, 'lib %s not found (in %s)' % (dep, lib.name) link_libs = link_libs + ' -l' + dep lib_deps = lib_deps + ' $(LIBDIR)/$(CONFIG)/lib' + dep + '.$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' - mingw_libs = mingw_libs + ' -l' + dep + '-imp' + mingw_libs = mingw_libs + ' -l' + dep mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '$(SHARED_VERSION_' + lang_to_var[dep_lib.language] + ').$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' security = lib.get('secure', 'check') From 44b2d08149af2f976eca8b7fdb155543a101faaf Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 13 Jan 2017 12:35:49 +0100 Subject: [PATCH 080/104] Makefile.template: use import library names for mingw, instead of static libraries --- Makefile | 26 +++++++++++++------------- templates/Makefile.template | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index bec4f3172ce..504d06f4aed 100644 --- a/Makefile +++ b/Makefile @@ -2342,7 +2342,7 @@ install-shared_c: shared_c strip-shared_c install-pkg-config_c $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr.a $(prefix)/lib/libgpr.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgpr.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so.2 $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgpr.so @@ -2351,7 +2351,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc.a $(prefix)/lib/libgrpc.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc.so @@ -2360,7 +2360,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.a $(prefix)/lib/libgrpc_cronet.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_cronet.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_cronet.so @@ -2369,7 +2369,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/$(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(prefix)/lib/libgrpc_unsecure.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a $(prefix)/lib/libgrpc_unsecure.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(prefix)/lib/libgrpc_unsecure.so @@ -2386,7 +2386,7 @@ install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-con $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(prefix)/lib/libgrpc++.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so @@ -2395,7 +2395,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet.a $(prefix)/lib/libgrpc++_cronet.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_cronet.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so @@ -2404,7 +2404,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(prefix)/lib/libgrpc++_reflection.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_reflection.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so @@ -2413,7 +2413,7 @@ endif $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/$(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(prefix)/lib/libgrpc++_unsecure.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_unsecure.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so @@ -2430,7 +2430,7 @@ install-shared_csharp: shared_csharp strip-shared_csharp $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a $(prefix)/lib/libgrpc_csharp_ext.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.2 $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so @@ -3947,7 +3947,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc$(SHARED_VERSION_CORE)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4322,7 +4322,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4445,7 +4445,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++$(SHARED_VERSION_CPP)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(E) "[LD] Linking $@" @@ -4837,7 +4837,7 @@ ifeq ($(SYSTEM),MINGW32) $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll else $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(E) "[LD] Linking $@" diff --git a/templates/Makefile.template b/templates/Makefile.template index 6f4a2ed6440..6f4db26f2bf 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -1305,7 +1305,7 @@ $(Q) $(INSTALL) -d $(prefix)/lib $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/$(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) ifeq ($(SYSTEM),MINGW32) - $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.a $(prefix)/lib/lib${lib.name}.a + $(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]})-dll.a $(prefix)/lib/lib${lib.name}.a else ifneq ($(SYSTEM),Darwin) $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so.${settings.core_version.major} $(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so @@ -1519,7 +1519,7 @@ assert dep_lib, 'lib %s not found (in %s)' % (dep, lib.name) link_libs = link_libs + ' -l' + dep lib_deps = lib_deps + ' $(LIBDIR)/$(CONFIG)/lib' + dep + '.$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' - mingw_libs = mingw_libs + ' -l' + dep + mingw_libs = mingw_libs + ' -l' + dep + '$(SHARED_VERSION_' + lang_to_var[dep_lib.language] + ')-dll' mingw_lib_deps = mingw_lib_deps + ' $(LIBDIR)/$(CONFIG)/' + dep + '$(SHARED_VERSION_' + lang_to_var[dep_lib.language] + ').$(SHARED_EXT_' + lang_to_var[dep_lib.language] + ')' security = lib.get('secure', 'check') From 6fb04d6924b3714baa95b69d51fa40c082578124 Mon Sep 17 00:00:00 2001 From: Yuxuan Li Date: Fri, 18 Nov 2016 18:08:36 -0800 Subject: [PATCH 081/104] memory usage profiling for client call, client channel, server creation, server call and server channel. fix bug. server: snapshot pass by pointer --- Makefile | 104 ++++++ build.yaml | 37 ++ test/core/memory_usage/client.c | 314 +++++++++++++++++ test/core/memory_usage/memory_usage_test.c | 93 +++++ test/core/memory_usage/server.c | 321 ++++++++++++++++++ tools/doxygen/Doxyfile.c++ | 38 +-- tools/doxygen/Doxyfile.c++.internal | 36 +- tools/doxygen/Doxyfile.core | 34 +- tools/doxygen/Doxyfile.core.internal | 62 ++-- .../generated/sources_and_headers.json | 51 +++ tools/run_tests/generated/tests.json | 20 ++ vsprojects/buildtests_c.sln | 54 +++ .../memory_profile_client.vcxproj | 199 +++++++++++ .../memory_profile_client.vcxproj.filters | 21 ++ .../memory_profile_server.vcxproj | 199 +++++++++++ .../memory_profile_server.vcxproj.filters | 21 ++ 16 files changed, 1519 insertions(+), 85 deletions(-) create mode 100644 test/core/memory_usage/client.c create mode 100644 test/core/memory_usage/memory_usage_test.c create mode 100644 test/core/memory_usage/server.c create mode 100644 vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj create mode 100644 vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj.filters create mode 100644 vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj create mode 100644 vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj.filters diff --git a/Makefile b/Makefile index a26842e71b1..cfd53c69f71 100644 --- a/Makefile +++ b/Makefile @@ -1013,6 +1013,9 @@ lame_client_test: $(BINDIR)/$(CONFIG)/lame_client_test lb_policies_test: $(BINDIR)/$(CONFIG)/lb_policies_test load_file_test: $(BINDIR)/$(CONFIG)/load_file_test low_level_ping_pong_benchmark: $(BINDIR)/$(CONFIG)/low_level_ping_pong_benchmark +memory_profile_client: $(BINDIR)/$(CONFIG)/memory_profile_client +memory_profile_server: $(BINDIR)/$(CONFIG)/memory_profile_server +memory_profile_test: $(BINDIR)/$(CONFIG)/memory_profile_test message_compress_test: $(BINDIR)/$(CONFIG)/message_compress_test mlog_test: $(BINDIR)/$(CONFIG)/mlog_test multiple_server_queues_test: $(BINDIR)/$(CONFIG)/multiple_server_queues_test @@ -1348,6 +1351,9 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/lame_client_test \ $(BINDIR)/$(CONFIG)/lb_policies_test \ $(BINDIR)/$(CONFIG)/load_file_test \ + $(BINDIR)/$(CONFIG)/memory_profile_client \ + $(BINDIR)/$(CONFIG)/memory_profile_server \ + $(BINDIR)/$(CONFIG)/memory_profile_test \ $(BINDIR)/$(CONFIG)/message_compress_test \ $(BINDIR)/$(CONFIG)/mlog_test \ $(BINDIR)/$(CONFIG)/multiple_server_queues_test \ @@ -1739,6 +1745,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/lame_client_test || ( echo test lame_client_test failed ; exit 1 ) $(E) "[RUN] Testing load_file_test" $(Q) $(BINDIR)/$(CONFIG)/load_file_test || ( echo test load_file_test failed ; exit 1 ) + $(E) "[RUN] Testing memory_profile_test" + $(Q) $(BINDIR)/$(CONFIG)/memory_profile_test || ( echo test memory_profile_test failed ; exit 1 ) $(E) "[RUN] Testing message_compress_test" $(Q) $(BINDIR)/$(CONFIG)/message_compress_test || ( echo test message_compress_test failed ; exit 1 ) $(E) "[RUN] Testing multiple_server_queues_test" @@ -10290,6 +10298,102 @@ endif endif +MEMORY_PROFILE_CLIENT_SRC = \ + test/core/memory_usage/client.c \ + +MEMORY_PROFILE_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_CLIENT_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/memory_profile_client: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/memory_profile_client: $(MEMORY_PROFILE_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(MEMORY_PROFILE_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/memory_profile_client + +endif + +$(OBJDIR)/$(CONFIG)/test/core/memory_usage/client.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_memory_profile_client: $(MEMORY_PROFILE_CLIENT_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(MEMORY_PROFILE_CLIENT_OBJS:.o=.dep) +endif +endif + + +MEMORY_PROFILE_SERVER_SRC = \ + test/core/memory_usage/server.c \ + +MEMORY_PROFILE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_SERVER_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/memory_profile_server: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/memory_profile_server: $(MEMORY_PROFILE_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(MEMORY_PROFILE_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/memory_profile_server + +endif + +$(OBJDIR)/$(CONFIG)/test/core/memory_usage/server.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_memory_profile_server: $(MEMORY_PROFILE_SERVER_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(MEMORY_PROFILE_SERVER_OBJS:.o=.dep) +endif +endif + + +MEMORY_PROFILE_TEST_SRC = \ + test/core/memory_usage/memory_usage_test.c \ + +MEMORY_PROFILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(MEMORY_PROFILE_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/memory_profile_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/memory_profile_test: $(MEMORY_PROFILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(MEMORY_PROFILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/memory_profile_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/memory_usage/memory_usage_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_memory_profile_test: $(MEMORY_PROFILE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(MEMORY_PROFILE_TEST_OBJS:.o=.dep) +endif +endif + + MESSAGE_COMPRESS_TEST_SRC = \ test/core/compression/message_compress_test.c \ diff --git a/build.yaml b/build.yaml index 55aca52f680..0dbab7c55a5 100644 --- a/build.yaml +++ b/build.yaml @@ -2322,6 +2322,43 @@ targets: - mac - linux - posix +- name: memory_profile_client + build: test + run: false + language: c + src: + - test/core/memory_usage/client.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr +- name: memory_profile_server + build: test + run: false + language: c + src: + - test/core/memory_usage/server.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr +- name: memory_profile_test + cpu_cost: 1.5 + build: test + language: c + src: + - test/core/memory_usage/memory_usage_test.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + platforms: + - mac + - linux + - posix - name: message_compress_test build: test language: c diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c new file mode 100644 index 00000000000..9fc122b4c36 --- /dev/null +++ b/test/core/memory_usage/client.c @@ -0,0 +1,314 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/test_config.h" + +static grpc_channel *channel; +static grpc_completion_queue *cq; +static grpc_op metadata_ops[2]; +static grpc_op status_ops[2]; +static grpc_op snapshot_ops[6]; +static grpc_op *op; + +typedef struct { + grpc_call *call; + grpc_metadata_array initial_metadata_recv; + grpc_status_code status; + char *details; + size_t details_capacity; + grpc_metadata_array trailing_metadata_recv; +} fling_call; + +// Statically allocate call data structs. Enough to accomodate 10000 ping-pong +// calls and 1 extra for the snapshot calls. +static fling_call calls[10001]; + +static void *tag(intptr_t t) { return (void *)t; } + +// A call is intentionally divided into two steps. First step is to initiate a +// call (i.e send and recv metadata). A call is outstanding after we initated, +// so we can measure the call memory usage. +static void init_ping_pong_request(int call_idx) { + grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); + + memset(metadata_ops, 0, sizeof(metadata_ops)); + op = metadata_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &calls[call_idx].initial_metadata_recv; + op++; + + calls[call_idx].call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Reflector/reflectUnary", + "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, + metadata_ops, + (size_t)(op - metadata_ops), + tag(call_idx), NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +} + +// Second step is to finish the call (i.e recv status) and destroy the call. +static void finish_ping_pong_request(int call_idx) { + grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); + + memset(status_ops, 0, sizeof(status_ops)); + op = status_ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &calls[call_idx].trailing_metadata_recv; + op->data.recv_status_on_client.status = &calls[call_idx].status; + op->data.recv_status_on_client.status_details = &calls[call_idx].details; + op->data.recv_status_on_client.status_details_capacity = + &calls[call_idx].details_capacity; + op++; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, + status_ops, + (size_t)(op - status_ops), + tag(call_idx), NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); + gpr_free(calls[call_idx].details); + grpc_call_destroy(calls[call_idx].call); + calls[call_idx].call = NULL; +} + +static struct grpc_memory_counters send_snapshot_request( + int call_idx, const char *call_type) { + grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); + + grpc_byte_buffer *response_payload_recv = NULL; + memset(snapshot_ops, 0, sizeof(snapshot_ops)); + op = snapshot_ops; + + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &calls[call_idx].initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &response_payload_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &calls[call_idx].trailing_metadata_recv; + op->data.recv_status_on_client.status = &calls[call_idx].status; + op->data.recv_status_on_client.status_details = &calls[call_idx].details; + op->data.recv_status_on_client.status_details_capacity = + &calls[call_idx].details_capacity; + op++; + + calls[call_idx].call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, "localhost", + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( + calls[call_idx].call, snapshot_ops, + (size_t)(op - snapshot_ops), (void *)0, NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_byte_buffer_reader reader; + grpc_byte_buffer_reader_init(&reader, response_payload_recv); + grpc_slice response = grpc_byte_buffer_reader_readall(&reader); + + struct grpc_memory_counters snapshot; + snapshot.total_size_absolute = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_size_absolute; + snapshot.total_allocs_absolute = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_allocs_absolute; + snapshot.total_size_relative = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_size_relative; + snapshot.total_allocs_relative = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_allocs_relative; + + grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); + grpc_slice_unref(response); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(response_payload_recv); + gpr_free(calls[call_idx].details); + calls[call_idx].details = NULL; + calls[call_idx].details_capacity = 0; + grpc_call_destroy(calls[call_idx].call); + calls[call_idx].call = NULL; + + return snapshot; +} + +int main(int argc, char **argv) { + grpc_memory_counters_init(); + grpc_slice slice = grpc_slice_from_copied_string("x"); + char *fake_argv[1]; + + char *target = "localhost:443"; + gpr_cmdline *cl; + grpc_event event; + + grpc_init(); + + GPR_ASSERT(argc >= 1); + fake_argv[0] = argv[0]; + grpc_test_init(1, fake_argv); + + int warmup_iterations = 100; + int benchmark_iterations = 1000; + + cl = gpr_cmdline_create("memory profiling client"); + gpr_cmdline_add_string(cl, "target", "Target host:port", &target); + gpr_cmdline_add_int(cl, "warmup", "Warmup iterations", &warmup_iterations); + gpr_cmdline_add_int(cl, "benchmark", "Benchmark iterations", + &benchmark_iterations); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); k++) { + calls[k].details = NULL; + calls[k].details_capacity = 0; + } + + cq = grpc_completion_queue_create(NULL); + + struct grpc_memory_counters client_channel_start = + grpc_memory_counters_snapshot(); + channel = grpc_insecure_channel_create(target, NULL, NULL); + + int call_idx = 0; + + struct grpc_memory_counters before_server_create = + send_snapshot_request(0, "Reflector/GetBeforeSvrCreation"); + struct grpc_memory_counters after_server_create = + send_snapshot_request(0, "Reflector/GetAfterSvrCreation"); + + // warmup period + for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) { + init_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters server_benchmark_calls_start = + send_snapshot_request(0, "Reflector/SimpleSnapshot"); + + struct grpc_memory_counters client_benchmark_calls_start = + grpc_memory_counters_snapshot(); + + // benchmark period + for (; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) { + init_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters client_calls_inflight = + grpc_memory_counters_snapshot(); + + struct grpc_memory_counters server_calls_inflight = + send_snapshot_request(0, "Reflector/DestroyCalls"); + + do { + event = grpc_completion_queue_next( + cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(10000, GPR_TIMESPAN)), + NULL); + } while (event.type != GRPC_QUEUE_TIMEOUT); + + // second step - recv status and destroy call + for (call_idx = 0; call_idx < warmup_iterations + benchmark_iterations; + ++call_idx) { + finish_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters server_calls_end = + send_snapshot_request(0, "Reflector/SimpleSnapshot"); + + struct grpc_memory_counters client_channel_end = + grpc_memory_counters_snapshot(); + + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + + do { + event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + } while (event.type != GRPC_QUEUE_SHUTDOWN); + grpc_slice_unref(slice); + + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + + gpr_log(GPR_INFO, "---------client stats--------"); + gpr_log(GPR_INFO, "client call memory usage: %f bytes per call", + (double)(client_calls_inflight.total_size_relative - + client_benchmark_calls_start.total_size_relative) / + benchmark_iterations); + gpr_log(GPR_INFO, "client channel memory usage %zi bytes", + client_channel_end.total_size_relative - + client_channel_start.total_size_relative); + + gpr_log(GPR_INFO, "---------server stats--------"); + gpr_log(GPR_INFO, "server create: %zi bytes", + after_server_create.total_size_relative - + before_server_create.total_size_relative); + gpr_log(GPR_INFO, "server call memory usage: %f bytes per call", + (double)(server_calls_inflight.total_size_relative - + server_benchmark_calls_start.total_size_relative) / + benchmark_iterations); + gpr_log(GPR_INFO, "server channel memory usage %zi bytes", + server_calls_end.total_size_relative - + after_server_create.total_size_relative); + + grpc_memory_counters_destroy(); + return 0; +} diff --git a/test/core/memory_usage/memory_usage_test.c b/test/core/memory_usage/memory_usage_test.c new file mode 100644 index 00000000000..7e7a9d050da --- /dev/null +++ b/test/core/memory_usage/memory_usage_test.c @@ -0,0 +1,93 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include +#include +#include +#include +#include "src/core/lib/support/string.h" +#include "test/core/util/port.h" + +int main(int argc, char **argv) { + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + char *args[10]; + int status; + gpr_subprocess *svr, *cli; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* start the server */ + gpr_asprintf(&args[0], "%s/memory_profile_server%s", root, + gpr_subprocess_binary_extension()); + args[1] = "--bind"; + gpr_join_host_port(&args[2], "::", port); + args[3] = "--no-secure"; + svr = gpr_subprocess_create(4, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* start the client */ + gpr_asprintf(&args[0], "%s/memory_profile_client%s", root, + gpr_subprocess_binary_extension()); + args[1] = "--target"; + gpr_join_host_port(&args[2], "127.0.0.1", port); + args[3] = "--warmup=1000"; + args[4] = "--benchmark=9000"; + cli = gpr_subprocess_create(5, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* wait for completion */ + printf("waiting for client\n"); + if ((status = gpr_subprocess_join(cli))) { + gpr_subprocess_destroy(cli); + gpr_subprocess_destroy(svr); + return status; + } + gpr_subprocess_destroy(cli); + + gpr_subprocess_interrupt(svr); + status = gpr_subprocess_join(svr); + gpr_subprocess_destroy(svr); + return status; +} diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c new file mode 100644 index 00000000000..c0710930b07 --- /dev/null +++ b/test/core/memory_usage/server.c @@ -0,0 +1,321 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#ifndef _WIN32 +/* This is for _exit() below, which is temporary. */ +#include +#endif + +#include +#include +#include +#include +#include +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static grpc_completion_queue *cq; +static grpc_server *server; +static grpc_op metadata_ops[2]; +static grpc_op snapshot_ops[5]; +static grpc_op status_op; +static int got_sigint = 0; +static grpc_byte_buffer *payload_buffer = NULL; +static grpc_byte_buffer *terminal_buffer = NULL; +static int was_cancelled = 2; + +static void *tag(intptr_t t) { return (void *)t; } + +typedef enum { + FLING_SERVER_NEW_REQUEST = 1, + FLING_SERVER_SEND_INIT_METADATA, + FLING_SERVER_WAIT_FOR_DESTROY, + FLING_SERVER_SEND_STATUS_FLING_CALL, + FLING_SERVER_SEND_STATUS_SNAPSHOT, + FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL +} fling_server_tags; + +typedef struct { + fling_server_tags state; + grpc_call *call; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_metadata_array initial_metadata_send; +} fling_call; + +// hold up to 10000 calls and 6 snaphost calls +static fling_call calls[100006]; + +static void request_call_unary(int call_idx) { + if (call_idx == (int)(sizeof(calls) / sizeof(fling_call))) { + gpr_log(GPR_INFO, "Used all call slots (10000) on server. Server exit."); + _exit(0); + } + grpc_metadata_array_init(&calls[call_idx].request_metadata_recv); + grpc_server_request_call( + server, &calls[call_idx].call, &calls[call_idx].call_details, + &calls[call_idx].request_metadata_recv, cq, cq, &calls[call_idx]); +} + +static void send_initial_metadata_unary(void *tag) { + grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); + metadata_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; + metadata_ops[0].data.send_initial_metadata.count = 0; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, + metadata_ops, 1, tag, NULL)); +} + +static void send_status(void *tag) { + status_op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; + status_op.data.send_status_from_server.status = GRPC_STATUS_OK; + status_op.data.send_status_from_server.trailing_metadata_count = 0; + status_op.data.send_status_from_server.status_details = ""; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, + &status_op, 1, tag, NULL)); +} + +static void send_snapshot(void *tag, struct grpc_memory_counters *snapshot) { + grpc_op *op; + + grpc_slice snapshot_slice = + grpc_slice_new(snapshot, sizeof(*snapshot), gpr_free); + payload_buffer = grpc_raw_byte_buffer_create(&snapshot_slice, 1); + grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); + + op = snapshot_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &terminal_buffer; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + if (payload_buffer == NULL) { + gpr_log(GPR_INFO, "NULL payload buffer !!!"); + } + op->data.send_message = payload_buffer; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status_details = ""; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op++; + + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_batch((*(fling_call *)tag).call, snapshot_ops, + (size_t)(op - snapshot_ops), tag, NULL)); +} +/* We have some sort of deadlock, so let's not exit gracefully for now. + When that is resolved, please remove the #include above. */ +static void sigint_handler(int x) { _exit(0); } + +int main(int argc, char **argv) { + grpc_memory_counters_init(); + grpc_event ev; + char *addr_buf = NULL; + gpr_cmdline *cl; + int shutdown_started = 0; + int shutdown_finished = 0; + + int secure = 0; + char *addr = NULL; + + char *fake_argv[1]; + + GPR_ASSERT(argc >= 1); + fake_argv[0] = argv[0]; + grpc_test_init(1, fake_argv); + + grpc_init(); + srand((unsigned)clock()); + + cl = gpr_cmdline_create("fling server"); + gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); + gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + if (addr == NULL) { + gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); + addr = addr_buf; + } + gpr_log(GPR_INFO, "creating server on: %s", addr); + + cq = grpc_completion_queue_create(NULL); + + struct grpc_memory_counters before_server_create = + grpc_memory_counters_snapshot(); + if (secure) { + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( + NULL, &pem_key_cert_pair, 1, 0, NULL); + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + grpc_server_credentials_release(ssl_creds); + } else { + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); + } + + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + struct grpc_memory_counters after_server_create = + grpc_memory_counters_snapshot(); + + gpr_free(addr_buf); + addr = addr_buf = NULL; + + // initialize call instances + for (int i = 0; i < (int)(sizeof(calls) / sizeof(fling_call)); i++) { + grpc_call_details_init(&calls[i].call_details); + calls[i].state = FLING_SERVER_NEW_REQUEST; + } + + int next_call_idx = 0; + struct grpc_memory_counters current_snapshot; + + request_call_unary(next_call_idx); + + signal(SIGINT, sigint_handler); + + while (!shutdown_finished) { + if (got_sigint && !shutdown_started) { + gpr_log(GPR_INFO, "Shutting down due to SIGINT"); + grpc_server_shutdown_and_notify(server, cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_shutdown(cq); + shutdown_started = 1; + } + ev = grpc_completion_queue_next( + cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000000, GPR_TIMESPAN)), + NULL); + fling_call *s = ev.tag; + switch (ev.type) { + case GRPC_OP_COMPLETE: + switch (s->state) { + case FLING_SERVER_NEW_REQUEST: + request_call_unary(++next_call_idx); + if (0 == + strcmp(s->call_details.method, "/Reflector/reflectUnary")) { + s->state = FLING_SERVER_SEND_INIT_METADATA; + send_initial_metadata_unary(s); + } else if (0 == strcmp(s->call_details.method, + "Reflector/GetBeforeSvrCreation")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + send_snapshot(s, &before_server_create); + } else if (0 == strcmp(s->call_details.method, + "Reflector/GetAfterSvrCreation")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + send_snapshot(s, &after_server_create); + } else if (0 == strcmp(s->call_details.method, + "Reflector/SimpleSnapshot")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + current_snapshot = grpc_memory_counters_snapshot(); + send_snapshot(s, ¤t_snapshot); + } else if (0 == strcmp(s->call_details.method, + "Reflector/DestroyCalls")) { + s->state = FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL; + current_snapshot = grpc_memory_counters_snapshot(); + send_snapshot(s, ¤t_snapshot); + } else { + gpr_log(GPR_ERROR, "Wrong call method"); + } + break; + case FLING_SERVER_SEND_INIT_METADATA: + s->state = FLING_SERVER_WAIT_FOR_DESTROY; + break; + case FLING_SERVER_WAIT_FOR_DESTROY: + break; + case FLING_SERVER_SEND_STATUS_FLING_CALL: + grpc_call_destroy(s->call); + grpc_call_details_destroy(&s->call_details); + grpc_metadata_array_destroy(&s->initial_metadata_send); + grpc_metadata_array_destroy(&s->request_metadata_recv); + break; + case FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL: + for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); + ++k) { + if (calls[k].state == FLING_SERVER_WAIT_FOR_DESTROY) { + calls[k].state = FLING_SERVER_SEND_STATUS_FLING_CALL; + send_status(&calls[k]); + } + } + // no break here since we want to continue to case + // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call + case FLING_SERVER_SEND_STATUS_SNAPSHOT: + grpc_byte_buffer_destroy(payload_buffer); + grpc_byte_buffer_destroy(terminal_buffer); + grpc_call_destroy(s->call); + grpc_call_details_destroy(&s->call_details); + grpc_metadata_array_destroy(&s->initial_metadata_send); + grpc_metadata_array_destroy(&s->request_metadata_recv); + terminal_buffer = NULL; + payload_buffer = NULL; + break; + } + break; + case GRPC_QUEUE_SHUTDOWN: + GPR_ASSERT(shutdown_started); + shutdown_finished = 1; + break; + case GRPC_QUEUE_TIMEOUT: + break; + } + } + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + grpc_memory_counters_destroy(); + return 0; +} diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 6539f965658..225991781ed 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -848,34 +848,34 @@ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ +doc/wait-for-ready.md \ +doc/stress_test_framework.md \ doc/binary-logging.md \ +doc/load-balancing.md \ +doc/g_stands_for.md \ +doc/connectivity-semantics-and-api.md \ +doc/negative-http2-interop-test-descriptions.md \ doc/c-style-guide.md \ -doc/command_line_tool.md \ -doc/compression.md \ +doc/fail_fast.md \ +doc/PROTOCOL-WEB.md \ +doc/server_reflection_tutorial.md \ +doc/server-reflection.md \ +doc/naming.md \ doc/compression_cookbook.md \ +doc/health-checking.md \ +doc/http-grpc-status-mapping.md \ doc/connection-backoff-interop-test-description.md \ +doc/command_line_tool.md \ doc/connection-backoff.md \ -doc/connectivity-semantics-and-api.md \ doc/cpp-style-guide.md \ +doc/compression.md \ doc/environment_variables.md \ -doc/epoll-polling-engine.md \ -doc/fail_fast.md \ -doc/g_stands_for.md \ -doc/health-checking.md \ -doc/http-grpc-status-mapping.md \ -doc/interop-test-descriptions.md \ -doc/load-balancing.md \ -doc/naming.md \ -doc/negative-http2-interop-test-descriptions.md \ doc/PROTOCOL-HTTP2.md \ -doc/PROTOCOL-WEB.md \ -doc/server-reflection.md \ -doc/server_reflection_tutorial.md \ doc/statuscodes.md \ -doc/stress_test_framework.md \ -doc/wait-for-ready.md \ -doc/cpp/pending_api_cleanups.md \ -doc/cpp/perf_notes.md +doc/epoll-polling-engine.md \ +doc/interop-test-descriptions.md \ +doc/cpp/perf_notes.md \ +doc/cpp/pending_api_cleanups.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index ffef534fe27..2944b3ba38b 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -894,34 +894,34 @@ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ src/cpp/codegen/codegen_init.cc \ +doc/wait-for-ready.md \ +doc/stress_test_framework.md \ doc/binary-logging.md \ +doc/load-balancing.md \ +doc/g_stands_for.md \ +doc/connectivity-semantics-and-api.md \ +doc/negative-http2-interop-test-descriptions.md \ doc/c-style-guide.md \ -doc/command_line_tool.md \ -doc/compression.md \ +doc/fail_fast.md \ +doc/PROTOCOL-WEB.md \ +doc/server_reflection_tutorial.md \ +doc/server-reflection.md \ +doc/naming.md \ doc/compression_cookbook.md \ +doc/health-checking.md \ +doc/http-grpc-status-mapping.md \ doc/connection-backoff-interop-test-description.md \ +doc/command_line_tool.md \ doc/connection-backoff.md \ -doc/connectivity-semantics-and-api.md \ doc/cpp-style-guide.md \ +doc/compression.md \ doc/environment_variables.md \ -doc/epoll-polling-engine.md \ -doc/fail_fast.md \ -doc/g_stands_for.md \ -doc/health-checking.md \ -doc/http-grpc-status-mapping.md \ -doc/interop-test-descriptions.md \ -doc/load-balancing.md \ -doc/naming.md \ -doc/negative-http2-interop-test-descriptions.md \ doc/PROTOCOL-HTTP2.md \ -doc/PROTOCOL-WEB.md \ -doc/server-reflection.md \ -doc/server_reflection_tutorial.md \ doc/statuscodes.md \ -doc/stress_test_framework.md \ -doc/wait-for-ready.md \ -doc/cpp/pending_api_cleanups.md \ +doc/epoll-polling-engine.md \ +doc/interop-test-descriptions.md \ doc/cpp/perf_notes.md \ +doc/cpp/pending_api_cleanups.md \ src/cpp/README.md # This tag can be used to specify the character encoding of the source files diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index f8a3970416d..c6d7432e3f2 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -826,32 +826,32 @@ include/grpc/impl/codegen/sync.h \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ +doc/wait-for-ready.md \ +doc/stress_test_framework.md \ doc/binary-logging.md \ +doc/load-balancing.md \ +doc/g_stands_for.md \ +doc/connectivity-semantics-and-api.md \ +doc/negative-http2-interop-test-descriptions.md \ doc/c-style-guide.md \ -doc/command_line_tool.md \ -doc/compression.md \ +doc/fail_fast.md \ +doc/PROTOCOL-WEB.md \ +doc/server_reflection_tutorial.md \ +doc/server-reflection.md \ +doc/naming.md \ doc/compression_cookbook.md \ +doc/health-checking.md \ +doc/http-grpc-status-mapping.md \ doc/connection-backoff-interop-test-description.md \ +doc/command_line_tool.md \ doc/connection-backoff.md \ -doc/connectivity-semantics-and-api.md \ doc/cpp-style-guide.md \ +doc/compression.md \ doc/environment_variables.md \ -doc/epoll-polling-engine.md \ -doc/fail_fast.md \ -doc/g_stands_for.md \ -doc/health-checking.md \ -doc/http-grpc-status-mapping.md \ -doc/interop-test-descriptions.md \ -doc/load-balancing.md \ -doc/naming.md \ -doc/negative-http2-interop-test-descriptions.md \ doc/PROTOCOL-HTTP2.md \ -doc/PROTOCOL-WEB.md \ -doc/server-reflection.md \ -doc/server_reflection_tutorial.md \ doc/statuscodes.md \ -doc/stress_test_framework.md \ -doc/wait-for-ready.md \ +doc/epoll-polling-engine.md \ +doc/interop-test-descriptions.md \ doc/core/pending_api_cleanups.md # This tag can be used to specify the character encoding of the source files diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 1a945bec49f..e0d3dc535ba 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1281,54 +1281,54 @@ src/core/lib/support/tmpfile_msys.c \ src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_windows.c \ src/core/lib/support/wrap_memcpy.c \ +doc/wait-for-ready.md \ +doc/stress_test_framework.md \ doc/binary-logging.md \ +doc/load-balancing.md \ +doc/g_stands_for.md \ +doc/connectivity-semantics-and-api.md \ +doc/negative-http2-interop-test-descriptions.md \ doc/c-style-guide.md \ -doc/command_line_tool.md \ -doc/compression.md \ +doc/fail_fast.md \ +doc/PROTOCOL-WEB.md \ +doc/server_reflection_tutorial.md \ +doc/server-reflection.md \ +doc/naming.md \ doc/compression_cookbook.md \ +doc/health-checking.md \ +doc/http-grpc-status-mapping.md \ doc/connection-backoff-interop-test-description.md \ +doc/command_line_tool.md \ doc/connection-backoff.md \ -doc/connectivity-semantics-and-api.md \ doc/cpp-style-guide.md \ +doc/compression.md \ doc/environment_variables.md \ -doc/epoll-polling-engine.md \ -doc/fail_fast.md \ -doc/g_stands_for.md \ -doc/health-checking.md \ -doc/http-grpc-status-mapping.md \ -doc/interop-test-descriptions.md \ -doc/load-balancing.md \ -doc/naming.md \ -doc/negative-http2-interop-test-descriptions.md \ doc/PROTOCOL-HTTP2.md \ -doc/PROTOCOL-WEB.md \ -doc/server-reflection.md \ -doc/server_reflection_tutorial.md \ doc/statuscodes.md \ -doc/stress_test_framework.md \ -doc/wait-for-ready.md \ +doc/epoll-polling-engine.md \ +doc/interop-test-descriptions.md \ doc/core/pending_api_cleanups.md \ src/core/README.md \ +src/core/lib/README.md \ +src/core/lib/channel/README.md \ +src/core/lib/transport/README.md \ +src/core/lib/tsi/README.md \ +src/core/lib/iomgr/README.md \ +src/core/lib/surface/README.md \ src/core/ext/README.md \ +src/core/ext/transport/README.md \ +src/core/ext/transport/chttp2/README.md \ +src/core/ext/transport/chttp2/server/secure/README.md \ +src/core/ext/transport/chttp2/server/insecure/README.md \ +src/core/ext/transport/chttp2/transport/README.md \ +src/core/ext/transport/chttp2/client/secure/README.md \ +src/core/ext/transport/chttp2/client/insecure/README.md \ src/core/ext/census/README.md \ src/core/ext/census/gen/README.md \ src/core/ext/client_channel/README.md \ src/core/ext/resolver/README.md \ src/core/ext/resolver/dns/native/README.md \ -src/core/ext/resolver/sockaddr/README.md \ -src/core/ext/transport/README.md \ -src/core/ext/transport/chttp2/README.md \ -src/core/ext/transport/chttp2/client/insecure/README.md \ -src/core/ext/transport/chttp2/client/secure/README.md \ -src/core/ext/transport/chttp2/server/insecure/README.md \ -src/core/ext/transport/chttp2/server/secure/README.md \ -src/core/ext/transport/chttp2/transport/README.md \ -src/core/lib/README.md \ -src/core/lib/channel/README.md \ -src/core/lib/iomgr/README.md \ -src/core/lib/surface/README.md \ -src/core/lib/transport/README.md \ -src/core/lib/tsi/README.md +src/core/ext/resolver/sockaddr/README.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8849dcc600c..ea90f200b95 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1508,6 +1508,57 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "memory_profile_client", + "src": [ + "test/core/memory_usage/client.c" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "memory_profile_server", + "src": [ + "test/core/memory_usage/server.c" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "memory_profile_test", + "src": [ + "test/core/memory_usage/memory_usage_test.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index b76263b8b98..8b4427ba8ca 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1565,6 +1565,26 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.5, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "memory_profile_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [], "ci_platforms": [ diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index d08a47aa86e..f484f29a4b2 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -1202,6 +1202,28 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "load_file_test", "vcxproj\t {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memory_profile_client", "vcxproj\test\memory_profile_client\memory_profile_client.vcxproj", "{98C01DBE-EFFE-6988-0762-829DC88F0EB4}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memory_profile_server", "vcxproj\test\memory_profile_server\memory_profile_server.vcxproj", "{7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "message_compress_test", "vcxproj\test\message_compress_test\message_compress_test.vcxproj", "{07170557-CCB0-D23C-8018-C2909D115DF9}" ProjectSection(myProperties) = preProject lib = "False" @@ -3377,6 +3399,38 @@ Global {DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|Win32.Build.0 = Release|Win32 {DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|x64.ActiveCfg = Release|x64 {DC76C089-0D55-DF19-7CCA-49DAE5D29E49}.Release-DLL|x64.Build.0 = Release|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug|Win32.ActiveCfg = Debug|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug|x64.ActiveCfg = Debug|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release|Win32.ActiveCfg = Release|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release|x64.ActiveCfg = Release|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug|Win32.Build.0 = Debug|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug|x64.Build.0 = Debug|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release|Win32.Build.0 = Release|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release|x64.Build.0 = Release|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Debug-DLL|x64.Build.0 = Debug|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release-DLL|Win32.Build.0 = Release|Win32 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release-DLL|x64.ActiveCfg = Release|x64 + {98C01DBE-EFFE-6988-0762-829DC88F0EB4}.Release-DLL|x64.Build.0 = Release|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug|Win32.ActiveCfg = Debug|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug|x64.ActiveCfg = Debug|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release|Win32.ActiveCfg = Release|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release|x64.ActiveCfg = Release|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug|Win32.Build.0 = Debug|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug|x64.Build.0 = Debug|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release|Win32.Build.0 = Release|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release|x64.Build.0 = Release|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Debug-DLL|x64.Build.0 = Debug|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release-DLL|Win32.Build.0 = Release|Win32 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release-DLL|x64.ActiveCfg = Release|x64 + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC}.Release-DLL|x64.Build.0 = Release|x64 {07170557-CCB0-D23C-8018-C2909D115DF9}.Debug|Win32.ActiveCfg = Debug|Win32 {07170557-CCB0-D23C-8018-C2909D115DF9}.Debug|x64.ActiveCfg = Debug|x64 {07170557-CCB0-D23C-8018-C2909D115DF9}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj b/vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj new file mode 100644 index 00000000000..b955bcae37e --- /dev/null +++ b/vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {98C01DBE-EFFE-6988-0762-829DC88F0EB4} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + memory_profile_client + static + Debug + static + Debug + + + memory_profile_client + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj.filters b/vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj.filters new file mode 100644 index 00000000000..b250b538d12 --- /dev/null +++ b/vsprojects/vcxproj/test/memory_profile_client/memory_profile_client.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\memory_usage + + + + + + {4445c589-fe29-9a74-3b53-c83c7bac669e} + + + {8f263e3f-4f47-64ed-e45f-8f4385a6056d} + + + {2de23f1d-3faf-3318-2e31-b7cfa4a89220} + + + + diff --git a/vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj b/vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj new file mode 100644 index 00000000000..0b3c87997e1 --- /dev/null +++ b/vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj @@ -0,0 +1,199 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {7430B8AF-2A0E-EDF4-FD53-C8004DEE39EC} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + memory_profile_server + static + Debug + static + Debug + + + memory_profile_server + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj.filters b/vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj.filters new file mode 100644 index 00000000000..c95888e7a1c --- /dev/null +++ b/vsprojects/vcxproj/test/memory_profile_server/memory_profile_server.vcxproj.filters @@ -0,0 +1,21 @@ + + + + + test\core\memory_usage + + + + + + {0193b199-ddad-5387-8a4f-ab1e6c36b835} + + + {31db3ee2-d7ca-bedb-eacc-1bc7785dcae6} + + + {5b7c6ebd-9730-e59c-59bf-806a8b7ccda2} + + + + From 0748f3925cf0892b4780de25199bdd82aab30e57 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 13 Jan 2017 09:22:44 -0800 Subject: [PATCH 082/104] Store subchannel address in a channel arg. --- src/core/ext/client_channel/connector.h | 3 -- src/core/ext/client_channel/subchannel.c | 40 ++++++++++++++----- src/core/ext/client_channel/subchannel.h | 8 +++- .../ext/client_channel/subchannel_index.c | 12 ------ .../ext/lb_policy/pick_first/pick_first.c | 15 +++++-- .../ext/lb_policy/round_robin/round_robin.c | 15 +++++-- .../chttp2/client/chttp2_connector.c | 10 ++++- 7 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/core/ext/client_channel/connector.h b/src/core/ext/client_channel/connector.h index 3de061620e3..395f89b3b2c 100644 --- a/src/core/ext/client_channel/connector.h +++ b/src/core/ext/client_channel/connector.h @@ -48,9 +48,6 @@ struct grpc_connector { typedef struct { /** set of pollsets interested in this connection */ grpc_pollset_set *interested_parties; - /** address to connect to */ - const grpc_resolved_address *addr; - size_t addr_len; /** initial connect string to send */ grpc_slice initial_connect_string; /** deadline for connection */ diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c index 1bac82b4512..7a2ad984333 100644 --- a/src/core/ext/client_channel/subchannel.c +++ b/src/core/ext/client_channel/subchannel.c @@ -41,9 +41,12 @@ #include "src/core/ext/client_channel/client_channel.h" #include "src/core/ext/client_channel/initial_connect_string.h" +#include "src/core/ext/client_channel/parse_address.h" #include "src/core/ext/client_channel/subchannel_index.h" +#include "src/core/ext/client_channel/uri_parser.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -95,8 +98,6 @@ struct grpc_subchannel { size_t num_filters; /** channel arguments */ grpc_channel_args *args; - /** address to connect to */ - grpc_resolved_address *addr; grpc_subchannel_key *key; @@ -211,7 +212,6 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_subchannel *c = arg; gpr_free((void *)c->filters); grpc_channel_args_destroy(exec_ctx, c->args); - gpr_free(c->addr); grpc_slice_unref_internal(exec_ctx, c->initial_connect_string); grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker); grpc_connector_unref(exec_ctx, c->connector); @@ -327,12 +327,22 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, } else { c->filters = NULL; } - c->addr = gpr_malloc(sizeof(grpc_resolved_address)); - if (args->addr->len) - memcpy(c->addr, args->addr, sizeof(grpc_resolved_address)); c->pollset_set = grpc_pollset_set_create(); - grpc_set_initial_connect_string(&c->addr, &c->initial_connect_string); - c->args = grpc_channel_args_copy(args->args); + const grpc_arg *addr_arg = + grpc_channel_args_find(args->args, GRPC_ARG_SUBCHANNEL_ADDRESS); + GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. + grpc_resolved_address *addr = gpr_malloc(sizeof(*addr)); + grpc_uri_to_sockaddr(addr_arg->value.string, addr); + grpc_set_initial_connect_string(&addr, &c->initial_connect_string); + static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; + grpc_arg new_arg; + new_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; + new_arg.type = GRPC_ARG_STRING; + new_arg.value.string = grpc_sockaddr_to_uri(addr); + gpr_free(addr); + c->args = grpc_channel_args_copy_and_add_and_remove( + args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); + gpr_free(new_arg.value.string); c->root_external_state_watcher.next = c->root_external_state_watcher.prev = &c->root_external_state_watcher; grpc_closure_init(&c->connected, subchannel_connected, c, @@ -385,7 +395,6 @@ static void continue_connect_locked(grpc_exec_ctx *exec_ctx, grpc_connect_in_args args; args.interested_parties = c->pollset_set; - args.addr = c->addr; args.deadline = c->next_attempt; args.channel_args = c->args; args.initial_connect_string = c->initial_connect_string; @@ -771,3 +780,16 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack( grpc_subchannel_call *subchannel_call) { return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); } + +void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { + grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); + GPR_ASSERT(uri != NULL); + if (strcmp(uri->scheme, "ipv4") == 0) { + GPR_ASSERT(parse_ipv4(uri, addr)); + } else if (strcmp(uri->scheme, "ipv6") == 0) { + GPR_ASSERT(parse_ipv6(uri, addr)); + } else { + GPR_ASSERT(parse_unix(uri, addr)); + } + grpc_uri_destroy(uri); +} diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h index 24aa9f73dca..4cc33fc79bf 100644 --- a/src/core/ext/client_channel/subchannel.h +++ b/src/core/ext/client_channel/subchannel.h @@ -40,6 +40,9 @@ #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/metadata.h" +// Channel arg containing a grpc_resolved_address to connect to. +#define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" + /** A (sub-)channel that knows how to connect to exactly one target address. Provides a target for load balancing. */ typedef struct grpc_subchannel grpc_subchannel; @@ -164,8 +167,6 @@ struct grpc_subchannel_args { size_t filter_count; /** Channel arguments to be supplied to the newly created channel */ const grpc_channel_args *args; - /** Address to connect to */ - grpc_resolved_address *addr; }; /** create a subchannel given a connector */ @@ -173,4 +174,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_connector *connector, const grpc_subchannel_args *args); +/// Sets \a addr from \a uri_str. +void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr); + #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */ diff --git a/src/core/ext/client_channel/subchannel_index.c b/src/core/ext/client_channel/subchannel_index.c index 1ebe03ef119..11889300a2c 100644 --- a/src/core/ext/client_channel/subchannel_index.c +++ b/src/core/ext/client_channel/subchannel_index.c @@ -86,11 +86,6 @@ static grpc_subchannel_key *create_key( } else { k->args.filters = NULL; } - k->args.addr = gpr_malloc(sizeof(grpc_resolved_address)); - k->args.addr->len = args->addr->len; - if (k->args.addr->len > 0) { - memcpy(k->args.addr, args->addr, sizeof(grpc_resolved_address)); - } k->args.args = copy_channel_args(args->args); return k; } @@ -108,14 +103,8 @@ static int subchannel_key_compare(grpc_subchannel_key *a, grpc_subchannel_key *b) { int c = GPR_ICMP(a->connector, b->connector); if (c != 0) return c; - c = GPR_ICMP(a->args.addr->len, b->args.addr->len); - if (c != 0) return c; c = GPR_ICMP(a->args.filter_count, b->args.filter_count); if (c != 0) return c; - if (a->args.addr->len) { - c = memcmp(a->args.addr->addr, b->args.addr->addr, a->args.addr->len); - if (c != 0) return c; - } if (a->args.filter_count > 0) { c = memcmp(a->args.filters, b->args.filters, a->args.filter_count * sizeof(*a->args.filters)); @@ -129,7 +118,6 @@ void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx, grpc_connector_unref(exec_ctx, k->connector); gpr_free((grpc_channel_args *)k->args.filters); grpc_channel_args_destroy(exec_ctx, (grpc_channel_args *)k->args.args); - gpr_free(k->args.addr); gpr_free(k); } diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c index 821becff69d..4677fb23435 100644 --- a/src/core/ext/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/lb_policy/pick_first/pick_first.c @@ -36,7 +36,9 @@ #include #include "src/core/ext/client_channel/lb_policy_registry.h" +#include "src/core/ext/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" typedef struct pending_pick { @@ -466,11 +468,18 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, } memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - sc_args.addr = &addresses->addresses[i].address; - sc_args.args = args->args; - + grpc_arg addr_arg; + addr_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; + addr_arg.type = GRPC_ARG_STRING; + addr_arg.value.string = + grpc_sockaddr_to_uri(&addresses->addresses[i].address); + grpc_channel_args *new_args = + grpc_channel_args_copy_and_add(args->args, &addr_arg, 1); + gpr_free(addr_arg.value.string); + sc_args.args = new_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); + grpc_channel_args_destroy(exec_ctx, new_args); if (subchannel != NULL) { p->subchannels[subchannel_idx++] = subchannel; diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index cb679489c3e..3fe157a23c8 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -64,8 +64,10 @@ #include #include "src/core/ext/client_channel/lb_policy_registry.h" +#include "src/core/ext/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" +#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/static_metadata.h" @@ -729,11 +731,18 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, if (addresses->addresses[i].is_balancer) continue; memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - sc_args.addr = &addresses->addresses[i].address; - sc_args.args = args->args; - + grpc_arg addr_arg; + addr_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; + addr_arg.type = GRPC_ARG_STRING; + addr_arg.value.string = + grpc_sockaddr_to_uri(&addresses->addresses[i].address); + grpc_channel_args *new_args = + grpc_channel_args_copy_and_add(args->args, &addr_arg, 1); + gpr_free(addr_arg.value.string); + sc_args.args = new_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); + grpc_channel_args_destroy(exec_ctx, new_args); if (subchannel != NULL) { subchannel_data *sd = gpr_malloc(sizeof(*sd)); diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.c b/src/core/ext/transport/chttp2/client/chttp2_connector.c index 2c5dfaea601..ebe884b1158 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.c +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.c @@ -43,6 +43,7 @@ #include "src/core/ext/client_channel/connector.h" #include "src/core/ext/client_channel/http_connect_handshaker.h" +#include "src/core/ext/client_channel/subchannel.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" @@ -220,6 +221,11 @@ static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connect_out_args *result, grpc_closure *notify) { chttp2_connector *c = (chttp2_connector *)con; + const grpc_arg *addr_arg = + grpc_channel_args_find(args->channel_args, GRPC_ARG_SUBCHANNEL_ADDRESS); + GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. + grpc_resolved_address addr; + grpc_uri_to_sockaddr(addr_arg->value.string, &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == NULL); c->notify = notify; @@ -231,8 +237,8 @@ static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx, GPR_ASSERT(!c->connecting); c->connecting = true; grpc_tcp_client_connect(exec_ctx, &c->connected, &c->endpoint, - args->interested_parties, args->channel_args, - args->addr, args->deadline); + args->interested_parties, args->channel_args, &addr, + args->deadline); gpr_mu_unlock(&c->mu); } From 972b7975a6f25a76ef26aa9d2e7494c018a40e28 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Jan 2017 09:28:09 -0800 Subject: [PATCH 083/104] Fixed package name in dockerfile --- .../tools/dockerfile/test/node_jessie_x64/Dockerfile.template | 2 +- tools/dockerfile/test/node_jessie_x64/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template index fa5c8c3816b..ceaa9aa5abc 100644 --- a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template @@ -35,7 +35,7 @@ # Install Electron apt dependencies RUN apt-get update && apt-get install -y ${'\\'} - libasound ${'\\'} + libasound2 ${'\\'} libgconf-2-4 ${'\\'} libgtk2.0-0 ${'\\'} libnss3 ${'\\'} diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile index 184298f9138..7f93933ecac 100644 --- a/tools/dockerfile/test/node_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile @@ -66,7 +66,7 @@ RUN apt-get update && apt-get install -y time && apt-get clean # Install Electron apt dependencies RUN apt-get update && apt-get install -y \ - libasound \ + libasound2 \ libgconf-2-4 \ libgtk2.0-0 \ libnss3 \ From b19ac964876a694c58a2aa7527d456a765e85515 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Jan 2017 10:56:36 -0800 Subject: [PATCH 084/104] Fix electron artifact builds --- binding.gyp | 2 +- templates/binding.gyp.template | 2 +- tools/run_tests/artifacts/build_artifact_node.bat | 2 +- tools/run_tests/artifacts/build_artifact_node.sh | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/binding.gyp b/binding.gyp index fd48da875a8..d9461dbe00d 100644 --- a/binding.gyp +++ b/binding.gyp @@ -54,7 +54,7 @@ 'GRPC_UV' ] }], - ['runtime=="electron"', { + ['OS!="win" && runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' ] diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template index 7570aa5e7ee..b0585475ece 100644 --- a/templates/binding.gyp.template +++ b/templates/binding.gyp.template @@ -56,7 +56,7 @@ 'GRPC_UV' ] }], - ['runtime=="electron"', { + ['OS!="win" && runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' ] diff --git a/tools/run_tests/artifacts/build_artifact_node.bat b/tools/run_tests/artifacts/build_artifact_node.bat index f1a5b8aaaf3..0a2bc4b9d7d 100644 --- a/tools/run_tests/artifacts/build_artifact_node.bat +++ b/tools/run_tests/artifacts/build_artifact_node.bat @@ -51,7 +51,7 @@ for %%v in (%node_versions%) do ( ) for %%v in (%electron_versions%) do ( - call .\node_modules\.bin\node-pre-gyp.cmd configure rebuild package testpackage --runtime=electron --target=%%v --target_arch=%1 || goto :error + cmd /V /C "set "HOME=%HOMEDRIVE%%HOMEPATH%\electron-gyp" && call .\node_modules\.bin\node-pre-gyp.cmd configure rebuild package testpackage --runtime=electron --target=%%v --target_arch=%1 --disturl=https://atom.io/download/electron" || goto :error xcopy /Y /I /S build\stage\* artifacts\ || goto :error ) diff --git a/tools/run_tests/artifacts/build_artifact_node.sh b/tools/run_tests/artifacts/build_artifact_node.sh index bb662d25d45..47b1f339fb8 100755 --- a/tools/run_tests/artifacts/build_artifact_node.sh +++ b/tools/run_tests/artifacts/build_artifact_node.sh @@ -52,8 +52,8 @@ do cp -r build/stage/* artifacts/ done -for version in ${node_versions[@]} +for version in ${electron_versions[@]} do - HOME=~/.electron-gyp ./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --runtime=electron --target=$version --target_arch=$NODE_TARGET_ARCH + HOME=~/.electron-gyp ./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --runtime=electron --target=$version --target_arch=$NODE_TARGET_ARCH --disturl=https://atom.io/download/electron cp -r build/stage/* artifacts/ done From e8ec16da0ea70fd8d052d637e890af36cd91e951 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Jan 2017 11:00:53 -0800 Subject: [PATCH 085/104] Fix binding.gyp syntax --- binding.gyp | 2 +- templates/binding.gyp.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/binding.gyp b/binding.gyp index d9461dbe00d..479403ed218 100644 --- a/binding.gyp +++ b/binding.gyp @@ -54,7 +54,7 @@ 'GRPC_UV' ] }], - ['OS!="win" && runtime=="electron"', { + ['OS!="win" and runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' ] diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template index b0585475ece..851effc4f3d 100644 --- a/templates/binding.gyp.template +++ b/templates/binding.gyp.template @@ -56,7 +56,7 @@ 'GRPC_UV' ] }], - ['OS!="win" && runtime=="electron"', { + ['OS!="win" and runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' ] From df8f12203ce662860d514376af92c76237fd5b7f Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 13 Jan 2017 22:59:39 +0000 Subject: [PATCH 086/104] Fix API fuzzer tests. --- src/core/ext/client_channel/subchannel.c | 35 ++++++++++++++----- src/core/ext/client_channel/subchannel.h | 9 +++-- .../ext/lb_policy/pick_first/pick_first.c | 7 ++-- .../ext/lb_policy/round_robin/round_robin.c | 7 ++-- .../chttp2/client/chttp2_connector.c | 5 +-- 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c index 7a2ad984333..f9de9993b7b 100644 --- a/src/core/ext/client_channel/subchannel.c +++ b/src/core/ext/client_channel/subchannel.c @@ -38,6 +38,7 @@ #include #include +#include #include "src/core/ext/client_channel/client_channel.h" #include "src/core/ext/client_channel/initial_connect_string.h" @@ -328,21 +329,16 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, c->filters = NULL; } c->pollset_set = grpc_pollset_set_create(); - const grpc_arg *addr_arg = - grpc_channel_args_find(args->args, GRPC_ARG_SUBCHANNEL_ADDRESS); - GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. grpc_resolved_address *addr = gpr_malloc(sizeof(*addr)); - grpc_uri_to_sockaddr(addr_arg->value.string, addr); + grpc_get_subchannel_address_arg(args->args, addr); grpc_set_initial_connect_string(&addr, &c->initial_connect_string); static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS}; - grpc_arg new_arg; - new_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; - new_arg.type = GRPC_ARG_STRING; - new_arg.value.string = grpc_sockaddr_to_uri(addr); + grpc_arg new_arg = grpc_create_subchannel_address_arg(addr); gpr_free(addr); c->args = grpc_channel_args_copy_and_add_and_remove( args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1); gpr_free(new_arg.value.string); + c->root_external_state_watcher.next = c->root_external_state_watcher.prev = &c->root_external_state_watcher; grpc_closure_init(&c->connected, subchannel_connected, c, @@ -781,7 +777,7 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack( return SUBCHANNEL_CALL_TO_CALL_STACK(subchannel_call); } -void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { +static void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { grpc_uri *uri = grpc_uri_parse(uri_str, 0 /* suppress_errors */); GPR_ASSERT(uri != NULL); if (strcmp(uri->scheme, "ipv4") == 0) { @@ -793,3 +789,24 @@ void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr) { } grpc_uri_destroy(uri); } + +void grpc_get_subchannel_address_arg(const grpc_channel_args *args, + grpc_resolved_address *addr) { + const grpc_arg *addr_arg = + grpc_channel_args_find(args, GRPC_ARG_SUBCHANNEL_ADDRESS); + GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. + GPR_ASSERT(addr_arg->type == GRPC_ARG_STRING); + memset(addr, 0, sizeof(*addr)); + if (*addr_arg->value.string != '\0') { + grpc_uri_to_sockaddr(addr_arg->value.string, addr); + } +} + +grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { + grpc_arg new_arg; + new_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; + new_arg.type = GRPC_ARG_STRING; + new_arg.value.string = + addr->len > 0 ? grpc_sockaddr_to_uri(addr) : gpr_strdup(""); + return new_arg; +} diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h index 4cc33fc79bf..c7a9577ce99 100644 --- a/src/core/ext/client_channel/subchannel.h +++ b/src/core/ext/client_channel/subchannel.h @@ -174,7 +174,12 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_connector *connector, const grpc_subchannel_args *args); -/// Sets \a addr from \a uri_str. -void grpc_uri_to_sockaddr(char *uri_str, grpc_resolved_address *addr); +/// Sets \a addr from \a args. +void grpc_get_subchannel_address_arg(const grpc_channel_args *args, + grpc_resolved_address *addr); + +/// Returns a new channel arg encoding the subchannel address as a string. +/// Caller is responsible for freeing the string. +grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr); #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */ diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c index 4677fb23435..9f2aa461bed 100644 --- a/src/core/ext/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/lb_policy/pick_first/pick_first.c @@ -468,11 +468,8 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, } memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - grpc_arg addr_arg; - addr_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; - addr_arg.type = GRPC_ARG_STRING; - addr_arg.value.string = - grpc_sockaddr_to_uri(&addresses->addresses[i].address); + grpc_arg addr_arg = + grpc_create_subchannel_address_arg(&addresses->addresses[i].address); grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args->args, &addr_arg, 1); gpr_free(addr_arg.value.string); diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c index 3fe157a23c8..d17d8fa057a 100644 --- a/src/core/ext/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/lb_policy/round_robin/round_robin.c @@ -731,11 +731,8 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, if (addresses->addresses[i].is_balancer) continue; memset(&sc_args, 0, sizeof(grpc_subchannel_args)); - grpc_arg addr_arg; - addr_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; - addr_arg.type = GRPC_ARG_STRING; - addr_arg.value.string = - grpc_sockaddr_to_uri(&addresses->addresses[i].address); + grpc_arg addr_arg = + grpc_create_subchannel_address_arg(&addresses->addresses[i].address); grpc_channel_args *new_args = grpc_channel_args_copy_and_add(args->args, &addr_arg, 1); gpr_free(addr_arg.value.string); diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.c b/src/core/ext/transport/chttp2/client/chttp2_connector.c index ebe884b1158..013c96dc703 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.c +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.c @@ -221,11 +221,8 @@ static void chttp2_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connect_out_args *result, grpc_closure *notify) { chttp2_connector *c = (chttp2_connector *)con; - const grpc_arg *addr_arg = - grpc_channel_args_find(args->channel_args, GRPC_ARG_SUBCHANNEL_ADDRESS); - GPR_ASSERT(addr_arg != NULL); // Should have been set by LB policy. grpc_resolved_address addr; - grpc_uri_to_sockaddr(addr_arg->value.string, &addr); + grpc_get_subchannel_address_arg(args->channel_args, &addr); gpr_mu_lock(&c->mu); GPR_ASSERT(c->notify == NULL); c->notify = notify; From 92c93b99a0a46b7112288ca138df7e772a0431f0 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 13 Jan 2017 15:07:57 -0800 Subject: [PATCH 087/104] Ran generate_projects.sh. --- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core | 2 ++ tools/doxygen/Doxyfile.core.internal | 2 ++ 4 files changed, 6 insertions(+) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index fa9b7057c57..84daed1041c 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -866,6 +866,7 @@ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/port_platform.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index bca5652a463..37e4ad3f373 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -867,6 +867,7 @@ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/grpc_types.h \ include/grpc/impl/codegen/port_platform.h \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index ccbfe3a4e66..da990379ce4 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -807,6 +807,8 @@ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ +include/grpc/impl/codegen/gpr_slice.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/grpc_types.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index fc8fac32f0d..4591aa50e3c 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -807,6 +807,8 @@ include/grpc/impl/codegen/byte_buffer_reader.h \ include/grpc/impl/codegen/compression_types.h \ include/grpc/impl/codegen/connectivity_state.h \ include/grpc/impl/codegen/exec_ctx_fwd.h \ +include/grpc/impl/codegen/gpr_slice.h \ +include/grpc/impl/codegen/gpr_slice.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/gpr_types.h \ include/grpc/impl/codegen/grpc_types.h \ From 4242075c335473f8c3fc0b578196bdc878a3b9df Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 13 Jan 2017 15:23:11 -0800 Subject: [PATCH 088/104] PHP: Prepare for 1.1.0 release --- package.xml | 46 ++++++++++++++++++++++++++++------ src/php/README.md | 7 ++++++ templates/package.xml.template | 46 ++++++++++++++++++++++++++++------ 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/package.xml b/package.xml index 4df15258275..ac5bcc54bf6 100644 --- a/package.xml +++ b/package.xml @@ -10,19 +10,20 @@ grpc-packages@google.com yes - 2016-08-22 + 2017-01-13 1.1.0dev 1.1.0dev - stable - stable + beta + beta BSD -- Reject metadata keys which are not legal #7881 +- PHP Proto3 adoption #8179 +- Various bug fixes

@@ -1215,18 +1216,49 @@ Update to wrap gRPC C Core version 0.10.0 - 1.1.0dev - 1.1.0dev + 1.0.1RC1 + 1.0.1RC1 + + + beta + beta + + 2016-10-06 + BSD + +- Reject metadata keys which are not legal #7881 + + + + + 1.0.1 + 1.0.1 stable stable - 2016-08-22 + 2016-10-27 BSD - Reject metadata keys which are not legal #7881 + + + 1.1.0dev + 1.1.0dev + + + beta + beta + + 2017-01-13 + BSD + +- PHP Proto3 adoption #8179 +- Various bug fixes + + diff --git a/src/php/README.md b/src/php/README.md index 1b15768d44a..320220d3e4a 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -163,6 +163,13 @@ of this repo. The plugin can be found in the `bins/opt` directory. We are planning to provide a better way to download and install the plugin in the future. +You can also just build the gRPC PHP protoc plugin by running: + +```sh +$ cd grpc +$ make grpc_php_plugin +``` + ### Client Stub diff --git a/templates/package.xml.template b/templates/package.xml.template index 32ed3b633e8..80f1a1fe974 100644 --- a/templates/package.xml.template +++ b/templates/package.xml.template @@ -12,19 +12,20 @@ grpc-packages@google.com yes - 2016-08-22 + 2017-01-13 ${settings.php_version.php()} ${settings.php_version.php()} - stable - stable + beta + beta BSD - - Reject metadata keys which are not legal #7881 + - PHP Proto3 adoption #8179 + - Various bug fixes @@ -281,18 +282,49 @@ - ${settings.php_version.php()} - ${settings.php_version.php()} + 1.0.1RC1 + 1.0.1RC1 + + + beta + beta + + 2016-10-06 + BSD + + - Reject metadata keys which are not legal #7881 + + + + + 1.0.1 + 1.0.1 stable stable - 2016-08-22 + 2016-10-27 BSD - Reject metadata keys which are not legal #7881 + + + 1.1.0dev + 1.1.0dev + + + beta + beta + + 2017-01-13 + BSD + + - PHP Proto3 adoption #8179 + - Various bug fixes + + From 0a5a31868a3166fd4e5b5581def5630e09e675a1 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 13 Jan 2017 16:54:03 -0800 Subject: [PATCH 089/104] Name constant --- src/core/ext/transport/chttp2/transport/chttp2_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 339d2138c65..68a6a2155dd 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -62,7 +62,7 @@ #define DEFAULT_WINDOW 65535 #define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024) #define MAX_WINDOW 0x7fffffffu - +#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024) #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024) #define MAX_CLIENT_STREAM_ID 0x7fffffffu @@ -326,7 +326,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) { t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer( &channel_args->args[i], - (grpc_integer_options){0, 0, 64 * 1024 * 1024}); + (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE}); } else { static const struct { const char *channel_arg_name; From c1002c9f22e7bddc9d71831a6c20e0cb844f7846 Mon Sep 17 00:00:00 2001 From: Matt Kwong Date: Fri, 13 Jan 2017 17:26:11 -0800 Subject: [PATCH 090/104] Add api-fuzzer corpus --- .../08455b3ef9d516deb8155d8db7d51c43ce0ff07a | Bin 0 -> 426 bytes .../0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 | Bin 0 -> 167 bytes .../14064ac4844c709b247a4345a92d8be9766785c4 | Bin 0 -> 316 bytes .../1901234bd7c9cb6ee19ff8b17179c481bdc7c5f2 | Bin 0 -> 345 bytes .../20ff1f8d5d34cb01d58aa334dc46a6644e6e1d12 | Bin 0 -> 199 bytes .../2378c3f1206f20711468391ce739116ffe58374b | Bin 0 -> 216 bytes .../40640a91fda4e4e42d3063a28b9ffbba1b8c3701 | Bin 0 -> 226 bytes .../49f564289c79de9e0342f8b0821a167bc8c5ec00 | Bin 0 -> 183 bytes .../507865c4a5ce880b80400d93fa85def2682581cb | Bin 0 -> 314 bytes .../5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 | Bin 0 -> 349 bytes .../61de97a9d6c4b082602c02277d8d763921f5f95b | Bin 0 -> 175 bytes .../62b039b8a318cc08471f13629da08c68c414d8e7 | Bin 0 -> 176 bytes .../641739453f7d4d3b55a1c7b79bed7da6dfd62ae0 | Bin 0 -> 175 bytes .../6589505362ffb5164a3c7cb1b9feadcddfba44e9 | Bin 0 -> 33 bytes .../724f5400f19e5a0be97022341c39eeaaaffeb390 | Bin 0 -> 336 bytes .../7254b9ff59ab3fcf345effdabbc25ebd2e907b23 | Bin 0 -> 167 bytes .../784d6f5c093ab5360670173ce001e1a446f95822 | Bin 0 -> 202 bytes .../79328fdc89d0af0e38da089dab062fd3ea5aae59 | Bin 0 -> 474 bytes .../7a2569f4daf4480ad142cb4ee7c675bed82db74c | Bin 0 -> 547 bytes .../87a300cd25d2e57745bd00499d4d2352a10a2fa1 | Bin 0 -> 35 bytes .../8a1c629910280f8beebb88687696de98da988ecc | Bin 0 -> 41 bytes .../8ff7b1568d2da2e4196c2e28617e1911d62021e6 | Bin 0 -> 371 bytes .../982f375b183d984958667461c7767206062eb4cb | Bin 0 -> 429 bytes .../98739af631223fa05ad88f1e63a52052a9bb4b1c | Bin 0 -> 178 bytes .../a78bca1ef8829d720dd5dedac3a9d4d12684da34 | Bin 0 -> 373 bytes .../ac763d89466ebfad676e75be0076831c03fe2a5d | Bin 0 -> 473 bytes .../b165523f699e6ae9b2ad15873b9d56465d1af546 | Bin 0 -> 224 bytes .../b2a5ec3ef40c68d594638218e3c943a479f82215 | Bin 0 -> 474 bytes .../b92b1c5e0dba009a9516e7185f5df019c62c5cc9 | Bin 0 -> 414 bytes .../c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 | Bin 0 -> 425 bytes ...h-da39a3ee5e6b4b0d3255bfef95601890afd80709 | 0 .../e28ffd8c2816f12f6395805199c792d1718191df | Bin 0 -> 371 bytes .../ec823f4018389e64a99f6580277fba28df6bd136 | Bin 0 -> 226 bytes .../ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 | Bin 0 -> 338 bytes .../ee6855178435d2046d8763ecae46e1e0a71a95f4 | Bin 0 -> 178 bytes .../eeb310d91038cb02862e187e68c5d6578233485b | Bin 0 -> 46 bytes .../f07bc2907c95f2aeb79ca60e2ad826e13b848f45 | Bin 0 -> 351 bytes .../fb655905396b768cf3ff015afdb0b564dae2cdfd | Bin 0 -> 349 bytes .../fdb038087233cd176746558875932029f779221d | Bin 0 -> 371 bytes tools/run_tests/generated/tests.json | 932 +++++++++++++++++- 40 files changed, 895 insertions(+), 37 deletions(-) create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/14064ac4844c709b247a4345a92d8be9766785c4 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/1901234bd7c9cb6ee19ff8b17179c481bdc7c5f2 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/20ff1f8d5d34cb01d58aa334dc46a6644e6e1d12 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/2378c3f1206f20711468391ce739116ffe58374b create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/49f564289c79de9e0342f8b0821a167bc8c5ec00 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/61de97a9d6c4b082602c02277d8d763921f5f95b create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/641739453f7d4d3b55a1c7b79bed7da6dfd62ae0 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/6589505362ffb5164a3c7cb1b9feadcddfba44e9 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/724f5400f19e5a0be97022341c39eeaaaffeb390 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/79328fdc89d0af0e38da089dab062fd3ea5aae59 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/8a1c629910280f8beebb88687696de98da988ecc create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/8ff7b1568d2da2e4196c2e28617e1911d62021e6 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/a78bca1ef8829d720dd5dedac3a9d4d12684da34 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/b2a5ec3ef40c68d594638218e3c943a479f82215 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/ec823f4018389e64a99f6580277fba28df6bd136 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/ee6855178435d2046d8763ecae46e1e0a71a95f4 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/eeb310d91038cb02862e187e68c5d6578233485b create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/f07bc2907c95f2aeb79ca60e2ad826e13b848f45 create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd create mode 100644 test/core/end2end/fuzzers/api_fuzzer_corpus/fdb038087233cd176746558875932029f779221d diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a b/test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a new file mode 100644 index 0000000000000000000000000000000000000000..4b698ba9ee26c4cd200fcbdc446d61490dafbd70 GIT binary patch literal 426 zcmZutJx;?g6#neANgz=db|fYcLp!n13vdf7G;UQX#L;t-iixEIOk98~^a>oN$EXnI zIRP~wEWPD@fA6!jnp#c32&b4W&D>c1#tSL`0KE6a6;+~}3#xuoF3mTk$EjLOtu0hW zD_yHHd(g_Tp4PdBo!U>gC{&%%yY|=-dUfvUEJ=egB>0Va#Nh>q1$sZ${AQBjo>TR^&`3x2qGEE*^T~S!L$F9uG5cPj5ZTZ zrYUnp=6)?8LtjANCh2*rClrU9t826ZB4*cs#}lGCkfZ|SxbJok=fsv%gZ&OCF`^yr F@CB$9iKhSn literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 new file mode 100644 index 0000000000000000000000000000000000000000..2889e7040e8eaf3d989ac735a1f866b4fef66b9f GIT binary patch literal 167 zcmZQ7PAw`+En;9`Vc=rWSI^If@EOyK3P3nnuedlTKCvo2wIn_-F*h|nAE>xUGczTX zp;)i@-~Z&C_>#mTs4PShB-j7{|Nl_NdTt(OCI(gpFkt-E$-}_Fc$9@fn4O6&l}Xv) wzkRTNM-dZSIbSMAQJIDoLm6Yyf1r|dUg!cAtJxD|r@XJuJxCeF<- zF}06mW;rn@BSO~8eteu7XL(G{1oPi}^WHzTb{jPrP*PcO_5BjQaNdIk+{Te=0-vNC z;s&*CsU%AXhWe5;eCH^Ks7iDWQ7@ix;5EcYQN4OP9$eg>uUV>PlQid17r9^`<`mUN zJ0-p5yQu5K#ClPkZJ~uIPd!0i=Q@4?gGq_&Z~pWl)Z#WC8lv#Pl%FyEo0{KHhZVT$WgwbCKNHTTb#&EVG+y zhMTxgpJqw%>vm@F{4>12qKBQqu&1zw<)QbdAwVyEZ0m}Rlxn0a&%Je}S?!C23wP7FCgmw>Y9g+SJjhCpQ(eT+p ly0EL%vv2D2*B|N_$!Y|V@?RDWLS4Gx4TA3pQjfUFamM1UU6|wd}2|0YDs)vVs2`D zK2S$;Mq*xGYEFD{Nn&z#d{Sv{{$FNx!?Ja&XlQ)?^ zGf@<LFC9L4vo?Pdn~41iy$C|yvdiTp$4zR TFY8(xuH(YYX3{a;wz_=)JcdB; literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701 b/test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701 new file mode 100644 index 0000000000000000000000000000000000000000..f11821acc9a961be2847021d76fabc0f07f5bea6 GIT binary patch literal 226 zcmZvVJ8r^26h-fh5nqdjB~XAUfEo%&M~|pS6Z^?n*kknkK{QE25f;NTvJo0~kRpxq zkW$jz;(pH6IdMe{r6N8C)0~3Lg_h5zl)%`CTmcQBfi7mFEE8AyZx3nzFY?4#j;Jus zrerdK1$*lpB_=Oya4_#>oP_dVQ{xs?aU9xXjJn>b&q2@kG?d`6ev10N`l8jr64~uuY@5!&kCqJGbJ&T;s5_o#(H6H9%d#6#ttS11_lQp zh6Bc5ojeRY3=E7%Ss0kvnb=a9lnt!ygY`R#nApnsQaOssG_)AX7>oV`m9%_&1T@Wx Sv4xT05r-z{T86a@9t;3_wlwYl literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb new file mode 100644 index 0000000000000000000000000000000000000000..c4473eacbb20789a2fb08b49a3affb734ee8e81f GIT binary patch literal 314 zcmXw!u}T9$6h-e$WSwY;NWj`4$Qno_ZJM<9g6%NbJd?$B6W>fWq_Wu}*!U4*xj*5L z2n+s%h2t#Zs~-0h=iW0J0TANUtW!v_;B_*Z)4kbbPMeKet~hl&g!m6xo9U%<>oIck zNP1Whb2=y3k^S*Wrk&vhIUS&0{j*o^{d4cQ(~`j?BO|_nR(PA6av$eW7x*OA5hrLx zQsPiZW<+0-X73yqjXfD9l-nl@1@TeVFP<)@!%V^sr#qj`zU>}y0brW6Dp6}v8 zGpcOEN2rGf=phcuqYB=OQnj(|DwyB;LzCZ1nNov MZG{Rqcmvb~zi}X0q5uE@ literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 new file mode 100644 index 0000000000000000000000000000000000000000..b91a052534a42714136e08b8481e1cc6604783b1 GIT binary patch literal 349 zcmZ9GJxjw-6o%h(TVt#xi{R)74hlNd!F|^reLX9fG&C%53)=)GsTq0B6&0_it8Yhn9CpymmFle99@NJ z$`s2`V~(=)GL%(tqfJ2=b6Nu5*4hQ#?d|qETOe#6eLeO8dg-FGZ5%cyli7UyAja7@ zj{dKA$e^ROdNr41`LC1^3p6rg2bKww`DjhQdMbSDu`8AD4^fHwq#Tt=m6WTXD8rKR zr=?bwXL5Yxc!0dK-gDms&WGWPCuK>fCbWJgj5QD#aiL;wH(|3ew;g}Hf{nHU%u85kH#7$AW0 zS0@jUdz6KNnVpF(l}Xv)zkRTNM-dZSIbSMAQJIDoLm6Yyf1r|dnVPtr; NmVuLlVJ(9P0{}^oHBJBk literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7 new file mode 100644 index 0000000000000000000000000000000000000000..e5e218acc372b72f89d20710875377e0a1ff8da9 GIT binary patch literal 176 zcmZQ7PAw`+En;9`Vc=rWSI^If@EOyK3P3nnuehirH9kGDI43?YF*h|nAE-DvBQY;8 zH7CBfBr(Y}GAB8^GzDlvVlG&+C^IFMq5uE?|DlZa!rVN}Obm<+V89BY7=K;rgj5QD#aiL;wH(|3ew;g}Hf{nHU%u85kH#KnMsJ ze|7Qz$)hX`%+?)3b5mP|ngXrl+O8D^U-du9=u{64<5iBu+ZGS!MQDvXII1nb*t6(rK}ig>5A z%(&9TYqg9~RpqEZXnE-1@x)~h3|9k>li=~WIPmp&D>YfGLXrukp^H$6bHyjS6IY0x t_~ir*kJ9w|^X-}c1x3!~_yvJM$1jj-fKZD}S&L2wbf-9A!9sygx&ch5YXJZN literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23 new file mode 100644 index 0000000000000000000000000000000000000000..92371e031fd5a3a16eb92dcc275eff45ee322ad8 GIT binary patch literal 167 zcmZQ7PAw`+En;9`Vc=rWSI^HcP6zQB(~Al~I9ac_I47|vK0UQ0J})shH9j9GnU& literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822 b/test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822 new file mode 100644 index 0000000000000000000000000000000000000000..79885b7f2a89ad24923574be3e4f35e300028aee GIT binary patch literal 202 zcmXYqy$%6E6ot>775~wA1O-u`)`(6o>dDx>Sz>oq?yeP;MnUCCJcbwX5DLwhgp-`& zBwxOxa+Z<>sGx~)Kg)i59?PD5!%?0m+DOcWwkBnrc{tn{YdO(*VZxnWAGS&44JOrg z$|Bo{ad*zG=-h3!0|g@B@8U4Ck&%-=_#16vwgsrbFZ8*!J^8F4sHrNe-o(w81weEm2?-)ZCoaGhat0;_ zu91ZsFm%8?TSTI}tB6(x^u*z`6@XZQx6vn<5x$&4=&Q0js_Y>&JF1@fZ+$BEv^>eIvh z!-Bz(+TwBd=y-BIev#C^+Z2wh`~WH%@tWty^@3KcirgR7SLM?>|J!${piYXO>|wHlihA zO`vVSbqMfjtmPd5kw8)TrHO=tCqGa)-~ST*3er9e1LLS$w~h7eI^ZI^4jK#K41NK} C*OFTR literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c b/test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c new file mode 100644 index 0000000000000000000000000000000000000000..75b55e7e107328f55f696cc1053637e8f9b78ed8 GIT binary patch literal 547 zcmZuuJ5Iwu6r5crj=@$M`bbnDilm|m7vL6_v7dt_V_WM_L`9PVDlWhYka7hMlVe1P z<*l87R$yt1-I+I^XQ{R7NC6|9Vv&|NWleAVAZ1M!!0+b1QkCe>xvFf+MR}kMxT@lL zUFTt>R@8(=^gvb4i{=Hnx#+-u~N>JQXh-G2lG7!m4wo$&6_Z41&}q5=v%;67`- zW+`U+{WvW~>nW+SEs{``cbR~6O#`{~gIPyY<+~*LAulukbtG2zl9%_%j;wLrY`=}@==Qu#0xX;67zX1j|vuFSS literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1 new file mode 100644 index 0000000000000000000000000000000000000000..c8f79862bc3c1721fbcccce5198bfe48ea3d3eec GIT binary patch literal 35 qcmZQ#<0?Ap3uLHfBQZ4d91=9D#gaO3^Q&DA!NIL8v==M&hz>% literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb new file mode 100644 index 0000000000000000000000000000000000000000..01d07d64087e8f4ad4c927b72adff6746ad91a4b GIT binary patch literal 429 zcmZXQF;Bu!6ot=wkXnJ%7>y%pOcWV_nWd{cgJV<5wKkTP+&*fUTu8*pU*Xul;^c19 z#6RIuZ&h5p$s2C&yXT(o?E7(yBW(c+QmUasUIc>$M{}Q7-ZCTh{E!kObFJXmR>osCNq!IX;j}CsuV8#L literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c b/test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c new file mode 100644 index 0000000000000000000000000000000000000000..a4adb7aee6aed697073e4b761c17810c122928c5 GIT binary patch literal 178 zcmWkmy$*sv80!J?m(53T&^V|wlWx9%^W}gGUW7Yx2du_~#fRZBd=VDkz`+GSnzTuq zww{x=kroKBz+qzyc?!;-%$AIp?48TGu$ip57KP-7+R065EpzT-!RvdKs63?$QE(m6 zTBV{?7=|l*td^ngfjt?3(_C+zrL@z_Q)~B`GhZe5ypijyHWg=0 zfMi!3{__98MoM-^4zuRgx%MvIw&poVKkhlRyH`#N&YL2*@&4`VVjU4qF^Bqo2i7## z(HX^yMrB^Iys7hEglm^sCu}NjAXz3Idxdk20rwCPMw&VTbqIDN=#59H$3a2#512u7HUIzs literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d b/test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d new file mode 100644 index 0000000000000000000000000000000000000000..64c9720c9b9d11d6183076147266f1ea1cd0115f GIT binary patch literal 473 zcmZXQy-veG5QOKB=s1$dh#yfx5E6tGN$NCi=_x2J$610!Vn-XtQ7Rfsgo>x2^s7+O zBU$1lkdRpeso3i7_I7sW+c!(HoNC7`OKR9Xe=@<5Hh_YZ+EQbl1>G5kQ=eDfVovP& zV~P^#YX!%Wdmh~RQA8T^#1HOi;0+hrES*Z#?UbUC9qtx6E<*~_a55r>VhiY6GG>Uj z?irM%(7*1kS({gfIBj>3auADbkjPZB@Eid)FY8hS9nUSEWrBbo0b#)fo zsG*MDZ5;pJD>A=y=JSb{_&lb>i~K2hv546LWQM~LA?W`5uxUL@j)#NBj|rjDLXp8X uRfUh^MKtm_9)^`C_4$NBqkr97^I$_)AT^JLZ>snQb0JtHvakiVw!Z;s1d5#i literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546 new file mode 100644 index 0000000000000000000000000000000000000000..b0b7452924d35154493a18fe3db2c24b524d5e17 GIT binary patch literal 224 zcmZQ7PAw`+En;9~OfM=()+;E=%uOt+j4uTW$0w$z=9MroF)%Q&FmN&GtLNtfMS-dv zp99rG)E5`$#3vS|re<)+UFgFh~69XgAcm@X$!T76_2S^@eVPIxwVoPOGHn6r2*6%1{Vk_rM og_)HJmA6qc9c81W+9k>NN(WpjyG`6(>#t615a zT;i87G3T6U~6UKhgT@o8v-~{{KGjHE|OW`%E#?~1MAs}#Q*>R literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9 new file mode 100644 index 0000000000000000000000000000000000000000..3d542f38ec941b8daf69e53a4efdc309ce989ba2 GIT binary patch literal 414 zcmZvYJx;_h5QU!|6wI=Ugg65YMJPDHw)7mpGRcr#kw1-10yH#fs5r@9YL7rkW1NIY zD}g0zjN!#5UrIa;!fbstQ@_Zdh%tw5G0Bea~nlM!7 zhF|q_VArOg+D&uOsf_3F%Dm_>l=aNC04gtr!ydKM)-joC5P%ilBZyhtUneS+ai5Sn z-g)L8SuyWRAbk3XPsHeC5j)qO}Azf>)aWbSn21IcTbfV%(y literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 new file mode 100644 index 0000000000000000000000000000000000000000..c8fca17ad38310b58ac412d25d5a72f963576097 GIT binary patch literal 425 zcmZutJ5Iwu5S?8+w!u~!dL$|kMN-kg1-Qj(i6@aIA%X4aNU z(+V3^=|@zC@2SWU?96_-MX4H1ALy|o^yb|2S(*hCkic)kBlfQViGV?mZ~hfzD-U_| zG4W`e<9M&CaVj5*od@eZ3?ex$bz3${w;ZBqo}ljlK`bLVzrj!DzxXfdD;=&yxSk@J zw#pTmheCjiIDaT_)9k#%DJ9YR>KZx$B4O2l#}i_1m}UaVaox=hoD&GiTD5j literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df b/test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df new file mode 100644 index 0000000000000000000000000000000000000000..a867a8b0be95755dba75d7a18e644d00086fbdc0 GIT binary patch literal 371 zcmZvYJx;_h5QU!|6wI=Ugg65YMJPDHw)7mpGRcr#kw1;C1kuo>q2eUDRE|JNW1O{C zLIO*p@yzIZe&Z`s*N{?L;(-`A!v=THU1w#wIkrT_{TfAXZLOX8s%WGg-{{sfq`Ls| zp`8Bm|Gb;@5JmqiW?2HF2nPsKil7ugp9`c%)E0t?g#>XlYuRNQ7oo~Ye2iSghoC@$ zVU4AXG{yWk^ZyvnlCuC29x#7N({`przM9_5yx+%bNjQr?*9VT%uq+?DEyK_JRX6)M z`=>1oOn;%eqVMrw*sGXBDhc%jby=bBPyr6~9+Gbn%tuQA literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 new file mode 100644 index 0000000000000000000000000000000000000000..f1990ac2315efdb5d9d0f2ee1dd090355d4811d6 GIT binary patch literal 338 zcmXv}!AiqG6r9~kOtloG;MpQbEVSyimtMUKUYBk1OoK5kZ#OADdC8%8@gu}ze!?FS z0{(;t*A3#FhM9qxIh6qbAx`urgA^%m;#oouy3DQ8rCqH#vpabC&oU-gD{D75DD)Gl zX+_LgLNGJ)suH)z~i>nWyAgEaE+FOX7y;z4K-u;1SmOCLSZBl6EljJdcku<)6 zg`ne2HYsH=arHhPrOee$8*Y}NB2NcD&;&| z-V17vVN67O#k literal 0 HcmV?d00001 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd new file mode 100644 index 0000000000000000000000000000000000000000..b02dabe03a80f708a041d18d13df473b2d7a97b5 GIT binary patch literal 349 zcmZXQy-ve06ot=qOE9#mC_Dg2NPrkxb_T@8j+i4W-2O;`RM$~5vSfgXC&^>*B3XC? z1|%?cQz{iKdGI;+$KM&6G=;J(1q;x{F2<)>*1l;fi*S>XwP|c*%6a@~9yrc?u}tRo z3_G&lE=l8j?Y5@(+$)^Bqo;#jzoW2)<)P1)K0t3>?3=|LQOQ~gHHb>booyAdI=*m+ zw>>Yi`w~#q)R%i&Md3r59kmjP9zTnU%0Xy9J4Zp{{MhQF@jIy^G)HKvfc1xJxWx61 ony*fhnb{q2eUDRE|JNW1O{C zLIO*p@yzIZe&Z`s*N{?L;(-`A!v=THU1w#wIkrT_{TfAXZLOX8s%WGg-{{sfq`Ls| zp`8Bm|GY{787@1n9tz$BcMS#U5u*@jZ@itSrOvjAW?^U9m)dJ!g1j46}uZk3d%mPG; thmd^8QauKl^{dorkj2SBUf@Du#sfImTjbhdh$*;DpmrYNzRUuwegOCOaY6t9 literal 0 HcmV?d00001 diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index b76263b8b98..b595ef50558 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -40169,6 +40169,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/085865a209776911782f592c9f30ffe0ad3814a0" @@ -40895,6 +40917,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/0d604693a9d3e76f54d28a26142abd729b0a9acd" @@ -41907,6 +41951,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/14064ac4844c709b247a4345a92d8be9766785c4" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/143789594154049441d565b65ce725fc4f8c12bc" @@ -42677,6 +42743,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/1901234bd7c9cb6ee19ff8b17179c481bdc7c5f2" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/190c4ca0cf29c99bc987d2792c7f62e1007c0245" @@ -43777,6 +43865,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/20ff1f8d5d34cb01d58aa334dc46a6644e6e1d12" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/21357c3613a47180eb668b1c6c849ce9096a46eb" @@ -44041,6 +44151,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/2378c3f1206f20711468391ce739116ffe58374b" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/23982956d17d2f55e61a5d9111b1c0c7ee530214" @@ -48639,6 +48771,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/40b4b92460c4e76a39af9042fb3d86d491a98e16" @@ -50157,6 +50311,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/49f564289c79de9e0342f8b0821a167bc8c5ec00" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/49ff30e0f070fe37b642dd0d361c5cbca139f223" @@ -50971,6 +51147,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/507b8ecbb9fd3eea9084087bce22a94cca8a7c41" @@ -53303,6 +53501,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/5f52309deaa1b641fe199889d18f921d6909fc14" @@ -53679,7 +53899,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/61f410c711bc5d53be9e932217ebd035f2716417" + "test/core/end2end/fuzzers/api_fuzzer_corpus/61de97a9d6c4b082602c02277d8d763921f5f95b" ], "ci_platforms": [ "linux" @@ -53701,7 +53921,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/622a3505d10767b795fc2c2922c0d5305d9b84e6" + "test/core/end2end/fuzzers/api_fuzzer_corpus/61f410c711bc5d53be9e932217ebd035f2716417" ], "ci_platforms": [ "linux" @@ -53723,7 +53943,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18" + "test/core/end2end/fuzzers/api_fuzzer_corpus/622a3505d10767b795fc2c2922c0d5305d9b84e6" ], "ci_platforms": [ "linux" @@ -53745,7 +53965,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/6245a105123761558a71a9207b3048d2f3d691f0" + "test/core/end2end/fuzzers/api_fuzzer_corpus/6230cce2862a18c4c92dc6fb4e034a1d15e1ff18" ], "ci_platforms": [ "linux" @@ -53767,7 +53987,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c" + "test/core/end2end/fuzzers/api_fuzzer_corpus/6245a105123761558a71a9207b3048d2f3d691f0" ], "ci_platforms": [ "linux" @@ -53789,7 +54009,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/62c995646f15be1819bd13e32a60af46297d73b4" + "test/core/end2end/fuzzers/api_fuzzer_corpus/629eac0e7443a273b5c351757c03fe15a0b87c1c" ], "ci_platforms": [ "linux" @@ -53811,7 +54031,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e" + "test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7" ], "ci_platforms": [ "linux" @@ -53833,7 +54053,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/634d809c430738b89f0e677eec36506e537e86b3" + "test/core/end2end/fuzzers/api_fuzzer_corpus/62c995646f15be1819bd13e32a60af46297d73b4" ], "ci_platforms": [ "linux" @@ -53855,7 +54075,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/63626e71d4e8e15905f13933f5b88d89073b3411" + "test/core/end2end/fuzzers/api_fuzzer_corpus/62fbfe90a1b9ac471bc2644c896f64515f6b3c7e" ], "ci_platforms": [ "linux" @@ -53877,7 +54097,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae" + "test/core/end2end/fuzzers/api_fuzzer_corpus/634d809c430738b89f0e677eec36506e537e86b3" ], "ci_platforms": [ "linux" @@ -53899,7 +54119,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/63b74d17bfbd015bb55dda59a05101bee001369c" + "test/core/end2end/fuzzers/api_fuzzer_corpus/63626e71d4e8e15905f13933f5b88d89073b3411" ], "ci_platforms": [ "linux" @@ -53921,7 +54141,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/63b91deaac58a7b64fb5999628ff3ff5d32b719d" + "test/core/end2end/fuzzers/api_fuzzer_corpus/638c36cfe098b98008e594eddf90fdacfc078fae" ], "ci_platforms": [ "linux" @@ -53943,7 +54163,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/63babc04d35adbe48add6e93386dfc838b0bbd25" + "test/core/end2end/fuzzers/api_fuzzer_corpus/63b74d17bfbd015bb55dda59a05101bee001369c" ], "ci_platforms": [ "linux" @@ -53965,7 +54185,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/63d83cb5580d3222eb5e2d7982f7f995634ba5c1" + "test/core/end2end/fuzzers/api_fuzzer_corpus/63b91deaac58a7b64fb5999628ff3ff5d32b719d" ], "ci_platforms": [ "linux" @@ -53987,7 +54207,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3" + "test/core/end2end/fuzzers/api_fuzzer_corpus/63babc04d35adbe48add6e93386dfc838b0bbd25" ], "ci_platforms": [ "linux" @@ -54009,7 +54229,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/645b8377f905399af625a01c76ff088745fe1640" + "test/core/end2end/fuzzers/api_fuzzer_corpus/63d83cb5580d3222eb5e2d7982f7f995634ba5c1" ], "ci_platforms": [ "linux" @@ -54031,7 +54251,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2" + "test/core/end2end/fuzzers/api_fuzzer_corpus/641739453f7d4d3b55a1c7b79bed7da6dfd62ae0" ], "ci_platforms": [ "linux" @@ -54053,7 +54273,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/649cf0ee983cb5792042687181ce7e4d81f090a5" + "test/core/end2end/fuzzers/api_fuzzer_corpus/6421db654fff309bc191aba0330fbcd1347655e3" ], "ci_platforms": [ "linux" @@ -54075,7 +54295,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b" + "test/core/end2end/fuzzers/api_fuzzer_corpus/645b8377f905399af625a01c76ff088745fe1640" ], "ci_platforms": [ "linux" @@ -54097,7 +54317,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/64ce7e5553de2c081991af4fc386bffdd8d2e210" + "test/core/end2end/fuzzers/api_fuzzer_corpus/646c501021c79bf6eb1a39a9bcc82e018f31bca2" ], "ci_platforms": [ "linux" @@ -54119,7 +54339,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24" + "test/core/end2end/fuzzers/api_fuzzer_corpus/649cf0ee983cb5792042687181ce7e4d81f090a5" ], "ci_platforms": [ "linux" @@ -54141,7 +54361,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156" + "test/core/end2end/fuzzers/api_fuzzer_corpus/64c572e594c2d491a902e8fdff7b617ac0c6881b" ], "ci_platforms": [ "linux" @@ -54163,7 +54383,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/6531f1c311678c9247ad6820519bc7e73f56cb81" + "test/core/end2end/fuzzers/api_fuzzer_corpus/64ce7e5553de2c081991af4fc386bffdd8d2e210" ], "ci_platforms": [ "linux" @@ -54185,7 +54405,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653" + "test/core/end2end/fuzzers/api_fuzzer_corpus/64d55e872c2148eefb0d7c3df101fd955b709f24" ], "ci_platforms": [ "linux" @@ -54207,7 +54427,95 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/655f952ec49cbc6176ad1bcfa45a87bd6c3542f0" + "test/core/end2end/fuzzers/api_fuzzer_corpus/64eb970cc80162a4b80d49364f4227db3429e156" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/6531f1c311678c9247ad6820519bc7e73f56cb81" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/655b880459e6e00100727af9df52b64f6d77a653" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/655f952ec49cbc6176ad1bcfa45a87bd6c3542f0" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/6589505362ffb5164a3c7cb1b9feadcddfba44e9" ], "ci_platforms": [ "linux" @@ -56141,6 +56449,50 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/724f5400f19e5a0be97022341c39eeaaaffeb390" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/727f43500183aec9c0d9be7d2363fa1761cda5d5" @@ -57131,6 +57483,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/788f18727a0aeb5e200527bca7c889c9954be343" @@ -57219,6 +57593,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/79328fdc89d0af0e38da089dab062fd3ea5aae59" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/7957953ca449974ec39c6a137c0acdedb71c3b02" @@ -57417,6 +57813,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/7a5a769942efac79863bb154cf1e7574e6d98e22" @@ -59397,6 +59815,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/87add83a18a25fe585df8adc124eae6d70733f74" @@ -59793,6 +60233,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/8a1c629910280f8beebb88687696de98da988ecc" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/8a4183e6bb75036228a42039d678fca0ea6751b7" @@ -60653,7 +61115,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/901c9a33205897999e7e78063ccdc5d363267568" + "test/core/end2end/fuzzers/api_fuzzer_corpus/8ff7b1568d2da2e4196c2e28617e1911d62021e6" ], "ci_platforms": [ "linux" @@ -60675,7 +61137,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/90230730fae07c8eeb6b5bd571a119b486a21473" + "test/core/end2end/fuzzers/api_fuzzer_corpus/901c9a33205897999e7e78063ccdc5d363267568" ], "ci_platforms": [ "linux" @@ -60697,7 +61159,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/904edc7bb14e4da0172f3d58a74c8abf141da9fb" + "test/core/end2end/fuzzers/api_fuzzer_corpus/90230730fae07c8eeb6b5bd571a119b486a21473" ], "ci_platforms": [ "linux" @@ -60719,7 +61181,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/9080684608701e015c764f643dc45fa939d86ed3" + "test/core/end2end/fuzzers/api_fuzzer_corpus/904edc7bb14e4da0172f3d58a74c8abf141da9fb" ], "ci_platforms": [ "linux" @@ -60741,7 +61203,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/908b1f170a721682465838d0c0eca40810beb722" + "test/core/end2end/fuzzers/api_fuzzer_corpus/9080684608701e015c764f643dc45fa939d86ed3" ], "ci_platforms": [ "linux" @@ -60763,7 +61225,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/90a94b19bcf5aed7bfee94764acc906e889e47f8" + "test/core/end2end/fuzzers/api_fuzzer_corpus/908b1f170a721682465838d0c0eca40810beb722" ], "ci_platforms": [ "linux" @@ -60785,7 +61247,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7" + "test/core/end2end/fuzzers/api_fuzzer_corpus/90a94b19bcf5aed7bfee94764acc906e889e47f8" ], "ci_platforms": [ "linux" @@ -60807,7 +61269,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/910246d4e894dbf88b09e9c1994e0f7bd563bcc5" + "test/core/end2end/fuzzers/api_fuzzer_corpus/90cd72030567bddbce06152fa0af1a024d542fa7" ], "ci_platforms": [ "linux" @@ -60829,7 +61291,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/913614cd0ae1b1210d2f1bc354b876080726f7a8" + "test/core/end2end/fuzzers/api_fuzzer_corpus/910246d4e894dbf88b09e9c1994e0f7bd563bcc5" ], "ci_platforms": [ "linux" @@ -60851,7 +61313,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/91434e8bf241b54d98e0f664a12ecf5c9d144a8d" + "test/core/end2end/fuzzers/api_fuzzer_corpus/913614cd0ae1b1210d2f1bc354b876080726f7a8" ], "ci_platforms": [ "linux" @@ -60873,7 +61335,7 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7" + "test/core/end2end/fuzzers/api_fuzzer_corpus/91434e8bf241b54d98e0f664a12ecf5c9d144a8d" ], "ci_platforms": [ "linux" @@ -60895,7 +61357,29 @@ }, { "args": [ - "test/core/end2end/fuzzers/api_fuzzer_corpus/92273cf09f18534ae700c1f35dfab49faa091c54" + "test/core/end2end/fuzzers/api_fuzzer_corpus/91e2f574e7ceb7f69a93011aac68903cd014a6c7" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/92273cf09f18534ae700c1f35dfab49faa091c54" ], "ci_platforms": [ "linux" @@ -61597,6 +62081,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/984b6ee241b92be62923c6dc5bacaadb36183b89" @@ -61663,6 +62169,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/988bd333d5dabe1561cf4429e7481ff110be0da4" @@ -63797,6 +64325,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/a78bca1ef8829d720dd5dedac3a9d4d12684da34" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/a7ccc1f7db49512983fe4d42c16b2160357e3585" @@ -64523,6 +65073,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/ac7b2971ff39a368145148524511dd68df83d522" @@ -64985,6 +65557,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/b1e28018e26e6baaba5a907e5e6ff9b7a7942018" @@ -65095,6 +65689,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/b2a5ec3ef40c68d594638218e3c943a479f82215" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/b2af0db70de3a6ddcb188d1f6f2a673133a8f9c7" @@ -66239,6 +66855,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/b9318513eb6b1db553855cd062ebbd4d1db9b846" @@ -68373,6 +69011,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/c5dbc50d9174bde5542b2bb18c63f6583a23ff13" @@ -71871,6 +72531,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/crash-dc6abf90d5e8e1b96f7e25f418b1a7f572e6a738" @@ -75039,6 +75721,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/e29bab478641dd412057dfb6b0a0d78afd96dd60" @@ -76513,6 +77217,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/ec823f4018389e64a99f6580277fba28df6bd136" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/ec89eb7e84e6cf7859ab478362e0ae5227a5e154" @@ -76843,6 +77569,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/ee624b408f8a50c79cdaebf4fb4195e6162b70da" @@ -76865,6 +77613,50 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/ee6855178435d2046d8763ecae46e1e0a71a95f4" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/eeb310d91038cb02862e187e68c5d6578233485b" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/eed65ac63a044c87423f333f3b9c5f0d3bc7bd3b" @@ -77129,6 +77921,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/f07bc2907c95f2aeb79ca60e2ad826e13b848f45" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/f0a7e39c194ee3f30312ae2f4827bdbd43416a42" @@ -78779,6 +79593,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/fb76689d3c70bd5927b3256eda9738a2208e2b13" @@ -79197,6 +80033,28 @@ ], "uses_polling": false }, + { + "args": [ + "test/core/end2end/fuzzers/api_fuzzer_corpus/fdb038087233cd176746558875932029f779221d" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "tsan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "api_fuzzer_one_entry", + "platforms": [ + "linux" + ], + "uses_polling": false + }, { "args": [ "test/core/end2end/fuzzers/api_fuzzer_corpus/fdecd05733278ece9993eb2bef13917675cc062c" From cc641688296a3cf7efbfd30b942b4cdf8d8049e7 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 17 Jan 2017 11:59:31 +0100 Subject: [PATCH 091/104] cmake support for generating from .proto files --- templates/CMakeLists.txt.template | 95 ++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template index 028c1b8c328..7868d412290 100644 --- a/templates/CMakeLists.txt.template +++ b/templates/CMakeLists.txt.template @@ -40,6 +40,17 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <%! + + import re + + proto_re = re.compile('(.*)\\.proto') + + def proto_replace_ext(filename, ext): + m = proto_re.match(filename) + if not m: + return filename + return '${_gRPC_PROTO_GENS_DIR}/' + m.group(1) + ext + def get_deps(target_dict): deps = [] if target_dict.get('baselib', False): @@ -140,6 +151,9 @@ if(TARGET libprotoc) set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc) endif() + if(TARGET protoc) + set(_gRPC_PROTOBUF_PROTOC protoc) + endif() else() message(WARNING "gRPC_PROTOBUF_PROVIDER is \"module\" but PROTOBUF_ROOT_DIR is wrong") endif() @@ -152,6 +166,9 @@ if(TARGET protobuf::libprotoc) set(_gRPC_PROTOBUF_PROTOC_LIBRARIES protobuf::libprotoc) endif() + if(TARGET protobuf::protoc) + set(_gRPC_PROTOBUF_PROTOC protobuf::protoc) + endif() set(_gRPC_FIND_PROTOBUF "if(NOT protobuf_FOUND)\n find_package(protobuf CONFIG)\nendif()") else() find_package(Protobuf MODULE) @@ -192,16 +209,60 @@ if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR) set(CMAKE_INSTALL_CMAKEDIR "<%text>${CMAKE_INSTALL_LIBDIR}/cmake/gRPC") endif() - + + # Create directory for generated .proto files + set(_gRPC_PROTO_GENS_DIR <%text>${CMAKE_BINARY_DIR}/gens) + file(MAKE_DIRECTORY <%text>${_gRPC_PROTO_GENS_DIR}) + + # protobuf_generate_grpc_cpp + # -------------------------- + # + # Add custom commands to process ``.proto`` files to C++ using protoc and + # GRPC plugin:: + # + # protobuf_generate_grpc_cpp [...] + # + # ``ARGN`` + # ``.proto`` files + # + function(protobuf_generate_grpc_cpp) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files") + return() + endif() + + set(_protobuf_include_path -I .) + foreach(FIL <%text>${ARGN}) + get_filename_component(ABS_FIL <%text>${FIL} ABSOLUTE) + get_filename_component(FIL_WE <%text>${FIL} NAME_WE) + file(RELATIVE_PATH REL_FIL <%text>${CMAKE_SOURCE_DIR} <%text>${ABS_FIL}) + get_filename_component(REL_DIR <%text>${REL_FIL} DIRECTORY) + set(RELFIL_WE "<%text>${REL_DIR}/${FIL_WE}") + + add_custom_command( + OUTPUT <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" + <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" + <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" + <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" + COMMAND <%text>${_gRPC_PROTOBUF_PROTOC} + ARGS --grpc_out=<%text>${_gRPC_PROTO_GENS_DIR} + --cpp_out=<%text>${_gRPC_PROTO_GENS_DIR} + --plugin=protoc-gen-grpc=$ + <%text>${_protobuf_include_path} + <%text>${REL_FIL} + DEPENDS <%text>${ABS_FIL} <%text>${_gRPC_PROTOBUF_PROTOC} grpc_cpp_plugin + WORKING_DIRECTORY <%text>${CMAKE_SOURCE_DIR} + COMMENT "Running gRPC C++ protocol buffer compiler on <%text>${FIL}" + VERBATIM) + + <%text>set_source_files_properties("${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" PROPERTIES GENERATED TRUE) + endforeach() + endfunction() + % for lib in libs: % if lib.build in ["all", "protoc", "tool"] and lib.language in ['c', 'c++']: - ## TODO(jtattermusch): grpc++_reflection includes .proto files - ## which is not yet supported and thus fails the entire build. - ## Re-enable once fixed. - % if lib.name != 'grpc++_reflection': - ${cc_library(lib)} - ${cc_install(lib)} - % endif + ${cc_library(lib)} + ${cc_install(lib)} % endif % endfor @@ -215,9 +276,24 @@ <%def name="cc_library(lib)"> add_library(${lib.name} % for src in lib.src: + % if not proto_re.match(src): ${src} + % else: + ${proto_replace_ext(src, '.pb.cc')} + ${proto_replace_ext(src, '.grpc.pb.cc')} + ${proto_replace_ext(src, '.pb.h')} + ${proto_replace_ext(src, '.grpc.pb.h')} + % endif % endfor ) + + % for src in lib.src: + % if proto_re.match(src): + protobuf_generate_grpc_cpp( + ${src} + ) + % endif + % endfor target_include_directories(${lib.name} PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR} @@ -226,6 +302,9 @@ PRIVATE <%text>${PROTOBUF_ROOT_DIR}/src PRIVATE <%text>${ZLIB_INCLUDE_DIR} PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + % if any(proto_re.match(src) for src in lib.src): + PRIVATE <%text>${_gRPC_PROTO_GENS_DIR} + % endif ) % if len(get_deps(lib)) > 0: From 54492aa70f366bfe9626f857c08702c5d010988c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 17 Jan 2017 11:53:33 +0100 Subject: [PATCH 092/104] regenerate --- CMakeLists.txt | 142 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4627c10e2e8..a87e150b539 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,9 @@ if("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "module") if(TARGET libprotoc) set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc) endif() + if(TARGET protoc) + set(_gRPC_PROTOBUF_PROTOC protoc) + endif() else() message(WARNING "gRPC_PROTOBUF_PROVIDER is \"module\" but PROTOBUF_ROOT_DIR is wrong") endif() @@ -134,6 +137,9 @@ elseif("${gRPC_PROTOBUF_PROVIDER}" STREQUAL "package") if(TARGET protobuf::libprotoc) set(_gRPC_PROTOBUF_PROTOC_LIBRARIES protobuf::libprotoc) endif() + if(TARGET protobuf::protoc) + set(_gRPC_PROTOBUF_PROTOC protobuf::protoc) + endif() set(_gRPC_FIND_PROTOBUF "if(NOT protobuf_FOUND)\n find_package(protobuf CONFIG)\nendif()") else() find_package(Protobuf MODULE) @@ -175,7 +181,56 @@ if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR) set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/gRPC") endif() - +# Create directory for generated .proto files +set(_gRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens) +file(MAKE_DIRECTORY ${_gRPC_PROTO_GENS_DIR}) + +# protobuf_generate_grpc_cpp +# -------------------------- +# +# Add custom commands to process ``.proto`` files to C++ using protoc and +# GRPC plugin:: +# +# protobuf_generate_grpc_cpp [...] +# +# ``ARGN`` +# ``.proto`` files +# +function(protobuf_generate_grpc_cpp) + if(NOT ARGN) + message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files") + return() + endif() + + set(_protobuf_include_path -I .) + foreach(FIL ${ARGN}) + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + file(RELATIVE_PATH REL_FIL ${CMAKE_SOURCE_DIR} ${ABS_FIL}) + get_filename_component(REL_DIR ${REL_FIL} DIRECTORY) + set(RELFIL_WE "${REL_DIR}/${FIL_WE}") + + add_custom_command( + OUTPUT "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" + "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" + "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" + "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" + COMMAND ${_gRPC_PROTOBUF_PROTOC} + ARGS --grpc_out=${_gRPC_PROTO_GENS_DIR} + --cpp_out=${_gRPC_PROTO_GENS_DIR} + --plugin=protoc-gen-grpc=$ + ${_protobuf_include_path} + ${REL_FIL} + DEPENDS ${ABS_FIL} ${_gRPC_PROTOBUF_PROTOC} grpc_cpp_plugin + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}" + VERBATIM) + + set_source_files_properties("${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" PROPERTIES GENERATED TRUE) + endforeach() +endfunction() + + add_library(gpr src/core/lib/profiling/basic_timers.c src/core/lib/profiling/stap_timers.c @@ -223,6 +278,7 @@ add_library(gpr src/core/lib/support/wrap_memcpy.c ) + target_include_directories(gpr PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -279,7 +335,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS gpr EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -288,7 +344,7 @@ if (gRPC_INSTALL) ) endif() - + add_library(grpc src/core/lib/surface/init.c src/core/lib/channel/channel_args.c @@ -509,6 +565,7 @@ add_library(grpc src/core/plugin_registry/grpc_plugin_registry.c ) + target_include_directories(grpc PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -563,7 +620,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -572,7 +629,7 @@ if (gRPC_INSTALL) ) endif() - + add_library(grpc_cronet src/core/lib/surface/init.c src/core/lib/channel/channel_args.c @@ -764,6 +821,7 @@ add_library(grpc_cronet src/core/plugin_registry/grpc_cronet_plugin_registry.c ) + target_include_directories(grpc_cronet PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -817,7 +875,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc_cronet EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -826,7 +884,7 @@ if (gRPC_INSTALL) ) endif() - + add_library(grpc_unsecure src/core/lib/surface/init.c src/core/lib/surface/init_unsecure.c @@ -1019,6 +1077,7 @@ add_library(grpc_unsecure src/core/plugin_registry/grpc_unsecure_plugin_registry.c ) + target_include_directories(grpc_unsecure PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -1070,7 +1129,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc_unsecure EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -1079,7 +1138,7 @@ if (gRPC_INSTALL) ) endif() - + add_library(grpc++ src/cpp/client/insecure_credentials.cc src/cpp/client/secure_credentials.cc @@ -1120,6 +1179,7 @@ add_library(grpc++ src/cpp/codegen/codegen_init.cc ) + target_include_directories(grpc++ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -1233,7 +1293,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc++ EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -1242,7 +1302,7 @@ if (gRPC_INSTALL) ) endif() - + add_library(grpc++_cronet src/cpp/client/cronet_credentials.cc src/cpp/client/insecure_credentials.cc @@ -1456,6 +1516,7 @@ add_library(grpc++_cronet third_party/nanopb/pb_encode.c ) + target_include_directories(grpc++_cronet PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -1579,7 +1640,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc++_cronet EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -1588,7 +1649,54 @@ if (gRPC_INSTALL) ) endif() - + +add_library(grpc++_reflection + src/cpp/ext/proto_server_reflection.cc + src/cpp/ext/proto_server_reflection_plugin.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h +) + +protobuf_generate_grpc_cpp( + src/proto/grpc/reflection/v1alpha/reflection.proto +) + +target_include_directories(grpc++_reflection + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${ZLIB_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(grpc++_reflection + grpc++ +) + +foreach(_hdr + include/grpc++/ext/proto_server_reflection_plugin.h +) + string(REPLACE "include/" "" _path ${_hdr}) + get_filename_component(_path ${_path} PATH) + install(FILES ${_hdr} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}" + ) +endforeach() + + +if (gRPC_INSTALL) + install(TARGETS grpc++_reflection EXPORT gRPCTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) +endif() + + add_library(grpc++_unsecure src/cpp/client/insecure_credentials.cc src/cpp/common/insecure_create_auth_context.cc @@ -1624,6 +1732,7 @@ add_library(grpc++_unsecure src/cpp/codegen/codegen_init.cc ) + target_include_directories(grpc++_unsecure PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -1737,7 +1846,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc++_unsecure EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} @@ -1746,7 +1855,7 @@ if (gRPC_INSTALL) ) endif() - + add_library(grpc_plugin_support src/compiler/cpp_generator.cc src/compiler/csharp_generator.cc @@ -1757,6 +1866,7 @@ add_library(grpc_plugin_support src/compiler/ruby_generator.cc ) + target_include_directories(grpc_plugin_support PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -1780,7 +1890,7 @@ foreach(_hdr ) endforeach() - + if (gRPC_INSTALL) install(TARGETS grpc_plugin_support EXPORT gRPCTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} From 31f2dd43e22f41c89cfdd3d25002972247d01954 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 17 Jan 2017 07:25:06 -0800 Subject: [PATCH 093/104] clang-format --- src/core/ext/client_channel/subchannel.c | 2 +- src/core/ext/client_channel/subchannel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c index f9de9993b7b..8bd284507d2 100644 --- a/src/core/ext/client_channel/subchannel.c +++ b/src/core/ext/client_channel/subchannel.c @@ -802,7 +802,7 @@ void grpc_get_subchannel_address_arg(const grpc_channel_args *args, } } -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr) { +grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr) { grpc_arg new_arg; new_arg.key = GRPC_ARG_SUBCHANNEL_ADDRESS; new_arg.type = GRPC_ARG_STRING; diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h index c7a9577ce99..684675eb37d 100644 --- a/src/core/ext/client_channel/subchannel.h +++ b/src/core/ext/client_channel/subchannel.h @@ -180,6 +180,6 @@ void grpc_get_subchannel_address_arg(const grpc_channel_args *args, /// Returns a new channel arg encoding the subchannel address as a string. /// Caller is responsible for freeing the string. -grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address* addr); +grpc_arg grpc_create_subchannel_address_arg(const grpc_resolved_address *addr); #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */ From ce0105fac4986f63ea86d75cc4c8b0f46a71d372 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 17 Jan 2017 07:36:51 -0800 Subject: [PATCH 094/104] Ran generate_projects.sh --- tools/doxygen/Doxyfile.c++ | 1 + tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core | 1 + tools/doxygen/Doxyfile.core.internal | 1 + 4 files changed, 4 insertions(+) diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index fa9b7057c57..ffa167898cd 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -785,6 +785,7 @@ doc/naming.md \ doc/negative-http2-interop-test-descriptions.md \ doc/server-reflection.md \ doc/server_reflection_tutorial.md \ +doc/service_config.md \ doc/statuscodes.md \ doc/stress_test_framework.md \ doc/wait-for-ready.md \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index bca5652a463..0a12e458d64 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -785,6 +785,7 @@ doc/naming.md \ doc/negative-http2-interop-test-descriptions.md \ doc/server-reflection.md \ doc/server_reflection_tutorial.md \ +doc/service_config.md \ doc/statuscodes.md \ doc/stress_test_framework.md \ doc/wait-for-ready.md \ diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index ccbfe3a4e66..6e66ba0f39e 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -784,6 +784,7 @@ doc/naming.md \ doc/negative-http2-interop-test-descriptions.md \ doc/server-reflection.md \ doc/server_reflection_tutorial.md \ +doc/service_config.md \ doc/statuscodes.md \ doc/stress_test_framework.md \ doc/wait-for-ready.md \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index fc8fac32f0d..d8c2f197040 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -784,6 +784,7 @@ doc/naming.md \ doc/negative-http2-interop-test-descriptions.md \ doc/server-reflection.md \ doc/server_reflection_tutorial.md \ +doc/service_config.md \ doc/statuscodes.md \ doc/stress_test_framework.md \ doc/wait-for-ready.md \ From 886fb1245c97878725e0f82ffde0779e3ec8d394 Mon Sep 17 00:00:00 2001 From: Robbie Shade Date: Tue, 17 Jan 2017 13:22:11 -0500 Subject: [PATCH 095/104] Force client to wait for server to start --- test/core/memory_usage/client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c index 9fc122b4c36..f4432bf5727 100644 --- a/test/core/memory_usage/client.c +++ b/test/core/memory_usage/client.c @@ -79,6 +79,7 @@ static void init_ping_pong_request(int call_idx) { op = metadata_ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &calls[call_idx].initial_metadata_recv; @@ -133,6 +134,7 @@ static struct grpc_memory_counters send_snapshot_request( op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; + op->flags = GRPC_INITIAL_METADATA_WAIT_FOR_READY; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op++; From 06dea573daa2175b244a430bb89b49bb5c8e8c5b Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 11 May 2016 12:01:40 -0700 Subject: [PATCH 096/104] Enable running Python formatting --- .gitignore | 1 + setup.cfg | 4 ++ tools/distrib/pyformat_code.sh | 60 ++++++++++++++++++++++++ tools/run_tests/sanity/sanity_tests.yaml | 1 + 4 files changed, 66 insertions(+) create mode 100755 tools/distrib/pyformat_code.sh diff --git a/.gitignore b/.gitignore index 31124451768..618c9ba5ae1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ objs # Python items cython_debug/ python_build/ +python_format_venv/ .coverage* .eggs htmlcov/ diff --git a/setup.cfg b/setup.cfg index dd9161ca8b9..218792e674c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,3 +11,7 @@ inplace=1 [build_package_protos] exclude=.*protoc_plugin/protoc_plugin_test\.proto$ + +# Style settings +[yapf] +based_on_style = google diff --git a/tools/distrib/pyformat_code.sh b/tools/distrib/pyformat_code.sh new file mode 100755 index 00000000000..e3ebf1c4908 --- /dev/null +++ b/tools/distrib/pyformat_code.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Copyright 2015, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -ex + +# change to root directory +cd $(dirname $0)/../.. + +DIRS=src/python +EXCLUSIONS='src/python/grpcio/grpc_*.py src/python/grpcio_health_checking/grpc_*.py src/python/grpcio_reflection/grpc_*.py src/python/grpcio_tests/grpc_*.py' + +VIRTUALENV=python_format_venv + +virtualenv $VIRTUALENV +PYTHON=`realpath $VIRTUALENV/bin/python` +$PYTHON -m pip install --upgrade futures yapf + +exclusion_args="" +for exclusion in $EXCLUSIONS; do + exclusion_args="$exclusion_args --exclude $exclusion" +done + +script_result=0 +for dir in $DIRS; do + tempdir=`mktemp -d` + cp -RT $dir $tempdir + $PYTHON -m yapf -i -r -p $exclusion_args $dir + if ! diff -rq $dir $tempdir; then + script_result=1 + fi + rm -rf $tempdir +done +exit $script_result diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml index 37819166e33..f29b700572b 100644 --- a/tools/run_tests/sanity/sanity_tests.yaml +++ b/tools/run_tests/sanity/sanity_tests.yaml @@ -12,5 +12,6 @@ - script: tools/distrib/check_trailing_newlines.sh - script: tools/distrib/check_nanopb_output.sh - script: tools/distrib/check_include_guards.py +- script: tools/distrib/pyformat_code.sh - script: tools/distrib/python/check_grpcio_tools.py From cc793703bfba6f661f523b6fec82ff8a913e1759 Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Fri, 13 Jan 2017 19:20:10 -0800 Subject: [PATCH 097/104] Run Python formatting --- src/python/grpcio/_spawn_patch.py | 46 +- src/python/grpcio/commands.py | 352 ++-- src/python/grpcio/grpc/__init__.py | 744 ++++---- src/python/grpcio/grpc/_auth.py | 83 +- src/python/grpcio/grpc/_channel.py | 1529 +++++++++-------- src/python/grpcio/grpc/_common.py | 123 +- .../grpcio/grpc/_credential_composition.py | 18 +- src/python/grpcio/grpc/_plugin_wrapping.py | 123 +- src/python/grpcio/grpc/_server.py | 1092 ++++++------ src/python/grpcio/grpc/_utilities.py | 235 +-- .../grpcio/grpc/beta/_client_adaptations.py | 1028 ++++++----- .../grpcio/grpc/beta/_connectivity_channel.py | 213 +-- .../grpcio/grpc/beta/_server_adaptations.py | 544 +++--- .../grpcio/grpc/beta/implementations.py | 173 +- src/python/grpcio/grpc/beta/interfaces.py | 78 +- src/python/grpcio/grpc/beta/utilities.py | 202 ++- src/python/grpcio/grpc/framework/__init__.py | 2 - .../grpcio/grpc/framework/common/__init__.py | 2 - .../grpc/framework/common/cardinality.py | 11 +- .../grpcio/grpc/framework/common/style.py | 7 +- .../grpc/framework/foundation/__init__.py | 2 - .../grpc/framework/foundation/abandonment.py | 3 +- .../framework/foundation/callable_util.py | 47 +- .../grpc/framework/foundation/future.py | 129 +- .../grpc/framework/foundation/logging_pool.py | 55 +- .../grpc/framework/foundation/stream.py | 28 +- .../grpc/framework/foundation/stream_util.py | 227 ++- .../grpc/framework/interfaces/__init__.py | 2 - .../framework/interfaces/base/__init__.py | 2 - .../grpc/framework/interfaces/base/base.py | 184 +- .../framework/interfaces/base/utilities.py | 42 +- .../framework/interfaces/face/__init__.py | 2 - .../grpc/framework/interfaces/face/face.py | 610 ++++--- .../framework/interfaces/face/utilities.py | 87 +- src/python/grpcio/support.py | 103 +- .../grpc_health/__init__.py | 2 - .../grpc_health/v1/__init__.py | 2 - .../grpc_health/v1/health.py | 33 +- .../grpcio_health_checking/health_commands.py | 53 +- src/python/grpcio_health_checking/setup.py | 14 +- .../grpc_reflection/__init__.py | 1 - .../grpc_reflection/v1alpha/__init__.py | 1 - .../grpc_reflection/v1alpha/reflection.py | 168 +- .../grpcio_reflection/reflection_commands.py | 57 +- src/python/grpcio_reflection/setup.py | 14 +- src/python/grpcio_tests/commands.py | 266 ++- src/python/grpcio_tests/setup.py | 42 +- src/python/grpcio_tests/tests/_loader.py | 89 +- src/python/grpcio_tests/tests/_result.py | 618 +++---- src/python/grpcio_tests/tests/_runner.py | 273 +-- .../health_check/_health_servicer_test.py | 87 +- .../tests/http2/_negative_http2_client.py | 175 +- .../grpcio_tests/tests/interop/__init__.py | 2 - .../tests/interop/_insecure_intraop_test.py | 24 +- .../tests/interop/_intraop_test_case.py | 38 +- .../tests/interop/_secure_intraop_test.py | 35 +- .../grpcio_tests/tests/interop/client.py | 163 +- .../grpcio_tests/tests/interop/methods.py | 759 ++++---- .../grpcio_tests/tests/interop/resources.py | 21 +- .../grpcio_tests/tests/interop/server.py | 57 +- .../tests/protoc_plugin/__init__.py | 2 - .../protoc_plugin/_python_plugin_test.py | 754 ++++---- .../protoc_plugin/_split_definitions_test.py | 446 ++--- .../protoc_plugin/beta_python_plugin_test.py | 716 ++++---- .../tests/protoc_plugin/protos/__init__.py | 2 - .../protos/invocation_testing/__init__.py | 2 - .../split_messages/__init__.py | 2 - .../split_services/__init__.py | 2 - .../protoc_plugin/protos/payload/__init__.py | 2 - .../protoc_plugin/protos/requests/__init__.py | 2 - .../protos/requests/r/__init__.py | 2 - .../protos/responses/__init__.py | 2 - .../protoc_plugin/protos/service/__init__.py | 2 - .../tests/qps/benchmark_client.py | 280 +-- .../tests/qps/benchmark_server.py | 32 +- .../grpcio_tests/tests/qps/client_runner.py | 107 +- .../grpcio_tests/tests/qps/histogram.py | 82 +- .../grpcio_tests/tests/qps/qps_worker.py | 34 +- .../grpcio_tests/tests/qps/worker_server.py | 297 ++-- .../reflection/_reflection_servicer_test.py | 234 ++- .../grpcio_tests/tests/stress/client.py | 217 +-- .../tests/stress/metrics_server.py | 41 +- .../grpcio_tests/tests/stress/test_runner.py | 59 +- .../grpcio_tests/tests/unit/__init__.py | 2 - .../grpcio_tests/tests/unit/_api_test.py | 117 +- .../grpcio_tests/tests/unit/_auth_test.py | 69 +- .../tests/unit/_channel_args_test.py | 20 +- .../tests/unit/_channel_connectivity_test.py | 209 ++- .../tests/unit/_channel_ready_future_test.py | 108 +- .../tests/unit/_compression_test.py | 147 +- .../tests/unit/_credentials_test.py | 56 +- .../unit/_cython/_cancel_many_calls_test.py | 302 ++-- .../tests/unit/_cython/_channel_test.py | 55 +- .../_read_some_but_not_all_responses_test.py | 402 ++--- .../tests/unit/_cython/cygrpc_test.py | 710 ++++---- .../tests/unit/_cython/test_utilities.py | 45 +- .../tests/unit/_empty_message_test.py | 125 +- .../tests/unit/_exit_scenarios.py | 269 ++- .../grpcio_tests/tests/unit/_exit_test.py | 243 +-- .../tests/unit/_invalid_metadata_test.py | 223 +-- .../tests/unit/_invocation_defects_test.py | 316 ++-- .../tests/unit/_junkdrawer/__init__.py | 2 - .../tests/unit/_junkdrawer/stock_pb2.py | 209 ++- .../tests/unit/_metadata_code_details_test.py | 901 +++++----- .../grpcio_tests/tests/unit/_metadata_test.py | 254 +-- .../grpcio_tests/tests/unit/_rpc_test.py | 1414 +++++++-------- .../tests/unit/_sanity/__init__.py | 2 - .../tests/unit/_sanity/_sanity_test.py | 32 +- .../tests/unit/_thread_cleanup_test.py | 143 +- .../grpcio_tests/tests/unit/_thread_pool.py | 25 +- .../grpcio_tests/tests/unit/beta/__init__.py | 2 - .../tests/unit/beta/_beta_features_test.py | 528 +++--- .../unit/beta/_connectivity_channel_test.py | 15 +- .../tests/unit/beta/_face_interface_test.py | 160 +- .../tests/unit/beta/_implementations_test.py | 44 +- .../tests/unit/beta/_not_found_test.py | 58 +- .../tests/unit/beta/_utilities_test.py | 113 +- .../tests/unit/beta/test_utilities.py | 17 +- .../tests/unit/framework/__init__.py | 2 - .../tests/unit/framework/common/__init__.py | 2 - .../unit/framework/common/test_constants.py | 1 - .../unit/framework/common/test_control.py | 97 +- .../unit/framework/common/test_coverage.py | 117 +- .../unit/framework/foundation/__init__.py | 2 - .../foundation/_logging_pool_test.py | 64 +- .../framework/foundation/stream_testing.py | 55 +- .../unit/framework/interfaces/__init__.py | 2 - .../interfaces/face/_3069_test_constant.py | 1 - .../framework/interfaces/face/__init__.py | 2 - .../_blocking_invocation_inline_service.py | 465 ++--- .../unit/framework/interfaces/face/_digest.py | 550 +++--- ...e_invocation_asynchronous_event_service.py | 876 +++++----- .../framework/interfaces/face/_invocation.py | 187 +- .../framework/interfaces/face/_service.py | 159 +- .../interfaces/face/_stock_service.py | 519 +++--- .../framework/interfaces/face/test_cases.py | 27 +- .../interfaces/face/test_interfaces.py | 144 +- .../grpcio_tests/tests/unit/resources.py | 11 +- .../grpcio_tests/tests/unit/test_common.py | 69 +- 139 files changed, 12827 insertions(+), 12303 deletions(-) diff --git a/src/python/grpcio/_spawn_patch.py b/src/python/grpcio/_spawn_patch.py index 24306f0dd95..75d0a8b3527 100644 --- a/src/python/grpcio/_spawn_patch.py +++ b/src/python/grpcio/_spawn_patch.py @@ -26,7 +26,6 @@ # 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. - """Patches the spawn() command for windows compilers. Windows has an 8191 character command line limit, but some compilers @@ -45,29 +44,32 @@ MAX_COMMAND_LENGTH = 8191 _classic_spawn = ccompiler.CCompiler.spawn + def _commandfile_spawn(self, command): - command_length = sum([len(arg) for arg in command]) - if os.name == 'nt' and command_length > MAX_COMMAND_LENGTH: - # Even if this command doesn't support the @command_file, it will - # fail as is so we try blindly - print('Command line length exceeded, using command file') - print(' '.join(command)) - temporary_directory = tempfile.mkdtemp() - command_filename = os.path.abspath( - os.path.join(temporary_directory, 'command')) - with open(command_filename, 'w') as command_file: - escaped_args = ['"' + arg.replace('\\', '\\\\') + '"' for arg in command[1:]] - command_file.write(' '.join(escaped_args)) - modified_command = command[:1] + ['@{}'.format(command_filename)] - try: - _classic_spawn(self, modified_command) - finally: - shutil.rmtree(temporary_directory) - else: - _classic_spawn(self, command) + command_length = sum([len(arg) for arg in command]) + if os.name == 'nt' and command_length > MAX_COMMAND_LENGTH: + # Even if this command doesn't support the @command_file, it will + # fail as is so we try blindly + print('Command line length exceeded, using command file') + print(' '.join(command)) + temporary_directory = tempfile.mkdtemp() + command_filename = os.path.abspath( + os.path.join(temporary_directory, 'command')) + with open(command_filename, 'w') as command_file: + escaped_args = [ + '"' + arg.replace('\\', '\\\\') + '"' for arg in command[1:] + ] + command_file.write(' '.join(escaped_args)) + modified_command = command[:1] + ['@{}'.format(command_filename)] + try: + _classic_spawn(self, modified_command) + finally: + shutil.rmtree(temporary_directory) + else: + _classic_spawn(self, command) def monkeypatch_spawn(): - """Monkeypatching is dumb, but it's either that or we become maintainers of + """Monkeypatching is dumb, but it's either that or we become maintainers of something much, much bigger.""" - ccompiler.CCompiler.spawn = _commandfile_spawn + ccompiler.CCompiler.spawn = _commandfile_spawn diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index 701c6af0179..e09f9225912 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -26,7 +26,6 @@ # 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. - """Provides distutils command classes for the GRPC Python setup process.""" import distutils @@ -87,138 +86,144 @@ Glossary class CommandError(Exception): - """Simple exception class for GRPC custom commands.""" + """Simple exception class for GRPC custom commands.""" # TODO(atash): Remove this once PyPI has better Linux bdist support. See # https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported def _get_grpc_custom_bdist(decorated_basename, target_bdist_basename): - """Returns a string path to a bdist file for Linux to install. + """Returns a string path to a bdist file for Linux to install. If we can retrieve a pre-compiled bdist from online, uses it. Else, emits a warning and builds from source. """ - # TODO(atash): somehow the name that's returned from `wheel` is different - # between different versions of 'wheel' (but from a compatibility standpoint, - # the names are compatible); we should have some way of determining name - # compatibility in the same way `wheel` does to avoid having to rename all of - # the custom wheels that we build/upload to GCS. - - # Break import style to ensure that setup.py has had a chance to install the - # relevant package. - from six.moves.urllib import request - decorated_path = decorated_basename + GRPC_CUSTOM_BDIST_EXT - try: - url = BINARIES_REPOSITORY + '/{target}'.format(target=decorated_path) - bdist_data = request.urlopen(url).read() - except IOError as error: - raise CommandError( - '{}\n\nCould not find the bdist {}: {}' - .format(traceback.format_exc(), decorated_path, error.message)) - # Our chosen local bdist path. - bdist_path = target_bdist_basename + GRPC_CUSTOM_BDIST_EXT - try: - with open(bdist_path, 'w') as bdist_file: - bdist_file.write(bdist_data) - except IOError as error: - raise CommandError( - '{}\n\nCould not write grpcio bdist: {}' - .format(traceback.format_exc(), error.message)) - return bdist_path + # TODO(atash): somehow the name that's returned from `wheel` is different + # between different versions of 'wheel' (but from a compatibility standpoint, + # the names are compatible); we should have some way of determining name + # compatibility in the same way `wheel` does to avoid having to rename all of + # the custom wheels that we build/upload to GCS. + + # Break import style to ensure that setup.py has had a chance to install the + # relevant package. + from six.moves.urllib import request + decorated_path = decorated_basename + GRPC_CUSTOM_BDIST_EXT + try: + url = BINARIES_REPOSITORY + '/{target}'.format(target=decorated_path) + bdist_data = request.urlopen(url).read() + except IOError as error: + raise CommandError('{}\n\nCould not find the bdist {}: {}'.format( + traceback.format_exc(), decorated_path, error.message)) + # Our chosen local bdist path. + bdist_path = target_bdist_basename + GRPC_CUSTOM_BDIST_EXT + try: + with open(bdist_path, 'w') as bdist_file: + bdist_file.write(bdist_data) + except IOError as error: + raise CommandError('{}\n\nCould not write grpcio bdist: {}' + .format(traceback.format_exc(), error.message)) + return bdist_path class SphinxDocumentation(setuptools.Command): - """Command to generate documentation via sphinx.""" - - description = 'generate sphinx documentation' - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - # We import here to ensure that setup.py has had a chance to install the - # relevant package eggs first. - import sphinx - import sphinx.apidoc - metadata = self.distribution.metadata - src_dir = os.path.join(PYTHON_STEM, 'grpc') - sys.path.append(src_dir) - sphinx.apidoc.main([ - '', '--force', '--full', '-H', metadata.name, '-A', metadata.author, - '-V', metadata.version, '-R', metadata.version, - '-o', os.path.join('doc', 'src'), src_dir]) - conf_filepath = os.path.join('doc', 'src', 'conf.py') - with open(conf_filepath, 'a') as conf_file: - conf_file.write(CONF_PY_ADDENDUM) - glossary_filepath = os.path.join('doc', 'src', 'grpc.rst') - with open(glossary_filepath, 'a') as glossary_filepath: - glossary_filepath.write(API_GLOSSARY) - sphinx.main(['', os.path.join('doc', 'src'), os.path.join('doc', 'build')]) + """Command to generate documentation via sphinx.""" + + description = 'generate sphinx documentation' + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + # We import here to ensure that setup.py has had a chance to install the + # relevant package eggs first. + import sphinx + import sphinx.apidoc + metadata = self.distribution.metadata + src_dir = os.path.join(PYTHON_STEM, 'grpc') + sys.path.append(src_dir) + sphinx.apidoc.main([ + '', '--force', '--full', '-H', metadata.name, '-A', metadata.author, + '-V', metadata.version, '-R', metadata.version, '-o', + os.path.join('doc', 'src'), src_dir + ]) + conf_filepath = os.path.join('doc', 'src', 'conf.py') + with open(conf_filepath, 'a') as conf_file: + conf_file.write(CONF_PY_ADDENDUM) + glossary_filepath = os.path.join('doc', 'src', 'grpc.rst') + with open(glossary_filepath, 'a') as glossary_filepath: + glossary_filepath.write(API_GLOSSARY) + sphinx.main( + ['', os.path.join('doc', 'src'), os.path.join('doc', 'build')]) class BuildProjectMetadata(setuptools.Command): - """Command to generate project metadata in a module.""" + """Command to generate project metadata in a module.""" - description = 'build grpcio project metadata files' - user_options = [] + description = 'build grpcio project metadata files' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - pass + def finalize_options(self): + pass - def run(self): - with open(os.path.join(PYTHON_STEM, 'grpc/_grpcio_metadata.py'), 'w') as module_file: - module_file.write('__version__ = """{}"""'.format( - self.distribution.get_version())) + def run(self): + with open(os.path.join(PYTHON_STEM, 'grpc/_grpcio_metadata.py'), + 'w') as module_file: + module_file.write('__version__ = """{}"""'.format( + self.distribution.get_version())) class BuildPy(build_py.build_py): - """Custom project build command.""" + """Custom project build command.""" - def run(self): - self.run_command('build_project_metadata') - build_py.build_py.run(self) + def run(self): + self.run_command('build_project_metadata') + build_py.build_py.run(self) def _poison_extensions(extensions, message): - """Includes a file that will always fail to compile in all extensions.""" - poison_filename = os.path.join(PYTHON_STEM, 'poison.c') - with open(poison_filename, 'w') as poison: - poison.write('#error {}'.format(message)) - for extension in extensions: - extension.sources = [poison_filename] + """Includes a file that will always fail to compile in all extensions.""" + poison_filename = os.path.join(PYTHON_STEM, 'poison.c') + with open(poison_filename, 'w') as poison: + poison.write('#error {}'.format(message)) + for extension in extensions: + extension.sources = [poison_filename] + def check_and_update_cythonization(extensions): - """Replace .pyx files with their generated counterparts and return whether or + """Replace .pyx files with their generated counterparts and return whether or not cythonization still needs to occur.""" - for extension in extensions: - generated_pyx_sources = [] - other_sources = [] - for source in extension.sources: - base, file_ext = os.path.splitext(source) - if file_ext == '.pyx': - generated_pyx_source = next( - (base + gen_ext for gen_ext in ('.c', '.cpp',) - if os.path.isfile(base + gen_ext)), None) - if generated_pyx_source: - generated_pyx_sources.append(generated_pyx_source) - else: - sys.stderr.write('Cython-generated files are missing...\n') - return False - else: - other_sources.append(source) - extension.sources = generated_pyx_sources + other_sources - sys.stderr.write('Found cython-generated files...\n') - return True + for extension in extensions: + generated_pyx_sources = [] + other_sources = [] + for source in extension.sources: + base, file_ext = os.path.splitext(source) + if file_ext == '.pyx': + generated_pyx_source = next((base + gen_ext + for gen_ext in ( + '.c', + '.cpp',) + if os.path.isfile(base + gen_ext)), + None) + if generated_pyx_source: + generated_pyx_sources.append(generated_pyx_source) + else: + sys.stderr.write('Cython-generated files are missing...\n') + return False + else: + other_sources.append(source) + extension.sources = generated_pyx_sources + other_sources + sys.stderr.write('Found cython-generated files...\n') + return True + def try_cythonize(extensions, linetracing=False, mandatory=True): - """Attempt to cythonize the extensions. + """Attempt to cythonize the extensions. Args: extensions: A list of `distutils.extension.Extension`. @@ -226,78 +231,83 @@ def try_cythonize(extensions, linetracing=False, mandatory=True): mandatory: Whether or not having Cython-generated files is mandatory. If it is, extensions will be poisoned when they can't be fully generated. """ - try: - # Break import style to ensure we have access to Cython post-setup_requires - import Cython.Build - except ImportError: - if mandatory: - sys.stderr.write( - "This package needs to generate C files with Cython but it cannot. " - "Poisoning extension sources to disallow extension commands...") - _poison_extensions( - extensions, - "Extensions have been poisoned due to missing Cython-generated code.") - return extensions - cython_compiler_directives = {} - if linetracing: - additional_define_macros = [('CYTHON_TRACE_NOGIL', '1')] - cython_compiler_directives['linetrace'] = True - return Cython.Build.cythonize( - extensions, - include_path=[ - include_dir for extension in extensions for include_dir in extension.include_dirs - ] + [CYTHON_STEM], - compiler_directives=cython_compiler_directives - ) + try: + # Break import style to ensure we have access to Cython post-setup_requires + import Cython.Build + except ImportError: + if mandatory: + sys.stderr.write( + "This package needs to generate C files with Cython but it cannot. " + "Poisoning extension sources to disallow extension commands...") + _poison_extensions( + extensions, + "Extensions have been poisoned due to missing Cython-generated code." + ) + return extensions + cython_compiler_directives = {} + if linetracing: + additional_define_macros = [('CYTHON_TRACE_NOGIL', '1')] + cython_compiler_directives['linetrace'] = True + return Cython.Build.cythonize( + extensions, + include_path=[ + include_dir + for extension in extensions + for include_dir in extension.include_dirs + ] + [CYTHON_STEM], + compiler_directives=cython_compiler_directives) class BuildExt(build_ext.build_ext): - """Custom build_ext command to enable compiler-specific flags.""" - - C_OPTIONS = { - 'unix': ('-pthread', '-std=gnu99'), - 'msvc': (), - } - LINK_OPTIONS = {} - - def build_extensions(self): - compiler = self.compiler.compiler_type - if compiler in BuildExt.C_OPTIONS: - for extension in self.extensions: - extension.extra_compile_args += list(BuildExt.C_OPTIONS[compiler]) - if compiler in BuildExt.LINK_OPTIONS: - for extension in self.extensions: - extension.extra_link_args += list(BuildExt.LINK_OPTIONS[compiler]) - if not check_and_update_cythonization(self.extensions): - self.extensions = try_cythonize(self.extensions) - try: - build_ext.build_ext.build_extensions(self) - except Exception as error: - formatted_exception = traceback.format_exc() - support.diagnose_build_ext_error(self, error, formatted_exception) - raise CommandError( - "Failed `build_ext` step:\n{}".format(formatted_exception)) + """Custom build_ext command to enable compiler-specific flags.""" + + C_OPTIONS = { + 'unix': ('-pthread', '-std=gnu99'), + 'msvc': (), + } + LINK_OPTIONS = {} + + def build_extensions(self): + compiler = self.compiler.compiler_type + if compiler in BuildExt.C_OPTIONS: + for extension in self.extensions: + extension.extra_compile_args += list(BuildExt.C_OPTIONS[ + compiler]) + if compiler in BuildExt.LINK_OPTIONS: + for extension in self.extensions: + extension.extra_link_args += list(BuildExt.LINK_OPTIONS[ + compiler]) + if not check_and_update_cythonization(self.extensions): + self.extensions = try_cythonize(self.extensions) + try: + build_ext.build_ext.build_extensions(self) + except Exception as error: + formatted_exception = traceback.format_exc() + support.diagnose_build_ext_error(self, error, formatted_exception) + raise CommandError("Failed `build_ext` step:\n{}".format( + formatted_exception)) class Gather(setuptools.Command): - """Command to gather project dependencies.""" - - description = 'gather dependencies for grpcio' - user_options = [ - ('test', 't', 'flag indicating to gather test dependencies'), - ('install', 'i', 'flag indicating to gather install dependencies') - ] - - def initialize_options(self): - self.test = False - self.install = False - - def finalize_options(self): - # distutils requires this override. - pass - - def run(self): - if self.install and self.distribution.install_requires: - self.distribution.fetch_build_eggs(self.distribution.install_requires) - if self.test and self.distribution.tests_require: - self.distribution.fetch_build_eggs(self.distribution.tests_require) + """Command to gather project dependencies.""" + + description = 'gather dependencies for grpcio' + user_options = [ + ('test', 't', 'flag indicating to gather test dependencies'), + ('install', 'i', 'flag indicating to gather install dependencies') + ] + + def initialize_options(self): + self.test = False + self.install = False + + def finalize_options(self): + # distutils requires this override. + pass + + def run(self): + if self.install and self.distribution.install_requires: + self.distribution.fetch_build_eggs( + self.distribution.install_requires) + if self.test and self.distribution.tests_require: + self.distribution.fetch_build_eggs(self.distribution.tests_require) diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index e3c10156d0f..abe14e70498 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -26,7 +26,6 @@ # 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. - """gRPC's Python API.""" import abc @@ -37,28 +36,27 @@ import six from grpc._cython import cygrpc as _cygrpc - ############################## Future Interface ############################### class FutureTimeoutError(Exception): - """Indicates that a method call on a Future timed out.""" + """Indicates that a method call on a Future timed out.""" class FutureCancelledError(Exception): - """Indicates that the computation underlying a Future was cancelled.""" + """Indicates that the computation underlying a Future was cancelled.""" class Future(six.with_metaclass(abc.ABCMeta)): - """A representation of a computation in another control flow. + """A representation of a computation in another control flow. Computations represented by a Future may be yet to be begun, may be ongoing, or may have already completed. """ - @abc.abstractmethod - def cancel(self): - """Attempts to cancel the computation. + @abc.abstractmethod + def cancel(self): + """Attempts to cancel the computation. This method does not block. @@ -71,11 +69,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): remote system for which a determination of whether or not it commenced before being cancelled cannot be made without blocking. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def cancelled(self): - """Describes whether the computation was cancelled. + @abc.abstractmethod + def cancelled(self): + """Describes whether the computation was cancelled. This method does not block. @@ -85,11 +83,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): not limited to this object's cancel method not having been called and the computation's result having become immediately available. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def running(self): - """Describes whether the computation is taking place. + @abc.abstractmethod + def running(self): + """Describes whether the computation is taking place. This method does not block. @@ -98,11 +96,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): taking place now, or False if the computation took place in the past or was cancelled. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def done(self): - """Describes whether the computation has taken place. + @abc.abstractmethod + def done(self): + """Describes whether the computation has taken place. This method does not block. @@ -111,11 +109,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): unscheduled or interrupted. False if the computation may possibly be executing or scheduled to execute later. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def result(self, timeout=None): - """Accesses the outcome of the computation or raises its exception. + @abc.abstractmethod + def result(self, timeout=None): + """Accesses the outcome of the computation or raises its exception. This method may return immediately or may block. @@ -134,11 +132,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): Exception: If the computation raised an exception, this call will raise the same exception. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def exception(self, timeout=None): - """Return the exception raised by the computation. + @abc.abstractmethod + def exception(self, timeout=None): + """Return the exception raised by the computation. This method may return immediately or may block. @@ -157,11 +155,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): not terminate within the allotted time. FutureCancelledError: If the computation was cancelled. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def traceback(self, timeout=None): - """Access the traceback of the exception raised by the computation. + @abc.abstractmethod + def traceback(self, timeout=None): + """Access the traceback of the exception raised by the computation. This method may return immediately or may block. @@ -180,11 +178,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): not terminate within the allotted time. FutureCancelledError: If the computation was cancelled. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_done_callback(self, fn): - """Adds a function to be called at completion of the computation. + @abc.abstractmethod + def add_done_callback(self, fn): + """Adds a function to be called at completion of the computation. The callback will be passed this Future object describing the outcome of the computation. @@ -195,7 +193,7 @@ class Future(six.with_metaclass(abc.ABCMeta)): Args: fn: A callable taking this Future object as its single parameter. """ - raise NotImplementedError() + raise NotImplementedError() ################################ gRPC Enums ################################## @@ -203,7 +201,7 @@ class Future(six.with_metaclass(abc.ABCMeta)): @enum.unique class ChannelConnectivity(enum.Enum): - """Mirrors grpc_connectivity_state in the gRPC Core. + """Mirrors grpc_connectivity_state in the gRPC Core. Attributes: IDLE: The channel is idle. @@ -213,81 +211,80 @@ class ChannelConnectivity(enum.Enum): recover. SHUTDOWN: The channel has seen a failure from which it cannot recover. """ - IDLE = (_cygrpc.ConnectivityState.idle, 'idle') - CONNECTING = (_cygrpc.ConnectivityState.connecting, 'connecting') - READY = (_cygrpc.ConnectivityState.ready, 'ready') - TRANSIENT_FAILURE = ( - _cygrpc.ConnectivityState.transient_failure, 'transient failure') - SHUTDOWN = (_cygrpc.ConnectivityState.shutdown, 'shutdown') + IDLE = (_cygrpc.ConnectivityState.idle, 'idle') + CONNECTING = (_cygrpc.ConnectivityState.connecting, 'connecting') + READY = (_cygrpc.ConnectivityState.ready, 'ready') + TRANSIENT_FAILURE = (_cygrpc.ConnectivityState.transient_failure, + 'transient failure') + SHUTDOWN = (_cygrpc.ConnectivityState.shutdown, 'shutdown') @enum.unique class StatusCode(enum.Enum): - """Mirrors grpc_status_code in the gRPC Core.""" - OK = (_cygrpc.StatusCode.ok, 'ok') - CANCELLED = (_cygrpc.StatusCode.cancelled, 'cancelled') - UNKNOWN = (_cygrpc.StatusCode.unknown, 'unknown') - INVALID_ARGUMENT = ( - _cygrpc.StatusCode.invalid_argument, 'invalid argument') - DEADLINE_EXCEEDED = ( - _cygrpc.StatusCode.deadline_exceeded, 'deadline exceeded') - NOT_FOUND = (_cygrpc.StatusCode.not_found, 'not found') - ALREADY_EXISTS = (_cygrpc.StatusCode.already_exists, 'already exists') - PERMISSION_DENIED = ( - _cygrpc.StatusCode.permission_denied, 'permission denied') - RESOURCE_EXHAUSTED = ( - _cygrpc.StatusCode.resource_exhausted, 'resource exhausted') - FAILED_PRECONDITION = ( - _cygrpc.StatusCode.failed_precondition, 'failed precondition') - ABORTED = (_cygrpc.StatusCode.aborted, 'aborted') - OUT_OF_RANGE = (_cygrpc.StatusCode.out_of_range, 'out of range') - UNIMPLEMENTED = (_cygrpc.StatusCode.unimplemented, 'unimplemented') - INTERNAL = (_cygrpc.StatusCode.internal, 'internal') - UNAVAILABLE = (_cygrpc.StatusCode.unavailable, 'unavailable') - DATA_LOSS = (_cygrpc.StatusCode.data_loss, 'data loss') - UNAUTHENTICATED = (_cygrpc.StatusCode.unauthenticated, 'unauthenticated') + """Mirrors grpc_status_code in the gRPC Core.""" + OK = (_cygrpc.StatusCode.ok, 'ok') + CANCELLED = (_cygrpc.StatusCode.cancelled, 'cancelled') + UNKNOWN = (_cygrpc.StatusCode.unknown, 'unknown') + INVALID_ARGUMENT = (_cygrpc.StatusCode.invalid_argument, 'invalid argument') + DEADLINE_EXCEEDED = (_cygrpc.StatusCode.deadline_exceeded, + 'deadline exceeded') + NOT_FOUND = (_cygrpc.StatusCode.not_found, 'not found') + ALREADY_EXISTS = (_cygrpc.StatusCode.already_exists, 'already exists') + PERMISSION_DENIED = (_cygrpc.StatusCode.permission_denied, + 'permission denied') + RESOURCE_EXHAUSTED = (_cygrpc.StatusCode.resource_exhausted, + 'resource exhausted') + FAILED_PRECONDITION = (_cygrpc.StatusCode.failed_precondition, + 'failed precondition') + ABORTED = (_cygrpc.StatusCode.aborted, 'aborted') + OUT_OF_RANGE = (_cygrpc.StatusCode.out_of_range, 'out of range') + UNIMPLEMENTED = (_cygrpc.StatusCode.unimplemented, 'unimplemented') + INTERNAL = (_cygrpc.StatusCode.internal, 'internal') + UNAVAILABLE = (_cygrpc.StatusCode.unavailable, 'unavailable') + DATA_LOSS = (_cygrpc.StatusCode.data_loss, 'data loss') + UNAUTHENTICATED = (_cygrpc.StatusCode.unauthenticated, 'unauthenticated') ############################# gRPC Exceptions ################################ class RpcError(Exception): - """Raised by the gRPC library to indicate non-OK-status RPC termination.""" + """Raised by the gRPC library to indicate non-OK-status RPC termination.""" ############################## Shared Context ################################ class RpcContext(six.with_metaclass(abc.ABCMeta)): - """Provides RPC-related information and action.""" + """Provides RPC-related information and action.""" - @abc.abstractmethod - def is_active(self): - """Describes whether the RPC is active or has terminated.""" - raise NotImplementedError() + @abc.abstractmethod + def is_active(self): + """Describes whether the RPC is active or has terminated.""" + raise NotImplementedError() - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the RPC. + @abc.abstractmethod + def time_remaining(self): + """Describes the length of allowed time remaining for the RPC. Returns: A nonnegative float indicating the length of allowed time in seconds remaining for the RPC to complete before it is considered to have timed out, or None if no deadline was specified for the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def cancel(self): - """Cancels the RPC. + @abc.abstractmethod + def cancel(self): + """Cancels the RPC. Idempotent and has no effect if the RPC has already terminated. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_callback(self, callback): - """Registers a callback to be called on RPC termination. + @abc.abstractmethod + def add_callback(self, callback): + """Registers a callback to be called on RPC termination. Args: callback: A no-parameter callable to be called on RPC termination. @@ -297,76 +294,76 @@ class RpcContext(six.with_metaclass(abc.ABCMeta)): callback was not added and will not later be called (because the RPC already terminated or some other reason). """ - raise NotImplementedError() + raise NotImplementedError() ######################### Invocation-Side Context ############################ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): - """Invocation-side utility object for an RPC.""" + """Invocation-side utility object for an RPC.""" - @abc.abstractmethod - def initial_metadata(self): - """Accesses the initial metadata from the service-side of the RPC. + @abc.abstractmethod + def initial_metadata(self): + """Accesses the initial metadata from the service-side of the RPC. This method blocks until the value is available. Returns: The initial :term:`metadata`. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def trailing_metadata(self): - """Accesses the trailing metadata from the service-side of the RPC. + @abc.abstractmethod + def trailing_metadata(self): + """Accesses the trailing metadata from the service-side of the RPC. This method blocks until the value is available. Returns: The trailing :term:`metadata`. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def code(self): - """Accesses the status code emitted by the service-side of the RPC. + @abc.abstractmethod + def code(self): + """Accesses the status code emitted by the service-side of the RPC. This method blocks until the value is available. Returns: The StatusCode value for the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def details(self): - """Accesses the details value emitted by the service-side of the RPC. + @abc.abstractmethod + def details(self): + """Accesses the details value emitted by the service-side of the RPC. This method blocks until the value is available. Returns: The details string of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() ############ Authentication & Authorization Interfaces & Classes ############# class ChannelCredentials(object): - """A value encapsulating the data required to create a secure Channel. + """A value encapsulating the data required to create a secure Channel. This class has no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ - def __init__(self, credentials): - self._credentials = credentials + def __init__(self, credentials): + self._credentials = credentials class CallCredentials(object): - """A value encapsulating data asserting an identity over a channel. + """A value encapsulating data asserting an identity over a channel. A CallCredentials may be composed with ChannelCredentials to always assert identity for every call over that Channel. @@ -375,12 +372,12 @@ class CallCredentials(object): instances and its instances exist to be passed to other functions. """ - def __init__(self, credentials): - self._credentials = credentials + def __init__(self, credentials): + self._credentials = credentials class AuthMetadataContext(six.with_metaclass(abc.ABCMeta)): - """Provides information to call credentials metadata plugins. + """Provides information to call credentials metadata plugins. Attributes: service_url: A string URL of the service being called into. @@ -389,23 +386,23 @@ class AuthMetadataContext(six.with_metaclass(abc.ABCMeta)): class AuthMetadataPluginCallback(six.with_metaclass(abc.ABCMeta)): - """Callback object received by a metadata plugin.""" + """Callback object received by a metadata plugin.""" - def __call__(self, metadata, error): - """Inform the gRPC runtime of the metadata to construct a CallCredentials. + def __call__(self, metadata, error): + """Inform the gRPC runtime of the metadata to construct a CallCredentials. Args: metadata: The :term:`metadata` used to construct the CallCredentials. error: An Exception to indicate error or None to indicate success. """ - raise NotImplementedError() + raise NotImplementedError() class AuthMetadataPlugin(six.with_metaclass(abc.ABCMeta)): - """A specification for custom authentication.""" + """A specification for custom authentication.""" - def __call__(self, context, callback): - """Implements authentication by passing metadata to a callback. + def __call__(self, context, callback): + """Implements authentication by passing metadata to a callback. Implementations of this method must not block. @@ -415,29 +412,29 @@ class AuthMetadataPlugin(six.with_metaclass(abc.ABCMeta)): callback: An AuthMetadataPluginCallback to be invoked either synchronously or asynchronously. """ - raise NotImplementedError() + raise NotImplementedError() class ServerCredentials(object): - """A value encapsulating the data required to open a secure port on a Server. + """A value encapsulating the data required to open a secure port on a Server. This class has no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ - def __init__(self, credentials): - self._credentials = credentials + def __init__(self, credentials): + self._credentials = credentials ######################## Multi-Callable Interfaces ########################### class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-unary RPC.""" + """Affords invoking a unary-unary RPC.""" - @abc.abstractmethod - def __call__(self, request, timeout=None, metadata=None, credentials=None): - """Synchronously invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, request, timeout=None, metadata=None, credentials=None): + """Synchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -454,11 +451,11 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def with_call(self, request, timeout=None, metadata=None, credentials=None): - """Synchronously invokes the underlying RPC. + @abc.abstractmethod + def with_call(self, request, timeout=None, metadata=None, credentials=None): + """Synchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -475,11 +472,11 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def future(self, request, timeout=None, metadata=None, credentials=None): - """Asynchronously invokes the underlying RPC. + @abc.abstractmethod + def future(self, request, timeout=None, metadata=None, credentials=None): + """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -494,15 +491,15 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): message of the RPC. Should the event terminate with non-OK status, the returned Future's exception value will be an RpcError. """ - raise NotImplementedError() + raise NotImplementedError() class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-stream RPC.""" + """Affords invoking a unary-stream RPC.""" - @abc.abstractmethod - def __call__(self, request, timeout=None, metadata=None, credentials=None): - """Invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, request, timeout=None, metadata=None, credentials=None): + """Invokes the underlying RPC. Args: request: The request value for the RPC. @@ -516,16 +513,19 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): values. Drawing response values from the returned iterator may raise RpcError indicating termination of the RPC with non-OK status. """ - raise NotImplementedError() + raise NotImplementedError() class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-unary RPC in any call style.""" + """Affords invoking a stream-unary RPC in any call style.""" - @abc.abstractmethod - def __call__( - self, request_iterator, timeout=None, metadata=None, credentials=None): - """Synchronously invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + """Synchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -543,12 +543,15 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def with_call( - self, request_iterator, timeout=None, metadata=None, credentials=None): - """Synchronously invokes the underlying RPC. + @abc.abstractmethod + def with_call(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + """Synchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -565,12 +568,15 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): raised RpcError will also be a Call for the RPC affording the RPC's metadata, status code, and details. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def future( - self, request_iterator, timeout=None, metadata=None, credentials=None): - """Asynchronously invokes the underlying RPC. + @abc.abstractmethod + def future(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + """Asynchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -585,16 +591,19 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): message of the RPC. Should the event terminate with non-OK status, the returned Future's exception value will be an RpcError. """ - raise NotImplementedError() + raise NotImplementedError() class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-stream RPC in any call style.""" + """Affords invoking a stream-stream RPC in any call style.""" - @abc.abstractmethod - def __call__( - self, request_iterator, timeout=None, metadata=None, credentials=None): - """Invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + """Invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -608,18 +617,18 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): values. Drawing response values from the returned iterator may raise RpcError indicating termination of the RPC with non-OK status. """ - raise NotImplementedError() + raise NotImplementedError() ############################# Channel Interface ############################## class Channel(six.with_metaclass(abc.ABCMeta)): - """Affords RPC invocation via generic methods.""" + """Affords RPC invocation via generic methods.""" - @abc.abstractmethod - def subscribe(self, callback, try_to_connect=False): - """Subscribes to this Channel's connectivity. + @abc.abstractmethod + def subscribe(self, callback, try_to_connect=False): + """Subscribes to this Channel's connectivity. Args: callback: A callable to be invoked and passed a ChannelConnectivity value @@ -631,22 +640,24 @@ class Channel(six.with_metaclass(abc.ABCMeta)): attempt to connect if it is not already connected and ready to conduct RPCs. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def unsubscribe(self, callback): - """Unsubscribes a callback from this Channel's connectivity. + @abc.abstractmethod + def unsubscribe(self, callback): + """Unsubscribes a callback from this Channel's connectivity. Args: callback: A callable previously registered with this Channel from having been passed to its "subscribe" method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def unary_unary( - self, method, request_serializer=None, response_deserializer=None): - """Creates a UnaryUnaryMultiCallable for a unary-unary method. + @abc.abstractmethod + def unary_unary(self, + method, + request_serializer=None, + response_deserializer=None): + """Creates a UnaryUnaryMultiCallable for a unary-unary method. Args: method: The name of the RPC method. @@ -658,12 +669,14 @@ class Channel(six.with_metaclass(abc.ABCMeta)): Returns: A UnaryUnaryMultiCallable value for the named unary-unary method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def unary_stream( - self, method, request_serializer=None, response_deserializer=None): - """Creates a UnaryStreamMultiCallable for a unary-stream method. + @abc.abstractmethod + def unary_stream(self, + method, + request_serializer=None, + response_deserializer=None): + """Creates a UnaryStreamMultiCallable for a unary-stream method. Args: method: The name of the RPC method. @@ -675,12 +688,14 @@ class Channel(six.with_metaclass(abc.ABCMeta)): Returns: A UnaryStreamMultiCallable value for the name unary-stream method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stream_unary( - self, method, request_serializer=None, response_deserializer=None): - """Creates a StreamUnaryMultiCallable for a stream-unary method. + @abc.abstractmethod + def stream_unary(self, + method, + request_serializer=None, + response_deserializer=None): + """Creates a StreamUnaryMultiCallable for a stream-unary method. Args: method: The name of the RPC method. @@ -692,12 +707,14 @@ class Channel(six.with_metaclass(abc.ABCMeta)): Returns: A StreamUnaryMultiCallable value for the named stream-unary method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stream_stream( - self, method, request_serializer=None, response_deserializer=None): - """Creates a StreamStreamMultiCallable for a stream-stream method. + @abc.abstractmethod + def stream_stream(self, + method, + request_serializer=None, + response_deserializer=None): + """Creates a StreamStreamMultiCallable for a stream-stream method. Args: method: The name of the RPC method. @@ -709,36 +726,36 @@ class Channel(six.with_metaclass(abc.ABCMeta)): Returns: A StreamStreamMultiCallable value for the named stream-stream method. """ - raise NotImplementedError() + raise NotImplementedError() ########################## Service-Side Context ############################## class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): - """A context object passed to method implementations.""" + """A context object passed to method implementations.""" - @abc.abstractmethod - def invocation_metadata(self): - """Accesses the metadata from the invocation-side of the RPC. + @abc.abstractmethod + def invocation_metadata(self): + """Accesses the metadata from the invocation-side of the RPC. Returns: The invocation :term:`metadata`. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def peer(self): - """Identifies the peer that invoked the RPC being serviced. + @abc.abstractmethod + def peer(self): + """Identifies the peer that invoked the RPC being serviced. Returns: A string identifying the peer that invoked the RPC being serviced. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def send_initial_metadata(self, initial_metadata): - """Sends the initial metadata value to the invocation-side of the RPC. + @abc.abstractmethod + def send_initial_metadata(self, initial_metadata): + """Sends the initial metadata value to the invocation-side of the RPC. This method need not be called by method implementations if they have no service-side initial metadata to transmit. @@ -746,11 +763,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): Args: initial_metadata: The initial :term:`metadata`. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def set_trailing_metadata(self, trailing_metadata): - """Accepts the trailing metadata value of the RPC. + @abc.abstractmethod + def set_trailing_metadata(self, trailing_metadata): + """Accepts the trailing metadata value of the RPC. This method need not be called by method implementations if they have no service-side trailing metadata to transmit. @@ -758,11 +775,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): Args: trailing_metadata: The trailing :term:`metadata`. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def set_code(self, code): - """Accepts the status code of the RPC. + @abc.abstractmethod + def set_code(self, code): + """Accepts the status code of the RPC. This method need not be called by method implementations if they wish the gRPC runtime to determine the status code of the RPC. @@ -771,11 +788,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): code: A StatusCode value to be transmitted to the invocation side of the RPC as the status code of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def set_details(self, details): - """Accepts the service-side details of the RPC. + @abc.abstractmethod + def set_details(self, details): + """Accepts the service-side details of the RPC. This method need not be called by method implementations if they have no details to transmit. @@ -784,14 +801,14 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): details: A string to be transmitted to the invocation side of the RPC as the status details of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() ##################### Service-Side Handler Interfaces ######################## class RpcMethodHandler(six.with_metaclass(abc.ABCMeta)): - """An implementation of a single RPC method. + """An implementation of a single RPC method. Attributes: request_streaming: Whether the RPC supports exactly one request message or @@ -826,7 +843,7 @@ class RpcMethodHandler(six.with_metaclass(abc.ABCMeta)): class HandlerCallDetails(six.with_metaclass(abc.ABCMeta)): - """Describes an RPC that has just arrived for service. + """Describes an RPC that has just arrived for service. Attributes: method: The method name of the RPC. invocation_metadata: The :term:`metadata` from the invocation side of the RPC. @@ -834,11 +851,11 @@ class HandlerCallDetails(six.with_metaclass(abc.ABCMeta)): class GenericRpcHandler(six.with_metaclass(abc.ABCMeta)): - """An implementation of arbitrarily many RPC methods.""" + """An implementation of arbitrarily many RPC methods.""" - @abc.abstractmethod - def service(self, handler_call_details): - """Services an RPC (or not). + @abc.abstractmethod + def service(self, handler_call_details): + """Services an RPC (or not). Args: handler_call_details: A HandlerCallDetails describing the RPC. @@ -847,11 +864,11 @@ class GenericRpcHandler(six.with_metaclass(abc.ABCMeta)): An RpcMethodHandler with which the RPC may be serviced, or None to indicate that this object will not be servicing the RPC. """ - raise NotImplementedError() + raise NotImplementedError() class ServiceRpcHandler(six.with_metaclass(abc.ABCMeta, GenericRpcHandler)): - """An implementation of RPC methods belonging to a service. + """An implementation of RPC methods belonging to a service. A service handles RPC methods with structured names of the form '/Service.Name/Service.MethodX', where 'Service.Name' is the value @@ -860,25 +877,25 @@ class ServiceRpcHandler(six.with_metaclass(abc.ABCMeta, GenericRpcHandler)): service name. """ - @abc.abstractmethod - def service_name(self): - """Returns this services name. + @abc.abstractmethod + def service_name(self): + """Returns this services name. Returns: The service name. """ - raise NotImplementedError() + raise NotImplementedError() ############################# Server Interface ############################### class Server(six.with_metaclass(abc.ABCMeta)): - """Services RPCs.""" + """Services RPCs.""" - @abc.abstractmethod - def add_generic_rpc_handlers(self, generic_rpc_handlers): - """Registers GenericRpcHandlers with this Server. + @abc.abstractmethod + def add_generic_rpc_handlers(self, generic_rpc_handlers): + """Registers GenericRpcHandlers with this Server. This method is only safe to call before the server is started. @@ -886,11 +903,11 @@ class Server(six.with_metaclass(abc.ABCMeta)): generic_rpc_handlers: An iterable of GenericRpcHandlers that will be used to service RPCs after this Server is started. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_insecure_port(self, address): - """Reserves a port for insecure RPC service once this Server becomes active. + @abc.abstractmethod + def add_insecure_port(self, address): + """Reserves a port for insecure RPC service once this Server becomes active. This method may only be called before calling this Server's start method is called. @@ -904,11 +921,11 @@ class Server(six.with_metaclass(abc.ABCMeta)): in the passed address, but will likely be different if the port number contained in the passed address was zero. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_secure_port(self, address, server_credentials): - """Reserves a port for secure RPC service after this Server becomes active. + @abc.abstractmethod + def add_secure_port(self, address, server_credentials): + """Reserves a port for secure RPC service after this Server becomes active. This method may only be called before calling this Server's start method is called. @@ -923,20 +940,20 @@ class Server(six.with_metaclass(abc.ABCMeta)): in the passed address, but will likely be different if the port number contained in the passed address was zero. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def start(self): - """Starts this Server's service of RPCs. + @abc.abstractmethod + def start(self): + """Starts this Server's service of RPCs. This method may only be called while the server is not serving RPCs (i.e. it is not idempotent). """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stop(self, grace): - """Stops this Server's service of RPCs. + @abc.abstractmethod + def stop(self, grace): + """Stops this Server's service of RPCs. All calls to this method immediately stop service of new RPCs. When existing RPCs are aborted is controlled by the grace period parameter passed to this @@ -967,15 +984,16 @@ class Server(six.with_metaclass(abc.ABCMeta)): at the time it was stopped or if all RPCs that it had underway completed very early in the grace period). """ - raise NotImplementedError() + raise NotImplementedError() ################################# Functions ################################ -def unary_unary_rpc_method_handler( - behavior, request_deserializer=None, response_serializer=None): - """Creates an RpcMethodHandler for a unary-unary RPC method. +def unary_unary_rpc_method_handler(behavior, + request_deserializer=None, + response_serializer=None): + """Creates an RpcMethodHandler for a unary-unary RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking @@ -987,15 +1005,16 @@ def unary_unary_rpc_method_handler( An RpcMethodHandler for a unary-unary RPC method constructed from the given parameters. """ - from grpc import _utilities - return _utilities.RpcMethodHandler( - False, False, request_deserializer, response_serializer, behavior, None, - None, None) + from grpc import _utilities + return _utilities.RpcMethodHandler(False, False, request_deserializer, + response_serializer, behavior, None, + None, None) -def unary_stream_rpc_method_handler( - behavior, request_deserializer=None, response_serializer=None): - """Creates an RpcMethodHandler for a unary-stream RPC method. +def unary_stream_rpc_method_handler(behavior, + request_deserializer=None, + response_serializer=None): + """Creates an RpcMethodHandler for a unary-stream RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking @@ -1007,15 +1026,16 @@ def unary_stream_rpc_method_handler( An RpcMethodHandler for a unary-stream RPC method constructed from the given parameters. """ - from grpc import _utilities - return _utilities.RpcMethodHandler( - False, True, request_deserializer, response_serializer, None, behavior, - None, None) + from grpc import _utilities + return _utilities.RpcMethodHandler(False, True, request_deserializer, + response_serializer, None, behavior, + None, None) -def stream_unary_rpc_method_handler( - behavior, request_deserializer=None, response_serializer=None): - """Creates an RpcMethodHandler for a stream-unary RPC method. +def stream_unary_rpc_method_handler(behavior, + request_deserializer=None, + response_serializer=None): + """Creates an RpcMethodHandler for a stream-unary RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking @@ -1027,15 +1047,16 @@ def stream_unary_rpc_method_handler( An RpcMethodHandler for a stream-unary RPC method constructed from the given parameters. """ - from grpc import _utilities - return _utilities.RpcMethodHandler( - True, False, request_deserializer, response_serializer, None, None, - behavior, None) + from grpc import _utilities + return _utilities.RpcMethodHandler(True, False, request_deserializer, + response_serializer, None, None, + behavior, None) -def stream_stream_rpc_method_handler( - behavior, request_deserializer=None, response_serializer=None): - """Creates an RpcMethodHandler for a stream-stream RPC method. +def stream_stream_rpc_method_handler(behavior, + request_deserializer=None, + response_serializer=None): + """Creates an RpcMethodHandler for a stream-stream RPC method. Args: behavior: The implementation of an RPC method as a callable behavior taking @@ -1048,14 +1069,14 @@ def stream_stream_rpc_method_handler( An RpcMethodHandler for a stream-stream RPC method constructed from the given parameters. """ - from grpc import _utilities - return _utilities.RpcMethodHandler( - True, True, request_deserializer, response_serializer, None, None, None, - behavior) + from grpc import _utilities + return _utilities.RpcMethodHandler(True, True, request_deserializer, + response_serializer, None, None, None, + behavior) def method_handlers_generic_handler(service, method_handlers): - """Creates a grpc.GenericRpcHandler from RpcMethodHandlers. + """Creates a grpc.GenericRpcHandler from RpcMethodHandlers. Args: service: A service name to be used for the given method handlers. @@ -1065,13 +1086,14 @@ def method_handlers_generic_handler(service, method_handlers): Returns: A GenericRpcHandler constructed from the given parameters. """ - from grpc import _utilities - return _utilities.DictionaryGenericHandler(service, method_handlers) + from grpc import _utilities + return _utilities.DictionaryGenericHandler(service, method_handlers) -def ssl_channel_credentials( - root_certificates=None, private_key=None, certificate_chain=None): - """Creates a ChannelCredentials for use with an SSL-enabled Channel. +def ssl_channel_credentials(root_certificates=None, + private_key=None, + certificate_chain=None): + """Creates a ChannelCredentials for use with an SSL-enabled Channel. Args: root_certificates: The PEM-encoded root certificates or unset to ask for @@ -1084,16 +1106,16 @@ def ssl_channel_credentials( Returns: A ChannelCredentials for use with an SSL-enabled Channel. """ - if private_key is not None or certificate_chain is not None: - pair = _cygrpc.SslPemKeyCertPair(private_key, certificate_chain) - else: - pair = None - return ChannelCredentials( - _cygrpc.channel_credentials_ssl(root_certificates, pair)) + if private_key is not None or certificate_chain is not None: + pair = _cygrpc.SslPemKeyCertPair(private_key, certificate_chain) + else: + pair = None + return ChannelCredentials( + _cygrpc.channel_credentials_ssl(root_certificates, pair)) def metadata_call_credentials(metadata_plugin, name=None): - """Construct CallCredentials from an AuthMetadataPlugin. + """Construct CallCredentials from an AuthMetadataPlugin. Args: metadata_plugin: An AuthMetadataPlugin to use as the authentication behavior @@ -1103,21 +1125,21 @@ def metadata_call_credentials(metadata_plugin, name=None): Returns: A CallCredentials. """ - from grpc import _plugin_wrapping - if name is None: - try: - effective_name = metadata_plugin.__name__ - except AttributeError: - effective_name = metadata_plugin.__class__.__name__ - else: - effective_name = name - return CallCredentials( - _plugin_wrapping.call_credentials_metadata_plugin( - metadata_plugin, effective_name)) + from grpc import _plugin_wrapping + if name is None: + try: + effective_name = metadata_plugin.__name__ + except AttributeError: + effective_name = metadata_plugin.__class__.__name__ + else: + effective_name = name + return CallCredentials( + _plugin_wrapping.call_credentials_metadata_plugin(metadata_plugin, + effective_name)) def access_token_call_credentials(access_token): - """Construct CallCredentials from an access token. + """Construct CallCredentials from an access token. Args: access_token: A string to place directly in the http request @@ -1126,13 +1148,13 @@ def access_token_call_credentials(access_token): Returns: A CallCredentials. """ - from grpc import _auth - return metadata_call_credentials( - _auth.AccessTokenCallCredentials(access_token)) + from grpc import _auth + return metadata_call_credentials( + _auth.AccessTokenCallCredentials(access_token)) def composite_call_credentials(*call_credentials): - """Compose multiple CallCredentials to make a new CallCredentials. + """Compose multiple CallCredentials to make a new CallCredentials. Args: *call_credentials: At least two CallCredentials objects. @@ -1140,16 +1162,16 @@ def composite_call_credentials(*call_credentials): Returns: A CallCredentials object composed of the given CallCredentials objects. """ - from grpc import _credential_composition - cygrpc_call_credentials = tuple( - single_call_credentials._credentials - for single_call_credentials in call_credentials) - return CallCredentials( - _credential_composition.call(cygrpc_call_credentials)) + from grpc import _credential_composition + cygrpc_call_credentials = tuple( + single_call_credentials._credentials + for single_call_credentials in call_credentials) + return CallCredentials( + _credential_composition.call(cygrpc_call_credentials)) def composite_channel_credentials(channel_credentials, *call_credentials): - """Compose a ChannelCredentials and one or more CallCredentials objects. + """Compose a ChannelCredentials and one or more CallCredentials objects. Args: channel_credentials: A ChannelCredentials. @@ -1159,19 +1181,19 @@ def composite_channel_credentials(channel_credentials, *call_credentials): A ChannelCredentials composed of the given ChannelCredentials and CallCredentials objects. """ - from grpc import _credential_composition - cygrpc_call_credentials = tuple( - single_call_credentials._credentials - for single_call_credentials in call_credentials) - return ChannelCredentials( - _credential_composition.channel( - channel_credentials._credentials, cygrpc_call_credentials)) + from grpc import _credential_composition + cygrpc_call_credentials = tuple( + single_call_credentials._credentials + for single_call_credentials in call_credentials) + return ChannelCredentials( + _credential_composition.channel(channel_credentials._credentials, + cygrpc_call_credentials)) -def ssl_server_credentials( - private_key_certificate_chain_pairs, root_certificates=None, - require_client_auth=False): - """Creates a ServerCredentials for use with an SSL-enabled Server. +def ssl_server_credentials(private_key_certificate_chain_pairs, + root_certificates=None, + require_client_auth=False): + """Creates a ServerCredentials for use with an SSL-enabled Server. Args: private_key_certificate_chain_pairs: A nonempty sequence each element of @@ -1187,23 +1209,23 @@ def ssl_server_credentials( Returns: A ServerCredentials for use with an SSL-enabled Server. """ - if len(private_key_certificate_chain_pairs) == 0: - raise ValueError( - 'At least one private key-certificate chain pair is required!') - elif require_client_auth and root_certificates is None: - raise ValueError( - 'Illegal to require client auth without providing root certificates!') - else: - return ServerCredentials( - _cygrpc.server_credentials_ssl( - root_certificates, - [_cygrpc.SslPemKeyCertPair(key, pem) - for key, pem in private_key_certificate_chain_pairs], - require_client_auth)) + if len(private_key_certificate_chain_pairs) == 0: + raise ValueError( + 'At least one private key-certificate chain pair is required!') + elif require_client_auth and root_certificates is None: + raise ValueError( + 'Illegal to require client auth without providing root certificates!' + ) + else: + return ServerCredentials( + _cygrpc.server_credentials_ssl(root_certificates, [ + _cygrpc.SslPemKeyCertPair(key, pem) + for key, pem in private_key_certificate_chain_pairs + ], require_client_auth)) def channel_ready_future(channel): - """Creates a Future tracking when a Channel is ready. + """Creates a Future tracking when a Channel is ready. Cancelling the returned Future does not tell the given Channel to abandon attempts it may have been making to connect; cancelling merely deactivates the @@ -1216,12 +1238,12 @@ def channel_ready_future(channel): A Future that matures when the given Channel has connectivity ChannelConnectivity.READY. """ - from grpc import _utilities - return _utilities.channel_ready_future(channel) + from grpc import _utilities + return _utilities.channel_ready_future(channel) def insecure_channel(target, options=None): - """Creates an insecure Channel to a server. + """Creates an insecure Channel to a server. Args: target: The target to which to connect. @@ -1231,12 +1253,12 @@ def insecure_channel(target, options=None): Returns: A Channel to the target through which RPCs may be conducted. """ - from grpc import _channel - return _channel.Channel(target, () if options is None else options, None) + from grpc import _channel + return _channel.Channel(target, () if options is None else options, None) def secure_channel(target, credentials, options=None): - """Creates a secure Channel to a server. + """Creates a secure Channel to a server. Args: target: The target to which to connect. @@ -1247,13 +1269,13 @@ def secure_channel(target, credentials, options=None): Returns: A Channel to the target through which RPCs may be conducted. """ - from grpc import _channel - return _channel.Channel(target, () if options is None else options, - credentials._credentials) + from grpc import _channel + return _channel.Channel(target, () if options is None else options, + credentials._credentials) def server(thread_pool, handlers=None, options=None): - """Creates a Server with which RPCs can be serviced. + """Creates a Server with which RPCs can be serviced. Args: thread_pool: A futures.ThreadPoolExecutor to be used by the returned Server @@ -1269,14 +1291,13 @@ def server(thread_pool, handlers=None, options=None): Returns: A Server with which RPCs can be serviced. """ - from grpc import _server - return _server.Server(thread_pool, () if handlers is None else handlers, - () if options is None else options) + from grpc import _server + return _server.Server(thread_pool, () if handlers is None else handlers, () + if options is None else options) ################################### __all__ ################################# - __all__ = ( 'FutureTimeoutError', 'FutureCancelledError', @@ -1317,26 +1338,23 @@ __all__ = ( 'channel_ready_future', 'insecure_channel', 'secure_channel', - 'server', -) - + 'server',) ############################### Extension Shims ################################ - # Here to maintain backwards compatibility; avoid using these in new code! try: - import grpc_tools - sys.modules.update({'grpc.tools': grpc_tools}) + import grpc_tools + sys.modules.update({'grpc.tools': grpc_tools}) except ImportError: - pass + pass try: - import grpc_health - sys.modules.update({'grpc.health': grpc_health}) + import grpc_health + sys.modules.update({'grpc.health': grpc_health}) except ImportError: - pass + pass try: - import grpc_reflection - sys.modules.update({'grpc.reflection': grpc_reflection}) + import grpc_reflection + sys.modules.update({'grpc.reflection': grpc_reflection}) except ImportError: - pass + pass diff --git a/src/python/grpcio/grpc/_auth.py b/src/python/grpcio/grpc/_auth.py index dea3221c9d8..e8a90cf5047 100644 --- a/src/python/grpcio/grpc/_auth.py +++ b/src/python/grpcio/grpc/_auth.py @@ -26,7 +26,6 @@ # 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. - """GRPCAuthMetadataPlugins for standard authentication.""" import inspect @@ -36,51 +35,53 @@ import grpc def _sign_request(callback, token, error): - metadata = (('authorization', 'Bearer {}'.format(token)),) - callback(metadata, error) + metadata = (('authorization', 'Bearer {}'.format(token)),) + callback(metadata, error) class GoogleCallCredentials(grpc.AuthMetadataPlugin): - """Metadata wrapper for GoogleCredentials from the oauth2client library.""" - - def __init__(self, credentials): - self._credentials = credentials - self._pool = futures.ThreadPoolExecutor(max_workers=1) - - # Hack to determine if these are JWT creds and we need to pass - # additional_claims when getting a token - if 'additional_claims' in inspect.getargspec( - credentials.get_access_token).args: - self._is_jwt = True - else: - self._is_jwt = False - - def __call__(self, context, callback): - # MetadataPlugins cannot block (see grpc.beta.interfaces.py) - if self._is_jwt: - future = self._pool.submit(self._credentials.get_access_token, - additional_claims={'aud': context.service_url}) - else: - future = self._pool.submit(self._credentials.get_access_token) - future.add_done_callback(lambda x: self._get_token_callback(callback, x)) - - def _get_token_callback(self, callback, future): - try: - access_token = future.result().access_token - except Exception as e: - _sign_request(callback, None, e) - else: - _sign_request(callback, access_token, None) - - def __del__(self): - self._pool.shutdown(wait=False) + """Metadata wrapper for GoogleCredentials from the oauth2client library.""" + + def __init__(self, credentials): + self._credentials = credentials + self._pool = futures.ThreadPoolExecutor(max_workers=1) + + # Hack to determine if these are JWT creds and we need to pass + # additional_claims when getting a token + if 'additional_claims' in inspect.getargspec( + credentials.get_access_token).args: + self._is_jwt = True + else: + self._is_jwt = False + + def __call__(self, context, callback): + # MetadataPlugins cannot block (see grpc.beta.interfaces.py) + if self._is_jwt: + future = self._pool.submit( + self._credentials.get_access_token, + additional_claims={'aud': context.service_url}) + else: + future = self._pool.submit(self._credentials.get_access_token) + future.add_done_callback( + lambda x: self._get_token_callback(callback, x)) + + def _get_token_callback(self, callback, future): + try: + access_token = future.result().access_token + except Exception as e: + _sign_request(callback, None, e) + else: + _sign_request(callback, access_token, None) + + def __del__(self): + self._pool.shutdown(wait=False) class AccessTokenCallCredentials(grpc.AuthMetadataPlugin): - """Metadata wrapper for raw access token credentials.""" + """Metadata wrapper for raw access token credentials.""" - def __init__(self, access_token): - self._access_token = access_token + def __init__(self, access_token): + self._access_token = access_token - def __call__(self, context, callback): - _sign_request(callback, self._access_token, None) + def __call__(self, context, callback): + _sign_request(callback, self._access_token, None) diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py index e8c6a99cb18..77412236cc6 100644 --- a/src/python/grpcio/grpc/_channel.py +++ b/src/python/grpcio/grpc/_channel.py @@ -26,7 +26,6 @@ # 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. - """Invocation-side implementation of gRPC Python.""" import sys @@ -52,692 +51,710 @@ _UNARY_UNARY_INITIAL_DUE = ( cygrpc.OperationType.send_close_from_client, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_message, - cygrpc.OperationType.receive_status_on_client, -) + cygrpc.OperationType.receive_status_on_client,) _UNARY_STREAM_INITIAL_DUE = ( cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.send_message, cygrpc.OperationType.send_close_from_client, cygrpc.OperationType.receive_initial_metadata, - cygrpc.OperationType.receive_status_on_client, -) + cygrpc.OperationType.receive_status_on_client,) _STREAM_UNARY_INITIAL_DUE = ( cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.receive_initial_metadata, cygrpc.OperationType.receive_message, - cygrpc.OperationType.receive_status_on_client, -) + cygrpc.OperationType.receive_status_on_client,) _STREAM_STREAM_INITIAL_DUE = ( cygrpc.OperationType.send_initial_metadata, cygrpc.OperationType.receive_initial_metadata, - cygrpc.OperationType.receive_status_on_client, -) + cygrpc.OperationType.receive_status_on_client,) _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = ( 'Exception calling channel subscription callback!') def _deadline(timeout): - if timeout is None: - return None, _INFINITE_FUTURE - else: - deadline = time.time() + timeout - return deadline, cygrpc.Timespec(deadline) + if timeout is None: + return None, _INFINITE_FUTURE + else: + deadline = time.time() + timeout + return deadline, cygrpc.Timespec(deadline) def _unknown_code_details(unknown_cygrpc_code, details): - return 'Server sent unknown code {} and details "{}"'.format( - unknown_cygrpc_code, details) + return 'Server sent unknown code {} and details "{}"'.format( + unknown_cygrpc_code, details) def _wait_once_until(condition, until): - if until is None: - condition.wait() - else: - remaining = until - time.time() - if remaining < 0: - raise grpc.FutureTimeoutError() + if until is None: + condition.wait() else: - condition.wait(timeout=remaining) + remaining = until - time.time() + if remaining < 0: + raise grpc.FutureTimeoutError() + else: + condition.wait(timeout=remaining) + _INTERNAL_CALL_ERROR_MESSAGE_FORMAT = ( 'Internal gRPC call error %d. ' + 'Please report to https://github.com/grpc/grpc/issues') + def _check_call_error(call_error, metadata): - if call_error == cygrpc.CallError.invalid_metadata: - raise ValueError('metadata was invalid: %s' % metadata) - elif call_error != cygrpc.CallError.ok: - raise ValueError(_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) + if call_error == cygrpc.CallError.invalid_metadata: + raise ValueError('metadata was invalid: %s' % metadata) + elif call_error != cygrpc.CallError.ok: + raise ValueError(_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) + def _call_error_set_RPCstate(state, call_error, metadata): - if call_error == cygrpc.CallError.invalid_metadata: - _abort(state, grpc.StatusCode.INTERNAL, 'metadata was invalid: %s' % metadata) - else: - _abort(state, grpc.StatusCode.INTERNAL, - _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) + if call_error == cygrpc.CallError.invalid_metadata: + _abort(state, grpc.StatusCode.INTERNAL, + 'metadata was invalid: %s' % metadata) + else: + _abort(state, grpc.StatusCode.INTERNAL, + _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) + class _RPCState(object): - def __init__(self, due, initial_metadata, trailing_metadata, code, details): - self.condition = threading.Condition() - # The cygrpc.OperationType objects representing events due from the RPC's - # completion queue. - self.due = set(due) - self.initial_metadata = initial_metadata - self.response = None - self.trailing_metadata = trailing_metadata - self.code = code - self.details = details - # The semantics of grpc.Future.cancel and grpc.Future.cancelled are - # slightly wonky, so they have to be tracked separately from the rest of the - # result of the RPC. This field tracks whether cancellation was requested - # prior to termination of the RPC. - self.cancelled = False - self.callbacks = [] + def __init__(self, due, initial_metadata, trailing_metadata, code, details): + self.condition = threading.Condition() + # The cygrpc.OperationType objects representing events due from the RPC's + # completion queue. + self.due = set(due) + self.initial_metadata = initial_metadata + self.response = None + self.trailing_metadata = trailing_metadata + self.code = code + self.details = details + # The semantics of grpc.Future.cancel and grpc.Future.cancelled are + # slightly wonky, so they have to be tracked separately from the rest of the + # result of the RPC. This field tracks whether cancellation was requested + # prior to termination of the RPC. + self.cancelled = False + self.callbacks = [] def _abort(state, code, details): - if state.code is None: - state.code = code - state.details = details - if state.initial_metadata is None: - state.initial_metadata = _EMPTY_METADATA - state.trailing_metadata = _EMPTY_METADATA + if state.code is None: + state.code = code + state.details = details + if state.initial_metadata is None: + state.initial_metadata = _EMPTY_METADATA + state.trailing_metadata = _EMPTY_METADATA def _handle_event(event, state, response_deserializer): - callbacks = [] - for batch_operation in event.batch_operations: - operation_type = batch_operation.type - state.due.remove(operation_type) - if operation_type == cygrpc.OperationType.receive_initial_metadata: - state.initial_metadata = batch_operation.received_metadata - elif operation_type == cygrpc.OperationType.receive_message: - serialized_response = batch_operation.received_message.bytes() - if serialized_response is not None: - response = _common.deserialize( - serialized_response, response_deserializer) - if response is None: - details = 'Exception deserializing response!' - _abort(state, grpc.StatusCode.INTERNAL, details) - else: - state.response = response - elif operation_type == cygrpc.OperationType.receive_status_on_client: - state.trailing_metadata = batch_operation.received_metadata - if state.code is None: - code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get( - batch_operation.received_status_code) - if code is None: - state.code = grpc.StatusCode.UNKNOWN - state.details = _unknown_code_details( - batch_operation.received_status_code, - batch_operation.received_status_details) - else: - state.code = code - state.details = batch_operation.received_status_details - callbacks.extend(state.callbacks) - state.callbacks = None - return callbacks + callbacks = [] + for batch_operation in event.batch_operations: + operation_type = batch_operation.type + state.due.remove(operation_type) + if operation_type == cygrpc.OperationType.receive_initial_metadata: + state.initial_metadata = batch_operation.received_metadata + elif operation_type == cygrpc.OperationType.receive_message: + serialized_response = batch_operation.received_message.bytes() + if serialized_response is not None: + response = _common.deserialize(serialized_response, + response_deserializer) + if response is None: + details = 'Exception deserializing response!' + _abort(state, grpc.StatusCode.INTERNAL, details) + else: + state.response = response + elif operation_type == cygrpc.OperationType.receive_status_on_client: + state.trailing_metadata = batch_operation.received_metadata + if state.code is None: + code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get( + batch_operation.received_status_code) + if code is None: + state.code = grpc.StatusCode.UNKNOWN + state.details = _unknown_code_details( + batch_operation.received_status_code, + batch_operation.received_status_details) + else: + state.code = code + state.details = batch_operation.received_status_details + callbacks.extend(state.callbacks) + state.callbacks = None + return callbacks def _event_handler(state, call, response_deserializer): - def handle_event(event): - with state.condition: - callbacks = _handle_event(event, state, response_deserializer) - state.condition.notify_all() - done = not state.due - for callback in callbacks: - callback() - return call if done else None - return handle_event - - -def _consume_request_iterator( - request_iterator, state, call, request_serializer): - event_handler = _event_handler(state, call, None) - - def consume_request_iterator(): - while True: - try: - request = next(request_iterator) - except StopIteration: - break - except Exception as e: - logging.exception("Exception iterating requests!") - call.cancel() - _abort(state, grpc.StatusCode.UNKNOWN, "Exception iterating requests!") - return - serialized_request = _common.serialize(request, request_serializer) - with state.condition: - if state.code is None and not state.cancelled: - if serialized_request is None: - call.cancel() - details = 'Exception serializing request!' - _abort(state, grpc.StatusCode.INTERNAL, details) - return - else: - operations = ( - cygrpc.operation_send_message( - serialized_request, _EMPTY_FLAGS), - ) - call.start_client_batch(cygrpc.Operations(operations), - event_handler) - state.due.add(cygrpc.OperationType.send_message) - while True: - state.condition.wait() - if state.code is None: - if cygrpc.OperationType.send_message not in state.due: - break - else: + + def handle_event(event): + with state.condition: + callbacks = _handle_event(event, state, response_deserializer) + state.condition.notify_all() + done = not state.due + for callback in callbacks: + callback() + return call if done else None + + return handle_event + + +def _consume_request_iterator(request_iterator, state, call, + request_serializer): + event_handler = _event_handler(state, call, None) + + def consume_request_iterator(): + while True: + try: + request = next(request_iterator) + except StopIteration: + break + except Exception as e: + logging.exception("Exception iterating requests!") + call.cancel() + _abort(state, grpc.StatusCode.UNKNOWN, + "Exception iterating requests!") return - else: - return - with state.condition: - if state.code is None: - operations = ( - cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), - ) - call.start_client_batch(cygrpc.Operations(operations), event_handler) - state.due.add(cygrpc.OperationType.send_close_from_client) - - def stop_consumption_thread(timeout): - with state.condition: - if state.code is None: - call.cancel() - state.cancelled = True - _abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!') - state.condition.notify_all() - - consumption_thread = _common.CleanupThread( - stop_consumption_thread, target=consume_request_iterator) - consumption_thread.start() + serialized_request = _common.serialize(request, request_serializer) + with state.condition: + if state.code is None and not state.cancelled: + if serialized_request is None: + call.cancel() + details = 'Exception serializing request!' + _abort(state, grpc.StatusCode.INTERNAL, details) + return + else: + operations = (cygrpc.operation_send_message( + serialized_request, _EMPTY_FLAGS),) + call.start_client_batch( + cygrpc.Operations(operations), event_handler) + state.due.add(cygrpc.OperationType.send_message) + while True: + state.condition.wait() + if state.code is None: + if cygrpc.OperationType.send_message not in state.due: + break + else: + return + else: + return + with state.condition: + if state.code is None: + operations = ( + cygrpc.operation_send_close_from_client(_EMPTY_FLAGS),) + call.start_client_batch( + cygrpc.Operations(operations), event_handler) + state.due.add(cygrpc.OperationType.send_close_from_client) + + def stop_consumption_thread(timeout): + with state.condition: + if state.code is None: + call.cancel() + state.cancelled = True + _abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!') + state.condition.notify_all() + + consumption_thread = _common.CleanupThread( + stop_consumption_thread, target=consume_request_iterator) + consumption_thread.start() class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): - def __init__(self, state, call, response_deserializer, deadline): - super(_Rendezvous, self).__init__() - self._state = state - self._call = call - self._response_deserializer = response_deserializer - self._deadline = deadline - - def cancel(self): - with self._state.condition: - if self._state.code is None: - self._call.cancel() - self._state.cancelled = True - _abort(self._state, grpc.StatusCode.CANCELLED, 'Cancelled!') - self._state.condition.notify_all() - return False - - def cancelled(self): - with self._state.condition: - return self._state.cancelled - - def running(self): - with self._state.condition: - return self._state.code is None - - def done(self): - with self._state.condition: - return self._state.code is not None - - def result(self, timeout=None): - until = None if timeout is None else time.time() + timeout - with self._state.condition: - while True: - if self._state.code is None: - _wait_once_until(self._state.condition, until) - elif self._state.code is grpc.StatusCode.OK: - return self._state.response - elif self._state.cancelled: - raise grpc.FutureCancelledError() - else: - raise self - - def exception(self, timeout=None): - until = None if timeout is None else time.time() + timeout - with self._state.condition: - while True: - if self._state.code is None: - _wait_once_until(self._state.condition, until) - elif self._state.code is grpc.StatusCode.OK: - return None - elif self._state.cancelled: - raise grpc.FutureCancelledError() - else: - return self - - def traceback(self, timeout=None): - until = None if timeout is None else time.time() + timeout - with self._state.condition: - while True: - if self._state.code is None: - _wait_once_until(self._state.condition, until) - elif self._state.code is grpc.StatusCode.OK: - return None - elif self._state.cancelled: - raise grpc.FutureCancelledError() + def __init__(self, state, call, response_deserializer, deadline): + super(_Rendezvous, self).__init__() + self._state = state + self._call = call + self._response_deserializer = response_deserializer + self._deadline = deadline + + def cancel(self): + with self._state.condition: + if self._state.code is None: + self._call.cancel() + self._state.cancelled = True + _abort(self._state, grpc.StatusCode.CANCELLED, 'Cancelled!') + self._state.condition.notify_all() + return False + + def cancelled(self): + with self._state.condition: + return self._state.cancelled + + def running(self): + with self._state.condition: + return self._state.code is None + + def done(self): + with self._state.condition: + return self._state.code is not None + + def result(self, timeout=None): + until = None if timeout is None else time.time() + timeout + with self._state.condition: + while True: + if self._state.code is None: + _wait_once_until(self._state.condition, until) + elif self._state.code is grpc.StatusCode.OK: + return self._state.response + elif self._state.cancelled: + raise grpc.FutureCancelledError() + else: + raise self + + def exception(self, timeout=None): + until = None if timeout is None else time.time() + timeout + with self._state.condition: + while True: + if self._state.code is None: + _wait_once_until(self._state.condition, until) + elif self._state.code is grpc.StatusCode.OK: + return None + elif self._state.cancelled: + raise grpc.FutureCancelledError() + else: + return self + + def traceback(self, timeout=None): + until = None if timeout is None else time.time() + timeout + with self._state.condition: + while True: + if self._state.code is None: + _wait_once_until(self._state.condition, until) + elif self._state.code is grpc.StatusCode.OK: + return None + elif self._state.cancelled: + raise grpc.FutureCancelledError() + else: + try: + raise self + except grpc.RpcError: + return sys.exc_info()[2] + + def add_done_callback(self, fn): + with self._state.condition: + if self._state.code is None: + self._state.callbacks.append(lambda: fn(self)) + return + + fn(self) + + def _next(self): + with self._state.condition: + if self._state.code is None: + event_handler = _event_handler(self._state, self._call, + self._response_deserializer) + self._call.start_client_batch( + cygrpc.Operations( + (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), + event_handler) + self._state.due.add(cygrpc.OperationType.receive_message) + elif self._state.code is grpc.StatusCode.OK: + raise StopIteration() + else: + raise self + while True: + self._state.condition.wait() + if self._state.response is not None: + response = self._state.response + self._state.response = None + return response + elif cygrpc.OperationType.receive_message not in self._state.due: + if self._state.code is grpc.StatusCode.OK: + raise StopIteration() + elif self._state.code is not None: + raise self + + def __iter__(self): + return self + + def __next__(self): + return self._next() + + def next(self): + return self._next() + + def is_active(self): + with self._state.condition: + return self._state.code is None + + def time_remaining(self): + if self._deadline is None: + return None else: - try: - raise self - except grpc.RpcError: - return sys.exc_info()[2] - - def add_done_callback(self, fn): - with self._state.condition: - if self._state.code is None: - self._state.callbacks.append(lambda: fn(self)) - return - - fn(self) - - def _next(self): - with self._state.condition: - if self._state.code is None: - event_handler = _event_handler( - self._state, self._call, self._response_deserializer) - self._call.start_client_batch( - cygrpc.Operations( - (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), - event_handler) - self._state.due.add(cygrpc.OperationType.receive_message) - elif self._state.code is grpc.StatusCode.OK: - raise StopIteration() - else: - raise self - while True: - self._state.condition.wait() - if self._state.response is not None: - response = self._state.response - self._state.response = None - return response - elif cygrpc.OperationType.receive_message not in self._state.due: - if self._state.code is grpc.StatusCode.OK: - raise StopIteration() - elif self._state.code is not None: - raise self - - def __iter__(self): - return self - - def __next__(self): - return self._next() - - def next(self): - return self._next() - - def is_active(self): - with self._state.condition: - return self._state.code is None - - def time_remaining(self): - if self._deadline is None: - return None - else: - return max(self._deadline - time.time(), 0) - - def add_callback(self, callback): - with self._state.condition: - if self._state.callbacks is None: - return False - else: - self._state.callbacks.append(callback) - return True - - def initial_metadata(self): - with self._state.condition: - while self._state.initial_metadata is None: - self._state.condition.wait() - return _common.application_metadata(self._state.initial_metadata) - - def trailing_metadata(self): - with self._state.condition: - while self._state.trailing_metadata is None: - self._state.condition.wait() - return _common.application_metadata(self._state.trailing_metadata) - - def code(self): - with self._state.condition: - while self._state.code is None: - self._state.condition.wait() - return self._state.code - - def details(self): - with self._state.condition: - while self._state.details is None: - self._state.condition.wait() - return _common.decode(self._state.details) - - def _repr(self): - with self._state.condition: - if self._state.code is None: - return '<_Rendezvous object of in-flight RPC>' - else: - return '<_Rendezvous of RPC that terminated with ({}, {})>'.format( - self._state.code, _common.decode(self._state.details)) - - def __repr__(self): - return self._repr() - - def __str__(self): - return self._repr() - - def __del__(self): - with self._state.condition: - if self._state.code is None: - self._call.cancel() - self._state.cancelled = True - self._state.code = grpc.StatusCode.CANCELLED - self._state.condition.notify_all() + return max(self._deadline - time.time(), 0) + + def add_callback(self, callback): + with self._state.condition: + if self._state.callbacks is None: + return False + else: + self._state.callbacks.append(callback) + return True + + def initial_metadata(self): + with self._state.condition: + while self._state.initial_metadata is None: + self._state.condition.wait() + return _common.application_metadata(self._state.initial_metadata) + + def trailing_metadata(self): + with self._state.condition: + while self._state.trailing_metadata is None: + self._state.condition.wait() + return _common.application_metadata(self._state.trailing_metadata) + + def code(self): + with self._state.condition: + while self._state.code is None: + self._state.condition.wait() + return self._state.code + + def details(self): + with self._state.condition: + while self._state.details is None: + self._state.condition.wait() + return _common.decode(self._state.details) + + def _repr(self): + with self._state.condition: + if self._state.code is None: + return '<_Rendezvous object of in-flight RPC>' + else: + return '<_Rendezvous of RPC that terminated with ({}, {})>'.format( + self._state.code, _common.decode(self._state.details)) + + def __repr__(self): + return self._repr() + + def __str__(self): + return self._repr() + + def __del__(self): + with self._state.condition: + if self._state.code is None: + self._call.cancel() + self._state.cancelled = True + self._state.code = grpc.StatusCode.CANCELLED + self._state.condition.notify_all() def _start_unary_request(request, timeout, request_serializer): - deadline, deadline_timespec = _deadline(timeout) - serialized_request = _common.serialize(request, request_serializer) - if serialized_request is None: - state = _RPCState( - (), _EMPTY_METADATA, _EMPTY_METADATA, grpc.StatusCode.INTERNAL, - 'Exception serializing request!') - rendezvous = _Rendezvous(state, None, None, deadline) - return deadline, deadline_timespec, None, rendezvous - else: - return deadline, deadline_timespec, serialized_request, None + deadline, deadline_timespec = _deadline(timeout) + serialized_request = _common.serialize(request, request_serializer) + if serialized_request is None: + state = _RPCState((), _EMPTY_METADATA, _EMPTY_METADATA, + grpc.StatusCode.INTERNAL, + 'Exception serializing request!') + rendezvous = _Rendezvous(state, None, None, deadline) + return deadline, deadline_timespec, None, rendezvous + else: + return deadline, deadline_timespec, serialized_request, None def _end_unary_response_blocking(state, with_call, deadline): - if state.code is grpc.StatusCode.OK: - if with_call: - rendezvous = _Rendezvous(state, None, None, deadline) - return state.response, rendezvous + if state.code is grpc.StatusCode.OK: + if with_call: + rendezvous = _Rendezvous(state, None, None, deadline) + return state.response, rendezvous + else: + return state.response else: - return state.response - else: - raise _Rendezvous(state, None, None, deadline) + raise _Rendezvous(state, None, None, deadline) class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): - def __init__( - self, channel, managed_call, method, request_serializer, - response_deserializer): - self._channel = channel - self._managed_call = managed_call - self._method = method - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def _prepare(self, request, timeout, metadata): - deadline, deadline_timespec, serialized_request, rendezvous = ( - _start_unary_request(request, timeout, self._request_serializer)) - if serialized_request is None: - return None, None, None, None, rendezvous - else: - state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None) - operations = ( - cygrpc.operation_send_initial_metadata( - _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), - cygrpc.operation_send_message(serialized_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), - ) - return state, operations, deadline, deadline_timespec, None - - def _blocking(self, request, timeout, metadata, credentials): - state, operations, deadline, deadline_timespec, rendezvous = self._prepare( - request, timeout, metadata) - if rendezvous: - raise rendezvous - else: - completion_queue = cygrpc.CompletionQueue() - call = self._channel.create_call( - None, 0, completion_queue, self._method, None, deadline_timespec) - if credentials is not None: - call.set_credentials(credentials._credentials) - call_error = call.start_client_batch(cygrpc.Operations(operations), None) - _check_call_error(call_error, metadata) - _handle_event(completion_queue.poll(), state, self._response_deserializer) - return state, deadline - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - state, deadline, = self._blocking(request, timeout, metadata, credentials) - return _end_unary_response_blocking(state, False, deadline) - - def with_call(self, request, timeout=None, metadata=None, credentials=None): - state, deadline, = self._blocking(request, timeout, metadata, credentials) - return _end_unary_response_blocking(state, True, deadline) - - def future(self, request, timeout=None, metadata=None, credentials=None): - state, operations, deadline, deadline_timespec, rendezvous = self._prepare( - request, timeout, metadata) - if rendezvous: - return rendezvous - else: - call, drive_call = self._managed_call( - None, 0, self._method, None, deadline_timespec) - if credentials is not None: - call.set_credentials(credentials._credentials) - event_handler = _event_handler(state, call, self._response_deserializer) - with state.condition: - call_error = call.start_client_batch(cygrpc.Operations(operations), - event_handler) - if call_error != cygrpc.CallError.ok: - _call_error_set_RPCstate(state, call_error, metadata) - return _Rendezvous(state, None, None, deadline) - drive_call() - return _Rendezvous(state, call, self._response_deserializer, deadline) + def __init__(self, channel, managed_call, method, request_serializer, + response_deserializer): + self._channel = channel + self._managed_call = managed_call + self._method = method + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def _prepare(self, request, timeout, metadata): + deadline, deadline_timespec, serialized_request, rendezvous = ( + _start_unary_request(request, timeout, self._request_serializer)) + if serialized_request is None: + return None, None, None, None, rendezvous + else: + state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None) + operations = ( + cygrpc.operation_send_initial_metadata( + _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), + cygrpc.operation_send_message(serialized_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),) + return state, operations, deadline, deadline_timespec, None + + def _blocking(self, request, timeout, metadata, credentials): + state, operations, deadline, deadline_timespec, rendezvous = self._prepare( + request, timeout, metadata) + if rendezvous: + raise rendezvous + else: + completion_queue = cygrpc.CompletionQueue() + call = self._channel.create_call(None, 0, completion_queue, + self._method, None, + deadline_timespec) + if credentials is not None: + call.set_credentials(credentials._credentials) + call_error = call.start_client_batch( + cygrpc.Operations(operations), None) + _check_call_error(call_error, metadata) + _handle_event(completion_queue.poll(), state, + self._response_deserializer) + return state, deadline + + def __call__(self, request, timeout=None, metadata=None, credentials=None): + state, deadline, = self._blocking(request, timeout, metadata, + credentials) + return _end_unary_response_blocking(state, False, deadline) + + def with_call(self, request, timeout=None, metadata=None, credentials=None): + state, deadline, = self._blocking(request, timeout, metadata, + credentials) + return _end_unary_response_blocking(state, True, deadline) + + def future(self, request, timeout=None, metadata=None, credentials=None): + state, operations, deadline, deadline_timespec, rendezvous = self._prepare( + request, timeout, metadata) + if rendezvous: + return rendezvous + else: + call, drive_call = self._managed_call(None, 0, self._method, None, + deadline_timespec) + if credentials is not None: + call.set_credentials(credentials._credentials) + event_handler = _event_handler(state, call, + self._response_deserializer) + with state.condition: + call_error = call.start_client_batch( + cygrpc.Operations(operations), event_handler) + if call_error != cygrpc.CallError.ok: + _call_error_set_RPCstate(state, call_error, metadata) + return _Rendezvous(state, None, None, deadline) + drive_call() + return _Rendezvous(state, call, self._response_deserializer, + deadline) class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): - def __init__( - self, channel, managed_call, method, request_serializer, - response_deserializer): - self._channel = channel - self._managed_call = managed_call - self._method = method - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def __call__(self, request, timeout=None, metadata=None, credentials=None): - deadline, deadline_timespec, serialized_request, rendezvous = ( - _start_unary_request(request, timeout, self._request_serializer)) - if serialized_request is None: - raise rendezvous - else: - state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None) - call, drive_call = self._managed_call( - None, 0, self._method, None, deadline_timespec) - if credentials is not None: - call.set_credentials(credentials._credentials) - event_handler = _event_handler(state, call, self._response_deserializer) - with state.condition: - call.start_client_batch( - cygrpc.Operations( - (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), - event_handler) - operations = ( - cygrpc.operation_send_initial_metadata( - _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), - cygrpc.operation_send_message(serialized_request, _EMPTY_FLAGS), - cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), - cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), - ) - call_error = call.start_client_batch(cygrpc.Operations(operations), - event_handler) - if call_error != cygrpc.CallError.ok: - _call_error_set_RPCstate(state, call_error, metadata) - return _Rendezvous(state, None, None, deadline) - drive_call() - return _Rendezvous(state, call, self._response_deserializer, deadline) + def __init__(self, channel, managed_call, method, request_serializer, + response_deserializer): + self._channel = channel + self._managed_call = managed_call + self._method = method + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def __call__(self, request, timeout=None, metadata=None, credentials=None): + deadline, deadline_timespec, serialized_request, rendezvous = ( + _start_unary_request(request, timeout, self._request_serializer)) + if serialized_request is None: + raise rendezvous + else: + state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None) + call, drive_call = self._managed_call(None, 0, self._method, None, + deadline_timespec) + if credentials is not None: + call.set_credentials(credentials._credentials) + event_handler = _event_handler(state, call, + self._response_deserializer) + with state.condition: + call.start_client_batch( + cygrpc.Operations(( + cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), + )), event_handler) + operations = ( + cygrpc.operation_send_initial_metadata( + _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), + cygrpc.operation_send_message(serialized_request, + _EMPTY_FLAGS), + cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) + call_error = call.start_client_batch( + cygrpc.Operations(operations), event_handler) + if call_error != cygrpc.CallError.ok: + _call_error_set_RPCstate(state, call_error, metadata) + return _Rendezvous(state, None, None, deadline) + drive_call() + return _Rendezvous(state, call, self._response_deserializer, + deadline) class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): - def __init__( - self, channel, managed_call, method, request_serializer, - response_deserializer): - self._channel = channel - self._managed_call = managed_call - self._method = method - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def _blocking(self, request_iterator, timeout, metadata, credentials): - deadline, deadline_timespec = _deadline(timeout) - state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) - completion_queue = cygrpc.CompletionQueue() - call = self._channel.create_call( - None, 0, completion_queue, self._method, None, deadline_timespec) - if credentials is not None: - call.set_credentials(credentials._credentials) - with state.condition: - call.start_client_batch( - cygrpc.Operations( - (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), - None) - operations = ( - cygrpc.operation_send_initial_metadata( - _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), - cygrpc.operation_receive_message(_EMPTY_FLAGS), - cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), - ) - call_error = call.start_client_batch(cygrpc.Operations(operations), None) - _check_call_error(call_error, metadata) - _consume_request_iterator( - request_iterator, state, call, self._request_serializer) - while True: - event = completion_queue.poll() - with state.condition: - _handle_event(event, state, self._response_deserializer) - state.condition.notify_all() - if not state.due: - break - return state, deadline - - def __call__( - self, request_iterator, timeout=None, metadata=None, credentials=None): - state, deadline, = self._blocking( - request_iterator, timeout, metadata, credentials) - return _end_unary_response_blocking(state, False, deadline) - - def with_call( - self, request_iterator, timeout=None, metadata=None, credentials=None): - state, deadline, = self._blocking( - request_iterator, timeout, metadata, credentials) - return _end_unary_response_blocking(state, True, deadline) - - def future( - self, request_iterator, timeout=None, metadata=None, credentials=None): - deadline, deadline_timespec = _deadline(timeout) - state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) - call, drive_call = self._managed_call( - None, 0, self._method, None, deadline_timespec) - if credentials is not None: - call.set_credentials(credentials._credentials) - event_handler = _event_handler(state, call, self._response_deserializer) - with state.condition: - call.start_client_batch( - cygrpc.Operations( - (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), - event_handler) - operations = ( - cygrpc.operation_send_initial_metadata( - _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), - cygrpc.operation_receive_message(_EMPTY_FLAGS), - cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), - ) - call_error = call.start_client_batch(cygrpc.Operations(operations), - event_handler) - if call_error != cygrpc.CallError.ok: - _call_error_set_RPCstate(state, call_error, metadata) - return _Rendezvous(state, None, None, deadline) - drive_call() - _consume_request_iterator( - request_iterator, state, call, self._request_serializer) - return _Rendezvous(state, call, self._response_deserializer, deadline) + def __init__(self, channel, managed_call, method, request_serializer, + response_deserializer): + self._channel = channel + self._managed_call = managed_call + self._method = method + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def _blocking(self, request_iterator, timeout, metadata, credentials): + deadline, deadline_timespec = _deadline(timeout) + state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) + completion_queue = cygrpc.CompletionQueue() + call = self._channel.create_call(None, 0, completion_queue, + self._method, None, deadline_timespec) + if credentials is not None: + call.set_credentials(credentials._credentials) + with state.condition: + call.start_client_batch( + cygrpc.Operations( + (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), + None) + operations = ( + cygrpc.operation_send_initial_metadata( + _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) + call_error = call.start_client_batch( + cygrpc.Operations(operations), None) + _check_call_error(call_error, metadata) + _consume_request_iterator(request_iterator, state, call, + self._request_serializer) + while True: + event = completion_queue.poll() + with state.condition: + _handle_event(event, state, self._response_deserializer) + state.condition.notify_all() + if not state.due: + break + return state, deadline + + def __call__(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + state, deadline, = self._blocking(request_iterator, timeout, metadata, + credentials) + return _end_unary_response_blocking(state, False, deadline) + + def with_call(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + state, deadline, = self._blocking(request_iterator, timeout, metadata, + credentials) + return _end_unary_response_blocking(state, True, deadline) + + def future(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + deadline, deadline_timespec = _deadline(timeout) + state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) + call, drive_call = self._managed_call(None, 0, self._method, None, + deadline_timespec) + if credentials is not None: + call.set_credentials(credentials._credentials) + event_handler = _event_handler(state, call, self._response_deserializer) + with state.condition: + call.start_client_batch( + cygrpc.Operations( + (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), + event_handler) + operations = ( + cygrpc.operation_send_initial_metadata( + _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), + cygrpc.operation_receive_message(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) + call_error = call.start_client_batch( + cygrpc.Operations(operations), event_handler) + if call_error != cygrpc.CallError.ok: + _call_error_set_RPCstate(state, call_error, metadata) + return _Rendezvous(state, None, None, deadline) + drive_call() + _consume_request_iterator(request_iterator, state, call, + self._request_serializer) + return _Rendezvous(state, call, self._response_deserializer, deadline) class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): - def __init__( - self, channel, managed_call, method, request_serializer, - response_deserializer): - self._channel = channel - self._managed_call = managed_call - self._method = method - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def __call__( - self, request_iterator, timeout=None, metadata=None, credentials=None): - deadline, deadline_timespec = _deadline(timeout) - state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None) - call, drive_call = self._managed_call( - None, 0, self._method, None, deadline_timespec) - if credentials is not None: - call.set_credentials(credentials._credentials) - event_handler = _event_handler(state, call, self._response_deserializer) - with state.condition: - call.start_client_batch( - cygrpc.Operations( - (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), - event_handler) - operations = ( - cygrpc.operation_send_initial_metadata( - _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), - cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), - ) - call_error = call.start_client_batch(cygrpc.Operations(operations), - event_handler) - if call_error != cygrpc.CallError.ok: - _call_error_set_RPCstate(state, call_error, metadata) - return _Rendezvous(state, None, None, deadline) - drive_call() - _consume_request_iterator( - request_iterator, state, call, self._request_serializer) - return _Rendezvous(state, call, self._response_deserializer, deadline) + def __init__(self, channel, managed_call, method, request_serializer, + response_deserializer): + self._channel = channel + self._managed_call = managed_call + self._method = method + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def __call__(self, + request_iterator, + timeout=None, + metadata=None, + credentials=None): + deadline, deadline_timespec = _deadline(timeout) + state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None) + call, drive_call = self._managed_call(None, 0, self._method, None, + deadline_timespec) + if credentials is not None: + call.set_credentials(credentials._credentials) + event_handler = _event_handler(state, call, self._response_deserializer) + with state.condition: + call.start_client_batch( + cygrpc.Operations( + (cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS),)), + event_handler) + operations = ( + cygrpc.operation_send_initial_metadata( + _common.cygrpc_metadata(metadata), _EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS),) + call_error = call.start_client_batch( + cygrpc.Operations(operations), event_handler) + if call_error != cygrpc.CallError.ok: + _call_error_set_RPCstate(state, call_error, metadata) + return _Rendezvous(state, None, None, deadline) + drive_call() + _consume_request_iterator(request_iterator, state, call, + self._request_serializer) + return _Rendezvous(state, call, self._response_deserializer, deadline) class _ChannelCallState(object): - def __init__(self, channel): - self.lock = threading.Lock() - self.channel = channel - self.completion_queue = cygrpc.CompletionQueue() - self.managed_calls = None + def __init__(self, channel): + self.lock = threading.Lock() + self.channel = channel + self.completion_queue = cygrpc.CompletionQueue() + self.managed_calls = None def _run_channel_spin_thread(state): - def channel_spin(): - while True: - event = state.completion_queue.poll() - completed_call = event.tag(event) - if completed_call is not None: - with state.lock: - state.managed_calls.remove(completed_call) - if not state.managed_calls: - state.managed_calls = None - return - def stop_channel_spin(timeout): - with state.lock: - if state.managed_calls is not None: - for call in state.managed_calls: - call.cancel() + def channel_spin(): + while True: + event = state.completion_queue.poll() + completed_call = event.tag(event) + if completed_call is not None: + with state.lock: + state.managed_calls.remove(completed_call) + if not state.managed_calls: + state.managed_calls = None + return + + def stop_channel_spin(timeout): + with state.lock: + if state.managed_calls is not None: + for call in state.managed_calls: + call.cancel() - channel_spin_thread = _common.CleanupThread( - stop_channel_spin, target=channel_spin) - channel_spin_thread.start() + channel_spin_thread = _common.CleanupThread( + stop_channel_spin, target=channel_spin) + channel_spin_thread.start() def _channel_managed_call_management(state): - def create(parent, flags, method, host, deadline): - """Creates a managed cygrpc.Call and a function to call to drive it. + + def create(parent, flags, method, host, deadline): + """Creates a managed cygrpc.Call and a function to call to drive it. If operations are successfully added to the returned cygrpc.Call, the returned function must be called. If operations are not successfully added @@ -754,193 +771,213 @@ def _channel_managed_call_management(state): A cygrpc.Call with which to conduct an RPC and a function to call if operations are successfully started on the call. """ - call = state.channel.create_call( - parent, flags, state.completion_queue, method, host, deadline) - - def drive(): - with state.lock: - if state.managed_calls is None: - state.managed_calls = set((call,)) - _run_channel_spin_thread(state) - else: - state.managed_calls.add(call) + call = state.channel.create_call(parent, flags, state.completion_queue, + method, host, deadline) + + def drive(): + with state.lock: + if state.managed_calls is None: + state.managed_calls = set((call,)) + _run_channel_spin_thread(state) + else: + state.managed_calls.add(call) + + return call, drive - return call, drive - return create + return create class _ChannelConnectivityState(object): - def __init__(self, channel): - self.lock = threading.Lock() - self.channel = channel - self.polling = False - self.connectivity = None - self.try_to_connect = False - self.callbacks_and_connectivities = [] - self.delivering = False + def __init__(self, channel): + self.lock = threading.Lock() + self.channel = channel + self.polling = False + self.connectivity = None + self.try_to_connect = False + self.callbacks_and_connectivities = [] + self.delivering = False def _deliveries(state): - callbacks_needing_update = [] - for callback_and_connectivity in state.callbacks_and_connectivities: - callback, callback_connectivity, = callback_and_connectivity - if callback_connectivity is not state.connectivity: - callbacks_needing_update.append(callback) - callback_and_connectivity[1] = state.connectivity - return callbacks_needing_update + callbacks_needing_update = [] + for callback_and_connectivity in state.callbacks_and_connectivities: + callback, callback_connectivity, = callback_and_connectivity + if callback_connectivity is not state.connectivity: + callbacks_needing_update.append(callback) + callback_and_connectivity[1] = state.connectivity + return callbacks_needing_update def _deliver(state, initial_connectivity, initial_callbacks): - connectivity = initial_connectivity - callbacks = initial_callbacks - while True: - for callback in callbacks: - callable_util.call_logging_exceptions( - callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, - connectivity) - with state.lock: - callbacks = _deliveries(state) - if callbacks: - connectivity = state.connectivity - else: - state.delivering = False - return + connectivity = initial_connectivity + callbacks = initial_callbacks + while True: + for callback in callbacks: + callable_util.call_logging_exceptions( + callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, + connectivity) + with state.lock: + callbacks = _deliveries(state) + if callbacks: + connectivity = state.connectivity + else: + state.delivering = False + return def _spawn_delivery(state, callbacks): - delivering_thread = threading.Thread( - target=_deliver, args=(state, state.connectivity, callbacks,)) - delivering_thread.start() - state.delivering = True + delivering_thread = threading.Thread( + target=_deliver, args=( + state, + state.connectivity, + callbacks,)) + delivering_thread.start() + state.delivering = True # NOTE(https://github.com/grpc/grpc/issues/3064): We'd rather not poll. def _poll_connectivity(state, channel, initial_try_to_connect): - try_to_connect = initial_try_to_connect - connectivity = channel.check_connectivity_state(try_to_connect) - with state.lock: - state.connectivity = ( - _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ - connectivity]) - callbacks = tuple( - callback for callback, unused_but_known_to_be_none_connectivity - in state.callbacks_and_connectivities) - for callback_and_connectivity in state.callbacks_and_connectivities: - callback_and_connectivity[1] = state.connectivity - if callbacks: - _spawn_delivery(state, callbacks) - completion_queue = cygrpc.CompletionQueue() - while True: - channel.watch_connectivity_state( - connectivity, cygrpc.Timespec(time.time() + 0.2), - completion_queue, None) - event = completion_queue.poll() + try_to_connect = initial_try_to_connect + connectivity = channel.check_connectivity_state(try_to_connect) with state.lock: - if not state.callbacks_and_connectivities and not state.try_to_connect: - state.polling = False - state.connectivity = None - break - try_to_connect = state.try_to_connect - state.try_to_connect = False - if event.success or try_to_connect: - connectivity = channel.check_connectivity_state(try_to_connect) - with state.lock: state.connectivity = ( _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ connectivity]) - if not state.delivering: - callbacks = _deliveries(state) - if callbacks: + callbacks = tuple(callback + for callback, unused_but_known_to_be_none_connectivity + in state.callbacks_and_connectivities) + for callback_and_connectivity in state.callbacks_and_connectivities: + callback_and_connectivity[1] = state.connectivity + if callbacks: _spawn_delivery(state, callbacks) + completion_queue = cygrpc.CompletionQueue() + while True: + channel.watch_connectivity_state(connectivity, + cygrpc.Timespec(time.time() + 0.2), + completion_queue, None) + event = completion_queue.poll() + with state.lock: + if not state.callbacks_and_connectivities and not state.try_to_connect: + state.polling = False + state.connectivity = None + break + try_to_connect = state.try_to_connect + state.try_to_connect = False + if event.success or try_to_connect: + connectivity = channel.check_connectivity_state(try_to_connect) + with state.lock: + state.connectivity = ( + _common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ + connectivity]) + if not state.delivering: + callbacks = _deliveries(state) + if callbacks: + _spawn_delivery(state, callbacks) def _moot(state): - with state.lock: - del state.callbacks_and_connectivities[:] + with state.lock: + del state.callbacks_and_connectivities[:] def _subscribe(state, callback, try_to_connect): - with state.lock: - if not state.callbacks_and_connectivities and not state.polling: - def cancel_all_subscriptions(timeout): - _moot(state) - polling_thread = _common.CleanupThread( - cancel_all_subscriptions, target=_poll_connectivity, - args=(state, state.channel, bool(try_to_connect))) - polling_thread.start() - state.polling = True - state.callbacks_and_connectivities.append([callback, None]) - elif not state.delivering and state.connectivity is not None: - _spawn_delivery(state, (callback,)) - state.try_to_connect |= bool(try_to_connect) - state.callbacks_and_connectivities.append( - [callback, state.connectivity]) - else: - state.try_to_connect |= bool(try_to_connect) - state.callbacks_and_connectivities.append([callback, None]) + with state.lock: + if not state.callbacks_and_connectivities and not state.polling: + + def cancel_all_subscriptions(timeout): + _moot(state) + + polling_thread = _common.CleanupThread( + cancel_all_subscriptions, + target=_poll_connectivity, + args=(state, state.channel, bool(try_to_connect))) + polling_thread.start() + state.polling = True + state.callbacks_and_connectivities.append([callback, None]) + elif not state.delivering and state.connectivity is not None: + _spawn_delivery(state, (callback,)) + state.try_to_connect |= bool(try_to_connect) + state.callbacks_and_connectivities.append( + [callback, state.connectivity]) + else: + state.try_to_connect |= bool(try_to_connect) + state.callbacks_and_connectivities.append([callback, None]) def _unsubscribe(state, callback): - with state.lock: - for index, (subscribed_callback, unused_connectivity) in enumerate( - state.callbacks_and_connectivities): - if callback == subscribed_callback: - state.callbacks_and_connectivities.pop(index) - break + with state.lock: + for index, (subscribed_callback, unused_connectivity + ) in enumerate(state.callbacks_and_connectivities): + if callback == subscribed_callback: + state.callbacks_and_connectivities.pop(index) + break def _options(options): - return list(options) + [ - (cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)] + return list(options) + [ + (cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT) + ] class Channel(grpc.Channel): - """A cygrpc.Channel-backed implementation of grpc.Channel.""" + """A cygrpc.Channel-backed implementation of grpc.Channel.""" - def __init__(self, target, options, credentials): - """Constructor. + def __init__(self, target, options, credentials): + """Constructor. Args: target: The target to which to connect. options: Configuration options for the channel. credentials: A cygrpc.ChannelCredentials or None. """ - self._channel = cygrpc.Channel( - _common.encode(target), _common.channel_args(_options(options)), - credentials) - self._call_state = _ChannelCallState(self._channel) - self._connectivity_state = _ChannelConnectivityState(self._channel) - - def subscribe(self, callback, try_to_connect=None): - _subscribe(self._connectivity_state, callback, try_to_connect) - - def unsubscribe(self, callback): - _unsubscribe(self._connectivity_state, callback) - - def unary_unary( - self, method, request_serializer=None, response_deserializer=None): - return _UnaryUnaryMultiCallable( - self._channel, _channel_managed_call_management(self._call_state), - _common.encode(method), request_serializer, response_deserializer) - - def unary_stream( - self, method, request_serializer=None, response_deserializer=None): - return _UnaryStreamMultiCallable( - self._channel, _channel_managed_call_management(self._call_state), - _common.encode(method), request_serializer, response_deserializer) - - def stream_unary( - self, method, request_serializer=None, response_deserializer=None): - return _StreamUnaryMultiCallable( - self._channel, _channel_managed_call_management(self._call_state), - _common.encode(method), request_serializer, response_deserializer) - - def stream_stream( - self, method, request_serializer=None, response_deserializer=None): - return _StreamStreamMultiCallable( - self._channel, _channel_managed_call_management(self._call_state), - _common.encode(method), request_serializer, response_deserializer) - - def __del__(self): - _moot(self._connectivity_state) + self._channel = cygrpc.Channel( + _common.encode(target), + _common.channel_args(_options(options)), credentials) + self._call_state = _ChannelCallState(self._channel) + self._connectivity_state = _ChannelConnectivityState(self._channel) + + def subscribe(self, callback, try_to_connect=None): + _subscribe(self._connectivity_state, callback, try_to_connect) + + def unsubscribe(self, callback): + _unsubscribe(self._connectivity_state, callback) + + def unary_unary(self, + method, + request_serializer=None, + response_deserializer=None): + return _UnaryUnaryMultiCallable( + self._channel, + _channel_managed_call_management(self._call_state), + _common.encode(method), request_serializer, response_deserializer) + + def unary_stream(self, + method, + request_serializer=None, + response_deserializer=None): + return _UnaryStreamMultiCallable( + self._channel, + _channel_managed_call_management(self._call_state), + _common.encode(method), request_serializer, response_deserializer) + + def stream_unary(self, + method, + request_serializer=None, + response_deserializer=None): + return _StreamUnaryMultiCallable( + self._channel, + _channel_managed_call_management(self._call_state), + _common.encode(method), request_serializer, response_deserializer) + + def stream_stream(self, + method, + request_serializer=None, + response_deserializer=None): + return _StreamStreamMultiCallable( + self._channel, + _channel_managed_call_management(self._call_state), + _common.encode(method), request_serializer, response_deserializer) + + def __del__(self): + _moot(self._connectivity_state) diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py index cc0984c8c63..7ef2571379b 100644 --- a/src/python/grpcio/grpc/_common.py +++ b/src/python/grpcio/grpc/_common.py @@ -26,7 +26,6 @@ # 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. - """Shared implementation.""" import logging @@ -45,9 +44,8 @@ CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = { cygrpc.ConnectivityState.connecting: grpc.ChannelConnectivity.CONNECTING, cygrpc.ConnectivityState.ready: grpc.ChannelConnectivity.READY, cygrpc.ConnectivityState.transient_failure: - grpc.ChannelConnectivity.TRANSIENT_FAILURE, - cygrpc.ConnectivityState.shutdown: - grpc.ChannelConnectivity.SHUTDOWN, + grpc.ChannelConnectivity.TRANSIENT_FAILURE, + cygrpc.ConnectivityState.shutdown: grpc.ChannelConnectivity.SHUTDOWN, } CYGRPC_STATUS_CODE_TO_STATUS_CODE = { @@ -77,83 +75,88 @@ STATUS_CODE_TO_CYGRPC_STATUS_CODE = { def encode(s): - if isinstance(s, bytes): - return s - else: - return s.encode('ascii') + if isinstance(s, bytes): + return s + else: + return s.encode('ascii') def decode(b): - if isinstance(b, str): - return b - else: - try: - return b.decode('utf8') - except UnicodeDecodeError: - logging.exception('Invalid encoding on {}'.format(b)) - return b.decode('latin1') + if isinstance(b, str): + return b + else: + try: + return b.decode('utf8') + except UnicodeDecodeError: + logging.exception('Invalid encoding on {}'.format(b)) + return b.decode('latin1') def channel_args(options): - channel_args = [] - for key, value in options: - if isinstance(value, six.string_types): - channel_args.append(cygrpc.ChannelArg(encode(key), encode(value))) - else: - channel_args.append(cygrpc.ChannelArg(encode(key), value)) - return cygrpc.ChannelArgs(channel_args) + channel_args = [] + for key, value in options: + if isinstance(value, six.string_types): + channel_args.append(cygrpc.ChannelArg(encode(key), encode(value))) + else: + channel_args.append(cygrpc.ChannelArg(encode(key), value)) + return cygrpc.ChannelArgs(channel_args) def cygrpc_metadata(application_metadata): - return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata( - cygrpc.Metadatum(encode(key), encode(value)) - for key, value in application_metadata) + return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata( + cygrpc.Metadatum(encode(key), encode(value)) + for key, value in application_metadata) def application_metadata(cygrpc_metadata): - if cygrpc_metadata is None: - return () - else: - return tuple( - (decode(key), value if key[-4:] == b'-bin' else decode(value)) - for key, value in cygrpc_metadata) + if cygrpc_metadata is None: + return () + else: + return tuple((decode(key), value + if key[-4:] == b'-bin' else decode(value)) + for key, value in cygrpc_metadata) def _transform(message, transformer, exception_message): - if transformer is None: - return message - else: - try: - return transformer(message) - except Exception: # pylint: disable=broad-except - logging.exception(exception_message) - return None + if transformer is None: + return message + else: + try: + return transformer(message) + except Exception: # pylint: disable=broad-except + logging.exception(exception_message) + return None def serialize(message, serializer): - return _transform(message, serializer, 'Exception serializing message!') + return _transform(message, serializer, 'Exception serializing message!') def deserialize(serialized_message, deserializer): - return _transform(serialized_message, deserializer, - 'Exception deserializing message!') + return _transform(serialized_message, deserializer, + 'Exception deserializing message!') def fully_qualified_method(group, method): - return '/{}/{}'.format(group, method) + return '/{}/{}'.format(group, method) class CleanupThread(threading.Thread): - """A threading.Thread subclass supporting custom behavior on join(). + """A threading.Thread subclass supporting custom behavior on join(). On Python Interpreter exit, Python will attempt to join outstanding threads prior to garbage collection. We may need to do additional cleanup, and we accomplish this by overriding the join() method. """ - def __init__(self, behavior, group=None, target=None, name=None, - args=(), kwargs={}): - """Constructor. + def __init__(self, + behavior, + group=None, + target=None, + name=None, + args=(), + kwargs={}): + """Constructor. Args: behavior (function): Function called on join() with a single @@ -169,15 +172,15 @@ class CleanupThread(threading.Thread): kwargs (dict[str,object]): A dictionary of keyword arguments to pass to `target`. """ - super(CleanupThread, self).__init__(group=group, target=target, - name=name, args=args, kwargs=kwargs) - self._behavior = behavior - - def join(self, timeout=None): - start_time = time.time() - self._behavior(timeout) - end_time = time.time() - if timeout is not None: - timeout -= end_time - start_time - timeout = max(timeout, 0) - super(CleanupThread, self).join(timeout) + super(CleanupThread, self).__init__( + group=group, target=target, name=name, args=args, kwargs=kwargs) + self._behavior = behavior + + def join(self, timeout=None): + start_time = time.time() + self._behavior(timeout) + end_time = time.time() + if timeout is not None: + timeout -= end_time - start_time + timeout = max(timeout, 0) + super(CleanupThread, self).join(timeout) diff --git a/src/python/grpcio/grpc/_credential_composition.py b/src/python/grpcio/grpc/_credential_composition.py index 9cb5508e27c..bdf017baa56 100644 --- a/src/python/grpcio/grpc/_credential_composition.py +++ b/src/python/grpcio/grpc/_credential_composition.py @@ -31,18 +31,18 @@ from grpc._cython import cygrpc def _call(call_credentialses): - call_credentials_iterator = iter(call_credentialses) - composition = next(call_credentials_iterator) - for additional_call_credentials in call_credentials_iterator: - composition = cygrpc.call_credentials_composite( - composition, additional_call_credentials) - return composition + call_credentials_iterator = iter(call_credentialses) + composition = next(call_credentials_iterator) + for additional_call_credentials in call_credentials_iterator: + composition = cygrpc.call_credentials_composite( + composition, additional_call_credentials) + return composition def call(call_credentialses): - return _call(call_credentialses) + return _call(call_credentialses) def channel(channel_credentials, call_credentialses): - return cygrpc.channel_credentials_composite( - channel_credentials, _call(call_credentialses)) + return cygrpc.channel_credentials_composite(channel_credentials, + _call(call_credentialses)) diff --git a/src/python/grpcio/grpc/_plugin_wrapping.py b/src/python/grpcio/grpc/_plugin_wrapping.py index 7cb5218c22b..bb9a42f3ffe 100644 --- a/src/python/grpcio/grpc/_plugin_wrapping.py +++ b/src/python/grpcio/grpc/_plugin_wrapping.py @@ -36,82 +36,82 @@ from grpc._cython import cygrpc class AuthMetadataContext( - collections.namedtuple( - 'AuthMetadataContext', ('service_url', 'method_name',)), - grpc.AuthMetadataContext): - pass + collections.namedtuple('AuthMetadataContext', ( + 'service_url', + 'method_name',)), grpc.AuthMetadataContext): + pass class AuthMetadataPluginCallback(grpc.AuthMetadataContext): - def __init__(self, callback): - self._callback = callback + def __init__(self, callback): + self._callback = callback - def __call__(self, metadata, error): - self._callback(metadata, error) + def __call__(self, metadata, error): + self._callback(metadata, error) class _WrappedCygrpcCallback(object): - def __init__(self, cygrpc_callback): - self.is_called = False - self.error = None - self.is_called_lock = threading.Lock() - self.cygrpc_callback = cygrpc_callback - - def _invoke_failure(self, error): - # TODO(atash) translate different Exception superclasses into different - # status codes. - self.cygrpc_callback( - _common.EMPTY_METADATA, cygrpc.StatusCode.internal, - _common.encode(str(error))) - - def _invoke_success(self, metadata): - try: - cygrpc_metadata = _common.cygrpc_metadata(metadata) - except Exception as error: - self._invoke_failure(error) - return - self.cygrpc_callback(cygrpc_metadata, cygrpc.StatusCode.ok, b'') - - def __call__(self, metadata, error): - with self.is_called_lock: - if self.is_called: - raise RuntimeError('callback should only ever be invoked once') - if self.error: - self._invoke_failure(self.error) - return - self.is_called = True - if error is None: - self._invoke_success(metadata) - else: - self._invoke_failure(error) - - def notify_failure(self, error): - with self.is_called_lock: - if not self.is_called: - self.error = error + def __init__(self, cygrpc_callback): + self.is_called = False + self.error = None + self.is_called_lock = threading.Lock() + self.cygrpc_callback = cygrpc_callback + + def _invoke_failure(self, error): + # TODO(atash) translate different Exception superclasses into different + # status codes. + self.cygrpc_callback(_common.EMPTY_METADATA, cygrpc.StatusCode.internal, + _common.encode(str(error))) + + def _invoke_success(self, metadata): + try: + cygrpc_metadata = _common.cygrpc_metadata(metadata) + except Exception as error: + self._invoke_failure(error) + return + self.cygrpc_callback(cygrpc_metadata, cygrpc.StatusCode.ok, b'') + + def __call__(self, metadata, error): + with self.is_called_lock: + if self.is_called: + raise RuntimeError('callback should only ever be invoked once') + if self.error: + self._invoke_failure(self.error) + return + self.is_called = True + if error is None: + self._invoke_success(metadata) + else: + self._invoke_failure(error) + + def notify_failure(self, error): + with self.is_called_lock: + if not self.is_called: + self.error = error class _WrappedPlugin(object): - def __init__(self, plugin): - self.plugin = plugin + def __init__(self, plugin): + self.plugin = plugin - def __call__(self, context, cygrpc_callback): - wrapped_cygrpc_callback = _WrappedCygrpcCallback(cygrpc_callback) - wrapped_context = AuthMetadataContext( - _common.decode(context.service_url), _common.decode(context.method_name)) - try: - self.plugin( - wrapped_context, AuthMetadataPluginCallback(wrapped_cygrpc_callback)) - except Exception as error: - wrapped_cygrpc_callback.notify_failure(error) - raise + def __call__(self, context, cygrpc_callback): + wrapped_cygrpc_callback = _WrappedCygrpcCallback(cygrpc_callback) + wrapped_context = AuthMetadataContext( + _common.decode(context.service_url), + _common.decode(context.method_name)) + try: + self.plugin(wrapped_context, + AuthMetadataPluginCallback(wrapped_cygrpc_callback)) + except Exception as error: + wrapped_cygrpc_callback.notify_failure(error) + raise def call_credentials_metadata_plugin(plugin, name): - """ + """ Args: plugin: A callable accepting a grpc.AuthMetadataContext object and a callback (itself accepting a list of metadata key/value @@ -119,5 +119,6 @@ def call_credentials_metadata_plugin(plugin, name): called, but need not be called in plugin's invocation. plugin's invocation must be non-blocking. """ - return cygrpc.call_credentials_metadata_plugin( - cygrpc.CredentialsMetadataPlugin(_WrappedPlugin(plugin), _common.encode(name))) + return cygrpc.call_credentials_metadata_plugin( + cygrpc.CredentialsMetadataPlugin( + _WrappedPlugin(plugin), _common.encode(name))) diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index 5223712dfa7..158cdf8b0e6 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -26,7 +26,6 @@ # 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. - """Service-side implementation of gRPC Python.""" import collections @@ -64,692 +63,715 @@ _UNEXPECTED_EXIT_SERVER_GRACE = 1.0 def _serialized_request(request_event): - return request_event.batch_operations[0].received_message.bytes() + return request_event.batch_operations[0].received_message.bytes() def _application_code(code): - cygrpc_code = _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE.get(code) - return cygrpc.StatusCode.unknown if cygrpc_code is None else cygrpc_code + cygrpc_code = _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE.get(code) + return cygrpc.StatusCode.unknown if cygrpc_code is None else cygrpc_code def _completion_code(state): - if state.code is None: - return cygrpc.StatusCode.ok - else: - return _application_code(state.code) + if state.code is None: + return cygrpc.StatusCode.ok + else: + return _application_code(state.code) def _abortion_code(state, code): - if state.code is None: - return code - else: - return _application_code(state.code) + if state.code is None: + return code + else: + return _application_code(state.code) def _details(state): - return b'' if state.details is None else state.details + return b'' if state.details is None else state.details class _HandlerCallDetails( - collections.namedtuple( - '_HandlerCallDetails', ('method', 'invocation_metadata',)), - grpc.HandlerCallDetails): - pass + collections.namedtuple('_HandlerCallDetails', ( + 'method', + 'invocation_metadata',)), grpc.HandlerCallDetails): + pass class _RPCState(object): - def __init__(self): - self.condition = threading.Condition() - self.due = set() - self.request = None - self.client = _OPEN - self.initial_metadata_allowed = True - self.disable_next_compression = False - self.trailing_metadata = None - self.code = None - self.details = None - self.statused = False - self.rpc_errors = [] - self.callbacks = [] + def __init__(self): + self.condition = threading.Condition() + self.due = set() + self.request = None + self.client = _OPEN + self.initial_metadata_allowed = True + self.disable_next_compression = False + self.trailing_metadata = None + self.code = None + self.details = None + self.statused = False + self.rpc_errors = [] + self.callbacks = [] def _raise_rpc_error(state): - rpc_error = grpc.RpcError() - state.rpc_errors.append(rpc_error) - raise rpc_error + rpc_error = grpc.RpcError() + state.rpc_errors.append(rpc_error) + raise rpc_error def _possibly_finish_call(state, token): - state.due.remove(token) - if (state.client is _CANCELLED or state.statused) and not state.due: - callbacks = state.callbacks - state.callbacks = None - return state, callbacks - else: - return None, () + state.due.remove(token) + if (state.client is _CANCELLED or state.statused) and not state.due: + callbacks = state.callbacks + state.callbacks = None + return state, callbacks + else: + return None, () def _send_status_from_server(state, token): - def send_status_from_server(unused_send_status_from_server_event): - with state.condition: - return _possibly_finish_call(state, token) - return send_status_from_server + + def send_status_from_server(unused_send_status_from_server_event): + with state.condition: + return _possibly_finish_call(state, token) + + return send_status_from_server def _abort(state, call, code, details): - if state.client is not _CANCELLED: - effective_code = _abortion_code(state, code) - effective_details = details if state.details is None else state.details - if state.initial_metadata_allowed: - operations = ( - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS), - cygrpc.operation_send_status_from_server( - _common.cygrpc_metadata(state.trailing_metadata), effective_code, - effective_details, _EMPTY_FLAGS), - ) - token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN - else: - operations = ( - cygrpc.operation_send_status_from_server( - _common.cygrpc_metadata(state.trailing_metadata), effective_code, - effective_details, _EMPTY_FLAGS), - ) - token = _SEND_STATUS_FROM_SERVER_TOKEN - call.start_server_batch( - cygrpc.Operations(operations), - _send_status_from_server(state, token)) - state.statused = True - state.due.add(token) + if state.client is not _CANCELLED: + effective_code = _abortion_code(state, code) + effective_details = details if state.details is None else state.details + if state.initial_metadata_allowed: + operations = ( + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS), + cygrpc.operation_send_status_from_server( + _common.cygrpc_metadata(state.trailing_metadata), + effective_code, effective_details, _EMPTY_FLAGS),) + token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN + else: + operations = (cygrpc.operation_send_status_from_server( + _common.cygrpc_metadata(state.trailing_metadata), + effective_code, effective_details, _EMPTY_FLAGS),) + token = _SEND_STATUS_FROM_SERVER_TOKEN + call.start_server_batch( + cygrpc.Operations(operations), + _send_status_from_server(state, token)) + state.statused = True + state.due.add(token) def _receive_close_on_server(state): - def receive_close_on_server(receive_close_on_server_event): - with state.condition: - if receive_close_on_server_event.batch_operations[0].received_cancelled: - state.client = _CANCELLED - elif state.client is _OPEN: - state.client = _CLOSED - state.condition.notify_all() - return _possibly_finish_call(state, _RECEIVE_CLOSE_ON_SERVER_TOKEN) - return receive_close_on_server + + def receive_close_on_server(receive_close_on_server_event): + with state.condition: + if receive_close_on_server_event.batch_operations[ + 0].received_cancelled: + state.client = _CANCELLED + elif state.client is _OPEN: + state.client = _CLOSED + state.condition.notify_all() + return _possibly_finish_call(state, _RECEIVE_CLOSE_ON_SERVER_TOKEN) + + return receive_close_on_server def _receive_message(state, call, request_deserializer): - def receive_message(receive_message_event): - serialized_request = _serialized_request(receive_message_event) - if serialized_request is None: - with state.condition: - if state.client is _OPEN: - state.client = _CLOSED - state.condition.notify_all() - return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) - else: - request = _common.deserialize(serialized_request, request_deserializer) - with state.condition: - if request is None: - _abort( - state, call, cygrpc.StatusCode.internal, - b'Exception deserializing request!') + + def receive_message(receive_message_event): + serialized_request = _serialized_request(receive_message_event) + if serialized_request is None: + with state.condition: + if state.client is _OPEN: + state.client = _CLOSED + state.condition.notify_all() + return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) else: - state.request = request - state.condition.notify_all() - return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) - return receive_message + request = _common.deserialize(serialized_request, + request_deserializer) + with state.condition: + if request is None: + _abort(state, call, cygrpc.StatusCode.internal, + b'Exception deserializing request!') + else: + state.request = request + state.condition.notify_all() + return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN) + + return receive_message def _send_initial_metadata(state): - def send_initial_metadata(unused_send_initial_metadata_event): - with state.condition: - return _possibly_finish_call(state, _SEND_INITIAL_METADATA_TOKEN) - return send_initial_metadata + + def send_initial_metadata(unused_send_initial_metadata_event): + with state.condition: + return _possibly_finish_call(state, _SEND_INITIAL_METADATA_TOKEN) + + return send_initial_metadata def _send_message(state, token): - def send_message(unused_send_message_event): - with state.condition: - state.condition.notify_all() - return _possibly_finish_call(state, token) - return send_message + + def send_message(unused_send_message_event): + with state.condition: + state.condition.notify_all() + return _possibly_finish_call(state, token) + + return send_message class _Context(grpc.ServicerContext): - def __init__(self, rpc_event, state, request_deserializer): - self._rpc_event = rpc_event - self._state = state - self._request_deserializer = request_deserializer + def __init__(self, rpc_event, state, request_deserializer): + self._rpc_event = rpc_event + self._state = state + self._request_deserializer = request_deserializer - def is_active(self): - with self._state.condition: - return self._state.client is not _CANCELLED and not self._state.statused + def is_active(self): + with self._state.condition: + return self._state.client is not _CANCELLED and not self._state.statused - def time_remaining(self): - return max(self._rpc_event.request_call_details.deadline - time.time(), 0) + def time_remaining(self): + return max(self._rpc_event.request_call_details.deadline - time.time(), + 0) - def cancel(self): - self._rpc_event.operation_call.cancel() + def cancel(self): + self._rpc_event.operation_call.cancel() - def add_callback(self, callback): - with self._state.condition: - if self._state.callbacks is None: - return False - else: - self._state.callbacks.append(callback) - return True + def add_callback(self, callback): + with self._state.condition: + if self._state.callbacks is None: + return False + else: + self._state.callbacks.append(callback) + return True - def disable_next_message_compression(self): - with self._state.condition: - self._state.disable_next_compression = True - - def invocation_metadata(self): - return _common.application_metadata(self._rpc_event.request_metadata) - - def peer(self): - return _common.decode(self._rpc_event.operation_call.peer()) - - def send_initial_metadata(self, initial_metadata): - with self._state.condition: - if self._state.client is _CANCELLED: - _raise_rpc_error(self._state) - else: - if self._state.initial_metadata_allowed: - operation = cygrpc.operation_send_initial_metadata( - _common.cygrpc_metadata(initial_metadata), _EMPTY_FLAGS) - self._rpc_event.operation_call.start_server_batch( - cygrpc.Operations((operation,)), - _send_initial_metadata(self._state)) - self._state.initial_metadata_allowed = False - self._state.due.add(_SEND_INITIAL_METADATA_TOKEN) - else: - raise ValueError('Initial metadata no longer allowed!') + def disable_next_message_compression(self): + with self._state.condition: + self._state.disable_next_compression = True - def set_trailing_metadata(self, trailing_metadata): - with self._state.condition: - self._state.trailing_metadata = _common.cygrpc_metadata( - trailing_metadata) + def invocation_metadata(self): + return _common.application_metadata(self._rpc_event.request_metadata) - def set_code(self, code): - with self._state.condition: - self._state.code = code + def peer(self): + return _common.decode(self._rpc_event.operation_call.peer()) - def set_details(self, details): - with self._state.condition: - self._state.details = _common.encode(details) + def send_initial_metadata(self, initial_metadata): + with self._state.condition: + if self._state.client is _CANCELLED: + _raise_rpc_error(self._state) + else: + if self._state.initial_metadata_allowed: + operation = cygrpc.operation_send_initial_metadata( + _common.cygrpc_metadata(initial_metadata), _EMPTY_FLAGS) + self._rpc_event.operation_call.start_server_batch( + cygrpc.Operations((operation,)), + _send_initial_metadata(self._state)) + self._state.initial_metadata_allowed = False + self._state.due.add(_SEND_INITIAL_METADATA_TOKEN) + else: + raise ValueError('Initial metadata no longer allowed!') + + def set_trailing_metadata(self, trailing_metadata): + with self._state.condition: + self._state.trailing_metadata = _common.cygrpc_metadata( + trailing_metadata) + + def set_code(self, code): + with self._state.condition: + self._state.code = code + + def set_details(self, details): + with self._state.condition: + self._state.details = _common.encode(details) class _RequestIterator(object): - def __init__(self, state, call, request_deserializer): - self._state = state - self._call = call - self._request_deserializer = request_deserializer + def __init__(self, state, call, request_deserializer): + self._state = state + self._call = call + self._request_deserializer = request_deserializer - def _raise_or_start_receive_message(self): - if self._state.client is _CANCELLED: - _raise_rpc_error(self._state) - elif self._state.client is _CLOSED or self._state.statused: - raise StopIteration() - else: - self._call.start_server_batch( - cygrpc.Operations((cygrpc.operation_receive_message(_EMPTY_FLAGS),)), - _receive_message(self._state, self._call, self._request_deserializer)) - self._state.due.add(_RECEIVE_MESSAGE_TOKEN) - - def _look_for_request(self): - if self._state.client is _CANCELLED: - _raise_rpc_error(self._state) - elif (self._state.request is None and - _RECEIVE_MESSAGE_TOKEN not in self._state.due): - raise StopIteration() - else: - request = self._state.request - self._state.request = None - return request + def _raise_or_start_receive_message(self): + if self._state.client is _CANCELLED: + _raise_rpc_error(self._state) + elif self._state.client is _CLOSED or self._state.statused: + raise StopIteration() + else: + self._call.start_server_batch( + cygrpc.Operations( + (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), + _receive_message(self._state, self._call, + self._request_deserializer)) + self._state.due.add(_RECEIVE_MESSAGE_TOKEN) + + def _look_for_request(self): + if self._state.client is _CANCELLED: + _raise_rpc_error(self._state) + elif (self._state.request is None and + _RECEIVE_MESSAGE_TOKEN not in self._state.due): + raise StopIteration() + else: + request = self._state.request + self._state.request = None + return request - def _next(self): - with self._state.condition: - self._raise_or_start_receive_message() - while True: - self._state.condition.wait() - request = self._look_for_request() - if request is not None: - return request + def _next(self): + with self._state.condition: + self._raise_or_start_receive_message() + while True: + self._state.condition.wait() + request = self._look_for_request() + if request is not None: + return request - def __iter__(self): - return self + def __iter__(self): + return self - def __next__(self): - return self._next() + def __next__(self): + return self._next() - def next(self): - return self._next() + def next(self): + return self._next() def _unary_request(rpc_event, state, request_deserializer): - def unary_request(): - with state.condition: - if state.client is _CANCELLED or state.statused: - return None - else: - start_server_batch_result = rpc_event.operation_call.start_server_batch( - cygrpc.Operations( - (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), - _receive_message( - state, rpc_event.operation_call, request_deserializer)) - state.due.add(_RECEIVE_MESSAGE_TOKEN) - while True: - state.condition.wait() - if state.request is None: - if state.client is _CLOSED: - details = '"{}" requires exactly one request message.'.format( - rpc_event.request_call_details.method) - _abort( - state, rpc_event.operation_call, - cygrpc.StatusCode.unimplemented, _common.encode(details)) - return None - elif state.client is _CANCELLED: - return None - else: - request = state.request - state.request = None - return request - return unary_request + + def unary_request(): + with state.condition: + if state.client is _CANCELLED or state.statused: + return None + else: + start_server_batch_result = rpc_event.operation_call.start_server_batch( + cygrpc.Operations( + (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), + _receive_message(state, rpc_event.operation_call, + request_deserializer)) + state.due.add(_RECEIVE_MESSAGE_TOKEN) + while True: + state.condition.wait() + if state.request is None: + if state.client is _CLOSED: + details = '"{}" requires exactly one request message.'.format( + rpc_event.request_call_details.method) + _abort(state, rpc_event.operation_call, + cygrpc.StatusCode.unimplemented, + _common.encode(details)) + return None + elif state.client is _CANCELLED: + return None + else: + request = state.request + state.request = None + return request + + return unary_request def _call_behavior(rpc_event, state, behavior, argument, request_deserializer): - context = _Context(rpc_event, state, request_deserializer) - try: - return behavior(argument, context), True - except Exception as e: # pylint: disable=broad-except - with state.condition: - if e not in state.rpc_errors: - details = 'Exception calling application: {}'.format(e) - logging.exception(details) - _abort(state, rpc_event.operation_call, - cygrpc.StatusCode.unknown, _common.encode(details)) - return None, False + context = _Context(rpc_event, state, request_deserializer) + try: + return behavior(argument, context), True + except Exception as e: # pylint: disable=broad-except + with state.condition: + if e not in state.rpc_errors: + details = 'Exception calling application: {}'.format(e) + logging.exception(details) + _abort(state, rpc_event.operation_call, + cygrpc.StatusCode.unknown, _common.encode(details)) + return None, False def _take_response_from_response_iterator(rpc_event, state, response_iterator): - try: - return next(response_iterator), True - except StopIteration: - return None, True - except Exception as e: # pylint: disable=broad-except - with state.condition: - if e not in state.rpc_errors: - details = 'Exception iterating responses: {}'.format(e) - logging.exception(details) - _abort(state, rpc_event.operation_call, - cygrpc.StatusCode.unknown, _common.encode(details)) - return None, False + try: + return next(response_iterator), True + except StopIteration: + return None, True + except Exception as e: # pylint: disable=broad-except + with state.condition: + if e not in state.rpc_errors: + details = 'Exception iterating responses: {}'.format(e) + logging.exception(details) + _abort(state, rpc_event.operation_call, + cygrpc.StatusCode.unknown, _common.encode(details)) + return None, False def _serialize_response(rpc_event, state, response, response_serializer): - serialized_response = _common.serialize(response, response_serializer) - if serialized_response is None: - with state.condition: - _abort( - state, rpc_event.operation_call, cygrpc.StatusCode.internal, - b'Failed to serialize response!') - return None - else: - return serialized_response + serialized_response = _common.serialize(response, response_serializer) + if serialized_response is None: + with state.condition: + _abort(state, rpc_event.operation_call, cygrpc.StatusCode.internal, + b'Failed to serialize response!') + return None + else: + return serialized_response def _send_response(rpc_event, state, serialized_response): - with state.condition: - if state.client is _CANCELLED or state.statused: - return False - else: - if state.initial_metadata_allowed: - operations = ( - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS), - cygrpc.operation_send_message(serialized_response, _EMPTY_FLAGS), - ) - state.initial_metadata_allowed = False - token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN - else: - operations = ( - cygrpc.operation_send_message(serialized_response, _EMPTY_FLAGS), - ) - token = _SEND_MESSAGE_TOKEN - rpc_event.operation_call.start_server_batch( - cygrpc.Operations(operations), _send_message(state, token)) - state.due.add(token) - while True: - state.condition.wait() - if token not in state.due: - return state.client is not _CANCELLED and not state.statused + with state.condition: + if state.client is _CANCELLED or state.statused: + return False + else: + if state.initial_metadata_allowed: + operations = ( + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS), + cygrpc.operation_send_message(serialized_response, + _EMPTY_FLAGS),) + state.initial_metadata_allowed = False + token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN + else: + operations = (cygrpc.operation_send_message(serialized_response, + _EMPTY_FLAGS),) + token = _SEND_MESSAGE_TOKEN + rpc_event.operation_call.start_server_batch( + cygrpc.Operations(operations), _send_message(state, token)) + state.due.add(token) + while True: + state.condition.wait() + if token not in state.due: + return state.client is not _CANCELLED and not state.statused def _status(rpc_event, state, serialized_response): - with state.condition: - if state.client is not _CANCELLED: - trailing_metadata = _common.cygrpc_metadata(state.trailing_metadata) - code = _completion_code(state) - details = _details(state) - operations = [ - cygrpc.operation_send_status_from_server( - trailing_metadata, code, details, _EMPTY_FLAGS), - ] - if state.initial_metadata_allowed: - operations.append( - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS)) - if serialized_response is not None: - operations.append(cygrpc.operation_send_message( - serialized_response, _EMPTY_FLAGS)) - rpc_event.operation_call.start_server_batch( - cygrpc.Operations(operations), - _send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN)) - state.statused = True - state.due.add(_SEND_STATUS_FROM_SERVER_TOKEN) - - -def _unary_response_in_pool( - rpc_event, state, behavior, argument_thunk, request_deserializer, - response_serializer): - argument = argument_thunk() - if argument is not None: - response, proceed = _call_behavior( - rpc_event, state, behavior, argument, request_deserializer) - if proceed: - serialized_response = _serialize_response( - rpc_event, state, response, response_serializer) - if serialized_response is not None: - _status(rpc_event, state, serialized_response) - - -def _stream_response_in_pool( - rpc_event, state, behavior, argument_thunk, request_deserializer, - response_serializer): - argument = argument_thunk() - if argument is not None: - response_iterator, proceed = _call_behavior( - rpc_event, state, behavior, argument, request_deserializer) - if proceed: - while True: - response, proceed = _take_response_from_response_iterator( - rpc_event, state, response_iterator) + with state.condition: + if state.client is not _CANCELLED: + trailing_metadata = _common.cygrpc_metadata(state.trailing_metadata) + code = _completion_code(state) + details = _details(state) + operations = [ + cygrpc.operation_send_status_from_server( + trailing_metadata, code, details, _EMPTY_FLAGS), + ] + if state.initial_metadata_allowed: + operations.append( + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS)) + if serialized_response is not None: + operations.append( + cygrpc.operation_send_message(serialized_response, + _EMPTY_FLAGS)) + rpc_event.operation_call.start_server_batch( + cygrpc.Operations(operations), + _send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN)) + state.statused = True + state.due.add(_SEND_STATUS_FROM_SERVER_TOKEN) + + +def _unary_response_in_pool(rpc_event, state, behavior, argument_thunk, + request_deserializer, response_serializer): + argument = argument_thunk() + if argument is not None: + response, proceed = _call_behavior(rpc_event, state, behavior, argument, + request_deserializer) if proceed: - if response is None: - _status(rpc_event, state, None) - break - else: serialized_response = _serialize_response( rpc_event, state, response, response_serializer) if serialized_response is not None: - proceed = _send_response(rpc_event, state, serialized_response) - if not proceed: - break - else: - break - else: - break + _status(rpc_event, state, serialized_response) + + +def _stream_response_in_pool(rpc_event, state, behavior, argument_thunk, + request_deserializer, response_serializer): + argument = argument_thunk() + if argument is not None: + response_iterator, proceed = _call_behavior( + rpc_event, state, behavior, argument, request_deserializer) + if proceed: + while True: + response, proceed = _take_response_from_response_iterator( + rpc_event, state, response_iterator) + if proceed: + if response is None: + _status(rpc_event, state, None) + break + else: + serialized_response = _serialize_response( + rpc_event, state, response, response_serializer) + if serialized_response is not None: + proceed = _send_response(rpc_event, state, + serialized_response) + if not proceed: + break + else: + break + else: + break def _handle_unary_unary(rpc_event, state, method_handler, thread_pool): - unary_request = _unary_request( - rpc_event, state, method_handler.request_deserializer) - thread_pool.submit( - _unary_response_in_pool, rpc_event, state, method_handler.unary_unary, - unary_request, method_handler.request_deserializer, - method_handler.response_serializer) + unary_request = _unary_request(rpc_event, state, + method_handler.request_deserializer) + thread_pool.submit(_unary_response_in_pool, rpc_event, state, + method_handler.unary_unary, unary_request, + method_handler.request_deserializer, + method_handler.response_serializer) def _handle_unary_stream(rpc_event, state, method_handler, thread_pool): - unary_request = _unary_request( - rpc_event, state, method_handler.request_deserializer) - thread_pool.submit( - _stream_response_in_pool, rpc_event, state, method_handler.unary_stream, - unary_request, method_handler.request_deserializer, - method_handler.response_serializer) + unary_request = _unary_request(rpc_event, state, + method_handler.request_deserializer) + thread_pool.submit(_stream_response_in_pool, rpc_event, state, + method_handler.unary_stream, unary_request, + method_handler.request_deserializer, + method_handler.response_serializer) def _handle_stream_unary(rpc_event, state, method_handler, thread_pool): - request_iterator = _RequestIterator( - state, rpc_event.operation_call, method_handler.request_deserializer) - thread_pool.submit( - _unary_response_in_pool, rpc_event, state, method_handler.stream_unary, - lambda: request_iterator, method_handler.request_deserializer, - method_handler.response_serializer) + request_iterator = _RequestIterator(state, rpc_event.operation_call, + method_handler.request_deserializer) + thread_pool.submit(_unary_response_in_pool, rpc_event, state, + method_handler.stream_unary, lambda: request_iterator, + method_handler.request_deserializer, + method_handler.response_serializer) def _handle_stream_stream(rpc_event, state, method_handler, thread_pool): - request_iterator = _RequestIterator( - state, rpc_event.operation_call, method_handler.request_deserializer) - thread_pool.submit( - _stream_response_in_pool, rpc_event, state, method_handler.stream_stream, - lambda: request_iterator, method_handler.request_deserializer, - method_handler.response_serializer) + request_iterator = _RequestIterator(state, rpc_event.operation_call, + method_handler.request_deserializer) + thread_pool.submit(_stream_response_in_pool, rpc_event, state, + method_handler.stream_stream, lambda: request_iterator, + method_handler.request_deserializer, + method_handler.response_serializer) def _find_method_handler(rpc_event, generic_handlers): - for generic_handler in generic_handlers: - method_handler = generic_handler.service( - _HandlerCallDetails( - _common.decode(rpc_event.request_call_details.method), - rpc_event.request_metadata)) - if method_handler is not None: - return method_handler - else: - return None + for generic_handler in generic_handlers: + method_handler = generic_handler.service( + _HandlerCallDetails( + _common.decode(rpc_event.request_call_details.method), + rpc_event.request_metadata)) + if method_handler is not None: + return method_handler + else: + return None def _handle_unrecognized_method(rpc_event): - operations = ( - cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), - cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), - cygrpc.operation_send_status_from_server( - _EMPTY_METADATA, cygrpc.StatusCode.unimplemented, - b'Method not found!', _EMPTY_FLAGS), - ) - rpc_state = _RPCState() - rpc_event.operation_call.start_server_batch( - operations, lambda ignored_event: (rpc_state, (),)) - return rpc_state + operations = ( + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), + cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), + cygrpc.operation_send_status_from_server( + _EMPTY_METADATA, cygrpc.StatusCode.unimplemented, + b'Method not found!', _EMPTY_FLAGS),) + rpc_state = _RPCState() + rpc_event.operation_call.start_server_batch(operations, + lambda ignored_event: ( + rpc_state, + (),)) + return rpc_state def _handle_with_method_handler(rpc_event, method_handler, thread_pool): - state = _RPCState() - with state.condition: - rpc_event.operation_call.start_server_batch( - cygrpc.Operations( - (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), - _receive_close_on_server(state)) - state.due.add(_RECEIVE_CLOSE_ON_SERVER_TOKEN) - if method_handler.request_streaming: - if method_handler.response_streaming: - _handle_stream_stream(rpc_event, state, method_handler, thread_pool) - else: - _handle_stream_unary(rpc_event, state, method_handler, thread_pool) - else: - if method_handler.response_streaming: - _handle_unary_stream(rpc_event, state, method_handler, thread_pool) - else: - _handle_unary_unary(rpc_event, state, method_handler, thread_pool) - return state + state = _RPCState() + with state.condition: + rpc_event.operation_call.start_server_batch( + cygrpc.Operations( + (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), + _receive_close_on_server(state)) + state.due.add(_RECEIVE_CLOSE_ON_SERVER_TOKEN) + if method_handler.request_streaming: + if method_handler.response_streaming: + _handle_stream_stream(rpc_event, state, method_handler, + thread_pool) + else: + _handle_stream_unary(rpc_event, state, method_handler, + thread_pool) + else: + if method_handler.response_streaming: + _handle_unary_stream(rpc_event, state, method_handler, + thread_pool) + else: + _handle_unary_unary(rpc_event, state, method_handler, + thread_pool) + return state def _handle_call(rpc_event, generic_handlers, thread_pool): - if rpc_event.request_call_details.method is not None: - method_handler = _find_method_handler(rpc_event, generic_handlers) - if method_handler is None: - return _handle_unrecognized_method(rpc_event) + if rpc_event.request_call_details.method is not None: + method_handler = _find_method_handler(rpc_event, generic_handlers) + if method_handler is None: + return _handle_unrecognized_method(rpc_event) + else: + return _handle_with_method_handler(rpc_event, method_handler, + thread_pool) else: - return _handle_with_method_handler(rpc_event, method_handler, thread_pool) - else: - return None + return None @enum.unique class _ServerStage(enum.Enum): - STOPPED = 'stopped' - STARTED = 'started' - GRACE = 'grace' + STOPPED = 'stopped' + STARTED = 'started' + GRACE = 'grace' class _ServerState(object): - def __init__(self, completion_queue, server, generic_handlers, thread_pool): - self.lock = threading.Lock() - self.completion_queue = completion_queue - self.server = server - self.generic_handlers = list(generic_handlers) - self.thread_pool = thread_pool - self.stage = _ServerStage.STOPPED - self.shutdown_events = None + def __init__(self, completion_queue, server, generic_handlers, thread_pool): + self.lock = threading.Lock() + self.completion_queue = completion_queue + self.server = server + self.generic_handlers = list(generic_handlers) + self.thread_pool = thread_pool + self.stage = _ServerStage.STOPPED + self.shutdown_events = None - # TODO(https://github.com/grpc/grpc/issues/6597): eliminate these fields. - self.rpc_states = set() - self.due = set() + # TODO(https://github.com/grpc/grpc/issues/6597): eliminate these fields. + self.rpc_states = set() + self.due = set() def _add_generic_handlers(state, generic_handlers): - with state.lock: - state.generic_handlers.extend(generic_handlers) + with state.lock: + state.generic_handlers.extend(generic_handlers) def _add_insecure_port(state, address): - with state.lock: - return state.server.add_http2_port(address) + with state.lock: + return state.server.add_http2_port(address) def _add_secure_port(state, address, server_credentials): - with state.lock: - return state.server.add_http2_port(address, server_credentials._credentials) + with state.lock: + return state.server.add_http2_port(address, + server_credentials._credentials) def _request_call(state): - state.server.request_call( - state.completion_queue, state.completion_queue, _REQUEST_CALL_TAG) - state.due.add(_REQUEST_CALL_TAG) + state.server.request_call(state.completion_queue, state.completion_queue, + _REQUEST_CALL_TAG) + state.due.add(_REQUEST_CALL_TAG) # TODO(https://github.com/grpc/grpc/issues/6597): delete this function. def _stop_serving(state): - if not state.rpc_states and not state.due: - for shutdown_event in state.shutdown_events: - shutdown_event.set() - state.stage = _ServerStage.STOPPED - return True - else: - return False + if not state.rpc_states and not state.due: + for shutdown_event in state.shutdown_events: + shutdown_event.set() + state.stage = _ServerStage.STOPPED + return True + else: + return False def _serve(state): - while True: - event = state.completion_queue.poll() - if event.tag is _SHUTDOWN_TAG: - with state.lock: - state.due.remove(_SHUTDOWN_TAG) - if _stop_serving(state): - return - elif event.tag is _REQUEST_CALL_TAG: - with state.lock: - state.due.remove(_REQUEST_CALL_TAG) - rpc_state = _handle_call( - event, state.generic_handlers, state.thread_pool) - if rpc_state is not None: - state.rpc_states.add(rpc_state) - if state.stage is _ServerStage.STARTED: - _request_call(state) - elif _stop_serving(state): - return - else: - rpc_state, callbacks = event.tag(event) - for callback in callbacks: - callable_util.call_logging_exceptions( - callback, 'Exception calling callback!') - if rpc_state is not None: - with state.lock: - state.rpc_states.remove(rpc_state) - if _stop_serving(state): - return + while True: + event = state.completion_queue.poll() + if event.tag is _SHUTDOWN_TAG: + with state.lock: + state.due.remove(_SHUTDOWN_TAG) + if _stop_serving(state): + return + elif event.tag is _REQUEST_CALL_TAG: + with state.lock: + state.due.remove(_REQUEST_CALL_TAG) + rpc_state = _handle_call(event, state.generic_handlers, + state.thread_pool) + if rpc_state is not None: + state.rpc_states.add(rpc_state) + if state.stage is _ServerStage.STARTED: + _request_call(state) + elif _stop_serving(state): + return + else: + rpc_state, callbacks = event.tag(event) + for callback in callbacks: + callable_util.call_logging_exceptions( + callback, 'Exception calling callback!') + if rpc_state is not None: + with state.lock: + state.rpc_states.remove(rpc_state) + if _stop_serving(state): + return def _stop(state, grace): - with state.lock: - if state.stage is _ServerStage.STOPPED: - shutdown_event = threading.Event() - shutdown_event.set() - return shutdown_event - else: - if state.stage is _ServerStage.STARTED: - state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG) - state.stage = _ServerStage.GRACE - state.shutdown_events = [] - state.due.add(_SHUTDOWN_TAG) - shutdown_event = threading.Event() - state.shutdown_events.append(shutdown_event) - if grace is None: - state.server.cancel_all_calls() - # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. - for rpc_state in state.rpc_states: - with rpc_state.condition: - rpc_state.client = _CANCELLED - rpc_state.condition.notify_all() - else: - def cancel_all_calls_after_grace(): - shutdown_event.wait(timeout=grace) - with state.lock: - state.server.cancel_all_calls() - # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. - for rpc_state in state.rpc_states: - with rpc_state.condition: - rpc_state.client = _CANCELLED - rpc_state.condition.notify_all() - thread = threading.Thread(target=cancel_all_calls_after_grace) - thread.start() - return shutdown_event - shutdown_event.wait() - return shutdown_event + with state.lock: + if state.stage is _ServerStage.STOPPED: + shutdown_event = threading.Event() + shutdown_event.set() + return shutdown_event + else: + if state.stage is _ServerStage.STARTED: + state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG) + state.stage = _ServerStage.GRACE + state.shutdown_events = [] + state.due.add(_SHUTDOWN_TAG) + shutdown_event = threading.Event() + state.shutdown_events.append(shutdown_event) + if grace is None: + state.server.cancel_all_calls() + # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. + for rpc_state in state.rpc_states: + with rpc_state.condition: + rpc_state.client = _CANCELLED + rpc_state.condition.notify_all() + else: + + def cancel_all_calls_after_grace(): + shutdown_event.wait(timeout=grace) + with state.lock: + state.server.cancel_all_calls() + # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop. + for rpc_state in state.rpc_states: + with rpc_state.condition: + rpc_state.client = _CANCELLED + rpc_state.condition.notify_all() + + thread = threading.Thread(target=cancel_all_calls_after_grace) + thread.start() + return shutdown_event + shutdown_event.wait() + return shutdown_event def _start(state): - with state.lock: - if state.stage is not _ServerStage.STOPPED: - raise ValueError('Cannot start already-started server!') - state.server.start() - state.stage = _ServerStage.STARTED - _request_call(state) - def cleanup_server(timeout): - if timeout is None: - _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait() - else: - _stop(state, timeout).wait() - - thread = _common.CleanupThread( - cleanup_server, target=_serve, args=(state,)) - thread.start() + with state.lock: + if state.stage is not _ServerStage.STOPPED: + raise ValueError('Cannot start already-started server!') + state.server.start() + state.stage = _ServerStage.STARTED + _request_call(state) + + def cleanup_server(timeout): + if timeout is None: + _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait() + else: + _stop(state, timeout).wait() + + thread = _common.CleanupThread( + cleanup_server, target=_serve, args=(state,)) + thread.start() + class Server(grpc.Server): - def __init__(self, thread_pool, generic_handlers, options): - completion_queue = cygrpc.CompletionQueue() - server = cygrpc.Server(_common.channel_args(options)) - server.register_completion_queue(completion_queue) - self._state = _ServerState( - completion_queue, server, generic_handlers, thread_pool) + def __init__(self, thread_pool, generic_handlers, options): + completion_queue = cygrpc.CompletionQueue() + server = cygrpc.Server(_common.channel_args(options)) + server.register_completion_queue(completion_queue) + self._state = _ServerState(completion_queue, server, generic_handlers, + thread_pool) - def add_generic_rpc_handlers(self, generic_rpc_handlers): - _add_generic_handlers(self._state, generic_rpc_handlers) + def add_generic_rpc_handlers(self, generic_rpc_handlers): + _add_generic_handlers(self._state, generic_rpc_handlers) - def add_insecure_port(self, address): - return _add_insecure_port(self._state, _common.encode(address)) + def add_insecure_port(self, address): + return _add_insecure_port(self._state, _common.encode(address)) - def add_secure_port(self, address, server_credentials): - return _add_secure_port(self._state, _common.encode(address), server_credentials) + def add_secure_port(self, address, server_credentials): + return _add_secure_port(self._state, + _common.encode(address), server_credentials) - def start(self): - _start(self._state) + def start(self): + _start(self._state) - def stop(self, grace): - return _stop(self._state, grace) + def stop(self, grace): + return _stop(self._state, grace) - def __del__(self): - _stop(self._state, None) + def __del__(self): + _stop(self._state, None) diff --git a/src/python/grpcio/grpc/_utilities.py b/src/python/grpcio/grpc/_utilities.py index a375896e6e6..7c602eb37e3 100644 --- a/src/python/grpcio/grpc/_utilities.py +++ b/src/python/grpcio/grpc/_utilities.py @@ -26,7 +26,6 @@ # 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. - """Internal utilities for gRPC Python.""" import collections @@ -44,132 +43,136 @@ _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = ( class RpcMethodHandler( - collections.namedtuple( - '_RpcMethodHandler', - ('request_streaming', 'response_streaming', 'request_deserializer', - 'response_serializer', 'unary_unary', 'unary_stream', 'stream_unary', - 'stream_stream',)), - grpc.RpcMethodHandler): - pass + collections.namedtuple('_RpcMethodHandler', ( + 'request_streaming', + 'response_streaming', + 'request_deserializer', + 'response_serializer', + 'unary_unary', + 'unary_stream', + 'stream_unary', + 'stream_stream',)), grpc.RpcMethodHandler): + pass class DictionaryGenericHandler(grpc.ServiceRpcHandler): - def __init__(self, service, method_handlers): - self._name = service - self._method_handlers = { - _common.fully_qualified_method(service, method): method_handler - for method, method_handler in six.iteritems(method_handlers)} + def __init__(self, service, method_handlers): + self._name = service + self._method_handlers = { + _common.fully_qualified_method(service, method): method_handler + for method, method_handler in six.iteritems(method_handlers) + } - def service_name(self): - return self._name + def service_name(self): + return self._name - def service(self, handler_call_details): - return self._method_handlers.get(handler_call_details.method) + def service(self, handler_call_details): + return self._method_handlers.get(handler_call_details.method) class _ChannelReadyFuture(grpc.Future): - def __init__(self, channel): - self._condition = threading.Condition() - self._channel = channel - - self._matured = False - self._cancelled = False - self._done_callbacks = [] - - def _block(self, timeout): - until = None if timeout is None else time.time() + timeout - with self._condition: - while True: - if self._cancelled: - raise grpc.FutureCancelledError() - elif self._matured: - return - else: - if until is None: - self._condition.wait() - else: - remaining = until - time.time() - if remaining < 0: - raise grpc.FutureTimeoutError() + def __init__(self, channel): + self._condition = threading.Condition() + self._channel = channel + + self._matured = False + self._cancelled = False + self._done_callbacks = [] + + def _block(self, timeout): + until = None if timeout is None else time.time() + timeout + with self._condition: + while True: + if self._cancelled: + raise grpc.FutureCancelledError() + elif self._matured: + return + else: + if until is None: + self._condition.wait() + else: + remaining = until - time.time() + if remaining < 0: + raise grpc.FutureTimeoutError() + else: + self._condition.wait(timeout=remaining) + + def _update(self, connectivity): + with self._condition: + if (not self._cancelled and + connectivity is grpc.ChannelConnectivity.READY): + self._matured = True + self._channel.unsubscribe(self._update) + self._condition.notify_all() + done_callbacks = tuple(self._done_callbacks) + self._done_callbacks = None + else: + return + + for done_callback in done_callbacks: + callable_util.call_logging_exceptions( + done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) + + def cancel(self): + with self._condition: + if not self._matured: + self._cancelled = True + self._channel.unsubscribe(self._update) + self._condition.notify_all() + done_callbacks = tuple(self._done_callbacks) + self._done_callbacks = None else: - self._condition.wait(timeout=remaining) - - def _update(self, connectivity): - with self._condition: - if (not self._cancelled and - connectivity is grpc.ChannelConnectivity.READY): - self._matured = True - self._channel.unsubscribe(self._update) - self._condition.notify_all() - done_callbacks = tuple(self._done_callbacks) - self._done_callbacks = None - else: - return - - for done_callback in done_callbacks: - callable_util.call_logging_exceptions( - done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) - - def cancel(self): - with self._condition: - if not self._matured: - self._cancelled = True - self._channel.unsubscribe(self._update) - self._condition.notify_all() - done_callbacks = tuple(self._done_callbacks) - self._done_callbacks = None - else: - return False - - for done_callback in done_callbacks: - callable_util.call_logging_exceptions( - done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) - - def cancelled(self): - with self._condition: - return self._cancelled - - def running(self): - with self._condition: - return not self._cancelled and not self._matured - - def done(self): - with self._condition: - return self._cancelled or self._matured - - def result(self, timeout=None): - self._block(timeout) - return None - - def exception(self, timeout=None): - self._block(timeout) - return None - - def traceback(self, timeout=None): - self._block(timeout) - return None - - def add_done_callback(self, fn): - with self._condition: - if not self._cancelled and not self._matured: - self._done_callbacks.append(fn) - return - - fn(self) - - def start(self): - with self._condition: - self._channel.subscribe(self._update, try_to_connect=True) - - def __del__(self): - with self._condition: - if not self._cancelled and not self._matured: - self._channel.unsubscribe(self._update) + return False + + for done_callback in done_callbacks: + callable_util.call_logging_exceptions( + done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) + + def cancelled(self): + with self._condition: + return self._cancelled + + def running(self): + with self._condition: + return not self._cancelled and not self._matured + + def done(self): + with self._condition: + return self._cancelled or self._matured + + def result(self, timeout=None): + self._block(timeout) + return None + + def exception(self, timeout=None): + self._block(timeout) + return None + + def traceback(self, timeout=None): + self._block(timeout) + return None + + def add_done_callback(self, fn): + with self._condition: + if not self._cancelled and not self._matured: + self._done_callbacks.append(fn) + return + + fn(self) + + def start(self): + with self._condition: + self._channel.subscribe(self._update, try_to_connect=True) + + def __del__(self): + with self._condition: + if not self._cancelled and not self._matured: + self._channel.unsubscribe(self._update) def channel_ready_future(channel): - ready_future = _ChannelReadyFuture(channel) - ready_future.start() - return ready_future + ready_future = _ChannelReadyFuture(channel) + ready_future.start() + return ready_future diff --git a/src/python/grpcio/grpc/beta/_client_adaptations.py b/src/python/grpcio/grpc/beta/_client_adaptations.py index e4ee44d7a3e..e5b28e9408e 100644 --- a/src/python/grpcio/grpc/beta/_client_adaptations.py +++ b/src/python/grpcio/grpc/beta/_client_adaptations.py @@ -26,7 +26,6 @@ # 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. - """Translates gRPC's client-side API into gRPC's client-side Beta API.""" import grpc @@ -38,531 +37,654 @@ from grpc.framework.foundation import future from grpc.framework.interfaces.face import face _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS = { - grpc.StatusCode.CANCELLED: ( - face.Abortion.Kind.CANCELLED, face.CancellationError), - grpc.StatusCode.UNKNOWN: ( - face.Abortion.Kind.REMOTE_FAILURE, face.RemoteError), - grpc.StatusCode.DEADLINE_EXCEEDED: ( - face.Abortion.Kind.EXPIRED, face.ExpirationError), - grpc.StatusCode.UNIMPLEMENTED: ( - face.Abortion.Kind.LOCAL_FAILURE, face.LocalError), + grpc.StatusCode.CANCELLED: (face.Abortion.Kind.CANCELLED, + face.CancellationError), + grpc.StatusCode.UNKNOWN: (face.Abortion.Kind.REMOTE_FAILURE, + face.RemoteError), + grpc.StatusCode.DEADLINE_EXCEEDED: (face.Abortion.Kind.EXPIRED, + face.ExpirationError), + grpc.StatusCode.UNIMPLEMENTED: (face.Abortion.Kind.LOCAL_FAILURE, + face.LocalError), } def _effective_metadata(metadata, metadata_transformer): - non_none_metadata = () if metadata is None else metadata - if metadata_transformer is None: - return non_none_metadata - else: - return metadata_transformer(non_none_metadata) + non_none_metadata = () if metadata is None else metadata + if metadata_transformer is None: + return non_none_metadata + else: + return metadata_transformer(non_none_metadata) def _credentials(grpc_call_options): - return None if grpc_call_options is None else grpc_call_options.credentials + return None if grpc_call_options is None else grpc_call_options.credentials def _abortion(rpc_error_call): - code = rpc_error_call.code() - pair = _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS.get(code) - error_kind = face.Abortion.Kind.LOCAL_FAILURE if pair is None else pair[0] - return face.Abortion( - error_kind, rpc_error_call.initial_metadata(), - rpc_error_call.trailing_metadata(), code, rpc_error_call.details()) + code = rpc_error_call.code() + pair = _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS.get(code) + error_kind = face.Abortion.Kind.LOCAL_FAILURE if pair is None else pair[0] + return face.Abortion(error_kind, + rpc_error_call.initial_metadata(), + rpc_error_call.trailing_metadata(), code, + rpc_error_call.details()) def _abortion_error(rpc_error_call): - code = rpc_error_call.code() - pair = _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS.get(code) - exception_class = face.AbortionError if pair is None else pair[1] - return exception_class( - rpc_error_call.initial_metadata(), rpc_error_call.trailing_metadata(), - code, rpc_error_call.details()) + code = rpc_error_call.code() + pair = _STATUS_CODE_TO_ABORTION_KIND_AND_ABORTION_ERROR_CLASS.get(code) + exception_class = face.AbortionError if pair is None else pair[1] + return exception_class(rpc_error_call.initial_metadata(), + rpc_error_call.trailing_metadata(), code, + rpc_error_call.details()) class _InvocationProtocolContext(interfaces.GRPCInvocationContext): - def disable_next_request_compression(self): - pass # TODO(https://github.com/grpc/grpc/issues/4078): design, implement. + def disable_next_request_compression(self): + pass # TODO(https://github.com/grpc/grpc/issues/4078): design, implement. class _Rendezvous(future.Future, face.Call): - def __init__(self, response_future, response_iterator, call): - self._future = response_future - self._iterator = response_iterator - self._call = call + def __init__(self, response_future, response_iterator, call): + self._future = response_future + self._iterator = response_iterator + self._call = call - def cancel(self): - return self._call.cancel() + def cancel(self): + return self._call.cancel() - def cancelled(self): - return self._future.cancelled() + def cancelled(self): + return self._future.cancelled() - def running(self): - return self._future.running() + def running(self): + return self._future.running() - def done(self): - return self._future.done() + def done(self): + return self._future.done() - def result(self, timeout=None): - try: - return self._future.result(timeout=timeout) - except grpc.RpcError as rpc_error_call: - raise _abortion_error(rpc_error_call) - except grpc.FutureTimeoutError: - raise future.TimeoutError() - except grpc.FutureCancelledError: - raise future.CancelledError() + def result(self, timeout=None): + try: + return self._future.result(timeout=timeout) + except grpc.RpcError as rpc_error_call: + raise _abortion_error(rpc_error_call) + except grpc.FutureTimeoutError: + raise future.TimeoutError() + except grpc.FutureCancelledError: + raise future.CancelledError() - def exception(self, timeout=None): - try: - rpc_error_call = self._future.exception(timeout=timeout) - if rpc_error_call is None: - return None - else: - return _abortion_error(rpc_error_call) - except grpc.FutureTimeoutError: - raise future.TimeoutError() - except grpc.FutureCancelledError: - raise future.CancelledError() - - def traceback(self, timeout=None): - try: - return self._future.traceback(timeout=timeout) - except grpc.FutureTimeoutError: - raise future.TimeoutError() - except grpc.FutureCancelledError: - raise future.CancelledError() + def exception(self, timeout=None): + try: + rpc_error_call = self._future.exception(timeout=timeout) + if rpc_error_call is None: + return None + else: + return _abortion_error(rpc_error_call) + except grpc.FutureTimeoutError: + raise future.TimeoutError() + except grpc.FutureCancelledError: + raise future.CancelledError() - def add_done_callback(self, fn): - self._future.add_done_callback(lambda ignored_callback: fn(self)) + def traceback(self, timeout=None): + try: + return self._future.traceback(timeout=timeout) + except grpc.FutureTimeoutError: + raise future.TimeoutError() + except grpc.FutureCancelledError: + raise future.CancelledError() - def __iter__(self): - return self + def add_done_callback(self, fn): + self._future.add_done_callback(lambda ignored_callback: fn(self)) - def _next(self): - try: - return next(self._iterator) - except grpc.RpcError as rpc_error_call: - raise _abortion_error(rpc_error_call) + def __iter__(self): + return self + + def _next(self): + try: + return next(self._iterator) + except grpc.RpcError as rpc_error_call: + raise _abortion_error(rpc_error_call) + + def __next__(self): + return self._next() - def __next__(self): - return self._next() + def next(self): + return self._next() - def next(self): - return self._next() + def is_active(self): + return self._call.is_active() - def is_active(self): - return self._call.is_active() + def time_remaining(self): + return self._call.time_remaining() - def time_remaining(self): - return self._call.time_remaining() + def add_abortion_callback(self, abortion_callback): - def add_abortion_callback(self, abortion_callback): - def done_callback(): - if self.code() is not grpc.StatusCode.OK: - abortion_callback(_abortion(self._call)) - registered = self._call.add_callback(done_callback) - return None if registered else done_callback() + def done_callback(): + if self.code() is not grpc.StatusCode.OK: + abortion_callback(_abortion(self._call)) - def protocol_context(self): - return _InvocationProtocolContext() + registered = self._call.add_callback(done_callback) + return None if registered else done_callback() - def initial_metadata(self): - return self._call.initial_metadata() + def protocol_context(self): + return _InvocationProtocolContext() - def terminal_metadata(self): - return self._call.terminal_metadata() + def initial_metadata(self): + return self._call.initial_metadata() - def code(self): - return self._call.code() + def terminal_metadata(self): + return self._call.terminal_metadata() - def details(self): - return self._call.details() + def code(self): + return self._call.code() + def details(self): + return self._call.details() -def _blocking_unary_unary( - channel, group, method, timeout, with_call, protocol_options, metadata, - metadata_transformer, request, request_serializer, response_deserializer): - try: + +def _blocking_unary_unary(channel, group, method, timeout, with_call, + protocol_options, metadata, metadata_transformer, + request, request_serializer, response_deserializer): + try: + multi_callable = channel.unary_unary( + _common.fully_qualified_method(group, method), + request_serializer=request_serializer, + response_deserializer=response_deserializer) + effective_metadata = _effective_metadata(metadata, metadata_transformer) + if with_call: + response, call = multi_callable.with_call( + request, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + return response, _Rendezvous(None, None, call) + else: + return multi_callable( + request, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + except grpc.RpcError as rpc_error_call: + raise _abortion_error(rpc_error_call) + + +def _future_unary_unary(channel, group, method, timeout, protocol_options, + metadata, metadata_transformer, request, + request_serializer, response_deserializer): multi_callable = channel.unary_unary( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) - if with_call: - response, call = multi_callable.with_call( - request, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - return response, _Rendezvous(None, None, call) - else: - return multi_callable( - request, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - except grpc.RpcError as rpc_error_call: - raise _abortion_error(rpc_error_call) - - -def _future_unary_unary( - channel, group, method, timeout, protocol_options, metadata, - metadata_transformer, request, request_serializer, response_deserializer): - multi_callable = channel.unary_unary( - _common.fully_qualified_method(group, method), - request_serializer=request_serializer, - response_deserializer=response_deserializer) - effective_metadata = _effective_metadata(metadata, metadata_transformer) - response_future = multi_callable.future( - request, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - return _Rendezvous(response_future, None, response_future) - - -def _unary_stream( - channel, group, method, timeout, protocol_options, metadata, - metadata_transformer, request, request_serializer, response_deserializer): - multi_callable = channel.unary_stream( - _common.fully_qualified_method(group, method), - request_serializer=request_serializer, - response_deserializer=response_deserializer) - effective_metadata = _effective_metadata(metadata, metadata_transformer) - response_iterator = multi_callable( - request, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - return _Rendezvous(None, response_iterator, response_iterator) - - -def _blocking_stream_unary( - channel, group, method, timeout, with_call, protocol_options, metadata, - metadata_transformer, request_iterator, request_serializer, - response_deserializer): - try: + response_future = multi_callable.future( + request, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + return _Rendezvous(response_future, None, response_future) + + +def _unary_stream(channel, group, method, timeout, protocol_options, metadata, + metadata_transformer, request, request_serializer, + response_deserializer): + multi_callable = channel.unary_stream( + _common.fully_qualified_method(group, method), + request_serializer=request_serializer, + response_deserializer=response_deserializer) + effective_metadata = _effective_metadata(metadata, metadata_transformer) + response_iterator = multi_callable( + request, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + return _Rendezvous(None, response_iterator, response_iterator) + + +def _blocking_stream_unary(channel, group, method, timeout, with_call, + protocol_options, metadata, metadata_transformer, + request_iterator, request_serializer, + response_deserializer): + try: + multi_callable = channel.stream_unary( + _common.fully_qualified_method(group, method), + request_serializer=request_serializer, + response_deserializer=response_deserializer) + effective_metadata = _effective_metadata(metadata, metadata_transformer) + if with_call: + response, call = multi_callable.with_call( + request_iterator, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + return response, _Rendezvous(None, None, call) + else: + return multi_callable( + request_iterator, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + except grpc.RpcError as rpc_error_call: + raise _abortion_error(rpc_error_call) + + +def _future_stream_unary(channel, group, method, timeout, protocol_options, + metadata, metadata_transformer, request_iterator, + request_serializer, response_deserializer): multi_callable = channel.stream_unary( _common.fully_qualified_method(group, method), request_serializer=request_serializer, response_deserializer=response_deserializer) effective_metadata = _effective_metadata(metadata, metadata_transformer) - if with_call: - response, call = multi_callable.with_call( - request_iterator, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - return response, _Rendezvous(None, None, call) - else: - return multi_callable( - request_iterator, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - except grpc.RpcError as rpc_error_call: - raise _abortion_error(rpc_error_call) - - -def _future_stream_unary( - channel, group, method, timeout, protocol_options, metadata, - metadata_transformer, request_iterator, request_serializer, - response_deserializer): - multi_callable = channel.stream_unary( - _common.fully_qualified_method(group, method), - request_serializer=request_serializer, - response_deserializer=response_deserializer) - effective_metadata = _effective_metadata(metadata, metadata_transformer) - response_future = multi_callable.future( - request_iterator, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - return _Rendezvous(response_future, None, response_future) - - -def _stream_stream( - channel, group, method, timeout, protocol_options, metadata, - metadata_transformer, request_iterator, request_serializer, - response_deserializer): - multi_callable = channel.stream_stream( - _common.fully_qualified_method(group, method), - request_serializer=request_serializer, - response_deserializer=response_deserializer) - effective_metadata = _effective_metadata(metadata, metadata_transformer) - response_iterator = multi_callable( - request_iterator, timeout=timeout, metadata=effective_metadata, - credentials=_credentials(protocol_options)) - return _Rendezvous(None, response_iterator, response_iterator) + response_future = multi_callable.future( + request_iterator, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + return _Rendezvous(response_future, None, response_future) + + +def _stream_stream(channel, group, method, timeout, protocol_options, metadata, + metadata_transformer, request_iterator, request_serializer, + response_deserializer): + multi_callable = channel.stream_stream( + _common.fully_qualified_method(group, method), + request_serializer=request_serializer, + response_deserializer=response_deserializer) + effective_metadata = _effective_metadata(metadata, metadata_transformer) + response_iterator = multi_callable( + request_iterator, + timeout=timeout, + metadata=effective_metadata, + credentials=_credentials(protocol_options)) + return _Rendezvous(None, response_iterator, response_iterator) class _UnaryUnaryMultiCallable(face.UnaryUnaryMultiCallable): - def __init__( - self, channel, group, method, metadata_transformer, request_serializer, - response_deserializer): - self._channel = channel - self._group = group - self._method = method - self._metadata_transformer = metadata_transformer - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def __call__( - self, request, timeout, metadata=None, with_call=False, - protocol_options=None): - return _blocking_unary_unary( - self._channel, self._group, self._method, timeout, with_call, - protocol_options, metadata, self._metadata_transformer, request, - self._request_serializer, self._response_deserializer) - - def future(self, request, timeout, metadata=None, protocol_options=None): - return _future_unary_unary( - self._channel, self._group, self._method, timeout, protocol_options, - metadata, self._metadata_transformer, request, self._request_serializer, - self._response_deserializer) - - def event( - self, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - raise NotImplementedError() + def __init__(self, channel, group, method, metadata_transformer, + request_serializer, response_deserializer): + self._channel = channel + self._group = group + self._method = method + self._metadata_transformer = metadata_transformer + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def __call__(self, + request, + timeout, + metadata=None, + with_call=False, + protocol_options=None): + return _blocking_unary_unary( + self._channel, self._group, self._method, timeout, with_call, + protocol_options, metadata, self._metadata_transformer, request, + self._request_serializer, self._response_deserializer) + + def future(self, request, timeout, metadata=None, protocol_options=None): + return _future_unary_unary( + self._channel, self._group, self._method, timeout, protocol_options, + metadata, self._metadata_transformer, request, + self._request_serializer, self._response_deserializer) + + def event(self, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() class _UnaryStreamMultiCallable(face.UnaryStreamMultiCallable): - def __init__( - self, channel, group, method, metadata_transformer, request_serializer, - response_deserializer): - self._channel = channel - self._group = group - self._method = method - self._metadata_transformer = metadata_transformer - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def __call__(self, request, timeout, metadata=None, protocol_options=None): - return _unary_stream( - self._channel, self._group, self._method, timeout, protocol_options, - metadata, self._metadata_transformer, request, self._request_serializer, - self._response_deserializer) - - def event( - self, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - raise NotImplementedError() + def __init__(self, channel, group, method, metadata_transformer, + request_serializer, response_deserializer): + self._channel = channel + self._group = group + self._method = method + self._metadata_transformer = metadata_transformer + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def __call__(self, request, timeout, metadata=None, protocol_options=None): + return _unary_stream( + self._channel, self._group, self._method, timeout, protocol_options, + metadata, self._metadata_transformer, request, + self._request_serializer, self._response_deserializer) + + def event(self, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() class _StreamUnaryMultiCallable(face.StreamUnaryMultiCallable): - def __init__( - self, channel, group, method, metadata_transformer, request_serializer, - response_deserializer): - self._channel = channel - self._group = group - self._method = method - self._metadata_transformer = metadata_transformer - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def __call__( - self, request_iterator, timeout, metadata=None, with_call=False, - protocol_options=None): - return _blocking_stream_unary( - self._channel, self._group, self._method, timeout, with_call, - protocol_options, metadata, self._metadata_transformer, - request_iterator, self._request_serializer, self._response_deserializer) - - def future( - self, request_iterator, timeout, metadata=None, protocol_options=None): - return _future_stream_unary( - self._channel, self._group, self._method, timeout, protocol_options, - metadata, self._metadata_transformer, request_iterator, - self._request_serializer, self._response_deserializer) - - def event( - self, receiver, abortion_callback, timeout, metadata=None, - protocol_options=None): - raise NotImplementedError() + def __init__(self, channel, group, method, metadata_transformer, + request_serializer, response_deserializer): + self._channel = channel + self._group = group + self._method = method + self._metadata_transformer = metadata_transformer + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def __call__(self, + request_iterator, + timeout, + metadata=None, + with_call=False, + protocol_options=None): + return _blocking_stream_unary( + self._channel, self._group, self._method, timeout, with_call, + protocol_options, metadata, self._metadata_transformer, + request_iterator, self._request_serializer, + self._response_deserializer) + + def future(self, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + return _future_stream_unary( + self._channel, self._group, self._method, timeout, protocol_options, + metadata, self._metadata_transformer, request_iterator, + self._request_serializer, self._response_deserializer) + + def event(self, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() class _StreamStreamMultiCallable(face.StreamStreamMultiCallable): - def __init__( - self, channel, group, method, metadata_transformer, request_serializer, - response_deserializer): - self._channel = channel - self._group = group - self._method = method - self._metadata_transformer = metadata_transformer - self._request_serializer = request_serializer - self._response_deserializer = response_deserializer - - def __call__( - self, request_iterator, timeout, metadata=None, protocol_options=None): - return _stream_stream( - self._channel, self._group, self._method, timeout, protocol_options, - metadata, self._metadata_transformer, request_iterator, - self._request_serializer, self._response_deserializer) - - def event( - self, receiver, abortion_callback, timeout, metadata=None, - protocol_options=None): - raise NotImplementedError() + def __init__(self, channel, group, method, metadata_transformer, + request_serializer, response_deserializer): + self._channel = channel + self._group = group + self._method = method + self._metadata_transformer = metadata_transformer + self._request_serializer = request_serializer + self._response_deserializer = response_deserializer + + def __call__(self, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + return _stream_stream( + self._channel, self._group, self._method, timeout, protocol_options, + metadata, self._metadata_transformer, request_iterator, + self._request_serializer, self._response_deserializer) + + def event(self, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() class _GenericStub(face.GenericStub): - def __init__( - self, channel, metadata_transformer, request_serializers, - response_deserializers): - self._channel = channel - self._metadata_transformer = metadata_transformer - self._request_serializers = request_serializers or {} - self._response_deserializers = response_deserializers or {} - - def blocking_unary_unary( - self, group, method, request, timeout, metadata=None, - with_call=None, protocol_options=None): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _blocking_unary_unary( - self._channel, group, method, timeout, with_call, protocol_options, - metadata, self._metadata_transformer, request, request_serializer, - response_deserializer) - - def future_unary_unary( - self, group, method, request, timeout, metadata=None, - protocol_options=None): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _future_unary_unary( - self._channel, group, method, timeout, protocol_options, metadata, - self._metadata_transformer, request, request_serializer, - response_deserializer) - - def inline_unary_stream( - self, group, method, request, timeout, metadata=None, - protocol_options=None): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _unary_stream( - self._channel, group, method, timeout, protocol_options, metadata, - self._metadata_transformer, request, request_serializer, - response_deserializer) - - def blocking_stream_unary( - self, group, method, request_iterator, timeout, metadata=None, - with_call=None, protocol_options=None): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _blocking_stream_unary( - self._channel, group, method, timeout, with_call, protocol_options, - metadata, self._metadata_transformer, request_iterator, - request_serializer, response_deserializer) - - def future_stream_unary( - self, group, method, request_iterator, timeout, metadata=None, - protocol_options=None): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _future_stream_unary( - self._channel, group, method, timeout, protocol_options, metadata, - self._metadata_transformer, request_iterator, request_serializer, - response_deserializer) - - def inline_stream_stream( - self, group, method, request_iterator, timeout, metadata=None, - protocol_options=None): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _stream_stream( - self._channel, group, method, timeout, protocol_options, metadata, - self._metadata_transformer, request_iterator, request_serializer, - response_deserializer) - - def event_unary_unary( - self, group, method, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - raise NotImplementedError() - - def event_unary_stream( - self, group, method, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - raise NotImplementedError() - - def event_stream_unary( - self, group, method, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - raise NotImplementedError() - - def event_stream_stream( - self, group, method, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - raise NotImplementedError() - - def unary_unary(self, group, method): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _UnaryUnaryMultiCallable( - self._channel, group, method, self._metadata_transformer, - request_serializer, response_deserializer) - - def unary_stream(self, group, method): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _UnaryStreamMultiCallable( - self._channel, group, method, self._metadata_transformer, - request_serializer, response_deserializer) - - def stream_unary(self, group, method): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _StreamUnaryMultiCallable( - self._channel, group, method, self._metadata_transformer, - request_serializer, response_deserializer) - - def stream_stream(self, group, method): - request_serializer = self._request_serializers.get((group, method,)) - response_deserializer = self._response_deserializers.get((group, method,)) - return _StreamStreamMultiCallable( - self._channel, group, method, self._metadata_transformer, - request_serializer, response_deserializer) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - return False + def __init__(self, channel, metadata_transformer, request_serializers, + response_deserializers): + self._channel = channel + self._metadata_transformer = metadata_transformer + self._request_serializers = request_serializers or {} + self._response_deserializers = response_deserializers or {} + + def blocking_unary_unary(self, + group, + method, + request, + timeout, + metadata=None, + with_call=None, + protocol_options=None): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _blocking_unary_unary(self._channel, group, method, timeout, + with_call, protocol_options, metadata, + self._metadata_transformer, request, + request_serializer, response_deserializer) + + def future_unary_unary(self, + group, + method, + request, + timeout, + metadata=None, + protocol_options=None): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _future_unary_unary(self._channel, group, method, timeout, + protocol_options, metadata, + self._metadata_transformer, request, + request_serializer, response_deserializer) + + def inline_unary_stream(self, + group, + method, + request, + timeout, + metadata=None, + protocol_options=None): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _unary_stream(self._channel, group, method, timeout, + protocol_options, metadata, + self._metadata_transformer, request, + request_serializer, response_deserializer) + + def blocking_stream_unary(self, + group, + method, + request_iterator, + timeout, + metadata=None, + with_call=None, + protocol_options=None): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _blocking_stream_unary( + self._channel, group, method, timeout, with_call, protocol_options, + metadata, self._metadata_transformer, request_iterator, + request_serializer, response_deserializer) + + def future_stream_unary(self, + group, + method, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _future_stream_unary( + self._channel, group, method, timeout, protocol_options, metadata, + self._metadata_transformer, request_iterator, request_serializer, + response_deserializer) + + def inline_stream_stream(self, + group, + method, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _stream_stream(self._channel, group, method, timeout, + protocol_options, metadata, + self._metadata_transformer, request_iterator, + request_serializer, response_deserializer) + + def event_unary_unary(self, + group, + method, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() + + def event_unary_stream(self, + group, + method, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() + + def event_stream_unary(self, + group, + method, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() + + def event_stream_stream(self, + group, + method, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + raise NotImplementedError() + + def unary_unary(self, group, method): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _UnaryUnaryMultiCallable( + self._channel, group, method, self._metadata_transformer, + request_serializer, response_deserializer) + + def unary_stream(self, group, method): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _UnaryStreamMultiCallable( + self._channel, group, method, self._metadata_transformer, + request_serializer, response_deserializer) + + def stream_unary(self, group, method): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _StreamUnaryMultiCallable( + self._channel, group, method, self._metadata_transformer, + request_serializer, response_deserializer) + + def stream_stream(self, group, method): + request_serializer = self._request_serializers.get(( + group, + method,)) + response_deserializer = self._response_deserializers.get(( + group, + method,)) + return _StreamStreamMultiCallable( + self._channel, group, method, self._metadata_transformer, + request_serializer, response_deserializer) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + return False class _DynamicStub(face.DynamicStub): - def __init__(self, generic_stub, group, cardinalities): - self._generic_stub = generic_stub - self._group = group - self._cardinalities = cardinalities - - def __getattr__(self, attr): - method_cardinality = self._cardinalities.get(attr) - if method_cardinality is cardinality.Cardinality.UNARY_UNARY: - return self._generic_stub.unary_unary(self._group, attr) - elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: - return self._generic_stub.unary_stream(self._group, attr) - elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: - return self._generic_stub.stream_unary(self._group, attr) - elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: - return self._generic_stub.stream_stream(self._group, attr) - else: - raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - return False - - -def generic_stub( - channel, host, metadata_transformer, request_serializers, - response_deserializers): - return _GenericStub( - channel, metadata_transformer, request_serializers, - response_deserializers) - - -def dynamic_stub( - channel, service, cardinalities, host, metadata_transformer, - request_serializers, response_deserializers): - return _DynamicStub( - _GenericStub( - channel, metadata_transformer, request_serializers, - response_deserializers), - service, cardinalities) + def __init__(self, generic_stub, group, cardinalities): + self._generic_stub = generic_stub + self._group = group + self._cardinalities = cardinalities + + def __getattr__(self, attr): + method_cardinality = self._cardinalities.get(attr) + if method_cardinality is cardinality.Cardinality.UNARY_UNARY: + return self._generic_stub.unary_unary(self._group, attr) + elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: + return self._generic_stub.unary_stream(self._group, attr) + elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: + return self._generic_stub.stream_unary(self._group, attr) + elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: + return self._generic_stub.stream_stream(self._group, attr) + else: + raise AttributeError('_DynamicStub object has no attribute "%s"!' % + attr) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + return False + + +def generic_stub(channel, host, metadata_transformer, request_serializers, + response_deserializers): + return _GenericStub(channel, metadata_transformer, request_serializers, + response_deserializers) + + +def dynamic_stub(channel, service, cardinalities, host, metadata_transformer, + request_serializers, response_deserializers): + return _DynamicStub( + _GenericStub(channel, metadata_transformer, request_serializers, + response_deserializers), service, cardinalities) diff --git a/src/python/grpcio/grpc/beta/_connectivity_channel.py b/src/python/grpcio/grpc/beta/_connectivity_channel.py index 61674a70add..39020d2b4ef 100644 --- a/src/python/grpcio/grpc/beta/_connectivity_channel.py +++ b/src/python/grpcio/grpc/beta/_connectivity_channel.py @@ -26,7 +26,6 @@ # 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. - """Affords a connectivity-state-listenable channel.""" import threading @@ -41,116 +40,122 @@ _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = ( 'Exception calling channel subscription callback!') _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = { - state: connectivity for state, connectivity in zip( - _types.ConnectivityState, interfaces.ChannelConnectivity) + state: connectivity + for state, connectivity in zip(_types.ConnectivityState, + interfaces.ChannelConnectivity) } class ConnectivityChannel(object): - def __init__(self, low_channel): - self._lock = threading.Lock() - self._low_channel = low_channel - - self._polling = False - self._connectivity = None - self._try_to_connect = False - self._callbacks_and_connectivities = [] - self._delivering = False - - def _deliveries(self, connectivity): - callbacks_needing_update = [] - for callback_and_connectivity in self._callbacks_and_connectivities: - callback, callback_connectivity = callback_and_connectivity - if callback_connectivity is not connectivity: - callbacks_needing_update.append(callback) - callback_and_connectivity[1] = connectivity - return callbacks_needing_update - - def _deliver(self, initial_connectivity, initial_callbacks): - connectivity = initial_connectivity - callbacks = initial_callbacks - while True: - for callback in callbacks: - callable_util.call_logging_exceptions( - callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, - connectivity) - with self._lock: - callbacks = self._deliveries(self._connectivity) - if callbacks: - connectivity = self._connectivity - else: - self._delivering = False - return - - def _spawn_delivery(self, connectivity, callbacks): - delivering_thread = threading.Thread( - target=self._deliver, args=(connectivity, callbacks,)) - delivering_thread.start() - self._delivering = True + def __init__(self, low_channel): + self._lock = threading.Lock() + self._low_channel = low_channel - # TODO(issue 3064): Don't poll. - def _poll_connectivity(self, low_channel, initial_try_to_connect): - try_to_connect = initial_try_to_connect - low_connectivity = low_channel.check_connectivity_state(try_to_connect) - with self._lock: - self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ - low_connectivity] - callbacks = tuple( - callback for callback, unused_but_known_to_be_none_connectivity - in self._callbacks_and_connectivities) - for callback_and_connectivity in self._callbacks_and_connectivities: - callback_and_connectivity[1] = self._connectivity - if callbacks: - self._spawn_delivery(self._connectivity, callbacks) - completion_queue = _low.CompletionQueue() - while True: - low_channel.watch_connectivity_state( - low_connectivity, time.time() + 0.2, completion_queue, None) - event = completion_queue.next() - with self._lock: - if not self._callbacks_and_connectivities and not self._try_to_connect: - self._polling = False - self._connectivity = None - completion_queue.shutdown() - break - try_to_connect = self._try_to_connect + self._polling = False + self._connectivity = None self._try_to_connect = False - if event.success or try_to_connect: + self._callbacks_and_connectivities = [] + self._delivering = False + + def _deliveries(self, connectivity): + callbacks_needing_update = [] + for callback_and_connectivity in self._callbacks_and_connectivities: + callback, callback_connectivity = callback_and_connectivity + if callback_connectivity is not connectivity: + callbacks_needing_update.append(callback) + callback_and_connectivity[1] = connectivity + return callbacks_needing_update + + def _deliver(self, initial_connectivity, initial_callbacks): + connectivity = initial_connectivity + callbacks = initial_callbacks + while True: + for callback in callbacks: + callable_util.call_logging_exceptions( + callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, + connectivity) + with self._lock: + callbacks = self._deliveries(self._connectivity) + if callbacks: + connectivity = self._connectivity + else: + self._delivering = False + return + + def _spawn_delivery(self, connectivity, callbacks): + delivering_thread = threading.Thread( + target=self._deliver, args=( + connectivity, + callbacks,)) + delivering_thread.start() + self._delivering = True + + # TODO(issue 3064): Don't poll. + def _poll_connectivity(self, low_channel, initial_try_to_connect): + try_to_connect = initial_try_to_connect low_connectivity = low_channel.check_connectivity_state(try_to_connect) with self._lock: - self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ - low_connectivity] - if not self._delivering: - callbacks = self._deliveries(self._connectivity) + self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ + low_connectivity] + callbacks = tuple( + callback + for callback, unused_but_known_to_be_none_connectivity in + self._callbacks_and_connectivities) + for callback_and_connectivity in self._callbacks_and_connectivities: + callback_and_connectivity[1] = self._connectivity if callbacks: - self._spawn_delivery(self._connectivity, callbacks) - - def subscribe(self, callback, try_to_connect): - with self._lock: - if not self._callbacks_and_connectivities and not self._polling: - polling_thread = threading.Thread( - target=self._poll_connectivity, - args=(self._low_channel, bool(try_to_connect))) - polling_thread.start() - self._polling = True - self._callbacks_and_connectivities.append([callback, None]) - elif not self._delivering and self._connectivity is not None: - self._spawn_delivery(self._connectivity, (callback,)) - self._try_to_connect |= bool(try_to_connect) - self._callbacks_and_connectivities.append( - [callback, self._connectivity]) - else: - self._try_to_connect |= bool(try_to_connect) - self._callbacks_and_connectivities.append([callback, None]) - - def unsubscribe(self, callback): - with self._lock: - for index, (subscribed_callback, unused_connectivity) in enumerate( - self._callbacks_and_connectivities): - if callback == subscribed_callback: - self._callbacks_and_connectivities.pop(index) - break - - def low_channel(self): - return self._low_channel + self._spawn_delivery(self._connectivity, callbacks) + completion_queue = _low.CompletionQueue() + while True: + low_channel.watch_connectivity_state(low_connectivity, + time.time() + 0.2, + completion_queue, None) + event = completion_queue.next() + with self._lock: + if not self._callbacks_and_connectivities and not self._try_to_connect: + self._polling = False + self._connectivity = None + completion_queue.shutdown() + break + try_to_connect = self._try_to_connect + self._try_to_connect = False + if event.success or try_to_connect: + low_connectivity = low_channel.check_connectivity_state( + try_to_connect) + with self._lock: + self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ + low_connectivity] + if not self._delivering: + callbacks = self._deliveries(self._connectivity) + if callbacks: + self._spawn_delivery(self._connectivity, callbacks) + + def subscribe(self, callback, try_to_connect): + with self._lock: + if not self._callbacks_and_connectivities and not self._polling: + polling_thread = threading.Thread( + target=self._poll_connectivity, + args=(self._low_channel, bool(try_to_connect))) + polling_thread.start() + self._polling = True + self._callbacks_and_connectivities.append([callback, None]) + elif not self._delivering and self._connectivity is not None: + self._spawn_delivery(self._connectivity, (callback,)) + self._try_to_connect |= bool(try_to_connect) + self._callbacks_and_connectivities.append( + [callback, self._connectivity]) + else: + self._try_to_connect |= bool(try_to_connect) + self._callbacks_and_connectivities.append([callback, None]) + + def unsubscribe(self, callback): + with self._lock: + for index, (subscribed_callback, unused_connectivity + ) in enumerate(self._callbacks_and_connectivities): + if callback == subscribed_callback: + self._callbacks_and_connectivities.pop(index) + break + + def low_channel(self): + return self._low_channel diff --git a/src/python/grpcio/grpc/beta/_server_adaptations.py b/src/python/grpcio/grpc/beta/_server_adaptations.py index cca4a1797a1..bb7c0960d5d 100644 --- a/src/python/grpcio/grpc/beta/_server_adaptations.py +++ b/src/python/grpcio/grpc/beta/_server_adaptations.py @@ -26,7 +26,6 @@ # 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. - """Translates gRPC's server-side API into gRPC's server-side Beta API.""" import collections @@ -47,329 +46,352 @@ _DEFAULT_POOL_SIZE = 8 class _ServerProtocolContext(interfaces.GRPCServicerContext): - def __init__(self, servicer_context): - self._servicer_context = servicer_context + def __init__(self, servicer_context): + self._servicer_context = servicer_context - def peer(self): - return self._servicer_context.peer() + def peer(self): + return self._servicer_context.peer() - def disable_next_response_compression(self): - pass # TODO(https://github.com/grpc/grpc/issues/4078): design, implement. + def disable_next_response_compression(self): + pass # TODO(https://github.com/grpc/grpc/issues/4078): design, implement. class _FaceServicerContext(face.ServicerContext): - def __init__(self, servicer_context): - self._servicer_context = servicer_context + def __init__(self, servicer_context): + self._servicer_context = servicer_context - def is_active(self): - return self._servicer_context.is_active() + def is_active(self): + return self._servicer_context.is_active() - def time_remaining(self): - return self._servicer_context.time_remaining() + def time_remaining(self): + return self._servicer_context.time_remaining() - def add_abortion_callback(self, abortion_callback): - raise NotImplementedError( - 'add_abortion_callback no longer supported server-side!') + def add_abortion_callback(self, abortion_callback): + raise NotImplementedError( + 'add_abortion_callback no longer supported server-side!') - def cancel(self): - self._servicer_context.cancel() + def cancel(self): + self._servicer_context.cancel() - def protocol_context(self): - return _ServerProtocolContext(self._servicer_context) + def protocol_context(self): + return _ServerProtocolContext(self._servicer_context) - def invocation_metadata(self): - return _common.cygrpc_metadata( - self._servicer_context.invocation_metadata()) + def invocation_metadata(self): + return _common.cygrpc_metadata( + self._servicer_context.invocation_metadata()) - def initial_metadata(self, initial_metadata): - self._servicer_context.send_initial_metadata(initial_metadata) + def initial_metadata(self, initial_metadata): + self._servicer_context.send_initial_metadata(initial_metadata) - def terminal_metadata(self, terminal_metadata): - self._servicer_context.set_terminal_metadata(terminal_metadata) + def terminal_metadata(self, terminal_metadata): + self._servicer_context.set_terminal_metadata(terminal_metadata) - def code(self, code): - self._servicer_context.set_code(code) + def code(self, code): + self._servicer_context.set_code(code) - def details(self, details): - self._servicer_context.set_details(details) + def details(self, details): + self._servicer_context.set_details(details) def _adapt_unary_request_inline(unary_request_inline): - def adaptation(request, servicer_context): - return unary_request_inline(request, _FaceServicerContext(servicer_context)) - return adaptation + + def adaptation(request, servicer_context): + return unary_request_inline(request, + _FaceServicerContext(servicer_context)) + + return adaptation def _adapt_stream_request_inline(stream_request_inline): - def adaptation(request_iterator, servicer_context): - return stream_request_inline( - request_iterator, _FaceServicerContext(servicer_context)) - return adaptation + + def adaptation(request_iterator, servicer_context): + return stream_request_inline(request_iterator, + _FaceServicerContext(servicer_context)) + + return adaptation class _Callback(stream.Consumer): - def __init__(self): - self._condition = threading.Condition() - self._values = [] - self._terminated = False - self._cancelled = False - - def consume(self, value): - with self._condition: - self._values.append(value) - self._condition.notify_all() - - def terminate(self): - with self._condition: - self._terminated = True - self._condition.notify_all() - - def consume_and_terminate(self, value): - with self._condition: - self._values.append(value) - self._terminated = True - self._condition.notify_all() - - def cancel(self): - with self._condition: - self._cancelled = True - self._condition.notify_all() - - def draw_one_value(self): - with self._condition: - while True: - if self._cancelled: - raise abandonment.Abandoned() - elif self._values: - return self._values.pop(0) - elif self._terminated: - return None - else: - self._condition.wait() - - def draw_all_values(self): - with self._condition: - while True: - if self._cancelled: - raise abandonment.Abandoned() - elif self._terminated: - all_values = tuple(self._values) - self._values = None - return all_values - else: - self._condition.wait() + def __init__(self): + self._condition = threading.Condition() + self._values = [] + self._terminated = False + self._cancelled = False + + def consume(self, value): + with self._condition: + self._values.append(value) + self._condition.notify_all() + + def terminate(self): + with self._condition: + self._terminated = True + self._condition.notify_all() + + def consume_and_terminate(self, value): + with self._condition: + self._values.append(value) + self._terminated = True + self._condition.notify_all() + + def cancel(self): + with self._condition: + self._cancelled = True + self._condition.notify_all() + + def draw_one_value(self): + with self._condition: + while True: + if self._cancelled: + raise abandonment.Abandoned() + elif self._values: + return self._values.pop(0) + elif self._terminated: + return None + else: + self._condition.wait() + + def draw_all_values(self): + with self._condition: + while True: + if self._cancelled: + raise abandonment.Abandoned() + elif self._terminated: + all_values = tuple(self._values) + self._values = None + return all_values + else: + self._condition.wait() def _run_request_pipe_thread(request_iterator, request_consumer, servicer_context): - thread_joined = threading.Event() - def pipe_requests(): - for request in request_iterator: - if not servicer_context.is_active() or thread_joined.is_set(): - return - request_consumer.consume(request) - if not servicer_context.is_active() or thread_joined.is_set(): - return - request_consumer.terminate() + thread_joined = threading.Event() + + def pipe_requests(): + for request in request_iterator: + if not servicer_context.is_active() or thread_joined.is_set(): + return + request_consumer.consume(request) + if not servicer_context.is_active() or thread_joined.is_set(): + return + request_consumer.terminate() - def stop_request_pipe(timeout): - thread_joined.set() + def stop_request_pipe(timeout): + thread_joined.set() - request_pipe_thread = _common.CleanupThread( - stop_request_pipe, target=pipe_requests) - request_pipe_thread.start() + request_pipe_thread = _common.CleanupThread( + stop_request_pipe, target=pipe_requests) + request_pipe_thread.start() def _adapt_unary_unary_event(unary_unary_event): - def adaptation(request, servicer_context): - callback = _Callback() - if not servicer_context.add_callback(callback.cancel): - raise abandonment.Abandoned() - unary_unary_event( - request, callback.consume_and_terminate, - _FaceServicerContext(servicer_context)) - return callback.draw_all_values()[0] - return adaptation + + def adaptation(request, servicer_context): + callback = _Callback() + if not servicer_context.add_callback(callback.cancel): + raise abandonment.Abandoned() + unary_unary_event(request, callback.consume_and_terminate, + _FaceServicerContext(servicer_context)) + return callback.draw_all_values()[0] + + return adaptation def _adapt_unary_stream_event(unary_stream_event): - def adaptation(request, servicer_context): - callback = _Callback() - if not servicer_context.add_callback(callback.cancel): - raise abandonment.Abandoned() - unary_stream_event( - request, callback, _FaceServicerContext(servicer_context)) - while True: - response = callback.draw_one_value() - if response is None: - return - else: - yield response - return adaptation + + def adaptation(request, servicer_context): + callback = _Callback() + if not servicer_context.add_callback(callback.cancel): + raise abandonment.Abandoned() + unary_stream_event(request, callback, + _FaceServicerContext(servicer_context)) + while True: + response = callback.draw_one_value() + if response is None: + return + else: + yield response + + return adaptation def _adapt_stream_unary_event(stream_unary_event): - def adaptation(request_iterator, servicer_context): - callback = _Callback() - if not servicer_context.add_callback(callback.cancel): - raise abandonment.Abandoned() - request_consumer = stream_unary_event( - callback.consume_and_terminate, _FaceServicerContext(servicer_context)) - _run_request_pipe_thread( - request_iterator, request_consumer, servicer_context) - return callback.draw_all_values()[0] - return adaptation + + def adaptation(request_iterator, servicer_context): + callback = _Callback() + if not servicer_context.add_callback(callback.cancel): + raise abandonment.Abandoned() + request_consumer = stream_unary_event( + callback.consume_and_terminate, + _FaceServicerContext(servicer_context)) + _run_request_pipe_thread(request_iterator, request_consumer, + servicer_context) + return callback.draw_all_values()[0] + + return adaptation def _adapt_stream_stream_event(stream_stream_event): - def adaptation(request_iterator, servicer_context): - callback = _Callback() - if not servicer_context.add_callback(callback.cancel): - raise abandonment.Abandoned() - request_consumer = stream_stream_event( - callback, _FaceServicerContext(servicer_context)) - _run_request_pipe_thread( - request_iterator, request_consumer, servicer_context) - while True: - response = callback.draw_one_value() - if response is None: - return - else: - yield response - return adaptation + + def adaptation(request_iterator, servicer_context): + callback = _Callback() + if not servicer_context.add_callback(callback.cancel): + raise abandonment.Abandoned() + request_consumer = stream_stream_event( + callback, _FaceServicerContext(servicer_context)) + _run_request_pipe_thread(request_iterator, request_consumer, + servicer_context) + while True: + response = callback.draw_one_value() + if response is None: + return + else: + yield response + + return adaptation class _SimpleMethodHandler( - collections.namedtuple( - '_MethodHandler', - ('request_streaming', 'response_streaming', 'request_deserializer', - 'response_serializer', 'unary_unary', 'unary_stream', 'stream_unary', - 'stream_stream',)), - grpc.RpcMethodHandler): - pass - - -def _simple_method_handler( - implementation, request_deserializer, response_serializer): - if implementation.style is style.Service.INLINE: - if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - return _SimpleMethodHandler( - False, False, request_deserializer, response_serializer, - _adapt_unary_request_inline(implementation.unary_unary_inline), None, - None, None) - elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - return _SimpleMethodHandler( - False, True, request_deserializer, response_serializer, None, - _adapt_unary_request_inline(implementation.unary_stream_inline), None, - None) - elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - return _SimpleMethodHandler( - True, False, request_deserializer, response_serializer, None, None, - _adapt_stream_request_inline(implementation.stream_unary_inline), - None) - elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - return _SimpleMethodHandler( - True, True, request_deserializer, response_serializer, None, None, - None, - _adapt_stream_request_inline(implementation.stream_stream_inline)) - elif implementation.style is style.Service.EVENT: - if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: - return _SimpleMethodHandler( - False, False, request_deserializer, response_serializer, - _adapt_unary_unary_event(implementation.unary_unary_event), None, - None, None) - elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: - return _SimpleMethodHandler( - False, True, request_deserializer, response_serializer, None, - _adapt_unary_stream_event(implementation.unary_stream_event), None, - None) - elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: - return _SimpleMethodHandler( - True, False, request_deserializer, response_serializer, None, None, - _adapt_stream_unary_event(implementation.stream_unary_event), None) - elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: - return _SimpleMethodHandler( - True, True, request_deserializer, response_serializer, None, None, - None, _adapt_stream_stream_event(implementation.stream_stream_event)) + collections.namedtuple('_MethodHandler', ( + 'request_streaming', + 'response_streaming', + 'request_deserializer', + 'response_serializer', + 'unary_unary', + 'unary_stream', + 'stream_unary', + 'stream_stream',)), grpc.RpcMethodHandler): + pass + + +def _simple_method_handler(implementation, request_deserializer, + response_serializer): + if implementation.style is style.Service.INLINE: + if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: + return _SimpleMethodHandler( + False, False, request_deserializer, response_serializer, + _adapt_unary_request_inline(implementation.unary_unary_inline), + None, None, None) + elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: + return _SimpleMethodHandler( + False, True, request_deserializer, response_serializer, None, + _adapt_unary_request_inline(implementation.unary_stream_inline), + None, None) + elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: + return _SimpleMethodHandler(True, False, request_deserializer, + response_serializer, None, None, + _adapt_stream_request_inline( + implementation.stream_unary_inline), + None) + elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: + return _SimpleMethodHandler( + True, True, request_deserializer, response_serializer, None, + None, None, + _adapt_stream_request_inline( + implementation.stream_stream_inline)) + elif implementation.style is style.Service.EVENT: + if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: + return _SimpleMethodHandler( + False, False, request_deserializer, response_serializer, + _adapt_unary_unary_event(implementation.unary_unary_event), + None, None, None) + elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: + return _SimpleMethodHandler( + False, True, request_deserializer, response_serializer, None, + _adapt_unary_stream_event(implementation.unary_stream_event), + None, None) + elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: + return _SimpleMethodHandler( + True, False, request_deserializer, response_serializer, None, + None, + _adapt_stream_unary_event(implementation.stream_unary_event), + None) + elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: + return _SimpleMethodHandler( + True, True, request_deserializer, response_serializer, None, + None, None, + _adapt_stream_stream_event(implementation.stream_stream_event)) def _flatten_method_pair_map(method_pair_map): - method_pair_map = method_pair_map or {} - flat_map = {} - for method_pair in method_pair_map: - method = _common.fully_qualified_method(method_pair[0], method_pair[1]) - flat_map[method] = method_pair_map[method_pair] - return flat_map + method_pair_map = method_pair_map or {} + flat_map = {} + for method_pair in method_pair_map: + method = _common.fully_qualified_method(method_pair[0], method_pair[1]) + flat_map[method] = method_pair_map[method_pair] + return flat_map class _GenericRpcHandler(grpc.GenericRpcHandler): - def __init__( - self, method_implementations, multi_method_implementation, - request_deserializers, response_serializers): - self._method_implementations = _flatten_method_pair_map( - method_implementations) - self._request_deserializers = _flatten_method_pair_map( - request_deserializers) - self._response_serializers = _flatten_method_pair_map( - response_serializers) - self._multi_method_implementation = multi_method_implementation - - def service(self, handler_call_details): - method_implementation = self._method_implementations.get( - handler_call_details.method) - if method_implementation is not None: - return _simple_method_handler( - method_implementation, - self._request_deserializers.get(handler_call_details.method), - self._response_serializers.get(handler_call_details.method)) - elif self._multi_method_implementation is None: - return None - else: - try: - return None #TODO(nathaniel): call the multimethod. - except face.NoSuchMethodError: - return None + def __init__(self, method_implementations, multi_method_implementation, + request_deserializers, response_serializers): + self._method_implementations = _flatten_method_pair_map( + method_implementations) + self._request_deserializers = _flatten_method_pair_map( + request_deserializers) + self._response_serializers = _flatten_method_pair_map( + response_serializers) + self._multi_method_implementation = multi_method_implementation + + def service(self, handler_call_details): + method_implementation = self._method_implementations.get( + handler_call_details.method) + if method_implementation is not None: + return _simple_method_handler( + method_implementation, + self._request_deserializers.get(handler_call_details.method), + self._response_serializers.get(handler_call_details.method)) + elif self._multi_method_implementation is None: + return None + else: + try: + return None #TODO(nathaniel): call the multimethod. + except face.NoSuchMethodError: + return None class _Server(interfaces.Server): - def __init__(self, server): - self._server = server + def __init__(self, server): + self._server = server - def add_insecure_port(self, address): - return self._server.add_insecure_port(address) + def add_insecure_port(self, address): + return self._server.add_insecure_port(address) - def add_secure_port(self, address, server_credentials): - return self._server.add_secure_port(address, server_credentials) + def add_secure_port(self, address, server_credentials): + return self._server.add_secure_port(address, server_credentials) - def start(self): - self._server.start() + def start(self): + self._server.start() - def stop(self, grace): - return self._server.stop(grace) + def stop(self, grace): + return self._server.stop(grace) - def __enter__(self): - self._server.start() - return self + def __enter__(self): + self._server.start() + return self - def __exit__(self, exc_type, exc_val, exc_tb): - self._server.stop(None) - return False + def __exit__(self, exc_type, exc_val, exc_tb): + self._server.stop(None) + return False -def server( - service_implementations, multi_method_implementation, request_deserializers, - response_serializers, thread_pool, thread_pool_size): - generic_rpc_handler = _GenericRpcHandler( - service_implementations, multi_method_implementation, - request_deserializers, response_serializers) - if thread_pool is None: - effective_thread_pool = logging_pool.pool( - _DEFAULT_POOL_SIZE if thread_pool_size is None else thread_pool_size) - else: - effective_thread_pool = thread_pool - return _Server( - grpc.server(effective_thread_pool, handlers=(generic_rpc_handler,))) +def server(service_implementations, multi_method_implementation, + request_deserializers, response_serializers, thread_pool, + thread_pool_size): + generic_rpc_handler = _GenericRpcHandler( + service_implementations, multi_method_implementation, + request_deserializers, response_serializers) + if thread_pool is None: + effective_thread_pool = logging_pool.pool(_DEFAULT_POOL_SIZE + if thread_pool_size is None + else thread_pool_size) + else: + effective_thread_pool = thread_pool + return _Server( + grpc.server( + effective_thread_pool, handlers=(generic_rpc_handler,))) diff --git a/src/python/grpcio/grpc/beta/implementations.py b/src/python/grpcio/grpc/beta/implementations.py index ab25fd5eec7..70938522781 100644 --- a/src/python/grpcio/grpc/beta/implementations.py +++ b/src/python/grpcio/grpc/beta/implementations.py @@ -26,7 +26,6 @@ # 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. - """Entry points into the Beta API of gRPC Python.""" # threading is referenced from specification in this module. @@ -43,7 +42,6 @@ from grpc.beta import interfaces from grpc.framework.common import cardinality # pylint: disable=unused-import from grpc.framework.interfaces.face import face # pylint: disable=unused-import - ChannelCredentials = grpc.ChannelCredentials ssl_channel_credentials = grpc.ssl_channel_credentials CallCredentials = grpc.CallCredentials @@ -51,7 +49,7 @@ metadata_call_credentials = grpc.metadata_call_credentials def google_call_credentials(credentials): - """Construct CallCredentials from GoogleCredentials. + """Construct CallCredentials from GoogleCredentials. Args: credentials: A GoogleCredentials object from the oauth2client library. @@ -59,7 +57,8 @@ def google_call_credentials(credentials): Returns: A CallCredentials object for use in a GRPCCallOptions object. """ - return metadata_call_credentials(_auth.GoogleCallCredentials(credentials)) + return metadata_call_credentials(_auth.GoogleCallCredentials(credentials)) + access_token_call_credentials = grpc.access_token_call_credentials composite_call_credentials = grpc.composite_call_credentials @@ -67,18 +66,18 @@ composite_channel_credentials = grpc.composite_channel_credentials class Channel(object): - """A channel to a remote host through which RPCs may be conducted. + """A channel to a remote host through which RPCs may be conducted. Only the "subscribe" and "unsubscribe" methods are supported for application use. This class' instance constructor and all other attributes are unsupported. """ - def __init__(self, channel): - self._channel = channel + def __init__(self, channel): + self._channel = channel - def subscribe(self, callback, try_to_connect=None): - """Subscribes to this Channel's connectivity. + def subscribe(self, callback, try_to_connect=None): + """Subscribes to this Channel's connectivity. Args: callback: A callable to be invoked and passed an @@ -90,20 +89,20 @@ class Channel(object): attempt to connect if it is not already connected and ready to conduct RPCs. """ - self._channel.subscribe(callback, try_to_connect=try_to_connect) + self._channel.subscribe(callback, try_to_connect=try_to_connect) - def unsubscribe(self, callback): - """Unsubscribes a callback from this Channel's connectivity. + def unsubscribe(self, callback): + """Unsubscribes a callback from this Channel's connectivity. Args: callback: A callable previously registered with this Channel from having been passed to its "subscribe" method. """ - self._channel.unsubscribe(callback) + self._channel.unsubscribe(callback) def insecure_channel(host, port): - """Creates an insecure Channel to a remote host. + """Creates an insecure Channel to a remote host. Args: host: The name of the remote host to which to connect. @@ -113,13 +112,13 @@ def insecure_channel(host, port): Returns: A Channel to the remote host through which RPCs may be conducted. """ - channel = grpc.insecure_channel( - host if port is None else '%s:%d' % (host, port)) - return Channel(channel) + channel = grpc.insecure_channel(host + if port is None else '%s:%d' % (host, port)) + return Channel(channel) def secure_channel(host, port, channel_credentials): - """Creates a secure Channel to a remote host. + """Creates a secure Channel to a remote host. Args: host: The name of the remote host to which to connect. @@ -130,37 +129,39 @@ def secure_channel(host, port, channel_credentials): Returns: A secure Channel to the remote host through which RPCs may be conducted. """ - channel = grpc.secure_channel( - host if port is None else '%s:%d' % (host, port), channel_credentials) - return Channel(channel) + channel = grpc.secure_channel(host if port is None else + '%s:%d' % (host, port), channel_credentials) + return Channel(channel) class StubOptions(object): - """A value encapsulating the various options for creation of a Stub. + """A value encapsulating the various options for creation of a Stub. This class and its instances have no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ - def __init__( - self, host, request_serializers, response_deserializers, - metadata_transformer, thread_pool, thread_pool_size): - self.host = host - self.request_serializers = request_serializers - self.response_deserializers = response_deserializers - self.metadata_transformer = metadata_transformer - self.thread_pool = thread_pool - self.thread_pool_size = thread_pool_size + def __init__(self, host, request_serializers, response_deserializers, + metadata_transformer, thread_pool, thread_pool_size): + self.host = host + self.request_serializers = request_serializers + self.response_deserializers = response_deserializers + self.metadata_transformer = metadata_transformer + self.thread_pool = thread_pool + self.thread_pool_size = thread_pool_size -_EMPTY_STUB_OPTIONS = StubOptions( - None, None, None, None, None, None) +_EMPTY_STUB_OPTIONS = StubOptions(None, None, None, None, None, None) -def stub_options( - host=None, request_serializers=None, response_deserializers=None, - metadata_transformer=None, thread_pool=None, thread_pool_size=None): - """Creates a StubOptions value to be passed at stub creation. + +def stub_options(host=None, + request_serializers=None, + response_deserializers=None, + metadata_transformer=None, + thread_pool=None, + thread_pool_size=None): + """Creates a StubOptions value to be passed at stub creation. All parameters are optional and should always be passed by keyword. @@ -180,13 +181,12 @@ def stub_options( Returns: A StubOptions value created from the passed parameters. """ - return StubOptions( - host, request_serializers, response_deserializers, - metadata_transformer, thread_pool, thread_pool_size) + return StubOptions(host, request_serializers, response_deserializers, + metadata_transformer, thread_pool, thread_pool_size) def generic_stub(channel, options=None): - """Creates a face.GenericStub on which RPCs can be made. + """Creates a face.GenericStub on which RPCs can be made. Args: channel: A Channel for use by the created stub. @@ -195,16 +195,17 @@ def generic_stub(channel, options=None): Returns: A face.GenericStub on which RPCs can be made. """ - effective_options = _EMPTY_STUB_OPTIONS if options is None else options - return _client_adaptations.generic_stub( - channel._channel, # pylint: disable=protected-access - effective_options.host, effective_options.metadata_transformer, - effective_options.request_serializers, - effective_options.response_deserializers) + effective_options = _EMPTY_STUB_OPTIONS if options is None else options + return _client_adaptations.generic_stub( + channel._channel, # pylint: disable=protected-access + effective_options.host, + effective_options.metadata_transformer, + effective_options.request_serializers, + effective_options.response_deserializers) def dynamic_stub(channel, service, cardinalities, options=None): - """Creates a face.DynamicStub with which RPCs can be invoked. + """Creates a face.DynamicStub with which RPCs can be invoked. Args: channel: A Channel for the returned face.DynamicStub to use. @@ -217,13 +218,15 @@ def dynamic_stub(channel, service, cardinalities, options=None): Returns: A face.DynamicStub with which RPCs can be invoked. """ - effective_options = StubOptions() if options is None else options - return _client_adaptations.dynamic_stub( - channel._channel, # pylint: disable=protected-access - service, cardinalities, effective_options.host, - effective_options.metadata_transformer, - effective_options.request_serializers, - effective_options.response_deserializers) + effective_options = StubOptions() if options is None else options + return _client_adaptations.dynamic_stub( + channel._channel, # pylint: disable=protected-access + service, + cardinalities, + effective_options.host, + effective_options.metadata_transformer, + effective_options.request_serializers, + effective_options.response_deserializers) ServerCredentials = grpc.ServerCredentials @@ -231,34 +234,36 @@ ssl_server_credentials = grpc.ssl_server_credentials class ServerOptions(object): - """A value encapsulating the various options for creation of a Server. + """A value encapsulating the various options for creation of a Server. This class and its instances have no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ - def __init__( - self, multi_method_implementation, request_deserializers, - response_serializers, thread_pool, thread_pool_size, default_timeout, - maximum_timeout): - self.multi_method_implementation = multi_method_implementation - self.request_deserializers = request_deserializers - self.response_serializers = response_serializers - self.thread_pool = thread_pool - self.thread_pool_size = thread_pool_size - self.default_timeout = default_timeout - self.maximum_timeout = maximum_timeout + def __init__(self, multi_method_implementation, request_deserializers, + response_serializers, thread_pool, thread_pool_size, + default_timeout, maximum_timeout): + self.multi_method_implementation = multi_method_implementation + self.request_deserializers = request_deserializers + self.response_serializers = response_serializers + self.thread_pool = thread_pool + self.thread_pool_size = thread_pool_size + self.default_timeout = default_timeout + self.maximum_timeout = maximum_timeout + -_EMPTY_SERVER_OPTIONS = ServerOptions( - None, None, None, None, None, None, None) +_EMPTY_SERVER_OPTIONS = ServerOptions(None, None, None, None, None, None, None) -def server_options( - multi_method_implementation=None, request_deserializers=None, - response_serializers=None, thread_pool=None, thread_pool_size=None, - default_timeout=None, maximum_timeout=None): - """Creates a ServerOptions value to be passed at server creation. +def server_options(multi_method_implementation=None, + request_deserializers=None, + response_serializers=None, + thread_pool=None, + thread_pool_size=None, + default_timeout=None, + maximum_timeout=None): + """Creates a ServerOptions value to be passed at server creation. All parameters are optional and should always be passed by keyword. @@ -282,13 +287,13 @@ def server_options( Returns: A StubOptions value created from the passed parameters. """ - return ServerOptions( - multi_method_implementation, request_deserializers, response_serializers, - thread_pool, thread_pool_size, default_timeout, maximum_timeout) + return ServerOptions(multi_method_implementation, request_deserializers, + response_serializers, thread_pool, thread_pool_size, + default_timeout, maximum_timeout) def server(service_implementations, options=None): - """Creates an interfaces.Server with which RPCs can be serviced. + """Creates an interfaces.Server with which RPCs can be serviced. Args: service_implementations: A dictionary from service name-method name pair to @@ -299,9 +304,9 @@ def server(service_implementations, options=None): Returns: An interfaces.Server with which RPCs can be serviced. """ - effective_options = _EMPTY_SERVER_OPTIONS if options is None else options - return _server_adaptations.server( - service_implementations, effective_options.multi_method_implementation, - effective_options.request_deserializers, - effective_options.response_serializers, effective_options.thread_pool, - effective_options.thread_pool_size) + effective_options = _EMPTY_SERVER_OPTIONS if options is None else options + return _server_adaptations.server( + service_implementations, effective_options.multi_method_implementation, + effective_options.request_deserializers, + effective_options.response_serializers, effective_options.thread_pool, + effective_options.thread_pool_size) diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py index 90f6bbbfcc1..361d1bcffea 100644 --- a/src/python/grpcio/grpc/beta/interfaces.py +++ b/src/python/grpcio/grpc/beta/interfaces.py @@ -26,7 +26,6 @@ # 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. - """Constants and interfaces of the Beta API of gRPC Python.""" import abc @@ -43,21 +42,21 @@ StatusCode = grpc.StatusCode class GRPCCallOptions(object): - """A value encapsulating gRPC-specific options passed on RPC invocation. + """A value encapsulating gRPC-specific options passed on RPC invocation. This class and its instances have no supported interface - it exists to define the type of its instances and its instances exist to be passed to other functions. """ - def __init__(self, disable_compression, subcall_of, credentials): - self.disable_compression = disable_compression - self.subcall_of = subcall_of - self.credentials = credentials + def __init__(self, disable_compression, subcall_of, credentials): + self.disable_compression = disable_compression + self.subcall_of = subcall_of + self.credentials = credentials def grpc_call_options(disable_compression=False, credentials=None): - """Creates a GRPCCallOptions value to be passed at RPC invocation. + """Creates a GRPCCallOptions value to be passed at RPC invocation. All parameters are optional and should always be passed by keyword. @@ -67,7 +66,8 @@ def grpc_call_options(disable_compression=False, credentials=None): request-unary RPCs. credentials: A CallCredentials object to use for the invoked RPC. """ - return GRPCCallOptions(disable_compression, None, credentials) + return GRPCCallOptions(disable_compression, None, credentials) + GRPCAuthMetadataContext = grpc.AuthMetadataContext GRPCAuthMetadataPluginCallback = grpc.AuthMetadataPluginCallback @@ -75,38 +75,38 @@ GRPCAuthMetadataPlugin = grpc.AuthMetadataPlugin class GRPCServicerContext(six.with_metaclass(abc.ABCMeta)): - """Exposes gRPC-specific options and behaviors to code servicing RPCs.""" + """Exposes gRPC-specific options and behaviors to code servicing RPCs.""" - @abc.abstractmethod - def peer(self): - """Identifies the peer that invoked the RPC being serviced. + @abc.abstractmethod + def peer(self): + """Identifies the peer that invoked the RPC being serviced. Returns: A string identifying the peer that invoked the RPC being serviced. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def disable_next_response_compression(self): - """Disables compression of the next response passed by the application.""" - raise NotImplementedError() + @abc.abstractmethod + def disable_next_response_compression(self): + """Disables compression of the next response passed by the application.""" + raise NotImplementedError() class GRPCInvocationContext(six.with_metaclass(abc.ABCMeta)): - """Exposes gRPC-specific options and behaviors to code invoking RPCs.""" + """Exposes gRPC-specific options and behaviors to code invoking RPCs.""" - @abc.abstractmethod - def disable_next_request_compression(self): - """Disables compression of the next request passed by the application.""" - raise NotImplementedError() + @abc.abstractmethod + def disable_next_request_compression(self): + """Disables compression of the next request passed by the application.""" + raise NotImplementedError() class Server(six.with_metaclass(abc.ABCMeta)): - """Services RPCs.""" + """Services RPCs.""" - @abc.abstractmethod - def add_insecure_port(self, address): - """Reserves a port for insecure RPC service once this Server becomes active. + @abc.abstractmethod + def add_insecure_port(self, address): + """Reserves a port for insecure RPC service once this Server becomes active. This method may only be called before calling this Server's start method is called. @@ -120,11 +120,11 @@ class Server(six.with_metaclass(abc.ABCMeta)): in the passed address, but will likely be different if the port number contained in the passed address was zero. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_secure_port(self, address, server_credentials): - """Reserves a port for secure RPC service after this Server becomes active. + @abc.abstractmethod + def add_secure_port(self, address, server_credentials): + """Reserves a port for secure RPC service after this Server becomes active. This method may only be called before calling this Server's start method is called. @@ -139,20 +139,20 @@ class Server(six.with_metaclass(abc.ABCMeta)): in the passed address, but will likely be different if the port number contained in the passed address was zero. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def start(self): - """Starts this Server's service of RPCs. + @abc.abstractmethod + def start(self): + """Starts this Server's service of RPCs. This method may only be called while the server is not serving RPCs (i.e. it is not idempotent). """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stop(self, grace): - """Stops this Server's service of RPCs. + @abc.abstractmethod + def stop(self, grace): + """Stops this Server's service of RPCs. All calls to this method immediately stop service of new RPCs. When existing RPCs are aborted is controlled by the grace period parameter passed to this @@ -177,4 +177,4 @@ class Server(six.with_metaclass(abc.ABCMeta)): at the time it was stopped or if all RPCs that it had underway completed very early in the grace period). """ - raise NotImplementedError() + raise NotImplementedError() diff --git a/src/python/grpcio/grpc/beta/utilities.py b/src/python/grpcio/grpc/beta/utilities.py index fb07a765795..60525350a7c 100644 --- a/src/python/grpcio/grpc/beta/utilities.py +++ b/src/python/grpcio/grpc/beta/utilities.py @@ -26,7 +26,6 @@ # 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. - """Utilities for the gRPC Python Beta API.""" import threading @@ -44,107 +43,107 @@ _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = ( class _ChannelReadyFuture(future.Future): - def __init__(self, channel): - self._condition = threading.Condition() - self._channel = channel - - self._matured = False - self._cancelled = False - self._done_callbacks = [] - - def _block(self, timeout): - until = None if timeout is None else time.time() + timeout - with self._condition: - while True: - if self._cancelled: - raise future.CancelledError() - elif self._matured: - return - else: - if until is None: - self._condition.wait() - else: - remaining = until - time.time() - if remaining < 0: - raise future.TimeoutError() + def __init__(self, channel): + self._condition = threading.Condition() + self._channel = channel + + self._matured = False + self._cancelled = False + self._done_callbacks = [] + + def _block(self, timeout): + until = None if timeout is None else time.time() + timeout + with self._condition: + while True: + if self._cancelled: + raise future.CancelledError() + elif self._matured: + return + else: + if until is None: + self._condition.wait() + else: + remaining = until - time.time() + if remaining < 0: + raise future.TimeoutError() + else: + self._condition.wait(timeout=remaining) + + def _update(self, connectivity): + with self._condition: + if (not self._cancelled and + connectivity is interfaces.ChannelConnectivity.READY): + self._matured = True + self._channel.unsubscribe(self._update) + self._condition.notify_all() + done_callbacks = tuple(self._done_callbacks) + self._done_callbacks = None + else: + return + + for done_callback in done_callbacks: + callable_util.call_logging_exceptions( + done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) + + def cancel(self): + with self._condition: + if not self._matured: + self._cancelled = True + self._channel.unsubscribe(self._update) + self._condition.notify_all() + done_callbacks = tuple(self._done_callbacks) + self._done_callbacks = None else: - self._condition.wait(timeout=remaining) - - def _update(self, connectivity): - with self._condition: - if (not self._cancelled and - connectivity is interfaces.ChannelConnectivity.READY): - self._matured = True - self._channel.unsubscribe(self._update) - self._condition.notify_all() - done_callbacks = tuple(self._done_callbacks) - self._done_callbacks = None - else: - return - - for done_callback in done_callbacks: - callable_util.call_logging_exceptions( - done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) - - def cancel(self): - with self._condition: - if not self._matured: - self._cancelled = True - self._channel.unsubscribe(self._update) - self._condition.notify_all() - done_callbacks = tuple(self._done_callbacks) - self._done_callbacks = None - else: - return False - - for done_callback in done_callbacks: - callable_util.call_logging_exceptions( - done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) - - def cancelled(self): - with self._condition: - return self._cancelled - - def running(self): - with self._condition: - return not self._cancelled and not self._matured - - def done(self): - with self._condition: - return self._cancelled or self._matured - - def result(self, timeout=None): - self._block(timeout) - return None - - def exception(self, timeout=None): - self._block(timeout) - return None - - def traceback(self, timeout=None): - self._block(timeout) - return None - - def add_done_callback(self, fn): - with self._condition: - if not self._cancelled and not self._matured: - self._done_callbacks.append(fn) - return - - fn(self) - - def start(self): - with self._condition: - self._channel.subscribe(self._update, try_to_connect=True) - - def __del__(self): - with self._condition: - if not self._cancelled and not self._matured: - self._channel.unsubscribe(self._update) + return False + + for done_callback in done_callbacks: + callable_util.call_logging_exceptions( + done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) + + def cancelled(self): + with self._condition: + return self._cancelled + + def running(self): + with self._condition: + return not self._cancelled and not self._matured + + def done(self): + with self._condition: + return self._cancelled or self._matured + + def result(self, timeout=None): + self._block(timeout) + return None + + def exception(self, timeout=None): + self._block(timeout) + return None + + def traceback(self, timeout=None): + self._block(timeout) + return None + + def add_done_callback(self, fn): + with self._condition: + if not self._cancelled and not self._matured: + self._done_callbacks.append(fn) + return + + fn(self) + + def start(self): + with self._condition: + self._channel.subscribe(self._update, try_to_connect=True) + + def __del__(self): + with self._condition: + if not self._cancelled and not self._matured: + self._channel.unsubscribe(self._update) def channel_ready_future(channel): - """Creates a future.Future tracking when an implementations.Channel is ready. + """Creates a future.Future tracking when an implementations.Channel is ready. Cancelling the returned future.Future does not tell the given implementations.Channel to abandon attempts it may have been making to @@ -158,7 +157,6 @@ def channel_ready_future(channel): A future.Future that matures when the given Channel has connectivity interfaces.ChannelConnectivity.READY. """ - ready_future = _ChannelReadyFuture(channel) - ready_future.start() - return ready_future - + ready_future = _ChannelReadyFuture(channel) + ready_future.start() + return ready_future diff --git a/src/python/grpcio/grpc/framework/__init__.py b/src/python/grpcio/grpc/framework/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio/grpc/framework/__init__.py +++ b/src/python/grpcio/grpc/framework/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio/grpc/framework/common/__init__.py b/src/python/grpcio/grpc/framework/common/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio/grpc/framework/common/__init__.py +++ b/src/python/grpcio/grpc/framework/common/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio/grpc/framework/common/cardinality.py b/src/python/grpcio/grpc/framework/common/cardinality.py index 610425e8032..d8927cf9b06 100644 --- a/src/python/grpcio/grpc/framework/common/cardinality.py +++ b/src/python/grpcio/grpc/framework/common/cardinality.py @@ -26,7 +26,6 @@ # 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. - """Defines an enum for classifying RPC methods by streaming semantics.""" import enum @@ -34,9 +33,9 @@ import enum @enum.unique class Cardinality(enum.Enum): - """Describes the streaming semantics of an RPC method.""" + """Describes the streaming semantics of an RPC method.""" - UNARY_UNARY = 'request-unary/response-unary' - UNARY_STREAM = 'request-unary/response-streaming' - STREAM_UNARY = 'request-streaming/response-unary' - STREAM_STREAM = 'request-streaming/response-streaming' + UNARY_UNARY = 'request-unary/response-unary' + UNARY_STREAM = 'request-unary/response-streaming' + STREAM_UNARY = 'request-streaming/response-unary' + STREAM_STREAM = 'request-streaming/response-streaming' diff --git a/src/python/grpcio/grpc/framework/common/style.py b/src/python/grpcio/grpc/framework/common/style.py index 6ae694bdcb4..43f4211145d 100644 --- a/src/python/grpcio/grpc/framework/common/style.py +++ b/src/python/grpcio/grpc/framework/common/style.py @@ -26,7 +26,6 @@ # 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. - """Defines an enum for classifying RPC methods by control flow semantics.""" import enum @@ -34,7 +33,7 @@ import enum @enum.unique class Service(enum.Enum): - """Describes the control flow style of RPC method implementation.""" + """Describes the control flow style of RPC method implementation.""" - INLINE = 'inline' - EVENT = 'event' + INLINE = 'inline' + EVENT = 'event' diff --git a/src/python/grpcio/grpc/framework/foundation/__init__.py b/src/python/grpcio/grpc/framework/foundation/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio/grpc/framework/foundation/__init__.py +++ b/src/python/grpcio/grpc/framework/foundation/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio/grpc/framework/foundation/abandonment.py b/src/python/grpcio/grpc/framework/foundation/abandonment.py index 960b4d06b49..32385b96574 100644 --- a/src/python/grpcio/grpc/framework/foundation/abandonment.py +++ b/src/python/grpcio/grpc/framework/foundation/abandonment.py @@ -26,12 +26,11 @@ # 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. - """Utilities for indicating abandonment of computation.""" class Abandoned(Exception): - """Indicates that some computation is being abandoned. + """Indicates that some computation is being abandoned. Abandoning a computation is different than returning a value or raising an exception indicating some operational or programming defect. diff --git a/src/python/grpcio/grpc/framework/foundation/callable_util.py b/src/python/grpcio/grpc/framework/foundation/callable_util.py index 4f029f97bb8..3b8351c19bd 100644 --- a/src/python/grpcio/grpc/framework/foundation/callable_util.py +++ b/src/python/grpcio/grpc/framework/foundation/callable_util.py @@ -26,7 +26,6 @@ # 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. - """Utilities for working with callables.""" import abc @@ -39,7 +38,7 @@ import six class Outcome(six.with_metaclass(abc.ABCMeta)): - """A sum type describing the outcome of some call. + """A sum type describing the outcome of some call. Attributes: kind: One of Kind.RETURNED or Kind.RAISED respectively indicating that the @@ -50,31 +49,31 @@ class Outcome(six.with_metaclass(abc.ABCMeta)): Kind.RAISED. """ - @enum.unique - class Kind(enum.Enum): - """Identifies the general kind of the outcome of some call.""" + @enum.unique + class Kind(enum.Enum): + """Identifies the general kind of the outcome of some call.""" - RETURNED = object() - RAISED = object() + RETURNED = object() + RAISED = object() class _EasyOutcome( - collections.namedtuple( - '_EasyOutcome', ['kind', 'return_value', 'exception']), - Outcome): - """A trivial implementation of Outcome.""" + collections.namedtuple('_EasyOutcome', + ['kind', 'return_value', 'exception']), Outcome): + """A trivial implementation of Outcome.""" def _call_logging_exceptions(behavior, message, *args, **kwargs): - try: - return _EasyOutcome(Outcome.Kind.RETURNED, behavior(*args, **kwargs), None) - except Exception as e: # pylint: disable=broad-except - logging.exception(message) - return _EasyOutcome(Outcome.Kind.RAISED, None, e) + try: + return _EasyOutcome(Outcome.Kind.RETURNED, + behavior(*args, **kwargs), None) + except Exception as e: # pylint: disable=broad-except + logging.exception(message) + return _EasyOutcome(Outcome.Kind.RAISED, None, e) def with_exceptions_logged(behavior, message): - """Wraps a callable in a try-except that logs any exceptions it raises. + """Wraps a callable in a try-except that logs any exceptions it raises. Args: behavior: Any callable. @@ -86,14 +85,16 @@ def with_exceptions_logged(behavior, message): future.Outcome describing whether the given behavior returned a value or raised an exception. """ - @functools.wraps(behavior) - def wrapped_behavior(*args, **kwargs): - return _call_logging_exceptions(behavior, message, *args, **kwargs) - return wrapped_behavior + + @functools.wraps(behavior) + def wrapped_behavior(*args, **kwargs): + return _call_logging_exceptions(behavior, message, *args, **kwargs) + + return wrapped_behavior def call_logging_exceptions(behavior, message, *args, **kwargs): - """Calls a behavior in a try-except that logs any exceptions it raises. + """Calls a behavior in a try-except that logs any exceptions it raises. Args: behavior: Any callable. @@ -105,4 +106,4 @@ def call_logging_exceptions(behavior, message, *args, **kwargs): An Outcome describing whether the given behavior returned a value or raised an exception. """ - return _call_logging_exceptions(behavior, message, *args, **kwargs) + return _call_logging_exceptions(behavior, message, *args, **kwargs) diff --git a/src/python/grpcio/grpc/framework/foundation/future.py b/src/python/grpcio/grpc/framework/foundation/future.py index 6fb58eadb60..e2ecf629210 100644 --- a/src/python/grpcio/grpc/framework/foundation/future.py +++ b/src/python/grpcio/grpc/framework/foundation/future.py @@ -26,7 +26,6 @@ # 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. - """A Future interface. Python doesn't have a Future interface in its standard library. In the absence @@ -53,33 +52,33 @@ import six class TimeoutError(Exception): - """Indicates that a particular call timed out.""" + """Indicates that a particular call timed out.""" class CancelledError(Exception): - """Indicates that the computation underlying a Future was cancelled.""" + """Indicates that the computation underlying a Future was cancelled.""" class Future(six.with_metaclass(abc.ABCMeta)): - """A representation of a computation in another control flow. + """A representation of a computation in another control flow. Computations represented by a Future may be yet to be begun, may be ongoing, or may have already completed. """ - # NOTE(nathaniel): This isn't the return type that I would want to have if it - # were up to me. Were this interface being written from scratch, the return - # type of this method would probably be a sum type like: - # - # NOT_COMMENCED - # COMMENCED_AND_NOT_COMPLETED - # PARTIAL_RESULT - # COMPLETED - # UNCANCELLABLE - # NOT_IMMEDIATELY_DETERMINABLE - @abc.abstractmethod - def cancel(self): - """Attempts to cancel the computation. + # NOTE(nathaniel): This isn't the return type that I would want to have if it + # were up to me. Were this interface being written from scratch, the return + # type of this method would probably be a sum type like: + # + # NOT_COMMENCED + # COMMENCED_AND_NOT_COMPLETED + # PARTIAL_RESULT + # COMPLETED + # UNCANCELLABLE + # NOT_IMMEDIATELY_DETERMINABLE + @abc.abstractmethod + def cancel(self): + """Attempts to cancel the computation. This method does not block. @@ -92,25 +91,25 @@ class Future(six.with_metaclass(abc.ABCMeta)): remote system for which a determination of whether or not it commenced before being cancelled cannot be made without blocking. """ - raise NotImplementedError() - - # NOTE(nathaniel): Here too this isn't the return type that I'd want this - # method to have if it were up to me. I think I'd go with another sum type - # like: - # - # NOT_CANCELLED (this object's cancel method hasn't been called) - # NOT_COMMENCED - # COMMENCED_AND_NOT_COMPLETED - # PARTIAL_RESULT - # COMPLETED - # UNCANCELLABLE - # NOT_IMMEDIATELY_DETERMINABLE - # - # Notice how giving the cancel method the right semantics obviates most - # reasons for this method to exist. - @abc.abstractmethod - def cancelled(self): - """Describes whether the computation was cancelled. + raise NotImplementedError() + + # NOTE(nathaniel): Here too this isn't the return type that I'd want this + # method to have if it were up to me. I think I'd go with another sum type + # like: + # + # NOT_CANCELLED (this object's cancel method hasn't been called) + # NOT_COMMENCED + # COMMENCED_AND_NOT_COMPLETED + # PARTIAL_RESULT + # COMPLETED + # UNCANCELLABLE + # NOT_IMMEDIATELY_DETERMINABLE + # + # Notice how giving the cancel method the right semantics obviates most + # reasons for this method to exist. + @abc.abstractmethod + def cancelled(self): + """Describes whether the computation was cancelled. This method does not block. @@ -120,11 +119,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): not limited to this object's cancel method not having been called and the computation's result having become immediately available. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def running(self): - """Describes whether the computation is taking place. + @abc.abstractmethod + def running(self): + """Describes whether the computation is taking place. This method does not block. @@ -133,15 +132,15 @@ class Future(six.with_metaclass(abc.ABCMeta)): taking place now, or False if the computation took place in the past or was cancelled. """ - raise NotImplementedError() + raise NotImplementedError() - # NOTE(nathaniel): These aren't quite the semantics I'd like here either. I - # would rather this only returned True in cases in which the underlying - # computation completed successfully. A computation's having been cancelled - # conflicts with considering that computation "done". - @abc.abstractmethod - def done(self): - """Describes whether the computation has taken place. + # NOTE(nathaniel): These aren't quite the semantics I'd like here either. I + # would rather this only returned True in cases in which the underlying + # computation completed successfully. A computation's having been cancelled + # conflicts with considering that computation "done". + @abc.abstractmethod + def done(self): + """Describes whether the computation has taken place. This method does not block. @@ -150,11 +149,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): unscheduled or interrupted. False if the computation may possibly be executing or scheduled to execute later. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def result(self, timeout=None): - """Accesses the outcome of the computation or raises its exception. + @abc.abstractmethod + def result(self, timeout=None): + """Accesses the outcome of the computation or raises its exception. This method may return immediately or may block. @@ -173,11 +172,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): Exception: If the computation raised an exception, this call will raise the same exception. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def exception(self, timeout=None): - """Return the exception raised by the computation. + @abc.abstractmethod + def exception(self, timeout=None): + """Return the exception raised by the computation. This method may return immediately or may block. @@ -196,11 +195,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): terminate within the allotted time. CancelledError: If the computation was cancelled. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def traceback(self, timeout=None): - """Access the traceback of the exception raised by the computation. + @abc.abstractmethod + def traceback(self, timeout=None): + """Access the traceback of the exception raised by the computation. This method may return immediately or may block. @@ -219,11 +218,11 @@ class Future(six.with_metaclass(abc.ABCMeta)): terminate within the allotted time. CancelledError: If the computation was cancelled. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_done_callback(self, fn): - """Adds a function to be called at completion of the computation. + @abc.abstractmethod + def add_done_callback(self, fn): + """Adds a function to be called at completion of the computation. The callback will be passed this Future object describing the outcome of the computation. @@ -234,4 +233,4 @@ class Future(six.with_metaclass(abc.ABCMeta)): Args: fn: A callable taking this Future object as its single parameter. """ - raise NotImplementedError() + raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/foundation/logging_pool.py b/src/python/grpcio/grpc/framework/foundation/logging_pool.py index 9b469a1452e..9164173d348 100644 --- a/src/python/grpcio/grpc/framework/foundation/logging_pool.py +++ b/src/python/grpcio/grpc/framework/foundation/logging_pool.py @@ -26,7 +26,6 @@ # 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. - """A thread pool that logs exceptions raised by tasks executed within it.""" import logging @@ -35,42 +34,46 @@ from concurrent import futures def _wrap(behavior): - """Wraps an arbitrary callable behavior in exception-logging.""" - def _wrapping(*args, **kwargs): - try: - return behavior(*args, **kwargs) - except Exception as e: - logging.exception( - 'Unexpected exception from %s executed in logging pool!', behavior) - raise - return _wrapping + """Wraps an arbitrary callable behavior in exception-logging.""" + + def _wrapping(*args, **kwargs): + try: + return behavior(*args, **kwargs) + except Exception as e: + logging.exception( + 'Unexpected exception from %s executed in logging pool!', + behavior) + raise + + return _wrapping class _LoggingPool(object): - """An exception-logging futures.ThreadPoolExecutor-compatible thread pool.""" + """An exception-logging futures.ThreadPoolExecutor-compatible thread pool.""" - def __init__(self, backing_pool): - self._backing_pool = backing_pool + def __init__(self, backing_pool): + self._backing_pool = backing_pool - def __enter__(self): - return self + def __enter__(self): + return self - def __exit__(self, exc_type, exc_val, exc_tb): - self._backing_pool.shutdown(wait=True) + def __exit__(self, exc_type, exc_val, exc_tb): + self._backing_pool.shutdown(wait=True) - def submit(self, fn, *args, **kwargs): - return self._backing_pool.submit(_wrap(fn), *args, **kwargs) + def submit(self, fn, *args, **kwargs): + return self._backing_pool.submit(_wrap(fn), *args, **kwargs) - def map(self, func, *iterables, **kwargs): - return self._backing_pool.map( - _wrap(func), *iterables, timeout=kwargs.get('timeout', None)) + def map(self, func, *iterables, **kwargs): + return self._backing_pool.map(_wrap(func), + *iterables, + timeout=kwargs.get('timeout', None)) - def shutdown(self, wait=True): - self._backing_pool.shutdown(wait=wait) + def shutdown(self, wait=True): + self._backing_pool.shutdown(wait=wait) def pool(max_workers): - """Creates a thread pool that logs exceptions raised by the tasks within it. + """Creates a thread pool that logs exceptions raised by the tasks within it. Args: max_workers: The maximum number of worker threads to allow the pool. @@ -79,4 +82,4 @@ def pool(max_workers): A futures.ThreadPoolExecutor-compatible thread pool that logs exceptions raised by the tasks executed within it. """ - return _LoggingPool(futures.ThreadPoolExecutor(max_workers)) + return _LoggingPool(futures.ThreadPoolExecutor(max_workers)) diff --git a/src/python/grpcio/grpc/framework/foundation/stream.py b/src/python/grpcio/grpc/framework/foundation/stream.py index ddd6cc496a9..2529a6944b8 100644 --- a/src/python/grpcio/grpc/framework/foundation/stream.py +++ b/src/python/grpcio/grpc/framework/foundation/stream.py @@ -26,35 +26,35 @@ # 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. - """Interfaces related to streams of values or objects.""" import abc import six + class Consumer(six.with_metaclass(abc.ABCMeta)): - """Interface for consumers of finite streams of values or objects.""" + """Interface for consumers of finite streams of values or objects.""" - @abc.abstractmethod - def consume(self, value): - """Accepts a value. + @abc.abstractmethod + def consume(self, value): + """Accepts a value. Args: value: Any value accepted by this Consumer. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def terminate(self): - """Indicates to this Consumer that no more values will be supplied.""" - raise NotImplementedError() + @abc.abstractmethod + def terminate(self): + """Indicates to this Consumer that no more values will be supplied.""" + raise NotImplementedError() - @abc.abstractmethod - def consume_and_terminate(self, value): - """Supplies a value and signals that no more values will be supplied. + @abc.abstractmethod + def consume_and_terminate(self, value): + """Supplies a value and signals that no more values will be supplied. Args: value: Any value accepted by this Consumer. """ - raise NotImplementedError() + raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/foundation/stream_util.py b/src/python/grpcio/grpc/framework/foundation/stream_util.py index a6f234f1feb..6b356f176fc 100644 --- a/src/python/grpcio/grpc/framework/foundation/stream_util.py +++ b/src/python/grpcio/grpc/framework/foundation/stream_util.py @@ -26,7 +26,6 @@ # 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. - """Helpful utilities related to the stream module.""" import logging @@ -38,126 +37,126 @@ _NO_VALUE = object() class TransformingConsumer(stream.Consumer): - """A stream.Consumer that passes a transformation of its input to another.""" + """A stream.Consumer that passes a transformation of its input to another.""" - def __init__(self, transformation, downstream): - self._transformation = transformation - self._downstream = downstream + def __init__(self, transformation, downstream): + self._transformation = transformation + self._downstream = downstream - def consume(self, value): - self._downstream.consume(self._transformation(value)) + def consume(self, value): + self._downstream.consume(self._transformation(value)) - def terminate(self): - self._downstream.terminate() + def terminate(self): + self._downstream.terminate() - def consume_and_terminate(self, value): - self._downstream.consume_and_terminate(self._transformation(value)) + def consume_and_terminate(self, value): + self._downstream.consume_and_terminate(self._transformation(value)) class IterableConsumer(stream.Consumer): - """A Consumer that when iterated over emits the values it has consumed.""" - - def __init__(self): - self._condition = threading.Condition() - self._values = [] - self._active = True - - def consume(self, stock_reply): - with self._condition: - if self._active: - self._values.append(stock_reply) - self._condition.notify() - - def terminate(self): - with self._condition: - self._active = False - self._condition.notify() - - def consume_and_terminate(self, stock_reply): - with self._condition: - if self._active: - self._values.append(stock_reply) - self._active = False - self._condition.notify() - - def __iter__(self): - return self - - def __next__(self): - return self.next() - - def next(self): - with self._condition: - while self._active and not self._values: - self._condition.wait() - if self._values: - return self._values.pop(0) - else: - raise StopIteration() + """A Consumer that when iterated over emits the values it has consumed.""" + + def __init__(self): + self._condition = threading.Condition() + self._values = [] + self._active = True + + def consume(self, stock_reply): + with self._condition: + if self._active: + self._values.append(stock_reply) + self._condition.notify() + + def terminate(self): + with self._condition: + self._active = False + self._condition.notify() + + def consume_and_terminate(self, stock_reply): + with self._condition: + if self._active: + self._values.append(stock_reply) + self._active = False + self._condition.notify() + + def __iter__(self): + return self + + def __next__(self): + return self.next() + + def next(self): + with self._condition: + while self._active and not self._values: + self._condition.wait() + if self._values: + return self._values.pop(0) + else: + raise StopIteration() class ThreadSwitchingConsumer(stream.Consumer): - """A Consumer decorator that affords serialization and asynchrony.""" - - def __init__(self, sink, pool): - self._lock = threading.Lock() - self._sink = sink - self._pool = pool - # True if self._spin has been submitted to the pool to be called once and - # that call has not yet returned, False otherwise. - self._spinning = False - self._values = [] - self._active = True - - def _spin(self, sink, value, terminate): - while True: - try: - if value is _NO_VALUE: - sink.terminate() - elif terminate: - sink.consume_and_terminate(value) - else: - sink.consume(value) - except Exception as e: # pylint:disable=broad-except - logging.exception(e) - - with self._lock: - if terminate: - self._spinning = False - return - elif self._values: - value = self._values.pop(0) - terminate = not self._values and not self._active - elif not self._active: - value = _NO_VALUE - terminate = True - else: - self._spinning = False - return - - def consume(self, value): - with self._lock: - if self._active: - if self._spinning: - self._values.append(value) - else: - self._pool.submit(self._spin, self._sink, value, False) - self._spinning = True - - def terminate(self): - with self._lock: - if self._active: - self._active = False - if not self._spinning: - self._pool.submit(self._spin, self._sink, _NO_VALUE, True) - self._spinning = True - - def consume_and_terminate(self, value): - with self._lock: - if self._active: - self._active = False - if self._spinning: - self._values.append(value) - else: - self._pool.submit(self._spin, self._sink, value, True) - self._spinning = True + """A Consumer decorator that affords serialization and asynchrony.""" + + def __init__(self, sink, pool): + self._lock = threading.Lock() + self._sink = sink + self._pool = pool + # True if self._spin has been submitted to the pool to be called once and + # that call has not yet returned, False otherwise. + self._spinning = False + self._values = [] + self._active = True + + def _spin(self, sink, value, terminate): + while True: + try: + if value is _NO_VALUE: + sink.terminate() + elif terminate: + sink.consume_and_terminate(value) + else: + sink.consume(value) + except Exception as e: # pylint:disable=broad-except + logging.exception(e) + + with self._lock: + if terminate: + self._spinning = False + return + elif self._values: + value = self._values.pop(0) + terminate = not self._values and not self._active + elif not self._active: + value = _NO_VALUE + terminate = True + else: + self._spinning = False + return + + def consume(self, value): + with self._lock: + if self._active: + if self._spinning: + self._values.append(value) + else: + self._pool.submit(self._spin, self._sink, value, False) + self._spinning = True + + def terminate(self): + with self._lock: + if self._active: + self._active = False + if not self._spinning: + self._pool.submit(self._spin, self._sink, _NO_VALUE, True) + self._spinning = True + + def consume_and_terminate(self, value): + with self._lock: + if self._active: + self._active = False + if self._spinning: + self._values.append(value) + else: + self._pool.submit(self._spin, self._sink, value, True) + self._spinning = True diff --git a/src/python/grpcio/grpc/framework/interfaces/__init__.py b/src/python/grpcio/grpc/framework/interfaces/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio/grpc/framework/interfaces/__init__.py +++ b/src/python/grpcio/grpc/framework/interfaces/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio/grpc/framework/interfaces/base/__init__.py b/src/python/grpcio/grpc/framework/interfaces/base/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/__init__.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py index a2ddd9c4747..cb3328296c5 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/base.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py @@ -26,7 +26,6 @@ # 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. - """The base interface of RPC Framework. Implementations of this interface support the conduct of "operations": @@ -49,7 +48,7 @@ from grpc.framework.foundation import abandonment # pylint: disable=unused-impo class NoSuchMethodError(Exception): - """Indicates that an unrecognized operation has been called. + """Indicates that an unrecognized operation has been called. Attributes: code: A code value to communicate to the other side of the operation along @@ -58,8 +57,8 @@ class NoSuchMethodError(Exception): along with indication of operation termination. May be None. """ - def __init__(self, code, details): - """Constructor. + def __init__(self, code, details): + """Constructor. Args: code: A code value to communicate to the other side of the operation @@ -67,12 +66,12 @@ class NoSuchMethodError(Exception): details: A details value to communicate to the other side of the operation along with indication of operation termination. May be None. """ - self.code = code - self.details = details + self.code = code + self.details = details class Outcome(object): - """The outcome of an operation. + """The outcome of an operation. Attributes: kind: A Kind value coarsely identifying how the operation terminated. @@ -82,23 +81,23 @@ class Outcome(object): provided. """ - @enum.unique - class Kind(enum.Enum): - """Ways in which an operation can terminate.""" + @enum.unique + class Kind(enum.Enum): + """Ways in which an operation can terminate.""" - COMPLETED = 'completed' - CANCELLED = 'cancelled' - EXPIRED = 'expired' - LOCAL_SHUTDOWN = 'local shutdown' - REMOTE_SHUTDOWN = 'remote shutdown' - RECEPTION_FAILURE = 'reception failure' - TRANSMISSION_FAILURE = 'transmission failure' - LOCAL_FAILURE = 'local failure' - REMOTE_FAILURE = 'remote failure' + COMPLETED = 'completed' + CANCELLED = 'cancelled' + EXPIRED = 'expired' + LOCAL_SHUTDOWN = 'local shutdown' + REMOTE_SHUTDOWN = 'remote shutdown' + RECEPTION_FAILURE = 'reception failure' + TRANSMISSION_FAILURE = 'transmission failure' + LOCAL_FAILURE = 'local failure' + REMOTE_FAILURE = 'remote failure' class Completion(six.with_metaclass(abc.ABCMeta)): - """An aggregate of the values exchanged upon operation completion. + """An aggregate of the values exchanged upon operation completion. Attributes: terminal_metadata: A terminal metadata value for the operaton. @@ -108,21 +107,21 @@ class Completion(six.with_metaclass(abc.ABCMeta)): class OperationContext(six.with_metaclass(abc.ABCMeta)): - """Provides operation-related information and action.""" + """Provides operation-related information and action.""" - @abc.abstractmethod - def outcome(self): - """Indicates the operation's outcome (or that the operation is ongoing). + @abc.abstractmethod + def outcome(self): + """Indicates the operation's outcome (or that the operation is ongoing). Returns: None if the operation is still active or the Outcome value for the operation if it has terminated. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_termination_callback(self, callback): - """Adds a function to be called upon operation termination. + @abc.abstractmethod + def add_termination_callback(self, callback): + """Adds a function to be called upon operation termination. Args: callback: A callable to be passed an Outcome value on operation @@ -134,42 +133,44 @@ class OperationContext(six.with_metaclass(abc.ABCMeta)): terminated an Outcome value describing the operation termination and the passed callback will not be called as a result of this method call. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the operation. + @abc.abstractmethod + def time_remaining(self): + """Describes the length of allowed time remaining for the operation. Returns: A nonnegative float indicating the length of allowed time in seconds remaining for the operation to complete before it is considered to have timed out. Zero is returned if the operation has terminated. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def cancel(self): - """Cancels the operation if the operation has not yet terminated.""" - raise NotImplementedError() + @abc.abstractmethod + def cancel(self): + """Cancels the operation if the operation has not yet terminated.""" + raise NotImplementedError() - @abc.abstractmethod - def fail(self, exception): - """Indicates that the operation has failed. + @abc.abstractmethod + def fail(self, exception): + """Indicates that the operation has failed. Args: exception: An exception germane to the operation failure. May be None. """ - raise NotImplementedError() + raise NotImplementedError() class Operator(six.with_metaclass(abc.ABCMeta)): - """An interface through which to participate in an operation.""" + """An interface through which to participate in an operation.""" - @abc.abstractmethod - def advance( - self, initial_metadata=None, payload=None, completion=None, - allowance=None): - """Progresses the operation. + @abc.abstractmethod + def advance(self, + initial_metadata=None, + payload=None, + completion=None, + allowance=None): + """Progresses the operation. Args: initial_metadata: An initial metadata value. Only one may ever be @@ -181,23 +182,24 @@ class Operator(six.with_metaclass(abc.ABCMeta)): allowance: A positive integer communicating the number of additional payloads allowed to be passed by the remote side of the operation. """ - raise NotImplementedError() + raise NotImplementedError() + class ProtocolReceiver(six.with_metaclass(abc.ABCMeta)): - """A means of receiving protocol values during an operation.""" + """A means of receiving protocol values during an operation.""" - @abc.abstractmethod - def context(self, protocol_context): - """Accepts the protocol context object for the operation. + @abc.abstractmethod + def context(self, protocol_context): + """Accepts the protocol context object for the operation. Args: protocol_context: The protocol context object for the operation. """ - raise NotImplementedError() + raise NotImplementedError() class Subscription(six.with_metaclass(abc.ABCMeta)): - """Describes customer code's interest in values from the other side. + """Describes customer code's interest in values from the other side. Attributes: kind: A Kind value describing the overall kind of this value. @@ -215,20 +217,20 @@ class Subscription(six.with_metaclass(abc.ABCMeta)): Kind.FULL. """ - @enum.unique - class Kind(enum.Enum): + @enum.unique + class Kind(enum.Enum): - NONE = 'none' - TERMINATION_ONLY = 'termination only' - FULL = 'full' + NONE = 'none' + TERMINATION_ONLY = 'termination only' + FULL = 'full' class Servicer(six.with_metaclass(abc.ABCMeta)): - """Interface for service implementations.""" + """Interface for service implementations.""" - @abc.abstractmethod - def service(self, group, method, context, output_operator): - """Services an operation. + @abc.abstractmethod + def service(self, group, method, context, output_operator): + """Services an operation. Args: group: The group identifier of the operation to be serviced. @@ -248,20 +250,20 @@ class Servicer(six.with_metaclass(abc.ABCMeta)): abandonment.Abandoned: If the operation has been aborted and there no longer is any reason to service the operation. """ - raise NotImplementedError() + raise NotImplementedError() class End(six.with_metaclass(abc.ABCMeta)): - """Common type for entry-point objects on both sides of an operation.""" + """Common type for entry-point objects on both sides of an operation.""" - @abc.abstractmethod - def start(self): - """Starts this object's service of operations.""" - raise NotImplementedError() + @abc.abstractmethod + def start(self): + """Starts this object's service of operations.""" + raise NotImplementedError() - @abc.abstractmethod - def stop(self, grace): - """Stops this object's service of operations. + @abc.abstractmethod + def stop(self, grace): + """Stops this object's service of operations. This object will refuse service of new operations as soon as this method is called but operations under way at the time of the call may be given a @@ -281,13 +283,19 @@ class End(six.with_metaclass(abc.ABCMeta)): much sooner (if for example this End had no operations in progress at the time its stop method was called). """ - raise NotImplementedError() - - @abc.abstractmethod - def operate( - self, group, method, subscription, timeout, initial_metadata=None, - payload=None, completion=None, protocol_options=None): - """Commences an operation. + raise NotImplementedError() + + @abc.abstractmethod + def operate(self, + group, + method, + subscription, + timeout, + initial_metadata=None, + payload=None, + completion=None, + protocol_options=None): + """Commences an operation. Args: group: The group identifier of the invoked operation. @@ -312,23 +320,23 @@ class End(six.with_metaclass(abc.ABCMeta)): returned pair is an Operator to which operation values not passed in this call should later be passed. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def operation_stats(self): - """Reports the number of terminated operations broken down by outcome. + @abc.abstractmethod + def operation_stats(self): + """Reports the number of terminated operations broken down by outcome. Returns: A dictionary from Outcome.Kind value to an integer identifying the number of operations that terminated with that outcome kind. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_idle_action(self, action): - """Adds an action to be called when this End has no ongoing operations. + @abc.abstractmethod + def add_idle_action(self, action): + """Adds an action to be called when this End has no ongoing operations. Args: action: A callable that accepts no arguments. """ - raise NotImplementedError() + raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/interfaces/base/utilities.py b/src/python/grpcio/grpc/framework/interfaces/base/utilities.py index 87a85018f52..461706ff9f2 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/utilities.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/utilities.py @@ -26,7 +26,6 @@ # 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. - """Utilities for use with the base interface of RPC Framework.""" import collections @@ -34,27 +33,30 @@ import collections from grpc.framework.interfaces.base import base -class _Completion( - base.Completion, - collections.namedtuple( - '_Completion', ('terminal_metadata', 'code', 'message',))): - """A trivial implementation of base.Completion.""" +class _Completion(base.Completion, + collections.namedtuple('_Completion', ( + 'terminal_metadata', + 'code', + 'message',))): + """A trivial implementation of base.Completion.""" + +class _Subscription(base.Subscription, + collections.namedtuple('_Subscription', ( + 'kind', + 'termination_callback', + 'allowance', + 'operator', + 'protocol_receiver',))): + """A trivial implementation of base.Subscription.""" -class _Subscription( - base.Subscription, - collections.namedtuple( - '_Subscription', - ('kind', 'termination_callback', 'allowance', 'operator', - 'protocol_receiver',))): - """A trivial implementation of base.Subscription.""" -_NONE_SUBSCRIPTION = _Subscription( - base.Subscription.Kind.NONE, None, None, None, None) +_NONE_SUBSCRIPTION = _Subscription(base.Subscription.Kind.NONE, None, None, + None, None) def completion(terminal_metadata, code, message): - """Creates a base.Completion aggregating the given operation values. + """Creates a base.Completion aggregating the given operation values. Args: terminal_metadata: A terminal metadata value for an operaton. @@ -64,11 +66,11 @@ def completion(terminal_metadata, code, message): Returns: A base.Completion aggregating the given operation values. """ - return _Completion(terminal_metadata, code, message) + return _Completion(terminal_metadata, code, message) def full_subscription(operator, protocol_receiver): - """Creates a "full" base.Subscription for the given base.Operator. + """Creates a "full" base.Subscription for the given base.Operator. Args: operator: A base.Operator to be used in an operation. @@ -78,5 +80,5 @@ def full_subscription(operator, protocol_receiver): A base.Subscription of kind base.Subscription.Kind.FULL wrapping the given base.Operator and base.ProtocolReceiver. """ - return _Subscription( - base.Subscription.Kind.FULL, None, None, operator, protocol_receiver) + return _Subscription(base.Subscription.Kind.FULL, None, None, operator, + protocol_receiver) diff --git a/src/python/grpcio/grpc/framework/interfaces/face/__init__.py b/src/python/grpcio/grpc/framework/interfaces/face/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio/grpc/framework/interfaces/face/__init__.py +++ b/src/python/grpcio/grpc/framework/interfaces/face/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio/grpc/framework/interfaces/face/face.py b/src/python/grpcio/grpc/framework/interfaces/face/face.py index 4826e7fff64..36ddca18c14 100644 --- a/src/python/grpcio/grpc/framework/interfaces/face/face.py +++ b/src/python/grpcio/grpc/framework/interfaces/face/face.py @@ -26,7 +26,6 @@ # 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. - """Interfaces defining the Face layer of RPC Framework.""" import abc @@ -45,33 +44,38 @@ from grpc.framework.foundation import stream # pylint: disable=unused-import class NoSuchMethodError(Exception): - """Raised by customer code to indicate an unrecognized method. + """Raised by customer code to indicate an unrecognized method. Attributes: group: The group of the unrecognized method. name: The name of the unrecognized method. """ - def __init__(self, group, method): - """Constructor. + def __init__(self, group, method): + """Constructor. Args: group: The group identifier of the unrecognized RPC name. method: The method identifier of the unrecognized RPC name. """ - super(NoSuchMethodError, self).__init__() - self.group = group - self.method = method + super(NoSuchMethodError, self).__init__() + self.group = group + self.method = method - def __repr__(self): - return 'face.NoSuchMethodError(%s, %s)' % (self.group, self.method,) + def __repr__(self): + return 'face.NoSuchMethodError(%s, %s)' % ( + self.group, + self.method,) class Abortion( - collections.namedtuple( - 'Abortion', - ('kind', 'initial_metadata', 'terminal_metadata', 'code', 'details',))): - """A value describing RPC abortion. + collections.namedtuple('Abortion', ( + 'kind', + 'initial_metadata', + 'terminal_metadata', + 'code', + 'details',))): + """A value describing RPC abortion. Attributes: kind: A Kind value identifying how the RPC failed. @@ -85,21 +89,21 @@ class Abortion( details value was received. """ - @enum.unique - class Kind(enum.Enum): - """Types of RPC abortion.""" + @enum.unique + class Kind(enum.Enum): + """Types of RPC abortion.""" - CANCELLED = 'cancelled' - EXPIRED = 'expired' - LOCAL_SHUTDOWN = 'local shutdown' - REMOTE_SHUTDOWN = 'remote shutdown' - NETWORK_FAILURE = 'network failure' - LOCAL_FAILURE = 'local failure' - REMOTE_FAILURE = 'remote failure' + CANCELLED = 'cancelled' + EXPIRED = 'expired' + LOCAL_SHUTDOWN = 'local shutdown' + REMOTE_SHUTDOWN = 'remote shutdown' + NETWORK_FAILURE = 'network failure' + LOCAL_FAILURE = 'local failure' + REMOTE_FAILURE = 'remote failure' class AbortionError(six.with_metaclass(abc.ABCMeta, Exception)): - """Common super type for exceptions indicating RPC abortion. + """Common super type for exceptions indicating RPC abortion. initial_metadata: The initial metadata from the other side of the RPC or None if no initial metadata value was received. @@ -111,100 +115,100 @@ class AbortionError(six.with_metaclass(abc.ABCMeta, Exception)): details value was received. """ - def __init__(self, initial_metadata, terminal_metadata, code, details): - super(AbortionError, self).__init__() - self.initial_metadata = initial_metadata - self.terminal_metadata = terminal_metadata - self.code = code - self.details = details + def __init__(self, initial_metadata, terminal_metadata, code, details): + super(AbortionError, self).__init__() + self.initial_metadata = initial_metadata + self.terminal_metadata = terminal_metadata + self.code = code + self.details = details - def __str__(self): - return '%s(code=%s, details="%s")' % ( - self.__class__.__name__, self.code, self.details) + def __str__(self): + return '%s(code=%s, details="%s")' % (self.__class__.__name__, + self.code, self.details) class CancellationError(AbortionError): - """Indicates that an RPC has been cancelled.""" + """Indicates that an RPC has been cancelled.""" class ExpirationError(AbortionError): - """Indicates that an RPC has expired ("timed out").""" + """Indicates that an RPC has expired ("timed out").""" class LocalShutdownError(AbortionError): - """Indicates that an RPC has terminated due to local shutdown of RPCs.""" + """Indicates that an RPC has terminated due to local shutdown of RPCs.""" class RemoteShutdownError(AbortionError): - """Indicates that an RPC has terminated due to remote shutdown of RPCs.""" + """Indicates that an RPC has terminated due to remote shutdown of RPCs.""" class NetworkError(AbortionError): - """Indicates that some error occurred on the network.""" + """Indicates that some error occurred on the network.""" class LocalError(AbortionError): - """Indicates that an RPC has terminated due to a local defect.""" + """Indicates that an RPC has terminated due to a local defect.""" class RemoteError(AbortionError): - """Indicates that an RPC has terminated due to a remote defect.""" + """Indicates that an RPC has terminated due to a remote defect.""" class RpcContext(six.with_metaclass(abc.ABCMeta)): - """Provides RPC-related information and action.""" + """Provides RPC-related information and action.""" - @abc.abstractmethod - def is_active(self): - """Describes whether the RPC is active or has terminated.""" - raise NotImplementedError() + @abc.abstractmethod + def is_active(self): + """Describes whether the RPC is active or has terminated.""" + raise NotImplementedError() - @abc.abstractmethod - def time_remaining(self): - """Describes the length of allowed time remaining for the RPC. + @abc.abstractmethod + def time_remaining(self): + """Describes the length of allowed time remaining for the RPC. Returns: A nonnegative float indicating the length of allowed time in seconds remaining for the RPC to complete before it is considered to have timed out. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def add_abortion_callback(self, abortion_callback): - """Registers a callback to be called if the RPC is aborted. + @abc.abstractmethod + def add_abortion_callback(self, abortion_callback): + """Registers a callback to be called if the RPC is aborted. Args: abortion_callback: A callable to be called and passed an Abortion value in the event of RPC abortion. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def cancel(self): - """Cancels the RPC. + @abc.abstractmethod + def cancel(self): + """Cancels the RPC. Idempotent and has no effect if the RPC has already terminated. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def protocol_context(self): - """Accesses a custom object specified by an implementation provider. + @abc.abstractmethod + def protocol_context(self): + """Accesses a custom object specified by an implementation provider. Returns: A value specified by the provider of a Face interface implementation affording custom state and behavior. """ - raise NotImplementedError() + raise NotImplementedError() class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): - """Invocation-side utility object for an RPC.""" + """Invocation-side utility object for an RPC.""" - @abc.abstractmethod - def initial_metadata(self): - """Accesses the initial metadata from the service-side of the RPC. + @abc.abstractmethod + def initial_metadata(self): + """Accesses the initial metadata from the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. @@ -213,11 +217,11 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): The initial metadata object emitted by the service-side of the RPC, or None if there was no such value. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def terminal_metadata(self): - """Accesses the terminal metadata from the service-side of the RPC. + @abc.abstractmethod + def terminal_metadata(self): + """Accesses the terminal metadata from the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. @@ -226,11 +230,11 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): The terminal metadata object emitted by the service-side of the RPC, or None if there was no such value. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def code(self): - """Accesses the code emitted by the service-side of the RPC. + @abc.abstractmethod + def code(self): + """Accesses the code emitted by the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. @@ -239,11 +243,11 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): The code object emitted by the service-side of the RPC, or None if there was no such value. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def details(self): - """Accesses the details value emitted by the service-side of the RPC. + @abc.abstractmethod + def details(self): + """Accesses the details value emitted by the service-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the service-side of the RPC. @@ -252,15 +256,15 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): The details value emitted by the service-side of the RPC, or None if there was no such value. """ - raise NotImplementedError() + raise NotImplementedError() class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): - """A context object passed to method implementations.""" + """A context object passed to method implementations.""" - @abc.abstractmethod - def invocation_metadata(self): - """Accesses the metadata from the invocation-side of the RPC. + @abc.abstractmethod + def invocation_metadata(self): + """Accesses the metadata from the invocation-side of the RPC. This method blocks until the value is available or is known not to have been emitted from the invocation-side of the RPC. @@ -269,11 +273,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): The metadata object emitted by the invocation-side of the RPC, or None if there was no such value. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def initial_metadata(self, initial_metadata): - """Accepts the service-side initial metadata value of the RPC. + @abc.abstractmethod + def initial_metadata(self, initial_metadata): + """Accepts the service-side initial metadata value of the RPC. This method need not be called by method implementations if they have no service-side initial metadata to transmit. @@ -282,11 +286,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): initial_metadata: The service-side initial metadata value of the RPC to be transmitted to the invocation side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def terminal_metadata(self, terminal_metadata): - """Accepts the service-side terminal metadata value of the RPC. + @abc.abstractmethod + def terminal_metadata(self, terminal_metadata): + """Accepts the service-side terminal metadata value of the RPC. This method need not be called by method implementations if they have no service-side terminal metadata to transmit. @@ -295,11 +299,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): terminal_metadata: The service-side terminal metadata value of the RPC to be transmitted to the invocation side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def code(self, code): - """Accepts the service-side code of the RPC. + @abc.abstractmethod + def code(self, code): + """Accepts the service-side code of the RPC. This method need not be called by method implementations if they have no code to transmit. @@ -308,11 +312,11 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): code: The code of the RPC to be transmitted to the invocation side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def details(self, details): - """Accepts the service-side details of the RPC. + @abc.abstractmethod + def details(self, details): + """Accepts the service-side details of the RPC. This method need not be called by method implementations if they have no service-side details to transmit. @@ -321,34 +325,34 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): details: The service-side details value of the RPC to be transmitted to the invocation side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() class ResponseReceiver(six.with_metaclass(abc.ABCMeta)): - """Invocation-side object used to accept the output of an RPC.""" + """Invocation-side object used to accept the output of an RPC.""" - @abc.abstractmethod - def initial_metadata(self, initial_metadata): - """Receives the initial metadata from the service-side of the RPC. + @abc.abstractmethod + def initial_metadata(self, initial_metadata): + """Receives the initial metadata from the service-side of the RPC. Args: initial_metadata: The initial metadata object emitted from the service-side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def response(self, response): - """Receives a response from the service-side of the RPC. + @abc.abstractmethod + def response(self, response): + """Receives a response from the service-side of the RPC. Args: response: A response object emitted from the service-side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def complete(self, terminal_metadata, code, details): - """Receives the completion values emitted from the service-side of the RPC. + @abc.abstractmethod + def complete(self, terminal_metadata, code, details): + """Receives the completion values emitted from the service-side of the RPC. Args: terminal_metadata: The terminal metadata object emitted from the @@ -356,17 +360,20 @@ class ResponseReceiver(six.with_metaclass(abc.ABCMeta)): code: The code object emitted from the service-side of the RPC. details: The details object emitted from the service-side of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-unary RPC in any call style.""" + """Affords invoking a unary-unary RPC in any call style.""" - @abc.abstractmethod - def __call__( - self, request, timeout, metadata=None, with_call=False, - protocol_options=None): - """Synchronously invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, + request, + timeout, + metadata=None, + with_call=False, + protocol_options=None): + """Synchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -385,11 +392,11 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Raises: AbortionError: Indicating that the RPC was aborted. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def future(self, request, timeout, metadata=None, protocol_options=None): - """Asynchronously invokes the underlying RPC. + @abc.abstractmethod + def future(self, request, timeout, metadata=None, protocol_options=None): + """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -405,13 +412,17 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ - raise NotImplementedError() - - @abc.abstractmethod - def event( - self, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - """Asynchronously invokes the underlying RPC. + raise NotImplementedError() + + @abc.abstractmethod + def event(self, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -427,15 +438,15 @@ class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Returns: A Call for the RPC. """ - raise NotImplementedError() + raise NotImplementedError() class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a unary-stream RPC in any call style.""" + """Affords invoking a unary-stream RPC in any call style.""" - @abc.abstractmethod - def __call__(self, request, timeout, metadata=None, protocol_options=None): - """Invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, request, timeout, metadata=None, protocol_options=None): + """Invokes the underlying RPC. Args: request: The request value for the RPC. @@ -450,13 +461,17 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ - raise NotImplementedError() - - @abc.abstractmethod - def event( - self, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - """Asynchronously invokes the underlying RPC. + raise NotImplementedError() + + @abc.abstractmethod + def event(self, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Asynchronously invokes the underlying RPC. Args: request: The request value for the RPC. @@ -472,17 +487,20 @@ class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): Returns: A Call object for the RPC. """ - raise NotImplementedError() + raise NotImplementedError() class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-unary RPC in any call style.""" + """Affords invoking a stream-unary RPC in any call style.""" - @abc.abstractmethod - def __call__( - self, request_iterator, timeout, metadata=None, - with_call=False, protocol_options=None): - """Synchronously invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, + request_iterator, + timeout, + metadata=None, + with_call=False, + protocol_options=None): + """Synchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -501,12 +519,15 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): Raises: AbortionError: Indicating that the RPC was aborted. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def future( - self, request_iterator, timeout, metadata=None, protocol_options=None): - """Asynchronously invokes the underlying RPC. + @abc.abstractmethod + def future(self, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + """Asynchronously invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -522,13 +543,16 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def event( - self, receiver, abortion_callback, timeout, metadata=None, - protocol_options=None): - """Asynchronously invokes the underlying RPC. + @abc.abstractmethod + def event(self, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Asynchronously invokes the underlying RPC. Args: receiver: A ResponseReceiver to be passed the response data of the RPC. @@ -544,16 +568,19 @@ class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)): A single object that is both a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ - raise NotImplementedError() + raise NotImplementedError() class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): - """Affords invoking a stream-stream RPC in any call style.""" + """Affords invoking a stream-stream RPC in any call style.""" - @abc.abstractmethod - def __call__( - self, request_iterator, timeout, metadata=None, protocol_options=None): - """Invokes the underlying RPC. + @abc.abstractmethod + def __call__(self, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + """Invokes the underlying RPC. Args: request_iterator: An iterator that yields request values for the RPC. @@ -568,13 +595,16 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def event( - self, receiver, abortion_callback, timeout, metadata=None, - protocol_options=None): - """Asynchronously invokes the underlying RPC. + @abc.abstractmethod + def event(self, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Asynchronously invokes the underlying RPC. Args: receiver: A ResponseReceiver to be passed the response data of the RPC. @@ -590,11 +620,11 @@ class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)): A single object that is both a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ - raise NotImplementedError() + raise NotImplementedError() class MethodImplementation(six.with_metaclass(abc.ABCMeta)): - """A sum type that describes a method implementation. + """A sum type that describes a method implementation. Attributes: cardinality: A cardinality.Cardinality value. @@ -639,11 +669,11 @@ class MethodImplementation(six.with_metaclass(abc.ABCMeta)): class MultiMethodImplementation(six.with_metaclass(abc.ABCMeta)): - """A general type able to service many methods.""" + """A general type able to service many methods.""" - @abc.abstractmethod - def service(self, group, method, response_consumer, context): - """Services an RPC. + @abc.abstractmethod + def service(self, group, method, response_consumer, context): + """Services an RPC. Args: group: The group identifier of the RPC. @@ -666,17 +696,22 @@ class MultiMethodImplementation(six.with_metaclass(abc.ABCMeta)): NoSuchMethodError: If this MultiMethod does not recognize the given group and name for the RPC and is not able to service the RPC. """ - raise NotImplementedError() + raise NotImplementedError() class GenericStub(six.with_metaclass(abc.ABCMeta)): - """Affords RPC invocation via generic methods.""" - - @abc.abstractmethod - def blocking_unary_unary( - self, group, method, request, timeout, metadata=None, - with_call=False, protocol_options=None): - """Invokes a unary-request-unary-response method. + """Affords RPC invocation via generic methods.""" + + @abc.abstractmethod + def blocking_unary_unary(self, + group, + method, + request, + timeout, + metadata=None, + with_call=False, + protocol_options=None): + """Invokes a unary-request-unary-response method. This method blocks until either returning the response value of the RPC (in the event of RPC completion) or raising an exception (in the event of @@ -700,13 +735,17 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Raises: AbortionError: Indicating that the RPC was aborted. """ - raise NotImplementedError() - - @abc.abstractmethod - def future_unary_unary( - self, group, method, request, timeout, metadata=None, - protocol_options=None): - """Invokes a unary-request-unary-response method. + raise NotImplementedError() + + @abc.abstractmethod + def future_unary_unary(self, + group, + method, + request, + timeout, + metadata=None, + protocol_options=None): + """Invokes a unary-request-unary-response method. Args: group: The group identifier of the RPC. @@ -723,13 +762,17 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ - raise NotImplementedError() - - @abc.abstractmethod - def inline_unary_stream( - self, group, method, request, timeout, metadata=None, - protocol_options=None): - """Invokes a unary-request-stream-response method. + raise NotImplementedError() + + @abc.abstractmethod + def inline_unary_stream(self, + group, + method, + request, + timeout, + metadata=None, + protocol_options=None): + """Invokes a unary-request-stream-response method. Args: group: The group identifier of the RPC. @@ -745,13 +788,18 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ - raise NotImplementedError() - - @abc.abstractmethod - def blocking_stream_unary( - self, group, method, request_iterator, timeout, metadata=None, - with_call=False, protocol_options=None): - """Invokes a stream-request-unary-response method. + raise NotImplementedError() + + @abc.abstractmethod + def blocking_stream_unary(self, + group, + method, + request_iterator, + timeout, + metadata=None, + with_call=False, + protocol_options=None): + """Invokes a stream-request-unary-response method. This method blocks until either returning the response value of the RPC (in the event of RPC completion) or raising an exception (in the event of @@ -775,13 +823,17 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Raises: AbortionError: Indicating that the RPC was aborted. """ - raise NotImplementedError() - - @abc.abstractmethod - def future_stream_unary( - self, group, method, request_iterator, timeout, metadata=None, - protocol_options=None): - """Invokes a stream-request-unary-response method. + raise NotImplementedError() + + @abc.abstractmethod + def future_stream_unary(self, + group, + method, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + """Invokes a stream-request-unary-response method. Args: group: The group identifier of the RPC. @@ -798,13 +850,17 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): response value of the RPC. In the event of RPC abortion, the returned Future's exception value will be an AbortionError. """ - raise NotImplementedError() - - @abc.abstractmethod - def inline_stream_stream( - self, group, method, request_iterator, timeout, metadata=None, - protocol_options=None): - """Invokes a stream-request-stream-response method. + raise NotImplementedError() + + @abc.abstractmethod + def inline_stream_stream(self, + group, + method, + request_iterator, + timeout, + metadata=None, + protocol_options=None): + """Invokes a stream-request-stream-response method. Args: group: The group identifier of the RPC. @@ -820,13 +876,19 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): values. Drawing response values from the returned iterator may raise AbortionError indicating abortion of the RPC. """ - raise NotImplementedError() - - @abc.abstractmethod - def event_unary_unary( - self, group, method, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - """Event-driven invocation of a unary-request-unary-response method. + raise NotImplementedError() + + @abc.abstractmethod + def event_unary_unary(self, + group, + method, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Event-driven invocation of a unary-request-unary-response method. Args: group: The group identifier of the RPC. @@ -843,13 +905,19 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Returns: A Call for the RPC. """ - raise NotImplementedError() - - @abc.abstractmethod - def event_unary_stream( - self, group, method, request, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - """Event-driven invocation of a unary-request-stream-response method. + raise NotImplementedError() + + @abc.abstractmethod + def event_unary_stream(self, + group, + method, + request, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Event-driven invocation of a unary-request-stream-response method. Args: group: The group identifier of the RPC. @@ -866,13 +934,18 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Returns: A Call for the RPC. """ - raise NotImplementedError() - - @abc.abstractmethod - def event_stream_unary( - self, group, method, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - """Event-driven invocation of a unary-request-unary-response method. + raise NotImplementedError() + + @abc.abstractmethod + def event_stream_unary(self, + group, + method, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Event-driven invocation of a unary-request-unary-response method. Args: group: The group identifier of the RPC. @@ -889,13 +962,18 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): A pair of a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ - raise NotImplementedError() - - @abc.abstractmethod - def event_stream_stream( - self, group, method, receiver, abortion_callback, timeout, - metadata=None, protocol_options=None): - """Event-driven invocation of a unary-request-stream-response method. + raise NotImplementedError() + + @abc.abstractmethod + def event_stream_stream(self, + group, + method, + receiver, + abortion_callback, + timeout, + metadata=None, + protocol_options=None): + """Event-driven invocation of a unary-request-stream-response method. Args: group: The group identifier of the RPC. @@ -912,11 +990,11 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): A pair of a Call object for the RPC and a stream.Consumer to which the request values of the RPC should be passed. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def unary_unary(self, group, method): - """Creates a UnaryUnaryMultiCallable for a unary-unary method. + @abc.abstractmethod + def unary_unary(self, group, method): + """Creates a UnaryUnaryMultiCallable for a unary-unary method. Args: group: The group identifier of the RPC. @@ -925,11 +1003,11 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Returns: A UnaryUnaryMultiCallable value for the named unary-unary method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def unary_stream(self, group, method): - """Creates a UnaryStreamMultiCallable for a unary-stream method. + @abc.abstractmethod + def unary_stream(self, group, method): + """Creates a UnaryStreamMultiCallable for a unary-stream method. Args: group: The group identifier of the RPC. @@ -938,11 +1016,11 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Returns: A UnaryStreamMultiCallable value for the name unary-stream method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stream_unary(self, group, method): - """Creates a StreamUnaryMultiCallable for a stream-unary method. + @abc.abstractmethod + def stream_unary(self, group, method): + """Creates a StreamUnaryMultiCallable for a stream-unary method. Args: group: The group identifier of the RPC. @@ -951,11 +1029,11 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Returns: A StreamUnaryMultiCallable value for the named stream-unary method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stream_stream(self, group, method): - """Creates a StreamStreamMultiCallable for a stream-stream method. + @abc.abstractmethod + def stream_stream(self, group, method): + """Creates a StreamStreamMultiCallable for a stream-stream method. Args: group: The group identifier of the RPC. @@ -964,11 +1042,11 @@ class GenericStub(six.with_metaclass(abc.ABCMeta)): Returns: A StreamStreamMultiCallable value for the named stream-stream method. """ - raise NotImplementedError() + raise NotImplementedError() class DynamicStub(six.with_metaclass(abc.ABCMeta)): - """Affords RPC invocation via attributes corresponding to afforded methods. + """Affords RPC invocation via attributes corresponding to afforded methods. Instances of this type may be scoped to a single group so that attribute access is unambiguous. diff --git a/src/python/grpcio/grpc/framework/interfaces/face/utilities.py b/src/python/grpcio/grpc/framework/interfaces/face/utilities.py index db2ec6ed87f..39a642f0ae2 100644 --- a/src/python/grpcio/grpc/framework/interfaces/face/utilities.py +++ b/src/python/grpcio/grpc/framework/interfaces/face/utilities.py @@ -26,7 +26,6 @@ # 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. - """Utilities for RPC Framework's Face interface.""" import collections @@ -38,18 +37,24 @@ from grpc.framework.foundation import stream # pylint: disable=unused-import from grpc.framework.interfaces.face import face -class _MethodImplementation( - face.MethodImplementation, - collections.namedtuple( - '_MethodImplementation', - ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline', - 'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event', - 'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])): - pass +class _MethodImplementation(face.MethodImplementation, + collections.namedtuple('_MethodImplementation', [ + 'cardinality', + 'style', + 'unary_unary_inline', + 'unary_stream_inline', + 'stream_unary_inline', + 'stream_stream_inline', + 'unary_unary_event', + 'unary_stream_event', + 'stream_unary_event', + 'stream_stream_event', + ])): + pass def unary_unary_inline(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-unary RPC method as a callable value @@ -59,13 +64,13 @@ def unary_unary_inline(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior, - None, None, None, None, None, None, None) + return _MethodImplementation(cardinality.Cardinality.UNARY_UNARY, + style.Service.INLINE, behavior, None, None, + None, None, None, None, None) def unary_stream_inline(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-stream RPC method as a callable @@ -75,13 +80,13 @@ def unary_stream_inline(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None, - behavior, None, None, None, None, None, None) + return _MethodImplementation(cardinality.Cardinality.UNARY_STREAM, + style.Service.INLINE, None, behavior, None, + None, None, None, None, None) def stream_unary_inline(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-unary RPC method as a callable @@ -91,13 +96,13 @@ def stream_unary_inline(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None, - behavior, None, None, None, None, None) + return _MethodImplementation(cardinality.Cardinality.STREAM_UNARY, + style.Service.INLINE, None, None, behavior, + None, None, None, None, None) def stream_stream_inline(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-stream RPC method as a callable @@ -107,13 +112,13 @@ def stream_stream_inline(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None, - None, behavior, None, None, None, None) + return _MethodImplementation(cardinality.Cardinality.STREAM_STREAM, + style.Service.INLINE, None, None, None, + behavior, None, None, None, None) def unary_unary_event(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-unary RPC method as a callable @@ -123,13 +128,13 @@ def unary_unary_event(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None, - None, None, behavior, None, None, None) + return _MethodImplementation(cardinality.Cardinality.UNARY_UNARY, + style.Service.EVENT, None, None, None, None, + behavior, None, None, None) def unary_stream_event(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a unary-stream RPC method as a callable @@ -139,13 +144,13 @@ def unary_stream_event(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None, - None, None, None, behavior, None, None) + return _MethodImplementation(cardinality.Cardinality.UNARY_STREAM, + style.Service.EVENT, None, None, None, None, + None, behavior, None, None) def stream_unary_event(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-unary RPC method as a callable @@ -156,13 +161,13 @@ def stream_unary_event(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None, - None, None, None, None, behavior, None) + return _MethodImplementation(cardinality.Cardinality.STREAM_UNARY, + style.Service.EVENT, None, None, None, None, + None, None, behavior, None) def stream_stream_event(behavior): - """Creates an face.MethodImplementation for the given behavior. + """Creates an face.MethodImplementation for the given behavior. Args: behavior: The implementation of a stream-stream RPC method as a callable @@ -173,6 +178,6 @@ def stream_stream_event(behavior): Returns: An face.MethodImplementation derived from the given behavior. """ - return _MethodImplementation( - cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None, - None, None, None, None, None, behavior) + return _MethodImplementation(cardinality.Cardinality.STREAM_STREAM, + style.Service.EVENT, None, None, None, None, + None, None, None, behavior) diff --git a/src/python/grpcio/support.py b/src/python/grpcio/support.py index b226e690fdd..a228ba4a482 100644 --- a/src/python/grpcio/support.py +++ b/src/python/grpcio/support.py @@ -27,7 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - import os import os.path import shutil @@ -38,7 +37,6 @@ from distutils import errors import commands - C_PYTHON_DEV = """ #include int main(int argc, char **argv) { return 0; } @@ -55,69 +53,70 @@ Could not find . This could mean the following: (check your environment variables or try re-installing?) """ -C_CHECKS = { - C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE, -} +C_CHECKS = {C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE,} + def _compile(compiler, source_string): - tempdir = tempfile.mkdtemp() - cpath = os.path.join(tempdir, 'a.c') - with open(cpath, 'w') as cfile: - cfile.write(source_string) - try: - compiler.compile([cpath]) - except errors.CompileError as error: - return error - finally: - shutil.rmtree(tempdir) + tempdir = tempfile.mkdtemp() + cpath = os.path.join(tempdir, 'a.c') + with open(cpath, 'w') as cfile: + cfile.write(source_string) + try: + compiler.compile([cpath]) + except errors.CompileError as error: + return error + finally: + shutil.rmtree(tempdir) + def _expect_compile(compiler, source_string, error_message): - if _compile(compiler, source_string) is not None: - sys.stderr.write(error_message) - raise commands.CommandError( - "Diagnostics found a compilation environment issue:\n{}" + if _compile(compiler, source_string) is not None: + sys.stderr.write(error_message) + raise commands.CommandError( + "Diagnostics found a compilation environment issue:\n{}" .format(error_message)) + def diagnose_compile_error(build_ext, error): - """Attempt to diagnose an error during compilation.""" - for c_check, message in C_CHECKS.items(): - _expect_compile(build_ext.compiler, c_check, message) - python_sources = [ - source for source in build_ext.get_source_files() - if source.startswith('./src/python') and source.endswith('c') - ] - for source in python_sources: - if not os.path.isfile(source): - raise commands.CommandError( - ("Diagnostics found a missing Python extension source file:\n{}\n\n" - "This is usually because the Cython sources haven't been transpiled " - "into C yet and you're building from source.\n" - "Try setting the environment variable " - "`GRPC_PYTHON_BUILD_WITH_CYTHON=1` when invoking `setup.py` or " - "when using `pip`, e.g.:\n\n" - "pip install -rrequirements.txt\n" - "GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install .") - .format(source) - ) + """Attempt to diagnose an error during compilation.""" + for c_check, message in C_CHECKS.items(): + _expect_compile(build_ext.compiler, c_check, message) + python_sources = [ + source for source in build_ext.get_source_files() + if source.startswith('./src/python') and source.endswith('c') + ] + for source in python_sources: + if not os.path.isfile(source): + raise commands.CommandError(( + "Diagnostics found a missing Python extension source file:\n{}\n\n" + "This is usually because the Cython sources haven't been transpiled " + "into C yet and you're building from source.\n" + "Try setting the environment variable " + "`GRPC_PYTHON_BUILD_WITH_CYTHON=1` when invoking `setup.py` or " + "when using `pip`, e.g.:\n\n" + "pip install -rrequirements.txt\n" + "GRPC_PYTHON_BUILD_WITH_CYTHON=1 pip install .").format(source)) + def diagnose_attribute_error(build_ext, error): - if any('_needs_stub' in arg for arg in error.args): - raise commands.CommandError( - "We expect a missing `_needs_stub` attribute from older versions of " - "setuptools. Consider upgrading setuptools.") + if any('_needs_stub' in arg for arg in error.args): + raise commands.CommandError( + "We expect a missing `_needs_stub` attribute from older versions of " + "setuptools. Consider upgrading setuptools.") + _ERROR_DIAGNOSES = { errors.CompileError: diagnose_compile_error, AttributeError: diagnose_attribute_error } -def diagnose_build_ext_error(build_ext, error, formatted): - diagnostic = _ERROR_DIAGNOSES.get(type(error)) - if diagnostic is None: - raise commands.CommandError( - "\n\nWe could not diagnose your build failure. Please file an issue at " - "http://www.github.com/grpc/grpc with `[Python install]` in the title." - "\n\n{}".format(formatted)) - else: - diagnostic(build_ext, error) +def diagnose_build_ext_error(build_ext, error, formatted): + diagnostic = _ERROR_DIAGNOSES.get(type(error)) + if diagnostic is None: + raise commands.CommandError( + "\n\nWe could not diagnose your build failure. Please file an issue at " + "http://www.github.com/grpc/grpc with `[Python install]` in the title." + "\n\n{}".format(formatted)) + else: + diagnostic(build_ext, error) diff --git a/src/python/grpcio_health_checking/grpc_health/__init__.py b/src/python/grpcio_health_checking/grpc_health/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_health_checking/grpc_health/__init__.py +++ b/src/python/grpcio_health_checking/grpc_health/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_health_checking/grpc_health/v1/__init__.py b/src/python/grpcio_health_checking/grpc_health/v1/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_health_checking/grpc_health/v1/__init__.py +++ b/src/python/grpcio_health_checking/grpc_health/v1/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_health_checking/grpc_health/v1/health.py b/src/python/grpcio_health_checking/grpc_health/v1/health.py index 0df679b0e22..f0f11cf84b0 100644 --- a/src/python/grpcio_health_checking/grpc_health/v1/health.py +++ b/src/python/grpcio_health_checking/grpc_health/v1/health.py @@ -26,7 +26,6 @@ # 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. - """Reference implementation for health checking in gRPC Python.""" import threading @@ -37,23 +36,23 @@ from grpc_health.v1 import health_pb2 class HealthServicer(health_pb2.HealthServicer): - """Servicer handling RPCs for service statuses.""" + """Servicer handling RPCs for service statuses.""" - def __init__(self): - self._server_status_lock = threading.Lock() - self._server_status = {} + def __init__(self): + self._server_status_lock = threading.Lock() + self._server_status = {} - def Check(self, request, context): - with self._server_status_lock: - status = self._server_status.get(request.service) - if status is None: - context.set_code(grpc.StatusCode.NOT_FOUND) - return health_pb2.HealthCheckResponse() - else: - return health_pb2.HealthCheckResponse(status=status) + def Check(self, request, context): + with self._server_status_lock: + status = self._server_status.get(request.service) + if status is None: + context.set_code(grpc.StatusCode.NOT_FOUND) + return health_pb2.HealthCheckResponse() + else: + return health_pb2.HealthCheckResponse(status=status) - def set(self, service, status): - """Sets the status of a service. + def set(self, service, status): + """Sets the status of a service. Args: service: string, the name of the service. @@ -61,5 +60,5 @@ class HealthServicer(health_pb2.HealthServicer): status: HealthCheckResponse.status enum value indicating the status of the service """ - with self._server_status_lock: - self._server_status[service] = status + with self._server_status_lock: + self._server_status[service] = status diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py index 0c420a655f5..14375a74c0e 100644 --- a/src/python/grpcio_health_checking/health_commands.py +++ b/src/python/grpcio_health_checking/health_commands.py @@ -26,7 +26,6 @@ # 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. - """Provides distutils command classes for the GRPC Python setup process.""" import os @@ -39,40 +38,40 @@ HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/health/v1/health.proto') class CopyProtoModules(setuptools.Command): - """Command to copy proto modules from grpc/src/proto.""" + """Command to copy proto modules from grpc/src/proto.""" - description = '' - user_options = [] + description = '' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - pass + def finalize_options(self): + pass - def run(self): - if os.path.isfile(HEALTH_PROTO): - shutil.copyfile( - HEALTH_PROTO, - os.path.join(ROOT_DIR, 'grpc_health/v1/health.proto')) + def run(self): + if os.path.isfile(HEALTH_PROTO): + shutil.copyfile( + HEALTH_PROTO, + os.path.join(ROOT_DIR, 'grpc_health/v1/health.proto')) class BuildPackageProtos(setuptools.Command): - """Command to generate project *_pb2.py modules from proto files.""" + """Command to generate project *_pb2.py modules from proto files.""" - description = 'build grpc protobuf modules' - user_options = [] + description = 'build grpc protobuf modules' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - pass + def finalize_options(self): + pass - def run(self): - # due to limitations of the proto generator, we require that only *one* - # directory is provided as an 'include' directory. We assume it's the '' key - # to `self.distribution.package_dir` (and get a key error if it's not - # there). - from grpc_tools import command - command.build_package_protos(self.distribution.package_dir['']) + def run(self): + # due to limitations of the proto generator, we require that only *one* + # directory is provided as an 'include' directory. We assume it's the '' key + # to `self.distribution.package_dir` (and get a key error if it's not + # there). + from grpc_tools import command + command.build_package_protos(self.distribution.package_dir['']) diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index e88f389ba8a..4c3991dcc4a 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -26,7 +26,6 @@ # 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. - """Setup module for the GRPC Python package's optional health checking.""" import os @@ -41,18 +40,14 @@ os.chdir(os.path.dirname(os.path.abspath(__file__))) import health_commands import grpc_version -PACKAGE_DIRECTORIES = { - '': '.', -} +PACKAGE_DIRECTORIES = {'': '.',} SETUP_REQUIRES = ( - 'grpcio-tools>={version}'.format(version=grpc_version.VERSION), -) + 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),) INSTALL_REQUIRES = ( 'protobuf>=3.0.0', - 'grpcio>={version}'.format(version=grpc_version.VERSION), -) + 'grpcio>={version}'.format(version=grpc_version.VERSION),) COMMAND_CLASS = { # Run preprocess from the repository *before* doing any packaging! @@ -68,5 +63,4 @@ setuptools.setup( packages=setuptools.find_packages('.'), install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, - cmdclass=COMMAND_CLASS -) + cmdclass=COMMAND_CLASS) diff --git a/src/python/grpcio_reflection/grpc_reflection/__init__.py b/src/python/grpcio_reflection/grpc_reflection/__init__.py index d5ad73a74ab..100a624dc9c 100644 --- a/src/python/grpcio_reflection/grpc_reflection/__init__.py +++ b/src/python/grpcio_reflection/grpc_reflection/__init__.py @@ -26,4 +26,3 @@ # 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. - diff --git a/src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py b/src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py index d5ad73a74ab..100a624dc9c 100644 --- a/src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py +++ b/src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py @@ -26,4 +26,3 @@ # 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. - diff --git a/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py b/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py index bfcbce8e041..87f28396ce2 100644 --- a/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py +++ b/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py @@ -26,7 +26,6 @@ # 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. - """Reference implementation for reflection in gRPC Python.""" import threading @@ -39,105 +38,96 @@ from grpc_reflection.v1alpha import reflection_pb2 _POOL = descriptor_pool.Default() + def _not_found_error(): - return reflection_pb2.ServerReflectionResponse( - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.NOT_FOUND.value[0], - error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), - ) - ) + return reflection_pb2.ServerReflectionResponse( + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.NOT_FOUND.value[0], + error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(),)) + def _file_descriptor_response(descriptor): - proto = descriptor_pb2.FileDescriptorProto() - descriptor.CopyToProto(proto) - serialized_proto = proto.SerializeToString() - return reflection_pb2.ServerReflectionResponse( - file_descriptor_response=reflection_pb2.FileDescriptorResponse( - file_descriptor_proto=(serialized_proto,) - ), - ) + proto = descriptor_pb2.FileDescriptorProto() + descriptor.CopyToProto(proto) + serialized_proto = proto.SerializeToString() + return reflection_pb2.ServerReflectionResponse( + file_descriptor_response=reflection_pb2.FileDescriptorResponse( + file_descriptor_proto=(serialized_proto,)),) class ReflectionServicer(reflection_pb2.ServerReflectionServicer): - """Servicer handling RPCs for service statuses.""" + """Servicer handling RPCs for service statuses.""" - def __init__(self, service_names, pool=None): - """Constructor. + def __init__(self, service_names, pool=None): + """Constructor. Args: service_names: Iterable of fully-qualified service names available. """ - self._service_names = list(service_names) - self._pool = _POOL if pool is None else pool - - def _file_by_filename(self, filename): - try: - descriptor = self._pool.FindFileByName(filename) - except KeyError: - return _not_found_error() - else: - return _file_descriptor_response(descriptor) - - def _file_containing_symbol(self, fully_qualified_name): - try: - descriptor = self._pool.FindFileContainingSymbol(fully_qualified_name) - except KeyError: - return _not_found_error() - else: - return _file_descriptor_response(descriptor) - - def _file_containing_extension(containing_type, extension_number): - # TODO(atash) Python protobuf currently doesn't support querying extensions. - # https://github.com/google/protobuf/issues/2248 - return reflection_pb2.ServerReflectionResponse( - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.UNIMPLEMENTED.value[0], - error_message=grpc.StatusCode.UNIMPLMENTED.value[1].encode(), - ) - ) - - def _extension_numbers_of_type(fully_qualified_name): - # TODO(atash) We're allowed to leave this unsupported according to the - # protocol, but we should still eventually implement it. Hits the same issue - # as `_file_containing_extension`, however. - # https://github.com/google/protobuf/issues/2248 - return reflection_pb2.ServerReflectionResponse( - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.UNIMPLEMENTED.value[0], - error_message=grpc.StatusCode.UNIMPLMENTED.value[1].encode(), - ) - ) + self._service_names = list(service_names) + self._pool = _POOL if pool is None else pool + + def _file_by_filename(self, filename): + try: + descriptor = self._pool.FindFileByName(filename) + except KeyError: + return _not_found_error() + else: + return _file_descriptor_response(descriptor) + + def _file_containing_symbol(self, fully_qualified_name): + try: + descriptor = self._pool.FindFileContainingSymbol( + fully_qualified_name) + except KeyError: + return _not_found_error() + else: + return _file_descriptor_response(descriptor) + + def _file_containing_extension(containing_type, extension_number): + # TODO(atash) Python protobuf currently doesn't support querying extensions. + # https://github.com/google/protobuf/issues/2248 + return reflection_pb2.ServerReflectionResponse( + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.UNIMPLEMENTED.value[0], + error_message=grpc.StatusCode.UNIMPLMENTED.value[1].encode(),)) + + def _extension_numbers_of_type(fully_qualified_name): + # TODO(atash) We're allowed to leave this unsupported according to the + # protocol, but we should still eventually implement it. Hits the same issue + # as `_file_containing_extension`, however. + # https://github.com/google/protobuf/issues/2248 + return reflection_pb2.ServerReflectionResponse( + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.UNIMPLEMENTED.value[0], + error_message=grpc.StatusCode.UNIMPLMENTED.value[1].encode(),)) - def _list_services(self): - return reflection_pb2.ServerReflectionResponse( - list_services_response=reflection_pb2.ListServiceResponse( - service=[ + def _list_services(self): + return reflection_pb2.ServerReflectionResponse( + list_services_response=reflection_pb2.ListServiceResponse(service=[ reflection_pb2.ServiceResponse(name=service_name) for service_name in self._service_names - ] - ) - ) - - def ServerReflectionInfo(self, request_iterator, context): - for request in request_iterator: - if request.HasField('file_by_filename'): - yield self._file_by_filename(request.file_by_filename) - elif request.HasField('file_containing_symbol'): - yield self._file_containing_symbol(request.file_containing_symbol) - elif request.HasField('file_containing_extension'): - yield self._file_containing_extension( - request.file_containing_extension.containing_type, - request.file_containing_extension.extension_number) - elif request.HasField('all_extension_numbers_of_type'): - yield _all_extension_numbers_of_type( - request.all_extension_numbers_of_type) - elif request.HasField('list_services'): - yield self._list_services() - else: - yield reflection_pb2.ServerReflectionResponse( - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.INVALID_ARGUMENT.value[0], - error_message=grpc.StatusCode.INVALID_ARGUMENT.value[1].encode(), - ) - ) - + ])) + + def ServerReflectionInfo(self, request_iterator, context): + for request in request_iterator: + if request.HasField('file_by_filename'): + yield self._file_by_filename(request.file_by_filename) + elif request.HasField('file_containing_symbol'): + yield self._file_containing_symbol( + request.file_containing_symbol) + elif request.HasField('file_containing_extension'): + yield self._file_containing_extension( + request.file_containing_extension.containing_type, + request.file_containing_extension.extension_number) + elif request.HasField('all_extension_numbers_of_type'): + yield _all_extension_numbers_of_type( + request.all_extension_numbers_of_type) + elif request.HasField('list_services'): + yield self._list_services() + else: + yield reflection_pb2.ServerReflectionResponse( + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.INVALID_ARGUMENT.value[0], + error_message=grpc.StatusCode.INVALID_ARGUMENT.value[1] + .encode(),)) diff --git a/src/python/grpcio_reflection/reflection_commands.py b/src/python/grpcio_reflection/reflection_commands.py index dee5491e0ad..62237e09719 100644 --- a/src/python/grpcio_reflection/reflection_commands.py +++ b/src/python/grpcio_reflection/reflection_commands.py @@ -26,7 +26,6 @@ # 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. - """Provides distutils command classes for the GRPC Python setup process.""" import os @@ -35,44 +34,46 @@ import shutil import setuptools ROOT_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) -HEALTH_PROTO = os.path.join(ROOT_DIR, '../../proto/grpc/reflection/v1alpha/reflection.proto') +HEALTH_PROTO = os.path.join( + ROOT_DIR, '../../proto/grpc/reflection/v1alpha/reflection.proto') class CopyProtoModules(setuptools.Command): - """Command to copy proto modules from grpc/src/proto.""" + """Command to copy proto modules from grpc/src/proto.""" - description = '' - user_options = [] + description = '' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - pass + def finalize_options(self): + pass - def run(self): - if os.path.isfile(HEALTH_PROTO): - shutil.copyfile( - HEALTH_PROTO, - os.path.join(ROOT_DIR, 'grpc_reflection/v1alpha/reflection.proto')) + def run(self): + if os.path.isfile(HEALTH_PROTO): + shutil.copyfile( + HEALTH_PROTO, + os.path.join(ROOT_DIR, + 'grpc_reflection/v1alpha/reflection.proto')) class BuildPackageProtos(setuptools.Command): - """Command to generate project *_pb2.py modules from proto files.""" + """Command to generate project *_pb2.py modules from proto files.""" - description = 'build grpc protobuf modules' - user_options = [] + description = 'build grpc protobuf modules' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - pass + def finalize_options(self): + pass - def run(self): - # due to limitations of the proto generator, we require that only *one* - # directory is provided as an 'include' directory. We assume it's the '' key - # to `self.distribution.package_dir` (and get a key error if it's not - # there). - from grpc_tools import command - command.build_package_protos(self.distribution.package_dir['']) + def run(self): + # due to limitations of the proto generator, we require that only *one* + # directory is provided as an 'include' directory. We assume it's the '' key + # to `self.distribution.package_dir` (and get a key error if it's not + # there). + from grpc_tools import command + command.build_package_protos(self.distribution.package_dir['']) diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py index cfc41f4fe74..2926923029a 100644 --- a/src/python/grpcio_reflection/setup.py +++ b/src/python/grpcio_reflection/setup.py @@ -26,7 +26,6 @@ # 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. - """Setup module for the GRPC Python package's optional reflection.""" import os @@ -41,18 +40,14 @@ os.chdir(os.path.dirname(os.path.abspath(__file__))) import reflection_commands import grpc_version -PACKAGE_DIRECTORIES = { - '': '.', -} +PACKAGE_DIRECTORIES = {'': '.',} SETUP_REQUIRES = ( - 'grpcio-tools>={version}'.format(version=grpc_version.VERSION), -) + 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),) INSTALL_REQUIRES = ( 'protobuf>=3.0.0', - 'grpcio>={version}'.format(version=grpc_version.VERSION), -) + 'grpcio>={version}'.format(version=grpc_version.VERSION),) COMMAND_CLASS = { # Run preprocess from the repository *before* doing any packaging! @@ -68,5 +63,4 @@ setuptools.setup( packages=setuptools.find_packages('.'), install_requires=INSTALL_REQUIRES, setup_requires=SETUP_REQUIRES, - cmdclass=COMMAND_CLASS -) + cmdclass=COMMAND_CLASS) diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index e822971fe09..845b7f598c0 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -26,7 +26,6 @@ # 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. - """Provides distutils command classes for the gRPC Python setup process.""" import distutils @@ -55,163 +54,162 @@ PYTHON_PROTO_TOP_LEVEL = os.path.join(PYTHON_STEM, 'src') class CommandError(object): - pass + pass class GatherProto(setuptools.Command): - description = 'gather proto dependencies' - user_options = [] + description = 'gather proto dependencies' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - pass + def finalize_options(self): + pass - def run(self): - # TODO(atash) ensure that we're running from the repository directory when - # this command is used - try: - shutil.rmtree(PROTO_STEM) - except Exception as error: - # We don't care if this command fails - pass - shutil.copytree(GRPC_PROTO_STEM, PROTO_STEM) - for root, _, _ in os.walk(PYTHON_PROTO_TOP_LEVEL): - path = os.path.join(root, '__init__.py') - open(path, 'a').close() + def run(self): + # TODO(atash) ensure that we're running from the repository directory when + # this command is used + try: + shutil.rmtree(PROTO_STEM) + except Exception as error: + # We don't care if this command fails + pass + shutil.copytree(GRPC_PROTO_STEM, PROTO_STEM) + for root, _, _ in os.walk(PYTHON_PROTO_TOP_LEVEL): + path = os.path.join(root, '__init__.py') + open(path, 'a').close() class BuildProtoModules(setuptools.Command): - """Command to generate project *_pb2.py modules from proto files.""" - - description = 'build protobuf modules' - user_options = [ - ('include=', None, 'path patterns to include in protobuf generation'), - ('exclude=', None, 'path patterns to exclude from protobuf generation') - ] - - def initialize_options(self): - self.exclude = None - self.include = r'.*\.proto$' - - def finalize_options(self): - pass - - def run(self): - import grpc_tools.protoc as protoc - - include_regex = re.compile(self.include) - exclude_regex = re.compile(self.exclude) if self.exclude else None - paths = [] - for walk_root, directories, filenames in os.walk(PROTO_STEM): - for filename in filenames: - path = os.path.join(walk_root, filename) - if include_regex.match(path) and not ( - exclude_regex and exclude_regex.match(path)): - paths.append(path) - - # TODO(kpayson): It would be nice to do this in a batch command, - # but we currently have name conflicts in src/proto - for path in paths: - command = [ - 'grpc_tools.protoc', - '-I {}'.format(PROTO_STEM), - '--python_out={}'.format(PROTO_STEM), - '--grpc_python_out={}'.format(PROTO_STEM), - ] + [path] - if protoc.main(command) != 0: - sys.stderr.write( - 'warning: Command:\n{}\nFailed'.format( - command)) - - # Generated proto directories dont include __init__.py, but - # these are needed for python package resolution - for walk_root, _, _ in os.walk(PROTO_STEM): - path = os.path.join(walk_root, '__init__.py') - open(path, 'a').close() + """Command to generate project *_pb2.py modules from proto files.""" + + description = 'build protobuf modules' + user_options = [ + ('include=', None, 'path patterns to include in protobuf generation'), + ('exclude=', None, 'path patterns to exclude from protobuf generation') + ] + + def initialize_options(self): + self.exclude = None + self.include = r'.*\.proto$' + + def finalize_options(self): + pass + + def run(self): + import grpc_tools.protoc as protoc + + include_regex = re.compile(self.include) + exclude_regex = re.compile(self.exclude) if self.exclude else None + paths = [] + for walk_root, directories, filenames in os.walk(PROTO_STEM): + for filename in filenames: + path = os.path.join(walk_root, filename) + if include_regex.match(path) and not ( + exclude_regex and exclude_regex.match(path)): + paths.append(path) + + # TODO(kpayson): It would be nice to do this in a batch command, + # but we currently have name conflicts in src/proto + for path in paths: + command = [ + 'grpc_tools.protoc', + '-I {}'.format(PROTO_STEM), + '--python_out={}'.format(PROTO_STEM), + '--grpc_python_out={}'.format(PROTO_STEM), + ] + [path] + if protoc.main(command) != 0: + sys.stderr.write('warning: Command:\n{}\nFailed'.format( + command)) + + # Generated proto directories dont include __init__.py, but + # these are needed for python package resolution + for walk_root, _, _ in os.walk(PROTO_STEM): + path = os.path.join(walk_root, '__init__.py') + open(path, 'a').close() class BuildPy(build_py.build_py): - """Custom project build command.""" + """Custom project build command.""" - def run(self): - try: - self.run_command('build_package_protos') - except CommandError as error: - sys.stderr.write('warning: %s\n' % error.message) - build_py.build_py.run(self) + def run(self): + try: + self.run_command('build_package_protos') + except CommandError as error: + sys.stderr.write('warning: %s\n' % error.message) + build_py.build_py.run(self) class TestLite(setuptools.Command): - """Command to run tests without fetching or building anything.""" + """Command to run tests without fetching or building anything.""" - description = 'run tests without fetching or building anything.' - user_options = [] + description = 'run tests without fetching or building anything.' + user_options = [] - def initialize_options(self): - pass + def initialize_options(self): + pass - def finalize_options(self): - # distutils requires this override. - pass + def finalize_options(self): + # distutils requires this override. + pass - def run(self): - self._add_eggs_to_path() + def run(self): + self._add_eggs_to_path() - import tests - loader = tests.Loader() - loader.loadTestsFromNames(['tests']) - runner = tests.Runner() - result = runner.run(loader.suite) - if not result.wasSuccessful(): - sys.exit('Test failure') + import tests + loader = tests.Loader() + loader.loadTestsFromNames(['tests']) + runner = tests.Runner() + result = runner.run(loader.suite) + if not result.wasSuccessful(): + sys.exit('Test failure') - def _add_eggs_to_path(self): - """Fetch install and test requirements""" - self.distribution.fetch_build_eggs(self.distribution.install_requires) - self.distribution.fetch_build_eggs(self.distribution.tests_require) + def _add_eggs_to_path(self): + """Fetch install and test requirements""" + self.distribution.fetch_build_eggs(self.distribution.install_requires) + self.distribution.fetch_build_eggs(self.distribution.tests_require) class RunInterop(test.test): - description = 'run interop test client/server' - user_options = [ - ('args=', 'a', 'pass-thru arguments for the client/server'), - ('client', 'c', 'flag indicating to run the client'), - ('server', 's', 'flag indicating to run the server') - ] - - def initialize_options(self): - self.args = '' - self.client = False - self.server = False - - def finalize_options(self): - if self.client and self.server: - raise DistutilsOptionError('you may only specify one of client or server') - - def run(self): - if self.distribution.install_requires: - self.distribution.fetch_build_eggs(self.distribution.install_requires) - if self.distribution.tests_require: - self.distribution.fetch_build_eggs(self.distribution.tests_require) - if self.client: - self.run_client() - elif self.server: - self.run_server() - - def run_server(self): - # We import here to ensure that our setuptools parent has had a chance to - # edit the Python system path. - from tests.interop import server - sys.argv[1:] = self.args.split() - server.serve() - - def run_client(self): - # We import here to ensure that our setuptools parent has had a chance to - # edit the Python system path. - from tests.interop import client - sys.argv[1:] = self.args.split() - client.test_interoperability() + description = 'run interop test client/server' + user_options = [('args=', 'a', 'pass-thru arguments for the client/server'), + ('client', 'c', 'flag indicating to run the client'), + ('server', 's', 'flag indicating to run the server')] + + def initialize_options(self): + self.args = '' + self.client = False + self.server = False + + def finalize_options(self): + if self.client and self.server: + raise DistutilsOptionError( + 'you may only specify one of client or server') + + def run(self): + if self.distribution.install_requires: + self.distribution.fetch_build_eggs( + self.distribution.install_requires) + if self.distribution.tests_require: + self.distribution.fetch_build_eggs(self.distribution.tests_require) + if self.client: + self.run_client() + elif self.server: + self.run_server() + + def run_server(self): + # We import here to ensure that our setuptools parent has had a chance to + # edit the Python system path. + from tests.interop import server + sys.argv[1:] = self.args.split() + server.serve() + + def run_client(self): + # We import here to ensure that our setuptools parent has had a chance to + # edit the Python system path. + from tests.interop import client + sys.argv[1:] = self.args.split() + client.test_interoperability() diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py index 375fbd6c77d..f0407d1a557 100644 --- a/src/python/grpcio_tests/setup.py +++ b/src/python/grpcio_tests/setup.py @@ -26,7 +26,6 @@ # 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. - """A setup module for the gRPC Python package.""" import os @@ -48,9 +47,7 @@ import grpc_version LICENSE = '3-clause BSD' -PACKAGE_DIRECTORIES = { - '': '.', -} +PACKAGE_DIRECTORIES = {'': '.',} INSTALL_REQUIRES = ( 'coverage>=4.0', @@ -61,13 +58,11 @@ INSTALL_REQUIRES = ( 'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION), 'oauth2client>=1.4.7', 'protobuf>=3.0.0', - 'six>=1.10', -) + 'six>=1.10',) COMMAND_CLASS = { # Run `preprocess` *before* doing any packaging! 'preprocess': commands.GatherProto, - 'build_package_protos': grpc_tools.command.BuildPackageProtos, 'build_py': commands.BuildPy, 'run_interop': commands.RunInterop, @@ -80,9 +75,7 @@ PACKAGE_DATA = { 'credentials/server1.key', 'credentials/server1.pem', ], - 'tests.protoc_plugin.protos.invocation_testing': [ - 'same.proto', - ], + 'tests.protoc_plugin.protos.invocation_testing': ['same.proto',], 'tests.protoc_plugin.protos.invocation_testing.split_messages': [ 'messages.proto', ], @@ -94,9 +87,7 @@ PACKAGE_DATA = { 'credentials/server1.key', 'credentials/server1.pem', ], - 'tests': [ - 'tests.json' - ], + 'tests': ['tests.json'], } TEST_SUITE = 'tests' @@ -107,16 +98,15 @@ TESTS_REQUIRE = INSTALL_REQUIRES PACKAGES = setuptools.find_packages('.') setuptools.setup( - name='grpcio-tests', - version=grpc_version.VERSION, - license=LICENSE, - packages=list(PACKAGES), - package_dir=PACKAGE_DIRECTORIES, - package_data=PACKAGE_DATA, - install_requires=INSTALL_REQUIRES, - cmdclass=COMMAND_CLASS, - tests_require=TESTS_REQUIRE, - test_suite=TEST_SUITE, - test_loader=TEST_LOADER, - test_runner=TEST_RUNNER, -) + name='grpcio-tests', + version=grpc_version.VERSION, + license=LICENSE, + packages=list(PACKAGES), + package_dir=PACKAGE_DIRECTORIES, + package_data=PACKAGE_DATA, + install_requires=INSTALL_REQUIRES, + cmdclass=COMMAND_CLASS, + tests_require=TESTS_REQUIRE, + test_suite=TEST_SUITE, + test_loader=TEST_LOADER, + test_runner=TEST_RUNNER,) diff --git a/src/python/grpcio_tests/tests/_loader.py b/src/python/grpcio_tests/tests/_loader.py index 621bedc7bb8..42cf9ab4cac 100644 --- a/src/python/grpcio_tests/tests/_loader.py +++ b/src/python/grpcio_tests/tests/_loader.py @@ -40,7 +40,7 @@ TEST_MODULE_REGEX = r'^.*_test$' class Loader(object): - """Test loader for setuptools test suite support. + """Test loader for setuptools test suite support. Attributes: suite (unittest.TestSuite): All tests collected by the loader. @@ -51,57 +51,57 @@ class Loader(object): contributes to the test suite. """ - def __init__(self): - self.suite = unittest.TestSuite() - self.loader = unittest.TestLoader() - self.module_matcher = re.compile(TEST_MODULE_REGEX) + def __init__(self): + self.suite = unittest.TestSuite() + self.loader = unittest.TestLoader() + self.module_matcher = re.compile(TEST_MODULE_REGEX) - def loadTestsFromNames(self, names, module=None): - """Function mirroring TestLoader::loadTestsFromNames, as expected by + def loadTestsFromNames(self, names, module=None): + """Function mirroring TestLoader::loadTestsFromNames, as expected by setuptools.setup argument `test_loader`.""" - # ensure that we capture decorators and definitions (else our coverage - # measure unnecessarily suffers) - coverage_context = coverage.Coverage(data_suffix=True) - coverage_context.start() - modules = [importlib.import_module(name) for name in names] - for module in modules: - self.visit_module(module) - for module in modules: - try: - package_paths = module.__path__ - except: - continue - self.walk_packages(package_paths) - coverage_context.stop() - coverage_context.save() - return self.suite - - def walk_packages(self, package_paths): - """Walks over the packages, dispatching `visit_module` calls. + # ensure that we capture decorators and definitions (else our coverage + # measure unnecessarily suffers) + coverage_context = coverage.Coverage(data_suffix=True) + coverage_context.start() + modules = [importlib.import_module(name) for name in names] + for module in modules: + self.visit_module(module) + for module in modules: + try: + package_paths = module.__path__ + except: + continue + self.walk_packages(package_paths) + coverage_context.stop() + coverage_context.save() + return self.suite + + def walk_packages(self, package_paths): + """Walks over the packages, dispatching `visit_module` calls. Args: package_paths (list): A list of paths over which to walk through modules along. """ - for importer, module_name, is_package in ( - pkgutil.walk_packages(package_paths)): - module = importer.find_module(module_name).load_module(module_name) - self.visit_module(module) + for importer, module_name, is_package in ( + pkgutil.walk_packages(package_paths)): + module = importer.find_module(module_name).load_module(module_name) + self.visit_module(module) - def visit_module(self, module): - """Visits the module, adding discovered tests to the test suite. + def visit_module(self, module): + """Visits the module, adding discovered tests to the test suite. Args: module (module): Module to match against self.module_matcher; if matched it has its tests loaded via self.loader into self.suite. """ - if self.module_matcher.match(module.__name__): - module_suite = self.loader.loadTestsFromModule(module) - self.suite.addTest(module_suite) + if self.module_matcher.match(module.__name__): + module_suite = self.loader.loadTestsFromModule(module) + self.suite.addTest(module_suite) def iterate_suite_cases(suite): - """Generator over all unittest.TestCases in a unittest.TestSuite. + """Generator over all unittest.TestCases in a unittest.TestSuite. Args: suite (unittest.TestSuite): Suite to iterate over in the generator. @@ -109,11 +109,12 @@ def iterate_suite_cases(suite): Returns: generator: A generator over all unittest.TestCases in `suite`. """ - for item in suite: - if isinstance(item, unittest.TestSuite): - for child_item in iterate_suite_cases(item): - yield child_item - elif isinstance(item, unittest.TestCase): - yield item - else: - raise ValueError('unexpected suite item of type {}'.format(type(item))) + for item in suite: + if isinstance(item, unittest.TestSuite): + for child_item in iterate_suite_cases(item): + yield child_item + elif isinstance(item, unittest.TestCase): + yield item + else: + raise ValueError('unexpected suite item of type {}'.format( + type(item))) diff --git a/src/python/grpcio_tests/tests/_result.py b/src/python/grpcio_tests/tests/_result.py index 1acec6a9b59..794b7540f14 100644 --- a/src/python/grpcio_tests/tests/_result.py +++ b/src/python/grpcio_tests/tests/_result.py @@ -41,9 +41,11 @@ from six import moves from tests import _loader -class CaseResult(collections.namedtuple('CaseResult', [ - 'id', 'name', 'kind', 'stdout', 'stderr', 'skip_reason', 'traceback'])): - """A serializable result of a single test case. +class CaseResult( + collections.namedtuple('CaseResult', [ + 'id', 'name', 'kind', 'stdout', 'stderr', 'skip_reason', 'traceback' + ])): + """A serializable result of a single test case. Attributes: id (object): Any serializable object used to denote the identity of this @@ -59,62 +61,78 @@ class CaseResult(collections.namedtuple('CaseResult', [ None. """ - class Kind: - UNTESTED = 'untested' - RUNNING = 'running' - ERROR = 'error' - FAILURE = 'failure' - SUCCESS = 'success' - SKIP = 'skip' - EXPECTED_FAILURE = 'expected failure' - UNEXPECTED_SUCCESS = 'unexpected success' - - def __new__(cls, id=None, name=None, kind=None, stdout=None, stderr=None, - skip_reason=None, traceback=None): - """Helper keyword constructor for the namedtuple. + class Kind: + UNTESTED = 'untested' + RUNNING = 'running' + ERROR = 'error' + FAILURE = 'failure' + SUCCESS = 'success' + SKIP = 'skip' + EXPECTED_FAILURE = 'expected failure' + UNEXPECTED_SUCCESS = 'unexpected success' + + def __new__(cls, + id=None, + name=None, + kind=None, + stdout=None, + stderr=None, + skip_reason=None, + traceback=None): + """Helper keyword constructor for the namedtuple. See this class' attributes for information on the arguments.""" - assert id is not None - assert name is None or isinstance(name, str) - if kind is CaseResult.Kind.UNTESTED: - pass - elif kind is CaseResult.Kind.RUNNING: - pass - elif kind is CaseResult.Kind.ERROR: - assert traceback is not None - elif kind is CaseResult.Kind.FAILURE: - assert traceback is not None - elif kind is CaseResult.Kind.SUCCESS: - pass - elif kind is CaseResult.Kind.SKIP: - assert skip_reason is not None - elif kind is CaseResult.Kind.EXPECTED_FAILURE: - assert traceback is not None - elif kind is CaseResult.Kind.UNEXPECTED_SUCCESS: - pass - else: - assert False - return super(cls, CaseResult).__new__( - cls, id, name, kind, stdout, stderr, skip_reason, traceback) - - def updated(self, name=None, kind=None, stdout=None, stderr=None, - skip_reason=None, traceback=None): - """Get a new validated CaseResult with the fields updated. + assert id is not None + assert name is None or isinstance(name, str) + if kind is CaseResult.Kind.UNTESTED: + pass + elif kind is CaseResult.Kind.RUNNING: + pass + elif kind is CaseResult.Kind.ERROR: + assert traceback is not None + elif kind is CaseResult.Kind.FAILURE: + assert traceback is not None + elif kind is CaseResult.Kind.SUCCESS: + pass + elif kind is CaseResult.Kind.SKIP: + assert skip_reason is not None + elif kind is CaseResult.Kind.EXPECTED_FAILURE: + assert traceback is not None + elif kind is CaseResult.Kind.UNEXPECTED_SUCCESS: + pass + else: + assert False + return super(cls, CaseResult).__new__(cls, id, name, kind, stdout, + stderr, skip_reason, traceback) + + def updated(self, + name=None, + kind=None, + stdout=None, + stderr=None, + skip_reason=None, + traceback=None): + """Get a new validated CaseResult with the fields updated. See this class' attributes for information on the arguments.""" - name = self.name if name is None else name - kind = self.kind if kind is None else kind - stdout = self.stdout if stdout is None else stdout - stderr = self.stderr if stderr is None else stderr - skip_reason = self.skip_reason if skip_reason is None else skip_reason - traceback = self.traceback if traceback is None else traceback - return CaseResult(id=self.id, name=name, kind=kind, stdout=stdout, - stderr=stderr, skip_reason=skip_reason, - traceback=traceback) + name = self.name if name is None else name + kind = self.kind if kind is None else kind + stdout = self.stdout if stdout is None else stdout + stderr = self.stderr if stderr is None else stderr + skip_reason = self.skip_reason if skip_reason is None else skip_reason + traceback = self.traceback if traceback is None else traceback + return CaseResult( + id=self.id, + name=name, + kind=kind, + stdout=stdout, + stderr=stderr, + skip_reason=skip_reason, + traceback=traceback) class AugmentedResult(unittest.TestResult): - """unittest.Result that keeps track of additional information. + """unittest.Result that keeps track of additional information. Uses CaseResult objects to store test-case results, providing additional information beyond that of the standard Python unittest library, such as @@ -127,228 +145,215 @@ class AugmentedResult(unittest.TestResult): to CaseResult objects corresponding to those IDs. """ - def __init__(self, id_map): - """Initialize the object with an identifier mapping. + def __init__(self, id_map): + """Initialize the object with an identifier mapping. Arguments: id_map (callable): Corresponds to the attribute `id_map`.""" - super(AugmentedResult, self).__init__() - self.id_map = id_map - self.cases = None - - def startTestRun(self): - """See unittest.TestResult.startTestRun.""" - super(AugmentedResult, self).startTestRun() - self.cases = dict() - - def stopTestRun(self): - """See unittest.TestResult.stopTestRun.""" - super(AugmentedResult, self).stopTestRun() - - def startTest(self, test): - """See unittest.TestResult.startTest.""" - super(AugmentedResult, self).startTest(test) - case_id = self.id_map(test) - self.cases[case_id] = CaseResult( - id=case_id, name=test.id(), kind=CaseResult.Kind.RUNNING) - - def addError(self, test, error): - """See unittest.TestResult.addError.""" - super(AugmentedResult, self).addError(test, error) - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - kind=CaseResult.Kind.ERROR, traceback=error) - - def addFailure(self, test, error): - """See unittest.TestResult.addFailure.""" - super(AugmentedResult, self).addFailure(test, error) - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - kind=CaseResult.Kind.FAILURE, traceback=error) - - def addSuccess(self, test): - """See unittest.TestResult.addSuccess.""" - super(AugmentedResult, self).addSuccess(test) - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - kind=CaseResult.Kind.SUCCESS) - - def addSkip(self, test, reason): - """See unittest.TestResult.addSkip.""" - super(AugmentedResult, self).addSkip(test, reason) - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - kind=CaseResult.Kind.SKIP, skip_reason=reason) - - def addExpectedFailure(self, test, error): - """See unittest.TestResult.addExpectedFailure.""" - super(AugmentedResult, self).addExpectedFailure(test, error) - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - kind=CaseResult.Kind.EXPECTED_FAILURE, traceback=error) - - def addUnexpectedSuccess(self, test): - """See unittest.TestResult.addUnexpectedSuccess.""" - super(AugmentedResult, self).addUnexpectedSuccess(test) - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - kind=CaseResult.Kind.UNEXPECTED_SUCCESS) - - def set_output(self, test, stdout, stderr): - """Set the output attributes for the CaseResult corresponding to a test. + super(AugmentedResult, self).__init__() + self.id_map = id_map + self.cases = None + + def startTestRun(self): + """See unittest.TestResult.startTestRun.""" + super(AugmentedResult, self).startTestRun() + self.cases = dict() + + def stopTestRun(self): + """See unittest.TestResult.stopTestRun.""" + super(AugmentedResult, self).stopTestRun() + + def startTest(self, test): + """See unittest.TestResult.startTest.""" + super(AugmentedResult, self).startTest(test) + case_id = self.id_map(test) + self.cases[case_id] = CaseResult( + id=case_id, name=test.id(), kind=CaseResult.Kind.RUNNING) + + def addError(self, test, error): + """See unittest.TestResult.addError.""" + super(AugmentedResult, self).addError(test, error) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + kind=CaseResult.Kind.ERROR, traceback=error) + + def addFailure(self, test, error): + """See unittest.TestResult.addFailure.""" + super(AugmentedResult, self).addFailure(test, error) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + kind=CaseResult.Kind.FAILURE, traceback=error) + + def addSuccess(self, test): + """See unittest.TestResult.addSuccess.""" + super(AugmentedResult, self).addSuccess(test) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + kind=CaseResult.Kind.SUCCESS) + + def addSkip(self, test, reason): + """See unittest.TestResult.addSkip.""" + super(AugmentedResult, self).addSkip(test, reason) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + kind=CaseResult.Kind.SKIP, skip_reason=reason) + + def addExpectedFailure(self, test, error): + """See unittest.TestResult.addExpectedFailure.""" + super(AugmentedResult, self).addExpectedFailure(test, error) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + kind=CaseResult.Kind.EXPECTED_FAILURE, traceback=error) + + def addUnexpectedSuccess(self, test): + """See unittest.TestResult.addUnexpectedSuccess.""" + super(AugmentedResult, self).addUnexpectedSuccess(test) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + kind=CaseResult.Kind.UNEXPECTED_SUCCESS) + + def set_output(self, test, stdout, stderr): + """Set the output attributes for the CaseResult corresponding to a test. Args: test (unittest.TestCase): The TestCase to set the outputs of. stdout (str): Output from stdout to assign to self.id_map(test). stderr (str): Output from stderr to assign to self.id_map(test). """ - case_id = self.id_map(test) - self.cases[case_id] = self.cases[case_id].updated( - stdout=stdout.decode(), stderr=stderr.decode()) + case_id = self.id_map(test) + self.cases[case_id] = self.cases[case_id].updated( + stdout=stdout.decode(), stderr=stderr.decode()) - def augmented_results(self, filter): - """Convenience method to retrieve filtered case results. + def augmented_results(self, filter): + """Convenience method to retrieve filtered case results. Args: filter (callable): A unary predicate to filter over CaseResult objects. """ - return (self.cases[case_id] for case_id in self.cases - if filter(self.cases[case_id])) + return (self.cases[case_id] for case_id in self.cases + if filter(self.cases[case_id])) class CoverageResult(AugmentedResult): - """Extension to AugmentedResult adding coverage.py support per test.\ + """Extension to AugmentedResult adding coverage.py support per test.\ Attributes: coverage_context (coverage.Coverage): coverage.py management object. """ - def __init__(self, id_map): - """See AugmentedResult.__init__.""" - super(CoverageResult, self).__init__(id_map=id_map) - self.coverage_context = None + def __init__(self, id_map): + """See AugmentedResult.__init__.""" + super(CoverageResult, self).__init__(id_map=id_map) + self.coverage_context = None - def startTest(self, test): - """See unittest.TestResult.startTest. + def startTest(self, test): + """See unittest.TestResult.startTest. Additionally initializes and begins code coverage tracking.""" - super(CoverageResult, self).startTest(test) - self.coverage_context = coverage.Coverage(data_suffix=True) - self.coverage_context.start() + super(CoverageResult, self).startTest(test) + self.coverage_context = coverage.Coverage(data_suffix=True) + self.coverage_context.start() - def stopTest(self, test): - """See unittest.TestResult.stopTest. + def stopTest(self, test): + """See unittest.TestResult.stopTest. Additionally stops and deinitializes code coverage tracking.""" - super(CoverageResult, self).stopTest(test) - self.coverage_context.stop() - self.coverage_context.save() - self.coverage_context = None + super(CoverageResult, self).stopTest(test) + self.coverage_context.stop() + self.coverage_context.save() + self.coverage_context = None - def stopTestRun(self): - """See unittest.TestResult.stopTestRun.""" - super(CoverageResult, self).stopTestRun() - # TODO(atash): Dig deeper into why the following line fails to properly - # combine coverage data from the Cython plugin. - #coverage.Coverage().combine() + def stopTestRun(self): + """See unittest.TestResult.stopTestRun.""" + super(CoverageResult, self).stopTestRun() + # TODO(atash): Dig deeper into why the following line fails to properly + # combine coverage data from the Cython plugin. + #coverage.Coverage().combine() class _Colors: - """Namespaced constants for terminal color magic numbers.""" - HEADER = '\033[95m' - INFO = '\033[94m' - OK = '\033[92m' - WARN = '\033[93m' - FAIL = '\033[91m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - END = '\033[0m' + """Namespaced constants for terminal color magic numbers.""" + HEADER = '\033[95m' + INFO = '\033[94m' + OK = '\033[92m' + WARN = '\033[93m' + FAIL = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + END = '\033[0m' class TerminalResult(CoverageResult): - """Extension to CoverageResult adding basic terminal reporting.""" + """Extension to CoverageResult adding basic terminal reporting.""" - def __init__(self, out, id_map): - """Initialize the result object. + def __init__(self, out, id_map): + """Initialize the result object. Args: out (file-like): Output file to which terminal-colored live results will be written. id_map (callable): See AugmentedResult.__init__. """ - super(TerminalResult, self).__init__(id_map=id_map) - self.out = out - - def startTestRun(self): - """See unittest.TestResult.startTestRun.""" - super(TerminalResult, self).startTestRun() - self.out.write( - _Colors.HEADER + - 'Testing gRPC Python...\n' + - _Colors.END) - - def stopTestRun(self): - """See unittest.TestResult.stopTestRun.""" - super(TerminalResult, self).stopTestRun() - self.out.write(summary(self)) - self.out.flush() - - def addError(self, test, error): - """See unittest.TestResult.addError.""" - super(TerminalResult, self).addError(test, error) - self.out.write( - _Colors.FAIL + - 'ERROR {}\n'.format(test.id()) + - _Colors.END) - self.out.flush() - - def addFailure(self, test, error): - """See unittest.TestResult.addFailure.""" - super(TerminalResult, self).addFailure(test, error) - self.out.write( - _Colors.FAIL + - 'FAILURE {}\n'.format(test.id()) + - _Colors.END) - self.out.flush() - - def addSuccess(self, test): - """See unittest.TestResult.addSuccess.""" - super(TerminalResult, self).addSuccess(test) - self.out.write( - _Colors.OK + - 'SUCCESS {}\n'.format(test.id()) + - _Colors.END) - self.out.flush() - - def addSkip(self, test, reason): - """See unittest.TestResult.addSkip.""" - super(TerminalResult, self).addSkip(test, reason) - self.out.write( - _Colors.INFO + - 'SKIP {}\n'.format(test.id()) + - _Colors.END) - self.out.flush() - - def addExpectedFailure(self, test, error): - """See unittest.TestResult.addExpectedFailure.""" - super(TerminalResult, self).addExpectedFailure(test, error) - self.out.write( - _Colors.INFO + - 'FAILURE_OK {}\n'.format(test.id()) + - _Colors.END) - self.out.flush() - - def addUnexpectedSuccess(self, test): - """See unittest.TestResult.addUnexpectedSuccess.""" - super(TerminalResult, self).addUnexpectedSuccess(test) - self.out.write( - _Colors.INFO + - 'UNEXPECTED_OK {}\n'.format(test.id()) + - _Colors.END) - self.out.flush() + super(TerminalResult, self).__init__(id_map=id_map) + self.out = out + + def startTestRun(self): + """See unittest.TestResult.startTestRun.""" + super(TerminalResult, self).startTestRun() + self.out.write(_Colors.HEADER + 'Testing gRPC Python...\n' + + _Colors.END) + + def stopTestRun(self): + """See unittest.TestResult.stopTestRun.""" + super(TerminalResult, self).stopTestRun() + self.out.write(summary(self)) + self.out.flush() + + def addError(self, test, error): + """See unittest.TestResult.addError.""" + super(TerminalResult, self).addError(test, error) + self.out.write(_Colors.FAIL + 'ERROR {}\n'.format(test.id()) + + _Colors.END) + self.out.flush() + + def addFailure(self, test, error): + """See unittest.TestResult.addFailure.""" + super(TerminalResult, self).addFailure(test, error) + self.out.write(_Colors.FAIL + 'FAILURE {}\n'.format(test.id()) + + _Colors.END) + self.out.flush() + + def addSuccess(self, test): + """See unittest.TestResult.addSuccess.""" + super(TerminalResult, self).addSuccess(test) + self.out.write(_Colors.OK + 'SUCCESS {}\n'.format(test.id()) + + _Colors.END) + self.out.flush() + + def addSkip(self, test, reason): + """See unittest.TestResult.addSkip.""" + super(TerminalResult, self).addSkip(test, reason) + self.out.write(_Colors.INFO + 'SKIP {}\n'.format(test.id()) + + _Colors.END) + self.out.flush() + + def addExpectedFailure(self, test, error): + """See unittest.TestResult.addExpectedFailure.""" + super(TerminalResult, self).addExpectedFailure(test, error) + self.out.write(_Colors.INFO + 'FAILURE_OK {}\n'.format(test.id()) + + _Colors.END) + self.out.flush() + + def addUnexpectedSuccess(self, test): + """See unittest.TestResult.addUnexpectedSuccess.""" + super(TerminalResult, self).addUnexpectedSuccess(test) + self.out.write(_Colors.INFO + 'UNEXPECTED_OK {}\n'.format(test.id()) + + _Colors.END) + self.out.flush() + def _traceback_string(type, value, trace): - """Generate a descriptive string of a Python exception traceback. + """Generate a descriptive string of a Python exception traceback. Args: type (class): The type of the exception. @@ -358,12 +363,13 @@ def _traceback_string(type, value, trace): Returns: str: Formatted exception descriptive string. """ - buffer = moves.cStringIO() - traceback.print_exception(type, value, trace, file=buffer) - return buffer.getvalue() + buffer = moves.cStringIO() + traceback.print_exception(type, value, trace, file=buffer) + return buffer.getvalue() + def summary(result): - """A summary string of a result object. + """A summary string of a result object. Args: result (AugmentedResult): The result object to get the summary of. @@ -371,62 +377,68 @@ def summary(result): Returns: str: The summary string. """ - assert isinstance(result, AugmentedResult) - untested = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.UNTESTED)) - running = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.RUNNING)) - failures = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.FAILURE)) - errors = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.ERROR)) - successes = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.SUCCESS)) - skips = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.SKIP)) - expected_failures = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.EXPECTED_FAILURE)) - unexpected_successes = list(result.augmented_results( - lambda case_result: case_result.kind is CaseResult.Kind.UNEXPECTED_SUCCESS)) - running_names = [case.name for case in running] - finished_count = (len(failures) + len(errors) + len(successes) + - len(expected_failures) + len(unexpected_successes)) - statistics = ( - '{finished} tests finished:\n' - '\t{successful} successful\n' - '\t{unsuccessful} unsuccessful\n' - '\t{skipped} skipped\n' - '\t{expected_fail} expected failures\n' - '\t{unexpected_successful} unexpected successes\n' - 'Interrupted Tests:\n' - '\t{interrupted}\n' - .format(finished=finished_count, - successful=len(successes), - unsuccessful=(len(failures)+len(errors)), - skipped=len(skips), - expected_fail=len(expected_failures), - unexpected_successful=len(unexpected_successes), - interrupted=str(running_names))) - tracebacks = '\n\n'.join([ - (_Colors.FAIL + '{test_name}' + _Colors.END + '\n' + - _Colors.BOLD + 'traceback:' + _Colors.END + '\n' + - '{traceback}\n' + - _Colors.BOLD + 'stdout:' + _Colors.END + '\n' + - '{stdout}\n' + - _Colors.BOLD + 'stderr:' + _Colors.END + '\n' + - '{stderr}\n').format( - test_name=result.name, - traceback=_traceback_string(*result.traceback), - stdout=result.stdout, stderr=result.stderr) - for result in itertools.chain(failures, errors) - ]) - notes = 'Unexpected successes: {}\n'.format([ - result.name for result in unexpected_successes]) - return statistics + '\nErrors/Failures: \n' + tracebacks + '\n' + notes + assert isinstance(result, AugmentedResult) + untested = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.UNTESTED)) + running = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.RUNNING)) + failures = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.FAILURE)) + errors = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.ERROR)) + successes = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.SUCCESS)) + skips = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.SKIP)) + expected_failures = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.EXPECTED_FAILURE + )) + unexpected_successes = list( + result.augmented_results( + lambda case_result: case_result.kind is CaseResult.Kind.UNEXPECTED_SUCCESS + )) + running_names = [case.name for case in running] + finished_count = (len(failures) + len(errors) + len(successes) + + len(expected_failures) + len(unexpected_successes)) + statistics = ('{finished} tests finished:\n' + '\t{successful} successful\n' + '\t{unsuccessful} unsuccessful\n' + '\t{skipped} skipped\n' + '\t{expected_fail} expected failures\n' + '\t{unexpected_successful} unexpected successes\n' + 'Interrupted Tests:\n' + '\t{interrupted}\n'.format( + finished=finished_count, + successful=len(successes), + unsuccessful=(len(failures) + len(errors)), + skipped=len(skips), + expected_fail=len(expected_failures), + unexpected_successful=len(unexpected_successes), + interrupted=str(running_names))) + tracebacks = '\n\n'.join( + [(_Colors.FAIL + '{test_name}' + _Colors.END + '\n' + _Colors.BOLD + + 'traceback:' + _Colors.END + '\n' + '{traceback}\n' + _Colors.BOLD + + 'stdout:' + _Colors.END + '\n' + '{stdout}\n' + _Colors.BOLD + + 'stderr:' + _Colors.END + '\n' + '{stderr}\n').format( + test_name=result.name, + traceback=_traceback_string(*result.traceback), + stdout=result.stdout, + stderr=result.stderr) + for result in itertools.chain(failures, errors)]) + notes = 'Unexpected successes: {}\n'.format( + [result.name for result in unexpected_successes]) + return statistics + '\nErrors/Failures: \n' + tracebacks + '\n' + notes def jenkins_junit_xml(result): - """An XML tree object that when written is recognizable by Jenkins. + """An XML tree object that when written is recognizable by Jenkins. Args: result (AugmentedResult): The result object to get the junit xml output of. @@ -434,20 +446,18 @@ def jenkins_junit_xml(result): Returns: ElementTree.ElementTree: The XML tree. """ - assert isinstance(result, AugmentedResult) - root = ElementTree.Element('testsuites') - suite = ElementTree.SubElement(root, 'testsuite', { - 'name': 'Python gRPC tests', - }) - for case in result.cases.values(): - if case.kind is CaseResult.Kind.SUCCESS: - ElementTree.SubElement(suite, 'testcase', { - 'name': case.name, - }) - elif case.kind in (CaseResult.Kind.ERROR, CaseResult.Kind.FAILURE): - case_xml = ElementTree.SubElement(suite, 'testcase', { - 'name': case.name, - }) - error_xml = ElementTree.SubElement(case_xml, 'error', {}) - error_xml.text = ''.format(case.stderr, case.traceback) - return ElementTree.ElementTree(element=root) + assert isinstance(result, AugmentedResult) + root = ElementTree.Element('testsuites') + suite = ElementTree.SubElement(root, 'testsuite', { + 'name': 'Python gRPC tests', + }) + for case in result.cases.values(): + if case.kind is CaseResult.Kind.SUCCESS: + ElementTree.SubElement(suite, 'testcase', {'name': case.name,}) + elif case.kind in (CaseResult.Kind.ERROR, CaseResult.Kind.FAILURE): + case_xml = ElementTree.SubElement(suite, 'testcase', { + 'name': case.name, + }) + error_xml = ElementTree.SubElement(case_xml, 'error', {}) + error_xml.text = ''.format(case.stderr, case.traceback) + return ElementTree.ElementTree(element=root) diff --git a/src/python/grpcio_tests/tests/_runner.py b/src/python/grpcio_tests/tests/_runner.py index 926dcbe23a1..59964b271c7 100644 --- a/src/python/grpcio_tests/tests/_runner.py +++ b/src/python/grpcio_tests/tests/_runner.py @@ -49,7 +49,7 @@ from tests import _result class CaptureFile(object): - """A context-managed file to redirect output to a byte array. + """A context-managed file to redirect output to a byte array. Use by invoking `start` (`__enter__`) and at some point invoking `stop` (`__exit__`). At any point after the initial call to `start` call `output` to @@ -66,57 +66,56 @@ class CaptureFile(object): Only non-None when self is started. """ - def __init__(self, fd): - self._redirected_fd = fd - self._saved_fd = os.dup(self._redirected_fd) - self._into_file = None + def __init__(self, fd): + self._redirected_fd = fd + self._saved_fd = os.dup(self._redirected_fd) + self._into_file = None - def output(self): - """Get all output from the redirected-to file if it exists.""" - if self._into_file: - self._into_file.seek(0) - return bytes(self._into_file.read()) - else: - return bytes() + def output(self): + """Get all output from the redirected-to file if it exists.""" + if self._into_file: + self._into_file.seek(0) + return bytes(self._into_file.read()) + else: + return bytes() - def start(self): - """Start redirection of writes to the file descriptor.""" - self._into_file = tempfile.TemporaryFile() - os.dup2(self._into_file.fileno(), self._redirected_fd) + def start(self): + """Start redirection of writes to the file descriptor.""" + self._into_file = tempfile.TemporaryFile() + os.dup2(self._into_file.fileno(), self._redirected_fd) - def stop(self): - """Stop redirection of writes to the file descriptor.""" - # n.b. this dup2 call auto-closes self._redirected_fd - os.dup2(self._saved_fd, self._redirected_fd) + def stop(self): + """Stop redirection of writes to the file descriptor.""" + # n.b. this dup2 call auto-closes self._redirected_fd + os.dup2(self._saved_fd, self._redirected_fd) - def write_bypass(self, value): - """Bypass the redirection and write directly to the original file. + def write_bypass(self, value): + """Bypass the redirection and write directly to the original file. Arguments: value (str): What to write to the original file. """ - if six.PY3 and not isinstance(value, six.binary_type): - value = bytes(value, 'ascii') - if self._saved_fd is None: - os.write(self._redirect_fd, value) - else: - os.write(self._saved_fd, value) + if six.PY3 and not isinstance(value, six.binary_type): + value = bytes(value, 'ascii') + if self._saved_fd is None: + os.write(self._redirect_fd, value) + else: + os.write(self._saved_fd, value) - def __enter__(self): - self.start() - return self + def __enter__(self): + self.start() + return self - def __exit__(self, type, value, traceback): - self.stop() + def __exit__(self, type, value, traceback): + self.stop() - def close(self): - """Close any resources used by self not closed by stop().""" - os.close(self._saved_fd) + def close(self): + """Close any resources used by self not closed by stop().""" + os.close(self._saved_fd) -class AugmentedCase(collections.namedtuple('AugmentedCase', [ - 'case', 'id'])): - """A test case with a guaranteed unique externally specified identifier. +class AugmentedCase(collections.namedtuple('AugmentedCase', ['case', 'id'])): + """A test case with a guaranteed unique externally specified identifier. Attributes: case (unittest.TestCase): TestCase we're decorating with an additional @@ -125,105 +124,107 @@ class AugmentedCase(collections.namedtuple('AugmentedCase', [ purposes. """ - def __new__(cls, case, id=None): - if id is None: - id = uuid.uuid4() - return super(cls, AugmentedCase).__new__(cls, case, id) + def __new__(cls, case, id=None): + if id is None: + id = uuid.uuid4() + return super(cls, AugmentedCase).__new__(cls, case, id) class Runner(object): - def run(self, suite): - """See setuptools' test_runner setup argument for information.""" - # only run test cases with id starting with given prefix - testcase_filter = os.getenv('GRPC_PYTHON_TESTRUNNER_FILTER') - filtered_cases = [] - for case in _loader.iterate_suite_cases(suite): - if not testcase_filter or case.id().startswith(testcase_filter): - filtered_cases.append(case) - - # Ensure that every test case has no collision with any other test case in - # the augmented results. - augmented_cases = [AugmentedCase(case, uuid.uuid4()) - for case in filtered_cases] - case_id_by_case = dict((augmented_case.case, augmented_case.id) - for augmented_case in augmented_cases) - result_out = moves.cStringIO() - result = _result.TerminalResult( - result_out, id_map=lambda case: case_id_by_case[case]) - stdout_pipe = CaptureFile(sys.stdout.fileno()) - stderr_pipe = CaptureFile(sys.stderr.fileno()) - kill_flag = [False] - - def sigint_handler(signal_number, frame): - if signal_number == signal.SIGINT: - kill_flag[0] = True # Python 2.7 not having 'local'... :-( - signal.signal(signal_number, signal.SIG_DFL) - - def fault_handler(signal_number, frame): - stdout_pipe.write_bypass( - 'Received fault signal {}\nstdout:\n{}\n\nstderr:{}\n' - .format(signal_number, stdout_pipe.output(), - stderr_pipe.output())) - os._exit(1) - - def check_kill_self(): - if kill_flag[0]: - stdout_pipe.write_bypass('Stopping tests short...') - result.stopTestRun() - stdout_pipe.write_bypass(result_out.getvalue()) - stdout_pipe.write_bypass( - '\ninterrupted stdout:\n{}\n'.format(stdout_pipe.output().decode())) - stderr_pipe.write_bypass( - '\ninterrupted stderr:\n{}\n'.format(stderr_pipe.output().decode())) - os._exit(1) - def try_set_handler(name, handler): - try: - signal.signal(getattr(signal, name), handler) - except AttributeError: - pass - try_set_handler('SIGINT', sigint_handler) - try_set_handler('SIGSEGV', fault_handler) - try_set_handler('SIGBUS', fault_handler) - try_set_handler('SIGABRT', fault_handler) - try_set_handler('SIGFPE', fault_handler) - try_set_handler('SIGILL', fault_handler) - # Sometimes output will lag after a test has successfully finished; we - # ignore such writes to our pipes. - try_set_handler('SIGPIPE', signal.SIG_IGN) - - # Run the tests - result.startTestRun() - for augmented_case in augmented_cases: - sys.stdout.write('Running {}\n'.format(augmented_case.case.id())) - sys.stdout.flush() - case_thread = threading.Thread( - target=augmented_case.case.run, args=(result,)) - try: - with stdout_pipe, stderr_pipe: - case_thread.start() - while case_thread.is_alive(): + def run(self, suite): + """See setuptools' test_runner setup argument for information.""" + # only run test cases with id starting with given prefix + testcase_filter = os.getenv('GRPC_PYTHON_TESTRUNNER_FILTER') + filtered_cases = [] + for case in _loader.iterate_suite_cases(suite): + if not testcase_filter or case.id().startswith(testcase_filter): + filtered_cases.append(case) + + # Ensure that every test case has no collision with any other test case in + # the augmented results. + augmented_cases = [ + AugmentedCase(case, uuid.uuid4()) for case in filtered_cases + ] + case_id_by_case = dict((augmented_case.case, augmented_case.id) + for augmented_case in augmented_cases) + result_out = moves.cStringIO() + result = _result.TerminalResult( + result_out, id_map=lambda case: case_id_by_case[case]) + stdout_pipe = CaptureFile(sys.stdout.fileno()) + stderr_pipe = CaptureFile(sys.stderr.fileno()) + kill_flag = [False] + + def sigint_handler(signal_number, frame): + if signal_number == signal.SIGINT: + kill_flag[0] = True # Python 2.7 not having 'local'... :-( + signal.signal(signal_number, signal.SIG_DFL) + + def fault_handler(signal_number, frame): + stdout_pipe.write_bypass( + 'Received fault signal {}\nstdout:\n{}\n\nstderr:{}\n'.format( + signal_number, stdout_pipe.output(), stderr_pipe.output())) + os._exit(1) + + def check_kill_self(): + if kill_flag[0]: + stdout_pipe.write_bypass('Stopping tests short...') + result.stopTestRun() + stdout_pipe.write_bypass(result_out.getvalue()) + stdout_pipe.write_bypass('\ninterrupted stdout:\n{}\n'.format( + stdout_pipe.output().decode())) + stderr_pipe.write_bypass('\ninterrupted stderr:\n{}\n'.format( + stderr_pipe.output().decode())) + os._exit(1) + + def try_set_handler(name, handler): + try: + signal.signal(getattr(signal, name), handler) + except AttributeError: + pass + + try_set_handler('SIGINT', sigint_handler) + try_set_handler('SIGSEGV', fault_handler) + try_set_handler('SIGBUS', fault_handler) + try_set_handler('SIGABRT', fault_handler) + try_set_handler('SIGFPE', fault_handler) + try_set_handler('SIGILL', fault_handler) + # Sometimes output will lag after a test has successfully finished; we + # ignore such writes to our pipes. + try_set_handler('SIGPIPE', signal.SIG_IGN) + + # Run the tests + result.startTestRun() + for augmented_case in augmented_cases: + sys.stdout.write('Running {}\n'.format(augmented_case.case.id( + ))) + sys.stdout.flush() + case_thread = threading.Thread( + target=augmented_case.case.run, args=(result,)) + try: + with stdout_pipe, stderr_pipe: + case_thread.start() + while case_thread.is_alive(): + check_kill_self() + time.sleep(0) + case_thread.join() + except: + # re-raise the exception after forcing the with-block to end + raise + result.set_output(augmented_case.case, + stdout_pipe.output(), stderr_pipe.output()) + sys.stdout.write(result_out.getvalue()) + sys.stdout.flush() + result_out.truncate(0) check_kill_self() - time.sleep(0) - case_thread.join() - except: - # re-raise the exception after forcing the with-block to end - raise - result.set_output( - augmented_case.case, stdout_pipe.output(), stderr_pipe.output()) - sys.stdout.write(result_out.getvalue()) - sys.stdout.flush() - result_out.truncate(0) - check_kill_self() - result.stopTestRun() - stdout_pipe.close() - stderr_pipe.close() - - # Report results - sys.stdout.write(result_out.getvalue()) - sys.stdout.flush() - signal.signal(signal.SIGINT, signal.SIG_DFL) - with open('report.xml', 'wb') as report_xml_file: - _result.jenkins_junit_xml(result).write(report_xml_file) - return result - + result.stopTestRun() + stdout_pipe.close() + stderr_pipe.close() + + # Report results + sys.stdout.write(result_out.getvalue()) + sys.stdout.flush() + signal.signal(signal.SIGINT, signal.SIG_DFL) + with open('report.xml', 'wb') as report_xml_file: + _result.jenkins_junit_xml(result).write(report_xml_file) + return result diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py index 5dde72b1698..363b4c5f994 100644 --- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py +++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of grpc_health.v1.health.""" import unittest @@ -41,55 +40,55 @@ from tests.unit.framework.common import test_constants class HealthServicerTest(unittest.TestCase): - def setUp(self): - servicer = health.HealthServicer() - servicer.set('', health_pb2.HealthCheckResponse.SERVING) - servicer.set('grpc.test.TestServiceServing', - health_pb2.HealthCheckResponse.SERVING) - servicer.set('grpc.test.TestServiceUnknown', - health_pb2.HealthCheckResponse.UNKNOWN) - servicer.set('grpc.test.TestServiceNotServing', - health_pb2.HealthCheckResponse.NOT_SERVING) - server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server(server_pool) - port = self._server.add_insecure_port('[::]:0') - health_pb2.add_HealthServicer_to_server(servicer, self._server) - self._server.start() + def setUp(self): + servicer = health.HealthServicer() + servicer.set('', health_pb2.HealthCheckResponse.SERVING) + servicer.set('grpc.test.TestServiceServing', + health_pb2.HealthCheckResponse.SERVING) + servicer.set('grpc.test.TestServiceUnknown', + health_pb2.HealthCheckResponse.UNKNOWN) + servicer.set('grpc.test.TestServiceNotServing', + health_pb2.HealthCheckResponse.NOT_SERVING) + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server(server_pool) + port = self._server.add_insecure_port('[::]:0') + health_pb2.add_HealthServicer_to_server(servicer, self._server) + self._server.start() + + channel = grpc.insecure_channel('localhost:%d' % port) + self._stub = health_pb2.HealthStub(channel) - channel = grpc.insecure_channel('localhost:%d' % port) - self._stub = health_pb2.HealthStub(channel) + def test_empty_service(self): + request = health_pb2.HealthCheckRequest() + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) - def test_empty_service(self): - request = health_pb2.HealthCheckRequest() - resp = self._stub.Check(request) - self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) + def test_serving_service(self): + request = health_pb2.HealthCheckRequest( + service='grpc.test.TestServiceServing') + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) - def test_serving_service(self): - request = health_pb2.HealthCheckRequest( - service='grpc.test.TestServiceServing') - resp = self._stub.Check(request) - self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status) + def test_unknown_serivce(self): + request = health_pb2.HealthCheckRequest( + service='grpc.test.TestServiceUnknown') + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status) - def test_unknown_serivce(self): - request = health_pb2.HealthCheckRequest( - service='grpc.test.TestServiceUnknown') - resp = self._stub.Check(request) - self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status) + def test_not_serving_service(self): + request = health_pb2.HealthCheckRequest( + service='grpc.test.TestServiceNotServing') + resp = self._stub.Check(request) + self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, + resp.status) - def test_not_serving_service(self): - request = health_pb2.HealthCheckRequest( - service='grpc.test.TestServiceNotServing') - resp = self._stub.Check(request) - self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING, resp.status) + def test_not_found_service(self): + request = health_pb2.HealthCheckRequest(service='not-found') + with self.assertRaises(grpc.RpcError) as context: + resp = self._stub.Check(request) - def test_not_found_service(self): - request = health_pb2.HealthCheckRequest( - service='not-found') - with self.assertRaises(grpc.RpcError) as context: - resp = self._stub.Check(request) - - self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code()) + self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code()) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/http2/_negative_http2_client.py b/src/python/grpcio_tests/tests/http2/_negative_http2_client.py index f8604683b3a..c192d827c40 100644 --- a/src/python/grpcio_tests/tests/http2/_negative_http2_client.py +++ b/src/python/grpcio_tests/tests/http2/_negative_http2_client.py @@ -26,7 +26,6 @@ # 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. - """The Python client used to test negative http2 conditions.""" import argparse @@ -35,29 +34,32 @@ import grpc from src.proto.grpc.testing import test_pb2 from src.proto.grpc.testing import messages_pb2 + def _validate_payload_type_and_length(response, expected_type, expected_length): - if response.payload.type is not expected_type: - raise ValueError( - 'expected payload type %s, got %s' % - (expected_type, type(response.payload.type))) - elif len(response.payload.body) != expected_length: - raise ValueError( - 'expected payload body size %d, got %d' % - (expected_length, len(response.payload.body))) + if response.payload.type is not expected_type: + raise ValueError('expected payload type %s, got %s' % + (expected_type, type(response.payload.type))) + elif len(response.payload.body) != expected_length: + raise ValueError('expected payload body size %d, got %d' % + (expected_length, len(response.payload.body))) + def _expect_status_code(call, expected_code): - if call.code() != expected_code: - raise ValueError( - 'expected code %s, got %s' % (expected_code, call.code())) + if call.code() != expected_code: + raise ValueError('expected code %s, got %s' % + (expected_code, call.code())) + def _expect_status_details(call, expected_details): - if call.details() != expected_details: - raise ValueError( - 'expected message %s, got %s' % (expected_details, call.details())) + if call.details() != expected_details: + raise ValueError('expected message %s, got %s' % + (expected_details, call.details())) + def _validate_status_code_and_details(call, expected_code, expected_details): - _expect_status_code(call, expected_code) - _expect_status_details(call, expected_details) + _expect_status_code(call, expected_code) + _expect_status_details(call, expected_details) + # common requests _REQUEST_SIZE = 314159 @@ -68,86 +70,103 @@ _SIMPLE_REQUEST = messages_pb2.SimpleRequest( response_size=_RESPONSE_SIZE, payload=messages_pb2.Payload(body=b'\x00' * _REQUEST_SIZE)) + def _goaway(stub): - first_response = stub.UnaryCall(_SIMPLE_REQUEST) - _validate_payload_type_and_length(first_response, - messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) - second_response = stub.UnaryCall(_SIMPLE_REQUEST) - _validate_payload_type_and_length(second_response, - messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) + first_response = stub.UnaryCall(_SIMPLE_REQUEST) + _validate_payload_type_and_length(first_response, messages_pb2.COMPRESSABLE, + _RESPONSE_SIZE) + second_response = stub.UnaryCall(_SIMPLE_REQUEST) + _validate_payload_type_and_length(second_response, + messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) + def _rst_after_header(stub): - resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) - _validate_status_code_and_details(resp_future, grpc.StatusCode.UNAVAILABLE, "") + resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) + _validate_status_code_and_details(resp_future, grpc.StatusCode.UNAVAILABLE, + "") + def _rst_during_data(stub): - resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) - _validate_status_code_and_details(resp_future, grpc.StatusCode.UNKNOWN, "") + resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) + _validate_status_code_and_details(resp_future, grpc.StatusCode.UNKNOWN, "") + def _rst_after_data(stub): - resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) - _validate_payload_type_and_length(next(resp_future), - messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) - _validate_status_code_and_details(resp_future, grpc.StatusCode.UNKNOWN, "") + resp_future = stub.UnaryCall.future(_SIMPLE_REQUEST) + _validate_payload_type_and_length( + next(resp_future), messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) + _validate_status_code_and_details(resp_future, grpc.StatusCode.UNKNOWN, "") + def _ping(stub): - response = stub.UnaryCall(_SIMPLE_REQUEST) - _validate_payload_type_and_length(response, - messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) + response = stub.UnaryCall(_SIMPLE_REQUEST) + _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, + _RESPONSE_SIZE) + def _max_streams(stub): - # send one req to ensure server sets MAX_STREAMS - response = stub.UnaryCall(_SIMPLE_REQUEST) - _validate_payload_type_and_length(response, - messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) - - # give the streams a workout - futures = [] - for _ in range(15): - futures.append(stub.UnaryCall.future(_SIMPLE_REQUEST)) - for future in futures: - _validate_payload_type_and_length(future.result(), - messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) + # send one req to ensure server sets MAX_STREAMS + response = stub.UnaryCall(_SIMPLE_REQUEST) + _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, + _RESPONSE_SIZE) + + # give the streams a workout + futures = [] + for _ in range(15): + futures.append(stub.UnaryCall.future(_SIMPLE_REQUEST)) + for future in futures: + _validate_payload_type_and_length( + future.result(), messages_pb2.COMPRESSABLE, _RESPONSE_SIZE) + def _run_test_case(test_case, stub): - if test_case == 'goaway': - _goaway(stub) - elif test_case == 'rst_after_header': - _rst_after_header(stub) - elif test_case == 'rst_during_data': - _rst_during_data(stub) - elif test_case == 'rst_after_data': - _rst_after_data(stub) - elif test_case =='ping': - _ping(stub) - elif test_case == 'max_streams': - _max_streams(stub) - else: - raise ValueError("Invalid test case: %s" % test_case) + if test_case == 'goaway': + _goaway(stub) + elif test_case == 'rst_after_header': + _rst_after_header(stub) + elif test_case == 'rst_during_data': + _rst_during_data(stub) + elif test_case == 'rst_after_data': + _rst_after_data(stub) + elif test_case == 'ping': + _ping(stub) + elif test_case == 'max_streams': + _max_streams(stub) + else: + raise ValueError("Invalid test case: %s" % test_case) + def _args(): - parser = argparse.ArgumentParser() - parser.add_argument( - '--server_host', help='the host to which to connect', type=str, - default="127.0.0.1") - parser.add_argument( - '--server_port', help='the port to which to connect', type=int, - default="8080") - parser.add_argument( - '--test_case', help='the test case to execute', type=str, - default="goaway") - return parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument( + '--server_host', + help='the host to which to connect', + type=str, + default="127.0.0.1") + parser.add_argument( + '--server_port', + help='the port to which to connect', + type=int, + default="8080") + parser.add_argument( + '--test_case', + help='the test case to execute', + type=str, + default="goaway") + return parser.parse_args() + def _stub(server_host, server_port): - target = '{}:{}'.format(server_host, server_port) - channel = grpc.insecure_channel(target) - return test_pb2.TestServiceStub(channel) + target = '{}:{}'.format(server_host, server_port) + channel = grpc.insecure_channel(target) + return test_pb2.TestServiceStub(channel) + def main(): - args = _args() - stub = _stub(args.server_host, args.server_port) - _run_test_case(args.test_case, stub) + args = _args() + stub = _stub(args.server_host, args.server_port) + _run_test_case(args.test_case, stub) if __name__ == '__main__': - main() + main() diff --git a/src/python/grpcio_tests/tests/interop/__init__.py b/src/python/grpcio_tests/tests/interop/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/interop/__init__.py +++ b/src/python/grpcio_tests/tests/interop/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py index 4fb22b4d9df..58f3b364bad 100644 --- a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py +++ b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py @@ -26,7 +26,6 @@ # 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. - """Insecure client-server interoperability as a unit test.""" from concurrent import futures @@ -40,19 +39,18 @@ from tests.interop import methods from tests.interop import server -class InsecureIntraopTest( - _intraop_test_case.IntraopTestCase, - unittest.TestCase): +class InsecureIntraopTest(_intraop_test_case.IntraopTestCase, + unittest.TestCase): - def setUp(self): - self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - test_pb2.add_TestServiceServicer_to_server( - methods.TestService(), self.server) - port = self.server.add_insecure_port('[::]:0') - self.server.start() - self.stub = test_pb2.TestServiceStub( - grpc.insecure_channel('localhost:{}'.format(port))) + def setUp(self): + self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + test_pb2.add_TestServiceServicer_to_server(methods.TestService(), + self.server) + port = self.server.add_insecure_port('[::]:0') + self.server.start() + self.stub = test_pb2.TestServiceStub( + grpc.insecure_channel('localhost:{}'.format(port))) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/interop/_intraop_test_case.py b/src/python/grpcio_tests/tests/interop/_intraop_test_case.py index fe1c1739929..424f93980cf 100644 --- a/src/python/grpcio_tests/tests/interop/_intraop_test_case.py +++ b/src/python/grpcio_tests/tests/interop/_intraop_test_case.py @@ -26,39 +26,41 @@ # 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. - """Common code for unit tests of the interoperability test code.""" from tests.interop import methods class IntraopTestCase(object): - """Unit test methods. + """Unit test methods. This class must be mixed in with unittest.TestCase and a class that defines setUp and tearDown methods that manage a stub attribute. """ - def testEmptyUnary(self): - methods.TestCase.EMPTY_UNARY.test_interoperability(self.stub, None) + def testEmptyUnary(self): + methods.TestCase.EMPTY_UNARY.test_interoperability(self.stub, None) - def testLargeUnary(self): - methods.TestCase.LARGE_UNARY.test_interoperability(self.stub, None) + def testLargeUnary(self): + methods.TestCase.LARGE_UNARY.test_interoperability(self.stub, None) - def testServerStreaming(self): - methods.TestCase.SERVER_STREAMING.test_interoperability(self.stub, None) + def testServerStreaming(self): + methods.TestCase.SERVER_STREAMING.test_interoperability(self.stub, None) - def testClientStreaming(self): - methods.TestCase.CLIENT_STREAMING.test_interoperability(self.stub, None) + def testClientStreaming(self): + methods.TestCase.CLIENT_STREAMING.test_interoperability(self.stub, None) - def testPingPong(self): - methods.TestCase.PING_PONG.test_interoperability(self.stub, None) + def testPingPong(self): + methods.TestCase.PING_PONG.test_interoperability(self.stub, None) - def testCancelAfterBegin(self): - methods.TestCase.CANCEL_AFTER_BEGIN.test_interoperability(self.stub, None) + def testCancelAfterBegin(self): + methods.TestCase.CANCEL_AFTER_BEGIN.test_interoperability(self.stub, + None) - def testCancelAfterFirstResponse(self): - methods.TestCase.CANCEL_AFTER_FIRST_RESPONSE.test_interoperability(self.stub, None) + def testCancelAfterFirstResponse(self): + methods.TestCase.CANCEL_AFTER_FIRST_RESPONSE.test_interoperability( + self.stub, None) - def testTimeoutOnSleepingServer(self): - methods.TestCase.TIMEOUT_ON_SLEEPING_SERVER.test_interoperability(self.stub, None) + def testTimeoutOnSleepingServer(self): + methods.TestCase.TIMEOUT_ON_SLEEPING_SERVER.test_interoperability( + self.stub, None) diff --git a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py index 3665c69726c..b28406ed3ff 100644 --- a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py +++ b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py @@ -26,7 +26,6 @@ # 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. - """Secure client-server interoperability as a unit test.""" from concurrent import futures @@ -42,24 +41,24 @@ from tests.interop import resources _SERVER_HOST_OVERRIDE = 'foo.test.google.fr' -class SecureIntraopTest( - _intraop_test_case.IntraopTestCase, - unittest.TestCase): +class SecureIntraopTest(_intraop_test_case.IntraopTestCase, unittest.TestCase): - def setUp(self): - self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - test_pb2.add_TestServiceServicer_to_server( - methods.TestService(), self.server) - port = self.server.add_secure_port( - '[::]:0', grpc.ssl_server_credentials( - [(resources.private_key(), resources.certificate_chain())])) - self.server.start() - self.stub = test_pb2.TestServiceStub( - grpc.secure_channel( - 'localhost:{}'.format(port), - grpc.ssl_channel_credentials(resources.test_root_certificates()), - (('grpc.ssl_target_name_override', _SERVER_HOST_OVERRIDE,),))) + def setUp(self): + self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + test_pb2.add_TestServiceServicer_to_server(methods.TestService(), + self.server) + port = self.server.add_secure_port( + '[::]:0', + grpc.ssl_server_credentials( + [(resources.private_key(), resources.certificate_chain())])) + self.server.start() + self.stub = test_pb2.TestServiceStub( + grpc.secure_channel('localhost:{}'.format(port), + grpc.ssl_channel_credentials( + resources.test_root_certificates()), (( + 'grpc.ssl_target_name_override', + _SERVER_HOST_OVERRIDE,),))) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py index afaa4662541..f177896e8e6 100644 --- a/src/python/grpcio_tests/tests/interop/client.py +++ b/src/python/grpcio_tests/tests/interop/client.py @@ -26,7 +26,6 @@ # 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. - """The Python implementation of the GRPC interoperability test client.""" import argparse @@ -41,93 +40,107 @@ from tests.interop import resources def _args(): - parser = argparse.ArgumentParser() - parser.add_argument( - '--server_host', help='the host to which to connect', type=str, - default="127.0.0.1") - parser.add_argument( - '--server_port', help='the port to which to connect', type=int) - parser.add_argument( - '--test_case', help='the test case to execute', type=str, - default="large_unary") - parser.add_argument( - '--use_tls', help='require a secure connection', default=False, - type=resources.parse_bool) - parser.add_argument( - '--use_test_ca', help='replace platform root CAs with ca.pem', - default=False, type=resources.parse_bool) - parser.add_argument( - '--server_host_override', default="foo.test.google.fr", - help='the server host to which to claim to connect', type=str) - parser.add_argument('--oauth_scope', help='scope for OAuth tokens', type=str) - parser.add_argument( - '--default_service_account', - help='email address of the default service account', type=str) - return parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument( + '--server_host', + help='the host to which to connect', + type=str, + default="127.0.0.1") + parser.add_argument( + '--server_port', help='the port to which to connect', type=int) + parser.add_argument( + '--test_case', + help='the test case to execute', + type=str, + default="large_unary") + parser.add_argument( + '--use_tls', + help='require a secure connection', + default=False, + type=resources.parse_bool) + parser.add_argument( + '--use_test_ca', + help='replace platform root CAs with ca.pem', + default=False, + type=resources.parse_bool) + parser.add_argument( + '--server_host_override', + default="foo.test.google.fr", + help='the server host to which to claim to connect', + type=str) + parser.add_argument( + '--oauth_scope', help='scope for OAuth tokens', type=str) + parser.add_argument( + '--default_service_account', + help='email address of the default service account', + type=str) + return parser.parse_args() def _application_default_credentials(): - return oauth2client_client.GoogleCredentials.get_application_default() + return oauth2client_client.GoogleCredentials.get_application_default() def _stub(args): - target = '{}:{}'.format(args.server_host, args.server_port) - if args.test_case == 'oauth2_auth_token': - google_credentials = _application_default_credentials() - scoped_credentials = google_credentials.create_scoped([args.oauth_scope]) - access_token = scoped_credentials.get_access_token().access_token - call_credentials = grpc.access_token_call_credentials(access_token) - elif args.test_case == 'compute_engine_creds': - google_credentials = _application_default_credentials() - scoped_credentials = google_credentials.create_scoped([args.oauth_scope]) - # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last - # remaining use of the Beta API. - call_credentials = implementations.google_call_credentials( - scoped_credentials) - elif args.test_case == 'jwt_token_creds': - google_credentials = _application_default_credentials() - # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last - # remaining use of the Beta API. - call_credentials = implementations.google_call_credentials( - google_credentials) - else: - call_credentials = None - if args.use_tls: - if args.use_test_ca: - root_certificates = resources.test_root_certificates() + target = '{}:{}'.format(args.server_host, args.server_port) + if args.test_case == 'oauth2_auth_token': + google_credentials = _application_default_credentials() + scoped_credentials = google_credentials.create_scoped( + [args.oauth_scope]) + access_token = scoped_credentials.get_access_token().access_token + call_credentials = grpc.access_token_call_credentials(access_token) + elif args.test_case == 'compute_engine_creds': + google_credentials = _application_default_credentials() + scoped_credentials = google_credentials.create_scoped( + [args.oauth_scope]) + # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last + # remaining use of the Beta API. + call_credentials = implementations.google_call_credentials( + scoped_credentials) + elif args.test_case == 'jwt_token_creds': + google_credentials = _application_default_credentials() + # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last + # remaining use of the Beta API. + call_credentials = implementations.google_call_credentials( + google_credentials) else: - root_certificates = None # will load default roots. - - channel_credentials = grpc.ssl_channel_credentials(root_certificates) - if call_credentials is not None: - channel_credentials = grpc.composite_channel_credentials( - channel_credentials, call_credentials) - - channel = grpc.secure_channel( - target, channel_credentials, - (('grpc.ssl_target_name_override', args.server_host_override,),)) - else: - channel = grpc.insecure_channel(target) - if args.test_case == "unimplemented_service": - return test_pb2.UnimplementedServiceStub(channel) - else: - return test_pb2.TestServiceStub(channel) + call_credentials = None + if args.use_tls: + if args.use_test_ca: + root_certificates = resources.test_root_certificates() + else: + root_certificates = None # will load default roots. + + channel_credentials = grpc.ssl_channel_credentials(root_certificates) + if call_credentials is not None: + channel_credentials = grpc.composite_channel_credentials( + channel_credentials, call_credentials) + + channel = grpc.secure_channel(target, channel_credentials, (( + 'grpc.ssl_target_name_override', + args.server_host_override,),)) + else: + channel = grpc.insecure_channel(target) + if args.test_case == "unimplemented_service": + return test_pb2.UnimplementedServiceStub(channel) + else: + return test_pb2.TestServiceStub(channel) def _test_case_from_arg(test_case_arg): - for test_case in methods.TestCase: - if test_case_arg == test_case.value: - return test_case - else: - raise ValueError('No test case "%s"!' % test_case_arg) + for test_case in methods.TestCase: + if test_case_arg == test_case.value: + return test_case + else: + raise ValueError('No test case "%s"!' % test_case_arg) def test_interoperability(): - args = _args() - stub = _stub(args) - test_case = _test_case_from_arg(args.test_case) - test_case.test_interoperability(stub, args) + args = _args() + stub = _stub(args) + test_case = _test_case_from_arg(args.test_case) + test_case.test_interoperability(stub, args) if __name__ == '__main__': - test_interoperability() + test_interoperability() diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py index 9038ae57515..e1f87221686 100644 --- a/src/python/grpcio_tests/tests/interop/methods.py +++ b/src/python/grpcio_tests/tests/interop/methods.py @@ -26,7 +26,6 @@ # 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. - """Implementations of interoperability test methods.""" import enum @@ -46,463 +45,483 @@ from src.proto.grpc.testing import test_pb2 _INITIAL_METADATA_KEY = "x-grpc-test-echo-initial" _TRAILING_METADATA_KEY = "x-grpc-test-echo-trailing-bin" + def _maybe_echo_metadata(servicer_context): - """Copies metadata from request to response if it is present.""" - invocation_metadata = dict(servicer_context.invocation_metadata()) - if _INITIAL_METADATA_KEY in invocation_metadata: - initial_metadatum = ( - _INITIAL_METADATA_KEY, invocation_metadata[_INITIAL_METADATA_KEY]) - servicer_context.send_initial_metadata((initial_metadatum,)) - if _TRAILING_METADATA_KEY in invocation_metadata: - trailing_metadatum = ( - _TRAILING_METADATA_KEY, invocation_metadata[_TRAILING_METADATA_KEY]) - servicer_context.set_trailing_metadata((trailing_metadatum,)) + """Copies metadata from request to response if it is present.""" + invocation_metadata = dict(servicer_context.invocation_metadata()) + if _INITIAL_METADATA_KEY in invocation_metadata: + initial_metadatum = (_INITIAL_METADATA_KEY, + invocation_metadata[_INITIAL_METADATA_KEY]) + servicer_context.send_initial_metadata((initial_metadatum,)) + if _TRAILING_METADATA_KEY in invocation_metadata: + trailing_metadatum = (_TRAILING_METADATA_KEY, + invocation_metadata[_TRAILING_METADATA_KEY]) + servicer_context.set_trailing_metadata((trailing_metadatum,)) + def _maybe_echo_status_and_message(request, servicer_context): - """Sets the response context code and details if the request asks for them""" - if request.HasField('response_status'): - servicer_context.set_code(request.response_status.code) - servicer_context.set_details(request.response_status.message) + """Sets the response context code and details if the request asks for them""" + if request.HasField('response_status'): + servicer_context.set_code(request.response_status.code) + servicer_context.set_details(request.response_status.message) + class TestService(test_pb2.TestServiceServicer): - def EmptyCall(self, request, context): - _maybe_echo_metadata(context) - return empty_pb2.Empty() + def EmptyCall(self, request, context): + _maybe_echo_metadata(context) + return empty_pb2.Empty() - def UnaryCall(self, request, context): - _maybe_echo_metadata(context) - _maybe_echo_status_and_message(request, context) - return messages_pb2.SimpleResponse( - payload=messages_pb2.Payload( + def UnaryCall(self, request, context): + _maybe_echo_metadata(context) + _maybe_echo_status_and_message(request, context) + return messages_pb2.SimpleResponse(payload=messages_pb2.Payload( type=messages_pb2.COMPRESSABLE, body=b'\x00' * request.response_size)) - def StreamingOutputCall(self, request, context): - _maybe_echo_status_and_message(request, context) - for response_parameters in request.response_parameters: - yield messages_pb2.StreamingOutputCallResponse( - payload=messages_pb2.Payload( - type=request.response_type, - body=b'\x00' * response_parameters.size)) - - def StreamingInputCall(self, request_iterator, context): - aggregate_size = 0 - for request in request_iterator: - if request.payload is not None and request.payload.body: - aggregate_size += len(request.payload.body) - return messages_pb2.StreamingInputCallResponse( - aggregated_payload_size=aggregate_size) - - def FullDuplexCall(self, request_iterator, context): - _maybe_echo_metadata(context) - for request in request_iterator: - _maybe_echo_status_and_message(request, context) - for response_parameters in request.response_parameters: - yield messages_pb2.StreamingOutputCallResponse( - payload=messages_pb2.Payload( - type=request.payload.type, - body=b'\x00' * response_parameters.size)) - - # NOTE(nathaniel): Apparently this is the same as the full-duplex call? - # NOTE(atash): It isn't even called in the interop spec (Oct 22 2015)... - def HalfDuplexCall(self, request_iterator, context): - return self.FullDuplexCall(request_iterator, context) + def StreamingOutputCall(self, request, context): + _maybe_echo_status_and_message(request, context) + for response_parameters in request.response_parameters: + yield messages_pb2.StreamingOutputCallResponse( + payload=messages_pb2.Payload( + type=request.response_type, + body=b'\x00' * response_parameters.size)) + + def StreamingInputCall(self, request_iterator, context): + aggregate_size = 0 + for request in request_iterator: + if request.payload is not None and request.payload.body: + aggregate_size += len(request.payload.body) + return messages_pb2.StreamingInputCallResponse( + aggregated_payload_size=aggregate_size) + + def FullDuplexCall(self, request_iterator, context): + _maybe_echo_metadata(context) + for request in request_iterator: + _maybe_echo_status_and_message(request, context) + for response_parameters in request.response_parameters: + yield messages_pb2.StreamingOutputCallResponse( + payload=messages_pb2.Payload( + type=request.payload.type, + body=b'\x00' * response_parameters.size)) + + # NOTE(nathaniel): Apparently this is the same as the full-duplex call? + # NOTE(atash): It isn't even called in the interop spec (Oct 22 2015)... + def HalfDuplexCall(self, request_iterator, context): + return self.FullDuplexCall(request_iterator, context) def _expect_status_code(call, expected_code): - if call.code() != expected_code: - raise ValueError( - 'expected code %s, got %s' % (expected_code, call.code())) + if call.code() != expected_code: + raise ValueError('expected code %s, got %s' % + (expected_code, call.code())) def _expect_status_details(call, expected_details): - if call.details() != expected_details: - raise ValueError( - 'expected message %s, got %s' % (expected_details, call.details())) + if call.details() != expected_details: + raise ValueError('expected message %s, got %s' % + (expected_details, call.details())) def _validate_status_code_and_details(call, expected_code, expected_details): - _expect_status_code(call, expected_code) - _expect_status_details(call, expected_details) + _expect_status_code(call, expected_code) + _expect_status_details(call, expected_details) def _validate_payload_type_and_length(response, expected_type, expected_length): - if response.payload.type is not expected_type: - raise ValueError( - 'expected payload type %s, got %s' % - (expected_type, type(response.payload.type))) - elif len(response.payload.body) != expected_length: - raise ValueError( - 'expected payload body size %d, got %d' % - (expected_length, len(response.payload.body))) - - -def _large_unary_common_behavior( - stub, fill_username, fill_oauth_scope, call_credentials): - size = 314159 - request = messages_pb2.SimpleRequest( - response_type=messages_pb2.COMPRESSABLE, response_size=size, - payload=messages_pb2.Payload(body=b'\x00' * 271828), - fill_username=fill_username, fill_oauth_scope=fill_oauth_scope) - response_future = stub.UnaryCall.future( - request, credentials=call_credentials) - response = response_future.result() - _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, size) - return response + if response.payload.type is not expected_type: + raise ValueError('expected payload type %s, got %s' % + (expected_type, type(response.payload.type))) + elif len(response.payload.body) != expected_length: + raise ValueError('expected payload body size %d, got %d' % + (expected_length, len(response.payload.body))) + + +def _large_unary_common_behavior(stub, fill_username, fill_oauth_scope, + call_credentials): + size = 314159 + request = messages_pb2.SimpleRequest( + response_type=messages_pb2.COMPRESSABLE, + response_size=size, + payload=messages_pb2.Payload(body=b'\x00' * 271828), + fill_username=fill_username, + fill_oauth_scope=fill_oauth_scope) + response_future = stub.UnaryCall.future( + request, credentials=call_credentials) + response = response_future.result() + _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, size) + return response def _empty_unary(stub): - response = stub.EmptyCall(empty_pb2.Empty()) - if not isinstance(response, empty_pb2.Empty): - raise TypeError( - 'response is of type "%s", not empty_pb2.Empty!', type(response)) + response = stub.EmptyCall(empty_pb2.Empty()) + if not isinstance(response, empty_pb2.Empty): + raise TypeError('response is of type "%s", not empty_pb2.Empty!', + type(response)) def _large_unary(stub): - _large_unary_common_behavior(stub, False, False, None) + _large_unary_common_behavior(stub, False, False, None) def _client_streaming(stub): - payload_body_sizes = (27182, 8, 1828, 45904,) - payloads = ( - messages_pb2.Payload(body=b'\x00' * size) - for size in payload_body_sizes) - requests = ( - messages_pb2.StreamingInputCallRequest(payload=payload) - for payload in payloads) - response = stub.StreamingInputCall(requests) - if response.aggregated_payload_size != 74922: - raise ValueError( - 'incorrect size %d!' % response.aggregated_payload_size) + payload_body_sizes = ( + 27182, + 8, + 1828, + 45904,) + payloads = (messages_pb2.Payload(body=b'\x00' * size) + for size in payload_body_sizes) + requests = (messages_pb2.StreamingInputCallRequest(payload=payload) + for payload in payloads) + response = stub.StreamingInputCall(requests) + if response.aggregated_payload_size != 74922: + raise ValueError('incorrect size %d!' % + response.aggregated_payload_size) def _server_streaming(stub): - sizes = (31415, 9, 2653, 58979,) - - request = messages_pb2.StreamingOutputCallRequest( - response_type=messages_pb2.COMPRESSABLE, - response_parameters=( - messages_pb2.ResponseParameters(size=sizes[0]), - messages_pb2.ResponseParameters(size=sizes[1]), - messages_pb2.ResponseParameters(size=sizes[2]), - messages_pb2.ResponseParameters(size=sizes[3]), - ) - ) - response_iterator = stub.StreamingOutputCall(request) - for index, response in enumerate(response_iterator): - _validate_payload_type_and_length( - response, messages_pb2.COMPRESSABLE, sizes[index]) + sizes = ( + 31415, + 9, + 2653, + 58979,) + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + response_parameters=( + messages_pb2.ResponseParameters(size=sizes[0]), + messages_pb2.ResponseParameters(size=sizes[1]), + messages_pb2.ResponseParameters(size=sizes[2]), + messages_pb2.ResponseParameters(size=sizes[3]),)) + response_iterator = stub.StreamingOutputCall(request) + for index, response in enumerate(response_iterator): + _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, + sizes[index]) class _Pipe(object): - def __init__(self): - self._condition = threading.Condition() - self._values = [] - self._open = True + def __init__(self): + self._condition = threading.Condition() + self._values = [] + self._open = True - def __iter__(self): - return self + def __iter__(self): + return self - def __next__(self): - return self.next() + def __next__(self): + return self.next() - def next(self): - with self._condition: - while not self._values and self._open: - self._condition.wait() - if self._values: - return self._values.pop(0) - else: - raise StopIteration() + def next(self): + with self._condition: + while not self._values and self._open: + self._condition.wait() + if self._values: + return self._values.pop(0) + else: + raise StopIteration() - def add(self, value): - with self._condition: - self._values.append(value) - self._condition.notify() + def add(self, value): + with self._condition: + self._values.append(value) + self._condition.notify() - def close(self): - with self._condition: - self._open = False - self._condition.notify() + def close(self): + with self._condition: + self._open = False + self._condition.notify() - def __enter__(self): - return self + def __enter__(self): + return self - def __exit__(self, type, value, traceback): - self.close() + def __exit__(self, type, value, traceback): + self.close() def _ping_pong(stub): - request_response_sizes = (31415, 9, 2653, 58979,) - request_payload_sizes = (27182, 8, 1828, 45904,) - - with _Pipe() as pipe: - response_iterator = stub.FullDuplexCall(pipe) - for response_size, payload_size in zip( - request_response_sizes, request_payload_sizes): - request = messages_pb2.StreamingOutputCallRequest( - response_type=messages_pb2.COMPRESSABLE, - response_parameters=( - messages_pb2.ResponseParameters(size=response_size),), - payload=messages_pb2.Payload(body=b'\x00' * payload_size)) - pipe.add(request) - response = next(response_iterator) - _validate_payload_type_and_length( - response, messages_pb2.COMPRESSABLE, response_size) + request_response_sizes = ( + 31415, + 9, + 2653, + 58979,) + request_payload_sizes = ( + 27182, + 8, + 1828, + 45904,) + + with _Pipe() as pipe: + response_iterator = stub.FullDuplexCall(pipe) + for response_size, payload_size in zip(request_response_sizes, + request_payload_sizes): + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + response_parameters=( + messages_pb2.ResponseParameters(size=response_size),), + payload=messages_pb2.Payload(body=b'\x00' * payload_size)) + pipe.add(request) + response = next(response_iterator) + _validate_payload_type_and_length( + response, messages_pb2.COMPRESSABLE, response_size) def _cancel_after_begin(stub): - with _Pipe() as pipe: - response_future = stub.StreamingInputCall.future(pipe) - response_future.cancel() - if not response_future.cancelled(): - raise ValueError('expected cancelled method to return True') - if response_future.code() is not grpc.StatusCode.CANCELLED: - raise ValueError('expected status code CANCELLED') + with _Pipe() as pipe: + response_future = stub.StreamingInputCall.future(pipe) + response_future.cancel() + if not response_future.cancelled(): + raise ValueError('expected cancelled method to return True') + if response_future.code() is not grpc.StatusCode.CANCELLED: + raise ValueError('expected status code CANCELLED') def _cancel_after_first_response(stub): - request_response_sizes = (31415, 9, 2653, 58979,) - request_payload_sizes = (27182, 8, 1828, 45904,) - with _Pipe() as pipe: - response_iterator = stub.FullDuplexCall(pipe) - - response_size = request_response_sizes[0] - payload_size = request_payload_sizes[0] - request = messages_pb2.StreamingOutputCallRequest( - response_type=messages_pb2.COMPRESSABLE, - response_parameters=( - messages_pb2.ResponseParameters(size=response_size),), - payload=messages_pb2.Payload(body=b'\x00' * payload_size)) - pipe.add(request) - response = next(response_iterator) - # We test the contents of `response` in the Ping Pong test - don't check - # them here. - response_iterator.cancel() - - try: - next(response_iterator) - except grpc.RpcError as rpc_error: - if rpc_error.code() is not grpc.StatusCode.CANCELLED: - raise - else: - raise ValueError('expected call to be cancelled') + request_response_sizes = ( + 31415, + 9, + 2653, + 58979,) + request_payload_sizes = ( + 27182, + 8, + 1828, + 45904,) + with _Pipe() as pipe: + response_iterator = stub.FullDuplexCall(pipe) + + response_size = request_response_sizes[0] + payload_size = request_payload_sizes[0] + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + response_parameters=( + messages_pb2.ResponseParameters(size=response_size),), + payload=messages_pb2.Payload(body=b'\x00' * payload_size)) + pipe.add(request) + response = next(response_iterator) + # We test the contents of `response` in the Ping Pong test - don't check + # them here. + response_iterator.cancel() + + try: + next(response_iterator) + except grpc.RpcError as rpc_error: + if rpc_error.code() is not grpc.StatusCode.CANCELLED: + raise + else: + raise ValueError('expected call to be cancelled') def _timeout_on_sleeping_server(stub): - request_payload_size = 27182 - with _Pipe() as pipe: - response_iterator = stub.FullDuplexCall(pipe, timeout=0.001) - - request = messages_pb2.StreamingOutputCallRequest( - response_type=messages_pb2.COMPRESSABLE, - payload=messages_pb2.Payload(body=b'\x00' * request_payload_size)) - pipe.add(request) - try: - next(response_iterator) - except grpc.RpcError as rpc_error: - if rpc_error.code() is not grpc.StatusCode.DEADLINE_EXCEEDED: - raise - else: - raise ValueError('expected call to exceed deadline') + request_payload_size = 27182 + with _Pipe() as pipe: + response_iterator = stub.FullDuplexCall(pipe, timeout=0.001) + + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + payload=messages_pb2.Payload(body=b'\x00' * request_payload_size)) + pipe.add(request) + try: + next(response_iterator) + except grpc.RpcError as rpc_error: + if rpc_error.code() is not grpc.StatusCode.DEADLINE_EXCEEDED: + raise + else: + raise ValueError('expected call to exceed deadline') def _empty_stream(stub): - with _Pipe() as pipe: - response_iterator = stub.FullDuplexCall(pipe) - pipe.close() - try: - next(response_iterator) - raise ValueError('expected exactly 0 responses') - except StopIteration: - pass + with _Pipe() as pipe: + response_iterator = stub.FullDuplexCall(pipe) + pipe.close() + try: + next(response_iterator) + raise ValueError('expected exactly 0 responses') + except StopIteration: + pass def _status_code_and_message(stub): - details = 'test status message' - code = 2 - status = grpc.StatusCode.UNKNOWN # code = 2 - - # Test with a UnaryCall - request = messages_pb2.SimpleRequest( - response_type=messages_pb2.COMPRESSABLE, - response_size=1, - payload=messages_pb2.Payload(body=b'\x00'), - response_status=messages_pb2.EchoStatus(code=code, message=details) - ) - response_future = stub.UnaryCall.future(request) - _validate_status_code_and_details(response_future, status, details) - - # Test with a FullDuplexCall - with _Pipe() as pipe: - response_iterator = stub.FullDuplexCall(pipe) - request = messages_pb2.StreamingOutputCallRequest( + details = 'test status message' + code = 2 + status = grpc.StatusCode.UNKNOWN # code = 2 + + # Test with a UnaryCall + request = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, - response_parameters=( - messages_pb2.ResponseParameters(size=1),), + response_size=1, payload=messages_pb2.Payload(body=b'\x00'), - response_status=messages_pb2.EchoStatus(code=code, message=details)) - pipe.add(request) # sends the initial request. - # Dropping out of with block closes the pipe - _validate_status_code_and_details(response_iterator, status, details) + response_status=messages_pb2.EchoStatus( + code=code, message=details)) + response_future = stub.UnaryCall.future(request) + _validate_status_code_and_details(response_future, status, details) + + # Test with a FullDuplexCall + with _Pipe() as pipe: + response_iterator = stub.FullDuplexCall(pipe) + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + response_parameters=(messages_pb2.ResponseParameters(size=1),), + payload=messages_pb2.Payload(body=b'\x00'), + response_status=messages_pb2.EchoStatus( + code=code, message=details)) + pipe.add(request) # sends the initial request. + # Dropping out of with block closes the pipe + _validate_status_code_and_details(response_iterator, status, details) def _unimplemented_method(test_service_stub): - response_future = ( - test_service_stub.UnimplementedCall.future(empty_pb2.Empty())) - _expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED) + response_future = ( + test_service_stub.UnimplementedCall.future(empty_pb2.Empty())) + _expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED) def _unimplemented_service(unimplemented_service_stub): - response_future = ( - unimplemented_service_stub.UnimplementedCall.future(empty_pb2.Empty())) - _expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED) + response_future = ( + unimplemented_service_stub.UnimplementedCall.future(empty_pb2.Empty())) + _expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED) def _custom_metadata(stub): - initial_metadata_value = "test_initial_metadata_value" - trailing_metadata_value = "\x0a\x0b\x0a\x0b\x0a\x0b" - metadata = ( - (_INITIAL_METADATA_KEY, initial_metadata_value), - (_TRAILING_METADATA_KEY, trailing_metadata_value)) - - def _validate_metadata(response): - initial_metadata = dict(response.initial_metadata()) - if initial_metadata[_INITIAL_METADATA_KEY] != initial_metadata_value: - raise ValueError( - 'expected initial metadata %s, got %s' % ( - initial_metadata_value, initial_metadata[_INITIAL_METADATA_KEY])) - trailing_metadata = dict(response.trailing_metadata()) - if trailing_metadata[_TRAILING_METADATA_KEY] != trailing_metadata_value: - raise ValueError( - 'expected trailing metadata %s, got %s' % ( - trailing_metadata_value, initial_metadata[_TRAILING_METADATA_KEY])) - - # Testing with UnaryCall - request = messages_pb2.SimpleRequest( - response_type=messages_pb2.COMPRESSABLE, - response_size=1, - payload=messages_pb2.Payload(body=b'\x00')) - response_future = stub.UnaryCall.future(request, metadata=metadata) - _validate_metadata(response_future) - - # Testing with FullDuplexCall - with _Pipe() as pipe: - response_iterator = stub.FullDuplexCall(pipe, metadata=metadata) - request = messages_pb2.StreamingOutputCallRequest( + initial_metadata_value = "test_initial_metadata_value" + trailing_metadata_value = "\x0a\x0b\x0a\x0b\x0a\x0b" + metadata = ((_INITIAL_METADATA_KEY, initial_metadata_value), + (_TRAILING_METADATA_KEY, trailing_metadata_value)) + + def _validate_metadata(response): + initial_metadata = dict(response.initial_metadata()) + if initial_metadata[_INITIAL_METADATA_KEY] != initial_metadata_value: + raise ValueError('expected initial metadata %s, got %s' % + (initial_metadata_value, + initial_metadata[_INITIAL_METADATA_KEY])) + trailing_metadata = dict(response.trailing_metadata()) + if trailing_metadata[_TRAILING_METADATA_KEY] != trailing_metadata_value: + raise ValueError('expected trailing metadata %s, got %s' % + (trailing_metadata_value, + initial_metadata[_TRAILING_METADATA_KEY])) + + # Testing with UnaryCall + request = messages_pb2.SimpleRequest( response_type=messages_pb2.COMPRESSABLE, - response_parameters=( - messages_pb2.ResponseParameters(size=1),)) - pipe.add(request) # Sends the request - next(response_iterator) # Causes server to send trailing metadata - # Dropping out of the with block closes the pipe - _validate_metadata(response_iterator) + response_size=1, + payload=messages_pb2.Payload(body=b'\x00')) + response_future = stub.UnaryCall.future(request, metadata=metadata) + _validate_metadata(response_future) + + # Testing with FullDuplexCall + with _Pipe() as pipe: + response_iterator = stub.FullDuplexCall(pipe, metadata=metadata) + request = messages_pb2.StreamingOutputCallRequest( + response_type=messages_pb2.COMPRESSABLE, + response_parameters=(messages_pb2.ResponseParameters(size=1),)) + pipe.add(request) # Sends the request + next(response_iterator) # Causes server to send trailing metadata + # Dropping out of the with block closes the pipe + _validate_metadata(response_iterator) + def _compute_engine_creds(stub, args): - response = _large_unary_common_behavior(stub, True, True, None) - if args.default_service_account != response.username: - raise ValueError( - 'expected username %s, got %s' % ( - args.default_service_account, response.username)) + response = _large_unary_common_behavior(stub, True, True, None) + if args.default_service_account != response.username: + raise ValueError('expected username %s, got %s' % + (args.default_service_account, response.username)) def _oauth2_auth_token(stub, args): - json_key_filename = os.environ[ - oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] - wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] - response = _large_unary_common_behavior(stub, True, True, None) - if wanted_email != response.username: - raise ValueError( - 'expected username %s, got %s' % (wanted_email, response.username)) - if args.oauth_scope.find(response.oauth_scope) == -1: - raise ValueError( - 'expected to find oauth scope "{}" in received "{}"'.format( - response.oauth_scope, args.oauth_scope)) + json_key_filename = os.environ[ + oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] + wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] + response = _large_unary_common_behavior(stub, True, True, None) + if wanted_email != response.username: + raise ValueError('expected username %s, got %s' % + (wanted_email, response.username)) + if args.oauth_scope.find(response.oauth_scope) == -1: + raise ValueError('expected to find oauth scope "{}" in received "{}"'. + format(response.oauth_scope, args.oauth_scope)) def _jwt_token_creds(stub, args): - json_key_filename = os.environ[ - oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] - wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] - response = _large_unary_common_behavior(stub, True, False, None) - if wanted_email != response.username: - raise ValueError( - 'expected username %s, got %s' % (wanted_email, response.username)) + json_key_filename = os.environ[ + oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] + wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] + response = _large_unary_common_behavior(stub, True, False, None) + if wanted_email != response.username: + raise ValueError('expected username %s, got %s' % + (wanted_email, response.username)) def _per_rpc_creds(stub, args): - json_key_filename = os.environ[ - oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] - wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] - credentials = oauth2client_client.GoogleCredentials.get_application_default() - scoped_credentials = credentials.create_scoped([args.oauth_scope]) - # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last - # remaining use of the Beta API. - call_credentials = implementations.google_call_credentials( - scoped_credentials) - response = _large_unary_common_behavior(stub, True, False, call_credentials) - if wanted_email != response.username: - raise ValueError( - 'expected username %s, got %s' % (wanted_email, response.username)) + json_key_filename = os.environ[ + oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] + wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] + credentials = oauth2client_client.GoogleCredentials.get_application_default( + ) + scoped_credentials = credentials.create_scoped([args.oauth_scope]) + # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last + # remaining use of the Beta API. + call_credentials = implementations.google_call_credentials( + scoped_credentials) + response = _large_unary_common_behavior(stub, True, False, call_credentials) + if wanted_email != response.username: + raise ValueError('expected username %s, got %s' % + (wanted_email, response.username)) @enum.unique class TestCase(enum.Enum): - EMPTY_UNARY = 'empty_unary' - LARGE_UNARY = 'large_unary' - SERVER_STREAMING = 'server_streaming' - CLIENT_STREAMING = 'client_streaming' - PING_PONG = 'ping_pong' - CANCEL_AFTER_BEGIN = 'cancel_after_begin' - CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response' - EMPTY_STREAM = 'empty_stream' - STATUS_CODE_AND_MESSAGE = 'status_code_and_message' - UNIMPLEMENTED_METHOD = 'unimplemented_method' - UNIMPLEMENTED_SERVICE = 'unimplemented_service' - CUSTOM_METADATA = "custom_metadata" - COMPUTE_ENGINE_CREDS = 'compute_engine_creds' - OAUTH2_AUTH_TOKEN = 'oauth2_auth_token' - JWT_TOKEN_CREDS = 'jwt_token_creds' - PER_RPC_CREDS = 'per_rpc_creds' - TIMEOUT_ON_SLEEPING_SERVER = 'timeout_on_sleeping_server' - - def test_interoperability(self, stub, args): - if self is TestCase.EMPTY_UNARY: - _empty_unary(stub) - elif self is TestCase.LARGE_UNARY: - _large_unary(stub) - elif self is TestCase.SERVER_STREAMING: - _server_streaming(stub) - elif self is TestCase.CLIENT_STREAMING: - _client_streaming(stub) - elif self is TestCase.PING_PONG: - _ping_pong(stub) - elif self is TestCase.CANCEL_AFTER_BEGIN: - _cancel_after_begin(stub) - elif self is TestCase.CANCEL_AFTER_FIRST_RESPONSE: - _cancel_after_first_response(stub) - elif self is TestCase.TIMEOUT_ON_SLEEPING_SERVER: - _timeout_on_sleeping_server(stub) - elif self is TestCase.EMPTY_STREAM: - _empty_stream(stub) - elif self is TestCase.STATUS_CODE_AND_MESSAGE: - _status_code_and_message(stub) - elif self is TestCase.UNIMPLEMENTED_METHOD: - _unimplemented_method(stub) - elif self is TestCase.UNIMPLEMENTED_SERVICE: - _unimplemented_service(stub) - elif self is TestCase.CUSTOM_METADATA: - _custom_metadata(stub) - elif self is TestCase.COMPUTE_ENGINE_CREDS: - _compute_engine_creds(stub, args) - elif self is TestCase.OAUTH2_AUTH_TOKEN: - _oauth2_auth_token(stub, args) - elif self is TestCase.JWT_TOKEN_CREDS: - _jwt_token_creds(stub, args) - elif self is TestCase.PER_RPC_CREDS: - _per_rpc_creds(stub, args) - else: - raise NotImplementedError('Test case "%s" not implemented!' % self.name) + EMPTY_UNARY = 'empty_unary' + LARGE_UNARY = 'large_unary' + SERVER_STREAMING = 'server_streaming' + CLIENT_STREAMING = 'client_streaming' + PING_PONG = 'ping_pong' + CANCEL_AFTER_BEGIN = 'cancel_after_begin' + CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response' + EMPTY_STREAM = 'empty_stream' + STATUS_CODE_AND_MESSAGE = 'status_code_and_message' + UNIMPLEMENTED_METHOD = 'unimplemented_method' + UNIMPLEMENTED_SERVICE = 'unimplemented_service' + CUSTOM_METADATA = "custom_metadata" + COMPUTE_ENGINE_CREDS = 'compute_engine_creds' + OAUTH2_AUTH_TOKEN = 'oauth2_auth_token' + JWT_TOKEN_CREDS = 'jwt_token_creds' + PER_RPC_CREDS = 'per_rpc_creds' + TIMEOUT_ON_SLEEPING_SERVER = 'timeout_on_sleeping_server' + + def test_interoperability(self, stub, args): + if self is TestCase.EMPTY_UNARY: + _empty_unary(stub) + elif self is TestCase.LARGE_UNARY: + _large_unary(stub) + elif self is TestCase.SERVER_STREAMING: + _server_streaming(stub) + elif self is TestCase.CLIENT_STREAMING: + _client_streaming(stub) + elif self is TestCase.PING_PONG: + _ping_pong(stub) + elif self is TestCase.CANCEL_AFTER_BEGIN: + _cancel_after_begin(stub) + elif self is TestCase.CANCEL_AFTER_FIRST_RESPONSE: + _cancel_after_first_response(stub) + elif self is TestCase.TIMEOUT_ON_SLEEPING_SERVER: + _timeout_on_sleeping_server(stub) + elif self is TestCase.EMPTY_STREAM: + _empty_stream(stub) + elif self is TestCase.STATUS_CODE_AND_MESSAGE: + _status_code_and_message(stub) + elif self is TestCase.UNIMPLEMENTED_METHOD: + _unimplemented_method(stub) + elif self is TestCase.UNIMPLEMENTED_SERVICE: + _unimplemented_service(stub) + elif self is TestCase.CUSTOM_METADATA: + _custom_metadata(stub) + elif self is TestCase.COMPUTE_ENGINE_CREDS: + _compute_engine_creds(stub, args) + elif self is TestCase.OAUTH2_AUTH_TOKEN: + _oauth2_auth_token(stub, args) + elif self is TestCase.JWT_TOKEN_CREDS: + _jwt_token_creds(stub, args) + elif self is TestCase.PER_RPC_CREDS: + _per_rpc_creds(stub, args) + else: + raise NotImplementedError('Test case "%s" not implemented!' % + self.name) diff --git a/src/python/grpcio_tests/tests/interop/resources.py b/src/python/grpcio_tests/tests/interop/resources.py index c424385cf60..2ec2eb92b4f 100644 --- a/src/python/grpcio_tests/tests/interop/resources.py +++ b/src/python/grpcio_tests/tests/interop/resources.py @@ -26,7 +26,6 @@ # 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. - """Constants and functions for data used in interoperability testing.""" import argparse @@ -40,22 +39,22 @@ _CERTIFICATE_CHAIN_RESOURCE_PATH = 'credentials/server1.pem' def test_root_certificates(): - return pkg_resources.resource_string( - __name__, _ROOT_CERTIFICATES_RESOURCE_PATH) + return pkg_resources.resource_string(__name__, + _ROOT_CERTIFICATES_RESOURCE_PATH) def private_key(): - return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) + return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) def certificate_chain(): - return pkg_resources.resource_string( - __name__, _CERTIFICATE_CHAIN_RESOURCE_PATH) + return pkg_resources.resource_string(__name__, + _CERTIFICATE_CHAIN_RESOURCE_PATH) def parse_bool(value): - if value == 'true': - return True - if value == 'false': - return False - raise argparse.ArgumentTypeError('Only true/false allowed') + if value == 'true': + return True + if value == 'false': + return False + raise argparse.ArgumentTypeError('Only true/false allowed') diff --git a/src/python/grpcio_tests/tests/interop/server.py b/src/python/grpcio_tests/tests/interop/server.py index 1ae83bc57d0..65f1604eb82 100644 --- a/src/python/grpcio_tests/tests/interop/server.py +++ b/src/python/grpcio_tests/tests/interop/server.py @@ -26,7 +26,6 @@ # 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. - """The Python implementation of the GRPC interoperability test server.""" import argparse @@ -44,34 +43,36 @@ _ONE_DAY_IN_SECONDS = 60 * 60 * 24 def serve(): - parser = argparse.ArgumentParser() - parser.add_argument( - '--port', help='the port on which to serve', type=int) - parser.add_argument( - '--use_tls', help='require a secure connection', - default=False, type=resources.parse_bool) - args = parser.parse_args() + parser = argparse.ArgumentParser() + parser.add_argument('--port', help='the port on which to serve', type=int) + parser.add_argument( + '--use_tls', + help='require a secure connection', + default=False, + type=resources.parse_bool) + args = parser.parse_args() + + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + test_pb2.add_TestServiceServicer_to_server(methods.TestService(), server) + if args.use_tls: + private_key = resources.private_key() + certificate_chain = resources.certificate_chain() + credentials = grpc.ssl_server_credentials(( + (private_key, certificate_chain),)) + server.add_secure_port('[::]:{}'.format(args.port), credentials) + else: + server.add_insecure_port('[::]:{}'.format(args.port)) - server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - test_pb2.add_TestServiceServicer_to_server(methods.TestService(), server) - if args.use_tls: - private_key = resources.private_key() - certificate_chain = resources.certificate_chain() - credentials = grpc.ssl_server_credentials( - ((private_key, certificate_chain),)) - server.add_secure_port('[::]:{}'.format(args.port), credentials) - else: - server.add_insecure_port('[::]:{}'.format(args.port)) + server.start() + logging.info('Server serving.') + try: + while True: + time.sleep(_ONE_DAY_IN_SECONDS) + except BaseException as e: + logging.info('Caught exception "%s"; stopping server...', e) + server.stop(None) + logging.info('Server stopped; exiting.') - server.start() - logging.info('Server serving.') - try: - while True: - time.sleep(_ONE_DAY_IN_SECONDS) - except BaseException as e: - logging.info('Caught exception "%s"; stopping server...', e) - server.stop(None) - logging.info('Server stopped; exiting.') if __name__ == '__main__': - serve() + serve() diff --git a/src/python/grpcio_tests/tests/protoc_plugin/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py index 7ca2bcff383..ae5da2c3dbe 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py @@ -58,436 +58,440 @@ ADD_SERVICER_TO_SERVER_IDENTIFIER = 'add_TestServiceServicer_to_server' class _ServicerMethods(object): - def __init__(self): - self._condition = threading.Condition() - self._paused = False - self._fail = False - - @contextlib.contextmanager - def pause(self): # pylint: disable=invalid-name - with self._condition: - self._paused = True - yield - with self._condition: - self._paused = False - self._condition.notify_all() - - @contextlib.contextmanager - def fail(self): # pylint: disable=invalid-name - with self._condition: - self._fail = True - yield - with self._condition: - self._fail = False - - def _control(self): # pylint: disable=invalid-name - with self._condition: - if self._fail: - raise ValueError() - while self._paused: - self._condition.wait() - - def UnaryCall(self, request, unused_rpc_context): - response = response_pb2.SimpleResponse() - response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * request.response_size - self._control() - return response - - def StreamingOutputCall(self, request, unused_rpc_context): - for parameter in request.response_parameters: - response = response_pb2.StreamingOutputCallResponse() - response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * parameter.size - self._control() - yield response - - def StreamingInputCall(self, request_iter, unused_rpc_context): - response = response_pb2.StreamingInputCallResponse() - aggregated_payload_size = 0 - for request in request_iter: - aggregated_payload_size += len(request.payload.payload_compressable) - response.aggregated_payload_size = aggregated_payload_size - self._control() - return response - - def FullDuplexCall(self, request_iter, unused_rpc_context): - for request in request_iter: - for parameter in request.response_parameters: - response = response_pb2.StreamingOutputCallResponse() - response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * parameter.size - self._control() - yield response + def __init__(self): + self._condition = threading.Condition() + self._paused = False + self._fail = False + + @contextlib.contextmanager + def pause(self): # pylint: disable=invalid-name + with self._condition: + self._paused = True + yield + with self._condition: + self._paused = False + self._condition.notify_all() - def HalfDuplexCall(self, request_iter, unused_rpc_context): - responses = [] - for request in request_iter: - for parameter in request.response_parameters: - response = response_pb2.StreamingOutputCallResponse() + @contextlib.contextmanager + def fail(self): # pylint: disable=invalid-name + with self._condition: + self._fail = True + yield + with self._condition: + self._fail = False + + def _control(self): # pylint: disable=invalid-name + with self._condition: + if self._fail: + raise ValueError() + while self._paused: + self._condition.wait() + + def UnaryCall(self, request, unused_rpc_context): + response = response_pb2.SimpleResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * parameter.size + response.payload.payload_compressable = 'a' * request.response_size + self._control() + return response + + def StreamingOutputCall(self, request, unused_rpc_context): + for parameter in request.response_parameters: + response = response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = payload_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def StreamingInputCall(self, request_iter, unused_rpc_context): + response = response_pb2.StreamingInputCallResponse() + aggregated_payload_size = 0 + for request in request_iter: + aggregated_payload_size += len(request.payload.payload_compressable) + response.aggregated_payload_size = aggregated_payload_size self._control() - responses.append(response) - for response in responses: - yield response + return response + + def FullDuplexCall(self, request_iter, unused_rpc_context): + for request in request_iter: + for parameter in request.response_parameters: + response = response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = payload_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def HalfDuplexCall(self, request_iter, unused_rpc_context): + responses = [] + for request in request_iter: + for parameter in request.response_parameters: + response = response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = payload_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + responses.append(response) + for response in responses: + yield response class _Service( - collections.namedtuple( - '_Service', ('servicer_methods', 'server', 'stub',))): - """A live and running service. + collections.namedtuple('_Service', ( + 'servicer_methods', + 'server', + 'stub',))): + """A live and running service. Attributes: servicer_methods: The _ServicerMethods servicing RPCs. server: The grpc.Server servicing RPCs. stub: A stub on which to invoke RPCs. """ - + def _CreateService(): - """Provides a servicer backend and a stub. + """Provides a servicer backend and a stub. Returns: A _Service with which to test RPCs. """ - servicer_methods = _ServicerMethods() + servicer_methods = _ServicerMethods() - class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): + class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): - def UnaryCall(self, request, context): - return servicer_methods.UnaryCall(request, context) + def UnaryCall(self, request, context): + return servicer_methods.UnaryCall(request, context) - def StreamingOutputCall(self, request, context): - return servicer_methods.StreamingOutputCall(request, context) + def StreamingOutputCall(self, request, context): + return servicer_methods.StreamingOutputCall(request, context) - def StreamingInputCall(self, request_iter, context): - return servicer_methods.StreamingInputCall(request_iter, context) + def StreamingInputCall(self, request_iter, context): + return servicer_methods.StreamingInputCall(request_iter, context) - def FullDuplexCall(self, request_iter, context): - return servicer_methods.FullDuplexCall(request_iter, context) + def FullDuplexCall(self, request_iter, context): + return servicer_methods.FullDuplexCall(request_iter, context) - def HalfDuplexCall(self, request_iter, context): - return servicer_methods.HalfDuplexCall(request_iter, context) + def HalfDuplexCall(self, request_iter, context): + return servicer_methods.HalfDuplexCall(request_iter, context) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) - getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) - port = server.add_insecure_port('[::]:0') - server.start() - channel = grpc.insecure_channel('localhost:{}'.format(port)) - stub = getattr(service_pb2, STUB_IDENTIFIER)(channel) - return _Service(servicer_methods, server, stub) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) + getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:{}'.format(port)) + stub = getattr(service_pb2, STUB_IDENTIFIER)(channel) + return _Service(servicer_methods, server, stub) def _CreateIncompleteService(): - """Provides a servicer backend that fails to implement methods and its stub. + """Provides a servicer backend that fails to implement methods and its stub. Returns: A _Service with which to test RPCs. The returned _Service's servicer_methods implements none of the methods required of it. """ - class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): - pass + class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): + pass - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) - getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) - port = server.add_insecure_port('[::]:0') - server.start() - channel = grpc.insecure_channel('localhost:{}'.format(port)) - stub = getattr(service_pb2, STUB_IDENTIFIER)(channel) - return _Service(None, server, stub) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) + getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER)(Servicer(), server) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:{}'.format(port)) + stub = getattr(service_pb2, STUB_IDENTIFIER)(channel) + return _Service(None, server, stub) def _streaming_input_request_iterator(): - for _ in range(3): - request = request_pb2.StreamingInputCallRequest() - request.payload.payload_type = payload_pb2.COMPRESSABLE - request.payload.payload_compressable = 'a' - yield request + for _ in range(3): + request = request_pb2.StreamingInputCallRequest() + request.payload.payload_type = payload_pb2.COMPRESSABLE + request.payload.payload_compressable = 'a' + yield request def _streaming_output_request(): - request = request_pb2.StreamingOutputCallRequest() - sizes = [1, 2, 3] - request.response_parameters.add(size=sizes[0], interval_us=0) - request.response_parameters.add(size=sizes[1], interval_us=0) - request.response_parameters.add(size=sizes[2], interval_us=0) - return request + request = request_pb2.StreamingOutputCallRequest() + sizes = [1, 2, 3] + request.response_parameters.add(size=sizes[0], interval_us=0) + request.response_parameters.add(size=sizes[1], interval_us=0) + request.response_parameters.add(size=sizes[2], interval_us=0) + return request def _full_duplex_request_iterator(): - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=1, interval_us=0) - yield request - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=2, interval_us=0) - request.response_parameters.add(size=3, interval_us=0) - yield request + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request class PythonPluginTest(unittest.TestCase): - """Test case for the gRPC Python protoc-plugin. + """Test case for the gRPC Python protoc-plugin. While reading these tests, remember that the futures API (`stub.method.future()`) only gives futures for the *response-unary* methods and does not exist for response-streaming methods. """ - def testImportAttributes(self): - # check that we can access the generated module and its members. - self.assertIsNotNone( - getattr(service_pb2, STUB_IDENTIFIER, None)) - self.assertIsNotNone( - getattr(service_pb2, SERVICER_IDENTIFIER, None)) - self.assertIsNotNone( - getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER, None)) - - def testUpDown(self): - service = _CreateService() - self.assertIsNotNone(service.servicer_methods) - self.assertIsNotNone(service.server) - self.assertIsNotNone(service.stub) - - def testIncompleteServicer(self): - service = _CreateIncompleteService() - request = request_pb2.SimpleRequest(response_size=13) - with self.assertRaises(grpc.RpcError) as exception_context: - service.stub.UnaryCall(request) - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.UNIMPLEMENTED) - - def testUnaryCall(self): - service = _CreateService() - request = request_pb2.SimpleRequest(response_size=13) - response = service.stub.UnaryCall(request) - expected_response = service.servicer_methods.UnaryCall( - request, 'not a real context!') - self.assertEqual(expected_response, response) - - def testUnaryCallFuture(self): - service = _CreateService() - request = request_pb2.SimpleRequest(response_size=13) - # Check that the call does not block waiting for the server to respond. - with service.servicer_methods.pause(): - response_future = service.stub.UnaryCall.future(request) - response = response_future.result() - expected_response = service.servicer_methods.UnaryCall( - request, 'not a real RpcContext!') - self.assertEqual(expected_response, response) - - def testUnaryCallFutureExpired(self): - service = _CreateService() - request = request_pb2.SimpleRequest(response_size=13) - with service.servicer_methods.pause(): - response_future = service.stub.UnaryCall.future( - request, timeout=test_constants.SHORT_TIMEOUT) - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) - self.assertIs(response_future.code(), grpc.StatusCode.DEADLINE_EXCEEDED) - - def testUnaryCallFutureCancelled(self): - service = _CreateService() - request = request_pb2.SimpleRequest(response_size=13) - with service.servicer_methods.pause(): - response_future = service.stub.UnaryCall.future(request) - response_future.cancel() - self.assertTrue(response_future.cancelled()) - self.assertIs(response_future.code(), grpc.StatusCode.CANCELLED) - - def testUnaryCallFutureFailed(self): - service = _CreateService() - request = request_pb2.SimpleRequest(response_size=13) - with service.servicer_methods.fail(): - response_future = service.stub.UnaryCall.future(request) - self.assertIsNotNone(response_future.exception()) - self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN) - - def testStreamingOutputCall(self): - service = _CreateService() - request = _streaming_output_request() - responses = service.stub.StreamingOutputCall(request) - expected_responses = service.servicer_methods.StreamingOutputCall( - request, 'not a real RpcContext!') - for expected_response, response in moves.zip_longest( - expected_responses, responses): - self.assertEqual(expected_response, response) - - def testStreamingOutputCallExpired(self): - service = _CreateService() - request = _streaming_output_request() - with service.servicer_methods.pause(): - responses = service.stub.StreamingOutputCall( - request, timeout=test_constants.SHORT_TIMEOUT) - with self.assertRaises(grpc.RpcError) as exception_context: - list(responses) - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) - - def testStreamingOutputCallCancelled(self): - service = _CreateService() - request = _streaming_output_request() - responses = service.stub.StreamingOutputCall(request) - next(responses) - responses.cancel() - with self.assertRaises(grpc.RpcError) as exception_context: - next(responses) - self.assertIs(responses.code(), grpc.StatusCode.CANCELLED) - - def testStreamingOutputCallFailed(self): - service = _CreateService() - request = _streaming_output_request() - with service.servicer_methods.fail(): - responses = service.stub.StreamingOutputCall(request) - self.assertIsNotNone(responses) - with self.assertRaises(grpc.RpcError) as exception_context: - next(responses) - self.assertIs(exception_context.exception.code(), grpc.StatusCode.UNKNOWN) - - def testStreamingInputCall(self): - service = _CreateService() - response = service.stub.StreamingInputCall( - _streaming_input_request_iterator()) - expected_response = service.servicer_methods.StreamingInputCall( - _streaming_input_request_iterator(), - 'not a real RpcContext!') - self.assertEqual(expected_response, response) - - def testStreamingInputCallFuture(self): - service = _CreateService() - with service.servicer_methods.pause(): - response_future = service.stub.StreamingInputCall.future( - _streaming_input_request_iterator()) - response = response_future.result() - expected_response = service.servicer_methods.StreamingInputCall( - _streaming_input_request_iterator(), - 'not a real RpcContext!') - self.assertEqual(expected_response, response) - - def testStreamingInputCallFutureExpired(self): - service = _CreateService() - with service.servicer_methods.pause(): - response_future = service.stub.StreamingInputCall.future( - _streaming_input_request_iterator(), - timeout=test_constants.SHORT_TIMEOUT) - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertIsInstance(response_future.exception(), grpc.RpcError) - self.assertIs( - response_future.exception().code(), grpc.StatusCode.DEADLINE_EXCEEDED) - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) - - def testStreamingInputCallFutureCancelled(self): - service = _CreateService() - with service.servicer_methods.pause(): - response_future = service.stub.StreamingInputCall.future( - _streaming_input_request_iterator()) - response_future.cancel() - self.assertTrue(response_future.cancelled()) - with self.assertRaises(grpc.FutureCancelledError): - response_future.result() - - def testStreamingInputCallFutureFailed(self): - service = _CreateService() - with service.servicer_methods.fail(): - response_future = service.stub.StreamingInputCall.future( - _streaming_input_request_iterator()) - self.assertIsNotNone(response_future.exception()) - self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN) - - def testFullDuplexCall(self): - service = _CreateService() - responses = service.stub.FullDuplexCall( - _full_duplex_request_iterator()) - expected_responses = service.servicer_methods.FullDuplexCall( - _full_duplex_request_iterator(), - 'not a real RpcContext!') - for expected_response, response in moves.zip_longest( - expected_responses, responses): - self.assertEqual(expected_response, response) - - def testFullDuplexCallExpired(self): - request_iterator = _full_duplex_request_iterator() - service = _CreateService() - with service.servicer_methods.pause(): - responses = service.stub.FullDuplexCall( - request_iterator, timeout=test_constants.SHORT_TIMEOUT) - with self.assertRaises(grpc.RpcError) as exception_context: - list(responses) - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) - - def testFullDuplexCallCancelled(self): - service = _CreateService() - request_iterator = _full_duplex_request_iterator() - responses = service.stub.FullDuplexCall(request_iterator) - next(responses) - responses.cancel() - with self.assertRaises(grpc.RpcError) as exception_context: - next(responses) - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.CANCELLED) - - def testFullDuplexCallFailed(self): - request_iterator = _full_duplex_request_iterator() - service = _CreateService() - with service.servicer_methods.fail(): - responses = service.stub.FullDuplexCall(request_iterator) - with self.assertRaises(grpc.RpcError) as exception_context: + def testImportAttributes(self): + # check that we can access the generated module and its members. + self.assertIsNotNone(getattr(service_pb2, STUB_IDENTIFIER, None)) + self.assertIsNotNone(getattr(service_pb2, SERVICER_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(service_pb2, ADD_SERVICER_TO_SERVER_IDENTIFIER, None)) + + def testUpDown(self): + service = _CreateService() + self.assertIsNotNone(service.servicer_methods) + self.assertIsNotNone(service.server) + self.assertIsNotNone(service.stub) + + def testIncompleteServicer(self): + service = _CreateIncompleteService() + request = request_pb2.SimpleRequest(response_size=13) + with self.assertRaises(grpc.RpcError) as exception_context: + service.stub.UnaryCall(request) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.UNIMPLEMENTED) + + def testUnaryCall(self): + service = _CreateService() + request = request_pb2.SimpleRequest(response_size=13) + response = service.stub.UnaryCall(request) + expected_response = service.servicer_methods.UnaryCall( + request, 'not a real context!') + self.assertEqual(expected_response, response) + + def testUnaryCallFuture(self): + service = _CreateService() + request = request_pb2.SimpleRequest(response_size=13) + # Check that the call does not block waiting for the server to respond. + with service.servicer_methods.pause(): + response_future = service.stub.UnaryCall.future(request) + response = response_future.result() + expected_response = service.servicer_methods.UnaryCall( + request, 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testUnaryCallFutureExpired(self): + service = _CreateService() + request = request_pb2.SimpleRequest(response_size=13) + with service.servicer_methods.pause(): + response_future = service.stub.UnaryCall.future( + request, timeout=test_constants.SHORT_TIMEOUT) + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.DEADLINE_EXCEEDED) + self.assertIs(response_future.code(), grpc.StatusCode.DEADLINE_EXCEEDED) + + def testUnaryCallFutureCancelled(self): + service = _CreateService() + request = request_pb2.SimpleRequest(response_size=13) + with service.servicer_methods.pause(): + response_future = service.stub.UnaryCall.future(request) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + self.assertIs(response_future.code(), grpc.StatusCode.CANCELLED) + + def testUnaryCallFutureFailed(self): + service = _CreateService() + request = request_pb2.SimpleRequest(response_size=13) + with service.servicer_methods.fail(): + response_future = service.stub.UnaryCall.future(request) + self.assertIsNotNone(response_future.exception()) + self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN) + + def testStreamingOutputCall(self): + service = _CreateService() + request = _streaming_output_request() + responses = service.stub.StreamingOutputCall(request) + expected_responses = service.servicer_methods.StreamingOutputCall( + request, 'not a real RpcContext!') + for expected_response, response in moves.zip_longest(expected_responses, + responses): + self.assertEqual(expected_response, response) + + def testStreamingOutputCallExpired(self): + service = _CreateService() + request = _streaming_output_request() + with service.servicer_methods.pause(): + responses = service.stub.StreamingOutputCall( + request, timeout=test_constants.SHORT_TIMEOUT) + with self.assertRaises(grpc.RpcError) as exception_context: + list(responses) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.DEADLINE_EXCEEDED) + + def testStreamingOutputCallCancelled(self): + service = _CreateService() + request = _streaming_output_request() + responses = service.stub.StreamingOutputCall(request) next(responses) - self.assertIs(exception_context.exception.code(), grpc.StatusCode.UNKNOWN) - - def testHalfDuplexCall(self): - service = _CreateService() - def half_duplex_request_iterator(): - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=1, interval_us=0) - yield request - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=2, interval_us=0) - request.response_parameters.add(size=3, interval_us=0) - yield request - responses = service.stub.HalfDuplexCall(half_duplex_request_iterator()) - expected_responses = service.servicer_methods.HalfDuplexCall( - half_duplex_request_iterator(), 'not a real RpcContext!') - for expected_response, response in moves.zip_longest( - expected_responses, responses): - self.assertEqual(expected_response, response) - - def testHalfDuplexCallWedged(self): - condition = threading.Condition() - wait_cell = [False] - @contextlib.contextmanager - def wait(): # pylint: disable=invalid-name - # Where's Python 3's 'nonlocal' statement when you need it? - with condition: - wait_cell[0] = True - yield - with condition: - wait_cell[0] = False - condition.notify_all() - def half_duplex_request_iterator(): - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=1, interval_us=0) - yield request - with condition: - while wait_cell[0]: - condition.wait() - service = _CreateService() - with wait(): - responses = service.stub.HalfDuplexCall( - half_duplex_request_iterator(), timeout=test_constants.SHORT_TIMEOUT) - # half-duplex waits for the client to send all info - with self.assertRaises(grpc.RpcError) as exception_context: + responses.cancel() + with self.assertRaises(grpc.RpcError) as exception_context: + next(responses) + self.assertIs(responses.code(), grpc.StatusCode.CANCELLED) + + def testStreamingOutputCallFailed(self): + service = _CreateService() + request = _streaming_output_request() + with service.servicer_methods.fail(): + responses = service.stub.StreamingOutputCall(request) + self.assertIsNotNone(responses) + with self.assertRaises(grpc.RpcError) as exception_context: + next(responses) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.UNKNOWN) + + def testStreamingInputCall(self): + service = _CreateService() + response = service.stub.StreamingInputCall( + _streaming_input_request_iterator()) + expected_response = service.servicer_methods.StreamingInputCall( + _streaming_input_request_iterator(), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallFuture(self): + service = _CreateService() + with service.servicer_methods.pause(): + response_future = service.stub.StreamingInputCall.future( + _streaming_input_request_iterator()) + response = response_future.result() + expected_response = service.servicer_methods.StreamingInputCall( + _streaming_input_request_iterator(), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallFutureExpired(self): + service = _CreateService() + with service.servicer_methods.pause(): + response_future = service.stub.StreamingInputCall.future( + _streaming_input_request_iterator(), + timeout=test_constants.SHORT_TIMEOUT) + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertIsInstance(response_future.exception(), grpc.RpcError) + self.assertIs(response_future.exception().code(), + grpc.StatusCode.DEADLINE_EXCEEDED) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.DEADLINE_EXCEEDED) + + def testStreamingInputCallFutureCancelled(self): + service = _CreateService() + with service.servicer_methods.pause(): + response_future = service.stub.StreamingInputCall.future( + _streaming_input_request_iterator()) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + with self.assertRaises(grpc.FutureCancelledError): + response_future.result() + + def testStreamingInputCallFutureFailed(self): + service = _CreateService() + with service.servicer_methods.fail(): + response_future = service.stub.StreamingInputCall.future( + _streaming_input_request_iterator()) + self.assertIsNotNone(response_future.exception()) + self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN) + + def testFullDuplexCall(self): + service = _CreateService() + responses = service.stub.FullDuplexCall(_full_duplex_request_iterator()) + expected_responses = service.servicer_methods.FullDuplexCall( + _full_duplex_request_iterator(), 'not a real RpcContext!') + for expected_response, response in moves.zip_longest(expected_responses, + responses): + self.assertEqual(expected_response, response) + + def testFullDuplexCallExpired(self): + request_iterator = _full_duplex_request_iterator() + service = _CreateService() + with service.servicer_methods.pause(): + responses = service.stub.FullDuplexCall( + request_iterator, timeout=test_constants.SHORT_TIMEOUT) + with self.assertRaises(grpc.RpcError) as exception_context: + list(responses) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.DEADLINE_EXCEEDED) + + def testFullDuplexCallCancelled(self): + service = _CreateService() + request_iterator = _full_duplex_request_iterator() + responses = service.stub.FullDuplexCall(request_iterator) next(responses) - self.assertIs( - exception_context.exception.code(), grpc.StatusCode.DEADLINE_EXCEEDED) + responses.cancel() + with self.assertRaises(grpc.RpcError) as exception_context: + next(responses) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.CANCELLED) + + def testFullDuplexCallFailed(self): + request_iterator = _full_duplex_request_iterator() + service = _CreateService() + with service.servicer_methods.fail(): + responses = service.stub.FullDuplexCall(request_iterator) + with self.assertRaises(grpc.RpcError) as exception_context: + next(responses) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.UNKNOWN) + + def testHalfDuplexCall(self): + service = _CreateService() + + def half_duplex_request_iterator(): + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request + + responses = service.stub.HalfDuplexCall(half_duplex_request_iterator()) + expected_responses = service.servicer_methods.HalfDuplexCall( + half_duplex_request_iterator(), 'not a real RpcContext!') + for expected_response, response in moves.zip_longest(expected_responses, + responses): + self.assertEqual(expected_response, response) + + def testHalfDuplexCallWedged(self): + condition = threading.Condition() + wait_cell = [False] + + @contextlib.contextmanager + def wait(): # pylint: disable=invalid-name + # Where's Python 3's 'nonlocal' statement when you need it? + with condition: + wait_cell[0] = True + yield + with condition: + wait_cell[0] = False + condition.notify_all() + + def half_duplex_request_iterator(): + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + with condition: + while wait_cell[0]: + condition.wait() + + service = _CreateService() + with wait(): + responses = service.stub.HalfDuplexCall( + half_duplex_request_iterator(), + timeout=test_constants.SHORT_TIMEOUT) + # half-duplex waits for the client to send all info + with self.assertRaises(grpc.RpcError) as exception_context: + next(responses) + self.assertIs(exception_context.exception.code(), + grpc.StatusCode.DEADLINE_EXCEEDED) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py index f8ae05bb7a9..bcc01f39787 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py @@ -49,256 +49,264 @@ from tests.unit.framework.common import test_constants _MESSAGES_IMPORT = b'import "messages.proto";' + @contextlib.contextmanager def _system_path(path): - old_system_path = sys.path[:] - sys.path = sys.path[0:1] + path + sys.path[1:] - yield - sys.path = old_system_path + old_system_path = sys.path[:] + sys.path = sys.path[0:1] + path + sys.path[1:] + yield + sys.path = old_system_path class DummySplitServicer(object): - def __init__(self, request_class, response_class): - self.request_class = request_class - self.response_class = response_class + def __init__(self, request_class, response_class): + self.request_class = request_class + self.response_class = response_class - def Call(self, request, context): - return self.response_class() + def Call(self, request, context): + return self.response_class() class SeparateTestMixin(object): - def testImportAttributes(self): - with _system_path([self.python_out_directory]): - pb2 = importlib.import_module(self.pb2_import) - pb2.Request - pb2.Response - if self.should_find_services_in_pb2: - pb2.TestServiceServicer - else: - with self.assertRaises(AttributeError): - pb2.TestServiceServicer - - with _system_path([self.grpc_python_out_directory]): - pb2_grpc = importlib.import_module(self.pb2_grpc_import) - pb2_grpc.TestServiceServicer - with self.assertRaises(AttributeError): - pb2_grpc.Request - with self.assertRaises(AttributeError): - pb2_grpc.Response - - def testCall(self): - with _system_path([self.python_out_directory]): - pb2 = importlib.import_module(self.pb2_import) - with _system_path([self.grpc_python_out_directory]): - pb2_grpc = importlib.import_module(self.pb2_grpc_import) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) - pb2_grpc.add_TestServiceServicer_to_server( - DummySplitServicer( - pb2.Request, pb2.Response), server) - port = server.add_insecure_port('[::]:0') - server.start() - channel = grpc.insecure_channel('localhost:{}'.format(port)) - stub = pb2_grpc.TestServiceStub(channel) - request = pb2.Request() - expected_response = pb2.Response() - response = stub.Call(request) - self.assertEqual(expected_response, response) + def testImportAttributes(self): + with _system_path([self.python_out_directory]): + pb2 = importlib.import_module(self.pb2_import) + pb2.Request + pb2.Response + if self.should_find_services_in_pb2: + pb2.TestServiceServicer + else: + with self.assertRaises(AttributeError): + pb2.TestServiceServicer + + with _system_path([self.grpc_python_out_directory]): + pb2_grpc = importlib.import_module(self.pb2_grpc_import) + pb2_grpc.TestServiceServicer + with self.assertRaises(AttributeError): + pb2_grpc.Request + with self.assertRaises(AttributeError): + pb2_grpc.Response + + def testCall(self): + with _system_path([self.python_out_directory]): + pb2 = importlib.import_module(self.pb2_import) + with _system_path([self.grpc_python_out_directory]): + pb2_grpc = importlib.import_module(self.pb2_grpc_import) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) + pb2_grpc.add_TestServiceServicer_to_server( + DummySplitServicer(pb2.Request, pb2.Response), server) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:{}'.format(port)) + stub = pb2_grpc.TestServiceStub(channel) + request = pb2.Request() + expected_response = pb2.Response() + response = stub.Call(request) + self.assertEqual(expected_response, response) class CommonTestMixin(object): - def testImportAttributes(self): - with _system_path([self.python_out_directory]): - pb2 = importlib.import_module(self.pb2_import) - pb2.Request - pb2.Response - if self.should_find_services_in_pb2: - pb2.TestServiceServicer - else: - with self.assertRaises(AttributeError): - pb2.TestServiceServicer - - with _system_path([self.grpc_python_out_directory]): - pb2_grpc = importlib.import_module(self.pb2_grpc_import) - pb2_grpc.TestServiceServicer - with self.assertRaises(AttributeError): - pb2_grpc.Request - with self.assertRaises(AttributeError): - pb2_grpc.Response - - def testCall(self): - with _system_path([self.python_out_directory]): - pb2 = importlib.import_module(self.pb2_import) - with _system_path([self.grpc_python_out_directory]): - pb2_grpc = importlib.import_module(self.pb2_grpc_import) - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) - pb2_grpc.add_TestServiceServicer_to_server( - DummySplitServicer( - pb2.Request, pb2.Response), server) - port = server.add_insecure_port('[::]:0') - server.start() - channel = grpc.insecure_channel('localhost:{}'.format(port)) - stub = pb2_grpc.TestServiceStub(channel) - request = pb2.Request() - expected_response = pb2.Response() - response = stub.Call(request) - self.assertEqual(expected_response, response) + def testImportAttributes(self): + with _system_path([self.python_out_directory]): + pb2 = importlib.import_module(self.pb2_import) + pb2.Request + pb2.Response + if self.should_find_services_in_pb2: + pb2.TestServiceServicer + else: + with self.assertRaises(AttributeError): + pb2.TestServiceServicer + + with _system_path([self.grpc_python_out_directory]): + pb2_grpc = importlib.import_module(self.pb2_grpc_import) + pb2_grpc.TestServiceServicer + with self.assertRaises(AttributeError): + pb2_grpc.Request + with self.assertRaises(AttributeError): + pb2_grpc.Response + + def testCall(self): + with _system_path([self.python_out_directory]): + pb2 = importlib.import_module(self.pb2_import) + with _system_path([self.grpc_python_out_directory]): + pb2_grpc = importlib.import_module(self.pb2_grpc_import) + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=test_constants.POOL_SIZE)) + pb2_grpc.add_TestServiceServicer_to_server( + DummySplitServicer(pb2.Request, pb2.Response), server) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:{}'.format(port)) + stub = pb2_grpc.TestServiceStub(channel) + request = pb2.Request() + expected_response = pb2.Response() + response = stub.Call(request) + self.assertEqual(expected_response, response) class SameSeparateTest(unittest.TestCase, SeparateTestMixin): - def setUp(self): - same_proto_contents = pkgutil.get_data( - 'tests.protoc_plugin.protos.invocation_testing', 'same.proto') - self.directory = tempfile.mkdtemp(suffix='same_separate', dir='.') - self.proto_directory = os.path.join(self.directory, 'proto_path') - self.python_out_directory = os.path.join(self.directory, 'python_out') - self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out') - os.makedirs(self.proto_directory) - os.makedirs(self.python_out_directory) - os.makedirs(self.grpc_python_out_directory) - same_proto_file = os.path.join(self.proto_directory, 'same_separate.proto') - open(same_proto_file, 'wb').write(same_proto_contents) - protoc_result = protoc.main([ - '', - '--proto_path={}'.format(self.proto_directory), - '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out=grpc_2_0:{}'.format(self.grpc_python_out_directory), - same_proto_file, - ]) - if protoc_result != 0: - raise Exception("unexpected protoc error") - open(os.path.join(self.grpc_python_out_directory, '__init__.py'), 'w').write('') - open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') - self.pb2_import = 'same_separate_pb2' - self.pb2_grpc_import = 'same_separate_pb2_grpc' - self.should_find_services_in_pb2 = False - - def tearDown(self): - shutil.rmtree(self.directory) + def setUp(self): + same_proto_contents = pkgutil.get_data( + 'tests.protoc_plugin.protos.invocation_testing', 'same.proto') + self.directory = tempfile.mkdtemp(suffix='same_separate', dir='.') + self.proto_directory = os.path.join(self.directory, 'proto_path') + self.python_out_directory = os.path.join(self.directory, 'python_out') + self.grpc_python_out_directory = os.path.join(self.directory, + 'grpc_python_out') + os.makedirs(self.proto_directory) + os.makedirs(self.python_out_directory) + os.makedirs(self.grpc_python_out_directory) + same_proto_file = os.path.join(self.proto_directory, + 'same_separate.proto') + open(same_proto_file, 'wb').write(same_proto_contents) + protoc_result = protoc.main([ + '', + '--proto_path={}'.format(self.proto_directory), + '--python_out={}'.format(self.python_out_directory), + '--grpc_python_out=grpc_2_0:{}'.format( + self.grpc_python_out_directory), + same_proto_file, + ]) + if protoc_result != 0: + raise Exception("unexpected protoc error") + open(os.path.join(self.grpc_python_out_directory, '__init__.py'), + 'w').write('') + open(os.path.join(self.python_out_directory, '__init__.py'), + 'w').write('') + self.pb2_import = 'same_separate_pb2' + self.pb2_grpc_import = 'same_separate_pb2_grpc' + self.should_find_services_in_pb2 = False + + def tearDown(self): + shutil.rmtree(self.directory) class SameCommonTest(unittest.TestCase, CommonTestMixin): - def setUp(self): - same_proto_contents = pkgutil.get_data( - 'tests.protoc_plugin.protos.invocation_testing', 'same.proto') - self.directory = tempfile.mkdtemp(suffix='same_common', dir='.') - self.proto_directory = os.path.join(self.directory, 'proto_path') - self.python_out_directory = os.path.join(self.directory, 'python_out') - self.grpc_python_out_directory = self.python_out_directory - os.makedirs(self.proto_directory) - os.makedirs(self.python_out_directory) - same_proto_file = os.path.join(self.proto_directory, 'same_common.proto') - open(same_proto_file, 'wb').write(same_proto_contents) - protoc_result = protoc.main([ - '', - '--proto_path={}'.format(self.proto_directory), - '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out={}'.format(self.grpc_python_out_directory), - same_proto_file, - ]) - if protoc_result != 0: - raise Exception("unexpected protoc error") - open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') - self.pb2_import = 'same_common_pb2' - self.pb2_grpc_import = 'same_common_pb2_grpc' - self.should_find_services_in_pb2 = True - - def tearDown(self): - shutil.rmtree(self.directory) + def setUp(self): + same_proto_contents = pkgutil.get_data( + 'tests.protoc_plugin.protos.invocation_testing', 'same.proto') + self.directory = tempfile.mkdtemp(suffix='same_common', dir='.') + self.proto_directory = os.path.join(self.directory, 'proto_path') + self.python_out_directory = os.path.join(self.directory, 'python_out') + self.grpc_python_out_directory = self.python_out_directory + os.makedirs(self.proto_directory) + os.makedirs(self.python_out_directory) + same_proto_file = os.path.join(self.proto_directory, + 'same_common.proto') + open(same_proto_file, 'wb').write(same_proto_contents) + protoc_result = protoc.main([ + '', + '--proto_path={}'.format(self.proto_directory), + '--python_out={}'.format(self.python_out_directory), + '--grpc_python_out={}'.format(self.grpc_python_out_directory), + same_proto_file, + ]) + if protoc_result != 0: + raise Exception("unexpected protoc error") + open(os.path.join(self.python_out_directory, '__init__.py'), + 'w').write('') + self.pb2_import = 'same_common_pb2' + self.pb2_grpc_import = 'same_common_pb2_grpc' + self.should_find_services_in_pb2 = True + + def tearDown(self): + shutil.rmtree(self.directory) class SplitCommonTest(unittest.TestCase, CommonTestMixin): - def setUp(self): - services_proto_contents = pkgutil.get_data( - 'tests.protoc_plugin.protos.invocation_testing.split_services', - 'services.proto') - messages_proto_contents = pkgutil.get_data( - 'tests.protoc_plugin.protos.invocation_testing.split_messages', - 'messages.proto') - self.directory = tempfile.mkdtemp(suffix='split_common', dir='.') - self.proto_directory = os.path.join(self.directory, 'proto_path') - self.python_out_directory = os.path.join(self.directory, 'python_out') - self.grpc_python_out_directory = self.python_out_directory - os.makedirs(self.proto_directory) - os.makedirs(self.python_out_directory) - services_proto_file = os.path.join(self.proto_directory, - 'split_common_services.proto') - messages_proto_file = os.path.join(self.proto_directory, - 'split_common_messages.proto') - open(services_proto_file, 'wb').write(services_proto_contents.replace( - _MESSAGES_IMPORT, - b'import "split_common_messages.proto";' - )) - open(messages_proto_file, 'wb').write(messages_proto_contents) - protoc_result = protoc.main([ - '', - '--proto_path={}'.format(self.proto_directory), - '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out={}'.format(self.grpc_python_out_directory), - services_proto_file, - messages_proto_file, - ]) - if protoc_result != 0: - raise Exception("unexpected protoc error") - open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') - self.pb2_import = 'split_common_messages_pb2' - self.pb2_grpc_import = 'split_common_services_pb2_grpc' - self.should_find_services_in_pb2 = False - - def tearDown(self): - shutil.rmtree(self.directory) + def setUp(self): + services_proto_contents = pkgutil.get_data( + 'tests.protoc_plugin.protos.invocation_testing.split_services', + 'services.proto') + messages_proto_contents = pkgutil.get_data( + 'tests.protoc_plugin.protos.invocation_testing.split_messages', + 'messages.proto') + self.directory = tempfile.mkdtemp(suffix='split_common', dir='.') + self.proto_directory = os.path.join(self.directory, 'proto_path') + self.python_out_directory = os.path.join(self.directory, 'python_out') + self.grpc_python_out_directory = self.python_out_directory + os.makedirs(self.proto_directory) + os.makedirs(self.python_out_directory) + services_proto_file = os.path.join(self.proto_directory, + 'split_common_services.proto') + messages_proto_file = os.path.join(self.proto_directory, + 'split_common_messages.proto') + open(services_proto_file, 'wb').write( + services_proto_contents.replace( + _MESSAGES_IMPORT, b'import "split_common_messages.proto";')) + open(messages_proto_file, 'wb').write(messages_proto_contents) + protoc_result = protoc.main([ + '', + '--proto_path={}'.format(self.proto_directory), + '--python_out={}'.format(self.python_out_directory), + '--grpc_python_out={}'.format(self.grpc_python_out_directory), + services_proto_file, + messages_proto_file, + ]) + if protoc_result != 0: + raise Exception("unexpected protoc error") + open(os.path.join(self.python_out_directory, '__init__.py'), + 'w').write('') + self.pb2_import = 'split_common_messages_pb2' + self.pb2_grpc_import = 'split_common_services_pb2_grpc' + self.should_find_services_in_pb2 = False + + def tearDown(self): + shutil.rmtree(self.directory) class SplitSeparateTest(unittest.TestCase, SeparateTestMixin): - def setUp(self): - services_proto_contents = pkgutil.get_data( - 'tests.protoc_plugin.protos.invocation_testing.split_services', - 'services.proto') - messages_proto_contents = pkgutil.get_data( - 'tests.protoc_plugin.protos.invocation_testing.split_messages', - 'messages.proto') - self.directory = tempfile.mkdtemp(suffix='split_separate', dir='.') - self.proto_directory = os.path.join(self.directory, 'proto_path') - self.python_out_directory = os.path.join(self.directory, 'python_out') - self.grpc_python_out_directory = os.path.join(self.directory, 'grpc_python_out') - os.makedirs(self.proto_directory) - os.makedirs(self.python_out_directory) - os.makedirs(self.grpc_python_out_directory) - services_proto_file = os.path.join(self.proto_directory, - 'split_separate_services.proto') - messages_proto_file = os.path.join(self.proto_directory, - 'split_separate_messages.proto') - open(services_proto_file, 'wb').write(services_proto_contents.replace( - _MESSAGES_IMPORT, - b'import "split_separate_messages.proto";' - )) - open(messages_proto_file, 'wb').write(messages_proto_contents) - protoc_result = protoc.main([ - '', - '--proto_path={}'.format(self.proto_directory), - '--python_out={}'.format(self.python_out_directory), - '--grpc_python_out=grpc_2_0:{}'.format(self.grpc_python_out_directory), - services_proto_file, - messages_proto_file, - ]) - if protoc_result != 0: - raise Exception("unexpected protoc error") - open(os.path.join(self.python_out_directory, '__init__.py'), 'w').write('') - self.pb2_import = 'split_separate_messages_pb2' - self.pb2_grpc_import = 'split_separate_services_pb2_grpc' - self.should_find_services_in_pb2 = False - - def tearDown(self): - shutil.rmtree(self.directory) + def setUp(self): + services_proto_contents = pkgutil.get_data( + 'tests.protoc_plugin.protos.invocation_testing.split_services', + 'services.proto') + messages_proto_contents = pkgutil.get_data( + 'tests.protoc_plugin.protos.invocation_testing.split_messages', + 'messages.proto') + self.directory = tempfile.mkdtemp(suffix='split_separate', dir='.') + self.proto_directory = os.path.join(self.directory, 'proto_path') + self.python_out_directory = os.path.join(self.directory, 'python_out') + self.grpc_python_out_directory = os.path.join(self.directory, + 'grpc_python_out') + os.makedirs(self.proto_directory) + os.makedirs(self.python_out_directory) + os.makedirs(self.grpc_python_out_directory) + services_proto_file = os.path.join(self.proto_directory, + 'split_separate_services.proto') + messages_proto_file = os.path.join(self.proto_directory, + 'split_separate_messages.proto') + open(services_proto_file, 'wb').write( + services_proto_contents.replace( + _MESSAGES_IMPORT, b'import "split_separate_messages.proto";')) + open(messages_proto_file, 'wb').write(messages_proto_contents) + protoc_result = protoc.main([ + '', + '--proto_path={}'.format(self.proto_directory), + '--python_out={}'.format(self.python_out_directory), + '--grpc_python_out=grpc_2_0:{}'.format( + self.grpc_python_out_directory), + services_proto_file, + messages_proto_file, + ]) + if protoc_result != 0: + raise Exception("unexpected protoc error") + open(os.path.join(self.python_out_directory, '__init__.py'), + 'w').write('') + self.pb2_import = 'split_separate_messages_pb2' + self.pb2_grpc_import = 'split_separate_services_pb2_grpc' + self.should_find_services_in_pb2 = False + + def tearDown(self): + shutil.rmtree(self.directory) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py index 1eba9c93543..f64f4e962ba 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py @@ -64,84 +64,84 @@ STUB_FACTORY_IDENTIFIER = 'beta_create_TestService_stub' class _ServicerMethods(object): - def __init__(self): - self._condition = threading.Condition() - self._paused = False - self._fail = False - - @contextlib.contextmanager - def pause(self): # pylint: disable=invalid-name - with self._condition: - self._paused = True - yield - with self._condition: - self._paused = False - self._condition.notify_all() - - @contextlib.contextmanager - def fail(self): # pylint: disable=invalid-name - with self._condition: - self._fail = True - yield - with self._condition: - self._fail = False - - def _control(self): # pylint: disable=invalid-name - with self._condition: - if self._fail: - raise ValueError() - while self._paused: - self._condition.wait() - - def UnaryCall(self, request, unused_rpc_context): - response = response_pb2.SimpleResponse() - response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * request.response_size - self._control() - return response - - def StreamingOutputCall(self, request, unused_rpc_context): - for parameter in request.response_parameters: - response = response_pb2.StreamingOutputCallResponse() - response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * parameter.size - self._control() - yield response - - def StreamingInputCall(self, request_iter, unused_rpc_context): - response = response_pb2.StreamingInputCallResponse() - aggregated_payload_size = 0 - for request in request_iter: - aggregated_payload_size += len(request.payload.payload_compressable) - response.aggregated_payload_size = aggregated_payload_size - self._control() - return response - - def FullDuplexCall(self, request_iter, unused_rpc_context): - for request in request_iter: - for parameter in request.response_parameters: - response = response_pb2.StreamingOutputCallResponse() - response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * parameter.size - self._control() - yield response + def __init__(self): + self._condition = threading.Condition() + self._paused = False + self._fail = False + + @contextlib.contextmanager + def pause(self): # pylint: disable=invalid-name + with self._condition: + self._paused = True + yield + with self._condition: + self._paused = False + self._condition.notify_all() - def HalfDuplexCall(self, request_iter, unused_rpc_context): - responses = [] - for request in request_iter: - for parameter in request.response_parameters: - response = response_pb2.StreamingOutputCallResponse() + @contextlib.contextmanager + def fail(self): # pylint: disable=invalid-name + with self._condition: + self._fail = True + yield + with self._condition: + self._fail = False + + def _control(self): # pylint: disable=invalid-name + with self._condition: + if self._fail: + raise ValueError() + while self._paused: + self._condition.wait() + + def UnaryCall(self, request, unused_rpc_context): + response = response_pb2.SimpleResponse() response.payload.payload_type = payload_pb2.COMPRESSABLE - response.payload.payload_compressable = 'a' * parameter.size + response.payload.payload_compressable = 'a' * request.response_size + self._control() + return response + + def StreamingOutputCall(self, request, unused_rpc_context): + for parameter in request.response_parameters: + response = response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = payload_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def StreamingInputCall(self, request_iter, unused_rpc_context): + response = response_pb2.StreamingInputCallResponse() + aggregated_payload_size = 0 + for request in request_iter: + aggregated_payload_size += len(request.payload.payload_compressable) + response.aggregated_payload_size = aggregated_payload_size self._control() - responses.append(response) - for response in responses: - yield response + return response + + def FullDuplexCall(self, request_iter, unused_rpc_context): + for request in request_iter: + for parameter in request.response_parameters: + response = response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = payload_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def HalfDuplexCall(self, request_iter, unused_rpc_context): + responses = [] + for request in request_iter: + for parameter in request.response_parameters: + response = response_pb2.StreamingOutputCallResponse() + response.payload.payload_type = payload_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + responses.append(response) + for response in responses: + yield response @contextlib.contextmanager def _CreateService(): - """Provides a servicer backend and a stub. + """Provides a servicer backend and a stub. The servicer is just the implementation of the actual servicer passed to the face player of the python RPC implementation; the two are detached. @@ -151,38 +151,38 @@ def _CreateService(): the service bound to the stub and and stub is the stub on which to invoke RPCs. """ - servicer_methods = _ServicerMethods() + servicer_methods = _ServicerMethods() - class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): + class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): - def UnaryCall(self, request, context): - return servicer_methods.UnaryCall(request, context) + def UnaryCall(self, request, context): + return servicer_methods.UnaryCall(request, context) - def StreamingOutputCall(self, request, context): - return servicer_methods.StreamingOutputCall(request, context) + def StreamingOutputCall(self, request, context): + return servicer_methods.StreamingOutputCall(request, context) - def StreamingInputCall(self, request_iter, context): - return servicer_methods.StreamingInputCall(request_iter, context) + def StreamingInputCall(self, request_iter, context): + return servicer_methods.StreamingInputCall(request_iter, context) - def FullDuplexCall(self, request_iter, context): - return servicer_methods.FullDuplexCall(request_iter, context) + def FullDuplexCall(self, request_iter, context): + return servicer_methods.FullDuplexCall(request_iter, context) - def HalfDuplexCall(self, request_iter, context): - return servicer_methods.HalfDuplexCall(request_iter, context) + def HalfDuplexCall(self, request_iter, context): + return servicer_methods.HalfDuplexCall(request_iter, context) - servicer = Servicer() - server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) - port = server.add_insecure_port('[::]:0') - server.start() - channel = implementations.insecure_channel('localhost', port) - stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) - yield (servicer_methods, stub) - server.stop(0) + servicer = Servicer() + server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) + port = server.add_insecure_port('[::]:0') + server.start() + channel = implementations.insecure_channel('localhost', port) + stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) + yield (servicer_methods, stub) + server.stop(0) @contextlib.contextmanager def _CreateIncompleteService(): - """Provides a servicer backend that fails to implement methods and its stub. + """Provides a servicer backend that fails to implement methods and its stub. The servicer is just the implementation of the actual servicer passed to the face player of the python RPC implementation; the two are detached. @@ -194,297 +194,297 @@ def _CreateIncompleteService(): RPCs. """ - class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): - pass + class Servicer(getattr(service_pb2, SERVICER_IDENTIFIER)): + pass - servicer = Servicer() - server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) - port = server.add_insecure_port('[::]:0') - server.start() - channel = implementations.insecure_channel('localhost', port) - stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) - yield None, stub - server.stop(0) + servicer = Servicer() + server = getattr(service_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) + port = server.add_insecure_port('[::]:0') + server.start() + channel = implementations.insecure_channel('localhost', port) + stub = getattr(service_pb2, STUB_FACTORY_IDENTIFIER)(channel) + yield None, stub + server.stop(0) def _streaming_input_request_iterator(): - for _ in range(3): - request = request_pb2.StreamingInputCallRequest() - request.payload.payload_type = payload_pb2.COMPRESSABLE - request.payload.payload_compressable = 'a' - yield request + for _ in range(3): + request = request_pb2.StreamingInputCallRequest() + request.payload.payload_type = payload_pb2.COMPRESSABLE + request.payload.payload_compressable = 'a' + yield request def _streaming_output_request(): - request = request_pb2.StreamingOutputCallRequest() - sizes = [1, 2, 3] - request.response_parameters.add(size=sizes[0], interval_us=0) - request.response_parameters.add(size=sizes[1], interval_us=0) - request.response_parameters.add(size=sizes[2], interval_us=0) - return request + request = request_pb2.StreamingOutputCallRequest() + sizes = [1, 2, 3] + request.response_parameters.add(size=sizes[0], interval_us=0) + request.response_parameters.add(size=sizes[1], interval_us=0) + request.response_parameters.add(size=sizes[2], interval_us=0) + return request def _full_duplex_request_iterator(): - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=1, interval_us=0) - yield request - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=2, interval_us=0) - request.response_parameters.add(size=3, interval_us=0) - yield request + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request class PythonPluginTest(unittest.TestCase): - """Test case for the gRPC Python protoc-plugin. + """Test case for the gRPC Python protoc-plugin. While reading these tests, remember that the futures API (`stub.method.future()`) only gives futures for the *response-unary* methods and does not exist for response-streaming methods. """ - def testImportAttributes(self): - # check that we can access the generated module and its members. - self.assertIsNotNone( - getattr(service_pb2, SERVICER_IDENTIFIER, None)) - self.assertIsNotNone( - getattr(service_pb2, STUB_IDENTIFIER, None)) - self.assertIsNotNone( - getattr(service_pb2, SERVER_FACTORY_IDENTIFIER, None)) - self.assertIsNotNone( - getattr(service_pb2, STUB_FACTORY_IDENTIFIER, None)) - - def testUpDown(self): - with _CreateService(): - request_pb2.SimpleRequest(response_size=13) - - def testIncompleteServicer(self): - with _CreateIncompleteService() as (_, stub): - request = request_pb2.SimpleRequest(response_size=13) - try: - stub.UnaryCall(request, test_constants.LONG_TIMEOUT) - except face.AbortionError as error: - self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, error.code) - - def testUnaryCall(self): - with _CreateService() as (methods, stub): - request = request_pb2.SimpleRequest(response_size=13) - response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) - expected_response = methods.UnaryCall(request, 'not a real context!') - self.assertEqual(expected_response, response) - - def testUnaryCallFuture(self): - with _CreateService() as (methods, stub): - request = request_pb2.SimpleRequest(response_size=13) - # Check that the call does not block waiting for the server to respond. - with methods.pause(): - response_future = stub.UnaryCall.future( - request, test_constants.LONG_TIMEOUT) - response = response_future.result() - expected_response = methods.UnaryCall(request, 'not a real RpcContext!') - self.assertEqual(expected_response, response) - - def testUnaryCallFutureExpired(self): - with _CreateService() as (methods, stub): - request = request_pb2.SimpleRequest(response_size=13) - with methods.pause(): - response_future = stub.UnaryCall.future( - request, test_constants.SHORT_TIMEOUT) - with self.assertRaises(face.ExpirationError): - response_future.result() - - def testUnaryCallFutureCancelled(self): - with _CreateService() as (methods, stub): - request = request_pb2.SimpleRequest(response_size=13) - with methods.pause(): - response_future = stub.UnaryCall.future(request, 1) - response_future.cancel() - self.assertTrue(response_future.cancelled()) - - def testUnaryCallFutureFailed(self): - with _CreateService() as (methods, stub): - request = request_pb2.SimpleRequest(response_size=13) - with methods.fail(): - response_future = stub.UnaryCall.future( - request, test_constants.LONG_TIMEOUT) - self.assertIsNotNone(response_future.exception()) - - def testStreamingOutputCall(self): - with _CreateService() as (methods, stub): - request = _streaming_output_request() - responses = stub.StreamingOutputCall( - request, test_constants.LONG_TIMEOUT) - expected_responses = methods.StreamingOutputCall( - request, 'not a real RpcContext!') - for expected_response, response in moves.zip_longest( - expected_responses, responses): + def testImportAttributes(self): + # check that we can access the generated module and its members. + self.assertIsNotNone(getattr(service_pb2, SERVICER_IDENTIFIER, None)) + self.assertIsNotNone(getattr(service_pb2, STUB_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(service_pb2, SERVER_FACTORY_IDENTIFIER, None)) + self.assertIsNotNone( + getattr(service_pb2, STUB_FACTORY_IDENTIFIER, None)) + + def testUpDown(self): + with _CreateService(): + request_pb2.SimpleRequest(response_size=13) + + def testIncompleteServicer(self): + with _CreateIncompleteService() as (_, stub): + request = request_pb2.SimpleRequest(response_size=13) + try: + stub.UnaryCall(request, test_constants.LONG_TIMEOUT) + except face.AbortionError as error: + self.assertEqual(interfaces.StatusCode.UNIMPLEMENTED, + error.code) + + def testUnaryCall(self): + with _CreateService() as (methods, stub): + request = request_pb2.SimpleRequest(response_size=13) + response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) + expected_response = methods.UnaryCall(request, 'not a real context!') self.assertEqual(expected_response, response) - def testStreamingOutputCallExpired(self): - with _CreateService() as (methods, stub): - request = _streaming_output_request() - with methods.pause(): - responses = stub.StreamingOutputCall( - request, test_constants.SHORT_TIMEOUT) - with self.assertRaises(face.ExpirationError): - list(responses) - - def testStreamingOutputCallCancelled(self): - with _CreateService() as (methods, stub): - request = _streaming_output_request() - responses = stub.StreamingOutputCall( - request, test_constants.LONG_TIMEOUT) - next(responses) - responses.cancel() - with self.assertRaises(face.CancellationError): - next(responses) - - def testStreamingOutputCallFailed(self): - with _CreateService() as (methods, stub): - request = _streaming_output_request() - with methods.fail(): - responses = stub.StreamingOutputCall(request, 1) - self.assertIsNotNone(responses) - with self.assertRaises(face.RemoteError): - next(responses) - - def testStreamingInputCall(self): - with _CreateService() as (methods, stub): - response = stub.StreamingInputCall( - _streaming_input_request_iterator(), - test_constants.LONG_TIMEOUT) - expected_response = methods.StreamingInputCall( - _streaming_input_request_iterator(), - 'not a real RpcContext!') - self.assertEqual(expected_response, response) - - def testStreamingInputCallFuture(self): - with _CreateService() as (methods, stub): - with methods.pause(): - response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(), - test_constants.LONG_TIMEOUT) - response = response_future.result() - expected_response = methods.StreamingInputCall( - _streaming_input_request_iterator(), - 'not a real RpcContext!') - self.assertEqual(expected_response, response) - - def testStreamingInputCallFutureExpired(self): - with _CreateService() as (methods, stub): - with methods.pause(): - response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(), - test_constants.SHORT_TIMEOUT) - with self.assertRaises(face.ExpirationError): - response_future.result() - self.assertIsInstance( - response_future.exception(), face.ExpirationError) - - def testStreamingInputCallFutureCancelled(self): - with _CreateService() as (methods, stub): - with methods.pause(): - response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(), - test_constants.LONG_TIMEOUT) - response_future.cancel() - self.assertTrue(response_future.cancelled()) - with self.assertRaises(future.CancelledError): - response_future.result() - - def testStreamingInputCallFutureFailed(self): - with _CreateService() as (methods, stub): - with methods.fail(): - response_future = stub.StreamingInputCall.future( - _streaming_input_request_iterator(), - test_constants.LONG_TIMEOUT) - self.assertIsNotNone(response_future.exception()) - - def testFullDuplexCall(self): - with _CreateService() as (methods, stub): - responses = stub.FullDuplexCall( - _full_duplex_request_iterator(), - test_constants.LONG_TIMEOUT) - expected_responses = methods.FullDuplexCall( - _full_duplex_request_iterator(), - 'not a real RpcContext!') - for expected_response, response in moves.zip_longest( - expected_responses, responses): + def testUnaryCallFuture(self): + with _CreateService() as (methods, stub): + request = request_pb2.SimpleRequest(response_size=13) + # Check that the call does not block waiting for the server to respond. + with methods.pause(): + response_future = stub.UnaryCall.future( + request, test_constants.LONG_TIMEOUT) + response = response_future.result() + expected_response = methods.UnaryCall(request, 'not a real RpcContext!') self.assertEqual(expected_response, response) - def testFullDuplexCallExpired(self): - request_iterator = _full_duplex_request_iterator() - with _CreateService() as (methods, stub): - with methods.pause(): - responses = stub.FullDuplexCall( - request_iterator, test_constants.SHORT_TIMEOUT) - with self.assertRaises(face.ExpirationError): - list(responses) - - def testFullDuplexCallCancelled(self): - with _CreateService() as (methods, stub): - request_iterator = _full_duplex_request_iterator() - responses = stub.FullDuplexCall( - request_iterator, test_constants.LONG_TIMEOUT) - next(responses) - responses.cancel() - with self.assertRaises(face.CancellationError): - next(responses) - - def testFullDuplexCallFailed(self): - request_iterator = _full_duplex_request_iterator() - with _CreateService() as (methods, stub): - with methods.fail(): - responses = stub.FullDuplexCall( - request_iterator, test_constants.LONG_TIMEOUT) - self.assertIsNotNone(responses) - with self.assertRaises(face.RemoteError): - next(responses) - - def testHalfDuplexCall(self): - with _CreateService() as (methods, stub): - def half_duplex_request_iterator(): - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=1, interval_us=0) - yield request - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=2, interval_us=0) - request.response_parameters.add(size=3, interval_us=0) - yield request - responses = stub.HalfDuplexCall( - half_duplex_request_iterator(), test_constants.LONG_TIMEOUT) - expected_responses = methods.HalfDuplexCall( - half_duplex_request_iterator(), 'not a real RpcContext!') - for check in moves.zip_longest(expected_responses, responses): - expected_response, response = check + def testUnaryCallFutureExpired(self): + with _CreateService() as (methods, stub): + request = request_pb2.SimpleRequest(response_size=13) + with methods.pause(): + response_future = stub.UnaryCall.future( + request, test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + response_future.result() + + def testUnaryCallFutureCancelled(self): + with _CreateService() as (methods, stub): + request = request_pb2.SimpleRequest(response_size=13) + with methods.pause(): + response_future = stub.UnaryCall.future(request, 1) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + + def testUnaryCallFutureFailed(self): + with _CreateService() as (methods, stub): + request = request_pb2.SimpleRequest(response_size=13) + with methods.fail(): + response_future = stub.UnaryCall.future( + request, test_constants.LONG_TIMEOUT) + self.assertIsNotNone(response_future.exception()) + + def testStreamingOutputCall(self): + with _CreateService() as (methods, stub): + request = _streaming_output_request() + responses = stub.StreamingOutputCall(request, + test_constants.LONG_TIMEOUT) + expected_responses = methods.StreamingOutputCall( + request, 'not a real RpcContext!') + for expected_response, response in moves.zip_longest( + expected_responses, responses): + self.assertEqual(expected_response, response) + + def testStreamingOutputCallExpired(self): + with _CreateService() as (methods, stub): + request = _streaming_output_request() + with methods.pause(): + responses = stub.StreamingOutputCall( + request, test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + list(responses) + + def testStreamingOutputCallCancelled(self): + with _CreateService() as (methods, stub): + request = _streaming_output_request() + responses = stub.StreamingOutputCall(request, + test_constants.LONG_TIMEOUT) + next(responses) + responses.cancel() + with self.assertRaises(face.CancellationError): + next(responses) + + def testStreamingOutputCallFailed(self): + with _CreateService() as (methods, stub): + request = _streaming_output_request() + with methods.fail(): + responses = stub.StreamingOutputCall(request, 1) + self.assertIsNotNone(responses) + with self.assertRaises(face.RemoteError): + next(responses) + + def testStreamingInputCall(self): + with _CreateService() as (methods, stub): + response = stub.StreamingInputCall( + _streaming_input_request_iterator(), + test_constants.LONG_TIMEOUT) + expected_response = methods.StreamingInputCall( + _streaming_input_request_iterator(), 'not a real RpcContext!') self.assertEqual(expected_response, response) - def testHalfDuplexCallWedged(self): - condition = threading.Condition() - wait_cell = [False] - @contextlib.contextmanager - def wait(): # pylint: disable=invalid-name - # Where's Python 3's 'nonlocal' statement when you need it? - with condition: - wait_cell[0] = True - yield - with condition: - wait_cell[0] = False - condition.notify_all() - def half_duplex_request_iterator(): - request = request_pb2.StreamingOutputCallRequest() - request.response_parameters.add(size=1, interval_us=0) - yield request - with condition: - while wait_cell[0]: - condition.wait() - with _CreateService() as (methods, stub): - with wait(): - responses = stub.HalfDuplexCall( - half_duplex_request_iterator(), test_constants.SHORT_TIMEOUT) - # half-duplex waits for the client to send all info - with self.assertRaises(face.ExpirationError): - next(responses) + def testStreamingInputCallFuture(self): + with _CreateService() as (methods, stub): + with methods.pause(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(), + test_constants.LONG_TIMEOUT) + response = response_future.result() + expected_response = methods.StreamingInputCall( + _streaming_input_request_iterator(), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallFutureExpired(self): + with _CreateService() as (methods, stub): + with methods.pause(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(), + test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + response_future.result() + self.assertIsInstance(response_future.exception(), + face.ExpirationError) + + def testStreamingInputCallFutureCancelled(self): + with _CreateService() as (methods, stub): + with methods.pause(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(), + test_constants.LONG_TIMEOUT) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + + def testStreamingInputCallFutureFailed(self): + with _CreateService() as (methods, stub): + with methods.fail(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(), + test_constants.LONG_TIMEOUT) + self.assertIsNotNone(response_future.exception()) + + def testFullDuplexCall(self): + with _CreateService() as (methods, stub): + responses = stub.FullDuplexCall(_full_duplex_request_iterator(), + test_constants.LONG_TIMEOUT) + expected_responses = methods.FullDuplexCall( + _full_duplex_request_iterator(), 'not a real RpcContext!') + for expected_response, response in moves.zip_longest( + expected_responses, responses): + self.assertEqual(expected_response, response) + + def testFullDuplexCallExpired(self): + request_iterator = _full_duplex_request_iterator() + with _CreateService() as (methods, stub): + with methods.pause(): + responses = stub.FullDuplexCall(request_iterator, + test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + list(responses) + + def testFullDuplexCallCancelled(self): + with _CreateService() as (methods, stub): + request_iterator = _full_duplex_request_iterator() + responses = stub.FullDuplexCall(request_iterator, + test_constants.LONG_TIMEOUT) + next(responses) + responses.cancel() + with self.assertRaises(face.CancellationError): + next(responses) + + def testFullDuplexCallFailed(self): + request_iterator = _full_duplex_request_iterator() + with _CreateService() as (methods, stub): + with methods.fail(): + responses = stub.FullDuplexCall(request_iterator, + test_constants.LONG_TIMEOUT) + self.assertIsNotNone(responses) + with self.assertRaises(face.RemoteError): + next(responses) + + def testHalfDuplexCall(self): + with _CreateService() as (methods, stub): + + def half_duplex_request_iterator(): + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request + + responses = stub.HalfDuplexCall(half_duplex_request_iterator(), + test_constants.LONG_TIMEOUT) + expected_responses = methods.HalfDuplexCall( + half_duplex_request_iterator(), 'not a real RpcContext!') + for check in moves.zip_longest(expected_responses, responses): + expected_response, response = check + self.assertEqual(expected_response, response) + + def testHalfDuplexCallWedged(self): + condition = threading.Condition() + wait_cell = [False] + + @contextlib.contextmanager + def wait(): # pylint: disable=invalid-name + # Where's Python 3's 'nonlocal' statement when you need it? + with condition: + wait_cell[0] = True + yield + with condition: + wait_cell[0] = False + condition.notify_all() + + def half_duplex_request_iterator(): + request = request_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + with condition: + while wait_cell[0]: + condition.wait() + + with _CreateService() as (methods, stub): + with wait(): + responses = stub.HalfDuplexCall(half_duplex_request_iterator(), + test_constants.SHORT_TIMEOUT) + # half-duplex waits for the client to send all info + with self.assertRaises(face.ExpirationError): + next(responses) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py index 2f88fa04122..100a624dc9c 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py index 2f88fa04122..100a624dc9c 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_messages/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py index 2f88fa04122..100a624dc9c 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/invocation_testing/split_services/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/payload/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/requests/r/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/responses/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/protoc_plugin/protos/service/__init__.py b/src/python/grpcio_tests/tests/protoc_plugin/protos/service/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/protoc_plugin/protos/service/__init__.py +++ b/src/python/grpcio_tests/tests/protoc_plugin/protos/service/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/qps/benchmark_client.py b/src/python/grpcio_tests/tests/qps/benchmark_client.py index 650e4756e72..2e8afc8e7f9 100644 --- a/src/python/grpcio_tests/tests/qps/benchmark_client.py +++ b/src/python/grpcio_tests/tests/qps/benchmark_client.py @@ -26,7 +26,6 @@ # 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. - """Defines test client behaviors (UNARY/STREAMING) (SYNC/ASYNC).""" import abc @@ -47,165 +46,168 @@ _TIMEOUT = 60 * 60 * 24 class GenericStub(object): - def __init__(self, channel): - self.UnaryCall = channel.unary_unary( - '/grpc.testing.BenchmarkService/UnaryCall') - self.StreamingCall = channel.stream_stream( - '/grpc.testing.BenchmarkService/StreamingCall') + def __init__(self, channel): + self.UnaryCall = channel.unary_unary( + '/grpc.testing.BenchmarkService/UnaryCall') + self.StreamingCall = channel.stream_stream( + '/grpc.testing.BenchmarkService/StreamingCall') class BenchmarkClient: - """Benchmark client interface that exposes a non-blocking send_request().""" - - __metaclass__ = abc.ABCMeta - - def __init__(self, server, config, hist): - # Create the stub - if config.HasField('security_params'): - creds = grpc.ssl_channel_credentials(resources.test_root_certificates()) - channel = test_common.test_secure_channel( - server, creds, config.security_params.server_host_override) - else: - channel = grpc.insecure_channel(server) - - # waits for the channel to be ready before we start sending messages - grpc.channel_ready_future(channel).result() - - if config.payload_config.WhichOneof('payload') == 'simple_params': - self._generic = False - self._stub = services_pb2.BenchmarkServiceStub(channel) - payload = messages_pb2.Payload( - body='\0' * config.payload_config.simple_params.req_size) - self._request = messages_pb2.SimpleRequest( - payload=payload, - response_size=config.payload_config.simple_params.resp_size) - else: - self._generic = True - self._stub = GenericStub(channel) - self._request = '\0' * config.payload_config.bytebuf_params.req_size - - self._hist = hist - self._response_callbacks = [] - - def add_response_callback(self, callback): - """callback will be invoked as callback(client, query_time)""" - self._response_callbacks.append(callback) - - @abc.abstractmethod - def send_request(self): - """Non-blocking wrapper for a client's request operation.""" - raise NotImplementedError() - - def start(self): - pass - - def stop(self): - pass - - def _handle_response(self, client, query_time): - self._hist.add(query_time * 1e9) # Report times in nanoseconds - for callback in self._response_callbacks: - callback(client, query_time) + """Benchmark client interface that exposes a non-blocking send_request().""" + + __metaclass__ = abc.ABCMeta + + def __init__(self, server, config, hist): + # Create the stub + if config.HasField('security_params'): + creds = grpc.ssl_channel_credentials( + resources.test_root_certificates()) + channel = test_common.test_secure_channel( + server, creds, config.security_params.server_host_override) + else: + channel = grpc.insecure_channel(server) + + # waits for the channel to be ready before we start sending messages + grpc.channel_ready_future(channel).result() + + if config.payload_config.WhichOneof('payload') == 'simple_params': + self._generic = False + self._stub = services_pb2.BenchmarkServiceStub(channel) + payload = messages_pb2.Payload( + body='\0' * config.payload_config.simple_params.req_size) + self._request = messages_pb2.SimpleRequest( + payload=payload, + response_size=config.payload_config.simple_params.resp_size) + else: + self._generic = True + self._stub = GenericStub(channel) + self._request = '\0' * config.payload_config.bytebuf_params.req_size + + self._hist = hist + self._response_callbacks = [] + + def add_response_callback(self, callback): + """callback will be invoked as callback(client, query_time)""" + self._response_callbacks.append(callback) + + @abc.abstractmethod + def send_request(self): + """Non-blocking wrapper for a client's request operation.""" + raise NotImplementedError() + + def start(self): + pass + + def stop(self): + pass + + def _handle_response(self, client, query_time): + self._hist.add(query_time * 1e9) # Report times in nanoseconds + for callback in self._response_callbacks: + callback(client, query_time) class UnarySyncBenchmarkClient(BenchmarkClient): - def __init__(self, server, config, hist): - super(UnarySyncBenchmarkClient, self).__init__(server, config, hist) - self._pool = futures.ThreadPoolExecutor( - max_workers=config.outstanding_rpcs_per_channel) + def __init__(self, server, config, hist): + super(UnarySyncBenchmarkClient, self).__init__(server, config, hist) + self._pool = futures.ThreadPoolExecutor( + max_workers=config.outstanding_rpcs_per_channel) - def send_request(self): - # Send requests in seperate threads to support multiple outstanding rpcs - # (See src/proto/grpc/testing/control.proto) - self._pool.submit(self._dispatch_request) + def send_request(self): + # Send requests in seperate threads to support multiple outstanding rpcs + # (See src/proto/grpc/testing/control.proto) + self._pool.submit(self._dispatch_request) - def stop(self): - self._pool.shutdown(wait=True) - self._stub = None + def stop(self): + self._pool.shutdown(wait=True) + self._stub = None - def _dispatch_request(self): - start_time = time.time() - self._stub.UnaryCall(self._request, _TIMEOUT) - end_time = time.time() - self._handle_response(self, end_time - start_time) + def _dispatch_request(self): + start_time = time.time() + self._stub.UnaryCall(self._request, _TIMEOUT) + end_time = time.time() + self._handle_response(self, end_time - start_time) class UnaryAsyncBenchmarkClient(BenchmarkClient): - def send_request(self): - # Use the Future callback api to support multiple outstanding rpcs - start_time = time.time() - response_future = self._stub.UnaryCall.future(self._request, _TIMEOUT) - response_future.add_done_callback( - lambda resp: self._response_received(start_time, resp)) + def send_request(self): + # Use the Future callback api to support multiple outstanding rpcs + start_time = time.time() + response_future = self._stub.UnaryCall.future(self._request, _TIMEOUT) + response_future.add_done_callback( + lambda resp: self._response_received(start_time, resp)) - def _response_received(self, start_time, resp): - resp.result() - end_time = time.time() - self._handle_response(self, end_time - start_time) + def _response_received(self, start_time, resp): + resp.result() + end_time = time.time() + self._handle_response(self, end_time - start_time) - def stop(self): - self._stub = None + def stop(self): + self._stub = None class _SyncStream(object): - def __init__(self, stub, generic, request, handle_response): - self._stub = stub - self._generic = generic - self._request = request - self._handle_response = handle_response - self._is_streaming = False - self._request_queue = queue.Queue() - self._send_time_queue = queue.Queue() - - def send_request(self): - self._send_time_queue.put(time.time()) - self._request_queue.put(self._request) - - def start(self): - self._is_streaming = True - response_stream = self._stub.StreamingCall( - self._request_generator(), _TIMEOUT) - for _ in response_stream: - self._handle_response( - self, time.time() - self._send_time_queue.get_nowait()) - - def stop(self): - self._is_streaming = False - - def _request_generator(self): - while self._is_streaming: - try: - request = self._request_queue.get(block=True, timeout=1.0) - yield request - except queue.Empty: - pass + def __init__(self, stub, generic, request, handle_response): + self._stub = stub + self._generic = generic + self._request = request + self._handle_response = handle_response + self._is_streaming = False + self._request_queue = queue.Queue() + self._send_time_queue = queue.Queue() + + def send_request(self): + self._send_time_queue.put(time.time()) + self._request_queue.put(self._request) + + def start(self): + self._is_streaming = True + response_stream = self._stub.StreamingCall(self._request_generator(), + _TIMEOUT) + for _ in response_stream: + self._handle_response( + self, time.time() - self._send_time_queue.get_nowait()) + + def stop(self): + self._is_streaming = False + + def _request_generator(self): + while self._is_streaming: + try: + request = self._request_queue.get(block=True, timeout=1.0) + yield request + except queue.Empty: + pass class StreamingSyncBenchmarkClient(BenchmarkClient): - def __init__(self, server, config, hist): - super(StreamingSyncBenchmarkClient, self).__init__(server, config, hist) - self._pool = futures.ThreadPoolExecutor( - max_workers=config.outstanding_rpcs_per_channel) - self._streams = [_SyncStream(self._stub, self._generic, - self._request, self._handle_response) - for _ in xrange(config.outstanding_rpcs_per_channel)] - self._curr_stream = 0 - - def send_request(self): - # Use a round_robin scheduler to determine what stream to send on - self._streams[self._curr_stream].send_request() - self._curr_stream = (self._curr_stream + 1) % len(self._streams) - - def start(self): - for stream in self._streams: - self._pool.submit(stream.start) - - def stop(self): - for stream in self._streams: - stream.stop() - self._pool.shutdown(wait=True) - self._stub = None + def __init__(self, server, config, hist): + super(StreamingSyncBenchmarkClient, self).__init__(server, config, hist) + self._pool = futures.ThreadPoolExecutor( + max_workers=config.outstanding_rpcs_per_channel) + self._streams = [ + _SyncStream(self._stub, self._generic, self._request, + self._handle_response) + for _ in xrange(config.outstanding_rpcs_per_channel) + ] + self._curr_stream = 0 + + def send_request(self): + # Use a round_robin scheduler to determine what stream to send on + self._streams[self._curr_stream].send_request() + self._curr_stream = (self._curr_stream + 1) % len(self._streams) + + def start(self): + for stream in self._streams: + self._pool.submit(stream.start) + + def stop(self): + for stream in self._streams: + stream.stop() + self._pool.shutdown(wait=True) + self._stub = None diff --git a/src/python/grpcio_tests/tests/qps/benchmark_server.py b/src/python/grpcio_tests/tests/qps/benchmark_server.py index 2b76b810cdd..423d03b8042 100644 --- a/src/python/grpcio_tests/tests/qps/benchmark_server.py +++ b/src/python/grpcio_tests/tests/qps/benchmark_server.py @@ -32,27 +32,27 @@ from src.proto.grpc.testing import services_pb2 class BenchmarkServer(services_pb2.BenchmarkServiceServicer): - """Synchronous Server implementation for the Benchmark service.""" + """Synchronous Server implementation for the Benchmark service.""" - def UnaryCall(self, request, context): - payload = messages_pb2.Payload(body='\0' * request.response_size) - return messages_pb2.SimpleResponse(payload=payload) + def UnaryCall(self, request, context): + payload = messages_pb2.Payload(body='\0' * request.response_size) + return messages_pb2.SimpleResponse(payload=payload) - def StreamingCall(self, request_iterator, context): - for request in request_iterator: - payload = messages_pb2.Payload(body='\0' * request.response_size) - yield messages_pb2.SimpleResponse(payload=payload) + def StreamingCall(self, request_iterator, context): + for request in request_iterator: + payload = messages_pb2.Payload(body='\0' * request.response_size) + yield messages_pb2.SimpleResponse(payload=payload) class GenericBenchmarkServer(services_pb2.BenchmarkServiceServicer): - """Generic Server implementation for the Benchmark service.""" + """Generic Server implementation for the Benchmark service.""" - def __init__(self, resp_size): - self._response = '\0' * resp_size + def __init__(self, resp_size): + self._response = '\0' * resp_size - def UnaryCall(self, request, context): - return self._response + def UnaryCall(self, request, context): + return self._response - def StreamingCall(self, request_iterator, context): - for request in request_iterator: - yield self._response + def StreamingCall(self, request_iterator, context): + for request in request_iterator: + yield self._response diff --git a/src/python/grpcio_tests/tests/qps/client_runner.py b/src/python/grpcio_tests/tests/qps/client_runner.py index 1fd58687ad4..037092313c1 100644 --- a/src/python/grpcio_tests/tests/qps/client_runner.py +++ b/src/python/grpcio_tests/tests/qps/client_runner.py @@ -26,7 +26,6 @@ # 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. - """Defines behavior for WHEN clients send requests. Each client exposes a non-blocking send_request() method that the @@ -39,68 +38,68 @@ import time class ClientRunner: - """Abstract interface for sending requests from clients.""" + """Abstract interface for sending requests from clients.""" - __metaclass__ = abc.ABCMeta + __metaclass__ = abc.ABCMeta - def __init__(self, client): - self._client = client + def __init__(self, client): + self._client = client - @abc.abstractmethod - def start(self): - raise NotImplementedError() + @abc.abstractmethod + def start(self): + raise NotImplementedError() - @abc.abstractmethod - def stop(self): - raise NotImplementedError() + @abc.abstractmethod + def stop(self): + raise NotImplementedError() class OpenLoopClientRunner(ClientRunner): - def __init__(self, client, interval_generator): - super(OpenLoopClientRunner, self).__init__(client) - self._is_running = False - self._interval_generator = interval_generator - self._dispatch_thread = threading.Thread( - target=self._dispatch_requests, args=()) - - def start(self): - self._is_running = True - self._client.start() - self._dispatch_thread.start() - - def stop(self): - self._is_running = False - self._client.stop() - self._dispatch_thread.join() - self._client = None - - def _dispatch_requests(self): - while self._is_running: - self._client.send_request() - time.sleep(next(self._interval_generator)) + def __init__(self, client, interval_generator): + super(OpenLoopClientRunner, self).__init__(client) + self._is_running = False + self._interval_generator = interval_generator + self._dispatch_thread = threading.Thread( + target=self._dispatch_requests, args=()) + + def start(self): + self._is_running = True + self._client.start() + self._dispatch_thread.start() + + def stop(self): + self._is_running = False + self._client.stop() + self._dispatch_thread.join() + self._client = None + + def _dispatch_requests(self): + while self._is_running: + self._client.send_request() + time.sleep(next(self._interval_generator)) class ClosedLoopClientRunner(ClientRunner): - def __init__(self, client, request_count): - super(ClosedLoopClientRunner, self).__init__(client) - self._is_running = False - self._request_count = request_count - # Send a new request on each response for closed loop - self._client.add_response_callback(self._send_request) - - def start(self): - self._is_running = True - self._client.start() - for _ in xrange(self._request_count): - self._client.send_request() - - def stop(self): - self._is_running = False - self._client.stop() - self._client = None - - def _send_request(self, client, response_time): - if self._is_running: - client.send_request() + def __init__(self, client, request_count): + super(ClosedLoopClientRunner, self).__init__(client) + self._is_running = False + self._request_count = request_count + # Send a new request on each response for closed loop + self._client.add_response_callback(self._send_request) + + def start(self): + self._is_running = True + self._client.start() + for _ in xrange(self._request_count): + self._client.send_request() + + def stop(self): + self._is_running = False + self._client.stop() + self._client = None + + def _send_request(self, client, response_time): + if self._is_running: + client.send_request() diff --git a/src/python/grpcio_tests/tests/qps/histogram.py b/src/python/grpcio_tests/tests/qps/histogram.py index 9a7b5eb2ba6..61040b6f3bf 100644 --- a/src/python/grpcio_tests/tests/qps/histogram.py +++ b/src/python/grpcio_tests/tests/qps/histogram.py @@ -34,52 +34,52 @@ from src.proto.grpc.testing import stats_pb2 class Histogram(object): - """Histogram class used for recording performance testing data. + """Histogram class used for recording performance testing data. This class is thread safe. """ - def __init__(self, resolution, max_possible): - self._lock = threading.Lock() - self._resolution = resolution - self._max_possible = max_possible - self._sum = 0 - self._sum_of_squares = 0 - self.multiplier = 1.0 + self._resolution - self._count = 0 - self._min = self._max_possible - self._max = 0 - self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) + def __init__(self, resolution, max_possible): + self._lock = threading.Lock() + self._resolution = resolution + self._max_possible = max_possible + self._sum = 0 + self._sum_of_squares = 0 + self.multiplier = 1.0 + self._resolution + self._count = 0 + self._min = self._max_possible + self._max = 0 + self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) - def reset(self): - with self._lock: - self._sum = 0 - self._sum_of_squares = 0 - self._count = 0 - self._min = self._max_possible - self._max = 0 - self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) + def reset(self): + with self._lock: + self._sum = 0 + self._sum_of_squares = 0 + self._count = 0 + self._min = self._max_possible + self._max = 0 + self._buckets = [0] * (self._bucket_for(self._max_possible) + 1) - def add(self, val): - with self._lock: - self._sum += val - self._sum_of_squares += val * val - self._count += 1 - self._min = min(self._min, val) - self._max = max(self._max, val) - self._buckets[self._bucket_for(val)] += 1 + def add(self, val): + with self._lock: + self._sum += val + self._sum_of_squares += val * val + self._count += 1 + self._min = min(self._min, val) + self._max = max(self._max, val) + self._buckets[self._bucket_for(val)] += 1 - def get_data(self): - with self._lock: - data = stats_pb2.HistogramData() - data.bucket.extend(self._buckets) - data.min_seen = self._min - data.max_seen = self._max - data.sum = self._sum - data.sum_of_squares = self._sum_of_squares - data.count = self._count - return data + def get_data(self): + with self._lock: + data = stats_pb2.HistogramData() + data.bucket.extend(self._buckets) + data.min_seen = self._min + data.max_seen = self._max + data.sum = self._sum + data.sum_of_squares = self._sum_of_squares + data.count = self._count + return data - def _bucket_for(self, val): - val = min(val, self._max_possible) - return int(math.log(val, self.multiplier)) + def _bucket_for(self, val): + val = min(val, self._max_possible) + return int(math.log(val, self.multiplier)) diff --git a/src/python/grpcio_tests/tests/qps/qps_worker.py b/src/python/grpcio_tests/tests/qps/qps_worker.py index 2371ff09562..025dfb9d4a7 100644 --- a/src/python/grpcio_tests/tests/qps/qps_worker.py +++ b/src/python/grpcio_tests/tests/qps/qps_worker.py @@ -26,7 +26,6 @@ # 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. - """The entry point for the qps worker.""" import argparse @@ -40,22 +39,23 @@ from tests.qps import worker_server def run_worker_server(port): - server = grpc.server(futures.ThreadPoolExecutor(max_workers=5)) - servicer = worker_server.WorkerServer() - services_pb2.add_WorkerServiceServicer_to_server(servicer, server) - server.add_insecure_port('[::]:{}'.format(port)) - server.start() - servicer.wait_for_quit() - server.stop(0) + server = grpc.server(futures.ThreadPoolExecutor(max_workers=5)) + servicer = worker_server.WorkerServer() + services_pb2.add_WorkerServiceServicer_to_server(servicer, server) + server.add_insecure_port('[::]:{}'.format(port)) + server.start() + servicer.wait_for_quit() + server.stop(0) if __name__ == '__main__': - parser = argparse.ArgumentParser( - description='gRPC Python performance testing worker') - parser.add_argument('--driver_port', - type=int, - dest='port', - help='The port the worker should listen on') - args = parser.parse_args() - - run_worker_server(args.port) + parser = argparse.ArgumentParser( + description='gRPC Python performance testing worker') + parser.add_argument( + '--driver_port', + type=int, + dest='port', + help='The port the worker should listen on') + args = parser.parse_args() + + run_worker_server(args.port) diff --git a/src/python/grpcio_tests/tests/qps/worker_server.py b/src/python/grpcio_tests/tests/qps/worker_server.py index 46d542940f1..1deb7ed698c 100644 --- a/src/python/grpcio_tests/tests/qps/worker_server.py +++ b/src/python/grpcio_tests/tests/qps/worker_server.py @@ -46,149 +46,156 @@ from tests.unit import resources class WorkerServer(services_pb2.WorkerServiceServicer): - """Python Worker Server implementation.""" - - def __init__(self): - self._quit_event = threading.Event() - - def RunServer(self, request_iterator, context): - config = next(request_iterator).setup - server, port = self._create_server(config) - cores = multiprocessing.cpu_count() - server.start() - start_time = time.time() - yield self._get_server_status(start_time, start_time, port, cores) - - for request in request_iterator: - end_time = time.time() - status = self._get_server_status(start_time, end_time, port, cores) - if request.mark.reset: - start_time = end_time - yield status - server.stop(None) - - def _get_server_status(self, start_time, end_time, port, cores): - end_time = time.time() - elapsed_time = end_time - start_time - stats = stats_pb2.ServerStats(time_elapsed=elapsed_time, - time_user=elapsed_time, - time_system=elapsed_time) - return control_pb2.ServerStatus(stats=stats, port=port, cores=cores) - - def _create_server(self, config): - if config.async_server_threads == 0: - # This is the default concurrent.futures thread pool size, but - # None doesn't seem to work - server_threads = multiprocessing.cpu_count() * 5 - else: - server_threads = config.async_server_threads - server = grpc.server(futures.ThreadPoolExecutor( - max_workers=server_threads)) - if config.server_type == control_pb2.ASYNC_SERVER: - servicer = benchmark_server.BenchmarkServer() - services_pb2.add_BenchmarkServiceServicer_to_server(servicer, server) - elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER: - resp_size = config.payload_config.bytebuf_params.resp_size - servicer = benchmark_server.GenericBenchmarkServer(resp_size) - method_implementations = { - 'StreamingCall': - grpc.stream_stream_rpc_method_handler(servicer.StreamingCall), - 'UnaryCall': - grpc.unary_unary_rpc_method_handler(servicer.UnaryCall), - } - handler = grpc.method_handlers_generic_handler( - 'grpc.testing.BenchmarkService', method_implementations) - server.add_generic_rpc_handlers((handler,)) - else: - raise Exception('Unsupported server type {}'.format(config.server_type)) - - if config.HasField('security_params'): # Use SSL - server_creds = grpc.ssl_server_credentials( - ((resources.private_key(), resources.certificate_chain()),)) - port = server.add_secure_port('[::]:{}'.format(config.port), server_creds) - else: - port = server.add_insecure_port('[::]:{}'.format(config.port)) - - return (server, port) - - def RunClient(self, request_iterator, context): - config = next(request_iterator).setup - client_runners = [] - qps_data = histogram.Histogram(config.histogram_params.resolution, - config.histogram_params.max_possible) - start_time = time.time() - - # Create a client for each channel - for i in xrange(config.client_channels): - server = config.server_targets[i % len(config.server_targets)] - runner = self._create_client_runner(server, config, qps_data) - client_runners.append(runner) - runner.start() - - end_time = time.time() - yield self._get_client_status(start_time, end_time, qps_data) - - # Respond to stat requests - for request in request_iterator: - end_time = time.time() - status = self._get_client_status(start_time, end_time, qps_data) - if request.mark.reset: - qps_data.reset() + """Python Worker Server implementation.""" + + def __init__(self): + self._quit_event = threading.Event() + + def RunServer(self, request_iterator, context): + config = next(request_iterator).setup + server, port = self._create_server(config) + cores = multiprocessing.cpu_count() + server.start() start_time = time.time() - yield status - - # Cleanup the clients - for runner in client_runners: - runner.stop() - - def _get_client_status(self, start_time, end_time, qps_data): - latencies = qps_data.get_data() - end_time = time.time() - elapsed_time = end_time - start_time - stats = stats_pb2.ClientStats(latencies=latencies, - time_elapsed=elapsed_time, - time_user=elapsed_time, - time_system=elapsed_time) - return control_pb2.ClientStatus(stats=stats) - - def _create_client_runner(self, server, config, qps_data): - if config.client_type == control_pb2.SYNC_CLIENT: - if config.rpc_type == control_pb2.UNARY: - client = benchmark_client.UnarySyncBenchmarkClient( - server, config, qps_data) - elif config.rpc_type == control_pb2.STREAMING: - client = benchmark_client.StreamingSyncBenchmarkClient( - server, config, qps_data) - elif config.client_type == control_pb2.ASYNC_CLIENT: - if config.rpc_type == control_pb2.UNARY: - client = benchmark_client.UnaryAsyncBenchmarkClient( - server, config, qps_data) - else: - raise Exception('Async streaming client not supported') - else: - raise Exception('Unsupported client type {}'.format(config.client_type)) - - # In multi-channel tests, we split the load across all channels - load_factor = float(config.client_channels) - if config.load_params.WhichOneof('load') == 'closed_loop': - runner = client_runner.ClosedLoopClientRunner( - client, config.outstanding_rpcs_per_channel) - else: # Open loop Poisson - alpha = config.load_params.poisson.offered_load / load_factor - def poisson(): - while True: - yield random.expovariate(alpha) - - runner = client_runner.OpenLoopClientRunner(client, poisson()) - - return runner - - def CoreCount(self, request, context): - return control_pb2.CoreResponse(cores=multiprocessing.cpu_count()) - - def QuitWorker(self, request, context): - self._quit_event.set() - return control_pb2.Void() - - def wait_for_quit(self): - self._quit_event.wait() + yield self._get_server_status(start_time, start_time, port, cores) + + for request in request_iterator: + end_time = time.time() + status = self._get_server_status(start_time, end_time, port, cores) + if request.mark.reset: + start_time = end_time + yield status + server.stop(None) + + def _get_server_status(self, start_time, end_time, port, cores): + end_time = time.time() + elapsed_time = end_time - start_time + stats = stats_pb2.ServerStats( + time_elapsed=elapsed_time, + time_user=elapsed_time, + time_system=elapsed_time) + return control_pb2.ServerStatus(stats=stats, port=port, cores=cores) + + def _create_server(self, config): + if config.async_server_threads == 0: + # This is the default concurrent.futures thread pool size, but + # None doesn't seem to work + server_threads = multiprocessing.cpu_count() * 5 + else: + server_threads = config.async_server_threads + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=server_threads)) + if config.server_type == control_pb2.ASYNC_SERVER: + servicer = benchmark_server.BenchmarkServer() + services_pb2.add_BenchmarkServiceServicer_to_server(servicer, + server) + elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER: + resp_size = config.payload_config.bytebuf_params.resp_size + servicer = benchmark_server.GenericBenchmarkServer(resp_size) + method_implementations = { + 'StreamingCall': + grpc.stream_stream_rpc_method_handler(servicer.StreamingCall), + 'UnaryCall': + grpc.unary_unary_rpc_method_handler(servicer.UnaryCall), + } + handler = grpc.method_handlers_generic_handler( + 'grpc.testing.BenchmarkService', method_implementations) + server.add_generic_rpc_handlers((handler,)) + else: + raise Exception('Unsupported server type {}'.format( + config.server_type)) + + if config.HasField('security_params'): # Use SSL + server_creds = grpc.ssl_server_credentials(( + (resources.private_key(), resources.certificate_chain()),)) + port = server.add_secure_port('[::]:{}'.format(config.port), + server_creds) + else: + port = server.add_insecure_port('[::]:{}'.format(config.port)) + + return (server, port) + + def RunClient(self, request_iterator, context): + config = next(request_iterator).setup + client_runners = [] + qps_data = histogram.Histogram(config.histogram_params.resolution, + config.histogram_params.max_possible) + start_time = time.time() + + # Create a client for each channel + for i in xrange(config.client_channels): + server = config.server_targets[i % len(config.server_targets)] + runner = self._create_client_runner(server, config, qps_data) + client_runners.append(runner) + runner.start() + + end_time = time.time() + yield self._get_client_status(start_time, end_time, qps_data) + + # Respond to stat requests + for request in request_iterator: + end_time = time.time() + status = self._get_client_status(start_time, end_time, qps_data) + if request.mark.reset: + qps_data.reset() + start_time = time.time() + yield status + + # Cleanup the clients + for runner in client_runners: + runner.stop() + + def _get_client_status(self, start_time, end_time, qps_data): + latencies = qps_data.get_data() + end_time = time.time() + elapsed_time = end_time - start_time + stats = stats_pb2.ClientStats( + latencies=latencies, + time_elapsed=elapsed_time, + time_user=elapsed_time, + time_system=elapsed_time) + return control_pb2.ClientStatus(stats=stats) + + def _create_client_runner(self, server, config, qps_data): + if config.client_type == control_pb2.SYNC_CLIENT: + if config.rpc_type == control_pb2.UNARY: + client = benchmark_client.UnarySyncBenchmarkClient( + server, config, qps_data) + elif config.rpc_type == control_pb2.STREAMING: + client = benchmark_client.StreamingSyncBenchmarkClient( + server, config, qps_data) + elif config.client_type == control_pb2.ASYNC_CLIENT: + if config.rpc_type == control_pb2.UNARY: + client = benchmark_client.UnaryAsyncBenchmarkClient( + server, config, qps_data) + else: + raise Exception('Async streaming client not supported') + else: + raise Exception('Unsupported client type {}'.format( + config.client_type)) + + # In multi-channel tests, we split the load across all channels + load_factor = float(config.client_channels) + if config.load_params.WhichOneof('load') == 'closed_loop': + runner = client_runner.ClosedLoopClientRunner( + client, config.outstanding_rpcs_per_channel) + else: # Open loop Poisson + alpha = config.load_params.poisson.offered_load / load_factor + + def poisson(): + while True: + yield random.expovariate(alpha) + + runner = client_runner.OpenLoopClientRunner(client, poisson()) + + return runner + + def CoreCount(self, request, context): + return control_pb2.CoreResponse(cores=multiprocessing.cpu_count()) + + def QuitWorker(self, request, context): + self._quit_event.set() + return control_pb2.Void() + + def wait_for_quit(self): + self._quit_event.wait() diff --git a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py index 43d6c971b52..76e89ca039f 100644 --- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py +++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of grpc_reflection.v1alpha.reflection.""" import unittest @@ -45,141 +44,112 @@ from tests.unit.framework.common import test_constants _EMPTY_PROTO_FILE_NAME = 'src/proto/grpc/testing/empty.proto' _EMPTY_PROTO_SYMBOL_NAME = 'grpc.testing.Empty' -_SERVICE_NAMES = ( - 'Angstrom', 'Bohr', 'Curie', 'Dyson', 'Einstein', 'Feynman', 'Galilei') +_SERVICE_NAMES = ('Angstrom', 'Bohr', 'Curie', 'Dyson', 'Einstein', 'Feynman', + 'Galilei') + def _file_descriptor_to_proto(descriptor): - proto = descriptor_pb2.FileDescriptorProto() - descriptor.CopyToProto(proto) - return proto.SerializeToString() + proto = descriptor_pb2.FileDescriptorProto() + descriptor.CopyToProto(proto) + return proto.SerializeToString() + class ReflectionServicerTest(unittest.TestCase): - def setUp(self): - servicer = reflection.ReflectionServicer(service_names=_SERVICE_NAMES) - server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server(server_pool) - port = self._server.add_insecure_port('[::]:0') - reflection_pb2.add_ServerReflectionServicer_to_server(servicer, self._server) - self._server.start() - - channel = grpc.insecure_channel('localhost:%d' % port) - self._stub = reflection_pb2.ServerReflectionStub(channel) - - def testFileByName(self): - requests = ( - reflection_pb2.ServerReflectionRequest( - file_by_filename=_EMPTY_PROTO_FILE_NAME - ), - reflection_pb2.ServerReflectionRequest( - file_by_filename='i-donut-exist' - ), - ) - responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) - expected_responses = ( - reflection_pb2.ServerReflectionResponse( - valid_host='', - file_descriptor_response=reflection_pb2.FileDescriptorResponse( - file_descriptor_proto=( - _file_descriptor_to_proto(empty_pb2.DESCRIPTOR), - ) - ) - ), - reflection_pb2.ServerReflectionResponse( - valid_host='', - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.NOT_FOUND.value[0], - error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), - ) - ), - ) - self.assertSequenceEqual(expected_responses, responses) - - def testFileBySymbol(self): - requests = ( - reflection_pb2.ServerReflectionRequest( - file_containing_symbol=_EMPTY_PROTO_SYMBOL_NAME - ), - reflection_pb2.ServerReflectionRequest( - file_containing_symbol='i.donut.exist.co.uk.org.net.me.name.foo' - ), - ) - responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) - expected_responses = ( - reflection_pb2.ServerReflectionResponse( - valid_host='', - file_descriptor_response=reflection_pb2.FileDescriptorResponse( - file_descriptor_proto=( - _file_descriptor_to_proto(empty_pb2.DESCRIPTOR), - ) - ) - ), - reflection_pb2.ServerReflectionResponse( - valid_host='', - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.NOT_FOUND.value[0], - error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), - ) - ), - ) - self.assertSequenceEqual(expected_responses, responses) - - @unittest.skip('TODO(atash): implement file-containing-extension reflection ' - '(see https://github.com/google/protobuf/issues/2248)') - def testFileContainingExtension(self): - requests = ( - reflection_pb2.ServerReflectionRequest( - file_containing_extension=reflection_pb2.ExtensionRequest( - containing_type='grpc.testing.proto2.Empty', - extension_number=125, - ), - ), - reflection_pb2.ServerReflectionRequest( - file_containing_extension=reflection_pb2.ExtensionRequest( - containing_type='i.donut.exist.co.uk.org.net.me.name.foo', - extension_number=55, - ), - ), - ) - responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) - expected_responses = ( - reflection_pb2.ServerReflectionResponse( - valid_host='', - file_descriptor_response=reflection_pb2.FileDescriptorResponse( - file_descriptor_proto=( - _file_descriptor_to_proto(empty_extensions_pb2.DESCRIPTOR), - ) - ) - ), - reflection_pb2.ServerReflectionResponse( - valid_host='', - error_response=reflection_pb2.ErrorResponse( - error_code=grpc.StatusCode.NOT_FOUND.value[0], - error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), - ) - ), - ) - self.assertSequenceEqual(expected_responses, responses) - - def testListServices(self): - requests = ( - reflection_pb2.ServerReflectionRequest( - list_services='', - ), - ) - responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) - expected_responses = ( - reflection_pb2.ServerReflectionResponse( - valid_host='', - list_services_response=reflection_pb2.ListServiceResponse( - service=tuple( - reflection_pb2.ServiceResponse(name=name) - for name in _SERVICE_NAMES - ) - ) - ), - ) - self.assertSequenceEqual(expected_responses, responses) + def setUp(self): + servicer = reflection.ReflectionServicer(service_names=_SERVICE_NAMES) + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server(server_pool) + port = self._server.add_insecure_port('[::]:0') + reflection_pb2.add_ServerReflectionServicer_to_server(servicer, + self._server) + self._server.start() + + channel = grpc.insecure_channel('localhost:%d' % port) + self._stub = reflection_pb2.ServerReflectionStub(channel) + + def testFileByName(self): + requests = ( + reflection_pb2.ServerReflectionRequest( + file_by_filename=_EMPTY_PROTO_FILE_NAME), + reflection_pb2.ServerReflectionRequest( + file_by_filename='i-donut-exist'),) + responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) + expected_responses = ( + reflection_pb2.ServerReflectionResponse( + valid_host='', + file_descriptor_response=reflection_pb2.FileDescriptorResponse( + file_descriptor_proto=( + _file_descriptor_to_proto(empty_pb2.DESCRIPTOR),))), + reflection_pb2.ServerReflectionResponse( + valid_host='', + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.NOT_FOUND.value[0], + error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), + )),) + self.assertSequenceEqual(expected_responses, responses) + + def testFileBySymbol(self): + requests = ( + reflection_pb2.ServerReflectionRequest( + file_containing_symbol=_EMPTY_PROTO_SYMBOL_NAME), + reflection_pb2.ServerReflectionRequest( + file_containing_symbol='i.donut.exist.co.uk.org.net.me.name.foo' + ),) + responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) + expected_responses = ( + reflection_pb2.ServerReflectionResponse( + valid_host='', + file_descriptor_response=reflection_pb2.FileDescriptorResponse( + file_descriptor_proto=( + _file_descriptor_to_proto(empty_pb2.DESCRIPTOR),))), + reflection_pb2.ServerReflectionResponse( + valid_host='', + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.NOT_FOUND.value[0], + error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), + )),) + self.assertSequenceEqual(expected_responses, responses) + + @unittest.skip( + 'TODO(atash): implement file-containing-extension reflection ' + '(see https://github.com/google/protobuf/issues/2248)') + def testFileContainingExtension(self): + requests = ( + reflection_pb2.ServerReflectionRequest( + file_containing_extension=reflection_pb2.ExtensionRequest( + containing_type='grpc.testing.proto2.Empty', + extension_number=125,),), + reflection_pb2.ServerReflectionRequest( + file_containing_extension=reflection_pb2.ExtensionRequest( + containing_type='i.donut.exist.co.uk.org.net.me.name.foo', + extension_number=55,),),) + responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) + expected_responses = ( + reflection_pb2.ServerReflectionResponse( + valid_host='', + file_descriptor_response=reflection_pb2.FileDescriptorResponse( + file_descriptor_proto=(_file_descriptor_to_proto( + empty_extensions_pb2.DESCRIPTOR),))), + reflection_pb2.ServerReflectionResponse( + valid_host='', + error_response=reflection_pb2.ErrorResponse( + error_code=grpc.StatusCode.NOT_FOUND.value[0], + error_message=grpc.StatusCode.NOT_FOUND.value[1].encode(), + )),) + self.assertSequenceEqual(expected_responses, responses) + + def testListServices(self): + requests = (reflection_pb2.ServerReflectionRequest(list_services='',),) + responses = tuple(self._stub.ServerReflectionInfo(iter(requests))) + expected_responses = (reflection_pb2.ServerReflectionResponse( + valid_host='', + list_services_response=reflection_pb2.ListServiceResponse( + service=tuple( + reflection_pb2.ServiceResponse(name=name) + for name in _SERVICE_NAMES))),) + self.assertSequenceEqual(expected_responses, responses) + if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/stress/client.py b/src/python/grpcio_tests/tests/stress/client.py index b8116729b57..61f9e1c6b17 100644 --- a/src/python/grpcio_tests/tests/stress/client.py +++ b/src/python/grpcio_tests/tests/stress/client.py @@ -26,7 +26,6 @@ # 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. - """Entry point for running stress tests.""" import argparse @@ -46,118 +45,132 @@ from tests.stress import test_runner def _args(): - parser = argparse.ArgumentParser(description='gRPC Python stress test client') - parser.add_argument( - '--server_addresses', - help='comma seperated list of hostname:port to run servers on', - default='localhost:8080', type=str) - parser.add_argument( - '--test_cases', - help='comma seperated list of testcase:weighting of tests to run', - default='large_unary:100', - type=str) - parser.add_argument( - '--test_duration_secs', - help='number of seconds to run the stress test', - default=-1, type=int) - parser.add_argument( - '--num_channels_per_server', - help='number of channels per server', - default=1, type=int) - parser.add_argument( - '--num_stubs_per_channel', - help='number of stubs to create per channel', - default=1, type=int) - parser.add_argument( - '--metrics_port', - help='the port to listen for metrics requests on', - default=8081, type=int) - parser.add_argument( - '--use_test_ca', - help='Whether to use our fake CA. Requires --use_tls=true', - default=False, type=bool) - parser.add_argument( - '--use_tls', - help='Whether to use TLS', default=False, type=bool) - parser.add_argument( - '--server_host_override', default="foo.test.google.fr", - help='the server host to which to claim to connect', type=str) - return parser.parse_args() + parser = argparse.ArgumentParser( + description='gRPC Python stress test client') + parser.add_argument( + '--server_addresses', + help='comma seperated list of hostname:port to run servers on', + default='localhost:8080', + type=str) + parser.add_argument( + '--test_cases', + help='comma seperated list of testcase:weighting of tests to run', + default='large_unary:100', + type=str) + parser.add_argument( + '--test_duration_secs', + help='number of seconds to run the stress test', + default=-1, + type=int) + parser.add_argument( + '--num_channels_per_server', + help='number of channels per server', + default=1, + type=int) + parser.add_argument( + '--num_stubs_per_channel', + help='number of stubs to create per channel', + default=1, + type=int) + parser.add_argument( + '--metrics_port', + help='the port to listen for metrics requests on', + default=8081, + type=int) + parser.add_argument( + '--use_test_ca', + help='Whether to use our fake CA. Requires --use_tls=true', + default=False, + type=bool) + parser.add_argument( + '--use_tls', help='Whether to use TLS', default=False, type=bool) + parser.add_argument( + '--server_host_override', + default="foo.test.google.fr", + help='the server host to which to claim to connect', + type=str) + return parser.parse_args() def _test_case_from_arg(test_case_arg): - for test_case in methods.TestCase: - if test_case_arg == test_case.value: - return test_case - else: - raise ValueError('No test case {}!'.format(test_case_arg)) + for test_case in methods.TestCase: + if test_case_arg == test_case.value: + return test_case + else: + raise ValueError('No test case {}!'.format(test_case_arg)) def _parse_weighted_test_cases(test_case_args): - weighted_test_cases = {} - for test_case_arg in test_case_args.split(','): - name, weight = test_case_arg.split(':', 1) - test_case = _test_case_from_arg(name) - weighted_test_cases[test_case] = int(weight) - return weighted_test_cases + weighted_test_cases = {} + for test_case_arg in test_case_args.split(','): + name, weight = test_case_arg.split(':', 1) + test_case = _test_case_from_arg(name) + weighted_test_cases[test_case] = int(weight) + return weighted_test_cases + def _get_channel(target, args): - if args.use_tls: - if args.use_test_ca: - root_certificates = resources.test_root_certificates() + if args.use_tls: + if args.use_test_ca: + root_certificates = resources.test_root_certificates() + else: + root_certificates = None # will load default roots. + channel_credentials = grpc.ssl_channel_credentials( + root_certificates=root_certificates) + options = (( + 'grpc.ssl_target_name_override', + args.server_host_override,),) + channel = grpc.secure_channel( + target, channel_credentials, options=options) else: - root_certificates = None # will load default roots. - channel_credentials = grpc.ssl_channel_credentials( - root_certificates=root_certificates) - options = (('grpc.ssl_target_name_override', args.server_host_override,),) - channel = grpc.secure_channel(target, channel_credentials, options=options) - else: - channel = grpc.insecure_channel(target) - - # waits for the channel to be ready before we start sending messages - grpc.channel_ready_future(channel).result() - return channel + channel = grpc.insecure_channel(target) + + # waits for the channel to be ready before we start sending messages + grpc.channel_ready_future(channel).result() + return channel + def run_test(args): - test_cases = _parse_weighted_test_cases(args.test_cases) - test_server_targets = args.server_addresses.split(',') - # Propagate any client exceptions with a queue - exception_queue = queue.Queue() - stop_event = threading.Event() - hist = histogram.Histogram(1, 1) - runners = [] - - server = grpc.server(futures.ThreadPoolExecutor(max_workers=25)) - metrics_pb2.add_MetricsServiceServicer_to_server( - metrics_server.MetricsServer(hist), server) - server.add_insecure_port('[::]:{}'.format(args.metrics_port)) - server.start() - - for test_server_target in test_server_targets: - for _ in xrange(args.num_channels_per_server): - channel = _get_channel(test_server_target, args) - for _ in xrange(args.num_stubs_per_channel): - stub = test_pb2.TestServiceStub(channel) - runner = test_runner.TestRunner(stub, test_cases, hist, - exception_queue, stop_event) - runners.append(runner) - - for runner in runners: - runner.start() - try: - timeout_secs = args.test_duration_secs - if timeout_secs < 0: - timeout_secs = None - raise exception_queue.get(block=True, timeout=timeout_secs) - except queue.Empty: - # No exceptions thrown, success - pass - finally: - stop_event.set() + test_cases = _parse_weighted_test_cases(args.test_cases) + test_server_targets = args.server_addresses.split(',') + # Propagate any client exceptions with a queue + exception_queue = queue.Queue() + stop_event = threading.Event() + hist = histogram.Histogram(1, 1) + runners = [] + + server = grpc.server(futures.ThreadPoolExecutor(max_workers=25)) + metrics_pb2.add_MetricsServiceServicer_to_server( + metrics_server.MetricsServer(hist), server) + server.add_insecure_port('[::]:{}'.format(args.metrics_port)) + server.start() + + for test_server_target in test_server_targets: + for _ in xrange(args.num_channels_per_server): + channel = _get_channel(test_server_target, args) + for _ in xrange(args.num_stubs_per_channel): + stub = test_pb2.TestServiceStub(channel) + runner = test_runner.TestRunner(stub, test_cases, hist, + exception_queue, stop_event) + runners.append(runner) + for runner in runners: - runner.join() - runner = None - server.stop(None) + runner.start() + try: + timeout_secs = args.test_duration_secs + if timeout_secs < 0: + timeout_secs = None + raise exception_queue.get(block=True, timeout=timeout_secs) + except queue.Empty: + # No exceptions thrown, success + pass + finally: + stop_event.set() + for runner in runners: + runner.join() + runner = None + server.stop(None) + if __name__ == '__main__': - run_test(_args()) + run_test(_args()) diff --git a/src/python/grpcio_tests/tests/stress/metrics_server.py b/src/python/grpcio_tests/tests/stress/metrics_server.py index 33dd1d6f2ad..3a4cbc27ba3 100644 --- a/src/python/grpcio_tests/tests/stress/metrics_server.py +++ b/src/python/grpcio_tests/tests/stress/metrics_server.py @@ -26,7 +26,6 @@ # 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. - """MetricsService for publishing stress test qps data.""" import time @@ -38,23 +37,23 @@ GAUGE_NAME = 'python_overall_qps' class MetricsServer(metrics_pb2.MetricsServiceServicer): - def __init__(self, histogram): - self._start_time = time.time() - self._histogram = histogram - - def _get_qps(self): - count = self._histogram.get_data().count - delta = time.time() - self._start_time - self._histogram.reset() - self._start_time = time.time() - return int(count/delta) - - def GetAllGauges(self, request, context): - qps = self._get_qps() - return [metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)] - - def GetGauge(self, request, context): - if request.name != GAUGE_NAME: - raise Exception('Gauge {} does not exist'.format(request.name)) - qps = self._get_qps() - return metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps) + def __init__(self, histogram): + self._start_time = time.time() + self._histogram = histogram + + def _get_qps(self): + count = self._histogram.get_data().count + delta = time.time() - self._start_time + self._histogram.reset() + self._start_time = time.time() + return int(count / delta) + + def GetAllGauges(self, request, context): + qps = self._get_qps() + return [metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps)] + + def GetGauge(self, request, context): + if request.name != GAUGE_NAME: + raise Exception('Gauge {} does not exist'.format(request.name)) + qps = self._get_qps() + return metrics_pb2.GaugeResponse(name=GAUGE_NAME, long_value=qps) diff --git a/src/python/grpcio_tests/tests/stress/test_runner.py b/src/python/grpcio_tests/tests/stress/test_runner.py index 88f13727e37..258abe9c217 100644 --- a/src/python/grpcio_tests/tests/stress/test_runner.py +++ b/src/python/grpcio_tests/tests/stress/test_runner.py @@ -26,7 +26,6 @@ # 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. - """Thread that sends random weighted requests on a TestService stub.""" import random @@ -36,38 +35,38 @@ import traceback def _weighted_test_case_generator(weighted_cases): - weight_sum = sum(weighted_cases.itervalues()) + weight_sum = sum(weighted_cases.itervalues()) - while True: - val = random.uniform(0, weight_sum) - partial_sum = 0 - for case in weighted_cases: - partial_sum += weighted_cases[case] - if val <= partial_sum: - yield case - break + while True: + val = random.uniform(0, weight_sum) + partial_sum = 0 + for case in weighted_cases: + partial_sum += weighted_cases[case] + if val <= partial_sum: + yield case + break class TestRunner(threading.Thread): - def __init__(self, stub, test_cases, hist, exception_queue, stop_event): - super(TestRunner, self).__init__() - self._exception_queue = exception_queue - self._stop_event = stop_event - self._stub = stub - self._test_cases = _weighted_test_case_generator(test_cases) - self._histogram = hist + def __init__(self, stub, test_cases, hist, exception_queue, stop_event): + super(TestRunner, self).__init__() + self._exception_queue = exception_queue + self._stop_event = stop_event + self._stub = stub + self._test_cases = _weighted_test_case_generator(test_cases) + self._histogram = hist - def run(self): - while not self._stop_event.is_set(): - try: - test_case = next(self._test_cases) - start_time = time.time() - test_case.test_interoperability(self._stub, None) - end_time = time.time() - self._histogram.add((end_time - start_time)*1e9) - except Exception as e: - traceback.print_exc() - self._exception_queue.put( - Exception("An exception occured during test {}" - .format(test_case), e)) + def run(self): + while not self._stop_event.is_set(): + try: + test_case = next(self._test_cases) + start_time = time.time() + test_case.test_interoperability(self._stub, None) + end_time = time.time() + self._histogram.add((end_time - start_time) * 1e9) + except Exception as e: + traceback.print_exc() + self._exception_queue.put( + Exception("An exception occured during test {}" + .format(test_case), e)) diff --git a/src/python/grpcio_tests/tests/unit/__init__.py b/src/python/grpcio_tests/tests/unit/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/__init__.py +++ b/src/python/grpcio_tests/tests/unit/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/_api_test.py b/src/python/grpcio_tests/tests/unit/_api_test.py index 51dc4254208..5435c5500cc 100644 --- a/src/python/grpcio_tests/tests/unit/_api_test.py +++ b/src/python/grpcio_tests/tests/unit/_api_test.py @@ -26,7 +26,6 @@ # 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. - """Test of gRPC Python's application-layer API.""" import unittest @@ -40,73 +39,71 @@ from tests.unit import _from_grpc_import_star class AllTest(unittest.TestCase): - def testAll(self): - expected_grpc_code_elements = ( - 'FutureTimeoutError', - 'FutureCancelledError', - 'Future', - 'ChannelConnectivity', - 'StatusCode', - 'RpcError', - 'RpcContext', - 'Call', - 'ChannelCredentials', - 'CallCredentials', - 'AuthMetadataContext', - 'AuthMetadataPluginCallback', - 'AuthMetadataPlugin', - 'ServerCredentials', - 'UnaryUnaryMultiCallable', - 'UnaryStreamMultiCallable', - 'StreamUnaryMultiCallable', - 'StreamStreamMultiCallable', - 'Channel', - 'ServicerContext', - 'RpcMethodHandler', - 'HandlerCallDetails', - 'GenericRpcHandler', - 'ServiceRpcHandler', - 'Server', - 'unary_unary_rpc_method_handler', - 'unary_stream_rpc_method_handler', - 'stream_unary_rpc_method_handler', - 'stream_stream_rpc_method_handler', - 'method_handlers_generic_handler', - 'ssl_channel_credentials', - 'metadata_call_credentials', - 'access_token_call_credentials', - 'composite_call_credentials', - 'composite_channel_credentials', - 'ssl_server_credentials', - 'channel_ready_future', - 'insecure_channel', - 'secure_channel', - 'server', - ) - - six.assertCountEqual( - self, expected_grpc_code_elements, - _from_grpc_import_star.GRPC_ELEMENTS) + def testAll(self): + expected_grpc_code_elements = ( + 'FutureTimeoutError', + 'FutureCancelledError', + 'Future', + 'ChannelConnectivity', + 'StatusCode', + 'RpcError', + 'RpcContext', + 'Call', + 'ChannelCredentials', + 'CallCredentials', + 'AuthMetadataContext', + 'AuthMetadataPluginCallback', + 'AuthMetadataPlugin', + 'ServerCredentials', + 'UnaryUnaryMultiCallable', + 'UnaryStreamMultiCallable', + 'StreamUnaryMultiCallable', + 'StreamStreamMultiCallable', + 'Channel', + 'ServicerContext', + 'RpcMethodHandler', + 'HandlerCallDetails', + 'GenericRpcHandler', + 'ServiceRpcHandler', + 'Server', + 'unary_unary_rpc_method_handler', + 'unary_stream_rpc_method_handler', + 'stream_unary_rpc_method_handler', + 'stream_stream_rpc_method_handler', + 'method_handlers_generic_handler', + 'ssl_channel_credentials', + 'metadata_call_credentials', + 'access_token_call_credentials', + 'composite_call_credentials', + 'composite_channel_credentials', + 'ssl_server_credentials', + 'channel_ready_future', + 'insecure_channel', + 'secure_channel', + 'server',) + + six.assertCountEqual(self, expected_grpc_code_elements, + _from_grpc_import_star.GRPC_ELEMENTS) class ChannelConnectivityTest(unittest.TestCase): - def testChannelConnectivity(self): - self.assertSequenceEqual( - (grpc.ChannelConnectivity.IDLE, - grpc.ChannelConnectivity.CONNECTING, - grpc.ChannelConnectivity.READY, - grpc.ChannelConnectivity.TRANSIENT_FAILURE, - grpc.ChannelConnectivity.SHUTDOWN,), - tuple(grpc.ChannelConnectivity)) + def testChannelConnectivity(self): + self.assertSequenceEqual(( + grpc.ChannelConnectivity.IDLE, + grpc.ChannelConnectivity.CONNECTING, + grpc.ChannelConnectivity.READY, + grpc.ChannelConnectivity.TRANSIENT_FAILURE, + grpc.ChannelConnectivity.SHUTDOWN,), + tuple(grpc.ChannelConnectivity)) class ChannelTest(unittest.TestCase): - def test_secure_channel(self): - channel_credentials = grpc.ssl_channel_credentials() - channel = grpc.secure_channel('google.com:443', channel_credentials) + def test_secure_channel(self): + channel_credentials = grpc.ssl_channel_credentials() + channel = grpc.secure_channel('google.com:443', channel_credentials) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_auth_test.py b/src/python/grpcio_tests/tests/unit/_auth_test.py index c31f7b06f73..52bd1cb7ba4 100644 --- a/src/python/grpcio_tests/tests/unit/_auth_test.py +++ b/src/python/grpcio_tests/tests/unit/_auth_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of standard AuthMetadataPlugins.""" import collections @@ -38,59 +37,59 @@ from grpc import _auth class MockGoogleCreds(object): - def get_access_token(self): - token = collections.namedtuple('MockAccessTokenInfo', - ('access_token', 'expires_in')) - token.access_token = 'token' - return token + def get_access_token(self): + token = collections.namedtuple('MockAccessTokenInfo', + ('access_token', 'expires_in')) + token.access_token = 'token' + return token class MockExceptionGoogleCreds(object): - def get_access_token(self): - raise Exception() + def get_access_token(self): + raise Exception() class GoogleCallCredentialsTest(unittest.TestCase): - def test_google_call_credentials_success(self): - callback_event = threading.Event() + def test_google_call_credentials_success(self): + callback_event = threading.Event() - def mock_callback(metadata, error): - self.assertEqual(metadata, (('authorization', 'Bearer token'),)) - self.assertIsNone(error) - callback_event.set() + def mock_callback(metadata, error): + self.assertEqual(metadata, (('authorization', 'Bearer token'),)) + self.assertIsNone(error) + callback_event.set() - call_creds = _auth.GoogleCallCredentials(MockGoogleCreds()) - call_creds(None, mock_callback) - self.assertTrue(callback_event.wait(1.0)) + call_creds = _auth.GoogleCallCredentials(MockGoogleCreds()) + call_creds(None, mock_callback) + self.assertTrue(callback_event.wait(1.0)) - def test_google_call_credentials_error(self): - callback_event = threading.Event() + def test_google_call_credentials_error(self): + callback_event = threading.Event() - def mock_callback(metadata, error): - self.assertIsNotNone(error) - callback_event.set() + def mock_callback(metadata, error): + self.assertIsNotNone(error) + callback_event.set() - call_creds = _auth.GoogleCallCredentials(MockExceptionGoogleCreds()) - call_creds(None, mock_callback) - self.assertTrue(callback_event.wait(1.0)) + call_creds = _auth.GoogleCallCredentials(MockExceptionGoogleCreds()) + call_creds(None, mock_callback) + self.assertTrue(callback_event.wait(1.0)) class AccessTokenCallCredentialsTest(unittest.TestCase): - def test_google_call_credentials_success(self): - callback_event = threading.Event() + def test_google_call_credentials_success(self): + callback_event = threading.Event() - def mock_callback(metadata, error): - self.assertEqual(metadata, (('authorization', 'Bearer token'),)) - self.assertIsNone(error) - callback_event.set() + def mock_callback(metadata, error): + self.assertEqual(metadata, (('authorization', 'Bearer token'),)) + self.assertIsNone(error) + callback_event.set() - call_creds = _auth.AccessTokenCallCredentials('token') - call_creds(None, mock_callback) - self.assertTrue(callback_event.wait(1.0)) + call_creds = _auth.AccessTokenCallCredentials('token') + call_creds(None, mock_callback) + self.assertTrue(callback_event.wait(1.0)) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_channel_args_test.py b/src/python/grpcio_tests/tests/unit/_channel_args_test.py index b46497afd60..845db777a4c 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_args_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_args_test.py @@ -26,17 +26,17 @@ # 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. - """Tests of Channel Args on client/server side.""" import unittest import grpc + class TestPointerWrapper(object): - def __int__(self): - return 123456 + def __int__(self): + return 123456 TEST_CHANNEL_ARGS = ( @@ -44,17 +44,17 @@ TEST_CHANNEL_ARGS = ( ('arg2', 'str_val'), ('arg3', 1), (b'arg4', 'str_val'), - ('arg6', TestPointerWrapper()), -) + ('arg6', TestPointerWrapper()),) class ChannelArgsTest(unittest.TestCase): - def test_client(self): - grpc.insecure_channel('localhost:8080', options=TEST_CHANNEL_ARGS) + def test_client(self): + grpc.insecure_channel('localhost:8080', options=TEST_CHANNEL_ARGS) + + def test_server(self): + grpc.server(None, options=TEST_CHANNEL_ARGS) - def test_server(self): - grpc.server(None, options=TEST_CHANNEL_ARGS) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py index 3d9dd17ff68..d67693154b8 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of grpc._channel.Channel connectivity.""" import threading @@ -39,125 +38,123 @@ from tests.unit import _thread_pool def _ready_in_connectivities(connectivities): - return grpc.ChannelConnectivity.READY in connectivities + return grpc.ChannelConnectivity.READY in connectivities def _last_connectivity_is_not_ready(connectivities): - return connectivities[-1] is not grpc.ChannelConnectivity.READY + return connectivities[-1] is not grpc.ChannelConnectivity.READY class _Callback(object): - def __init__(self): - self._condition = threading.Condition() - self._connectivities = [] + def __init__(self): + self._condition = threading.Condition() + self._connectivities = [] - def update(self, connectivity): - with self._condition: - self._connectivities.append(connectivity) - self._condition.notify() + def update(self, connectivity): + with self._condition: + self._connectivities.append(connectivity) + self._condition.notify() - def connectivities(self): - with self._condition: - return tuple(self._connectivities) + def connectivities(self): + with self._condition: + return tuple(self._connectivities) - def block_until_connectivities_satisfy(self, predicate): - with self._condition: - while True: - connectivities = tuple(self._connectivities) - if predicate(connectivities): - return connectivities - else: - self._condition.wait() + def block_until_connectivities_satisfy(self, predicate): + with self._condition: + while True: + connectivities = tuple(self._connectivities) + if predicate(connectivities): + return connectivities + else: + self._condition.wait() class ChannelConnectivityTest(unittest.TestCase): - def test_lonely_channel_connectivity(self): - callback = _Callback() - - channel = grpc.insecure_channel('localhost:12345') - channel.subscribe(callback.update, try_to_connect=False) - first_connectivities = callback.block_until_connectivities_satisfy(bool) - channel.subscribe(callback.update, try_to_connect=True) - second_connectivities = callback.block_until_connectivities_satisfy( - lambda connectivities: 2 <= len(connectivities)) - # Wait for a connection that will never happen. - time.sleep(test_constants.SHORT_TIMEOUT) - third_connectivities = callback.connectivities() - channel.unsubscribe(callback.update) - fourth_connectivities = callback.connectivities() - channel.unsubscribe(callback.update) - fifth_connectivities = callback.connectivities() - - self.assertSequenceEqual( - (grpc.ChannelConnectivity.IDLE,), first_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.READY, second_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.READY, third_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.READY, fourth_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.READY, fifth_connectivities) - - def test_immediately_connectable_channel_connectivity(self): - thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) - server = grpc.server(thread_pool) - port = server.add_insecure_port('[::]:0') - server.start() - first_callback = _Callback() - second_callback = _Callback() - - channel = grpc.insecure_channel('localhost:{}'.format(port)) - channel.subscribe(first_callback.update, try_to_connect=False) - first_connectivities = first_callback.block_until_connectivities_satisfy( - bool) - # Wait for a connection that will never happen because try_to_connect=True - # has not yet been passed. - time.sleep(test_constants.SHORT_TIMEOUT) - second_connectivities = first_callback.connectivities() - channel.subscribe(second_callback.update, try_to_connect=True) - third_connectivities = first_callback.block_until_connectivities_satisfy( - lambda connectivities: 2 <= len(connectivities)) - fourth_connectivities = second_callback.block_until_connectivities_satisfy( - bool) - # Wait for a connection that will happen (or may already have happened). - first_callback.block_until_connectivities_satisfy(_ready_in_connectivities) - second_callback.block_until_connectivities_satisfy(_ready_in_connectivities) - del channel - - self.assertSequenceEqual( - (grpc.ChannelConnectivity.IDLE,), first_connectivities) - self.assertSequenceEqual( - (grpc.ChannelConnectivity.IDLE,), second_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.TRANSIENT_FAILURE, third_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.SHUTDOWN, third_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.TRANSIENT_FAILURE, - fourth_connectivities) - self.assertNotIn( - grpc.ChannelConnectivity.SHUTDOWN, fourth_connectivities) - self.assertFalse(thread_pool.was_used()) - - def test_reachable_then_unreachable_channel_connectivity(self): - thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) - server = grpc.server(thread_pool) - port = server.add_insecure_port('[::]:0') - server.start() - callback = _Callback() - - channel = grpc.insecure_channel('localhost:{}'.format(port)) - channel.subscribe(callback.update, try_to_connect=True) - callback.block_until_connectivities_satisfy(_ready_in_connectivities) - # Now take down the server and confirm that channel readiness is repudiated. - server.stop(None) - callback.block_until_connectivities_satisfy(_last_connectivity_is_not_ready) - channel.unsubscribe(callback.update) - self.assertFalse(thread_pool.was_used()) + def test_lonely_channel_connectivity(self): + callback = _Callback() + + channel = grpc.insecure_channel('localhost:12345') + channel.subscribe(callback.update, try_to_connect=False) + first_connectivities = callback.block_until_connectivities_satisfy(bool) + channel.subscribe(callback.update, try_to_connect=True) + second_connectivities = callback.block_until_connectivities_satisfy( + lambda connectivities: 2 <= len(connectivities)) + # Wait for a connection that will never happen. + time.sleep(test_constants.SHORT_TIMEOUT) + third_connectivities = callback.connectivities() + channel.unsubscribe(callback.update) + fourth_connectivities = callback.connectivities() + channel.unsubscribe(callback.update) + fifth_connectivities = callback.connectivities() + + self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), + first_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.READY, second_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.READY, third_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.READY, fourth_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.READY, fifth_connectivities) + + def test_immediately_connectable_channel_connectivity(self): + thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) + server = grpc.server(thread_pool) + port = server.add_insecure_port('[::]:0') + server.start() + first_callback = _Callback() + second_callback = _Callback() + + channel = grpc.insecure_channel('localhost:{}'.format(port)) + channel.subscribe(first_callback.update, try_to_connect=False) + first_connectivities = first_callback.block_until_connectivities_satisfy( + bool) + # Wait for a connection that will never happen because try_to_connect=True + # has not yet been passed. + time.sleep(test_constants.SHORT_TIMEOUT) + second_connectivities = first_callback.connectivities() + channel.subscribe(second_callback.update, try_to_connect=True) + third_connectivities = first_callback.block_until_connectivities_satisfy( + lambda connectivities: 2 <= len(connectivities)) + fourth_connectivities = second_callback.block_until_connectivities_satisfy( + bool) + # Wait for a connection that will happen (or may already have happened). + first_callback.block_until_connectivities_satisfy( + _ready_in_connectivities) + second_callback.block_until_connectivities_satisfy( + _ready_in_connectivities) + del channel + + self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), + first_connectivities) + self.assertSequenceEqual((grpc.ChannelConnectivity.IDLE,), + second_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.TRANSIENT_FAILURE, + third_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.SHUTDOWN, + third_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.TRANSIENT_FAILURE, + fourth_connectivities) + self.assertNotIn(grpc.ChannelConnectivity.SHUTDOWN, + fourth_connectivities) + self.assertFalse(thread_pool.was_used()) + + def test_reachable_then_unreachable_channel_connectivity(self): + thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) + server = grpc.server(thread_pool) + port = server.add_insecure_port('[::]:0') + server.start() + callback = _Callback() + + channel = grpc.insecure_channel('localhost:{}'.format(port)) + channel.subscribe(callback.update, try_to_connect=True) + callback.block_until_connectivities_satisfy(_ready_in_connectivities) + # Now take down the server and confirm that channel readiness is repudiated. + server.stop(None) + callback.block_until_connectivities_satisfy( + _last_connectivity_is_not_ready) + channel.unsubscribe(callback.update) + self.assertFalse(thread_pool.was_used()) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py index 46a964db8cf..2d1b63e15f3 100644 --- a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py +++ b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of grpc.channel_ready_future.""" import threading @@ -39,65 +38,66 @@ from tests.unit import _thread_pool class _Callback(object): - def __init__(self): - self._condition = threading.Condition() - self._value = None + def __init__(self): + self._condition = threading.Condition() + self._value = None - def accept_value(self, value): - with self._condition: - self._value = value - self._condition.notify_all() + def accept_value(self, value): + with self._condition: + self._value = value + self._condition.notify_all() - def block_until_called(self): - with self._condition: - while self._value is None: - self._condition.wait() - return self._value + def block_until_called(self): + with self._condition: + while self._value is None: + self._condition.wait() + return self._value class ChannelReadyFutureTest(unittest.TestCase): - def test_lonely_channel_connectivity(self): - channel = grpc.insecure_channel('localhost:12345') - callback = _Callback() - - ready_future = grpc.channel_ready_future(channel) - ready_future.add_done_callback(callback.accept_value) - with self.assertRaises(grpc.FutureTimeoutError): - ready_future.result(timeout=test_constants.SHORT_TIMEOUT) - self.assertFalse(ready_future.cancelled()) - self.assertFalse(ready_future.done()) - self.assertTrue(ready_future.running()) - ready_future.cancel() - value_passed_to_callback = callback.block_until_called() - self.assertIs(ready_future, value_passed_to_callback) - self.assertTrue(ready_future.cancelled()) - self.assertTrue(ready_future.done()) - self.assertFalse(ready_future.running()) - - def test_immediately_connectable_channel_connectivity(self): - thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) - server = grpc.server(thread_pool) - port = server.add_insecure_port('[::]:0') - server.start() - channel = grpc.insecure_channel('localhost:{}'.format(port)) - callback = _Callback() - - ready_future = grpc.channel_ready_future(channel) - ready_future.add_done_callback(callback.accept_value) - self.assertIsNone(ready_future.result(timeout=test_constants.LONG_TIMEOUT)) - value_passed_to_callback = callback.block_until_called() - self.assertIs(ready_future, value_passed_to_callback) - self.assertFalse(ready_future.cancelled()) - self.assertTrue(ready_future.done()) - self.assertFalse(ready_future.running()) - # Cancellation after maturity has no effect. - ready_future.cancel() - self.assertFalse(ready_future.cancelled()) - self.assertTrue(ready_future.done()) - self.assertFalse(ready_future.running()) - self.assertFalse(thread_pool.was_used()) + def test_lonely_channel_connectivity(self): + channel = grpc.insecure_channel('localhost:12345') + callback = _Callback() + + ready_future = grpc.channel_ready_future(channel) + ready_future.add_done_callback(callback.accept_value) + with self.assertRaises(grpc.FutureTimeoutError): + ready_future.result(timeout=test_constants.SHORT_TIMEOUT) + self.assertFalse(ready_future.cancelled()) + self.assertFalse(ready_future.done()) + self.assertTrue(ready_future.running()) + ready_future.cancel() + value_passed_to_callback = callback.block_until_called() + self.assertIs(ready_future, value_passed_to_callback) + self.assertTrue(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + + def test_immediately_connectable_channel_connectivity(self): + thread_pool = _thread_pool.RecordingThreadPool(max_workers=None) + server = grpc.server(thread_pool) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:{}'.format(port)) + callback = _Callback() + + ready_future = grpc.channel_ready_future(channel) + ready_future.add_done_callback(callback.accept_value) + self.assertIsNone( + ready_future.result(timeout=test_constants.LONG_TIMEOUT)) + value_passed_to_callback = callback.block_until_called() + self.assertIs(ready_future, value_passed_to_callback) + self.assertFalse(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + # Cancellation after maturity has no effect. + ready_future.cancel() + self.assertFalse(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + self.assertFalse(thread_pool.was_used()) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py index 4d3f02e9175..7dd944e6008 100644 --- a/src/python/grpcio_tests/tests/unit/_compression_test.py +++ b/src/python/grpcio_tests/tests/unit/_compression_test.py @@ -42,93 +42,96 @@ _STREAM_STREAM = '/test/StreamStream' def handle_unary(request, servicer_context): - servicer_context.send_initial_metadata([ - ('grpc-internal-encoding-request', 'gzip')]) - return request + servicer_context.send_initial_metadata( + [('grpc-internal-encoding-request', 'gzip')]) + return request def handle_stream(request_iterator, servicer_context): - # TODO(issue:#6891) We should be able to remove this loop, - # and replace with return; yield - servicer_context.send_initial_metadata([ - ('grpc-internal-encoding-request', 'gzip')]) - for request in request_iterator: - yield request + # TODO(issue:#6891) We should be able to remove this loop, + # and replace with return; yield + servicer_context.send_initial_metadata( + [('grpc-internal-encoding-request', 'gzip')]) + for request in request_iterator: + yield request class _MethodHandler(grpc.RpcMethodHandler): - def __init__(self, request_streaming, response_streaming): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = None - self.response_serializer = None - self.unary_unary = None - self.unary_stream = None - self.stream_unary = None - self.stream_stream = None - if self.request_streaming and self.response_streaming: - self.stream_stream = lambda x, y: handle_stream(x, y) - elif not self.request_streaming and not self.response_streaming: - self.unary_unary = lambda x, y: handle_unary(x, y) + def __init__(self, request_streaming, response_streaming): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = None + self.response_serializer = None + self.unary_unary = None + self.unary_stream = None + self.stream_unary = None + self.stream_stream = None + if self.request_streaming and self.response_streaming: + self.stream_stream = lambda x, y: handle_stream(x, y) + elif not self.request_streaming and not self.response_streaming: + self.unary_unary = lambda x, y: handle_unary(x, y) class _GenericHandler(grpc.GenericRpcHandler): - def service(self, handler_call_details): - if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler(False, False) - elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler(True, True) - else: - return None + def service(self, handler_call_details): + if handler_call_details.method == _UNARY_UNARY: + return _MethodHandler(False, False) + elif handler_call_details.method == _STREAM_STREAM: + return _MethodHandler(True, True) + else: + return None class CompressionTest(unittest.TestCase): - def setUp(self): - self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server( - self._server_pool, handlers=(_GenericHandler(),)) - self._port = self._server.add_insecure_port('[::]:0') - self._server.start() - - def testUnary(self): - request = b'\x00' * 100 - - # Client -> server compressed through default client channel compression - # settings. Server -> client compressed via server-side metadata setting. - # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer - # literal with proper use of the public API. - compressed_channel = grpc.insecure_channel('localhost:%d' % self._port, - options=[('grpc.default_compression_algorithm', 1)]) - multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) - response = multi_callable(request) - self.assertEqual(request, response) - - # Client -> server compressed through client metadata setting. Server -> - # client compressed via server-side metadata setting. - # TODO(https://github.com/grpc/grpc/issues/4078): replace the "0" integer - # literal with proper use of the public API. - uncompressed_channel = grpc.insecure_channel('localhost:%d' % self._port, - options=[('grpc.default_compression_algorithm', 0)]) - multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) - response = multi_callable(request, metadata=[ - ('grpc-internal-encoding-request', 'gzip')]) - self.assertEqual(request, response) - - def testStreaming(self): - request = b'\x00' * 100 - - # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer - # literal with proper use of the public API. - compressed_channel = grpc.insecure_channel('localhost:%d' % self._port, - options=[('grpc.default_compression_algorithm', 1)]) - multi_callable = compressed_channel.stream_stream(_STREAM_STREAM) - call = multi_callable(iter([request] * test_constants.STREAM_LENGTH)) - for response in call: - self.assertEqual(request, response) + def setUp(self): + self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server( + self._server_pool, handlers=(_GenericHandler(),)) + self._port = self._server.add_insecure_port('[::]:0') + self._server.start() + + def testUnary(self): + request = b'\x00' * 100 + + # Client -> server compressed through default client channel compression + # settings. Server -> client compressed via server-side metadata setting. + # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer + # literal with proper use of the public API. + compressed_channel = grpc.insecure_channel( + 'localhost:%d' % self._port, + options=[('grpc.default_compression_algorithm', 1)]) + multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) + response = multi_callable(request) + self.assertEqual(request, response) + + # Client -> server compressed through client metadata setting. Server -> + # client compressed via server-side metadata setting. + # TODO(https://github.com/grpc/grpc/issues/4078): replace the "0" integer + # literal with proper use of the public API. + uncompressed_channel = grpc.insecure_channel( + 'localhost:%d' % self._port, + options=[('grpc.default_compression_algorithm', 0)]) + multi_callable = compressed_channel.unary_unary(_UNARY_UNARY) + response = multi_callable( + request, metadata=[('grpc-internal-encoding-request', 'gzip')]) + self.assertEqual(request, response) + + def testStreaming(self): + request = b'\x00' * 100 + + # TODO(https://github.com/grpc/grpc/issues/4078): replace the "1" integer + # literal with proper use of the public API. + compressed_channel = grpc.insecure_channel( + 'localhost:%d' % self._port, + options=[('grpc.default_compression_algorithm', 1)]) + multi_callable = compressed_channel.stream_stream(_STREAM_STREAM) + call = multi_callable(iter([request] * test_constants.STREAM_LENGTH)) + for response in call: + self.assertEqual(request, response) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_credentials_test.py b/src/python/grpcio_tests/tests/unit/_credentials_test.py index 87af85a0b9b..21bf29789a7 100644 --- a/src/python/grpcio_tests/tests/unit/_credentials_test.py +++ b/src/python/grpcio_tests/tests/unit/_credentials_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of credentials.""" import unittest @@ -36,37 +35,38 @@ import grpc class CredentialsTest(unittest.TestCase): - def test_call_credentials_composition(self): - first = grpc.access_token_call_credentials('abc') - second = grpc.access_token_call_credentials('def') - third = grpc.access_token_call_credentials('ghi') + def test_call_credentials_composition(self): + first = grpc.access_token_call_credentials('abc') + second = grpc.access_token_call_credentials('def') + third = grpc.access_token_call_credentials('ghi') + + first_and_second = grpc.composite_call_credentials(first, second) + first_second_and_third = grpc.composite_call_credentials(first, second, + third) - first_and_second = grpc.composite_call_credentials(first, second) - first_second_and_third = grpc.composite_call_credentials( - first, second, third) - - self.assertIsInstance(first_and_second, grpc.CallCredentials) - self.assertIsInstance(first_second_and_third, grpc.CallCredentials) + self.assertIsInstance(first_and_second, grpc.CallCredentials) + self.assertIsInstance(first_second_and_third, grpc.CallCredentials) - def test_channel_credentials_composition(self): - first_call_credentials = grpc.access_token_call_credentials('abc') - second_call_credentials = grpc.access_token_call_credentials('def') - third_call_credentials = grpc.access_token_call_credentials('ghi') - channel_credentials = grpc.ssl_channel_credentials() + def test_channel_credentials_composition(self): + first_call_credentials = grpc.access_token_call_credentials('abc') + second_call_credentials = grpc.access_token_call_credentials('def') + third_call_credentials = grpc.access_token_call_credentials('ghi') + channel_credentials = grpc.ssl_channel_credentials() - channel_and_first = grpc.composite_channel_credentials( - channel_credentials, first_call_credentials) - channel_first_and_second = grpc.composite_channel_credentials( - channel_credentials, first_call_credentials, second_call_credentials) - channel_first_second_and_third = grpc.composite_channel_credentials( - channel_credentials, first_call_credentials, second_call_credentials, - third_call_credentials) + channel_and_first = grpc.composite_channel_credentials( + channel_credentials, first_call_credentials) + channel_first_and_second = grpc.composite_channel_credentials( + channel_credentials, first_call_credentials, + second_call_credentials) + channel_first_second_and_third = grpc.composite_channel_credentials( + channel_credentials, first_call_credentials, + second_call_credentials, third_call_credentials) - self.assertIsInstance(channel_and_first, grpc.ChannelCredentials) - self.assertIsInstance(channel_first_and_second, grpc.ChannelCredentials) - self.assertIsInstance( - channel_first_second_and_third, grpc.ChannelCredentials) + self.assertIsInstance(channel_and_first, grpc.ChannelCredentials) + self.assertIsInstance(channel_first_and_second, grpc.ChannelCredentials) + self.assertIsInstance(channel_first_second_and_third, + grpc.ChannelCredentials) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py index 20115fb22cb..d77f5ecb27e 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py @@ -26,7 +26,6 @@ # 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. - """Test making many calls and immediately cancelling most of them.""" import threading @@ -51,173 +50,178 @@ _SUCCESS_CALL_FRACTION = 1.0 / 8.0 class _State(object): - def __init__(self): - self.condition = threading.Condition() - self.handlers_released = False - self.parked_handlers = 0 - self.handled_rpcs = 0 + def __init__(self): + self.condition = threading.Condition() + self.handlers_released = False + self.parked_handlers = 0 + self.handled_rpcs = 0 def _is_cancellation_event(event): - return ( - event.tag is _RECEIVE_CLOSE_ON_SERVER_TAG and - event.batch_operations[0].received_cancelled) + return (event.tag is _RECEIVE_CLOSE_ON_SERVER_TAG and + event.batch_operations[0].received_cancelled) class _Handler(object): - def __init__(self, state, completion_queue, rpc_event): - self._state = state - self._lock = threading.Lock() - self._completion_queue = completion_queue - self._call = rpc_event.operation_call - - def __call__(self): - with self._state.condition: - self._state.parked_handlers += 1 - if self._state.parked_handlers == test_constants.THREAD_CONCURRENCY: - self._state.condition.notify_all() - while not self._state.handlers_released: - self._state.condition.wait() - - with self._lock: - self._call.start_server_batch( - cygrpc.Operations( - (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), - _RECEIVE_CLOSE_ON_SERVER_TAG) - self._call.start_server_batch( - cygrpc.Operations((cygrpc.operation_receive_message(_EMPTY_FLAGS),)), - _RECEIVE_MESSAGE_TAG) - first_event = self._completion_queue.poll() - if _is_cancellation_event(first_event): - self._completion_queue.poll() - else: - with self._lock: - operations = ( - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS), - cygrpc.operation_send_message(b'\x79\x57', _EMPTY_FLAGS), - cygrpc.operation_send_status_from_server( - _EMPTY_METADATA, cygrpc.StatusCode.ok, b'test details!', - _EMPTY_FLAGS), - ) - self._call.start_server_batch( - cygrpc.Operations(operations), _SERVER_COMPLETE_CALL_TAG) - self._completion_queue.poll() - self._completion_queue.poll() + def __init__(self, state, completion_queue, rpc_event): + self._state = state + self._lock = threading.Lock() + self._completion_queue = completion_queue + self._call = rpc_event.operation_call + + def __call__(self): + with self._state.condition: + self._state.parked_handlers += 1 + if self._state.parked_handlers == test_constants.THREAD_CONCURRENCY: + self._state.condition.notify_all() + while not self._state.handlers_released: + self._state.condition.wait() + + with self._lock: + self._call.start_server_batch( + cygrpc.Operations( + (cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),)), + _RECEIVE_CLOSE_ON_SERVER_TAG) + self._call.start_server_batch( + cygrpc.Operations( + (cygrpc.operation_receive_message(_EMPTY_FLAGS),)), + _RECEIVE_MESSAGE_TAG) + first_event = self._completion_queue.poll() + if _is_cancellation_event(first_event): + self._completion_queue.poll() + else: + with self._lock: + operations = ( + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS), + cygrpc.operation_send_message(b'\x79\x57', _EMPTY_FLAGS), + cygrpc.operation_send_status_from_server( + _EMPTY_METADATA, cygrpc.StatusCode.ok, b'test details!', + _EMPTY_FLAGS),) + self._call.start_server_batch( + cygrpc.Operations(operations), _SERVER_COMPLETE_CALL_TAG) + self._completion_queue.poll() + self._completion_queue.poll() def _serve(state, server, server_completion_queue, thread_pool): - for _ in range(test_constants.RPC_CONCURRENCY): - call_completion_queue = cygrpc.CompletionQueue() - server.request_call( - call_completion_queue, server_completion_queue, _REQUEST_CALL_TAG) - rpc_event = server_completion_queue.poll() - thread_pool.submit(_Handler(state, call_completion_queue, rpc_event)) - with state.condition: - state.handled_rpcs += 1 - if test_constants.RPC_CONCURRENCY <= state.handled_rpcs: - state.condition.notify_all() - server_completion_queue.poll() + for _ in range(test_constants.RPC_CONCURRENCY): + call_completion_queue = cygrpc.CompletionQueue() + server.request_call(call_completion_queue, server_completion_queue, + _REQUEST_CALL_TAG) + rpc_event = server_completion_queue.poll() + thread_pool.submit(_Handler(state, call_completion_queue, rpc_event)) + with state.condition: + state.handled_rpcs += 1 + if test_constants.RPC_CONCURRENCY <= state.handled_rpcs: + state.condition.notify_all() + server_completion_queue.poll() class _QueueDriver(object): - def __init__(self, condition, completion_queue, due): - self._condition = condition - self._completion_queue = completion_queue - self._due = due - self._events = [] - self._returned = False - - def start(self): - def in_thread(): - while True: - event = self._completion_queue.poll() + def __init__(self, condition, completion_queue, due): + self._condition = condition + self._completion_queue = completion_queue + self._due = due + self._events = [] + self._returned = False + + def start(self): + + def in_thread(): + while True: + event = self._completion_queue.poll() + with self._condition: + self._events.append(event) + self._due.remove(event.tag) + self._condition.notify_all() + if not self._due: + self._returned = True + return + + thread = threading.Thread(target=in_thread) + thread.start() + + def events(self, at_least): with self._condition: - self._events.append(event) - self._due.remove(event.tag) - self._condition.notify_all() - if not self._due: - self._returned = True - return - thread = threading.Thread(target=in_thread) - thread.start() - - def events(self, at_least): - with self._condition: - while len(self._events) < at_least: - self._condition.wait() - return tuple(self._events) + while len(self._events) < at_least: + self._condition.wait() + return tuple(self._events) class CancelManyCallsTest(unittest.TestCase): - def testCancelManyCalls(self): - server_thread_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - - server_completion_queue = cygrpc.CompletionQueue() - server = cygrpc.Server(cygrpc.ChannelArgs([])) - server.register_completion_queue(server_completion_queue) - port = server.add_http2_port(b'[::]:0') - server.start() - channel = cygrpc.Channel('localhost:{}'.format(port).encode(), - cygrpc.ChannelArgs([])) - - state = _State() - - server_thread_args = ( - state, server, server_completion_queue, server_thread_pool,) - server_thread = threading.Thread(target=_serve, args=server_thread_args) - server_thread.start() - - client_condition = threading.Condition() - client_due = set() - client_completion_queue = cygrpc.CompletionQueue() - client_driver = _QueueDriver( - client_condition, client_completion_queue, client_due) - client_driver.start() - - with client_condition: - client_calls = [] - for index in range(test_constants.RPC_CONCURRENCY): - client_call = channel.create_call( - None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', None, - _INFINITE_FUTURE) - operations = ( - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS), - cygrpc.operation_send_message(b'\x45\x56', _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), - ) - tag = 'client_complete_call_{0:04d}_tag'.format(index) - client_call.start_client_batch(cygrpc.Operations(operations), tag) - client_due.add(tag) - client_calls.append(client_call) - - with state.condition: - while True: - if state.parked_handlers < test_constants.THREAD_CONCURRENCY: - state.condition.wait() - elif state.handled_rpcs < test_constants.RPC_CONCURRENCY: - state.condition.wait() - else: - state.handlers_released = True - state.condition.notify_all() - break - - client_driver.events( - test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION) - with client_condition: - for client_call in client_calls: - client_call.cancel() - - with state.condition: - server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG) + def testCancelManyCalls(self): + server_thread_pool = logging_pool.pool( + test_constants.THREAD_CONCURRENCY) + + server_completion_queue = cygrpc.CompletionQueue() + server = cygrpc.Server(cygrpc.ChannelArgs([])) + server.register_completion_queue(server_completion_queue) + port = server.add_http2_port(b'[::]:0') + server.start() + channel = cygrpc.Channel('localhost:{}'.format(port).encode(), + cygrpc.ChannelArgs([])) + + state = _State() + + server_thread_args = ( + state, + server, + server_completion_queue, + server_thread_pool,) + server_thread = threading.Thread(target=_serve, args=server_thread_args) + server_thread.start() + + client_condition = threading.Condition() + client_due = set() + client_completion_queue = cygrpc.CompletionQueue() + client_driver = _QueueDriver(client_condition, client_completion_queue, + client_due) + client_driver.start() + + with client_condition: + client_calls = [] + for index in range(test_constants.RPC_CONCURRENCY): + client_call = channel.create_call( + None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', + None, _INFINITE_FUTURE) + operations = ( + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS), + cygrpc.operation_send_message(b'\x45\x56', _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),) + tag = 'client_complete_call_{0:04d}_tag'.format(index) + client_call.start_client_batch( + cygrpc.Operations(operations), tag) + client_due.add(tag) + client_calls.append(client_call) + + with state.condition: + while True: + if state.parked_handlers < test_constants.THREAD_CONCURRENCY: + state.condition.wait() + elif state.handled_rpcs < test_constants.RPC_CONCURRENCY: + state.condition.wait() + else: + state.handlers_released = True + state.condition.notify_all() + break + + client_driver.events(test_constants.RPC_CONCURRENCY * + _SUCCESS_CALL_FRACTION) + with client_condition: + for client_call in client_calls: + client_call.cancel() + + with state.condition: + server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py index f9c8a3ac62b..0ca06868b2d 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py @@ -37,46 +37,49 @@ from tests.unit.framework.common import test_constants def _channel_and_completion_queue(): - channel = cygrpc.Channel(b'localhost:54321', cygrpc.ChannelArgs(())) - completion_queue = cygrpc.CompletionQueue() - return channel, completion_queue + channel = cygrpc.Channel(b'localhost:54321', cygrpc.ChannelArgs(())) + completion_queue = cygrpc.CompletionQueue() + return channel, completion_queue def _connectivity_loop(channel, completion_queue): - for _ in range(100): - connectivity = channel.check_connectivity_state(True) - channel.watch_connectivity_state( - connectivity, cygrpc.Timespec(time.time() + 0.2), completion_queue, - None) - completion_queue.poll(deadline=cygrpc.Timespec(float('+inf'))) + for _ in range(100): + connectivity = channel.check_connectivity_state(True) + channel.watch_connectivity_state(connectivity, + cygrpc.Timespec(time.time() + 0.2), + completion_queue, None) + completion_queue.poll(deadline=cygrpc.Timespec(float('+inf'))) def _create_loop_destroy(): - channel, completion_queue = _channel_and_completion_queue() - _connectivity_loop(channel, completion_queue) - completion_queue.shutdown() + channel, completion_queue = _channel_and_completion_queue() + _connectivity_loop(channel, completion_queue) + completion_queue.shutdown() def _in_parallel(behavior, arguments): - threads = tuple( - threading.Thread(target=behavior, args=arguments) - for _ in range(test_constants.THREAD_CONCURRENCY)) - for thread in threads: - thread.start() - for thread in threads: - thread.join() + threads = tuple( + threading.Thread( + target=behavior, args=arguments) + for _ in range(test_constants.THREAD_CONCURRENCY)) + for thread in threads: + thread.start() + for thread in threads: + thread.join() class ChannelTest(unittest.TestCase): - def test_single_channel_lonely_connectivity(self): - channel, completion_queue = _channel_and_completion_queue() - _in_parallel(_connectivity_loop, (channel, completion_queue,)) - completion_queue.shutdown() + def test_single_channel_lonely_connectivity(self): + channel, completion_queue = _channel_and_completion_queue() + _in_parallel(_connectivity_loop, ( + channel, + completion_queue,)) + completion_queue.shutdown() - def test_multiple_channels_lonely_connectivity(self): - _in_parallel(_create_loop_destroy, ()) + def test_multiple_channels_lonely_connectivity(self): + _in_parallel(_create_loop_destroy, ()) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py index 2ae5285232c..9fbfcbb9c02 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py @@ -26,7 +26,6 @@ # 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. - """Test a corner-case at the level of the Cython API.""" import threading @@ -41,212 +40,221 @@ _EMPTY_METADATA = cygrpc.Metadata(()) class _ServerDriver(object): - def __init__(self, completion_queue, shutdown_tag): - self._condition = threading.Condition() - self._completion_queue = completion_queue - self._shutdown_tag = shutdown_tag - self._events = [] - self._saw_shutdown_tag = False - - def start(self): - def in_thread(): - while True: - event = self._completion_queue.poll() + def __init__(self, completion_queue, shutdown_tag): + self._condition = threading.Condition() + self._completion_queue = completion_queue + self._shutdown_tag = shutdown_tag + self._events = [] + self._saw_shutdown_tag = False + + def start(self): + + def in_thread(): + while True: + event = self._completion_queue.poll() + with self._condition: + self._events.append(event) + self._condition.notify() + if event.tag is self._shutdown_tag: + self._saw_shutdown_tag = True + break + + thread = threading.Thread(target=in_thread) + thread.start() + + def done(self): + with self._condition: + return self._saw_shutdown_tag + + def first_event(self): + with self._condition: + while not self._events: + self._condition.wait() + return self._events[0] + + def events(self): with self._condition: - self._events.append(event) - self._condition.notify() - if event.tag is self._shutdown_tag: - self._saw_shutdown_tag = True - break - thread = threading.Thread(target=in_thread) - thread.start() - - def done(self): - with self._condition: - return self._saw_shutdown_tag - - def first_event(self): - with self._condition: - while not self._events: - self._condition.wait() - return self._events[0] - - def events(self): - with self._condition: - while not self._saw_shutdown_tag: - self._condition.wait() - return tuple(self._events) + while not self._saw_shutdown_tag: + self._condition.wait() + return tuple(self._events) class _QueueDriver(object): - def __init__(self, condition, completion_queue, due): - self._condition = condition - self._completion_queue = completion_queue - self._due = due - self._events = [] - self._returned = False - - def start(self): - def in_thread(): - while True: - event = self._completion_queue.poll() + def __init__(self, condition, completion_queue, due): + self._condition = condition + self._completion_queue = completion_queue + self._due = due + self._events = [] + self._returned = False + + def start(self): + + def in_thread(): + while True: + event = self._completion_queue.poll() + with self._condition: + self._events.append(event) + self._due.remove(event.tag) + self._condition.notify_all() + if not self._due: + self._returned = True + return + + thread = threading.Thread(target=in_thread) + thread.start() + + def done(self): + with self._condition: + return self._returned + + def event_with_tag(self, tag): + with self._condition: + while True: + for event in self._events: + if event.tag is tag: + return event + self._condition.wait() + + def events(self): with self._condition: - self._events.append(event) - self._due.remove(event.tag) - self._condition.notify_all() - if not self._due: - self._returned = True - return - thread = threading.Thread(target=in_thread) - thread.start() - - def done(self): - with self._condition: - return self._returned - - def event_with_tag(self, tag): - with self._condition: - while True: - for event in self._events: - if event.tag is tag: - return event - self._condition.wait() - - def events(self): - with self._condition: - while not self._returned: - self._condition.wait() - return tuple(self._events) + while not self._returned: + self._condition.wait() + return tuple(self._events) class ReadSomeButNotAllResponsesTest(unittest.TestCase): - def testReadSomeButNotAllResponses(self): - server_completion_queue = cygrpc.CompletionQueue() - server = cygrpc.Server(cygrpc.ChannelArgs([])) - server.register_completion_queue(server_completion_queue) - port = server.add_http2_port(b'[::]:0') - server.start() - channel = cygrpc.Channel('localhost:{}'.format(port).encode(), - cygrpc.ChannelArgs([])) - - server_shutdown_tag = 'server_shutdown_tag' - server_driver = _ServerDriver(server_completion_queue, server_shutdown_tag) - server_driver.start() - - client_condition = threading.Condition() - client_due = set() - client_completion_queue = cygrpc.CompletionQueue() - client_driver = _QueueDriver( - client_condition, client_completion_queue, client_due) - client_driver.start() - - server_call_condition = threading.Condition() - server_send_initial_metadata_tag = 'server_send_initial_metadata_tag' - server_send_first_message_tag = 'server_send_first_message_tag' - server_send_second_message_tag = 'server_send_second_message_tag' - server_complete_rpc_tag = 'server_complete_rpc_tag' - server_call_due = set(( - server_send_initial_metadata_tag, - server_send_first_message_tag, - server_send_second_message_tag, - server_complete_rpc_tag, - )) - server_call_completion_queue = cygrpc.CompletionQueue() - server_call_driver = _QueueDriver( - server_call_condition, server_call_completion_queue, server_call_due) - server_call_driver.start() - - server_rpc_tag = 'server_rpc_tag' - request_call_result = server.request_call( - server_call_completion_queue, server_completion_queue, server_rpc_tag) - - client_call = channel.create_call( - None, _EMPTY_FLAGS, client_completion_queue, b'/twinkies', None, - _INFINITE_FUTURE) - client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag' - client_complete_rpc_tag = 'client_complete_rpc_tag' - with client_condition: - client_receive_initial_metadata_start_batch_result = ( - client_call.start_client_batch(cygrpc.Operations([ - cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), - ]), client_receive_initial_metadata_tag)) - client_due.add(client_receive_initial_metadata_tag) - client_complete_rpc_start_batch_result = ( - client_call.start_client_batch(cygrpc.Operations([ - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS), - cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), - cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), - ]), client_complete_rpc_tag)) - client_due.add(client_complete_rpc_tag) - - server_rpc_event = server_driver.first_event() - - with server_call_condition: - server_send_initial_metadata_start_batch_result = ( - server_rpc_event.operation_call.start_server_batch([ - cygrpc.operation_send_initial_metadata( - _EMPTY_METADATA, _EMPTY_FLAGS), - ], server_send_initial_metadata_tag)) - server_send_first_message_start_batch_result = ( - server_rpc_event.operation_call.start_server_batch([ - cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), - ], server_send_first_message_tag)) - server_send_initial_metadata_event = server_call_driver.event_with_tag( - server_send_initial_metadata_tag) - server_send_first_message_event = server_call_driver.event_with_tag( - server_send_first_message_tag) - with server_call_condition: - server_send_second_message_start_batch_result = ( - server_rpc_event.operation_call.start_server_batch([ - cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), - ], server_send_second_message_tag)) - server_complete_rpc_start_batch_result = ( - server_rpc_event.operation_call.start_server_batch([ - cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), - cygrpc.operation_send_status_from_server( - cygrpc.Metadata(()), cygrpc.StatusCode.ok, b'test details', - _EMPTY_FLAGS), - ], server_complete_rpc_tag)) - server_send_second_message_event = server_call_driver.event_with_tag( - server_send_second_message_tag) - server_complete_rpc_event = server_call_driver.event_with_tag( - server_complete_rpc_tag) - server_call_driver.events() - - with client_condition: - client_receive_first_message_tag = 'client_receive_first_message_tag' - client_receive_first_message_start_batch_result = ( - client_call.start_client_batch(cygrpc.Operations([ - cygrpc.operation_receive_message(_EMPTY_FLAGS), - ]), client_receive_first_message_tag)) - client_due.add(client_receive_first_message_tag) - client_receive_first_message_event = client_driver.event_with_tag( - client_receive_first_message_tag) - - client_call_cancel_result = client_call.cancel() - client_driver.events() - - server.shutdown(server_completion_queue, server_shutdown_tag) - server.cancel_all_calls() - server_driver.events() - - self.assertEqual(cygrpc.CallError.ok, request_call_result) - self.assertEqual( - cygrpc.CallError.ok, server_send_initial_metadata_start_batch_result) - self.assertEqual( - cygrpc.CallError.ok, client_receive_initial_metadata_start_batch_result) - self.assertEqual( - cygrpc.CallError.ok, client_complete_rpc_start_batch_result) - self.assertEqual(cygrpc.CallError.ok, client_call_cancel_result) - self.assertIs(server_rpc_tag, server_rpc_event.tag) - self.assertEqual( - cygrpc.CompletionType.operation_complete, server_rpc_event.type) - self.assertIsInstance(server_rpc_event.operation_call, cygrpc.Call) - self.assertEqual(0, len(server_rpc_event.batch_operations)) + def testReadSomeButNotAllResponses(self): + server_completion_queue = cygrpc.CompletionQueue() + server = cygrpc.Server(cygrpc.ChannelArgs([])) + server.register_completion_queue(server_completion_queue) + port = server.add_http2_port(b'[::]:0') + server.start() + channel = cygrpc.Channel('localhost:{}'.format(port).encode(), + cygrpc.ChannelArgs([])) + + server_shutdown_tag = 'server_shutdown_tag' + server_driver = _ServerDriver(server_completion_queue, + server_shutdown_tag) + server_driver.start() + + client_condition = threading.Condition() + client_due = set() + client_completion_queue = cygrpc.CompletionQueue() + client_driver = _QueueDriver(client_condition, client_completion_queue, + client_due) + client_driver.start() + + server_call_condition = threading.Condition() + server_send_initial_metadata_tag = 'server_send_initial_metadata_tag' + server_send_first_message_tag = 'server_send_first_message_tag' + server_send_second_message_tag = 'server_send_second_message_tag' + server_complete_rpc_tag = 'server_complete_rpc_tag' + server_call_due = set(( + server_send_initial_metadata_tag, + server_send_first_message_tag, + server_send_second_message_tag, + server_complete_rpc_tag,)) + server_call_completion_queue = cygrpc.CompletionQueue() + server_call_driver = _QueueDriver(server_call_condition, + server_call_completion_queue, + server_call_due) + server_call_driver.start() + + server_rpc_tag = 'server_rpc_tag' + request_call_result = server.request_call(server_call_completion_queue, + server_completion_queue, + server_rpc_tag) + + client_call = channel.create_call(None, _EMPTY_FLAGS, + client_completion_queue, b'/twinkies', + None, _INFINITE_FUTURE) + client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag' + client_complete_rpc_tag = 'client_complete_rpc_tag' + with client_condition: + client_receive_initial_metadata_start_batch_result = ( + client_call.start_client_batch( + cygrpc.Operations([ + cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), + ]), client_receive_initial_metadata_tag)) + client_due.add(client_receive_initial_metadata_tag) + client_complete_rpc_start_batch_result = ( + client_call.start_client_batch( + cygrpc.Operations([ + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS), + cygrpc.operation_send_close_from_client(_EMPTY_FLAGS), + cygrpc.operation_receive_status_on_client(_EMPTY_FLAGS), + ]), client_complete_rpc_tag)) + client_due.add(client_complete_rpc_tag) + + server_rpc_event = server_driver.first_event() + + with server_call_condition: + server_send_initial_metadata_start_batch_result = ( + server_rpc_event.operation_call.start_server_batch([ + cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, + _EMPTY_FLAGS), + ], server_send_initial_metadata_tag)) + server_send_first_message_start_batch_result = ( + server_rpc_event.operation_call.start_server_batch([ + cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), + ], server_send_first_message_tag)) + server_send_initial_metadata_event = server_call_driver.event_with_tag( + server_send_initial_metadata_tag) + server_send_first_message_event = server_call_driver.event_with_tag( + server_send_first_message_tag) + with server_call_condition: + server_send_second_message_start_batch_result = ( + server_rpc_event.operation_call.start_server_batch([ + cygrpc.operation_send_message(b'\x07', _EMPTY_FLAGS), + ], server_send_second_message_tag)) + server_complete_rpc_start_batch_result = ( + server_rpc_event.operation_call.start_server_batch([ + cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), + cygrpc.operation_send_status_from_server( + cygrpc.Metadata(()), cygrpc.StatusCode.ok, + b'test details', _EMPTY_FLAGS), + ], server_complete_rpc_tag)) + server_send_second_message_event = server_call_driver.event_with_tag( + server_send_second_message_tag) + server_complete_rpc_event = server_call_driver.event_with_tag( + server_complete_rpc_tag) + server_call_driver.events() + + with client_condition: + client_receive_first_message_tag = 'client_receive_first_message_tag' + client_receive_first_message_start_batch_result = ( + client_call.start_client_batch( + cygrpc.Operations([ + cygrpc.operation_receive_message(_EMPTY_FLAGS), + ]), client_receive_first_message_tag)) + client_due.add(client_receive_first_message_tag) + client_receive_first_message_event = client_driver.event_with_tag( + client_receive_first_message_tag) + + client_call_cancel_result = client_call.cancel() + client_driver.events() + + server.shutdown(server_completion_queue, server_shutdown_tag) + server.cancel_all_calls() + server_driver.events() + + self.assertEqual(cygrpc.CallError.ok, request_call_result) + self.assertEqual(cygrpc.CallError.ok, + server_send_initial_metadata_start_batch_result) + self.assertEqual(cygrpc.CallError.ok, + client_receive_initial_metadata_start_batch_result) + self.assertEqual(cygrpc.CallError.ok, + client_complete_rpc_start_batch_result) + self.assertEqual(cygrpc.CallError.ok, client_call_cancel_result) + self.assertIs(server_rpc_tag, server_rpc_event.tag) + self.assertEqual(cygrpc.CompletionType.operation_complete, + server_rpc_event.type) + self.assertIsInstance(server_rpc_event.operation_call, cygrpc.Call) + self.assertEqual(0, len(server_rpc_event.batch_operations)) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py index 8dedebfabee..7aec316b95d 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py +++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py @@ -37,399 +37,421 @@ from tests.unit._cython import test_utilities from tests.unit import test_common from tests.unit import resources - _SSL_HOST_OVERRIDE = b'foo.test.google.fr' _CALL_CREDENTIALS_METADATA_KEY = 'call-creds-key' _CALL_CREDENTIALS_METADATA_VALUE = 'call-creds-value' _EMPTY_FLAGS = 0 + def _metadata_plugin_callback(context, callback): - callback(cygrpc.Metadata( - [cygrpc.Metadatum(_CALL_CREDENTIALS_METADATA_KEY, - _CALL_CREDENTIALS_METADATA_VALUE)]), - cygrpc.StatusCode.ok, b'') + callback( + cygrpc.Metadata([ + cygrpc.Metadatum(_CALL_CREDENTIALS_METADATA_KEY, + _CALL_CREDENTIALS_METADATA_VALUE) + ]), cygrpc.StatusCode.ok, b'') class TypeSmokeTest(unittest.TestCase): - def testStringsInUtilitiesUpDown(self): - self.assertEqual(0, cygrpc.StatusCode.ok) - metadatum = cygrpc.Metadatum(b'a', b'b') - self.assertEqual(b'a', metadatum.key) - self.assertEqual(b'b', metadatum.value) - metadata = cygrpc.Metadata([metadatum]) - self.assertEqual(1, len(metadata)) - self.assertEqual(metadatum.key, metadata[0].key) - - def testMetadataIteration(self): - metadata = cygrpc.Metadata([ - cygrpc.Metadatum(b'a', b'b'), cygrpc.Metadatum(b'c', b'd')]) - iterator = iter(metadata) - metadatum = next(iterator) - self.assertIsInstance(metadatum, cygrpc.Metadatum) - self.assertEqual(metadatum.key, b'a') - self.assertEqual(metadatum.value, b'b') - metadatum = next(iterator) - self.assertIsInstance(metadatum, cygrpc.Metadatum) - self.assertEqual(metadatum.key, b'c') - self.assertEqual(metadatum.value, b'd') - with self.assertRaises(StopIteration): - next(iterator) - - def testOperationsIteration(self): - operations = cygrpc.Operations([ - cygrpc.operation_send_message(b'asdf', _EMPTY_FLAGS)]) - iterator = iter(operations) - operation = next(iterator) - self.assertIsInstance(operation, cygrpc.Operation) - # `Operation`s are write-only structures; can't directly debug anything out - # of them. Just check that we stop iterating. - with self.assertRaises(StopIteration): - next(iterator) - - def testOperationFlags(self): - operation = cygrpc.operation_send_message(b'asdf', - cygrpc.WriteFlag.no_compress) - self.assertEqual(cygrpc.WriteFlag.no_compress, operation.flags) - - def testTimespec(self): - now = time.time() - timespec = cygrpc.Timespec(now) - self.assertAlmostEqual(now, float(timespec), places=8) - - def testCompletionQueueUpDown(self): - completion_queue = cygrpc.CompletionQueue() - del completion_queue - - def testServerUpDown(self): - server = cygrpc.Server(cygrpc.ChannelArgs([])) - del server - - def testChannelUpDown(self): - channel = cygrpc.Channel(b'[::]:0', cygrpc.ChannelArgs([])) - del channel - - def testCredentialsMetadataPluginUpDown(self): - plugin = cygrpc.CredentialsMetadataPlugin( - lambda ignored_a, ignored_b: None, b'') - del plugin - - def testCallCredentialsFromPluginUpDown(self): - plugin = cygrpc.CredentialsMetadataPlugin(_metadata_plugin_callback, b'') - call_credentials = cygrpc.call_credentials_metadata_plugin(plugin) - del plugin - del call_credentials - - def testServerStartNoExplicitShutdown(self): - server = cygrpc.Server(cygrpc.ChannelArgs([])) - completion_queue = cygrpc.CompletionQueue() - server.register_completion_queue(completion_queue) - port = server.add_http2_port(b'[::]:0') - self.assertIsInstance(port, int) - server.start() - del server - - def testServerStartShutdown(self): - completion_queue = cygrpc.CompletionQueue() - server = cygrpc.Server(cygrpc.ChannelArgs([])) - server.add_http2_port(b'[::]:0') - server.register_completion_queue(completion_queue) - server.start() - shutdown_tag = object() - server.shutdown(completion_queue, shutdown_tag) - event = completion_queue.poll() - self.assertEqual(cygrpc.CompletionType.operation_complete, event.type) - self.assertIs(shutdown_tag, event.tag) - del server - del completion_queue + def testStringsInUtilitiesUpDown(self): + self.assertEqual(0, cygrpc.StatusCode.ok) + metadatum = cygrpc.Metadatum(b'a', b'b') + self.assertEqual(b'a', metadatum.key) + self.assertEqual(b'b', metadatum.value) + metadata = cygrpc.Metadata([metadatum]) + self.assertEqual(1, len(metadata)) + self.assertEqual(metadatum.key, metadata[0].key) + + def testMetadataIteration(self): + metadata = cygrpc.Metadata( + [cygrpc.Metadatum(b'a', b'b'), cygrpc.Metadatum(b'c', b'd')]) + iterator = iter(metadata) + metadatum = next(iterator) + self.assertIsInstance(metadatum, cygrpc.Metadatum) + self.assertEqual(metadatum.key, b'a') + self.assertEqual(metadatum.value, b'b') + metadatum = next(iterator) + self.assertIsInstance(metadatum, cygrpc.Metadatum) + self.assertEqual(metadatum.key, b'c') + self.assertEqual(metadatum.value, b'd') + with self.assertRaises(StopIteration): + next(iterator) + + def testOperationsIteration(self): + operations = cygrpc.Operations( + [cygrpc.operation_send_message(b'asdf', _EMPTY_FLAGS)]) + iterator = iter(operations) + operation = next(iterator) + self.assertIsInstance(operation, cygrpc.Operation) + # `Operation`s are write-only structures; can't directly debug anything out + # of them. Just check that we stop iterating. + with self.assertRaises(StopIteration): + next(iterator) + + def testOperationFlags(self): + operation = cygrpc.operation_send_message(b'asdf', + cygrpc.WriteFlag.no_compress) + self.assertEqual(cygrpc.WriteFlag.no_compress, operation.flags) + + def testTimespec(self): + now = time.time() + timespec = cygrpc.Timespec(now) + self.assertAlmostEqual(now, float(timespec), places=8) + + def testCompletionQueueUpDown(self): + completion_queue = cygrpc.CompletionQueue() + del completion_queue + + def testServerUpDown(self): + server = cygrpc.Server(cygrpc.ChannelArgs([])) + del server + + def testChannelUpDown(self): + channel = cygrpc.Channel(b'[::]:0', cygrpc.ChannelArgs([])) + del channel + + def testCredentialsMetadataPluginUpDown(self): + plugin = cygrpc.CredentialsMetadataPlugin( + lambda ignored_a, ignored_b: None, b'') + del plugin + + def testCallCredentialsFromPluginUpDown(self): + plugin = cygrpc.CredentialsMetadataPlugin(_metadata_plugin_callback, + b'') + call_credentials = cygrpc.call_credentials_metadata_plugin(plugin) + del plugin + del call_credentials + + def testServerStartNoExplicitShutdown(self): + server = cygrpc.Server(cygrpc.ChannelArgs([])) + completion_queue = cygrpc.CompletionQueue() + server.register_completion_queue(completion_queue) + port = server.add_http2_port(b'[::]:0') + self.assertIsInstance(port, int) + server.start() + del server + + def testServerStartShutdown(self): + completion_queue = cygrpc.CompletionQueue() + server = cygrpc.Server(cygrpc.ChannelArgs([])) + server.add_http2_port(b'[::]:0') + server.register_completion_queue(completion_queue) + server.start() + shutdown_tag = object() + server.shutdown(completion_queue, shutdown_tag) + event = completion_queue.poll() + self.assertEqual(cygrpc.CompletionType.operation_complete, event.type) + self.assertIs(shutdown_tag, event.tag) + del server + del completion_queue class ServerClientMixin(object): - def setUpMixin(self, server_credentials, client_credentials, host_override): - self.server_completion_queue = cygrpc.CompletionQueue() - self.server = cygrpc.Server(cygrpc.ChannelArgs([])) - self.server.register_completion_queue(self.server_completion_queue) - if server_credentials: - self.port = self.server.add_http2_port(b'[::]:0', server_credentials) - else: - self.port = self.server.add_http2_port(b'[::]:0') - self.server.start() - self.client_completion_queue = cygrpc.CompletionQueue() - if client_credentials: - client_channel_arguments = cygrpc.ChannelArgs([ - cygrpc.ChannelArg(cygrpc.ChannelArgKey.ssl_target_name_override, - host_override)]) - self.client_channel = cygrpc.Channel( - 'localhost:{}'.format(self.port).encode(), client_channel_arguments, - client_credentials) - else: - self.client_channel = cygrpc.Channel( - 'localhost:{}'.format(self.port).encode(), cygrpc.ChannelArgs([])) - 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.client_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. + def setUpMixin(self, server_credentials, client_credentials, host_override): + self.server_completion_queue = cygrpc.CompletionQueue() + self.server = cygrpc.Server(cygrpc.ChannelArgs([])) + self.server.register_completion_queue(self.server_completion_queue) + if server_credentials: + self.port = self.server.add_http2_port(b'[::]:0', + server_credentials) + else: + self.port = self.server.add_http2_port(b'[::]:0') + self.server.start() + self.client_completion_queue = cygrpc.CompletionQueue() + if client_credentials: + client_channel_arguments = cygrpc.ChannelArgs([ + cygrpc.ChannelArg(cygrpc.ChannelArgKey.ssl_target_name_override, + host_override) + ]) + self.client_channel = cygrpc.Channel( + 'localhost:{}'.format(self.port).encode(), + client_channel_arguments, client_credentials) + else: + self.client_channel = cygrpc.Channel( + 'localhost:{}'.format(self.port).encode(), + cygrpc.ChannelArgs([])) + 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.client_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_client_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): - DEADLINE = time.time()+5 - DEADLINE_TOLERANCE = 0.25 - CLIENT_METADATA_ASCII_KEY = b'key' - 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' - - cygrpc_deadline = cygrpc.Timespec(DEADLINE) - - server_request_tag = object() - request_call_result = self.server.request_call( - self.server_completion_queue, self.server_completion_queue, - server_request_tag) - - self.assertEqual(cygrpc.CallError.ok, request_call_result) - - client_call_tag = object() - client_call = self.client_channel.create_call( - None, 0, self.client_completion_queue, METHOD, self.host_argument, - cygrpc_deadline) - client_initial_metadata = cygrpc.Metadata([ - 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_client_batch([ - 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) - 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)) - self.assertTrue( - test_common.metadata_transmitted(client_initial_metadata, - request_event.request_metadata)) - self.assertEqual(METHOD, request_event.request_call_details.method) - self.assertEqual(self.expected_host, - 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_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_server_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) - - server_event = self.server_completion_queue.poll(cygrpc_deadline) - client_event = client_event_future.result() - - self.assertEqual(6, len(client_event.batch_operations)) - found_client_op_types = set() - for client_result in client_event.batch_operations: - # we expect each op type to be unique - 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: + + def performer(): + tag = object() + try: + call_result = call.start_client_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): + DEADLINE = time.time() + 5 + DEADLINE_TOLERANCE = 0.25 + CLIENT_METADATA_ASCII_KEY = b'key' + 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' + + cygrpc_deadline = cygrpc.Timespec(DEADLINE) + + server_request_tag = object() + request_call_result = self.server.request_call( + self.server_completion_queue, self.server_completion_queue, + server_request_tag) + + self.assertEqual(cygrpc.CallError.ok, request_call_result) + + client_call_tag = object() + client_call = self.client_channel.create_call( + None, 0, self.client_completion_queue, METHOD, self.host_argument, + cygrpc_deadline) + client_initial_metadata = cygrpc.Metadata([ + 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_client_batch([ + 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) + 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)) 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)) - found_server_op_types = set() - 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 - del server_call - - def test6522(self): - DEADLINE = time.time()+5 - DEADLINE_TOLERANCE = 0.25 - METHOD = b'twinkies' - - cygrpc_deadline = cygrpc.Timespec(DEADLINE) - empty_metadata = cygrpc.Metadata([]) - - server_request_tag = object() - self.server.request_call( - self.server_completion_queue, self.server_completion_queue, - server_request_tag) - client_call = self.client_channel.create_call( - None, 0, self.client_completion_queue, METHOD, self.host_argument, - cygrpc_deadline) - - # Prologue - def perform_client_operations(operations, description): - return self._perform_operations( - operations, client_call, - self.client_completion_queue, cygrpc_deadline, description) - - client_event_future = perform_client_operations([ + test_common.metadata_transmitted(client_initial_metadata, + request_event.request_metadata)) + self.assertEqual(METHOD, request_event.request_call_details.method) + self.assertEqual(self.expected_host, + 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_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_server_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) + + server_event = self.server_completion_queue.poll(cygrpc_deadline) + client_event = client_event_future.result() + + self.assertEqual(6, len(client_event.batch_operations)) + found_client_op_types = set() + for client_result in client_event.batch_operations: + # we expect each op type to be unique + 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)) + found_server_op_types = set() + 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 + del server_call + + def test6522(self): + DEADLINE = time.time() + 5 + DEADLINE_TOLERANCE = 0.25 + METHOD = b'twinkies' + + cygrpc_deadline = cygrpc.Timespec(DEADLINE) + empty_metadata = cygrpc.Metadata([]) + + server_request_tag = object() + self.server.request_call(self.server_completion_queue, + self.server_completion_queue, + server_request_tag) + client_call = self.client_channel.create_call( + None, 0, self.client_completion_queue, METHOD, self.host_argument, + cygrpc_deadline) + + # Prologue + def perform_client_operations(operations, description): + return self._perform_operations(operations, client_call, + self.client_completion_queue, + cygrpc_deadline, description) + + client_event_future = perform_client_operations([ cygrpc.operation_send_initial_metadata(empty_metadata, _EMPTY_FLAGS), cygrpc.operation_receive_initial_metadata(_EMPTY_FLAGS), ], "Client prologue") - request_event = self.server_completion_queue.poll(cygrpc_deadline) - server_call = request_event.operation_call + request_event = self.server_completion_queue.poll(cygrpc_deadline) + server_call = request_event.operation_call - def perform_server_operations(operations, description): - return self._perform_operations( - operations, server_call, - self.server_completion_queue, cygrpc_deadline, description) + def perform_server_operations(operations, description): + return self._perform_operations(operations, server_call, + self.server_completion_queue, + cygrpc_deadline, description) - server_event_future = perform_server_operations([ + server_event_future = perform_server_operations([ cygrpc.operation_send_initial_metadata(empty_metadata, _EMPTY_FLAGS), ], "Server prologue") - client_event_future.result() # force completion - server_event_future.result() - - # Messaging - 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([ + client_event_future.result() # force completion + server_event_future.result() + + # Messaging + 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([ + 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() + client_event_future.result() # force completion + server_event_future.result() class InsecureServerInsecureClient(unittest.TestCase, ServerClientMixin): - def setUp(self): - self.setUpMixin(None, None, None) + def setUp(self): + self.setUpMixin(None, None, None) - def tearDown(self): - self.tearDownMixin() + 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 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() + def tearDown(self): + self.tearDownMixin() if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py b/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py index 6280ce74c47..dffb3733b6f 100644 --- a/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py +++ b/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py @@ -33,34 +33,35 @@ from grpc._cython import cygrpc class SimpleFuture(object): - """A simple future mechanism.""" + """A simple future mechanism.""" - def __init__(self, function, *args, **kwargs): - def wrapped_function(): - try: - self._result = function(*args, **kwargs) - except Exception as error: - self._error = error - self._result = None - self._error = None - self._thread = threading.Thread(target=wrapped_function) - self._thread.start() + def __init__(self, function, *args, **kwargs): - def result(self): - """The resulting value of this future. + def wrapped_function(): + try: + self._result = function(*args, **kwargs) + except Exception as error: + self._error = error + + self._result = None + self._error = None + self._thread = threading.Thread(target=wrapped_function) + self._thread.start() + + def result(self): + """The resulting value of this future. Re-raises any exceptions. """ - self._thread.join() - if self._error: - # TODO(atash): re-raise exceptions in a way that preserves tracebacks - raise self._error - return self._result + self._thread.join() + 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)) - + def __init__(self, completion_queue, deadline): + super(CompletionQueuePollFuture, + self).__init__(lambda: completion_queue.poll(deadline)) diff --git a/src/python/grpcio_tests/tests/unit/_empty_message_test.py b/src/python/grpcio_tests/tests/unit/_empty_message_test.py index 69f46892790..4588688ea60 100644 --- a/src/python/grpcio_tests/tests/unit/_empty_message_test.py +++ b/src/python/grpcio_tests/tests/unit/_empty_message_test.py @@ -44,95 +44,94 @@ _STREAM_STREAM = '/test/StreamStream' def handle_unary_unary(request, servicer_context): - return _RESPONSE + return _RESPONSE def handle_unary_stream(request, servicer_context): - for _ in range(test_constants.STREAM_LENGTH): - yield _RESPONSE + for _ in range(test_constants.STREAM_LENGTH): + yield _RESPONSE def handle_stream_unary(request_iterator, servicer_context): - for request in request_iterator: - pass - return _RESPONSE + for request in request_iterator: + pass + return _RESPONSE def handle_stream_stream(request_iterator, servicer_context): - for request in request_iterator: - yield _RESPONSE + for request in request_iterator: + yield _RESPONSE class _MethodHandler(grpc.RpcMethodHandler): - def __init__(self, request_streaming, response_streaming): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = None - self.response_serializer = None - self.unary_unary = None - self.unary_stream = None - self.stream_unary = None - self.stream_stream = None - if self.request_streaming and self.response_streaming: - self.stream_stream = handle_stream_stream - elif self.request_streaming: - self.stream_unary = handle_stream_unary - elif self.response_streaming: - self.unary_stream = handle_unary_stream - else: - self.unary_unary = handle_unary_unary + def __init__(self, request_streaming, response_streaming): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = None + self.response_serializer = None + self.unary_unary = None + self.unary_stream = None + self.stream_unary = None + self.stream_stream = None + if self.request_streaming and self.response_streaming: + self.stream_stream = handle_stream_stream + elif self.request_streaming: + self.stream_unary = handle_stream_unary + elif self.response_streaming: + self.unary_stream = handle_unary_stream + else: + self.unary_unary = handle_unary_unary class _GenericHandler(grpc.GenericRpcHandler): - def service(self, handler_call_details): - if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler(False, False) - elif handler_call_details.method == _UNARY_STREAM: - return _MethodHandler(False, True) - elif handler_call_details.method == _STREAM_UNARY: - return _MethodHandler(True, False) - elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler(True, True) - else: - return None + def service(self, handler_call_details): + if handler_call_details.method == _UNARY_UNARY: + return _MethodHandler(False, False) + elif handler_call_details.method == _UNARY_STREAM: + return _MethodHandler(False, True) + elif handler_call_details.method == _STREAM_UNARY: + return _MethodHandler(True, False) + elif handler_call_details.method == _STREAM_STREAM: + return _MethodHandler(True, True) + else: + return None class EmptyMessageTest(unittest.TestCase): - def setUp(self): - self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server( - self._server_pool, handlers=(_GenericHandler(),)) - port = self._server.add_insecure_port('[::]:0') - self._server.start() - self._channel = grpc.insecure_channel('localhost:%d' % port) + def setUp(self): + self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server( + self._server_pool, handlers=(_GenericHandler(),)) + port = self._server.add_insecure_port('[::]:0') + self._server.start() + self._channel = grpc.insecure_channel('localhost:%d' % port) - def tearDown(self): - self._server.stop(0) + def tearDown(self): + self._server.stop(0) - def testUnaryUnary(self): - response = self._channel.unary_unary(_UNARY_UNARY)(_REQUEST) - self.assertEqual(_RESPONSE, response) + def testUnaryUnary(self): + response = self._channel.unary_unary(_UNARY_UNARY)(_REQUEST) + self.assertEqual(_RESPONSE, response) - def testUnaryStream(self): - response_iterator = self._channel.unary_stream(_UNARY_STREAM)(_REQUEST) - self.assertSequenceEqual( - [_RESPONSE] * test_constants.STREAM_LENGTH, list(response_iterator)) + def testUnaryStream(self): + response_iterator = self._channel.unary_stream(_UNARY_STREAM)(_REQUEST) + self.assertSequenceEqual([_RESPONSE] * test_constants.STREAM_LENGTH, + list(response_iterator)) - def testStreamUnary(self): - response = self._channel.stream_unary(_STREAM_UNARY)( - iter([_REQUEST] * test_constants.STREAM_LENGTH)) - self.assertEqual(_RESPONSE, response) + def testStreamUnary(self): + response = self._channel.stream_unary(_STREAM_UNARY)(iter( + [_REQUEST] * test_constants.STREAM_LENGTH)) + self.assertEqual(_RESPONSE, response) - def testStreamStream(self): - response_iterator = self._channel.stream_stream(_STREAM_STREAM)( - iter([_REQUEST] * test_constants.STREAM_LENGTH)) - self.assertSequenceEqual( - [_RESPONSE] * test_constants.STREAM_LENGTH, list(response_iterator)) + def testStreamStream(self): + response_iterator = self._channel.stream_stream(_STREAM_STREAM)(iter( + [_REQUEST] * test_constants.STREAM_LENGTH)) + self.assertSequenceEqual([_RESPONSE] * test_constants.STREAM_LENGTH, + list(response_iterator)) if __name__ == '__main__': - unittest.main(verbosity=2) - + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_exit_scenarios.py b/src/python/grpcio_tests/tests/unit/_exit_scenarios.py index 777527137f0..22a66438485 100644 --- a/src/python/grpcio_tests/tests/unit/_exit_scenarios.py +++ b/src/python/grpcio_tests/tests/unit/_exit_scenarios.py @@ -26,7 +26,6 @@ # 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. - """Defines a number of module-scope gRPC scenarios to test clean exit.""" import argparse @@ -73,88 +72,88 @@ TEST_TO_METHOD = { def hang_unary_unary(request, servicer_context): - time.sleep(WAIT_TIME) + time.sleep(WAIT_TIME) def hang_unary_stream(request, servicer_context): - time.sleep(WAIT_TIME) + time.sleep(WAIT_TIME) def hang_partial_unary_stream(request, servicer_context): - for _ in range(test_constants.STREAM_LENGTH // 2): - yield request - time.sleep(WAIT_TIME) + for _ in range(test_constants.STREAM_LENGTH // 2): + yield request + time.sleep(WAIT_TIME) def hang_stream_unary(request_iterator, servicer_context): - time.sleep(WAIT_TIME) + time.sleep(WAIT_TIME) def hang_partial_stream_unary(request_iterator, servicer_context): - for _ in range(test_constants.STREAM_LENGTH // 2): - next(request_iterator) - time.sleep(WAIT_TIME) + for _ in range(test_constants.STREAM_LENGTH // 2): + next(request_iterator) + time.sleep(WAIT_TIME) def hang_stream_stream(request_iterator, servicer_context): - time.sleep(WAIT_TIME) + time.sleep(WAIT_TIME) def hang_partial_stream_stream(request_iterator, servicer_context): - for _ in range(test_constants.STREAM_LENGTH // 2): - yield next(request_iterator) - time.sleep(WAIT_TIME) + for _ in range(test_constants.STREAM_LENGTH // 2): + yield next(request_iterator) + time.sleep(WAIT_TIME) class MethodHandler(grpc.RpcMethodHandler): - def __init__(self, request_streaming, response_streaming, partial_hang): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = None - self.response_serializer = None - self.unary_unary = None - self.unary_stream = None - self.stream_unary = None - self.stream_stream = None - if self.request_streaming and self.response_streaming: - if partial_hang: - self.stream_stream = hang_partial_stream_stream - else: - self.stream_stream = hang_stream_stream - elif self.request_streaming: - if partial_hang: - self.stream_unary = hang_partial_stream_unary - else: - self.stream_unary = hang_stream_unary - elif self.response_streaming: - if partial_hang: - self.unary_stream = hang_partial_unary_stream - else: - self.unary_stream = hang_unary_stream - else: - self.unary_unary = hang_unary_unary + def __init__(self, request_streaming, response_streaming, partial_hang): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = None + self.response_serializer = None + self.unary_unary = None + self.unary_stream = None + self.stream_unary = None + self.stream_stream = None + if self.request_streaming and self.response_streaming: + if partial_hang: + self.stream_stream = hang_partial_stream_stream + else: + self.stream_stream = hang_stream_stream + elif self.request_streaming: + if partial_hang: + self.stream_unary = hang_partial_stream_unary + else: + self.stream_unary = hang_stream_unary + elif self.response_streaming: + if partial_hang: + self.unary_stream = hang_partial_unary_stream + else: + self.unary_stream = hang_unary_stream + else: + self.unary_unary = hang_unary_unary class GenericHandler(grpc.GenericRpcHandler): - def service(self, handler_call_details): - if handler_call_details.method == UNARY_UNARY: - return MethodHandler(False, False, False) - elif handler_call_details.method == UNARY_STREAM: - return MethodHandler(False, True, False) - elif handler_call_details.method == STREAM_UNARY: - return MethodHandler(True, False, False) - elif handler_call_details.method == STREAM_STREAM: - return MethodHandler(True, True, False) - elif handler_call_details.method == PARTIAL_UNARY_STREAM: - return MethodHandler(False, True, True) - elif handler_call_details.method == PARTIAL_STREAM_UNARY: - return MethodHandler(True, False, True) - elif handler_call_details.method == PARTIAL_STREAM_STREAM: - return MethodHandler(True, True, True) - else: - return None + def service(self, handler_call_details): + if handler_call_details.method == UNARY_UNARY: + return MethodHandler(False, False, False) + elif handler_call_details.method == UNARY_STREAM: + return MethodHandler(False, True, False) + elif handler_call_details.method == STREAM_UNARY: + return MethodHandler(True, False, False) + elif handler_call_details.method == STREAM_STREAM: + return MethodHandler(True, True, False) + elif handler_call_details.method == PARTIAL_UNARY_STREAM: + return MethodHandler(False, True, True) + elif handler_call_details.method == PARTIAL_STREAM_UNARY: + return MethodHandler(True, False, True) + elif handler_call_details.method == PARTIAL_STREAM_STREAM: + return MethodHandler(True, True, True) + else: + return None # Traditional executors will not exit until all their @@ -162,88 +161,88 @@ class GenericHandler(grpc.GenericRpcHandler): # never finish, we don't want to block exit on these jobs. class DaemonPool(object): - def submit(self, fn, *args, **kwargs): - thread = threading.Thread(target=fn, args=args, kwargs=kwargs) - thread.daemon = True - thread.start() + def submit(self, fn, *args, **kwargs): + thread = threading.Thread(target=fn, args=args, kwargs=kwargs) + thread.daemon = True + thread.start() - def shutdown(self, wait=True): - pass + def shutdown(self, wait=True): + pass def infinite_request_iterator(): - while True: - yield REQUEST + while True: + yield REQUEST if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('scenario', type=str) - parser.add_argument( - '--wait_for_interrupt', dest='wait_for_interrupt', action='store_true') - args = parser.parse_args() - - if args.scenario == UNSTARTED_SERVER: - server = grpc.server(DaemonPool()) - if args.wait_for_interrupt: - time.sleep(WAIT_TIME) - elif args.scenario == RUNNING_SERVER: - server = grpc.server(DaemonPool()) - port = server.add_insecure_port('[::]:0') - server.start() - if args.wait_for_interrupt: - time.sleep(WAIT_TIME) - elif args.scenario == POLL_CONNECTIVITY_NO_SERVER: - channel = grpc.insecure_channel('localhost:12345') - - def connectivity_callback(connectivity): - pass - - channel.subscribe(connectivity_callback, try_to_connect=True) - if args.wait_for_interrupt: - time.sleep(WAIT_TIME) - elif args.scenario == POLL_CONNECTIVITY: - server = grpc.server(DaemonPool()) - port = server.add_insecure_port('[::]:0') - server.start() - channel = grpc.insecure_channel('localhost:%d' % port) - - def connectivity_callback(connectivity): - pass - - channel.subscribe(connectivity_callback, try_to_connect=True) - if args.wait_for_interrupt: - time.sleep(WAIT_TIME) - - else: - handler = GenericHandler() - server = grpc.server(DaemonPool()) - port = server.add_insecure_port('[::]:0') - server.add_generic_rpc_handlers((handler,)) - server.start() - channel = grpc.insecure_channel('localhost:%d' % port) - - method = TEST_TO_METHOD[args.scenario] - - if args.scenario == IN_FLIGHT_UNARY_UNARY_CALL: - multi_callable = channel.unary_unary(method) - future = multi_callable.future(REQUEST) - result, call = multi_callable.with_call(REQUEST) - elif (args.scenario == IN_FLIGHT_UNARY_STREAM_CALL or - args.scenario == IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL): - multi_callable = channel.unary_stream(method) - response_iterator = multi_callable(REQUEST) - for response in response_iterator: - pass - elif (args.scenario == IN_FLIGHT_STREAM_UNARY_CALL or - args.scenario == IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL): - multi_callable = channel.stream_unary(method) - future = multi_callable.future(infinite_request_iterator()) - result, call = multi_callable.with_call( - iter([REQUEST] * test_constants.STREAM_LENGTH)) - elif (args.scenario == IN_FLIGHT_STREAM_STREAM_CALL or - args.scenario == IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL): - multi_callable = channel.stream_stream(method) - response_iterator = multi_callable(infinite_request_iterator()) - for response in response_iterator: - pass + parser = argparse.ArgumentParser() + parser.add_argument('scenario', type=str) + parser.add_argument( + '--wait_for_interrupt', dest='wait_for_interrupt', action='store_true') + args = parser.parse_args() + + if args.scenario == UNSTARTED_SERVER: + server = grpc.server(DaemonPool()) + if args.wait_for_interrupt: + time.sleep(WAIT_TIME) + elif args.scenario == RUNNING_SERVER: + server = grpc.server(DaemonPool()) + port = server.add_insecure_port('[::]:0') + server.start() + if args.wait_for_interrupt: + time.sleep(WAIT_TIME) + elif args.scenario == POLL_CONNECTIVITY_NO_SERVER: + channel = grpc.insecure_channel('localhost:12345') + + def connectivity_callback(connectivity): + pass + + channel.subscribe(connectivity_callback, try_to_connect=True) + if args.wait_for_interrupt: + time.sleep(WAIT_TIME) + elif args.scenario == POLL_CONNECTIVITY: + server = grpc.server(DaemonPool()) + port = server.add_insecure_port('[::]:0') + server.start() + channel = grpc.insecure_channel('localhost:%d' % port) + + def connectivity_callback(connectivity): + pass + + channel.subscribe(connectivity_callback, try_to_connect=True) + if args.wait_for_interrupt: + time.sleep(WAIT_TIME) + + else: + handler = GenericHandler() + server = grpc.server(DaemonPool()) + port = server.add_insecure_port('[::]:0') + server.add_generic_rpc_handlers((handler,)) + server.start() + channel = grpc.insecure_channel('localhost:%d' % port) + + method = TEST_TO_METHOD[args.scenario] + + if args.scenario == IN_FLIGHT_UNARY_UNARY_CALL: + multi_callable = channel.unary_unary(method) + future = multi_callable.future(REQUEST) + result, call = multi_callable.with_call(REQUEST) + elif (args.scenario == IN_FLIGHT_UNARY_STREAM_CALL or + args.scenario == IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL): + multi_callable = channel.unary_stream(method) + response_iterator = multi_callable(REQUEST) + for response in response_iterator: + pass + elif (args.scenario == IN_FLIGHT_STREAM_UNARY_CALL or + args.scenario == IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL): + multi_callable = channel.stream_unary(method) + future = multi_callable.future(infinite_request_iterator()) + result, call = multi_callable.with_call( + iter([REQUEST] * test_constants.STREAM_LENGTH)) + elif (args.scenario == IN_FLIGHT_STREAM_STREAM_CALL or + args.scenario == IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL): + multi_callable = channel.stream_stream(method) + response_iterator = multi_callable(infinite_request_iterator()) + for response in response_iterator: + pass diff --git a/src/python/grpcio_tests/tests/unit/_exit_test.py b/src/python/grpcio_tests/tests/unit/_exit_test.py index 5a4a32887c3..b99605dcb85 100644 --- a/src/python/grpcio_tests/tests/unit/_exit_test.py +++ b/src/python/grpcio_tests/tests/unit/_exit_test.py @@ -26,7 +26,6 @@ # 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. - """Tests clean exit of server/client on Python Interpreter exit/sigint. The tests in this module spawn a subprocess for each test case, the @@ -45,15 +44,15 @@ import unittest from tests.unit import _exit_scenarios -SCENARIO_FILE = os.path.abspath(os.path.join( - os.path.dirname(os.path.realpath(__file__)), '_exit_scenarios.py')) +SCENARIO_FILE = os.path.abspath( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), '_exit_scenarios.py')) INTERPRETER = sys.executable BASE_COMMAND = [INTERPRETER, SCENARIO_FILE] BASE_SIGTERM_COMMAND = BASE_COMMAND + ['--wait_for_interrupt'] INIT_TIME = 1.0 - processes = [] process_lock = threading.Lock() @@ -61,126 +60,146 @@ process_lock = threading.Lock() # Make sure we attempt to clean up any # processes we may have left running def cleanup_processes(): - with process_lock: - for process in processes: - try: - process.kill() - except Exception: - pass + with process_lock: + for process in processes: + try: + process.kill() + except Exception: + pass + + atexit.register(cleanup_processes) def interrupt_and_wait(process): - with process_lock: - processes.append(process) - time.sleep(INIT_TIME) - os.kill(process.pid, signal.SIGINT) - process.wait() + with process_lock: + processes.append(process) + time.sleep(INIT_TIME) + os.kill(process.pid, signal.SIGINT) + process.wait() def wait(process): - with process_lock: - processes.append(process) - process.wait() + with process_lock: + processes.append(process) + process.wait() @unittest.skip('https://github.com/grpc/grpc/issues/7311') class ExitTest(unittest.TestCase): - def test_unstarted_server(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.UNSTARTED_SERVER], - stdout=sys.stdout, stderr=sys.stderr) - wait(process) - - def test_unstarted_server_terminate(self): - process = subprocess.Popen( - BASE_SIGTERM_COMMAND + [_exit_scenarios.UNSTARTED_SERVER], - stdout=sys.stdout) - interrupt_and_wait(process) - - def test_running_server(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.RUNNING_SERVER], - stdout=sys.stdout, stderr=sys.stderr) - wait(process) - - def test_running_server_terminate(self): - process = subprocess.Popen( - BASE_SIGTERM_COMMAND + [_exit_scenarios.RUNNING_SERVER], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - def test_poll_connectivity_no_server(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER], - stdout=sys.stdout, stderr=sys.stderr) - wait(process) - - def test_poll_connectivity_no_server_terminate(self): - process = subprocess.Popen( - BASE_SIGTERM_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - def test_poll_connectivity(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY], - stdout=sys.stdout, stderr=sys.stderr) - wait(process) - - def test_poll_connectivity_terminate(self): - process = subprocess.Popen( - BASE_SIGTERM_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - def test_in_flight_unary_unary_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_UNARY_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') - def test_in_flight_unary_stream_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_STREAM_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - def test_in_flight_stream_unary_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_UNARY_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') - def test_in_flight_stream_stream_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_STREAM_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') - def test_in_flight_partial_unary_stream_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - def test_in_flight_partial_stream_unary_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) - - @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') - def test_in_flight_partial_stream_stream_call(self): - process = subprocess.Popen( - BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL], - stdout=sys.stdout, stderr=sys.stderr) - interrupt_and_wait(process) + def test_unstarted_server(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.UNSTARTED_SERVER], + stdout=sys.stdout, + stderr=sys.stderr) + wait(process) + + def test_unstarted_server_terminate(self): + process = subprocess.Popen( + BASE_SIGTERM_COMMAND + [_exit_scenarios.UNSTARTED_SERVER], + stdout=sys.stdout) + interrupt_and_wait(process) + + def test_running_server(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.RUNNING_SERVER], + stdout=sys.stdout, + stderr=sys.stderr) + wait(process) + + def test_running_server_terminate(self): + process = subprocess.Popen( + BASE_SIGTERM_COMMAND + [_exit_scenarios.RUNNING_SERVER], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + def test_poll_connectivity_no_server(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER], + stdout=sys.stdout, + stderr=sys.stderr) + wait(process) + + def test_poll_connectivity_no_server_terminate(self): + process = subprocess.Popen( + BASE_SIGTERM_COMMAND + + [_exit_scenarios.POLL_CONNECTIVITY_NO_SERVER], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + def test_poll_connectivity(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY], + stdout=sys.stdout, + stderr=sys.stderr) + wait(process) + + def test_poll_connectivity_terminate(self): + process = subprocess.Popen( + BASE_SIGTERM_COMMAND + [_exit_scenarios.POLL_CONNECTIVITY], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + def test_in_flight_unary_unary_call(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_UNARY_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') + def test_in_flight_unary_stream_call(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_UNARY_STREAM_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + def test_in_flight_stream_unary_call(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_UNARY_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') + def test_in_flight_stream_stream_call(self): + process = subprocess.Popen( + BASE_COMMAND + [_exit_scenarios.IN_FLIGHT_STREAM_STREAM_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') + def test_in_flight_partial_unary_stream_call(self): + process = subprocess.Popen( + BASE_COMMAND + + [_exit_scenarios.IN_FLIGHT_PARTIAL_UNARY_STREAM_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + def test_in_flight_partial_stream_unary_call(self): + process = subprocess.Popen( + BASE_COMMAND + + [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_UNARY_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) + + @unittest.skipIf(six.PY2, 'https://github.com/grpc/grpc/issues/6999') + def test_in_flight_partial_stream_stream_call(self): + process = subprocess.Popen( + BASE_COMMAND + + [_exit_scenarios.IN_FLIGHT_PARTIAL_STREAM_STREAM_CALL], + stdout=sys.stdout, + stderr=sys.stderr) + interrupt_and_wait(process) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py index 2dc225de292..1b1b1bd598c 100644 --- a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py +++ b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py @@ -26,7 +26,6 @@ # 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. - """Test of RPCs made against gRPC Python's application-layer API.""" import unittest @@ -47,129 +46,131 @@ _STREAM_STREAM = '/test/StreamStream' def _unary_unary_multi_callable(channel): - return channel.unary_unary(_UNARY_UNARY) + return channel.unary_unary(_UNARY_UNARY) def _unary_stream_multi_callable(channel): - return channel.unary_stream( - _UNARY_STREAM, - request_serializer=_SERIALIZE_REQUEST, - response_deserializer=_DESERIALIZE_RESPONSE) + return channel.unary_stream( + _UNARY_STREAM, + request_serializer=_SERIALIZE_REQUEST, + response_deserializer=_DESERIALIZE_RESPONSE) def _stream_unary_multi_callable(channel): - return channel.stream_unary( - _STREAM_UNARY, - request_serializer=_SERIALIZE_REQUEST, - response_deserializer=_DESERIALIZE_RESPONSE) + return channel.stream_unary( + _STREAM_UNARY, + request_serializer=_SERIALIZE_REQUEST, + response_deserializer=_DESERIALIZE_RESPONSE) def _stream_stream_multi_callable(channel): - return channel.stream_stream(_STREAM_STREAM) + return channel.stream_stream(_STREAM_STREAM) class InvalidMetadataTest(unittest.TestCase): - def setUp(self): - self._channel = grpc.insecure_channel('localhost:8080') - self._unary_unary = _unary_unary_multi_callable(self._channel) - self._unary_stream = _unary_stream_multi_callable(self._channel) - self._stream_unary = _stream_unary_multi_callable(self._channel) - self._stream_stream = _stream_stream_multi_callable(self._channel) - - def testUnaryRequestBlockingUnaryResponse(self): - request = b'\x07\x08' - metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponse'),) - expected_error_details = "metadata was invalid: %s" % metadata - with self.assertRaises(ValueError) as exception_context: - self._unary_unary(request, metadata=metadata) - self.assertIn(expected_error_details, str(exception_context.exception)) - - def testUnaryRequestBlockingUnaryResponseWithCall(self): - request = b'\x07\x08' - metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponseWithCall'),) - expected_error_details = "metadata was invalid: %s" % metadata - with self.assertRaises(ValueError) as exception_context: - self._unary_unary.with_call(request, metadata=metadata) - self.assertIn(expected_error_details, str(exception_context.exception)) - - def testUnaryRequestFutureUnaryResponse(self): - request = b'\x07\x08' - metadata = (('InVaLiD', 'UnaryRequestFutureUnaryResponse'),) - expected_error_details = "metadata was invalid: %s" % metadata - response_future = self._unary_unary.future(request, metadata=metadata) - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertEqual( - exception_context.exception.details(), expected_error_details) - self.assertEqual( - exception_context.exception.code(), grpc.StatusCode.INTERNAL) - self.assertEqual(response_future.details(), expected_error_details) - self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL) - - def testUnaryRequestStreamResponse(self): - request = b'\x37\x58' - metadata = (('InVaLiD', 'UnaryRequestStreamResponse'),) - expected_error_details = "metadata was invalid: %s" % metadata - response_iterator = self._unary_stream(request, metadata=metadata) - with self.assertRaises(grpc.RpcError) as exception_context: - next(response_iterator) - self.assertEqual( - exception_context.exception.details(), expected_error_details) - self.assertEqual( - exception_context.exception.code(), grpc.StatusCode.INTERNAL) - self.assertEqual(response_iterator.details(), expected_error_details) - self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL) - - def testStreamRequestBlockingUnaryResponse(self): - request_iterator = (b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - metadata = (('InVaLiD', 'StreamRequestBlockingUnaryResponse'),) - expected_error_details = "metadata was invalid: %s" % metadata - with self.assertRaises(ValueError) as exception_context: - self._stream_unary(request_iterator, metadata=metadata) - self.assertIn(expected_error_details, str(exception_context.exception)) - - def testStreamRequestBlockingUnaryResponseWithCall(self): - request_iterator = ( - b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - metadata = (('InVaLiD', 'StreamRequestBlockingUnaryResponseWithCall'),) - expected_error_details = "metadata was invalid: %s" % metadata - multi_callable = _stream_unary_multi_callable(self._channel) - with self.assertRaises(ValueError) as exception_context: - multi_callable.with_call(request_iterator, metadata=metadata) - self.assertIn(expected_error_details, str(exception_context.exception)) - - def testStreamRequestFutureUnaryResponse(self): - request_iterator = ( - b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - metadata = (('InVaLiD', 'StreamRequestFutureUnaryResponse'),) - expected_error_details = "metadata was invalid: %s" % metadata - response_future = self._stream_unary.future( - request_iterator, metadata=metadata) - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertEqual( - exception_context.exception.details(), expected_error_details) - self.assertEqual( - exception_context.exception.code(), grpc.StatusCode.INTERNAL) - self.assertEqual(response_future.details(), expected_error_details) - self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL) - - def testStreamRequestStreamResponse(self): - request_iterator = ( - b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - metadata = (('InVaLiD', 'StreamRequestStreamResponse'),) - expected_error_details = "metadata was invalid: %s" % metadata - response_iterator = self._stream_stream(request_iterator, metadata=metadata) - with self.assertRaises(grpc.RpcError) as exception_context: - next(response_iterator) - self.assertEqual( - exception_context.exception.details(), expected_error_details) - self.assertEqual( - exception_context.exception.code(), grpc.StatusCode.INTERNAL) - self.assertEqual(response_iterator.details(), expected_error_details) - self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL) + def setUp(self): + self._channel = grpc.insecure_channel('localhost:8080') + self._unary_unary = _unary_unary_multi_callable(self._channel) + self._unary_stream = _unary_stream_multi_callable(self._channel) + self._stream_unary = _stream_unary_multi_callable(self._channel) + self._stream_stream = _stream_stream_multi_callable(self._channel) + + def testUnaryRequestBlockingUnaryResponse(self): + request = b'\x07\x08' + metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponse'),) + expected_error_details = "metadata was invalid: %s" % metadata + with self.assertRaises(ValueError) as exception_context: + self._unary_unary(request, metadata=metadata) + self.assertIn(expected_error_details, str(exception_context.exception)) + + def testUnaryRequestBlockingUnaryResponseWithCall(self): + request = b'\x07\x08' + metadata = (('InVaLiD', 'UnaryRequestBlockingUnaryResponseWithCall'),) + expected_error_details = "metadata was invalid: %s" % metadata + with self.assertRaises(ValueError) as exception_context: + self._unary_unary.with_call(request, metadata=metadata) + self.assertIn(expected_error_details, str(exception_context.exception)) + + def testUnaryRequestFutureUnaryResponse(self): + request = b'\x07\x08' + metadata = (('InVaLiD', 'UnaryRequestFutureUnaryResponse'),) + expected_error_details = "metadata was invalid: %s" % metadata + response_future = self._unary_unary.future(request, metadata=metadata) + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertEqual(exception_context.exception.details(), + expected_error_details) + self.assertEqual(exception_context.exception.code(), + grpc.StatusCode.INTERNAL) + self.assertEqual(response_future.details(), expected_error_details) + self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL) + + def testUnaryRequestStreamResponse(self): + request = b'\x37\x58' + metadata = (('InVaLiD', 'UnaryRequestStreamResponse'),) + expected_error_details = "metadata was invalid: %s" % metadata + response_iterator = self._unary_stream(request, metadata=metadata) + with self.assertRaises(grpc.RpcError) as exception_context: + next(response_iterator) + self.assertEqual(exception_context.exception.details(), + expected_error_details) + self.assertEqual(exception_context.exception.code(), + grpc.StatusCode.INTERNAL) + self.assertEqual(response_iterator.details(), expected_error_details) + self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL) + + def testStreamRequestBlockingUnaryResponse(self): + request_iterator = (b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + metadata = (('InVaLiD', 'StreamRequestBlockingUnaryResponse'),) + expected_error_details = "metadata was invalid: %s" % metadata + with self.assertRaises(ValueError) as exception_context: + self._stream_unary(request_iterator, metadata=metadata) + self.assertIn(expected_error_details, str(exception_context.exception)) + + def testStreamRequestBlockingUnaryResponseWithCall(self): + request_iterator = (b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + metadata = (('InVaLiD', 'StreamRequestBlockingUnaryResponseWithCall'),) + expected_error_details = "metadata was invalid: %s" % metadata + multi_callable = _stream_unary_multi_callable(self._channel) + with self.assertRaises(ValueError) as exception_context: + multi_callable.with_call(request_iterator, metadata=metadata) + self.assertIn(expected_error_details, str(exception_context.exception)) + + def testStreamRequestFutureUnaryResponse(self): + request_iterator = (b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + metadata = (('InVaLiD', 'StreamRequestFutureUnaryResponse'),) + expected_error_details = "metadata was invalid: %s" % metadata + response_future = self._stream_unary.future( + request_iterator, metadata=metadata) + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertEqual(exception_context.exception.details(), + expected_error_details) + self.assertEqual(exception_context.exception.code(), + grpc.StatusCode.INTERNAL) + self.assertEqual(response_future.details(), expected_error_details) + self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL) + + def testStreamRequestStreamResponse(self): + request_iterator = (b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + metadata = (('InVaLiD', 'StreamRequestStreamResponse'),) + expected_error_details = "metadata was invalid: %s" % metadata + response_iterator = self._stream_stream( + request_iterator, metadata=metadata) + with self.assertRaises(grpc.RpcError) as exception_context: + next(response_iterator) + self.assertEqual(exception_context.exception.details(), + expected_error_details) + self.assertEqual(exception_context.exception.code(), + grpc.StatusCode.INTERNAL) + self.assertEqual(response_iterator.details(), expected_error_details) + self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py index 4312679bb96..efeb237874f 100644 --- a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py +++ b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py @@ -50,106 +50,117 @@ _STREAM_STREAM = '/test/StreamStream' class _Callback(object): - def __init__(self): - self._condition = threading.Condition() - self._value = None - self._called = False - def __call__(self, value): - with self._condition: - self._value = value - self._called = True - self._condition.notify_all() + def __init__(self): + self._condition = threading.Condition() + self._value = None + self._called = False - def value(self): - with self._condition: - while not self._called: - self._condition.wait() - return self._value + def __call__(self, value): + with self._condition: + self._value = value + self._called = True + self._condition.notify_all() + + def value(self): + with self._condition: + while not self._called: + self._condition.wait() + return self._value class _Handler(object): - def __init__(self, control): - self._control = control - - def handle_unary_unary(self, request, servicer_context): - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - return request - - def handle_unary_stream(self, request, servicer_context): - for _ in range(test_constants.STREAM_LENGTH): - self._control.control() - yield request - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - - def handle_stream_unary(self, request_iterator, servicer_context): - if servicer_context is not None: - servicer_context.invocation_metadata() - self._control.control() - response_elements = [] - for request in request_iterator: - self._control.control() - response_elements.append(request) - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - return b''.join(response_elements) - - def handle_stream_stream(self, request_iterator, servicer_context): - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - for request in request_iterator: - self._control.control() - yield request - self._control.control() + + def __init__(self, control): + self._control = control + + def handle_unary_unary(self, request, servicer_context): + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + return request + + def handle_unary_stream(self, request, servicer_context): + for _ in range(test_constants.STREAM_LENGTH): + self._control.control() + yield request + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + + def handle_stream_unary(self, request_iterator, servicer_context): + if servicer_context is not None: + servicer_context.invocation_metadata() + self._control.control() + response_elements = [] + for request in request_iterator: + self._control.control() + response_elements.append(request) + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + return b''.join(response_elements) + + def handle_stream_stream(self, request_iterator, servicer_context): + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + for request in request_iterator: + self._control.control() + yield request + self._control.control() class _MethodHandler(grpc.RpcMethodHandler): - def __init__( - self, request_streaming, response_streaming, request_deserializer, - response_serializer, unary_unary, unary_stream, stream_unary, - stream_stream): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = request_deserializer - self.response_serializer = response_serializer - self.unary_unary = unary_unary - self.unary_stream = unary_stream - self.stream_unary = stream_unary - self.stream_stream = stream_stream + + def __init__(self, request_streaming, response_streaming, + request_deserializer, response_serializer, unary_unary, + unary_stream, stream_unary, stream_stream): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = request_deserializer + self.response_serializer = response_serializer + self.unary_unary = unary_unary + self.unary_stream = unary_stream + self.stream_unary = stream_unary + self.stream_stream = stream_stream class _GenericHandler(grpc.GenericRpcHandler): - def __init__(self, handler): - self._handler = handler - - def service(self, handler_call_details): - if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler( - False, False, None, None, self._handler.handle_unary_unary, None, - None, None) - elif handler_call_details.method == _UNARY_STREAM: - return _MethodHandler( - False, True, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, - self._handler.handle_unary_stream, None, None) - elif handler_call_details.method == _STREAM_UNARY: - return _MethodHandler( - True, False, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, None, - self._handler.handle_stream_unary, None) - elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler( - True, True, None, None, None, None, None, - self._handler.handle_stream_stream) - else: - return None + + def __init__(self, handler): + self._handler = handler + + def service(self, handler_call_details): + if handler_call_details.method == _UNARY_UNARY: + return _MethodHandler(False, False, None, None, + self._handler.handle_unary_unary, None, None, + None) + elif handler_call_details.method == _UNARY_STREAM: + return _MethodHandler(False, True, _DESERIALIZE_REQUEST, + _SERIALIZE_RESPONSE, None, + self._handler.handle_unary_stream, None, None) + elif handler_call_details.method == _STREAM_UNARY: + return _MethodHandler(True, False, _DESERIALIZE_REQUEST, + _SERIALIZE_RESPONSE, None, None, + self._handler.handle_stream_unary, None) + elif handler_call_details.method == _STREAM_STREAM: + return _MethodHandler(True, True, None, None, None, None, None, + self._handler.handle_stream_stream) + else: + return None class FailAfterFewIterationsCounter(object): + def __init__(self, high, bytestring): self._current = 0 self._high = high @@ -167,81 +178,82 @@ class FailAfterFewIterationsCounter(object): def _unary_unary_multi_callable(channel): - return channel.unary_unary(_UNARY_UNARY) + return channel.unary_unary(_UNARY_UNARY) def _unary_stream_multi_callable(channel): - return channel.unary_stream( - _UNARY_STREAM, - request_serializer=_SERIALIZE_REQUEST, - response_deserializer=_DESERIALIZE_RESPONSE) + return channel.unary_stream( + _UNARY_STREAM, + request_serializer=_SERIALIZE_REQUEST, + response_deserializer=_DESERIALIZE_RESPONSE) def _stream_unary_multi_callable(channel): - return channel.stream_unary( - _STREAM_UNARY, - request_serializer=_SERIALIZE_REQUEST, - response_deserializer=_DESERIALIZE_RESPONSE) + return channel.stream_unary( + _STREAM_UNARY, + request_serializer=_SERIALIZE_REQUEST, + response_deserializer=_DESERIALIZE_RESPONSE) def _stream_stream_multi_callable(channel): - return channel.stream_stream(_STREAM_STREAM) + return channel.stream_stream(_STREAM_STREAM) class InvocationDefectsTest(unittest.TestCase): - def setUp(self): - self._control = test_control.PauseFailControl() - self._handler = _Handler(self._control) - self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - - self._server = grpc.server(self._server_pool) - port = self._server.add_insecure_port('[::]:0') - self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) - self._server.start() - - self._channel = grpc.insecure_channel('localhost:%d' % port) - - def tearDown(self): - self._server.stop(0) - - def testIterableStreamRequestBlockingUnaryResponse(self): - requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] - multi_callable = _stream_unary_multi_callable(self._channel) - - with self.assertRaises(grpc.RpcError): - response = multi_callable( - requests, - metadata=(('test', 'IterableStreamRequestBlockingUnaryResponse'),)) - - def testIterableStreamRequestFutureUnaryResponse(self): - requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] - multi_callable = _stream_unary_multi_callable(self._channel) - response_future = multi_callable.future( - requests, - metadata=( - ('test', 'IterableStreamRequestFutureUnaryResponse'),)) - - with self.assertRaises(grpc.RpcError): - response = response_future.result() - - def testIterableStreamRequestStreamResponse(self): - requests = [b'\x77\x58' for _ in range(test_constants.STREAM_LENGTH)] - multi_callable = _stream_stream_multi_callable(self._channel) - response_iterator = multi_callable( - requests, - metadata=(('test', 'IterableStreamRequestStreamResponse'),)) - - with self.assertRaises(grpc.RpcError): - next(response_iterator) - - def testIteratorStreamRequestStreamResponse(self): - requests_iterator = FailAfterFewIterationsCounter( - test_constants.STREAM_LENGTH // 2, b'\x07\x08') - multi_callable = _stream_stream_multi_callable(self._channel) - response_iterator = multi_callable( - requests_iterator, - metadata=(('test', 'IteratorStreamRequestStreamResponse'),)) - - with self.assertRaises(grpc.RpcError): - for _ in range(test_constants.STREAM_LENGTH // 2 + 1): - next(response_iterator) + + def setUp(self): + self._control = test_control.PauseFailControl() + self._handler = _Handler(self._control) + self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + + self._server = grpc.server(self._server_pool) + port = self._server.add_insecure_port('[::]:0') + self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) + self._server.start() + + self._channel = grpc.insecure_channel('localhost:%d' % port) + + def tearDown(self): + self._server.stop(0) + + def testIterableStreamRequestBlockingUnaryResponse(self): + requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] + multi_callable = _stream_unary_multi_callable(self._channel) + + with self.assertRaises(grpc.RpcError): + response = multi_callable( + requests, + metadata=( + ('test', 'IterableStreamRequestBlockingUnaryResponse'),)) + + def testIterableStreamRequestFutureUnaryResponse(self): + requests = [b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)] + multi_callable = _stream_unary_multi_callable(self._channel) + response_future = multi_callable.future( + requests, + metadata=(('test', 'IterableStreamRequestFutureUnaryResponse'),)) + + with self.assertRaises(grpc.RpcError): + response = response_future.result() + + def testIterableStreamRequestStreamResponse(self): + requests = [b'\x77\x58' for _ in range(test_constants.STREAM_LENGTH)] + multi_callable = _stream_stream_multi_callable(self._channel) + response_iterator = multi_callable( + requests, + metadata=(('test', 'IterableStreamRequestStreamResponse'),)) + + with self.assertRaises(grpc.RpcError): + next(response_iterator) + + def testIteratorStreamRequestStreamResponse(self): + requests_iterator = FailAfterFewIterationsCounter( + test_constants.STREAM_LENGTH // 2, b'\x07\x08') + multi_callable = _stream_stream_multi_callable(self._channel) + response_iterator = multi_callable( + requests_iterator, + metadata=(('test', 'IteratorStreamRequestStreamResponse'),)) + + with self.assertRaises(grpc.RpcError): + for _ in range(test_constants.STREAM_LENGTH // 2 + 1): + next(response_iterator) diff --git a/src/python/grpcio_tests/tests/unit/_junkdrawer/__init__.py b/src/python/grpcio_tests/tests/unit/_junkdrawer/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/_junkdrawer/__init__.py +++ b/src/python/grpcio_tests/tests/unit/_junkdrawer/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/_junkdrawer/stock_pb2.py b/src/python/grpcio_tests/tests/unit/_junkdrawer/stock_pb2.py index eef18f82d65..70f437bc83c 100644 --- a/src/python/grpcio_tests/tests/unit/_junkdrawer/stock_pb2.py +++ b/src/python/grpcio_tests/tests/unit/_junkdrawer/stock_pb2.py @@ -35,7 +35,7 @@ # source: stock.proto import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode('latin1')) from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -45,108 +45,135 @@ from google.protobuf import descriptor_pb2 _sym_db = _symbol_database.Default() - - - DESCRIPTOR = _descriptor.FileDescriptor( - name='stock.proto', - package='stock', - serialized_pb=_b('\n\x0bstock.proto\x12\x05stock\">\n\x0cStockRequest\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x1e\n\x13num_trades_to_watch\x18\x02 \x01(\x05:\x01\x30\"+\n\nStockReply\x12\r\n\x05price\x18\x01 \x01(\x02\x12\x0e\n\x06symbol\x18\x02 \x01(\t2\x96\x02\n\x05Stock\x12=\n\x11GetLastTradePrice\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00\x12I\n\x19GetLastTradePriceMultiple\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00(\x01\x30\x01\x12?\n\x11WatchFutureTrades\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00\x30\x01\x12\x42\n\x14GetHighestTradePrice\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00(\x01') -) + name='stock.proto', + package='stock', + serialized_pb=_b( + '\n\x0bstock.proto\x12\x05stock\">\n\x0cStockRequest\x12\x0e\n\x06symbol\x18\x01 \x01(\t\x12\x1e\n\x13num_trades_to_watch\x18\x02 \x01(\x05:\x01\x30\"+\n\nStockReply\x12\r\n\x05price\x18\x01 \x01(\x02\x12\x0e\n\x06symbol\x18\x02 \x01(\t2\x96\x02\n\x05Stock\x12=\n\x11GetLastTradePrice\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00\x12I\n\x19GetLastTradePriceMultiple\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00(\x01\x30\x01\x12?\n\x11WatchFutureTrades\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00\x30\x01\x12\x42\n\x14GetHighestTradePrice\x12\x13.stock.StockRequest\x1a\x11.stock.StockReply\"\x00(\x01' + )) _sym_db.RegisterFileDescriptor(DESCRIPTOR) - - - _STOCKREQUEST = _descriptor.Descriptor( - name='StockRequest', - full_name='stock.StockRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='symbol', full_name='stock.StockRequest.symbol', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - _descriptor.FieldDescriptor( - name='num_trades_to_watch', full_name='stock.StockRequest.num_trades_to_watch', index=1, - number=2, type=5, cpp_type=1, label=1, - has_default_value=True, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=22, - serialized_end=84, -) - + name='StockRequest', + full_name='stock.StockRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='symbol', + full_name='stock.StockRequest.symbol', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='num_trades_to_watch', + full_name='stock.StockRequest.num_trades_to_watch', + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=True, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[], + serialized_start=22, + serialized_end=84,) _STOCKREPLY = _descriptor.Descriptor( - name='StockReply', - full_name='stock.StockReply', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='price', full_name='stock.StockReply.price', index=0, - number=1, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - _descriptor.FieldDescriptor( - name='symbol', full_name='stock.StockReply.symbol', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - oneofs=[ - ], - serialized_start=86, - serialized_end=129, -) + name='StockReply', + full_name='stock.StockReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='price', + full_name='stock.StockReply.price', + index=0, + number=1, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='symbol', + full_name='stock.StockReply.symbol', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + options=None), + ], + extensions=[], + nested_types=[], + enum_types=[], + options=None, + is_extendable=False, + extension_ranges=[], + oneofs=[], + serialized_start=86, + serialized_end=129,) DESCRIPTOR.message_types_by_name['StockRequest'] = _STOCKREQUEST DESCRIPTOR.message_types_by_name['StockReply'] = _STOCKREPLY -StockRequest = _reflection.GeneratedProtocolMessageType('StockRequest', (_message.Message,), dict( - DESCRIPTOR = _STOCKREQUEST, - __module__ = 'stock_pb2' - # @@protoc_insertion_point(class_scope:stock.StockRequest) - )) +StockRequest = _reflection.GeneratedProtocolMessageType( + 'StockRequest', + (_message.Message,), + dict( + DESCRIPTOR=_STOCKREQUEST, + __module__='stock_pb2' + # @@protoc_insertion_point(class_scope:stock.StockRequest) + )) _sym_db.RegisterMessage(StockRequest) -StockReply = _reflection.GeneratedProtocolMessageType('StockReply', (_message.Message,), dict( - DESCRIPTOR = _STOCKREPLY, - __module__ = 'stock_pb2' - # @@protoc_insertion_point(class_scope:stock.StockReply) - )) +StockReply = _reflection.GeneratedProtocolMessageType( + 'StockReply', + (_message.Message,), + dict( + DESCRIPTOR=_STOCKREPLY, + __module__='stock_pb2' + # @@protoc_insertion_point(class_scope:stock.StockReply) + )) _sym_db.RegisterMessage(StockReply) - # @@protoc_insertion_point(module_scope) diff --git a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py index fb3e5477815..af2ce64dcea 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py @@ -26,7 +26,6 @@ # 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. - """Tests application-provided metadata, status code, and details.""" import threading @@ -53,20 +52,16 @@ _UNARY_STREAM = 'UnaryStream' _STREAM_UNARY = 'StreamUnary' _STREAM_STREAM = 'StreamStream' -_CLIENT_METADATA = ( - ('client-md-key', 'client-md-key'), - ('client-md-key-bin', b'\x00\x01') -) +_CLIENT_METADATA = (('client-md-key', 'client-md-key'), + ('client-md-key-bin', b'\x00\x01')) _SERVER_INITIAL_METADATA = ( ('server-initial-md-key', 'server-initial-md-value'), - ('server-initial-md-key-bin', b'\x00\x02') -) + ('server-initial-md-key-bin', b'\x00\x02')) _SERVER_TRAILING_METADATA = ( ('server-trailing-md-key', 'server-trailing-md-value'), - ('server-trailing-md-key-bin', b'\x00\x03') -) + ('server-trailing-md-key-bin', b'\x00\x03')) _NON_OK_CODE = grpc.StatusCode.NOT_FOUND _DETAILS = 'Test details!' @@ -74,450 +69,464 @@ _DETAILS = 'Test details!' class _Servicer(object): - def __init__(self): - self._lock = threading.Lock() - self._code = None - self._details = None - self._exception = False - self._return_none = False - self._received_client_metadata = None - - def unary_unary(self, request, context): - with self._lock: - self._received_client_metadata = context.invocation_metadata() - context.send_initial_metadata(_SERVER_INITIAL_METADATA) - context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - if self._code is not None: - context.set_code(self._code) - if self._details is not None: - context.set_details(self._details) - if self._exception: - raise test_control.Defect() - else: - return None if self._return_none else object() - - def unary_stream(self, request, context): - with self._lock: - self._received_client_metadata = context.invocation_metadata() - context.send_initial_metadata(_SERVER_INITIAL_METADATA) - context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - if self._code is not None: - context.set_code(self._code) - if self._details is not None: - context.set_details(self._details) - for _ in range(test_constants.STREAM_LENGTH // 2): - yield _SERIALIZED_RESPONSE - if self._exception: - raise test_control.Defect() - - def stream_unary(self, request_iterator, context): - with self._lock: - self._received_client_metadata = context.invocation_metadata() - context.send_initial_metadata(_SERVER_INITIAL_METADATA) - context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - if self._code is not None: - context.set_code(self._code) - if self._details is not None: - context.set_details(self._details) - # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the - # request iterator. - for ignored_request in request_iterator: - pass - if self._exception: - raise test_control.Defect() - else: - return None if self._return_none else _SERIALIZED_RESPONSE - - def stream_stream(self, request_iterator, context): - with self._lock: - self._received_client_metadata = context.invocation_metadata() - context.send_initial_metadata(_SERVER_INITIAL_METADATA) - context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - if self._code is not None: - context.set_code(self._code) - if self._details is not None: - context.set_details(self._details) - # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the - # request iterator. - for ignored_request in request_iterator: - pass - for _ in range(test_constants.STREAM_LENGTH // 3): - yield object() - if self._exception: - raise test_control.Defect() - - def set_code(self, code): - with self._lock: - self._code = code - - def set_details(self, details): - with self._lock: - self._details = details - - def set_exception(self): - with self._lock: - self._exception = True - - def set_return_none(self): - with self._lock: - self._return_none = True - - def received_client_metadata(self): - with self._lock: - return self._received_client_metadata + def __init__(self): + self._lock = threading.Lock() + self._code = None + self._details = None + self._exception = False + self._return_none = False + self._received_client_metadata = None + + def unary_unary(self, request, context): + with self._lock: + self._received_client_metadata = context.invocation_metadata() + context.send_initial_metadata(_SERVER_INITIAL_METADATA) + context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + if self._code is not None: + context.set_code(self._code) + if self._details is not None: + context.set_details(self._details) + if self._exception: + raise test_control.Defect() + else: + return None if self._return_none else object() + + def unary_stream(self, request, context): + with self._lock: + self._received_client_metadata = context.invocation_metadata() + context.send_initial_metadata(_SERVER_INITIAL_METADATA) + context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + if self._code is not None: + context.set_code(self._code) + if self._details is not None: + context.set_details(self._details) + for _ in range(test_constants.STREAM_LENGTH // 2): + yield _SERIALIZED_RESPONSE + if self._exception: + raise test_control.Defect() + + def stream_unary(self, request_iterator, context): + with self._lock: + self._received_client_metadata = context.invocation_metadata() + context.send_initial_metadata(_SERVER_INITIAL_METADATA) + context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + if self._code is not None: + context.set_code(self._code) + if self._details is not None: + context.set_details(self._details) + # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the + # request iterator. + for ignored_request in request_iterator: + pass + if self._exception: + raise test_control.Defect() + else: + return None if self._return_none else _SERIALIZED_RESPONSE + + def stream_stream(self, request_iterator, context): + with self._lock: + self._received_client_metadata = context.invocation_metadata() + context.send_initial_metadata(_SERVER_INITIAL_METADATA) + context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + if self._code is not None: + context.set_code(self._code) + if self._details is not None: + context.set_details(self._details) + # TODO(https://github.com/grpc/grpc/issues/6891): just ignore the + # request iterator. + for ignored_request in request_iterator: + pass + for _ in range(test_constants.STREAM_LENGTH // 3): + yield object() + if self._exception: + raise test_control.Defect() + + def set_code(self, code): + with self._lock: + self._code = code + + def set_details(self, details): + with self._lock: + self._details = details + + def set_exception(self): + with self._lock: + self._exception = True + + def set_return_none(self): + with self._lock: + self._return_none = True + + def received_client_metadata(self): + with self._lock: + return self._received_client_metadata def _generic_handler(servicer): - method_handlers = { - _UNARY_UNARY: grpc.unary_unary_rpc_method_handler( - servicer.unary_unary, request_deserializer=_REQUEST_DESERIALIZER, - response_serializer=_RESPONSE_SERIALIZER), - _UNARY_STREAM: grpc.unary_stream_rpc_method_handler( - servicer.unary_stream), - _STREAM_UNARY: grpc.stream_unary_rpc_method_handler( - servicer.stream_unary), - _STREAM_STREAM: grpc.stream_stream_rpc_method_handler( - servicer.stream_stream, request_deserializer=_REQUEST_DESERIALIZER, - response_serializer=_RESPONSE_SERIALIZER), - } - return grpc.method_handlers_generic_handler(_SERVICE, method_handlers) + method_handlers = { + _UNARY_UNARY: grpc.unary_unary_rpc_method_handler( + servicer.unary_unary, + request_deserializer=_REQUEST_DESERIALIZER, + response_serializer=_RESPONSE_SERIALIZER), + _UNARY_STREAM: + grpc.unary_stream_rpc_method_handler(servicer.unary_stream), + _STREAM_UNARY: + grpc.stream_unary_rpc_method_handler(servicer.stream_unary), + _STREAM_STREAM: grpc.stream_stream_rpc_method_handler( + servicer.stream_stream, + request_deserializer=_REQUEST_DESERIALIZER, + response_serializer=_RESPONSE_SERIALIZER), + } + return grpc.method_handlers_generic_handler(_SERVICE, method_handlers) class MetadataCodeDetailsTest(unittest.TestCase): - def setUp(self): - self._servicer = _Servicer() - self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server( - self._server_pool, handlers=(_generic_handler(self._servicer),)) - port = self._server.add_insecure_port('[::]:0') - self._server.start() - - channel = grpc.insecure_channel('localhost:{}'.format(port)) - self._unary_unary = channel.unary_unary( - '/'.join(('', _SERVICE, _UNARY_UNARY,)), - request_serializer=_REQUEST_SERIALIZER, - response_deserializer=_RESPONSE_DESERIALIZER,) - self._unary_stream = channel.unary_stream( - '/'.join(('', _SERVICE, _UNARY_STREAM,)),) - self._stream_unary = channel.stream_unary( - '/'.join(('', _SERVICE, _STREAM_UNARY,)),) - self._stream_stream = channel.stream_stream( - '/'.join(('', _SERVICE, _STREAM_STREAM,)), - request_serializer=_REQUEST_SERIALIZER, - response_deserializer=_RESPONSE_DESERIALIZER,) - - - def testSuccessfulUnaryUnary(self): - self._servicer.set_details(_DETAILS) - - unused_response, call = self._unary_unary.with_call( - object(), metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, call.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(grpc.StatusCode.OK, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testSuccessfulUnaryStream(self): - self._servicer.set_details(_DETAILS) - - call = self._unary_stream(_SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) - received_initial_metadata = call.initial_metadata() - for _ in call: - pass - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, received_initial_metadata)) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(grpc.StatusCode.OK, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testSuccessfulStreamUnary(self): - self._servicer.set_details(_DETAILS) - - unused_response, call = self._stream_unary.with_call( - iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, call.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(grpc.StatusCode.OK, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testSuccessfulStreamStream(self): - self._servicer.set_details(_DETAILS) - - call = self._stream_stream( - iter([object()] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - received_initial_metadata = call.initial_metadata() - for _ in call: - pass - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, received_initial_metadata)) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(grpc.StatusCode.OK, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testCustomCodeUnaryUnary(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - - with self.assertRaises(grpc.RpcError) as exception_context: - self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, - exception_context.exception.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) - - def testCustomCodeUnaryStream(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - - call = self._unary_stream(_SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) - received_initial_metadata = call.initial_metadata() - with self.assertRaises(grpc.RpcError): - for _ in call: - pass - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, received_initial_metadata)) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(_NON_OK_CODE, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testCustomCodeStreamUnary(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - - with self.assertRaises(grpc.RpcError) as exception_context: - self._stream_unary.with_call( - iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, - exception_context.exception.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) - - def testCustomCodeStreamStream(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - - call = self._stream_stream( - iter([object()] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - received_initial_metadata = call.initial_metadata() - with self.assertRaises(grpc.RpcError) as exception_context: - for _ in call: - pass - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, received_initial_metadata)) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) - - def testCustomCodeExceptionUnaryUnary(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - self._servicer.set_exception() - - with self.assertRaises(grpc.RpcError) as exception_context: - self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, - exception_context.exception.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) - - def testCustomCodeExceptionUnaryStream(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - self._servicer.set_exception() - - call = self._unary_stream(_SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) - received_initial_metadata = call.initial_metadata() - with self.assertRaises(grpc.RpcError): - for _ in call: - pass - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, received_initial_metadata)) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(_NON_OK_CODE, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testCustomCodeExceptionStreamUnary(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - self._servicer.set_exception() - - with self.assertRaises(grpc.RpcError) as exception_context: - self._stream_unary.with_call( - iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, - exception_context.exception.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) - - def testCustomCodeExceptionStreamStream(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - self._servicer.set_exception() - - call = self._stream_stream( - iter([object()] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - received_initial_metadata = call.initial_metadata() - with self.assertRaises(grpc.RpcError): - for _ in call: - pass - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, received_initial_metadata)) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - self.assertIs(_NON_OK_CODE, call.code()) - self.assertEqual(_DETAILS, call.details()) - - def testCustomCodeReturnNoneUnaryUnary(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - self._servicer.set_return_none() - - with self.assertRaises(grpc.RpcError) as exception_context: - self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, - exception_context.exception.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) - - def testCustomCodeReturnNoneStreamUnary(self): - self._servicer.set_code(_NON_OK_CODE) - self._servicer.set_details(_DETAILS) - self._servicer.set_return_none() - - with self.assertRaises(grpc.RpcError) as exception_context: - self._stream_unary.with_call( - iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - - self.assertTrue( - test_common.metadata_transmitted( - _CLIENT_METADATA, self._servicer.received_client_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, - exception_context.exception.initial_metadata())) - self.assertTrue( - test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, - exception_context.exception.trailing_metadata())) - self.assertIs(_NON_OK_CODE, exception_context.exception.code()) - self.assertEqual(_DETAILS, exception_context.exception.details()) + def setUp(self): + self._servicer = _Servicer() + self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server( + self._server_pool, handlers=(_generic_handler(self._servicer),)) + port = self._server.add_insecure_port('[::]:0') + self._server.start() + + channel = grpc.insecure_channel('localhost:{}'.format(port)) + self._unary_unary = channel.unary_unary( + '/'.join(( + '', + _SERVICE, + _UNARY_UNARY,)), + request_serializer=_REQUEST_SERIALIZER, + response_deserializer=_RESPONSE_DESERIALIZER,) + self._unary_stream = channel.unary_stream('/'.join(( + '', + _SERVICE, + _UNARY_STREAM,)),) + self._stream_unary = channel.stream_unary('/'.join(( + '', + _SERVICE, + _STREAM_UNARY,)),) + self._stream_stream = channel.stream_stream( + '/'.join(( + '', + _SERVICE, + _STREAM_STREAM,)), + request_serializer=_REQUEST_SERIALIZER, + response_deserializer=_RESPONSE_DESERIALIZER,) + + def testSuccessfulUnaryUnary(self): + self._servicer.set_details(_DETAILS) + + unused_response, call = self._unary_unary.with_call( + object(), metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + call.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(grpc.StatusCode.OK, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testSuccessfulUnaryStream(self): + self._servicer.set_details(_DETAILS) + + call = self._unary_stream( + _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) + received_initial_metadata = call.initial_metadata() + for _ in call: + pass + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + received_initial_metadata)) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(grpc.StatusCode.OK, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testSuccessfulStreamUnary(self): + self._servicer.set_details(_DETAILS) + + unused_response, call = self._stream_unary.with_call( + iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + call.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(grpc.StatusCode.OK, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testSuccessfulStreamStream(self): + self._servicer.set_details(_DETAILS) + + call = self._stream_stream( + iter([object()] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + received_initial_metadata = call.initial_metadata() + for _ in call: + pass + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + received_initial_metadata)) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(grpc.StatusCode.OK, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testCustomCodeUnaryUnary(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + + with self.assertRaises(grpc.RpcError) as exception_context: + self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_INITIAL_METADATA, + exception_context.exception.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) + + def testCustomCodeUnaryStream(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + + call = self._unary_stream( + _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) + received_initial_metadata = call.initial_metadata() + with self.assertRaises(grpc.RpcError): + for _ in call: + pass + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + received_initial_metadata)) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(_NON_OK_CODE, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testCustomCodeStreamUnary(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + + with self.assertRaises(grpc.RpcError) as exception_context: + self._stream_unary.with_call( + iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_INITIAL_METADATA, + exception_context.exception.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) + + def testCustomCodeStreamStream(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + + call = self._stream_stream( + iter([object()] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + received_initial_metadata = call.initial_metadata() + with self.assertRaises(grpc.RpcError) as exception_context: + for _ in call: + pass + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + received_initial_metadata)) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) + + def testCustomCodeExceptionUnaryUnary(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + self._servicer.set_exception() + + with self.assertRaises(grpc.RpcError) as exception_context: + self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_INITIAL_METADATA, + exception_context.exception.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) + + def testCustomCodeExceptionUnaryStream(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + self._servicer.set_exception() + + call = self._unary_stream( + _SERIALIZED_REQUEST, metadata=_CLIENT_METADATA) + received_initial_metadata = call.initial_metadata() + with self.assertRaises(grpc.RpcError): + for _ in call: + pass + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + received_initial_metadata)) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(_NON_OK_CODE, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testCustomCodeExceptionStreamUnary(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + self._servicer.set_exception() + + with self.assertRaises(grpc.RpcError) as exception_context: + self._stream_unary.with_call( + iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_INITIAL_METADATA, + exception_context.exception.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) + + def testCustomCodeExceptionStreamStream(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + self._servicer.set_exception() + + call = self._stream_stream( + iter([object()] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + received_initial_metadata = call.initial_metadata() + with self.assertRaises(grpc.RpcError): + for _ in call: + pass + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + received_initial_metadata)) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + self.assertIs(_NON_OK_CODE, call.code()) + self.assertEqual(_DETAILS, call.details()) + + def testCustomCodeReturnNoneUnaryUnary(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + self._servicer.set_return_none() + + with self.assertRaises(grpc.RpcError) as exception_context: + self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_INITIAL_METADATA, + exception_context.exception.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) + + def testCustomCodeReturnNoneStreamUnary(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + self._servicer.set_return_none() + + with self.assertRaises(grpc.RpcError) as exception_context: + self._stream_unary.with_call( + iter([_SERIALIZED_REQUEST] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + + self.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, self._servicer.received_client_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_INITIAL_METADATA, + exception_context.exception.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted( + _SERVER_TRAILING_METADATA, + exception_context.exception.trailing_metadata())) + self.assertIs(_NON_OK_CODE, exception_context.exception.code()) + self.assertEqual(_DETAILS, exception_context.exception.details()) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_metadata_test.py b/src/python/grpcio_tests/tests/unit/_metadata_test.py index caba53ffcc9..53fe7ba8aa5 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_test.py @@ -51,166 +51,174 @@ _STREAM_STREAM = '/test/StreamStream' _USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__) -_CLIENT_METADATA = ( - ('client-md-key', 'client-md-key'), - ('client-md-key-bin', b'\x00\x01') -) +_CLIENT_METADATA = (('client-md-key', 'client-md-key'), + ('client-md-key-bin', b'\x00\x01')) _SERVER_INITIAL_METADATA = ( ('server-initial-md-key', 'server-initial-md-value'), - ('server-initial-md-key-bin', b'\x00\x02') -) + ('server-initial-md-key-bin', b'\x00\x02')) _SERVER_TRAILING_METADATA = ( ('server-trailing-md-key', 'server-trailing-md-value'), - ('server-trailing-md-key-bin', b'\x00\x03') -) + ('server-trailing-md-key-bin', b'\x00\x03')) def user_agent(metadata): - for key, val in metadata: - if key == 'user-agent': - return val - raise KeyError('No user agent!') + for key, val in metadata: + if key == 'user-agent': + return val + raise KeyError('No user agent!') def validate_client_metadata(test, servicer_context): - test.assertTrue(test_common.metadata_transmitted( - _CLIENT_METADATA, servicer_context.invocation_metadata())) - test.assertTrue(user_agent(servicer_context.invocation_metadata()) - .startswith('primary-agent ' + _USER_AGENT)) - test.assertTrue(user_agent(servicer_context.invocation_metadata()) - .endswith('secondary-agent')) + test.assertTrue( + test_common.metadata_transmitted( + _CLIENT_METADATA, servicer_context.invocation_metadata())) + test.assertTrue( + user_agent(servicer_context.invocation_metadata()) + .startswith('primary-agent ' + _USER_AGENT)) + test.assertTrue( + user_agent(servicer_context.invocation_metadata()) + .endswith('secondary-agent')) def handle_unary_unary(test, request, servicer_context): - validate_client_metadata(test, servicer_context) - servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) - servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - return _RESPONSE + validate_client_metadata(test, servicer_context) + servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) + servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + return _RESPONSE def handle_unary_stream(test, request, servicer_context): - validate_client_metadata(test, servicer_context) - servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) - servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - for _ in range(test_constants.STREAM_LENGTH): - yield _RESPONSE + validate_client_metadata(test, servicer_context) + servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) + servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + for _ in range(test_constants.STREAM_LENGTH): + yield _RESPONSE def handle_stream_unary(test, request_iterator, servicer_context): - validate_client_metadata(test, servicer_context) - servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) - servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - # TODO(issue:#6891) We should be able to remove this loop - for request in request_iterator: - pass - return _RESPONSE + validate_client_metadata(test, servicer_context) + servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) + servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + # TODO(issue:#6891) We should be able to remove this loop + for request in request_iterator: + pass + return _RESPONSE def handle_stream_stream(test, request_iterator, servicer_context): - validate_client_metadata(test, servicer_context) - servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) - servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) - # TODO(issue:#6891) We should be able to remove this loop, - # and replace with return; yield - for request in request_iterator: - yield _RESPONSE + validate_client_metadata(test, servicer_context) + servicer_context.send_initial_metadata(_SERVER_INITIAL_METADATA) + servicer_context.set_trailing_metadata(_SERVER_TRAILING_METADATA) + # TODO(issue:#6891) We should be able to remove this loop, + # and replace with return; yield + for request in request_iterator: + yield _RESPONSE class _MethodHandler(grpc.RpcMethodHandler): - def __init__(self, test, request_streaming, response_streaming): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = None - self.response_serializer = None - self.unary_unary = None - self.unary_stream = None - self.stream_unary = None - self.stream_stream = None - if self.request_streaming and self.response_streaming: - self.stream_stream = lambda x, y: handle_stream_stream(test, x, y) - elif self.request_streaming: - self.stream_unary = lambda x, y: handle_stream_unary(test, x, y) - elif self.response_streaming: - self.unary_stream = lambda x, y: handle_unary_stream(test, x, y) - else: - self.unary_unary = lambda x, y: handle_unary_unary(test, x, y) + def __init__(self, test, request_streaming, response_streaming): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = None + self.response_serializer = None + self.unary_unary = None + self.unary_stream = None + self.stream_unary = None + self.stream_stream = None + if self.request_streaming and self.response_streaming: + self.stream_stream = lambda x, y: handle_stream_stream(test, x, y) + elif self.request_streaming: + self.stream_unary = lambda x, y: handle_stream_unary(test, x, y) + elif self.response_streaming: + self.unary_stream = lambda x, y: handle_unary_stream(test, x, y) + else: + self.unary_unary = lambda x, y: handle_unary_unary(test, x, y) class _GenericHandler(grpc.GenericRpcHandler): - def __init__(self, test): - self._test = test + def __init__(self, test): + self._test = test - def service(self, handler_call_details): - if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler(self._test, False, False) - elif handler_call_details.method == _UNARY_STREAM: - return _MethodHandler(self._test, False, True) - elif handler_call_details.method == _STREAM_UNARY: - return _MethodHandler(self._test, True, False) - elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler(self._test, True, True) - else: - return None + def service(self, handler_call_details): + if handler_call_details.method == _UNARY_UNARY: + return _MethodHandler(self._test, False, False) + elif handler_call_details.method == _UNARY_STREAM: + return _MethodHandler(self._test, False, True) + elif handler_call_details.method == _STREAM_UNARY: + return _MethodHandler(self._test, True, False) + elif handler_call_details.method == _STREAM_STREAM: + return _MethodHandler(self._test, True, True) + else: + return None class MetadataTest(unittest.TestCase): - def setUp(self): - self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server( - self._server_pool, handlers=(_GenericHandler(weakref.proxy(self)),)) - port = self._server.add_insecure_port('[::]:0') - self._server.start() - self._channel = grpc.insecure_channel('localhost:%d' % port, - options=_CHANNEL_ARGS) - - def tearDown(self): - self._server.stop(0) - - def testUnaryUnary(self): - multi_callable = self._channel.unary_unary(_UNARY_UNARY) - unused_response, call = multi_callable.with_call( - _REQUEST, metadata=_CLIENT_METADATA) - self.assertTrue(test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, call.initial_metadata())) - self.assertTrue(test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - - def testUnaryStream(self): - multi_callable = self._channel.unary_stream(_UNARY_STREAM) - call = multi_callable(_REQUEST, metadata=_CLIENT_METADATA) - self.assertTrue(test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, call.initial_metadata())) - for _ in call: - pass - self.assertTrue(test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - - def testStreamUnary(self): - multi_callable = self._channel.stream_unary(_STREAM_UNARY) - unused_response, call = multi_callable.with_call( - iter([_REQUEST] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - self.assertTrue(test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, call.initial_metadata())) - self.assertTrue(test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) - - def testStreamStream(self): - multi_callable = self._channel.stream_stream(_STREAM_STREAM) - call = multi_callable(iter([_REQUEST] * test_constants.STREAM_LENGTH), - metadata=_CLIENT_METADATA) - self.assertTrue(test_common.metadata_transmitted( - _SERVER_INITIAL_METADATA, call.initial_metadata())) - for _ in call: - pass - self.assertTrue(test_common.metadata_transmitted( - _SERVER_TRAILING_METADATA, call.trailing_metadata())) + def setUp(self): + self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + self._server = grpc.server( + self._server_pool, handlers=(_GenericHandler(weakref.proxy(self)),)) + port = self._server.add_insecure_port('[::]:0') + self._server.start() + self._channel = grpc.insecure_channel( + 'localhost:%d' % port, options=_CHANNEL_ARGS) + + def tearDown(self): + self._server.stop(0) + + def testUnaryUnary(self): + multi_callable = self._channel.unary_unary(_UNARY_UNARY) + unused_response, call = multi_callable.with_call( + _REQUEST, metadata=_CLIENT_METADATA) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + call.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + + def testUnaryStream(self): + multi_callable = self._channel.unary_stream(_UNARY_STREAM) + call = multi_callable(_REQUEST, metadata=_CLIENT_METADATA) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + call.initial_metadata())) + for _ in call: + pass + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + + def testStreamUnary(self): + multi_callable = self._channel.stream_unary(_STREAM_UNARY) + unused_response, call = multi_callable.with_call( + iter([_REQUEST] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + call.initial_metadata())) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) + + def testStreamStream(self): + multi_callable = self._channel.stream_stream(_STREAM_STREAM) + call = multi_callable( + iter([_REQUEST] * test_constants.STREAM_LENGTH), + metadata=_CLIENT_METADATA) + self.assertTrue( + test_common.metadata_transmitted(_SERVER_INITIAL_METADATA, + call.initial_metadata())) + for _ in call: + pass + self.assertTrue( + test_common.metadata_transmitted(_SERVER_TRAILING_METADATA, + call.trailing_metadata())) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_rpc_test.py b/src/python/grpcio_tests/tests/unit/_rpc_test.py index eb00156da51..2cf6dfea620 100644 --- a/src/python/grpcio_tests/tests/unit/_rpc_test.py +++ b/src/python/grpcio_tests/tests/unit/_rpc_test.py @@ -26,7 +26,6 @@ # 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. - """Test of RPCs made against gRPC Python's application-layer API.""" import itertools @@ -53,742 +52,797 @@ _STREAM_STREAM = '/test/StreamStream' class _Callback(object): - def __init__(self): - self._condition = threading.Condition() - self._value = None - self._called = False + def __init__(self): + self._condition = threading.Condition() + self._value = None + self._called = False - def __call__(self, value): - with self._condition: - self._value = value - self._called = True - self._condition.notify_all() + def __call__(self, value): + with self._condition: + self._value = value + self._called = True + self._condition.notify_all() - def value(self): - with self._condition: - while not self._called: - self._condition.wait() - return self._value + def value(self): + with self._condition: + while not self._called: + self._condition.wait() + return self._value class _Handler(object): - def __init__(self, control): - self._control = control - - def handle_unary_unary(self, request, servicer_context): - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - return request - - def handle_unary_stream(self, request, servicer_context): - for _ in range(test_constants.STREAM_LENGTH): - self._control.control() - yield request - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - - def handle_stream_unary(self, request_iterator, servicer_context): - if servicer_context is not None: - servicer_context.invocation_metadata() - self._control.control() - response_elements = [] - for request in request_iterator: - self._control.control() - response_elements.append(request) - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - return b''.join(response_elements) - - def handle_stream_stream(self, request_iterator, servicer_context): - self._control.control() - if servicer_context is not None: - servicer_context.set_trailing_metadata((('testkey', 'testvalue',),)) - for request in request_iterator: - self._control.control() - yield request - self._control.control() + def __init__(self, control): + self._control = control + + def handle_unary_unary(self, request, servicer_context): + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + return request + + def handle_unary_stream(self, request, servicer_context): + for _ in range(test_constants.STREAM_LENGTH): + self._control.control() + yield request + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + + def handle_stream_unary(self, request_iterator, servicer_context): + if servicer_context is not None: + servicer_context.invocation_metadata() + self._control.control() + response_elements = [] + for request in request_iterator: + self._control.control() + response_elements.append(request) + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + return b''.join(response_elements) + + def handle_stream_stream(self, request_iterator, servicer_context): + self._control.control() + if servicer_context is not None: + servicer_context.set_trailing_metadata((( + 'testkey', + 'testvalue',),)) + for request in request_iterator: + self._control.control() + yield request + self._control.control() class _MethodHandler(grpc.RpcMethodHandler): - def __init__( - self, request_streaming, response_streaming, request_deserializer, - response_serializer, unary_unary, unary_stream, stream_unary, - stream_stream): - self.request_streaming = request_streaming - self.response_streaming = response_streaming - self.request_deserializer = request_deserializer - self.response_serializer = response_serializer - self.unary_unary = unary_unary - self.unary_stream = unary_stream - self.stream_unary = stream_unary - self.stream_stream = stream_stream + def __init__(self, request_streaming, response_streaming, + request_deserializer, response_serializer, unary_unary, + unary_stream, stream_unary, stream_stream): + self.request_streaming = request_streaming + self.response_streaming = response_streaming + self.request_deserializer = request_deserializer + self.response_serializer = response_serializer + self.unary_unary = unary_unary + self.unary_stream = unary_stream + self.stream_unary = stream_unary + self.stream_stream = stream_stream class _GenericHandler(grpc.GenericRpcHandler): - def __init__(self, handler): - self._handler = handler - - def service(self, handler_call_details): - if handler_call_details.method == _UNARY_UNARY: - return _MethodHandler( - False, False, None, None, self._handler.handle_unary_unary, None, - None, None) - elif handler_call_details.method == _UNARY_STREAM: - return _MethodHandler( - False, True, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, - self._handler.handle_unary_stream, None, None) - elif handler_call_details.method == _STREAM_UNARY: - return _MethodHandler( - True, False, _DESERIALIZE_REQUEST, _SERIALIZE_RESPONSE, None, None, - self._handler.handle_stream_unary, None) - elif handler_call_details.method == _STREAM_STREAM: - return _MethodHandler( - True, True, None, None, None, None, None, - self._handler.handle_stream_stream) - else: - return None + def __init__(self, handler): + self._handler = handler + + def service(self, handler_call_details): + if handler_call_details.method == _UNARY_UNARY: + return _MethodHandler(False, False, None, None, + self._handler.handle_unary_unary, None, None, + None) + elif handler_call_details.method == _UNARY_STREAM: + return _MethodHandler(False, True, _DESERIALIZE_REQUEST, + _SERIALIZE_RESPONSE, None, + self._handler.handle_unary_stream, None, None) + elif handler_call_details.method == _STREAM_UNARY: + return _MethodHandler(True, False, _DESERIALIZE_REQUEST, + _SERIALIZE_RESPONSE, None, None, + self._handler.handle_stream_unary, None) + elif handler_call_details.method == _STREAM_STREAM: + return _MethodHandler(True, True, None, None, None, None, None, + self._handler.handle_stream_stream) + else: + return None def _unary_unary_multi_callable(channel): - return channel.unary_unary(_UNARY_UNARY) + return channel.unary_unary(_UNARY_UNARY) def _unary_stream_multi_callable(channel): - return channel.unary_stream( - _UNARY_STREAM, - request_serializer=_SERIALIZE_REQUEST, - response_deserializer=_DESERIALIZE_RESPONSE) + return channel.unary_stream( + _UNARY_STREAM, + request_serializer=_SERIALIZE_REQUEST, + response_deserializer=_DESERIALIZE_RESPONSE) def _stream_unary_multi_callable(channel): - return channel.stream_unary( - _STREAM_UNARY, - request_serializer=_SERIALIZE_REQUEST, - response_deserializer=_DESERIALIZE_RESPONSE) + return channel.stream_unary( + _STREAM_UNARY, + request_serializer=_SERIALIZE_REQUEST, + response_deserializer=_DESERIALIZE_RESPONSE) def _stream_stream_multi_callable(channel): - return channel.stream_stream(_STREAM_STREAM) + return channel.stream_stream(_STREAM_STREAM) class RPCTest(unittest.TestCase): - def setUp(self): - self._control = test_control.PauseFailControl() - self._handler = _Handler(self._control) - self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + def setUp(self): + self._control = test_control.PauseFailControl() + self._handler = _Handler(self._control) + self._server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - self._server = grpc.server(self._server_pool) - port = self._server.add_insecure_port('[::]:0') - self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) - self._server.start() + self._server = grpc.server(self._server_pool) + port = self._server.add_insecure_port('[::]:0') + self._server.add_generic_rpc_handlers((_GenericHandler(self._handler),)) + self._server.start() - self._channel = grpc.insecure_channel('localhost:%d' % port) - - def tearDown(self): - self._server.stop(None) - self._server_pool.shutdown(wait=True) - - def testUnrecognizedMethod(self): - request = b'abc' - - with self.assertRaises(grpc.RpcError) as exception_context: - self._channel.unary_unary('NoSuchMethod')(request) - - self.assertEqual( - grpc.StatusCode.UNIMPLEMENTED, exception_context.exception.code()) - - def testSuccessfulUnaryRequestBlockingUnaryResponse(self): - request = b'\x07\x08' - expected_response = self._handler.handle_unary_unary(request, None) - - multi_callable = _unary_unary_multi_callable(self._channel) - response = multi_callable( - request, metadata=( - ('test', 'SuccessfulUnaryRequestBlockingUnaryResponse'),)) - - self.assertEqual(expected_response, response) - - def testSuccessfulUnaryRequestBlockingUnaryResponseWithCall(self): - request = b'\x07\x08' - expected_response = self._handler.handle_unary_unary(request, None) - - multi_callable = _unary_unary_multi_callable(self._channel) - response, call = multi_callable.with_call( - request, metadata=( - ('test', 'SuccessfulUnaryRequestBlockingUnaryResponseWithCall'),)) - - self.assertEqual(expected_response, response) - self.assertIs(grpc.StatusCode.OK, call.code()) - - def testSuccessfulUnaryRequestFutureUnaryResponse(self): - request = b'\x07\x08' - expected_response = self._handler.handle_unary_unary(request, None) - - multi_callable = _unary_unary_multi_callable(self._channel) - response_future = multi_callable.future( - request, metadata=( - ('test', 'SuccessfulUnaryRequestFutureUnaryResponse'),)) - response = response_future.result() - - self.assertIsInstance(response_future, grpc.Future) - self.assertIsInstance(response_future, grpc.Call) - self.assertEqual(expected_response, response) - self.assertIsNone(response_future.exception()) - self.assertIsNone(response_future.traceback()) - - def testSuccessfulUnaryRequestStreamResponse(self): - request = b'\x37\x58' - expected_responses = tuple(self._handler.handle_unary_stream(request, None)) - - multi_callable = _unary_stream_multi_callable(self._channel) - response_iterator = multi_callable( - request, - metadata=(('test', 'SuccessfulUnaryRequestStreamResponse'),)) - responses = tuple(response_iterator) - - self.assertSequenceEqual(expected_responses, responses) - - def testSuccessfulStreamRequestBlockingUnaryResponse(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - expected_response = self._handler.handle_stream_unary(iter(requests), None) - request_iterator = iter(requests) - - multi_callable = _stream_unary_multi_callable(self._channel) - response = multi_callable( - request_iterator, - metadata=(('test', 'SuccessfulStreamRequestBlockingUnaryResponse'),)) - - self.assertEqual(expected_response, response) - - def testSuccessfulStreamRequestBlockingUnaryResponseWithCall(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - expected_response = self._handler.handle_stream_unary(iter(requests), None) - request_iterator = iter(requests) - - multi_callable = _stream_unary_multi_callable(self._channel) - response, call = multi_callable.with_call( - request_iterator, - metadata=( - ('test', 'SuccessfulStreamRequestBlockingUnaryResponseWithCall'), - )) - - self.assertEqual(expected_response, response) - self.assertIs(grpc.StatusCode.OK, call.code()) - - def testSuccessfulStreamRequestFutureUnaryResponse(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - expected_response = self._handler.handle_stream_unary(iter(requests), None) - request_iterator = iter(requests) - - multi_callable = _stream_unary_multi_callable(self._channel) - response_future = multi_callable.future( - request_iterator, - metadata=( - ('test', 'SuccessfulStreamRequestFutureUnaryResponse'),)) - response = response_future.result() - - self.assertEqual(expected_response, response) - self.assertIsNone(response_future.exception()) - self.assertIsNone(response_future.traceback()) - - def testSuccessfulStreamRequestStreamResponse(self): - requests = tuple(b'\x77\x58' for _ in range(test_constants.STREAM_LENGTH)) - expected_responses = tuple( - self._handler.handle_stream_stream(iter(requests), None)) - request_iterator = iter(requests) - - multi_callable = _stream_stream_multi_callable(self._channel) - response_iterator = multi_callable( - request_iterator, - metadata=(('test', 'SuccessfulStreamRequestStreamResponse'),)) - responses = tuple(response_iterator) - - self.assertSequenceEqual(expected_responses, responses) - - def testSequentialInvocations(self): - first_request = b'\x07\x08' - second_request = b'\x0809' - expected_first_response = self._handler.handle_unary_unary( - first_request, None) - expected_second_response = self._handler.handle_unary_unary( - second_request, None) - - multi_callable = _unary_unary_multi_callable(self._channel) - first_response = multi_callable( - first_request, metadata=(('test', 'SequentialInvocations'),)) - second_response = multi_callable( - second_request, metadata=(('test', 'SequentialInvocations'),)) - - self.assertEqual(expected_first_response, first_response) - self.assertEqual(expected_second_response, second_response) - - def testConcurrentBlockingInvocations(self): - pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - expected_response = self._handler.handle_stream_unary(iter(requests), None) - expected_responses = [expected_response] * test_constants.THREAD_CONCURRENCY - response_futures = [None] * test_constants.THREAD_CONCURRENCY - - multi_callable = _stream_unary_multi_callable(self._channel) - for index in range(test_constants.THREAD_CONCURRENCY): - request_iterator = iter(requests) - response_future = pool.submit( - multi_callable, request_iterator, - metadata=(('test', 'ConcurrentBlockingInvocations'),)) - response_futures[index] = response_future - responses = tuple( - response_future.result() for response_future in response_futures) - - pool.shutdown(wait=True) - self.assertSequenceEqual(expected_responses, responses) - - def testConcurrentFutureInvocations(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - expected_response = self._handler.handle_stream_unary(iter(requests), None) - expected_responses = [expected_response] * test_constants.THREAD_CONCURRENCY - response_futures = [None] * test_constants.THREAD_CONCURRENCY - - multi_callable = _stream_unary_multi_callable(self._channel) - for index in range(test_constants.THREAD_CONCURRENCY): - request_iterator = iter(requests) - response_future = multi_callable.future( - request_iterator, - metadata=(('test', 'ConcurrentFutureInvocations'),)) - response_futures[index] = response_future - responses = tuple( - response_future.result() for response_future in response_futures) - - self.assertSequenceEqual(expected_responses, responses) - - def testWaitingForSomeButNotAllConcurrentFutureInvocations(self): - pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - request = b'\x67\x68' - expected_response = self._handler.handle_unary_unary(request, None) - response_futures = [None] * test_constants.THREAD_CONCURRENCY - lock = threading.Lock() - test_is_running_cell = [True] - def wrap_future(future): - def wrap(): - try: - return future.result() - except grpc.RpcError: - with lock: - if test_is_running_cell[0]: - raise - return None - return wrap - - multi_callable = _unary_unary_multi_callable(self._channel) - for index in range(test_constants.THREAD_CONCURRENCY): - inner_response_future = multi_callable.future( - request, - metadata=( - ('test', - 'WaitingForSomeButNotAllConcurrentFutureInvocations'),)) - outer_response_future = pool.submit(wrap_future(inner_response_future)) - response_futures[index] = outer_response_future - - some_completed_response_futures_iterator = itertools.islice( - futures.as_completed(response_futures), - test_constants.THREAD_CONCURRENCY // 2) - for response_future in some_completed_response_futures_iterator: - self.assertEqual(expected_response, response_future.result()) - with lock: - test_is_running_cell[0] = False - - def testConsumingOneStreamResponseUnaryRequest(self): - request = b'\x57\x38' - - multi_callable = _unary_stream_multi_callable(self._channel) - response_iterator = multi_callable( - request, - metadata=( - ('test', 'ConsumingOneStreamResponseUnaryRequest'),)) - next(response_iterator) - - def testConsumingSomeButNotAllStreamResponsesUnaryRequest(self): - request = b'\x57\x38' - - multi_callable = _unary_stream_multi_callable(self._channel) - response_iterator = multi_callable( - request, - metadata=( - ('test', 'ConsumingSomeButNotAllStreamResponsesUnaryRequest'),)) - for _ in range(test_constants.STREAM_LENGTH // 2): - next(response_iterator) - - def testConsumingSomeButNotAllStreamResponsesStreamRequest(self): - requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - - multi_callable = _stream_stream_multi_callable(self._channel) - response_iterator = multi_callable( - request_iterator, - metadata=( - ('test', 'ConsumingSomeButNotAllStreamResponsesStreamRequest'),)) - for _ in range(test_constants.STREAM_LENGTH // 2): - next(response_iterator) - - def testConsumingTooManyStreamResponsesStreamRequest(self): - requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - - multi_callable = _stream_stream_multi_callable(self._channel) - response_iterator = multi_callable( - request_iterator, - metadata=( - ('test', 'ConsumingTooManyStreamResponsesStreamRequest'),)) - for _ in range(test_constants.STREAM_LENGTH): - next(response_iterator) - for _ in range(test_constants.STREAM_LENGTH): - with self.assertRaises(StopIteration): - next(response_iterator) + self._channel = grpc.insecure_channel('localhost:%d' % port) - self.assertIsNotNone(response_iterator.initial_metadata()) - self.assertIs(grpc.StatusCode.OK, response_iterator.code()) - self.assertIsNotNone(response_iterator.details()) - self.assertIsNotNone(response_iterator.trailing_metadata()) - - def testCancelledUnaryRequestUnaryResponse(self): - request = b'\x07\x17' - - multi_callable = _unary_unary_multi_callable(self._channel) - with self._control.pause(): - response_future = multi_callable.future( - request, - metadata=(('test', 'CancelledUnaryRequestUnaryResponse'),)) - response_future.cancel() - - self.assertTrue(response_future.cancelled()) - with self.assertRaises(grpc.FutureCancelledError): - response_future.result() - with self.assertRaises(grpc.FutureCancelledError): - response_future.exception() - with self.assertRaises(grpc.FutureCancelledError): - response_future.traceback() - self.assertIs(grpc.StatusCode.CANCELLED, response_future.code()) - - def testCancelledUnaryRequestStreamResponse(self): - request = b'\x07\x19' - - multi_callable = _unary_stream_multi_callable(self._channel) - with self._control.pause(): - response_iterator = multi_callable( - request, - metadata=(('test', 'CancelledUnaryRequestStreamResponse'),)) - self._control.block_until_paused() - response_iterator.cancel() - - with self.assertRaises(grpc.RpcError) as exception_context: - next(response_iterator) - self.assertIs(grpc.StatusCode.CANCELLED, exception_context.exception.code()) - self.assertIsNotNone(response_iterator.initial_metadata()) - self.assertIs(grpc.StatusCode.CANCELLED, response_iterator.code()) - self.assertIsNotNone(response_iterator.details()) - self.assertIsNotNone(response_iterator.trailing_metadata()) - - def testCancelledStreamRequestUnaryResponse(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - - multi_callable = _stream_unary_multi_callable(self._channel) - with self._control.pause(): - response_future = multi_callable.future( - request_iterator, - metadata=(('test', 'CancelledStreamRequestUnaryResponse'),)) - self._control.block_until_paused() - response_future.cancel() - - self.assertTrue(response_future.cancelled()) - with self.assertRaises(grpc.FutureCancelledError): - response_future.result() - with self.assertRaises(grpc.FutureCancelledError): - response_future.exception() - with self.assertRaises(grpc.FutureCancelledError): - response_future.traceback() - self.assertIsNotNone(response_future.initial_metadata()) - self.assertIs(grpc.StatusCode.CANCELLED, response_future.code()) - self.assertIsNotNone(response_future.details()) - self.assertIsNotNone(response_future.trailing_metadata()) - - def testCancelledStreamRequestStreamResponse(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - - multi_callable = _stream_stream_multi_callable(self._channel) - with self._control.pause(): - response_iterator = multi_callable( - request_iterator, - metadata=(('test', 'CancelledStreamRequestStreamResponse'),)) - response_iterator.cancel() - - with self.assertRaises(grpc.RpcError): - next(response_iterator) - self.assertIsNotNone(response_iterator.initial_metadata()) - self.assertIs(grpc.StatusCode.CANCELLED, response_iterator.code()) - self.assertIsNotNone(response_iterator.details()) - self.assertIsNotNone(response_iterator.trailing_metadata()) - - def testExpiredUnaryRequestBlockingUnaryResponse(self): - request = b'\x07\x17' - - multi_callable = _unary_unary_multi_callable(self._channel) - with self._control.pause(): - with self.assertRaises(grpc.RpcError) as exception_context: - multi_callable.with_call( - request, timeout=test_constants.SHORT_TIMEOUT, - metadata=(('test', 'ExpiredUnaryRequestBlockingUnaryResponse'),)) - - self.assertIsInstance(exception_context.exception, grpc.Call) - self.assertIsNotNone(exception_context.exception.initial_metadata()) - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) - self.assertIsNotNone(exception_context.exception.details()) - self.assertIsNotNone(exception_context.exception.trailing_metadata()) - - def testExpiredUnaryRequestFutureUnaryResponse(self): - request = b'\x07\x17' - callback = _Callback() - - multi_callable = _unary_unary_multi_callable(self._channel) - with self._control.pause(): - response_future = multi_callable.future( - request, timeout=test_constants.SHORT_TIMEOUT, - metadata=(('test', 'ExpiredUnaryRequestFutureUnaryResponse'),)) - response_future.add_done_callback(callback) - value_passed_to_callback = callback.value() - - self.assertIs(response_future, value_passed_to_callback) - self.assertIsNotNone(response_future.initial_metadata()) - self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) - self.assertIsNotNone(response_future.details()) - self.assertIsNotNone(response_future.trailing_metadata()) - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) - self.assertIsInstance(response_future.exception(), grpc.RpcError) - self.assertIsNotNone(response_future.traceback()) - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, response_future.exception().code()) - - def testExpiredUnaryRequestStreamResponse(self): - request = b'\x07\x19' - - multi_callable = _unary_stream_multi_callable(self._channel) - with self._control.pause(): - with self.assertRaises(grpc.RpcError) as exception_context: - response_iterator = multi_callable( - request, timeout=test_constants.SHORT_TIMEOUT, - metadata=(('test', 'ExpiredUnaryRequestStreamResponse'),)) - next(response_iterator) + def tearDown(self): + self._server.stop(None) + self._server_pool.shutdown(wait=True) - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) - self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_iterator.code()) + def testUnrecognizedMethod(self): + request = b'abc' - def testExpiredStreamRequestBlockingUnaryResponse(self): - requests = tuple(b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) + with self.assertRaises(grpc.RpcError) as exception_context: + self._channel.unary_unary('NoSuchMethod')(request) - multi_callable = _stream_unary_multi_callable(self._channel) - with self._control.pause(): - with self.assertRaises(grpc.RpcError) as exception_context: - multi_callable( - request_iterator, timeout=test_constants.SHORT_TIMEOUT, - metadata=(('test', 'ExpiredStreamRequestBlockingUnaryResponse'),)) - - self.assertIsInstance(exception_context.exception, grpc.RpcError) - self.assertIsInstance(exception_context.exception, grpc.Call) - self.assertIsNotNone(exception_context.exception.initial_metadata()) - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) - self.assertIsNotNone(exception_context.exception.details()) - self.assertIsNotNone(exception_context.exception.trailing_metadata()) - - def testExpiredStreamRequestFutureUnaryResponse(self): - requests = tuple(b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - callback = _Callback() - - multi_callable = _stream_unary_multi_callable(self._channel) - with self._control.pause(): - response_future = multi_callable.future( - request_iterator, timeout=test_constants.SHORT_TIMEOUT, - metadata=(('test', 'ExpiredStreamRequestFutureUnaryResponse'),)) - with self.assertRaises(grpc.FutureTimeoutError): - response_future.result(timeout=test_constants.SHORT_TIMEOUT / 2.0) - response_future.add_done_callback(callback) - value_passed_to_callback = callback.value() - - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) - self.assertIsInstance(response_future.exception(), grpc.RpcError) - self.assertIsNotNone(response_future.traceback()) - self.assertIs(response_future, value_passed_to_callback) - self.assertIsNotNone(response_future.initial_metadata()) - self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) - self.assertIsNotNone(response_future.details()) - self.assertIsNotNone(response_future.trailing_metadata()) - - def testExpiredStreamRequestStreamResponse(self): - requests = tuple(b'\x67\x18' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - - multi_callable = _stream_stream_multi_callable(self._channel) - with self._control.pause(): - with self.assertRaises(grpc.RpcError) as exception_context: - response_iterator = multi_callable( - request_iterator, timeout=test_constants.SHORT_TIMEOUT, - metadata=(('test', 'ExpiredStreamRequestStreamResponse'),)) - next(response_iterator) + self.assertEqual(grpc.StatusCode.UNIMPLEMENTED, + exception_context.exception.code()) + + def testSuccessfulUnaryRequestBlockingUnaryResponse(self): + request = b'\x07\x08' + expected_response = self._handler.handle_unary_unary(request, None) + + multi_callable = _unary_unary_multi_callable(self._channel) + response = multi_callable( + request, + metadata=(('test', 'SuccessfulUnaryRequestBlockingUnaryResponse'),)) + + self.assertEqual(expected_response, response) - self.assertIs( - grpc.StatusCode.DEADLINE_EXCEEDED, exception_context.exception.code()) - self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_iterator.code()) + def testSuccessfulUnaryRequestBlockingUnaryResponseWithCall(self): + request = b'\x07\x08' + expected_response = self._handler.handle_unary_unary(request, None) - def testFailedUnaryRequestBlockingUnaryResponse(self): - request = b'\x37\x17' + multi_callable = _unary_unary_multi_callable(self._channel) + response, call = multi_callable.with_call( + request, + metadata=(('test', + 'SuccessfulUnaryRequestBlockingUnaryResponseWithCall'),)) + + self.assertEqual(expected_response, response) + self.assertIs(grpc.StatusCode.OK, call.code()) + + def testSuccessfulUnaryRequestFutureUnaryResponse(self): + request = b'\x07\x08' + expected_response = self._handler.handle_unary_unary(request, None) - multi_callable = _unary_unary_multi_callable(self._channel) - with self._control.fail(): - with self.assertRaises(grpc.RpcError) as exception_context: - multi_callable.with_call( + multi_callable = _unary_unary_multi_callable(self._channel) + response_future = multi_callable.future( request, - metadata=(('test', 'FailedUnaryRequestBlockingUnaryResponse'),)) - - self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) - - def testFailedUnaryRequestFutureUnaryResponse(self): - request = b'\x37\x17' - callback = _Callback() - - multi_callable = _unary_unary_multi_callable(self._channel) - with self._control.fail(): - response_future = multi_callable.future( - request, - metadata=(('test', 'FailedUnaryRequestFutureUnaryResponse'),)) - response_future.add_done_callback(callback) - value_passed_to_callback = callback.value() - - self.assertIsInstance(response_future, grpc.Future) - self.assertIsInstance(response_future, grpc.Call) - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertIs( - grpc.StatusCode.UNKNOWN, exception_context.exception.code()) - self.assertIsInstance(response_future.exception(), grpc.RpcError) - self.assertIsNotNone(response_future.traceback()) - self.assertIs(grpc.StatusCode.UNKNOWN, response_future.exception().code()) - self.assertIs(response_future, value_passed_to_callback) - - def testFailedUnaryRequestStreamResponse(self): - request = b'\x37\x17' - - multi_callable = _unary_stream_multi_callable(self._channel) - with self.assertRaises(grpc.RpcError) as exception_context: - with self._control.fail(): + metadata=(('test', 'SuccessfulUnaryRequestFutureUnaryResponse'),)) + response = response_future.result() + + self.assertIsInstance(response_future, grpc.Future) + self.assertIsInstance(response_future, grpc.Call) + self.assertEqual(expected_response, response) + self.assertIsNone(response_future.exception()) + self.assertIsNone(response_future.traceback()) + + def testSuccessfulUnaryRequestStreamResponse(self): + request = b'\x37\x58' + expected_responses = tuple( + self._handler.handle_unary_stream(request, None)) + + multi_callable = _unary_stream_multi_callable(self._channel) response_iterator = multi_callable( request, - metadata=(('test', 'FailedUnaryRequestStreamResponse'),)) - next(response_iterator) + metadata=(('test', 'SuccessfulUnaryRequestStreamResponse'),)) + responses = tuple(response_iterator) - self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) + self.assertSequenceEqual(expected_responses, responses) - def testFailedStreamRequestBlockingUnaryResponse(self): - requests = tuple(b'\x47\x58' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) + def testSuccessfulStreamRequestBlockingUnaryResponse(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + expected_response = self._handler.handle_stream_unary( + iter(requests), None) + request_iterator = iter(requests) - multi_callable = _stream_unary_multi_callable(self._channel) - with self._control.fail(): - with self.assertRaises(grpc.RpcError) as exception_context: - multi_callable( + multi_callable = _stream_unary_multi_callable(self._channel) + response = multi_callable( + request_iterator, + metadata=( + ('test', 'SuccessfulStreamRequestBlockingUnaryResponse'),)) + + self.assertEqual(expected_response, response) + + def testSuccessfulStreamRequestBlockingUnaryResponseWithCall(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + expected_response = self._handler.handle_stream_unary( + iter(requests), None) + request_iterator = iter(requests) + + multi_callable = _stream_unary_multi_callable(self._channel) + response, call = multi_callable.with_call( + request_iterator, + metadata=( + ('test', + 'SuccessfulStreamRequestBlockingUnaryResponseWithCall'),)) + + self.assertEqual(expected_response, response) + self.assertIs(grpc.StatusCode.OK, call.code()) + + def testSuccessfulStreamRequestFutureUnaryResponse(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + expected_response = self._handler.handle_stream_unary( + iter(requests), None) + request_iterator = iter(requests) + + multi_callable = _stream_unary_multi_callable(self._channel) + response_future = multi_callable.future( request_iterator, - metadata=(('test', 'FailedStreamRequestBlockingUnaryResponse'),)) - - self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) - - def testFailedStreamRequestFutureUnaryResponse(self): - requests = tuple(b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - callback = _Callback() - - multi_callable = _stream_unary_multi_callable(self._channel) - with self._control.fail(): - response_future = multi_callable.future( - request_iterator, - metadata=(('test', 'FailedStreamRequestFutureUnaryResponse'),)) - response_future.add_done_callback(callback) - value_passed_to_callback = callback.value() - - with self.assertRaises(grpc.RpcError) as exception_context: - response_future.result() - self.assertIs(grpc.StatusCode.UNKNOWN, response_future.code()) - self.assertIs( - grpc.StatusCode.UNKNOWN, exception_context.exception.code()) - self.assertIsInstance(response_future.exception(), grpc.RpcError) - self.assertIsNotNone(response_future.traceback()) - self.assertIs(response_future, value_passed_to_callback) - - def testFailedStreamRequestStreamResponse(self): - requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) - - multi_callable = _stream_stream_multi_callable(self._channel) - with self._control.fail(): - with self.assertRaises(grpc.RpcError) as exception_context: + metadata=(('test', 'SuccessfulStreamRequestFutureUnaryResponse'),)) + response = response_future.result() + + self.assertEqual(expected_response, response) + self.assertIsNone(response_future.exception()) + self.assertIsNone(response_future.traceback()) + + def testSuccessfulStreamRequestStreamResponse(self): + requests = tuple(b'\x77\x58' + for _ in range(test_constants.STREAM_LENGTH)) + expected_responses = tuple( + self._handler.handle_stream_stream(iter(requests), None)) + request_iterator = iter(requests) + + multi_callable = _stream_stream_multi_callable(self._channel) response_iterator = multi_callable( request_iterator, - metadata=(('test', 'FailedStreamRequestStreamResponse'),)) - tuple(response_iterator) + metadata=(('test', 'SuccessfulStreamRequestStreamResponse'),)) + responses = tuple(response_iterator) + + self.assertSequenceEqual(expected_responses, responses) + + def testSequentialInvocations(self): + first_request = b'\x07\x08' + second_request = b'\x0809' + expected_first_response = self._handler.handle_unary_unary( + first_request, None) + expected_second_response = self._handler.handle_unary_unary( + second_request, None) + + multi_callable = _unary_unary_multi_callable(self._channel) + first_response = multi_callable( + first_request, metadata=(('test', 'SequentialInvocations'),)) + second_response = multi_callable( + second_request, metadata=(('test', 'SequentialInvocations'),)) + + self.assertEqual(expected_first_response, first_response) + self.assertEqual(expected_second_response, second_response) + + def testConcurrentBlockingInvocations(self): + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + expected_response = self._handler.handle_stream_unary( + iter(requests), None) + expected_responses = [expected_response + ] * test_constants.THREAD_CONCURRENCY + response_futures = [None] * test_constants.THREAD_CONCURRENCY + + multi_callable = _stream_unary_multi_callable(self._channel) + for index in range(test_constants.THREAD_CONCURRENCY): + request_iterator = iter(requests) + response_future = pool.submit( + multi_callable, + request_iterator, + metadata=(('test', 'ConcurrentBlockingInvocations'),)) + response_futures[index] = response_future + responses = tuple(response_future.result() + for response_future in response_futures) + + pool.shutdown(wait=True) + self.assertSequenceEqual(expected_responses, responses) + + def testConcurrentFutureInvocations(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + expected_response = self._handler.handle_stream_unary( + iter(requests), None) + expected_responses = [expected_response + ] * test_constants.THREAD_CONCURRENCY + response_futures = [None] * test_constants.THREAD_CONCURRENCY + + multi_callable = _stream_unary_multi_callable(self._channel) + for index in range(test_constants.THREAD_CONCURRENCY): + request_iterator = iter(requests) + response_future = multi_callable.future( + request_iterator, + metadata=(('test', 'ConcurrentFutureInvocations'),)) + response_futures[index] = response_future + responses = tuple(response_future.result() + for response_future in response_futures) + + self.assertSequenceEqual(expected_responses, responses) + + def testWaitingForSomeButNotAllConcurrentFutureInvocations(self): + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + request = b'\x67\x68' + expected_response = self._handler.handle_unary_unary(request, None) + response_futures = [None] * test_constants.THREAD_CONCURRENCY + lock = threading.Lock() + test_is_running_cell = [True] + + def wrap_future(future): + + def wrap(): + try: + return future.result() + except grpc.RpcError: + with lock: + if test_is_running_cell[0]: + raise + return None + + return wrap + + multi_callable = _unary_unary_multi_callable(self._channel) + for index in range(test_constants.THREAD_CONCURRENCY): + inner_response_future = multi_callable.future( + request, + metadata=( + ('test', + 'WaitingForSomeButNotAllConcurrentFutureInvocations'),)) + outer_response_future = pool.submit( + wrap_future(inner_response_future)) + response_futures[index] = outer_response_future + + some_completed_response_futures_iterator = itertools.islice( + futures.as_completed(response_futures), + test_constants.THREAD_CONCURRENCY // 2) + for response_future in some_completed_response_futures_iterator: + self.assertEqual(expected_response, response_future.result()) + with lock: + test_is_running_cell[0] = False + + def testConsumingOneStreamResponseUnaryRequest(self): + request = b'\x57\x38' + + multi_callable = _unary_stream_multi_callable(self._channel) + response_iterator = multi_callable( + request, + metadata=(('test', 'ConsumingOneStreamResponseUnaryRequest'),)) + next(response_iterator) + + def testConsumingSomeButNotAllStreamResponsesUnaryRequest(self): + request = b'\x57\x38' + + multi_callable = _unary_stream_multi_callable(self._channel) + response_iterator = multi_callable( + request, + metadata=( + ('test', 'ConsumingSomeButNotAllStreamResponsesUnaryRequest'),)) + for _ in range(test_constants.STREAM_LENGTH // 2): + next(response_iterator) - self.assertIs(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) - self.assertIs(grpc.StatusCode.UNKNOWN, response_iterator.code()) + def testConsumingSomeButNotAllStreamResponsesStreamRequest(self): + requests = tuple(b'\x67\x88' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) - def testIgnoredUnaryRequestFutureUnaryResponse(self): - request = b'\x37\x17' + multi_callable = _stream_stream_multi_callable(self._channel) + response_iterator = multi_callable( + request_iterator, + metadata=(('test', + 'ConsumingSomeButNotAllStreamResponsesStreamRequest'),)) + for _ in range(test_constants.STREAM_LENGTH // 2): + next(response_iterator) - multi_callable = _unary_unary_multi_callable(self._channel) - multi_callable.future( - request, - metadata=(('test', 'IgnoredUnaryRequestFutureUnaryResponse'),)) + def testConsumingTooManyStreamResponsesStreamRequest(self): + requests = tuple(b'\x67\x88' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) - def testIgnoredUnaryRequestStreamResponse(self): - request = b'\x37\x17' + multi_callable = _stream_stream_multi_callable(self._channel) + response_iterator = multi_callable( + request_iterator, + metadata=( + ('test', 'ConsumingTooManyStreamResponsesStreamRequest'),)) + for _ in range(test_constants.STREAM_LENGTH): + next(response_iterator) + for _ in range(test_constants.STREAM_LENGTH): + with self.assertRaises(StopIteration): + next(response_iterator) + + self.assertIsNotNone(response_iterator.initial_metadata()) + self.assertIs(grpc.StatusCode.OK, response_iterator.code()) + self.assertIsNotNone(response_iterator.details()) + self.assertIsNotNone(response_iterator.trailing_metadata()) + + def testCancelledUnaryRequestUnaryResponse(self): + request = b'\x07\x17' + + multi_callable = _unary_unary_multi_callable(self._channel) + with self._control.pause(): + response_future = multi_callable.future( + request, + metadata=(('test', 'CancelledUnaryRequestUnaryResponse'),)) + response_future.cancel() + + self.assertTrue(response_future.cancelled()) + with self.assertRaises(grpc.FutureCancelledError): + response_future.result() + with self.assertRaises(grpc.FutureCancelledError): + response_future.exception() + with self.assertRaises(grpc.FutureCancelledError): + response_future.traceback() + self.assertIs(grpc.StatusCode.CANCELLED, response_future.code()) + + def testCancelledUnaryRequestStreamResponse(self): + request = b'\x07\x19' + + multi_callable = _unary_stream_multi_callable(self._channel) + with self._control.pause(): + response_iterator = multi_callable( + request, + metadata=(('test', 'CancelledUnaryRequestStreamResponse'),)) + self._control.block_until_paused() + response_iterator.cancel() + + with self.assertRaises(grpc.RpcError) as exception_context: + next(response_iterator) + self.assertIs(grpc.StatusCode.CANCELLED, + exception_context.exception.code()) + self.assertIsNotNone(response_iterator.initial_metadata()) + self.assertIs(grpc.StatusCode.CANCELLED, response_iterator.code()) + self.assertIsNotNone(response_iterator.details()) + self.assertIsNotNone(response_iterator.trailing_metadata()) + + def testCancelledStreamRequestUnaryResponse(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + + multi_callable = _stream_unary_multi_callable(self._channel) + with self._control.pause(): + response_future = multi_callable.future( + request_iterator, + metadata=(('test', 'CancelledStreamRequestUnaryResponse'),)) + self._control.block_until_paused() + response_future.cancel() + + self.assertTrue(response_future.cancelled()) + with self.assertRaises(grpc.FutureCancelledError): + response_future.result() + with self.assertRaises(grpc.FutureCancelledError): + response_future.exception() + with self.assertRaises(grpc.FutureCancelledError): + response_future.traceback() + self.assertIsNotNone(response_future.initial_metadata()) + self.assertIs(grpc.StatusCode.CANCELLED, response_future.code()) + self.assertIsNotNone(response_future.details()) + self.assertIsNotNone(response_future.trailing_metadata()) + + def testCancelledStreamRequestStreamResponse(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + + multi_callable = _stream_stream_multi_callable(self._channel) + with self._control.pause(): + response_iterator = multi_callable( + request_iterator, + metadata=(('test', 'CancelledStreamRequestStreamResponse'),)) + response_iterator.cancel() + + with self.assertRaises(grpc.RpcError): + next(response_iterator) + self.assertIsNotNone(response_iterator.initial_metadata()) + self.assertIs(grpc.StatusCode.CANCELLED, response_iterator.code()) + self.assertIsNotNone(response_iterator.details()) + self.assertIsNotNone(response_iterator.trailing_metadata()) + + def testExpiredUnaryRequestBlockingUnaryResponse(self): + request = b'\x07\x17' + + multi_callable = _unary_unary_multi_callable(self._channel) + with self._control.pause(): + with self.assertRaises(grpc.RpcError) as exception_context: + multi_callable.with_call( + request, + timeout=test_constants.SHORT_TIMEOUT, + metadata=( + ('test', 'ExpiredUnaryRequestBlockingUnaryResponse'),)) + + self.assertIsInstance(exception_context.exception, grpc.Call) + self.assertIsNotNone(exception_context.exception.initial_metadata()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + exception_context.exception.code()) + self.assertIsNotNone(exception_context.exception.details()) + self.assertIsNotNone(exception_context.exception.trailing_metadata()) + + def testExpiredUnaryRequestFutureUnaryResponse(self): + request = b'\x07\x17' + callback = _Callback() + + multi_callable = _unary_unary_multi_callable(self._channel) + with self._control.pause(): + response_future = multi_callable.future( + request, + timeout=test_constants.SHORT_TIMEOUT, + metadata=(('test', 'ExpiredUnaryRequestFutureUnaryResponse'),)) + response_future.add_done_callback(callback) + value_passed_to_callback = callback.value() + + self.assertIs(response_future, value_passed_to_callback) + self.assertIsNotNone(response_future.initial_metadata()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) + self.assertIsNotNone(response_future.details()) + self.assertIsNotNone(response_future.trailing_metadata()) + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + exception_context.exception.code()) + self.assertIsInstance(response_future.exception(), grpc.RpcError) + self.assertIsNotNone(response_future.traceback()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + response_future.exception().code()) + + def testExpiredUnaryRequestStreamResponse(self): + request = b'\x07\x19' + + multi_callable = _unary_stream_multi_callable(self._channel) + with self._control.pause(): + with self.assertRaises(grpc.RpcError) as exception_context: + response_iterator = multi_callable( + request, + timeout=test_constants.SHORT_TIMEOUT, + metadata=(('test', 'ExpiredUnaryRequestStreamResponse'),)) + next(response_iterator) + + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + exception_context.exception.code()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + response_iterator.code()) + + def testExpiredStreamRequestBlockingUnaryResponse(self): + requests = tuple(b'\x07\x08' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + + multi_callable = _stream_unary_multi_callable(self._channel) + with self._control.pause(): + with self.assertRaises(grpc.RpcError) as exception_context: + multi_callable( + request_iterator, + timeout=test_constants.SHORT_TIMEOUT, + metadata=( + ('test', 'ExpiredStreamRequestBlockingUnaryResponse'),)) + + self.assertIsInstance(exception_context.exception, grpc.RpcError) + self.assertIsInstance(exception_context.exception, grpc.Call) + self.assertIsNotNone(exception_context.exception.initial_metadata()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + exception_context.exception.code()) + self.assertIsNotNone(exception_context.exception.details()) + self.assertIsNotNone(exception_context.exception.trailing_metadata()) + + def testExpiredStreamRequestFutureUnaryResponse(self): + requests = tuple(b'\x07\x18' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + callback = _Callback() + + multi_callable = _stream_unary_multi_callable(self._channel) + with self._control.pause(): + response_future = multi_callable.future( + request_iterator, + timeout=test_constants.SHORT_TIMEOUT, + metadata=(('test', 'ExpiredStreamRequestFutureUnaryResponse'),)) + with self.assertRaises(grpc.FutureTimeoutError): + response_future.result(timeout=test_constants.SHORT_TIMEOUT / + 2.0) + response_future.add_done_callback(callback) + value_passed_to_callback = callback.value() + + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + exception_context.exception.code()) + self.assertIsInstance(response_future.exception(), grpc.RpcError) + self.assertIsNotNone(response_future.traceback()) + self.assertIs(response_future, value_passed_to_callback) + self.assertIsNotNone(response_future.initial_metadata()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, response_future.code()) + self.assertIsNotNone(response_future.details()) + self.assertIsNotNone(response_future.trailing_metadata()) + + def testExpiredStreamRequestStreamResponse(self): + requests = tuple(b'\x67\x18' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + + multi_callable = _stream_stream_multi_callable(self._channel) + with self._control.pause(): + with self.assertRaises(grpc.RpcError) as exception_context: + response_iterator = multi_callable( + request_iterator, + timeout=test_constants.SHORT_TIMEOUT, + metadata=(('test', 'ExpiredStreamRequestStreamResponse'),)) + next(response_iterator) + + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + exception_context.exception.code()) + self.assertIs(grpc.StatusCode.DEADLINE_EXCEEDED, + response_iterator.code()) + + def testFailedUnaryRequestBlockingUnaryResponse(self): + request = b'\x37\x17' + + multi_callable = _unary_unary_multi_callable(self._channel) + with self._control.fail(): + with self.assertRaises(grpc.RpcError) as exception_context: + multi_callable.with_call( + request, + metadata=( + ('test', 'FailedUnaryRequestBlockingUnaryResponse'),)) + + self.assertIs(grpc.StatusCode.UNKNOWN, + exception_context.exception.code()) + + def testFailedUnaryRequestFutureUnaryResponse(self): + request = b'\x37\x17' + callback = _Callback() + + multi_callable = _unary_unary_multi_callable(self._channel) + with self._control.fail(): + response_future = multi_callable.future( + request, + metadata=(('test', 'FailedUnaryRequestFutureUnaryResponse'),)) + response_future.add_done_callback(callback) + value_passed_to_callback = callback.value() + + self.assertIsInstance(response_future, grpc.Future) + self.assertIsInstance(response_future, grpc.Call) + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertIs(grpc.StatusCode.UNKNOWN, + exception_context.exception.code()) + self.assertIsInstance(response_future.exception(), grpc.RpcError) + self.assertIsNotNone(response_future.traceback()) + self.assertIs(grpc.StatusCode.UNKNOWN, + response_future.exception().code()) + self.assertIs(response_future, value_passed_to_callback) + + def testFailedUnaryRequestStreamResponse(self): + request = b'\x37\x17' + + multi_callable = _unary_stream_multi_callable(self._channel) + with self.assertRaises(grpc.RpcError) as exception_context: + with self._control.fail(): + response_iterator = multi_callable( + request, + metadata=(('test', 'FailedUnaryRequestStreamResponse'),)) + next(response_iterator) + + self.assertIs(grpc.StatusCode.UNKNOWN, + exception_context.exception.code()) + + def testFailedStreamRequestBlockingUnaryResponse(self): + requests = tuple(b'\x47\x58' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + + multi_callable = _stream_unary_multi_callable(self._channel) + with self._control.fail(): + with self.assertRaises(grpc.RpcError) as exception_context: + multi_callable( + request_iterator, + metadata=( + ('test', 'FailedStreamRequestBlockingUnaryResponse'),)) + + self.assertIs(grpc.StatusCode.UNKNOWN, + exception_context.exception.code()) + + def testFailedStreamRequestFutureUnaryResponse(self): + requests = tuple(b'\x07\x18' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + callback = _Callback() + + multi_callable = _stream_unary_multi_callable(self._channel) + with self._control.fail(): + response_future = multi_callable.future( + request_iterator, + metadata=(('test', 'FailedStreamRequestFutureUnaryResponse'),)) + response_future.add_done_callback(callback) + value_passed_to_callback = callback.value() + + with self.assertRaises(grpc.RpcError) as exception_context: + response_future.result() + self.assertIs(grpc.StatusCode.UNKNOWN, response_future.code()) + self.assertIs(grpc.StatusCode.UNKNOWN, + exception_context.exception.code()) + self.assertIsInstance(response_future.exception(), grpc.RpcError) + self.assertIsNotNone(response_future.traceback()) + self.assertIs(response_future, value_passed_to_callback) + + def testFailedStreamRequestStreamResponse(self): + requests = tuple(b'\x67\x88' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) + + multi_callable = _stream_stream_multi_callable(self._channel) + with self._control.fail(): + with self.assertRaises(grpc.RpcError) as exception_context: + response_iterator = multi_callable( + request_iterator, + metadata=(('test', 'FailedStreamRequestStreamResponse'),)) + tuple(response_iterator) + + self.assertIs(grpc.StatusCode.UNKNOWN, + exception_context.exception.code()) + self.assertIs(grpc.StatusCode.UNKNOWN, response_iterator.code()) + + def testIgnoredUnaryRequestFutureUnaryResponse(self): + request = b'\x37\x17' + + multi_callable = _unary_unary_multi_callable(self._channel) + multi_callable.future( + request, + metadata=(('test', 'IgnoredUnaryRequestFutureUnaryResponse'),)) - multi_callable = _unary_stream_multi_callable(self._channel) - multi_callable( - request, - metadata=(('test', 'IgnoredUnaryRequestStreamResponse'),)) + def testIgnoredUnaryRequestStreamResponse(self): + request = b'\x37\x17' - def testIgnoredStreamRequestFutureUnaryResponse(self): - requests = tuple(b'\x07\x18' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) + multi_callable = _unary_stream_multi_callable(self._channel) + multi_callable( + request, metadata=(('test', 'IgnoredUnaryRequestStreamResponse'),)) + + def testIgnoredStreamRequestFutureUnaryResponse(self): + requests = tuple(b'\x07\x18' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) - multi_callable = _stream_unary_multi_callable(self._channel) - multi_callable.future( - request_iterator, - metadata=(('test', 'IgnoredStreamRequestFutureUnaryResponse'),)) + multi_callable = _stream_unary_multi_callable(self._channel) + multi_callable.future( + request_iterator, + metadata=(('test', 'IgnoredStreamRequestFutureUnaryResponse'),)) - def testIgnoredStreamRequestStreamResponse(self): - requests = tuple(b'\x67\x88' for _ in range(test_constants.STREAM_LENGTH)) - request_iterator = iter(requests) + def testIgnoredStreamRequestStreamResponse(self): + requests = tuple(b'\x67\x88' + for _ in range(test_constants.STREAM_LENGTH)) + request_iterator = iter(requests) - multi_callable = _stream_stream_multi_callable(self._channel) - multi_callable( - request_iterator, - metadata=(('test', 'IgnoredStreamRequestStreamResponse'),)) + multi_callable = _stream_stream_multi_callable(self._channel) + multi_callable( + request_iterator, + metadata=(('test', 'IgnoredStreamRequestStreamResponse'),)) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_sanity/__init__.py b/src/python/grpcio_tests/tests/unit/_sanity/__init__.py index 2f88fa04122..100a624dc9c 100644 --- a/src/python/grpcio_tests/tests/unit/_sanity/__init__.py +++ b/src/python/grpcio_tests/tests/unit/_sanity/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/_sanity/_sanity_test.py b/src/python/grpcio_tests/tests/unit/_sanity/_sanity_test.py index e9fdf217aef..0fbe6a2b5d0 100644 --- a/src/python/grpcio_tests/tests/unit/_sanity/_sanity_test.py +++ b/src/python/grpcio_tests/tests/unit/_sanity/_sanity_test.py @@ -38,21 +38,23 @@ import tests class Sanity(unittest.TestCase): - def testTestsJsonUpToDate(self): - """Autodiscovers all test suites and checks that tests.json is up to date""" - loader = tests.Loader() - loader.loadTestsFromNames(['tests']) - test_suite_names = [ - test_case_class.id().rsplit('.', 1)[0] - for test_case_class in tests._loader.iterate_suite_cases(loader.suite)] - test_suite_names = sorted(set(test_suite_names)) - - tests_json_string = pkg_resources.resource_string('tests', 'tests.json') - if six.PY3: - tests_json_string = tests_json_string.decode() - tests_json = json.loads(tests_json_string) - self.assertListEqual(test_suite_names, tests_json) + def testTestsJsonUpToDate(self): + """Autodiscovers all test suites and checks that tests.json is up to date""" + loader = tests.Loader() + loader.loadTestsFromNames(['tests']) + test_suite_names = [ + test_case_class.id().rsplit('.', 1)[0] + for test_case_class in tests._loader.iterate_suite_cases( + loader.suite) + ] + test_suite_names = sorted(set(test_suite_names)) + + tests_json_string = pkg_resources.resource_string('tests', 'tests.json') + if six.PY3: + tests_json_string = tests_json_string.decode() + tests_json = json.loads(tests_json_string) + self.assertListEqual(test_suite_names, tests_json) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py b/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py index 3e4f317edcd..be3522f46f2 100644 --- a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py +++ b/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py @@ -40,78 +40,89 @@ _EPSILON = 0.1 def cleanup(timeout): - if timeout is not None: - time.sleep(timeout) - else: - time.sleep(_LONG_TIME) + if timeout is not None: + time.sleep(timeout) + else: + time.sleep(_LONG_TIME) def slow_cleanup(timeout): - # Don't respect timeout - time.sleep(_LONG_TIME) + # Don't respect timeout + time.sleep(_LONG_TIME) class CleanupThreadTest(unittest.TestCase): - def testTargetInvocation(self): - event = threading.Event() - def target(arg1, arg2, arg3=None): - self.assertEqual('arg1', arg1) - self.assertEqual('arg2', arg2) - self.assertEqual('arg3', arg3) - event.set() - - cleanup_thread = _common.CleanupThread(behavior=lambda x: None, - target=target, name='test-name', - args=('arg1', 'arg2'), kwargs={'arg3': 'arg3'}) - cleanup_thread.start() - cleanup_thread.join() - self.assertEqual(cleanup_thread.name, 'test-name') - self.assertTrue(event.is_set()) - - def testJoinNoTimeout(self): - cleanup_thread = _common.CleanupThread(behavior=cleanup) - cleanup_thread.start() - start_time = time.time() - cleanup_thread.join() - end_time = time.time() - self.assertAlmostEqual(_LONG_TIME, end_time - start_time, delta=_EPSILON) - - def testJoinTimeout(self): - cleanup_thread = _common.CleanupThread(behavior=cleanup) - cleanup_thread.start() - start_time = time.time() - cleanup_thread.join(_SHORT_TIME) - end_time = time.time() - self.assertAlmostEqual(_SHORT_TIME, end_time - start_time, delta=_EPSILON) - - def testJoinTimeoutSlowBehavior(self): - cleanup_thread = _common.CleanupThread(behavior=slow_cleanup) - cleanup_thread.start() - start_time = time.time() - cleanup_thread.join(_SHORT_TIME) - end_time = time.time() - self.assertAlmostEqual(_LONG_TIME, end_time - start_time, delta=_EPSILON) - - def testJoinTimeoutSlowTarget(self): - event = threading.Event() - def target(): - event.wait(_LONG_TIME) - cleanup_thread = _common.CleanupThread(behavior=cleanup, target=target) - cleanup_thread.start() - start_time = time.time() - cleanup_thread.join(_SHORT_TIME) - end_time = time.time() - self.assertAlmostEqual(_SHORT_TIME, end_time - start_time, delta=_EPSILON) - event.set() - - def testJoinZeroTimeout(self): - cleanup_thread = _common.CleanupThread(behavior=cleanup) - cleanup_thread.start() - start_time = time.time() - cleanup_thread.join(0) - end_time = time.time() - self.assertAlmostEqual(0, end_time - start_time, delta=_EPSILON) + def testTargetInvocation(self): + event = threading.Event() + + def target(arg1, arg2, arg3=None): + self.assertEqual('arg1', arg1) + self.assertEqual('arg2', arg2) + self.assertEqual('arg3', arg3) + event.set() + + cleanup_thread = _common.CleanupThread( + behavior=lambda x: None, + target=target, + name='test-name', + args=('arg1', 'arg2'), + kwargs={'arg3': 'arg3'}) + cleanup_thread.start() + cleanup_thread.join() + self.assertEqual(cleanup_thread.name, 'test-name') + self.assertTrue(event.is_set()) + + def testJoinNoTimeout(self): + cleanup_thread = _common.CleanupThread(behavior=cleanup) + cleanup_thread.start() + start_time = time.time() + cleanup_thread.join() + end_time = time.time() + self.assertAlmostEqual( + _LONG_TIME, end_time - start_time, delta=_EPSILON) + + def testJoinTimeout(self): + cleanup_thread = _common.CleanupThread(behavior=cleanup) + cleanup_thread.start() + start_time = time.time() + cleanup_thread.join(_SHORT_TIME) + end_time = time.time() + self.assertAlmostEqual( + _SHORT_TIME, end_time - start_time, delta=_EPSILON) + + def testJoinTimeoutSlowBehavior(self): + cleanup_thread = _common.CleanupThread(behavior=slow_cleanup) + cleanup_thread.start() + start_time = time.time() + cleanup_thread.join(_SHORT_TIME) + end_time = time.time() + self.assertAlmostEqual( + _LONG_TIME, end_time - start_time, delta=_EPSILON) + + def testJoinTimeoutSlowTarget(self): + event = threading.Event() + + def target(): + event.wait(_LONG_TIME) + + cleanup_thread = _common.CleanupThread(behavior=cleanup, target=target) + cleanup_thread.start() + start_time = time.time() + cleanup_thread.join(_SHORT_TIME) + end_time = time.time() + self.assertAlmostEqual( + _SHORT_TIME, end_time - start_time, delta=_EPSILON) + event.set() + + def testJoinZeroTimeout(self): + cleanup_thread = _common.CleanupThread(behavior=cleanup) + cleanup_thread.start() + start_time = time.time() + cleanup_thread.join(0) + end_time = time.time() + self.assertAlmostEqual(0, end_time - start_time, delta=_EPSILON) + if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/_thread_pool.py b/src/python/grpcio_tests/tests/unit/_thread_pool.py index f13cc2f86fc..fad2e1c8f6d 100644 --- a/src/python/grpcio_tests/tests/unit/_thread_pool.py +++ b/src/python/grpcio_tests/tests/unit/_thread_pool.py @@ -32,17 +32,18 @@ from concurrent import futures class RecordingThreadPool(futures.Executor): - """A thread pool that records if used.""" - def __init__(self, max_workers): - self._tp_executor = futures.ThreadPoolExecutor(max_workers=max_workers) - self._lock = threading.Lock() - self._was_used = False + """A thread pool that records if used.""" - def submit(self, fn, *args, **kwargs): - with self._lock: - self._was_used = True - self._tp_executor.submit(fn, *args, **kwargs) + def __init__(self, max_workers): + self._tp_executor = futures.ThreadPoolExecutor(max_workers=max_workers) + self._lock = threading.Lock() + self._was_used = False - def was_used(self): - with self._lock: - return self._was_used + def submit(self, fn, *args, **kwargs): + with self._lock: + self._was_used = True + self._tp_executor.submit(fn, *args, **kwargs) + + def was_used(self): + with self._lock: + return self._was_used diff --git a/src/python/grpcio_tests/tests/unit/beta/__init__.py b/src/python/grpcio_tests/tests/unit/beta/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/beta/__init__.py +++ b/src/python/grpcio_tests/tests/unit/beta/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py b/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py index 3a9701b8ebe..b5fdac26c11 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py @@ -26,7 +26,6 @@ # 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. - """Tests Face interface compliance of the gRPC Python Beta API.""" import threading @@ -57,290 +56,303 @@ _RESPONSE = b'123' class _Servicer(object): - def __init__(self): - self._condition = threading.Condition() - self._peer = None - self._serviced = False - - def unary_unary(self, request, context): - with self._condition: - self._request = request - self._peer = context.protocol_context().peer() - self._invocation_metadata = context.invocation_metadata() - context.protocol_context().disable_next_response_compression() - self._serviced = True - self._condition.notify_all() - return _RESPONSE - - def unary_stream(self, request, context): - with self._condition: - self._request = request - self._peer = context.protocol_context().peer() - self._invocation_metadata = context.invocation_metadata() - context.protocol_context().disable_next_response_compression() - self._serviced = True - self._condition.notify_all() - return - yield - - def stream_unary(self, request_iterator, context): - for request in request_iterator: - self._request = request - with self._condition: - self._peer = context.protocol_context().peer() - self._invocation_metadata = context.invocation_metadata() - context.protocol_context().disable_next_response_compression() - self._serviced = True - self._condition.notify_all() - return _RESPONSE - - def stream_stream(self, request_iterator, context): - for request in request_iterator: - with self._condition: - self._peer = context.protocol_context().peer() - context.protocol_context().disable_next_response_compression() - yield _RESPONSE - with self._condition: - self._invocation_metadata = context.invocation_metadata() - self._serviced = True - self._condition.notify_all() - - def peer(self): - with self._condition: - return self._peer - - def block_until_serviced(self): - with self._condition: - while not self._serviced: - self._condition.wait() + def __init__(self): + self._condition = threading.Condition() + self._peer = None + self._serviced = False + + def unary_unary(self, request, context): + with self._condition: + self._request = request + self._peer = context.protocol_context().peer() + self._invocation_metadata = context.invocation_metadata() + context.protocol_context().disable_next_response_compression() + self._serviced = True + self._condition.notify_all() + return _RESPONSE + + def unary_stream(self, request, context): + with self._condition: + self._request = request + self._peer = context.protocol_context().peer() + self._invocation_metadata = context.invocation_metadata() + context.protocol_context().disable_next_response_compression() + self._serviced = True + self._condition.notify_all() + return + yield + + def stream_unary(self, request_iterator, context): + for request in request_iterator: + self._request = request + with self._condition: + self._peer = context.protocol_context().peer() + self._invocation_metadata = context.invocation_metadata() + context.protocol_context().disable_next_response_compression() + self._serviced = True + self._condition.notify_all() + return _RESPONSE + + def stream_stream(self, request_iterator, context): + for request in request_iterator: + with self._condition: + self._peer = context.protocol_context().peer() + context.protocol_context().disable_next_response_compression() + yield _RESPONSE + with self._condition: + self._invocation_metadata = context.invocation_metadata() + self._serviced = True + self._condition.notify_all() + + def peer(self): + with self._condition: + return self._peer + + def block_until_serviced(self): + with self._condition: + while not self._serviced: + self._condition.wait() class _BlockingIterator(object): - def __init__(self, upstream): - self._condition = threading.Condition() - self._upstream = upstream - self._allowed = [] + def __init__(self, upstream): + self._condition = threading.Condition() + self._upstream = upstream + self._allowed = [] - def __iter__(self): - return self + def __iter__(self): + return self - def __next__(self): - return self.next() + def __next__(self): + return self.next() - def next(self): - with self._condition: - while True: - if self._allowed is None: - raise StopIteration() - elif self._allowed: - return self._allowed.pop(0) - else: - self._condition.wait() + def next(self): + with self._condition: + while True: + if self._allowed is None: + raise StopIteration() + elif self._allowed: + return self._allowed.pop(0) + else: + self._condition.wait() - def allow(self): - with self._condition: - try: - self._allowed.append(next(self._upstream)) - except StopIteration: - self._allowed = None - self._condition.notify_all() + def allow(self): + with self._condition: + try: + self._allowed.append(next(self._upstream)) + except StopIteration: + self._allowed = None + self._condition.notify_all() def _metadata_plugin(context, callback): - callback([(_PER_RPC_CREDENTIALS_METADATA_KEY, - _PER_RPC_CREDENTIALS_METADATA_VALUE)], None) + callback([(_PER_RPC_CREDENTIALS_METADATA_KEY, + _PER_RPC_CREDENTIALS_METADATA_VALUE)], None) class BetaFeaturesTest(unittest.TestCase): - def setUp(self): - self._servicer = _Servicer() - method_implementations = { - (_GROUP, _UNARY_UNARY): + def setUp(self): + self._servicer = _Servicer() + method_implementations = { + (_GROUP, _UNARY_UNARY): utilities.unary_unary_inline(self._servicer.unary_unary), - (_GROUP, _UNARY_STREAM): + (_GROUP, _UNARY_STREAM): utilities.unary_stream_inline(self._servicer.unary_stream), - (_GROUP, _STREAM_UNARY): + (_GROUP, _STREAM_UNARY): utilities.stream_unary_inline(self._servicer.stream_unary), - (_GROUP, _STREAM_STREAM): + (_GROUP, _STREAM_STREAM): utilities.stream_stream_inline(self._servicer.stream_stream), - } - - cardinalities = { - _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, - _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, - _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, - _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, - } - - server_options = implementations.server_options( - thread_pool_size=test_constants.POOL_SIZE) - self._server = implementations.server( - method_implementations, options=server_options) - server_credentials = implementations.ssl_server_credentials( - [(resources.private_key(), resources.certificate_chain(),),]) - port = self._server.add_secure_port('[::]:0', server_credentials) - self._server.start() - self._channel_credentials = implementations.ssl_channel_credentials( - resources.test_root_certificates()) - self._call_credentials = implementations.metadata_call_credentials( - _metadata_plugin) - channel = test_utilities.not_really_secure_channel( - 'localhost', port, self._channel_credentials, _SERVER_HOST_OVERRIDE) - stub_options = implementations.stub_options( - thread_pool_size=test_constants.POOL_SIZE) - self._dynamic_stub = implementations.dynamic_stub( - channel, _GROUP, cardinalities, options=stub_options) - - def tearDown(self): - self._dynamic_stub = None - self._server.stop(test_constants.SHORT_TIMEOUT).wait() - - def test_unary_unary(self): - call_options = interfaces.grpc_call_options( - disable_compression=True, credentials=self._call_credentials) - response = getattr(self._dynamic_stub, _UNARY_UNARY)( - _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) - self.assertEqual(_RESPONSE, response) - self.assertIsNotNone(self._servicer.peer()) - invocation_metadata = [(metadatum.key, metadatum.value) for metadatum in - self._servicer._invocation_metadata] - self.assertIn( - (_PER_RPC_CREDENTIALS_METADATA_KEY, - _PER_RPC_CREDENTIALS_METADATA_VALUE), - invocation_metadata) - - def test_unary_stream(self): - call_options = interfaces.grpc_call_options( - disable_compression=True, credentials=self._call_credentials) - response_iterator = getattr(self._dynamic_stub, _UNARY_STREAM)( - _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) - self._servicer.block_until_serviced() - self.assertIsNotNone(self._servicer.peer()) - invocation_metadata = [(metadatum.key, metadatum.value) for metadatum in - self._servicer._invocation_metadata] - self.assertIn( - (_PER_RPC_CREDENTIALS_METADATA_KEY, - _PER_RPC_CREDENTIALS_METADATA_VALUE), - invocation_metadata) - - def test_stream_unary(self): - call_options = interfaces.grpc_call_options( - credentials=self._call_credentials) - request_iterator = _BlockingIterator(iter((_REQUEST,))) - response_future = getattr(self._dynamic_stub, _STREAM_UNARY).future( - request_iterator, test_constants.LONG_TIMEOUT, - protocol_options=call_options) - response_future.protocol_context().disable_next_request_compression() - request_iterator.allow() - response_future.protocol_context().disable_next_request_compression() - request_iterator.allow() - self._servicer.block_until_serviced() - self.assertIsNotNone(self._servicer.peer()) - self.assertEqual(_RESPONSE, response_future.result()) - invocation_metadata = [(metadatum.key, metadatum.value) for metadatum in - self._servicer._invocation_metadata] - self.assertIn( - (_PER_RPC_CREDENTIALS_METADATA_KEY, - _PER_RPC_CREDENTIALS_METADATA_VALUE), - invocation_metadata) - - def test_stream_stream(self): - call_options = interfaces.grpc_call_options( - credentials=self._call_credentials) - request_iterator = _BlockingIterator(iter((_REQUEST,))) - response_iterator = getattr(self._dynamic_stub, _STREAM_STREAM)( - request_iterator, test_constants.SHORT_TIMEOUT, - protocol_options=call_options) - response_iterator.protocol_context().disable_next_request_compression() - request_iterator.allow() - response = next(response_iterator) - response_iterator.protocol_context().disable_next_request_compression() - request_iterator.allow() - self._servicer.block_until_serviced() - self.assertIsNotNone(self._servicer.peer()) - self.assertEqual(_RESPONSE, response) - invocation_metadata = [(metadatum.key, metadatum.value) for metadatum in - self._servicer._invocation_metadata] - self.assertIn( - (_PER_RPC_CREDENTIALS_METADATA_KEY, - _PER_RPC_CREDENTIALS_METADATA_VALUE), - invocation_metadata) + } + + cardinalities = { + _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, + _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, + _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, + _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, + } + + server_options = implementations.server_options( + thread_pool_size=test_constants.POOL_SIZE) + self._server = implementations.server( + method_implementations, options=server_options) + server_credentials = implementations.ssl_server_credentials([( + resources.private_key(), + resources.certificate_chain(),),]) + port = self._server.add_secure_port('[::]:0', server_credentials) + self._server.start() + self._channel_credentials = implementations.ssl_channel_credentials( + resources.test_root_certificates()) + self._call_credentials = implementations.metadata_call_credentials( + _metadata_plugin) + channel = test_utilities.not_really_secure_channel( + 'localhost', port, self._channel_credentials, _SERVER_HOST_OVERRIDE) + stub_options = implementations.stub_options( + thread_pool_size=test_constants.POOL_SIZE) + self._dynamic_stub = implementations.dynamic_stub( + channel, _GROUP, cardinalities, options=stub_options) + + def tearDown(self): + self._dynamic_stub = None + self._server.stop(test_constants.SHORT_TIMEOUT).wait() + + def test_unary_unary(self): + call_options = interfaces.grpc_call_options( + disable_compression=True, credentials=self._call_credentials) + response = getattr(self._dynamic_stub, _UNARY_UNARY)( + _REQUEST, + test_constants.LONG_TIMEOUT, + protocol_options=call_options) + self.assertEqual(_RESPONSE, response) + self.assertIsNotNone(self._servicer.peer()) + invocation_metadata = [ + (metadatum.key, metadatum.value) + for metadatum in self._servicer._invocation_metadata + ] + self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, + _PER_RPC_CREDENTIALS_METADATA_VALUE), + invocation_metadata) + + def test_unary_stream(self): + call_options = interfaces.grpc_call_options( + disable_compression=True, credentials=self._call_credentials) + response_iterator = getattr(self._dynamic_stub, _UNARY_STREAM)( + _REQUEST, + test_constants.LONG_TIMEOUT, + protocol_options=call_options) + self._servicer.block_until_serviced() + self.assertIsNotNone(self._servicer.peer()) + invocation_metadata = [ + (metadatum.key, metadatum.value) + for metadatum in self._servicer._invocation_metadata + ] + self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, + _PER_RPC_CREDENTIALS_METADATA_VALUE), + invocation_metadata) + + def test_stream_unary(self): + call_options = interfaces.grpc_call_options( + credentials=self._call_credentials) + request_iterator = _BlockingIterator(iter((_REQUEST,))) + response_future = getattr(self._dynamic_stub, _STREAM_UNARY).future( + request_iterator, + test_constants.LONG_TIMEOUT, + protocol_options=call_options) + response_future.protocol_context().disable_next_request_compression() + request_iterator.allow() + response_future.protocol_context().disable_next_request_compression() + request_iterator.allow() + self._servicer.block_until_serviced() + self.assertIsNotNone(self._servicer.peer()) + self.assertEqual(_RESPONSE, response_future.result()) + invocation_metadata = [ + (metadatum.key, metadatum.value) + for metadatum in self._servicer._invocation_metadata + ] + self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, + _PER_RPC_CREDENTIALS_METADATA_VALUE), + invocation_metadata) + + def test_stream_stream(self): + call_options = interfaces.grpc_call_options( + credentials=self._call_credentials) + request_iterator = _BlockingIterator(iter((_REQUEST,))) + response_iterator = getattr(self._dynamic_stub, _STREAM_STREAM)( + request_iterator, + test_constants.SHORT_TIMEOUT, + protocol_options=call_options) + response_iterator.protocol_context().disable_next_request_compression() + request_iterator.allow() + response = next(response_iterator) + response_iterator.protocol_context().disable_next_request_compression() + request_iterator.allow() + self._servicer.block_until_serviced() + self.assertIsNotNone(self._servicer.peer()) + self.assertEqual(_RESPONSE, response) + invocation_metadata = [ + (metadatum.key, metadatum.value) + for metadatum in self._servicer._invocation_metadata + ] + self.assertIn((_PER_RPC_CREDENTIALS_METADATA_KEY, + _PER_RPC_CREDENTIALS_METADATA_VALUE), + invocation_metadata) class ContextManagementAndLifecycleTest(unittest.TestCase): - def setUp(self): - self._servicer = _Servicer() - self._method_implementations = { - (_GROUP, _UNARY_UNARY): + def setUp(self): + self._servicer = _Servicer() + self._method_implementations = { + (_GROUP, _UNARY_UNARY): utilities.unary_unary_inline(self._servicer.unary_unary), - (_GROUP, _UNARY_STREAM): + (_GROUP, _UNARY_STREAM): utilities.unary_stream_inline(self._servicer.unary_stream), - (_GROUP, _STREAM_UNARY): + (_GROUP, _STREAM_UNARY): utilities.stream_unary_inline(self._servicer.stream_unary), - (_GROUP, _STREAM_STREAM): + (_GROUP, _STREAM_STREAM): utilities.stream_stream_inline(self._servicer.stream_stream), - } - - self._cardinalities = { - _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, - _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, - _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, - _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, - } - - self._server_options = implementations.server_options( - thread_pool_size=test_constants.POOL_SIZE) - self._server_credentials = implementations.ssl_server_credentials( - [(resources.private_key(), resources.certificate_chain(),),]) - self._channel_credentials = implementations.ssl_channel_credentials( - resources.test_root_certificates()) - self._stub_options = implementations.stub_options( - thread_pool_size=test_constants.POOL_SIZE) - - def test_stub_context(self): - server = implementations.server( - self._method_implementations, options=self._server_options) - port = server.add_secure_port('[::]:0', self._server_credentials) - server.start() - - channel = test_utilities.not_really_secure_channel( - 'localhost', port, self._channel_credentials, _SERVER_HOST_OVERRIDE) - dynamic_stub = implementations.dynamic_stub( - channel, _GROUP, self._cardinalities, options=self._stub_options) - for _ in range(100): - with dynamic_stub: - pass - for _ in range(10): - with dynamic_stub: - call_options = interfaces.grpc_call_options( - disable_compression=True) - response = getattr(dynamic_stub, _UNARY_UNARY)( - _REQUEST, test_constants.LONG_TIMEOUT, - protocol_options=call_options) - self.assertEqual(_RESPONSE, response) - self.assertIsNotNone(self._servicer.peer()) - - server.stop(test_constants.SHORT_TIMEOUT).wait() - - def test_server_lifecycle(self): - for _ in range(100): - server = implementations.server( - self._method_implementations, options=self._server_options) - port = server.add_secure_port('[::]:0', self._server_credentials) - server.start() - server.stop(test_constants.SHORT_TIMEOUT).wait() - for _ in range(100): - server = implementations.server( - self._method_implementations, options=self._server_options) - server.add_secure_port('[::]:0', self._server_credentials) - server.add_insecure_port('[::]:0') - with server: - server.stop(test_constants.SHORT_TIMEOUT) - server.stop(test_constants.SHORT_TIMEOUT) + } + + self._cardinalities = { + _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, + _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, + _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, + _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, + } + + self._server_options = implementations.server_options( + thread_pool_size=test_constants.POOL_SIZE) + self._server_credentials = implementations.ssl_server_credentials([( + resources.private_key(), + resources.certificate_chain(),),]) + self._channel_credentials = implementations.ssl_channel_credentials( + resources.test_root_certificates()) + self._stub_options = implementations.stub_options( + thread_pool_size=test_constants.POOL_SIZE) + + def test_stub_context(self): + server = implementations.server( + self._method_implementations, options=self._server_options) + port = server.add_secure_port('[::]:0', self._server_credentials) + server.start() + + channel = test_utilities.not_really_secure_channel( + 'localhost', port, self._channel_credentials, _SERVER_HOST_OVERRIDE) + dynamic_stub = implementations.dynamic_stub( + channel, _GROUP, self._cardinalities, options=self._stub_options) + for _ in range(100): + with dynamic_stub: + pass + for _ in range(10): + with dynamic_stub: + call_options = interfaces.grpc_call_options( + disable_compression=True) + response = getattr(dynamic_stub, _UNARY_UNARY)( + _REQUEST, + test_constants.LONG_TIMEOUT, + protocol_options=call_options) + self.assertEqual(_RESPONSE, response) + self.assertIsNotNone(self._servicer.peer()) + + server.stop(test_constants.SHORT_TIMEOUT).wait() + + def test_server_lifecycle(self): + for _ in range(100): + server = implementations.server( + self._method_implementations, options=self._server_options) + port = server.add_secure_port('[::]:0', self._server_credentials) + server.start() + server.stop(test_constants.SHORT_TIMEOUT).wait() + for _ in range(100): + server = implementations.server( + self._method_implementations, options=self._server_options) + server.add_secure_port('[::]:0', self._server_credentials) + server.add_insecure_port('[::]:0') + with server: + server.stop(test_constants.SHORT_TIMEOUT) + server.stop(test_constants.SHORT_TIMEOUT) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/beta/_connectivity_channel_test.py b/src/python/grpcio_tests/tests/unit/beta/_connectivity_channel_test.py index 5d826a269db..49d683b8a6c 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_connectivity_channel_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_connectivity_channel_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of grpc.beta._connectivity_channel.""" import unittest @@ -36,13 +35,13 @@ from grpc.beta import interfaces class ConnectivityStatesTest(unittest.TestCase): - def testBetaConnectivityStates(self): - self.assertIsNotNone(interfaces.ChannelConnectivity.IDLE) - self.assertIsNotNone(interfaces.ChannelConnectivity.CONNECTING) - self.assertIsNotNone(interfaces.ChannelConnectivity.READY) - self.assertIsNotNone(interfaces.ChannelConnectivity.TRANSIENT_FAILURE) - self.assertIsNotNone(interfaces.ChannelConnectivity.FATAL_FAILURE) + def testBetaConnectivityStates(self): + self.assertIsNotNone(interfaces.ChannelConnectivity.IDLE) + self.assertIsNotNone(interfaces.ChannelConnectivity.CONNECTING) + self.assertIsNotNone(interfaces.ChannelConnectivity.READY) + self.assertIsNotNone(interfaces.ChannelConnectivity.TRANSIENT_FAILURE) + self.assertIsNotNone(interfaces.ChannelConnectivity.FATAL_FAILURE) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/beta/_face_interface_test.py b/src/python/grpcio_tests/tests/unit/beta/_face_interface_test.py index 3a67516906d..f4214426241 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_face_interface_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_face_interface_test.py @@ -26,7 +26,6 @@ # 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. - """Tests Face interface compliance of the gRPC Python Beta API.""" import collections @@ -47,94 +46,97 @@ _SERVER_HOST_OVERRIDE = 'foo.test.google.fr' class _SerializationBehaviors( - collections.namedtuple( - '_SerializationBehaviors', - ('request_serializers', 'request_deserializers', 'response_serializers', - 'response_deserializers',))): - pass + collections.namedtuple('_SerializationBehaviors', ( + 'request_serializers', + 'request_deserializers', + 'response_serializers', + 'response_deserializers',))): + pass def _serialization_behaviors_from_test_methods(test_methods): - request_serializers = {} - request_deserializers = {} - response_serializers = {} - response_deserializers = {} - for (group, method), test_method in six.iteritems(test_methods): - request_serializers[group, method] = test_method.serialize_request - request_deserializers[group, method] = test_method.deserialize_request - response_serializers[group, method] = test_method.serialize_response - response_deserializers[group, method] = test_method.deserialize_response - return _SerializationBehaviors( - request_serializers, request_deserializers, response_serializers, - response_deserializers) + request_serializers = {} + request_deserializers = {} + response_serializers = {} + response_deserializers = {} + for (group, method), test_method in six.iteritems(test_methods): + request_serializers[group, method] = test_method.serialize_request + request_deserializers[group, method] = test_method.deserialize_request + response_serializers[group, method] = test_method.serialize_response + response_deserializers[group, method] = test_method.deserialize_response + return _SerializationBehaviors(request_serializers, request_deserializers, + response_serializers, response_deserializers) class _Implementation(test_interfaces.Implementation): - def instantiate( - self, methods, method_implementations, multi_method_implementation): - serialization_behaviors = _serialization_behaviors_from_test_methods( - methods) - # TODO(nathaniel): Add a "groups" attribute to _digest.TestServiceDigest. - service = next(iter(methods))[0] - # TODO(nathaniel): Add a "cardinalities_by_group" attribute to - # _digest.TestServiceDigest. - cardinalities = { - method: method_object.cardinality() - for (group, method), method_object in six.iteritems(methods)} - - server_options = implementations.server_options( - request_deserializers=serialization_behaviors.request_deserializers, - response_serializers=serialization_behaviors.response_serializers, - thread_pool_size=test_constants.POOL_SIZE) - server = implementations.server( - method_implementations, options=server_options) - server_credentials = implementations.ssl_server_credentials( - [(resources.private_key(), resources.certificate_chain(),),]) - port = server.add_secure_port('[::]:0', server_credentials) - server.start() - channel_credentials = implementations.ssl_channel_credentials( - resources.test_root_certificates()) - channel = test_utilities.not_really_secure_channel( - 'localhost', port, channel_credentials, _SERVER_HOST_OVERRIDE) - stub_options = implementations.stub_options( - request_serializers=serialization_behaviors.request_serializers, - response_deserializers=serialization_behaviors.response_deserializers, - thread_pool_size=test_constants.POOL_SIZE) - generic_stub = implementations.generic_stub(channel, options=stub_options) - dynamic_stub = implementations.dynamic_stub( - channel, service, cardinalities, options=stub_options) - return generic_stub, {service: dynamic_stub}, server - - def destantiate(self, memo): - memo.stop(test_constants.SHORT_TIMEOUT).wait() - - def invocation_metadata(self): - return grpc_test_common.INVOCATION_INITIAL_METADATA - - def initial_metadata(self): - return grpc_test_common.SERVICE_INITIAL_METADATA - - def terminal_metadata(self): - return grpc_test_common.SERVICE_TERMINAL_METADATA - - def code(self): - return interfaces.StatusCode.OK - - def details(self): - return grpc_test_common.DETAILS - - def metadata_transmitted(self, original_metadata, transmitted_metadata): - return original_metadata is None or grpc_test_common.metadata_transmitted( - original_metadata, transmitted_metadata) + def instantiate(self, methods, method_implementations, + multi_method_implementation): + serialization_behaviors = _serialization_behaviors_from_test_methods( + methods) + # TODO(nathaniel): Add a "groups" attribute to _digest.TestServiceDigest. + service = next(iter(methods))[0] + # TODO(nathaniel): Add a "cardinalities_by_group" attribute to + # _digest.TestServiceDigest. + cardinalities = { + method: method_object.cardinality() + for (group, method), method_object in six.iteritems(methods) + } + + server_options = implementations.server_options( + request_deserializers=serialization_behaviors.request_deserializers, + response_serializers=serialization_behaviors.response_serializers, + thread_pool_size=test_constants.POOL_SIZE) + server = implementations.server( + method_implementations, options=server_options) + server_credentials = implementations.ssl_server_credentials([( + resources.private_key(), + resources.certificate_chain(),),]) + port = server.add_secure_port('[::]:0', server_credentials) + server.start() + channel_credentials = implementations.ssl_channel_credentials( + resources.test_root_certificates()) + channel = test_utilities.not_really_secure_channel( + 'localhost', port, channel_credentials, _SERVER_HOST_OVERRIDE) + stub_options = implementations.stub_options( + request_serializers=serialization_behaviors.request_serializers, + response_deserializers=serialization_behaviors. + response_deserializers, + thread_pool_size=test_constants.POOL_SIZE) + generic_stub = implementations.generic_stub( + channel, options=stub_options) + dynamic_stub = implementations.dynamic_stub( + channel, service, cardinalities, options=stub_options) + return generic_stub, {service: dynamic_stub}, server + + def destantiate(self, memo): + memo.stop(test_constants.SHORT_TIMEOUT).wait() + + def invocation_metadata(self): + return grpc_test_common.INVOCATION_INITIAL_METADATA + + def initial_metadata(self): + return grpc_test_common.SERVICE_INITIAL_METADATA + + def terminal_metadata(self): + return grpc_test_common.SERVICE_TERMINAL_METADATA + + def code(self): + return interfaces.StatusCode.OK + + def details(self): + return grpc_test_common.DETAILS + + def metadata_transmitted(self, original_metadata, transmitted_metadata): + return original_metadata is None or grpc_test_common.metadata_transmitted( + original_metadata, transmitted_metadata) def load_tests(loader, tests, pattern): - return unittest.TestSuite( - tests=tuple( - loader.loadTestsFromTestCase(test_case_class) - for test_case_class in test_cases.test_cases(_Implementation()))) + return unittest.TestSuite(tests=tuple( + loader.loadTestsFromTestCase(test_case_class) + for test_case_class in test_cases.test_cases(_Implementation()))) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/beta/_implementations_test.py b/src/python/grpcio_tests/tests/unit/beta/_implementations_test.py index 127f93e9bb5..69bb5cc2a53 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_implementations_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_implementations_test.py @@ -26,7 +26,6 @@ # 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. - """Tests the implementations module of the gRPC Python Beta API.""" import datetime @@ -40,31 +39,32 @@ from tests.unit import resources class ChannelCredentialsTest(unittest.TestCase): - def test_runtime_provided_root_certificates(self): - channel_credentials = implementations.ssl_channel_credentials() - self.assertIsInstance( - channel_credentials, implementations.ChannelCredentials) - - def test_application_provided_root_certificates(self): - channel_credentials = implementations.ssl_channel_credentials( - resources.test_root_certificates()) - self.assertIsInstance( - channel_credentials, implementations.ChannelCredentials) + def test_runtime_provided_root_certificates(self): + channel_credentials = implementations.ssl_channel_credentials() + self.assertIsInstance(channel_credentials, + implementations.ChannelCredentials) + + def test_application_provided_root_certificates(self): + channel_credentials = implementations.ssl_channel_credentials( + resources.test_root_certificates()) + self.assertIsInstance(channel_credentials, + implementations.ChannelCredentials) class CallCredentialsTest(unittest.TestCase): - def test_google_call_credentials(self): - creds = oauth2client_client.GoogleCredentials( - 'token', 'client_id', 'secret', 'refresh_token', - datetime.datetime(2008, 6, 24), 'https://refresh.uri.com/', - 'user_agent') - call_creds = implementations.google_call_credentials(creds) - self.assertIsInstance(call_creds, implementations.CallCredentials) + def test_google_call_credentials(self): + creds = oauth2client_client.GoogleCredentials( + 'token', 'client_id', 'secret', 'refresh_token', + datetime.datetime(2008, 6, 24), 'https://refresh.uri.com/', + 'user_agent') + call_creds = implementations.google_call_credentials(creds) + self.assertIsInstance(call_creds, implementations.CallCredentials) + + def test_access_token_call_credentials(self): + call_creds = implementations.access_token_call_credentials('token') + self.assertIsInstance(call_creds, implementations.CallCredentials) - def test_access_token_call_credentials(self): - call_creds = implementations.access_token_call_credentials('token') - self.assertIsInstance(call_creds, implementations.CallCredentials) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py b/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py index 37b8c49120f..664e47c7696 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of RPC-method-not-found behavior.""" import unittest @@ -39,37 +38,38 @@ from tests.unit.framework.common import test_constants class NotFoundTest(unittest.TestCase): - def setUp(self): - self._server = implementations.server({}) - port = self._server.add_insecure_port('[::]:0') - channel = implementations.insecure_channel('localhost', port) - self._generic_stub = implementations.generic_stub(channel) - self._server.start() + def setUp(self): + self._server = implementations.server({}) + port = self._server.add_insecure_port('[::]:0') + channel = implementations.insecure_channel('localhost', port) + self._generic_stub = implementations.generic_stub(channel) + self._server.start() - def tearDown(self): - self._server.stop(0).wait() - self._generic_stub = None + def tearDown(self): + self._server.stop(0).wait() + self._generic_stub = None - def test_blocking_unary_unary_not_found(self): - with self.assertRaises(face.LocalError) as exception_assertion_context: - self._generic_stub.blocking_unary_unary( - 'groop', 'meffod', b'abc', test_constants.LONG_TIMEOUT, - with_call=True) - self.assertIs( - exception_assertion_context.exception.code, - interfaces.StatusCode.UNIMPLEMENTED) + def test_blocking_unary_unary_not_found(self): + with self.assertRaises(face.LocalError) as exception_assertion_context: + self._generic_stub.blocking_unary_unary( + 'groop', + 'meffod', + b'abc', + test_constants.LONG_TIMEOUT, + with_call=True) + self.assertIs(exception_assertion_context.exception.code, + interfaces.StatusCode.UNIMPLEMENTED) - def test_future_stream_unary_not_found(self): - rpc_future = self._generic_stub.future_stream_unary( - 'grupe', 'mevvod', [b'def'], test_constants.LONG_TIMEOUT) - with self.assertRaises(face.LocalError) as exception_assertion_context: - rpc_future.result() - self.assertIs( - exception_assertion_context.exception.code, - interfaces.StatusCode.UNIMPLEMENTED) - self.assertIs( - rpc_future.exception().code, interfaces.StatusCode.UNIMPLEMENTED) + def test_future_stream_unary_not_found(self): + rpc_future = self._generic_stub.future_stream_unary( + 'grupe', 'mevvod', [b'def'], test_constants.LONG_TIMEOUT) + with self.assertRaises(face.LocalError) as exception_assertion_context: + rpc_future.result() + self.assertIs(exception_assertion_context.exception.code, + interfaces.StatusCode.UNIMPLEMENTED) + self.assertIs(rpc_future.exception().code, + interfaces.StatusCode.UNIMPLEMENTED) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/beta/_utilities_test.py b/src/python/grpcio_tests/tests/unit/beta/_utilities_test.py index 9cce96cc85c..e8e62c322a7 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_utilities_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_utilities_test.py @@ -26,7 +26,6 @@ # 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. - """Tests of grpc.beta.utilities.""" import threading @@ -41,68 +40,68 @@ from tests.unit.framework.common import test_constants class _Callback(object): - def __init__(self): - self._condition = threading.Condition() - self._value = None + def __init__(self): + self._condition = threading.Condition() + self._value = None - def accept_value(self, value): - with self._condition: - self._value = value - self._condition.notify_all() + def accept_value(self, value): + with self._condition: + self._value = value + self._condition.notify_all() - def block_until_called(self): - with self._condition: - while self._value is None: - self._condition.wait() - return self._value + def block_until_called(self): + with self._condition: + while self._value is None: + self._condition.wait() + return self._value class ChannelConnectivityTest(unittest.TestCase): - def test_lonely_channel_connectivity(self): - channel = implementations.insecure_channel('localhost', 12345) - callback = _Callback() - - ready_future = utilities.channel_ready_future(channel) - ready_future.add_done_callback(callback.accept_value) - with self.assertRaises(future.TimeoutError): - ready_future.result(timeout=test_constants.SHORT_TIMEOUT) - self.assertFalse(ready_future.cancelled()) - self.assertFalse(ready_future.done()) - self.assertTrue(ready_future.running()) - ready_future.cancel() - value_passed_to_callback = callback.block_until_called() - self.assertIs(ready_future, value_passed_to_callback) - self.assertTrue(ready_future.cancelled()) - self.assertTrue(ready_future.done()) - self.assertFalse(ready_future.running()) - - def test_immediately_connectable_channel_connectivity(self): - server = implementations.server({}) - port = server.add_insecure_port('[::]:0') - server.start() - channel = implementations.insecure_channel('localhost', port) - callback = _Callback() - - try: - ready_future = utilities.channel_ready_future(channel) - ready_future.add_done_callback(callback.accept_value) - self.assertIsNone( - ready_future.result(timeout=test_constants.LONG_TIMEOUT)) - value_passed_to_callback = callback.block_until_called() - self.assertIs(ready_future, value_passed_to_callback) - self.assertFalse(ready_future.cancelled()) - self.assertTrue(ready_future.done()) - self.assertFalse(ready_future.running()) - # Cancellation after maturity has no effect. - ready_future.cancel() - self.assertFalse(ready_future.cancelled()) - self.assertTrue(ready_future.done()) - self.assertFalse(ready_future.running()) - finally: - ready_future.cancel() - server.stop(0) + def test_lonely_channel_connectivity(self): + channel = implementations.insecure_channel('localhost', 12345) + callback = _Callback() + + ready_future = utilities.channel_ready_future(channel) + ready_future.add_done_callback(callback.accept_value) + with self.assertRaises(future.TimeoutError): + ready_future.result(timeout=test_constants.SHORT_TIMEOUT) + self.assertFalse(ready_future.cancelled()) + self.assertFalse(ready_future.done()) + self.assertTrue(ready_future.running()) + ready_future.cancel() + value_passed_to_callback = callback.block_until_called() + self.assertIs(ready_future, value_passed_to_callback) + self.assertTrue(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + + def test_immediately_connectable_channel_connectivity(self): + server = implementations.server({}) + port = server.add_insecure_port('[::]:0') + server.start() + channel = implementations.insecure_channel('localhost', port) + callback = _Callback() + + try: + ready_future = utilities.channel_ready_future(channel) + ready_future.add_done_callback(callback.accept_value) + self.assertIsNone( + ready_future.result(timeout=test_constants.LONG_TIMEOUT)) + value_passed_to_callback = callback.block_until_called() + self.assertIs(ready_future, value_passed_to_callback) + self.assertFalse(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + # Cancellation after maturity has no effect. + ready_future.cancel() + self.assertFalse(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + finally: + ready_future.cancel() + server.stop(0) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/beta/test_utilities.py b/src/python/grpcio_tests/tests/unit/beta/test_utilities.py index 692da9c97d7..f5424206837 100644 --- a/src/python/grpcio_tests/tests/unit/beta/test_utilities.py +++ b/src/python/grpcio_tests/tests/unit/beta/test_utilities.py @@ -26,16 +26,15 @@ # 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. - """Test-appropriate entry points into the gRPC Python Beta API.""" import grpc from grpc.beta import implementations -def not_really_secure_channel( - host, port, channel_credentials, server_host_override): - """Creates an insecure Channel to a remote host. +def not_really_secure_channel(host, port, channel_credentials, + server_host_override): + """Creates an insecure Channel to a remote host. Args: host: The name of the remote host to which to connect. @@ -48,8 +47,8 @@ def not_really_secure_channel( An implementations.Channel to the remote host through which RPCs may be conducted. """ - target = '%s:%d' % (host, port) - channel = grpc.secure_channel( - target, channel_credentials, - (('grpc.ssl_target_name_override', server_host_override,),)) - return implementations.Channel(channel) + target = '%s:%d' % (host, port) + channel = grpc.secure_channel(target, channel_credentials, (( + 'grpc.ssl_target_name_override', + server_host_override,),)) + return implementations.Channel(channel) diff --git a/src/python/grpcio_tests/tests/unit/framework/__init__.py b/src/python/grpcio_tests/tests/unit/framework/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/framework/__init__.py +++ b/src/python/grpcio_tests/tests/unit/framework/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/common/__init__.py b/src/python/grpcio_tests/tests/unit/framework/common/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/framework/common/__init__.py +++ b/src/python/grpcio_tests/tests/unit/framework/common/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/common/test_constants.py b/src/python/grpcio_tests/tests/unit/framework/common/test_constants.py index b6682d396c9..905483c08d7 100644 --- a/src/python/grpcio_tests/tests/unit/framework/common/test_constants.py +++ b/src/python/grpcio_tests/tests/unit/framework/common/test_constants.py @@ -26,7 +26,6 @@ # 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. - """Constants shared among tests throughout RPC Framework.""" # Value for maximum duration in seconds that a test is allowed for its actual diff --git a/src/python/grpcio_tests/tests/unit/framework/common/test_control.py b/src/python/grpcio_tests/tests/unit/framework/common/test_control.py index 088e2f8b885..af08731b1ee 100644 --- a/src/python/grpcio_tests/tests/unit/framework/common/test_control.py +++ b/src/python/grpcio_tests/tests/unit/framework/common/test_control.py @@ -26,7 +26,6 @@ # 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. - """Code for instructing systems under test to block or fail.""" import abc @@ -37,7 +36,7 @@ import six class Defect(Exception): - """Simulates a programming defect raised into in a system under test. + """Simulates a programming defect raised into in a system under test. Use of a standard exception type is too easily misconstrued as an actual defect in either the test infrastructure or the system under test. @@ -45,7 +44,7 @@ class Defect(Exception): class Control(six.with_metaclass(abc.ABCMeta)): - """An object that accepts program control from a system under test. + """An object that accepts program control from a system under test. Systems under test passed a Control should call its control() method frequently during execution. The control() method may block, raise an @@ -53,61 +52,61 @@ class Control(six.with_metaclass(abc.ABCMeta)): the system under test to simulate hanging, failing, or functioning. """ - @abc.abstractmethod - def control(self): - """Potentially does anything.""" - raise NotImplementedError() + @abc.abstractmethod + def control(self): + """Potentially does anything.""" + raise NotImplementedError() class PauseFailControl(Control): - """A Control that can be used to pause or fail code under control. + """A Control that can be used to pause or fail code under control. This object is only safe for use from two threads: one of the system under test calling control and the other from the test system calling pause, block_until_paused, and fail. """ - def __init__(self): - self._condition = threading.Condition() - self._pause = False - self._paused = False - self._fail = False - - def control(self): - with self._condition: - if self._fail: - raise Defect() - - while self._pause: - self._paused = True - self._condition.notify_all() - self._condition.wait() - self._paused = False - - @contextlib.contextmanager - def pause(self): - """Pauses code under control while controlling code is in context.""" - with self._condition: - self._pause = True - yield - with self._condition: - self._pause = False - self._condition.notify_all() - - def block_until_paused(self): - """Blocks controlling code until code under control is paused. + def __init__(self): + self._condition = threading.Condition() + self._pause = False + self._paused = False + self._fail = False + + def control(self): + with self._condition: + if self._fail: + raise Defect() + + while self._pause: + self._paused = True + self._condition.notify_all() + self._condition.wait() + self._paused = False + + @contextlib.contextmanager + def pause(self): + """Pauses code under control while controlling code is in context.""" + with self._condition: + self._pause = True + yield + with self._condition: + self._pause = False + self._condition.notify_all() + + def block_until_paused(self): + """Blocks controlling code until code under control is paused. May only be called within the context of a pause call. """ - with self._condition: - while not self._paused: - self._condition.wait() - - @contextlib.contextmanager - def fail(self): - """Fails code under control while controlling code is in context.""" - with self._condition: - self._fail = True - yield - with self._condition: - self._fail = False + with self._condition: + while not self._paused: + self._condition.wait() + + @contextlib.contextmanager + def fail(self): + """Fails code under control while controlling code is in context.""" + with self._condition: + self._fail = True + yield + with self._condition: + self._fail = False diff --git a/src/python/grpcio_tests/tests/unit/framework/common/test_coverage.py b/src/python/grpcio_tests/tests/unit/framework/common/test_coverage.py index ea2d2812ce6..13ceec31a01 100644 --- a/src/python/grpcio_tests/tests/unit/framework/common/test_coverage.py +++ b/src/python/grpcio_tests/tests/unit/framework/common/test_coverage.py @@ -26,7 +26,6 @@ # 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. - """Governs coverage for tests of RPCs throughout RPC Framework.""" import abc @@ -38,80 +37,80 @@ import six class Coverage(six.with_metaclass(abc.ABCMeta)): - """Specification of test coverage.""" + """Specification of test coverage.""" - @abc.abstractmethod - def testSuccessfulUnaryRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testSuccessfulUnaryRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testSuccessfulUnaryRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testSuccessfulUnaryRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testSuccessfulStreamRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testSuccessfulStreamRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testSuccessfulStreamRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testSuccessfulStreamRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testSequentialInvocations(self): - raise NotImplementedError() + @abc.abstractmethod + def testSequentialInvocations(self): + raise NotImplementedError() - @abc.abstractmethod - def testParallelInvocations(self): - raise NotImplementedError() + @abc.abstractmethod + def testParallelInvocations(self): + raise NotImplementedError() - @abc.abstractmethod - def testWaitingForSomeButNotAllParallelInvocations(self): - raise NotImplementedError() + @abc.abstractmethod + def testWaitingForSomeButNotAllParallelInvocations(self): + raise NotImplementedError() - @abc.abstractmethod - def testCancelledUnaryRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testCancelledUnaryRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testCancelledUnaryRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testCancelledUnaryRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testCancelledStreamRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testCancelledStreamRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testCancelledStreamRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testCancelledStreamRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testExpiredUnaryRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testExpiredUnaryRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testExpiredUnaryRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testExpiredUnaryRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testExpiredStreamRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testExpiredStreamRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testExpiredStreamRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testExpiredStreamRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testFailedUnaryRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testFailedUnaryRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testFailedUnaryRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testFailedUnaryRequestStreamResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testFailedStreamRequestUnaryResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testFailedStreamRequestUnaryResponse(self): + raise NotImplementedError() - @abc.abstractmethod - def testFailedStreamRequestStreamResponse(self): - raise NotImplementedError() + @abc.abstractmethod + def testFailedStreamRequestStreamResponse(self): + raise NotImplementedError() diff --git a/src/python/grpcio_tests/tests/unit/framework/foundation/__init__.py b/src/python/grpcio_tests/tests/unit/framework/foundation/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/framework/foundation/__init__.py +++ b/src/python/grpcio_tests/tests/unit/framework/foundation/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/foundation/_logging_pool_test.py b/src/python/grpcio_tests/tests/unit/framework/foundation/_logging_pool_test.py index 330e445d433..19e8cbdd8eb 100644 --- a/src/python/grpcio_tests/tests/unit/framework/foundation/_logging_pool_test.py +++ b/src/python/grpcio_tests/tests/unit/framework/foundation/_logging_pool_test.py @@ -26,7 +26,6 @@ # 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. - """Tests for grpc.framework.foundation.logging_pool.""" import threading @@ -39,50 +38,51 @@ _POOL_SIZE = 16 class _CallableObject(object): - def __init__(self): - self._lock = threading.Lock() - self._passed_values = [] + def __init__(self): + self._lock = threading.Lock() + self._passed_values = [] - def __call__(self, value): - with self._lock: - self._passed_values.append(value) + def __call__(self, value): + with self._lock: + self._passed_values.append(value) - def passed_values(self): - with self._lock: - return tuple(self._passed_values) + def passed_values(self): + with self._lock: + return tuple(self._passed_values) class LoggingPoolTest(unittest.TestCase): - def testUpAndDown(self): - pool = logging_pool.pool(_POOL_SIZE) - pool.shutdown(wait=True) + def testUpAndDown(self): + pool = logging_pool.pool(_POOL_SIZE) + pool.shutdown(wait=True) - with logging_pool.pool(_POOL_SIZE) as pool: - self.assertIsNotNone(pool) + with logging_pool.pool(_POOL_SIZE) as pool: + self.assertIsNotNone(pool) - def testTaskExecuted(self): - test_list = [] + def testTaskExecuted(self): + test_list = [] - with logging_pool.pool(_POOL_SIZE) as pool: - pool.submit(lambda: test_list.append(object())).result() + with logging_pool.pool(_POOL_SIZE) as pool: + pool.submit(lambda: test_list.append(object())).result() - self.assertTrue(test_list) + self.assertTrue(test_list) - def testException(self): - with logging_pool.pool(_POOL_SIZE) as pool: - raised_exception = pool.submit(lambda: 1/0).exception() + def testException(self): + with logging_pool.pool(_POOL_SIZE) as pool: + raised_exception = pool.submit(lambda: 1 / 0).exception() - self.assertIsNotNone(raised_exception) + self.assertIsNotNone(raised_exception) - def testCallableObjectExecuted(self): - callable_object = _CallableObject() - passed_object = object() - with logging_pool.pool(_POOL_SIZE) as pool: - future = pool.submit(callable_object, passed_object) - self.assertIsNone(future.result()) - self.assertSequenceEqual((passed_object,), callable_object.passed_values()) + def testCallableObjectExecuted(self): + callable_object = _CallableObject() + passed_object = object() + with logging_pool.pool(_POOL_SIZE) as pool: + future = pool.submit(callable_object, passed_object) + self.assertIsNone(future.result()) + self.assertSequenceEqual((passed_object,), + callable_object.passed_values()) if __name__ == '__main__': - unittest.main(verbosity=2) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/unit/framework/foundation/stream_testing.py b/src/python/grpcio_tests/tests/unit/framework/foundation/stream_testing.py index 098a53d5e75..2929e4dd786 100644 --- a/src/python/grpcio_tests/tests/unit/framework/foundation/stream_testing.py +++ b/src/python/grpcio_tests/tests/unit/framework/foundation/stream_testing.py @@ -26,48 +26,47 @@ # 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. - """Utilities for testing stream-related code.""" from grpc.framework.foundation import stream class TestConsumer(stream.Consumer): - """A stream.Consumer instrumented for testing. + """A stream.Consumer instrumented for testing. Attributes: calls: A sequence of value-termination pairs describing the history of calls made on this object. """ - def __init__(self): - self.calls = [] + def __init__(self): + self.calls = [] - def consume(self, value): - """See stream.Consumer.consume for specification.""" - self.calls.append((value, False)) + def consume(self, value): + """See stream.Consumer.consume for specification.""" + self.calls.append((value, False)) - def terminate(self): - """See stream.Consumer.terminate for specification.""" - self.calls.append((None, True)) + def terminate(self): + """See stream.Consumer.terminate for specification.""" + self.calls.append((None, True)) - def consume_and_terminate(self, value): - """See stream.Consumer.consume_and_terminate for specification.""" - self.calls.append((value, True)) + def consume_and_terminate(self, value): + """See stream.Consumer.consume_and_terminate for specification.""" + self.calls.append((value, True)) - def is_legal(self): - """Reports whether or not a legal sequence of calls has been made.""" - terminated = False - for value, terminal in self.calls: - if terminated: - return False - elif terminal: - terminated = True - elif value is None: - return False - else: # pylint: disable=useless-else-on-loop - return True + def is_legal(self): + """Reports whether or not a legal sequence of calls has been made.""" + terminated = False + for value, terminal in self.calls: + if terminated: + return False + elif terminal: + terminated = True + elif value is None: + return False + else: # pylint: disable=useless-else-on-loop + return True - def values(self): - """Returns the sequence of values that have been passed to this Consumer.""" - return [value for value, _ in self.calls if value] + def values(self): + """Returns the sequence of values that have been passed to this Consumer.""" + return [value for value, _ in self.calls if value] diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/__init__.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/__init__.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_3069_test_constant.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_3069_test_constant.py index 1ea356c0bf2..2aec25c9eff 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_3069_test_constant.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_3069_test_constant.py @@ -26,7 +26,6 @@ # 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. - """A test constant working around issue 3069.""" # test_constants is referenced from specification in this module. diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/__init__.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/__init__.py index 70865191060..b89398809fa 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/__init__.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/__init__.py @@ -26,5 +26,3 @@ # 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. - - diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py index e338aaa396d..a79834f96ff 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_blocking_invocation_inline_service.py @@ -26,7 +26,6 @@ # 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. - """Test code for the Face layer of RPC Framework.""" from __future__ import division @@ -50,246 +49,254 @@ from tests.unit.framework.interfaces.face import _stock_service from tests.unit.framework.interfaces.face import test_interfaces # pylint: disable=unused-import -class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.TestCase)): - """A test of the Face layer of RPC Framework. +class TestCase( + six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, + unittest.TestCase)): + """A test of the Face layer of RPC Framework. Concrete subclasses must have an "implementation" attribute of type test_interfaces.Implementation and an "invoker_constructor" attribute of type _invocation.InvokerConstructor. """ - NAME = 'BlockingInvocationInlineServiceTest' + NAME = 'BlockingInvocationInlineServiceTest' - def setUp(self): - """See unittest.TestCase.setUp for full specification. + def setUp(self): + """See unittest.TestCase.setUp for full specification. Overriding implementations must call this implementation. """ - self._control = test_control.PauseFailControl() - self._digest = _digest.digest( - _stock_service.STOCK_TEST_SERVICE, self._control, None) + self._control = test_control.PauseFailControl() + self._digest = _digest.digest(_stock_service.STOCK_TEST_SERVICE, + self._control, None) - generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate( - self._digest.methods, self._digest.inline_method_implementations, None) - self._invoker = self.invoker_constructor.construct_invoker( - generic_stub, dynamic_stubs, self._digest.methods) + generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate( + self._digest.methods, self._digest.inline_method_implementations, + None) + self._invoker = self.invoker_constructor.construct_invoker( + generic_stub, dynamic_stubs, self._digest.methods) - def tearDown(self): - """See unittest.TestCase.tearDown for full specification. + def tearDown(self): + """See unittest.TestCase.tearDown for full specification. Overriding implementations must call this implementation. """ - self._invoker = None - self.implementation.destantiate(self._memo) - - def testSuccessfulUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response, call = self._invoker.blocking(group, method)( - request, test_constants.LONG_TIMEOUT, with_call=True) - - test_messages.verify(request, response, self) - - def testSuccessfulUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response_iterator = self._invoker.blocking(group, method)( - request, test_constants.LONG_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(request, responses, self) - - def testSuccessfulStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - response, call = self._invoker.blocking(group, method)( - iter(requests), test_constants.LONG_TIMEOUT, with_call=True) - - test_messages.verify(requests, response, self) - - def testSuccessfulStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - response_iterator = self._invoker.blocking(group, method)( - iter(requests), test_constants.LONG_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(requests, responses, self) - - def testSequentialInvocations(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - - first_response = self._invoker.blocking(group, method)( - first_request, test_constants.LONG_TIMEOUT) - - test_messages.verify(first_request, first_response, self) - - second_response = self._invoker.blocking(group, method)( - second_request, test_constants.LONG_TIMEOUT) - - test_messages.verify(second_request, second_response, self) - - def testParallelInvocations(self): - pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = [] - response_futures = [] - for _ in range(test_constants.THREAD_CONCURRENCY): - request = test_messages.request() - response_future = pool.submit( - self._invoker.blocking(group, method), request, - test_constants.LONG_TIMEOUT) - requests.append(request) - response_futures.append(response_future) - - responses = [ - response_future.result() for response_future in response_futures] - - for request, response in zip(requests, responses): - test_messages.verify(request, response, self) - pool.shutdown(wait=True) - - def testWaitingForSomeButNotAllParallelInvocations(self): - pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = [] - response_futures_to_indices = {} - for index in range(test_constants.THREAD_CONCURRENCY): - request = test_messages.request() - response_future = pool.submit( - self._invoker.blocking(group, method), request, - test_constants.LONG_TIMEOUT) - requests.append(request) - response_futures_to_indices[response_future] = index - - some_completed_response_futures_iterator = itertools.islice( - futures.as_completed(response_futures_to_indices), - test_constants.THREAD_CONCURRENCY // 2) - for response_future in some_completed_response_futures_iterator: - index = response_futures_to_indices[response_future] - test_messages.verify(requests[index], response_future.result(), self) - pool.shutdown(wait=True) - - @unittest.skip('Cancellation impossible with blocking control flow!') - def testCancelledUnaryRequestUnaryResponse(self): - raise NotImplementedError() - - @unittest.skip('Cancellation impossible with blocking control flow!') - def testCancelledUnaryRequestStreamResponse(self): - raise NotImplementedError() - - @unittest.skip('Cancellation impossible with blocking control flow!') - def testCancelledStreamRequestUnaryResponse(self): - raise NotImplementedError() - - @unittest.skip('Cancellation impossible with blocking control flow!') - def testCancelledStreamRequestStreamResponse(self): - raise NotImplementedError() - - def testExpiredUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self._control.pause(), self.assertRaises( - face.ExpirationError): - self._invoker.blocking(group, method)( - request, _3069_test_constant.REALLY_SHORT_TIMEOUT) - - def testExpiredUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self._control.pause(), self.assertRaises( - face.ExpirationError): - response_iterator = self._invoker.blocking(group, method)( - request, _3069_test_constant.REALLY_SHORT_TIMEOUT) - list(response_iterator) - - def testExpiredStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self._control.pause(), self.assertRaises( - face.ExpirationError): - self._invoker.blocking(group, method)( - iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) - - def testExpiredStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self._control.pause(), self.assertRaises( - face.ExpirationError): - response_iterator = self._invoker.blocking(group, method)( - iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) - list(response_iterator) - - def testFailedUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self._control.fail(), self.assertRaises(face.RemoteError): - self._invoker.blocking(group, method)( - request, test_constants.LONG_TIMEOUT) - - def testFailedUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self._control.fail(), self.assertRaises(face.RemoteError): - response_iterator = self._invoker.blocking(group, method)( - request, test_constants.LONG_TIMEOUT) - list(response_iterator) - - def testFailedStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self._control.fail(), self.assertRaises(face.RemoteError): - self._invoker.blocking(group, method)( - iter(requests), test_constants.LONG_TIMEOUT) - - def testFailedStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self._control.fail(), self.assertRaises(face.RemoteError): - response_iterator = self._invoker.blocking(group, method)( - iter(requests), test_constants.LONG_TIMEOUT) - list(response_iterator) + self._invoker = None + self.implementation.destantiate(self._memo) + + def testSuccessfulUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + response, call = self._invoker.blocking(group, method)( + request, test_constants.LONG_TIMEOUT, with_call=True) + + test_messages.verify(request, response, self) + + def testSuccessfulUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + response_iterator = self._invoker.blocking(group, method)( + request, test_constants.LONG_TIMEOUT) + responses = list(response_iterator) + + test_messages.verify(request, responses, self) + + def testSuccessfulStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + response, call = self._invoker.blocking(group, method)( + iter(requests), test_constants.LONG_TIMEOUT, with_call=True) + + test_messages.verify(requests, response, self) + + def testSuccessfulStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + response_iterator = self._invoker.blocking(group, method)( + iter(requests), test_constants.LONG_TIMEOUT) + responses = list(response_iterator) + + test_messages.verify(requests, responses, self) + + def testSequentialInvocations(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + first_request = test_messages.request() + second_request = test_messages.request() + + first_response = self._invoker.blocking(group, method)( + first_request, test_constants.LONG_TIMEOUT) + + test_messages.verify(first_request, first_response, self) + + second_response = self._invoker.blocking(group, method)( + second_request, test_constants.LONG_TIMEOUT) + + test_messages.verify(second_request, second_response, self) + + def testParallelInvocations(self): + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = [] + response_futures = [] + for _ in range(test_constants.THREAD_CONCURRENCY): + request = test_messages.request() + response_future = pool.submit( + self._invoker.blocking(group, method), request, + test_constants.LONG_TIMEOUT) + requests.append(request) + response_futures.append(response_future) + + responses = [ + response_future.result() + for response_future in response_futures + ] + + for request, response in zip(requests, responses): + test_messages.verify(request, response, self) + pool.shutdown(wait=True) + + def testWaitingForSomeButNotAllParallelInvocations(self): + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = [] + response_futures_to_indices = {} + for index in range(test_constants.THREAD_CONCURRENCY): + request = test_messages.request() + response_future = pool.submit( + self._invoker.blocking(group, method), request, + test_constants.LONG_TIMEOUT) + requests.append(request) + response_futures_to_indices[response_future] = index + + some_completed_response_futures_iterator = itertools.islice( + futures.as_completed(response_futures_to_indices), + test_constants.THREAD_CONCURRENCY // 2) + for response_future in some_completed_response_futures_iterator: + index = response_futures_to_indices[response_future] + test_messages.verify(requests[index], + response_future.result(), self) + pool.shutdown(wait=True) + + @unittest.skip('Cancellation impossible with blocking control flow!') + def testCancelledUnaryRequestUnaryResponse(self): + raise NotImplementedError() + + @unittest.skip('Cancellation impossible with blocking control flow!') + def testCancelledUnaryRequestStreamResponse(self): + raise NotImplementedError() + + @unittest.skip('Cancellation impossible with blocking control flow!') + def testCancelledStreamRequestUnaryResponse(self): + raise NotImplementedError() + + @unittest.skip('Cancellation impossible with blocking control flow!') + def testCancelledStreamRequestStreamResponse(self): + raise NotImplementedError() + + def testExpiredUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + with self._control.pause(), self.assertRaises( + face.ExpirationError): + self._invoker.blocking(group, method)( + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) + + def testExpiredUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + with self._control.pause(), self.assertRaises( + face.ExpirationError): + response_iterator = self._invoker.blocking(group, method)( + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) + list(response_iterator) + + def testExpiredStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + with self._control.pause(), self.assertRaises( + face.ExpirationError): + self._invoker.blocking(group, method)( + iter(requests), + _3069_test_constant.REALLY_SHORT_TIMEOUT) + + def testExpiredStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + with self._control.pause(), self.assertRaises( + face.ExpirationError): + response_iterator = self._invoker.blocking(group, method)( + iter(requests), + _3069_test_constant.REALLY_SHORT_TIMEOUT) + list(response_iterator) + + def testFailedUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + with self._control.fail(), self.assertRaises(face.RemoteError): + self._invoker.blocking(group, method)( + request, test_constants.LONG_TIMEOUT) + + def testFailedUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + with self._control.fail(), self.assertRaises(face.RemoteError): + response_iterator = self._invoker.blocking(group, method)( + request, test_constants.LONG_TIMEOUT) + list(response_iterator) + + def testFailedStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + with self._control.fail(), self.assertRaises(face.RemoteError): + self._invoker.blocking(group, method)( + iter(requests), test_constants.LONG_TIMEOUT) + + def testFailedStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + with self._control.fail(), self.assertRaises(face.RemoteError): + response_iterator = self._invoker.blocking(group, method)( + iter(requests), test_constants.LONG_TIMEOUT) + list(response_iterator) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_digest.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_digest.py index f0befb0b273..0411da0a667 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_digest.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_digest.py @@ -26,7 +26,6 @@ # 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. - """Code for making a service.TestService more amenable to use in tests.""" import collections @@ -49,17 +48,16 @@ _IDENTITY = lambda x: x class TestServiceDigest( - collections.namedtuple( - 'TestServiceDigest', - ('methods', - 'inline_method_implementations', - 'event_method_implementations', - 'multi_method_implementation', - 'unary_unary_messages_sequences', - 'unary_stream_messages_sequences', - 'stream_unary_messages_sequences', - 'stream_stream_messages_sequences',))): - """A transformation of a service.TestService. + collections.namedtuple('TestServiceDigest', ( + 'methods', + 'inline_method_implementations', + 'event_method_implementations', + 'multi_method_implementation', + 'unary_unary_messages_sequences', + 'unary_stream_messages_sequences', + 'stream_unary_messages_sequences', + 'stream_stream_messages_sequences',))): + """A transformation of a service.TestService. Attributes: methods: A dict from method group-name pair to test_interfaces.Method object @@ -88,303 +86,308 @@ class TestServiceDigest( class _BufferingConsumer(stream.Consumer): - """A trivial Consumer that dumps what it consumes in a user-mutable buffer.""" + """A trivial Consumer that dumps what it consumes in a user-mutable buffer.""" - def __init__(self): - self.consumed = [] - self.terminated = False + def __init__(self): + self.consumed = [] + self.terminated = False - def consume(self, value): - self.consumed.append(value) + def consume(self, value): + self.consumed.append(value) - def terminate(self): - self.terminated = True + def terminate(self): + self.terminated = True - def consume_and_terminate(self, value): - self.consumed.append(value) - self.terminated = True + def consume_and_terminate(self, value): + self.consumed.append(value) + self.terminated = True class _InlineUnaryUnaryMethod(face.MethodImplementation): - def __init__(self, unary_unary_test_method, control): - self._test_method = unary_unary_test_method - self._control = control + def __init__(self, unary_unary_test_method, control): + self._test_method = unary_unary_test_method + self._control = control - self.cardinality = cardinality.Cardinality.UNARY_UNARY - self.style = style.Service.INLINE + self.cardinality = cardinality.Cardinality.UNARY_UNARY + self.style = style.Service.INLINE - def unary_unary_inline(self, request, context): - response_list = [] - self._test_method.service( - request, response_list.append, context, self._control) - return response_list.pop(0) + def unary_unary_inline(self, request, context): + response_list = [] + self._test_method.service(request, response_list.append, context, + self._control) + return response_list.pop(0) class _EventUnaryUnaryMethod(face.MethodImplementation): - def __init__(self, unary_unary_test_method, control, pool): - self._test_method = unary_unary_test_method - self._control = control - self._pool = pool + def __init__(self, unary_unary_test_method, control, pool): + self._test_method = unary_unary_test_method + self._control = control + self._pool = pool - self.cardinality = cardinality.Cardinality.UNARY_UNARY - self.style = style.Service.EVENT + self.cardinality = cardinality.Cardinality.UNARY_UNARY + self.style = style.Service.EVENT - def unary_unary_event(self, request, response_callback, context): - if self._pool is None: - self._test_method.service( - request, response_callback, context, self._control) - else: - self._pool.submit( - self._test_method.service, request, response_callback, context, - self._control) + def unary_unary_event(self, request, response_callback, context): + if self._pool is None: + self._test_method.service(request, response_callback, context, + self._control) + else: + self._pool.submit(self._test_method.service, request, + response_callback, context, self._control) class _InlineUnaryStreamMethod(face.MethodImplementation): - def __init__(self, unary_stream_test_method, control): - self._test_method = unary_stream_test_method - self._control = control + def __init__(self, unary_stream_test_method, control): + self._test_method = unary_stream_test_method + self._control = control - self.cardinality = cardinality.Cardinality.UNARY_STREAM - self.style = style.Service.INLINE + self.cardinality = cardinality.Cardinality.UNARY_STREAM + self.style = style.Service.INLINE - def unary_stream_inline(self, request, context): - response_consumer = _BufferingConsumer() - self._test_method.service( - request, response_consumer, context, self._control) - for response in response_consumer.consumed: - yield response + def unary_stream_inline(self, request, context): + response_consumer = _BufferingConsumer() + self._test_method.service(request, response_consumer, context, + self._control) + for response in response_consumer.consumed: + yield response class _EventUnaryStreamMethod(face.MethodImplementation): - def __init__(self, unary_stream_test_method, control, pool): - self._test_method = unary_stream_test_method - self._control = control - self._pool = pool + def __init__(self, unary_stream_test_method, control, pool): + self._test_method = unary_stream_test_method + self._control = control + self._pool = pool - self.cardinality = cardinality.Cardinality.UNARY_STREAM - self.style = style.Service.EVENT + self.cardinality = cardinality.Cardinality.UNARY_STREAM + self.style = style.Service.EVENT - def unary_stream_event(self, request, response_consumer, context): - if self._pool is None: - self._test_method.service( - request, response_consumer, context, self._control) - else: - self._pool.submit( - self._test_method.service, request, response_consumer, context, - self._control) + def unary_stream_event(self, request, response_consumer, context): + if self._pool is None: + self._test_method.service(request, response_consumer, context, + self._control) + else: + self._pool.submit(self._test_method.service, request, + response_consumer, context, self._control) class _InlineStreamUnaryMethod(face.MethodImplementation): - def __init__(self, stream_unary_test_method, control): - self._test_method = stream_unary_test_method - self._control = control + def __init__(self, stream_unary_test_method, control): + self._test_method = stream_unary_test_method + self._control = control - self.cardinality = cardinality.Cardinality.STREAM_UNARY - self.style = style.Service.INLINE + self.cardinality = cardinality.Cardinality.STREAM_UNARY + self.style = style.Service.INLINE - def stream_unary_inline(self, request_iterator, context): - response_list = [] - request_consumer = self._test_method.service( - response_list.append, context, self._control) - for request in request_iterator: - request_consumer.consume(request) - request_consumer.terminate() - return response_list.pop(0) + def stream_unary_inline(self, request_iterator, context): + response_list = [] + request_consumer = self._test_method.service(response_list.append, + context, self._control) + for request in request_iterator: + request_consumer.consume(request) + request_consumer.terminate() + return response_list.pop(0) class _EventStreamUnaryMethod(face.MethodImplementation): - def __init__(self, stream_unary_test_method, control, pool): - self._test_method = stream_unary_test_method - self._control = control - self._pool = pool + def __init__(self, stream_unary_test_method, control, pool): + self._test_method = stream_unary_test_method + self._control = control + self._pool = pool - self.cardinality = cardinality.Cardinality.STREAM_UNARY - self.style = style.Service.EVENT + self.cardinality = cardinality.Cardinality.STREAM_UNARY + self.style = style.Service.EVENT - def stream_unary_event(self, response_callback, context): - request_consumer = self._test_method.service( - response_callback, context, self._control) - if self._pool is None: - return request_consumer - else: - return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) + def stream_unary_event(self, response_callback, context): + request_consumer = self._test_method.service(response_callback, context, + self._control) + if self._pool is None: + return request_consumer + else: + return stream_util.ThreadSwitchingConsumer(request_consumer, + self._pool) class _InlineStreamStreamMethod(face.MethodImplementation): - def __init__(self, stream_stream_test_method, control): - self._test_method = stream_stream_test_method - self._control = control + def __init__(self, stream_stream_test_method, control): + self._test_method = stream_stream_test_method + self._control = control - self.cardinality = cardinality.Cardinality.STREAM_STREAM - self.style = style.Service.INLINE + self.cardinality = cardinality.Cardinality.STREAM_STREAM + self.style = style.Service.INLINE - def stream_stream_inline(self, request_iterator, context): - response_consumer = _BufferingConsumer() - request_consumer = self._test_method.service( - response_consumer, context, self._control) + def stream_stream_inline(self, request_iterator, context): + response_consumer = _BufferingConsumer() + request_consumer = self._test_method.service(response_consumer, context, + self._control) - for request in request_iterator: - request_consumer.consume(request) - while response_consumer.consumed: - yield response_consumer.consumed.pop(0) - response_consumer.terminate() + for request in request_iterator: + request_consumer.consume(request) + while response_consumer.consumed: + yield response_consumer.consumed.pop(0) + response_consumer.terminate() class _EventStreamStreamMethod(face.MethodImplementation): - def __init__(self, stream_stream_test_method, control, pool): - self._test_method = stream_stream_test_method - self._control = control - self._pool = pool + def __init__(self, stream_stream_test_method, control, pool): + self._test_method = stream_stream_test_method + self._control = control + self._pool = pool - self.cardinality = cardinality.Cardinality.STREAM_STREAM - self.style = style.Service.EVENT + self.cardinality = cardinality.Cardinality.STREAM_STREAM + self.style = style.Service.EVENT - def stream_stream_event(self, response_consumer, context): - request_consumer = self._test_method.service( - response_consumer, context, self._control) - if self._pool is None: - return request_consumer - else: - return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) + def stream_stream_event(self, response_consumer, context): + request_consumer = self._test_method.service(response_consumer, context, + self._control) + if self._pool is None: + return request_consumer + else: + return stream_util.ThreadSwitchingConsumer(request_consumer, + self._pool) class _UnaryConsumer(stream.Consumer): - """A Consumer that only allows consumption of exactly one value.""" - - def __init__(self, action): - self._lock = threading.Lock() - self._action = action - self._consumed = False - self._terminated = False - - def consume(self, value): - with self._lock: - if self._consumed: - raise ValueError('Unary consumer already consumed!') - elif self._terminated: - raise ValueError('Unary consumer already terminated!') - else: - self._consumed = True - - self._action(value) - - def terminate(self): - with self._lock: - if not self._consumed: - raise ValueError('Unary consumer hasn\'t yet consumed!') - elif self._terminated: - raise ValueError('Unary consumer already terminated!') - else: - self._terminated = True - - def consume_and_terminate(self, value): - with self._lock: - if self._consumed: - raise ValueError('Unary consumer already consumed!') - elif self._terminated: - raise ValueError('Unary consumer already terminated!') - else: - self._consumed = True - self._terminated = True - - self._action(value) + """A Consumer that only allows consumption of exactly one value.""" + + def __init__(self, action): + self._lock = threading.Lock() + self._action = action + self._consumed = False + self._terminated = False + + def consume(self, value): + with self._lock: + if self._consumed: + raise ValueError('Unary consumer already consumed!') + elif self._terminated: + raise ValueError('Unary consumer already terminated!') + else: + self._consumed = True + + self._action(value) + + def terminate(self): + with self._lock: + if not self._consumed: + raise ValueError('Unary consumer hasn\'t yet consumed!') + elif self._terminated: + raise ValueError('Unary consumer already terminated!') + else: + self._terminated = True + + def consume_and_terminate(self, value): + with self._lock: + if self._consumed: + raise ValueError('Unary consumer already consumed!') + elif self._terminated: + raise ValueError('Unary consumer already terminated!') + else: + self._consumed = True + self._terminated = True + + self._action(value) class _UnaryUnaryAdaptation(object): - def __init__(self, unary_unary_test_method): - self._method = unary_unary_test_method + def __init__(self, unary_unary_test_method): + self._method = unary_unary_test_method + + def service(self, response_consumer, context, control): + + def action(request): + self._method.service(request, + response_consumer.consume_and_terminate, + context, control) - def service(self, response_consumer, context, control): - def action(request): - self._method.service( - request, response_consumer.consume_and_terminate, context, control) - return _UnaryConsumer(action) + return _UnaryConsumer(action) class _UnaryStreamAdaptation(object): - def __init__(self, unary_stream_test_method): - self._method = unary_stream_test_method + def __init__(self, unary_stream_test_method): + self._method = unary_stream_test_method + + def service(self, response_consumer, context, control): + + def action(request): + self._method.service(request, response_consumer, context, control) - def service(self, response_consumer, context, control): - def action(request): - self._method.service(request, response_consumer, context, control) - return _UnaryConsumer(action) + return _UnaryConsumer(action) class _StreamUnaryAdaptation(object): - def __init__(self, stream_unary_test_method): - self._method = stream_unary_test_method + def __init__(self, stream_unary_test_method): + self._method = stream_unary_test_method - def service(self, response_consumer, context, control): - return self._method.service( - response_consumer.consume_and_terminate, context, control) + def service(self, response_consumer, context, control): + return self._method.service(response_consumer.consume_and_terminate, + context, control) class _MultiMethodImplementation(face.MultiMethodImplementation): - def __init__(self, methods, control, pool): - self._methods = methods - self._control = control - self._pool = pool + def __init__(self, methods, control, pool): + self._methods = methods + self._control = control + self._pool = pool - def service(self, group, name, response_consumer, context): - method = self._methods.get(group, name, None) - if method is None: - raise face.NoSuchMethodError(group, name) - elif self._pool is None: - return method(response_consumer, context, self._control) - else: - request_consumer = method(response_consumer, context, self._control) - return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool) + def service(self, group, name, response_consumer, context): + method = self._methods.get(group, name, None) + if method is None: + raise face.NoSuchMethodError(group, name) + elif self._pool is None: + return method(response_consumer, context, self._control) + else: + request_consumer = method(response_consumer, context, self._control) + return stream_util.ThreadSwitchingConsumer(request_consumer, + self._pool) class _Assembly( - collections.namedtuple( - '_Assembly', - ['methods', 'inlines', 'events', 'adaptations', 'messages'])): - """An intermediate structure created when creating a TestServiceDigest.""" - - -def _assemble( - scenarios, identifiers, inline_method_constructor, event_method_constructor, - adapter, control, pool): - """Creates an _Assembly from the given scenarios.""" - methods = {} - inlines = {} - events = {} - adaptations = {} - messages = {} - for identifier, scenario in six.iteritems(scenarios): - if identifier in identifiers: - raise ValueError('Repeated identifier "(%s, %s)"!' % identifier) - - test_method = scenario[0] - inline_method = inline_method_constructor(test_method, control) - event_method = event_method_constructor(test_method, control, pool) - adaptation = adapter(test_method) - - methods[identifier] = test_method - inlines[identifier] = inline_method - events[identifier] = event_method - adaptations[identifier] = adaptation - messages[identifier] = scenario[1] - - return _Assembly(methods, inlines, events, adaptations, messages) + collections.namedtuple( + '_Assembly', + ['methods', 'inlines', 'events', 'adaptations', 'messages'])): + """An intermediate structure created when creating a TestServiceDigest.""" + + +def _assemble(scenarios, identifiers, inline_method_constructor, + event_method_constructor, adapter, control, pool): + """Creates an _Assembly from the given scenarios.""" + methods = {} + inlines = {} + events = {} + adaptations = {} + messages = {} + for identifier, scenario in six.iteritems(scenarios): + if identifier in identifiers: + raise ValueError('Repeated identifier "(%s, %s)"!' % identifier) + + test_method = scenario[0] + inline_method = inline_method_constructor(test_method, control) + event_method = event_method_constructor(test_method, control, pool) + adaptation = adapter(test_method) + + methods[identifier] = test_method + inlines[identifier] = inline_method + events[identifier] = event_method + adaptations[identifier] = adaptation + messages[identifier] = scenario[1] + + return _Assembly(methods, inlines, events, adaptations, messages) def digest(service, control, pool): - """Creates a TestServiceDigest from a TestService. + """Creates a TestServiceDigest from a TestService. Args: service: A _service.TestService. @@ -396,51 +399,48 @@ def digest(service, control, pool): Returns: A TestServiceDigest synthesized from the given service.TestService. """ - identifiers = set() - - unary_unary = _assemble( - service.unary_unary_scenarios(), identifiers, _InlineUnaryUnaryMethod, - _EventUnaryUnaryMethod, _UnaryUnaryAdaptation, control, pool) - identifiers.update(unary_unary.inlines) - - unary_stream = _assemble( - service.unary_stream_scenarios(), identifiers, _InlineUnaryStreamMethod, - _EventUnaryStreamMethod, _UnaryStreamAdaptation, control, pool) - identifiers.update(unary_stream.inlines) - - stream_unary = _assemble( - service.stream_unary_scenarios(), identifiers, _InlineStreamUnaryMethod, - _EventStreamUnaryMethod, _StreamUnaryAdaptation, control, pool) - identifiers.update(stream_unary.inlines) - - stream_stream = _assemble( - service.stream_stream_scenarios(), identifiers, _InlineStreamStreamMethod, - _EventStreamStreamMethod, _IDENTITY, control, pool) - identifiers.update(stream_stream.inlines) - - methods = dict(unary_unary.methods) - methods.update(unary_stream.methods) - methods.update(stream_unary.methods) - methods.update(stream_stream.methods) - adaptations = dict(unary_unary.adaptations) - adaptations.update(unary_stream.adaptations) - adaptations.update(stream_unary.adaptations) - adaptations.update(stream_stream.adaptations) - inlines = dict(unary_unary.inlines) - inlines.update(unary_stream.inlines) - inlines.update(stream_unary.inlines) - inlines.update(stream_stream.inlines) - events = dict(unary_unary.events) - events.update(unary_stream.events) - events.update(stream_unary.events) - events.update(stream_stream.events) - - return TestServiceDigest( - methods, - inlines, - events, - _MultiMethodImplementation(adaptations, control, pool), - unary_unary.messages, - unary_stream.messages, - stream_unary.messages, - stream_stream.messages) + identifiers = set() + + unary_unary = _assemble(service.unary_unary_scenarios(), identifiers, + _InlineUnaryUnaryMethod, _EventUnaryUnaryMethod, + _UnaryUnaryAdaptation, control, pool) + identifiers.update(unary_unary.inlines) + + unary_stream = _assemble(service.unary_stream_scenarios(), identifiers, + _InlineUnaryStreamMethod, _EventUnaryStreamMethod, + _UnaryStreamAdaptation, control, pool) + identifiers.update(unary_stream.inlines) + + stream_unary = _assemble(service.stream_unary_scenarios(), identifiers, + _InlineStreamUnaryMethod, _EventStreamUnaryMethod, + _StreamUnaryAdaptation, control, pool) + identifiers.update(stream_unary.inlines) + + stream_stream = _assemble(service.stream_stream_scenarios(), identifiers, + _InlineStreamStreamMethod, + _EventStreamStreamMethod, _IDENTITY, control, + pool) + identifiers.update(stream_stream.inlines) + + methods = dict(unary_unary.methods) + methods.update(unary_stream.methods) + methods.update(stream_unary.methods) + methods.update(stream_stream.methods) + adaptations = dict(unary_unary.adaptations) + adaptations.update(unary_stream.adaptations) + adaptations.update(stream_unary.adaptations) + adaptations.update(stream_stream.adaptations) + inlines = dict(unary_unary.inlines) + inlines.update(unary_stream.inlines) + inlines.update(stream_unary.inlines) + inlines.update(stream_stream.inlines) + events = dict(unary_unary.events) + events.update(unary_stream.events) + events.update(stream_unary.events) + events.update(stream_stream.events) + + return TestServiceDigest( + methods, inlines, events, + _MultiMethodImplementation(adaptations, control, pool), + unary_unary.messages, unary_stream.messages, stream_unary.messages, + stream_stream.messages) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py index df620b19ba5..703eef3a82c 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_future_invocation_asynchronous_event_service.py @@ -26,7 +26,6 @@ # 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. - """Test code for the Face layer of RPC Framework.""" from __future__ import division @@ -55,457 +54,470 @@ from tests.unit.framework.interfaces.face import test_interfaces # pylint: disa class _PauseableIterator(object): - def __init__(self, upstream): - self._upstream = upstream - self._condition = threading.Condition() - self._paused = False + def __init__(self, upstream): + self._upstream = upstream + self._condition = threading.Condition() + self._paused = False - @contextlib.contextmanager - def pause(self): - with self._condition: - self._paused = True - yield - with self._condition: - self._paused = False - self._condition.notify_all() + @contextlib.contextmanager + def pause(self): + with self._condition: + self._paused = True + yield + with self._condition: + self._paused = False + self._condition.notify_all() - def __iter__(self): - return self + def __iter__(self): + return self - def __next__(self): - return self.next() + def __next__(self): + return self.next() - def next(self): - with self._condition: - while self._paused: - self._condition.wait() - return next(self._upstream) + def next(self): + with self._condition: + while self._paused: + self._condition.wait() + return next(self._upstream) class _Callback(object): - def __init__(self): - self._condition = threading.Condition() - self._called = False - self._passed_future = None - self._passed_other_stuff = None - - def __call__(self, *args, **kwargs): - with self._condition: - self._called = True - if args: - self._passed_future = args[0] - if 1 < len(args) or kwargs: - self._passed_other_stuff = tuple(args[1:]), dict(kwargs) - self._condition.notify_all() - - def future(self): - with self._condition: - while True: - if self._passed_other_stuff is not None: - raise ValueError( - 'Test callback passed unexpected values: %s', - self._passed_other_stuff) - elif self._called: - return self._passed_future - else: - self._condition.wait() - - -class TestCase(six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, unittest.TestCase)): - """A test of the Face layer of RPC Framework. + def __init__(self): + self._condition = threading.Condition() + self._called = False + self._passed_future = None + self._passed_other_stuff = None + + def __call__(self, *args, **kwargs): + with self._condition: + self._called = True + if args: + self._passed_future = args[0] + if 1 < len(args) or kwargs: + self._passed_other_stuff = tuple(args[1:]), dict(kwargs) + self._condition.notify_all() + + def future(self): + with self._condition: + while True: + if self._passed_other_stuff is not None: + raise ValueError( + 'Test callback passed unexpected values: %s', + self._passed_other_stuff) + elif self._called: + return self._passed_future + else: + self._condition.wait() + + +class TestCase( + six.with_metaclass(abc.ABCMeta, test_coverage.Coverage, + unittest.TestCase)): + """A test of the Face layer of RPC Framework. Concrete subclasses must have an "implementation" attribute of type test_interfaces.Implementation and an "invoker_constructor" attribute of type _invocation.InvokerConstructor. """ - NAME = 'FutureInvocationAsynchronousEventServiceTest' + NAME = 'FutureInvocationAsynchronousEventServiceTest' - def setUp(self): - """See unittest.TestCase.setUp for full specification. + def setUp(self): + """See unittest.TestCase.setUp for full specification. Overriding implementations must call this implementation. """ - self._control = test_control.PauseFailControl() - self._digest_pool = logging_pool.pool(test_constants.POOL_SIZE) - self._digest = _digest.digest( - _stock_service.STOCK_TEST_SERVICE, self._control, self._digest_pool) + self._control = test_control.PauseFailControl() + self._digest_pool = logging_pool.pool(test_constants.POOL_SIZE) + self._digest = _digest.digest(_stock_service.STOCK_TEST_SERVICE, + self._control, self._digest_pool) - generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate( - self._digest.methods, self._digest.event_method_implementations, None) - self._invoker = self.invoker_constructor.construct_invoker( - generic_stub, dynamic_stubs, self._digest.methods) + generic_stub, dynamic_stubs, self._memo = self.implementation.instantiate( + self._digest.methods, self._digest.event_method_implementations, + None) + self._invoker = self.invoker_constructor.construct_invoker( + generic_stub, dynamic_stubs, self._digest.methods) - def tearDown(self): - """See unittest.TestCase.tearDown for full specification. + def tearDown(self): + """See unittest.TestCase.tearDown for full specification. Overriding implementations must call this implementation. """ - self._invoker = None - self.implementation.destantiate(self._memo) - self._digest_pool.shutdown(wait=True) - - def testSuccessfulUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = _Callback() - - response_future = self._invoker.future(group, method)( - request, test_constants.LONG_TIMEOUT) - response_future.add_done_callback(callback) - response = response_future.result() - - test_messages.verify(request, response, self) - self.assertIs(callback.future(), response_future) - self.assertIsNone(response_future.exception()) - self.assertIsNone(response_future.traceback()) - - def testSuccessfulUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - response_iterator = self._invoker.future(group, method)( - request, test_constants.LONG_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(request, responses, self) - - def testSuccessfulStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - request_iterator = _PauseableIterator(iter(requests)) - callback = _Callback() - - # Use of a paused iterator of requests allows us to test that control is - # returned to calling code before the iterator yields any requests. - with request_iterator.pause(): - response_future = self._invoker.future(group, method)( - request_iterator, test_constants.LONG_TIMEOUT) - response_future.add_done_callback(callback) - future_passed_to_callback = callback.future() - response = future_passed_to_callback.result() - - test_messages.verify(requests, response, self) - self.assertIs(future_passed_to_callback, response_future) - self.assertIsNone(response_future.exception()) - self.assertIsNone(response_future.traceback()) - - def testSuccessfulStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - request_iterator = _PauseableIterator(iter(requests)) - - # Use of a paused iterator of requests allows us to test that control is - # returned to calling code before the iterator yields any requests. - with request_iterator.pause(): - response_iterator = self._invoker.future(group, method)( - request_iterator, test_constants.LONG_TIMEOUT) - responses = list(response_iterator) - - test_messages.verify(requests, responses, self) - - def testSequentialInvocations(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - - first_response_future = self._invoker.future(group, method)( - first_request, test_constants.LONG_TIMEOUT) - first_response = first_response_future.result() - - test_messages.verify(first_request, first_response, self) - - second_response_future = self._invoker.future(group, method)( - second_request, test_constants.LONG_TIMEOUT) - second_response = second_response_future.result() - - test_messages.verify(second_request, second_response, self) - - def testParallelInvocations(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - first_request = test_messages.request() - second_request = test_messages.request() - - first_response_future = self._invoker.future(group, method)( - first_request, test_constants.LONG_TIMEOUT) - second_response_future = self._invoker.future(group, method)( - second_request, test_constants.LONG_TIMEOUT) - first_response = first_response_future.result() - second_response = second_response_future.result() - - test_messages.verify(first_request, first_response, self) - test_messages.verify(second_request, second_response, self) - - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = [] - response_futures = [] - for _ in range(test_constants.THREAD_CONCURRENCY): - request = test_messages.request() - response_future = self._invoker.future(group, method)( - request, test_constants.LONG_TIMEOUT) - requests.append(request) - response_futures.append(response_future) - - responses = [ - response_future.result() for response_future in response_futures] - - for request, response in zip(requests, responses): - test_messages.verify(request, response, self) - - def testWaitingForSomeButNotAllParallelInvocations(self): - pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = [] - response_futures_to_indices = {} - for index in range(test_constants.THREAD_CONCURRENCY): - request = test_messages.request() - inner_response_future = self._invoker.future(group, method)( - request, test_constants.LONG_TIMEOUT) - outer_response_future = pool.submit(inner_response_future.result) - requests.append(request) - response_futures_to_indices[outer_response_future] = index - - some_completed_response_futures_iterator = itertools.islice( - futures.as_completed(response_futures_to_indices), - test_constants.THREAD_CONCURRENCY // 2) - for response_future in some_completed_response_futures_iterator: - index = response_futures_to_indices[response_future] - test_messages.verify(requests[index], response_future.result(), self) - pool.shutdown(wait=True) - - def testCancelledUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = _Callback() - - with self._control.pause(): - response_future = self._invoker.future(group, method)( - request, test_constants.LONG_TIMEOUT) - response_future.add_done_callback(callback) - cancel_method_return_value = response_future.cancel() - - self.assertIs(callback.future(), response_future) - self.assertFalse(cancel_method_return_value) - self.assertTrue(response_future.cancelled()) - with self.assertRaises(future.CancelledError): - response_future.result() - with self.assertRaises(future.CancelledError): - response_future.exception() - with self.assertRaises(future.CancelledError): - response_future.traceback() - - def testCancelledUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self._control.pause(): - response_iterator = self._invoker.future(group, method)( - request, test_constants.LONG_TIMEOUT) - response_iterator.cancel() - - with self.assertRaises(face.CancellationError): - next(response_iterator) - - def testCancelledStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = _Callback() - - with self._control.pause(): - response_future = self._invoker.future(group, method)( - iter(requests), test_constants.LONG_TIMEOUT) - response_future.add_done_callback(callback) - cancel_method_return_value = response_future.cancel() - - self.assertIs(callback.future(), response_future) - self.assertFalse(cancel_method_return_value) - self.assertTrue(response_future.cancelled()) - with self.assertRaises(future.CancelledError): - response_future.result() - with self.assertRaises(future.CancelledError): - response_future.exception() - with self.assertRaises(future.CancelledError): - response_future.traceback() - - def testCancelledStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self._control.pause(): - response_iterator = self._invoker.future(group, method)( - iter(requests), test_constants.LONG_TIMEOUT) - response_iterator.cancel() - - with self.assertRaises(face.CancellationError): - next(response_iterator) - - def testExpiredUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = _Callback() - - with self._control.pause(): - response_future = self._invoker.future( - group, method)(request, _3069_test_constant.REALLY_SHORT_TIMEOUT) - response_future.add_done_callback(callback) - self.assertIs(callback.future(), response_future) - self.assertIsInstance( - response_future.exception(), face.ExpirationError) - with self.assertRaises(face.ExpirationError): - response_future.result() - self.assertIsInstance( - response_future.exception(), face.AbortionError) - self.assertIsNotNone(response_future.traceback()) - - def testExpiredUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - with self._control.pause(): - response_iterator = self._invoker.future(group, method)( - request, _3069_test_constant.REALLY_SHORT_TIMEOUT) - with self.assertRaises(face.ExpirationError): - list(response_iterator) - - def testExpiredStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = _Callback() - - with self._control.pause(): - response_future = self._invoker.future(group, method)( - iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) - response_future.add_done_callback(callback) - self.assertIs(callback.future(), response_future) - self.assertIsInstance( - response_future.exception(), face.ExpirationError) - with self.assertRaises(face.ExpirationError): - response_future.result() - self.assertIsInstance( - response_future.exception(), face.AbortionError) - self.assertIsNotNone(response_future.traceback()) - - def testExpiredStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - with self._control.pause(): - response_iterator = self._invoker.future(group, method)( - iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) - with self.assertRaises(face.ExpirationError): - list(response_iterator) - - def testFailedUnaryRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_unary_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - callback = _Callback() - abortion_callback = _Callback() - - with self._control.fail(): - response_future = self._invoker.future(group, method)( - request, _3069_test_constant.REALLY_SHORT_TIMEOUT) - response_future.add_done_callback(callback) - response_future.add_abortion_callback(abortion_callback) - - self.assertIs(callback.future(), response_future) - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is - # indistinguishable from simply not having called its - # response_callback before the expiration of the RPC. - self.assertIsInstance( - response_future.exception(), face.ExpirationError) - with self.assertRaises(face.ExpirationError): - response_future.result() - self.assertIsNotNone(response_future.traceback()) - self.assertIsNotNone(abortion_callback.future()) - - def testFailedUnaryRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.unary_stream_messages_sequences)): - for test_messages in test_messages_sequence: - request = test_messages.request() - - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is indistinguishable - # from simply not having called its response_consumer before the - # expiration of the RPC. - with self._control.fail(), self.assertRaises(face.ExpirationError): - response_iterator = self._invoker.future(group, method)( - request, _3069_test_constant.REALLY_SHORT_TIMEOUT) - list(response_iterator) - - def testFailedStreamRequestUnaryResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_unary_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - callback = _Callback() - abortion_callback = _Callback() - - with self._control.fail(): - response_future = self._invoker.future(group, method)( - iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) - response_future.add_done_callback(callback) - response_future.add_abortion_callback(abortion_callback) - - self.assertIs(callback.future(), response_future) - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is - # indistinguishable from simply not having called its - # response_callback before the expiration of the RPC. - self.assertIsInstance( - response_future.exception(), face.ExpirationError) - with self.assertRaises(face.ExpirationError): - response_future.result() - self.assertIsNotNone(response_future.traceback()) - self.assertIsNotNone(abortion_callback.future()) - - def testFailedStreamRequestStreamResponse(self): - for (group, method), test_messages_sequence in ( - six.iteritems(self._digest.stream_stream_messages_sequences)): - for test_messages in test_messages_sequence: - requests = test_messages.requests() - - # Because the servicer fails outside of the thread from which the - # servicer-side runtime called into it its failure is indistinguishable - # from simply not having called its response_consumer before the - # expiration of the RPC. - with self._control.fail(), self.assertRaises(face.ExpirationError): - response_iterator = self._invoker.future(group, method)( - iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) - list(response_iterator) + self._invoker = None + self.implementation.destantiate(self._memo) + self._digest_pool.shutdown(wait=True) + + def testSuccessfulUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + callback = _Callback() + + response_future = self._invoker.future(group, method)( + request, test_constants.LONG_TIMEOUT) + response_future.add_done_callback(callback) + response = response_future.result() + + test_messages.verify(request, response, self) + self.assertIs(callback.future(), response_future) + self.assertIsNone(response_future.exception()) + self.assertIsNone(response_future.traceback()) + + def testSuccessfulUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + response_iterator = self._invoker.future(group, method)( + request, test_constants.LONG_TIMEOUT) + responses = list(response_iterator) + + test_messages.verify(request, responses, self) + + def testSuccessfulStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + request_iterator = _PauseableIterator(iter(requests)) + callback = _Callback() + + # Use of a paused iterator of requests allows us to test that control is + # returned to calling code before the iterator yields any requests. + with request_iterator.pause(): + response_future = self._invoker.future(group, method)( + request_iterator, test_constants.LONG_TIMEOUT) + response_future.add_done_callback(callback) + future_passed_to_callback = callback.future() + response = future_passed_to_callback.result() + + test_messages.verify(requests, response, self) + self.assertIs(future_passed_to_callback, response_future) + self.assertIsNone(response_future.exception()) + self.assertIsNone(response_future.traceback()) + + def testSuccessfulStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + request_iterator = _PauseableIterator(iter(requests)) + + # Use of a paused iterator of requests allows us to test that control is + # returned to calling code before the iterator yields any requests. + with request_iterator.pause(): + response_iterator = self._invoker.future(group, method)( + request_iterator, test_constants.LONG_TIMEOUT) + responses = list(response_iterator) + + test_messages.verify(requests, responses, self) + + def testSequentialInvocations(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + first_request = test_messages.request() + second_request = test_messages.request() + + first_response_future = self._invoker.future(group, method)( + first_request, test_constants.LONG_TIMEOUT) + first_response = first_response_future.result() + + test_messages.verify(first_request, first_response, self) + + second_response_future = self._invoker.future(group, method)( + second_request, test_constants.LONG_TIMEOUT) + second_response = second_response_future.result() + + test_messages.verify(second_request, second_response, self) + + def testParallelInvocations(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + first_request = test_messages.request() + second_request = test_messages.request() + + first_response_future = self._invoker.future(group, method)( + first_request, test_constants.LONG_TIMEOUT) + second_response_future = self._invoker.future(group, method)( + second_request, test_constants.LONG_TIMEOUT) + first_response = first_response_future.result() + second_response = second_response_future.result() + + test_messages.verify(first_request, first_response, self) + test_messages.verify(second_request, second_response, self) + + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = [] + response_futures = [] + for _ in range(test_constants.THREAD_CONCURRENCY): + request = test_messages.request() + response_future = self._invoker.future(group, method)( + request, test_constants.LONG_TIMEOUT) + requests.append(request) + response_futures.append(response_future) + + responses = [ + response_future.result() + for response_future in response_futures + ] + + for request, response in zip(requests, responses): + test_messages.verify(request, response, self) + + def testWaitingForSomeButNotAllParallelInvocations(self): + pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = [] + response_futures_to_indices = {} + for index in range(test_constants.THREAD_CONCURRENCY): + request = test_messages.request() + inner_response_future = self._invoker.future(group, method)( + request, test_constants.LONG_TIMEOUT) + outer_response_future = pool.submit( + inner_response_future.result) + requests.append(request) + response_futures_to_indices[outer_response_future] = index + + some_completed_response_futures_iterator = itertools.islice( + futures.as_completed(response_futures_to_indices), + test_constants.THREAD_CONCURRENCY // 2) + for response_future in some_completed_response_futures_iterator: + index = response_futures_to_indices[response_future] + test_messages.verify(requests[index], + response_future.result(), self) + pool.shutdown(wait=True) + + def testCancelledUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + callback = _Callback() + + with self._control.pause(): + response_future = self._invoker.future(group, method)( + request, test_constants.LONG_TIMEOUT) + response_future.add_done_callback(callback) + cancel_method_return_value = response_future.cancel() + + self.assertIs(callback.future(), response_future) + self.assertFalse(cancel_method_return_value) + self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + with self.assertRaises(future.CancelledError): + response_future.exception() + with self.assertRaises(future.CancelledError): + response_future.traceback() + + def testCancelledUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + with self._control.pause(): + response_iterator = self._invoker.future(group, method)( + request, test_constants.LONG_TIMEOUT) + response_iterator.cancel() + + with self.assertRaises(face.CancellationError): + next(response_iterator) + + def testCancelledStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + callback = _Callback() + + with self._control.pause(): + response_future = self._invoker.future(group, method)( + iter(requests), test_constants.LONG_TIMEOUT) + response_future.add_done_callback(callback) + cancel_method_return_value = response_future.cancel() + + self.assertIs(callback.future(), response_future) + self.assertFalse(cancel_method_return_value) + self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + with self.assertRaises(future.CancelledError): + response_future.exception() + with self.assertRaises(future.CancelledError): + response_future.traceback() + + def testCancelledStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + with self._control.pause(): + response_iterator = self._invoker.future(group, method)( + iter(requests), test_constants.LONG_TIMEOUT) + response_iterator.cancel() + + with self.assertRaises(face.CancellationError): + next(response_iterator) + + def testExpiredUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + callback = _Callback() + + with self._control.pause(): + response_future = self._invoker.future(group, method)( + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) + response_future.add_done_callback(callback) + self.assertIs(callback.future(), response_future) + self.assertIsInstance(response_future.exception(), + face.ExpirationError) + with self.assertRaises(face.ExpirationError): + response_future.result() + self.assertIsInstance(response_future.exception(), + face.AbortionError) + self.assertIsNotNone(response_future.traceback()) + + def testExpiredUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + with self._control.pause(): + response_iterator = self._invoker.future(group, method)( + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + list(response_iterator) + + def testExpiredStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + callback = _Callback() + + with self._control.pause(): + response_future = self._invoker.future(group, method)( + iter(requests), + _3069_test_constant.REALLY_SHORT_TIMEOUT) + response_future.add_done_callback(callback) + self.assertIs(callback.future(), response_future) + self.assertIsInstance(response_future.exception(), + face.ExpirationError) + with self.assertRaises(face.ExpirationError): + response_future.result() + self.assertIsInstance(response_future.exception(), + face.AbortionError) + self.assertIsNotNone(response_future.traceback()) + + def testExpiredStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + with self._control.pause(): + response_iterator = self._invoker.future(group, method)( + iter(requests), + _3069_test_constant.REALLY_SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + list(response_iterator) + + def testFailedUnaryRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_unary_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + callback = _Callback() + abortion_callback = _Callback() + + with self._control.fail(): + response_future = self._invoker.future(group, method)( + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) + response_future.add_done_callback(callback) + response_future.add_abortion_callback(abortion_callback) + + self.assertIs(callback.future(), response_future) + # Because the servicer fails outside of the thread from which the + # servicer-side runtime called into it its failure is + # indistinguishable from simply not having called its + # response_callback before the expiration of the RPC. + self.assertIsInstance(response_future.exception(), + face.ExpirationError) + with self.assertRaises(face.ExpirationError): + response_future.result() + self.assertIsNotNone(response_future.traceback()) + self.assertIsNotNone(abortion_callback.future()) + + def testFailedUnaryRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.unary_stream_messages_sequences)): + for test_messages in test_messages_sequence: + request = test_messages.request() + + # Because the servicer fails outside of the thread from which the + # servicer-side runtime called into it its failure is indistinguishable + # from simply not having called its response_consumer before the + # expiration of the RPC. + with self._control.fail(), self.assertRaises( + face.ExpirationError): + response_iterator = self._invoker.future(group, method)( + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) + list(response_iterator) + + def testFailedStreamRequestUnaryResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_unary_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + callback = _Callback() + abortion_callback = _Callback() + + with self._control.fail(): + response_future = self._invoker.future(group, method)( + iter(requests), + _3069_test_constant.REALLY_SHORT_TIMEOUT) + response_future.add_done_callback(callback) + response_future.add_abortion_callback(abortion_callback) + + self.assertIs(callback.future(), response_future) + # Because the servicer fails outside of the thread from which the + # servicer-side runtime called into it its failure is + # indistinguishable from simply not having called its + # response_callback before the expiration of the RPC. + self.assertIsInstance(response_future.exception(), + face.ExpirationError) + with self.assertRaises(face.ExpirationError): + response_future.result() + self.assertIsNotNone(response_future.traceback()) + self.assertIsNotNone(abortion_callback.future()) + + def testFailedStreamRequestStreamResponse(self): + for (group, method), test_messages_sequence in ( + six.iteritems(self._digest.stream_stream_messages_sequences)): + for test_messages in test_messages_sequence: + requests = test_messages.requests() + + # Because the servicer fails outside of the thread from which the + # servicer-side runtime called into it its failure is indistinguishable + # from simply not having called its response_consumer before the + # expiration of the RPC. + with self._control.fail(), self.assertRaises( + face.ExpirationError): + response_iterator = self._invoker.future(group, method)( + iter(requests), + _3069_test_constant.REALLY_SHORT_TIMEOUT) + list(response_iterator) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_invocation.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_invocation.py index ac487bed4f9..4e144a36352 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_invocation.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_invocation.py @@ -26,7 +26,6 @@ # 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. - """Coverage across the Face layer's generic-to-dynamic range for invocation.""" import abc @@ -65,149 +64,149 @@ _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE = { class Invoker(six.with_metaclass(abc.ABCMeta)): - """A type used to invoke test RPCs.""" + """A type used to invoke test RPCs.""" - @abc.abstractmethod - def blocking(self, group, name): - """Invokes an RPC with blocking control flow.""" - raise NotImplementedError() + @abc.abstractmethod + def blocking(self, group, name): + """Invokes an RPC with blocking control flow.""" + raise NotImplementedError() - @abc.abstractmethod - def future(self, group, name): - """Invokes an RPC with future control flow.""" - raise NotImplementedError() + @abc.abstractmethod + def future(self, group, name): + """Invokes an RPC with future control flow.""" + raise NotImplementedError() - @abc.abstractmethod - def event(self, group, name): - """Invokes an RPC with event control flow.""" - raise NotImplementedError() + @abc.abstractmethod + def event(self, group, name): + """Invokes an RPC with event control flow.""" + raise NotImplementedError() class InvokerConstructor(six.with_metaclass(abc.ABCMeta)): - """A type used to create Invokers.""" + """A type used to create Invokers.""" - @abc.abstractmethod - def name(self): - """Specifies the name of the Invoker constructed by this object.""" - raise NotImplementedError() + @abc.abstractmethod + def name(self): + """Specifies the name of the Invoker constructed by this object.""" + raise NotImplementedError() - @abc.abstractmethod - def construct_invoker(self, generic_stub, dynamic_stubs, methods): - """Constructs an Invoker for the given stubs and methods.""" - raise NotImplementedError() + @abc.abstractmethod + def construct_invoker(self, generic_stub, dynamic_stubs, methods): + """Constructs an Invoker for the given stubs and methods.""" + raise NotImplementedError() class _GenericInvoker(Invoker): - def __init__(self, generic_stub, methods): - self._stub = generic_stub - self._methods = methods + def __init__(self, generic_stub, methods): + self._stub = generic_stub + self._methods = methods - def _behavior(self, group, name, cardinality_to_generic_method): - method_cardinality = self._methods[group, name].cardinality() - behavior = getattr( - self._stub, cardinality_to_generic_method[method_cardinality]) - return lambda *args, **kwargs: behavior(group, name, *args, **kwargs) + def _behavior(self, group, name, cardinality_to_generic_method): + method_cardinality = self._methods[group, name].cardinality() + behavior = getattr(self._stub, + cardinality_to_generic_method[method_cardinality]) + return lambda *args, **kwargs: behavior(group, name, *args, **kwargs) - def blocking(self, group, name): - return self._behavior( - group, name, _CARDINALITY_TO_GENERIC_BLOCKING_BEHAVIOR) + def blocking(self, group, name): + return self._behavior(group, name, + _CARDINALITY_TO_GENERIC_BLOCKING_BEHAVIOR) - def future(self, group, name): - return self._behavior(group, name, _CARDINALITY_TO_GENERIC_FUTURE_BEHAVIOR) + def future(self, group, name): + return self._behavior(group, name, + _CARDINALITY_TO_GENERIC_FUTURE_BEHAVIOR) - def event(self, group, name): - return self._behavior(group, name, _CARDINALITY_TO_GENERIC_EVENT_BEHAVIOR) + def event(self, group, name): + return self._behavior(group, name, + _CARDINALITY_TO_GENERIC_EVENT_BEHAVIOR) class _GenericInvokerConstructor(InvokerConstructor): - def name(self): - return 'GenericInvoker' + def name(self): + return 'GenericInvoker' - def construct_invoker(self, generic_stub, dynamic_stub, methods): - return _GenericInvoker(generic_stub, methods) + def construct_invoker(self, generic_stub, dynamic_stub, methods): + return _GenericInvoker(generic_stub, methods) class _MultiCallableInvoker(Invoker): - def __init__(self, generic_stub, methods): - self._stub = generic_stub - self._methods = methods + def __init__(self, generic_stub, methods): + self._stub = generic_stub + self._methods = methods - def _multi_callable(self, group, name): - method_cardinality = self._methods[group, name].cardinality() - behavior = getattr( - self._stub, - _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE[method_cardinality]) - return behavior(group, name) + def _multi_callable(self, group, name): + method_cardinality = self._methods[group, name].cardinality() + behavior = getattr( + self._stub, + _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE[method_cardinality]) + return behavior(group, name) - def blocking(self, group, name): - return self._multi_callable(group, name) + def blocking(self, group, name): + return self._multi_callable(group, name) - def future(self, group, name): - method_cardinality = self._methods[group, name].cardinality() - behavior = getattr( - self._stub, - _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE[method_cardinality]) - if method_cardinality in ( - cardinality.Cardinality.UNARY_UNARY, - cardinality.Cardinality.STREAM_UNARY): - return behavior(group, name).future - else: - return behavior(group, name) + def future(self, group, name): + method_cardinality = self._methods[group, name].cardinality() + behavior = getattr( + self._stub, + _CARDINALITY_TO_MULTI_CALLABLE_ATTRIBUTE[method_cardinality]) + if method_cardinality in (cardinality.Cardinality.UNARY_UNARY, + cardinality.Cardinality.STREAM_UNARY): + return behavior(group, name).future + else: + return behavior(group, name) - def event(self, group, name): - return self._multi_callable(group, name).event + def event(self, group, name): + return self._multi_callable(group, name).event class _MultiCallableInvokerConstructor(InvokerConstructor): - def name(self): - return 'MultiCallableInvoker' + def name(self): + return 'MultiCallableInvoker' - def construct_invoker(self, generic_stub, dynamic_stub, methods): - return _MultiCallableInvoker(generic_stub, methods) + def construct_invoker(self, generic_stub, dynamic_stub, methods): + return _MultiCallableInvoker(generic_stub, methods) class _DynamicInvoker(Invoker): - def __init__(self, dynamic_stubs, methods): - self._stubs = dynamic_stubs - self._methods = methods + def __init__(self, dynamic_stubs, methods): + self._stubs = dynamic_stubs + self._methods = methods - def blocking(self, group, name): - return getattr(self._stubs[group], name) + def blocking(self, group, name): + return getattr(self._stubs[group], name) - def future(self, group, name): - if self._methods[group, name].cardinality() in ( - cardinality.Cardinality.UNARY_UNARY, - cardinality.Cardinality.STREAM_UNARY): - return getattr(self._stubs[group], name).future - else: - return getattr(self._stubs[group], name) + def future(self, group, name): + if self._methods[group, name].cardinality() in ( + cardinality.Cardinality.UNARY_UNARY, + cardinality.Cardinality.STREAM_UNARY): + return getattr(self._stubs[group], name).future + else: + return getattr(self._stubs[group], name) - def event(self, group, name): - return getattr(self._stubs[group], name).event + def event(self, group, name): + return getattr(self._stubs[group], name).event class _DynamicInvokerConstructor(InvokerConstructor): - def name(self): - return 'DynamicInvoker' + def name(self): + return 'DynamicInvoker' - def construct_invoker(self, generic_stub, dynamic_stubs, methods): - return _DynamicInvoker(dynamic_stubs, methods) + def construct_invoker(self, generic_stub, dynamic_stubs, methods): + return _DynamicInvoker(dynamic_stubs, methods) def invoker_constructors(): - """Creates a sequence of InvokerConstructors to use in tests of RPCs. + """Creates a sequence of InvokerConstructors to use in tests of RPCs. Returns: A sequence of InvokerConstructors. """ - return ( - _GenericInvokerConstructor(), - _MultiCallableInvokerConstructor(), - _DynamicInvokerConstructor(), - ) + return ( + _GenericInvokerConstructor(), + _MultiCallableInvokerConstructor(), + _DynamicInvokerConstructor(),) diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_service.py index f13dff05585..f14ac6a9871 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_service.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_service.py @@ -26,7 +26,6 @@ # 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. - """Private interfaces implemented by data sets used in Face-layer tests.""" import abc @@ -38,12 +37,13 @@ from grpc.framework.interfaces.face import face # pylint: disable=unused-import from tests.unit.framework.interfaces.face import test_interfaces -class UnaryUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): - """A controllable implementation of a unary-unary method.""" +class UnaryUnaryTestMethodImplementation( + six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): + """A controllable implementation of a unary-unary method.""" - @abc.abstractmethod - def service(self, request, response_callback, context, control): - """Services an RPC that accepts one message and produces one message. + @abc.abstractmethod + def service(self, request, response_callback, context, control): + """Services an RPC that accepts one message and produces one message. Args: request: The single request message for the RPC. @@ -56,15 +56,15 @@ class UnaryUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_in abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ - raise NotImplementedError() + raise NotImplementedError() class UnaryUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for unary-request-unary-response message pairings.""" + """A type for unary-request-unary-response message pairings.""" - @abc.abstractmethod - def request(self): - """Affords a request message. + @abc.abstractmethod + def request(self): + """Affords a request message. Implementations of this method should return a different message with each call so that multiple test executions of the test method may be made with @@ -73,11 +73,11 @@ class UnaryUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): Returns: A request message. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def verify(self, request, response, test_case): - """Verifies that the computed response matches the given request. + @abc.abstractmethod + def verify(self, request, response, test_case): + """Verifies that the computed response matches the given request. Args: request: A request message. @@ -88,15 +88,16 @@ class UnaryUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): AssertionError: If the request and response do not match, indicating that there was some problem executing the RPC under test. """ - raise NotImplementedError() + raise NotImplementedError() -class UnaryStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): - """A controllable implementation of a unary-stream method.""" +class UnaryStreamTestMethodImplementation( + six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): + """A controllable implementation of a unary-stream method.""" - @abc.abstractmethod - def service(self, request, response_consumer, context, control): - """Services an RPC that takes one message and produces a stream of messages. + @abc.abstractmethod + def service(self, request, response_consumer, context, control): + """Services an RPC that takes one message and produces a stream of messages. Args: request: The single request message for the RPC. @@ -109,15 +110,15 @@ class UnaryStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_i abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ - raise NotImplementedError() + raise NotImplementedError() class UnaryStreamTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for unary-request-stream-response message pairings.""" + """A type for unary-request-stream-response message pairings.""" - @abc.abstractmethod - def request(self): - """Affords a request message. + @abc.abstractmethod + def request(self): + """Affords a request message. Implementations of this method should return a different message with each call so that multiple test executions of the test method may be made with @@ -126,11 +127,11 @@ class UnaryStreamTestMessages(six.with_metaclass(abc.ABCMeta)): Returns: A request message. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def verify(self, request, responses, test_case): - """Verifies that the computed responses match the given request. + @abc.abstractmethod + def verify(self, request, responses, test_case): + """Verifies that the computed responses match the given request. Args: request: A request message. @@ -141,15 +142,16 @@ class UnaryStreamTestMessages(six.with_metaclass(abc.ABCMeta)): AssertionError: If the request and responses do not match, indicating that there was some problem executing the RPC under test. """ - raise NotImplementedError() + raise NotImplementedError() -class StreamUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): - """A controllable implementation of a stream-unary method.""" +class StreamUnaryTestMethodImplementation( + six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): + """A controllable implementation of a stream-unary method.""" - @abc.abstractmethod - def service(self, response_callback, context, control): - """Services an RPC that takes a stream of messages and produces one message. + @abc.abstractmethod + def service(self, response_callback, context, control): + """Services an RPC that takes a stream of messages and produces one message. Args: response_callback: A callback to be called to accept the response message @@ -169,15 +171,15 @@ class StreamUnaryTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_i abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ - raise NotImplementedError() + raise NotImplementedError() class StreamUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for stream-request-unary-response message pairings.""" + """A type for stream-request-unary-response message pairings.""" - @abc.abstractmethod - def requests(self): - """Affords a sequence of request messages. + @abc.abstractmethod + def requests(self): + """Affords a sequence of request messages. Implementations of this method should return a different sequences with each call so that multiple test executions of the test method may be made with @@ -186,11 +188,11 @@ class StreamUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): Returns: A sequence of request messages. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def verify(self, requests, response, test_case): - """Verifies that the computed response matches the given requests. + @abc.abstractmethod + def verify(self, requests, response, test_case): + """Verifies that the computed response matches the given requests. Args: requests: A sequence of request messages. @@ -201,15 +203,16 @@ class StreamUnaryTestMessages(six.with_metaclass(abc.ABCMeta)): AssertionError: If the requests and response do not match, indicating that there was some problem executing the RPC under test. """ - raise NotImplementedError() + raise NotImplementedError() -class StreamStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): - """A controllable implementation of a stream-stream method.""" +class StreamStreamTestMethodImplementation( + six.with_metaclass(abc.ABCMeta, test_interfaces.Method)): + """A controllable implementation of a stream-stream method.""" - @abc.abstractmethod - def service(self, response_consumer, context, control): - """Services an RPC that accepts and produces streams of messages. + @abc.abstractmethod + def service(self, response_consumer, context, control): + """Services an RPC that accepts and produces streams of messages. Args: response_consumer: A stream.Consumer to be called to accept the response @@ -229,15 +232,15 @@ class StreamStreamTestMethodImplementation(six.with_metaclass(abc.ABCMeta, test_ abandonment.Abandoned: May or may not be raised when the RPC has been aborted. """ - raise NotImplementedError() + raise NotImplementedError() class StreamStreamTestMessages(six.with_metaclass(abc.ABCMeta)): - """A type for stream-request-stream-response message pairings.""" + """A type for stream-request-stream-response message pairings.""" - @abc.abstractmethod - def requests(self): - """Affords a sequence of request messages. + @abc.abstractmethod + def requests(self): + """Affords a sequence of request messages. Implementations of this method should return a different sequences with each call so that multiple test executions of the test method may be made with @@ -246,11 +249,11 @@ class StreamStreamTestMessages(six.with_metaclass(abc.ABCMeta)): Returns: A sequence of request messages. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def verify(self, requests, responses, test_case): - """Verifies that the computed response matches the given requests. + @abc.abstractmethod + def verify(self, requests, responses, test_case): + """Verifies that the computed response matches the given requests. Args: requests: A sequence of request messages. @@ -261,15 +264,15 @@ class StreamStreamTestMessages(six.with_metaclass(abc.ABCMeta)): AssertionError: If the requests and responses do not match, indicating that there was some problem executing the RPC under test. """ - raise NotImplementedError() + raise NotImplementedError() class TestService(six.with_metaclass(abc.ABCMeta)): - """A specification of implemented methods to use in tests.""" + """A specification of implemented methods to use in tests.""" - @abc.abstractmethod - def unary_unary_scenarios(self): - """Affords unary-request-unary-response test methods and their messages. + @abc.abstractmethod + def unary_unary_scenarios(self): + """Affords unary-request-unary-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The @@ -277,11 +280,11 @@ class TestService(six.with_metaclass(abc.ABCMeta)): and the second element is a sequence of UnaryUnaryTestMethodMessages objects. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def unary_stream_scenarios(self): - """Affords unary-request-stream-response test methods and their messages. + @abc.abstractmethod + def unary_stream_scenarios(self): + """Affords unary-request-stream-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The @@ -289,11 +292,11 @@ class TestService(six.with_metaclass(abc.ABCMeta)): object and the second element is a sequence of UnaryStreamTestMethodMessages objects. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stream_unary_scenarios(self): - """Affords stream-request-unary-response test methods and their messages. + @abc.abstractmethod + def stream_unary_scenarios(self): + """Affords stream-request-unary-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The @@ -301,11 +304,11 @@ class TestService(six.with_metaclass(abc.ABCMeta)): object and the second element is a sequence of StreamUnaryTestMethodMessages objects. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def stream_stream_scenarios(self): - """Affords stream-request-stream-response test methods and their messages. + @abc.abstractmethod + def stream_stream_scenarios(self): + """Affords stream-request-stream-response test methods and their messages. Returns: A dict from method group-name pair to implementation/messages pair. The @@ -313,4 +316,4 @@ class TestService(six.with_metaclass(abc.ABCMeta)): object and the second element is a sequence of StreamStreamTestMethodMessages objects. """ - raise NotImplementedError() + raise NotImplementedError() diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_stock_service.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_stock_service.py index 5299655bb3b..41a55c13f4d 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_stock_service.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/_stock_service.py @@ -26,7 +26,6 @@ # 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. - """Examples of Python implementations of the stock.proto Stock service.""" from grpc.framework.common import cardinality @@ -44,353 +43,363 @@ _price = lambda symbol_name: float(hash(symbol_name) % 4096) def _get_last_trade_price(stock_request, stock_reply_callback, control, active): - """A unary-request, unary-response test method.""" - control.control() - if active(): - stock_reply_callback( - stock_pb2.StockReply( - symbol=stock_request.symbol, price=_price(stock_request.symbol))) - else: - raise abandonment.Abandoned() - - -def _get_last_trade_price_multiple(stock_reply_consumer, control, active): - """A stream-request, stream-response test method.""" - def stock_reply_for_stock_request(stock_request): + """A unary-request, unary-response test method.""" control.control() if active(): - return stock_pb2.StockReply( - symbol=stock_request.symbol, price=_price(stock_request.symbol)) + stock_reply_callback( + stock_pb2.StockReply( + symbol=stock_request.symbol, price=_price( + stock_request.symbol))) else: - raise abandonment.Abandoned() - - class StockRequestConsumer(stream.Consumer): + raise abandonment.Abandoned() - def consume(self, stock_request): - stock_reply_consumer.consume(stock_reply_for_stock_request(stock_request)) - def terminate(self): - control.control() - stock_reply_consumer.terminate() +def _get_last_trade_price_multiple(stock_reply_consumer, control, active): + """A stream-request, stream-response test method.""" - def consume_and_terminate(self, stock_request): - stock_reply_consumer.consume_and_terminate( - stock_reply_for_stock_request(stock_request)) + def stock_reply_for_stock_request(stock_request): + control.control() + if active(): + return stock_pb2.StockReply( + symbol=stock_request.symbol, price=_price(stock_request.symbol)) + else: + raise abandonment.Abandoned() - return StockRequestConsumer() + class StockRequestConsumer(stream.Consumer): + def consume(self, stock_request): + stock_reply_consumer.consume( + stock_reply_for_stock_request(stock_request)) -def _watch_future_trades(stock_request, stock_reply_consumer, control, active): - """A unary-request, stream-response test method.""" - base_price = _price(stock_request.symbol) - for index in range(stock_request.num_trades_to_watch): - control.control() - if active(): - stock_reply_consumer.consume( - stock_pb2.StockReply( - symbol=stock_request.symbol, price=base_price + index)) - else: - raise abandonment.Abandoned() - stock_reply_consumer.terminate() + def terminate(self): + control.control() + stock_reply_consumer.terminate() + def consume_and_terminate(self, stock_request): + stock_reply_consumer.consume_and_terminate( + stock_reply_for_stock_request(stock_request)) -def _get_highest_trade_price(stock_reply_callback, control, active): - """A stream-request, unary-response test method.""" + return StockRequestConsumer() - class StockRequestConsumer(stream.Consumer): - """Keeps an ongoing record of the most valuable symbol yet consumed.""" - def __init__(self): - self._symbol = None - self._price = None - - def consume(self, stock_request): - control.control() - if active(): - if self._price is None: - self._symbol = stock_request.symbol - self._price = _price(stock_request.symbol) - else: - candidate_price = _price(stock_request.symbol) - if self._price < candidate_price: - self._symbol = stock_request.symbol - self._price = candidate_price - - def terminate(self): - control.control() - if active(): - if self._symbol is None: - raise ValueError() - else: - stock_reply_callback( - stock_pb2.StockReply(symbol=self._symbol, price=self._price)) - self._symbol = None - self._price = None - - def consume_and_terminate(self, stock_request): - control.control() - if active(): - if self._price is None: - stock_reply_callback( - stock_pb2.StockReply( - symbol=stock_request.symbol, - price=_price(stock_request.symbol))) - else: - candidate_price = _price(stock_request.symbol) - if self._price < candidate_price: - stock_reply_callback( - stock_pb2.StockReply( - symbol=stock_request.symbol, price=candidate_price)) - else: - stock_reply_callback( +def _watch_future_trades(stock_request, stock_reply_consumer, control, active): + """A unary-request, stream-response test method.""" + base_price = _price(stock_request.symbol) + for index in range(stock_request.num_trades_to_watch): + control.control() + if active(): + stock_reply_consumer.consume( stock_pb2.StockReply( - symbol=self._symbol, price=self._price)) + symbol=stock_request.symbol, price=base_price + index)) + else: + raise abandonment.Abandoned() + stock_reply_consumer.terminate() - self._symbol = None - self._price = None - return StockRequestConsumer() +def _get_highest_trade_price(stock_reply_callback, control, active): + """A stream-request, unary-response test method.""" + + class StockRequestConsumer(stream.Consumer): + """Keeps an ongoing record of the most valuable symbol yet consumed.""" + + def __init__(self): + self._symbol = None + self._price = None + + def consume(self, stock_request): + control.control() + if active(): + if self._price is None: + self._symbol = stock_request.symbol + self._price = _price(stock_request.symbol) + else: + candidate_price = _price(stock_request.symbol) + if self._price < candidate_price: + self._symbol = stock_request.symbol + self._price = candidate_price + + def terminate(self): + control.control() + if active(): + if self._symbol is None: + raise ValueError() + else: + stock_reply_callback( + stock_pb2.StockReply( + symbol=self._symbol, price=self._price)) + self._symbol = None + self._price = None + + def consume_and_terminate(self, stock_request): + control.control() + if active(): + if self._price is None: + stock_reply_callback( + stock_pb2.StockReply( + symbol=stock_request.symbol, + price=_price(stock_request.symbol))) + else: + candidate_price = _price(stock_request.symbol) + if self._price < candidate_price: + stock_reply_callback( + stock_pb2.StockReply( + symbol=stock_request.symbol, + price=candidate_price)) + else: + stock_reply_callback( + stock_pb2.StockReply( + symbol=self._symbol, price=self._price)) + + self._symbol = None + self._price = None + + return StockRequestConsumer() class GetLastTradePrice(_service.UnaryUnaryTestMethodImplementation): - """GetLastTradePrice for use in tests.""" + """GetLastTradePrice for use in tests.""" - def group(self): - return _STOCK_GROUP_NAME + def group(self): + return _STOCK_GROUP_NAME - def name(self): - return 'GetLastTradePrice' + def name(self): + return 'GetLastTradePrice' - def cardinality(self): - return cardinality.Cardinality.UNARY_UNARY + def cardinality(self): + return cardinality.Cardinality.UNARY_UNARY - def request_class(self): - return stock_pb2.StockRequest + def request_class(self): + return stock_pb2.StockRequest - def response_class(self): - return stock_pb2.StockReply + def response_class(self): + return stock_pb2.StockReply - def serialize_request(self, request): - return request.SerializeToString() + def serialize_request(self, request): + return request.SerializeToString() - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) + def deserialize_request(self, serialized_request): + return stock_pb2.StockRequest.FromString(serialized_request) - def serialize_response(self, response): - return response.SerializeToString() + def serialize_response(self, response): + return response.SerializeToString() - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) + def deserialize_response(self, serialized_response): + return stock_pb2.StockReply.FromString(serialized_response) - def service(self, request, response_callback, context, control): - _get_last_trade_price( - request, response_callback, control, context.is_active) + def service(self, request, response_callback, context, control): + _get_last_trade_price(request, response_callback, control, + context.is_active) class GetLastTradePriceMessages(_service.UnaryUnaryTestMessages): - def __init__(self): - self._index = 0 + def __init__(self): + self._index = 0 - def request(self): - symbol = _SYMBOL_FORMAT % self._index - self._index += 1 - return stock_pb2.StockRequest(symbol=symbol) + def request(self): + symbol = _SYMBOL_FORMAT % self._index + self._index += 1 + return stock_pb2.StockRequest(symbol=symbol) - def verify(self, request, response, test_case): - test_case.assertEqual(request.symbol, response.symbol) - test_case.assertEqual(_price(request.symbol), response.price) + def verify(self, request, response, test_case): + test_case.assertEqual(request.symbol, response.symbol) + test_case.assertEqual(_price(request.symbol), response.price) class GetLastTradePriceMultiple(_service.StreamStreamTestMethodImplementation): - """GetLastTradePriceMultiple for use in tests.""" + """GetLastTradePriceMultiple for use in tests.""" - def group(self): - return _STOCK_GROUP_NAME + def group(self): + return _STOCK_GROUP_NAME - def name(self): - return 'GetLastTradePriceMultiple' + def name(self): + return 'GetLastTradePriceMultiple' - def cardinality(self): - return cardinality.Cardinality.STREAM_STREAM + def cardinality(self): + return cardinality.Cardinality.STREAM_STREAM - def request_class(self): - return stock_pb2.StockRequest + def request_class(self): + return stock_pb2.StockRequest - def response_class(self): - return stock_pb2.StockReply + def response_class(self): + return stock_pb2.StockReply - def serialize_request(self, request): - return request.SerializeToString() + def serialize_request(self, request): + return request.SerializeToString() - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) + def deserialize_request(self, serialized_request): + return stock_pb2.StockRequest.FromString(serialized_request) - def serialize_response(self, response): - return response.SerializeToString() + def serialize_response(self, response): + return response.SerializeToString() - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) + def deserialize_response(self, serialized_response): + return stock_pb2.StockReply.FromString(serialized_response) - def service(self, response_consumer, context, control): - return _get_last_trade_price_multiple( - response_consumer, control, context.is_active) + def service(self, response_consumer, context, control): + return _get_last_trade_price_multiple(response_consumer, control, + context.is_active) class GetLastTradePriceMultipleMessages(_service.StreamStreamTestMessages): - """Pairs of message streams for use with GetLastTradePriceMultiple.""" + """Pairs of message streams for use with GetLastTradePriceMultiple.""" - def __init__(self): - self._index = 0 + def __init__(self): + self._index = 0 - def requests(self): - base_index = self._index - self._index += 1 - return [ - stock_pb2.StockRequest(symbol=_SYMBOL_FORMAT % (base_index + index)) - for index in range(test_constants.STREAM_LENGTH)] + def requests(self): + base_index = self._index + self._index += 1 + return [ + stock_pb2.StockRequest(symbol=_SYMBOL_FORMAT % (base_index + index)) + for index in range(test_constants.STREAM_LENGTH) + ] - def verify(self, requests, responses, test_case): - test_case.assertEqual(len(requests), len(responses)) - for stock_request, stock_reply in zip(requests, responses): - test_case.assertEqual(stock_request.symbol, stock_reply.symbol) - test_case.assertEqual(_price(stock_request.symbol), stock_reply.price) + def verify(self, requests, responses, test_case): + test_case.assertEqual(len(requests), len(responses)) + for stock_request, stock_reply in zip(requests, responses): + test_case.assertEqual(stock_request.symbol, stock_reply.symbol) + test_case.assertEqual( + _price(stock_request.symbol), stock_reply.price) class WatchFutureTrades(_service.UnaryStreamTestMethodImplementation): - """WatchFutureTrades for use in tests.""" + """WatchFutureTrades for use in tests.""" - def group(self): - return _STOCK_GROUP_NAME + def group(self): + return _STOCK_GROUP_NAME - def name(self): - return 'WatchFutureTrades' + def name(self): + return 'WatchFutureTrades' - def cardinality(self): - return cardinality.Cardinality.UNARY_STREAM + def cardinality(self): + return cardinality.Cardinality.UNARY_STREAM - def request_class(self): - return stock_pb2.StockRequest + def request_class(self): + return stock_pb2.StockRequest - def response_class(self): - return stock_pb2.StockReply + def response_class(self): + return stock_pb2.StockReply - def serialize_request(self, request): - return request.SerializeToString() + def serialize_request(self, request): + return request.SerializeToString() - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) + def deserialize_request(self, serialized_request): + return stock_pb2.StockRequest.FromString(serialized_request) - def serialize_response(self, response): - return response.SerializeToString() + def serialize_response(self, response): + return response.SerializeToString() - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) + def deserialize_response(self, serialized_response): + return stock_pb2.StockReply.FromString(serialized_response) - def service(self, request, response_consumer, context, control): - _watch_future_trades(request, response_consumer, control, context.is_active) + def service(self, request, response_consumer, context, control): + _watch_future_trades(request, response_consumer, control, + context.is_active) class WatchFutureTradesMessages(_service.UnaryStreamTestMessages): - """Pairs of a single request message and a sequence of response messages.""" + """Pairs of a single request message and a sequence of response messages.""" - def __init__(self): - self._index = 0 + def __init__(self): + self._index = 0 - def request(self): - symbol = _SYMBOL_FORMAT % self._index - self._index += 1 - return stock_pb2.StockRequest( - symbol=symbol, num_trades_to_watch=test_constants.STREAM_LENGTH) + def request(self): + symbol = _SYMBOL_FORMAT % self._index + self._index += 1 + return stock_pb2.StockRequest( + symbol=symbol, num_trades_to_watch=test_constants.STREAM_LENGTH) - def verify(self, request, responses, test_case): - test_case.assertEqual(test_constants.STREAM_LENGTH, len(responses)) - base_price = _price(request.symbol) - for index, response in enumerate(responses): - test_case.assertEqual(base_price + index, response.price) + def verify(self, request, responses, test_case): + test_case.assertEqual(test_constants.STREAM_LENGTH, len(responses)) + base_price = _price(request.symbol) + for index, response in enumerate(responses): + test_case.assertEqual(base_price + index, response.price) class GetHighestTradePrice(_service.StreamUnaryTestMethodImplementation): - """GetHighestTradePrice for use in tests.""" + """GetHighestTradePrice for use in tests.""" - def group(self): - return _STOCK_GROUP_NAME + def group(self): + return _STOCK_GROUP_NAME - def name(self): - return 'GetHighestTradePrice' + def name(self): + return 'GetHighestTradePrice' - def cardinality(self): - return cardinality.Cardinality.STREAM_UNARY + def cardinality(self): + return cardinality.Cardinality.STREAM_UNARY - def request_class(self): - return stock_pb2.StockRequest + def request_class(self): + return stock_pb2.StockRequest - def response_class(self): - return stock_pb2.StockReply + def response_class(self): + return stock_pb2.StockReply - def serialize_request(self, request): - return request.SerializeToString() + def serialize_request(self, request): + return request.SerializeToString() - def deserialize_request(self, serialized_request): - return stock_pb2.StockRequest.FromString(serialized_request) + def deserialize_request(self, serialized_request): + return stock_pb2.StockRequest.FromString(serialized_request) - def serialize_response(self, response): - return response.SerializeToString() + def serialize_response(self, response): + return response.SerializeToString() - def deserialize_response(self, serialized_response): - return stock_pb2.StockReply.FromString(serialized_response) + def deserialize_response(self, serialized_response): + return stock_pb2.StockReply.FromString(serialized_response) - def service(self, response_callback, context, control): - return _get_highest_trade_price( - response_callback, control, context.is_active) + def service(self, response_callback, context, control): + return _get_highest_trade_price(response_callback, control, + context.is_active) class GetHighestTradePriceMessages(_service.StreamUnaryTestMessages): - def requests(self): - return [ - stock_pb2.StockRequest(symbol=_SYMBOL_FORMAT % index) - for index in range(test_constants.STREAM_LENGTH)] - - def verify(self, requests, response, test_case): - price = None - symbol = None - for stock_request in requests: - current_symbol = stock_request.symbol - current_price = _price(current_symbol) - if price is None or price < current_price: - price = current_price - symbol = current_symbol - test_case.assertEqual(price, response.price) - test_case.assertEqual(symbol, response.symbol) + def requests(self): + return [ + stock_pb2.StockRequest(symbol=_SYMBOL_FORMAT % index) + for index in range(test_constants.STREAM_LENGTH) + ] + + def verify(self, requests, response, test_case): + price = None + symbol = None + for stock_request in requests: + current_symbol = stock_request.symbol + current_price = _price(current_symbol) + if price is None or price < current_price: + price = current_price + symbol = current_symbol + test_case.assertEqual(price, response.price) + test_case.assertEqual(symbol, response.symbol) class StockTestService(_service.TestService): - """A corpus of test data with one method of each RPC cardinality.""" - - def unary_unary_scenarios(self): - return { - (_STOCK_GROUP_NAME, 'GetLastTradePrice'): ( - GetLastTradePrice(), [GetLastTradePriceMessages()]), - } - - def unary_stream_scenarios(self): - return { - (_STOCK_GROUP_NAME, 'WatchFutureTrades'): ( - WatchFutureTrades(), [WatchFutureTradesMessages()]), - } - - def stream_unary_scenarios(self): - return { - (_STOCK_GROUP_NAME, 'GetHighestTradePrice'): ( - GetHighestTradePrice(), [GetHighestTradePriceMessages()]) - } - - def stream_stream_scenarios(self): - return { - (_STOCK_GROUP_NAME, 'GetLastTradePriceMultiple'): ( - GetLastTradePriceMultiple(), [GetLastTradePriceMultipleMessages()]), - } + """A corpus of test data with one method of each RPC cardinality.""" + + def unary_unary_scenarios(self): + return { + (_STOCK_GROUP_NAME, 'GetLastTradePrice'): + (GetLastTradePrice(), [GetLastTradePriceMessages()]), + } + + def unary_stream_scenarios(self): + return { + (_STOCK_GROUP_NAME, 'WatchFutureTrades'): + (WatchFutureTrades(), [WatchFutureTradesMessages()]), + } + + def stream_unary_scenarios(self): + return { + (_STOCK_GROUP_NAME, 'GetHighestTradePrice'): + (GetHighestTradePrice(), [GetHighestTradePriceMessages()]) + } + + def stream_stream_scenarios(self): + return { + (_STOCK_GROUP_NAME, 'GetLastTradePriceMultiple'): + (GetLastTradePriceMultiple(), + [GetLastTradePriceMultipleMessages()]), + } STOCK_TEST_SERVICE = StockTestService() diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_cases.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_cases.py index 71de9d835e9..d84e1fc1361 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_cases.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_cases.py @@ -26,7 +26,6 @@ # 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. - """Tools for creating tests of implementations of the Face layer.""" # unittest is referenced from specification in this module. @@ -40,12 +39,11 @@ from tests.unit.framework.interfaces.face import test_interfaces # pylint: disa _TEST_CASE_SUPERCLASSES = ( _blocking_invocation_inline_service.TestCase, - _future_invocation_asynchronous_event_service.TestCase, -) + _future_invocation_asynchronous_event_service.TestCase,) def test_cases(implementation): - """Creates unittest.TestCase classes for a given Face layer implementation. + """Creates unittest.TestCase classes for a given Face layer implementation. Args: implementation: A test_interfaces.Implementation specifying creation and @@ -55,13 +53,14 @@ def test_cases(implementation): A sequence of subclasses of unittest.TestCase defining tests of the specified Face layer implementation. """ - test_case_classes = [] - for invoker_constructor in _invocation.invoker_constructors(): - for super_class in _TEST_CASE_SUPERCLASSES: - test_case_classes.append( - type(invoker_constructor.name() + super_class.NAME, (super_class,), - {'implementation': implementation, - 'invoker_constructor': invoker_constructor, - '__module__': implementation.__module__, - })) - return test_case_classes + test_case_classes = [] + for invoker_constructor in _invocation.invoker_constructors(): + for super_class in _TEST_CASE_SUPERCLASSES: + test_case_classes.append( + type(invoker_constructor.name() + super_class.NAME, ( + super_class,), { + 'implementation': implementation, + 'invoker_constructor': invoker_constructor, + '__module__': implementation.__module__, + })) + return test_case_classes diff --git a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_interfaces.py b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_interfaces.py index 40f38e68ba1..a789d435b48 100644 --- a/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_interfaces.py +++ b/src/python/grpcio_tests/tests/unit/framework/interfaces/face/test_interfaces.py @@ -26,7 +26,6 @@ # 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. - """Interfaces used in tests of implementations of the Face layer.""" import abc @@ -38,103 +37,102 @@ from grpc.framework.interfaces.face import face # pylint: disable=unused-import class Method(six.with_metaclass(abc.ABCMeta)): - """Specifies a method to be used in tests.""" + """Specifies a method to be used in tests.""" - @abc.abstractmethod - def group(self): - """Identify the group of the method. + @abc.abstractmethod + def group(self): + """Identify the group of the method. Returns: The group of the method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def name(self): - """Identify the name of the method. + @abc.abstractmethod + def name(self): + """Identify the name of the method. Returns: The name of the method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def cardinality(self): - """Identify the cardinality of the method. + @abc.abstractmethod + def cardinality(self): + """Identify the cardinality of the method. Returns: A cardinality.Cardinality value describing the streaming semantics of the method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def request_class(self): - """Identify the class used for the method's request objects. + @abc.abstractmethod + def request_class(self): + """Identify the class used for the method's request objects. Returns: The class object of the class to which the method's request objects belong. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def response_class(self): - """Identify the class used for the method's response objects. + @abc.abstractmethod + def response_class(self): + """Identify the class used for the method's response objects. Returns: The class object of the class to which the method's response objects belong. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def serialize_request(self, request): - """Serialize the given request object. + @abc.abstractmethod + def serialize_request(self, request): + """Serialize the given request object. Args: request: A request object appropriate for this method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def deserialize_request(self, serialized_request): - """Synthesize a request object from a given bytestring. + @abc.abstractmethod + def deserialize_request(self, serialized_request): + """Synthesize a request object from a given bytestring. Args: serialized_request: A bytestring deserializable into a request object appropriate for this method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def serialize_response(self, response): - """Serialize the given response object. + @abc.abstractmethod + def serialize_response(self, response): + """Serialize the given response object. Args: response: A response object appropriate for this method. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def deserialize_response(self, serialized_response): - """Synthesize a response object from a given bytestring. + @abc.abstractmethod + def deserialize_response(self, serialized_response): + """Synthesize a response object from a given bytestring. Args: serialized_response: A bytestring deserializable into a response object appropriate for this method. """ - raise NotImplementedError() + raise NotImplementedError() class Implementation(six.with_metaclass(abc.ABCMeta)): - """Specifies an implementation of the Face layer.""" + """Specifies an implementation of the Face layer.""" - @abc.abstractmethod - def instantiate( - self, methods, method_implementations, - multi_method_implementation): - """Instantiates the Face layer implementation to be used in a test. + @abc.abstractmethod + def instantiate(self, methods, method_implementations, + multi_method_implementation): + """Instantiates the Face layer implementation to be used in a test. Args: methods: A sequence of Method objects describing the methods available to @@ -151,69 +149,69 @@ class Implementation(six.with_metaclass(abc.ABCMeta)): passed to destantiate at the conclusion of the test. The returned stubs must be backed by the provided implementations. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def destantiate(self, memo): - """Destroys the Face layer implementation under test. + @abc.abstractmethod + def destantiate(self, memo): + """Destroys the Face layer implementation under test. Args: memo: The object from the third position of the return value of a call to instantiate. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def invocation_metadata(self): - """Provides the metadata to be used when invoking a test RPC. + @abc.abstractmethod + def invocation_metadata(self): + """Provides the metadata to be used when invoking a test RPC. Returns: An object to use as the supplied-at-invocation-time metadata in a test RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def initial_metadata(self): - """Provides the metadata for use as a test RPC's first servicer metadata. + @abc.abstractmethod + def initial_metadata(self): + """Provides the metadata for use as a test RPC's first servicer metadata. Returns: An object to use as the from-the-servicer-before-responses metadata in a test RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def terminal_metadata(self): - """Provides the metadata for use as a test RPC's second servicer metadata. + @abc.abstractmethod + def terminal_metadata(self): + """Provides the metadata for use as a test RPC's second servicer metadata. Returns: An object to use as the from-the-servicer-after-all-responses metadata in a test RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def code(self): - """Provides the value for use as a test RPC's code. + @abc.abstractmethod + def code(self): + """Provides the value for use as a test RPC's code. Returns: An object to use as the from-the-servicer code in a test RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def details(self): - """Provides the value for use as a test RPC's details. + @abc.abstractmethod + def details(self): + """Provides the value for use as a test RPC's details. Returns: An object to use as the from-the-servicer details in a test RPC. """ - raise NotImplementedError() + raise NotImplementedError() - @abc.abstractmethod - def metadata_transmitted(self, original_metadata, transmitted_metadata): - """Identifies whether or not metadata was properly transmitted. + @abc.abstractmethod + def metadata_transmitted(self, original_metadata, transmitted_metadata): + """Identifies whether or not metadata was properly transmitted. Args: original_metadata: A metadata value passed to the Face interface @@ -226,4 +224,4 @@ class Implementation(six.with_metaclass(abc.ABCMeta)): Whether or not the metadata was properly transmitted by the Face interface implementation under test. """ - raise NotImplementedError() + raise NotImplementedError() diff --git a/src/python/grpcio_tests/tests/unit/resources.py b/src/python/grpcio_tests/tests/unit/resources.py index 023cdb155f2..55a2fff979b 100644 --- a/src/python/grpcio_tests/tests/unit/resources.py +++ b/src/python/grpcio_tests/tests/unit/resources.py @@ -26,7 +26,6 @@ # 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. - """Constants and functions for data used in interoperability testing.""" import os @@ -39,14 +38,14 @@ _CERTIFICATE_CHAIN_RESOURCE_PATH = 'credentials/server1.pem' def test_root_certificates(): - return pkg_resources.resource_string( - __name__, _ROOT_CERTIFICATES_RESOURCE_PATH) + return pkg_resources.resource_string(__name__, + _ROOT_CERTIFICATES_RESOURCE_PATH) def private_key(): - return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) + return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) def certificate_chain(): - return pkg_resources.resource_string( - __name__, _CERTIFICATE_CHAIN_RESOURCE_PATH) + return pkg_resources.resource_string(__name__, + _CERTIFICATE_CHAIN_RESOURCE_PATH) diff --git a/src/python/grpcio_tests/tests/unit/test_common.py b/src/python/grpcio_tests/tests/unit/test_common.py index cd71bd80d75..00fbe0567a2 100644 --- a/src/python/grpcio_tests/tests/unit/test_common.py +++ b/src/python/grpcio_tests/tests/unit/test_common.py @@ -26,7 +26,6 @@ # 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. - """Common code used throughout tests of gRPC.""" import collections @@ -34,14 +33,23 @@ import collections import grpc import six -INVOCATION_INITIAL_METADATA = (('0', 'abc'), ('1', 'def'), ('2', 'ghi'),) -SERVICE_INITIAL_METADATA = (('3', 'jkl'), ('4', 'mno'), ('5', 'pqr'),) -SERVICE_TERMINAL_METADATA = (('6', 'stu'), ('7', 'vwx'), ('8', 'yza'),) +INVOCATION_INITIAL_METADATA = ( + ('0', 'abc'), + ('1', 'def'), + ('2', 'ghi'),) +SERVICE_INITIAL_METADATA = ( + ('3', 'jkl'), + ('4', 'mno'), + ('5', 'pqr'),) +SERVICE_TERMINAL_METADATA = ( + ('6', 'stu'), + ('7', 'vwx'), + ('8', 'yza'),) DETAILS = 'test details' def metadata_transmitted(original_metadata, transmitted_metadata): - """Judges whether or not metadata was acceptably transmitted. + """Judges whether or not metadata was acceptably transmitted. gRPC is allowed to insert key-value pairs into the metadata values given by applications and to reorder key-value pairs with different keys but it is not @@ -59,31 +67,30 @@ def metadata_transmitted(original_metadata, transmitted_metadata): A boolean indicating whether transmitted_metadata accurately reflects original_metadata after having been transmitted via gRPC. """ - original = collections.defaultdict(list) - for key, value in original_metadata: - original[key].append(value) - transmitted = collections.defaultdict(list) - for key, value in transmitted_metadata: - transmitted[key].append(value) + original = collections.defaultdict(list) + for key, value in original_metadata: + original[key].append(value) + transmitted = collections.defaultdict(list) + for key, value in transmitted_metadata: + transmitted[key].append(value) - for key, values in six.iteritems(original): - transmitted_values = transmitted[key] - transmitted_iterator = iter(transmitted_values) - try: - for value in values: - while True: - transmitted_value = next(transmitted_iterator) - if value == transmitted_value: - break - except StopIteration: - return False - else: - return True + for key, values in six.iteritems(original): + transmitted_values = transmitted[key] + transmitted_iterator = iter(transmitted_values) + try: + for value in values: + while True: + transmitted_value = next(transmitted_iterator) + if value == transmitted_value: + break + except StopIteration: + return False + else: + return True -def test_secure_channel( - target, channel_credentials, server_host_override): - """Creates an insecure Channel to a remote host. +def test_secure_channel(target, channel_credentials, server_host_override): + """Creates an insecure Channel to a remote host. Args: host: The name of the remote host to which to connect. @@ -96,7 +103,7 @@ def test_secure_channel( An implementations.Channel to the remote host through which RPCs may be conducted. """ - channel = grpc.secure_channel( - target, channel_credentials, - (('grpc.ssl_target_name_override', server_host_override,),)) - return channel + channel = grpc.secure_channel(target, channel_credentials, (( + 'grpc.ssl_target_name_override', + server_host_override,),)) + return channel From c781f6451887ee5b47623c511ba337b08532f583 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 17 Jan 2017 11:47:06 -0800 Subject: [PATCH 098/104] Use config file template instead of Rakefile template --- Rakefile | 4 +- build_config.rb | 3 + templates/Rakefile.template | 126 ----------------------------- templates/build_config.rb.template | 5 ++ 4 files changed, 11 insertions(+), 127 deletions(-) create mode 100644 build_config.rb delete mode 100644 templates/Rakefile.template create mode 100644 templates/build_config.rb.template diff --git a/Rakefile b/Rakefile index 8a88b4401f5..c8bca20ad1d 100755 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,8 @@ require 'rubocop/rake_task' require 'bundler/gem_tasks' require 'fileutils' +require_relative 'build_config.rb' + load 'tools/distrib/docker_for_windows.rb' # Add rubocop style checking tasks @@ -83,7 +85,7 @@ task 'dlls' do env += 'EMBED_ZLIB=true ' env += 'BUILDDIR=/tmp ' env += "V=#{verbose} " - out = '/tmp/libs/opt/grpc-2.dll' + out = GrpcBuildConfig::CORE_WINDOWS_DLL w64 = { cross: 'x86_64-w64-mingw32', out: 'grpc_c.64.ruby' } w32 = { cross: 'i686-w64-mingw32', out: 'grpc_c.32.ruby' } diff --git a/build_config.rb b/build_config.rb new file mode 100644 index 00000000000..83edb1c3900 --- /dev/null +++ b/build_config.rb @@ -0,0 +1,3 @@ +module GrpcBuildConfig + CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-2.dll' +end diff --git a/templates/Rakefile.template b/templates/Rakefile.template deleted file mode 100644 index 2ab505b7c10..00000000000 --- a/templates/Rakefile.template +++ /dev/null @@ -1,126 +0,0 @@ -%YAML 1.2 ---- | - # -*- ruby -*- - require 'rake/extensiontask' - require 'rspec/core/rake_task' - require 'rubocop/rake_task' - require 'bundler/gem_tasks' - require 'fileutils' - - load 'tools/distrib/docker_for_windows.rb' - - # Add rubocop style checking tasks - RuboCop::RakeTask.new(:rubocop) do |task| - task.options = ['-c', 'src/ruby/.rubocop.yml'] - task.patterns = ['src/ruby/{lib,spec}/**/*.rb'] - end - - spec = Gem::Specification.load('grpc.gemspec') - - Gem::PackageTask.new(spec) do |pkg| - end - - # Add the extension compiler task - Rake::ExtensionTask.new('grpc_c', spec) do |ext| - ext.source_pattern = '**/*.{c,h}' - ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc') - ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc') - ext.cross_compile = true - ext.cross_platform = [ - 'x86-mingw32', 'x64-mingw32', - 'x86_64-linux', 'x86-linux', - 'universal-darwin' - ] - ext.cross_compiling do |spec| - spec.files = %w( etc/roots.pem grpc_c.32.ruby grpc_c.64.ruby ) - spec.files += Dir.glob('src/ruby/bin/**/*') - spec.files += Dir.glob('src/ruby/ext/**/*') - spec.files += Dir.glob('src/ruby/lib/**/*') - spec.files += Dir.glob('src/ruby/pb/**/*') - end - end - - # Define the test suites - SPEC_SUITES = [ - { id: :wrapper, title: 'wrapper layer', files: %w(src/ruby/spec/*.rb) }, - { id: :idiomatic, title: 'idiomatic layer', dir: %w(src/ruby/spec/generic), - tags: ['~bidi', '~server'] }, - { id: :bidi, title: 'bidi tests', dir: %w(src/ruby/spec/generic), - tag: 'bidi' }, - { id: :server, title: 'rpc server thread tests', dir: %w(src/ruby/spec/generic), - tag: 'server' }, - { id: :pb, title: 'protobuf service tests', dir: %w(src/ruby/spec/pb) } - ] - namespace :suite do - SPEC_SUITES.each do |suite| - desc "Run all specs in the #{suite[:title]} spec suite" - RSpec::Core::RakeTask.new(suite[:id]) do |t| - ENV['COVERAGE_NAME'] = suite[:id].to_s - spec_files = [] - suite[:files].each { |f| spec_files += Dir[f] } if suite[:files] - - if suite[:dir] - suite[:dir].each { |f| spec_files += Dir["#{f}/**/*_spec.rb"] } - end - helper = 'src/ruby/spec/spec_helper.rb' - spec_files << helper unless spec_files.include?(helper) - - t.pattern = spec_files - t.rspec_opts = "--tag #{suite[:tag]}" if suite[:tag] - if suite[:tags] - t.rspec_opts = suite[:tags].map { |x| "--tag #{x}" }.join(' ') - end - end - end - end - - desc 'Build the Windows gRPC DLLs for Ruby' - task 'dlls' do - grpc_config = ENV['GRPC_CONFIG'] || 'opt' - verbose = ENV['V'] || '0' - - env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result" ' - env += 'LDFLAGS=-static ' - env += 'SYSTEM=MINGW32 ' - env += 'EMBED_ZLIB=true ' - env += 'BUILDDIR=/tmp ' - env += "V=#{verbose} " - out = '/tmp/libs/opt/grpc-${settings.core_version.major}.dll' - - w64 = { cross: 'x86_64-w64-mingw32', out: 'grpc_c.64.ruby' } - w32 = { cross: 'i686-w64-mingw32', out: 'grpc_c.32.ruby' } - - [ w64, w32 ].each do |opt| - env_comp = "CC=#{opt[:cross]}-gcc " - env_comp += "LD=#{opt[:cross]}-gcc " - docker_for_windows "#{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}" - end - - end - - desc 'Build the native gem file under rake_compiler_dock' - task 'gem:native' do - verbose = ENV['V'] || '0' - - grpc_config = ENV['GRPC_CONFIG'] || 'opt' - - if RUBY_PLATFORM =~ /darwin/ - FileUtils.touch 'grpc_c.32.ruby' - FileUtils.touch 'grpc_c.64.ruby' - system "rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" - else - Rake::Task['dlls'].execute - docker_for_windows "bundle && rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" - end - end - - # Define dependencies between the suites. - task 'suite:wrapper' => [:compile, :rubocop] - task 'suite:idiomatic' => 'suite:wrapper' - task 'suite:bidi' => 'suite:wrapper' - task 'suite:server' => 'suite:wrapper' - task 'suite:pb' => 'suite:server' - - desc 'Compiles the gRPC extension then runs all the tests' - task all: ['suite:idiomatic', 'suite:bidi', 'suite:pb', 'suite:server'] - task default: :all diff --git a/templates/build_config.rb.template b/templates/build_config.rb.template new file mode 100644 index 00000000000..4cb4810d335 --- /dev/null +++ b/templates/build_config.rb.template @@ -0,0 +1,5 @@ +%YAML 1.2 +--- | + module GrpcBuildConfig + CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-${settings.core_version.major}.dll' + end \ No newline at end of file From 5aa2bcfd4dea92ca18b7b6b0b3f40d1b8fabc246 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Tue, 17 Jan 2017 23:31:17 +0000 Subject: [PATCH 099/104] Pass an iterator rather than an iterable This should have been included in dd52a31337616fe935f79debfe5d56c6d73a but was missed because it falsely passes almost all of the time. --- src/python/grpcio_tests/tests/unit/beta/_not_found_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py b/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py index 664e47c7696..ce7b91e9fe9 100644 --- a/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py +++ b/src/python/grpcio_tests/tests/unit/beta/_not_found_test.py @@ -62,7 +62,7 @@ class NotFoundTest(unittest.TestCase): def test_future_stream_unary_not_found(self): rpc_future = self._generic_stub.future_stream_unary( - 'grupe', 'mevvod', [b'def'], test_constants.LONG_TIMEOUT) + 'grupe', 'mevvod', iter([b'def']), test_constants.LONG_TIMEOUT) with self.assertRaises(face.LocalError) as exception_assertion_context: rpc_future.result() self.assertIs(exception_assertion_context.exception.code, From 57b02fcaba2162631d787b4349b42146efdc45ab Mon Sep 17 00:00:00 2001 From: Adele Zhou Date: Tue, 17 Jan 2017 14:18:41 -0800 Subject: [PATCH 100/104] merge --- tools/run_tests/run_interop_tests.py | 44 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py index 56efac50ca0..b2dac7d1a87 100755 --- a/tools/run_tests/run_interop_tests.py +++ b/tools/run_tests/run_interop_tests.py @@ -86,7 +86,7 @@ class CXXLanguage: return {} def server_cmd(self, args): - return ['bins/opt/interop_server', '--use_tls=true'] + args + return ['bins/opt/interop_server'] + args def global_env(self): return {} @@ -115,7 +115,7 @@ class CSharpLanguage: return {} def server_cmd(self, args): - return ['mono', 'Grpc.IntegrationTesting.Server.exe', '--use_tls=true'] + args + return ['mono', 'Grpc.IntegrationTesting.Server.exe'] + args def global_env(self): return {} @@ -144,7 +144,7 @@ class CSharpCoreCLRLanguage: return {} def server_cmd(self, args): - return ['dotnet', 'exec', 'Grpc.IntegrationTesting.Server.dll', '--use_tls=true'] + args + return ['dotnet', 'exec', 'Grpc.IntegrationTesting.Server.dll'] + args def global_env(self): return {} @@ -176,7 +176,7 @@ class JavaLanguage: return {} def server_cmd(self, args): - return ['./run-test-server.sh', '--use_tls=true'] + args + return ['./run-test-server.sh'] + args def global_env(self): return {} @@ -206,7 +206,7 @@ class GoLanguage: return {} def server_cmd(self, args): - return ['go', 'run', 'server.go', '--use_tls=true'] + args + return ['go', 'run', 'server.go'] + args def global_env(self): return {} @@ -292,8 +292,7 @@ class NodeLanguage: def server_cmd(self, args): return ['tools/run_tests/interop/with_nvm.sh', - 'node', 'src/node/interop/interop_server.js', - '--use_tls=true'] + args + 'node', 'src/node/interop/interop_server.js'] + args def global_env(self): return {} @@ -374,7 +373,7 @@ class RubyLanguage: def server_cmd(self, args): return ['tools/run_tests/interop/with_rvm.sh', - 'ruby', 'src/ruby/pb/test/server.rb', '--use_tls=true'] + args + 'ruby', 'src/ruby/pb/test/server.rb'] + args def global_env(self): return {} @@ -419,7 +418,7 @@ class PythonLanguage: 'src/python/grpcio_tests/setup.py', 'run_interop', '--server', - '--args="{}"'.format(' '.join(args) + ' --use_tls=true') + '--args="{}"'.format(' '.join(args)) ] def global_env(self): @@ -586,11 +585,11 @@ def cloud_to_prod_jobspec(language, test_case, server_host_name, def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, - server_port, docker_image=None): + server_port, docker_image=None, insecure=False): """Creates jobspec for cloud-to-cloud interop test""" interop_only_options = [ '--server_host_override=foo.test.google.fr', - '--use_tls=true', + '--use_tls=%s' % ('false' if insecure else 'true'), '--use_test_ca=true', ] common_options = [ @@ -634,11 +633,12 @@ def cloud_to_cloud_jobspec(language, test_case, server_name, server_host, return test_job -def server_jobspec(language, docker_image): +def server_jobspec(language, docker_image, insecure=False): """Create jobspec for running a server""" container_name = dockerjob.random_name('interop_server_%s' % language.safename) cmdline = bash_cmdline( - language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT])) + language.server_cmd(['--port=%s' % _DEFAULT_SERVER_PORT, + '--use_tls=%s' % ('false' if insecure else 'true')])) environ = language.global_env() if language.safename == 'http2': # we are running the http2 interop server. Open next N ports beginning @@ -803,6 +803,11 @@ argp.add_argument('--http2_badserver_interop', action='store_const', const=True, help='Enable HTTP/2 server edge case testing. (Good client, bad server)') +argp.add_argument('--insecure', + default=False, + action='store_const', + const=True, + help='Whether to use secure channel.') args = argp.parse_args() @@ -868,7 +873,8 @@ server_addresses={} try: for s in servers: lang = str(s) - spec = server_jobspec(_LANGUAGES[lang], docker_images.get(lang)) + spec = server_jobspec(_LANGUAGES[lang], docker_images.get(lang), + args.insecure) job = dockerjob.DockerJob(spec) server_jobs[lang] = job server_addresses[lang] = ('localhost', job.mapped_port(_DEFAULT_SERVER_PORT)) @@ -883,6 +889,8 @@ try: jobs = [] if args.cloud_to_prod: + if args.insecure: + print('TLS is always enabled for cloud_to_prod scenarios.') for server_host_name in args.prod_servers: for language in languages: for test_case in _TEST_CASES: @@ -903,6 +911,8 @@ try: jobs.append(test_job) if args.cloud_to_prod_auth: + if args.insecure: + print('TLS is always enabled for cloud_to_prod scenarios.') for server_host_name in args.prod_servers: for language in languages: for test_case in _AUTH_TEST_CASES: @@ -934,7 +944,8 @@ try: server_name, server_host, server_port, - docker_image=docker_images.get(str(language))) + docker_image=docker_images.get(str(language)), + insecure=args.insecure) jobs.append(test_job) if args.http2_interop: @@ -947,7 +958,8 @@ try: server_name, server_host, server_port, - docker_image=docker_images.get(str(http2Interop))) + docker_image=docker_images.get(str(http2Interop)), + insecure=args.insecure) jobs.append(test_job) if args.http2_badserver_interop: From e375975e0d9e80516698271233a1d92ff1160a7f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 17 Jan 2017 16:32:23 -0800 Subject: [PATCH 101/104] Fixed sanity errors --- build_config.rb | 29 ++++++++++++++++++++++++++++ src/core/ext/census/tracing.c | 2 +- templates/build_config.rb.template | 31 +++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/build_config.rb b/build_config.rb index 83edb1c3900..35e887ef621 100644 --- a/build_config.rb +++ b/build_config.rb @@ -1,3 +1,32 @@ +# Copyright 2017, 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. + module GrpcBuildConfig CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-2.dll' end diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c index afb70441d28..9371fffc8d7 100644 --- a/src/core/ext/census/tracing.c +++ b/src/core/ext/census/tracing.c @@ -33,8 +33,8 @@ //#include "src/core/ext/census/tracing.h" -#include #include +#include /* TODO(aveitch): These are all placeholder implementations. */ diff --git a/templates/build_config.rb.template b/templates/build_config.rb.template index 4cb4810d335..0d9191b1a07 100644 --- a/templates/build_config.rb.template +++ b/templates/build_config.rb.template @@ -1,5 +1,34 @@ %YAML 1.2 --- | + # Copyright 2017, 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. + module GrpcBuildConfig CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-${settings.core_version.major}.dll' - end \ No newline at end of file + end From b4227370fc8b84fdf8d11c3d1ba94492347da1a8 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 18 Jan 2017 09:21:20 -0800 Subject: [PATCH 102/104] Code review changes and other improvements. --- doc/images/load-balancing.png | Bin 27733 -> 28073 bytes doc/images/load-balancing.svg | 2 +- doc/load-balancing.md | 67 +++++++++++++++++++++------------- doc/naming.md | 18 ++++++--- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/doc/images/load-balancing.png b/doc/images/load-balancing.png index 18b68bfdad83d15b33f37eeeb98f582feb8ee0c0..7c70465e653dcf732875e96ab80e65331ff7c67d 100644 GIT binary patch literal 28073 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எ zovxofG6*vO=hi6X6wBzzQ)1kAT33g+Wv!i9Iv@lm476@HDZkg!OjcS>qWR1eK?#5RSML$IyG z2uyvO!4AY|XRKqWe#fzLY_1`rmC8DI#D3OY+l%QnND@|4ILAr%6Y-1vY`DRWtI2l} zx-|NHf!ClW^BQRw@MS-{%umF`h0!GNsCf`G;;7r4@psYx>Gmz-E%;x$0R;bcQ)2vw z%wGn^N2nVpW&>pZZw$59lUKiI0uwv>@N76z@n1eXVgc}%45#yCN_Ic`^4!0UOm`=F zf<9XSK=1FEk4C1g=(1t{-~SEPkN#&XG5#e3%%L5m#He*ZpzhZjy{%__qvE>DqyGYX>j7;5 literal 27733 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≶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 - + diff --git a/doc/load-balancing.md b/doc/load-balancing.md index c5e59331c2d..1071961b116 100644 --- a/doc/load-balancing.md +++ b/doc/load-balancing.md @@ -1,17 +1,25 @@ Load Balancing in gRPC -======================= +====================== -# Objective +# Scope -To design a load balancing API between a gRPC client and a Load Balancer to -instruct the client how to send load to multiple backend servers. +This document explains the design for load balancing within gRPC. # Background +## Per-Call Load Balancing + +It is worth noting that load-balancing within gRPC happens on a per-call +basis, not a per-connection basis. In other words, even if all requests +come from a single client, we still want them to be load-balanced across +all servers. + +## Approaches to Load Balancing + Prior to any gRPC specifics, we explore some usual ways to approach load balancing. -## Proxy Model +### Proxy Model Using a proxy provides a solid trustable client that can report load to the load balancing system. Proxies typically require more resources to operate since they @@ -21,7 +29,7 @@ latency to the RPCs. The proxy model was deemed inefficient when considering request heavy services like storage. -## Balancing-aware Client +### Balancing-aware Client This thicker client places more of the load balancing logic in the client. For example, the client could contain many load balancing policies (Round Robin, @@ -41,7 +49,7 @@ It would also significantly complicate the client's code: the new design hides the load balancing complexity of multiple layers and presents it as a simple list of servers to the client. -## External Load Balancing Service +### External Load Balancing Service The client load balancing code is kept simple and portable, implementing well-known algorithms (e.g., Round Robin) for server selection. @@ -104,9 +112,7 @@ works: a load balancer address, and a [service config](service_config.md) that indicates which client-side load-balancing policy to use (e.g., `round_robin` or `grpclb`). -2. The client instantiates the load balancing policy, which is then - responsible for deciding which requests will be sent to which - addresses. +2. The client instantiates the load balancing policy. - Note: If all addresses returned by the resolver are balancer addresses, then the client will use the `grpclb` policy, regardless of what load-balancing policy was requested by the service config. @@ -114,19 +120,28 @@ works: by the service config. If no load-balancing policy is requested by the service config, then the client will default to a policy that picks the first available server address. -3. In the case of the `grpclb` policy, it opens a stream to one of the - balancer addresses returned by the resolver. It asks the balancer for - the server addresses to use for the server name originally requested by - the client (i.e., the same one originally passed to the name resolver). - - Note: Currently, the `grpclb` policy ignores any non-balancer - addresses returned by the resolver. However, in the future, it may - be changed to use these addresses as a fallback in case no balancers - can be contacted. -4. The gRPC servers to which the load balancer is directing the client - may report load to the load balancers, if that information is needed - by the load balancer's configuration. -5. The load balancer returns a server list to the gRPC client. If the - server list is empty, the call will block until a non-empty one is - received. -6. The gRPC client will send RPCs to the gRPC servers contained in - the server list from the Load Balancer. +3. The load balancing policy creates a subchannel to each server address. + - For all policies *except* `grpclb`, this means one subchannel for each + address returned by the resolver. Note that these policies + ignore any balancer addresses returned by the resolver. + - In the case of the `grpclb` policy, the workflow is as follows: + a. The policy opens a stream to one of the balancer addresses returned + by the resolver. It asks the balancer for the server addresses to + use for the server name originally requested by the client (i.e., + the same one originally passed to the name resolver). + - Note: The `grpclb` policy currently ignores any non-balancer + addresses returned by the resolver. However, in the future, it + may be changed to use these addresses as a fallback in case no + balancers can be contacted. + b. The gRPC servers to which the load balancer is directing the client + may report load to the load balancers, if that information is needed + by the load balancer's configuration. + c. The load balancer returns a server list to the gRPC client's `grpclb` + policy. The `grpclb` policy will then create a subchannel to each of + server in the list. +4. For each RPC sent, the load balancing policy decides which + subchannel (i.e., which server) the RPC should be sent to. + - In the case of the `grpclb` policy, the client will send requests + to the servers in the order in which they were returned by the load + balancer. If the server list is empty, the call will block until a + non-empty one is received. diff --git a/doc/naming.md b/doc/naming.md index 588f611f163..676aa9f2980 100644 --- a/doc/naming.md +++ b/doc/naming.md @@ -20,12 +20,18 @@ uses the syntax: scheme://authority/endpoint_name ``` -Here, `scheme` indicates the name-system to be used. Example schemes to -be supported include: +Here, `scheme` indicates the name-system to be used. Currently, we +support the following schemes: -* `dns` +- `dns` -* `etcd` +- `ipv4` (IPv4 address) + +- `ipv6` (IPv6 address) + +- `unix` (path to unix domain socket -- unix systems only) + +In the future, additional schemes such as `etcd` could be added. The `authority` indicates some scheme-specific bootstrap information, e.g., for DNS, the authority may include the IP[:port] of the DNS server to @@ -38,7 +44,7 @@ syntax of the endpoint name is dictated by the scheme in use. ### Resolver Plugins -The gRPC client library will switch on the scheme to pick the right +The gRPC client library will use the specified scheme to pick the right resolver plugin and pass it the fully qualified name string. Resolvers should be able to contact the authority and get a resolution @@ -46,7 +52,7 @@ that they return back to the gRPC client library. The returned contents include: - A list of resolved addresses, each of which has three attributes: - - The address itself, in IP:port form. + - The address itself, including both IP address and port. - A boolean indicating whether the address is a backend address (i.e., the address to use to contact the server directly) or a balancer address (for cases where [external load balancing](load-balancing.md) From e860359f231cdadc9ff1c8292ef869b91b8879d4 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 18 Jan 2017 09:22:26 -0800 Subject: [PATCH 103/104] Attempt to fix formatting. --- doc/load-balancing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/load-balancing.md b/doc/load-balancing.md index 1071961b116..f56d2b0c73a 100644 --- a/doc/load-balancing.md +++ b/doc/load-balancing.md @@ -125,7 +125,7 @@ works: address returned by the resolver. Note that these policies ignore any balancer addresses returned by the resolver. - In the case of the `grpclb` policy, the workflow is as follows: - a. The policy opens a stream to one of the balancer addresses returned + 1. The policy opens a stream to one of the balancer addresses returned by the resolver. It asks the balancer for the server addresses to use for the server name originally requested by the client (i.e., the same one originally passed to the name resolver). @@ -133,10 +133,10 @@ works: addresses returned by the resolver. However, in the future, it may be changed to use these addresses as a fallback in case no balancers can be contacted. - b. The gRPC servers to which the load balancer is directing the client + 2. The gRPC servers to which the load balancer is directing the client may report load to the load balancers, if that information is needed by the load balancer's configuration. - c. The load balancer returns a server list to the gRPC client's `grpclb` + 3. The load balancer returns a server list to the gRPC client's `grpclb` policy. The `grpclb` policy will then create a subchannel to each of server in the list. 4. For each RPC sent, the load balancing policy decides which From d0f7bf4a76be6e0f8d8212c8ce91d054f478f29c Mon Sep 17 00:00:00 2001 From: Yuchen Zeng Date: Wed, 18 Jan 2017 11:49:22 -0800 Subject: [PATCH 104/104] Document new args in grpc_resolver_create --- src/core/ext/client_channel/resolver_registry.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/ext/client_channel/resolver_registry.h b/src/core/ext/client_channel/resolver_registry.h index 4fb16131db9..a4606463ebd 100644 --- a/src/core/ext/client_channel/resolver_registry.h +++ b/src/core/ext/client_channel/resolver_registry.h @@ -60,7 +60,9 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory); return it. If a resolver factory was not found, return NULL. \a args is a set of channel arguments to be included in the result - (typically the set of arguments passed in from the client API). */ + (typically the set of arguments passed in from the client API). + \a pollset_set is used to drive IO in the name resolution process, it + should not be NULL. */ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target, const grpc_channel_args *args, grpc_pollset_set *pollset_set);