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

pull/7900/head
Yuchen Zeng 8 years ago
commit 676b6cbc10
  1. 3
      .gitmodules
  2. 405
      Makefile
  3. 40
      build.yaml
  4. 219
      include/grpc++/impl/codegen/thrift_serializer.h
  5. 85
      include/grpc++/impl/codegen/thrift_utils.h
  6. 1303
      src/core/ext/transport/cronet/transport/cronet_transport.c
  7. 1
      src/core/lib/iomgr/ev_epoll_linux.c
  8. 394
      src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
  9. 63
      test/cpp/util/cli_credentials.cc
  10. 53
      test/cpp/util/cli_credentials.h
  11. 85
      test/cpp/util/config_grpc_cli.h
  12. 194
      test/cpp/util/grpc_cli.cc
  13. 365
      test/cpp/util/grpc_tool.cc
  14. 54
      test/cpp/util/grpc_tool.h
  15. 227
      test/cpp/util/grpc_tool_test.cc
  16. 201
      test/cpp/util/proto_file_parser.cc
  17. 65
      test/cpp/util/proto_file_parser.h
  18. 2
      test/cpp/util/proto_reflection_descriptor_database.cc
  19. 1
      third_party/thrift
  20. 4
      tools/gce/create_linux_worker.sh
  21. 67
      tools/grift/Dockerfile
  22. 26
      tools/grift/README.md
  23. 2505
      tools/grift/grpc_plugins_generator.patch
  24. 2
      tools/run_tests/run_interop_tests.py
  25. 1
      tools/run_tests/sanity/check_submodules.sh
  26. 64
      tools/run_tests/sources_and_headers.json
  27. 21
      tools/run_tests/tests.json
  28. 2
      vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
  29. 6
      vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
  30. 11
      vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
  31. 15
      vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
  32. 9
      vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
  33. 286
      vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj
  34. 232
      vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters

3
.gitmodules vendored

@ -21,3 +21,6 @@
path = third_party/c-ares
url = https://github.com/c-ares/c-ares.git
branch = cares-1_11_0
[submodule "third_party/thrift"]
path = third_party/thrift
url = https://github.com/apache/thrift.git

File diff suppressed because it is too large Load Diff

@ -801,6 +801,13 @@ filegroups:
- src/cpp/ext/reflection.pb.cc
uses:
- grpc++_codegen_proto
- name: thrift_util
language: c++
public_headers:
- include/grpc++/impl/codegen/thrift_serializer.h
- include/grpc++/impl/codegen/thrift_utils.h
uses:
- grpc++_codegen_base
libs:
- name: gpr
build: all
@ -1043,6 +1050,7 @@ libs:
- grpc++_codegen_base_src
- grpc++_codegen_proto
- grpc++_config_proto
- thrift_util
- name: grpc++_unsecure
build: all
language: c++
@ -1064,16 +1072,21 @@ libs:
language: c++
headers:
- test/cpp/util/cli_call.h
- test/cpp/util/cli_credentials.h
- test/cpp/util/config_grpc_cli.h
- test/cpp/util/grpc_tool.h
- test/cpp/util/proto_file_parser.h
- test/cpp/util/proto_reflection_descriptor_database.h
src:
- test/cpp/util/cli_call.cc
- test/cpp/util/cli_credentials.cc
- test/cpp/util/grpc_tool.cc
- test/cpp/util/proto_file_parser.cc
- test/cpp/util/proto_reflection_descriptor_database.cc
deps:
- grpc++_reflection
- grpc++
- grpc_plugin_support
- grpc++_test_config
- name: grpc_plugin_support
build: protoc
language: c++
@ -2723,12 +2736,9 @@ targets:
- test/cpp/util/grpc_cli.cc
deps:
- grpc_cli_libs
- grpc++_test_util
- grpc_test_util
- grpc++_reflection
- grpc++
- grpc
- gpr_test_util
- gpr
- grpc++_test_config
- name: grpc_cpp_plugin
@ -2790,6 +2800,28 @@ targets:
secure: false
vs_config_type: Application
vs_project_guid: '{069E9D05-B78B-4751-9252-D21EBAE7DE8E}'
- name: grpc_tool_test
gtest: true
build: test
language: c++
headers:
- test/cpp/util/string_ref_helper.h
src:
- src/proto/grpc/testing/echo.proto
- src/proto/grpc/testing/echo_messages.proto
- test/cpp/util/grpc_tool_test.cc
- test/cpp/util/string_ref_helper.cc
deps:
- grpc_cli_libs
- grpc++_reflection
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
filegroups:
- grpc++_codegen_proto
- grpc++_config_proto
- name: grpclb_api_test
gtest: true
build: test

