Merge pull request #10662 from sreecha/cq_mpsc_based

grpc_mpsc queue based completion queue
diff --git a/BUILD b/BUILD
index 0a188a8..201b358 100644
--- a/BUILD
+++ b/BUILD
@@ -33,13 +33,19 @@
 
 exports_files(["LICENSE"])
 
-package(default_visibility = ["//visibility:public"])
+package(
+    default_visibility = ["//visibility:public"],
+    features = [
+        "-layering_check",
+        "-parse_headers",
+    ],
+)
 
 load(
     "//bazel:grpc_build_system.bzl",
     "grpc_cc_library",
     "grpc_proto_plugin",
-    "grpc_cc_libraries",
+    "grpc_generate_one_off_targets",
 )
 
 # This should be updated along with build.yaml
@@ -58,48 +64,35 @@
     ],
 )
 
-grpc_cc_libraries(
+grpc_cc_library(
+    name = "grpc_unsecure",
     srcs = [
         "src/core/lib/surface/init.c",
-    ],
-    additional_dep_list = [
-        [
-            "grpc_secure",
-            "grpc_resolver_dns_ares",
-            "grpc_lb_policy_grpclb_secure",
-            "grpc_transport_chttp2_client_secure",
-            "grpc_transport_chttp2_server_secure",
-        ],
-        [],
-    ],
-    additional_src_list = [
-        [
-            "src/core/plugin_registry/grpc_plugin_registry.c",
-        ],
-        [
-            "src/core/lib/surface/init_unsecure.c",
-            "src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
-        ],
+        "src/core/lib/surface/init_unsecure.c",
+        "src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
     ],
     language = "c",
-    name_list = [
-        "grpc",
-        "grpc_unsecure",
-    ],
     standalone = True,
     deps = [
-        "census",
-        "grpc_base",
-        "grpc_deadline_filter",
-        "grpc_lb_policy_pick_first",
-        "grpc_lb_policy_round_robin",
-        "grpc_load_reporting",
-        "grpc_max_age_filter",
-        "grpc_message_size_filter",
-        "grpc_resolver_dns_native",
-        "grpc_resolver_sockaddr",
-        "grpc_transport_chttp2_client_insecure",
-        "grpc_transport_chttp2_server_insecure",
+        "grpc_common",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc",
+    srcs = [
+        "src/core/lib/surface/init.c",
+        "src/core/plugin_registry/grpc_plugin_registry.c",
+    ],
+    language = "c",
+    standalone = True,
+    deps = [
+        "grpc_common",
+        "grpc_lb_policy_grpclb_secure",
+        "grpc_resolver_dns_ares",
+        "grpc_secure",
+        "grpc_transport_chttp2_client_secure",
+        "grpc_transport_chttp2_server_secure",
     ],
 )
 
@@ -457,7 +450,7 @@
 )
 
 grpc_cc_library(
-    name = "grpc_base",
+    name = "grpc_base_c",
     srcs = [
         "src/core/lib/channel/channel_args.c",
         "src/core/lib/channel/channel_stack.c",
@@ -479,11 +472,10 @@
         "src/core/lib/iomgr/endpoint_pair_windows.c",
         "src/core/lib/iomgr/error.c",
         "src/core/lib/iomgr/ev_epoll1_linux.c",
-        "src/core/lib/iomgr/ev_epollsig_linux.c",
-        "src/core/lib/iomgr/ev_epollex_linux.c",
-        "src/core/lib/iomgr/is_epollexclusive_available.c",
-        "src/core/lib/iomgr/ev_epoll_thread_pool_linux.c",
         "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c",
+        "src/core/lib/iomgr/ev_epoll_thread_pool_linux.c",
+        "src/core/lib/iomgr/ev_epollex_linux.c",
+        "src/core/lib/iomgr/ev_epollsig_linux.c",
         "src/core/lib/iomgr/ev_poll_posix.c",
         "src/core/lib/iomgr/ev_posix.c",
         "src/core/lib/iomgr/exec_ctx.c",
@@ -493,6 +485,7 @@
         "src/core/lib/iomgr/iomgr_posix.c",
         "src/core/lib/iomgr/iomgr_uv.c",
         "src/core/lib/iomgr/iomgr_windows.c",
+        "src/core/lib/iomgr/is_epollexclusive_available.c",
         "src/core/lib/iomgr/load_file.c",
         "src/core/lib/iomgr/lockfree_event.c",
         "src/core/lib/iomgr/network_status_tracker.c",
@@ -528,8 +521,8 @@
         "src/core/lib/iomgr/tcp_windows.c",
         "src/core/lib/iomgr/time_averaged_stats.c",
         "src/core/lib/iomgr/timer_generic.c",
-        "src/core/lib/iomgr/timer_manager.c",
         "src/core/lib/iomgr/timer_heap.c",
+        "src/core/lib/iomgr/timer_manager.c",
         "src/core/lib/iomgr/timer_uv.c",
         "src/core/lib/iomgr/udp_server.c",
         "src/core/lib/iomgr/unix_sockets_posix.c",
@@ -566,7 +559,6 @@
         "src/core/lib/surface/completion_queue.c",
         "src/core/lib/surface/completion_queue_factory.c",
         "src/core/lib/surface/event_string.c",
-        "src/core/lib/surface/lame_client.cc",
         "src/core/lib/surface/metadata_array.c",
         "src/core/lib/surface/server.c",
         "src/core/lib/surface/validate_metadata.c",
@@ -606,12 +598,10 @@
         "src/core/lib/iomgr/error.h",
         "src/core/lib/iomgr/error_internal.h",
         "src/core/lib/iomgr/ev_epoll1_linux.h",
-        "src/core/lib/iomgr/ev_epollsig_linux.h",
-        "src/core/lib/iomgr/ev_epollex_linux.h",
-        "src/core/lib/iomgr/is_epollexclusive_available.h",
-        "src/core/lib/iomgr/sys_epoll_wrapper.h",
-        "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h",
         "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h",
+        "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h",
+        "src/core/lib/iomgr/ev_epollex_linux.h",
+        "src/core/lib/iomgr/ev_epollsig_linux.h",
         "src/core/lib/iomgr/ev_poll_posix.h",
         "src/core/lib/iomgr/ev_posix.h",
         "src/core/lib/iomgr/exec_ctx.h",
@@ -620,6 +610,7 @@
         "src/core/lib/iomgr/iomgr.h",
         "src/core/lib/iomgr/iomgr_internal.h",
         "src/core/lib/iomgr/iomgr_posix.h",
+        "src/core/lib/iomgr/is_epollexclusive_available.h",
         "src/core/lib/iomgr/load_file.h",
         "src/core/lib/iomgr/lockfree_event.h",
         "src/core/lib/iomgr/network_status_tracker.h",
@@ -641,6 +632,7 @@
         "src/core/lib/iomgr/socket_utils.h",
         "src/core/lib/iomgr/socket_utils_posix.h",
         "src/core/lib/iomgr/socket_windows.h",
+        "src/core/lib/iomgr/sys_epoll_wrapper.h",
         "src/core/lib/iomgr/tcp_client.h",
         "src/core/lib/iomgr/tcp_client_posix.h",
         "src/core/lib/iomgr/tcp_posix.h",
@@ -651,8 +643,8 @@
         "src/core/lib/iomgr/time_averaged_stats.h",
         "src/core/lib/iomgr/timer.h",
         "src/core/lib/iomgr/timer_generic.h",
-        "src/core/lib/iomgr/timer_manager.h",
         "src/core/lib/iomgr/timer_heap.h",
+        "src/core/lib/iomgr/timer_manager.h",
         "src/core/lib/iomgr/timer_uv.h",
         "src/core/lib/iomgr/udp_server.h",
         "src/core/lib/iomgr/unix_sockets_posix.h",
@@ -723,6 +715,36 @@
 )
 
 grpc_cc_library(
+    name = "grpc_base",
+    srcs = [
+        "src/core/lib/surface/lame_client.cc",
+    ],
+    language = "c++",
+    deps = [
+        "grpc_base_c",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_common",
+    deps = [
+        "grpc_base",
+        # standard plugins
+        "census",
+        "grpc_deadline_filter",
+        "grpc_lb_policy_pick_first",
+        "grpc_lb_policy_round_robin",
+        "grpc_load_reporting",
+        "grpc_max_age_filter",
+        "grpc_message_size_filter",
+        "grpc_resolver_dns_native",
+        "grpc_resolver_sockaddr",
+        "grpc_transport_chttp2_client_insecure",
+        "grpc_transport_chttp2_server_insecure",
+    ]
+)
+
+grpc_cc_library(
     name = "grpc_client_channel",
     srcs = [
         "src/core/ext/filters/client_channel/channel_connectivity.c",
@@ -1260,111 +1282,124 @@
     ],
 )
 
-grpc_cc_libraries(
-    srcs = [
-        "src/cpp/client/channel_cc.cc",
-        "src/cpp/client/client_context.cc",
-        "src/cpp/client/create_channel.cc",
-        "src/cpp/client/create_channel_internal.cc",
-        "src/cpp/client/create_channel_posix.cc",
-        "src/cpp/client/credentials_cc.cc",
-        "src/cpp/client/generic_stub.cc",
-        "src/cpp/common/channel_arguments.cc",
-        "src/cpp/common/channel_filter.cc",
-        "src/cpp/common/completion_queue_cc.cc",
-        "src/cpp/common/core_codegen.cc",
-        "src/cpp/common/resource_quota_cc.cc",
-        "src/cpp/common/rpc_method.cc",
-        "src/cpp/common/version_cc.cc",
-        "src/cpp/server/async_generic_service.cc",
-        "src/cpp/server/channel_argument_option.cc",
-        "src/cpp/server/create_default_thread_pool.cc",
-        "src/cpp/server/dynamic_thread_pool.cc",
-        "src/cpp/server/health/default_health_check_service.cc",
-        "src/cpp/server/health/health.pb.c",
-        "src/cpp/server/health/health_check_service.cc",
-        "src/cpp/server/health/health_check_service_server_builder_option.cc",
-        "src/cpp/server/server_builder.cc",
-        "src/cpp/server/server_cc.cc",
-        "src/cpp/server/server_context.cc",
-        "src/cpp/server/server_credentials.cc",
-        "src/cpp/server/server_posix.cc",
-        "src/cpp/thread_manager/thread_manager.cc",
-        "src/cpp/util/byte_buffer_cc.cc",
-        "src/cpp/util/slice_cc.cc",
-        "src/cpp/util/status.cc",
-        "src/cpp/util/string_ref.cc",
-        "src/cpp/util/time_cc.cc",
-    ],
-    hdrs = [
-        "src/cpp/client/create_channel_internal.h",
-        "src/cpp/common/channel_filter.h",
-        "src/cpp/server/dynamic_thread_pool.h",
-        "src/cpp/server/health/default_health_check_service.h",
-        "src/cpp/server/health/health.pb.h",
-        "src/cpp/server/thread_pool_interface.h",
-        "src/cpp/thread_manager/thread_manager.h",
-    ],
-    additional_dep_list = [
-        ["grpc"],
-        ["grpc_unsecure"],
-    ],
+# TODO(ctiller): layer grpc atop grpc_unsecure, layer grpc++ atop grpc++_unsecure
+GRPCXX_SRCS = [
+    "src/cpp/client/channel_cc.cc",
+    "src/cpp/client/client_context.cc",
+    "src/cpp/client/create_channel.cc",
+    "src/cpp/client/create_channel_internal.cc",
+    "src/cpp/client/create_channel_posix.cc",
+    "src/cpp/client/credentials_cc.cc",
+    "src/cpp/client/generic_stub.cc",
+    "src/cpp/common/channel_arguments.cc",
+    "src/cpp/common/channel_filter.cc",
+    "src/cpp/common/completion_queue_cc.cc",
+    "src/cpp/common/core_codegen.cc",
+    "src/cpp/common/resource_quota_cc.cc",
+    "src/cpp/common/rpc_method.cc",
+    "src/cpp/common/version_cc.cc",
+    "src/cpp/server/async_generic_service.cc",
+    "src/cpp/server/channel_argument_option.cc",
+    "src/cpp/server/create_default_thread_pool.cc",
+    "src/cpp/server/dynamic_thread_pool.cc",
+    "src/cpp/server/health/default_health_check_service.cc",
+    "src/cpp/server/health/health.pb.c",
+    "src/cpp/server/health/health_check_service.cc",
+    "src/cpp/server/health/health_check_service_server_builder_option.cc",
+    "src/cpp/server/server_builder.cc",
+    "src/cpp/server/server_cc.cc",
+    "src/cpp/server/server_context.cc",
+    "src/cpp/server/server_credentials.cc",
+    "src/cpp/server/server_posix.cc",
+    "src/cpp/thread_manager/thread_manager.cc",
+    "src/cpp/util/byte_buffer_cc.cc",
+    "src/cpp/util/slice_cc.cc",
+    "src/cpp/util/status.cc",
+    "src/cpp/util/string_ref.cc",
+    "src/cpp/util/time_cc.cc",
+]
+
+GRPCXX_HDRS = [
+    "src/cpp/client/create_channel_internal.h",
+    "src/cpp/common/channel_filter.h",
+    "src/cpp/server/dynamic_thread_pool.h",
+    "src/cpp/server/health/default_health_check_service.h",
+    "src/cpp/server/health/health.pb.h",
+    "src/cpp/server/thread_pool_interface.h",
+    "src/cpp/thread_manager/thread_manager.h",
+]
+
+GRPCXX_PUBLIC_HDRS = [
+    "include/grpc++/alarm.h",
+    "include/grpc++/channel.h",
+    "include/grpc++/client_context.h",
+    "include/grpc++/completion_queue.h",
+    "include/grpc++/create_channel.h",
+    "include/grpc++/create_channel_posix.h",
+    "include/grpc++/ext/health_check_service_server_builder_option.h",
+    "include/grpc++/generic/async_generic_service.h",
+    "include/grpc++/generic/generic_stub.h",
+    "include/grpc++/grpc++.h",
+    "include/grpc++/health_check_service_interface.h",
+    "include/grpc++/impl/call.h",
+    "include/grpc++/impl/channel_argument_option.h",
+    "include/grpc++/impl/client_unary_call.h",
+    "include/grpc++/impl/codegen/core_codegen.h",
+    "include/grpc++/impl/grpc_library.h",
+    "include/grpc++/impl/method_handler_impl.h",
+    "include/grpc++/impl/rpc_method.h",
+    "include/grpc++/impl/rpc_service_method.h",
+    "include/grpc++/impl/serialization_traits.h",
+    "include/grpc++/impl/server_builder_option.h",
+    "include/grpc++/impl/server_builder_plugin.h",
+    "include/grpc++/impl/server_initializer.h",
+    "include/grpc++/impl/service_type.h",
+    "include/grpc++/impl/sync_cxx11.h",
+    "include/grpc++/impl/sync_no_cxx11.h",
+    "include/grpc++/resource_quota.h",
+    "include/grpc++/security/auth_context.h",
+    "include/grpc++/security/auth_metadata_processor.h",
+    "include/grpc++/security/credentials.h",
+    "include/grpc++/security/server_credentials.h",
+    "include/grpc++/server.h",
+    "include/grpc++/server_builder.h",
+    "include/grpc++/server_context.h",
+    "include/grpc++/server_posix.h",
+    "include/grpc++/support/async_stream.h",
+    "include/grpc++/support/async_unary_call.h",
+    "include/grpc++/support/byte_buffer.h",
+    "include/grpc++/support/channel_arguments.h",
+    "include/grpc++/support/config.h",
+    "include/grpc++/support/slice.h",
+    "include/grpc++/support/status.h",
+    "include/grpc++/support/status_code_enum.h",
+    "include/grpc++/support/string_ref.h",
+    "include/grpc++/support/stub_options.h",
+    "include/grpc++/support/sync_stream.h",
+    "include/grpc++/support/time.h",
+]
+
+grpc_cc_library(
+    name = "grpc++_base",
+    hdrs = GRPCXX_HDRS,
+    srcs = GRPCXX_SRCS,
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
     language = "c++",
-    name_list = [
-        "grpc++_base",
-        "grpc++_base_unsecure",
-    ],
-    public_hdrs = [
-        "include/grpc++/alarm.h",
-        "include/grpc++/channel.h",
-        "include/grpc++/client_context.h",
-        "include/grpc++/completion_queue.h",
-        "include/grpc++/create_channel.h",
-        "include/grpc++/create_channel_posix.h",
-        "include/grpc++/ext/health_check_service_server_builder_option.h",
-        "include/grpc++/generic/async_generic_service.h",
-        "include/grpc++/generic/generic_stub.h",
-        "include/grpc++/grpc++.h",
-        "include/grpc++/health_check_service_interface.h",
-        "include/grpc++/impl/call.h",
-        "include/grpc++/impl/channel_argument_option.h",
-        "include/grpc++/impl/client_unary_call.h",
-        "include/grpc++/impl/codegen/core_codegen.h",
-        "include/grpc++/impl/grpc_library.h",
-        "include/grpc++/impl/method_handler_impl.h",
-        "include/grpc++/impl/rpc_method.h",
-        "include/grpc++/impl/rpc_service_method.h",
-        "include/grpc++/impl/serialization_traits.h",
-        "include/grpc++/impl/server_builder_option.h",
-        "include/grpc++/impl/server_builder_plugin.h",
-        "include/grpc++/impl/server_initializer.h",
-        "include/grpc++/impl/service_type.h",
-        "include/grpc++/impl/sync_cxx11.h",
-        "include/grpc++/impl/sync_no_cxx11.h",
-        "include/grpc++/resource_quota.h",
-        "include/grpc++/security/auth_context.h",
-        "include/grpc++/security/auth_metadata_processor.h",
-        "include/grpc++/security/credentials.h",
-        "include/grpc++/security/server_credentials.h",
-        "include/grpc++/server.h",
-        "include/grpc++/server_builder.h",
-        "include/grpc++/server_context.h",
-        "include/grpc++/server_posix.h",
-        "include/grpc++/support/async_stream.h",
-        "include/grpc++/support/async_unary_call.h",
-        "include/grpc++/support/byte_buffer.h",
-        "include/grpc++/support/channel_arguments.h",
-        "include/grpc++/support/config.h",
-        "include/grpc++/support/slice.h",
-        "include/grpc++/support/status.h",
-        "include/grpc++/support/status_code_enum.h",
-        "include/grpc++/support/string_ref.h",
-        "include/grpc++/support/stub_options.h",
-        "include/grpc++/support/sync_stream.h",
-        "include/grpc++/support/time.h",
-    ],
     deps = [
         "grpc++_codegen_base",
+        "grpc",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc++_base_unsecure",
+    hdrs = GRPCXX_HDRS,
+    srcs = GRPCXX_SRCS,
+    public_hdrs = GRPCXX_PUBLIC_HDRS,
+    language = "c++",
+    deps = [
+        "grpc++_codegen_base",
+        "grpc_unsecure",
     ],
 )
 
@@ -1459,3 +1494,16 @@
         "//src/proto/grpc/reflection/v1alpha:reflection_proto",
     ],
 )
+
+grpc_cc_library(
+    name = "grpc++_test",
+    public_hdrs = [
+        "include/grpc++/test/mock_stream.h",
+        "include/grpc++/test/server_context_test_spouse.h",
+    ],
+    deps = [
+        ":grpc++",
+    ],
+)
+
+grpc_generate_one_off_targets()
diff --git a/WORKSPACE b/WORKSPACE
index a78a889..82ea99f 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -5,7 +5,7 @@
 
 bind(
     name = "libssl",
-    actual = "@submodule_boringssl//:ssl",
+    actual = "@boringssl//:ssl",
 )
 
 bind(
@@ -49,7 +49,7 @@
 )
 
 local_repository(
-    name = "submodule_boringssl",
+    name = "boringssl",
     path = "third_party/boringssl-with-bazel",
 )
 
diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl
index a104fa0..0f66edb 100644
--- a/bazel/grpc_build_system.bzl
+++ b/bazel/grpc_build_system.bzl
@@ -32,8 +32,15 @@
 # the BUILD file for gRPC. It contains the mapping for the template system we
 # use to generate other platform's build system files.
 #
+# Please consider that there should be a high bar for additions and changes to
+# this file.
+# Each rule listed must be re-written for Google's internal build system, and
+# each change must be ported from one to the other.
+#
 
-def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [], external_deps = [], deps = [], standalone = False, language = "C++"):
+def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
+                    external_deps = [], deps = [], standalone = False,
+                    language = "C++", testonly = False, visibility = None):
   copts = []
   if language.upper() == "C":
     copts = ["-std=c99"]
@@ -43,28 +50,14 @@
     hdrs = hdrs + public_hdrs,
     deps = deps + ["//external:" + dep for dep in external_deps],
     copts = copts,
+    visibility = visibility,
+    testonly = testonly,
     linkopts = ["-pthread"],
     includes = [
         "include"
     ]
   )
 
