Files
polaris/vendor/github.com/rogpeppe/go-internal/gotooltest/setup.go
Bobby Brennan 54a4f92695 Pack static assets into packr box for portability
copy config.yaml to docker image

enable external usage of dashboard package

gofmt

fix comment

use packr for assets

add gobuffalo/packr dependency

add dependencies

fix pointer issues

add output-file option
2019-04-18 18:25:16 +00:00

187 lines
4.5 KiB
Go

// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package gotooltest implements functionality useful for testing
// tools that use the go command.
package gotooltest
import (
"bytes"
"encoding/json"
"fmt"
"go/build"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
"github.com/rogpeppe/go-internal/testscript"
)
var (
goVersionRegex = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
goEnv struct {
GOROOT string
GOCACHE string
GOPROXY string
goversion string
releaseTags []string
once sync.Once
err error
}
)
// initGoEnv initialises goEnv. It should only be called using goEnv.once.Do,
// as in Setup.
func initGoEnv() error {
var err error
run := func(args ...string) (*bytes.Buffer, *bytes.Buffer, error) {
var stdout, stderr bytes.Buffer
cmd := exec.Command(args[0], args[1:]...)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
return &stdout, &stderr, cmd.Run()
}
lout, stderr, err := run("go", "list", "-f={{context.ReleaseTags}}", "runtime")
if err != nil {
return fmt.Errorf("failed to determine release tags from go command: %v\n%v", err, stderr.String())
}
tagStr := strings.TrimSpace(lout.String())
tagStr = strings.Trim(tagStr, "[]")
goEnv.releaseTags = strings.Split(tagStr, " ")
eout, stderr, err := run("go", "env", "-json",
"GOROOT",
"GOCACHE",
"GOPROXY",
)
if err != nil {
return fmt.Errorf("failed to determine environment from go command: %v\n%v", err, stderr)
}
if err := json.Unmarshal(eout.Bytes(), &goEnv); err != nil {
return fmt.Errorf("failed to unmarshal GOROOT and GOCACHE tags from go command out: %v\n%v", err, eout)
}
version := goEnv.releaseTags[len(goEnv.releaseTags)-1]
if !goVersionRegex.MatchString(version) {
return fmt.Errorf("invalid go version %q", version)
}
goEnv.goversion = version[2:]
return nil
}
// Setup sets up the given test environment for tests that use the go
// command. It adds support for go tags to p.Condition and adds the go
// command to p.Cmds. It also wraps p.Setup to set up the environment
// variables for running the go command appropriately.
//
// It checks go command can run, but not that it can build or run
// binaries.
func Setup(p *testscript.Params) error {
goEnv.once.Do(func() {
goEnv.err = initGoEnv()
})
if goEnv.err != nil {
return goEnv.err
}
origSetup := p.Setup
p.Setup = func(e *testscript.Env) error {
e.Vars = goEnviron(e.Vars)
if origSetup != nil {
return origSetup(e)
}
return nil
}
if p.Cmds == nil {
p.Cmds = make(map[string]func(ts *testscript.TestScript, neg bool, args []string))
}
p.Cmds["go"] = cmdGo
origCondition := p.Condition
p.Condition = func(cond string) (bool, error) {
if cond == "gc" || cond == "gccgo" {
// TODO this reflects the compiler that the current
// binary was built with but not necessarily the compiler
// that will be used.
return cond == runtime.Compiler, nil
}
if goVersionRegex.MatchString(cond) {
for _, v := range build.Default.ReleaseTags {
if cond == v {
return true, nil
}
}
return false, nil
}
if origCondition == nil {
return false, fmt.Errorf("unknown condition %q", cond)
}
return origCondition(cond)
}
return nil
}
func goEnviron(env0 []string) []string {
env := environ(env0)
workdir := env.get("WORK")
return append(env, []string{
"GOPATH=" + filepath.Join(workdir, "gopath"),
"CCACHE_DISABLE=1", // ccache breaks with non-existent HOME
"GOARCH=" + runtime.GOARCH,
"GOOS=" + runtime.GOOS,
"GOROOT=" + goEnv.GOROOT,
"GOCACHE=" + goEnv.GOCACHE,
"GOPROXY=" + goEnv.GOPROXY,
"goversion=" + goEnv.goversion,
}...)
}
func cmdGo(ts *testscript.TestScript, neg bool, args []string) {
if len(args) < 1 {
ts.Fatalf("usage: go subcommand ...")
}
err := ts.Exec("go", args...)
if err != nil {
ts.Logf("[%v]\n", err)
if !neg {
ts.Fatalf("unexpected go command failure")
}
} else {
if neg {
ts.Fatalf("unexpected go command success")
}
}
}
type environ []string
func (e0 *environ) get(name string) string {
e := *e0
for i := len(e) - 1; i >= 0; i-- {
v := e[i]
if len(v) <= len(name) {
continue
}
if strings.HasPrefix(v, name) && v[len(name)] == '=' {
return v[len(name)+1:]
}
}
return ""
}
func (e *environ) set(name, val string) {
*e = append(*e, name+"="+val)
}
func (e *environ) unset(name string) {
// TODO actually remove the name from the environment.
e.set(name, "")
}