From c73c4f7ae22c8f68a93b1bf062d92e37aef79431 Mon Sep 17 00:00:00 2001 From: Adam Czachorowski Date: Thu, 14 Dec 2017 16:21:00 +0100 Subject: [PATCH 01/39] Fix the ownership comment on grpc_lb_addresses_set_address() function. It does not take ownership of balancer_name since commit 53af23cfbf3b1fd4579ec084dbcb7b89a7ae2e96 --- src/core/ext/filters/client_channel/lb_policy_factory.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/ext/filters/client_channel/lb_policy_factory.h b/src/core/ext/filters/client_channel/lb_policy_factory.h index 9da231b657b..db917cba586 100644 --- a/src/core/ext/filters/client_channel/lb_policy_factory.h +++ b/src/core/ext/filters/client_channel/lb_policy_factory.h @@ -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, From 520b2a0786494ff530b7a91d616c255a33e940a8 Mon Sep 17 00:00:00 2001 From: ganmacs Date: Wed, 16 May 2018 00:26:11 +0900 Subject: [PATCH 02/39] Fix a error message To match the name with the code in #parse_args method. --- src/ruby/pb/test/client.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ruby/pb/test/client.rb b/src/ruby/pb/test/client.rb index 1b9d7cbbe61..7ac12c39a51 100755 --- a/src/ruby/pb/test/client.rb +++ b/src/ruby/pb/test/client.rb @@ -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 From 26d3e774df8d601c5ce9c5fb181f846b1fe07049 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 16 Aug 2018 13:13:30 +0200 Subject: [PATCH 03/39] new C# serialization API --- .../Grpc.Core/DeserializationContext.cs | 49 ++++++++ src/csharp/Grpc.Core/Marshaller.cs | 110 ++++++++++++++++-- src/csharp/Grpc.Core/SerializationContext.cs | 34 ++++++ 3 files changed, 181 insertions(+), 12 deletions(-) create mode 100644 src/csharp/Grpc.Core/DeserializationContext.cs create mode 100644 src/csharp/Grpc.Core/SerializationContext.cs diff --git a/src/csharp/Grpc.Core/DeserializationContext.cs b/src/csharp/Grpc.Core/DeserializationContext.cs new file mode 100644 index 00000000000..17f0ba2805c --- /dev/null +++ b/src/csharp/Grpc.Core/DeserializationContext.cs @@ -0,0 +1,49 @@ +#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 +{ + /// + /// Provides access to the payload being deserialized when deserializing messages. + /// + public abstract class DeserializationContext + { + /// + /// Returns true if there is a payload to deserialize (= payload is not null), false otherwise. + /// + public virtual bool HasPayload => PayloadLength.HasValue; + + /// + /// Get the total length of the payload in bytes or null if the payload is null. + /// + public abstract int? PayloadLength { get; } + + /// + /// 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). + /// + /// byte array containing the entire payload or null if there is no payload. + public abstract byte[] PayloadAsNewBuffer(); + } +} diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index 1d758ca935d..df59cbd8d3a 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -29,36 +29,122 @@ namespace Grpc.Core readonly Func serializer; readonly Func deserializer; + readonly Action contextualSerializer; + readonly Func contextualDeserializer; + /// - /// Initializes a new marshaller. + /// Initializes a new marshaller from simple serialize/deserialize functions. /// /// Function that will be used to serialize messages. /// Function that will be used to deserialize messages. public Marshaller(Func serializer, Func 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; } /// - /// 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. /// - public Func Serializer + /// Function that will be used to serialize messages. + /// Function that will be used to deserialize messages. + public Marshaller(Action serializer, Func deserializer) { - get - { - return this.serializer; - } + this.contextualSerializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer)); + this.contextualDeserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer)); + this.serializer = EmulateSimpleSerializer; + this.deserializer = EmulateSimpleDeserializer; } + /// + /// Gets the serializer function. + /// + public Func Serializer => this.serializer; + /// /// Gets the deserializer function. /// - public Func Deserializer + public Func Deserializer => this.deserializer; + + /// + /// Gets the serializer function. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public Action ContextualSerializer => this.contextualSerializer; + + /// + /// Gets the serializer function. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public Func 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 + 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 + 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; + + public EmulatedDeserializationContext(byte[] payload) + { + this.payload = payload; + } + + public override int? PayloadLength => payload?.Length; + + public override byte[] PayloadAsNewBuffer() { - return this.deserializer; + return payload; } } } diff --git a/src/csharp/Grpc.Core/SerializationContext.cs b/src/csharp/Grpc.Core/SerializationContext.cs new file mode 100644 index 00000000000..cf4d1595da2 --- /dev/null +++ b/src/csharp/Grpc.Core/SerializationContext.cs @@ -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 +{ + /// + /// Provides storage for payload when serializing a message. + /// + public abstract class SerializationContext + { + /// + /// 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. + /// + /// the serialized form of current message + public abstract void Complete(byte[] payload); + } +} From fb704ee949047ebc1d78f00b4b7d6938f8e89a6a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 27 Aug 2018 20:39:26 +0200 Subject: [PATCH 04/39] deserialization context always has non-null payload --- src/csharp/Grpc.Core/DeserializationContext.cs | 11 +++-------- src/csharp/Grpc.Core/Marshaller.cs | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/csharp/Grpc.Core/DeserializationContext.cs b/src/csharp/Grpc.Core/DeserializationContext.cs index 17f0ba2805c..96de08f76d7 100644 --- a/src/csharp/Grpc.Core/DeserializationContext.cs +++ b/src/csharp/Grpc.Core/DeserializationContext.cs @@ -24,14 +24,9 @@ namespace Grpc.Core public abstract class DeserializationContext { /// - /// Returns true if there is a payload to deserialize (= payload is not null), false otherwise. + /// Get the total length of the payload in bytes. /// - public virtual bool HasPayload => PayloadLength.HasValue; - - /// - /// Get the total length of the payload in bytes or null if the payload is null. - /// - public abstract int? PayloadLength { get; } + public abstract int PayloadLength { get; } /// /// Gets the entire payload as a newly allocated byte array. @@ -43,7 +38,7 @@ namespace Grpc.Core /// 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). /// - /// byte array containing the entire payload or null if there is no payload. + /// byte array containing the entire payload. public abstract byte[] PayloadAsNewBuffer(); } } diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index df59cbd8d3a..ad01b9383cd 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -137,10 +137,10 @@ namespace Grpc.Core public EmulatedDeserializationContext(byte[] payload) { - this.payload = payload; + this.payload = GrpcPreconditions.CheckNotNull(payload); } - public override int? PayloadLength => payload?.Length; + public override int PayloadLength => payload.Length; public override byte[] PayloadAsNewBuffer() { From 6ba637f7ecdd45bf43c1a7959115190ca5a2f5c8 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 27 Aug 2018 20:42:06 +0200 Subject: [PATCH 05/39] add Marshallers.Create factory method --- src/csharp/Grpc.Core/Marshaller.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index ad01b9383cd..7f010dc4192 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -162,6 +162,15 @@ namespace Grpc.Core return new Marshaller(serializer, deserializer); } + /// + /// 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. + /// + public static Marshaller Create(Action serializer, Func deserializer) + { + return new Marshaller(serializer, deserializer); + } + /// /// Returns a marshaller for string type. This is useful for testing. /// From 97264ea3365bfa895dbd20983772178feaef0908 Mon Sep 17 00:00:00 2001 From: Eundoo Song Date: Sat, 1 Sep 2018 02:18:52 +0900 Subject: [PATCH 06/39] Remove unused import --- .../default_value/default_value_client_interceptor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/python/interceptors/default_value/default_value_client_interceptor.py b/examples/python/interceptors/default_value/default_value_client_interceptor.py index c549f2b8613..c935b954918 100644 --- a/examples/python/interceptors/default_value/default_value_client_interceptor.py +++ b/examples/python/interceptors/default_value/default_value_client_interceptor.py @@ -13,8 +13,6 @@ # limitations under the License. """Interceptor that adds headers to outgoing requests.""" -import collections - import grpc From bd9d97a2003322f523d54f7bc9fa89dff3e36ab5 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 12 Sep 2018 11:34:00 -0700 Subject: [PATCH 07/39] Channelz socket support --- include/grpc/grpc.h | 4 + .../chttp2/transport/chttp2_transport.cc | 24 +++ .../transport/chttp2/transport/frame_data.cc | 1 + .../ext/transport/chttp2/transport/internal.h | 7 + .../ext/transport/chttp2/transport/parsing.cc | 6 + .../ext/transport/chttp2/transport/writing.cc | 1 + src/core/lib/channel/channelz.cc | 112 ++++++++++- src/core/lib/channel/channelz.h | 29 ++- src/core/lib/channel/channelz_registry.cc | 18 ++ test/core/end2end/tests/channelz.cc | 176 ++++++++++++++++++ 10 files changed, 372 insertions(+), 6 deletions(-) diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index ce421e93bd8..fc0a0d3cce0 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -510,6 +510,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 diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 26cad2cc9a6..38032d56a60 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -335,6 +335,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(); } else { static const struct { const char* channel_arg_name; @@ -720,6 +724,14 @@ static void destroy_stream_locked(void* sp, grpc_error* error) { grpc_chttp2_stream* s = static_cast(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 +1419,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 +1507,9 @@ static void perform_stream_op_locked(void* stream_op, if (op->send_message) { GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE(); + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordMessageSent(); + } GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE( op->payload->send_message.send_message->length()); on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; @@ -1609,6 +1627,9 @@ static void perform_stream_op_locked(void* stream_op, if (op->recv_message) { GRPC_STATS_INC_HTTP2_OP_RECV_MESSAGE(); + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordMessageRecieved(); + } size_t before = 0; GPR_ASSERT(s->recv_message_ready == nullptr); GPR_ASSERT(!s->pending_byte_stream); @@ -2707,6 +2728,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, diff --git a/src/core/ext/transport/chttp2/transport/frame_data.cc b/src/core/ext/transport/chttp2/transport/frame_data.cc index f8f06f67891..15de8795282 100644 --- a/src/core/ext/transport/chttp2/transport/frame_data.cc +++ b/src/core/ext/transport/chttp2/transport/frame_data.cc @@ -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; } diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 6b5309bab48..bf0dfa98af8 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -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,8 @@ struct grpc_chttp2_transport { bool keepalive_permit_without_calls; /** keep-alive state machine state */ grpc_chttp2_keepalive_state keepalive_state; + + grpc_core::RefCountedPtr channelz_socket; }; typedef enum { @@ -534,6 +537,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 */ diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc index 1e491d2ef86..0694ad743bb 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.cc +++ b/src/core/ext/transport/chttp2/transport/parsing.cc @@ -598,6 +598,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; } @@ -611,6 +614,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) { diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index 8b73b01dea2..5beaf5491ef 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -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( diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 375cf25cc66..e1ab2ead626 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -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, @@ -184,5 +186,105 @@ grpc_json* ServerNode::RenderJson() { return top_level_json; } +void SocketNode::RecordStreamStartedFromLocal() { + gpr_atm_no_barrier_fetch_add(&streams_started_, (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_, (gpr_atm)1); + gpr_atm_no_barrier_store(&last_remote_stream_created_millis_, + (gpr_atm)ExecCtx::Get()->Now()); +} + +void SocketNode::RecordMessageSent() { + gpr_atm_no_barrier_fetch_add(&messages_sent_, (gpr_atm)1); + gpr_atm_no_barrier_store(&last_message_sent_millis_, + (gpr_atm)ExecCtx::Get()->Now()); +} + +void SocketNode::RecordMessageRecieved() { + gpr_atm_no_barrier_fetch_add(&messages_recieved_, (gpr_atm)1); + gpr_atm_no_barrier_store(&last_message_recieved_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; + if (streams_started_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "streamsStarted", streams_started_); + } + 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_); + } + if (messages_recieved_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "messagesRecieved", messages_recieved_); + } + if (keepalives_sent_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "keepAlivesSent", keepalives_sent_); + } + gpr_timespec ts; + if (streams_started_ != 0 && 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 (streams_started_ != 0 && 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 (messages_sent_ != 0) { + 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_recieved_ != 0) { + ts = grpc_millis_to_timespec(last_message_recieved_millis_, + GPR_CLOCK_REALTIME); + json_iterator = grpc_json_create_child( + json_iterator, json, "lastMessageRecievedTimestamp", + gpr_format_timespec(ts), GRPC_JSON_STRING, true); + } + json = top_level_json; + return top_level_json; +} + } // namespace channelz } // namespace grpc_core diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 9be256147bb..24868208632 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -197,11 +197,38 @@ 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() override {} + + grpc_json* RenderJson() override; + + void RecordStreamStartedFromLocal(); + void RecordStreamStartedFromRemote(); + void RecordStreamSucceeded() { + gpr_atm_no_barrier_fetch_add(&streams_succeeded_, (gpr_atm(1))); + } + void RecordStreamFailed() { + gpr_atm_no_barrier_fetch_add(&streams_failed_, (gpr_atm(1))); + } + void RecordMessageSent(); + void RecordMessageRecieved(); + void RecordKeepaliveSent() { + gpr_atm_no_barrier_fetch_add(&keepalives_sent_, (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_recieved_ = 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_recieved_millis_ = 0; }; // Creation functions diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index adc7b6ba441..841f1c6104b 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -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; +} diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 40a0370f0ea..3ebaea2afc5 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -196,6 +196,178 @@ static void run_one_request(grpc_end2end_test_config config, cq_verifier_destroy(cqv); } +/* Creates and returns a grpc_slice containing random alphanumeric characters. + */ +static grpc_slice generate_random_slice() { + size_t i; + static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; + char* output; + const size_t output_size = 1024 * 1024; + output = static_cast(gpr_malloc(output_size)); + for (i = 0; i < output_size - 1; ++i) { + output[i] = chars[rand() % static_cast(sizeof(chars) - 1)]; + } + output[output_size - 1] = '\0'; + grpc_slice out = grpc_slice_from_copied_string(output); + gpr_free(output); + return out; +} + +static void run_one_request_with_payload(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + /* Create large request and response bodies. These are big enough to require + * multiple round trips to deliver to the peer, and their exact contents of + * will be verified on completion. */ + grpc_slice request_payload_slice = generate_random_slice(); + grpc_slice response_payload_slice = generate_random_slice(); + + grpc_call* c; + grpc_call* s; + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + cq_verifier* cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op* op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer* request_payload_recv = nullptr; + grpc_byte_buffer* response_payload_recv = nullptr; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + + gpr_timespec deadline = n_seconds_from_now(60); + c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), nullptr, + deadline, nullptr); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(1), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(102), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = nullptr; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = nullptr; + op++; + error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(103), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); + GPR_ASSERT( + byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); +} + static void test_channelz(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; @@ -258,6 +430,10 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + // one successful request with payload to test socket data + // TODO(ncteisen): add some programatic spot checks on the socket json. + run_one_request_with_payload(config, f); + end_test(&f); config.tear_down_data(&f); } From 0a650eae58901a3a45313ad61aa641d5804a680a Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 19 Sep 2018 07:41:59 -0700 Subject: [PATCH 08/39] regenerate projects --- grpc.def | 1 + src/ruby/ext/grpc/rb_grpc_imports.generated.c | 2 ++ src/ruby/ext/grpc/rb_grpc_imports.generated.h | 3 +++ test/core/surface/public_headers_must_be_c89.c | 1 + 4 files changed, 7 insertions(+) diff --git a/grpc.def b/grpc.def index b7ba2c5d10e..345c0a786ce 100644 --- a/grpc.def +++ b/grpc.def @@ -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 diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 0c46f6c85a1..1e7d7f687f0 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -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"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index 6adddb536c9..1375f68bbfb 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -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 diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index b0af788796f..3ebdb88a08e 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -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); From 63a31d85f1557f1c0e2b1be04e7bd4d07a88607e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sun, 23 Sep 2018 18:58:37 -0700 Subject: [PATCH 09/39] contextual marshaller test --- .../ContextualMarshallerTest.cs | 119 ++++++++++++++++++ src/csharp/tests.json | 1 + 2 files changed, 120 insertions(+) create mode 100644 src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs diff --git a/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs b/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs new file mode 100644 index 00000000000..c3aee726f26 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs @@ -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( + (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((request, context) => + { + return Task.FromResult(request); + }); + Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC")); + } + + [Test] + public void ResponseParsingError_UnaryResponse() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("UNPARSEABLE_VALUE"); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST")); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void RequestSerializationError_BlockingUnary() + { + Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public void SerializationResultIsNull_BlockingUnary() + { + Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "SERIALIZE_TO_NULL")); + } + } +} diff --git a/src/csharp/tests.json b/src/csharp/tests.json index c2f243fe0ae..e4feb4dc3ad 100644 --- a/src/csharp/tests.json +++ b/src/csharp/tests.json @@ -23,6 +23,7 @@ "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.MarshallingErrorsTest", From a2a4629614bb79e3a4d7ea6594e31e33d63a65be Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sun, 23 Sep 2018 21:10:03 -0700 Subject: [PATCH 10/39] add MarshallerTest --- src/csharp/Grpc.Core.Tests/MarshallerTest.cs | 105 +++++++++++++++++++ src/csharp/tests.json | 1 + 2 files changed, 106 insertions(+) create mode 100644 src/csharp/Grpc.Core.Tests/MarshallerTest.cs diff --git a/src/csharp/Grpc.Core.Tests/MarshallerTest.cs b/src/csharp/Grpc.Core.Tests/MarshallerTest.cs new file mode 100644 index 00000000000..97f64a0575e --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/MarshallerTest.cs @@ -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 simpleSerializer = System.Text.Encoding.UTF8.GetBytes; + Func simpleDeserializer = System.Text.Encoding.UTF8.GetString; + var marshaller = new Marshaller(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 contextualSerializer = (str, context) => + { + var bytes = System.Text.Encoding.UTF8.GetBytes(str); + context.Complete(bytes); + }; + Func contextualDeserializer = (context) => + { + return System.Text.Encoding.UTF8.GetString(context.PayloadAsNewBuffer()); + }; + var marshaller = new Marshaller(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; + } + } + } +} diff --git a/src/csharp/tests.json b/src/csharp/tests.json index e4feb4dc3ad..5683d164c6a 100644 --- a/src/csharp/tests.json +++ b/src/csharp/tests.json @@ -26,6 +26,7 @@ "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", From 86600071b0ec7dd405b970c2a2b0ef808b130967 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 24 Sep 2018 16:12:00 -0700 Subject: [PATCH 11/39] reviewer feedback --- .../chttp2/transport/chttp2_transport.cc | 7 +- .../transport/chttp2/transport/frame_data.cc | 3 + .../ext/transport/chttp2/transport/internal.h | 1 + .../ext/transport/chttp2/transport/writing.cc | 5 ++ src/core/lib/channel/channelz.cc | 74 +++++++++---------- src/core/lib/channel/channelz.h | 21 +++--- test/core/end2end/tests/channelz.cc | 32 ++++++-- 7 files changed, 84 insertions(+), 59 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 38032d56a60..9da9a7a63c3 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -1507,9 +1507,7 @@ static void perform_stream_op_locked(void* stream_op, if (op->send_message) { GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE(); - if (t->channelz_socket != nullptr) { - t->channelz_socket->RecordMessageSent(); - } + 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; @@ -1627,9 +1625,6 @@ static void perform_stream_op_locked(void* stream_op, if (op->recv_message) { GRPC_STATS_INC_HTTP2_OP_RECV_MESSAGE(); - if (t->channelz_socket != nullptr) { - t->channelz_socket->RecordMessageRecieved(); - } size_t before = 0; GPR_ASSERT(s->recv_message_ready == nullptr); GPR_ASSERT(!s->pending_byte_stream); diff --git a/src/core/ext/transport/chttp2/transport/frame_data.cc b/src/core/ext/transport/chttp2/transport/frame_data.cc index 15de8795282..933b32c03c0 100644 --- a/src/core/ext/transport/chttp2/transport/frame_data.cc +++ b/src/core/ext/transport/chttp2/transport/frame_data.cc @@ -192,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(*cur)); + if (t->channelz_socket != nullptr) { + t->channelz_socket->RecordMessageReceived(); + } p->state = GRPC_CHTTP2_DATA_FRAME; ++cur; message_flags = 0; diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index bf0dfa98af8..ff26dd9255d 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -474,6 +474,7 @@ struct grpc_chttp2_transport { grpc_chttp2_keepalive_state keepalive_state; grpc_core::RefCountedPtr channelz_socket; + uint32_t num_messages_in_next_write; }; typedef enum { diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index 5beaf5491ef..d533989444c 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -633,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(s->sending_bytes), diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index e1ab2ead626..df5c99f91e2 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -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(1)); gpr_atm_no_barrier_store(&last_call_started_millis_, (gpr_atm)ExecCtx::Get()->Now()); } @@ -182,31 +182,32 @@ grpc_json* ServerNode::RenderJson() { } // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); - json = top_level_json; return top_level_json; } +SocketNode::SocketNode() : BaseNode(EntityType::kSocket) {} + void SocketNode::RecordStreamStartedFromLocal() { - gpr_atm_no_barrier_fetch_add(&streams_started_, (gpr_atm)1); + gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast(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_, (gpr_atm)1); + gpr_atm_no_barrier_fetch_add(&streams_started_, static_cast(1)); gpr_atm_no_barrier_store(&last_remote_stream_created_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void SocketNode::RecordMessageSent() { - gpr_atm_no_barrier_fetch_add(&messages_sent_, (gpr_atm)1); +void SocketNode::RecordMessagesSent(uint32_t num_sent) { + gpr_atm_no_barrier_fetch_add(&messages_sent_, static_cast(num_sent)); gpr_atm_no_barrier_store(&last_message_sent_millis_, (gpr_atm)ExecCtx::Get()->Now()); } -void SocketNode::RecordMessageRecieved() { - gpr_atm_no_barrier_fetch_add(&messages_recieved_, (gpr_atm)1); - gpr_atm_no_barrier_store(&last_message_recieved_millis_, +void SocketNode::RecordMessageReceived() { + gpr_atm_no_barrier_fetch_add(&messages_received_, static_cast(1)); + gpr_atm_no_barrier_store(&last_message_received_millis_, (gpr_atm)ExecCtx::Get()->Now()); } @@ -242,47 +243,44 @@ grpc_json* SocketNode::RenderJson() { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "streamsFailed", streams_failed_); } + gpr_timespec ts; if (messages_sent_ != 0) { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "messagesSent", messages_sent_); - } - if (messages_recieved_ != 0) { - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "messagesRecieved", messages_recieved_); - } - if (keepalives_sent_ != 0) { - json_iterator = grpc_json_add_number_string_child( - json, json_iterator, "keepAlivesSent", keepalives_sent_); - } - gpr_timespec ts; - if (streams_started_ != 0 && 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 (streams_started_ != 0 && 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 (messages_sent_ != 0) { 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_recieved_ != 0) { - ts = grpc_millis_to_timespec(last_message_recieved_millis_, + 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, "lastMessageRecievedTimestamp", + json_iterator, json, "lastMessageReceivedTimestamp", gpr_format_timespec(ts), GRPC_JSON_STRING, true); } - json = top_level_json; + if (keepalives_sent_ != 0) { + json_iterator = grpc_json_add_number_string_child( + json, json_iterator, "keepAlivesSent", keepalives_sent_); + } + if (streams_started_ != 0) { + 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); + } + } return top_level_json; } diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 24868208632..b7ae1012389 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -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(1)); } void RecordCallSucceeded() { - gpr_atm_no_barrier_fetch_add(&calls_succeeded_, (gpr_atm(1))); + gpr_atm_no_barrier_fetch_add(&calls_succeeded_, static_cast(1)); } // Common rendering of the call count data and last_call_started_timestamp. @@ -199,7 +199,7 @@ class ServerNode : public BaseNode { // Handles channelz bookkeeping for sockets class SocketNode : public BaseNode { public: - SocketNode() : BaseNode(EntityType::kSocket) {} + SocketNode(); ~SocketNode() override {} grpc_json* RenderJson() override; @@ -207,15 +207,15 @@ class SocketNode : public BaseNode { void RecordStreamStartedFromLocal(); void RecordStreamStartedFromRemote(); void RecordStreamSucceeded() { - gpr_atm_no_barrier_fetch_add(&streams_succeeded_, (gpr_atm(1))); + gpr_atm_no_barrier_fetch_add(&streams_succeeded_, static_cast(1)); } void RecordStreamFailed() { - gpr_atm_no_barrier_fetch_add(&streams_failed_, (gpr_atm(1))); + gpr_atm_no_barrier_fetch_add(&streams_failed_, static_cast(1)); } - void RecordMessageSent(); - void RecordMessageRecieved(); + void RecordMessagesSent(uint32_t num_sent); + void RecordMessageReceived(); void RecordKeepaliveSent() { - gpr_atm_no_barrier_fetch_add(&keepalives_sent_, (gpr_atm(1))); + gpr_atm_no_barrier_fetch_add(&keepalives_sent_, static_cast(1)); } private: @@ -223,12 +223,13 @@ class SocketNode : public BaseNode { gpr_atm streams_succeeded_ = 0; gpr_atm streams_failed_ = 0; gpr_atm messages_sent_ = 0; - gpr_atm messages_recieved_ = 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_recieved_millis_ = 0; + gpr_atm last_message_received_millis_ = 0; + UniquePtr peer_string_; }; // Creation functions diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index 3ebaea2afc5..bb99045d1e5 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -202,12 +202,12 @@ static grpc_slice generate_random_slice() { size_t i; static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; char* output; - const size_t output_size = 1024 * 1024; - output = static_cast(gpr_malloc(output_size)); - for (i = 0; i < output_size - 1; ++i) { + const size_t kOutputSize = 1024 * 1024; + output = static_cast(gpr_malloc(kOutputSize)); + for (i = 0; i < kOutputSize - 1; ++i) { output[i] = chars[rand() % static_cast(sizeof(chars) - 1)]; } - output[output_size - 1] = '\0'; + output[kOutputSize - 1] = '\0'; grpc_slice out = grpc_slice_from_copied_string(output); gpr_free(output); return out; @@ -430,10 +430,32 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); + // TODO(ncteisen): add logic to query for socket id once child socket support + // is in place. For now, we hardcode uuid=5, which we know is a socket. + json = grpc_channelz_get_socket(5); + GPR_ASSERT(json != nullptr); + gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"socketId\":\"5\"")); + GPR_ASSERT(nullptr != strstr(json, "\"streamsStarted\":\"2\"")); + GPR_ASSERT(nullptr != strstr(json, "\"streamsSucceeded\":\"2\"")); + // no messaged sent yet. + GPR_ASSERT(nullptr == strstr(json, "\"messagesSent\"")); + GPR_ASSERT(nullptr == strstr(json, "\"messagesReceived\"")); + gpr_free(json); + // one successful request with payload to test socket data - // TODO(ncteisen): add some programatic spot checks on the socket json. run_one_request_with_payload(config, f); + json = grpc_channelz_get_socket(5); + GPR_ASSERT(json != nullptr); + gpr_log(GPR_INFO, "%s", json); + GPR_ASSERT(nullptr != strstr(json, "\"socketId\":\"5\"")); + GPR_ASSERT(nullptr != strstr(json, "\"streamsStarted\":\"3\"")); + GPR_ASSERT(nullptr != strstr(json, "\"streamsSucceeded\":\"3\"")); + GPR_ASSERT(nullptr != strstr(json, "\"messagesSent\":\"1\"")); + GPR_ASSERT(nullptr != strstr(json, "\"messagesReceived\":\"1\"")); + gpr_free(json); + end_test(&f); config.tear_down_data(&f); } From 7e34212e50b4275be556fe806bb7c259d77ab7d3 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 24 Sep 2018 16:36:55 -0700 Subject: [PATCH 12/39] Don't test socket in core end2end test --- test/core/end2end/tests/channelz.cc | 198 ---------------------------- 1 file changed, 198 deletions(-) diff --git a/test/core/end2end/tests/channelz.cc b/test/core/end2end/tests/channelz.cc index bb99045d1e5..40a0370f0ea 100644 --- a/test/core/end2end/tests/channelz.cc +++ b/test/core/end2end/tests/channelz.cc @@ -196,178 +196,6 @@ static void run_one_request(grpc_end2end_test_config config, cq_verifier_destroy(cqv); } -/* Creates and returns a grpc_slice containing random alphanumeric characters. - */ -static grpc_slice generate_random_slice() { - size_t i; - static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; - char* output; - const size_t kOutputSize = 1024 * 1024; - output = static_cast(gpr_malloc(kOutputSize)); - for (i = 0; i < kOutputSize - 1; ++i) { - output[i] = chars[rand() % static_cast(sizeof(chars) - 1)]; - } - output[kOutputSize - 1] = '\0'; - grpc_slice out = grpc_slice_from_copied_string(output); - gpr_free(output); - return out; -} - -static void run_one_request_with_payload(grpc_end2end_test_config config, - grpc_end2end_test_fixture f) { - /* Create large request and response bodies. These are big enough to require - * multiple round trips to deliver to the peer, and their exact contents of - * will be verified on completion. */ - grpc_slice request_payload_slice = generate_random_slice(); - grpc_slice response_payload_slice = generate_random_slice(); - - grpc_call* c; - grpc_call* s; - grpc_byte_buffer* request_payload = - grpc_raw_byte_buffer_create(&request_payload_slice, 1); - grpc_byte_buffer* response_payload = - grpc_raw_byte_buffer_create(&response_payload_slice, 1); - cq_verifier* cqv = cq_verifier_create(f.cq); - grpc_op ops[6]; - grpc_op* op; - grpc_metadata_array initial_metadata_recv; - grpc_metadata_array trailing_metadata_recv; - grpc_metadata_array request_metadata_recv; - grpc_byte_buffer* request_payload_recv = nullptr; - grpc_byte_buffer* response_payload_recv = nullptr; - grpc_call_details call_details; - grpc_status_code status; - grpc_call_error error; - grpc_slice details; - int was_cancelled = 2; - - gpr_timespec deadline = n_seconds_from_now(60); - c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, - grpc_slice_from_static_string("/foo"), nullptr, - deadline, nullptr); - GPR_ASSERT(c); - - grpc_metadata_array_init(&initial_metadata_recv); - grpc_metadata_array_init(&trailing_metadata_recv); - grpc_metadata_array_init(&request_metadata_recv); - grpc_call_details_init(&call_details); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = request_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &response_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; - op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; - op->data.recv_status_on_client.status = &status; - op->data.recv_status_on_client.status_details = &details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(1), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - error = - grpc_server_request_call(f.server, &s, &call_details, - &request_metadata_recv, f.cq, f.cq, tag(101)); - GPR_ASSERT(GRPC_CALL_OK == error); - CQ_EXPECT_COMPLETION(cqv, tag(101), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_SEND_INITIAL_METADATA; - op->data.send_initial_metadata.count = 0; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_RECV_MESSAGE; - op->data.recv_message.recv_message = &request_payload_recv; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(102), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(102), 1); - cq_verify(cqv); - - memset(ops, 0, sizeof(ops)); - op = ops; - op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; - op->data.recv_close_on_server.cancelled = &was_cancelled; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_MESSAGE; - op->data.send_message.send_message = response_payload; - op->flags = 0; - op->reserved = nullptr; - op++; - op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; - op->data.send_status_from_server.trailing_metadata_count = 0; - op->data.send_status_from_server.status = GRPC_STATUS_OK; - grpc_slice status_details = grpc_slice_from_static_string("xyz"); - op->data.send_status_from_server.status_details = &status_details; - op->flags = 0; - op->reserved = nullptr; - op++; - error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(103), - nullptr); - GPR_ASSERT(GRPC_CALL_OK == error); - - CQ_EXPECT_COMPLETION(cqv, tag(103), 1); - CQ_EXPECT_COMPLETION(cqv, tag(1), 1); - cq_verify(cqv); - - GPR_ASSERT(status == GRPC_STATUS_OK); - GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); - GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); - GPR_ASSERT(was_cancelled == 0); - GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice)); - GPR_ASSERT( - byte_buffer_eq_slice(response_payload_recv, response_payload_slice)); - - grpc_slice_unref(details); - grpc_metadata_array_destroy(&initial_metadata_recv); - grpc_metadata_array_destroy(&trailing_metadata_recv); - grpc_metadata_array_destroy(&request_metadata_recv); - grpc_call_details_destroy(&call_details); - - grpc_call_unref(c); - grpc_call_unref(s); - - cq_verifier_destroy(cqv); - - grpc_byte_buffer_destroy(request_payload); - grpc_byte_buffer_destroy(response_payload); - grpc_byte_buffer_destroy(request_payload_recv); - grpc_byte_buffer_destroy(response_payload_recv); -} - static void test_channelz(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; @@ -430,32 +258,6 @@ static void test_channelz(grpc_end2end_test_config config) { GPR_ASSERT(nullptr == strstr(json, "\"severity\":\"CT_INFO\"")); gpr_free(json); - // TODO(ncteisen): add logic to query for socket id once child socket support - // is in place. For now, we hardcode uuid=5, which we know is a socket. - json = grpc_channelz_get_socket(5); - GPR_ASSERT(json != nullptr); - gpr_log(GPR_INFO, "%s", json); - GPR_ASSERT(nullptr != strstr(json, "\"socketId\":\"5\"")); - GPR_ASSERT(nullptr != strstr(json, "\"streamsStarted\":\"2\"")); - GPR_ASSERT(nullptr != strstr(json, "\"streamsSucceeded\":\"2\"")); - // no messaged sent yet. - GPR_ASSERT(nullptr == strstr(json, "\"messagesSent\"")); - GPR_ASSERT(nullptr == strstr(json, "\"messagesReceived\"")); - gpr_free(json); - - // one successful request with payload to test socket data - run_one_request_with_payload(config, f); - - json = grpc_channelz_get_socket(5); - GPR_ASSERT(json != nullptr); - gpr_log(GPR_INFO, "%s", json); - GPR_ASSERT(nullptr != strstr(json, "\"socketId\":\"5\"")); - GPR_ASSERT(nullptr != strstr(json, "\"streamsStarted\":\"3\"")); - GPR_ASSERT(nullptr != strstr(json, "\"streamsSucceeded\":\"3\"")); - GPR_ASSERT(nullptr != strstr(json, "\"messagesSent\":\"1\"")); - GPR_ASSERT(nullptr != strstr(json, "\"messagesReceived\":\"1\"")); - gpr_free(json); - end_test(&f); config.tear_down_data(&f); } From 805b8db33ced4888b325fdaf8980afdb7c155769 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Mon, 24 Sep 2018 22:07:56 -0700 Subject: [PATCH 13/39] fix asan --- src/core/ext/transport/chttp2/transport/chttp2_transport.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 9da9a7a63c3..d3232f4d268 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -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); From cc0a1e1d7eca67f35f3c5bf002b1485df548e67e Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 25 Sep 2018 09:39:41 -0700 Subject: [PATCH 14/39] reviewer feedback: --- src/core/lib/channel/channelz.cc | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index df5c99f91e2..339c827525c 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -231,9 +231,24 @@ grpc_json* SocketNode::RenderJson() { 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( @@ -243,7 +258,6 @@ grpc_json* SocketNode::RenderJson() { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "streamsFailed", streams_failed_); } - gpr_timespec ts; if (messages_sent_ != 0) { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "messagesSent", messages_sent_); @@ -265,22 +279,6 @@ grpc_json* SocketNode::RenderJson() { json_iterator = grpc_json_add_number_string_child( json, json_iterator, "keepAlivesSent", keepalives_sent_); } - if (streams_started_ != 0) { - 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); - } - } return top_level_json; } From f83ca91702f666b6e8fb07e5004817e60b390dd7 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 25 Sep 2018 10:52:31 -0700 Subject: [PATCH 15/39] Fix crash in grpc_errorFromStatusCode --- .../GRPCClient/private/NSError+GRPC.h | 2 +- .../GRPCClient/private/NSError+GRPC.m | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.h b/src/objective-c/GRPCClient/private/NSError+GRPC.h index a63e76ee4d0..fb05638b784 100644 --- a/src/objective-c/GRPCClient/private/NSError+GRPC.h +++ b/src/objective-c/GRPCClient/private/NSError+GRPC.h @@ -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 diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m index 199b2ebb6c3..c0f7e019a23 100644 --- a/src/objective-c/GRPCClient/private/NSError+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m @@ -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]; + 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:@{ - NSLocalizedDescriptionKey : message, - NSDebugDescriptionErrorKey : debugMessage - }]; + userInfo:userInfo]; } @end From bd1279ebf11960a29f726a56d3d62fc8f5c7ef79 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 25 Sep 2018 10:52:55 -0700 Subject: [PATCH 16/39] Add tests for NSError+GRPC --- src/objective-c/tests/Podfile | 1 + .../tests/Tests.xcodeproj/project.pbxproj | 257 ++++++++++++++++++ .../xcshareddata/xcschemes/UnitTests.xcscheme | 92 +++++++ src/objective-c/tests/UnitTests/Info.plist | 22 ++ src/objective-c/tests/UnitTests/UnitTests.m | 54 ++++ src/objective-c/tests/run_tests.sh | 10 + 6 files changed, 436 insertions(+) create mode 100644 src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme create mode 100644 src/objective-c/tests/UnitTests/Info.plist create mode 100644 src/objective-c/tests/UnitTests/UnitTests.m diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 507d251b481..5d2f1340daa 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -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 diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index 0e0e8babc0f..f0d81232635 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ""; }; 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 = ""; }; 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 = ""; }; 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 = ""; }; @@ -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 = ""; }; 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 = ""; }; 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 = ""; }; + 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 = ""; }; + 5E0282EA215AA697007AC99D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; @@ -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 = ""; }; 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 = ""; }; 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 = ""; }; + 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 = ""; }; 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 = ""; }; 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 = ""; }; 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 = ""; }; @@ -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 = ""; }; 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 = ""; }; + 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 = ""; }; 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 = ""; }; 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 = ""; }; 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 = ""; }; + 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 = ""; }; 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 = ""; @@ -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 = ""; }; + 5E0282E7215AA697007AC99D /* UnitTests */ = { + isa = PBXGroup; + children = ( + 5E0282E8215AA697007AC99D /* UnitTests.m */, + 5E0282EA215AA697007AC99D /* Info.plist */, + ); + path = UnitTests; + sourceTree = ""; + }; 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 = ""; @@ -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 = ( diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme new file mode 100644 index 00000000000..3af3555f48e --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/UnitTests.xcscheme @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/UnitTests/Info.plist b/src/objective-c/tests/UnitTests/Info.plist new file mode 100644 index 00000000000..6c40a6cd0c4 --- /dev/null +++ b/src/objective-c/tests/UnitTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/src/objective-c/tests/UnitTests/UnitTests.m b/src/objective-c/tests/UnitTests/UnitTests.m new file mode 100644 index 00000000000..002c4f86594 --- /dev/null +++ b/src/objective-c/tests/UnitTests/UnitTests.m @@ -0,0 +1,54 @@ +/* + * + * 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 + +#import + +#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 diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index 9dde07d55c8..f37c6cf9f62 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -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 From 10447318588a281d737af159a5dceec142135a43 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 25 Sep 2018 20:37:02 +0200 Subject: [PATCH 17/39] add DeserializationContext implementation note --- src/csharp/Grpc.Core/DeserializationContext.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/csharp/Grpc.Core/DeserializationContext.cs b/src/csharp/Grpc.Core/DeserializationContext.cs index 96de08f76d7..5b6372ef85d 100644 --- a/src/csharp/Grpc.Core/DeserializationContext.cs +++ b/src/csharp/Grpc.Core/DeserializationContext.cs @@ -37,6 +37,8 @@ namespace Grpc.Core /// 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 DeserializationContext implementations are free to assume so. /// /// byte array containing the entire payload. public abstract byte[] PayloadAsNewBuffer(); From 46a97e5f550f12c9b1dbef7657a0ff42694a0932 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 25 Sep 2018 16:48:14 -0400 Subject: [PATCH 18/39] Avoid extra branches in grpc_error_get_(str|int). Moving the check for "which" inside the for loop, will let the compiler unroll the loop and merge it with the branches grpc_error_is_especial. This is visible in the following godbolts: Before: https://godbolt.org/z/Nqujh1 After: https://godbolt.org/z/fA2PX- --- src/core/lib/iomgr/error.cc | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 13bc69ffb60..146a539027d 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -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) { From c2fd689bad731f30b2ab43a5613e164f7e44be5c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 25 Sep 2018 23:02:42 +0200 Subject: [PATCH 19/39] address comments --- src/csharp/Grpc.Core/Marshaller.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index 7f010dc4192..0af9aa586bf 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -57,6 +57,8 @@ namespace Grpc.Core { 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; } @@ -87,6 +89,7 @@ namespace Grpc.Core private byte[] EmulateSimpleSerializer(T msg) { // 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(); @@ -96,6 +99,7 @@ namespace Grpc.Core 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); } @@ -134,6 +138,7 @@ namespace Grpc.Core internal class EmulatedDeserializationContext : DeserializationContext { readonly byte[] payload; + bool alreadyCalledPayloadAsNewBuffer; public EmulatedDeserializationContext(byte[] payload) { @@ -144,6 +149,8 @@ namespace Grpc.Core public override byte[] PayloadAsNewBuffer() { + GrpcPreconditions.CheckState(!alreadyCalledPayloadAsNewBuffer); + alreadyCalledPayloadAsNewBuffer = true; return payload; } } From 87592fe9d9c54d6178966f40f4182e0bf6445380 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 14 Sep 2018 11:47:44 -0700 Subject: [PATCH 20/39] support custom logfile name in jobset.py --- tools/run_tests/python_utils/jobset.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py index 561f453da7b..35faed448d9 100755 --- a/tools/run_tests/python_utils/jobset.py +++ b/tools/run_tests/python_utils/jobset.py @@ -176,13 +176,15 @@ class JobSpec(object): timeout_retries=0, kill_handler=None, cpu_cost=1.0, - verbose_success=False): + verbose_success=False, + logfilename=None): """ Arguments: cmdline: a list of arguments to pass as the command line environ: a dictionary of environment variables to set in the child process kill_handler: a handler that will be called whenever job.kill() is invoked cpu_cost: number of cores per second this job needs + logfilename: use given file to store job's output, rather than using a temporary file """ if environ is None: environ = {} @@ -197,6 +199,10 @@ class JobSpec(object): self.kill_handler = kill_handler self.cpu_cost = cpu_cost self.verbose_success = verbose_success + self.logfilename = logfilename + if self.logfilename and self.flake_retries != 0 and self.timeout_retries != 0: + raise Exception( + 'Cannot use custom logfile when retries are enabled') def identity(self): return '%r %r' % (self.cmdline, self.environ) @@ -261,7 +267,15 @@ class Job(object): return self._spec def start(self): - self._tempfile = tempfile.TemporaryFile() + if self._spec.logfilename: + # make sure the log directory exists + logfile_dir = os.path.dirname( + os.path.abspath(self._spec.logfilename)) + if not os.path.exists(logfile_dir): + os.makedirs(logfile_dir) + self._tempfile = open(self._spec.logfilename, 'w+') + else: + self._tempfile = tempfile.TemporaryFile() env = dict(os.environ) env.update(self._spec.environ) env.update(self._add_env) From f952579464cf298bf9d0df3e5c3d4d74c666b903 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 14 Sep 2018 11:48:27 -0700 Subject: [PATCH 21/39] make logs available by run_tests_matrix.py suites --- tools/run_tests/run_tests_matrix.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index 1bbec94ee12..f8fcce45a4f 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -43,9 +43,6 @@ _OBJC_RUNTESTS_TIMEOUT = 90 * 60 # Number of jobs assigned to each run_tests.py instance _DEFAULT_INNER_JOBS = 2 -# report suffix is important for reports to get picked up by internal CI -_REPORT_SUFFIX = 'sponge_log.xml' - def _safe_report_name(name): """Reports with '+' in target name won't show correctly in ResultStore""" @@ -54,7 +51,14 @@ def _safe_report_name(name): def _report_filename(name): """Generates report file name with directory structure that leads to better presentation by internal CI""" - return '%s/%s' % (_safe_report_name(name), _REPORT_SUFFIX) + # 'sponge_log.xml' suffix must be there for results to get recognized by kokoro. + return '%s/%s' % (_safe_report_name(name), 'sponge_log.xml') + + +def _report_logfilename(name): + """Generates report file name with directory structure that leads to better presentation by internal CI""" + # 'sponge_log.log' suffix must be there for test log to get recognized by kokoro. + return '%s/%s' % (_safe_report_name(name), 'sponge_log.log') def _docker_jobspec(name, @@ -75,7 +79,8 @@ def _docker_jobspec(name, ] + runtests_args, environ=runtests_envs, shortname='run_tests_%s' % name, - timeout_seconds=timeout_seconds) + timeout_seconds=timeout_seconds, + logfilename=_report_logfilename(name)) return test_job @@ -102,7 +107,8 @@ def _workspace_jobspec(name, ] + runtests_args, environ=env, shortname='run_tests_%s' % name, - timeout_seconds=timeout_seconds) + timeout_seconds=timeout_seconds, + logfilename=_report_logfilename(name)) return test_job From ef1f8401e104ffc8a4d909985a83ea34a704b554 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 14 Sep 2018 12:02:45 -0700 Subject: [PATCH 22/39] update artifact cleanup script --- tools/internal_ci/helper_scripts/delete_nonartifacts.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/helper_scripts/delete_nonartifacts.sh b/tools/internal_ci/helper_scripts/delete_nonartifacts.sh index c7d6ba6d446..01e9427e1c7 100755 --- a/tools/internal_ci/helper_scripts/delete_nonartifacts.sh +++ b/tools/internal_ci/helper_scripts/delete_nonartifacts.sh @@ -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 {} + From 58f167abebdcf8276da52ac295712c1a808ffca7 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 14 Sep 2018 12:04:38 -0700 Subject: [PATCH 23/39] upload both sponge_log.xml and sponge_log.log --- tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg | 2 +- tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg | 2 +- tools/internal_ci/linux/grpc_basictests_multilang.cfg | 2 +- tools/internal_ci/linux/grpc_build_artifacts.cfg | 2 +- tools/internal_ci/linux/grpc_build_artifacts_extra.cfg | 2 +- tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg | 2 +- tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg | 2 +- tools/internal_ci/linux/grpc_build_packages.cfg | 2 +- tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg | 2 +- tools/internal_ci/linux/grpc_coverage.cfg | 2 +- tools/internal_ci/linux/grpc_distribtests.cfg | 2 +- tools/internal_ci/linux/grpc_distribtests_standalone.cfg | 2 +- tools/internal_ci/linux/grpc_full_performance_master.cfg | 2 +- tools/internal_ci/linux/grpc_full_performance_release.cfg | 2 +- tools/internal_ci/linux/grpc_interop_alts.cfg | 2 +- tools/internal_ci/linux/grpc_interop_matrix.cfg | 2 +- tools/internal_ci/linux/grpc_interop_tocloud.cfg | 2 +- tools/internal_ci/linux/grpc_interop_toprod.cfg | 2 +- tools/internal_ci/linux/grpc_portability.cfg | 2 +- tools/internal_ci/linux/grpc_portability_build_only.cfg | 2 +- tools/internal_ci/linux/grpc_publish_packages.cfg | 2 +- tools/internal_ci/linux/grpc_pull_request_sanity.cfg | 2 +- tools/internal_ci/linux/grpc_sanity.cfg | 2 +- .../linux/pull_request/grpc_basictests_c_cpp_dbg.cfg | 2 +- .../linux/pull_request/grpc_basictests_c_cpp_opt.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg | 2 +- .../internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg | 2 +- .../internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg | 2 +- .../linux/pull_request/grpc_basictests_multilang.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg | 2 +- .../internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_sanity.cfg | 2 +- tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg | 2 +- tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg | 2 +- tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg | 2 +- tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg | 2 +- tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg | 2 +- tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg | 2 +- tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg | 2 +- tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg | 2 +- tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg | 2 +- tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg | 2 +- tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg | 2 +- .../internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg | 2 +- .../internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg | 2 +- tools/internal_ci/macos/grpc_basictests_dbg.cfg | 2 +- tools/internal_ci/macos/grpc_basictests_opt.cfg | 2 +- tools/internal_ci/macos/grpc_build_artifacts.cfg | 2 +- tools/internal_ci/macos/grpc_distribtests.cfg | 2 +- tools/internal_ci/macos/grpc_interop.cfg | 2 +- tools/internal_ci/macos/grpc_interop_toprod.cfg | 2 +- tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg | 2 +- tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg | 2 +- tools/internal_ci/macos/pull_request/grpc_interop.cfg | 2 +- tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg | 2 +- tools/internal_ci/windows/grpc_basictests.cfg | 2 +- tools/internal_ci/windows/grpc_basictests_dbg.cfg | 2 +- tools/internal_ci/windows/grpc_basictests_opt.cfg | 2 +- tools/internal_ci/windows/grpc_build_artifacts.cfg | 2 +- tools/internal_ci/windows/grpc_build_packages.cfg | 2 +- tools/internal_ci/windows/grpc_distribtests.cfg | 2 +- tools/internal_ci/windows/grpc_distribtests_standalone.cfg | 2 +- tools/internal_ci/windows/grpc_portability.cfg | 2 +- tools/internal_ci/windows/grpc_portability_build_only.cfg | 2 +- tools/internal_ci/windows/pull_request/grpc_basictests.cfg | 2 +- tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg | 2 +- tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg | 2 +- tools/internal_ci/windows/pull_request/grpc_portability.cfg | 2 +- 71 files changed, 71 insertions(+), 71 deletions(-) diff --git a/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg b/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg index 4a0badf43bc..07f7f0c6591 100644 --- a/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg +++ b/tools/internal_ci/linux/grpc_basictests_c_cpp_dbg.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg b/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg index a2cfe021e16..8f2813febf8 100644 --- a/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg +++ b/tools/internal_ci/linux/grpc_basictests_c_cpp_opt.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_basictests_multilang.cfg b/tools/internal_ci/linux/grpc_basictests_multilang.cfg index 4433d14cd72..f8a5a4aea51 100644 --- a/tools/internal_ci/linux/grpc_basictests_multilang.cfg +++ b/tools/internal_ci/linux/grpc_basictests_multilang.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_build_artifacts.cfg b/tools/internal_ci/linux/grpc_build_artifacts.cfg index 88fc6b7b358..1e04a1e7880 100644 --- a/tools/internal_ci/linux/grpc_build_artifacts.cfg +++ b/tools/internal_ci/linux/grpc_build_artifacts.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg b/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg index 619e3ea3a97..2737e2f3453 100644 --- a/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg +++ b/tools/internal_ci/linux/grpc_build_artifacts_extra.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg b/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg index 619e3ea3a97..2737e2f3453 100644 --- a/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg +++ b/tools/internal_ci/linux/grpc_build_artifacts_extra_release.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg b/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg index 11c211fd2b4..9a430db0f9a 100644 --- a/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg +++ b/tools/internal_ci/linux/grpc_build_boringssl_at_head.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_build_packages.cfg b/tools/internal_ci/linux/grpc_build_packages.cfg index 6a4a163dfca..23a676cf727 100644 --- a/tools/internal_ci/linux/grpc_build_packages.cfg +++ b/tools/internal_ci/linux/grpc_build_packages.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg b/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg index 2f08e15e638..aef6a7a1dcb 100644 --- a/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg +++ b/tools/internal_ci/linux/grpc_build_protobuf_at_head.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_coverage.cfg b/tools/internal_ci/linux/grpc_coverage.cfg index 794a51d3f13..6eb37b7dec3 100644 --- a/tools/internal_ci/linux/grpc_coverage.cfg +++ b/tools/internal_ci/linux/grpc_coverage.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_distribtests.cfg b/tools/internal_ci/linux/grpc_distribtests.cfg index 0f1d79355a6..848d5713336 100644 --- a/tools/internal_ci/linux/grpc_distribtests.cfg +++ b/tools/internal_ci/linux/grpc_distribtests.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_distribtests_standalone.cfg b/tools/internal_ci/linux/grpc_distribtests_standalone.cfg index bc6c8e8f805..734bdfd78a7 100644 --- a/tools/internal_ci/linux/grpc_distribtests_standalone.cfg +++ b/tools/internal_ci/linux/grpc_distribtests_standalone.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_full_performance_master.cfg b/tools/internal_ci/linux/grpc_full_performance_master.cfg index 8852130a139..8ad93ee0529 100644 --- a/tools/internal_ci/linux/grpc_full_performance_master.cfg +++ b/tools/internal_ci/linux/grpc_full_performance_master.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_full_performance_release.cfg b/tools/internal_ci/linux/grpc_full_performance_release.cfg index e9a4bcdcaf3..11a95e889fa 100644 --- a/tools/internal_ci/linux/grpc_full_performance_release.cfg +++ b/tools/internal_ci/linux/grpc_full_performance_release.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_interop_alts.cfg b/tools/internal_ci/linux/grpc_interop_alts.cfg index bda76faf440..4684aba96bf 100644 --- a/tools/internal_ci/linux/grpc_interop_alts.cfg +++ b/tools/internal_ci/linux/grpc_interop_alts.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_interop_matrix.cfg b/tools/internal_ci/linux/grpc_interop_matrix.cfg index ae59e930f77..696a55c0df2 100644 --- a/tools/internal_ci/linux/grpc_interop_matrix.cfg +++ b/tools/internal_ci/linux/grpc_interop_matrix.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/grpc_interop_tocloud.cfg index 81f2fe9dec6..9b35adcece2 100644 --- a/tools/internal_ci/linux/grpc_interop_tocloud.cfg +++ b/tools/internal_ci/linux/grpc_interop_tocloud.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_interop_toprod.cfg b/tools/internal_ci/linux/grpc_interop_toprod.cfg index 8dfc529947c..de4db81e6ba 100644 --- a/tools/internal_ci/linux/grpc_interop_toprod.cfg +++ b/tools/internal_ci/linux/grpc_interop_toprod.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_portability.cfg b/tools/internal_ci/linux/grpc_portability.cfg index 76e50284777..f417f24bb1c 100644 --- a/tools/internal_ci/linux/grpc_portability.cfg +++ b/tools/internal_ci/linux/grpc_portability.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_portability_build_only.cfg b/tools/internal_ci/linux/grpc_portability_build_only.cfg index 4acd9353fb4..fab9dde3e58 100644 --- a/tools/internal_ci/linux/grpc_portability_build_only.cfg +++ b/tools/internal_ci/linux/grpc_portability_build_only.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_publish_packages.cfg b/tools/internal_ci/linux/grpc_publish_packages.cfg index 82d571d642c..dc9fe7d0a7a 100644 --- a/tools/internal_ci/linux/grpc_publish_packages.cfg +++ b/tools/internal_ci/linux/grpc_publish_packages.cfg @@ -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/**" } diff --git a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg index b20d2ffba8e..704d5c6cbc9 100644 --- a/tools/internal_ci/linux/grpc_pull_request_sanity.cfg +++ b/tools/internal_ci/linux/grpc_pull_request_sanity.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/grpc_sanity.cfg b/tools/internal_ci/linux/grpc_sanity.cfg index 9f65918e23a..341471bbb58 100644 --- a/tools/internal_ci/linux/grpc_sanity.cfg +++ b/tools/internal_ci/linux/grpc_sanity.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg index 8124f5c1b3f..8a67d28ce4c 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_dbg.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg index ecedc73e44d..a681978b6e2 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_cpp_opt.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg index 577cb28ae5f..249ecc99ce2 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_dbg.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg index 9e0b724b2e1..665d7f3d2c9 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_c_opt.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg index 0fda74cf44e..163274d4dc3 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_dbg.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg index 199a8905d94..b65cd3e05c2 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_cpp_opt.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg b/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg index f7e8d8ad33c..59f38f0d1b2 100644 --- a/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_basictests_multilang.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg index c1253b30f72..e91a6128788 100644 --- a/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg index cb18e8e8682..b1eb5756054 100644 --- a/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_interop_tocloud.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg index d14c79a1f6d..7321effc123 100644 --- a/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg b/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg index 9269c345f0a..47301d61415 100644 --- a/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_microbenchmark_diff.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_sanity.cfg b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg index 0f83299aaba..276c34f0cfe 100644 --- a/tools/internal_ci/linux/pull_request/grpc_sanity.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg b/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg index e86b3ab4758..78358eac28e 100644 --- a/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg +++ b/tools/internal_ci/linux/pull_request/grpc_trickle_diff.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg index 06a4372ce24..d6d70677ddf 100644 --- a/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg +++ b/tools/internal_ci/linux/sanitizer/grpc_c_asan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg index f875327c1b8..7b22c6afef5 100644 --- a/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg +++ b/tools/internal_ci/linux/sanitizer/grpc_c_msan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg index 6658a804d89..6c9dd6ef8dc 100644 --- a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg +++ b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg index 957a91ef2b4..8700c74c8d9 100644 --- a/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg +++ b/tools/internal_ci/linux/sanitizer/grpc_c_ubsan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg index dbbfce90cb5..02162d860b0 100644 --- a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg +++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg index fb0cefa1606..95582184ed1 100644 --- a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg +++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg index 1daf7a514e2..d444596a81e 100644 --- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg +++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_asan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg index a8503b7bcbe..3891cc37e8e 100644 --- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg +++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_msan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg index 12af4581eba..91ce1627afc 100644 --- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg +++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_tsan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg index 0d3803bf236..fcdc2de37bb 100644 --- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg +++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_c_ubsan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg index 557561810bd..de2a74051b6 100644 --- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg +++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_asan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg index cb15ca34fd7..51c291f7dff 100644 --- a/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg +++ b/tools/internal_ci/linux/sanitizer/pull_request/grpc_cpp_tsan.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/grpc_basictests_dbg.cfg b/tools/internal_ci/macos/grpc_basictests_dbg.cfg index 53bda1ff0a6..e6f9c7ec875 100644 --- a/tools/internal_ci/macos/grpc_basictests_dbg.cfg +++ b/tools/internal_ci/macos/grpc_basictests_dbg.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/grpc_basictests_opt.cfg b/tools/internal_ci/macos/grpc_basictests_opt.cfg index d359eb601a0..f2a83fe95a6 100644 --- a/tools/internal_ci/macos/grpc_basictests_opt.cfg +++ b/tools/internal_ci/macos/grpc_basictests_opt.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/grpc_build_artifacts.cfg b/tools/internal_ci/macos/grpc_build_artifacts.cfg index 4da61faed36..c73cf4359f9 100644 --- a/tools/internal_ci/macos/grpc_build_artifacts.cfg +++ b/tools/internal_ci/macos/grpc_build_artifacts.cfg @@ -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/**" } diff --git a/tools/internal_ci/macos/grpc_distribtests.cfg b/tools/internal_ci/macos/grpc_distribtests.cfg index ae88f39b903..156ec6fe33f 100644 --- a/tools/internal_ci/macos/grpc_distribtests.cfg +++ b/tools/internal_ci/macos/grpc_distribtests.cfg @@ -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/**" } diff --git a/tools/internal_ci/macos/grpc_interop.cfg b/tools/internal_ci/macos/grpc_interop.cfg index b4b1b15cb40..434ecd19c4d 100644 --- a/tools/internal_ci/macos/grpc_interop.cfg +++ b/tools/internal_ci/macos/grpc_interop.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/grpc_interop_toprod.cfg b/tools/internal_ci/macos/grpc_interop_toprod.cfg index c92c397daa7..2cfc8a2d6de 100644 --- a/tools/internal_ci/macos/grpc_interop_toprod.cfg +++ b/tools/internal_ci/macos/grpc_interop_toprod.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg b/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg index 30c01d3e2f3..c759397b781 100644 --- a/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg +++ b/tools/internal_ci/macos/pull_request/grpc_basictests_dbg.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg b/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg index b63ee713bc4..4d68341405b 100644 --- a/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg +++ b/tools/internal_ci/macos/pull_request/grpc_basictests_opt.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/pull_request/grpc_interop.cfg b/tools/internal_ci/macos/pull_request/grpc_interop.cfg index b4b1b15cb40..434ecd19c4d 100644 --- a/tools/internal_ci/macos/pull_request/grpc_interop.cfg +++ b/tools/internal_ci/macos/pull_request/grpc_interop.cfg @@ -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/**" } } diff --git a/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg b/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg index 8942bc7ba71..fb215bdf994 100644 --- a/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg +++ b/tools/internal_ci/macos/pull_request/grpc_ios_binary_size.cfg @@ -20,7 +20,7 @@ timeout_mins: 60 gfile_resources: "/bigstore/grpc-testing-secrets/github_credentials/oauth_token.txt" action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/grpc_basictests.cfg b/tools/internal_ci/windows/grpc_basictests.cfg index 8e644e4c5e4..fcf5237bf3f 100644 --- a/tools/internal_ci/windows/grpc_basictests.cfg +++ b/tools/internal_ci/windows/grpc_basictests.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/grpc_basictests_dbg.cfg b/tools/internal_ci/windows/grpc_basictests_dbg.cfg index 28d53cdc7bd..4e5e7b65451 100644 --- a/tools/internal_ci/windows/grpc_basictests_dbg.cfg +++ b/tools/internal_ci/windows/grpc_basictests_dbg.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/grpc_basictests_opt.cfg b/tools/internal_ci/windows/grpc_basictests_opt.cfg index 4b7a9659776..f5db6a9897a 100644 --- a/tools/internal_ci/windows/grpc_basictests_opt.cfg +++ b/tools/internal_ci/windows/grpc_basictests_opt.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/grpc_build_artifacts.cfg b/tools/internal_ci/windows/grpc_build_artifacts.cfg index 38b0abd519b..f45cfda1215 100644 --- a/tools/internal_ci/windows/grpc_build_artifacts.cfg +++ b/tools/internal_ci/windows/grpc_build_artifacts.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_build_artifacts.bat" timeout_mins: 120 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" regex: "github/grpc/artifacts/**" } diff --git a/tools/internal_ci/windows/grpc_build_packages.cfg b/tools/internal_ci/windows/grpc_build_packages.cfg index 65a8b1eef33..b351bbb11b3 100644 --- a/tools/internal_ci/windows/grpc_build_packages.cfg +++ b/tools/internal_ci/windows/grpc_build_packages.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_build_packages.bat" timeout_mins: 120 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" regex: "github/grpc/artifacts/**" } diff --git a/tools/internal_ci/windows/grpc_distribtests.cfg b/tools/internal_ci/windows/grpc_distribtests.cfg index 1766e601e51..e12d4bf98dc 100644 --- a/tools/internal_ci/windows/grpc_distribtests.cfg +++ b/tools/internal_ci/windows/grpc_distribtests.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_distribtests.bat" timeout_mins: 120 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" regex: "github/grpc/artifacts/**" } diff --git a/tools/internal_ci/windows/grpc_distribtests_standalone.cfg b/tools/internal_ci/windows/grpc_distribtests_standalone.cfg index 33a50fdc456..7f32ba4c704 100644 --- a/tools/internal_ci/windows/grpc_distribtests_standalone.cfg +++ b/tools/internal_ci/windows/grpc_distribtests_standalone.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_distribtests_standalone.bat" timeout_mins: 120 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" regex: "github/grpc/artifacts/**" } diff --git a/tools/internal_ci/windows/grpc_portability.cfg b/tools/internal_ci/windows/grpc_portability.cfg index 94e71753efd..aa86c06632a 100644 --- a/tools/internal_ci/windows/grpc_portability.cfg +++ b/tools/internal_ci/windows/grpc_portability.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/grpc_portability_build_only.cfg b/tools/internal_ci/windows/grpc_portability_build_only.cfg index 3bc27f1f24a..3dace627eb2 100644 --- a/tools/internal_ci/windows/grpc_portability_build_only.cfg +++ b/tools/internal_ci/windows/grpc_portability_build_only.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/pull_request/grpc_basictests.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests.cfg index 91777cd7cbc..a8e6f0675bd 100644 --- a/tools/internal_ci/windows/pull_request/grpc_basictests.cfg +++ b/tools/internal_ci/windows/pull_request/grpc_basictests.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg index 81a1e9d3c8f..ce957232fdb 100644 --- a/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg +++ b/tools/internal_ci/windows/pull_request/grpc_basictests_dbg.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg b/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg index 3bb6510ca77..7d2abbfb19a 100644 --- a/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg +++ b/tools/internal_ci/windows/pull_request/grpc_basictests_opt.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } diff --git a/tools/internal_ci/windows/pull_request/grpc_portability.cfg b/tools/internal_ci/windows/pull_request/grpc_portability.cfg index 2bda4876298..6f332416fe7 100644 --- a/tools/internal_ci/windows/pull_request/grpc_portability.cfg +++ b/tools/internal_ci/windows/pull_request/grpc_portability.cfg @@ -19,7 +19,7 @@ build_file: "grpc/tools/internal_ci/windows/grpc_run_tests_matrix.bat" timeout_mins: 240 action { define_artifacts { - regex: "**/*sponge_log.xml" + regex: "**/*sponge_log.*" regex: "github/grpc/reports/**" } } From 2488dff74b808faf2e2a46e0f6b3579499b9983f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 25 Sep 2018 23:36:19 +0200 Subject: [PATCH 24/39] address comments --- tools/run_tests/python_utils/jobset.py | 1 + tools/run_tests/run_tests_matrix.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py index 35faed448d9..a426c6ef9c0 100755 --- a/tools/run_tests/python_utils/jobset.py +++ b/tools/run_tests/python_utils/jobset.py @@ -201,6 +201,7 @@ class JobSpec(object): self.verbose_success = verbose_success self.logfilename = logfilename if self.logfilename and self.flake_retries != 0 and self.timeout_retries != 0: + # Forbidden to avoid overwriting the test log when retrying. raise Exception( 'Cannot use custom logfile when retries are enabled') diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index f8fcce45a4f..00fc68ad171 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -56,8 +56,9 @@ def _report_filename(name): def _report_logfilename(name): - """Generates report file name with directory structure that leads to better presentation by internal CI""" - # 'sponge_log.log' suffix must be there for test log to get recognized by kokoro. + """Generates log file name that corresponds to name generated by _report_filename""" + # 'sponge_log.log' suffix must be there for log to get recognized as "target log" + # for the corresponding 'sponge_log.xml' report. return '%s/%s' % (_safe_report_name(name), 'sponge_log.log') From b772e67c570562222d043d0955c7cc428d7f30aa Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 25 Sep 2018 14:44:04 -0700 Subject: [PATCH 25/39] clang_format --- .../GRPCClient/private/NSError+GRPC.m | 10 +++++----- src/objective-c/tests/UnitTests/UnitTests.m | 20 +++++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m index c0f7e019a23..3eefed88d63 100644 --- a/src/objective-c/GRPCClient/private/NSError+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m @@ -31,13 +31,13 @@ NSString *const kGRPCErrorDomain = @"io.grpc"; } NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; if (details) { - userInfo[NSLocalizedDescriptionKey] = [NSString stringWithCString:details encoding:NSUTF8StringEncoding]; + userInfo[NSLocalizedDescriptionKey] = + [NSString stringWithCString:details encoding:NSUTF8StringEncoding]; } if (errorString) { - userInfo[NSDebugDescriptionErrorKey] = [NSString stringWithCString:errorString encoding:NSUTF8StringEncoding]; + userInfo[NSDebugDescriptionErrorKey] = + [NSString stringWithCString:errorString encoding:NSUTF8StringEncoding]; } - return [NSError errorWithDomain:kGRPCErrorDomain - code:statusCode - userInfo:userInfo]; + return [NSError errorWithDomain:kGRPCErrorDomain code:statusCode userInfo:userInfo]; } @end diff --git a/src/objective-c/tests/UnitTests/UnitTests.m b/src/objective-c/tests/UnitTests/UnitTests.m index 002c4f86594..57e686d1b67 100644 --- a/src/objective-c/tests/UnitTests/UnitTests.m +++ b/src/objective-c/tests/UnitTests/UnitTests.m @@ -32,18 +32,26 @@ 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]; + 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]); + 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]); + XCTAssertEqualObjects(error3.userInfo[NSLocalizedDescriptionKey], + [NSString stringWithUTF8String:kDetails]); XCTAssertNil(error3.userInfo[NSDebugDescriptionErrorKey]); XCTAssertEqual(error4.code, 14); XCTAssertEqualObjects(error4.domain, @"io.grpc"); From c1a1d66864a637f06b409b1768bc05a982b28949 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 25 Sep 2018 17:50:45 -0400 Subject: [PATCH 26/39] Avoid allocating temporary strings in Channel::CreateCall(). Add `SliceFromArray()` which takes a `char*` instead of `const string&`, to save string allocations for copying from a `char *`. Use the new API to eliminate two string allocations and copies per call for method and host names. release-note: no --- include/grpcpp/impl/codegen/slice.h | 4 ++++ src/cpp/client/channel_cc.cc | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/grpcpp/impl/codegen/slice.h b/include/grpcpp/impl/codegen/slice.h index 8966559dc85..9cdca3ab3c9 100644 --- a/include/grpcpp/impl/codegen/slice.h +++ b/include/grpcpp/impl/codegen/slice.h @@ -138,6 +138,10 @@ inline grpc_slice SliceFromCopiedString(const grpc::string& str) { str.length()); } +inline grpc_slice SliceFromArray(const char* arr, size_t len) { + return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len); +} + } // namespace grpc #endif // GRPCPP_IMPL_CODEGEN_SLICE_H diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index c59059f0450..5d1a9f4b961 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -116,10 +117,11 @@ internal::Call Channel::CreateCall(const internal::RpcMethod& method, } else if (!host_.empty()) { host_str = host_.c_str(); } - 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 = SliceFromArray(host_str, strlen(host_str)); } c_call = grpc_channel_create_call( c_channel_, context->propagate_from_call_, From a68ebc7cfde360fc904b99017702e8eedc251277 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 25 Sep 2018 17:59:46 -0400 Subject: [PATCH 27/39] Increase the maximum number of timer shards to 32. Commit 82f9886e accidentally sets the maximum number of timer shards 1, from previously 32. We probably want to increase the max shards further. --- src/core/lib/iomgr/timer_generic.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc index 008d37119a9..aeadd10b688 100644 --- a/src/core/lib/iomgr/timer_generic.cc +++ b/src/core/lib/iomgr/timer_generic.cc @@ -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_MIN(32, 2 * gpr_cpu_num_cores()); g_shards = static_cast(gpr_zalloc(g_num_shards * sizeof(*g_shards))); g_shard_queue = static_cast( From d8056c5906eb732d8d1f2419f29472d4094d16d3 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 26 Sep 2018 00:11:51 +0200 Subject: [PATCH 28/39] rename _tempfile -> _logfile --- tools/run_tests/python_utils/jobset.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py index a426c6ef9c0..b732e1e03e0 100755 --- a/tools/run_tests/python_utils/jobset.py +++ b/tools/run_tests/python_utils/jobset.py @@ -274,9 +274,9 @@ class Job(object): os.path.abspath(self._spec.logfilename)) if not os.path.exists(logfile_dir): os.makedirs(logfile_dir) - self._tempfile = open(self._spec.logfilename, 'w+') + self._logfile = open(self._spec.logfilename, 'w+') else: - self._tempfile = tempfile.TemporaryFile() + self._logfile = tempfile.TemporaryFile() env = dict(os.environ) env.update(self._spec.environ) env.update(self._add_env) @@ -292,7 +292,7 @@ class Job(object): measure_cpu_costs = False try_start = lambda: subprocess.Popen(args=cmdline, stderr=subprocess.STDOUT, - stdout=self._tempfile, + stdout=self._logfile, cwd=self._spec.cwd, shell=self._spec.shell, env=env) @@ -315,7 +315,7 @@ class Job(object): """Poll current state of the job. Prints messages at completion.""" def stdout(self=self): - stdout = read_from_start(self._tempfile) + stdout = read_from_start(self._logfile) self.result.message = stdout[-_MAX_RESULT_SIZE:] return stdout From 8442cc213b2316272764b6a89e5ded5929e35a78 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 25 Sep 2018 18:30:22 -0400 Subject: [PATCH 29/39] Fix styling issue added in c1a1d668 --- include/grpcpp/impl/codegen/slice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grpcpp/impl/codegen/slice.h b/include/grpcpp/impl/codegen/slice.h index 9cdca3ab3c9..75c093d1da0 100644 --- a/include/grpcpp/impl/codegen/slice.h +++ b/include/grpcpp/impl/codegen/slice.h @@ -139,7 +139,7 @@ inline grpc_slice SliceFromCopiedString(const grpc::string& str) { } inline grpc_slice SliceFromArray(const char* arr, size_t len) { - return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len); + return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len); } } // namespace grpc From 369cfe118cbfda61c3fc205a18d1b1924d853700 Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 25 Sep 2018 21:59:15 -0400 Subject: [PATCH 30/39] Use SliceFromCopiedString() for host name. This is to address Yang's review comment. --- src/cpp/client/channel_cc.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 5d1a9f4b961..510ae73478e 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -111,17 +111,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; + const string* host_str = nullptr; if (!context->authority().empty()) { - host_str = context->authority_.c_str(); + host_str = &context->authority_; } else if (!host_.empty()) { - host_str = host_.c_str(); + host_str = &host_; } grpc_slice method_slice = SliceFromArray(method.name(), strlen(method.name())); grpc_slice host_slice; if (host_str != nullptr) { - host_slice = SliceFromArray(host_str, strlen(host_str)); + host_slice = SliceFromCopiedString(*host_str); } c_call = grpc_channel_create_call( c_channel_, context->propagate_from_call_, From 0535f659f73e6f0073782691b2afa03ca6e6970f Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Tue, 25 Sep 2018 22:02:03 -0400 Subject: [PATCH 31/39] Set a minimum bound of 1 for the number of timer shards. --- src/core/lib/iomgr/timer_generic.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc index aeadd10b688..aba5539199d 100644 --- a/src/core/lib/iomgr/timer_generic.cc +++ b/src/core/lib/iomgr/timer_generic.cc @@ -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(32, 2 * gpr_cpu_num_cores()); + g_num_shards = GPR_CLAMP(2 * gpr_cpu_num_cores(), 1, 32); g_shards = static_cast(gpr_zalloc(g_num_shards * sizeof(*g_shards))); g_shard_queue = static_cast( From 18e8a30a518315fca22c687138d86de36e8cb754 Mon Sep 17 00:00:00 2001 From: Vijay Pai Date: Wed, 26 Sep 2018 06:49:14 -0700 Subject: [PATCH 32/39] Empty implementation of grpc_use_signal since not actually needed anymore --- src/core/lib/iomgr/ev_posix.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc index 8a7dc7b004a..764fb08142a 100644 --- a/src/core/lib/iomgr/ev_posix.cc +++ b/src/core/lib/iomgr/ev_posix.cc @@ -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 From 31d3134d5b525e2483d023d5e8efe461b7eab171 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Wed, 26 Sep 2018 12:36:11 -0700 Subject: [PATCH 33/39] Cq documentation --- doc/core/grpc-cq.md | 64 +++++++++++++++++++++++++++++++++++++++++ doc/images/grpc-cq.png | Bin 0 -> 41659 bytes 2 files changed, 64 insertions(+) create mode 100644 doc/core/grpc-cq.md create mode 100644 doc/images/grpc-cq.png diff --git a/doc/core/grpc-cq.md b/doc/core/grpc-cq.md new file mode 100644 index 00000000000..b485c354566 --- /dev/null +++ b/doc/core/grpc-cq.md @@ -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) +} + +``` + diff --git a/doc/images/grpc-cq.png b/doc/images/grpc-cq.png new file mode 100644 index 0000000000000000000000000000000000000000..2d9e0958623c8aa4080f6c799b5bc1d2cf0d5923 GIT binary patch literal 41659 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 literal 0 HcmV?d00001 From f13a74312672aaf7c72e984f59dbd351dcda4e8a Mon Sep 17 00:00:00 2001 From: ncteisen Date: Wed, 26 Sep 2018 17:19:39 -0700 Subject: [PATCH 34/39] Implement child socket support --- .../client_channel/client_channel_channelz.cc | 19 +++++++++++++++++++ .../client_channel/client_channel_channelz.h | 8 +++----- .../ext/filters/client_channel/subchannel.cc | 10 ++++++++++ .../ext/filters/client_channel/subchannel.h | 3 +++ .../chttp2/transport/chttp2_transport.cc | 12 +++++++++++- .../cronet/transport/cronet_transport.cc | 6 +++++- .../ext/transport/inproc/inproc_transport.cc | 5 ++++- src/core/lib/transport/transport.cc | 5 +++++ src/core/lib/transport/transport.h | 10 ++++++++++ src/core/lib/transport/transport_impl.h | 3 +++ 10 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 7e8f59bcd33..4fedcbcbb6c 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -136,6 +136,23 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) { false); } +void SubchannelNode::PopulateChildSockets(grpc_json* json) { + ChildRefsList child_sockets; + grpc_json* json_iterator = nullptr; + grpc_subchannel_populate_child_sockets(subchannel_, &child_sockets); + if (!child_sockets.empty()) { + grpc_json* array_parent = grpc_json_create_child( + nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); + for (size_t i = 0; i < child_sockets.size(); ++i) { + 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", + child_sockets[i]); + } + } +} + grpc_json* SubchannelNode::RenderJson() { grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; @@ -166,6 +183,8 @@ grpc_json* SubchannelNode::RenderJson() { } // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); + json = top_level_json; + PopulateChildSockets(json); return top_level_json; } diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 8ce331e529d..a63df00f9f2 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -31,11 +31,6 @@ typedef struct grpc_subchannel grpc_subchannel; namespace grpc_core { -// TODO(ncteisen), this only contains the uuids of the children for now, -// since that is all that is strictly needed. In a future enhancement we will -// add human readable names as in the channelz.proto -typedef InlinedVector ChildRefsList; - namespace channelz { // Subtype of ChannelNode that overrides and provides client_channel specific @@ -76,6 +71,9 @@ class SubchannelNode : public BaseNode { grpc_json* RenderJson() override; + // helper to populate the socket(s) that this subchannel owns. + void PopulateChildSockets(grpc_json* json); + // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { trace_.AddTraceEvent(severity, data); diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 57d0b3759f2..29aeb06e7bc 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -97,6 +97,8 @@ struct grpc_subchannel { /** set during connection */ grpc_connect_out_args connecting_result; + grpc_transport* transport; + /** callback for connection finishing */ grpc_closure on_connected; @@ -411,6 +413,13 @@ grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( return subchannel->channelz_subchannel.get(); } +void grpc_subchannel_populate_child_sockets( + grpc_subchannel* subchannel, grpc_core::ChildRefsList* child_sockets) { + if (subchannel->transport != nullptr) { + grpc_transport_populate_sockets(subchannel->transport, child_sockets); + } +} + static void continue_connect_locked(grpc_subchannel* c) { grpc_connect_in_args args; args.interested_parties = c->pollset_set; @@ -621,6 +630,7 @@ static bool publish_transport_locked(grpc_subchannel* c) { GRPC_ERROR_UNREF(error); return false; } + c->transport = c->connecting_result.transport; memset(&c->connecting_result, 0, sizeof(c->connecting_result)); /* initialize state watcher */ diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 84febb52040..2cf5067fc26 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -126,6 +126,9 @@ void grpc_subchannel_call_unref( grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( grpc_subchannel* subchannel); +void grpc_subchannel_populate_child_sockets( + grpc_subchannel* subchannel, grpc_core::ChildRefsList* child_sockets); + /** 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(). */ diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index d3232f4d268..202da652de7 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -3157,6 +3157,15 @@ static grpc_endpoint* chttp2_get_endpoint(grpc_transport* t) { return (reinterpret_cast(t))->ep; } +static void populate_sockets(grpc_transport* transport, + grpc_core::ChildRefsList* child_sockets) { + grpc_chttp2_transport* t = + reinterpret_cast(transport); + if (t->channelz_socket != nullptr) { + child_sockets->push_back(t->channelz_socket->uuid()); + } +} + static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), "chttp2", init_stream, @@ -3166,7 +3175,8 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), perform_transport_op, destroy_stream, destroy_transport, - chttp2_get_endpoint}; + chttp2_get_endpoint, + populate_sockets}; static const grpc_transport_vtable* get_vtable(void) { return &vtable; } diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 81e2634e3a7..f3826a78de0 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -1439,6 +1439,9 @@ static grpc_endpoint* get_endpoint(grpc_transport* gt) { return nullptr; } static void perform_op(grpc_transport* gt, grpc_transport_op* op) {} +static void populate_sockets(grpc_transport* t, + grpc_core::ChildRefsList* child_sockets) {} + static const grpc_transport_vtable grpc_cronet_vtable = { sizeof(stream_obj), "cronet_http", @@ -1449,7 +1452,8 @@ static const grpc_transport_vtable grpc_cronet_vtable = { perform_op, destroy_stream, destroy_transport, - get_endpoint}; + get_endpoint, + populate_sockets}; grpc_transport* grpc_create_cronet_transport(void* engine, const char* target, const grpc_channel_args* args, diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc index b0ca7f8207e..2deaacb2e06 100644 --- a/src/core/ext/transport/inproc/inproc_transport.cc +++ b/src/core/ext/transport/inproc/inproc_transport.cc @@ -1170,6 +1170,9 @@ static void set_pollset_set(grpc_transport* gt, grpc_stream* gs, static grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; } +static void populate_sockets(grpc_transport* t, + grpc_core::ChildRefsList* child_sockets) {} + /******************************************************************************* * GLOBAL INIT AND DESTROY */ @@ -1194,7 +1197,7 @@ static const grpc_transport_vtable inproc_vtable = { sizeof(inproc_stream), "inproc", init_stream, set_pollset, set_pollset_set, perform_stream_op, perform_transport_op, destroy_stream, destroy_transport, - get_endpoint}; + get_endpoint, populate_sockets}; /******************************************************************************* * Main inproc transport functions diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index cbdb77c8441..2e7c40dda45 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -199,6 +199,11 @@ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport) { return transport->vtable->get_endpoint(transport); } +void grpc_transport_populate_sockets(grpc_transport* transport, + grpc_core::ChildRefsList* child_sockets) { + return transport->vtable->populate_sockets(transport, child_sockets); +} + // This comment should be sung to the tune of // "Supercalifragilisticexpialidocious": // diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 9e784635c69..93445ebd051 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -39,6 +39,13 @@ #define GRPC_PROTOCOL_VERSION_MIN_MAJOR 2 #define GRPC_PROTOCOL_VERSION_MIN_MINOR 1 +namespace grpc_core { +// TODO(ncteisen), this only contains the uuids of the children for now, +// since that is all that is strictly needed. In a future enhancement we will +// add human readable names as in the channelz.proto +typedef InlinedVector ChildRefsList; +} // namespace grpc_core + /* forward declarations */ typedef struct grpc_transport grpc_transport; @@ -366,6 +373,9 @@ void grpc_transport_destroy(grpc_transport* transport); /* Get the endpoint used by \a transport */ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport); +void grpc_transport_populate_sockets(grpc_transport* transport, + grpc_core::ChildRefsList* child_sockets); + /* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to \a on_consumed and then delete the returned transport op */ grpc_transport_op* grpc_make_transport_op(grpc_closure* on_consumed); diff --git a/src/core/lib/transport/transport_impl.h b/src/core/lib/transport/transport_impl.h index ba5e05df0af..7ae59a1d17f 100644 --- a/src/core/lib/transport/transport_impl.h +++ b/src/core/lib/transport/transport_impl.h @@ -60,6 +60,9 @@ typedef struct grpc_transport_vtable { /* implementation of grpc_transport_get_endpoint */ grpc_endpoint* (*get_endpoint)(grpc_transport* self); + + void (*populate_sockets)(grpc_transport* self, + grpc_core::ChildRefsList* child_sockets); } grpc_transport_vtable; /* an instance of a grpc transport */ From 4cc16f951c0909196a9ed62774adcbbaf9cc88c1 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 27 Sep 2018 09:45:59 -0500 Subject: [PATCH 35/39] Simplifiy transport querying function --- .../client_channel/client_channel_channelz.cc | 29 +++++++------------ .../client_channel/client_channel_channelz.h | 5 ++++ .../ext/filters/client_channel/subchannel.cc | 16 +++++----- .../ext/filters/client_channel/subchannel.h | 4 +-- .../chttp2/transport/chttp2_transport.cc | 9 +++--- .../cronet/transport/cronet_transport.cc | 5 ++-- .../ext/transport/inproc/inproc_transport.cc | 5 ++-- src/core/lib/transport/transport.cc | 5 ++-- src/core/lib/transport/transport.h | 10 +------ src/core/lib/transport/transport_impl.h | 3 +- test/cpp/microbenchmarks/bm_call_create.cc | 10 ++++--- 11 files changed, 46 insertions(+), 55 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 4fedcbcbb6c..8d02304d19f 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -136,23 +136,6 @@ void SubchannelNode::PopulateConnectivityState(grpc_json* json) { false); } -void SubchannelNode::PopulateChildSockets(grpc_json* json) { - ChildRefsList child_sockets; - grpc_json* json_iterator = nullptr; - grpc_subchannel_populate_child_sockets(subchannel_, &child_sockets); - if (!child_sockets.empty()) { - grpc_json* array_parent = grpc_json_create_child( - nullptr, json, "socketRef", nullptr, GRPC_JSON_ARRAY, false); - for (size_t i = 0; i < child_sockets.size(); ++i) { - 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", - child_sockets[i]); - } - } -} - grpc_json* SubchannelNode::RenderJson() { grpc_json* top_level_json = grpc_json_create(GRPC_JSON_OBJECT); grpc_json* json = top_level_json; @@ -184,7 +167,17 @@ grpc_json* SubchannelNode::RenderJson() { // ask CallCountingHelper to populate trace and call count data. call_counter_.PopulateCallCounts(json); json = top_level_json; - PopulateChildSockets(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; } diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index a63df00f9f2..a6dae165223 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -31,6 +31,11 @@ typedef struct grpc_subchannel grpc_subchannel; namespace grpc_core { +// TODO(ncteisen), this only contains the uuids of the children for now, +// since that is all that is strictly needed. In a future enhancement we will +// add human readable names as in the channelz.proto +typedef InlinedVector ChildRefsList; + namespace channelz { // Subtype of ChannelNode that overrides and provides client_channel specific diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 29aeb06e7bc..4c33636646c 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -97,7 +97,9 @@ struct grpc_subchannel { /** set during connection */ grpc_connect_out_args connecting_result; - grpc_transport* transport; + /** uuid of this subchannel's socket. 0 if this subchannel is not + connected */ + intptr_t socket_uuid; /** callback for connection finishing */ grpc_closure on_connected; @@ -256,6 +258,7 @@ static void disconnect(grpc_subchannel* c) { c->disconnected = true; grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Subchannel disconnected")); + c->socket_uuid = 0; c->connected_subchannel.reset(); gpr_mu_unlock(&c->mu); } @@ -413,11 +416,9 @@ grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( return subchannel->channelz_subchannel.get(); } -void grpc_subchannel_populate_child_sockets( - grpc_subchannel* subchannel, grpc_core::ChildRefsList* child_sockets) { - if (subchannel->transport != nullptr) { - grpc_transport_populate_sockets(subchannel->transport, child_sockets); - } +intptr_t grpc_subchannel_get_child_socket_uuid( + grpc_subchannel* subchannel) { + return subchannel->socket_uuid; } static void continue_connect_locked(grpc_subchannel* c) { @@ -578,6 +579,7 @@ static void on_connected_subchannel_connectivity_changed(void* p, grpc_connectivity_state_name( connected_subchannel_watcher->connectivity_state)); } + c->socket_uuid = 0; c->connected_subchannel.reset(); grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, @@ -630,7 +632,7 @@ static bool publish_transport_locked(grpc_subchannel* c) { GRPC_ERROR_UNREF(error); return false; } - c->transport = c->connecting_result.transport; + c->socket_uuid = grpc_transport_get_socket_uuid(c->connecting_result.transport); memset(&c->connecting_result, 0, sizeof(c->connecting_result)); /* initialize state watcher */ diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 2cf5067fc26..67a2d497111 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -126,8 +126,8 @@ void grpc_subchannel_call_unref( grpc_core::channelz::SubchannelNode* grpc_subchannel_get_channelz_node( grpc_subchannel* subchannel); -void grpc_subchannel_populate_child_sockets( - grpc_subchannel* subchannel, grpc_core::ChildRefsList* child_sockets); +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 diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 202da652de7..45ef4161f78 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -3157,12 +3157,13 @@ static grpc_endpoint* chttp2_get_endpoint(grpc_transport* t) { return (reinterpret_cast(t))->ep; } -static void populate_sockets(grpc_transport* transport, - grpc_core::ChildRefsList* child_sockets) { +static intptr_t get_socket_uuid(grpc_transport* transport) { grpc_chttp2_transport* t = reinterpret_cast(transport); if (t->channelz_socket != nullptr) { - child_sockets->push_back(t->channelz_socket->uuid()); + return t->channelz_socket->uuid(); + } else { + return 0; } } @@ -3176,7 +3177,7 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), destroy_stream, destroy_transport, chttp2_get_endpoint, - populate_sockets}; + get_socket_uuid}; static const grpc_transport_vtable* get_vtable(void) { return &vtable; } diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index f3826a78de0..bb20d9db084 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -1439,8 +1439,7 @@ static grpc_endpoint* get_endpoint(grpc_transport* gt) { return nullptr; } static void perform_op(grpc_transport* gt, grpc_transport_op* op) {} -static void populate_sockets(grpc_transport* t, - grpc_core::ChildRefsList* child_sockets) {} +static intptr_t get_socket_uuid(grpc_transport* t) { return 0; } static const grpc_transport_vtable grpc_cronet_vtable = { sizeof(stream_obj), @@ -1453,7 +1452,7 @@ static const grpc_transport_vtable grpc_cronet_vtable = { destroy_stream, destroy_transport, get_endpoint, - populate_sockets}; + get_socket_uuid}; grpc_transport* grpc_create_cronet_transport(void* engine, const char* target, const grpc_channel_args* args, diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc index 2deaacb2e06..56951f83386 100644 --- a/src/core/ext/transport/inproc/inproc_transport.cc +++ b/src/core/ext/transport/inproc/inproc_transport.cc @@ -1170,8 +1170,7 @@ static void set_pollset_set(grpc_transport* gt, grpc_stream* gs, static grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; } -static void populate_sockets(grpc_transport* t, - grpc_core::ChildRefsList* child_sockets) {} +static intptr_t get_socket_uuid(grpc_transport* t) { return 0; } /******************************************************************************* * GLOBAL INIT AND DESTROY @@ -1197,7 +1196,7 @@ static const grpc_transport_vtable inproc_vtable = { sizeof(inproc_stream), "inproc", init_stream, set_pollset, set_pollset_set, perform_stream_op, perform_transport_op, destroy_stream, destroy_transport, - get_endpoint, populate_sockets}; + get_endpoint, get_socket_uuid}; /******************************************************************************* * Main inproc transport functions diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index 2e7c40dda45..c8fdbb4de26 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -199,9 +199,8 @@ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport) { return transport->vtable->get_endpoint(transport); } -void grpc_transport_populate_sockets(grpc_transport* transport, - grpc_core::ChildRefsList* child_sockets) { - return transport->vtable->populate_sockets(transport, child_sockets); +intptr_t grpc_transport_get_socket_uuid(grpc_transport* transport) { + return transport->vtable->get_socket_uuid(transport); } // This comment should be sung to the tune of diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 93445ebd051..aad133f6c3d 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -39,13 +39,6 @@ #define GRPC_PROTOCOL_VERSION_MIN_MAJOR 2 #define GRPC_PROTOCOL_VERSION_MIN_MINOR 1 -namespace grpc_core { -// TODO(ncteisen), this only contains the uuids of the children for now, -// since that is all that is strictly needed. In a future enhancement we will -// add human readable names as in the channelz.proto -typedef InlinedVector ChildRefsList; -} // namespace grpc_core - /* forward declarations */ typedef struct grpc_transport grpc_transport; @@ -373,8 +366,7 @@ void grpc_transport_destroy(grpc_transport* transport); /* Get the endpoint used by \a transport */ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport); -void grpc_transport_populate_sockets(grpc_transport* transport, - grpc_core::ChildRefsList* child_sockets); +intptr_t grpc_transport_get_socket_uuid(grpc_transport* transport); /* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to \a on_consumed and then delete the returned transport op */ diff --git a/src/core/lib/transport/transport_impl.h b/src/core/lib/transport/transport_impl.h index 7ae59a1d17f..d609470ef01 100644 --- a/src/core/lib/transport/transport_impl.h +++ b/src/core/lib/transport/transport_impl.h @@ -61,8 +61,7 @@ typedef struct grpc_transport_vtable { /* implementation of grpc_transport_get_endpoint */ grpc_endpoint* (*get_endpoint)(grpc_transport* self); - void (*populate_sockets)(grpc_transport* self, - grpc_core::ChildRefsList* child_sockets); + intptr_t (*get_socket_uuid)(grpc_transport* self); } grpc_transport_vtable; /* an instance of a grpc transport */ diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 9516b2e3e25..b0cccafcf82 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -446,11 +446,13 @@ void Destroy(grpc_transport* self) {} /* implementation of grpc_transport_get_endpoint */ grpc_endpoint* GetEndpoint(grpc_transport* self) { return nullptr; } +intptr_t GetSocketUuid(grpc_transport* t) { return 0; } + static const grpc_transport_vtable dummy_transport_vtable = { - 0, "dummy_http2", InitStream, - SetPollset, SetPollsetSet, PerformStreamOp, - PerformOp, DestroyStream, Destroy, - GetEndpoint}; + 0, "dummy_http2", InitStream, + SetPollset, SetPollsetSet, PerformStreamOp, + PerformOp, DestroyStream, Destroy, + GetEndpoint, GetSocketUuid}; static grpc_transport dummy_transport = {&dummy_transport_vtable}; From 80ce1865d765f3a3623a8d6420b8e82e3f4b5cca Mon Sep 17 00:00:00 2001 From: Soheil Hassas Yeganeh Date: Thu, 27 Sep 2018 11:26:05 -0400 Subject: [PATCH 36/39] Make SliceFromArray() static in channel_cc.cc. Also, use `context->authority_` instead of `context->authority()` for consistency. --- include/grpcpp/impl/codegen/slice.h | 4 ---- src/cpp/client/channel_cc.cc | 6 +++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/grpcpp/impl/codegen/slice.h b/include/grpcpp/impl/codegen/slice.h index 75c093d1da0..8966559dc85 100644 --- a/include/grpcpp/impl/codegen/slice.h +++ b/include/grpcpp/impl/codegen/slice.h @@ -138,10 +138,6 @@ inline grpc_slice SliceFromCopiedString(const grpc::string& str) { str.length()); } -inline grpc_slice SliceFromArray(const char* arr, size_t len) { - return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len); -} - } // namespace grpc #endif // GRPCPP_IMPL_CODEGEN_SLICE_H diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index 510ae73478e..31c02893b11 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -65,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) { @@ -112,7 +116,7 @@ internal::Call Channel::CreateCall(const internal::RpcMethod& method, method.channel_tag(), context->raw_deadline(), nullptr); } else { const string* host_str = nullptr; - if (!context->authority().empty()) { + if (!context->authority_.empty()) { host_str = &context->authority_; } else if (!host_.empty()) { host_str = &host_; From f2b493e3697211552a28dba582313174f2a932f2 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 27 Sep 2018 10:38:37 -0500 Subject: [PATCH 37/39] reviewer feedback --- .../client_channel/client_channel_channelz.cc | 5 ++-- .../client_channel/client_channel_channelz.h | 3 --- .../ext/filters/client_channel/subchannel.cc | 25 +++++++++---------- .../ext/filters/client_channel/subchannel.h | 9 ++++--- test/cpp/microbenchmarks/bm_call_create.cc | 6 ++--- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.cc b/src/core/ext/filters/client_channel/client_channel_channelz.cc index 8d02304d19f..b66c920b909 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.cc +++ b/src/core/ext/filters/client_channel/client_channel_channelz.cc @@ -172,9 +172,8 @@ grpc_json* SubchannelNode::RenderJson() { 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); + 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); } diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index a6dae165223..8ce331e529d 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -76,9 +76,6 @@ class SubchannelNode : public BaseNode { grpc_json* RenderJson() override; - // helper to populate the socket(s) that this subchannel owns. - void PopulateChildSockets(grpc_json* json); - // proxy methods to composed classes. void AddTraceEvent(ChannelTrace::Severity severity, grpc_slice data) { trace_.AddTraceEvent(severity, data); diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 4c33636646c..4756733f1f8 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -97,10 +97,6 @@ struct grpc_subchannel { /** set during connection */ grpc_connect_out_args connecting_result; - /** uuid of this subchannel's socket. 0 if this subchannel is not - connected */ - intptr_t socket_uuid; - /** callback for connection finishing */ grpc_closure on_connected; @@ -258,7 +254,6 @@ static void disconnect(grpc_subchannel* c) { c->disconnected = true; grpc_connector_shutdown(c->connector, GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Subchannel disconnected")); - c->socket_uuid = 0; c->connected_subchannel.reset(); gpr_mu_unlock(&c->mu); } @@ -416,9 +411,12 @@ 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) { - return subchannel->socket_uuid; +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) { @@ -579,7 +577,6 @@ static void on_connected_subchannel_connectivity_changed(void* p, grpc_connectivity_state_name( connected_subchannel_watcher->connectivity_state)); } - c->socket_uuid = 0; c->connected_subchannel.reset(); grpc_connectivity_state_set(&c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, @@ -632,7 +629,8 @@ static bool publish_transport_locked(grpc_subchannel* c) { GRPC_ERROR_UNREF(error); return false; } - c->socket_uuid = grpc_transport_get_socket_uuid(c->connecting_result.transport); + intptr_t socket_uuid = + grpc_transport_get_socket_uuid(c->connecting_result.transport); memset(&c->connecting_result, 0, sizeof(c->connecting_result)); /* initialize state watcher */ @@ -653,7 +651,7 @@ static bool publish_transport_locked(grpc_subchannel* c) { /* publish */ c->connected_subchannel.reset(grpc_core::New( - 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); @@ -823,10 +821,11 @@ namespace grpc_core { ConnectedSubchannel::ConnectedSubchannel( grpc_channel_stack* channel_stack, - channelz::SubchannelNode* channelz_subchannel) + channelz::SubchannelNode* channelz_subchannel, intptr_t socket_uuid) : RefCountedWithTracing(&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"); diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 67a2d497111..5d95a720853 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -86,7 +86,8 @@ class ConnectedSubchannel : public RefCountedWithTracing { }; 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 { 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. + intptr_t socket_uuid_; }; } // namespace grpc_core @@ -126,8 +130,7 @@ 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); +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 diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index b0cccafcf82..45ac782a0e1 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -449,9 +449,9 @@ grpc_endpoint* GetEndpoint(grpc_transport* self) { return nullptr; } intptr_t GetSocketUuid(grpc_transport* t) { return 0; } static const grpc_transport_vtable dummy_transport_vtable = { - 0, "dummy_http2", InitStream, - SetPollset, SetPollsetSet, PerformStreamOp, - PerformOp, DestroyStream, Destroy, + 0, "dummy_http2", InitStream, + SetPollset, SetPollsetSet, PerformStreamOp, + PerformOp, DestroyStream, Destroy, GetEndpoint, GetSocketUuid}; static grpc_transport dummy_transport = {&dummy_transport_vtable}; From 404b2515af9c4dcc29440dea8b955ba341521b68 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Thu, 27 Sep 2018 11:18:42 -0500 Subject: [PATCH 38/39] reviewer feedback --- .../ext/filters/client_channel/connector.h | 3 +++ .../ext/filters/client_channel/subchannel.cc | 3 +-- .../ext/filters/client_channel/subchannel.h | 2 +- .../chttp2/client/chttp2_connector.cc | 2 ++ .../chttp2/transport/chttp2_transport.cc | 23 +++++++++---------- .../chttp2/transport/chttp2_transport.h | 2 ++ .../cronet/transport/cronet_transport.cc | 5 +--- .../ext/transport/inproc/inproc_transport.cc | 4 +--- src/core/lib/transport/transport.cc | 4 ---- src/core/lib/transport/transport.h | 2 -- src/core/lib/transport/transport_impl.h | 2 -- test/cpp/microbenchmarks/bm_call_create.cc | 10 ++++---- 12 files changed, 26 insertions(+), 36 deletions(-) diff --git a/src/core/ext/filters/client_channel/connector.h b/src/core/ext/filters/client_channel/connector.h index 556594929c1..ea34dcdab57 100644 --- a/src/core/ext/filters/client_channel/connector.h +++ b/src/core/ext/filters/client_channel/connector.h @@ -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 { diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 4756733f1f8..2847f4bdc18 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -629,8 +629,7 @@ static bool publish_transport_locked(grpc_subchannel* c) { GRPC_ERROR_UNREF(error); return false; } - intptr_t socket_uuid = - grpc_transport_get_socket_uuid(c->connecting_result.transport); + intptr_t socket_uuid = c->connecting_result.socket_uuid; memset(&c->connecting_result, 0, sizeof(c->connecting_result)); /* initialize state watcher */ diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 5d95a720853..699f93a8e77 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -107,7 +107,7 @@ class ConnectedSubchannel : public RefCountedWithTracing { // owning subchannel. channelz::SubchannelNode* channelz_subchannel_; // uuid of this subchannel's socket. 0 if this subchannel is not connected. - intptr_t socket_uuid_; + const intptr_t socket_uuid_; }; } // namespace grpc_core diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index e7522ffba87..0ac84032fd4 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -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 diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 45ef4161f78..776c15138b8 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -3157,16 +3157,6 @@ static grpc_endpoint* chttp2_get_endpoint(grpc_transport* t) { return (reinterpret_cast(t))->ep; } -static intptr_t get_socket_uuid(grpc_transport* transport) { - grpc_chttp2_transport* t = - reinterpret_cast(transport); - if (t->channelz_socket != nullptr) { - return t->channelz_socket->uuid(); - } else { - return 0; - } -} - static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), "chttp2", init_stream, @@ -3176,11 +3166,20 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream), perform_transport_op, destroy_stream, destroy_transport, - chttp2_get_endpoint, - get_socket_uuid}; + chttp2_get_endpoint}; 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(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( diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h index 9d55b3f4b0d..e5872fee436 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.h +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.h @@ -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 diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index bb20d9db084..81e2634e3a7 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -1439,8 +1439,6 @@ static grpc_endpoint* get_endpoint(grpc_transport* gt) { return nullptr; } static void perform_op(grpc_transport* gt, grpc_transport_op* op) {} -static intptr_t get_socket_uuid(grpc_transport* t) { return 0; } - static const grpc_transport_vtable grpc_cronet_vtable = { sizeof(stream_obj), "cronet_http", @@ -1451,8 +1449,7 @@ static const grpc_transport_vtable grpc_cronet_vtable = { perform_op, destroy_stream, destroy_transport, - get_endpoint, - get_socket_uuid}; + get_endpoint}; grpc_transport* grpc_create_cronet_transport(void* engine, const char* target, const grpc_channel_args* args, diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc index 56951f83386..b0ca7f8207e 100644 --- a/src/core/ext/transport/inproc/inproc_transport.cc +++ b/src/core/ext/transport/inproc/inproc_transport.cc @@ -1170,8 +1170,6 @@ static void set_pollset_set(grpc_transport* gt, grpc_stream* gs, static grpc_endpoint* get_endpoint(grpc_transport* t) { return nullptr; } -static intptr_t get_socket_uuid(grpc_transport* t) { return 0; } - /******************************************************************************* * GLOBAL INIT AND DESTROY */ @@ -1196,7 +1194,7 @@ static const grpc_transport_vtable inproc_vtable = { sizeof(inproc_stream), "inproc", init_stream, set_pollset, set_pollset_set, perform_stream_op, perform_transport_op, destroy_stream, destroy_transport, - get_endpoint, get_socket_uuid}; + get_endpoint}; /******************************************************************************* * Main inproc transport functions diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index c8fdbb4de26..cbdb77c8441 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -199,10 +199,6 @@ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport) { return transport->vtable->get_endpoint(transport); } -intptr_t grpc_transport_get_socket_uuid(grpc_transport* transport) { - return transport->vtable->get_socket_uuid(transport); -} - // This comment should be sung to the tune of // "Supercalifragilisticexpialidocious": // diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index aad133f6c3d..9e784635c69 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -366,8 +366,6 @@ void grpc_transport_destroy(grpc_transport* transport); /* Get the endpoint used by \a transport */ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport); -intptr_t grpc_transport_get_socket_uuid(grpc_transport* transport); - /* Allocate a grpc_transport_op, and preconfigure the on_consumed closure to \a on_consumed and then delete the returned transport op */ grpc_transport_op* grpc_make_transport_op(grpc_closure* on_consumed); diff --git a/src/core/lib/transport/transport_impl.h b/src/core/lib/transport/transport_impl.h index d609470ef01..ba5e05df0af 100644 --- a/src/core/lib/transport/transport_impl.h +++ b/src/core/lib/transport/transport_impl.h @@ -60,8 +60,6 @@ typedef struct grpc_transport_vtable { /* implementation of grpc_transport_get_endpoint */ grpc_endpoint* (*get_endpoint)(grpc_transport* self); - - intptr_t (*get_socket_uuid)(grpc_transport* self); } grpc_transport_vtable; /* an instance of a grpc transport */ diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 45ac782a0e1..9516b2e3e25 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -446,13 +446,11 @@ void Destroy(grpc_transport* self) {} /* implementation of grpc_transport_get_endpoint */ grpc_endpoint* GetEndpoint(grpc_transport* self) { return nullptr; } -intptr_t GetSocketUuid(grpc_transport* t) { return 0; } - static const grpc_transport_vtable dummy_transport_vtable = { - 0, "dummy_http2", InitStream, - SetPollset, SetPollsetSet, PerformStreamOp, - PerformOp, DestroyStream, Destroy, - GetEndpoint, GetSocketUuid}; + 0, "dummy_http2", InitStream, + SetPollset, SetPollsetSet, PerformStreamOp, + PerformOp, DestroyStream, Destroy, + GetEndpoint}; static grpc_transport dummy_transport = {&dummy_transport_vtable}; From 018a14bdec298275ed0b560be55f783092defb85 Mon Sep 17 00:00:00 2001 From: Sree Kuchibhotla Date: Thu, 27 Sep 2018 11:18:18 -0700 Subject: [PATCH 39/39] generate_projects.sh --- tools/doxygen/Doxyfile.core | 1 + tools/doxygen/Doxyfile.core.internal | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index aa75bc68283..8562dfff3a9 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -771,6 +771,7 @@ doc/compression_cookbook.md \ doc/connection-backoff-interop-test-description.md \ doc/connection-backoff.md \ doc/connectivity-semantics-and-api.md \ +doc/core/grpc-cq.md \ doc/core/grpc-error.md \ doc/core/moving-to-c++.md \ doc/core/pending_api_cleanups.md \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 91860567339..aa7b11fd547 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -771,6 +771,7 @@ doc/compression_cookbook.md \ doc/connection-backoff-interop-test-description.md \ doc/connection-backoff.md \ doc/connectivity-semantics-and-api.md \ +doc/core/grpc-cq.md \ doc/core/grpc-error.md \ doc/core/moving-to-c++.md \ doc/core/pending_api_cleanups.md \