@ -0,0 +1,219 @@
/*
*
* 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_CODEGEN_THRIFT_SERIALIZER_H
#define GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/impl/codegen/byte_buffer_reader.h>
#include <grpc/impl/codegen/slice.h>
#include <grpc/impl/codegen/slice_buffer.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/protocol/TCompactProtocol.h>
#include <thrift/protocol/TProtocolException.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TTransportUtils.h>
#include <boost/make_shared.hpp>
#include <memory>
#include <stdexcept>
#include <string>
namespace apache {
namespace thrift {
namespace util {
using apache::thrift::protocol::TBinaryProtocolT;
using apache::thrift::protocol::TCompactProtocolT;
using apache::thrift::protocol::TMessageType;
using apache::thrift::protocol::TNetworkBigEndian;
using apache::thrift::transport::TMemoryBuffer;
using apache::thrift::transport::TBufferBase;
using apache::thrift::transport::TTransport;
template <typename Dummy, typename Protocol>
class ThriftSerializer {
public:
ThriftSerializer()
: prepared_(false),
last_deserialized_(false),
serialize_version_(false) {}
virtual ~ThriftSerializer() {}
// Serialize the passed type into the internal buffer
// and returns a pointer to internal buffer and its size
template <typename T>
void Serialize(const T& fields, const uint8_t** serialized_buffer,
size_t* serialized_len) {
// prepare or reset buffer
if (!prepared_ || last_deserialized_) {
prepare();
} else {
buffer_->resetBuffer();
}
last_deserialized_ = false;
// if required serialize protocol version
if (serialize_version_) {
protocol_->writeMessageBegin("", TMessageType(0), 0);
}
// serialize fields into buffer
fields.write(protocol_.get());
// write the end of message
if (serialize_version_) {
protocol_->writeMessageEnd();
}
uint8_t* byte_buffer;
uint32_t byte_buffer_size;
buffer_->getBuffer(&byte_buffer, &byte_buffer_size);
*serialized_buffer = byte_buffer;
*serialized_len = byte_buffer_size;
}
// Serialize the passed type into the byte buffer
template <typename T>
void Serialize(const T& fields, grpc_byte_buffer** bp) {
const uint8_t* byte_buffer;
size_t byte_buffer_size;
Serialize(fields, &byte_buffer, &byte_buffer_size);
gpr_slice slice = gpr_slice_from_copied_buffer(
reinterpret_cast<const char*>(byte_buffer), byte_buffer_size);
*bp = grpc_raw_byte_buffer_create(&slice, 1);
gpr_slice_unref(slice);
}
// Deserialize the passed char array into the passed type, returns the number
// of bytes that have been consumed from the passed string.
template <typename T>
uint32_t Deserialize(uint8_t* serialized_buffer, size_t length, T* fields) {
// prepare buffer if necessary
if (!prepared_) {
prepare();
}
last_deserialized_ = true;
// reset buffer transport
buffer_->resetBuffer(serialized_buffer, length);
// read the protocol version if necessary
if (serialize_version_) {
std::string name = "";
TMessageType mt = static_cast<TMessageType>(0);
int32_t seq_id = 0;
protocol_->readMessageBegin(name, mt, seq_id);
}
// deserialize buffer into fields
uint32_t len = fields->read(protocol_.get());
// read the end of message
if (serialize_version_) {
protocol_->readMessageEnd();
}
return len;
}
// Deserialize the passed byte buffer to passed type, returns the number
// of bytes consumed from byte buffer
template <typename T>
uint32_t Deserialize(grpc_byte_buffer* buffer, T* msg) {
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, buffer);
gpr_slice slice = grpc_byte_buffer_reader_readall(&reader);
uint32_t len =
Deserialize(GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice), msg);
gpr_slice_unref(slice);
grpc_byte_buffer_reader_destroy(&reader);
return len;
}
// set serialization version flag
void SetSerializeVersion(bool value) { serialize_version_ = value; }
// Set the container size limit to deserialize
// This function should be called after buffer_ is initialized
void SetContainerSizeLimit(int32_t container_limit) {
if (!prepared_) {
prepare();
}
protocol_->setContainerSizeLimit(container_limit);
}
// Set the string size limit to deserialize
// This function should be called after buffer_ is initialized
void SetStringSizeLimit(int32_t string_limit) {
if (!prepared_) {
prepare();
}
protocol_->setStringSizeLimit(string_limit);
}
private:
bool prepared_;
bool last_deserialized_;
boost::shared_ptr<TMemoryBuffer> buffer_;
std::shared_ptr<Protocol> protocol_;
bool serialize_version_;
void prepare() {
buffer_ = boost::make_shared<TMemoryBuffer>();
// create a protocol for the memory buffer transport
protocol_ = std::make_shared<Protocol>(buffer_);
prepared_ = true;
}
}; // ThriftSerializer
typedef ThriftSerializer<void, TBinaryProtocolT<TBufferBase, TNetworkBigEndian>>
ThriftSerializerBinary;
typedef ThriftSerializer<void, TCompactProtocolT<TBufferBase>>
ThriftSerializerCompact;
} // namespace util
} // namespace thrift
} // namespace apache
#endif

@ -0,0 +1,85 @@
/*
*
* 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_CODEGEN_THRIFT_UTILS_H
#define GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/status_code_enum.h>
#include <grpc++/impl/codegen/thrift_serializer.h>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/impl/codegen/byte_buffer_reader.h>
#include <grpc/impl/codegen/slice.h>
#include <grpc/impl/codegen/slice_buffer.h>
#include <cstdint>
#include <cstdlib>
namespace grpc {
using apache::thrift::util::ThriftSerializerCompact;
template <class T>
class SerializationTraits<T, typename std::enable_if<std::is_base_of<
apache::thrift::TBase, T>::value>::type> {
public:
static Status Serialize(const T& msg, grpc_byte_buffer** bp,
bool* own_buffer) {
*own_buffer = true;
ThriftSerializerCompact serializer;
serializer.Serialize(msg, bp);
return Status(StatusCode::OK, "ok");
}
static Status Deserialize(grpc_byte_buffer* buffer, T* msg,
int max_message_size) {
if (!buffer) {
return Status(StatusCode::INTERNAL, "No payload");
}
ThriftSerializerCompact deserializer;
deserializer.Deserialize(buffer, msg);
grpc_byte_buffer_destroy(buffer);
return Status(StatusCode::OK, "ok");
}
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H

File diff suppressed because it is too large Load Diff

@ -42,6 +42,7 @@
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/epoll.h>

@ -1,394 +0,0 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* This test file is derived from fixture h2_ssl.c in core end2end test
* (test/core/end2end/fixture/h2_ssl.c). The structure of the fixture is
* preserved as much as possible
*
* This fixture creates a server full stack using chttp2 and a client
* full stack using Cronet. End-to-end tests are run against this
* configuration
*
*/
#import <XCTest/XCTest.h>
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/support/tmpfile.h"
#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include <grpc/grpc_cronet.h>
#import <Cronet/Cronet.h>
typedef struct fullstack_secure_fixture_data {
char *localaddr;
} fullstack_secure_fixture_data;
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
grpc_channel_args *client_args, grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
int port = grpc_pick_unused_port_or_die();
fullstack_secure_fixture_data *ffd =
gpr_malloc(sizeof(fullstack_secure_fixture_data));
memset(&f, 0, sizeof(f));
gpr_join_host_port(&ffd->localaddr, "localhost", port);
f.fixture_data = ffd;
f.cq = grpc_completion_queue_create(NULL);
return f;
}
static void process_auth_failure(void *state, grpc_auth_context *ctx,
const grpc_metadata *md, size_t md_count,
grpc_process_auth_metadata_done_cb cb,
void *user_data) {
GPR_ASSERT(state == NULL);
cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
}
static void cronet_init_client_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
cronet_engine *cronetEngine) {
fullstack_secure_fixture_data *ffd = f->fixture_data;
f->client =
grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL);
GPR_ASSERT(f->client != NULL);
}
static void chttp2_init_server_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
grpc_server_credentials *server_creds) {
fullstack_secure_fixture_data *ffd = f->fixture_data;
if (f->server) {
grpc_server_destroy(f->server);
}
f->server = grpc_server_create(server_args, NULL);
grpc_server_register_completion_queue(f->server, f->cq, NULL);
GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr,
server_creds));
grpc_server_credentials_release(server_creds);
grpc_server_start(f->server);
}
static void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
fullstack_secure_fixture_data *ffd = f->fixture_data;
gpr_free(ffd->localaddr);
gpr_free(ffd);
}
static void cronet_init_client_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
grpc_arg ssl_name_override = {GRPC_ARG_STRING,
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
{"foo.test.google.fr"}};
grpc_channel_args *new_client_args =
grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
[Cronet setHttp2Enabled:YES];
[Cronet start];
cronet_engine *cronetEngine = [Cronet getGlobalEngine];
cronet_init_client_secure_fullstack(f, new_client_args, cronetEngine);
grpc_channel_args_destroy(new_client_args);
}
static int fail_server_auth_check(grpc_channel_args *server_args) {
size_t i;
if (server_args == NULL) return 0;
for (i = 0; i < server_args->num_args; i++) {
if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) ==
0) {
return 1;
}
}
return 0;
}
static void chttp2_init_server_simple_ssl_secure_fullstack(
grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
test_server1_cert};
grpc_server_credentials *ssl_creds =
grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
if (fail_server_auth_check(server_args)) {
grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
}
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
}
/* All test configurations */
static grpc_end2end_test_config configs[] = {
{"chttp2/simple_ssl_fullstack",
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
chttp2_create_fixture_secure_fullstack,
cronet_init_client_simple_ssl_secure_fullstack,
chttp2_init_server_simple_ssl_secure_fullstack,
chttp2_tear_down_secure_fullstack},
};
static char *roots_filename;
@interface CoreCronetEnd2EndTests : XCTestCase
@end
@implementation CoreCronetEnd2EndTests
// The setUp() function is run before the test cases run and only run once
+ (void)setUp {
[super setUp];
FILE *roots_file;
size_t roots_size = strlen(test_root_cert);
char *argv[] = {"CoreCronetEnd2EndTests"};
grpc_test_init(1, argv);
grpc_end2end_tests_pre_init();
/* Set the SSL roots env var. */
roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename);
GPR_ASSERT(roots_filename != NULL);
GPR_ASSERT(roots_file != NULL);
GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
fclose(roots_file);
gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
grpc_init();
}
// The tearDown() function is run after all test cases finish running
+ (void)tearDown {
grpc_shutdown();
/* Cleanup. */
remove(roots_filename);
gpr_free(roots_filename);
[super tearDown];
}
- (void)testIndividualCase:(char*)test_case {
char *argv[] = {"h2_ssl", test_case};
for (int i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
grpc_end2end_tests(sizeof(argv) / sizeof(argv[0]), argv, configs[i]);
}
}
// TODO(mxyan): Use NSStringFromSelector(_cmd) to acquire test name from the
// test case method name, so that bodies of test cases can stay identical
- (void)testBadHostname {
[self testIndividualCase:"bad_hostname"];
}
- (void)testBinaryMetadata {
[self testIndividualCase:"binary_metadata"];
}
- (void)testCallCreds {
[self testIndividualCase:"call_creds"];
}
- (void)testCancelAfterAccept {
[self testIndividualCase:"cancel_after_accept"];
}
- (void)testCancelAfterClientDone {
[self testIndividualCase:"cancel_after_client_done"];
}
- (void)testCancelAfterInvoke {
[self testIndividualCase:"cancel_after_invoke"];
}
- (void)testCancelBeforeInvoke {
[self testIndividualCase:"cancel_before_invoke"];
}
- (void)testCancelInAVacuum {
[self testIndividualCase:"cancel_in_a_vacuum"];
}
- (void)testCancelWithStatus {
[self testIndividualCase:"cancel_with_status"];
}
- (void)testCompressedPayload {
[self testIndividualCase:"compressed_payload"];
}
- (void)testConnectivity {
[self testIndividualCase:"connectivity"];
}
- (void)testDefaultHost {
[self testIndividualCase:"default_host"];
}
- (void)testDisappearingServer {
[self testIndividualCase:"disappearing_server"];
}
- (void)testEmptyBatch {
[self testIndividualCase:"empty_batch"];
}
- (void)testFilterCausesClose {
[self testIndividualCase:"filter_causes_close"];
}
- (void)testGracefulServerShutdown {
[self testIndividualCase:"graceful_server_shutdown"];
}
- (void)testHighInitialSeqno {
[self testIndividualCase:"high_initial_seqno"];
}
- (void)testHpackSize {
[self testIndividualCase:"hpack_size"];
}
- (void)testIdempotentRequest {
[self testIndividualCase:"idempotent_request"];
}
- (void)testInvokeLargeRequest {
[self testIndividualCase:"invoke_large_request"];
}
- (void)testLargeMetadata {
[self testIndividualCase:"large_metadata"];
}
- (void)testMaxConcurrentStreams {
[self testIndividualCase:"max_concurrent_streams"];
}
- (void)testMaxMessageLength {
[self testIndividualCase:"max_message_length"];
}
- (void)testNegativeDeadline {
[self testIndividualCase:"negative_deadline"];
}
- (void)testNetworkStatusChange {
[self testIndividualCase:"network_status_change"];
}
- (void)testNoOp {
[self testIndividualCase:"no_op"];
}
- (void)testPayload {
[self testIndividualCase:"payload"];
}
- (void)testPing {
[self testIndividualCase:"ping"];
}
- (void)testPingPongStreaming {
[self testIndividualCase:"ping_pong_streaming"];
}
- (void)testRegisteredCall {
[self testIndividualCase:"registered_call"];
}
- (void)testRequestWithFlags {
[self testIndividualCase:"request_with_flags"];
}
- (void)testRequestWithPayload {
[self testIndividualCase:"request_with_payload"];
}
- (void)testServerFinishesRequest {
[self testIndividualCase:"server_finishes_request"];
}
- (void)testShutdownFinishesCalls {
[self testIndividualCase:"shutdown_finishes_calls"];
}
- (void)testShutdownFinishesTags {
[self testIndividualCase:"shutdown_finishes_tags"];
}
- (void)testSimpleDelayedRequest {
[self testIndividualCase:"simple_delayed_request"];
}
- (void)testSimpleMetadata {
[self testIndividualCase:"simple_metadata"];
}
- (void)testSimpleRequest {
[self testIndividualCase:"simple_request"];
}
- (void)testStreamingErrorResponse {
[self testIndividualCase:"streaming_error_response"];
}
- (void)testTrailingMetadata {
[self testIndividualCase:"trailing_metadata"];
}
@end

