1// Copyright 2023 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 5package godebugs_test 6 7import ( 8 "internal/godebugs" 9 "internal/testenv" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "regexp" 14 "runtime" 15 "strings" 16 "testing" 17) 18 19func TestAll(t *testing.T) { 20 testenv.MustHaveGoBuild(t) 21 22 data, err := os.ReadFile("../../../doc/godebug.md") 23 if err != nil { 24 if os.IsNotExist(err) && (testenv.Builder() == "" || runtime.GOOS != "linux") { 25 t.Skip(err) 26 } 27 t.Fatal(err) 28 } 29 doc := string(data) 30 31 incs := incNonDefaults(t) 32 33 last := "" 34 for _, info := range godebugs.All { 35 if info.Name <= last { 36 t.Errorf("All not sorted: %s then %s", last, info.Name) 37 } 38 last = info.Name 39 40 if info.Package == "" { 41 t.Errorf("Name=%s missing Package", info.Name) 42 } 43 if info.Changed != 0 && info.Old == "" { 44 t.Errorf("Name=%s has Changed, missing Old", info.Name) 45 } 46 if info.Old != "" && info.Changed == 0 { 47 t.Errorf("Name=%s has Old, missing Changed", info.Name) 48 } 49 if !strings.Contains(doc, "`"+info.Name+"`") { 50 t.Errorf("Name=%s not documented in doc/godebug.md", info.Name) 51 } 52 if !info.Opaque && !incs[info.Name] { 53 t.Errorf("Name=%s missing IncNonDefault calls; see 'go doc internal/godebug'", info.Name) 54 } 55 } 56} 57 58var incNonDefaultRE = regexp.MustCompile(`([\pL\p{Nd}_]+)\.IncNonDefault\(\)`) 59 60func incNonDefaults(t *testing.T) map[string]bool { 61 // Build list of all files importing internal/godebug. 62 // Tried a more sophisticated search in go list looking for 63 // imports containing "internal/godebug", but that turned 64 // up a bug in go list instead. #66218 65 out, err := exec.Command("go", "list", "-f={{.Dir}}", "std", "cmd").CombinedOutput() 66 if err != nil { 67 t.Fatalf("go list: %v\n%s", err, out) 68 } 69 70 seen := map[string]bool{} 71 for _, dir := range strings.Split(string(out), "\n") { 72 if dir == "" { 73 continue 74 } 75 files, err := os.ReadDir(dir) 76 if err != nil { 77 t.Fatal(err) 78 } 79 for _, file := range files { 80 name := file.Name() 81 if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") { 82 continue 83 } 84 data, err := os.ReadFile(filepath.Join(dir, name)) 85 if err != nil { 86 t.Fatal(err) 87 } 88 for _, m := range incNonDefaultRE.FindAllSubmatch(data, -1) { 89 seen[string(m[1])] = true 90 } 91 } 92 } 93 return seen 94} 95