Merge pull request #15619 from yang-g/oauth_cache

Stop using cached time in oauth token expiration time
diff --git a/Makefile b/Makefile
index 0e54fb2..1247566f 100644
--- a/Makefile
+++ b/Makefile
@@ -501,7 +501,6 @@
 
 ifeq ($(HAS_PKG_CONFIG),true)
 OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
-OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
 ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
 PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
 CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
@@ -514,7 +513,6 @@
 endif
 
 OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
-OPENSSL_NPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
 BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) -Ithird_party/boringssl/include -fvisibility=hidden -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(CFLAGS) -Wno-sign-conversion -Wno-conversion -Wno-unused-value -Wno-unknown-pragmas -Wno-implicit-function-declaration -Wno-unused-variable -Wno-sign-compare -Wno-implicit-fallthrough $(NO_W_EXTRA_SEMI) -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS)
 ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
 PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
@@ -542,13 +540,7 @@
 ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
 HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
 ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
-HAS_SYSTEM_OPENSSL_NPN = true
 CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true,
-else
-HAS_SYSTEM_OPENSSL_NPN ?= $(shell $(OPENSSL_NPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
-endif
-ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
-CACHE_MK += HAS_SYSTEM_OPENSSL_NPN = true,
 endif
 HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
 ifeq ($(HAS_SYSTEM_ZLIB),true)
@@ -565,7 +557,6 @@
 else
 # override system libraries if the config requires a custom compiled library
 HAS_SYSTEM_OPENSSL_ALPN = false
-HAS_SYSTEM_OPENSSL_NPN = false
 HAS_SYSTEM_ZLIB = false
 HAS_SYSTEM_PROTOBUF = false
 HAS_SYSTEM_CARES = false
@@ -712,12 +703,7 @@
 EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN)
 NO_SECURE ?= false
 else # HAS_EMBEDDED_OPENSSL_ALPN=false
-ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
-EMBED_OPENSSL ?= false
-NO_SECURE ?= false
-else
 NO_SECURE ?= true
-endif # HAS_SYSTEM_OPENSSL_NPN=true
 endif # HAS_EMBEDDED_OPENSSL_ALPN
 endif # HAS_SYSTEM_OPENSSL_ALPN
 
@@ -751,10 +737,10 @@
 else # HAS_PKG_CONFIG=false
 LIBS_SECURE = $(OPENSSL_LIBS)
 endif # HAS_PKG_CONFIG
-ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
+ifeq ($(DISABLE_ALPN),true)
 CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0
 LIBS_SECURE = $(OPENSSL_LIBS)
-endif # HAS_SYSTEM_OPENSSL_NPN
+endif # DISABLE_ALPN
 PC_LIBS_SECURE = $(addprefix -l, $(LIBS_SECURE))
 endif # EMBED_OPENSSL
 endif # NO_SECURE
@@ -1347,7 +1333,6 @@
 
 run_dep_checks:
 	$(OPENSSL_ALPN_CHECK_CMD) || true
-	$(OPENSSL_NPN_CHECK_CMD) || true
 	$(ZLIB_CHECK_CMD) || true
 	$(PERFTOOLS_CHECK_CMD) || true
 	$(PROTOBUF_CHECK_CMD) || true
diff --git a/bazel/cc_grpc_library.bzl b/bazel/cc_grpc_library.bzl
index 5216a7a..3288565 100644
--- a/bazel/cc_grpc_library.bzl
+++ b/bazel/cc_grpc_library.bzl
@@ -43,12 +43,7 @@
   )
 
   if not proto_only:
-    if use_external:
-      # when this file is used by non-grpc projects
-      plugin = "//external:grpc_cpp_plugin"
-    else:
-      plugin = "//:grpc_cpp_plugin"
-
+    plugin = "@com_github_grpc_grpc//:grpc_cpp_plugin"
     generate_cc(
         name = codegen_grpc_target,
         srcs = [proto_target],
@@ -57,14 +52,8 @@
         generate_mocks = generate_mocks,
         **kwargs
     )
