Merge pull request #4302 from nicolasnoble/unreachable-gcov

Removing code coverage for unreachable code.
diff --git a/src/core/support/log.c b/src/core/support/log.c
index f52c203..04156a5 100644
--- a/src/core/support/log.c
+++ b/src/core/support/log.c
@@ -32,6 +32,7 @@
  */
 
 #include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
 
 #include <stdio.h>
 #include <string.h>
@@ -48,7 +49,7 @@
     case GPR_LOG_SEVERITY_ERROR:
       return "E";
   }
-  return "UNKNOWN";
+  GPR_UNREACHABLE_CODE(return "UNKNOWN");
 }
 
 void gpr_log_message(const char *file, int line, gpr_log_severity severity,
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 4affafa..84b9daa 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -1270,6 +1270,7 @@
         }
         if (call->receiving_message) {
           error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
+          goto done_with_error;
         }
         call->receiving_message = 1;
         bctl->recv_message = 1;
diff --git a/src/core/transport/chttp2/frame_data.h b/src/core/transport/chttp2/frame_data.h
index 472f9ce..27d4d00 100644
--- a/src/core/transport/chttp2/frame_data.h
+++ b/src/core/transport/chttp2/frame_data.h
@@ -94,9 +94,6 @@
     grpc_chttp2_transport_parsing *transport_parsing,
     grpc_chttp2_stream_parsing *stream_parsing, gpr_slice slice, int is_last);
 
-/* create a slice with an empty data frame and is_last set */
-gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id);
-
 void grpc_chttp2_encode_data(gpr_uint32 id, gpr_slice_buffer *inbuf,
                              gpr_uint32 write_bytes, int is_eof,
                              gpr_slice_buffer *outbuf);
diff --git a/src/core/transport/chttp2/hpack_encoder.c b/src/core/transport/chttp2/hpack_encoder.c
index 28d5433..7575031 100644
--- a/src/core/transport/chttp2/hpack_encoder.c
+++ b/src/core/transport/chttp2/hpack_encoder.c
@@ -458,12 +458,6 @@
   GRPC_MDELEM_UNREF(mdelem);
 }
 
-gpr_slice grpc_chttp2_data_frame_create_empty_close(gpr_uint32 id) {
-  gpr_slice slice = gpr_slice_malloc(9);
-  fill_header(GPR_SLICE_START_PTR(slice), GRPC_CHTTP2_FRAME_DATA, id, 0, 1);
-  return slice;
-}
-
 static gpr_uint32 elems_for_bytes(gpr_uint32 bytes) {
   return (bytes + 31) / 32;
 }
diff --git a/src/core/transport/chttp2/incoming_metadata.c b/src/core/transport/chttp2/incoming_metadata.c
index 956afc8..315bc2f 100644
--- a/src/core/transport/chttp2/incoming_metadata.c
+++ b/src/core/transport/chttp2/incoming_metadata.c
@@ -56,16 +56,6 @@
   gpr_free(buffer->elems);
 }
 
-void grpc_chttp2_incoming_metadata_buffer_reset(
-    grpc_chttp2_incoming_metadata_buffer *buffer) {
-  size_t i;
-  GPR_ASSERT(!buffer->published);
-  for (i = 0; i < buffer->count; i++) {
-    GRPC_MDELEM_UNREF(buffer->elems[i].md);
-  }
-  buffer->count = 0;
-}
-
 void grpc_chttp2_incoming_metadata_buffer_add(
     grpc_chttp2_incoming_metadata_buffer *buffer, grpc_mdelem *elem) {
   GPR_ASSERT(!buffer->published);
@@ -83,14 +73,6 @@
   buffer->deadline = deadline;
 }
 
