1// Copyright 2018 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 main
6
7import (
8	"bytes"
9	"os"
10	"os/exec"
11	"path/filepath"
12	"runtime"
13	"strings"
14	"testing"
15
16	"github.com/rogpeppe/go-internal/gotooltest"
17	"github.com/rogpeppe/go-internal/internal/os/execpath"
18	"github.com/rogpeppe/go-internal/testscript"
19)
20
21func TestMain(m *testing.M) {
22	os.Exit(testscript.RunMain(m, map[string]func() int{
23		"testscript": main1,
24	}))
25}
26
27func TestScripts(t *testing.T) {
28	if _, err := exec.LookPath("go"); err != nil {
29		t.Fatalf("need go in PATH for these tests")
30	}
31
32	var stderr bytes.Buffer
33	cmd := exec.Command("go", "env", "GOMOD")
34	cmd.Stderr = &stderr
35	out, err := cmd.Output()
36	if err != nil {
37		t.Fatalf("failed to run %v: %v\n%s", strings.Join(cmd.Args, " "), err, stderr.String())
38	}
39	gomod := string(out)
40
41	if gomod == "" {
42		t.Fatalf("apparently we are not running in module mode?")
43	}
44
45	p := testscript.Params{
46		Dir: "testdata",
47		Setup: func(env *testscript.Env) error {
48			env.Vars = append(env.Vars,
49				"GOINTERNALMODPATH="+filepath.Dir(gomod),
50				"GONOSUMDB=*",
51			)
52			return nil
53		},
54		Cmds: map[string]func(ts *testscript.TestScript, neg bool, args []string){
55			"dropgofrompath": dropgofrompath,
56			"setfilegoproxy": setfilegoproxy,
57			"expandone":      expandone,
58		},
59	}
60	if err := gotooltest.Setup(&p); err != nil {
61		t.Fatal(err)
62	}
63	testscript.Run(t, p)
64}
65
66func dropgofrompath(ts *testscript.TestScript, neg bool, args []string) {
67	if neg {
68		ts.Fatalf("unsupported: ! dropgofrompath")
69	}
70	var newPath []string
71	for _, d := range filepath.SplitList(ts.Getenv("PATH")) {
72		getenv := func(k string) string {
73			// Note that Windows and Plan9 use lowercase "path".
74			if strings.ToUpper(k) == "PATH" {
75				return d
76			}
77			return ts.Getenv(k)
78		}
79		if _, err := execpath.Look("go", getenv); err != nil {
80			newPath = append(newPath, d)
81		}
82	}
83	ts.Setenv("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
84}
85
86func setfilegoproxy(ts *testscript.TestScript, neg bool, args []string) {
87	if neg {
88		ts.Fatalf("unsupported: ! setfilegoproxy")
89	}
90	path := args[0]
91	path = filepath.ToSlash(path)
92	// probably sufficient to just handle spaces
93	path = strings.Replace(path, " ", "%20", -1)
94	if runtime.GOOS == "windows" {
95		path = "/" + path
96	}
97	ts.Setenv("GOPROXY", "file://"+path)
98}
99
100// expandone takes a single glob-style argument that should expand to
101// a single file, otherwise the command fails
102func expandone(ts *testscript.TestScript, neg bool, args []string) {
103	if len(args) != 1 {
104		ts.Fatalf("expandone: expected a single argument")
105	}
106	if neg {
107		ts.Fatalf("unsupported: ! expandone")
108	}
109	glob := ts.MkAbs(args[0])
110	matches, err := filepath.Glob(glob)
111	if err != nil {
112		ts.Fatalf("expandone: failed to glob %q: %v", glob, err)
113	}
114	if n := len(matches); n != 1 {
115		ts.Fatalf("expandone: %q matched %v files, not 1", glob, n)
116	}
117}
118