| | |
| | |
| | |
| |
|
| | package scripttest |
| |
|
| | import ( |
| | "bytes" |
| | "cmd/internal/script" |
| | "internal/diff" |
| | "internal/testenv" |
| | "os" |
| | "path/filepath" |
| | "strings" |
| | "testing" |
| | "text/template" |
| | ) |
| |
|
| | func checkScriptReadme(t *testing.T, engine *script.Engine, env []string, scriptspath, gotool string, fixReadme bool) { |
| | var args struct { |
| | Language string |
| | Commands string |
| | Conditions string |
| | } |
| |
|
| | cmds := new(strings.Builder) |
| | if err := engine.ListCmds(cmds, true); err != nil { |
| | t.Fatal(err) |
| | } |
| | args.Commands = cmds.String() |
| |
|
| | conds := new(strings.Builder) |
| | if err := engine.ListConds(conds, nil); err != nil { |
| | t.Fatal(err) |
| | } |
| | args.Conditions = conds.String() |
| |
|
| | doc := new(strings.Builder) |
| | cmd := testenv.Command(t, gotool, "doc", "cmd/internal/script") |
| | cmd.Env = env |
| | cmd.Stdout = doc |
| | if err := cmd.Run(); err != nil { |
| | t.Fatal(cmd, ":", err) |
| | } |
| | _, lang, ok := strings.Cut(doc.String(), "# Script Language\n\n") |
| | if !ok { |
| | t.Fatalf("%q did not include Script Language section", cmd) |
| | } |
| | lang, _, ok = strings.Cut(lang, "\n\nvar ") |
| | if !ok { |
| | t.Fatalf("%q did not include vars after Script Language section", cmd) |
| | } |
| | args.Language = lang |
| |
|
| | tmpl := template.Must(template.New("README").Parse(readmeTmpl[1:])) |
| | buf := new(bytes.Buffer) |
| | if err := tmpl.Execute(buf, args); err != nil { |
| | t.Fatal(err) |
| | } |
| |
|
| | readmePath := filepath.Join(scriptspath, "README") |
| | old, err := os.ReadFile(readmePath) |
| | if err != nil { |
| | t.Fatal(err) |
| | } |
| | diff := diff.Diff(readmePath, old, "readmeTmpl", buf.Bytes()) |
| | if diff == nil { |
| | t.Logf("%s is up to date.", readmePath) |
| | return |
| | } |
| |
|
| | if fixReadme { |
| | if err := os.WriteFile(readmePath, buf.Bytes(), 0666); err != nil { |
| | t.Fatal(err) |
| | } |
| | t.Logf("wrote %d bytes to %s", buf.Len(), readmePath) |
| | } else { |
| | t.Logf("\n%s", diff) |
| | t.Errorf("%s is stale. To update, run 'go generate cmd/go'.", readmePath) |
| | } |
| | } |
| |
|
| | const readmeTmpl = ` |
| | This file is generated by 'go generate'. DO NOT EDIT. |
| | |
| | This directory holds test scripts *.txt run during 'go test cmd/<toolname>'. |
| | To run a specific script foo.txt |
| | |
| | go test cmd/<toolname> -run=Script/^foo$ |
| | |
| | In general script files should have short names: a few words, |
| | not whole sentences. |
| | The first word should be the general category of behavior being tested, |
| | often the name of a go subcommand (build, link, compile, ...) or concept (vendor, pattern). |
| | |
| | Each script is a text archive (go doc internal/txtar). |
| | The script begins with an actual command script to run |
| | followed by the content of zero or more supporting files to |
| | create in the script's temporary file system before it starts executing. |
| | |
| | As an example, run_hello.txt says: |
| | |
| | # hello world |
| | go run hello.go |
| | stderr 'hello world' |
| | ! stdout . |
| | |
| | -- hello.go -- |
| | package main |
| | func main() { println("hello world") } |
| | |
| | Each script runs in a fresh temporary work directory tree, available to scripts as $WORK. |
| | Scripts also have access to other environment variables, including: |
| | |
| | GOARCH=<target GOARCH> |
| | GOOS=<target GOOS> |
| | TMPDIR=$WORK/tmp |
| | devnull=<value of os.DevNull> |
| | goversion=<current Go version; for example, 1.12> |
| | |
| | On Plan 9, the variables $path and $home are set instead of $PATH and $HOME. |
| | On Windows, the variables $USERPROFILE and $TMP are set instead of |
| | $HOME and $TMPDIR. |
| | |
| | The lines at the top of the script are a sequence of commands to be executed by |
| | a small script engine configured in .../cmd/internal/script/scripttest/run.go (not the system shell). |
| | |
| | {{.Language}} |
| | |
| | When TestScript runs a script and the script fails, by default TestScript shows |
| | the execution of the most recent phase of the script (since the last # comment) |
| | and only shows the # comments for earlier phases. |
| | |
| | Note also that in reported output, the actual name of the per-script temporary directory |
| | has been consistently replaced with the literal string $WORK. |
| | |
| | The available commands are: |
| | {{.Commands}} |
| | |
| | The available conditions are: |
| | {{.Conditions}} |
| | ` |
| |
|