-void grpc_chttp2_incoming_metadata_buffer_swap(
-    grpc_chttp2_incoming_metadata_buffer *a,
-    grpc_chttp2_incoming_metadata_buffer *b) {
-  GPR_ASSERT(!a->published);
-  GPR_ASSERT(!b->published);
-  GPR_SWAP(grpc_chttp2_incoming_metadata_buffer, *a, *b);
-}
-
 void grpc_chttp2_incoming_metadata_buffer_publish(
     grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch) {
   GPR_ASSERT(!buffer->published);
diff --git a/src/core/transport/chttp2/incoming_metadata.h b/src/core/transport/chttp2/incoming_metadata.h
index 0e1dabe..ea74cfc 100644
--- a/src/core/transport/chttp2/incoming_metadata.h
+++ b/src/core/transport/chttp2/incoming_metadata.h
@@ -49,8 +49,6 @@
     grpc_chttp2_incoming_metadata_buffer *buffer);
 void grpc_chttp2_incoming_metadata_buffer_destroy(
     grpc_chttp2_incoming_metadata_buffer *buffer);
-void grpc_chttp2_incoming_metadata_buffer_reset(
-    grpc_chttp2_incoming_metadata_buffer *buffer);
 void grpc_chttp2_incoming_metadata_buffer_publish(
     grpc_chttp2_incoming_metadata_buffer *buffer, grpc_metadata_batch *batch);
 
diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h
index 3952f8a..45d2599 100644
--- a/src/core/transport/chttp2/internal.h
+++ b/src/core/transport/chttp2/internal.h
@@ -512,9 +512,6 @@
 void grpc_chttp2_list_add_writable_stream(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_stream_global *stream_global);
-void grpc_chttp2_list_add_first_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global);
 int grpc_chttp2_list_pop_writable_stream(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_transport_writing *transport_writing,
diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c
index a81ffcc..a4c85b4 100644
--- a/src/core/transport/chttp2/stream_lists.c
+++ b/src/core/transport/chttp2/stream_lists.c
@@ -108,23 +108,6 @@
   }
 }
 
-static void stream_list_add_head(grpc_chttp2_transport *t,
-                                 grpc_chttp2_stream *s,
-                                 grpc_chttp2_stream_list_id id) {
-  grpc_chttp2_stream *old_head;
-  GPR_ASSERT(!s->included[id]);
-  old_head = t->lists[id].head;
-  s->links[id].next = old_head;
-  s->links[id].prev = NULL;
-  if (old_head) {
-    old_head->links[id].prev = s;
-  } else {
-    t->lists[id].tail = s;
-  }
-  t->lists[id].head = s;
-  s->included[id] = 1;
-}
-
 static void stream_list_add_tail(grpc_chttp2_transport *t,
                                  grpc_chttp2_stream *s,
                                  grpc_chttp2_stream_list_id id) {
@@ -161,15 +144,6 @@
                   STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
 }
 
-void grpc_chttp2_list_add_first_writable_stream(
-    grpc_chttp2_transport_global *transport_global,
-    grpc_chttp2_stream_global *stream_global) {
-  GPR_ASSERT(stream_global->id != 0);
-  stream_list_add_head(TRANSPORT_FROM_GLOBAL(transport_global),
-                       STREAM_FROM_GLOBAL(stream_global),
-                       GRPC_CHTTP2_LIST_WRITABLE);
-}
-
 int grpc_chttp2_list_pop_writable_stream(
     grpc_chttp2_transport_global *transport_global,
     grpc_chttp2_transport_writing *transport_writing,
diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec
index 61cf18c..363abe9 100755
--- a/src/ruby/grpc.gemspec
+++ b/src/ruby/grpc.gemspec
@@ -39,6 +39,7 @@
   s.add_development_dependency 'rake-compiler', '~> 0.9'
   s.add_development_dependency 'rspec', '~> 3.2'
   s.add_development_dependency 'rubocop', '~> 0.30.0'
+  s.add_development_dependency 'signet', '~>0.6.0'
 
   s.extensions = %w(ext/grpc/extconf.rb)
 end
diff --git a/test/core/bad_client/tests/initial_settings_frame.c b/test/core/bad_client/tests/initial_settings_frame.c
index 827e93b..6ed15bb 100644
--- a/test/core/bad_client/tests/initial_settings_frame.c
+++ b/test/core/bad_client/tests/initial_settings_frame.c
@@ -35,6 +35,7 @@
 #include "src/core/surface/server.h"
 
 #define PFX_STR "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+#define ONE_SETTING_HDR "\x00\x00\x06\x04\x00\x00\x00\x00\x00"
 
 static void verifier(grpc_server *server, grpc_completion_queue *cq) {
   while (grpc_server_has_open_connections(server)) {
@@ -90,6 +91,10 @@
                            PFX_STR "\x00\x00\x04\x04\x00\x00\x00\x00\x00", 0);
   GRPC_RUN_BAD_CLIENT_TEST(verifier,
                            PFX_STR "\x00\x00\x05\x04\x00\x00\x00\x00\x00", 0);
+  /* some settings values are illegal */
+  /* max frame size = 0 */
+  GRPC_RUN_BAD_CLIENT_TEST(verifier,
+                           PFX_STR ONE_SETTING_HDR "\x00\x05\x00\x00\x00\x00", GRPC_BAD_CLIENT_DISCONNECT);
 
   return 0;
 }
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index b2b7cfd..9af76be 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -31,8 +31,10 @@
  *
  */
 
+#include <grpc/support/port_platform.h>
 #include "src/core/security/credentials.h"
 
+#include <stdlib.h>
 #include <string.h>
 
 #include "src/core/httpcli/httpcli.h"
@@ -1013,6 +1015,30 @@
   grpc_exec_ctx_finish(&exec_ctx);
 }
 