@ -0,0 +1,63 @@
/*
*
* 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/util/cli_credentials.h"
#include <gflags/gflags.h>
DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
namespace grpc {
namespace testing {
std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
const {
if (!FLAGS_enable_ssl) {
return grpc::InsecureChannelCredentials();
} else {
if (FLAGS_use_auth) {
return grpc::GoogleDefaultCredentials();
} else {
return grpc::SslCredentials(grpc::SslCredentialsOptions());
}
}
}
const grpc::string CliCredentials::GetCredentialUsage() const {
return " --enable_ssl ; Set whether to use tls\n"
" --use_auth ; Set whether to create default google"
" credentials\n";
}
} // namespace testing
} // namespace grpc

@ -0,0 +1,53 @@
/*
*
* 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_UTIL_CLI_CREDENTIALS_H
#define GRPC_TEST_CPP_UTIL_CLI_CREDENTIALS_H
#include <grpc++/security/credentials.h>
#include <grpc++/support/config.h>
namespace grpc {
namespace testing {
class CliCredentials {
public:
virtual ~CliCredentials() {}
virtual std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const;
virtual const grpc::string GetCredentialUsage() const;
};
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_CLI_CREDENTIALS_H

@ -0,0 +1,85 @@
/*
*
* 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_UTIL_CONFIG_GRPC_CLI_H
#define GRPC_TEST_CPP_UTIL_CONFIG_GRPC_CLI_H
#include <grpc++/impl/codegen/config_protobuf.h>
#ifndef GRPC_CUSTOM_DYNAMICMESSAGEFACTORY
#include <google/protobuf/dynamic_message.h>
#define GRPC_CUSTOM_DYNAMICMESSAGEFACTORY \
::google::protobuf::DynamicMessageFactory
#endif
#ifndef GRPC_CUSTOM_DESCRIPTORPOOLDATABASE
#include <google/protobuf/descriptor.h>
#define GRPC_CUSTOM_DESCRIPTORPOOLDATABASE \
::google::protobuf::DescriptorPoolDatabase
#define GRPC_CUSTOM_MERGEDDESCRIPTORDATABASE \
::google::protobuf::MergedDescriptorDatabase
#endif
#ifndef GRPC_CUSTOM_TEXTFORMAT
#include <google/protobuf/text_format.h>
#define GRPC_CUSTOM_TEXTFORMAT ::google::protobuf::TextFormat
#endif
#ifndef GRPC_CUSTOM_DISKSOURCETREE
#include <google/protobuf/compiler/importer.h>
#define GRPC_CUSTOM_DISKSOURCETREE ::google::protobuf::compiler::DiskSourceTree
#define GRPC_CUSTOM_IMPORTER ::google::protobuf::compiler::Importer
#define GRPC_CUSTOM_MULTIFILEERRORCOLLECTOR \
::google::protobuf::compiler::MultiFileErrorCollector
#endif
namespace grpc {
namespace protobuf {
typedef GRPC_CUSTOM_DYNAMICMESSAGEFACTORY DynamicMessageFactory;
typedef GRPC_CUSTOM_DESCRIPTORPOOLDATABASE DescriptorPoolDatabase;
typedef GRPC_CUSTOM_MERGEDDESCRIPTORDATABASE MergedDescriptorDatabase;
typedef GRPC_CUSTOM_TEXTFORMAT TextFormat;
namespace compiler {
typedef GRPC_CUSTOM_DISKSOURCETREE DiskSourceTree;
typedef GRPC_CUSTOM_IMPORTER Importer;
typedef GRPC_CUSTOM_MULTIFILEERRORCOLLECTOR MultiFileErrorCollector;
} // namespace importer
} // namespace protobuf
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_CONFIG_GRPC_CLI_H

@ -33,12 +33,14 @@
/*
A command line tool to talk to a grpc server.
Run `grpc_cli help` command to see its usage information.
Example of talking to grpc interop server:
grpc_cli call localhost:50051 UnaryCall "response_size:10" \
--protofiles=src/proto/grpc/testing/test.proto --enable_ssl=false
Options:
1. --protofiles, use this flag to provide a proto file if the server does
1. --protofiles, use this flag to provide proto files if the server does
does not have the reflection service.
2. --proto_path, if your proto file is not under current working directory,
use this flag to provide a search root. It should work similar to the
@ -48,15 +50,17 @@
--metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
4. --enable_ssl, whether to use tls.
5. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
6. --input_binary_file, a file containing the serialized request. The file
can be generated by calling something like:
6. --infile, input filename (defaults to stdin)
7. --outfile, output filename (defaults to stdout)
8. --binary_input, use the serialized request as input. The serialized
request can be generated by calling something like:
protoc --proto_path=src/proto/grpc/testing/ \
--encode=grpc.testing.SimpleRequest \
src/proto/grpc/testing/messages.proto \
< input.txt > input.bin
If this is used and no proto file is provided in the argument list, the
method string has to be exact in the form of /package.service/method.
7. --output_binary_file, a file to write binary format response into, it can
9. --binary_output, use binary format response as output, it can
be later decoded using protoc:
protoc --proto_path=src/proto/grpc/testing/ \
--decode=grpc.testing.SimpleResponse \
@ -64,182 +68,34 @@
< output.bin > output.txt
*/
#include <unistd.h>
#include <fstream>
#include <functional>
#include <iostream>
#include <sstream>
#include <gflags/gflags.h>
#include <grpc++/channel.h>
#include <grpc++/create_channel.h>
#include <grpc++/security/credentials.h>
#include <grpc++/support/string_ref.h>
#include <grpc/grpc.h>
#include "test/cpp/util/cli_call.h"
#include "test/cpp/util/proto_file_parser.h"
#include "test/cpp/util/string_ref_helper.h"
#include <grpc++/support/config.h>
#include "test/cpp/util/cli_credentials.h"
#include "test/cpp/util/grpc_tool.h"
#include "test/cpp/util/test_config.h"
DEFINE_bool(enable_ssl, true, "Whether to use ssl/tls.");
DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
DEFINE_string(input_binary_file, "",
"Path to input file containing serialized request.");
DEFINE_string(output_binary_file, "",
"Path to output file to write serialized response.");
DEFINE_string(metadata, "",
"Metadata to send to server, in the form of key1:val1:key2:val2");
DEFINE_string(proto_path, ".", "Path to look for the proto file.");
// TODO(zyc): support a list of input proto files
DEFINE_string(protofiles, "", "Name of the proto file.");
void ParseMetadataFlag(
std::multimap<grpc::string, grpc::string>* client_metadata) {
if (FLAGS_metadata.empty()) {
return;
}
std::vector<grpc::string> fields;
const char* delim = ":";
size_t cur, next = -1;
do {
cur = next + 1;
next = FLAGS_metadata.find_first_of(delim, cur);
fields.push_back(FLAGS_metadata.substr(cur, next - cur));
} while (next != grpc::string::npos);
if (fields.size() % 2) {
std::cout << "Failed to parse metadata flag" << std::endl;
exit(1);
}
for (size_t i = 0; i < fields.size(); i += 2) {
client_metadata->insert(
std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
}
}
DEFINE_string(outfile, "", "Output file (default is stdout)");
template <typename T>
void PrintMetadata(const T& m, const grpc::string& message) {
if (m.empty()) {
return;
}
std::cout << message << std::endl;
grpc::string pair;
for (typename T::const_iterator iter = m.begin(); iter != m.end(); ++iter) {
pair.clear();
pair.append(iter->first.data(), iter->first.size());
pair.append(" : ");
pair.append(iter->second.data(), iter->second.size());
std::cout << pair << std::endl;
static bool SimplePrint(const grpc::string& outfile,
const grpc::string& output) {
if (outfile.empty()) {
std::cout << output;
} else {
std::ofstream output_file(outfile, std::ios::trunc | std::ios::binary);
output_file << output;
output_file.close();
}
return true;
}
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
if (argc < 4 || grpc::string(argv[1]) != "call") {
std::cout << "Usage: grpc_cli call server_host:port method_name "
<< "[proto file] [text format request] [<options>]" << std::endl;
return 1;
}
grpc::string request_text;
grpc::string server_address(argv[2]);
grpc::string method_name(argv[3]);
std::unique_ptr<grpc::testing::ProtoFileParser> parser;
grpc::string serialized_request_proto;
if (argc == 5) {
request_text = argv[4];
}
std::shared_ptr<grpc::ChannelCredentials> creds;
if (!FLAGS_enable_ssl) {
creds = grpc::InsecureChannelCredentials();
} else {
if (FLAGS_use_auth) {
creds = grpc::GoogleDefaultCredentials();
} else {
creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
}
}
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, creds);
if (request_text.empty() && FLAGS_input_binary_file.empty()) {
if (isatty(STDIN_FILENO)) {
std::cout << "reading request message from stdin..." << std::endl;
}
std::stringstream input_stream;
input_stream << std::cin.rdbuf();
request_text = input_stream.str();
}
if (!request_text.empty()) {
if (!FLAGS_protofiles.empty()) {
parser.reset(new grpc::testing::ProtoFileParser(
FLAGS_proto_path, FLAGS_protofiles, method_name));
} else {
parser.reset(new grpc::testing::ProtoFileParser(channel, method_name));
}
method_name = parser->GetFullMethodName();
if (parser->HasError()) {
return 1;
}
if (!FLAGS_input_binary_file.empty()) {
std::cout
<< "warning: request given in argv, ignoring --input_binary_file"
<< std::endl;
}
}
if (parser) {
serialized_request_proto =
parser->GetSerializedProto(request_text, true /* is_request */);
if (parser->HasError()) {
return 1;
}
} else if (!FLAGS_input_binary_file.empty()) {
std::ifstream input_file(FLAGS_input_binary_file,
std::ios::in | std::ios::binary);
std::stringstream input_stream;
input_stream << input_file.rdbuf();
serialized_request_proto = input_stream.str();
}
std::cout << "connecting to " << server_address << std::endl;
grpc::string serialized_response_proto;
std::multimap<grpc::string, grpc::string> client_metadata;
std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
server_trailing_metadata;
ParseMetadataFlag(&client_metadata);
PrintMetadata(client_metadata, "Sending client initial metadata:");
grpc::Status s = grpc::testing::CliCall::Call(
channel, method_name, serialized_request_proto,
&serialized_response_proto, client_metadata, &server_initial_metadata,
&server_trailing_metadata);
PrintMetadata(server_initial_metadata,
"Received initial metadata from server:");
PrintMetadata(server_trailing_metadata,
"Received trailing metadata from server:");
if (s.ok()) {
std::cout << "Rpc succeeded with OK status" << std::endl;
if (parser) {
grpc::string response_text = parser->GetTextFormat(
serialized_response_proto, false /* is_request */);
if (parser->HasError()) {
return 1;
}
std::cout << "Response: \n " << response_text << std::endl;
}
if (!FLAGS_output_binary_file.empty()) {
std::ofstream output_file(FLAGS_output_binary_file,
std::ios::trunc | std::ios::binary);
output_file << serialized_response_proto;
}
} else {
std::cout << "Rpc failed with status code " << s.error_code()
<< ", error message: " << s.error_message() << std::endl;
}
return 0;
return grpc::testing::GrpcToolMainLib(
argc, (const char**)argv, grpc::testing::CliCredentials(),
std::bind(SimplePrint, FLAGS_outfile, std::placeholders::_1));
}

@ -0,0 +1,365 @@
/*
*
* 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/util/grpc_tool.h"
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <gflags/gflags.h>
#include <grpc++/channel.h>
#include <grpc++/create_channel.h>
#include <grpc++/grpc++.h>
#include <grpc++/security/credentials.h>
#include <grpc++/support/string_ref.h>
#include <grpc/grpc.h>
#include "test/cpp/util/cli_call.h"
#include "test/cpp/util/proto_file_parser.h"
#include "test/cpp/util/proto_reflection_descriptor_database.h"
#include "test/cpp/util/test_config.h"
DEFINE_bool(remotedb, true, "Use server types to parse and format messages");
DEFINE_string(metadata, "",
"Metadata to send to server, in the form of key1:val1:key2:val2");
DEFINE_string(proto_path, ".", "Path to look for the proto file.");
DEFINE_string(proto_file, "", "Name of the proto file.");
DEFINE_bool(binary_input, false, "Input in binary format");
DEFINE_bool(binary_output, false, "Output in binary format");
DEFINE_string(infile, "", "Input file (default is stdin)");
namespace grpc {
namespace testing {
namespace {
class GrpcTool {
public:
explicit GrpcTool();
virtual ~GrpcTool() {}
bool Help(int argc, const char** argv, CliCredentials cred,
GrpcToolOutputCallback callback);
bool CallMethod(int argc, const char** argv, CliCredentials cred,
GrpcToolOutputCallback callback);
// TODO(zyc): implement the following methods
// bool ListServices(int argc, const char** argv, GrpcToolOutputCallback
// callback);
// bool PrintType(int argc, const char** argv, GrpcToolOutputCallback
// callback);
// bool PrintTypeId(int argc, const char** argv, GrpcToolOutputCallback
// callback);
// bool ParseMessage(int argc, const char** argv, GrpcToolOutputCallback
// callback);
// bool ToText(int argc, const char** argv, GrpcToolOutputCallback callback);
// bool ToBinary(int argc, const char** argv, GrpcToolOutputCallback
// callback);
void SetPrintCommandMode(int exit_status) {
print_command_usage_ = true;
usage_exit_status_ = exit_status;
}
private:
void CommandUsage(const grpc::string& usage) const;
bool print_command_usage_;
int usage_exit_status_;
const grpc::string cred_usage_;
};
template <typename T>
std::function<bool(GrpcTool*, int, const char**, const CliCredentials,
GrpcToolOutputCallback)>
BindWith5Args(T&& func) {
return std::bind(std::forward<T>(func), std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5);
}
template <typename T>
size_t ArraySize(T& a) {
return ((sizeof(a) / sizeof(*(a))) /
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
}
void ParseMetadataFlag(
std::multimap<grpc::string, grpc::string>* client_metadata) {
if (FLAGS_metadata.empty()) {
return;
}
std::vector<grpc::string> fields;
const char* delim = ":";
size_t cur, next = -1;
do {
cur = next + 1;
next = FLAGS_metadata.find_first_of(delim, cur);
fields.push_back(FLAGS_metadata.substr(cur, next - cur));
} while (next != grpc::string::npos);
if (fields.size() % 2) {
fprintf(stderr, "Failed to parse metadata flag.\n");
exit(1);
}
for (size_t i = 0; i < fields.size(); i += 2) {
client_metadata->insert(
std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
}
}
template <typename T>
void PrintMetadata(const T& m, const grpc::string& message) {
if (m.empty()) {
return;
}
fprintf(stderr, "%s\n", message.c_str());
grpc::string pair;
for (typename T::const_iterator iter = m.begin(); iter != m.end(); ++iter) {
pair.clear();
pair.append(iter->first.data(), iter->first.size());
pair.append(" : ");
pair.append(iter->second.data(), iter->second.size());
fprintf(stderr, "%s\n", pair.c_str());
}
}
struct Command {
const char* command;
std::function<bool(GrpcTool*, int, const char**, const CliCredentials,
GrpcToolOutputCallback)>
function;
int min_args;
int max_args;
};
const Command ops[] = {
{"help", BindWith5Args(&GrpcTool::Help), 0, INT_MAX},
// {"ls", BindWith5Args(&GrpcTool::ListServices), 1, 3},
// {"list", BindWith5Args(&GrpcTool::ListServices), 1, 3},
{"call", BindWith5Args(&GrpcTool::CallMethod), 2, 3},
// {"type", BindWith5Args(&GrpcTool::PrintType), 2, 2},
// {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3},
// {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3},
// {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3},
};
void Usage(const grpc::string& msg) {
fprintf(
stderr,
"%s\n"
// " grpc_cli ls ... ; List services\n"
" grpc_cli call ... ; Call method\n"
// " grpc_cli type ... ; Print type\n"
// " grpc_cli parse ... ; Parse message\n"
// " grpc_cli totext ... ; Convert binary message to text\n"
// " grpc_cli tobinary ... ; Convert text message to binary\n"
" grpc_cli help ... ; Print this message, or per-command usage\n"
"\n",
msg.c_str());
exit(1);
}
const Command* FindCommand(const grpc::string& name) {
for (int i = 0; i < (int)ArraySize(ops); i++) {
if (name == ops[i].command) {
return &ops[i];
}
}
return NULL;
}
} // namespace
int GrpcToolMainLib(int argc, const char** argv, const CliCredentials cred,
GrpcToolOutputCallback callback) {
if (argc < 2) {
Usage("No command specified");
}
grpc::string command = argv[1];
argc -= 2;
argv += 2;
const Command* cmd = FindCommand(command);
if (cmd != NULL) {
GrpcTool grpc_tool;
if (argc < cmd->min_args || argc > cmd->max_args) {
// Force the command to print its usage message
fprintf(stderr, "\nWrong number of arguments for %s\n", command.c_str());
grpc_tool.SetPrintCommandMode(1);
return cmd->function(&grpc_tool, -1, NULL, cred, callback);
}
const bool ok = cmd->function(&grpc_tool, argc, argv, cred, callback);
return ok ? 0 : 1;
} else {
Usage("Invalid command '" + grpc::string(command.c_str()) + "'");
}
return 1;
}
GrpcTool::GrpcTool() : print_command_usage_(false), usage_exit_status_(0) {}
void GrpcTool::CommandUsage(const grpc::string& usage) const {
if (print_command_usage_) {
fprintf(stderr, "\n%s%s\n", usage.c_str(),
(usage.empty() || usage[usage.size() - 1] != '\n') ? "\n" : "");
exit(usage_exit_status_);
}
}
bool GrpcTool::Help(int argc, const char** argv, const CliCredentials cred,
GrpcToolOutputCallback callback) {
CommandUsage(
"Print help\n"
" grpc_cli help [subcommand]\n");
if (argc == 0) {
Usage("");
} else {
const Command* cmd = FindCommand(argv[0]);
if (cmd == NULL) {
Usage("Unknown command '" + grpc::string(argv[0]) + "'");
}
SetPrintCommandMode(0);
cmd->function(this, -1, NULL, cred, callback);
}
return true;
}
bool GrpcTool::CallMethod(int argc, const char** argv,
const CliCredentials cred,
GrpcToolOutputCallback callback) {
CommandUsage(
"Call method\n"
" grpc_cli call <address> <service>[.<method>] <request>\n"
" <address> ; host:port\n"
" <service> ; Exported service name\n"
" <method> ; Method name\n"
" <request> ; Text protobuffer (overrides infile)\n"
" --proto_file ; Comma separated proto files used as a"
" fallback when parsing request/response\n"
" --proto_path ; The search path of proto files, valid"
" only when --proto_file is given\n"
" --metadata ; The metadata to be sent to the server\n"
" --infile ; Input filename (defaults to stdin)\n"
" --outfile ; Output filename (defaults to stdout)\n"
" --binary_input ; Input in binary format\n"
" --binary_output ; Output in binary format\n" +
cred.GetCredentialUsage());
std::stringstream output_ss;
grpc::string request_text;
grpc::string server_address(argv[0]);
grpc::string method_name(argv[1]);
std::unique_ptr<grpc::testing::ProtoFileParser> parser;
grpc::string serialized_request_proto;
if (argc == 3) {
request_text = argv[2];
if (!FLAGS_infile.empty()) {
fprintf(stderr, "warning: request given in argv, ignoring --infile\n");
}
} else {
std::stringstream input_stream;
if (FLAGS_infile.empty()) {
if (isatty(STDIN_FILENO)) {
fprintf(stderr, "reading request message from stdin...\n");
}
input_stream << std::cin.rdbuf();
} else {
std::ifstream input_file(FLAGS_infile, std::ios::in | std::ios::binary);
input_stream << input_file.rdbuf();
input_file.close();
}
request_text = input_stream.str();
}
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, cred.GetCredentials());
if (!FLAGS_binary_input || !FLAGS_binary_output) {
parser.reset(
new grpc::testing::ProtoFileParser(FLAGS_remotedb ? channel : nullptr,
FLAGS_proto_path, FLAGS_proto_file));
if (parser->HasError()) {
return false;
}
}
if (FLAGS_binary_input) {
serialized_request_proto = request_text;
} else {
serialized_request_proto = parser->GetSerializedProtoFromMethod(
method_name, request_text, true /* is_request */);
if (parser->HasError()) {
return false;
}
}
fprintf(stderr, "connecting to %s\n", server_address.c_str());
grpc::string serialized_response_proto;
std::multimap<grpc::string, grpc::string> client_metadata;
std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
server_trailing_metadata;
ParseMetadataFlag(&client_metadata);
PrintMetadata(client_metadata, "Sending client initial metadata:");
grpc::Status status = grpc::testing::CliCall::Call(
channel, parser->GetFormatedMethodName(method_name),
serialized_request_proto, &serialized_response_proto, client_metadata,
&server_initial_metadata, &server_trailing_metadata);
PrintMetadata(server_initial_metadata,
"Received initial metadata from server:");
PrintMetadata(server_trailing_metadata,
"Received trailing metadata from server:");
if (status.ok()) {
fprintf(stderr, "Rpc succeeded with OK status\n");
if (FLAGS_binary_output) {
output_ss << serialized_response_proto;
} else {
grpc::string response_text = parser->GetTextFormatFromMethod(
method_name, serialized_response_proto, false /* is_request */);
if (parser->HasError()) {
return false;
}
output_ss << "Response: \n " << response_text << std::endl;
}
} else {
fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
status.error_code(), status.error_message().c_str());
}
return callback(output_ss.str());
}
} // namespace testing
} // namespace grpc

