106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"os"
|
||
|
|
"os/exec"
|
||
|
|
"path/filepath"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
type GoTestResult struct {
|
||
|
|
Stdout string `json:"stdout"`
|
||
|
|
Stderr string `json:"stderr"`
|
||
|
|
ExitCode int `json:"exit_code"`
|
||
|
|
Error string `json:"error,omitempty"`
|
||
|
|
Command string `json:"command"`
|
||
|
|
WorkDir string `json:"work_dir"`
|
||
|
|
Passed bool `json:"passed"`
|
||
|
|
TestCount int `json:"test_count,omitempty"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func goTest(path string, flags []string, timeout time.Duration) (*GoTestResult, error) {
|
||
|
|
// Resolve absolute path
|
||
|
|
absPath, err := filepath.Abs(path)
|
||
|
|
if err != nil {
|
||
|
|
return &GoTestResult{
|
||
|
|
Error: err.Error(),
|
||
|
|
Command: "go test " + path,
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Determine working directory and target
|
||
|
|
var workDir string
|
||
|
|
var target string
|
||
|
|
|
||
|
|
// Check if path is a file or directory
|
||
|
|
info, err := os.Stat(absPath)
|
||
|
|
if err != nil {
|
||
|
|
return &GoTestResult{
|
||
|
|
Error: err.Error(),
|
||
|
|
Command: "go test " + path,
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
if info.IsDir() {
|
||
|
|
// Testing a package
|
||
|
|
workDir = absPath
|
||
|
|
target = "."
|
||
|
|
} else {
|
||
|
|
// Testing a specific file (though go test typically works with packages)
|
||
|
|
workDir = filepath.Dir(absPath)
|
||
|
|
target = "."
|
||
|
|
}
|
||
|
|
|
||
|
|
// Build command arguments
|
||
|
|
args := []string{"test"}
|
||
|
|
args = append(args, flags...)
|
||
|
|
args = append(args, target)
|
||
|
|
|
||
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||
|
|
defer cancel()
|
||
|
|
|
||
|
|
cmd := exec.CommandContext(ctx, "go", args...)
|
||
|
|
cmd.Dir = workDir
|
||
|
|
|
||
|
|
stdout, stderr, exitCode, cmdErr := runCommand(cmd)
|
||
|
|
|
||
|
|
result := &GoTestResult{
|
||
|
|
Stdout: stdout,
|
||
|
|
Stderr: stderr,
|
||
|
|
ExitCode: exitCode,
|
||
|
|
Command: "go " + strings.Join(args, " "),
|
||
|
|
WorkDir: workDir,
|
||
|
|
Passed: exitCode == 0,
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try to extract test count from output
|
||
|
|
if strings.Contains(stdout, "PASS") || strings.Contains(stdout, "FAIL") {
|
||
|
|
result.TestCount = countTests(stdout)
|
||
|
|
}
|
||
|
|
|
||
|
|
if cmdErr != nil {
|
||
|
|
if ctx.Err() == context.DeadlineExceeded {
|
||
|
|
result.Error = "execution timeout exceeded"
|
||
|
|
} else {
|
||
|
|
result.Error = cmdErr.Error()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return result, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Helper function to count tests from go test output
|
||
|
|
func countTests(output string) int {
|
||
|
|
count := 0
|
||
|
|
lines := strings.Split(output, "\n")
|
||
|
|
for _, line := range lines {
|
||
|
|
if strings.HasPrefix(strings.TrimSpace(line), "--- PASS:") ||
|
||
|
|
strings.HasPrefix(strings.TrimSpace(line), "--- FAIL:") ||
|
||
|
|
strings.HasPrefix(strings.TrimSpace(line), "--- SKIP:") {
|
||
|
|
count++
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return count
|
||
|
|
}
|