Merge remote-tracking branch 'upstream/master'

pull/6529/head
thinkerou 9 years ago
commit e43e27de3c
  1. 4
      BUILD
  2. 51
      Makefile
  3. 15
      build.yaml
  4. 14
      include/grpc++/impl/codegen/method_handler_impl.h
  5. 8
      include/grpc++/impl/server_builder_option.h
  6. 67
      include/grpc++/impl/server_builder_plugin.h
  7. 70
      include/grpc++/impl/server_initializer.h
  8. 8
      include/grpc++/server.h
  9. 13
      include/grpc++/server_builder.h
  10. 2
      package.json
  11. 19
      src/cpp/server/server.cc
  12. 36
      src/cpp/server/server_builder.cc
  13. 2
      src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
  14. 38
      src/csharp/Grpc.Examples/MathExamples.cs
  15. 29
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  16. 2
      src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
  17. 7
      src/node/tools/bin/protoc.js
  18. 8
      src/node/tools/bin/protoc_plugin.js
  19. 7
      src/proto/grpc/testing/echo_messages.proto
  20. 60
      src/python/grpcio/tests/qps/benchmark_client.py
  21. 2
      src/python/grpcio/tests/qps/client_runner.py
  22. 5
      src/python/grpcio/tests/qps/worker_server.py
  23. 7
      src/ruby/lib/grpc/generic/client_stub.rb
  24. 2
      src/ruby/tools/grpc-tools.gemspec
  25. 2
      templates/package.json.template
  26. 28
      test/cpp/end2end/async_end2end_test.cc
  27. 28
      test/cpp/end2end/end2end_test.cc
  28. 256
      test/cpp/end2end/server_builder_plugin_test.cc
  29. 8
      test/cpp/end2end/test_service_impl.cc
  30. 1
      test/cpp/end2end/test_service_impl.h
  31. 12
      test/cpp/qps/client_async.cc
  32. 6
      test/cpp/qps/server_async.cc
  33. 2
      third_party/protobuf
  34. 2
      tools/distrib/python/grpcio_tools/protoc_lib_deps.py
  35. 2
      tools/doxygen/Doxyfile.c++
  36. 2
      tools/doxygen/Doxyfile.c++.internal
  37. 42
      tools/gource/create_auth_context.h
  38. 47
      tools/gource/gen-all-logs.sh
  39. 12
      tools/gource/gource.sh
  40. 47
      tools/gource/make-video.sh
  41. 2
      tools/jenkins/run_performance.sh
  42. 2
      tools/run_tests/build_package_node.sh
  43. 5
      tools/run_tests/performance/build_performance.sh
  44. 44
      tools/run_tests/performance/build_performance_go.sh
  45. 3
      tools/run_tests/performance/kill_workers.sh
  46. 2
      tools/run_tests/performance/remote_host_prepare.sh
  47. 37
      tools/run_tests/performance/run_worker_go.sh
  48. 116
      tools/run_tests/performance/scenario_config.py
  49. 11
      tools/run_tests/run_performance_tests.py
  50. 2
      tools/run_tests/sanity/check_submodules.sh
  51. 22
      tools/run_tests/sources_and_headers.json
  52. 21
      tools/run_tests/tests.json
  53. 2
      vsprojects/vcxproj/grpc++/grpc++.vcxproj
  54. 6
      vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
  55. 2
      vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
  56. 6
      vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
  57. 207
      vsprojects/vcxproj/test/server_builder_plugin_test/server_builder_plugin_test.vcxproj
  58. 21
      vsprojects/vcxproj/test/server_builder_plugin_test/server_builder_plugin_test.vcxproj.filters