-
-    if use_external:
-      # when this file is used by non-grpc projects
-      grpc_deps = ["//external:grpc++_codegen_proto",
-                   "//external:protobuf"]
-    else:
-      grpc_deps = ["//:grpc++_codegen_proto", "//external:protobuf"]
-
+    grpc_deps  = ["@com_github_grpc_grpc//:grpc++_codegen_proto",
+                  "//external:protobuf"]
     native.cc_library(
         name = name,
         srcs = [":" + codegen_grpc_target, ":" + codegen_target],
diff --git a/examples/ruby/pubsub/.gitignore b/examples/ruby/pubsub/.gitignore
new file mode 100644
index 0000000..62fcb4f
--- /dev/null
+++ b/examples/ruby/pubsub/.gitignore
@@ -0,0 +1,15 @@
+/.bundle/
+/.yardoc
+/Gemfile.lock
+/_yardoc/
+/coverage/
+/doc/
+/pkg/
+/spec/reports/
+/tmp/
+*.bundle
+*.so
+*.o
+*.a
+mkmf.log
+vendor
diff --git a/examples/ruby/pubsub/Gemfile b/examples/ruby/pubsub/Gemfile
new file mode 100644
index 0000000..4ee8ffe
--- /dev/null
+++ b/examples/ruby/pubsub/Gemfile
@@ -0,0 +1,4 @@
+source 'https://rubygems.org/'
+
+gem 'grpc', '~> 1.0'
+gem 'googleauth', '>= 0.5.1', '< 0.7'
diff --git a/src/ruby/bin/apis/google/protobuf/empty.rb b/examples/ruby/pubsub/google/protobuf/empty.rb
similarity index 100%
rename from src/ruby/bin/apis/google/protobuf/empty.rb
rename to examples/ruby/pubsub/google/protobuf/empty.rb
diff --git a/src/ruby/bin/apis/pubsub_demo.rb b/examples/ruby/pubsub/pubsub_demo.rb
similarity index 100%
rename from src/ruby/bin/apis/pubsub_demo.rb
rename to examples/ruby/pubsub/pubsub_demo.rb
diff --git a/src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb b/examples/ruby/pubsub/tech/pubsub/proto/pubsub.rb
similarity index 100%
rename from src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb
rename to examples/ruby/pubsub/tech/pubsub/proto/pubsub.rb
diff --git a/src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb b/examples/ruby/pubsub/tech/pubsub/proto/pubsub_services.rb
similarity index 100%
rename from src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb
rename to examples/ruby/pubsub/tech/pubsub/proto/pubsub_services.rb
diff --git a/grpc.gemspec b/grpc.gemspec
index 1e4722d..5ab3713 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -20,7 +20,9 @@
   s.files += Dir.glob('src/ruby/bin/**/*')
   s.files += Dir.glob('src/ruby/ext/**/*')
   s.files += Dir.glob('src/ruby/lib/**/*')
-  s.files += Dir.glob('src/ruby/pb/**/*')
+  s.files += Dir.glob('src/ruby/pb/**/*').reject do |f|
+    f.match(%r{^src/ruby/pb/test})
+  end
   s.files += Dir.glob('include/grpc/**/*')
   s.test_files = Dir.glob('src/ruby/spec/**/*')
   s.bindir = 'src/ruby/bin'
@@ -28,7 +30,6 @@
   s.platform      = Gem::Platform::RUBY
 
   s.add_dependency 'google-protobuf', '~> 3.1'
-  s.add_dependency 'googleauth',      '>= 0.5.1', '< 0.7'
   s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0'
 
   s.add_development_dependency 'bundler',            '~> 1.9'
@@ -41,6 +42,7 @@
   s.add_development_dependency 'rspec',              '~> 3.6'
   s.add_development_dependency 'rubocop',            '~> 0.49.1'
   s.add_development_dependency 'signet',             '~> 0.7.0'
+  s.add_development_dependency 'googleauth',         '>= 0.5.1', '< 0.7'
 
   s.extensions = %w(src/ruby/ext/grpc/extconf.rb)
 
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
index d5ef063..0eaf63f 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
@@ -41,14 +41,18 @@
 #include "src/core/lib/transport/static_metadata.h"
 #include "src/core/lib/transport/timeout_encoding.h"
 
-#define HASH_FRAGMENT_1(x) ((x)&255)
-#define HASH_FRAGMENT_2(x) ((x >> 8) & 255)
-#define HASH_FRAGMENT_3(x) ((x >> 16) & 255)
-#define HASH_FRAGMENT_4(x) ((x >> 24) & 255)
+#define HASH_FRAGMENT_MASK (GRPC_CHTTP2_HPACKC_NUM_VALUES - 1)
+#define HASH_FRAGMENT_1(x) ((x)&HASH_FRAGMENT_MASK)
+#define HASH_FRAGMENT_2(x) \
+  (((x) >> GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS) & HASH_FRAGMENT_MASK)
+#define HASH_FRAGMENT_3(x) \
+  (((x) >> (GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS * 2)) & HASH_FRAGMENT_MASK)
+#define HASH_FRAGMENT_4(x) \
+  (((x) >> (GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS * 3)) & HASH_FRAGMENT_MASK)
 
 /* if the probability of this item being seen again is < 1/x then don't add
    it to the table */
-#define ONE_ON_ADD_PROBABILITY 128
+#define ONE_ON_ADD_PROBABILITY (GRPC_CHTTP2_HPACKC_NUM_VALUES >> 1)
 /* don't consider adding anything bigger than this to the hpack table */
 #define MAX_DECODER_SPACE_USAGE 512
 
@@ -135,7 +139,7 @@
   } else {
     int i;
     *sum = 0;
-    for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_FILTERS; i++) {
+    for (i = 0; i < GRPC_CHTTP2_HPACKC_NUM_VALUES; i++) {
       elems[i] /= 2;
       (*sum) += elems[i];
     }
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
index b370932..e31a739 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.h
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.h
@@ -28,8 +28,9 @@
 #include "src/core/lib/transport/metadata_batch.h"
 #include "src/core/lib/transport/transport.h"
 
-#define GRPC_CHTTP2_HPACKC_NUM_FILTERS 256
-#define GRPC_CHTTP2_HPACKC_NUM_VALUES 256
+// This should be <= 8. We use 6 to save space.
+#define GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS 6
+#define GRPC_CHTTP2_HPACKC_NUM_VALUES (1 << GRPC_CHTTP2_HPACKC_NUM_VALUES_BITS)
 /* initial table size, per spec */
 #define GRPC_CHTTP2_HPACKC_INITIAL_TABLE_SIZE 4096
 /* maximum table size we'll actually use */
@@ -58,7 +59,7 @@
      a new literal should be added to the compression table or not.
      They track a single integer that counts how often a particular value has
      been seen. When that count reaches max (255), all values are halved. */
-  uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_FILTERS];
+  uint8_t filter_elems[GRPC_CHTTP2_HPACKC_NUM_VALUES];
 
   /* entry tables for keys & elems: these tables track values that have been
      seen and *may* be in the decompressor table */
