1
2
3
4
5 package scripttest
6
7 import (
8 "bytes"
9 "cmd/internal/script"
10 "internal/diff"
11 "internal/testenv"
12 "os"
13 "path/filepath"
14 "strings"
15 "testing"
16 "text/template"
17 )
18
19 func checkScriptReadme(t *testing.T, engine *script.Engine, env []string, scriptspath, gotool string, fixReadme bool) {
20 var args struct {
21 Language string
22 Commands string
23 Conditions string
24 }
25
26 cmds := new(strings.Builder)
27 if err := engine.ListCmds(cmds, true); err != nil {
28 t.Fatal(err)
29 }
30 args.Commands = cmds.String()
31
32 conds := new(strings.Builder)
33 if err := engine.ListConds(conds, nil); err != nil {
34 t.Fatal(err)
35 }
36 args.Conditions = conds.String()
37
38 doc := new(strings.Builder)
39 cmd := testenv.Command(t, gotool, "doc", "cmd/internal/script")
40 cmd.Env = env
41 cmd.Stdout = doc
42 if err := cmd.Run(); err != nil {
43 t.Fatal(cmd, ":", err)
44 }
45 _, lang, ok := strings.Cut(doc.String(), "# Script Language\n\n")
46 if !ok {
47 t.Fatalf("%q did not include Script Language section", cmd)
48 }
49 lang, _, ok = strings.Cut(lang, "\n\nvar ")
50 if !ok {
51 t.Fatalf("%q did not include vars after Script Language section", cmd)
52 }
53 args.Language = lang
54
55 tmpl := template.Must(template.New("README").Parse(readmeTmpl[1:]))
56 buf := new(bytes.Buffer)
57 if err := tmpl.Execute(buf, args); err != nil {
58 t.Fatal(err)
59 }
60
61 readmePath := filepath.Join(scriptspath, "README")
62 old, err := os.ReadFile(readmePath)
63 if err != nil {
64 t.Fatal(err)
65 }
66 diff := diff.Diff(readmePath, old, "readmeTmpl", buf.Bytes())
67 if diff == nil {
68 t.Logf("%s is up to date.", readmePath)
69 return
70 }
71
72 if fixReadme {
73 if err := os.WriteFile(readmePath, buf.Bytes(), 0666); err != nil {
74 t.Fatal(err)
75 }
76 t.Logf("wrote %d bytes to %s", buf.Len(), readmePath)
77 } else {
78 t.Logf("\n%s", diff)
79 t.Errorf("%s is stale. To update, run 'go generate cmd/go'.", readmePath)
80 }
81 }
82
83 const readmeTmpl = `
84 This file is generated by 'go generate'. DO NOT EDIT.
85
86 This directory holds test scripts *.txt run during 'go test cmd/<toolname>'.
87 To run a specific script foo.txt
88
89 go test cmd/<toolname> -run=Script/^foo$
90
91 In general script files should have short names: a few words,
92 not whole sentences.
93 The first word should be the general category of behavior being tested,
94 often the name of a go subcommand (build, link, compile, ...) or concept (vendor, pattern).
95
96 Each script is a text archive (go doc internal/txtar).
97 The script begins with an actual command script to run
98 followed by the content of zero or more supporting files to
99 create in the script's temporary file system before it starts executing.
100
101 As an example, run_hello.txt says:
102
103 # hello world
104 go run hello.go
105 stderr 'hello world'
106 ! stdout .
107
108 -- hello.go --
109 package main
110 func main() { println("hello world") }
111
112 Each script runs in a fresh temporary work directory tree, available to scripts as $WORK.
113 Scripts also have access to other environment variables, including:
114
115 GOARCH=<target GOARCH>
116 GOOS=<target GOOS>
117 TMPDIR=$WORK/tmp
118 devnull=<value of os.DevNull>
119 goversion=<current Go version; for example, 1.12>
120
121 On Plan 9, the variables $path and $home are set instead of $PATH and $HOME.
122 On Windows, the variables $USERPROFILE and $TMP are set instead of
123 $HOME and $TMPDIR.
124
125 The lines at the top of the script are a sequence of commands to be executed by
126 a small script engine configured in .../cmd/internal/script/scripttest/run.go (not the system shell).
127
128 {{.Language}}
129
130 When TestScript runs a script and the script fails, by default TestScript shows
131 the execution of the most recent phase of the script (since the last # comment)
132 and only shows the # comments for earlier phases.
133
134 Note also that in reported output, the actual name of the per-script temporary directory
135 has been consistently replaced with the literal string $WORK.
136
137 The available commands are:
138 {{.Commands}}
139
140 The available conditions are:
141 {{.Conditions}}
142 `
143
View as plain text