+static void test_get_well_known_google_credentials_file_path(void) {
+#ifdef GPR_POSIX_FILE
+  char *path;
+  char *old_home = gpr_getenv("HOME");
+  gpr_setenv("HOME", "/tmp");
+  path = grpc_get_well_known_google_credentials_file_path();
+  GPR_ASSERT(path != NULL);
+  GPR_ASSERT(0 == strcmp("/tmp/.config/" GRPC_GOOGLE_CLOUD_SDK_CONFIG_DIRECTORY
+                         "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE,
+                         path));
+  gpr_free(path);
+#if defined(GPR_POSIX_ENV) || defined(GPR_LINUX_ENV)
+  unsetenv("HOME");
+  path = grpc_get_well_known_google_credentials_file_path();
+  GPR_ASSERT(path == NULL);
+#endif /* GPR_POSIX_ENV || GPR_LINUX_ENV */
+  gpr_setenv("HOME", old_home);
+#else /* GPR_POSIX_FILE */
+  char *path = grpc_get_well_known_google_credentials_file_path();
+  GPR_ASSERT(path != NULL);
+  gpr_free(path);
+#endif
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_empty_md_store();
@@ -1043,5 +1069,6 @@
   test_google_default_creds_access_token();
   test_metadata_plugin_success();
   test_metadata_plugin_failure();
+  test_get_well_known_google_credentials_file_path();
   return 0;
 }
diff --git a/test/core/surface/byte_buffer_reader_test.c b/test/core/surface/byte_buffer_reader_test.c
index 6b41698..c87fbdc 100644
--- a/test/core/surface/byte_buffer_reader_test.c
+++ b/test/core/surface/byte_buffer_reader_test.c
@@ -217,6 +217,42 @@
   grpc_byte_buffer_destroy(buffer);
 }
 