-def grpc_cc_libraries(name_list, additional_src_list = [], additional_dep_list = [], srcs = [], public_hdrs = [], hdrs = [], external_deps = [], deps = [], standalone = False, language="C++"):
-  names = len(name_list)
-  asl = additional_src_list + [[]]*(names - len(additional_src_list))
-  adl = additional_dep_list + [[]]*(names - len(additional_dep_list))
-  for i in range(names):
-    grpc_cc_library(
-      name = name_list[i],
-      srcs = srcs + asl[i],
-      hdrs = hdrs,
-      public_hdrs = public_hdrs,
-      deps = deps + adl[i],
-      external_deps = external_deps,
-      standalone = standalone,
-      language = language
-    )
-
 def grpc_proto_plugin(name, srcs = [], deps = []):
   native.cc_binary(
     name = name,
@@ -86,3 +79,42 @@
     generate_mock = generate_mock,
   )
 
+def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++"):
+  copts = []
+  if language.upper() == "C":
+    copts = ["-std=c99"]
+  native.cc_test(
+    name = name,
+    srcs = srcs,
+    args = args,
+    data = data,
+    deps = deps + ["//external:" + dep for dep in external_deps],
+    copts = copts,
+    linkopts = ["-pthread"],
+  )
+
+def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False):
+  copts = []
+  if language.upper() == "C":
+    copts = ["-std=c99"]
+  native.cc_binary(
+    name = name,
+    srcs = srcs,
+    args = args,
+    data = data,
+    testonly = testonly,
+    linkshared = linkshared,
+    deps = deps + ["//external:" + dep for dep in external_deps],
+    copts = copts,
+    linkopts = ["-pthread"],
+  )
+
+def grpc_generate_one_off_targets():
+    pass
+
+def grpc_sh_test(name, srcs, args = [], data = []):
+    native.sh_test(
+        name = name,
+        srcs = srcs,
+        args = args,
+        data = data)
diff --git a/build.yaml b/build.yaml
index 942b727..95f6788 100644
--- a/build.yaml
+++ b/build.yaml
@@ -4581,6 +4581,7 @@
   - src/node/src/client.js
   - src/node/src/common.js
   - src/node/src/credentials.js
+  - src/node/src/constants.js
   - src/node/src/grpc_extension.js
   - src/node/src/metadata.js
   - src/node/src/server.js
diff --git a/examples/BUILD b/examples/BUILD
index 382713e..bd2d3c3 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -54,13 +54,13 @@
 cc_binary(
     name = "greeter_client",
     srcs = ["cpp/helloworld/greeter_client.cc"],
-    deps = ["helloworld"],
     defines = ["BAZEL_BUILD"],
+    deps = [":helloworld"],
 )
 
 cc_binary(
     name = "greeter_server",
     srcs = ["cpp/helloworld/greeter_server.cc"],
-    deps = ["helloworld"],
     defines = ["BAZEL_BUILD"],
+    deps = [":helloworld"],
 )
diff --git a/src/core/lib/iomgr/error.c b/src/core/lib/iomgr/error.c
index 5f2c989..685581b 100644
--- a/src/core/lib/iomgr/error.c
+++ b/src/core/lib/iomgr/error.c
@@ -769,7 +769,7 @@
               GRPC_ERROR_INT_ERRNO, err),
           GRPC_ERROR_STR_OS_ERROR,
           grpc_slice_from_static_string(strerror(err))),
-      GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string(call_name));
+      GRPC_ERROR_STR_SYSCALL, grpc_slice_from_copied_string(call_name));
 }
 
 #ifdef GPR_WINDOWS
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index 2f89aa3..7c93bb8 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -686,6 +686,7 @@
         StringFromCopiedSlice(call_details_.method);
     static_cast<GenericServerContext*>(context_)->host_ =
         StringFromCopiedSlice(call_details_.host);
+    context_->deadline_ = call_details_.deadline;
   }
   grpc_slice_unref(call_details_.method);
   grpc_slice_unref(call_details_.host);
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 7e0f3f0..c086500 100755
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -19,27 +19,27 @@
 
   <ItemGroup>
     <EmbeddedResource Include="..\..\..\etc\roots.pem" />
-    <Content Include="..\nativelibs\macosx_x64\libgrpc_csharp_ext.dylib">
+    <Content Include="..\nativelibs\csharp_ext_macos_x64\libgrpc_csharp_ext.dylib">
       <PackagePath>runtimes/osx/native/libgrpc_csharp_ext.x64.dylib</PackagePath>
       <Pack>true</Pack>
     </Content>
-    <Content Include="..\nativelibs\macosx_x86\libgrpc_csharp_ext.dylib">
+    <Content Include="..\nativelibs\csharp_ext_macos_x86\libgrpc_csharp_ext.dylib">
       <PackagePath>runtimes/osx/native/libgrpc_csharp_ext.x86.dylib</PackagePath>
       <Pack>true</Pack>
     </Content>
-    <Content Include="..\nativelibs\linux_x64\libgrpc_csharp_ext.so">
+    <Content Include="..\nativelibs\csharp_ext_linux_x64\libgrpc_csharp_ext.so">
       <PackagePath>runtimes/linux/native/libgrpc_csharp_ext.x64.so</PackagePath>
       <Pack>true</Pack>
     </Content>
-    <Content Include="..\nativelibs\linux_x86\libgrpc_csharp_ext.so">
+    <Content Include="..\nativelibs\csharp_ext_linux_x86\libgrpc_csharp_ext.so">
       <PackagePath>runtimes/linux/native/libgrpc_csharp_ext.x86.so</PackagePath>
       <Pack>true</Pack>
     </Content>
-    <Content Include="..\nativelibs\windows_x64\grpc_csharp_ext.dll">
+    <Content Include="..\nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll">
       <PackagePath>runtimes/win/native/grpc_csharp_ext.x64.dll</PackagePath>
       <Pack>true</Pack>
     </Content>
-    <Content Include="..\nativelibs\windows_x86\grpc_csharp_ext.dll">
+    <Content Include="..\nativelibs\csharp_ext_windows_x86\grpc_csharp_ext.dll">
       <PackagePath>runtimes/win/native/grpc_csharp_ext.x86.dll</PackagePath>
       <Pack>true</Pack>
     </Content>
diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include
index 6af2af1..8388bfd 100755
--- a/src/csharp/Grpc.Core/Version.csproj.include
+++ b/src/csharp/Grpc.Core/Version.csproj.include
@@ -2,6 +2,6 @@
 <Project>
   <PropertyGroup>
     <GrpcCsharpVersion>1.4.0-dev</GrpcCsharpVersion>
-    <GoogleProtobufVersion>3.2.0</GoogleProtobufVersion>
+    <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion>
   </PropertyGroup>
 </Project>
diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec
index ba4e1d6..0cae5572 100644
--- a/src/csharp/Grpc.Tools.nuspec
+++ b/src/csharp/Grpc.Tools.nuspec
@@ -17,17 +17,17 @@
   </metadata>
   <files>
     <!-- forward slashes in src path enable building on Linux -->
-    <file src="protoc_plugins/windows_x86/protoc.exe" target="tools/windows_x86/protoc.exe" />
-    <file src="protoc_plugins/windows_x86/grpc_csharp_plugin.exe" target="tools/windows_x86/grpc_csharp_plugin.exe" />
-    <file src="protoc_plugins/windows_x64/protoc.exe" target="tools/windows_x64/protoc.exe" />
-    <file src="protoc_plugins/windows_x64/grpc_csharp_plugin.exe" target="tools/windows_x64/grpc_csharp_plugin.exe" />
-    <file src="protoc_plugins/linux_x86/protoc" target="tools/linux_x86/protoc" />
-    <file src="protoc_plugins/linux_x86/grpc_csharp_plugin" target="tools/linux_x86/grpc_csharp_plugin" />
-    <file src="protoc_plugins/linux_x64/protoc" target="tools/linux_x64/protoc" />
-    <file src="protoc_plugins/linux_x64/grpc_csharp_plugin" target="tools/linux_x64/grpc_csharp_plugin" />
-    <file src="protoc_plugins/macosx_x86/protoc" target="tools/macosx_x86/protoc" />
-    <file src="protoc_plugins/macosx_x86/grpc_csharp_plugin" target="tools/macosx_x86/grpc_csharp_plugin" />
-    <file src="protoc_plugins/macosx_x64/protoc" target="tools/macosx_x64/protoc" />
-    <file src="protoc_plugins/macosx_x64/grpc_csharp_plugin" target="tools/macosx_x64/grpc_csharp_plugin" />
+    <file src="protoc_plugins/protoc_windows_x86/protoc.exe" target="tools/windows_x86/protoc.exe" />
+    <file src="protoc_plugins/protoc_windows_x86/grpc_csharp_plugin.exe" target="tools/windows_x86/grpc_csharp_plugin.exe" />
+    <file src="protoc_plugins/protoc_windows_x64/protoc.exe" target="tools/windows_x64/protoc.exe" />
+    <file src="protoc_plugins/protoc_windows_x64/grpc_csharp_plugin.exe" target="tools/windows_x64/grpc_csharp_plugin.exe" />
+    <file src="protoc_plugins/protoc_linux_x86/protoc" target="tools/linux_x86/protoc" />
+    <file src="protoc_plugins/protoc_linux_x86/grpc_csharp_plugin" target="tools/linux_x86/grpc_csharp_plugin" />
+    <file src="protoc_plugins/protoc_linux_x64/protoc" target="tools/linux_x64/protoc" />
+    <file src="protoc_plugins/protoc_linux_x64/grpc_csharp_plugin" target="tools/linux_x64/grpc_csharp_plugin" />
+    <file src="protoc_plugins/protoc_macos_x86/protoc" target="tools/macosx_x86/protoc" />
+    <file src="protoc_plugins/protoc_macos_x86/grpc_csharp_plugin" target="tools/macosx_x86/grpc_csharp_plugin" />
+    <file src="protoc_plugins/protoc_macos_x64/protoc" target="tools/macosx_x64/protoc" />
+    <file src="protoc_plugins/protoc_macos_x64/grpc_csharp_plugin" target="tools/macosx_x64/grpc_csharp_plugin" />
   </files>
 </package>
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index 673642e..aa8a8d3 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -36,29 +36,20 @@
 
 set -ex
 
-mkdir -p ..\..\artifacts\
+mkdir ..\..\artifacts
 
 @rem Collect the artifacts built by the previous build step if running on Jenkins
-@rem TODO(jtattermusch): is there a better way to do this?
-xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* nativelibs\windows_x86\
-xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* nativelibs\windows_x64\
-xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* nativelibs\linux_x86\
-xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* nativelibs\linux_x64\
-xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x86\
-xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x64\
+mkdir nativelibs
+powershell -Command "cp -r ..\..\platform=*\artifacts\csharp_ext_* nativelibs"
 
 @rem Collect protoc artifacts built by the previous build step
-xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86\
-xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x64\
-xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x86\
-xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x64\
-xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86\
-xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64\
+mkdir protoc_plugins
+powershell -Command "cp -r ..\..\platform=*\artifacts\protoc_* protoc_plugins"
 
 %DOTNET% restore Grpc.sln || goto :error
 
 @rem To be able to build, we also need to put grpc_csharp_ext to its normal location
-xcopy /Y /I nativelibs\windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\
+xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release\
 
 %DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error
 %DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index ee923e3..d339238 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -34,35 +34,19 @@
 
 mkdir -p ../../artifacts/
 
-mkdir -p nativelibs/windows_x86 nativelibs/windows_x64 \
-    nativelibs/linux_x86 nativelibs/linux_x64 \
-    nativelibs/macosx_x86 nativelibs/macosx_x64
-
-mkdir -p protoc_plugins/windows_x86 protoc_plugins/windows_x64 \
-    protoc_plugins/linux_x86 protoc_plugins/linux_x64 \
-    protoc_plugins/macosx_x86 protoc_plugins/macosx_x64
-
-# Collect the artifacts built by the previous build step if running on Jenkins
-cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=windows/artifacts/* nativelibs/windows_x86 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=windows/artifacts/* nativelibs/windows_x64 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=linux/artifacts/* nativelibs/linux_x86 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=linux/artifacts/* nativelibs/linux_x64 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=macos/artifacts/* nativelibs/macosx_x86 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=macos/artifacts/* nativelibs/macosx_x64 || true
+# Collect the artifacts built by the previous build step
+mkdir -p nativelibs
+cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/csharp_ext_* nativelibs || true
 
 # Collect protoc artifacts built by the previous build step
-cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=windows/artifacts/* protoc_plugins/windows_x86 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=windows/artifacts/* protoc_plugins/windows_x64 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=linux/artifacts/* protoc_plugins/linux_x86 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=linux/artifacts/* protoc_plugins/linux_x64 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=macos/artifacts/* protoc_plugins/macosx_x86 || true
-cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=macos/artifacts/* protoc_plugins/macosx_x64 || true
+mkdir -p protoc_plugins
+cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/protoc_* protoc_plugins || true
 
 dotnet restore Grpc.sln
 
 # To be able to build, we also need to put grpc_csharp_ext to its normal location
 mkdir -p ../../libs/opt
-cp nativelibs/linux_x64/libgrpc_csharp_ext.so ../../libs/opt
+cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
 
 dotnet pack --configuration Release Grpc.Core --output ../../../artifacts
 dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index e193e82..c444ad0 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -85,98 +85,6 @@
 
 static char *pem_root_certs = NULL;
 
-void InitStatusConstants(Local<Object> exports) {
-  Nan::HandleScope scope;
-  Local<Object> status = Nan::New<Object>();
-  Nan::Set(exports, Nan::New("status").ToLocalChecked(), status);
-  Local<Value> OK(Nan::New<Uint32, uint32_t>(GRPC_STATUS_OK));
-  Nan::Set(status, Nan::New("OK").ToLocalChecked(), OK);
-  Local<Value> CANCELLED(Nan::New<Uint32, uint32_t>(GRPC_STATUS_CANCELLED));
-  Nan::Set(status, Nan::New("CANCELLED").ToLocalChecked(), CANCELLED);
-  Local<Value> UNKNOWN(Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNKNOWN));
-  Nan::Set(status, Nan::New("UNKNOWN").ToLocalChecked(), UNKNOWN);
-  Local<Value> INVALID_ARGUMENT(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_INVALID_ARGUMENT));
-  Nan::Set(status, Nan::New("INVALID_ARGUMENT").ToLocalChecked(),
-           INVALID_ARGUMENT);
-  Local<Value> DEADLINE_EXCEEDED(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_DEADLINE_EXCEEDED));
-  Nan::Set(status, Nan::New("DEADLINE_EXCEEDED").ToLocalChecked(),
-           DEADLINE_EXCEEDED);
-  Local<Value> NOT_FOUND(Nan::New<Uint32, uint32_t>(GRPC_STATUS_NOT_FOUND));
-  Nan::Set(status, Nan::New("NOT_FOUND").ToLocalChecked(), NOT_FOUND);
-  Local<Value> ALREADY_EXISTS(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_ALREADY_EXISTS));
-  Nan::Set(status, Nan::New("ALREADY_EXISTS").ToLocalChecked(), ALREADY_EXISTS);
-  Local<Value> PERMISSION_DENIED(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_PERMISSION_DENIED));
-  Nan::Set(status, Nan::New("PERMISSION_DENIED").ToLocalChecked(),
-           PERMISSION_DENIED);
-  Local<Value> UNAUTHENTICATED(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNAUTHENTICATED));
-  Nan::Set(status, Nan::New("UNAUTHENTICATED").ToLocalChecked(),
-           UNAUTHENTICATED);
-  Local<Value> RESOURCE_EXHAUSTED(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_RESOURCE_EXHAUSTED));
-  Nan::Set(status, Nan::New("RESOURCE_EXHAUSTED").ToLocalChecked(),
-           RESOURCE_EXHAUSTED);
-  Local<Value> FAILED_PRECONDITION(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_FAILED_PRECONDITION));
-  Nan::Set(status, Nan::New("FAILED_PRECONDITION").ToLocalChecked(),
-           FAILED_PRECONDITION);
-  Local<Value> ABORTED(Nan::New<Uint32, uint32_t>(GRPC_STATUS_ABORTED));
-  Nan::Set(status, Nan::New("ABORTED").ToLocalChecked(), ABORTED);
-  Local<Value> OUT_OF_RANGE(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_OUT_OF_RANGE));
-  Nan::Set(status, Nan::New("OUT_OF_RANGE").ToLocalChecked(), OUT_OF_RANGE);
-  Local<Value> UNIMPLEMENTED(
-      Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNIMPLEMENTED));
-  Nan::Set(status, Nan::New("UNIMPLEMENTED").ToLocalChecked(), UNIMPLEMENTED);
-  Local<Value> INTERNAL(Nan::New<Uint32, uint32_t>(GRPC_STATUS_INTERNAL));
-  Nan::Set(status, Nan::New("INTERNAL").ToLocalChecked(), INTERNAL);
-  Local<Value> UNAVAILABLE(Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNAVAILABLE));
-  Nan::Set(status, Nan::New("UNAVAILABLE").ToLocalChecked(), UNAVAILABLE);
-  Local<Value> DATA_LOSS(Nan::New<Uint32, uint32_t>(GRPC_STATUS_DATA_LOSS));
-  Nan::Set(status, Nan::New("DATA_LOSS").ToLocalChecked(), DATA_LOSS);
-}
-
-void InitCallErrorConstants(Local<Object> exports) {
-  Nan::HandleScope scope;
-  Local<Object> call_error = Nan::New<Object>();
-  Nan::Set(exports, Nan::New("callError").ToLocalChecked(), call_error);
-  Local<Value> OK(Nan::New<Uint32, uint32_t>(GRPC_CALL_OK));
-  Nan::Set(call_error, Nan::New("OK").ToLocalChecked(), OK);
-  Local<Value> CALL_ERROR(Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR));
-  Nan::Set(call_error, Nan::New("ERROR").ToLocalChecked(), CALL_ERROR);
-  Local<Value> NOT_ON_SERVER(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_ON_SERVER));
-  Nan::Set(call_error, Nan::New("NOT_ON_SERVER").ToLocalChecked(),
-           NOT_ON_SERVER);
-  Local<Value> NOT_ON_CLIENT(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_ON_CLIENT));
-  Nan::Set(call_error, Nan::New("NOT_ON_CLIENT").ToLocalChecked(),
-           NOT_ON_CLIENT);
-  Local<Value> ALREADY_INVOKED(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_ALREADY_INVOKED));
-  Nan::Set(call_error, Nan::New("ALREADY_INVOKED").ToLocalChecked(),
-           ALREADY_INVOKED);
-  Local<Value> NOT_INVOKED(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_INVOKED));
-  Nan::Set(call_error, Nan::New("NOT_INVOKED").ToLocalChecked(), NOT_INVOKED);
-  Local<Value> ALREADY_FINISHED(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_ALREADY_FINISHED));
-  Nan::Set(call_error, Nan::New("ALREADY_FINISHED").ToLocalChecked(),
-           ALREADY_FINISHED);
-  Local<Value> TOO_MANY_OPERATIONS(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS));
-  Nan::Set(call_error, Nan::New("TOO_MANY_OPERATIONS").ToLocalChecked(),
-           TOO_MANY_OPERATIONS);
-  Local<Value> INVALID_FLAGS(
-      Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_INVALID_FLAGS));
-  Nan::Set(call_error, Nan::New("INVALID_FLAGS").ToLocalChecked(),
-           INVALID_FLAGS);
-}
-
 void InitOpTypeConstants(Local<Object> exports) {
   Nan::HandleScope scope;
   Local<Object> op_type = Nan::New<Object>();
@@ -211,27 +119,6 @@
            RECV_CLOSE_ON_SERVER);
 }
 
-void InitPropagateConstants(Local<Object> exports) {
-  Nan::HandleScope scope;
-  Local<Object> propagate = Nan::New<Object>();
-  Nan::Set(exports, Nan::New("propagate").ToLocalChecked(), propagate);
-  Local<Value> DEADLINE(Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_DEADLINE));
-  Nan::Set(propagate, Nan::New("DEADLINE").ToLocalChecked(), DEADLINE);
-  Local<Value> CENSUS_STATS_CONTEXT(
-      Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_CENSUS_STATS_CONTEXT));
-  Nan::Set(propagate, Nan::New("CENSUS_STATS_CONTEXT").ToLocalChecked(),
-           CENSUS_STATS_CONTEXT);
-  Local<Value> CENSUS_TRACING_CONTEXT(
-      Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT));
-  Nan::Set(propagate, Nan::New("CENSUS_TRACING_CONTEXT").ToLocalChecked(),
-           CENSUS_TRACING_CONTEXT);
-  Local<Value> CANCELLATION(
-      Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_CANCELLATION));
-  Nan::Set(propagate, Nan::New("CANCELLATION").ToLocalChecked(), CANCELLATION);
-  Local<Value> DEFAULTS(Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_DEFAULTS));
-  Nan::Set(propagate, Nan::New("DEFAULTS").ToLocalChecked(), DEFAULTS);
-}
-
 void InitConnectivityStateConstants(Local<Object> exports) {
   Nan::HandleScope scope;
   Local<Object> channel_state = Nan::New<Object>();
@@ -252,28 +139,6 @@
            FATAL_FAILURE);
 }
 
-void InitWriteFlags(Local<Object> exports) {
-  Nan::HandleScope scope;
-  Local<Object> write_flags = Nan::New<Object>();
-  Nan::Set(exports, Nan::New("writeFlags").ToLocalChecked(), write_flags);
-  Local<Value> BUFFER_HINT(Nan::New<Uint32, uint32_t>(GRPC_WRITE_BUFFER_HINT));
-  Nan::Set(write_flags, Nan::New("BUFFER_HINT").ToLocalChecked(), BUFFER_HINT);
-  Local<Value> NO_COMPRESS(Nan::New<Uint32, uint32_t>(GRPC_WRITE_NO_COMPRESS));
-  Nan::Set(write_flags, Nan::New("NO_COMPRESS").ToLocalChecked(), NO_COMPRESS);
-}
-
-void InitLogConstants(Local<Object> exports) {
-  Nan::HandleScope scope;
-  Local<Object> log_verbosity = Nan::New<Object>();
-  Nan::Set(exports, Nan::New("logVerbosity").ToLocalChecked(), log_verbosity);
-  Local<Value> LOG_DEBUG(Nan::New<Uint32, uint32_t>(GPR_LOG_SEVERITY_DEBUG));
-  Nan::Set(log_verbosity, Nan::New("DEBUG").ToLocalChecked(), LOG_DEBUG);
-  Local<Value> LOG_INFO(Nan::New<Uint32, uint32_t>(GPR_LOG_SEVERITY_INFO));
-  Nan::Set(log_verbosity, Nan::New("INFO").ToLocalChecked(), LOG_INFO);
-  Local<Value> LOG_ERROR(Nan::New<Uint32, uint32_t>(GPR_LOG_SEVERITY_ERROR));
-  Nan::Set(log_verbosity, Nan::New("ERROR").ToLocalChecked(), LOG_ERROR);
-}
-
 NAN_METHOD(MetadataKeyIsLegal) {
   if (!info[0]->IsString()) {
     return Nan::ThrowTypeError("headerKeyIsLegal's argument must be a string");
@@ -421,13 +286,8 @@
   grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
   init_logger();
 
-  InitStatusConstants(exports);
-  InitCallErrorConstants(exports);
   InitOpTypeConstants(exports);
-  InitPropagateConstants(exports);
   InitConnectivityStateConstants(exports);
-  InitWriteFlags(exports);
-  InitLogConstants(exports);
 
   grpc_pollset_work_run_loop = 0;
 
diff --git a/src/node/index.js b/src/node/index.js
index 76ab174..0da3440 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -59,6 +59,8 @@
 var protobuf_js_5_common = require('./src/protobuf_js_5_common');
 var protobuf_js_6_common = require('./src/protobuf_js_6_common');
 
+var constants = require('./src/constants.js');
+
 grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii'));
 
 /**
@@ -212,27 +214,27 @@
 /**
  * Status name to code number mapping
  */
