golang.org/x/playground@v0.0.0-20230418134305-14ebe15bcd59/sandbox_test.go (about)

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"go/token"
     9  	"os"
    10  	"os/exec"
    11  	"reflect"
    12  	"runtime"
    13  	"strings"
    14  	"testing"
    15  )
    16  
    17  // TestIsTest verifies that the isTest helper function matches
    18  // exactly (and only) the names of functions recognized as tests.
    19  func TestIsTest(t *testing.T) {
    20  	cmd := exec.Command(os.Args[0], "-test.list=.")
    21  	out, err := cmd.CombinedOutput()
    22  	if err != nil {
    23  		t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
    24  	}
    25  	t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
    26  
    27  	isTestFunction := map[string]bool{}
    28  	lines := strings.Split(string(out), "\n")
    29  	for _, line := range lines {
    30  		isTestFunction[strings.TrimSpace(line)] = true
    31  	}
    32  
    33  	for _, tc := range []struct {
    34  		prefix string
    35  		f      interface{}
    36  		want   bool
    37  	}{
    38  		{"Test", Test, true},
    39  		{"Test", TestIsTest, true},
    40  		{"Test", Test1IsATest, true},
    41  		{"Test", TestÑIsATest, true},
    42  
    43  		{"Test", TestisNotATest, false},
    44  
    45  		{"Example", Example, true},
    46  		{"Example", ExampleTest, true},
    47  		{"Example", Example_isAnExample, true},
    48  		{"Example", ExampleTest_isAnExample, true},
    49  
    50  		// Example_noOutput has a valid example function name but lacks an output
    51  		// declaration, but the isTest function operates only on the test name
    52  		// so it cannot detect that the function is not a test.
    53  
    54  		{"Example", Example1IsAnExample, true},
    55  		{"Example", ExampleisNotAnExample, false},
    56  
    57  		{"Benchmark", Benchmark, true},
    58  		{"Benchmark", BenchmarkNop, true},
    59  		{"Benchmark", Benchmark1IsABenchmark, true},
    60  
    61  		{"Benchmark", BenchmarkisNotABenchmark, false},
    62  
    63  		{"Fuzz", Fuzz, true},
    64  		{"Fuzz", Fuzz1IsAFuzz, true},
    65  		{"Fuzz", FuzzÑIsAFuzz, true},
    66  
    67  		{"Fuzz", FuzzisNotAFuzz, false},
    68  	} {
    69  		name := nameOf(t, tc.f)
    70  		t.Run(name, func(t *testing.T) {
    71  			if tc.want != isTestFunction[name] {
    72  				t.Fatalf(".want (%v) is inconsistent with -test.list", tc.want)
    73  			}
    74  			if !strings.HasPrefix(name, tc.prefix) {
    75  				t.Fatalf("%q is not a prefix of %v", tc.prefix, name)
    76  			}
    77  
    78  			got := isTest(name, tc.prefix)
    79  			if got != tc.want {
    80  				t.Errorf(`isTest(%q, %q) = %v; want %v`, name, tc.prefix, got, tc.want)
    81  			}
    82  		})
    83  	}
    84  }
    85  
    86  // nameOf returns the runtime-reported name of function f.
    87  func nameOf(t *testing.T, f interface{}) string {
    88  	t.Helper()
    89  
    90  	v := reflect.ValueOf(f)
    91  	if v.Kind() != reflect.Func {
    92  		t.Fatalf("%v is not a function", f)
    93  	}
    94  
    95  	rf := runtime.FuncForPC(v.Pointer())
    96  	if rf == nil {
    97  		t.Fatalf("%v.Pointer() is not a known function", f)
    98  	}
    99  
   100  	fullName := rf.Name()
   101  	parts := strings.Split(fullName, ".")
   102  
   103  	name := parts[len(parts)-1]
   104  	if !token.IsIdentifier(name) {
   105  		t.Fatalf("%q is not a valid identifier", name)
   106  	}
   107  	return name
   108  }
   109  
   110  // TestisNotATest is not a test function, despite appearances.
   111  //
   112  // Please ignore any lint or vet warnings for this function.
   113  func TestisNotATest(t *testing.T) {
   114  	panic("This is not a valid test function.")
   115  }
   116  
   117  // Test1IsATest is a valid test function.
   118  func Test1IsATest(t *testing.T) {
   119  }
   120  
   121  // Test is a test with a minimal name.
   122  func Test(t *testing.T) {
   123  }
   124  
   125  // TestÑIsATest is a test with an interesting Unicode name.
   126  func TestÑIsATest(t *testing.T) {
   127  }
   128  
   129  func Example() {
   130  	// Output:
   131  }
   132  
   133  func ExampleTest() {
   134  	// This is an example for the function Test.
   135  	// ❤ recursion.
   136  	Test(nil)
   137  
   138  	// Output:
   139  }
   140  
   141  func Example1IsAnExample() {
   142  	// Output:
   143  }
   144  
   145  // ExampleisNotAnExample is not an example function, despite appearances.
   146  //
   147  // Please ignore any lint or vet warnings for this function.
   148  func ExampleisNotAnExample() {
   149  	panic("This is not a valid example function.")
   150  
   151  	// Output:
   152  	// None. (This is not really an example function.)
   153  }
   154  
   155  func Example_isAnExample() {
   156  	// Output:
   157  }
   158  
   159  func ExampleTest_isAnExample() {
   160  	Test(nil)
   161  
   162  	// Output:
   163  }
   164  
   165  func Example_noOutput() {
   166  	// No output declared: should be compiled but not run.
   167  }
   168  
   169  func Benchmark(b *testing.B) {
   170  	for i := 0; i < b.N; i++ {
   171  	}
   172  }
   173  
   174  func BenchmarkNop(b *testing.B) {
   175  	for i := 0; i < b.N; i++ {
   176  	}
   177  }
   178  
   179  func Benchmark1IsABenchmark(b *testing.B) {
   180  	for i := 0; i < b.N; i++ {
   181  	}
   182  }
   183  
   184  // BenchmarkisNotABenchmark is not a benchmark function, despite appearances.
   185  //
   186  // Please ignore any lint or vet warnings for this function.
   187  func BenchmarkisNotABenchmark(b *testing.B) {
   188  	panic("This is not a valid benchmark function.")
   189  }
   190  
   191  // FuzzisNotAFuzz is not a fuzz test function, despite appearances.
   192  //
   193  // Please ignore any lint or vet warnings for this function.
   194  func FuzzisNotAFuzz(f *testing.F) {
   195  	panic("This is not a valid fuzzing function.")
   196  }
   197  
   198  // Fuzz1IsAFuzz is a valid fuzz function.
   199  func Fuzz1IsAFuzz(f *testing.F) {
   200  	f.Skip()
   201  }
   202  
   203  // Fuzz is a fuzz with a minimal name.
   204  func Fuzz(f *testing.F) {
   205  	f.Skip()
   206  }
   207  
   208  // FuzzÑIsAFuzz is a fuzz with an interesting Unicode name.
   209  func FuzzÑIsAFuzz(f *testing.F) {
   210  	f.Skip()
   211  }