+static void test_byte_buffer_copy(void) {
+  char *lotsa_as[512];
+  char *lotsa_bs[1024];
+  gpr_slice slices[2];
+  grpc_byte_buffer *buffer;
+  grpc_byte_buffer *copied_buffer;
+  grpc_byte_buffer_reader reader;
+  gpr_slice slice_out;
+
+  LOG_TEST("test_byte_buffer_copy");
+
+  memset(lotsa_as, 'a', 512);
+  memset(lotsa_bs, 'b', 1024);
+  /* use slices large enough to overflow inlining */
+  slices[0] = gpr_slice_malloc(512);
+  memcpy(GPR_SLICE_START_PTR(slices[0]), lotsa_as, 512);
+  slices[1] = gpr_slice_malloc(1024);
+  memcpy(GPR_SLICE_START_PTR(slices[1]), lotsa_bs, 1024);
+
+  buffer = grpc_raw_byte_buffer_create(slices, 2);
+  gpr_slice_unref(slices[0]);
+  gpr_slice_unref(slices[1]);
+  copied_buffer = grpc_byte_buffer_copy(buffer);
+
+  grpc_byte_buffer_reader_init(&reader, copied_buffer);
+  slice_out = grpc_byte_buffer_reader_readall(&reader);
+
+  GPR_ASSERT(GPR_SLICE_LENGTH(slice_out) == 512 + 1024);
+  GPR_ASSERT(memcmp(GPR_SLICE_START_PTR(slice_out), lotsa_as, 512) == 0);
+  GPR_ASSERT(memcmp(&(GPR_SLICE_START_PTR(slice_out)[512]), lotsa_bs, 1024) ==
+             0);
+  gpr_slice_unref(slice_out);
+  grpc_byte_buffer_destroy(buffer);
+  grpc_byte_buffer_destroy(copied_buffer);
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_read_one_slice();
@@ -225,6 +261,7 @@
   test_read_gzip_compressed_slice();
   test_read_deflate_compressed_slice();
   test_byte_buffer_from_reader();
+  test_byte_buffer_copy();
   test_readall();
   return 0;
 }
diff --git a/tools/http2_interop/http2interop_test.go b/tools/http2_interop/http2interop_test.go
index b35d085..fb314da 100644
--- a/tools/http2_interop/http2interop_test.go
+++ b/tools/http2_interop/http2interop_test.go
@@ -3,6 +3,7 @@
 import (
 	"crypto/tls"
 	"crypto/x509"
+	"encoding/json"
 	"flag"
 	"fmt"
 	"io/ioutil"
@@ -67,7 +68,8 @@
 	return nil
 }
 
-func TestClientShortSettings(t *testing.T) {
+func TestSoonClientShortSettings(t *testing.T) {
+	defer Report(t)
 	if *testCase != "framing" {
 		t.SkipNow()
 	}
@@ -78,7 +80,8 @@
 	}
 }
 
-func TestShortPreface(t *testing.T) {
+func TestSoonShortPreface(t *testing.T) {
+	defer Report(t)
 	if *testCase != "framing" {
 		t.SkipNow()
 	}
@@ -89,7 +92,8 @@
 	}
 }
 
-func TestUnknownFrameType(t *testing.T) {
+func TestSoonUnknownFrameType(t *testing.T) {
+	defer Report(t)
 	if *testCase != "framing" {
 		t.SkipNow()
 	}
@@ -99,7 +103,8 @@
 	}
 }
 