-exports.status = grpc.status;
+exports.status = constants.status;
 
 /**
  * Propagate flag name to number mapping
  */
-exports.propagate = grpc.propagate;
+exports.propagate = constants.propagate;
 
 /**
  * Call error name to code number mapping
  */
-exports.callError = grpc.callError;
+exports.callError = constants.callError;
 
 /**
  * Write flag name to code number mapping
  */
-exports.writeFlags = grpc.writeFlags;
+exports.writeFlags = constants.writeFlags;
 
 /**
  * Log verbosity setting name to code number mapping
  */
-exports.logVerbosity = grpc.logVerbosity;
+exports.logVerbosity = constants.logVerbosity;
 
 /**
  * Credentials factories
diff --git a/src/node/jsdoc_conf.json b/src/node/jsdoc_conf.json
index c3a0174..2d96775 100644
--- a/src/node/jsdoc_conf.json
+++ b/src/node/jsdoc_conf.json
@@ -11,7 +11,7 @@
     "package": "package.json",
     "readme": "src/node/README.md"
   },
-  "plugins": [],
+  "plugins": ["plugins/markdown"],
   "templates": {
     "cleverLinks": false,
     "monospaceLinks": false,
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 43502da..16fe06a 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -58,6 +58,8 @@
 
 var Metadata = require('./metadata');
 
+var constants = require('./constants');
+
 var EventEmitter = require('events').EventEmitter;
 
 var stream = require('stream');
@@ -127,7 +129,8 @@
        but passing an object that causes a serialization failure is a misuse
        of the API anyway, so that's OK. The primary purpose here is to give the
        programmer a useful error and to stop the stream properly */
