Only run language specified tests

Add a template to generate a complete list of tests for C/C++, and use it to generate the list of binaries to run tests for.
diff --git a/templates/tools/run_tests/tests.json.template b/templates/tools/run_tests/tests.json.template
new file mode 100644
index 0000000..3a9e103
--- /dev/null
+++ b/templates/tools/run_tests/tests.json.template
@@ -0,0 +1,8 @@
+<%!
+import json
+%>
+
+${json.dumps([{"name": tgt.name, "language": tgt.language}
+              for tgt in targets
+              if tgt.build == "test" and tgt.name[-5:] == "_test"])}
+
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 0826dfc..71c68d7 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -41,12 +41,17 @@
 
 class CLanguage(object):
 
-  def __init__(self, make_target):
+  def __init__(self, make_target, test_lang):
     self.allow_hashing = True
     self.make_target = make_target
+    with open('tools/run_tests/tests.json') as f:
+      js = json.loads(f.read())
+      self.binaries = [tgt['name'] 
+                       for tgt in js 
+                       if tgt['language'] == test_lang]
 
   def test_binaries(self, config):
-    return glob.glob('bins/%s/*_test' % config)
+    return ['bins/%s/%s' % (config, binary) for binary in self.binaries]
 
   def make_targets(self):
     return ['buildtests_%s' % self.make_target]
