mirror of https://github.com/knative/func.git
218 lines
5.5 KiB
Go
218 lines
5.5 KiB
Go
// package testing includes minor testing helpers.
|
|
//
|
|
// These helpers include extensions to the testing nomenclature which exist to
|
|
// ease the development of tests for functions. It is mostly just syntactic
|
|
// sugar and closures for creating an removing test directories etc.
|
|
// It was originally included in each of the requisite testing packages, but
|
|
// since we use both private-access enabled tests (in the function package),
|
|
// as well as closed-box tests (in function_test package), and they are gradually
|
|
// increasing in size and complexity, the choice was made to choose a small
|
|
// dependency over a small amount of copying.
|
|
//
|
|
// Another reason for including these in a separate locaiton is that they will
|
|
// have no tags such that no combination of tags can cause them to either be
|
|
// missing or interfere with eachother (a problem encountered with knative
|
|
// tooling which by default runs tests with all tags enabled simultaneously)
|
|
package testing
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
"net/http/cgi"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Using the given path, create it as a new directory and return a deferrable
|
|
// which will remove it.
|
|
// usage:
|
|
//
|
|
// defer using(t, "testdata/example.com/someExampleTest")()
|
|
func Using(t *testing.T, root string) func() {
|
|
t.Helper()
|
|
mkdir(t, root)
|
|
return func() {
|
|
rm(t, root)
|
|
}
|
|
}
|
|
|
|
// mkdir creates a directory as a test helper, failing the test on error.
|
|
func mkdir(t *testing.T, dir string) {
|
|
t.Helper()
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// rm a directory as a test helper, failing the test on error.
|
|
func rm(t *testing.T, dir string) {
|
|
t.Helper()
|
|
if err := os.RemoveAll(dir); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Within the given root creates the directory, CDs to it, and rturns a
|
|
// closure that when executed (intended in a defer) removes the given dirctory
|
|
// and returns the caller to the initial working directory.
|
|
// usage:
|
|
// defer within(t, "somedir")()
|
|
func Within(t *testing.T, root string) func() {
|
|
t.Helper()
|
|
cwd := pwd(t)
|
|
mkdir(t, root)
|
|
cd(t, root)
|
|
return func() {
|
|
cd(t, cwd)
|
|
rm(t, root)
|
|
}
|
|
}
|
|
|
|
// Mktemp creates a temporary directory, CDs the current processes (test) to
|
|
// said directory, and returns the path to said directory.
|
|
// Usage:
|
|
// path, rm := Mktemp(t)
|
|
// defer rm()
|
|
// CWD is now 'path'
|
|
// errors encountererd fail the current test.
|
|
func Mktemp(t *testing.T) (string, func()) {
|
|
t.Helper()
|
|
tmp := t.TempDir()
|
|
owd := pwd(t)
|
|
cd(t, tmp)
|
|
return tmp, func() {
|
|
cd(t, owd)
|
|
}
|
|
}
|
|
|
|
// Fromtemp is like Mktemp, but does not bother returing the temp path.
|
|
func Fromtemp(t *testing.T) func() {
|
|
_, done := Mktemp(t)
|
|
return done
|
|
}
|
|
|
|
// pwd prints the current working directory.
|
|
// errors fail the test.
|
|
func pwd(t *testing.T) string {
|
|
t.Helper()
|
|
d, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return d
|
|
}
|
|
|
|
// cd changes directory to the given directory.
|
|
// errors fail the given test.
|
|
func cd(t *testing.T, dir string) {
|
|
if err := os.Chdir(dir); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// ServeRepositry [name] from ./testdata/[name] returning URL at which
|
|
// the named repository is available.
|
|
// Must be called before any helpers which change test working directory
|
|
// such as fromTempDirectory(t)
|
|
func ServeRepo(name string, t *testing.T) string {
|
|
t.Helper()
|
|
var (
|
|
path = filepath.Join("./testdata", name)
|
|
dir = filepath.Dir(path)
|
|
abs, _ = filepath.Abs(dir)
|
|
repo = filepath.Base(path)
|
|
url = RunGitServer(abs, t)
|
|
)
|
|
return fmt.Sprintf("%v/%v", url, repo)
|
|
}
|
|
|
|
// WithExecutable creates an executable of the given name and source in a temp
|
|
// directory which is then added to PATH. Returned is a deferrable which will
|
|
// clean up both the script and PATH.
|
|
func WithExecutable(t *testing.T, name, goSrc string) {
|
|
var err error
|
|
binDir := t.TempDir()
|
|
|
|
newPath := binDir + string(os.PathListSeparator) + os.Getenv("PATH")
|
|
t.Setenv("PATH", newPath)
|
|
|
|
goSrcPath := filepath.Join(binDir, fmt.Sprintf("%s.go", name))
|
|
|
|
err = os.WriteFile(goSrcPath,
|
|
[]byte(goSrc),
|
|
0400)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
runnerScriptName := name
|
|
if runtime.GOOS == "windows" {
|
|
runnerScriptName = runnerScriptName + ".bat"
|
|
}
|
|
|
|
runnerScriptSrc := `#!/bin/sh
|
|
exec go run GO_SCRIPT_PATH $@;
|
|
`
|
|
if runtime.GOOS == "windows" {
|
|
runnerScriptSrc = `@echo off
|
|
go.exe run GO_SCRIPT_PATH %*
|
|
`
|
|
}
|
|
|
|
runnerScriptPath := filepath.Join(binDir, runnerScriptName)
|
|
runnerScriptSrc = strings.ReplaceAll(runnerScriptSrc, "GO_SCRIPT_PATH", goSrcPath)
|
|
err = os.WriteFile(runnerScriptPath, []byte(runnerScriptSrc), 0700)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// RunGitServer starts serving git HTTP server and returns its address
|
|
func RunGitServer(root string, t *testing.T) (url string) {
|
|
l, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
url = l.Addr().String()
|
|
|
|
cmd := exec.Command("git", "--exec-path")
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
server := &http.Server{
|
|
Handler: &cgi.Handler{
|
|
Path: filepath.Join(strings.Trim(string(out), "\n"), "git-http-backend"),
|
|
Env: []string{"GIT_HTTP_EXPORT_ALL=true", fmt.Sprintf("GIT_PROJECT_ROOT=%s", root)},
|
|
},
|
|
}
|
|
|
|
go func() {
|
|
err = server.Serve(l)
|
|
if err != nil && !strings.Contains(err.Error(), "Server closed") {
|
|
fmt.Fprintf(os.Stderr, "ERROR: %v\n", err)
|
|
}
|
|
}()
|
|
|
|
t.Cleanup(func() {
|
|
server.Close()
|
|
})
|
|
|
|
return "http://" + url
|
|
}
|
|
|
|
// Cwd returns the current working directory or panic if unable to determine.
|
|
func Cwd() (cwd string) {
|
|
cwd, err := os.Getwd()
|
|
if err != nil {
|
|
panic(fmt.Sprintf("Unable to determine current working directory: %v", err))
|
|
}
|
|
return cwd
|
|
}
|