Files
Ant-Browser/backend/app_instance_start_helpers_test.go
T

172 lines
3.8 KiB
Go

package backend
import (
"fmt"
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
goruntime "runtime"
"testing"
"time"
)
func mustListenLoopback(t *testing.T) net.Listener {
t.Helper()
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("监听测试端口失败: %v", err)
}
go func() {
for {
conn, err := ln.Accept()
if err != nil {
return
}
_ = conn.Close()
}
}()
return ln
}
func listenerPort(t *testing.T, ln net.Listener) int {
t.Helper()
tcpAddr, ok := ln.Addr().(*net.TCPAddr)
if !ok {
t.Fatalf("解析监听地址失败: %T", ln.Addr())
}
return tcpAddr.Port
}
func shortLivedCommand() *exec.Cmd {
if goruntime.GOOS == "windows" {
return exec.Command("cmd", "/c", "exit", "0")
}
return exec.Command("sh", "-c", "exit 0")
}
func longLivedCommand(duration time.Duration) *exec.Cmd {
if goruntime.GOOS == "windows" {
seconds := int(duration / time.Second)
if seconds < 1 {
seconds = 1
}
return exec.Command("cmd", "/c", fmt.Sprintf("ping -n %d 127.0.0.1 >nul", seconds+1))
}
return exec.Command("sh", "-c", fmt.Sprintf("sleep %.1f", duration.Seconds()))
}
func stderrFailingCommand(message string) *exec.Cmd {
if goruntime.GOOS == "windows" {
return exec.Command("cmd", "/c", fmt.Sprintf("echo %s 1>&2 & exit 5", message))
}
return exec.Command("sh", "-c", fmt.Sprintf("echo '%s' 1>&2; exit 5", message))
}
func stderrPortCommand(port int, holdFor time.Duration) *exec.Cmd {
if goruntime.GOOS == "windows" {
seconds := int(holdFor / time.Second)
if seconds < 1 {
seconds = 1
}
// ping -n N waits roughly N-1 seconds on Windows.
return exec.Command("cmd", "/c", fmt.Sprintf("echo DevTools listening on ws://127.0.0.1:%d/devtools/browser/test 1>&2 & ping -n %d 127.0.0.1 >nul", port, seconds+1))
}
return exec.Command("sh", "-c", fmt.Sprintf("echo 'DevTools listening on ws://127.0.0.1:%d/devtools/browser/test' 1>&2; sleep %.1f", port, holdFor.Seconds()))
}
func waitForCondition(t *testing.T, timeout time.Duration, check func() bool) {
t.Helper()
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
if check() {
return
}
time.Sleep(100 * time.Millisecond)
}
t.Fatal("等待条件成立超时")
}
func freeLoopbackPort(t *testing.T) int {
t.Helper()
ln := mustListenLoopback(t)
port := listenerPort(t, ln)
_ = ln.Close()
return port
}
type devToolsTestServer struct {
port int
server *http.Server
done chan struct{}
}
func startDevToolsServer(t *testing.T, handler http.Handler) *devToolsTestServer {
t.Helper()
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("启动 DevTools 测试服务失败: %v", err)
}
srv := &http.Server{Handler: handler}
done := make(chan struct{})
go func() {
defer close(done)
_ = srv.Serve(ln)
}()
return &devToolsTestServer{
port: listenerPort(t, ln),
server: srv,
done: done,
}
}
func startDevToolsServerOnPort(t *testing.T, port int, handler http.Handler) *devToolsTestServer {
t.Helper()
ln, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
if err != nil {
t.Fatalf("在指定端口启动 DevTools 测试服务失败: %v", err)
}
srv := &http.Server{Handler: handler}
done := make(chan struct{})
go func() {
defer close(done)
_ = srv.Serve(ln)
}()
return &devToolsTestServer{
port: port,
server: srv,
done: done,
}
}
func (s *devToolsTestServer) Close() error {
if s == nil || s.server == nil {
return nil
}
err := s.server.Close()
<-s.done
return err
}
func writeDevToolsActivePortFile(t *testing.T, userDataDir string, port int) {
t.Helper()
content := fmt.Sprintf("%d\n/devtools/browser/test\n", port)
if err := os.WriteFile(filepath.Join(userDataDir, "DevToolsActivePort"), []byte(content), 0644); err != nil {
t.Fatalf("写入 DevToolsActivePort 失败: %v", err)
}
}