@@ -85,8 +90,8 @@
 
 _DEFAULT = ['dbg', 'opt']
 _LANGUAGES = {
-    'c++': CLanguage('cxx'),
-    'c': CLanguage('c'),
+    'c++': CLanguage('cxx', 'c++'),
+    'c': CLanguage('c', 'c'),
     'php': PhpLanguage()
 }
 
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
new file mode 100644
index 0000000..b042df8
--- /dev/null
+++ b/tools/run_tests/tests.json
@@ -0,0 +1,4 @@
+
+
+[{"name": "grpc_byte_buffer_reader_test", "language": "c"}, {"name": "gpr_cancellable_test", "language": "c"}, {"name": "gpr_log_test", "language": "c"}, {"name": "gpr_useful_test", "language": "c"}, {"name": "gpr_cmdline_test", "language": "c"}, {"name": "gpr_histogram_test", "language": "c"}, {"name": "gpr_host_port_test", "language": "c"}, {"name": "gpr_slice_buffer_test", "language": "c"}, {"name": "gpr_slice_test", "language": "c"}, {"name": "gpr_string_test", "language": "c"}, {"name": "gpr_sync_test", "language": "c"}, {"name": "gpr_thd_test", "language": "c"}, {"name": "gpr_time_test", "language": "c"}, {"name": "murmur_hash_test", "language": "c"}, {"name": "grpc_stream_op_test", "language": "c"}, {"name": "alpn_test", "language": "c"}, {"name": "time_averaged_stats_test", "language": "c"}, {"name": "chttp2_stream_encoder_test", "language": "c"}, {"name": "hpack_table_test", "language": "c"}, {"name": "chttp2_stream_map_test", "language": "c"}, {"name": "hpack_parser_test", "language": "c"}, {"name": "transport_metadata_test", "language": "c"}, {"name": "chttp2_status_conversion_test", "language": "c"}, {"name": "chttp2_transport_end2end_test", "language": "c"}, {"name": "tcp_posix_test", "language": "c"}, {"name": "dualstack_socket_test", "language": "c"}, {"name": "no_server_test", "language": "c"}, {"name": "resolve_address_test", "language": "c"}, {"name": "sockaddr_utils_test", "language": "c"}, {"name": "tcp_server_posix_test", "language": "c"}, {"name": "tcp_client_posix_test", "language": "c"}, {"name": "grpc_channel_stack_test", "language": "c"}, {"name": "metadata_buffer_test", "language": "c"}, {"name": "grpc_completion_queue_test", "language": "c"}, {"name": "census_window_stats_test", "language": "c"}, {"name": "census_statistics_quick_test", "language": "c"}, {"name": "census_statistics_small_log_test", "language": "c"}, {"name": "census_statistics_performance_test", "language": "c"}, {"name": "census_statistics_multiple_writers_test", "language": "c"}, {"name": "census_statistics_multiple_writers_circular_buffer_test", "language": "c"}, {"name": "census_stub_test", "language": "c"}, {"name": "census_hash_table_test", "language": "c"}, {"name": "fling_test", "language": "c"}, {"name": "echo_test", "language": "c"}, {"name": "message_compress_test", "language": "c"}, {"name": "bin_encoder_test", "language": "c"}, {"name": "secure_endpoint_test", "language": "c"}, {"name": "httpcli_format_request_test", "language": "c"}, {"name": "httpcli_parser_test", "language": "c"}, {"name": "httpcli_test", "language": "c"}, {"name": "grpc_credentials_test", "language": "c"}, {"name": "grpc_base64_test", "language": "c"}, {"name": "grpc_json_token_test", "language": "c"}, {"name": "timeout_encoding_test", "language": "c"}, {"name": "fd_posix_test", "language": "c"}, {"name": "fling_stream_test", "language": "c"}, {"name": "lame_client_test", "language": "c"}, {"name": "thread_pool_test", "language": "c++"}, {"name": "status_test", "language": "c++"}, {"name": "sync_client_async_server_test", "language": "c++"}, {"name": "end2end_test", "language": "c++"}, {"name": "channel_arguments_test", "language": "c++"}, {"name": "credentials_test", "language": "c++"}, {"name": "alarm_test", "language": "c"}, {"name": "alarm_list_test", "language": "c"}, {"name": "alarm_heap_test", "language": "c"}, {"name": "time_test", "language": "c"}, {"name": "poll_kick_test", "language": "c"}, {"name": "chttp2_fake_security_cancel_after_accept_test", "language": "c"}, {"name": "chttp2_fake_security_cancel_after_accept_and_writes_closed_test", "language": "c"}, {"name": "chttp2_fake_security_cancel_after_invoke_test", "language": "c"}, {"name": "chttp2_fake_security_cancel_before_invoke_test", "language": "c"}, {"name": "chttp2_fake_security_cancel_in_a_vacuum_test", "language": "c"}, {"name": "chttp2_fake_security_census_simple_request_test", "language": "c"}, {"name": "chttp2_fake_security_disappearing_server_test", "language": "c"}, {"name": "chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test", "language": "c"}, {"name": "chttp2_fake_security_early_server_shutdown_finishes_tags_test", "language": "c"}, {"name": "chttp2_fake_security_graceful_server_shutdown_test", "language": "c"}, {"name": "chttp2_fake_security_invoke_large_request_test", "language": "c"}, {"name": "chttp2_fake_security_max_concurrent_streams_test", "language": "c"}, {"name": "chttp2_fake_security_no_op_test", "language": "c"}, {"name": "chttp2_fake_security_ping_pong_streaming_test", "language": "c"}, {"name": "chttp2_fake_security_request_response_with_binary_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_fake_security_request_response_with_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_fake_security_request_response_with_payload_test", "language": "c"}, {"name": "chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_fake_security_simple_delayed_request_test", "language": "c"}, {"name": "chttp2_fake_security_simple_request_test", "language": "c"}, {"name": "chttp2_fake_security_thread_stress_test", "language": "c"}, {"name": "chttp2_fake_security_writes_done_hangs_with_pending_read_test", "language": "c"}, {"name": "chttp2_fullstack_cancel_after_accept_test", "language": "c"}, {"name": "chttp2_fullstack_cancel_after_accept_and_writes_closed_test", "language": "c"}, {"name": "chttp2_fullstack_cancel_after_invoke_test", "language": "c"}, {"name": "chttp2_fullstack_cancel_before_invoke_test", "language": "c"}, {"name": "chttp2_fullstack_cancel_in_a_vacuum_test", "language": "c"}, {"name": "chttp2_fullstack_census_simple_request_test", "language": "c"}, {"name": "chttp2_fullstack_disappearing_server_test", "language": "c"}, {"name": "chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test", "language": "c"}, {"name": "chttp2_fullstack_early_server_shutdown_finishes_tags_test", "language": "c"}, {"name": "chttp2_fullstack_graceful_server_shutdown_test", "language": "c"}, {"name": "chttp2_fullstack_invoke_large_request_test", "language": "c"}, {"name": "chttp2_fullstack_max_concurrent_streams_test", "language": "c"}, {"name": "chttp2_fullstack_no_op_test", "language": "c"}, {"name": "chttp2_fullstack_ping_pong_streaming_test", "language": "c"}, {"name": "chttp2_fullstack_request_response_with_binary_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_fullstack_request_response_with_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_fullstack_request_response_with_payload_test", "language": "c"}, {"name": "chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_fullstack_simple_delayed_request_test", "language": "c"}, {"name": "chttp2_fullstack_simple_request_test", "language": "c"}, {"name": "chttp2_fullstack_thread_stress_test", "language": "c"}, {"name": "chttp2_fullstack_writes_done_hangs_with_pending_read_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_cancel_after_invoke_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_cancel_before_invoke_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_census_simple_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_disappearing_server_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_graceful_server_shutdown_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_invoke_large_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_max_concurrent_streams_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_no_op_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_ping_pong_streaming_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_request_response_with_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_simple_delayed_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_simple_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_thread_stress_test", "language": "c"}, {"name": "chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_no_op_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test", "language": "c"}, {"name": "chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test", "language": "c"}, {"name": "chttp2_socket_pair_cancel_after_accept_test", "language": "c"}, {"name": "chttp2_socket_pair_cancel_after_accept_and_writes_closed_test", "language": "c"}, {"name": "chttp2_socket_pair_cancel_after_invoke_test", "language": "c"}, {"name": "chttp2_socket_pair_cancel_before_invoke_test", "language": "c"}, {"name": "chttp2_socket_pair_cancel_in_a_vacuum_test", "language": "c"}, {"name": "chttp2_socket_pair_census_simple_request_test", "language": "c"}, {"name": "chttp2_socket_pair_disappearing_server_test", "language": "c"}, {"name": "chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test", "language": "c"}, {"name": "chttp2_socket_pair_early_server_shutdown_finishes_tags_test", "language": "c"}, {"name": "chttp2_socket_pair_graceful_server_shutdown_test", "language": "c"}, {"name": "chttp2_socket_pair_invoke_large_request_test", "language": "c"}, {"name": "chttp2_socket_pair_max_concurrent_streams_test", "language": "c"}, {"name": "chttp2_socket_pair_no_op_test", "language": "c"}, {"name": "chttp2_socket_pair_ping_pong_streaming_test", "language": "c"}, {"name": "chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_request_response_with_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_request_response_with_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_simple_delayed_request_test", "language": "c"}, {"name": "chttp2_socket_pair_simple_request_test", "language": "c"}, {"name": "chttp2_socket_pair_thread_stress_test", "language": "c"}, {"name": "chttp2_socket_pair_writes_done_hangs_with_pending_read_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_no_op_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_simple_request_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_thread_stress_test", "language": "c"}, {"name": "chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test", "language": "c"}]
+