-    this.call.cancelWithStatus(grpc.status.INTERNAL, 'Serialization failure');
+    this.call.cancelWithStatus(constants.status.INTERNAL,
+                               'Serialization failure');
     callback(e);
   }
   if (_.isFinite(encoding)) {
@@ -185,9 +188,9 @@
 function _readsDone(status) {
   /* jshint validthis: true */
   if (!status) {
-    status = {code: grpc.status.OK, details: 'OK'};
+    status = {code: constants.status.OK, details: 'OK'};
   }
-  if (status.code !== grpc.status.OK) {
+  if (status.code !== constants.status.OK) {
     this.call.cancelWithStatus(status.code, status.details);
   }
   this.finished = true;
@@ -218,12 +221,12 @@
   /* jshint validthis: true */
   var status;
   if (this.read_status && this.received_status) {
-    if (this.read_status.code !== grpc.status.OK) {
+    if (this.read_status.code !== constants.status.OK) {
       status = this.read_status;
     } else {
       status = this.received_status;
     }
-    if (status.code === grpc.status.OK) {
+    if (status.code === constants.status.OK) {
       this.push(null);
     } else {
       var error = new Error(status.details);
@@ -262,7 +265,7 @@
     try {
       deserialized = self.deserialize(data);
     } catch (e) {
-      self._readsDone({code: grpc.status.INTERNAL,
+      self._readsDone({code: constants.status.INTERNAL,
                        details: 'Failed to parse server response'});
       return;
     }
@@ -510,7 +513,7 @@
     var deserialized;
     emitter.emit('metadata', Metadata._fromCoreRepresentation(
         response.metadata));
-    if (status.code === grpc.status.OK) {
+    if (status.code === constants.status.OK) {
       if (err) {
         // Got a batch error, but OK status. Something went wrong
         args.callback(err);
@@ -522,13 +525,13 @@
           /* Change status to indicate bad server response. This will result
            * in passing an error to the callback */
           status = {
-            code: grpc.status.INTERNAL,
+            code: constants.status.INTERNAL,
             details: 'Failed to parse server response'
           };
         }
       }
     }
-    if (status.code !== grpc.status.OK) {
+    if (status.code !== constants.status.OK) {
       error = new Error(status.details);
       error.code = status.code;
       error.metadata = status.metadata;
@@ -593,7 +596,7 @@
     var status = response.status;
     var error;
     var deserialized;
-    if (status.code === grpc.status.OK) {
+    if (status.code === constants.status.OK) {
       if (err) {
         // Got a batch error, but OK status. Something went wrong
         args.callback(err);
@@ -605,13 +608,13 @@
           /* Change status to indicate bad server response. This will result
            * in passing an error to the callback */
           status = {
-            code: grpc.status.INTERNAL,
+            code: constants.status.INTERNAL,
             details: 'Failed to parse server response'
           };
         }
       }
     }
-    if (status.code !== grpc.status.OK) {
+    if (status.code !== constants.status.OK) {
       error = new Error(response.status.details);
       error.code = status.code;
       error.metadata = status.metadata;
@@ -921,7 +924,7 @@
 /**
  * Map of status code names to status codes
  */
-exports.status = grpc.status;
+exports.status = constants.status;
 
 /**
  * See docs for client.callError
diff --git a/src/node/src/constants.js b/src/node/src/constants.js
new file mode 100644
index 0000000..528dab1
--- /dev/null
+++ b/src/node/src/constants.js
@@ -0,0 +1,241 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * @module
+ */
+
+/* The comments about status codes are copied verbatim (with some formatting
+ * modifications) from include/grpc/impl/codegen/status.h, for the purpose of
+ * including them in generated documentation.
+ */
+/**
+ * Enum of status codes that gRPC can return
+ * @readonly
+ * @enum {number}
+ */
+exports.status = {
+  /** Not an error; returned on success */
+  OK: 0,
+  /** The operation was cancelled (typically by the caller). */
+  CANCELLED: 1,
+  /**
+   * Unknown error.  An example of where this error may be returned is
+   * if a status value received from another address space belongs to
+   * an error-space that is not known in this address space.  Also
+   * errors raised by APIs that do not return enough error information
+   * may be converted to this error.
+   */
+  UNKNOWN: 2,
+  /**
+   * Client specified an invalid argument.  Note that this differs
+   * from FAILED_PRECONDITION.  INVALID_ARGUMENT indicates arguments
+   * that are problematic regardless of the state of the system
+   * (e.g., a malformed file name).
+   */
+  INVALID_ARGUMENT: 3,
+  /**
+   * Deadline expired before operation could complete.  For operations
+   * that change the state of the system, this error may be returned
+   * even if the operation has completed successfully.  For example, a
+   * successful response from a server could have been delayed long
+   * enough for the deadline to expire.
+   */
+  DEADLINE_EXCEEDED: 4,
+  /** Some requested entity (e.g., file or directory) was not found. */
+  NOT_FOUND: 5,
+  /**
+   * Some entity that we attempted to create (e.g., file or directory)
+   * already exists.
+   */
+  ALREADY_EXISTS: 6,
+  /**
+   * The caller does not have permission to execute the specified
+   * operation.  PERMISSION_DENIED must not be used for rejections
+   * caused by exhausting some resource (use RESOURCE_EXHAUSTED
+   * instead for those errors).  PERMISSION_DENIED must not be
+   * used if the caller can not be identified (use UNAUTHENTICATED
+   * instead for those errors).
+   */
+  PERMISSION_DENIED: 7,
+  /**
+   * Some resource has been exhausted, perhaps a per-user quota, or
+   * perhaps the entire file system is out of space.
+   */
+  RESOURCE_EXHAUSTED: 8,
+  /**
+   * Operation was rejected because the system is not in a state
+   * required for the operation's execution.  For example, directory
+   * to be deleted may be non-empty, an rmdir operation is applied to
+   * a non-directory, etc.
+   *
+   * A litmus test that may help a service implementor in deciding
+   * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
+   *
+   *  - Use UNAVAILABLE if the client can retry just the failing call.
+   *  - Use ABORTED if the client should retry at a higher-level
+   *    (e.g., restarting a read-modify-write sequence).
+   *  - Use FAILED_PRECONDITION if the client should not retry until
+   *    the system state has been explicitly fixed.  E.g., if an "rmdir"
+   *    fails because the directory is non-empty, FAILED_PRECONDITION
+   *    should be returned since the client should not retry unless
+   *    they have first fixed up the directory by deleting files from it.
+   *  - Use FAILED_PRECONDITION if the client performs conditional
+   *    REST Get/Update/Delete on a resource and the resource on the
+   *    server does not match the condition. E.g., conflicting
+   *    read-modify-write on the same resource.
+   */
+  FAILED_PRECONDITION: 9,
+  /**
+   * The operation was aborted, typically due to a concurrency issue
+   * like sequencer check failures, transaction aborts, etc.
+   *
+   * See litmus test above for deciding between FAILED_PRECONDITION,
+   * ABORTED, and UNAVAILABLE.
+   */
+  ABORTED: 10,
+  /**
+   * Operation was attempted past the valid range.  E.g., seeking or
+   * reading past end of file.
+   *
+   * Unlike INVALID_ARGUMENT, this error indicates a problem that may
+   * be fixed if the system state changes. For example, a 32-bit file
+   * system will generate INVALID_ARGUMENT if asked to read at an
+   * offset that is not in the range [0,2^32-1], but it will generate
+   * OUT_OF_RANGE if asked to read from an offset past the current
+   * file size.
+   *
+   * There is a fair bit of overlap between FAILED_PRECONDITION and
+   * OUT_OF_RANGE.  We recommend using OUT_OF_RANGE (the more specific
+   * error) when it applies so that callers who are iterating through
+   * a space can easily look for an OUT_OF_RANGE error to detect when
+   * they are done.
+   */
+  OUT_OF_RANGE: 11,
+  /** Operation is not implemented or not supported/enabled in this service. */
+  UNIMPLEMENTED: 12,
+  /**
+   * Internal errors.  Means some invariants expected by underlying
+   * system has been broken.  If you see one of these errors,
+   * something is very broken.
+   */
+  INTERNAL: 13,
+  /**
+   * The service is currently unavailable.  This is a most likely a
+   * transient condition and may be corrected by retrying with
+   * a backoff.
+   *
+   * See litmus test above for deciding between FAILED_PRECONDITION,
+   * ABORTED, and UNAVAILABLE. */
+  UNAVAILABLE: 14,
+  /** Unrecoverable data loss or corruption. */
+  DATA_LOSS: 15,
+  /**
+   * The request does not have valid authentication credentials for the
+   * operation.
+   */
+  UNAUTHENTICATED: 16
+};
+
+/* The comments about propagation bit flags are copied rom
+ * include/grpc/impl/codegen/propagation_bits.h for the purpose of including
+ * them in generated documentation.
+ */
+/**
+ * Propagation flags: these can be bitwise or-ed to form the propagation option
+ * for calls.
+ *
+ * Users are encouraged to write propagation masks as deltas from the default.
+ * i.e. write `grpc.propagate.DEFAULTS & ~grpc.propagate.DEADLINE` to disable
+ * deadline propagation.
+ * @enum {number}
+ */
+exports.propagate = {
+  DEADLINE: 1,
+  CENSUS_STATS_CONTEXT: 2,
+  CENSUS_TRACING_CONTEXT: 4,
+  CANCELLATION: 8,
+  DEFAULTS: 65535
+};
+
+/* Many of the following comments are copied from
+ * include/grpc/impl/codegen/grpc_types.h
+ */
+/**
+ * Call error constants. Call errors almost always indicate bugs in the gRPC
+ * library, and these error codes are mainly useful for finding those bugs.
+ * @enum {number}
+ */
+exports.callError = {
+  OK: 0,
+  ERROR: 1,
+  NOT_ON_SERVER: 2,
+  NOT_ON_CLIENT: 3,
+  ALREADY_INVOKED: 5,
+  NOT_INVOKED: 6,
+  ALREADY_FINISHED: 7,
+  TOO_MANY_OPERATIONS: 8,
+  INVALID_FLAGS: 9,
+  INVALID_METADATA: 10,
+  INVALID_MESSAGE: 11,
+  NOT_SERVER_COMPLETION_QUEUE: 12,
+  BATCH_TOO_BIG: 13,
+  PAYLOAD_TYPE_MISMATCH: 14
+};
+
+/**
+ * Write flags: these can be bitwise or-ed to form write options that modify
+ * how data is written.
+ * @enum {number}
+ */
+exports.writeFlags = {
+  /**
+   * Hint that the write may be buffered and need not go out on the wire
+   * immediately. GRPC is free to buffer the message until the next non-buffered
+   * write, or until writes_done, but it need not buffer completely or at all.
+   */
+  BUFFER_HINT: 1,
+  /**
+   * Force compression to be disabled for a particular write
+   */
+  NO_COMPRESS: 2
+};
+
+/**
+ * @enum {number}
+ */
+exports.logVerbosity = {
+  DEBUG: 0,
+  INFO: 1,
+  ERROR: 2
+};
diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js
index 51ff1da..b1e86bb 100644
--- a/src/node/src/credentials.js
+++ b/src/node/src/credentials.js
@@ -71,6 +71,8 @@
 
 var common = require('./common.js');
 
+var constants = require('./constants');
+
 var _ = require('lodash');
 
 /**
@@ -97,14 +99,14 @@
   return CallCredentials.createFromPlugin(function(service_url, cb_data,
                                                    callback) {
     metadata_generator({service_url: service_url}, function(error, metadata) {
-      var code = grpc.status.OK;
+      var code = constants.status.OK;
       var message = '';
       if (error) {
         message = error.message;
         if (error.hasOwnProperty('code') && _.isFinite(error.code)) {
           code = error.code;
         } else {
-          code = grpc.status.UNAUTHENTICATED;
+          code = constants.status.UNAUTHENTICATED;
         }
         if (!metadata) {
           metadata = new Metadata();
@@ -125,7 +127,7 @@
     var service_url = auth_context.service_url;
     google_credential.getRequestMetadata(service_url, function(err, header) {
       if (err) {
-        common.log(grpc.logVerbosity.INFO, 'Auth error:' + err);
+        common.log(constants.logVerbosity.INFO, 'Auth error:' + err);
         callback(err);
         return;
       }
diff --git a/src/node/src/server.js b/src/node/src/server.js
index 3450abe..08417a7 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -57,6 +57,8 @@
 
 var Metadata = require('./metadata');
 
+var constants = require('./constants');
+
 var stream = require('stream');
 
 var Readable = stream.Readable;
@@ -75,7 +77,7 @@
 function handleError(call, error) {
   var statusMetadata = new Metadata();
   var status = {
-    code: grpc.status.UNKNOWN,
+    code: constants.status.UNKNOWN,
     details: 'Unknown Error'
   };
   if (error.hasOwnProperty('message')) {
@@ -115,7 +117,7 @@
   var end_batch = {};
   var statusMetadata = new Metadata();
   var status = {
-    code: grpc.status.OK,
+    code: constants.status.OK,
     details: 'OK'
   };
   if (metadata) {
@@ -125,7 +127,7 @@
   try {
     message = serialize(value);
   } catch (e) {
-    e.code = grpc.status.INTERNAL;
+    e.code = constants.status.INTERNAL;
     handleError(call, e);
     return;
   }
@@ -151,7 +153,7 @@
 function setUpWritable(stream, serialize) {
   stream.finished = false;
   stream.status = {
-    code : grpc.status.OK,
+    code : constants.status.OK,
     details : 'OK',
     metadata : new Metadata()
   };
@@ -178,7 +180,7 @@
    * @param {Error} err The error object
    */
   function setStatus(err) {
-    var code = grpc.status.UNKNOWN;
+    var code = constants.status.UNKNOWN;
     var details = 'Unknown Error';
     var metadata = new Metadata();
     if (err.hasOwnProperty('message')) {
@@ -284,7 +286,7 @@
   try {
     message = this.serialize(chunk);
   } catch (e) {
-    e.code = grpc.status.INTERNAL;
+    e.code = constants.status.INTERNAL;
     callback(e);
     return;
   }
@@ -353,7 +355,7 @@
     try {
       deserialized = self.deserialize(data);
     } catch (e) {
-      e.code = grpc.status.INTERNAL;
+      e.code = constants.status.INTERNAL;
       self.emit('error', e);
       return;
     }
@@ -489,7 +491,7 @@
     try {
       emitter.request = handler.deserialize(result.read);
     } catch (e) {
-      e.code = grpc.status.INTERNAL;
+      e.code = constants.status.INTERNAL;
       handleError(call, e);
       return;
     }
@@ -530,7 +532,7 @@
     try {
       stream.request = handler.deserialize(result.read);
     } catch (e) {
-      e.code = grpc.status.INTERNAL;
+      e.code = constants.status.INTERNAL;
       stream.emit('error', e);
       return;
     }
@@ -636,7 +638,7 @@
         batch[grpc.opType.SEND_INITIAL_METADATA] =
             (new Metadata())._getCoreRepresentation();
         batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
-          code: grpc.status.UNIMPLEMENTED,
+          code: constants.status.UNIMPLEMENTED,
           details: '',
           metadata: {}
         };
@@ -699,7 +701,7 @@
 };
 
 var unimplementedStatusResponse = {
-  code: grpc.status.UNIMPLEMENTED,
+  code: constants.status.UNIMPLEMENTED,
   details: 'The server does not implement this method'
 };
 
@@ -759,8 +761,8 @@
          written in the proto file, instead of using JavaScript function
          naming style */
       if (implementation[attrs.originalName] === undefined) {
-        common.log(grpc.logVerbosity.ERROR, 'Method handler ' + name + ' for ' +
-            attrs.path + ' expected but not provided');
+        common.log(constants.logVerbosity.ERROR, 'Method handler ' + name +
+            ' for ' + attrs.path + ' expected but not provided');
         impl = defaultHandler[method_type];
       } else {
         impl = _.bind(implementation[attrs.originalName], implementation);
@@ -790,7 +792,7 @@
   var options;
   var protobuf_js_5_common = require('./protobuf_js_5_common');
   var protobuf_js_6_common = require('./protobuf_js_6_common');
-  common.log(grpc.logVerbosity.INFO,
+  common.log(constants.logVerbosity.INFO,
              'Server#addProtoService is deprecated. Use addService instead');
   if (protobuf_js_5_common.isProbablyProtobufJs5(service)) {
     options = _.defaults(service.grpc_options, common.defaultGrpcOptions);
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index eb26860..f25268e 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -35,6 +35,7 @@
 
 var assert = require('assert');
 var grpc = require('../src/grpc_extension');
+var constants = require('../src/constants');
 
 /**
  * Helper function to return an absolute deadline given a relative timeout in
@@ -120,7 +121,8 @@
       var batch = {};
       batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
       call.startBatch(batch, function(err, response) {
-        assert.strictEqual(response.status.code, grpc.status.DEADLINE_EXCEEDED);
+        assert.strictEqual(response.status.code,
+                           constants.status.DEADLINE_EXCEEDED);
         done();
       });
     });
diff --git a/src/node/test/constant_test.js b/src/node/test/constant_test.js
deleted file mode 100644
index 414b1ac..0000000
--- a/src/node/test/constant_test.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-'use strict';
-
-var assert = require('assert');
-var grpc = require('../src/grpc_extension');
-
-/**
- * List of all status names
- * @const
- * @type {Array.<string>}
- */
-var statusNames = [
-  'OK',
-  'CANCELLED',
-  'UNKNOWN',
-  'INVALID_ARGUMENT',
-  'DEADLINE_EXCEEDED',
-  'NOT_FOUND',
-  'ALREADY_EXISTS',
-  'PERMISSION_DENIED',
-  'UNAUTHENTICATED',
-  'RESOURCE_EXHAUSTED',
-  'FAILED_PRECONDITION',
-  'ABORTED',
-  'OUT_OF_RANGE',
-  'UNIMPLEMENTED',
-  'INTERNAL',
-  'UNAVAILABLE',
-  'DATA_LOSS'
-];
-
-/**
- * List of all call error names
- * @const
- * @type {Array.<string>}
- */
-var callErrorNames = [
-  'OK',
-  'ERROR',
-  'NOT_ON_SERVER',
-  'NOT_ON_CLIENT',
-  'ALREADY_INVOKED',
-  'NOT_INVOKED',
-  'ALREADY_FINISHED',
-  'TOO_MANY_OPERATIONS',
-  'INVALID_FLAGS'
-];
-
-/**
- * List of all propagate flag names
- * @const
- * @type {Array.<string>}
- */
-var propagateFlagNames = [
-  'DEADLINE',
-  'CENSUS_STATS_CONTEXT',
-  'CENSUS_TRACING_CONTEXT',
-  'CANCELLATION',
-  'DEFAULTS'
-];
-/*
- * List of all connectivity state names
- * @const
- * @type {Array.<string>}
- */
-var connectivityStateNames = [
-  'IDLE',
-  'CONNECTING',
-  'READY',
-  'TRANSIENT_FAILURE',
-  'FATAL_FAILURE'
-];
-
-describe('constants', function() {
-  it('should have all of the status constants', function() {
-    for (var i = 0; i < statusNames.length; i++) {
-      assert(grpc.status.hasOwnProperty(statusNames[i]),
-             'status missing: ' + statusNames[i]);
-    }
-  });
-  it('should have all of the call errors', function() {
-    for (var i = 0; i < callErrorNames.length; i++) {
-      assert(grpc.callError.hasOwnProperty(callErrorNames[i]),
-             'call error missing: ' + callErrorNames[i]);
-    }
-  });
-  it('should have all of the propagate flags', function() {
-    for (var i = 0; i < propagateFlagNames.length; i++) {
-      assert(grpc.propagate.hasOwnProperty(propagateFlagNames[i]),
-             'call error missing: ' + propagateFlagNames[i]);
-    }
-  });
-  it('should have all of the connectivity states', function() {
-    for (var i = 0; i < connectivityStateNames.length; i++) {
-      assert(grpc.connectivityState.hasOwnProperty(connectivityStateNames[i]),
-             'connectivity status missing: ' + connectivityStateNames[i]);
-    }
-  });
-});
diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js
index f127a41..af455e2 100644
--- a/src/node/test/end_to_end_test.js
+++ b/src/node/test/end_to_end_test.js
@@ -35,6 +35,7 @@
 
 var assert = require('assert');
 var grpc = require('../src/grpc_extension');
+var constants = require('../src/constants');
 
 /**
  * This is used for testing functions with multiple asynchronous calls that
@@ -90,7 +91,7 @@
         client_close: true,
         metadata: {},
         status: {
-          code: grpc.status.OK,
+          code: constants.status.OK,
           details: status_text,
           metadata: {}
         }
@@ -107,7 +108,7 @@
       server_batch[grpc.opType.SEND_INITIAL_METADATA] = {};
       server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
         metadata: {},
-        code: grpc.status.OK,
+        code: constants.status.OK,
         details: status_text
       };
       server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
@@ -141,7 +142,7 @@
         send_metadata: true,
         client_close: true,
         metadata: {server_key: ['server_value']},
-        status: {code: grpc.status.OK,
+        status: {code: constants.status.OK,
                  details: status_text,
                  metadata: {}}
       });
@@ -161,7 +162,7 @@
       };
       server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
         metadata: {},
-        code: grpc.status.OK,
+        code: constants.status.OK,
         details: status_text
       };
       server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
@@ -198,7 +199,7 @@
       assert.deepEqual(response.metadata, {});
       assert(response.send_message);
       assert.strictEqual(response.read.toString(), reply_text);
-      assert.deepEqual(response.status, {code: grpc.status.OK,
+      assert.deepEqual(response.status, {code: constants.status.OK,
                                          details: status_text,
                                          metadata: {}});
       done();
@@ -220,7 +221,7 @@
         response_batch[grpc.opType.SEND_MESSAGE] = new Buffer(reply_text);
         response_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
           metadata: {},
-          code: grpc.status.OK,
+          code: constants.status.OK,
           details: status_text
         };
         response_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
@@ -260,7 +261,7 @@
           send_message: true,
           client_close: true,
           status: {
-            code: grpc.status.OK,
+            code: constants.status.OK,
             details: status_text,
             metadata: {}
           }
@@ -290,7 +291,7 @@
           end_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
           end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
             metadata: {},
-            code: grpc.status.OK,
+            code: constants.status.OK,
             details: status_text
           };
           server_call.startBatch(end_batch, function(err, response) {
diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD
index 805988c..5f1c005 100644
--- a/src/proto/grpc/testing/BUILD
+++ b/src/proto/grpc/testing/BUILD
@@ -42,8 +42,11 @@
 grpc_proto_library(
     name = "control_proto",
     srcs = ["control.proto"],
-    deps = ["payloads_proto", "stats_proto"],
     has_services = False,
+    deps = [
+        "payloads_proto",
+        "stats_proto",
+    ],
 )
 
 grpc_proto_library(
@@ -101,5 +104,8 @@
 grpc_proto_library(
     name = "test_proto",
     srcs = ["test.proto"],
-    deps = ["empty_proto", "messages_proto"],
+    deps = [
+        "empty_proto",
+        "messages_proto",
+    ],
 )
diff --git a/templates/src/csharp/Grpc.Core/Version.csproj.include.template b/templates/src/csharp/Grpc.Core/Version.csproj.include.template
index 30b8d26..5bc66e9 100755
--- a/templates/src/csharp/Grpc.Core/Version.csproj.include.template
+++ b/templates/src/csharp/Grpc.Core/Version.csproj.include.template
@@ -4,6 +4,6 @@
   <Project>
     <PropertyGroup>
       <GrpcCsharpVersion>${settings.csharp_version}</GrpcCsharpVersion>
-      <GoogleProtobufVersion>3.2.0</GoogleProtobufVersion>
+      <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion>
     </PropertyGroup>
   </Project>
diff --git a/templates/src/csharp/build_packages_dotnetcli.bat.template b/templates/src/csharp/build_packages_dotnetcli.bat.template
index 91808e0..3db1e0a 100755
--- a/templates/src/csharp/build_packages_dotnetcli.bat.template
+++ b/templates/src/csharp/build_packages_dotnetcli.bat.template
@@ -38,29 +38,20 @@
   
   set -ex
   
-  mkdir -p ..\..\artifacts${"\\"}
+  mkdir ..\..\artifacts
   
   @rem Collect the artifacts built by the previous build step if running on Jenkins
-  @rem TODO(jtattermusch): is there a better way to do this?
-  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=windows\artifacts\* nativelibs\windows_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=windows\artifacts\* nativelibs\windows_x64${"\\"}
-  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=linux\artifacts\* nativelibs\linux_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=linux\artifacts\* nativelibs\linux_x64${"\\"}
-  xcopy /Y /I ..\..\architecture=x86,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=csharp,platform=macos\artifacts\* nativelibs\macosx_x64${"\\"}
+  mkdir nativelibs
+  powershell -Command "cp -r ..\..\platform=*\artifacts\csharp_ext_* nativelibs"
   
   @rem Collect protoc artifacts built by the previous build step
-  xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=windows\artifacts\* protoc_plugins\windows_x64${"\\"}
-  xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=linux\artifacts\* protoc_plugins\linux_x64${"\\"}
-  xcopy /Y /I ..\..\architecture=x86,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x86${"\\"}
-  xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* protoc_plugins\macosx_x64${"\\"}
+  mkdir protoc_plugins
+  powershell -Command "cp -r ..\..\platform=*\artifacts\protoc_* protoc_plugins"
   
   %%DOTNET% restore Grpc.sln || goto :error
   
   @rem To be able to build, we also need to put grpc_csharp_ext to its normal location
-  xcopy /Y /I nativelibs\windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"}
+  xcopy /Y /I nativelibs\csharp_ext_windows_x64\grpc_csharp_ext.dll ..\..\cmake\build\x64\Release${"\\"}
   
   %%DOTNET% pack --configuration Release Grpc.Core --output ..\..\..\artifacts || goto :error
   %%DOTNET% pack --configuration Release Grpc.Core.Testing --output ..\..\..\artifacts || goto :error
diff --git a/templates/src/csharp/build_packages_dotnetcli.sh.template b/templates/src/csharp/build_packages_dotnetcli.sh.template
index 374b236..65afec5 100755
--- a/templates/src/csharp/build_packages_dotnetcli.sh.template
+++ b/templates/src/csharp/build_packages_dotnetcli.sh.template
@@ -36,35 +36,19 @@
   
   mkdir -p ../../artifacts/
   
-  mkdir -p nativelibs/windows_x86 nativelibs/windows_x64 ${"\\"}
-      nativelibs/linux_x86 nativelibs/linux_x64 ${"\\"}
-      nativelibs/macosx_x86 nativelibs/macosx_x64
-  
-  mkdir -p protoc_plugins/windows_x86 protoc_plugins/windows_x64 ${"\\"}
-      protoc_plugins/linux_x86 protoc_plugins/linux_x64 ${"\\"}
-      protoc_plugins/macosx_x86 protoc_plugins/macosx_x64
-  
-  # Collect the artifacts built by the previous build step if running on Jenkins
-  cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=windows/artifacts/* nativelibs/windows_x86 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=windows/artifacts/* nativelibs/windows_x64 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=linux/artifacts/* nativelibs/linux_x86 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=linux/artifacts/* nativelibs/linux_x64 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x86,language=csharp,platform=macos/artifacts/* nativelibs/macosx_x86 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x64,language=csharp,platform=macos/artifacts/* nativelibs/macosx_x64 || true
+  # Collect the artifacts built by the previous build step
+  mkdir -p nativelibs
+  cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/csharp_ext_* nativelibs || true
   
   # Collect protoc artifacts built by the previous build step
-  cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=windows/artifacts/* protoc_plugins/windows_x86 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=windows/artifacts/* protoc_plugins/windows_x64 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=linux/artifacts/* protoc_plugins/linux_x86 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=linux/artifacts/* protoc_plugins/linux_x64 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x86,language=protoc,platform=macos/artifacts/* protoc_plugins/macosx_x86 || true
-  cp $EXTERNAL_GIT_ROOT/architecture=x64,language=protoc,platform=macos/artifacts/* protoc_plugins/macosx_x64 || true
+  mkdir -p protoc_plugins
+  cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/protoc_* protoc_plugins || true
   
   dotnet restore Grpc.sln
   
   # To be able to build, we also need to put grpc_csharp_ext to its normal location
   mkdir -p ../../libs/opt
-  cp nativelibs/linux_x64/libgrpc_csharp_ext.so ../../libs/opt
+  cp nativelibs/csharp_ext_linux_x64/libgrpc_csharp_ext.so ../../libs/opt
   
   dotnet pack --configuration Release Grpc.Core --output ../../../artifacts
   dotnet pack --configuration Release Grpc.Core.Testing --output ../../../artifacts
diff --git a/templates/vsprojects/protoc.props.template b/templates/vsprojects/protoc.props.template
index 2c3844a..65771fc 100644
--- a/templates/vsprojects/protoc.props.template
+++ b/templates/vsprojects/protoc.props.template
@@ -5,7 +5,7 @@
   <PropertyGroup />

   <ItemDefinitionGroup>

     <ClCompile>

-      <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

+      <DisableSpecificWarnings>4244;4267;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </ClCompile>

     <Link>

       <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies>

diff --git a/test/core/bad_client/BUILD b/test/core/bad_client/BUILD
index 6b06955..bcfd2f1 100644
--- a/test/core/bad_client/BUILD
+++ b/test/core/bad_client/BUILD
@@ -27,6 +27,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load(":generate_tests.bzl", "grpc_bad_client_tests")
diff --git a/test/core/bad_client/tests/large_metadata.c b/test/core/bad_client/tests/large_metadata.c
index d7a3ce9..5f3a9c9 100644
--- a/test/core/bad_client/tests/large_metadata.c
+++ b/test/core/bad_client/tests/large_metadata.c
@@ -212,12 +212,14 @@
 }
 
 int main(int argc, char **argv) {
+  int i;
+
   grpc_test_init(argc, argv);
 
   // Test sending more metadata than the server will accept.
   gpr_strvec headers;
   gpr_strvec_init(&headers);
-  for (int i = 0; i < NUM_HEADERS; ++i) {
+  for (i = 0; i < NUM_HEADERS; ++i) {
     char *str;
     gpr_asprintf(&str, "%s%02d%s",
                  PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i,
diff --git a/test/core/bad_ssl/BUILD b/test/core/bad_ssl/BUILD
index 288788a..61c634a 100644
--- a/test/core/bad_ssl/BUILD
+++ b/test/core/bad_ssl/BUILD
@@ -27,6 +27,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load(":generate_tests.bzl", "grpc_bad_ssl_tests")
diff --git a/test/core/census/BUILD b/test/core/census/BUILD
index 49680ab..3fdf511 100644
--- a/test/core/census/BUILD
+++ b/test/core/census/BUILD
@@ -27,12 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "context_test",
     srcs = ["context_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -41,10 +43,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "mlog_test",
     srcs = ["mlog_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -53,10 +55,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "resource_test",
     srcs = ["resource_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     data = [
         ":data/resource_empty_name.pb",
         ":data/resource_full.pb",
@@ -73,10 +75,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "trace_context_test",
     srcs = ["trace_context_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     data = [
         ":data/context_empty.pb",
         ":data/context_full.pb",
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
index c659046..5e7e8c1 100644
--- a/test/core/channel/BUILD
+++ b/test/core/channel/BUILD
@@ -27,12 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "channel_args_test",
     srcs = ["channel_args_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -41,10 +43,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "channel_stack_test",
     srcs = ["channel_stack_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index 55a74c6..6c4b40e 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -27,21 +27,33 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "uri_fuzzer_test",
-  srcs = ["uri_fuzzer_test.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "uri_corpus",
-  copts = ["-std=c99"],
+    name = "uri_fuzzer_test",
+    srcs = ["uri_fuzzer_test.c"],
+    language = "C",
+    corpus = "uri_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "lb_policies_test",
     srcs = ["lb_policies_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:cq_verifier"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:cq_verifier",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/client_channel/resolvers/BUILD b/test/core/client_channel/resolvers/BUILD
index e8361cd..80ca7d3 100644
--- a/test/core/client_channel/resolvers/BUILD
+++ b/test/core/client_channel/resolvers/BUILD
@@ -27,12 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "dns_resolver_connectivity_test",
     srcs = ["dns_resolver_connectivity_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -41,10 +43,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "dns_resolver_test",
     srcs = ["dns_resolver_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -53,10 +55,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "sockaddr_resolver_test",
     srcs = ["sockaddr_resolver_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -65,10 +67,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "fake_resolver_test",
     srcs = ["fake_resolver_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
diff --git a/test/core/compression/BUILD b/test/core/compression/BUILD
index 9ddb4c5..bbd66bd 100644
--- a/test/core/compression/BUILD
+++ b/test/core/compression/BUILD
@@ -27,12 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "algorithm_test",
     srcs = ["algorithm_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -41,10 +43,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "compression_test",
     srcs = ["compression_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -53,10 +55,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "message_compress_test",
     srcs = ["message_compress_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD
index ffea1cc..cf387a9 100644
--- a/test/core/end2end/BUILD
+++ b/test/core/end2end/BUILD
@@ -27,15 +27,17 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load(":generate_tests.bzl", "grpc_end2end_tests")
 
-cc_library(
+grpc_cc_library(
     name = "cq_verifier",
     srcs = ["cq_verifier.c"],
     hdrs = ["cq_verifier.h"],
-    copts = ["-std=c99"],
+    language = "C",
     visibility = ["//test:__subpackages__"],
     deps = [
         "//:gpr",
@@ -44,7 +46,7 @@
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "ssl_test_data",
     srcs = [
         "data/client_certs.c",
@@ -53,15 +55,15 @@
         "data/test_root_cert.c",
     ],
     hdrs = ["data/ssl_test_data.h"],
-    copts = ["-std=c99"],
+    language = "C",
     visibility = ["//test:__subpackages__"],
 )
 
-cc_library(
+grpc_cc_library(
     name = "fake_resolver",
     srcs = ["fake_resolver.c"],
     hdrs = ["fake_resolver.h"],
-    copts = ["-std=c99"],
+    language = "C",
     visibility = ["//test:__subpackages__"],
     deps = [
         "//:gpr",
@@ -70,11 +72,11 @@
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "http_proxy",
     srcs = ["fixtures/http_proxy_fixture.c"],
     hdrs = ["fixtures/http_proxy_fixture.h"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -82,11 +84,11 @@
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "proxy",
     srcs = ["fixtures/proxy.c"],
     hdrs = ["fixtures/proxy.h"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
diff --git a/test/core/end2end/fuzzers/BUILD b/test/core/end2end/fuzzers/BUILD
index 4d98aa0..55810bd 100644
--- a/test/core/end2end/fuzzers/BUILD
+++ b/test/core/end2end/fuzzers/BUILD
@@ -27,30 +27,45 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "api_fuzzer",
-  srcs = ["api_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util", "//test/core/end2end:ssl_test_data"],
-  corpus = "api_fuzzer_corpus",
-  copts = ["-std=c99"],
+    name = "api_fuzzer",
+    srcs = ["api_fuzzer.c"],
+    language = "C",
+    corpus = "api_fuzzer_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
 grpc_fuzzer(
-  name = "client_fuzzer",
-  srcs = ["client_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "client_fuzzer_corpus",
-  copts = ["-std=c99"],
+    name = "client_fuzzer",
+    srcs = ["client_fuzzer.c"],
+    language = "C",
+    corpus = "client_fuzzer_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
 grpc_fuzzer(
-  name = "server_fuzzer",
-  srcs = ["server_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "server_fuzzer_corpus",
-  copts = ["-std=c99"],
+    name = "server_fuzzer",
+    srcs = ["server_fuzzer.c"],
+    language = "C",
+    corpus = "server_fuzzer_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index e141578..a872bc7 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -28,6 +28,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_sh_test", "grpc_cc_binary", "grpc_cc_library")
 
 """Generates the appropriate build.json data for all the end2end tests."""
 
@@ -157,7 +158,7 @@
 
 
 def grpc_end2end_tests():
-  native.cc_library(
+  grpc_cc_library(
     name = 'end2end_tests',
     srcs = ['end2end_tests.c', 'end2end_test_utils.c'] + [
              'tests/%s.c' % t
@@ -166,31 +167,33 @@
       'tests/cancel_test_helpers.h',
       'end2end_tests.h'
     ],
-    copts = ['-std=c99'],
+    language = "C",
     deps = [
       ':cq_verifier',
       ':ssl_test_data',
       ':fake_resolver',
       ':http_proxy',
       ':proxy',
-      '//test/core/util:grpc_test_util',
-      '//:grpc',
-      '//test/core/util:gpr_test_util',
-      '//:gpr',
     ]
   )
 
   for f, fopt in END2END_FIXTURES.items():
-    native.cc_binary(
+    grpc_cc_binary(
       name = '%s_test' % f,
       srcs = ['fixtures/%s.c' % f],
-      copts = ['-std=c99'],
-      deps = [':end2end_tests']
+      language = "C",
+      deps = [
+        ':end2end_tests',
+        '//test/core/util:grpc_test_util',
+        '//:grpc',
+        '//test/core/util:gpr_test_util',
+        '//:gpr',
+      ],
     )
     for t, topt in END2END_TESTS.items():
       #print(compatible(fopt, topt), f, t, fopt, topt)
       if not compatible(fopt, topt): continue
-      native.sh_test(
+      grpc_sh_test(
         name = '%s_test@%s' % (f, t),
         srcs = ['end2end_test.sh'],
         args = ['$(location %s_test)' % f, t],
diff --git a/test/core/fling/BUILD b/test/core/fling/BUILD
index 0b0ebcb..8f17527 100644
--- a/test/core/fling/BUILD
+++ b/test/core/fling/BUILD
@@ -27,36 +27,68 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
-cc_binary(
+grpc_cc_binary(
     name = "client",
+    testonly = 1,
     srcs = ["client.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
-    testonly = 1,
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "server",
-    srcs = ["server.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
     testonly = 1,
-    copts = ['-std=c99']
+    srcs = ["server.c"],
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "fling",
     srcs = ["fling_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
-    data = [":client", ":server"]
+    data = [
+        ":client",
+        ":server",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "fling_stream",
     srcs = ["fling_stream_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
-    data = [":client", ":server"]
+    data = [
+        ":client",
+        ":server",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
index 996b503..bdb91ea 100644
--- a/test/core/handshake/BUILD
+++ b/test/core/handshake/BUILD
@@ -27,12 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "client_ssl",
     srcs = ["client_ssl.c"],
-    copts = ["-std=c99"],
+    language = "C",
     data = [
         "//src/core/tsi/test_creds:ca.pem",
         "//src/core/tsi/test_creds:server1.key",
@@ -46,10 +48,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "server_ssl",
     srcs = ["server_ssl.c"],
-    copts = ["-std=c99"],
+    language = "C",
     data = [
         "//src/core/tsi/test_creds:ca.pem",
         "//src/core/tsi/test_creds:server1.key",
diff --git a/test/core/http/BUILD b/test/core/http/BUILD
index abfa759..9350dac 100644
--- a/test/core/http/BUILD
+++ b/test/core/http/BUILD
@@ -27,24 +27,34 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "response_fuzzer",
-  srcs = ["response_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "response_corpus",
-  copts = ["-std=c99"],
+    name = "response_fuzzer",
+    srcs = ["response_fuzzer.c"],
+    language = "C",
+    corpus = "response_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
 grpc_fuzzer(
-  name = "request_fuzzer",
-  srcs = ["request_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "request_corpus",
-  copts = ["-std=c99"],
+    name = "request_fuzzer",
+    srcs = ["request_fuzzer.c"],
+    language = "C",
+    corpus = "request_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
 # Copyright 2017, Google Inc.
@@ -80,25 +90,43 @@
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
-cc_test(
+grpc_cc_test(
     name = "httpcli_test",
     srcs = ["httpcli_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
-    copts = ['-std=c99'],
-    data = ['test_server.py']
+    language = "C",
+    data = ["test_server.py"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "httpscli_test",
     srcs = ["httpscli_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
-    copts = ['-std=c99'],
-    data = ['test_server.py']
+    language = "C",
+    data = ["test_server.py"],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "parser_test",
     srcs = ["parser_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/end2end:ssl_test_data"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD
index 808faf5..269ca94 100644
--- a/test/core/iomgr/BUILD
+++ b/test/core/iomgr/BUILD
@@ -27,155 +27,266 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
-cc_library(
+package(default_visibility = ["//visibility:public"]) # Useful for third party devs to test their io manager implementation.
+
+grpc_cc_library(
     name = "endpoint_tests",
     srcs = ["endpoint_tests.c"],
     hdrs = ["endpoint_tests.h"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+    language = "C",
     visibility = ["//test:__subpackages__"],
-    copts = ['-std=c99']
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "combiner_test",
     srcs = ["combiner_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "endpoint_pair_test",
     srcs = ["endpoint_pair_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", ":endpoint_tests"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        ":endpoint_tests",
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "ev_epollsig_linux_test",
     srcs = ["ev_epollsig_linux_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+    language = "C",
 )
 
-cc_test(
+grpc_cc_test(
     name = "fd_conservation_posix_test",
     srcs = ["fd_conservation_posix_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "fd_posix_test",
     srcs = ["fd_posix_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "load_file_test",
     srcs = ["load_file_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "pollset_set_test",
     srcs = ["pollset_set_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "resolve_address_posix_test",
     srcs = ["resolve_address_posix_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "resolve_address_test",
     srcs = ["resolve_address_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "resource_quota_test",
     srcs = ["resource_quota_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "sockaddr_utils_test",
     srcs = ["sockaddr_utils_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "socket_utils_test",
     srcs = ["socket_utils_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "tcp_client_posix_test",
     srcs = ["tcp_client_posix_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "tcp_posix_test",
     srcs = ["tcp_posix_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", ":endpoint_tests"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        ":endpoint_tests",
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "tcp_server_posix_test",
     srcs = ["tcp_server_posix_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "time_averaged_stats_test",
     srcs = ["time_averaged_stats_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "timer_heap_test",
     srcs = ["timer_heap_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "timer_list_test",
     srcs = ["timer_list_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "udp_server_test",
     srcs = ["udp_server_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "wakeup_fd_cv_test",
     srcs = ["wakeup_fd_cv_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/json/BUILD b/test/core/json/BUILD
index f5a877e..aba2e2c 100644
--- a/test/core/json/BUILD
+++ b/test/core/json/BUILD
@@ -27,44 +27,75 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "json_fuzzer",
-  srcs = ["fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "corpus",
-  copts = ["-std=c99"],
+    name = "json_fuzzer",
+    srcs = ["fuzzer.c"],
+    language = "C",
+    corpus = "corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "json_rewrite",
-    srcs = ["json_rewrite.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
     testonly = 1,
-    copts = ['-std=c99']
+    srcs = ["json_rewrite.c"],
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "json_rewrite_test",
     srcs = ["json_rewrite_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99'],
-    data = ["rewrite_test_input.json", "rewrite_test_output_condensed.json", "rewrite_test_output_indented.json", ":json_stream_error_test"]
+    language = "C",
+    data = [
+        "rewrite_test_input.json",
+        "rewrite_test_output_condensed.json",
+        "rewrite_test_output_indented.json",
+        ":json_stream_error_test",
+    ],
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "json_stream_error_test",
     srcs = ["json_stream_error_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "json_test",
     srcs = ["json_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/nanopb/BUILD b/test/core/nanopb/BUILD
index b02d750..33e9338 100644
--- a/test/core/nanopb/BUILD
+++ b/test/core/nanopb/BUILD
@@ -27,23 +27,32 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "fuzzer_response",
-  srcs = ["fuzzer_response.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "corpus_response",
-  copts = ["-std=c99"],
+    name = "fuzzer_response",
+    srcs = ["fuzzer_response.c"],
+    language = "C",
+    corpus = "corpus_response",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
 grpc_fuzzer(
-  name = "fuzzer_serverlist",
-  srcs = ["fuzzer_serverlist.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "corpus_serverlist",
-  copts = ["-std=c99"],
+    name = "fuzzer_serverlist",
+    srcs = ["fuzzer_serverlist.c"],
+    language = "C",
+    corpus = "corpus_serverlist",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
-
diff --git a/test/core/network_benchmarks/BUILD b/test/core/network_benchmarks/BUILD
index a5209de..5c243f7 100644
--- a/test/core/network_benchmarks/BUILD
+++ b/test/core/network_benchmarks/BUILD
@@ -27,11 +27,18 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_binary(
+grpc_cc_binary(
     name = "low_level_ping_pong",
     srcs = ["low_level_ping_pong.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index a81e1d3..b2d8774 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -27,72 +27,110 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "ssl_server_fuzzer",
-  srcs = ["ssl_server_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util", "//test/core/end2end:ssl_test_data"],
-  corpus = "corpus",
-  copts = ["-std=c99"],
+    name = "ssl_server_fuzzer",
+    srcs = ["ssl_server_fuzzer.c"],
+    language = "C",
+    corpus = "corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/end2end:ssl_test_data",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "oauth2_utils",
     srcs = ["oauth2_utils.c"],
     hdrs = ["oauth2_utils.h"],
+    language = "C",
     deps = ["//:grpc"],
-    copts = ['-std=c99'],
     visibility = ["//test/cpp:__subpackages__"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "auth_context_test",
     srcs = ["auth_context_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "credentials_test",
     srcs = ["credentials_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "secure_endpoint_test",
     srcs = ["secure_endpoint_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util", "//test/core/iomgr:endpoint_tests"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/iomgr:endpoint_tests",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "security_connector_test",
     srcs = ["security_connector_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "create_jwt",
     srcs = ["create_jwt.c"],
-    deps = ["//:grpc", "//:gpr"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+    ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "fetch_oauth2",
     srcs = ["fetch_oauth2.c"],
-    deps = ["//:grpc", "//:gpr", ":oauth2_utils"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        ":oauth2_utils",
+        "//:gpr",
+        "//:grpc",
+    ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "verify_jwt",
     srcs = ["verify_jwt.c"],
-    deps = ["//:grpc", "//:gpr"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+    ],
 )
diff --git a/test/core/slice/BUILD b/test/core/slice/BUILD
index 18cf6f6..8dc34e7 100644
--- a/test/core/slice/BUILD
+++ b/test/core/slice/BUILD
@@ -27,56 +27,77 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "percent_decode_fuzzer",
-  srcs = ["percent_decode_fuzzer.c"],
-  deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "response_corpus",
-  copts = ["-std=c99"],
+    name = "percent_decode_fuzzer",
+    srcs = ["percent_decode_fuzzer.c"],
+    language = "C",
+    corpus = "response_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "percent_encoding_test",
     srcs = ["percent_encoding_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "slice_test",
     srcs = ["slice_test.c"],
     deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
 )
 
-cc_test(
+grpc_cc_test(
     name = "slice_string_helpers_test",
     srcs = ["slice_string_helpers_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "slice_buffer_test",
     srcs = ["slice_buffer_test.c"],
     deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
 )
 
-cc_test(
+grpc_cc_test(
     name = "slice_hash_table_test",
     srcs = ["slice_hash_table_test.c"],
     deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
 )
 
-cc_test(
+grpc_cc_test(
     name = "b64_test",
     srcs = ["b64_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index 3183510..db40819 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -27,137 +27,196 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "alloc_test",
     srcs = ["alloc_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "avl_test",
     srcs = ["avl_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "backoff_test",
     srcs = ["backoff_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "cmdline_test",
     srcs = ["cmdline_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "cpu_test",
     srcs = ["cpu_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "env_test",
     srcs = ["env_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "histogram_test",
     srcs = ["histogram_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "host_port_test",
     srcs = ["host_port_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "log_test",
     srcs = ["log_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "mpscq_test",
     srcs = ["mpscq_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "murmur_hash_test",
     srcs = ["murmur_hash_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "stack_lockfree_test",
     srcs = ["stack_lockfree_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "string_test",
     srcs = ["string_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "spinlock_test",
     srcs = ["spinlock_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "sync_test",
     srcs = ["sync_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "thd_test",
     srcs = ["thd_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "time_test",
     srcs = ["time_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "tls_test",
     srcs = ["tls_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "useful_test",
     srcs = ["useful_test.c"],
-    deps = ["//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//test/core/util:gpr_test_util",
+    ],
 )
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
index 3d5e26c..44d37da 100644
--- a/test/core/surface/BUILD
+++ b/test/core/surface/BUILD
@@ -27,12 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "alarm_test",
     srcs = ["alarm_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -41,10 +43,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "grpc_byte_buffer_reader_test",
     srcs = ["byte_buffer_reader_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -53,10 +55,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "channel_create_test",
     srcs = ["channel_create_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -65,10 +67,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "grpc_completion_queue_test",
     srcs = ["completion_queue_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -77,10 +79,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "concurrent_connectivity_test",
     srcs = ["concurrent_connectivity_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -89,10 +91,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "init_test",
     srcs = ["init_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -101,10 +103,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "grpc_invalid_channel_args_test",
     srcs = ["invalid_channel_args_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -113,10 +115,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "lame_client_test",
     srcs = ["lame_client_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -126,10 +128,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "public_headers_must_be_c89",
     srcs = ["public_headers_must_be_c89.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -138,10 +140,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "secure_channel_create_test",
     srcs = ["secure_channel_create_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -150,10 +152,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "sequential_connectivity_test",
     srcs = ["sequential_connectivity_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -163,10 +165,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "server_chttp2_test",
     srcs = ["server_chttp2_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
@@ -175,10 +177,10 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "server_test",
     srcs = ["server_test.c"],
-    copts = ["-std=c99"],
+    language = "C",
     deps = [
         "//:gpr",
         "//:grpc",
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
index 08b2fd3..2628c89 100644
--- a/test/core/transport/BUILD
+++ b/test/core/transport/BUILD
@@ -27,53 +27,90 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "bdp_estimator_test",
     srcs = ["bdp_estimator_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "connectivity_state_test",
     srcs = ["connectivity_state_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "metadata_test",
     srcs = ["metadata_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "pid_controller_test",
     srcs = ["pid_controller_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "status_conversion_test",
     srcs = ["status_conversion_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "stream_owned_slice_test",
     srcs = ["stream_owned_slice_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "timeout_encoding_test",
     srcs = ["timeout_encoding_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/transport/chttp2/BUILD b/test/core/transport/chttp2/BUILD
index b507e27..af2a4ae 100644
--- a/test/core/transport/chttp2/BUILD
+++ b/test/core/transport/chttp2/BUILD
@@ -27,69 +27,114 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
-  name = "hpack_parser_fuzzer",
-  srcs = ["hpack_parser_fuzzer_test.c"],
-  deps = ["//:grpc", "//test/core/util:grpc_test_util"],
-  corpus = "hpack_parser_corpus"
+    name = "hpack_parser_fuzzer",
+    srcs = ["hpack_parser_fuzzer_test.c"],
+    corpus = "hpack_parser_corpus",
+    deps = [
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "alpn_test",
     srcs = ["alpn_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bin_decoder_test",
     srcs = ["bin_decoder_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bin_encoder_test",
     srcs = ["bin_encoder_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "hpack_encoder_test",
     srcs = ["hpack_encoder_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "hpack_parser_test",
     srcs = ["hpack_parser_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "hpack_table_test",
     srcs = ["hpack_table_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "stream_map_test",
     srcs = ["stream_map_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "varint_test",
     srcs = ["varint_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/tsi/BUILD b/test/core/tsi/BUILD
index e6cba34..a0f2910 100644
--- a/test/core/tsi/BUILD
+++ b/test/core/tsi/BUILD
@@ -27,11 +27,18 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+grpc_cc_test(
     name = "transport_security_test",
     srcs = ["transport_security_test.c"],
-    deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
-    copts = ['-std=c99']
+    language = "C",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
 )
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index 03c79f1..6b99462 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -27,23 +27,26 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_cc_binary")
+
 licenses(["notice"])  # 3-clause BSD
 
-cc_library(
+package(default_visibility = ["//visibility:public"])
+
+grpc_cc_library(
     name = "gpr_test_util",
     srcs = [
-        "test_config.c",
         "memory_counters.c",
+        "test_config.c",
     ],
     hdrs = [
-        "test_config.h",
         "memory_counters.h",
+        "test_config.h",
     ],
     deps = ["//:gpr"],
-    visibility = ["//:__subpackages__"],
 )
 
-cc_library(
+grpc_cc_library(
     name = "grpc_test_util",
     srcs = [
         "debugger_macros.c",
@@ -60,7 +63,6 @@
     ],
     hdrs = [
         "debugger_macros.h",
-        "trickle_endpoint.h",
         "grpc_profiler.h",
         "mock_endpoint.h",
         "parse_hexstring.h",
@@ -70,21 +72,25 @@
         "reconnect_server.h",
         "slice_splitter.h",
         "test_tcp_server.h",
+        "trickle_endpoint.h",
     ],
-    deps = [":gpr_test_util", "//:grpc"],
-    visibility = ["//test:__subpackages__"],
-    copts = ["-std=c99"],
+    language = "C",
+    deps = [
+        ":gpr_test_util",
+        "//:grpc",
+    ],
 )
 
-cc_library(
-  name = "one_corpus_entry_fuzzer",
-  srcs = ["one_corpus_entry_fuzzer.c"],
-  deps = [":gpr_test_util", "//:grpc"],
-  visibility = ["//test:__subpackages__"],
+grpc_cc_library(
+    name = "one_corpus_entry_fuzzer",
+    srcs = ["one_corpus_entry_fuzzer.c"],
+    deps = [
+        ":gpr_test_util",
+        "//:grpc",
+    ],
 )
 
 sh_library(
-  name = "fuzzer_one_entry_runner",
-  srcs = ["fuzzer_one_entry_runner.sh"],
-  visibility = ["//test:__subpackages__"],
+    name = "fuzzer_one_entry_runner",
+    srcs = ["fuzzer_one_entry_runner.sh"],
 )
diff --git a/test/core/util/grpc_fuzzer.bzl b/test/core/util/grpc_fuzzer.bzl
index 2f552a9..2fcb58b 100644
--- a/test/core/util/grpc_fuzzer.bzl
+++ b/test/core/util/grpc_fuzzer.bzl
@@ -27,8 +27,10 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_binary")
+
 def grpc_fuzzer(name, corpus, srcs = [], deps = [], **kwargs):
-  native.cc_binary(
+  grpc_cc_binary(
     name = '%s/one_entry.bin' % name,
     srcs = srcs,
     deps = deps + ["//test/core/util:one_corpus_entry_fuzzer"],
diff --git a/test/cpp/codegen/BUILD b/test/cpp/codegen/BUILD
index 43d133f..f974e63 100644
--- a/test/cpp/codegen/BUILD
+++ b/test/cpp/codegen/BUILD
@@ -29,37 +29,45 @@
 
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
+
+grpc_cc_test(
     name = "codegen_test_full",
     srcs = ["codegen_test_full.cc"],
     deps = [
         "//:grpc++",
-        "//external:gtest",
         "//test/core/util:gpr_test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "codegen_test_minimal",
     srcs = ["codegen_test_minimal.cc"],
     deps = [
         "//:grpc++",
-        "//external:gtest",
         "//test/core/util:gpr_test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "proto_utils_test",
     srcs = ["proto_utils_test.cc"],
     deps = [
         "//:grpc++",
-        "//external:gtest",
         "//test/core/util:gpr_test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "golden_file_test",
     srcs = ["golden_file_test.cc"],
     args = ["--generated_file_path=$(GENDIR)/src/proto/grpc/testing/"],
@@ -69,9 +77,11 @@
     ],
     deps = [
         "//:grpc++",
-        "//external:gflags",
-        "//external:gtest",
         "//src/proto/grpc/testing:compiler_test_proto",
         "//test/core/util:gpr_test_util",
     ],
+    external_deps = [
+        "gtest",
+        "gflags",
+    ],
 )
diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD
index 48ad583..c8b3e46 100644
--- a/test/cpp/common/BUILD
+++ b/test/cpp/common/BUILD
@@ -29,32 +29,66 @@
 
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test")
+
+grpc_cc_test(
     name = "alarm_cpp_test",
     srcs = ["alarm_cpp_test.cc"],
-    deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"],
+    deps = [
+        "//:grpc++",
+        "//test/core/util:gpr_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "auth_property_iterator_test",
     srcs = ["auth_property_iterator_test.cc"],
-    deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util", "//test/cpp/util:test_util"],
+    deps = [
+        "//:grpc++",
+        "//test/core/util:gpr_test_util",
+        "//test/cpp/util:test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "channel_arguments_test",
     srcs = ["channel_arguments_test.cc"],
-    deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"],
+    deps = [
+        "//:grpc++",
+        "//test/core/util:gpr_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "channel_filter_test",
     srcs = ["channel_filter_test.cc"],
-    deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util"],
+    deps = [
+        "//:grpc++",
+        "//test/core/util:gpr_test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "secure_auth_context_test",
     srcs = ["secure_auth_context_test.cc"],
-    deps = ["//:grpc++", "//external:gtest", "//test/core/util:gpr_test_util", "//test/cpp/util:test_util"],
+    deps = [
+        "//:grpc++",
+        "//test/core/util:gpr_test_util",
+        "//test/cpp/util:test_util",
+    ],
+    external_deps = [
+        "gtest",
+    ],
 )
diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD
index e867493..9b691a8 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -29,25 +29,30 @@
 
 licenses(["notice"])  # 3-clause BSD
 
-cc_library(
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test")
+
+package(default_visibility=["//visibility:public"]) # Allows external users to implement end2end tests.
+
+grpc_cc_library(
     name = "test_service_impl",
     srcs = ["test_service_impl.cc"],
     hdrs = ["test_service_impl.h"],
     deps = [
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_proto",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "async_end2end_test",
     srcs = ["async_end2end_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/health/v1:health_proto",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
@@ -56,16 +61,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "client_crash_test",
     srcs = ["client_crash_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -73,17 +80,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "client_crash_test_server",
     srcs = ["client_crash_test_server.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gflags",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -91,17 +99,21 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gflags",
+        "gtest",
+    ],
 )
 
-cc_test(
-    name = "end2end_test",
+grpc_cc_library(
+    name = "end2end_test_lib",
     srcs = ["end2end_test.cc"],
+    testonly = True,
     deps = [
         ":test_service_impl",
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -109,16 +121,25 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
+    name = "end2end_test",
+    deps = [
+        ":end2end_test_lib"
+    ],
+)
+
+grpc_cc_test(
     name = "filter_end2end_test",
     srcs = ["filter_end2end_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -126,16 +147,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "generic_end2end_test",
     srcs = ["generic_end2end_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -143,9 +166,12 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "hybrid_end2end_test",
     srcs = ["hybrid_end2end_test.cc"],
     deps = [
@@ -153,7 +179,6 @@
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -161,16 +186,19 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "mock_test",
     srcs = ["mock_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
+        "//:grpc++_test",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -178,9 +206,12 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "round_robin_end2end_test",
     srcs = ["round_robin_end2end_test.cc"],
     deps = [
@@ -188,7 +219,6 @@
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -196,10 +226,12 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-
-cc_test(
+grpc_cc_test(
     name = "grpclb_end2end_test",
     srcs = ["grpclb_end2end_test.cc"],
     deps = [
@@ -207,7 +239,6 @@
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/lb/v1:load_balancer_proto",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
@@ -217,9 +248,12 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "proto_server_reflection_test",
     srcs = ["proto_server_reflection_test.cc"],
     deps = [
@@ -228,8 +262,6 @@
         "//:grpc",
         "//:grpc++",
         "//:grpc++_reflection",
-        "//external:gflags",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -238,9 +270,13 @@
         "//test/cpp/util:grpc++_proto_reflection_desc_db",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+        "gflags",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "server_builder_plugin_test",
     srcs = ["server_builder_plugin_test.cc"],
     deps = [
@@ -248,7 +284,6 @@
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -256,16 +291,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "server_crash_test",
     srcs = ["server_crash_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -273,17 +310,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "server_crash_test_client",
     srcs = ["server_crash_test_client.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gflags",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -291,16 +329,19 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gflags",
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "shutdown_test",
     srcs = ["shutdown_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -308,16 +349,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "streaming_throughput_test",
     srcs = ["streaming_throughput_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -325,16 +368,18 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "thread_stress_test",
     srcs = ["thread_stress_test.cc"],
     deps = [
         "//:gpr",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:echo_messages_proto",
         "//src/proto/grpc/testing:echo_proto",
         "//src/proto/grpc/testing/duplicate:echo_duplicate_proto",
@@ -342,4 +387,7 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index cc3958b..8d59cbb 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -47,7 +47,6 @@
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
 #include <grpc/support/tls.h>
-#include <gtest/gtest.h>
 
 #include "src/core/lib/iomgr/port.h"
 #include "src/proto/grpc/health/v1/health.grpc.pb.h"
@@ -58,6 +57,8 @@
 #include "test/cpp/util/string_ref_helper.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+#include <gtest/gtest.h>
+
 #ifdef GRPC_POSIX_SOCKET
 #include "src/core/lib/iomgr/ev_posix.h"
 #endif
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 966c04b..0ea5209 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -41,7 +41,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -49,6 +48,8 @@
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/subprocess.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index df71777..9a9e818 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -48,7 +48,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/core/lib/security/credentials/credentials.h"
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
@@ -59,6 +58,8 @@
 #include "test/cpp/util/string_ref_helper.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using grpc::testing::kTlsCredentialsType;
diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc
index 2f873ee..5589e2f 100644
--- a/test/cpp/end2end/filter_end2end_test.cc
+++ b/test/cpp/end2end/filter_end2end_test.cc
@@ -48,7 +48,6 @@
 #include <grpc/grpc.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/cpp/common/channel_filter.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -56,6 +55,8 @@
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/byte_buffer_proto_helper.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 25c221b..281c58e 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -46,13 +46,14 @@
 #include <grpc/grpc.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/byte_buffer_proto_helper.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
@@ -115,6 +116,10 @@
   void client_fail(int i) { verify_ok(&cli_cq_, i, false); }
 
   void SendRpc(int num_rpcs) {
+    SendRpc(num_rpcs, false, gpr_inf_future(GPR_CLOCK_MONOTONIC));
+  }
+
+  void SendRpc(int num_rpcs, bool check_deadline, gpr_timespec deadline) {
     const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo");
     for (int i = 0; i < num_rpcs; i++) {
       EchoRequest send_request;
@@ -129,6 +134,11 @@
 
       // The string needs to be long enough to test heap-based slice.
       send_request.set_message("Hello world. Hello world. Hello world.");
+
+      if (check_deadline) {
+        cli_ctx.set_deadline(deadline);
+      }
+
       std::unique_ptr<GenericClientAsyncReaderWriter> call =
           generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1));
       client_ok(1);
@@ -147,6 +157,12 @@
       verify_ok(srv_cq_.get(), 4, true);
       EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length()));
       EXPECT_EQ(kMethodName, srv_ctx.method());
+
+      if (check_deadline) {
+        EXPECT_TRUE(gpr_time_similar(deadline, srv_ctx.raw_deadline(),
+                                     gpr_time_from_millis(100, GPR_TIMESPAN)));
+      }
+
       ByteBuffer recv_buffer;
       stream.Read(&recv_buffer, tag(5));
       server_ok(5);
@@ -262,6 +278,12 @@
   EXPECT_TRUE(recv_status.ok());
 }
 
+TEST_F(GenericEnd2endTest, Deadline) {
+  ResetStub();
+  SendRpc(1, true, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                                gpr_time_from_seconds(10, GPR_TIMESPAN)));
+}
+
 }  // namespace
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/end2end/health_service_end2end_test.cc b/test/cpp/end2end/health_service_end2end_test.cc
index 3d51007..c320c78 100644
--- a/test/cpp/end2end/health_service_end2end_test.cc
+++ b/test/cpp/end2end/health_service_end2end_test.cc
@@ -46,7 +46,6 @@
 #include <grpc++/server_context.h>
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/health/v1/health.grpc.pb.h"
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
@@ -55,6 +54,8 @@
 #include "test/core/util/test_config.h"
 #include "test/cpp/end2end/test_service_impl.h"
 
+#include <gtest/gtest.h>
+
 using grpc::health::v1::Health;
 using grpc::health::v1::HealthCheckRequest;
 using grpc::health::v1::HealthCheckResponse;
diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc
index a4ba76f..1cd515a 100644
--- a/test/cpp/end2end/hybrid_end2end_test.cc
+++ b/test/cpp/end2end/hybrid_end2end_test.cc
@@ -42,7 +42,6 @@
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
 #include <grpc/grpc.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -51,6 +50,8 @@
 #include "test/cpp/end2end/test_service_impl.h"
 #include "test/cpp/util/byte_buffer_proto_helper.h"
 
+#include <gtest/gtest.h>
+
 namespace grpc {
 namespace testing {
 
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 7e33006..3a82b3a 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -45,7 +45,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include <grpc++/test/mock_stream.h>
 
@@ -55,6 +54,8 @@
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
+#include <gtest/gtest.h>
+
 #include <iostream>
 
 using namespace std;
diff --git a/test/cpp/end2end/proto_server_reflection_test.cc b/test/cpp/end2end/proto_server_reflection_test.cc
index 8b9688d..25cb0d5 100644
--- a/test/cpp/end2end/proto_server_reflection_test.cc
+++ b/test/cpp/end2end/proto_server_reflection_test.cc
@@ -41,7 +41,6 @@
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
 #include <grpc/grpc.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
@@ -49,6 +48,8 @@
 #include "test/cpp/end2end/test_service_impl.h"
 #include "test/cpp/util/proto_reflection_descriptor_database.h"
 
+#include <gtest/gtest.h>
+
 namespace grpc {
 namespace testing {
 
diff --git a/test/cpp/end2end/round_robin_end2end_test.cc b/test/cpp/end2end/round_robin_end2end_test.cc
index cc340b9..f8e3cc0 100644
--- a/test/cpp/end2end/round_robin_end2end_test.cc
+++ b/test/cpp/end2end/round_robin_end2end_test.cc
@@ -44,13 +44,14 @@
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/end2end/test_service_impl.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
diff --git a/test/cpp/end2end/server_builder_plugin_test.cc b/test/cpp/end2end/server_builder_plugin_test.cc
index 1b6f4ce..81b747a 100644
--- a/test/cpp/end2end/server_builder_plugin_test.cc
+++ b/test/cpp/end2end/server_builder_plugin_test.cc
@@ -45,13 +45,14 @@
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
 #include <grpc/grpc.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/end2end/test_service_impl.h"
 
+#include <gtest/gtest.h>
+
 #define PLUGIN_NAME "TestServerBuilderPlugin"
 
 namespace grpc {
diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc
index b1f9216..4b7041a 100644
--- a/test/cpp/end2end/server_crash_test.cc
+++ b/test/cpp/end2end/server_crash_test.cc
@@ -41,7 +41,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
@@ -49,6 +48,8 @@
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/subprocess.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc
index bd68e85..63b397d 100644
--- a/test/cpp/end2end/shutdown_test.cc
+++ b/test/cpp/end2end/shutdown_test.cc
@@ -33,8 +33,6 @@
 
 #include <thread>
 
-#include <gtest/gtest.h>
-
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
@@ -51,6 +49,8 @@
 #include "test/core/util/test_config.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 
diff --git a/test/cpp/end2end/streaming_throughput_test.cc b/test/cpp/end2end/streaming_throughput_test.cc
index 3025837..ec5b83d 100644
--- a/test/cpp/end2end/streaming_throughput_test.cc
+++ b/test/cpp/end2end/streaming_throughput_test.cc
@@ -35,8 +35,6 @@
 #include <mutex>
 #include <thread>
 
-#include <gtest/gtest.h>
-
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
@@ -56,6 +54,8 @@
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc
index b473dd1..5411b35 100644
--- a/test/cpp/end2end/test_service_impl.cc
+++ b/test/cpp/end2end/test_service_impl.cc
@@ -40,11 +40,11 @@
 #include <grpc++/server_context.h>
 #include <grpc/support/log.h>
 
-#include <gtest/gtest.h>
-
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/cpp/util/string_ref_helper.h"
 
+#include <gtest/gtest.h>
+
 using std::chrono::system_clock;
 
 namespace grpc {
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index d353f98..defa789 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -43,7 +43,6 @@
 #include <grpc/grpc.h>
 #include <grpc/support/thd.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/core/lib/surface/api_trace.h"
 #include "src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h"
@@ -51,6 +50,8 @@
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 
+#include <gtest/gtest.h>
+
 using grpc::testing::EchoRequest;
 using grpc::testing::EchoResponse;
 using std::chrono::system_clock;
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 208ac6d..3a968a0 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -29,14 +29,17 @@
 
 licenses(["notice"])  # 3-clause BSD
 
-cc_test(
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library")
+
+grpc_cc_test(
     name = "noop-benchmark",
     srcs = ["noop-benchmark.cc"],
-    linkopts = ["-pthread"],
-    deps = ["//external:benchmark"],
+    external_deps = [
+        "benchmark",
+    ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "helpers",
     srcs = ["helpers.cc"],
     hdrs = [
@@ -44,64 +47,68 @@
         "fullstack_fixtures.h",
         "helpers.h",
     ],
-    linkopts = ["-pthread"],
     deps = [
         "//:grpc++",
-        "//external:benchmark",
         "//src/proto/grpc/testing:echo_proto",
         "//test/core/util:grpc_test_util",
     ],
+    external_deps = [
+        "benchmark",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_closure",
     srcs = ["bm_closure.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_cq",
     srcs = ["bm_cq.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_cq_multiple_threads",
     srcs = ["bm_cq_multiple_threads.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_error",
     srcs = ["bm_error.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_fullstack_streaming_ping_pong",
     srcs = ["bm_fullstack_streaming_ping_pong.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_fullstack_streaming_pump",
     srcs = ["bm_fullstack_streaming_pump.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_fullstack_trickle",
     srcs = ["bm_fullstack_trickle.cc"],
-    deps = [":helpers", "//external:gflags"],
+    deps = [":helpers"],
+    external_deps = [
+        "gflags",
+    ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_fullstack_unary_ping_pong",
     srcs = ["bm_fullstack_unary_ping_pong.cc"],
     deps = [":helpers"],
 )
 
-cc_test(
+grpc_cc_test(
     name = "bm_metadata",
     srcs = ["bm_metadata.cc"],
     deps = [":helpers"],
diff --git a/test/cpp/microbenchmarks/helpers.cc b/test/cpp/microbenchmarks/helpers.cc
index 6550742..73ab9e4 100644
--- a/test/cpp/microbenchmarks/helpers.cc
+++ b/test/cpp/microbenchmarks/helpers.cc
@@ -36,11 +36,11 @@
 void TrackCounters::Finish(benchmark::State &state) {
   std::ostringstream out;
   AddToLabel(out, state);
-  auto label = out.str();
+  std::string label = out.str();
   if (label.length() && label[0] == ' ') {
     label = label.substr(1);
   }
-  state.SetLabel(label);
+  state.SetLabel(label.c_str());
 }
 
 void TrackCounters::AddToLabel(std::ostream &out, benchmark::State &state) {
diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD
index 6492b63..c6a1fd2 100644
--- a/test/cpp/qps/BUILD
+++ b/test/cpp/qps/BUILD
@@ -29,14 +29,17 @@
 
 licenses(["notice"])  # 3-clause BSD
 
-cc_library(
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary")
+
+grpc_cc_library(
     name = "parse_json",
     srcs = ["parse_json.cc"],
     hdrs = ["parse_json.h"],
     deps = ["//:grpc++"],
+    external_deps = ["protobuf"],
 )
 
-cc_library(
+grpc_cc_library(
     name = "qps_worker_impl",
     srcs = [
         "client_async.cc",
@@ -56,7 +59,6 @@
         ":usage_timer",
         "//:grpc",
         "//:grpc++",
-        "//external:gtest",
         "//src/proto/grpc/testing:control_proto",
         "//src/proto/grpc/testing:payloads_proto",
         "//src/proto/grpc/testing:services_proto",
@@ -65,9 +67,12 @@
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
     ],
+    external_deps = [
+        "gtest",
+    ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "driver_impl",
     srcs = [
         "driver.cc",
@@ -90,7 +95,7 @@
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "benchmark_config",
     srcs = [
         "benchmark_config.cc",
@@ -102,12 +107,14 @@
         ":driver_impl",
         ":histogram",
         "//:grpc++",
-        "//external:gflags",
         "//src/proto/grpc/testing:control_proto",
     ],
+    external_deps = [
+        "gflags",
+    ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "histogram",
     hdrs = [
         "histogram.h",
@@ -116,13 +123,13 @@
     deps = ["//:gpr"],
 )
 
-cc_library(
+grpc_cc_library(
     name = "interarrival",
     hdrs = ["interarrival.h"],
     deps = ["//:grpc++"],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "json_run_localhost",
     srcs = ["json_run_localhost.cc"],
     deps = [
@@ -133,7 +140,7 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "qps_interarrival_test",
     srcs = ["qps_interarrival_test.cc"],
     deps = [
@@ -142,18 +149,20 @@
     ],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "qps_json_driver",
     srcs = ["qps_json_driver.cc"],
     deps = [
         ":benchmark_config",
         ":driver_impl",
         "//:grpc++",
-        "//external:gflags",
+    ],
+    external_deps = [
+        "gflags",
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "qps_openloop_test",
     srcs = ["qps_openloop_test.cc"],
     deps = [
@@ -163,7 +172,7 @@
     ],
 )
 
-cc_test(
+grpc_cc_test(
     name = "secure_sync_unary_ping_pong_test",
     srcs = ["secure_sync_unary_ping_pong_test.cc"],
     deps = [
@@ -173,14 +182,14 @@
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "usage_timer",
     srcs = ["usage_timer.cc"],
     hdrs = ["usage_timer.h"],
     deps = ["//:gpr"],
 )
 
-cc_binary(
+grpc_cc_binary(
     name = "qps_worker",
     srcs = ["worker.cc"],
     deps = [
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 9075033..f357132 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -48,7 +48,6 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
-#include <gtest/gtest.h>
 
 #include "src/core/lib/profiling/timers.h"
 #include "src/proto/grpc/testing/services.grpc.pb.h"
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index 9dde22b..453e9b6 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -29,16 +29,20 @@
 
 licenses(["notice"])  # 3-clause BSD
 
+load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_binary")
+
+package(default_visibility = ["//visibility:public"])
+
 # The following builds a shared-object to confirm that grpc++_unsecure
 # builds properly. Build-only is sufficient here
-cc_binary(
+grpc_cc_binary(
     name = "testso.so",
     srcs = [],
     linkshared = 1,
     deps = ["//:grpc++_unsecure"],
 )
 
-cc_library(
+grpc_cc_library(
     name = "test_config",
     srcs = [
         "test_config_cc.cc",
@@ -46,14 +50,15 @@
     hdrs = [
         "test_config.h",
     ],
-    visibility = ["//test:__subpackages__"],
+    external_deps = [
+        "gflags",
+    ],
     deps = [
         "//:gpr",
-        "//external:gflags",
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "grpc++_proto_reflection_desc_db",
     srcs = [
         "proto_reflection_descriptor_database.cc",
@@ -61,14 +66,13 @@
     hdrs = [
         "proto_reflection_descriptor_database.h",
     ],
-    visibility = ["//test:__subpackages__"],
     deps = [
         "//:grpc++_config_proto",
         "//src/proto/grpc/reflection/v1alpha:reflection_proto",
     ],
 )
 
-cc_library(
+grpc_cc_library(
     name = "test_util",
     srcs = [
         "byte_buffer_proto_helper.cc",
@@ -84,12 +88,57 @@
         "subprocess.h",
         "test_credentials_provider.h",
     ],
-    visibility = ["//test:__subpackages__"],
     deps = [
         "//:grpc++",
         "//test/core/end2end:ssl_test_data",
         "//test/core/util:gpr_test_util",
     ],
+    external_deps = [
+        "protobuf",
+    ],
+)
+
+grpc_cc_library(
+    name = "grpc_cli_libs",
+    srcs = [
+        "cli_call.cc",
+        "cli_credentials.cc",
+        "grpc_tool.cc",
+        "proto_file_parser.cc",
+        "service_describer.cc",
+    ],
+    hdrs = [
+        "cli_call.h",
+        "cli_credentials.h",
+        "config_grpc_cli.h",
+        "grpc_tool.h",
+        "proto_file_parser.h",
+        "service_describer.h",
+    ],
+    deps = [
+        "//:grpc++",
+        "//src/proto/grpc/reflection/v1alpha:reflection_proto",
+        ":grpc++_proto_reflection_desc_db",
+    ],
+    external_deps = [
+        "gflags",
+        "protobuf",
+        "protobuf_clib",
+    ],
+)
+
+grpc_cc_library(
+    name = "metrics_server_lib",
+    srcs = [
+        "metrics_server.cc",
+    ],
+    hdrs = [
+        "metrics_server.h",
+    ],
+    deps = [
+        "//src/proto/grpc/testing:metrics_proto",
+        "//:grpc++",
+    ],
 )
 
 cc_test(
diff --git a/test/distrib/csharp/run_distrib_test.bat b/test/distrib/csharp/run_distrib_test.bat
index cb5dd55..aeadef3 100644
--- a/test/distrib/csharp/run_distrib_test.bat
+++ b/test/distrib/csharp/run_distrib_test.bat
@@ -31,7 +31,7 @@
 cd /d %~dp0
 
 @rem extract input artifacts
-powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('../../../input_artifacts/csharp_nugets_windows_dotnetcli.zip', 'TestNugetFeed');"
+powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('../../../../input_artifacts/csharp_nugets_windows_dotnetcli.zip', 'TestNugetFeed');"
 
 update_version.sh auto
 
diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile
index 6ea8ef3..c562704 100644
--- a/tools/dockerfile/test/bazel/Dockerfile
+++ b/tools/dockerfile/test/bazel/Dockerfile
@@ -27,46 +27,22 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-FROM ubuntu:15.10
+FROM gcr.io/oss-fuzz-base/base-builder
 
-# Install Git and basic packages.
-RUN apt-get update && apt-get install -y \
+# Install basic packages and Bazel dependencies.
+RUN apt-get update && apt-get install -y software-properties-common python-software-properties
+RUN add-apt-repository ppa:webupd8team/java
+RUN apt-get update && apt-get -y install \
   autoconf \
-  autotools-dev \
   build-essential \
-  bzip2 \
-  ccache \
   curl \
-  gcc \
-  gcc-multilib \
-  git \
-  golang \
-  gyp \
-  lcov \
-  libc6 \
-  libc6-dbg \
-  libc6-dev \
-  libgtest-dev \
   libtool \
   make \
-  perl \
-  strace \
-  python-dev \
-  python-setuptools \
-  python-yaml \
-  telnet \
-  unzip \
-  wget \
-  zip && apt-get clean
-
-#================
-# Build profiling
-RUN apt-get update && apt-get install -y time && apt-get clean
-
+  openjdk-8-jdk \
+  vim
 
 #========================
 # Bazel installation
-RUN apt-get install -y software-properties-common g++
 RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" > /etc/apt/sources.list.d/bazel.list
 RUN curl https://bazel.build/bazel-release.pub.gpg | apt-key add -
 RUN apt-get -y update
diff --git a/tools/gce/create_linux_worker.sh b/tools/gce/create_linux_worker.sh
index 322a592c..b934f22 100755
--- a/tools/gce/create_linux_worker.sh
+++ b/tools/gce/create_linux_worker.sh
@@ -45,7 +45,8 @@
     --machine-type n1-standard-16 \
     --image=ubuntu-1510 \
     --image-project=grpc-testing \
-    --boot-disk-size 1000
+    --boot-disk-size 1000 \
+    --scopes https://www.googleapis.com/auth/bigquery
 
 echo 'Created GCE instance, waiting 60 seconds for it to come online.'
 sleep 60
diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py
index c90da06..5a71b96 100644
--- a/tools/run_tests/artifacts/artifact_targets.py
+++ b/tools/run_tests/artifacts/artifact_targets.py
@@ -45,6 +45,7 @@
   """Creates jobspec for a task running under docker."""
   environ = environ.copy()
   environ['RUN_COMMAND'] = shell_command
+  environ['ARTIFACTS_OUT'] = 'artifacts/%s' % name
 
   docker_args=[]
   for k,v in environ.items():
@@ -65,9 +66,20 @@
   return jobspec
 
 
-def create_jobspec(name, cmdline, environ=None, shell=False,
-                   flake_retries=0, timeout_retries=0, timeout_seconds=30*60):
+def create_jobspec(name, cmdline, environ={}, shell=False,
+                   flake_retries=0, timeout_retries=0, timeout_seconds=30*60,
+                   use_workspace=False,
+                   cpu_cost=1.0):
   """Creates jobspec."""
+  environ = environ.copy()
+  if use_workspace:
+    environ['WORKSPACE_NAME'] = 'workspace_%s' % name
+    environ['ARTIFACTS_OUT'] = os.path.join('..', 'artifacts', name)
+    cmdline = ['bash',
+               'tools/run_tests/artifacts/run_in_workspace.sh'] + cmdline
+  else:
+    environ['ARTIFACTS_OUT'] = os.path.join('artifacts', name)
+
   jobspec = jobset.JobSpec(
           cmdline=cmdline,
           environ=environ,
@@ -75,7 +87,8 @@
           timeout_seconds=timeout_seconds,
           flake_retries=flake_retries,
           timeout_retries=timeout_retries,
-          shell=shell)
+          shell=shell,
+          cpu_cost=cpu_cost)
   return jobspec
 
 
@@ -137,13 +150,14 @@
                              dir
                             ],
                             environ=environ,
-                            shell=True)
+                            use_workspace=True)
     else:
       environ['PYTHON'] = self.py_version
       environ['SKIP_PIP_INSTALL'] = 'TRUE'
       return create_jobspec(self.name,
                             ['tools/run_tests/artifacts/build_artifact_python.sh'],
-                            environ=environ)
+                            environ=environ,
+                            use_workspace=True)
 
   def __str__(self):
     return self.name
@@ -162,20 +176,11 @@
     return []
 
   def build_jobspec(self):
-    if self.platform == 'windows':
-      raise Exception("Not supported yet")
-    else:
-      if self.platform == 'linux':
-        environ = {}
-        if self.arch == 'x86':
-          environ['SETARCH_CMD'] = 'linux32'
-        return create_docker_jobspec(self.name,
-            'tools/dockerfile/grpc_artifact_linux_%s' % self.arch,
-            'tools/run_tests/artifacts/build_artifact_ruby.sh',
-            environ=environ)
-      else:
-        return create_jobspec(self.name,
-                              ['tools/run_tests/artifacts/build_artifact_ruby.sh'])
+    # Ruby build uses docker internally and docker cannot be nested.
+    # We are using a custom workspace instead.
+    return create_jobspec(self.name,
+                          ['tools/run_tests/artifacts/build_artifact_ruby.sh'],
+                          use_workspace=True)
 
 
 class CSharpExtArtifact:
@@ -196,7 +201,7 @@
       return create_jobspec(self.name,
                             ['tools\\run_tests\\artifacts\\build_artifact_csharp.bat',
                              cmake_arch_option],
-                            shell=True)
+                            use_workspace=True)
     else:
       environ = {'CONFIG': 'opt',
                  'EMBED_OPENSSL': 'true',
@@ -216,7 +221,8 @@
         environ['LDFLAGS'] += ' %s' % archflag
         return create_jobspec(self.name,
                               ['tools/run_tests/artifacts/build_artifact_csharp.sh'],
-                              environ=environ)
+                              environ=environ,
+                              use_workspace=True)
 
   def __str__(self):
     return self.name
@@ -242,10 +248,15 @@
 
   def build_jobspec(self):
     if self.platform == 'windows':
+      # Simultaneous builds of node on the same windows machine are flaky.
+      # Set x86 build as exclusive to make sure there is only one node build
+      # at a time. See https://github.com/grpc/grpc/issues/8293
+      cpu_cost = 1e6 if self.arch != 'x64' else 1.0
       return create_jobspec(self.name,
                             ['tools\\run_tests\\artifacts\\build_artifact_node.bat',
                              self.gyp_arch],
-                            shell=True)
+                            use_workspace=True,
+                            cpu_cost=cpu_cost)
     else:
       if self.platform == 'linux':
         return create_docker_jobspec(
@@ -255,7 +266,8 @@
       else:
         return create_jobspec(self.name,
                               ['tools/run_tests/artifacts/build_artifact_node.sh',
-                               self.gyp_arch])
+                               self.gyp_arch],
+                               use_workspace=True)
 
 class PHPArtifact:
   """Builds PHP PECL package"""
@@ -277,7 +289,8 @@
           'tools/run_tests/artifacts/build_artifact_php.sh')
     else:
       return create_jobspec(self.name,
-                            ['tools/run_tests/artifacts/build_artifact_php.sh'])
+                            ['tools/run_tests/artifacts/build_artifact_php.sh'],
+                            use_workspace=True)
 
 class ProtocArtifact:
   """Builds protoc and protoc-plugin artifacts"""
@@ -310,14 +323,16 @@
         environ['CXXFLAGS'] += ' -std=c++11 -stdlib=libc++ %s' % _MACOS_COMPAT_FLAG
         return create_jobspec(self.name,
             ['tools/run_tests/artifacts/build_artifact_protoc.sh'],
-            environ=environ)
+            environ=environ,
+            use_workspace=True)
     else:
       generator = 'Visual Studio 12 Win64' if self.arch == 'x64' else 'Visual Studio 12' 
       vcplatform = 'x64' if self.arch == 'x64' else 'Win32'
       return create_jobspec(self.name,
                             ['tools\\run_tests\\artifacts\\build_artifact_protoc.bat'],
                             environ={'generator': generator,
-                                     'Platform': vcplatform})
+                                     'Platform': vcplatform},
+                            use_workspace=True)
 
   def __str__(self):
     return self.name
@@ -351,7 +366,6 @@
            PythonArtifact('windows', 'x64', 'Python34'),
            PythonArtifact('windows', 'x64', 'Python35'),
            PythonArtifact('windows', 'x64', 'Python36'),
-           RubyArtifact('linux', 'x86'),
            RubyArtifact('linux', 'x64'),
            RubyArtifact('macos', 'x64'),
            PHPArtifact('linux', 'x64'),
diff --git a/tools/run_tests/artifacts/build_artifact_csharp.bat b/tools/run_tests/artifacts/build_artifact_csharp.bat
index f84ebc5..ebb11bf 100644
--- a/tools/run_tests/artifacts/build_artifact_csharp.bat
+++ b/tools/run_tests/artifacts/build_artifact_csharp.bat
@@ -37,8 +37,8 @@
 cmake --build . --target grpc_csharp_ext --config Release
 cd ..\..\..
 
-mkdir artifacts
-copy /Y cmake\build\Win32\Release\grpc_csharp_ext.dll artifacts || copy /Y cmake\build\x64\Release\grpc_csharp_ext.dll artifacts || goto :error
+mkdir -p %ARTIFACTS_OUT%
+copy /Y cmake\build\Win32\Release\grpc_csharp_ext.dll %ARTIFACTS_OUT% || copy /Y cmake\build\x64\Release\grpc_csharp_ext.dll %ARTIFACTS_OUT% || goto :error
 
 goto :EOF
 
diff --git a/tools/run_tests/artifacts/build_artifact_csharp.sh b/tools/run_tests/artifacts/build_artifact_csharp.sh
index aed04b2..2bfa749 100755
--- a/tools/run_tests/artifacts/build_artifact_csharp.sh
+++ b/tools/run_tests/artifacts/build_artifact_csharp.sh
@@ -34,5 +34,5 @@
 
 make grpc_csharp_ext
 
-mkdir -p artifacts
-cp libs/opt/libgrpc_csharp_ext.so artifacts || cp libs/opt/libgrpc_csharp_ext.dylib artifacts
+mkdir -p "${ARTIFACTS_OUT}"
+cp libs/opt/libgrpc_csharp_ext.so "${ARTIFACTS_OUT}" || cp libs/opt/libgrpc_csharp_ext.dylib "${ARTIFACTS_OUT}"
diff --git a/tools/run_tests/artifacts/build_artifact_node.bat b/tools/run_tests/artifacts/build_artifact_node.bat
index bfd4461..da4d479 100644
--- a/tools/run_tests/artifacts/build_artifact_node.bat
+++ b/tools/run_tests/artifacts/build_artifact_node.bat
@@ -37,7 +37,7 @@
 
 call npm update || goto :error
 
-mkdir artifacts
+mkdir -p %ARTIFACTS_OUT%
 
 for %%v in (%node_versions%) do (
   call .\node_modules\.bin\node-pre-gyp.cmd configure build --target=%%v --target_arch=%1
@@ -47,13 +47,13 @@
   rmdir "%HOMEDRIVE%%HOMEPATH%\.node-gyp\iojs-%%v\include\node\openssl" /S /Q
   call .\node_modules\.bin\node-pre-gyp.cmd build package testpackage --target=%%v --target_arch=%1 || goto :error
 
-  xcopy /Y /I /S build\stage\* artifacts\ || goto :error
+  xcopy /Y /I /S build\stage\* %ARTIFACTS_OUT%\ || goto :error
 )
 
 for %%v in (%electron_versions%) do (
   cmd /V /C "set "HOME=%HOMEDRIVE%%HOMEPATH%\electron-gyp" && call .\node_modules\.bin\node-pre-gyp.cmd configure rebuild package testpackage --runtime=electron --target=%%v --target_arch=%1 --disturl=https://atom.io/download/electron" || goto :error
 
-  xcopy /Y /I /S build\stage\* artifacts\ || goto :error
+  xcopy /Y /I /S build\stage\* %ARTIFACTS_OUT%\ || goto :error
 )
 if %errorlevel% neq 0 exit /b %errorlevel%
 
diff --git a/tools/run_tests/artifacts/build_artifact_node.sh b/tools/run_tests/artifacts/build_artifact_node.sh
index 7a74755..3947bde 100755
--- a/tools/run_tests/artifacts/build_artifact_node.sh
+++ b/tools/run_tests/artifacts/build_artifact_node.sh
@@ -38,7 +38,7 @@
 
 rm -rf build || true
 
-mkdir -p artifacts
+mkdir -p "${ARTIFACTS_OUT}"
 
 npm update
 
@@ -49,11 +49,11 @@
 for version in ${node_versions[@]}
 do
   ./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --target=$version --target_arch=$NODE_TARGET_ARCH --grpc_alpine=true
-  cp -r build/stage/* artifacts/
+  cp -r build/stage/* "${ARTIFACTS_OUT}"/
 done
 
 for version in ${electron_versions[@]}
 do
   HOME=~/.electron-gyp ./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --runtime=electron --target=$version --target_arch=$NODE_TARGET_ARCH --disturl=https://atom.io/download/electron
-  cp -r build/stage/* artifacts/
+  cp -r build/stage/* "${ARTIFACTS_OUT}"/
 done
diff --git a/tools/run_tests/artifacts/build_artifact_php.sh b/tools/run_tests/artifacts/build_artifact_php.sh
index c8d5586..d7f8c8f 100755
--- a/tools/run_tests/artifacts/build_artifact_php.sh
+++ b/tools/run_tests/artifacts/build_artifact_php.sh
@@ -33,8 +33,8 @@
 
 cd $(dirname $0)/../../..
 
-mkdir -p artifacts
+mkdir -p "${ARTIFACTS_OUT}"
 
 pear package
 
-cp -r grpc-*.tgz artifacts/
+cp -r grpc-*.tgz "${ARTIFACTS_OUT}"/
diff --git a/tools/run_tests/artifacts/build_artifact_protoc.bat b/tools/run_tests/artifacts/build_artifact_protoc.bat
index b2bf86d..def64bd 100644
--- a/tools/run_tests/artifacts/build_artifact_protoc.bat
+++ b/tools/run_tests/artifacts/build_artifact_protoc.bat
@@ -27,7 +27,7 @@
 @rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 @rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-mkdir artifacts
+mkdir -p %ARTIFACTS_OUT%
 
 setlocal
 cd third_party/protobuf/cmake
@@ -39,8 +39,8 @@
 
 call vsprojects/build_plugins.bat || goto :error
 
-xcopy /Y third_party\protobuf\cmake\build\solution\Release\protoc.exe artifacts\ || goto :error
-xcopy /Y vsprojects\Release\*_plugin.exe artifacts\ || xcopy /Y vsprojects\x64\Release\*_plugin.exe artifacts\ || goto :error
+xcopy /Y third_party\protobuf\cmake\build\solution\Release\protoc.exe %ARTIFACTS_OUT%\ || goto :error
+xcopy /Y vsprojects\Release\*_plugin.exe %ARTIFACTS_OUT%\ || xcopy /Y vsprojects\x64\Release\*_plugin.exe %ARTIFACTS_OUT%\ || goto :error
 
 goto :EOF
 
diff --git a/tools/run_tests/artifacts/build_artifact_protoc.sh b/tools/run_tests/artifacts/build_artifact_protoc.sh
index 26c2280..df78203 100755
--- a/tools/run_tests/artifacts/build_artifact_protoc.sh
+++ b/tools/run_tests/artifacts/build_artifact_protoc.sh
@@ -37,5 +37,5 @@
 
 make plugins
 
-mkdir -p artifacts
-cp bins/opt/protobuf/protoc bins/opt/*_plugin artifacts/
+mkdir -p "${ARTIFACTS_OUT}"
+cp bins/opt/protobuf/protoc bins/opt/*_plugin "${ARTIFACTS_OUT}"/
diff --git a/tools/run_tests/artifacts/build_artifact_python.bat b/tools/run_tests/artifacts/build_artifact_python.bat
index 246713a..860b9e8 100644
--- a/tools/run_tests/artifacts/build_artifact_python.bat
+++ b/tools/run_tests/artifacts/build_artifact_python.bat
@@ -38,8 +38,9 @@
 
 @rem Multiple builds are running simultaneously, so to avoid distutils
 @rem file collisions, we build everything in a tmp directory
-if not exist "artifacts" mkdir "artifacts"
-set ARTIFACT_DIR=%cd%\artifacts
+@rem TODO(jtattermusch): it doesn't look like builds are actually running in parallel in the same dir
+mkdir -p %ARTIFACTS_OUT%
+set ARTIFACT_DIR=%cd%\%ARTIFACTS_OUT%
 set BUILD_DIR=C:\Windows\Temp\pygrpc-%3\
 mkdir %BUILD_DIR%
 xcopy /s/e/q %cd%\* %BUILD_DIR%
diff --git a/tools/run_tests/artifacts/build_artifact_python.sh b/tools/run_tests/artifacts/build_artifact_python.sh
index 5a55060..a1f0a58 100755
--- a/tools/run_tests/artifacts/build_artifact_python.sh
+++ b/tools/run_tests/artifacts/build_artifact_python.sh
@@ -41,8 +41,9 @@
 # Because multiple builds run in parallel, some distutils file
 # operations may collide.  To avoid this, each build is run in
 # a temp directory
-mkdir -p artifacts
-ARTIFACT_DIR="$PWD/artifacts"
+# TODO(jtattermusch): it doesn't look like builds are actually running in parallel in the same dir
+mkdir -p "${ARTIFACTS_OUT}"
+ARTIFACT_DIR="$PWD/${ARTIFACTS_OUT}"
 BUILD_DIR=`mktemp -d "${TMPDIR:-/tmp}/pygrpc.XXXXXX"`
 trap "rm -rf $BUILD_DIR" EXIT
 cp -r * "$BUILD_DIR"
diff --git a/tools/run_tests/artifacts/build_artifact_ruby.sh b/tools/run_tests/artifacts/build_artifact_ruby.sh
index ca461ba..c92d7a8 100755
--- a/tools/run_tests/artifacts/build_artifact_ruby.sh
+++ b/tools/run_tests/artifacts/build_artifact_ruby.sh
@@ -63,6 +63,6 @@
   rm `ls pkg/*.gem | grep -v darwin`
 fi
 
-mkdir -p artifacts
+mkdir -p "${ARTIFACTS_OUT}"
 
-cp pkg/*.gem artifacts
+cp pkg/*.gem "${ARTIFACTS_OUT}"/
diff --git a/tools/run_tests/artifacts/build_package_node.sh b/tools/run_tests/artifacts/build_package_node.sh
index 8b5e8c0..d06f141 100755
--- a/tools/run_tests/artifacts/build_package_node.sh
+++ b/tools/run_tests/artifacts/build_package_node.sh
@@ -40,7 +40,7 @@
 artifacts=$base/artifacts
 
 mkdir -p $artifacts
-cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=node,platform={windows,linux,macos}/artifacts/* $artifacts/ || true
+cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/node_ext_*/* $artifacts/ || true
 
 npm update
 npm pack
@@ -86,7 +86,7 @@
         ;;
     esac
     rm -r bin/*
-    input_dir="$EXTERNAL_GIT_ROOT/architecture=$arch,language=protoc,platform=$plat/artifacts"
+    input_dir="$EXTERNAL_GIT_ROOT/platform=${plat}/artifacts/protoc_${plat}_${arch}"
     cp $input_dir/protoc* bin/
     cp $input_dir/grpc_node_plugin* bin/
     mkdir -p bin/google/protobuf
diff --git a/tools/run_tests/artifacts/build_package_php.sh b/tools/run_tests/artifacts/build_package_php.sh
index 42a8d9f..16da58d 100755
--- a/tools/run_tests/artifacts/build_package_php.sh
+++ b/tools/run_tests/artifacts/build_package_php.sh
@@ -33,4 +33,4 @@
 cd $(dirname $0)/../../..
 
 mkdir -p artifacts/
-cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=php,platform={windows,linux,macos}/artifacts/* artifacts/ || true
+cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/php_*/* artifacts/ || true
diff --git a/tools/run_tests/artifacts/build_package_python.sh b/tools/run_tests/artifacts/build_package_python.sh
index 4a1c15c..9148bb0 100755
--- a/tools/run_tests/artifacts/build_package_python.sh
+++ b/tools/run_tests/artifacts/build_package_python.sh
@@ -36,7 +36,7 @@
 
 # All the python packages have been built in the artifact phase already
 # and we only collect them here to deliver them to the distribtest phase.
-cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=python,platform={windows,linux,macos}/artifacts/* artifacts/ || true
+cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/python_*/* artifacts/ || true
 
 # TODO: all the artifact builder configurations generate a grpcio-VERSION.tar.gz
 # source distribution package, and only one of them will end up
diff --git a/tools/run_tests/artifacts/build_package_ruby.sh b/tools/run_tests/artifacts/build_package_ruby.sh
index b4d20d8..8388b84 100755
--- a/tools/run_tests/artifacts/build_package_ruby.sh
+++ b/tools/run_tests/artifacts/build_package_ruby.sh
@@ -38,7 +38,7 @@
 
 # All the ruby packages have been built in the artifact phase already
 # and we only collect them here to deliver them to the distribtest phase.
-cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=ruby,platform={windows,linux,macos}/artifacts/* artifacts/ || true
+cp -r $EXTERNAL_GIT_ROOT/platform={windows,linux,macos}/artifacts/ruby_native_gem_*/* artifacts/ || true
 
 well_known_protos=( any api compiler/plugin descriptor duration empty field_mask source_context struct timestamp type wrappers )
 
@@ -56,7 +56,7 @@
       ;;
   esac
   for plat in {windows,linux,macos}; do
-    input_dir="$EXTERNAL_GIT_ROOT/architecture=$arch,language=protoc,platform=$plat/artifacts"
+    input_dir="$EXTERNAL_GIT_ROOT/platform=${plat}/artifacts/protoc_${plat}_${arch}"
     output_dir="$base/src/ruby/tools/bin/${ruby_arch}-${plat}"
     mkdir -p $output_dir/google/protobuf
     mkdir -p $output_dir/google/protobuf/compiler  # needed for plugin.proto
diff --git a/tools/run_tests/artifacts/distribtest_targets.py b/tools/run_tests/artifacts/distribtest_targets.py
index 097fd2d..3cb7d97 100644
--- a/tools/run_tests/artifacts/distribtest_targets.py
+++ b/tools/run_tests/artifacts/distribtest_targets.py
@@ -63,8 +63,14 @@
 
 
 def create_jobspec(name, cmdline, environ=None, shell=False,
-                   flake_retries=0, timeout_retries=0):
+                   flake_retries=0, timeout_retries=0,
+                   use_workspace=False):
   """Creates jobspec."""
+  environ = environ.copy()
+  if use_workspace:
+    environ['WORKSPACE_NAME'] = 'workspace_%s' % name
+    cmdline = ['bash',
+               'tools/run_tests/artifacts/run_in_workspace.sh'] + cmdline
   jobspec = jobset.JobSpec(
           cmdline=cmdline,
           environ=environ,
@@ -80,7 +86,7 @@
   """Tests C# NuGet package"""
 
   def __init__(self, platform, arch, docker_suffix=None, use_dotnet_cli=False):
-    self.name = 'csharp_nuget_%s_%s' % (platform, arch)
+    self.name = 'csharp_%s_%s' % (platform, arch)
     self.platform = platform
     self.arch = arch
     self.docker_suffix = docker_suffix
@@ -110,16 +116,18 @@
     elif self.platform == 'macos':
       return create_jobspec(self.name,
           ['test/distrib/csharp/run_distrib_test%s.sh' % self.script_suffix],
-          environ={'EXTERNAL_GIT_ROOT': '../../..'})
+          environ={'EXTERNAL_GIT_ROOT': '../../../..'},
+          use_workspace=True)
     elif self.platform == 'windows':
       if self.arch == 'x64':
         environ={'MSBUILD_EXTRA_ARGS': '/p:Platform=x64',
                  'DISTRIBTEST_OUTPATH': 'DistribTest\\bin\\x64\\Debug'}
       else:
-        environ={'DISTRIBTEST_OUTPATH': 'DistribTest\\bin\\\Debug'}
+        environ={'DISTRIBTEST_OUTPATH': 'DistribTest\\bin\\Debug'}
       return create_jobspec(self.name,
           ['test\\distrib\\csharp\\run_distrib_test%s.bat' % self.script_suffix],
-          environ=environ)
+          environ=environ,
+          use_workspace=True)
     else:
       raise Exception("Not supported yet.")
 
@@ -161,7 +169,8 @@
       return create_jobspec(self.name,
                             ['test/distrib/node/run_distrib_test.sh',
                              str(self.node_version)],
-                            environ={'EXTERNAL_GIT_ROOT': '../../..'})
+                            environ={'EXTERNAL_GIT_ROOT': '../../../..'},
+                            use_workspace=True)
     else:
       raise Exception("Not supported yet.")
 
@@ -249,7 +258,8 @@
     elif self.platform == 'macos':
       return create_jobspec(self.name,
           ['test/distrib/php/run_distrib_test.sh'],
-          environ={'EXTERNAL_GIT_ROOT': '../../..'})
+          environ={'EXTERNAL_GIT_ROOT': '../../../..'},
+          use_workspace=True)
     else:
       raise Exception("Not supported yet.")
 
@@ -339,5 +349,5 @@
             NodeDistribTest('linux', 'x64', os, version)
             for os in ('wheezy', 'jessie', 'ubuntu1204', 'ubuntu1404',
                        'ubuntu1504', 'ubuntu1510', 'ubuntu1604')
-            for version in ('0.12', '3', '4', '5')
+            for version in ('4', '5')
           ]
diff --git a/tools/run_tests/artifacts/run_in_workspace.sh b/tools/run_tests/artifacts/run_in_workspace.sh
new file mode 100755
index 0000000..ed3bfda
--- /dev/null
+++ b/tools/run_tests/artifacts/run_in_workspace.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Create a workspace in a subdirectory to allow running multiple builds in isolation.
+# WORKSPACE_NAME env variable needs to contain name of the workspace to create.
+# All cmdline args will be executed as a command.
+set -ex
+
+cd $(dirname $0)/../../..
+export repo_root=$(pwd)
+
+rm -rf "${WORKSPACE_NAME}"
+git clone . "${WORKSPACE_NAME}"
+# clone gRPC submodules, use data from locally cloned submodules where possible
+git submodule foreach 'cd "${repo_root}/${WORKSPACE_NAME}" \
+    && git submodule update --init --reference ${repo_root}/${name} ${name}'
+
+echo "Running in workspace ${WORKSPACE_NAME}"
+cd ${WORKSPACE_NAME}
+$@
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 04b9c68..0000fa2 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -41353,6 +41353,56 @@
   {
     "args": [
       "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_1channel_100rpcs_1MB", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "tsan", 
+      "asan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_1channel_1MB", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
@@ -42911,6 +42961,82 @@
   {
     "args": [
       "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_unary_1channel_100rpcs_1MB_low_thread_count", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
+      "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
+    ], 
+    "boringssl": true, 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": "capacity", 
+    "defaults": "boringssl", 
+    "exclude_configs": [
+      "asan-noleaks", 
+      "asan-trace-cmp", 
+      "basicprof", 
+      "c++-compat", 
+      "counters", 
+      "dbg", 
+      "gcov", 
+      "helgrind", 
+      "lto", 
+      "memcheck", 
+      "msan", 
+      "mutrace", 
+      "opt", 
+      "stapprof", 
+      "ubsan"
+    ], 
+    "excluded_poll_engines": [], 
+    "flaky": false, 
+    "language": "c++", 
+    "name": "json_run_localhost", 
+    "platforms": [
+      "linux"
+    ], 
+    "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_1channel_1MB_low_thread_count", 
+    "timeout_seconds": 360
+  }, 
+  {
+    "args": [
+      "--scenarios_json", 
       "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_ping_pong_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 1, \"async_client_threads\": 1, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}"
     ], 
     "boringssl": true, 
diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py
index 8ed675e..c2ffd67 100644
--- a/tools/run_tests/performance/scenario_config.py
+++ b/tools/run_tests/performance/scenario_config.py
@@ -112,6 +112,7 @@
                         categories=DEFAULT_CATEGORIES,
                         channels=None,
                         outstanding=None,
+                        num_clients=None,
                         resource_quota_size=None,
                         messages_per_stream=None,
                         excluded_poll_engines=[]):
@@ -158,7 +159,7 @@
     wide = channels if channels is not None else WIDE
     deep = int(math.ceil(1.0 * outstanding_calls / wide))
 
-    scenario['num_clients'] = 0  # use as many client as available.
+    scenario['num_clients'] = num_clients if num_clients is not None else 0  # use as many clients as available.
     scenario['client_config']['outstanding_rpcs_per_channel'] = deep
     scenario['client_config']['client_channels'] = wide
     scenario['client_config']['async_client_threads'] = 0
@@ -196,6 +197,24 @@
 
   def scenarios(self):
     # TODO(ctiller): add 70% load latency test
+    yield _ping_pong_scenario(
+      'cpp_protobuf_async_unary_1channel_100rpcs_1MB', rpc_type='UNARY',
+      client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
+      req_size=1024*1024, resp_size=1024*1024,
+      unconstrained_client='async', outstanding=100, channels=1,
+      num_clients=1,
+      secure=False,
+      categories=[SMOKETEST] + [SCALABLE])
+
+    yield _ping_pong_scenario(
+      'cpp_protobuf_async_streaming_from_client_1channel_1MB', rpc_type='STREAMING_FROM_CLIENT',
+      client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER',
+      req_size=1024*1024, resp_size=1024*1024,
+      unconstrained_client='async', outstanding=1, channels=1,
+      num_clients=1,
+      secure=False,
+      categories=[SMOKETEST] + [SCALABLE])
+
     for secure in [True, False]:
       secstr = 'secure' if secure else 'insecure'
       smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE]
diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py
index 4e97128..c1b1c88 100755
--- a/tools/run_tests/python_utils/jobset.py
+++ b/tools/run_tests/python_utils/jobset.py
@@ -255,7 +255,7 @@
     self._start = time.time()
     cmdline = self._spec.cmdline
     if measure_cpu_costs:
-      cmdline = ['time', '--portability'] + cmdline
+      cmdline = ['time', '-p'] + cmdline
     try_start = lambda: subprocess.Popen(args=cmdline,
                                          stderr=subprocess.STDOUT,
                                          stdout=self._tempfile,
@@ -307,7 +307,7 @@
         self._state = _SUCCESS
         measurement = ''
         if measure_cpu_costs:
-          m = re.search(r'real ([0-9.]+)\nuser ([0-9.]+)\nsys ([0-9.]+)', stdout())
+          m = re.search(r'real\s+([0-9.]+)\nuser\s+([0-9.]+)\nsys\s+([0-9.]+)', stdout())
           real = float(m.group(1))
           user = float(m.group(2))
           sys = float(m.group(3))
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 83a8394..196e26e 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -340,7 +340,8 @@
     if self.platform == 'windows':
       # don't build tools on windows just yet
       return ['buildtests_%s' % self.make_target]
-    return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target]
+    return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target,
+            'check_epollexclusive']
 
   def make_options(self):
     return self._make_options;
diff --git a/tools/run_tests/task_runner.py b/tools/run_tests/task_runner.py
index 0ec7efb..7feac29 100755
--- a/tools/run_tests/task_runner.py
+++ b/tools/run_tests/task_runner.py
@@ -40,6 +40,7 @@
 import artifacts.distribtest_targets as distribtest_targets
 import artifacts.package_targets as package_targets
 import python_utils.jobset as jobset
+import python_utils.report_utils as report_utils
 
 _TARGETS = []
 _TARGETS += artifact_targets.targets()
@@ -116,8 +117,10 @@
   sys.exit(1)
 
 jobset.message('START', 'Building targets.', do_newline=True)
-num_failures, _ = jobset.run(
+num_failures, resultset = jobset.run(
     build_jobs, newline_on_success=True, maxjobs=args.jobs)
+report_utils.render_junit_xml_report(resultset, 'report_taskrunner_sponge_log.xml',
+                                     suite_name='tasks')
 if num_failures == 0:
   jobset.message('SUCCESS', 'All targets built successfully.',
                  do_newline=True)
diff --git a/vsprojects/protoc.props b/vsprojects/protoc.props
index 87fff8f..6c842c2 100644
--- a/vsprojects/protoc.props
+++ b/vsprojects/protoc.props
@@ -1 +1 @@
-<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <ClCompile> <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\build\solution\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemGroup /> </Project>
\ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <ClCompile> <DisableSpecificWarnings>4244;4267;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\build\solution\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemGroup /> </Project>
\ No newline at end of file