func copyFile(src, dst string) error {
	srcInfo, err := os.Stat(src)
	if err != nil {
		return err
	}
	mode := srcInfo.Mode()
	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()
	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func() {
		closeErr := out.Close()
		if err == nil {
			err = closeErr
		}
	}()
	_, err = io.Copy(out, in)
	if err != nil {
		return err
	}
	err = out.Sync()
	if err != nil {
		return err
	}
	return out.Chmod(mode)
}
copyFile copies the contents of the file named src to the file named
by dst. The file will be created if it does not already exist. If the
destination file exists, all it's contents will be replaced by the contents
of the source file.
package testrunner
import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"
	"github.com/onsi/ginkgo/config"
	"github.com/onsi/ginkgo/ginkgo/testsuite"
	"github.com/onsi/ginkgo/internal/remote"
	"github.com/onsi/ginkgo/reporters/stenographer"
	colorable "github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable"
	"github.com/onsi/ginkgo/types"
)
type TestRunner struct {
	Suite testsuite.TestSuite
	compiled              bool
	compilationTargetPath string
	numCPU         int
	parallelStream bool
	timeout        time.Duration
	goOpts         map[string]interface{}
	additionalArgs []string
	stderr         *bytes.Buffer
	CoverageFile string
}
func New(suite testsuite.TestSuite, numCPU int, parallelStream bool, timeout time.Duration, goOpts map[string]interface{}, additionalArgs []string) *TestRunner {
	runner := &TestRunner{
		Suite:          suite,
		numCPU:         numCPU,
		parallelStream: parallelStream,
		goOpts:         goOpts,
		additionalArgs: additionalArgs,
		timeout:        timeout,
		stderr:         new(bytes.Buffer),
	}
	if !suite.Precompiled {
		runner.compilationTargetPath, _ = filepath.Abs(filepath.Join(suite.Path, suite.PackageName+".test"))
	}
	return runner
}
func (t *TestRunner) Compile() error {
	return t.CompileTo(t.compilationTargetPath)
}
func (t *TestRunner) BuildArgs(path string) []string {
	args := make([]string, len(buildArgs), len(buildArgs)+3)
	copy(args, buildArgs)
	args = append(args, "-o", path, t.Suite.Path)
	if t.getCoverMode() != "" {
		args = append(args, "-cover", fmt.Sprintf("-covermode=%s", t.getCoverMode()))
	} else {
		if t.shouldCover() || t.getCoverPackage() != "" {
			args = append(args, "-cover", "-covermode=atomic")
		}
	}
	boolOpts := []string{
		"a",
		"n",
		"msan",
		"race",
		"x",
		"work",
		"linkshared",
	}
	for _, opt := range boolOpts {
		if s, found := t.goOpts[opt].(*bool); found && *s {
			args = append(args, fmt.Sprintf("-%s", opt))
		}
	}
	intOpts := []string{
		"memprofilerate",
		"blockprofilerate",
	}
	for _, opt := range intOpts {
		if s, found := t.goOpts[opt].(*int); found {
			args = append(args, fmt.Sprintf("-%s=%d", opt, *s))
		}
	}
	stringOpts := []string{
		"asmflags",
		"buildmode",
		"compiler",
		"gccgoflags",
		"installsuffix",
		"ldflags",
		"pkgdir",
		"toolexec",
		"coverprofile",
		"cpuprofile",
		"memprofile",
		"outputdir",
		"coverpkg",
		"tags",
		"gcflags",
		"vet",
		"mod",
	}
	for _, opt := range stringOpts {
		if s, found := t.goOpts[opt].(*string); found && *s != "" {
			args = append(args, fmt.Sprintf("-%s=%s", opt, *s))
		}
	}
	return args
}
func (t *TestRunner) CompileTo(path string) error {
	if t.compiled {
		return nil
	}
	if t.Suite.Precompiled {
		return nil
	}
	args := t.BuildArgs(path)
	cmd := exec.Command("go", args...)
	output, err := cmd.CombinedOutput()
	if err != nil {
		if len(output) > 0 {
			return fmt.Errorf("Failed to compile %s:\n\n%s", t.Suite.PackageName, output)
		}
		return fmt.Errorf("Failed to compile %s", t.Suite.PackageName)
	}
	if len(output) > 0 {
		fmt.Println(string(output))
	}
	if !fileExists(path) {
		compiledFile := t.Suite.PackageName + ".test"
		if fileExists(compiledFile) {
			err = os.Rename(compiledFile, path)
			if err != nil {
				err = copyFile(compiledFile, path)
				if err != nil {
					return fmt.Errorf("Failed to copy compiled file: %s", err)
				}
			}
		} else {
			return fmt.Errorf("Failed to compile %s: output file %q could not be found", t.Suite.PackageName, path)
		}
	}
	t.compiled = true
	return nil
}
func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil || !os.IsNotExist(err)
}