@ -0,0 +1,54 @@
/*
*
* 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_UTIL_GRPC_TOOL_H
#define GRPC_TEST_CPP_UTIL_GRPC_TOOL_H
#include <functional>
#include <grpc++/support/config.h>
#include "test/cpp/util/cli_credentials.h"
namespace grpc {
namespace testing {
typedef std::function<bool(const grpc::string &)> GrpcToolOutputCallback;
int GrpcToolMainLib(int argc, const char **argv, CliCredentials cred,
GrpcToolOutputCallback callback);
} // namespace testing
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_GRPC_TOOL_H

@ -0,0 +1,227 @@
/*
*
* 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/util/grpc_tool.h"
#include <sstream>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/ext/proto_server_reflection_plugin.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 "src/proto/grpc/testing/echo.pb.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/cli_credentials.h"
#include "test/cpp/util/string_ref_helper.h"
using grpc::testing::EchoRequest;
using grpc::testing::EchoResponse;
namespace grpc {
namespace testing {
namespace {
class TestCliCredentials GRPC_FINAL : public grpc::testing::CliCredentials {
public:
std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const
GRPC_OVERRIDE {
return InsecureChannelCredentials();
}
const grpc::string GetCredentialUsage() const GRPC_OVERRIDE { return ""; }
};
} // namespame
class TestServiceImpl : public ::grpc::testing::EchoTestService::Service {
public:
Status Echo(ServerContext* context, const EchoRequest* request,
EchoResponse* response) GRPC_OVERRIDE {
if (!context->client_metadata().empty()) {
for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
iter = context->client_metadata().begin();
iter != context->client_metadata().end(); ++iter) {
context->AddInitialMetadata(ToString(iter->first),
ToString(iter->second));
}
}
context->AddTrailingMetadata("trailing_key", "trailing_value");
response->set_message(request->message());
return Status::OK;
}
};
class GrpcToolTest : public ::testing::Test {
protected:
GrpcToolTest() {}
// SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die()
// uses atexit() to free chosen ports, and it will spawn a new thread in
// resolve_address_posix.c:192 at exit time.
const grpc::string SetUpServer() {
std::ostringstream server_address;
int port = grpc_pick_unused_port_or_die();
server_address << "localhost:" << port;
// Setup server
ServerBuilder builder;
builder.AddListeningPort(server_address.str(), InsecureServerCredentials());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
return server_address.str();
}
void ShutdownServer() { server_->Shutdown(); }
std::unique_ptr<Server> server_;
TestServiceImpl service_;
reflection::ProtoServerReflectionPlugin plugin_;
};
static bool PrintStream(std::stringstream* ss, const grpc::string& output) {
(*ss) << output << std::endl;
return true;
}
template <typename T>
static size_t ArraySize(T& a) {
return ((sizeof(a) / sizeof(*(a))) /
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
}
#define USAGE_REGEX "( grpc_cli .+\n){2,10}"
TEST_F(GrpcToolTest, NoCommand) {
// Test input "grpc_cli"
std::stringstream output_stream;
const char* argv[] = {"grpc_cli"};
// Exit with 1, print usage instruction in stderr
EXPECT_EXIT(
GrpcToolMainLib(
ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream, std::placeholders::_1)),
::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
// No output
EXPECT_TRUE(0 == output_stream.tellp());
}
TEST_F(GrpcToolTest, InvalidCommand) {
// Test input "grpc_cli"
std::stringstream output_stream;
const char* argv[] = {"grpc_cli", "abc"};
// Exit with 1, print usage instruction in stderr
EXPECT_EXIT(
GrpcToolMainLib(
ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream, std::placeholders::_1)),
::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
// No output
EXPECT_TRUE(0 == output_stream.tellp());
}
TEST_F(GrpcToolTest, HelpCommand) {
// Test input "grpc_cli help"
std::stringstream output_stream;
const char* argv[] = {"grpc_cli", "help"};
// Exit with 1, print usage instruction in stderr
EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)),
::testing::ExitedWithCode(1), USAGE_REGEX);
// No output
EXPECT_TRUE(0 == output_stream.tellp());
}
TEST_F(GrpcToolTest, CallCommand) {
// Test input "grpc_cli call Echo"
std::stringstream output_stream;
const grpc::string server_address = SetUpServer();
const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
"message: 'Hello'"};
EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream,
std::placeholders::_1)));
// Expected output: "message: \"Hello\""
EXPECT_TRUE(NULL !=
strstr(output_stream.str().c_str(), "message: \"Hello\""));
ShutdownServer();
}
TEST_F(GrpcToolTest, TooFewArguments) {
// Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
std::stringstream output_stream;
const char* argv[] = {"grpc_cli", "call", "Echo"};
// Exit with 1
EXPECT_EXIT(
GrpcToolMainLib(
ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream, std::placeholders::_1)),
::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
// No output
EXPECT_TRUE(0 == output_stream.tellp());
}
TEST_F(GrpcToolTest, TooManyArguments) {
// Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
std::stringstream output_stream;
const char* argv[] = {"grpc_cli", "call", "localhost:10000",
"Echo", "Echo", "message: 'Hello'"};
// Exit with 1
EXPECT_EXIT(
GrpcToolMainLib(
ArraySize(argv), argv, TestCliCredentials(),
std::bind(PrintStream, &output_stream, std::placeholders::_1)),
::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
// No output
EXPECT_TRUE(0 == output_stream.tellp());
}
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
::testing::FLAGS_gtest_death_test_style = "threadsafe";
return RUN_ALL_TESTS();
}

@ -37,7 +37,6 @@
#include <iostream>
#include <sstream>
#include <google/protobuf/text_format.h>
#include <grpc++/support/config.h>
namespace grpc {
@ -56,8 +55,7 @@ bool MethodNameMatch(const grpc::string& full_name, const grpc::string& input) {
}
} // namespace
class ErrorPrinter
: public google::protobuf::compiler::MultiFileErrorCollector {
class ErrorPrinter : public protobuf::compiler::MultiFileErrorCollector {
public:
explicit ErrorPrinter(ProtoFileParser* parser) : parser_(parser) {}
@ -71,7 +69,7 @@ class ErrorPrinter
void AddWarning(const grpc::string& filename, int line, int column,
const grpc::string& message) GRPC_OVERRIDE {
std::cout << "warning " << filename << " " << line << " " << column << " "
std::cerr << "warning " << filename << " " << line << " " << column << " "
<< message << std::endl;
}
@ -79,62 +77,69 @@ class ErrorPrinter
ProtoFileParser* parser_; // not owned
};
ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
const grpc::string& file_name,
const grpc::string& method)
ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
const grpc::string& proto_path,
const grpc::string& protofiles)
: has_error_(false) {
source_tree_.MapPath("", proto_path);
error_printer_.reset(new ErrorPrinter(this));
importer_.reset(new google::protobuf::compiler::Importer(
&source_tree_, error_printer_.get()));
const auto* file_desc = importer_->Import(file_name);
if (!file_desc) {
LogError("");
return;
std::vector<std::string> service_list;
if (channel) {
reflection_db_.reset(new grpc::ProtoReflectionDescriptorDatabase(channel));
reflection_db_->GetServices(&service_list);
}
dynamic_factory_.reset(
new google::protobuf::DynamicMessageFactory(importer_->pool()));
std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
for (int i = 0; i < file_desc->service_count(); i++) {
service_desc_list.push_back(file_desc->service(i));
}
InitProtoFileParser(method, service_desc_list);
}
if (!protofiles.empty()) {
source_tree_.MapPath("", proto_path);
error_printer_.reset(new ErrorPrinter(this));
importer_.reset(
new protobuf::compiler::Importer(&source_tree_, error_printer_.get()));
ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
const grpc::string& method)
: has_error_(false),
desc_db_(new grpc::ProtoReflectionDescriptorDatabase(channel)),
desc_pool_(new google::protobuf::DescriptorPool(desc_db_.get())) {
std::vector<std::string> service_list;
if (!desc_db_->GetServices(&service_list)) {
LogError(
"Failed to get services from the server, "
"it may not have the reflection service.\n"
"Please try to use the --protofiles option to provide a proto file.");
grpc::string file_name;
std::stringstream ss(protofiles);
while (std::getline(ss, file_name, ',')) {
const auto* file_desc = importer_->Import(file_name);
if (file_desc) {
for (int i = 0; i < file_desc->service_count(); i++) {
service_desc_list_.push_back(file_desc->service(i));
}
} else {
std::cerr << file_name << " not found" << std::endl;
}
}
file_db_.reset(new protobuf::DescriptorPoolDatabase(*importer_->pool()));
}
if (has_error_) {
if (!reflection_db_ && !file_db_) {
LogError("No available proto database");
return;
}
dynamic_factory_.reset(
new google::protobuf::DynamicMessageFactory(desc_pool_.get()));
std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
if (!reflection_db_) {
desc_db_ = std::move(file_db_);
} else if (!file_db_) {
desc_db_ = std::move(reflection_db_);
} else {
desc_db_.reset(new protobuf::MergedDescriptorDatabase(reflection_db_.get(),
file_db_.get()));
}
desc_pool_.reset(new protobuf::DescriptorPool(desc_db_.get()));
dynamic_factory_.reset(new protobuf::DynamicMessageFactory(desc_pool_.get()));
for (auto it = service_list.begin(); it != service_list.end(); it++) {
service_desc_list.push_back(desc_pool_->FindServiceByName(*it));
if (const protobuf::ServiceDescriptor* service_desc =
desc_pool_->FindServiceByName(*it)) {
service_desc_list_.push_back(service_desc);
}
}
InitProtoFileParser(method, service_desc_list);
}
ProtoFileParser::~ProtoFileParser() {}
void ProtoFileParser::InitProtoFileParser(
const grpc::string& method,
const std::vector<const google::protobuf::ServiceDescriptor*>
service_desc_list) {
const google::protobuf::MethodDescriptor* method_descriptor = nullptr;
for (auto it = service_desc_list.begin(); it != service_desc_list.end();
grpc::string ProtoFileParser::GetFullMethodName(const grpc::string& method) {
has_error_ = false;
const protobuf::MethodDescriptor* method_descriptor = nullptr;
for (auto it = service_desc_list_.begin(); it != service_desc_list_.end();
it++) {
const auto* service_desc = *it;
for (int j = 0; j < service_desc->method_count(); j++) {
@ -154,28 +159,82 @@ void ProtoFileParser::InitProtoFileParser(
LogError("Method name not found");
}
if (has_error_) {
return;
return "";
}
return method_descriptor->full_name();
}
grpc::string ProtoFileParser::GetFormatedMethodName(
const grpc::string& method) {
has_error_ = false;
grpc::string formated_method_name = GetFullMethodName(method);
if (has_error_) {
return "";
}
full_method_name_ = method_descriptor->full_name();
size_t last_dot = full_method_name_.find_last_of('.');
size_t last_dot = formated_method_name.find_last_of('.');
if (last_dot != grpc::string::npos) {
full_method_name_[last_dot] = '/';
formated_method_name[last_dot] = '/';
}
formated_method_name.insert(formated_method_name.begin(), '/');
return formated_method_name;
}
grpc::string ProtoFileParser::GetMessageTypeFromMethod(
const grpc::string& method, bool is_request) {
has_error_ = false;
grpc::string full_method_name = GetFullMethodName(method);
if (has_error_) {
return "";
}
const protobuf::MethodDescriptor* method_desc =
desc_pool_->FindMethodByName(full_method_name);
if (!method_desc) {
LogError("Method not found");
return "";
}
full_method_name_.insert(full_method_name_.begin(), '/');
request_prototype_.reset(
dynamic_factory_->GetPrototype(method_descriptor->input_type())->New());
response_prototype_.reset(
dynamic_factory_->GetPrototype(method_descriptor->output_type())->New());
return is_request ? method_desc->input_type()->full_name()
: method_desc->output_type()->full_name();
}
grpc::string ProtoFileParser::GetSerializedProto(
const grpc::string& text_format_proto, bool is_request) {
grpc::string ProtoFileParser::GetSerializedProtoFromMethod(
const grpc::string& method, const grpc::string& text_format_proto,
bool is_request) {
has_error_ = false;
grpc::string message_type_name = GetMessageTypeFromMethod(method, is_request);
if (has_error_) {
return "";
}
return GetSerializedProtoFromMessageType(message_type_name,
text_format_proto);
}
grpc::string ProtoFileParser::GetTextFormatFromMethod(
const grpc::string& method, const grpc::string& serialized_proto,
bool is_request) {
has_error_ = false;
grpc::string message_type_name = GetMessageTypeFromMethod(method, is_request);
if (has_error_) {
return "";
}
return GetTextFormatFromMessageType(message_type_name, serialized_proto);
}
grpc::string ProtoFileParser::GetSerializedProtoFromMessageType(
const grpc::string& message_type_name,
const grpc::string& text_format_proto) {
has_error_ = false;
grpc::string serialized;
grpc::protobuf::Message* msg =
is_request ? request_prototype_.get() : response_prototype_.get();
bool ok =
google::protobuf::TextFormat::ParseFromString(text_format_proto, msg);
const protobuf::Descriptor* desc =
desc_pool_->FindMessageTypeByName(message_type_name);
if (!desc) {
LogError("Message type not found");
return "";
}
std::unique_ptr<grpc::protobuf::Message> msg(
dynamic_factory_->GetPrototype(desc)->New());
bool ok = protobuf::TextFormat::ParseFromString(text_format_proto, msg.get());
if (!ok) {
LogError("Failed to parse text format to proto.");
return "";
@ -188,16 +247,24 @@ grpc::string ProtoFileParser::GetSerializedProto(
return serialized;
}
grpc::string ProtoFileParser::GetTextFormat(
const grpc::string& serialized_proto, bool is_request) {
grpc::protobuf::Message* msg =
is_request ? request_prototype_.get() : response_prototype_.get();
grpc::string ProtoFileParser::GetTextFormatFromMessageType(
const grpc::string& message_type_name,
const grpc::string& serialized_proto) {
has_error_ = false;
const protobuf::Descriptor* desc =
desc_pool_->FindMessageTypeByName(message_type_name);
if (!desc) {
LogError("Message type not found");
return "";
}
std::unique_ptr<grpc::protobuf::Message> msg(
dynamic_factory_->GetPrototype(desc)->New());
if (!msg->ParseFromString(serialized_proto)) {
LogError("Failed to deserialize proto.");
return "";
}
grpc::string text_format;
if (!google::protobuf::TextFormat::PrintToString(*msg, &text_format)) {
if (!protobuf::TextFormat::PrintToString(*msg.get(), &text_format)) {
LogError("Failed to print proto message to text format");
return "";
}
@ -206,7 +273,7 @@ grpc::string ProtoFileParser::GetTextFormat(
void ProtoFileParser::LogError(const grpc::string& error_msg) {
if (!error_msg.empty()) {
std::cout << error_msg << std::endl;
std::cerr << error_msg << std::endl;
}
has_error_ = true;
}

@ -36,11 +36,9 @@
#include <memory>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h>
#include <grpc++/channel.h>
#include "src/compiler/config.h"
#include "test/cpp/util/config_grpc_cli.h"
#include "test/cpp/util/proto_reflection_descriptor_database.h"
namespace grpc {
@ -50,44 +48,63 @@ class ErrorPrinter;
// Find method and associated request/response types.
class ProtoFileParser {
public:
// The given proto file_name will be searched in a source tree rooted from
// proto_path. The method could be a partial string such as Service.Method or
// even just Method. It will log an error if there is ambiguity.
ProtoFileParser(const grpc::string& proto_path, const grpc::string& file_name,
const grpc::string& method);
// The parser will search proto files using the server reflection service
// provided on the given channel. The given protofiles in a source tree rooted
// from proto_path will also be searched.
ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
const grpc::string& method);
const grpc::string& proto_path,
const grpc::string& protofiles);
~ProtoFileParser();
grpc::string GetFullMethodName() const { return full_method_name_; }
// The input method name in the following four functions could be a partial
// string such as Service.Method or even just Method. It will log an error if
// there is ambiguity.
// Full method name is in the form of Service.Method, it's good to be used in
// descriptor database queries.
grpc::string GetFullMethodName(const grpc::string& method);
// Formated method name is in the form of /Service/Method, it's good to be
// used as the argument of Stub::Call()
grpc::string GetFormatedMethodName(const grpc::string& method);
grpc::string GetSerializedProtoFromMethod(
const grpc::string& method, const grpc::string& text_format_proto,
bool is_request);
grpc::string GetTextFormatFromMethod(const grpc::string& method,
const grpc::string& serialized_proto,
bool is_request);
grpc::string GetSerializedProto(const grpc::string& text_format_proto,
bool is_request);
grpc::string GetSerializedProtoFromMessageType(
const grpc::string& message_type_name,
const grpc::string& text_format_proto);
grpc::string GetTextFormat(const grpc::string& serialized_proto,
bool is_request);
grpc::string GetTextFormatFromMessageType(
const grpc::string& message_type_name,
const grpc::string& serialized_proto);
bool HasError() const { return has_error_; }
void LogError(const grpc::string& error_msg);
private:
void InitProtoFileParser(
const grpc::string& method,
const std::vector<const google::protobuf::ServiceDescriptor*> services);
grpc::string GetMessageTypeFromMethod(const grpc::string& method,
bool is_request);
bool has_error_;
grpc::string request_text_;
grpc::string full_method_name_;
google::protobuf::compiler::DiskSourceTree source_tree_;
protobuf::compiler::DiskSourceTree source_tree_;
std::unique_ptr<ErrorPrinter> error_printer_;
std::unique_ptr<google::protobuf::compiler::Importer> importer_;
std::unique_ptr<grpc::ProtoReflectionDescriptorDatabase> desc_db_;
std::unique_ptr<google::protobuf::DescriptorPool> desc_pool_;
std::unique_ptr<google::protobuf::DynamicMessageFactory> dynamic_factory_;
std::unique_ptr<protobuf::compiler::Importer> importer_;
std::unique_ptr<grpc::ProtoReflectionDescriptorDatabase> reflection_db_;
std::unique_ptr<protobuf::DescriptorPoolDatabase> file_db_;
std::unique_ptr<protobuf::DescriptorDatabase> desc_db_;
std::unique_ptr<protobuf::DescriptorPool> desc_pool_;
std::unique_ptr<protobuf::DynamicMessageFactory> dynamic_factory_;
std::unique_ptr<grpc::protobuf::Message> request_prototype_;
std::unique_ptr<grpc::protobuf::Message> response_prototype_;
std::vector<const protobuf::ServiceDescriptor*> service_desc_list_;
};
} // namespace testing

@ -58,7 +58,7 @@ ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {
stream_->WritesDone();
Status status = stream_->Finish();
if (!status.ok()) {
gpr_log(GPR_ERROR,
gpr_log(GPR_INFO,
"ServerReflectionInfo rpc failed. Error code: %d, details: %s",
(int)status.error_code(), status.error_message().c_str());
}

@ -0,0 +1 @@
Subproject commit bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c

@ -43,8 +43,8 @@ gcloud compute instances create $INSTANCE_NAME \
--project="$CLOUD_PROJECT" \
--zone "$ZONE" \
--machine-type n1-standard-8 \
--image-family=ubuntu-1510 \
--image-project=ubuntu-os-cloud \
--image=ubuntu-1510 \
--image-project=grpc-testing \
--boot-disk-size 1000
echo 'Created GCE instance, waiting 60 seconds for it to come online.'

@ -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.
FROM ubuntu:14.04
RUN apt-get update && \
apt-get install -y \
git build-essential \
pkg-config flex \
bison \
libkrb5-dev \
libsasl2-dev \
libnuma-dev \
pkg-config \
libssl-dev \
autoconf libtool \
cmake \
libiberty-dev \
g++ unzip \
curl make automake libtool libboost-dev
# Configure git
RUN git config --global user.name "Jenkins" && \
git config --global user.email "jenkins@grpc"
# Clone gRPC
RUN git clone https://github.com/grpc/grpc
# Update Submodules
RUN cd grpc && git submodule update --init
# Install protobuf
RUN cd grpc/third_party/protobuf && ./autogen.sh && ./configure && \
make -j && make check -j && make install && ldconfig
# Install gRPC
RUN cd grpc && make -j && make install
# Install thrift
RUN cd grpc/third_party/thrift && git am --signoff < ../../tools/grift/grpc_plugins_generator.patch && \
./bootstrap.sh && ./configure && make -j && make install

@ -0,0 +1,26 @@
Copyright 2016 Google Inc.
#Documentation
grift is integration of [Apache Thrift](https://github.com/apache/thrift.git) Serializer with gRPC.
This integration allows you to use grpc to send thrift messages in C++ and java.
grift uses Compact Protocol to serialize thrift messages.
##generating grpc plugins for thrift services
###CPP
```sh
$ thrift --gen cpp <thrift-file>
```
###JAVA
```sh
$ thrift --gen java <thrift-file>
```
#Installation
Before Installing thrift make sure to apply this [patch](grpc_plugins_generator.patch) to third_party/thrift.
Go to third_party/thrift and follow the [INSTALLATION](https://github.com/apache/thrift.git) instructions to install thrift with commit id bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c.

File diff suppressed because it is too large Load Diff

@ -662,7 +662,7 @@ argp.add_argument('--prod_servers',
'cloud_to_prod_auth tests against.'))
argp.add_argument('-s', '--server',
choices=['all'] + sorted(_SERVERS),
action='append',
nargs='+',
help='Run cloud_to_cloud servers in a separate docker ' +
'image. Servers can only be started automatically if ' +
'--use_docker option is enabled.',

@ -48,6 +48,7 @@ cat << EOF | awk '{ print $1 }' | sort > $want_submodules
e8ae137c96444ea313485ed1118c5e43b2099cf1 third_party/protobuf (v3.0.0-beta-4-74-ge8ae137)
50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8)
e7fe2744db383c4489b7adc2b74f8ec3069367e4 third_party/c-ares (1.11.0)
bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c third_party/thrift
EOF
diff -u $submodules $want_submodules

@ -2164,14 +2164,11 @@
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc++",
"grpc++_reflection",
"grpc++_test_config",
"grpc++_test_util",
"grpc_cli_libs",
"grpc_test_util"
"grpc_cli_libs"
],
"headers": [],
"language": "c++",
@ -2260,6 +2257,35 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc++",
"grpc++_codegen_proto",
"grpc++_config_proto",
"grpc++_reflection",
"grpc_cli_libs",
"grpc_test_util"
],
"headers": [
"src/proto/grpc/testing/echo.grpc.pb.h",
"src/proto/grpc/testing/echo.pb.h",
"src/proto/grpc/testing/echo_messages.grpc.pb.h",
"src/proto/grpc/testing/echo_messages.pb.h",
"test/cpp/util/string_ref_helper.h"
],
"language": "c++",
"name": "grpc_tool_test",
"src": [
"test/cpp/util/grpc_tool_test.cc",
"test/cpp/util/string_ref_helper.cc",
"test/cpp/util/string_ref_helper.h"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"grpc",
@ -4468,7 +4494,8 @@
"grpc++_codegen_base_src",
"grpc++_codegen_proto",
"grpc++_config_proto",
"grpc_test_util"
"grpc_test_util",
"thrift_util"
],
"headers": [
"src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h",
@ -4525,10 +4552,13 @@
"deps": [
"grpc++",
"grpc++_reflection",
"grpc_plugin_support"
"grpc++_test_config"
],
"headers": [
"test/cpp/util/cli_call.h",
"test/cpp/util/cli_credentials.h",
"test/cpp/util/config_grpc_cli.h",
"test/cpp/util/grpc_tool.h",
"test/cpp/util/proto_file_parser.h",
"test/cpp/util/proto_reflection_descriptor_database.h"
],
@ -4537,6 +4567,11 @@
"src": [
"test/cpp/util/cli_call.cc",
"test/cpp/util/cli_call.h",
"test/cpp/util/cli_credentials.cc",
"test/cpp/util/cli_credentials.h",
"test/cpp/util/config_grpc_cli.h",
"test/cpp/util/grpc_tool.cc",
"test/cpp/util/grpc_tool.h",
"test/cpp/util/proto_file_parser.cc",
"test/cpp/util/proto_file_parser.h",
"test/cpp/util/proto_reflection_descriptor_database.cc",
@ -6930,5 +6965,22 @@
],
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"grpc++_codegen_base"
],
"headers": [
"include/grpc++/impl/codegen/thrift_serializer.h",
"include/grpc++/impl/codegen/thrift_utils.h"
],
"language": "c++",
"name": "thrift_util",
"src": [
"include/grpc++/impl/codegen/thrift_serializer.h",
"include/grpc++/impl/codegen/thrift_utils.h"
],
"third_party": false,
"type": "filegroup"
}
]

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

@ -200,6 +200,8 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_serializer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_utils.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h" />

@ -192,6 +192,12 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_serializer.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_utils.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h">

@ -148,12 +148,19 @@
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\config_grpc_cli.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.cc">
@ -166,8 +173,8 @@
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_plugin_support\grpc_plugin_support.vcxproj">
<Project>{B6E81D84-2ACB-41B8-8781-493A944C7817}</Project>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
<Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

@ -4,6 +4,12 @@
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
@ -15,6 +21,15 @@
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\config_grpc_cli.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h">
<Filter>test\cpp\util</Filter>
</ClInclude>

@ -167,12 +167,6 @@
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_cli_libs\grpc_cli_libs.vcxproj">
<Project>{86E35862-43E8-F59E-F906-AFE0348AD3D2}</Project>
</ProjectReference>
<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++_reflection\grpc++_reflection.vcxproj">
<Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</Project>
</ProjectReference>
@ -182,9 +176,6 @@
<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>

@ -0,0 +1,286 @@
<?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>{F00D82D4-E988-6D2F-F0B9-9E82BCC2A2B2}</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>grpc_tool_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>grpc_tool_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>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.cc">
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.cc">
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.cc">
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.cc">
</ClCompile>
<ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.h">
</ClInclude>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool_test.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.cc">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_cli_libs\grpc_cli_libs.vcxproj">
<Project>{86E35862-43E8-F59E-F906-AFE0348AD3D2}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj">
<Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</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,232 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.proto">
<Filter>src\proto\grpc\testing</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.proto">
<Filter>src\proto\grpc\testing</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool_test.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
<Filter>include\grpc++\impl\codegen\security</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
<Filter>include\grpc\impl\codegen</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="include">
<UniqueIdentifier>{89fed779-17c5-23da-c8a2-9e868ff34480}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc">
<UniqueIdentifier>{96e4a1a8-0b91-1a6d-ae4d-ddf33abb93c0}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc++">
<UniqueIdentifier>{1d9dcc6f-7c1b-cdc3-4c35-73d5968dfd92}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc++\impl">
<UniqueIdentifier>{5eca7690-973a-c8ed-84d6-5325f8de43ac}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc++\impl\codegen">
<UniqueIdentifier>{5789073e-5b84-0ec9-af06-47866647874d}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc++\impl\codegen\security">
<UniqueIdentifier>{d3f3293f-204f-7771-fcdf-de673f6b06b6}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc\impl">
<UniqueIdentifier>{7e90f37b-f9cc-0725-b2c1-12aa7d4809ba}</UniqueIdentifier>
</Filter>
<Filter Include="include\grpc\impl\codegen">
<UniqueIdentifier>{7e4b71ef-8125-6446-bfc1-9bc90beed59c}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{169774bd-5c6c-6827-66a4-326b4aef44d6}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto">
<UniqueIdentifier>{1b609b37-ef2a-e5eb-e1ba-ad9e79c77438}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto\grpc">
<UniqueIdentifier>{cd1e35d8-8a61-62fe-6ce1-c8936872d1ef}</UniqueIdentifier>
</Filter>
<Filter Include="src\proto\grpc\testing">
<UniqueIdentifier>{f7ee4df5-1f47-1e7f-c91e-350382c1b729}</UniqueIdentifier>
</Filter>
<Filter Include="test">
<UniqueIdentifier>{f2166b83-6b0b-d53b-b58b-627bd9efcad2}</UniqueIdentifier>
</Filter>
<Filter Include="test\cpp">
<UniqueIdentifier>{bbe36cbc-7fbe-2817-0bd0-d03726f323e6}</UniqueIdentifier>
</Filter>
<Filter Include="test\cpp\util">
<UniqueIdentifier>{e106cd7b-cfa0-0645-f1a9-2acedc23afe7}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save