diff --git a/src/core/lib/iomgr/tcp_client_custom.cc b/src/core/lib/iomgr/tcp_client_custom.cc
index 932c79e..9389861 100644
--- a/src/core/lib/iomgr/tcp_client_custom.cc
+++ b/src/core/lib/iomgr/tcp_client_custom.cc
@@ -140,12 +140,12 @@
             socket, connect->addr_name);
   }
 
-  grpc_custom_socket_vtable->connect(
-      socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len,
-      custom_connect_callback);
   GRPC_CLOSURE_INIT(&connect->on_alarm, on_alarm, socket,
                     grpc_schedule_on_exec_ctx);
   grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm);
+  grpc_custom_socket_vtable->connect(
+      socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len,
+      custom_connect_callback);
 }
 
 grpc_tcp_client_vtable custom_tcp_client_vtable = {tcp_connect};
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
index 500086f..dff9097 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi
@@ -17,6 +17,17 @@
 import grpc
 import threading
 
+def _spawn_callback_in_thread(cb_func, args):
+  threading.Thread(target=cb_func, args=args).start()
+
+async_callback_func = _spawn_callback_in_thread
+
+def set_async_callback_func(callback_func):
+  global async_callback_func
+  async_callback_func = callback_func
+
+def _spawn_callback_async(callback, args):
+  async_callback_func(callback, args)
 
 cdef class CallCredentials:
 
@@ -40,7 +51,7 @@
     else:
       cb(user_data, NULL, 0, status, error_details)
   args = context.service_url, context.method_name, callback,
