TestIsTest: move ill-formed tests into a testdata subpackage

This avoids triggering the go1.24 vet check for ill-formed
Test (etc) function names.

Fixes golang/go#68999

Change-Id: I60a21e99dd4835f20c3e999a1ee8f29451cf653b
Reviewed-on: https://go-review.googlesource.com/c/playground/+/607835
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/sandbox_test.go b/sandbox_test.go
index 6130936..0beae04 100644
--- a/sandbox_test.go
+++ b/sandbox_test.go
@@ -5,11 +5,8 @@
 package main
 
 import (
-	"go/token"
-	"os"
 	"os/exec"
 	"reflect"
-	"runtime"
 	"strings"
 	"testing"
 )
@@ -39,7 +36,9 @@
 // TestIsTest verifies that the isTest helper function matches
 // exactly (and only) the names of functions recognized as tests.
 func TestIsTest(t *testing.T) {
-	cmd := exec.Command(os.Args[0], "-test.list=.")
+	// We must disable vet's "tests" analyzer which would otherwise cause
+	// go test to fail due to the intentional problems in testdata/p's tests.
+	cmd := exec.Command("go", "test", "./testdata/p", "-vet=off", "-test.list=.")
 	out, err := cmd.CombinedOutput()
 	if err != nil {
 		t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
@@ -49,46 +48,50 @@
 	isTestFunction := map[string]bool{}
 	lines := strings.Split(string(out), "\n")
 	for _, line := range lines {
+		// We want Test/Benchmark/Example/Fuzz functions.
+		// Reject extraneous output such as "ok ...".
+		if line == "" || !strings.Contains("TBEF", line[:1]) {
+			continue
+		}
 		isTestFunction[strings.TrimSpace(line)] = true
 	}
 
 	for _, tc := range []struct {
 		prefix string
-		f      interface{}
+		name   string // name of a Test (etc) in ./testdata/p
 		want   bool
 	}{
-		{"Test", Test, true},
-		{"Test", TestIsTest, true},
-		{"Test", Test1IsATest, true},
-		{"Test", TestÑIsATest, true},
+		{"Test", "Test", true},
+		{"Test", "Test1IsATest", true},
+		{"Test", "TestÑIsATest", true},
 
-		{"Test", TestisNotATest, false},
+		{"Test", "TestisNotATest", false},
 
-		{"Example", Example, true},
-		{"Example", ExampleTest, true},
-		{"Example", Example_isAnExample, true},
-		{"Example", ExampleTest_isAnExample, true},
+		{"Example", "Example", true},
+		{"Example", "ExampleTest", true},
+		{"Example", "Example_isAnExample", true},
+		{"Example", "ExampleTest_isAnExample", true},
 
 		// Example_noOutput has a valid example function name but lacks an output
 		// declaration, but the isTest function operates only on the test name
 		// so it cannot detect that the function is not a test.
 
-		{"Example", Example1IsAnExample, true},
-		{"Example", ExampleisNotAnExample, false},
+		{"Example", "Example1IsAnExample", true},
+		{"Example", "ExampleisNotAnExample", false},
 
-		{"Benchmark", Benchmark, true},
-		{"Benchmark", BenchmarkNop, true},
-		{"Benchmark", Benchmark1IsABenchmark, true},
+		{"Benchmark", "Benchmark", true},
+		{"Benchmark", "BenchmarkNop", true},
+		{"Benchmark", "Benchmark1IsABenchmark", true},
 
-		{"Benchmark", BenchmarkisNotABenchmark, false},
+		{"Benchmark", "BenchmarkisNotABenchmark", false},
 
-		{"Fuzz", Fuzz, true},
-		{"Fuzz", Fuzz1IsAFuzz, true},
-		{"Fuzz", FuzzÑIsAFuzz, true},
+		{"Fuzz", "Fuzz", true},
+		{"Fuzz", "Fuzz1IsAFuzz", true},
+		{"Fuzz", "FuzzÑIsAFuzz", true},
 
-		{"Fuzz", FuzzisNotAFuzz, false},
+		{"Fuzz", "FuzzisNotAFuzz", false},
 	} {
-		name := nameOf(t, tc.f)
+		name := tc.name
 		t.Run(name, func(t *testing.T) {
 			if tc.want != isTestFunction[name] {
 				t.Fatalf(".want (%v) is inconsistent with -test.list", tc.want)
@@ -104,130 +107,3 @@
 		})
 	}
 }
-
-// nameOf returns the runtime-reported name of function f.
-func nameOf(t *testing.T, f interface{}) string {
-	t.Helper()
-
-	v := reflect.ValueOf(f)
-	if v.Kind() != reflect.Func {
-		t.Fatalf("%v is not a function", f)
-	}
-
-	rf := runtime.FuncForPC(v.Pointer())
-	if rf == nil {
-		t.Fatalf("%v.Pointer() is not a known function", f)
-	}
-
-	fullName := rf.Name()
-	parts := strings.Split(fullName, ".")
-
-	name := parts[len(parts)-1]
-	if !token.IsIdentifier(name) {
-		t.Fatalf("%q is not a valid identifier", name)
-	}
-	return name
-}
-
-// TestisNotATest is not a test function, despite appearances.
-//
-// Please ignore any lint or vet warnings for this function.
-func TestisNotATest(t *testing.T) {
-	panic("This is not a valid test function.")
-}
-
-// Test1IsATest is a valid test function.
-func Test1IsATest(t *testing.T) {
-}
-
-// Test is a test with a minimal name.
-func Test(t *testing.T) {
-}
-
-// TestÑIsATest is a test with an interesting Unicode name.
-func TestÑIsATest(t *testing.T) {
-}
-
-func Example() {
-	// Output:
-}
-
-func ExampleTest() {
-	// This is an example for the function Test.
-	// ❤ recursion.
-	Test(nil)
-
-	// Output:
-}
-
-func Example1IsAnExample() {
-	// Output:
-}
-
-// ExampleisNotAnExample is not an example function, despite appearances.
-//
-// Please ignore any lint or vet warnings for this function.
-func ExampleisNotAnExample() {
-	panic("This is not a valid example function.")
-
-	// Output:
-	// None. (This is not really an example function.)
-}
-
-func Example_isAnExample() {
-	// Output:
-}
-
-func ExampleTest_isAnExample() {
-	Test(nil)
-
-	// Output:
-}
-
-func Example_noOutput() {
-	// No output declared: should be compiled but not run.
-}
-
-func Benchmark(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-	}
-}
-
-func BenchmarkNop(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-	}
-}
-
-func Benchmark1IsABenchmark(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-	}
-}
-
-// BenchmarkisNotABenchmark is not a benchmark function, despite appearances.
-//
-// Please ignore any lint or vet warnings for this function.
-func BenchmarkisNotABenchmark(b *testing.B) {
-	panic("This is not a valid benchmark function.")
-}
-
-// FuzzisNotAFuzz is not a fuzz test function, despite appearances.
-//
-// Please ignore any lint or vet warnings for this function.
-func FuzzisNotAFuzz(f *testing.F) {
-	panic("This is not a valid fuzzing function.")
-}
-
-// Fuzz1IsAFuzz is a valid fuzz function.
-func Fuzz1IsAFuzz(f *testing.F) {
-	f.Skip()
-}
-
-// Fuzz is a fuzz with a minimal name.
-func Fuzz(f *testing.F) {
-	f.Skip()
-}
-
-// FuzzÑIsAFuzz is a fuzz with an interesting Unicode name.
-func FuzzÑIsAFuzz(f *testing.F) {
-	f.Skip()
-}
diff --git a/testdata/p/p_test.go b/testdata/p/p_test.go
new file mode 100644
index 0000000..0d0c218
--- /dev/null
+++ b/testdata/p/p_test.go
@@ -0,0 +1,112 @@
+package p_test
+
+// This file defines various Test, Benchmark, Example, and Fuzz
+// functions for use by TestIsTest in sandbox_test.go. Some are
+// ill-formed and will fail go vet's static checks, would fail at
+// runtime if executed by go test, or would not be recognized as tests
+// by either tool.
+
+import "testing"
+
+// TestisNotATest is not a test function, despite appearances.
+//
+// Please ignore any lint or vet warnings for this function.
+func TestisNotATest(t *testing.T) {
+	panic("This is not a valid test function.")
+}
+
+// Test1IsATest is a valid test function.
+func Test1IsATest(t *testing.T) {
+}
+
+// Test is a test with a minimal name.
+func Test(t *testing.T) {
+}
+
+// TestÑIsATest is a test with an interesting Unicode name.
+func TestÑIsATest(t *testing.T) {
+}
+
+func Example() {
+	// Output:
+}
+
+func ExampleTest() {
+	// This is an example for the function Test.
+	// ❤ recursion.
+	Test(nil)
+
+	// Output:
+}
+
+func Example1IsAnExample() {
+	// Output:
+}
+
+// ExampleisNotAnExample is not an example function, despite appearances.
+//
+// Please ignore any lint or vet warnings for this function.
+func ExampleisNotAnExample() {
+	panic("This is not a valid example function.")
+
+	// Output:
+	// None. (This is not really an example function.)
+}
+
+func Example_isAnExample() {
+	// Output:
+}
+
+func ExampleTest_isAnExample() {
+	Test(nil)
+
+	// Output:
+}
+
+func Example_noOutput() {
+	// No output declared: should be compiled but not run.
+}
+
+func Benchmark(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+	}
+}
+
+func BenchmarkNop(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+	}
+}
+
+func Benchmark1IsABenchmark(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+	}
+}
+
+// BenchmarkisNotABenchmark is not a benchmark function, despite appearances.
+//
+// Please ignore any lint or vet warnings for this function.
+func BenchmarkisNotABenchmark(b *testing.B) {
+	panic("This is not a valid benchmark function.")
+}
+
+// FuzzisNotAFuzz is not a fuzz test function, despite appearances.
+//
+// Please ignore any lint or vet warnings for this function.
+func FuzzisNotAFuzz(f *testing.F) {
+	panic("This is not a valid fuzzing function.")
+}
+
+// Fuzz1IsAFuzz is a valid fuzz function.
+func Fuzz1IsAFuzz(f *testing.F) {
+	f.Skip()
+}
+
+// Fuzz is a fuzz with a minimal name.
+func Fuzz(f *testing.F) {
+	f.Skip()
+}
+
+// FuzzÑIsAFuzz is a fuzz with an interesting Unicode name.
+func FuzzÑIsAFuzz(f *testing.F) {
+	f.Skip()
+}