Merge branch 'master' into sreek-pe-usages-doc

pull/16724/head
Sree Kuchibhotla 6 years ago
commit 67d2fb7847
  1. 64
      doc/core/grpc-cq.md
  2. BIN
      doc/images/grpc-cq.png
  3. 2
      examples/python/interceptors/default_value/default_value_client_interceptor.py
  4. 1
      grpc.def
  5. 4
      include/grpc/grpc.h
  6. 11
      src/core/ext/filters/client_channel/client_channel_channelz.cc
  7. 3
      src/core/ext/filters/client_channel/connector.h
  8. 6
      src/core/ext/filters/client_channel/lb_policy_factory.h
  9. 16
      src/core/ext/filters/client_channel/subchannel.cc
  10. 8
      src/core/ext/filters/client_channel/subchannel.h
  11. 2
      src/core/ext/transport/chttp2/client/chttp2_connector.cc
  12. 33
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  13. 2
      src/core/ext/transport/chttp2/transport/chttp2_transport.h
  14. 4
      src/core/ext/transport/chttp2/transport/frame_data.cc
  15. 8
      src/core/ext/transport/chttp2/transport/internal.h
  16. 6
      src/core/ext/transport/chttp2/transport/parsing.cc
  17. 6
      src/core/ext/transport/chttp2/transport/writing.cc
  18. 110
      src/core/lib/channel/channelz.cc
  19. 36
      src/core/lib/channel/channelz.h
  20. 18
      src/core/lib/channel/channelz_registry.cc
  21. 26
      src/core/lib/iomgr/error.cc
  22. 2
      src/core/lib/iomgr/ev_posix.cc
  23. 2
      src/core/lib/iomgr/timer_generic.cc
  24. 18
      src/cpp/client/channel_cc.cc
  25. 119
      src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs
  26. 105
      src/csharp/Grpc.Core.Tests/MarshallerTest.cs
  27. 46
      src/csharp/Grpc.Core/DeserializationContext.cs
  28. 126
      src/csharp/Grpc.Core/Marshaller.cs
  29. 34
      src/csharp/Grpc.Core/SerializationContext.cs
  30. 2
      src/csharp/tests.json
  31. 2
      src/objective-c/GRPCClient/private/NSError+GRPC.h
  32. 20
      src/objective-c/GRPCClient/private/NSError+GRPC.m
  33. 1
      src/objective-c/tests/Podfile
  34. 257
      src/objective-c/tests/Tests.xcodeproj/project.pbxproj
  35. 92
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme
  36. 22
      src/objective-c/tests/UnitTests/Info.plist
  37. 62
      src/objective-c/tests/UnitTests/UnitTests.m
  38. 10
      src/objective-c/tests/run_tests.sh
  39. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.c
  40. 3
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  41. 14
      src/ruby/pb/test/client.rb
  42. 1
      test/core/surface/public_headers_must_be_c89.c
  43. 1
      tools/doxygen/Doxyfile.core
  44. 1
      tools/doxygen/Doxyfile.core.internal
  45. 2
      tools/internal_ci/helper_scripts/delete_nonartifacts.sh
  46. 2
      tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg
  47. 2
      tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg
  48. 2
      tools/internal_ci/linux/grpc_basictests_multilang.cfg
  49. 2
      tools/internal_ci/linux/grpc_build_artifacts.cfg
  50. 2
      tools/internal_ci/linux/grpc_build_artifacts_extra.cfg
  51. 2
      tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg
  52. 2
      tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg
  53. 2
      tools/internal_ci/linux/grpc_build_packages.cfg
  54. 2
      tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg
  55. 2
      tools/internal_ci/linux/grpc_coverage.cfg
  56. 2
      tools/internal_ci/linux/grpc_distribtests.cfg
  57. 2
      tools/internal_ci/linux/grpc_distribtests_standalone.cfg
  58. 2
      tools/internal_ci/linux/grpc_full_performance_master.cfg
  59. 2
      tools/internal_ci/linux/grpc_full_performance_release.cfg
  60. 2
      tools/internal_ci/linux/grpc_interop_alts.cfg
  61. 2
      tools/internal_ci/linux/grpc_interop_matrix.cfg
  62. 2
      tools/internal_ci/linux/grpc_interop_tocloud.cfg
  63. 2
      tools/internal_ci/linux/grpc_interop_toprod.cfg
  64. 2
      tools/internal_ci/linux/grpc_portability.cfg
  65. 2
      tools/internal_ci/linux/grpc_portability_build_only.cfg
  66. 2
      tools/internal_ci/linux/grpc_publish_packages.cfg
  67. 2
      tools/internal_ci/linux/grpc_pull_request_sanity.cfg
  68. 2
      tools/internal_ci/linux/grpc_sanity.cfg
  69. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg
  70. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg
  71. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg
  72. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg
  73. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg
  74. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg
  75. 2
      tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg
  76. 2
      tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
  77. 2
      tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg
  78. 2
      tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
  79. 2
      tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg
  80. 2
      tools/internal_ci/linux/pull_request/grpc_sanity.cfg
  81. 2
      tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg
  82. 2
      tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg
  83. 2
      tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg
  84. 2
      tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg
  85. 2
      tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg
  86. 2
      tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg
  87. 2
      tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg
  88. 2
      tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg
  89. 2
      tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg
  90. 2
      tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg
  91. 2
      tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg
  92. 2
      tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg
  93. 2
      tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg
  94. 2
      tools/internal_ci/macos/grpc_basictests_dbg.cfg
  95. 2
      tools/internal_ci/macos/grpc_basictests_opt.cfg
  96. 2
      tools/internal_ci/macos/grpc_build_artifacts.cfg
  97. 2
      tools/internal_ci/macos/grpc_distribtests.cfg
  98. 2
      tools/internal_ci/macos/grpc_interop.cfg
  99. 2
      tools/internal_ci/macos/grpc_interop_toprod.cfg
  100. 2
      tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,64 @@
