internal/fuzztest: factor out common fuzzer tests

All the fuzzers have the same test, which runs the fuzzer against every
entry in the corpus. Move the test logic into a separate package.

Change-Id: I3a7e2ca75d20a5ff6d51ed9e6151629e6667684b
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/212258
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/internal/fuzz/README.md b/internal/fuzz/README.md
index 9ec6586..fc211c1 100644
--- a/internal/fuzz/README.md
+++ b/internal/fuzz/README.md
@@ -10,3 +10,16 @@
 $ GOFUZZ111MODULE=on go-fuzz-build .
 $ go-fuzz
 ```
+
+## OSS-Fuzz
+
+Fuzzers are automatically run by
+[OSS-Fuzz](https://github.com/google/oss-fuzz).
+
+The OSS-Fuzz
+[configuration](https://github.com/google/oss-fuzz/blob/master/projects/golang-protobuf/build.sh)
+currently builds fuzzers in every directory under internal/fuzz.
+Only add fuzzers (not support packages) in this directory.
+
+Fuzzing results are available at the [OSS-Fuzz console](https://oss-fuzz.com/),
+under `golang-protobuf`.
diff --git a/internal/fuzz/jsonfuzz/fuzz.go b/internal/fuzz/jsonfuzz/fuzz.go
index 969ad6d..b990346 100644
--- a/internal/fuzz/jsonfuzz/fuzz.go
+++ b/internal/fuzz/jsonfuzz/fuzz.go
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package textfuzz includes a fuzzer for the text marshaler and unmarshaler.
-package textfuzz
+// Package jsonfuzz includes fuzzers for protojson.Marshal and protojson.Unmarshal.
+package jsonfuzz
 
 import (
 	"google.golang.org/protobuf/encoding/protojson"
diff --git a/internal/fuzz/jsonfuzz/fuzz_test.go b/internal/fuzz/jsonfuzz/fuzz_test.go
index a0e9d0c..1c81e6f 100644
--- a/internal/fuzz/jsonfuzz/fuzz_test.go
+++ b/internal/fuzz/jsonfuzz/fuzz_test.go
@@ -2,33 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package textfuzz
+package jsonfuzz
 
 import (
-	"io/ioutil"
-	"os"
-	"path/filepath"
 	"testing"
+
+	"google.golang.org/protobuf/internal/fuzztest"
 )
 
 func Test(t *testing.T) {
-	dir, err := os.Open("corpus")
-	if err != nil {
-		t.Fatal(err)
-	}
-	infos, err := dir.Readdir(0)
-	if err != nil {
-		t.Fatal(err)
-
-	}
-	for _, info := range infos {
-		name := info.Name()
-		t.Run(name, func(t *testing.T) {
-			b, err := ioutil.ReadFile(filepath.Join("corpus", name))
-			if err != nil {
-				t.Fatal(err)
-			}
-			Fuzz(b)
-		})
-	}
+	fuzztest.Test(t, Fuzz)
 }
diff --git a/internal/fuzz/textfuzz/fuzz.go b/internal/fuzz/textfuzz/fuzz.go
index bd89da0..242e4b6 100644
--- a/internal/fuzz/textfuzz/fuzz.go
+++ b/internal/fuzz/textfuzz/fuzz.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package textfuzz includes a fuzzer for the text marshaler and unmarshaler.
+// Package textfuzz includes fuzzers for prototext.Marshal and prototext.Unmarshal.
 package textfuzz
 
 import (
diff --git a/internal/fuzz/textfuzz/fuzz_test.go b/internal/fuzz/textfuzz/fuzz_test.go
index a0e9d0c..af27f06 100644
--- a/internal/fuzz/textfuzz/fuzz_test.go
+++ b/internal/fuzz/textfuzz/fuzz_test.go
@@ -5,30 +5,11 @@
 package textfuzz
 
 import (
-	"io/ioutil"
-	"os"
-	"path/filepath"
 	"testing"
+
+	"google.golang.org/protobuf/internal/fuzztest"
 )
 
 func Test(t *testing.T) {
-	dir, err := os.Open("corpus")
-	if err != nil {
-		t.Fatal(err)
-	}
-	infos, err := dir.Readdir(0)
-	if err != nil {
-		t.Fatal(err)
-
-	}
-	for _, info := range infos {
-		name := info.Name()
-		t.Run(name, func(t *testing.T) {
-			b, err := ioutil.ReadFile(filepath.Join("corpus", name))
-			if err != nil {
-				t.Fatal(err)
-			}
-			Fuzz(b)
-		})
-	}
+	fuzztest.Test(t, Fuzz)
 }
diff --git a/internal/fuzz/wirefuzz/fuzz_test.go b/internal/fuzz/wirefuzz/fuzz_test.go
index 3351ae9..d4510d2 100644
--- a/internal/fuzz/wirefuzz/fuzz_test.go
+++ b/internal/fuzz/wirefuzz/fuzz_test.go
@@ -5,30 +5,11 @@
 package wirefuzz
 
 import (
-	"io/ioutil"
-	"os"
-	"path/filepath"
 	"testing"
+
+	"google.golang.org/protobuf/internal/fuzztest"
 )
 
 func Test(t *testing.T) {
-	dir, err := os.Open("corpus")
-	if err != nil {
-		t.Fatal(err)
-	}
-	infos, err := dir.Readdir(0)
-	if err != nil {
-		t.Fatal(err)
-
-	}
-	for _, info := range infos {
-		name := info.Name()
-		t.Run(name, func(t *testing.T) {
-			b, err := ioutil.ReadFile(filepath.Join("corpus", name))
-			if err != nil {
-				t.Fatal(err)
-			}
-			Fuzz(b)
-		})
-	}
+	fuzztest.Test(t, Fuzz)
 }
diff --git a/internal/fuzztest/fuzztest.go b/internal/fuzztest/fuzztest.go
new file mode 100644
index 0000000..9c066dc
--- /dev/null
+++ b/internal/fuzztest/fuzztest.go
@@ -0,0 +1,44 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package fuzztest contains a common fuzzer test.
+package fuzztest
+
+import (
+	"flag"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"sort"
+	"testing"
+)
+
+var corpus = flag.String("corpus", "corpus", "directory containing the fuzzer corpus")
+
+// Test executes a fuzz function for every entry in the corpus.
+func Test(t *testing.T, fuzz func(b []byte) int) {
+	dir, err := os.Open(*corpus)
+	if err != nil {
+		t.Fatal(err)
+	}
+	infos, err := dir.Readdir(0)
+	if err != nil {
+		t.Fatal(err)
+
+	}
+	var names []string
+	for _, info := range infos {
+		names = append(names, info.Name())
+	}
+	sort.Strings(names)
+	for _, name := range names {
+		t.Run(name, func(t *testing.T) {
+			b, err := ioutil.ReadFile(filepath.Join(*corpus, name))
+			if err != nil {
+				t.Fatal(err)
+			}
+			fuzz(b)
+		})
+	}
+}