-  threading.Thread(target=<object>state, args=args).start()
+  _spawn_callback_async(<object>state, args)
   return 0  # Asynchronous return
 
 
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
index 31ef671..f9a1b28 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
@@ -418,6 +418,11 @@
 
   g_event = gevent.event.Event()
   g_pool = gevent.pool.Group()
+
+  def cb_func(cb, args):
+    _spawn_greenlet(cb, *args)
+  set_async_callback_func(cb_func)
+
   gevent_resolver_vtable.resolve = socket_resolve
   gevent_resolver_vtable.resolve_async = socket_resolve_async
 
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 901dbfc..43fa904 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -414,7 +414,6 @@
 
   ifeq ($(HAS_PKG_CONFIG),true)
   OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
-  OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
   ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
   PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
   CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
@@ -427,7 +426,6 @@
   endif
 
   OPENSSL_ALPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
-  OPENSSL_NPN_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/openssl-npn.c $(addprefix -l, $(OPENSSL_LIBS)) $(LDFLAGS)
   BORINGSSL_COMPILE_CHECK_CMD = $(CC) $(CPPFLAGS) ${defaults.boringssl.CPPFLAGS} $(CFLAGS) ${defaults.boringssl.CFLAGS} -o $(TMPOUT) test/build/boringssl.c $(LDFLAGS)
   ZLIB_CHECK_CMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
   PROTOBUF_CHECK_CMD = $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
@@ -455,13 +453,7 @@
   ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG)
   HAS_SYSTEM_OPENSSL_ALPN ?= $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
   ifeq ($(HAS_SYSTEM_OPENSSL_ALPN),true)
-  HAS_SYSTEM_OPENSSL_NPN = true
   CACHE_MK += HAS_SYSTEM_OPENSSL_ALPN = true,
-  else
-  HAS_SYSTEM_OPENSSL_NPN ?= $(shell $(OPENSSL_NPN_CHECK_CMD) 2> /dev/null && echo true || echo false)
-  endif
-  ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
-  CACHE_MK += HAS_SYSTEM_OPENSSL_NPN = true,
   endif
   HAS_SYSTEM_ZLIB ?= $(shell $(ZLIB_CHECK_CMD) 2> /dev/null && echo true || echo false)
   ifeq ($(HAS_SYSTEM_ZLIB),true)
@@ -478,7 +470,6 @@
   else
   # override system libraries if the config requires a custom compiled library
   HAS_SYSTEM_OPENSSL_ALPN = false
-  HAS_SYSTEM_OPENSSL_NPN = false
   HAS_SYSTEM_ZLIB = false
   HAS_SYSTEM_PROTOBUF = false
   HAS_SYSTEM_CARES = false
@@ -625,12 +616,7 @@
   EMBED_OPENSSL ?= $(HAS_EMBEDDED_OPENSSL_ALPN)
   NO_SECURE ?= false
   else # HAS_EMBEDDED_OPENSSL_ALPN=false
-  ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
-  EMBED_OPENSSL ?= false
-  NO_SECURE ?= false
-  else
   NO_SECURE ?= true
-  endif # HAS_SYSTEM_OPENSSL_NPN=true
   endif # HAS_EMBEDDED_OPENSSL_ALPN
   endif # HAS_SYSTEM_OPENSSL_ALPN
 
@@ -664,10 +650,10 @@
   else # HAS_PKG_CONFIG=false
   LIBS_SECURE = $(OPENSSL_LIBS)
   endif # HAS_PKG_CONFIG
-  ifeq ($(HAS_SYSTEM_OPENSSL_NPN),true)
+  ifeq ($(DISABLE_ALPN),true)
   CPPFLAGS += -DTSI_OPENSSL_ALPN_SUPPORT=0
   LIBS_SECURE = $(OPENSSL_LIBS)
-  endif # HAS_SYSTEM_OPENSSL_NPN
+  endif # DISABLE_ALPN
   PC_LIBS_SECURE = $(addprefix -l, $(LIBS_SECURE))
   endif # EMBED_OPENSSL
   endif # NO_SECURE
@@ -888,7 +874,6 @@
 
   run_dep_checks:
   	$(OPENSSL_ALPN_CHECK_CMD) || true
-  	$(OPENSSL_NPN_CHECK_CMD) || true
   	$(ZLIB_CHECK_CMD) || true
   	$(PERFTOOLS_CHECK_CMD) || true
   	$(PROTOBUF_CHECK_CMD) || true
diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template
index fb54de1..842035b 100644
--- a/templates/grpc.gemspec.template
+++ b/templates/grpc.gemspec.template
@@ -22,7 +22,9 @@
     s.files += Dir.glob('src/ruby/bin/**/*')
     s.files += Dir.glob('src/ruby/ext/**/*')
     s.files += Dir.glob('src/ruby/lib/**/*')
-    s.files += Dir.glob('src/ruby/pb/**/*')
+    s.files += Dir.glob('src/ruby/pb/**/*').reject do |f|
+      f.match(%r{^src/ruby/pb/test})
+    end
     s.files += Dir.glob('include/grpc/**/*')
     s.test_files = Dir.glob('src/ruby/spec/**/*')
     s.bindir = 'src/ruby/bin'
@@ -30,7 +32,6 @@
     s.platform      = Gem::Platform::RUBY
 
     s.add_dependency 'google-protobuf', '~> 3.1'
-    s.add_dependency 'googleauth',      '>= 0.5.1', '< 0.7'
     s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0'
 
     s.add_development_dependency 'bundler',            '~> 1.9'
@@ -43,6 +44,7 @@
     s.add_development_dependency 'rspec',              '~> 3.6'
     s.add_development_dependency 'rubocop',            '~> 0.49.1'
     s.add_development_dependency 'signet',             '~> 0.7.0'
+    s.add_development_dependency 'googleauth',         '>= 0.5.1', '< 0.7'
 
     s.extensions = %w(src/ruby/ext/grpc/extconf.rb)
 
diff --git a/test/build/openssl-npn.c b/test/build/openssl-npn.c
deleted file mode 100644
index 9c71382..0000000
--- a/test/build/openssl-npn.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *
- * Copyright 2015 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.
- *
- */
-
-/* This is just a compilation test, to see if we have a version of OpenSSL with
-   NPN support installed. It's not meant to be run, and all of the values and
-   function calls there are non-sensical. The code is only meant to test the
-   presence of symbols, and we're expecting a compilation failure otherwise. */
-
-#include <stdlib.h>
-#include <openssl/ssl.h>
-
-int main() {
-  SSL_get0_next_proto_negotiated(NULL, NULL, NULL);
-  return OPENSSL_NPN_UNSUPPORTED;
-}
diff --git a/test/core/transport/chttp2/hpack_encoder_test.cc b/test/core/transport/chttp2/hpack_encoder_test.cc
index d3ba50a..2a57198 100644
--- a/test/core/transport/chttp2/hpack_encoder_test.cc
+++ b/test/core/transport/chttp2/hpack_encoder_test.cc
@@ -160,6 +160,8 @@
 }
 
 static void test_decode_table_overflow() {
+  // Decrease the default table size to make decode table overflow easier.
+  grpc_chttp2_hpack_compressor_set_max_table_size(&g_compressor, 1024);
   int i;
   char key[3], value[3];
   char* expect;
@@ -170,27 +172,20 @@
       false,
   };
 