# gRPC Completion Queue
_Author: Sree Kuchibhotla (@sreecha) - Sep 2018_
Code: [completion_queue.cc](https://github.com/grpc/grpc/blob/v1.15.1/src/core/lib/surface/completion_queue.cc)
This document gives an overview of completion queue architecture and focuses mainly on the interaction between completion queue and the Polling engine layer.
## Completion queue attributes
Completion queue has two attributes
- Completion_type:
- GRPC_CQ_NEXT: grpc_completion_queue_next() can be called (but not grpc_completion_queue_pluck())
- GRPC_CQ_PLUCK: grpc_completion_queue_pluck() can be called (but not grpc_completion_queue_next())
- GRPC_CQ_CALLBACK: The tags in the queue are function pointers to callbacks. Also, neither next() nor pluck() can be called on this
- Polling_type:
- GRPC_CQ_NON_POLLING: Threads calling completion_queue_next/pluck do not do any polling
- GRPC_CQ_DEFAULT_POLLING: Threads calling completion_queue_next/pluck do polling
- GRPC_CQ_NON_LISTENING: Functionally similar to default polling except for a boolean attribute that states that the cq is non-listening. This is used by the grpc-server code to not associate any listening sockets with this completion-queue’s pollset
## Details
![image](../images/grpc-cq.png)
### **grpc\_completion\_queue\_next()** & **grpc_completion_queue_pluck()** APIS
``` C++
grpc_completion_queue_next(cq, deadline)/pluck(cq, deadline, tag) {
while(true) {
\\ 1. If an event is queued in the completion queue, dequeue and return
\\ (in case of pluck() dequeue only if the tag is the one we are interested in)
\\ 2. If completion queue shutdown return
\\ 3. In case of pluck, add (tag, worker) pair to the tag<->worker map on the cq
\\ 4. Call grpc_pollset_work(cq’s-pollset, deadline) to do polling
\\ Note that if this function found some fds to be readable/writable/error,
\\ it would have scheduled those closures (which may queue completion events
\\ on SOME completion queue - not necessarily this one)
}
}
```
### Queuing a completion event (i.e., "tag")
``` C++
grpc_cq_end_op(cq, tag) {
\\ 1. Queue the tag in the event queue
\\ 2. Find the pollset corresponding to the completion queue
\\ (i) If the cq is of type GRPC_CQ_NEXT, then KICK ANY worker
\\ i.e., call grpc_pollset_kick(pollset, nullptr)
\\ (ii) If the cq is of type GRPC_CQ_PLUCK, then search the tag<->worker
\\ map on the completion queue to find the worker. Then specifically
\\ kick that worker i.e call grpc_pollset_kick(pollset, worker)
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

@ -13,8 +13,6 @@
# limitations under the License.
"""Interceptor that adds headers to outgoing requests."""
import collections
import grpc

@ -77,6 +77,7 @@ EXPORTS
grpc_channelz_get_servers
grpc_channelz_get_channel
grpc_channelz_get_subchannel
grpc_channelz_get_socket
grpc_insecure_channel_create_from_fd
grpc_server_add_insecure_channel_from_fd
grpc_use_signal

@ -511,6 +511,10 @@ GRPCAPI char* grpc_channelz_get_channel(intptr_t channel_id);
is allocated and must be freed by the application. */
GRPCAPI char* grpc_channelz_get_subchannel(intptr_t subchannel_id);
/* Returns a single Socket, or else a NOT_FOUND code. The returned string
is allocated and must be freed by the application. */
GRPCAPI char* grpc_channelz_get_socket(intptr_t socket_id);
#ifdef __cplusplus
}
#endif

@ -166,6 +166,17 @@ grpc_json* SubchannelNode::RenderJson() {
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
json = top_level_json;
// populate the child socket.
intptr_t socket_uuid = grpc_subchannel_get_child_socket_uuid(subchannel_);
if (socket_uuid != 0) {
grpc_json* array_parent = grpc_json_create_child(
nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false);
json_iterator = grpc_json_create_child(json_iterator, array_parent, nullptr,
nullptr, GRPC_JSON_OBJECT, false);
grpc_json_add_number_string_child(json_iterator, nullptr, "socketId",
socket_uuid);
}
return top_level_json;
}

@ -47,6 +47,9 @@ typedef struct {
/** channel arguments (to be passed to the filters) */
grpc_channel_args* channel_args;
/** socket uuid of the connected transport. 0 if not available */
intptr_t socket_uuid;
} grpc_connect_out_args;
struct grpc_connector_vtable {

@ -70,16 +70,14 @@ grpc_lb_addresses* grpc_lb_addresses_create(
grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses);
/** Sets the value of the address at index \a index of \a addresses.
* \a address is a socket address of length \a address_len.
* Takes ownership of \a balancer_name. */
* \a address is a socket address of length \a address_len. */
void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
const void* address, size_t address_len,
bool is_balancer, const char* balancer_name,
void* user_data);
/** Sets the value of the address at index \a index of \a addresses from \a uri.
* Returns true upon success, false otherwise. Takes ownership of \a
* balancer_name. */
* Returns true upon success, false otherwise. */
bool grpc_lb_addresses_set_address_from_uri(grpc_lb_addresses* addresses,
size_t index, const grpc_uri* uri,
bool is_balancer,

@ -411,6 +411,14 @@ grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
return subchannel->channelz_subchannel.get();
}
intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel) {
if (subchannel->connected_subchannel != nullptr) {
return subchannel->connected_subchannel->socket_uuid();
} else {
return 0;
}
}
static void continue_connect_locked(grpc_subchannel* c) {
grpc_connect_in_args args;
args.interested_parties = c->pollset_set;
@ -621,6 +629,7 @@ static bool publish_transport_locked(grpc_subchannel* c) {
GRPC_ERROR_UNREF(error);
return false;
}
intptr_t socket_uuid = c->connecting_result.socket_uuid;
memset(&c->connecting_result, 0, sizeof(c->connecting_result));
/* initialize state watcher */
@ -641,7 +650,7 @@ static bool publish_transport_locked(grpc_subchannel* c) {
/* publish */
c->connected_subchannel.reset(grpc_core::New<grpc_core::ConnectedSubchannel>(
stk, c->channelz_subchannel.get()));
stk, c->channelz_subchannel.get(), socket_uuid));
gpr_log(GPR_INFO, "New connected subchannel at %p for subchannel %p",
c->connected_subchannel.get(), c);
@ -811,10 +820,11 @@ namespace grpc_core {
ConnectedSubchannel::ConnectedSubchannel(
grpc_channel_stack* channel_stack,
channelz::SubchannelNode* channelz_subchannel)
channelz::SubchannelNode* channelz_subchannel, intptr_t socket_uuid)
: RefCountedWithTracing<ConnectedSubchannel>(&grpc_trace_stream_refcount),
channel_stack_(channel_stack),
channelz_subchannel_(channelz_subchannel) {}
channelz_subchannel_(channelz_subchannel),
socket_uuid_(socket_uuid) {}
ConnectedSubchannel::~ConnectedSubchannel() {
GRPC_CHANNEL_STACK_UNREF(channel_stack_, "connected_subchannel_dtor");

@ -86,7 +86,8 @@ class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
};
explicit ConnectedSubchannel(grpc_channel_stack* channel_stack,
channelz::SubchannelNode* channelz_subchannel);
channelz::SubchannelNode* channelz_subchannel,
intptr_t socket_uuid);
~ConnectedSubchannel();
grpc_channel_stack* channel_stack() { return channel_stack_; }
@ -98,12 +99,15 @@ class ConnectedSubchannel : public RefCountedWithTracing<ConnectedSubchannel> {
channelz::SubchannelNode* channelz_subchannel() {
return channelz_subchannel_;
}
intptr_t socket_uuid() { return socket_uuid_; }
private:
grpc_channel_stack* channel_stack_;
// backpointer to the channelz node in this connected subchannel's
// owning subchannel.
channelz::SubchannelNode* channelz_subchannel_;
// uuid of this subchannel's socket. 0 if this subchannel is not connected.
const intptr_t socket_uuid_;
};
} // namespace grpc_core
@ -126,6 +130,8 @@ void grpc_subchannel_call_unref(
grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node(
grpc_subchannel* subchannel);
intptr_t grpc_subchannel_get_child_socket_uuid(grpc_subchannel* subchannel);
/** Returns a pointer to the parent data associated with \a subchannel_call.
The data will be of the size specified in \a parent_data_size
field of the args passed to \a grpc_connected_subchannel_create_call(). */

@ -117,6 +117,8 @@ static void on_handshake_done(void* arg, grpc_error* error) {
c->args.interested_parties);
c->result->transport =
grpc_create_chttp2_transport(args->args, args->endpoint, true);
c->result->socket_uuid =
grpc_chttp2_transport_get_socket_uuid(c->result->transport);
GPR_ASSERT(c->result->transport);
// TODO(roth): We ideally want to wait until we receive HTTP/2
// settings from the server before we consider the connection

@ -157,6 +157,10 @@ bool g_flow_control_enabled = true;
static void destruct_transport(grpc_chttp2_transport* t) {
size_t i;
if (t->channelz_socket != nullptr) {
t->channelz_socket.reset();
}
grpc_endpoint_destroy(t->ep);
grpc_slice_buffer_destroy_internal(&t->qbuf);
@ -335,6 +339,10 @@ static bool read_channel_args(grpc_chttp2_transport* t,
GRPC_ARG_OPTIMIZATION_TARGET,
channel_args->args[i].value.string);
}
} else if (0 ==
strcmp(channel_args->args[i].key, GRPC_ARG_ENABLE_CHANNELZ)) {
t->channelz_socket =
grpc_core::MakeRefCounted<grpc_core::channelz::SocketNode>();
} else {
static const struct {
const char* channel_arg_name;
@ -720,6 +728,14 @@ static void destroy_stream_locked(void* sp, grpc_error* error) {
grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(sp);
grpc_chttp2_transport* t = s->t;
if (t->channelz_socket != nullptr) {
if ((t->is_client && s->eos_received) || (!t->is_client && s->eos_sent)) {
t->channelz_socket->RecordStreamSucceeded();
} else {
t->channelz_socket->RecordStreamFailed();
}
}
GPR_ASSERT((s->write_closed && s->read_closed) || s->id == 0);
if (s->id != 0) {
GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, s->id) == nullptr);
@ -1407,6 +1423,9 @@ static void perform_stream_op_locked(void* stream_op,
}
if (op->send_initial_metadata) {
if (t->is_client && t->channelz_socket != nullptr) {
t->channelz_socket->RecordStreamStartedFromLocal();
}
GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA();
GPR_ASSERT(s->send_initial_metadata_finished == nullptr);
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
@ -1492,6 +1511,7 @@ static void perform_stream_op_locked(void* stream_op,
if (op->send_message) {
GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE();
t->num_messages_in_next_write++;
GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE(
op->payload->send_message.send_message->length());
on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
@ -2707,6 +2727,9 @@ static void start_keepalive_ping_locked(void* arg, grpc_error* error) {
if (error != GRPC_ERROR_NONE) {
return;
}
if (t->channelz_socket != nullptr) {
t->channelz_socket->RecordKeepaliveSent();
}
GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
grpc_timer_init(&t->keepalive_watchdog_timer,
grpc_core::ExecCtx::Get()->Now() + t->keepalive_timeout,
@ -3147,6 +3170,16 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
static const grpc_transport_vtable* get_vtable(void) { return &vtable; }
intptr_t grpc_chttp2_transport_get_socket_uuid(grpc_transport* transport) {
grpc_chttp2_transport* t =
reinterpret_cast<grpc_chttp2_transport*>(transport);
if (t->channelz_socket != nullptr) {
return t->channelz_socket->uuid();
} else {
return 0;
}
}
grpc_transport* grpc_create_chttp2_transport(
const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client) {
grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(

@ -34,6 +34,8 @@ extern bool g_flow_control_enabled;
grpc_transport* grpc_create_chttp2_transport(
const grpc_channel_args* channel_args, grpc_endpoint* ep, bool is_client);
intptr_t grpc_chttp2_transport_get_socket_uuid(grpc_transport* transport);
/// Takes ownership of \a read_buffer, which (if non-NULL) contains
/// leftover bytes previously read from the endpoint (e.g., by handshakers).
/// If non-null, \a notify_on_receive_settings will be scheduled when

@ -62,6 +62,7 @@ grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser,
if (flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) {
s->received_last_frame = true;
s->eos_received = true;
} else {
s->received_last_frame = false;
}
@ -191,6 +192,9 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames(
GPR_ASSERT(stream_out != nullptr);
GPR_ASSERT(p->parsing_frame == nullptr);
p->frame_size |= (static_cast<uint32_t>(*cur));
if (t->channelz_socket != nullptr) {
t->channelz_socket->RecordMessageReceived();
}
p->state = GRPC_CHTTP2_DATA_FRAME;
++cur;
message_flags = 0;

@ -36,6 +36,7 @@
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h"
#include "src/core/ext/transport/chttp2/transport/stream_map.h"
#include "src/core/lib/channel/channelz.h"
#include "src/core/lib/compression/stream_compression.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/iomgr/combiner.h"
@ -471,6 +472,9 @@ struct grpc_chttp2_transport {
bool keepalive_permit_without_calls;
/** keep-alive state machine state */
grpc_chttp2_keepalive_state keepalive_state;
grpc_core::RefCountedPtr<grpc_core::channelz::SocketNode> channelz_socket;
uint32_t num_messages_in_next_write;
};
typedef enum {
@ -534,6 +538,10 @@ struct grpc_chttp2_stream {
/** Has trailing metadata been received. */
bool received_trailing_metadata;
/* have we sent or received the EOS bit? */
bool eos_received;
bool eos_sent;
/** the error that resulted in this stream being read-closed */
grpc_error* read_closed_error;
/** the error that resulted in this stream being write-closed */

@ -623,6 +623,9 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted"));
return init_skip_frame_parser(t, 1);
}
if (t->channelz_socket != nullptr) {
t->channelz_socket->RecordStreamStartedFromRemote();
}
} else {
t->incoming_stream = s;
}
@ -636,6 +639,9 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t,
}
t->parser = grpc_chttp2_header_parser_parse;
t->parser_data = &t->hpack_parser;
if (t->header_eof) {
s->eos_received = true;
}
switch (s->header_frames_received) {
case 0:
if (t->is_client && t->header_eof) {

@ -569,6 +569,7 @@ class StreamWriteContext {
void SentLastFrame() {
s_->send_trailing_metadata = nullptr;
s_->sent_trailing_metadata = true;
s_->eos_sent = true;
if (!t_->is_client && !s_->read_closed) {
grpc_slice_buffer_add(
@ -632,6 +633,11 @@ void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error* error) {
GPR_TIMER_SCOPE("grpc_chttp2_end_write", 0);
grpc_chttp2_stream* s;
if (t->channelz_socket != nullptr) {
t->channelz_socket->RecordMessagesSent(t->num_messages_in_next_write);
}
t->num_messages_in_next_write = 0;
while (grpc_chttp2_list_pop_writing_stream(t, &s)) {
if (s->sending_bytes != 0) {
update_list(t, s, static_cast<int64_t>(s->sending_bytes),

@ -62,7 +62,7 @@ CallCountingHelper::CallCountingHelper() {
CallCountingHelper::~CallCountingHelper() {}
void CallCountingHelper::RecordCallStarted() {
gpr_atm_no_barrier_fetch_add(&calls_started_, (gpr_atm)1);
gpr_atm_no_barrier_fetch_add(&calls_started_, static_cast<gpr_atm>(1));
gpr_atm_no_barrier_store(&last_call_started_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
@ -81,11 +81,13 @@ void CallCountingHelper::PopulateCallCounts(grpc_json* json) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "callsFailed", calls_failed_);
}
gpr_timespec ts =
grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
if (calls_started_ != 0) {
gpr_timespec ts =
grpc_millis_to_timespec(last_call_started_millis_, GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastCallStartedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
}
}
ChannelNode::ChannelNode(grpc_channel* channel, size_t channel_tracer_max_nodes,
@ -180,7 +182,103 @@ grpc_json* ServerNode::RenderJson() {
}
// ask CallCountingHelper to populate trace and call count data.
call_counter_.PopulateCallCounts(json);
return top_level_json;
}
SocketNode::SocketNode() : BaseNode(EntityType::kSocket) {}
void SocketNode::RecordStreamStartedFromLocal() {
gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast<gpr_atm>(1));
gpr_atm_no_barrier_store(&last_local_stream_created_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
void SocketNode::RecordStreamStartedFromRemote() {
gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast<gpr_atm>(1));
gpr_atm_no_barrier_store(&last_remote_stream_created_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
void SocketNode::RecordMessagesSent(uint32_t num_sent) {
gpr_atm_no_barrier_fetch_add(&messages_sent_, static_cast<gpr_atm>(num_sent));
gpr_atm_no_barrier_store(&last_message_sent_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
void SocketNode::RecordMessageReceived() {
gpr_atm_no_barrier_fetch_add(&messages_received_, static_cast<gpr_atm>(1));
gpr_atm_no_barrier_store(&last_message_received_millis_,
(gpr_atm)ExecCtx::Get()->Now());
}
grpc_json* SocketNode::RenderJson() {
// We need to track these three json objects to build our object
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* json_iterator = nullptr;
// create and fill the ref child
json_iterator = grpc_json_create_child(json_iterator, json, "ref", nullptr,
GRPC_JSON_OBJECT, false);
json = json_iterator;
json_iterator = nullptr;
json_iterator = grpc_json_add_number_string_child(json, json_iterator,
"socketId", uuid());
// reset json iterators to top level object
json = top_level_json;
json_iterator = nullptr;
// create and fill the data child.
grpc_json* data = grpc_json_create_child(json_iterator, json, "data", nullptr,
GRPC_JSON_OBJECT, false);
json = data;
json_iterator = nullptr;
gpr_timespec ts;
if (streams_started_ != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "streamsStarted", streams_started_);
if (last_local_stream_created_millis_ != 0) {
ts = grpc_millis_to_timespec(last_local_stream_created_millis_,
GPR_CLOCK_REALTIME);
json_iterator = grpc_json_create_child(
json_iterator, json, "lastLocalStreamCreatedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
}
if (last_remote_stream_created_millis_ != 0) {
ts = grpc_millis_to_timespec(last_remote_stream_created_millis_,
GPR_CLOCK_REALTIME);
json_iterator = grpc_json_create_child(
json_iterator, json, "lastRemoteStreamCreatedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
}
}
if (streams_succeeded_ != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "streamsSucceeded", streams_succeeded_);
}
if (streams_failed_) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "streamsFailed", streams_failed_);
}
if (messages_sent_ != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "messagesSent", messages_sent_);
ts = grpc_millis_to_timespec(last_message_sent_millis_, GPR_CLOCK_REALTIME);
json_iterator =
grpc_json_create_child(json_iterator, json, "lastMessageSentTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
}
if (messages_received_ != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "messagesReceived", messages_received_);
ts = grpc_millis_to_timespec(last_message_received_millis_,
GPR_CLOCK_REALTIME);
json_iterator = grpc_json_create_child(
json_iterator, json, "lastMessageReceivedTimestamp",
gpr_format_timespec(ts), GRPC_JSON_STRING, true);
}
if (keepalives_sent_ != 0) {
json_iterator = grpc_json_add_number_string_child(
json, json_iterator, "keepAlivesSent", keepalives_sent_);
}
return top_level_json;
}

@ -92,10 +92,10 @@ class CallCountingHelper {
void RecordCallStarted();
void RecordCallFailed() {
gpr_atm_no_barrier_fetch_add(&calls_failed_, (gpr_atm(1)));
gpr_atm_no_barrier_fetch_add(&calls_failed_, static_cast<gpr_atm>(1));
}
void RecordCallSucceeded() {
gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1)));
gpr_atm_no_barrier_fetch_add(&calls_succeeded_, static_cast<gpr_atm>(1));
}
// Common rendering of the call count data and last_call_started_timestamp.
@ -197,11 +197,39 @@ class ServerNode : public BaseNode {
};
// Handles channelz bookkeeping for sockets
// TODO(ncteisen): implement in subsequent PR.
class SocketNode : public BaseNode {
public:
SocketNode() : BaseNode(EntityType::kSocket) {}
SocketNode();
~SocketNode() override {}
grpc_json* RenderJson() override;
void RecordStreamStartedFromLocal();
void RecordStreamStartedFromRemote();
void RecordStreamSucceeded() {
gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast<gpr_atm>(1));
}
void RecordStreamFailed() {
gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast<gpr_atm>(1));
}
void RecordMessagesSent(uint32_t num_sent);
void RecordMessageReceived();
void RecordKeepaliveSent() {
gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast<gpr_atm>(1));
}
private:
gpr_atm streams_started_ = 0;
gpr_atm streams_succeeded_ = 0;
gpr_atm streams_failed_ = 0;
gpr_atm messages_sent_ = 0;
gpr_atm messages_received_ = 0;
gpr_atm keepalives_sent_ = 0;
gpr_atm last_local_stream_created_millis_ = 0;
gpr_atm last_remote_stream_created_millis_ = 0;
gpr_atm last_message_sent_millis_ = 0;
gpr_atm last_message_received_millis_ = 0;
UniquePtr<char> peer_string_;
};
// Creation functions

@ -197,3 +197,21 @@ char* grpc_channelz_get_subchannel(intptr_t subchannel_id) {
grpc_json_destroy(top_level_json);
return json_str;
}
char* grpc_channelz_get_socket(intptr_t socket_id) {
grpc_core::channelz::BaseNode* socket_node =
grpc_core::channelz::ChannelzRegistry::Get(socket_id);
if (socket_node == nullptr ||
socket_node->type() !=
grpc_core::channelz::BaseNode::EntityType::kSocket) {
return nullptr;
}
grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT);
grpc_json* json = top_level_json;
grpc_json* socket_json = socket_node->RenderJson();
socket_json->key = "socket";
grpc_json_link_child(json, socket_json, nullptr);
char* json_str = grpc_json_dump_to_string(top_level_json, 0);
grpc_json_destroy(top_level_json);
return json_str;
}

@ -454,7 +454,7 @@ typedef struct {
grpc_status_code code;
const char* msg;
} special_error_status_map;
static special_error_status_map error_status_map[] = {
static const special_error_status_map error_status_map[] = {
{GRPC_ERROR_NONE, GRPC_STATUS_OK, ""},
{GRPC_ERROR_CANCELLED, GRPC_STATUS_CANCELLED, "Cancelled"},
{GRPC_ERROR_OOM, GRPC_STATUS_RESOURCE_EXHAUSTED, "Out of memory"},
@ -463,15 +463,13 @@ static special_error_status_map error_status_map[] = {
bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) {
GPR_TIMER_SCOPE("grpc_error_get_int", 0);
if (grpc_error_is_special(err)) {
if (which == GRPC_ERROR_INT_GRPC_STATUS) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
if (error_status_map[i].error == err) {
if (p != nullptr) *p = error_status_map[i].code;
return true;
}
for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
if (error_status_map[i].error == err) {
if (which != GRPC_ERROR_INT_GRPC_STATUS) return false;
if (p != nullptr) *p = error_status_map[i].code;
return true;
}
}
return false;
}
uint8_t slot = err->ints[which];
if (slot != UINT8_MAX) {
@ -492,15 +490,13 @@ grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which,
bool grpc_error_get_str(grpc_error* err, grpc_error_strs which,
grpc_slice* str) {
if (grpc_error_is_special(err)) {
if (which == GRPC_ERROR_STR_GRPC_MESSAGE) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
if (error_status_map[i].error == err) {
*str = grpc_slice_from_static_string(error_status_map[i].msg);
return true;
}
for (size_t i = 0; i < GPR_ARRAY_SIZE(error_status_map); i++) {
if (error_status_map[i].error == err) {
if (which != GRPC_ERROR_STR_GRPC_MESSAGE) return false;
*str = grpc_slice_from_static_string(error_status_map[i].msg);
return true;
}
}
return false;
}
uint8_t slot = err->strs[which];
if (slot != UINT8_MAX) {

@ -395,4 +395,6 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd) {
g_event_engine->pollset_set_del_fd(pollset_set, fd);
}
void grpc_use_signal(int signum) {}
#endif // GRPC_POSIX_SOCKET_EV

@ -256,7 +256,7 @@ static grpc_millis compute_min_deadline(timer_shard* shard) {
static void timer_list_init() {
uint32_t i;
g_num_shards = GPR_MIN(1, 2 * gpr_cpu_num_cores());
g_num_shards = GPR_CLAMP(2 * gpr_cpu_num_cores(), 1, 32);
g_shards =
static_cast<timer_shard*>(gpr_zalloc(g_num_shards * sizeof(*g_shards)));
g_shard_queue = static_cast<timer_shard**>(

@ -20,6 +20,7 @@
#include <chrono>
#include <condition_variable>
#include <cstring>
#include <memory>
#include <mutex>
@ -64,6 +65,10 @@ Channel::~Channel() {
namespace {
inline grpc_slice SliceFromArray(const char* arr, size_t len) {
return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len);
}
grpc::string GetChannelInfoField(grpc_channel* channel,
grpc_channel_info* channel_info,
char*** channel_info_field) {
@ -110,16 +115,17 @@ internal::Call Channel::CreateCall(const internal::RpcMethod& method,
context->propagation_options_.c_bitmask(), cq->cq(),
method.channel_tag(), context->raw_deadline(), nullptr);
} else {
const char* host_str = nullptr;
if (!context->authority().empty()) {
host_str = context->authority_.c_str();
const string* host_str = nullptr;
if (!context->authority_.empty()) {
host_str = &context->authority_;
} else if (!host_.empty()) {
host_str = host_.c_str();
host_str = &host_;
}
grpc_slice method_slice = SliceFromCopiedString(method.name());
grpc_slice method_slice =
SliceFromArray(method.name(), strlen(method.name()));
grpc_slice host_slice;
if (host_str != nullptr) {
host_slice = SliceFromCopiedString(host_str);
host_slice = SliceFromCopiedString(*host_str);
}
c_call = grpc_channel_create_call(
c_channel_, context->propagate_from_call_,

@ -0,0 +1,119 @@
#region Copyright notice and license
// Copyright 2018 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
namespace Grpc.Core.Tests
{
public class ContextualMarshallerTest
{
const string Host = "127.0.0.1";
MockServiceHelper helper;
Server server;
Channel channel;
[SetUp]
public void Init()
{
var contextualMarshaller = new Marshaller<string>(
(str, serializationContext) =>
{
if (str == "UNSERIALIZABLE_VALUE")
{
// Google.Protobuf throws exception inherited from IOException
throw new IOException("Error serializing the message.");
}
if (str == "SERIALIZE_TO_NULL")
{
return;
}
var bytes = System.Text.Encoding.UTF8.GetBytes(str);
serializationContext.Complete(bytes);
},
(deserializationContext) =>
{
var buffer = deserializationContext.PayloadAsNewBuffer();
Assert.AreEqual(buffer.Length, deserializationContext.PayloadLength);
var s = System.Text.Encoding.UTF8.GetString(buffer);
if (s == "UNPARSEABLE_VALUE")
{
// Google.Protobuf throws exception inherited from IOException
throw new IOException("Error parsing the message.");
}
return s;
});
helper = new MockServiceHelper(Host, contextualMarshaller);
server = helper.GetServer();
server.Start();
channel = helper.GetChannel();
}
[TearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public void UnaryCall()
{
helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
{
return Task.FromResult(request);
});
Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC"));
}
[Test]
public void ResponseParsingError_UnaryResponse()
{
helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
{
return Task.FromResult("UNPARSEABLE_VALUE");
});
var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST"));
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
}
[Test]
public void RequestSerializationError_BlockingUnary()
{
Assert.Throws<IOException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE"));
}
[Test]
public void SerializationResultIsNull_BlockingUnary()
{
Assert.Throws<NullReferenceException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "SERIALIZE_TO_NULL"));
}
}
}

@ -0,0 +1,105 @@
#region Copyright notice and license
// Copyright 2018 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
using NUnit.Framework;
namespace Grpc.Core.Tests
{
public class MarshallerTest
{
[Test]
public void ContextualSerializerEmulation()
{
Func<string, byte[]> simpleSerializer = System.Text.Encoding.UTF8.GetBytes;
Func<byte[], string> simpleDeserializer = System.Text.Encoding.UTF8.GetString;
var marshaller = new Marshaller<string>(simpleSerializer,
simpleDeserializer);
Assert.AreSame(simpleSerializer, marshaller.Serializer);
Assert.AreSame(simpleDeserializer, marshaller.Deserializer);
// test that emulated contextual serializer and deserializer work
string origMsg = "abc";
var serializationContext = new FakeSerializationContext();
marshaller.ContextualSerializer(origMsg, serializationContext);
var deserializationContext = new FakeDeserializationContext(serializationContext.Payload);
Assert.AreEqual(origMsg, marshaller.ContextualDeserializer(deserializationContext));
}
[Test]
public void SimpleSerializerEmulation()
{
Action<string, SerializationContext> contextualSerializer = (str, context) =>
{
var bytes = System.Text.Encoding.UTF8.GetBytes(str);
context.Complete(bytes);
};
Func<DeserializationContext, string> contextualDeserializer = (context) =>
{
return System.Text.Encoding.UTF8.GetString(context.PayloadAsNewBuffer());
};
var marshaller = new Marshaller<string>(contextualSerializer, contextualDeserializer);
Assert.AreSame(contextualSerializer, marshaller.ContextualSerializer);
Assert.AreSame(contextualDeserializer, marshaller.ContextualDeserializer);
// test that emulated serializer and deserializer work
var origMsg = "abc";
var serialized = marshaller.Serializer(origMsg);
Assert.AreEqual(origMsg, marshaller.Deserializer(serialized));
}
class FakeSerializationContext : SerializationContext
{
public byte[] Payload;
public override void Complete(byte[] payload)
{
this.Payload = payload;
}
}
class FakeDeserializationContext : DeserializationContext
{
public byte[] payload;
public FakeDeserializationContext(byte[] payload)
{
this.payload = payload;
}
public override int PayloadLength => payload.Length;
public override byte[] PayloadAsNewBuffer()
{
return payload;
}
}
}
}

@ -0,0 +1,46 @@
#region Copyright notice and license
// Copyright 2018 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
namespace Grpc.Core
{
/// <summary>
/// Provides access to the payload being deserialized when deserializing messages.
/// </summary>
public abstract class DeserializationContext
{
/// <summary>
/// Get the total length of the payload in bytes.
/// </summary>
public abstract int PayloadLength { get; }
/// <summary>
/// Gets the entire payload as a newly allocated byte array.
/// Once the byte array is returned, the byte array becomes owned by the caller and won't be ever accessed or reused by gRPC again.
/// NOTE: Obtaining the buffer as a newly allocated byte array is the simplest way of accessing the payload,
/// but it can have important consequences in high-performance scenarios.
/// In particular, using this method usually requires copying of the entire buffer one extra time.
/// Also, allocating a new buffer each time can put excessive pressure on GC, especially if
/// the payload is more than 86700 bytes large (which means the newly allocated buffer will be placed in LOH,
/// and LOH object can only be garbage collected via a full ("stop the world") GC run).
/// NOTE: Deserializers are expected not to call this method more than once per received message
/// (as there is no practical reason for doing so) and <c>DeserializationContext</c> implementations are free to assume so.
/// </summary>
/// <returns>byte array containing the entire payload.</returns>
public abstract byte[] PayloadAsNewBuffer();
}
}

@ -29,36 +29,129 @@ namespace Grpc.Core
readonly Func<T, byte[]> serializer;
readonly Func<byte[], T> deserializer;
readonly Action<T, SerializationContext> contextualSerializer;
readonly Func<DeserializationContext, T> contextualDeserializer;
/// <summary>
/// Initializes a new marshaller.
/// Initializes a new marshaller from simple serialize/deserialize functions.
/// </summary>
/// <param name="serializer">Function that will be used to serialize messages.</param>
/// <param name="deserializer">Function that will be used to deserialize messages.</param>
public Marshaller(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
{
this.serializer = GrpcPreconditions.CheckNotNull(serializer, "serializer");
this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, "deserializer");
this.serializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
this.contextualSerializer = EmulateContextualSerializer;
this.contextualDeserializer = EmulateContextualDeserializer;
}
/// <summary>
/// Gets the serializer function.
/// Initializes a new marshaller from serialize/deserialize fuctions that can access serialization and deserialization
/// context. Compared to the simple serializer/deserializer functions, using the contextual version provides more
/// flexibility and can lead to increased efficiency (and better performance).
/// Note: This constructor is part of an experimental API that can change or be removed without any prior notice.
/// </summary>
public Func<T, byte[]> Serializer
/// <param name="serializer">Function that will be used to serialize messages.</param>
/// <param name="deserializer">Function that will be used to deserialize messages.</param>
public Marshaller(Action<T, SerializationContext> serializer, Func<DeserializationContext, T> deserializer)
{
get
{
return this.serializer;
}
this.contextualSerializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
this.contextualDeserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
// TODO(jtattermusch): once gRPC C# library switches to using contextual (de)serializer,
// emulating the simple (de)serializer will become unnecessary.
this.serializer = EmulateSimpleSerializer;
this.deserializer = EmulateSimpleDeserializer;
}
/// <summary>
/// Gets the serializer function.
/// </summary>
public Func<T, byte[]> Serializer => this.serializer;
/// <summary>
/// Gets the deserializer function.
/// </summary>
public Func<byte[], T> Deserializer
public Func<byte[], T> Deserializer => this.deserializer;
/// <summary>
/// Gets the serializer function.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public Action<T, SerializationContext> ContextualSerializer => this.contextualSerializer;
/// <summary>
/// Gets the serializer function.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public Func<DeserializationContext, T> ContextualDeserializer => this.contextualDeserializer;
// for backward compatibility, emulate the simple serializer using the contextual one
private byte[] EmulateSimpleSerializer(T msg)
{
get
// TODO(jtattermusch): avoid the allocation by passing a thread-local instance
// This code will become unnecessary once gRPC C# library switches to using contextual (de)serializer.
var context = new EmulatedSerializationContext();
this.contextualSerializer(msg, context);
return context.GetPayload();
}
// for backward compatibility, emulate the simple deserializer using the contextual one
private T EmulateSimpleDeserializer(byte[] payload)
{
// TODO(jtattermusch): avoid the allocation by passing a thread-local instance
// This code will become unnecessary once gRPC C# library switches to using contextual (de)serializer.
var context = new EmulatedDeserializationContext(payload);
return this.contextualDeserializer(context);
}
// for backward compatibility, emulate the contextual serializer using the simple one
private void EmulateContextualSerializer(T message, SerializationContext context)
{
var payload = this.serializer(message);
context.Complete(payload);
}
// for backward compatibility, emulate the contextual deserializer using the simple one
private T EmulateContextualDeserializer(DeserializationContext context)
{
return this.deserializer(context.PayloadAsNewBuffer());
}
internal class EmulatedSerializationContext : SerializationContext
{
bool isComplete;
byte[] payload;
public override void Complete(byte[] payload)
{
GrpcPreconditions.CheckState(!isComplete);
this.isComplete = true;
this.payload = payload;
}
internal byte[] GetPayload()
{
return this.payload;
}
}
internal class EmulatedDeserializationContext : DeserializationContext
{
readonly byte[] payload;
bool alreadyCalledPayloadAsNewBuffer;
public EmulatedDeserializationContext(byte[] payload)
{
this.payload = GrpcPreconditions.CheckNotNull(payload);
}
public override int PayloadLength => payload.Length;
public override byte[] PayloadAsNewBuffer()
{
return this.deserializer;
GrpcPreconditions.CheckState(!alreadyCalledPayloadAsNewBuffer);
alreadyCalledPayloadAsNewBuffer = true;
return payload;
}
}
}
@ -76,6 +169,15 @@ namespace Grpc.Core
return new Marshaller<T>(serializer, deserializer);
}
/// <summary>
/// Creates a marshaller from specified contextual serializer and deserializer.
/// Note: This method is part of an experimental API that can change or be removed without any prior notice.
/// </summary>
public static Marshaller<T> Create<T>(Action<T, SerializationContext> serializer, Func<DeserializationContext, T> deserializer)
{
return new Marshaller<T>(serializer, deserializer);
}
/// <summary>
/// Returns a marshaller for <c>string</c> type. This is useful for testing.
/// </summary>

@ -0,0 +1,34 @@
#region Copyright notice and license
// Copyright 2018 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
namespace Grpc.Core
{
/// <summary>
/// Provides storage for payload when serializing a message.
/// </summary>
public abstract class SerializationContext
{
/// <summary>
/// Use the byte array as serialized form of current message and mark serialization process as complete.
/// Complete() can only be called once. By calling this method the caller gives up the ownership of the
/// payload which must not be accessed afterwards.
/// </summary>
/// <param name="payload">the serialized form of current message</param>
public abstract void Complete(byte[] payload);
}
}

@ -23,8 +23,10 @@
"Grpc.Core.Tests.ClientServerTest",
"Grpc.Core.Tests.CompressionTest",
"Grpc.Core.Tests.ContextPropagationTest",
"Grpc.Core.Tests.ContextualMarshallerTest",
"Grpc.Core.Tests.GrpcEnvironmentTest",
"Grpc.Core.Tests.HalfcloseTest",
"Grpc.Core.Tests.MarshallerTest",
"Grpc.Core.Tests.MarshallingErrorsTest",
"Grpc.Core.Tests.MetadataTest",
"Grpc.Core.Tests.PerformanceTest",

@ -25,6 +25,6 @@
* and whose domain is |kGRPCErrorDomain|.
*/
+ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode
details:(char *)details
details:(const char *)details
errorString:(const char *)errorString;
@end

@ -24,18 +24,20 @@ NSString *const kGRPCErrorDomain = @"io.grpc";
@implementation NSError (GRPC)
+ (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode
details:(char *)details
details:(const char *)details
errorString:(const char *)errorString {
if (statusCode == GRPC_STATUS_OK) {
return nil;
}
NSString *message = [NSString stringWithCString:details encoding:NSUTF8StringEncoding];
NSString *debugMessage = [NSString stringWithCString:errorString encoding:NSUTF8StringEncoding];
return [NSError errorWithDomain:kGRPCErrorDomain
code:statusCode
userInfo:@{
NSLocalizedDescriptionKey : message,
NSDebugDescriptionErrorKey : debugMessage
}];
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
if (details) {
userInfo[NSLocalizedDescriptionKey] =
[NSString stringWithCString:details encoding:NSUTF8StringEncoding];
}
if (errorString) {
userInfo[NSDebugDescriptionErrorKey] =
[NSString stringWithCString:errorString encoding:NSUTF8StringEncoding];
}
return [NSError errorWithDomain:kGRPCErrorDomain code:statusCode userInfo:userInfo];
}
@end

@ -14,6 +14,7 @@ GRPC_LOCAL_SRC = '../../..'
InteropTestsLocalSSL
InteropTestsLocalCleartext
InteropTestsRemoteWithCronet
UnitTests
).each do |target_name|
target target_name do
pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true

@ -13,6 +13,8 @@
16A9E77B6E336B3C0B9BA6E0 /* libPods-InteropTestsLocalSSL.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */; };
20DFDF829DD993A4A00D5662 /* libPods-RxLibraryUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */; };
333E8FC01C8285B7C547D799 /* libPods-InteropTestsLocalCleartext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD346DB2C23F676C4842F3FF /* libPods-InteropTestsLocalCleartext.a */; };
5E0282E9215AA697007AC99D /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E0282E8215AA697007AC99D /* UnitTests.m */; };
5E0282EB215AA697007AC99D /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
5E8A5DA71D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm */; };
5E8A5DA91D3840B4000F8BC4 /* libTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 635697C71B14FC11007A7283 /* libTests.a */; };
5EAD6D271E27047400002378 /* CronetUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAD6D261E27047400002378 /* CronetUnitTests.m */; };
@ -54,10 +56,18 @@
91D4B3C85B6D8562F409CB48 /* libPods-InteropTestsLocalSSLCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */; };
BC111C80CBF7068B62869352 /* libPods-InteropTestsRemoteCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */; };
C3D6F4270A2FFF634D8849ED /* libPods-InteropTestsLocalCleartextCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */; };
CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */; };
F15EF7852DC70770EFDB1D2C /* libPods-AllTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CAE086D5B470DA367D415AB0 /* libPods-AllTests.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
5E0282EC215AA697007AC99D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 635697C61B14FC11007A7283;
remoteInfo = Tests;
};
5E8A5DAA1D3840B4000F8BC4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 635697BF1B14FC11007A7283 /* Project object */;
@ -138,6 +148,7 @@
1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.test.xcconfig"; sourceTree = "<group>"; };
17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = "<group>"; };
20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-UnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.test.xcconfig"; sourceTree = "<group>"; };
303F4A17EB1650FC44603D17 /* Pods-InteropTestsRemoteCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.release.xcconfig"; sourceTree = "<group>"; };
32748C4078AEB05F8F954361 /* Pods-InteropTestsRemoteCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.debug.xcconfig"; sourceTree = "<group>"; };
@ -155,6 +166,9 @@
55B630C1FF8C36D1EFC4E0A4 /* Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig"; sourceTree = "<group>"; };
573450F334B331D0BED8B961 /* Pods-CoreCronetEnd2EndTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests.cronet.xcconfig"; sourceTree = "<group>"; };
5761E98978DDDF136A58CB7E /* Pods-AllTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.release.xcconfig"; sourceTree = "<group>"; };
5E0282E6215AA697007AC99D /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5E0282E8215AA697007AC99D /* UnitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnitTests.m; sourceTree = "<group>"; };
5E0282EA215AA697007AC99D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5E8A5DA41D3840B4000F8BC4 /* CoreCronetEnd2EndTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreCronetEnd2EndTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5E8A5DA61D3840B4000F8BC4 /* CoreCronetEnd2EndTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CoreCronetEnd2EndTests.mm; sourceTree = "<group>"; };
5EA908CF4CDA4CE218352A06 /* Pods-InteropTestsLocalSSLCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSLCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream.release.xcconfig"; sourceTree = "<group>"; };
@ -192,7 +206,9 @@
7BA53C6D224288D5870FE6F3 /* Pods-InteropTestsLocalCleartextCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.release.xcconfig"; sourceTree = "<group>"; };
8B498B05C6DA0818B2FA91D4 /* Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.cronet.xcconfig"; sourceTree = "<group>"; };
943138072A9605B5B8DC1FC0 /* Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.debug.xcconfig"; sourceTree = "<group>"; };
94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.test.xcconfig"; sourceTree = "<group>"; };
9E9444C764F0FFF64A7EB58E /* libPods-InteropTestsRemoteWithCronet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteWithCronet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.debug.xcconfig"; sourceTree = "<group>"; };
A58BE6DF1C62D1739EBB2C78 /* libPods-RxLibraryUnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RxLibraryUnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A6F832FCEFA6F6881E620F12 /* Pods-InteropTestsRemote.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.test.xcconfig"; sourceTree = "<group>"; };
AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = "<group>"; };
@ -208,9 +224,11 @@
DBEDE45BDA60DF1E1C8950C0 /* libPods-InteropTestsLocalSSL.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSL.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DC3CA1D948F068E76957A861 /* Pods-InteropTestsRemote.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.debug.xcconfig"; sourceTree = "<group>"; };
E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.debug.xcconfig"; sourceTree = "<group>"; };
E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.cronet.xcconfig"; sourceTree = "<group>"; };
E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = "<group>"; };
E4FD4606D4AB8D5A314D72F0 /* Pods-InteropTestsLocalCleartextCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; sourceTree = "<group>"; };
E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = "<group>"; };
EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.release.xcconfig"; sourceTree = "<group>"; };
F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsLocalSSLCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsRemoteCFStream.a"; sourceTree = BUILT_PRODUCTS_DIR; };
FBD98AC417B9882D32B19F28 /* libPods-CoreCronetEnd2EndTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-CoreCronetEnd2EndTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@ -219,6 +237,15 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
5E0282E3215AA697007AC99D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5E0282EB215AA697007AC99D /* libTests.a in Frameworks */,
CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5E8A5DA11D3840B4000F8BC4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -341,6 +368,7 @@
F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */,
0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */,
F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */,
22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@ -394,10 +422,23 @@
41AA59529240A6BBBD3DB904 /* Pods-InteropTestsLocalSSLCFStream.test.xcconfig */,
55B630C1FF8C36D1EFC4E0A4 /* Pods-InteropTestsLocalSSLCFStream.cronet.xcconfig */,
5EA908CF4CDA4CE218352A06 /* Pods-InteropTestsLocalSSLCFStream.release.xcconfig */,
A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */,
94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */,
E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */,
EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
5E0282E7215AA697007AC99D /* UnitTests */ = {
isa = PBXGroup;
children = (
5E0282E8215AA697007AC99D /* UnitTests.m */,
5E0282EA215AA697007AC99D /* Info.plist */,
);
path = UnitTests;
sourceTree = "<group>";
};
5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = {
isa = PBXGroup;
children = (
@ -432,6 +473,7 @@
5E8A5DA51D3840B4000F8BC4 /* CoreCronetEnd2EndTests */,
5EE84BF21D4717E40050C6CC /* InteropTestsRemoteWithCronet */,
5EAD6D251E27047400002378 /* CronetUnitTests */,
5E0282E7215AA697007AC99D /* UnitTests */,
635697C81B14FC11007A7283 /* Products */,
51E4650F34F854F41FF053B3 /* Pods */,
136D535E19727099B941D7B1 /* Frameworks */,
@ -453,6 +495,7 @@
5EC5E421208177CC000EF4AD /* InteropTestsRemoteCFStream.xctest */,
5EC5E4312081856B000EF4AD /* InteropTestsLocalCleartextCFStream.xctest */,
5EC5E442208185CE000EF4AD /* InteropTestsLocalSSLCFStream.xctest */,
5E0282E6215AA697007AC99D /* UnitTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -485,6 +528,26 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
5E0282E5215AA697007AC99D /* UnitTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5E0282F2215AA697007AC99D /* Build configuration list for PBXNativeTarget "UnitTests" */;
buildPhases = (
F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */,
5E0282E2215AA697007AC99D /* Sources */,
5E0282E3215AA697007AC99D /* Frameworks */,
5E0282E4215AA697007AC99D /* Resources */,
9AD0B5E94F2AA5962EA6AA36 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
5E0282ED215AA697007AC99D /* PBXTargetDependency */,
);
name = UnitTests;
productName = UnitTests;
productReference = 5E0282E6215AA697007AC99D /* UnitTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
5E8A5DA31D3840B4000F8BC4 /* CoreCronetEnd2EndTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */;
@ -729,6 +792,10 @@
LastUpgradeCheck = 0630;
ORGANIZATIONNAME = gRPC;
TargetAttributes = {
5E0282E5215AA697007AC99D = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Automatic;
};
5E8A5DA31D3840B4000F8BC4 = {
CreatedOnToolsVersion = 7.3.1;
};
@ -794,11 +861,19 @@
5EC5E420208177CC000EF4AD /* InteropTestsRemoteCFStream */,
5EC5E4302081856B000EF4AD /* InteropTestsLocalCleartextCFStream */,
5EC5E441208185CE000EF4AD /* InteropTestsLocalSSLCFStream */,
5E0282E5215AA697007AC99D /* UnitTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
5E0282E4215AA697007AC99D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
5E8A5DA21D3840B4000F8BC4 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -1098,6 +1173,24 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream-resources.sh\"\n";
showEnvVarsInLog = 0;
};
9AD0B5E94F2AA5962EA6AA36 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
A023FB55205A7EA37D413549 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -1260,6 +1353,24 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CoreCronetEnd2EndTests/Pods-CoreCronetEnd2EndTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
F07941C0BAF6A7C67AA60C48 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-UnitTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
F3D5B2CDA172580341682830 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -1299,6 +1410,14 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
5E0282E2215AA697007AC99D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5E0282E9215AA697007AC99D /* UnitTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5E8A5DA01D3840B4000F8BC4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -1412,6 +1531,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
5E0282ED215AA697007AC99D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 635697C61B14FC11007A7283 /* Tests */;
targetProxy = 5E0282EC215AA697007AC99D /* PBXContainerItemProxy */;
};
5E8A5DAB1D3840B4000F8BC4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 635697C61B14FC11007A7283 /* Tests */;
@ -1455,6 +1579,128 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
5E0282EE215AA697007AC99D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A2DCF2570BE515B62CB924CA /* Pods-UnitTests.debug.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = UnitTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
};
name = Debug;
};
5E0282EF215AA697007AC99D /* Test */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 94D7A5FAA13480E9A5166D7A /* Pods-UnitTests.test.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = UnitTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
};
name = Test;
};
5E0282F0215AA697007AC99D /* Cronet */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = UnitTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
};
name = Cronet;
};
5E0282F1215AA697007AC99D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = EBFFEC04B514CB0D4922DC40 /* Pods-UnitTests.release.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = UnitTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.grpc.UnitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "\"$(PODS_ROOT)/../../../..\"";
};
name = Release;
};
5E1228981E4D400F00E8504F /* Test */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -2602,6 +2848,17 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
5E0282F2215AA697007AC99D /* Build configuration list for PBXNativeTarget "UnitTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5E0282EE215AA697007AC99D /* Debug */,
5E0282EF215AA697007AC99D /* Test */,
5E0282F0215AA697007AC99D /* Cronet */,
5E0282F1215AA697007AC99D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5E8A5DAE1D3840B4000F8BC4 /* Build configuration list for PBXNativeTarget "CoreCronetEnd2EndTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0920"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E0282E5215AA697007AC99D"
BuildableName = "UnitTests.xctest"
BlueprintName = "UnitTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E0282E5215AA697007AC99D"
BuildableName = "UnitTests.xctest"
BlueprintName = "UnitTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E0282E5215AA697007AC99D"
BuildableName = "UnitTests.xctest"
BlueprintName = "UnitTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E0282E5215AA697007AC99D"
BuildableName = "UnitTests.xctest"
BlueprintName = "UnitTests"
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

@ -0,0 +1,62 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#import <XCTest/XCTest.h>
#import <GRPCClient/GRPCCall.h>
#import "src/objective-c/GRPCClient/private/NSError+GRPC.h"
@interface UnitTests : XCTestCase
@end
@implementation UnitTests
- (void)testNSError {
const char *kDetails = "test details";
const char *kErrorString = "test errorString";
NSError *error1 = [NSError grpc_errorFromStatusCode:GRPC_STATUS_OK details:nil errorString:nil];
NSError *error2 = [NSError grpc_errorFromStatusCode:GRPC_STATUS_CANCELLED
details:kDetails
errorString:kErrorString];
NSError *error3 = [NSError grpc_errorFromStatusCode:GRPC_STATUS_UNAUTHENTICATED
details:kDetails
errorString:nil];
NSError *error4 =
[NSError grpc_errorFromStatusCode:GRPC_STATUS_UNAVAILABLE details:nil errorString:nil];
XCTAssertNil(error1);
XCTAssertEqual(error2.code, 1);
XCTAssertEqualObjects(error2.domain, @"io.grpc");
XCTAssertEqualObjects(error2.userInfo[NSLocalizedDescriptionKey],
[NSString stringWithUTF8String:kDetails]);
XCTAssertEqualObjects(error2.userInfo[NSDebugDescriptionErrorKey],
[NSString stringWithUTF8String:kErrorString]);
XCTAssertEqual(error3.code, 16);
XCTAssertEqualObjects(error3.domain, @"io.grpc");
XCTAssertEqualObjects(error3.userInfo[NSLocalizedDescriptionKey],
[NSString stringWithUTF8String:kDetails]);
XCTAssertNil(error3.userInfo[NSDebugDescriptionErrorKey]);
XCTAssertEqual(error4.code, 14);
XCTAssertEqualObjects(error4.domain, @"io.grpc");
XCTAssertNil(error4.userInfo[NSLocalizedDescriptionKey]);
XCTAssertNil(error4.userInfo[NSDebugDescriptionErrorKey]);
}
@end

@ -163,4 +163,14 @@ xcodebuild \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
echo "TIME: $(date)"
xcodebuild \
-workspace Tests.xcworkspace \
-scheme UnitTests \
-destination name="iPhone 8" \
test \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v '^$' \
| egrep -v "(GPBDictionary|GPBArray)" -
exit 0

@ -100,6 +100,7 @@ grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import;
grpc_channelz_get_servers_type grpc_channelz_get_servers_import;
grpc_channelz_get_channel_type grpc_channelz_get_channel_import;
grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import;
grpc_channelz_get_socket_type grpc_channelz_get_socket_import;
grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import;
grpc_server_add_insecure_channel_from_fd_type grpc_server_add_insecure_channel_from_fd_import;
grpc_use_signal_type grpc_use_signal_import;
@ -356,6 +357,7 @@ void grpc_rb_load_imports(HMODULE library) {
grpc_channelz_get_servers_import = (grpc_channelz_get_servers_type) GetProcAddress(library, "grpc_channelz_get_servers");
grpc_channelz_get_channel_import = (grpc_channelz_get_channel_type) GetProcAddress(library, "grpc_channelz_get_channel");
grpc_channelz_get_subchannel_import = (grpc_channelz_get_subchannel_type) GetProcAddress(library, "grpc_channelz_get_subchannel");
grpc_channelz_get_socket_import = (grpc_channelz_get_socket_type) GetProcAddress(library, "grpc_channelz_get_socket");
grpc_insecure_channel_create_from_fd_import = (grpc_insecure_channel_create_from_fd_type) GetProcAddress(library, "grpc_insecure_channel_create_from_fd");
grpc_server_add_insecure_channel_from_fd_import = (grpc_server_add_insecure_channel_from_fd_type) GetProcAddress(library, "grpc_server_add_insecure_channel_from_fd");
grpc_use_signal_import = (grpc_use_signal_type) GetProcAddress(library, "grpc_use_signal");

@ -275,6 +275,9 @@ extern grpc_channelz_get_channel_type grpc_channelz_get_channel_import;
typedef char*(*grpc_channelz_get_subchannel_type)(intptr_t subchannel_id);
extern grpc_channelz_get_subchannel_type grpc_channelz_get_subchannel_import;
#define grpc_channelz_get_subchannel grpc_channelz_get_subchannel_import
typedef char*(*grpc_channelz_get_socket_type)(intptr_t socket_id);
extern grpc_channelz_get_socket_type grpc_channelz_get_socket_import;
#define grpc_channelz_get_socket grpc_channelz_get_socket_import
typedef grpc_channel*(*grpc_insecure_channel_create_from_fd_type)(const char* target, int fd, const grpc_channel_args* args);
extern grpc_insecure_channel_create_from_fd_type grpc_insecure_channel_create_from_fd_import;
#define grpc_insecure_channel_create_from_fd grpc_insecure_channel_create_from_fd_import

@ -95,7 +95,7 @@ end
# creates a test stub that accesses host:port securely.
def create_stub(opts)
address = "#{opts.host}:#{opts.port}"
address = "#{opts.server_host}:#{opts.server_port}"
# Provide channel args that request compression by default
# for compression interop tests
@ -703,8 +703,8 @@ class NamedTests
end
# Args is used to hold the command line info.
Args = Struct.new(:default_service_account, :host, :host_override,
:oauth_scope, :port, :secure, :test_case,
Args = Struct.new(:default_service_account, :server_host, :host_override,
:oauth_scope, :server_port, :secure, :test_case,
:use_test_ca)
# validates the command line options, returning them as a Hash.
@ -715,7 +715,7 @@ def parse_args
opts.on('--oauth_scope scope',
'Scope for OAuth tokens') { |v| args['oauth_scope'] = v }
opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
args['host'] = v
args['server_host'] = v
end
opts.on('--default_service_account email_address',
'email address of the default service account') do |v|
@ -725,7 +725,9 @@ def parse_args
'override host via a HTTP header') do |v|
args['host_override'] = v
end
opts.on('--server_port SERVER_PORT', 'server port') { |v| args['port'] = v }
opts.on('--server_port SERVER_PORT', 'server port') do |v|
args['server_port'] = v
end
# instance_methods(false) gives only the methods defined in that class
test_cases = NamedTests.instance_methods(false).map(&:to_s)
test_case_list = test_cases.join(',')
@ -744,7 +746,7 @@ def parse_args
end
def _check_args(args)
%w(host port test_case).each do |a|
%w(server_host server_port test_case).each do |a|
if args[a].nil?
fail(OptionParser::MissingArgument, "please specify --#{a}")
end

@ -139,6 +139,7 @@ int main(int argc, char **argv) {
printf("%lx", (unsigned long) grpc_channelz_get_servers);
printf("%lx", (unsigned long) grpc_channelz_get_channel);
printf("%lx", (unsigned long) grpc_channelz_get_subchannel);
printf("%lx", (unsigned long) grpc_channelz_get_socket);
printf("%lx", (unsigned long) grpc_auth_property_iterator_next);
printf("%lx", (unsigned long) grpc_auth_context_property_iterator);
printf("%lx", (unsigned long) grpc_auth_context_peer_identity);

@ -772,6 +772,7 @@ doc/connection-backoff-interop-test-description.md \
doc/connection-backoff.md \
doc/connectivity-semantics-and-api.md \
doc/core/grpc-client-server-polling-engine-usage.md \
doc/core/grpc-cq.md \
doc/core/grpc-error.md \
doc/core/moving-to-c++.md \
doc/core/pending_api_cleanups.md \

@ -772,6 +772,7 @@ doc/connection-backoff-interop-test-description.md \
doc/connection-backoff.md \
doc/connectivity-semantics-and-api.md \
doc/core/grpc-client-server-polling-engine-usage.md \
doc/core/grpc-cq.md \
doc/core/grpc-error.md \
doc/core/moving-to-c++.md \
doc/core/pending_api_cleanups.md \

@ -24,4 +24,4 @@ cd "$(dirname "$0")/../../.."
# after finishing each build. We only leave files we want to keep:
# - reports and artifacts
# - directory containing the kokoro scripts to prevent deleting a script while being executed.
time find . -type f -not -iname "*sponge_log.xml" -not -path "./reports/*" -not -path "./artifacts/*" -not -path "./tools/internal_ci/*" -exec rm -f {} +
time find . -type f -not -iname "*sponge_log.*" -not -path "./reports/*" -not -path "./artifacts/*" -not -path "./tools/internal_ci/*" -exec rm -f {} +

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_artifacts.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_artifacts_extra.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_artifacts_extra.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_submodule_at_head.sh"
timeout_mins: 180
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_packages.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_build_submodule_at_head.sh"
timeout_mins: 180
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_coverage.sh"
timeout_mins: 420
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_distribtests.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_distribtests_standalone.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_full_performance_master.sh"
timeout_mins: 600
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "**/perf_reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_full_performance_release.sh"
timeout_mins: 600
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "**/perf_reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_interop_matrix.sh"
timeout_mins: 300
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 180
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_publish_packages.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 30
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 40
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
timeout_mins: 60
action {
define_artifacts {
regex: "**/sponge_log.xml"
regex: "**/sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_microbenchmark_diff.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 40
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_trickle_diff.sh"
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
timeout_mins: 1440
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 120
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
regex: "github/grpc/artifacts/**"
}

@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -21,7 +21,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/interop/service_account/GrpcTes
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

@ -20,7 +20,7 @@ gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0e
timeout_mins: 240
action {
define_artifacts {
regex: "**/*sponge_log.xml"
regex: "**/*sponge_log.*"
regex: "github/grpc/reports/**"
}
}

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

Loading…
Cancel
Save