blob: e61083e8a43e0b00bc6c46c86e6cc409b8bc421b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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, 0o700); 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)
}
}
// FileExists checks whether file on the specified path exists
func FileExists(t *testing.T, filePath string) (bool, error) {
_, err := os.Stat(filePath)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
return true, nil
}
// 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)
}
}
// ServeRepo [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),
0o400)
if err != nil {
t.Fatal(err)
}
if runtime.GOOS == "windows" {
name = name + ".exe"
}
binaryPath := filepath.Join(binDir, name)
cmd := exec.Command("go", "build", "-o="+binaryPath, goSrcPath)
o, err := cmd.CombinedOutput()
if err != nil {
t.Log(string(o))
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
}
// ClearEnvs sets all environment variables with the prefix of FUNC_ to
// empty (unsets) for the duration of the test t and is used when
// a test needs to completely clear dubbo-related envs prior to running.
func ClearEnvs(t *testing.T) {
t.Helper()
for _, v := range os.Environ() {
if strings.HasPrefix(v, "DUBBO_") {
parts := strings.SplitN(v, "=", 2)
t.Setenv(parts[0], "")
}
}
}