-  for (i = 0; i < 114; i++) {
+  for (i = 0; i < 29; i++) {
     encode_int_to_str(i, key);
     encode_int_to_str(i + 1, value);
-
-    if (i + 61 >= 127) {
+    if (i == 0) {
+      // 3fe107 corresponds to the table size update.
       gpr_asprintf(&expect,
-                   "000009 0104 deadbeef ff%02x 40 02%02x%02x 02%02x%02x",
-                   i + 61 - 127, key[0], key[1], value[0], value[1]);
-    } else if (i > 0) {
+                   "00000a 0104 deadbeef 3fe107 40 02%02x%02x 02%02x%02x",
+                   key[0], key[1], value[0], value[1]);
+      verify(params, expect, 1, key, value);
+    } else {
       gpr_asprintf(&expect,
                    "000008 0104 deadbeef %02x 40 02%02x%02x 02%02x%02x",
                    0x80 + 61 + i, key[0], key[1], value[0], value[1]);
-    } else {
-      gpr_asprintf(&expect, "000007 0104 deadbeef 40 02%02x%02x 02%02x%02x",
-                   key[0], key[1], value[0], value[1]);
-    }
-
-    if (i > 0) {
       verify(params, expect, 2, "aa", "ba", key, value);
-    } else {
-      verify(params, expect, 1, key, value);
     }
     gpr_free(expect);
   }
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index 2d43e3e..d6a7046 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -326,7 +326,14 @@
         },
     ],
     'csharp': [
-        #{'v1.0.1': None},
+        {
+            'v1.0.1': {
+                'patch': [
+                    'tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile',
+                    'tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile',
+                ]
+            }
+        },
         {
             'v1.1.4': None
         },
@@ -377,6 +384,7 @@
     'node_v1.4.2': 'node__v1.1.4',
     'node_v1.6.6': 'node__v1.1.4',
     'ruby_v1.0.1': 'ruby__v1.0.1',
+    'csharp_v1.0.1': 'csharp__v1.1.4',
     'csharp_v1.1.4': 'csharp__v1.1.4',
     'csharp_v1.2.5': 'csharp__v1.1.4',
     'python_v1.0.x': 'python__v1.0.x',
diff --git a/tools/interop_matrix/create_matrix_images.py b/tools/interop_matrix/create_matrix_images.py
index ef9f6a5..c2568ef 100755
--- a/tools/interop_matrix/create_matrix_images.py
+++ b/tools/interop_matrix/create_matrix_images.py
@@ -97,6 +97,12 @@
     'reusing the repo can cause git checkout error if you switch '
     'between releases.')
 
+argp.add_argument(
+    '--upload_images',
+    action='store_true',
+    help='If set, images will be uploaded to container registry after building.'
+)
+
 args = argp.parse_args()
 
 
@@ -166,8 +172,10 @@
     """Build all docker images for a language across releases and runtimes."""
     if not args.git_checkout:
         if args.release != 'master':
-            print('WARNING: --release is set but will be ignored\n')
-        releases = ['master']
+            print(
+                'Cannot use --release without also enabling --git_checkout.\n')
+            sys.exit(1)
+        releases = [args.release]
     else:
         if args.release == 'all':
             releases = client_matrix.get_release_tags(lang)
@@ -268,6 +276,13 @@
         sys.exit(1)
     subprocess.check_output(
         ['git', 'apply', patch_file], cwd=stack_base, stderr=subprocess.STDOUT)