-func TestClientPrefaceWithStreamId(t *testing.T) {
+func TestSoonClientPrefaceWithStreamId(t *testing.T) {
+	defer Report(t)
 	if *testCase != "framing" {
 		t.SkipNow()
 	}
@@ -108,7 +113,8 @@
 	matchError(t, err, "EOF")
 }
 
-func TestTLSApplicationProtocol(t *testing.T) {
+func TestSoonTLSApplicationProtocol(t *testing.T) {
+	defer Report(t)
 	if *testCase != "tls" {
 		t.SkipNow()
 	}
@@ -117,7 +123,8 @@
 	matchError(t, err, "EOF", "broken pipe")
 }
 
-func TestTLSMaxVersion(t *testing.T) {
+func TestSoonTLSMaxVersion(t *testing.T) {
+	defer Report(t)
 	if *testCase != "tls" {
 		t.SkipNow()
 	}
@@ -128,7 +135,8 @@
 	matchError(t, err, "EOF", "server selected unsupported protocol")
 }
 
-func TestTLSBadCipherSuites(t *testing.T) {
+func TestSoonTLSBadCipherSuites(t *testing.T) {
+	defer Report(t)
 	if *testCase != "tls" {
 		t.SkipNow()
 	}
@@ -151,5 +159,25 @@
 
 func TestMain(m *testing.M) {
 	flag.Parse()
-	os.Exit(m.Run())
+	m.Run()
+	var fatal bool
+	var any bool
+	for _, ci := range allCaseInfos.Cases {
+		if ci.Skipped {
+			continue
+		}
+		any = true
+		if !ci.Passed && ci.Fatal {
+			fatal = true
+		}
+	}
+
+	if err := json.NewEncoder(os.Stderr).Encode(&allCaseInfos); err != nil {
+		fmt.Println("Failed to encode", err)
+	}
+	var code int
+	if !any || fatal {
+		code = 1
+	}
+	os.Exit(code)
 }
diff --git a/tools/http2_interop/s6.5.go b/tools/http2_interop/s6.5.go
index 8145b6e..32468ab 100644
--- a/tools/http2_interop/s6.5.go
+++ b/tools/http2_interop/s6.5.go
@@ -11,7 +11,6 @@
 		return err
 	}
 	defer conn.Close()
-	conn.Log = ctx.T.Log
 	conn.SetDeadline(time.Now().Add(defaultTimeout))
 
 	sf := &SettingsFrame{
diff --git a/tools/http2_interop/s6.5_test.go b/tools/http2_interop/s6.5_test.go
index 48e8ced..9dadd4e 100644
--- a/tools/http2_interop/s6.5_test.go
+++ b/tools/http2_interop/s6.5_test.go
@@ -4,8 +4,9 @@
 	"testing"
 )
 
-func TestSmallMaxFrameSize(t *testing.T) {
-	if *testCase != "experimental" {
+func TestSoonSmallMaxFrameSize(t *testing.T) {
+	defer Report(t)
+	if *testCase != "framing" {
 		t.SkipNow()
 	}
 	ctx := InteropCtx(t)
diff --git a/tools/http2_interop/testsuite.go b/tools/http2_interop/testsuite.go
new file mode 100644
index 0000000..51d36e2
--- /dev/null
+++ b/tools/http2_interop/testsuite.go
@@ -0,0 +1,56 @@
+package http2interop
+
+import (
+	"path"
+	"runtime"
+	"strings"
+	"sync"
+	"testing"
+)
+
+// When a test is skipped or fails, runtime.Goexit() is called which destroys the callstack.
+// This means the name of the test case is lost, so we need to grab a copy of pc before.
+func Report(t testing.TB) {
+	// If the goroutine panics, Fatal()s, or Skip()s, the function name is at the 3rd callstack
+	// layer.  On success, its at 1st.  Since it's hard to check which happened, just try both.
+	pcs := make([]uintptr, 10)
+	total := runtime.Callers(1, pcs)
+	var name string
+	for _, pc := range pcs[:total] {
+		fn := runtime.FuncForPC(pc)
+		fullName := fn.Name()
+		if strings.HasPrefix(path.Ext(fullName), ".Test") {
+			// Skip the leading .
+			name = string([]byte(path.Ext(fullName))[1:])
+			break
+		}
+	}
+	if name == "" {
+		return
+	}
+
+	allCaseInfos.lock.Lock()
+	defer allCaseInfos.lock.Unlock()
+	allCaseInfos.Cases = append(allCaseInfos.Cases, &caseInfo{
+		Name:    name,
+		Passed:  !t.Failed() && !t.Skipped(),
+		Skipped: t.Skipped(),
+		Fatal:   t.Failed() && !strings.HasPrefix(name, "TestSoon"),
+	})
+}
+
+type caseInfo struct {
+	Name    string `json:"name"`
+	Passed  bool   `json:"passed"`
+	Skipped bool   `json:"skipped,omitempty"`
+	Fatal   bool   `json:"fatal,omitempty"`
+}
+
+type caseInfos struct {
+	lock  sync.Mutex
+	Cases []*caseInfo `json:"cases"`
+}
+
+var (
+	allCaseInfos = caseInfos{}
+)
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 5435a1d..5feb4f0 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -661,9 +661,6 @@
           
     if args.http2_interop:
       for test_case in _HTTP2_TEST_CASES:
-        if server_name == "go":
-          # TODO(carl-mastrangelo): Reenable after https://github.com/grpc/grpc-go/issues/434
-          continue 
         test_job = cloud_to_cloud_jobspec(http2Interop,
                                           test_case,
                                           server_name,