@ -892,6 +892,8 @@ cc_library(
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",
@ -1038,6 +1040,8 @@ cc_library(
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",

@ -1042,6 +1042,7 @@ reconnect_interop_client: $(BINDIR)/$(CONFIG)/reconnect_interop_client
reconnect_interop_server: $(BINDIR)/$(CONFIG)/reconnect_interop_server
secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
secure_sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test
server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test
server_crash_test: $(BINDIR)/$(CONFIG)/server_crash_test
server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client
shutdown_test: $(BINDIR)/$(CONFIG)/shutdown_test
@ -1410,6 +1411,7 @@ buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/reconnect_interop_server \
$(BINDIR)/$(CONFIG)/secure_auth_context_test \
$(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
$(BINDIR)/$(CONFIG)/server_builder_plugin_test \
$(BINDIR)/$(CONFIG)/server_crash_test \
$(BINDIR)/$(CONFIG)/server_crash_test_client \
$(BINDIR)/$(CONFIG)/shutdown_test \
@ -1743,6 +1745,8 @@ test_cxx: test_zookeeper buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 )
$(E) "[RUN] Testing secure_sync_unary_ping_pong_test"
$(Q) $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test || ( echo test secure_sync_unary_ping_pong_test failed ; exit 1 )
$(E) "[RUN] Testing server_builder_plugin_test"
$(Q) $(BINDIR)/$(CONFIG)/server_builder_plugin_test || ( echo test server_builder_plugin_test failed ; exit 1 )
$(E) "[RUN] Testing server_crash_test"
$(Q) $(BINDIR)/$(CONFIG)/server_crash_test || ( echo test server_crash_test failed ; exit 1 )
$(E) "[RUN] Testing shutdown_test"
@ -3213,6 +3217,8 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \
@ -3517,6 +3523,8 @@ PUBLIC_HEADERS_CXX += \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \
@ -11494,6 +11502,49 @@ endif
endif
SERVER_BUILDER_PLUGIN_TEST_SRC = \
test/cpp/end2end/server_builder_plugin_test.cc \
SERVER_BUILDER_PLUGIN_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_BUILDER_PLUGIN_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/server_builder_plugin_test: 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)/server_builder_plugin_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/server_builder_plugin_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_PLUGIN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(SERVER_BUILDER_PLUGIN_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_builder_plugin_test
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/end2end/server_builder_plugin_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_server_builder_plugin_test: $(SERVER_BUILDER_PLUGIN_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SERVER_BUILDER_PLUGIN_TEST_OBJS:.o=.dep)
endif
endif
SERVER_CRASH_TEST_SRC = \
test/cpp/end2end/server_crash_test.cc \

@ -591,6 +591,8 @@ filegroups:
- include/grpc++/impl/rpc_service_method.h
- include/grpc++/impl/serialization_traits.h
- include/grpc++/impl/server_builder_option.h
- include/grpc++/impl/server_builder_plugin.h
- include/grpc++/impl/server_initializer.h
- include/grpc++/impl/service_type.h
- include/grpc++/impl/sync.h
- include/grpc++/impl/sync_cxx11.h
@ -2915,6 +2917,19 @@ targets:
- mac
- linux
- posix
- name: server_builder_plugin_test
gtest: true
build: test
language: c++
src:
- test/cpp/end2end/server_builder_plugin_test.cc
deps:
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
- name: server_crash_test
gtest: true
cpu_cost: 0.1

@ -44,10 +44,10 @@ namespace grpc {
template <class ServiceType, class RequestType, class ResponseType>
class RpcMethodHandler : public MethodHandler {
public:
RpcMethodHandler(
std::function<Status(ServiceType*, ServerContext*, const RequestType*,
ResponseType*)> func,
ServiceType* service)
RpcMethodHandler(std::function<Status(ServiceType*, ServerContext*,
const RequestType*, ResponseType*)>
func,
ServiceType* service)
: func_(func), service_(service) {}
void RunHandler(const HandlerParameter& param) GRPC_FINAL {
@ -88,7 +88,8 @@ class ClientStreamingHandler : public MethodHandler {
public:
ClientStreamingHandler(
std::function<Status(ServiceType*, ServerContext*,
ServerReader<RequestType>*, ResponseType*)> func,
ServerReader<RequestType>*, ResponseType*)>
func,
ServiceType* service)
: func_(func), service_(service) {}
@ -124,7 +125,8 @@ class ServerStreamingHandler : public MethodHandler {
public:
ServerStreamingHandler(
std::function<Status(ServiceType*, ServerContext*, const RequestType*,
ServerWriter<ResponseType>*)> func,
ServerWriter<ResponseType>*)>
func,
ServiceType* service)
: func_(func), service_(service) {}

@ -34,6 +34,10 @@
#ifndef GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
#define GRPCXX_IMPL_SERVER_BUILDER_OPTION_H
#include <map>
#include <memory>
#include <grpc++/impl/server_builder_plugin.h>
#include <grpc++/support/channel_arguments.h>
namespace grpc {
@ -44,6 +48,10 @@ class ServerBuilderOption {
virtual ~ServerBuilderOption() {}
/// Alter the \a ChannelArguments used to create the gRPC server.
virtual void UpdateArguments(ChannelArguments* args) = 0;
/// Alter the ServerBuilderPlugin map that will be added into ServerBuilder.
virtual void UpdatePlugins(
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin> >*
plugins) = 0;
};
} // namespace grpc

@ -0,0 +1,67 @@
/*
*
* 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 GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H
#define GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H
#include <memory>
#include <grpc++/support/config.h>
namespace grpc {
class ServerInitializer;
class ServerBuilderPlugin {
public:
virtual ~ServerBuilderPlugin() {}
virtual grpc::string name() = 0;
// InitServer will be called in ServerBuilder::BuildAndStart(), after the
// Server instance is created.
virtual void InitServer(ServerInitializer* si) = 0;
// Finish will be called at the end of ServerBuilder::BuildAndStart().
virtual void Finish(ServerInitializer* si) = 0;
// ChangeArguments is an interface that can be used in
// ServerBuilderOption::UpdatePlugins
virtual void ChangeArguments(const grpc::string& name, void* value) = 0;
virtual bool has_sync_methods() const { return false; }
virtual bool has_async_methods() const { return false; }
};
} // namespace grpc
#endif // GRPCXX_IMPL_SERVER_BUILDER_PLUGIN_H

@ -0,0 +1,70 @@
/*
*
* 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 GRPCXX_IMPL_SERVER_INITIALIZER_H
#define GRPCXX_IMPL_SERVER_INITIALIZER_H
#include <memory>
#include <vector>
#include <grpc++/server.h>
namespace grpc {
class Server;
class Service;
class ServerInitializer {
public:
ServerInitializer(Server* server) : server_(server) {}
bool RegisterService(std::shared_ptr<Service> service) {
if (!server_->RegisterService(nullptr, service.get())) {
return false;
}
default_services_.push_back(service);
return true;
}
const std::vector<grpc::string>* GetServiceList() {
return &server_->services_;
}
private:
Server* server_;
std::vector<std::shared_ptr<Service> > default_services_;
};
} // namespace grpc
#endif // GRPCXX_IMPL_SERVER_INITIALIZER_H

@ -36,6 +36,7 @@
#include <list>
#include <memory>
#include <vector>
#include <grpc++/completion_queue.h>
#include <grpc++/impl/call.h>
@ -57,6 +58,7 @@ class GenericServerContext;
class AsyncGenericService;
class ServerAsyncStreamingInterface;
class ServerContext;
class ServerInitializer;
class ThreadPoolInterface;
/// Models a gRPC server.
@ -94,6 +96,7 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
private:
friend class AsyncGenericService;
friend class ServerBuilder;
friend class ServerInitializer;
class SyncRequest;
class AsyncRequest;
@ -159,6 +162,8 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
grpc_server* server() GRPC_OVERRIDE { return server_; };
ServerInitializer* initializer();
const int max_message_size_;
// Completion queue.
@ -175,6 +180,7 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
std::shared_ptr<GlobalCallbacks> global_callbacks_;
std::list<SyncRequest>* sync_methods_;
std::vector<grpc::string> services_;
std::unique_ptr<RpcServiceMethod> unknown_method_;
bool has_generic_service_;
@ -184,6 +190,8 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
ThreadPoolInterface* thread_pool_;
// Whether the thread pool is created and owned by the server.
bool thread_pool_owned_;
std::unique_ptr<ServerInitializer> server_initializer_;
};
} // namespace grpc

@ -34,10 +34,12 @@
#ifndef GRPCXX_SERVER_BUILDER_H
#define GRPCXX_SERVER_BUILDER_H
#include <map>
#include <memory>
#include <vector>
#include <grpc++/impl/server_builder_option.h>
#include <grpc++/impl/server_builder_plugin.h>
#include <grpc++/support/config.h>
#include <grpc/compression.h>
@ -51,6 +53,10 @@ class ServerCompletionQueue;
class ServerCredentials;
class Service;
namespace testing {
class ServerBuilderPluginTest;
} // namespace testing
/// A builder class for the creation and startup of \a grpc::Server instances.
class ServerBuilder {
public:
@ -107,7 +113,13 @@ class ServerBuilder {
/// Return a running server which is ready for processing calls.
std::unique_ptr<Server> BuildAndStart();
/// For internal use only: Register a ServerBuilderPlugin factory function.
static void InternalAddPluginFactory(
std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)());
private:
friend class ::grpc::testing::ServerBuilderPluginTest;
struct Port {
grpc::string addr;
std::shared_ptr<ServerCredentials> creds;
@ -130,6 +142,7 @@ class ServerBuilder {
std::vector<Port> ports_;
std::vector<ServerCompletionQueue*> cqs_;
std::shared_ptr<ServerCredentials> creds_;
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>> plugins_;
AsyncGenericService* generic_service_;
};

@ -67,6 +67,8 @@
"src/node/ext",
"include/grpc",
"src/core",
"src/boringssl",
"src/zlib",
"third_party/nanopb",
"third_party/zlib",
"third_party/boringssl",

@ -33,6 +33,7 @@
#include <grpc++/server.h>
#include <sstream>
#include <utility>
#include <grpc++/completion_queue.h>
@ -41,6 +42,7 @@
#include <grpc++/impl/grpc_library.h>
#include <grpc++/impl/method_handler_impl.h>
#include <grpc++/impl/rpc_service_method.h>
#include <grpc++/impl/server_initializer.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server_context.h>
@ -284,7 +286,8 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
has_generic_service_(false),
server_(nullptr),
thread_pool_(thread_pool),
thread_pool_owned_(thread_pool_owned) {
thread_pool_owned_(thread_pool_owned),
server_initializer_(new ServerInitializer(this)) {
g_gli_initializer.summon();
gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
global_callbacks_ = g_callbacks;
@ -341,6 +344,7 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
"Can only register an asynchronous service against one server.");
service->server_ = this;
}
const char* method_name = nullptr;
for (auto it = service->methods_.begin(); it != service->methods_.end();
++it) {
if (it->get() == nullptr) { // Handled by generic service if any.
@ -360,6 +364,17 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
} else {
sync_methods_->emplace_back(method, tag);
}
method_name = method->name();
}
// Parse service name.
if (method_name != nullptr) {
std::stringstream ss(method_name);
grpc::string service_name;
if (std::getline(ss, service_name, '/') &&
std::getline(ss, service_name, '/')) {
services_.push_back(service_name);
}
}
return true;
}
@ -598,4 +613,6 @@ void Server::RunRpc() {
}
}
ServerInitializer* Server::initializer() { return server_initializer_.get(); }
} // namespace grpc

@ -41,9 +41,23 @@
namespace grpc {
static std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>*
g_plugin_factory_list;
static gpr_once once_init_plugin_list = GPR_ONCE_INIT;
static void do_plugin_list_init(void) {
g_plugin_factory_list =
new std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>();
}
ServerBuilder::ServerBuilder()
: max_message_size_(-1), generic_service_(nullptr) {
grpc_compression_options_init(&compression_options_);
gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
for (auto factory : (*g_plugin_factory_list)) {
std::unique_ptr<ServerBuilderPlugin> plugin = factory();
plugins_[plugin->name()] = std::move(plugin);
}
}
std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue() {
@ -96,6 +110,15 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
ChannelArguments args;
for (auto option = options_.begin(); option != options_.end(); ++option) {
(*option)->UpdateArguments(&args);
(*option)->UpdatePlugins(&plugins_);
}
if (thread_pool == nullptr) {
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
if ((*plugin).second->has_sync_methods()) {
thread_pool.reset(CreateDefaultThreadPool());
break;
}
}
}
if (max_message_size_ > 0) {
args.SetInt(GRPC_ARG_MAX_MESSAGE_LENGTH, max_message_size_);
@ -104,6 +127,7 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
compression_options_.enabled_algorithms_bitset);
std::unique_ptr<Server> server(
new Server(thread_pool.release(), true, max_message_size_, &args));
ServerInitializer* initializer = server->initializer();
for (auto cq = cqs_.begin(); cq != cqs_.end(); ++cq) {
grpc_server_register_completion_queue(server->server_, (*cq)->cq(),
nullptr);
@ -114,6 +138,9 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
return nullptr;
}
}
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin).second->InitServer(initializer);
}
if (generic_service_) {
server->RegisterAsyncGenericService(generic_service_);
} else {
@ -137,7 +164,16 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
if (!server->Start(cqs_data, cqs_.size())) {
return nullptr;
}
for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
(*plugin).second->Finish(initializer);
}
return server;
}
void ServerBuilder::InternalAddPluginFactory(
std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)()) {
gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
(*g_plugin_factory_list).push_back(CreatePlugin);
}
} // namespace grpc

@ -92,7 +92,7 @@ namespace Math.Tests
public void DivByZero()
{
var ex = Assert.Throws<RpcException>(() => client.Div(new DivArgs { Dividend = 0, Divisor = 0 }));
Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode);
Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode);
}
[Test]

@ -32,6 +32,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Math
@ -109,5 +110,42 @@ namespace Math
DivReply result = await client.DivAsync(new DivArgs { Dividend = sum.Num_, Divisor = numbers.Count });
Console.WriteLine("Avg Result: " + result);
}
/// <summary>
/// Shows how to handle a call ending with non-OK status.
/// </summary>
public static async Task HandleErrorExample(Math.MathClient client)
{
try
{
DivReply result = await client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 });
}
catch (RpcException ex)
{
Console.WriteLine(string.Format("RPC ended with status {0}", ex.Status));
}
}
/// <summary>
/// Shows how to send request headers and how to access response headers
/// and response trailers.
/// </summary>
public static async Task MetadataExample(Math.MathClient client)
{
var requestHeaders = new Metadata
{
{ "custom-header", "custom-value" }
};
var call = client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 }, requestHeaders);
// Get response headers
Metadata responseHeaders = await call.ResponseHeadersAsync;
var result = await call;
// Get response trailers after the call has finished.
Metadata responseTrailers = call.GetTrailers();
}
}
}

@ -52,23 +52,15 @@ namespace Math
public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
{
if (request.Limit <= 0)
{
// keep streaming the sequence until cancelled.
IEnumerator<Num> fibEnumerator = FibInternal(long.MaxValue).GetEnumerator();
while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext())
{
await responseStream.WriteAsync(fibEnumerator.Current);
await Task.Delay(100);
}
}
var limit = request.Limit > 0 ? request.Limit : long.MaxValue;
var fibEnumerator = FibInternal(limit).GetEnumerator();
if (request.Limit > 0)
// Keep streaming the sequence until the call is cancelled.
// Use CancellationToken from ServerCallContext to detect the cancellation.
while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext())
{
foreach (var num in FibInternal(request.Limit))
{
await responseStream.WriteAsync(num);
}
await responseStream.WriteAsync(fibEnumerator.Current);
await Task.Delay(100);
}
}
@ -89,6 +81,13 @@ namespace Math
static DivReply DivInternal(DivArgs args)
{
if (args.Divisor == 0)
{
// One can finish the RPC with non-ok status by throwing RpcException instance.
// Alternatively, resulting status can be set using ServerCallContext.Status
throw new RpcException(new Status(StatusCode.InvalidArgument, "Division by zero"));
}
long quotient = args.Dividend / args.Divisor;
long remainder = args.Dividend % args.Divisor;
return new DivReply { Quotient = quotient, Remainder = remainder };

@ -311,7 +311,7 @@ namespace Grpc.IntegrationTesting
var snapshot = histogram.GetSnapshot(true);
var elapsedSnapshot = wallClockStopwatch.GetElapsedSnapshot(true);
return (long) (snapshot.Count / elapsedSnapshot.Seconds);
return (long) (snapshot.Count / elapsedSnapshot.TotalSeconds);
}
}
}

@ -47,10 +47,11 @@ var exe_ext = process.platform === 'win32' ? '.exe' : '';
var protoc = path.resolve(__dirname, 'protoc' + exe_ext);
execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
var child_process = execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
if (error) {
throw error;
}
console.log(stdout);
console.log(stderr);
});
child_process.stdout.pipe(process.stdout);
child_process.stderr.pipe(process.stderr);

@ -47,10 +47,12 @@ var exe_ext = process.platform === 'win32' ? '.exe' : '';
var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext);
execFile(plugin, process.argv.slice(2), function(error, stdout, stderr) {
var child_process = execFile(plugin, process.argv.slice(2), {encoding: 'buffer'}, function(error, stdout, stderr) {
if (error) {
throw error;
}
console.log(stdout);
console.log(stderr);
});
process.stdin.pipe(child_process.stdin);
child_process.stdout.pipe(process.stdout);
child_process.stderr.pipe(process.stderr);

@ -32,6 +32,12 @@ syntax = "proto3";
package grpc.testing;
// Message to be echoed back serialized in trailer.
message DebugInfo {
repeated string stack_entries = 1;
string detail = 2;
}
message RequestParams {
bool echo_deadline = 1;
int32 client_cancel_after_us = 2;
@ -43,6 +49,7 @@ message RequestParams {
string expected_client_identity = 8; // will force check_auth_context.
bool skip_cancelled_check = 9;
string expected_transport_security_type = 10;
DebugInfo debug_info = 11;
}
message EchoRequest {

@ -39,6 +39,7 @@ except ImportError:
from concurrent import futures
from grpc.beta import implementations
from grpc.framework.interfaces.face import face
from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import services_pb2
from tests.unit import resources
@ -141,10 +142,10 @@ class UnaryAsyncBenchmarkClient(BenchmarkClient):
self._stub = None
class StreamingAsyncBenchmarkClient(BenchmarkClient):
class StreamingSyncBenchmarkClient(BenchmarkClient):
def __init__(self, server, config, hist):
super(StreamingAsyncBenchmarkClient, self).__init__(server, config, hist)
super(StreamingSyncBenchmarkClient, self).__init__(server, config, hist)
self._is_streaming = False
self._pool = futures.ThreadPoolExecutor(max_workers=1)
# Use a thread-safe queue to put requests on the stream
@ -167,12 +168,12 @@ class StreamingAsyncBenchmarkClient(BenchmarkClient):
def _request_stream(self):
self._is_streaming = True
if self._generic:
response_stream = self._stub.inline_stream_stream(
'grpc.testing.BenchmarkService', 'StreamingCall',
self._request_generator(), _TIMEOUT)
stream_callable = self._stub.stream_stream(
'grpc.testing.BenchmarkService', 'StreamingCall')
else:
response_stream = self._stub.StreamingCall(self._request_generator(),
_TIMEOUT)
stream_callable = self._stub.StreamingCall
response_stream = stream_callable(self._request_generator(), _TIMEOUT)
for _ in response_stream:
end_time = time.time()
self._handle_response(end_time - self._send_time_queue.get_nowait())
@ -184,3 +185,48 @@ class StreamingAsyncBenchmarkClient(BenchmarkClient):
yield request
except queue.Empty:
pass
class AsyncReceiver(face.ResponseReceiver):
"""Receiver for async stream responses."""
def __init__(self, send_time_queue, response_handler):
self._send_time_queue = send_time_queue
self._response_handler = response_handler
def initial_metadata(self, initial_mdetadata):
pass
def response(self, response):
end_time = time.time()
self._response_handler(end_time - self._send_time_queue.get_nowait())
def complete(self, terminal_metadata, code, details):
pass
class StreamingAsyncBenchmarkClient(BenchmarkClient):
def __init__(self, server, config, hist):
super(StreamingAsyncBenchmarkClient, self).__init__(server, config, hist)
self._send_time_queue = queue.Queue()
self._receiver = AsyncReceiver(self._send_time_queue, self._handle_response)
self._rendezvous = None
def send_request(self):
if self._rendezvous is not None:
self._send_time_queue.put(time.time())
self._rendezvous.consume(self._request)
def start(self):
if self._generic:
stream_callable = self._stub.stream_stream(
'grpc.testing.BenchmarkService', 'StreamingCall')
else:
stream_callable = self._stub.StreamingCall
self._rendezvous = stream_callable.event(
self._receiver, lambda *args: None, _TIMEOUT)
def stop(self):
self._rendezvous.terminate()
self._rendezvous = None

@ -89,9 +89,9 @@ class ClosedLoopClientRunner(ClientRunner):
def start(self):
self._is_running = True
self._client.start()
for _ in xrange(self._request_count):
self._client.send_request()
self._client.start()
def stop(self):
self._is_running = False

@ -146,8 +146,9 @@ class WorkerServer(services_pb2.BetaWorkerServiceServicer):
if config.rpc_type == control_pb2.UNARY:
client = benchmark_client.UnarySyncBenchmarkClient(
server, config, qps_data)
else:
raise Exception('STREAMING SYNC client not supported')
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(

@ -49,7 +49,12 @@ module GRPC
fail(TypeError, '!Channel') unless alt_chan.is_a?(Core::Channel)
return alt_chan
end
kw['grpc.primary_user_agent'] = "grpc-ruby/#{VERSION}"
if kw['grpc.primary_user_agent'].nil?
kw['grpc.primary_user_agent'] = ''
else
kw['grpc.primary_user_agent'] += ' '
end
kw['grpc.primary_user_agent'] += "grpc-ruby/#{VERSION}"
unless creds.is_a?(Core::ChannelCredentials) || creds.is_a?(Symbol)
fail(TypeError, '!ChannelCredentials or Symbol')
end

@ -18,5 +18,5 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.executables = %w( protoc.rb protoc_grpc_ruby_plugin.rb )
s.executables = %w( grpc_tools_ruby_protoc.rb grpc_tools_ruby_protoc_plugin.rb )
end

@ -69,6 +69,8 @@
"src/node/ext",
"include/grpc",
"src/core",
"src/boringssl",
"src/zlib",
"third_party/nanopb",
"third_party/zlib",
"third_party/boringssl",

@ -199,6 +199,28 @@ class Verifier {
bool spin_;
};
// This class disables the server builder plugins that may add sync services to
// the server. If there are sync services, UnimplementedRpc test will triger
// the sync unkown rpc routine on the server side, rather than the async one
// that needs to be tested here.
class ServerBuilderSyncPluginDisabler : public ::grpc::ServerBuilderOption {
public:
void UpdateArguments(ChannelArguments* arg) GRPC_OVERRIDE {}
void UpdatePlugins(
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>>* plugins)
GRPC_OVERRIDE {
auto plugin = plugins->begin();
while (plugin != plugins->end()) {
if ((*plugin).second->has_sync_methods()) {
plugins->erase(plugin++);
} else {
plugin++;
}
}
}
};
class TestScenario {
public:
TestScenario(bool non_block, const grpc::string& creds_type,
@ -232,6 +254,12 @@ class AsyncEnd2endTest : public ::testing::TestWithParam<TestScenario> {
builder.AddListeningPort(server_address_.str(), server_creds);
builder.RegisterService(&service_);
cq_ = builder.AddCompletionQueue();
// TODO(zyc): make a test option to choose wheather sync plugins should be
// deleted
std::unique_ptr<ServerBuilderOption> sync_plugin_disabler(
new ServerBuilderSyncPluginDisabler());
builder.SetOption(move(sync_plugin_disabler));
server_ = builder.BuildAndStart();
gpr_tls_set(&g_is_async_end2end_test, 1);

@ -975,6 +975,34 @@ TEST_P(End2endTest, NonExistingService) {
EXPECT_EQ("", s.error_message());
}
// Ask the server to send back a serialized proto in trailer.
// This is an example of setting error details.
TEST_P(End2endTest, BinaryTrailerTest) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
request.mutable_param()->set_echo_metadata(true);
DebugInfo* info = request.mutable_param()->mutable_debug_info();
info->add_stack_entries("stack_entry_1");
info->add_stack_entries("stack_entry_2");
info->add_stack_entries("stack_entry_3");
info->set_detail("detailed debug info");
grpc::string expected_string = info->SerializeAsString();
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
auto trailers = context.GetServerTrailingMetadata();
EXPECT_EQ(1u, trailers.count(kDebugInfoTrailerKey));
auto iter = trailers.find(kDebugInfoTrailerKey);
EXPECT_EQ(expected_string, iter->second);
// Parse the returned trailer into a DebugInfo proto.
DebugInfo returned_info;
EXPECT_TRUE(returned_info.ParseFromString(ToString(iter->second)));
}
//////////////////////////////////////////////////////////////////////////
// Test with and without a proxy.
class ProxyEnd2endTest : public End2endTest {

@ -0,0 +1,256 @@
/*
*
* 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 <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/impl/server_builder_option.h>
#include <grpc++/impl/server_builder_plugin.h>
#include <grpc++/impl/server_initializer.h>
#include <grpc++/security/credentials.h>
#include <grpc++/security/server_credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc/grpc.h>
#include <gtest/gtest.h>
#include "src/proto/grpc/testing/echo.grpc.pb.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/end2end/test_service_impl.h"
#define PLUGIN_NAME "TestServerBuilderPlugin"
namespace grpc {
namespace testing {
class TestServerBuilderPlugin : public ServerBuilderPlugin {
public:
TestServerBuilderPlugin() : service_(new TestServiceImpl()) {
init_server_is_called_ = false;
finish_is_called_ = false;
change_arguments_is_called_ = false;
}
grpc::string name() GRPC_OVERRIDE { return PLUGIN_NAME; }
void InitServer(ServerInitializer* si) GRPC_OVERRIDE {
init_server_is_called_ = true;
if (register_service_) {
si->RegisterService(service_);
}
}
void Finish(ServerInitializer* si) GRPC_OVERRIDE { finish_is_called_ = true; }
void ChangeArguments(const grpc::string& name, void* value) GRPC_OVERRIDE {
change_arguments_is_called_ = true;
}
bool has_async_methods() const GRPC_OVERRIDE {
if (register_service_) {
return service_->has_async_methods();
}
return false;
}
bool has_sync_methods() const GRPC_OVERRIDE {
if (register_service_) {
return service_->has_synchronous_methods();
}
return false;
}
void SetRegisterService() { register_service_ = true; }
bool init_server_is_called() { return init_server_is_called_; }
bool finish_is_called() { return finish_is_called_; }
bool change_arguments_is_called() { return change_arguments_is_called_; }
private:
bool init_server_is_called_;
bool finish_is_called_;
bool change_arguments_is_called_;
bool register_service_;
std::shared_ptr<TestServiceImpl> service_;
};
class InsertPluginServerBuilderOption : public ServerBuilderOption {
public:
InsertPluginServerBuilderOption() { register_service_ = false; }
void UpdateArguments(ChannelArguments* arg) GRPC_OVERRIDE {}
void UpdatePlugins(
std::map<grpc::string, std::unique_ptr<ServerBuilderPlugin>>* plugins)
GRPC_OVERRIDE {
plugins->clear();
std::unique_ptr<TestServerBuilderPlugin> plugin(
new TestServerBuilderPlugin());
if (register_service_) plugin->SetRegisterService();
(*plugins)[plugin->name()] = std::move(plugin);
}
void SetRegisterService() { register_service_ = true; }
private:
bool register_service_;
};
std::unique_ptr<ServerBuilderPlugin> CreateTestServerBuilderPlugin() {
return std::unique_ptr<ServerBuilderPlugin>(new TestServerBuilderPlugin());
}
void AddTestServerBuilderPlugin() {
static bool already_here = false;
if (already_here) return;
already_here = true;
::grpc::ServerBuilder::InternalAddPluginFactory(
&CreateTestServerBuilderPlugin);
}
// Force AddServerBuilderPlugin() to be called at static initialization time.
struct StaticTestPluginInitializer {
StaticTestPluginInitializer() { AddTestServerBuilderPlugin(); }
} static_plugin_initializer_test_;
// When the param boolean is true, the ServerBuilder plugin will be added at the
// time of static initialization. When it's false, the ServerBuilder plugin will
// be added using ServerBuilder::SetOption().
class ServerBuilderPluginTest : public ::testing::TestWithParam<bool> {
public:
ServerBuilderPluginTest() {}
void SetUp() GRPC_OVERRIDE {
port_ = grpc_pick_unused_port_or_die();
builder_.reset(new ServerBuilder());
}
void InsertPlugin() {
if (GetParam()) {
// Add ServerBuilder plugin in static initialization
EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
} else {
// Add ServerBuilder plugin using ServerBuilder::SetOption()
builder_->SetOption(std::unique_ptr<ServerBuilderOption>(
new InsertPluginServerBuilderOption()));
}
}
void InsertPluginWithTestService() {
if (GetParam()) {
// Add ServerBuilder plugin in static initialization
EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
auto plugin = static_cast<TestServerBuilderPlugin*>(
builder_->plugins_[PLUGIN_NAME].get());
EXPECT_TRUE(plugin != nullptr);
plugin->SetRegisterService();
} else {
// Add ServerBuilder plugin using ServerBuilder::SetOption()
std::unique_ptr<InsertPluginServerBuilderOption> option(
new InsertPluginServerBuilderOption());
option->SetRegisterService();
builder_->SetOption(std::move(option));
}
}
void StartServer() {
grpc::string server_address = "localhost:" + to_string(port_);
builder_->AddListeningPort(server_address, InsecureServerCredentials());
server_ = builder_->BuildAndStart();
EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
}
void ResetStub() {
string target = "dns:localhost:" + to_string(port_);
channel_ = CreateChannel(target, InsecureChannelCredentials());
stub_ = grpc::testing::EchoTestService::NewStub(channel_);
}
void TearDown() GRPC_OVERRIDE {
EXPECT_TRUE(builder_->plugins_[PLUGIN_NAME] != nullptr);
auto plugin = static_cast<TestServerBuilderPlugin*>(
builder_->plugins_[PLUGIN_NAME].get());
EXPECT_TRUE(plugin != nullptr);
EXPECT_TRUE(plugin->init_server_is_called());
EXPECT_TRUE(plugin->finish_is_called());
}
string to_string(const int number) {
std::stringstream strs;
strs << number;
return strs.str();
}
protected:
std::shared_ptr<Channel> channel_;
std::unique_ptr<ServerBuilder> builder_;
std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
std::unique_ptr<Server> server_;
TestServiceImpl service_;
int port_;
};
TEST_P(ServerBuilderPluginTest, PluginWithoutServiceTest) {
InsertPlugin();
StartServer();
}
TEST_P(ServerBuilderPluginTest, PluginWithServiceTest) {
InsertPluginWithTestService();
StartServer();
ResetStub();
EchoRequest request;
EchoResponse response;
request.set_message("Hello hello hello hello");
ClientContext context;
context.set_compression_algorithm(GRPC_COMPRESS_GZIP);
Status s = stub_->Echo(&context, request, &response);
EXPECT_EQ(response.message(), request.message());
EXPECT_TRUE(s.ok());
}
INSTANTIATE_TEST_CASE_P(ServerBuilderPluginTest, ServerBuilderPluginTest,
::testing::Values(false, true));
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -135,6 +135,14 @@ Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request,
context->AddTrailingMetadata(ToString(iter->first),
ToString(iter->second));
}
// Terminate rpc with error and debug info in trailer.
if (request->param().debug_info().stack_entries_size() ||
!request->param().debug_info().detail().empty()) {
grpc::string serialized_debug_info =
request->param().debug_info().SerializeAsString();
context->AddTrailingMetadata(kDebugInfoTrailerKey, serialized_debug_info);
return Status::CANCELLED;
}
}
if (request->has_param() &&
(request->param().expected_client_identity().length() > 0 ||

@ -47,6 +47,7 @@ namespace testing {
const int kNumResponseStreamsMsgs = 3;
const char* const kServerCancelAfterReads = "cancel_after_reads";
const char* const kServerTryCancelRequest = "server_try_cancel";
const char* const kDebugInfoTrailerKey = "debug-info-bin";
typedef enum {
DO_NOT_CANCEL = 0,

@ -84,7 +84,8 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext {
std::function<
std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>(
BenchmarkService::Stub*, grpc::ClientContext*, const RequestType&,
CompletionQueue*)> start_req,
CompletionQueue*)>
start_req,
std::function<void(grpc::Status, ResponseType*)> on_done)
: context_(),
stub_(stub),
@ -165,7 +166,8 @@ class AsyncClient : public ClientImpl<StubType, RequestType> {
AsyncClient(const ClientConfig& config,
std::function<ClientRpcContext*(
StubType*, std::function<gpr_timespec()> next_issue,
const RequestType&)> setup_ctx,
const RequestType&)>
setup_ctx,
std::function<std::unique_ptr<StubType>(std::shared_ptr<Channel>)>
create_stub)
: ClientImpl<StubType, RequestType>(config, create_stub),
@ -278,7 +280,8 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext {
std::function<std::unique_ptr<
grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>(
BenchmarkService::Stub*, grpc::ClientContext*, CompletionQueue*,
void*)> start_req,
void*)>
start_req,
std::function<void(grpc::Status, ResponseType*)> on_done)
: context_(),
stub_(stub),
@ -405,7 +408,8 @@ class ClientRpcContextGenericStreamingImpl : public ClientRpcContext {
std::function<gpr_timespec()> next_issue,
std::function<std::unique_ptr<grpc::GenericClientAsyncReaderWriter>(
grpc::GenericStub*, grpc::ClientContext*,
const grpc::string& method_name, CompletionQueue*, void*)> start_req,
const grpc::string& method_name, CompletionQueue*, void*)>
start_req,
std::function<void(grpc::Status, ByteBuffer*)> on_done)
: context_(),
stub_(stub),

@ -73,7 +73,8 @@ class AsyncQpsServerTest : public Server {
CompletionQueue *, ServerCompletionQueue *, void *)>
request_streaming_function,
std::function<grpc::Status(const PayloadConfig &, const RequestType *,
ResponseType *)> process_rpc)
ResponseType *)>
process_rpc)
: Server(config) {
char *server_address = NULL;
@ -190,7 +191,8 @@ class AsyncQpsServerTest : public Server {
ServerRpcContextUnaryImpl(
std::function<void(ServerContextType *, RequestType *,
grpc::ServerAsyncResponseWriter<ResponseType> *,
void *)> request_method,
void *)>
request_method,
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method)
: srv_ctx_(new ServerContextType),

@ -1 +1 @@
Subproject commit d5fb408ddc281ffcadeb08699e65bb694656d0bd
Subproject commit a1938b2aa9ca86ce7ce50c27ff9737c1008d2a03

File diff suppressed because one or more lines are too long

@ -777,6 +777,8 @@ include/grpc++/impl/rpc_method.h \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \

@ -777,6 +777,8 @@ include/grpc++/impl/rpc_method.h \
include/grpc++/impl/rpc_service_method.h \
include/grpc++/impl/serialization_traits.h \
include/grpc++/impl/server_builder_option.h \
include/grpc++/impl/server_builder_plugin.h \
include/grpc++/impl/server_initializer.h \
include/grpc++/impl/service_type.h \
include/grpc++/impl/sync.h \
include/grpc++/impl/sync_cxx11.h \

@ -0,0 +1,42 @@
/*
*
* 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 <memory>
#include <grpc++/security/auth_context.h>
#include <grpc/grpc.h>
namespace grpc {
std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
} // namespace grpc

@ -0,0 +1,47 @@
#!/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.
set -ex
outdir=`pwd`
tmpdir=`mktemp -d`
mkdir -p $tmpdir/logs
repos="grpc grpc-common grpc-go grpc-java grpc.github.io grpc-tools homebrew-grpc grpc-docker-library"
for repo in $repos
do
cd $tmpdir
git clone https://github.com/grpc/$repo.git
cd $repo
gource --output-custom-log $tmpdir/logs/$repo
sed -i .backup "s,\|/,\|/$repo/,g" $tmpdir/logs/$repo
done
rm $tmpdir/logs/*.backup
cat $tmpdir/logs/* | sort -n > $outdir/all-logs.txt

@ -28,5 +28,13 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
gource --multi-sampling -c 4 -s 0.1 --max-file-lag 0.05 --max-files 0 -e 0.05 --hide filenames,dirnames $*
gource \
--multi-sampling \
-s 0.1 \
--max-file-lag 0.05 \
--max-files 0 \
-e 0.01 \
--hide filenames,dirnames \
--disable-auto-rotate \
--file-filter '/grpc/doc/ref' \
$*

@ -0,0 +1,47 @@
#!/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.
set -ex
dst=$1
shift
$(dirname $0)/gource.sh \
--disable-progress \
--stop-at-end \
--output-ppm-stream - \
$@ | \
ffmpeg \
-y \
-r 60 \
-f image2pipe \
-vcodec ppm \
-i - \
-vcodec libx264 \
$dst

@ -34,4 +34,4 @@ set -ex
# Enter the gRPC repo root
cd $(dirname $0)/../..
tools/run_tests/run_performance_tests.py -l c++ node ruby csharp python
tools/run_tests/run_performance_tests.py -l c++ node ruby csharp python --netperf --category smoketest

@ -55,7 +55,7 @@ npm pack
cp grpc-tools-*.tgz $artifacts/
tools_version=$(npm list | grep -oP '(?<=grpc-tools@)\S+')
output_dir=$artifacts/grpc-precompiled-binaries/node/grpc-tools/$tools_version
output_dir=$artifacts/grpc-precompiled-binaries/node/grpc-tools/v$tools_version
mkdir -p $output_dir
for arch in {x86,x64}; do

@ -33,8 +33,6 @@ set -ex
cd $(dirname $0)/../../..
#TODO(jtattermusch): add support for more languages
CONFIG=${CONFIG:-opt}
# build C++ qps worker & driver always - we need at least the driver to
@ -53,6 +51,9 @@ do
(cd ../grpc-java/ &&
./gradlew -PskipCodegen=true :grpc-benchmarks:installDist)
;;
"go")
tools/run_tests/performance/build_performance_go.sh
;;
*)
tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8
;;

@ -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.
set -ex
cd $(dirname $0)/../../..
export GOPATH=$(pwd)/../gopath
# Get grpc-go and the dependencies but get rid of the upstream/master version
go get google.golang.org/grpc
rm -rf "${GOPATH}/src/google.golang.org/grpc"
# Get the revision of grpc-go we want to test
git clone --recursive ../grpc-go ${GOPATH}/src/google.golang.org/grpc
(cd ${GOPATH}/src/google.golang.org/grpc/benchmark/worker && go install)

@ -52,3 +52,6 @@ ps -C python -o pid=,cmd= | grep 'qps_worker.py' | awk '{print $1}' | xargs kill
# Java
jps | grep LoadWorker | awk '{print $1}' | xargs kill -9
# Go
killall -9 worker || true

@ -39,7 +39,7 @@ ssh "${USER_AT_HOST}" "rm -rf ~/performance_workspace && mkdir -p ~/performance_
# mess with the results, be rough and reboot the slave here
# and wait for it to come back online.
# could also kill jenkins.
ssh "${USER_AT_HOST}" "killall -9 qps_worker mono node ruby || true"
ssh "${USER_AT_HOST}" "killall -9 qps_worker mono node ruby worker || true"
# push the current sources to the slave and unpack it.
scp ../grpc.tar "${USER_AT_HOST}:~/performance_workspace"

@ -0,0 +1,37 @@
#!/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
cd $(dirname $0)/../../..
export GOPATH=$(pwd)/../gopath
${GOPATH}/bin/worker $@

@ -349,39 +349,39 @@ class PythonLanguage:
return 500
def scenarios(self):
# TODO(jtattermusch): this scenario reports QPS 0.0
yield _ping_pong_scenario(
'python_generic_async_streaming_ping_pong', rpc_type='STREAMING',
client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
use_generic_payload=True,
categories=[SMOKETEST])
# TODO(jtattermusch): make this scenario work
# TODO(issue #6522): Empty streaming requests does not work for python
#yield _ping_pong_scenario(
# 'python_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER')
# 'python_generic_async_streaming_ping_pong', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
# use_generic_payload=True,
# categories=[SMOKETEST])
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'python_protobuf_async_unary_ping_pong', rpc_type='UNARY',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER')
yield _ping_pong_scenario(
'python_protobuf_async_streaming_ping_pong', rpc_type='STREAMING',
client_type='ASYNC_CLIENT', server_type='SYNC_SERVER')
yield _ping_pong_scenario(
'python_protobuf_async_unary_ping_pong', rpc_type='UNARY',
client_type='ASYNC_CLIENT', server_type='SYNC_SERVER')
yield _ping_pong_scenario(
'python_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
categories=[SMOKETEST])
# TODO(jtattermusch): make this scenario work
# TODO(jtattermusch):
# The qps_worker server gets thread starved with ~6400 threads, the GIL
# enforces that a single thread runs at a time, with no way to set thread
# priority. Re-evaluate after changing DEEP and WIDE.
#yield _ping_pong_scenario(
# 'python_protobuf_sync_unary_qps_unconstrained', rpc_type='UNARY',
# client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
# use_unconstrained_client=True)
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'python_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING',
# client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
# use_unconstrained_client=True)
yield _ping_pong_scenario(
'python_protobuf_async_streaming_qps_unconstrained', rpc_type='STREAMING',
client_type='ASYNC_CLIENT', server_type='SYNC_SERVER',
use_unconstrained_client=True)
yield _ping_pong_scenario(
'python_to_cpp_protobuf_sync_unary_ping_pong', rpc_type='UNARY',
@ -389,11 +389,10 @@ class PythonLanguage:
server_language='c++', server_core_limit=1, async_server_threads=1,
categories=[SMOKETEST])
# TODO(jtattermusch): make this scenario work
#yield _ping_pong_scenario(
# 'python_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)
yield _ping_pong_scenario(
'python_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)
def __str__(self):
return 'python'
@ -522,6 +521,72 @@ class JavaLanguage:
return 'java'
class GoLanguage:
def __init__(self):
pass
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_go.sh']
def worker_port_offset(self):
return 600
def scenarios(self):
for secure in [True, False]:
secstr = 'secure' if secure else 'insecure'
smoketest_categories = [SMOKETEST] if secure else None
# ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
# but that's mostly because of lack of better name of the enum value.
yield _ping_pong_scenario(
'go_generic_sync_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
client_type='SYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
use_generic_payload=True, async_server_threads=1,
secure=secure,
categories=smoketest_categories)
yield _ping_pong_scenario(
'go_protobuf_sync_streaming_ping_pong_%s' % secstr, rpc_type='STREAMING',
client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
async_server_threads=1,
secure=secure)
yield _ping_pong_scenario(
'go_protobuf_sync_unary_ping_pong_%s' % secstr, rpc_type='UNARY',
client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
async_server_threads=1,
secure=secure,
categories=smoketest_categories)
yield _ping_pong_scenario(
'go_protobuf_sync_unary_qps_unconstrained_%s' % secstr, rpc_type='UNARY',
client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
use_unconstrained_client=True,
secure=secure,
categories=smoketest_categories)
yield _ping_pong_scenario(
'go_protobuf_sync_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
client_type='SYNC_CLIENT', server_type='SYNC_SERVER',
use_unconstrained_client=True,
secure=secure)
# ASYNC_GENERIC_SERVER for Go actually uses a sync streaming server,
# but that's mostly because of lack of better name of the enum value.
yield _ping_pong_scenario(
'go_generic_sync_streaming_qps_unconstrained_%s' % secstr, rpc_type='STREAMING',
client_type='SYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER',
use_unconstrained_client=True, use_generic_payload=True,
secure=secure)
# TODO(jtattermusch): add scenarios go vs C++
def __str__(self):
return 'go'
LANGUAGES = {
'c++' : CXXLanguage(),
'csharp' : CSharpLanguage(),
@ -529,4 +594,5 @@ LANGUAGES = {
'ruby' : RubyLanguage(),
'java' : JavaLanguage(),
'python' : PythonLanguage(),
'go' : GoLanguage(),
}

@ -137,6 +137,17 @@ def create_netperf_jobspec(server_host='localhost', client_host=None,
cmd = 'NETPERF_SERVER_HOST="%s" ' % server_host
if bq_result_table:
cmd += 'BQ_RESULT_TABLE="%s" ' % bq_result_table
if client_host:
# If netperf is running remotely, the env variables populated by Jenkins
# won't be available on the client, but we need them for uploading results
# to BigQuery.
jenkins_job_name = os.getenv('JOB_NAME')
if jenkins_job_name:
cmd += 'JOB_NAME="%s" ' % jenkins_job_name
jenkins_build_number = os.getenv('BUILD_NUMBER')
if jenkins_build_number:
cmd += 'BUILD_NUMBER="%s" ' % jenkins_build_number
cmd += 'tools/run_tests/performance/run_netperf.sh'
if client_host:
user_at_host = '%s@%s' % (_REMOTE_HOST_USERNAME, client_host)

@ -45,7 +45,7 @@ cat << EOF | awk '{ print $1 }' | sort > $want_submodules
05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f)
c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0)
f8ac463766281625ad710900479130c7fcb4d63b third_party/nanopb (nanopb-0.3.4-29-gf8ac463)
d5fb408ddc281ffcadeb08699e65bb694656d0bd third_party/protobuf (v3.0.0-beta-2)
a1938b2aa9ca86ce7ce50c27ff9737c1008d2a03 third_party/protobuf (v3.0.0-beta-3-pre1)
50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8)
EOF

@ -2588,6 +2588,24 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc++",
"grpc++_test_util",
"grpc_test_util"
],
"headers": [],
"language": "c++",
"name": "server_builder_plugin_test",
"src": [
"test/cpp/end2end/server_builder_plugin_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -6345,6 +6363,8 @@
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",
@ -6395,6 +6415,8 @@
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/serialization_traits.h",
"include/grpc++/impl/server_builder_option.h",
"include/grpc++/impl/server_builder_plugin.h",
"include/grpc++/impl/server_initializer.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/impl/sync.h",
"include/grpc++/impl/sync_cxx11.h",

@ -2448,6 +2448,27 @@
"posix"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "server_builder_plugin_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{
"args": [],
"ci_platforms": [

@ -275,6 +275,8 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\rpc_service_method.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\serialization_traits.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_option.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_plugin.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_initializer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\service_type.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\sync_cxx11.h" />

@ -147,6 +147,12 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_option.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_plugin.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_initializer.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\service_type.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>

@ -275,6 +275,8 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\rpc_service_method.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\serialization_traits.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_option.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_plugin.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_initializer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\service_type.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\sync_cxx11.h" />

@ -132,6 +132,12 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_option.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_builder_plugin.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\server_initializer.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\service_type.h">
<Filter>include\grpc++\impl</Filter>
</ClInclude>

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{86751DC8-C8D9-57B6-2C8A-BB33021C773C}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>server_builder_plugin_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>server_builder_plugin_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\server_builder_plugin_test.cc">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
<Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>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}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\server_builder_plugin_test.cc">
<Filter>test\cpp\end2end</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{37b2ebc1-b2f2-ecb9-37b7-f6d757bb99e3}</UniqueIdentifier>
</Filter>
<Filter Include="test\cpp">
<UniqueIdentifier>{39400fed-f7b7-0f44-0ef3-ba3693d42011}</UniqueIdentifier>
</Filter>
<Filter Include="test\cpp\end2end">
<UniqueIdentifier>{dab9dd19-3e5b-005e-4b5a-456de6111d71}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save