Index: third_party/grpc/tools/http2_interop/testsuite.go |
diff --git a/third_party/grpc/tools/http2_interop/testsuite.go b/third_party/grpc/tools/http2_interop/testsuite.go |
new file mode 100644 |
index 0000000000000000000000000000000000000000..51d36e217ed7c8632436595a82523ce98bc07113 |
--- /dev/null |
+++ b/third_party/grpc/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{} |
+) |