+
+    # TODO(jtattermusch): this really would need simplification and refactoring
+    # - "git add" and "git commit" can easily be done in a single command
+    # - it looks like the only reason for the existence of the "files_to_patch"
+    #   entry is to perform "git add" - which is clumsy and fragile.
+    # - we only allow a single patch with name "git_repo.patch". A better design
+    #   would be to allow multiple patches that can have more descriptive names.
     for repo_relative_path in files_to_patch:
         subprocess.check_output(
             ['git', 'add', repo_relative_path],
@@ -334,8 +349,12 @@
 for lang in languages:
     docker_images = build_all_images_for_lang(lang)
     for image in docker_images:
-        jobset.message('START', 'Uploading %s' % image, do_newline=True)
-        # docker image name must be in the format <gcr_path>/<image>:<gcr_tag>
-        assert image.startswith(args.gcr_path) and image.find(':') != -1
-
-        subprocess.call(['gcloud', 'docker', '--', 'push', image])
+        if args.upload_images:
+            jobset.message('START', 'Uploading %s' % image, do_newline=True)
+            # docker image name must be in the format <gcr_path>/<image>:<gcr_tag>
+            assert image.startswith(args.gcr_path) and image.find(':') != -1
+            subprocess.call(['gcloud', 'docker', '--', 'push', image])
+        else:
+            # Uploading (and overwriting images) by default can easily break things.
+            print('Not uploading image %s, run with --upload_images to upload.'
+                  % image)
diff --git a/tools/interop_matrix/patches/csharp_v1.0.1/git_repo.patch b/tools/interop_matrix/patches/csharp_v1.0.1/git_repo.patch
new file mode 100644
index 0000000..e07b9c8
--- /dev/null
+++ b/tools/interop_matrix/patches/csharp_v1.0.1/git_repo.patch
@@ -0,0 +1,81 @@
+diff --git a/third_party/boringssl b/third_party/boringssl
+index c880e42ba1..70ef9596bb 160000
+--- a/third_party/boringssl
++++ b/third_party/boringssl
+@@ -1 +1 @@
+-Subproject commit c880e42ba1c8032d4cdde2aba0541d8a9d9fa2e9
++Subproject commit 70ef9596bbcc11353b9bb8d4e91478694dd21439
+diff --git a/third_party/gflags b/third_party/gflags
+index 05b155ff59..30dbc81fb5 160000
+--- a/third_party/gflags
++++ b/third_party/gflags
+@@ -1 +1 @@
+-Subproject commit 05b155ff59114735ec8cd089f669c4c3d8f59029
++Subproject commit 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e
+diff --git a/third_party/googletest b/third_party/googletest
+index c99458533a..ec44c6c167 160000
+--- a/third_party/googletest
++++ b/third_party/googletest
+@@ -1 +1 @@
+-Subproject commit c99458533a9b4c743ed51537e25989ea55944908
++Subproject commit ec44c6c1675c25b9827aacd08c02433cccde7780
+diff --git a/third_party/protobuf b/third_party/protobuf
+index 1a58673508..b5fbb742af 160000
+--- a/third_party/protobuf
++++ b/third_party/protobuf
+@@ -1 +1 @@
+-Subproject commit 1a586735085e817b1f52e53feec92ce418049f69
++Subproject commit b5fbb742af122b565925987e65c08957739976a7
+diff --git a/third_party/zlib b/third_party/zlib
+index 5089329162..cacf7f1d4e 160000
+--- a/third_party/zlib
++++ b/third_party/zlib
+@@ -1 +1 @@
+-Subproject commit 50893291621658f355bc5b4d450a8d06a563053d
++Subproject commit cacf7f1d4e3d44d871b605da3b647f07d718623f
+diff --git a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
+index da1d2c645e..f405994293 100644
+--- a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
++++ b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
+@@ -67,11 +67,10 @@ RUN apt-get update && apt-get install -y time && apt-get clean
+ # C# dependencies
+ 
+ # Update to a newer version of mono
+-RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+-RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list
++RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
++RUN echo "deb http://download.mono-project.com/repo/debian wheezy/snapshots/4.6 main" | tee /etc/apt/sources.list.d/official.list
+ RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
+ RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
+-RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
+ 
+ # Install dependencies
+ RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \
+diff --git a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
+index 65f67d3650..26223753ed 100644
+--- a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
++++ b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
+@@ -82,11 +82,10 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0a2
+ # C# dependencies
+ 
+ # Update to a newer version of mono
+-RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
+-RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list
++RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
++RUN echo "deb http://download.mono-project.com/repo/debian jessie main" | tee /etc/apt/sources.list.d/mono-official.list
+ RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
+ RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
+-RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list
+ 
+ # Install dependencies
+ RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \
+@@ -99,7 +98,8 @@ RUN nuget update -self
+ 
+ # Install dotnet SDK based on https://www.microsoft.com/net/core#debian
+ RUN apt-get update && apt-get install -y curl libunwind8 gettext
+-RUN curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=809130
++# https://github.com/dotnet/core/blob/master/release-notes/download-archives/1.0.1-preview2-download.md
++RUN curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=827530
+ RUN mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet
+ RUN ln -s /opt/dotnet/dotnet /usr/local/bin
+ 
diff --git a/tools/interop_matrix/run_interop_matrix_tests.py b/tools/interop_matrix/run_interop_matrix_tests.py
index eb8b7d6..9d44234 100755
--- a/tools/interop_matrix/run_interop_matrix_tests.py
+++ b/tools/interop_matrix/run_interop_matrix_tests.py
@@ -116,6 +116,10 @@
             return {}
         releases = [args.release]
 
+    # TODO(jtattermusch): why do we need to query the existing images/tags?
+    # From LANG_RUNTIME_MATRIX and LANG_RELEASE_MATRIX it should be obvious
+    # which tags we want to test - and it should be an error if they are
+    # missing.
     # Images tuples keyed by runtime.
     images = {}
     for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]:
diff --git a/tools/run_tests/sanity/check_sources_and_headers.py b/tools/run_tests/sanity/check_sources_and_headers.py
deleted file mode 100755
index 57ae5c5..0000000
--- a/tools/run_tests/sanity/check_sources_and_headers.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 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.
-
-from __future__ import print_function
-
-import json
-import os
-import re
-import sys
-
-root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
-with open(
-        os.path.join(root, 'tools', 'run_tests', 'generated',
-                     'sources_and_headers.json')) as f:
-    js = json.loads(f.read())
-
-re_inc1 = re.compile(r'^#\s*include\s*"([^"]*)"')
-assert re_inc1.match('#include "foo"').group(1) == 'foo'
-re_inc2 = re.compile(r'^#\s*include\s*<((grpc|grpc\+\+)/[^"]*)>')
-assert re_inc2.match('#include <grpc++/foo>').group(1) == 'grpc++/foo'
-
-
-def get_target(name):
-    for target in js:
-        if target['name'] == name:
-            return target
-    assert False, 'no target %s' % name
-
-
-def get_headers_transitive():
-    """Computes set of headers transitively provided by each target"""
-    target_headers_transitive = {}
-    for target in js:
-        target_name = target['name']
-        assert not target_headers_transitive.has_key(target_name)
-        target_headers_transitive[target_name] = set(target['headers'])
-
-    # Make sure each target's transitive headers contain those
-    # of their dependencies. If not, add them and continue doing
-    # so until we get a full pass over all targets without any updates.
-    closure_changed = True
-    while closure_changed:
-        closure_changed = False
-        for target in js:
-            target_name = target['name']
-            for dep in target['deps']:
-                headers = target_headers_transitive[target_name]
-                old_count = len(headers)
-                headers.update(target_headers_transitive[dep])
-                if old_count != len(headers):
-                    closure_changed = True
-    return target_headers_transitive
-
-
-# precompute transitive closure of headers provided by each target
-target_headers_transitive = get_headers_transitive()
-
-
-def target_has_header(target, name):
-    if name in target_headers_transitive[target['name']]:
-        return True
-    if name.startswith('absl/'):
-        return True
-    if name in [
-            'src/core/lib/profiling/stap_probes.h',
-            'src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h'
-    ]:
-        return True
-    return False
-
-
-def produces_object(name):
-    return os.path.splitext(name)[1] in ['.c', '.cc']
-
-
-c_ish = {}
-obj_producer_to_source = {'c': c_ish, 'c++': c_ish, 'csharp': {}}
-
-errors = 0
-for target in js:
-    if not target['third_party']:
-        for fn in target['src']:
-            with open(os.path.join(root, fn)) as f:
-                src = f.read().splitlines()
-            for line in src:
-                m = re_inc1.match(line)
-                if m:
-                    if not target_has_header(target, m.group(1)):
-                        print(
-                            'target %s (%s) does not name header %s as a dependency'
-                            % (target['name'], fn, m.group(1)))
-                        errors += 1
-                m = re_inc2.match(line)
-                if m:
-                    if not target_has_header(target, 'include/' + m.group(1)):
-                        print(
-                            'target %s (%s) does not name header %s as a dependency'
-                            % (target['name'], fn, m.group(1)))
-                        errors += 1
-    if target['type'] in ['lib', 'filegroup']:
-        for fn in target['src']:
-            language = target['language']
-            if produces_object(fn):
-                obj_base = os.path.splitext(os.path.basename(fn))[0]
-                if obj_base in obj_producer_to_source[language]:
-                    if obj_producer_to_source[language][obj_base] != fn:
-                        print(
-                            'target %s (%s) produces an aliased object file with %s'
-                            % (target['name'], fn,
-                               obj_producer_to_source[language][obj_base]))
-                else:
-                    obj_producer_to_source[language][obj_base] = fn
-
-assert errors == 0
diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml
index a15473d..ac0d4c7 100644
--- a/tools/run_tests/sanity/sanity_tests.yaml
+++ b/tools/run_tests/sanity/sanity_tests.yaml
@@ -2,7 +2,6 @@
 - script: tools/run_tests/sanity/check_bazel_workspace.py
 - script: tools/run_tests/sanity/check_cache_mk.sh
 - script: tools/run_tests/sanity/check_owners.sh
-- script: tools/run_tests/sanity/check_sources_and_headers.py
 - script: tools/run_tests/sanity/check_shellcheck.sh
 - script: tools/run_tests/sanity/check_submodules.sh
 - script: tools/run_tests/sanity/check_test_filtering.py