aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/internal/testsuite/testsuite.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-10-06 22:23:20 +0900
committerOphestra <cat@gensokyo.uk>2026-10-06 23:09:19 +0900
commita9e2749f6654d0aa07b274a45c9177d10323f80a (patch)
tree291f5b23a67af036cbe5d374b3d3fb0240fc438c /test/internal/testsuite/testsuite.go
parent19f36491f2e2a5029ac396c10408d653cad6c81b (diff)
internal/testsuite: move from test
This structure is a lot less clumsy than the old nix-centric layout. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test/internal/testsuite/testsuite.go')
-rw-r--r--test/internal/testsuite/testsuite.go290
1 files changed, 0 insertions, 290 deletions
diff --git a/test/internal/testsuite/testsuite.go b/test/internal/testsuite/testsuite.go
deleted file mode 100644
index 456c36b4..00000000
--- a/test/internal/testsuite/testsuite.go
+++ /dev/null
@@ -1,290 +0,0 @@
-// Package testsuite provides many quick-and-dirty integration testing utilities.
-//
-// Attempting to import this package outside testing causes the resulting
-// program to panic.
-package testsuite
-
-import (
- "bufio"
- "context"
- "crypto/sha512"
- "errors"
- "log"
- "os"
- "os/exec"
- "os/signal"
- "sync"
- "syscall"
- "time"
-)
-
-// ReceiveSignals blocks until a termination signal arrives, and terminates.
-func ReceiveSignals() {
- s := make(chan os.Signal, 3)
- signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
- log.Fatalf("terminating on signal %s", <-s)
-}
-
-// MustRun runs command and terminates the testsuite on error.
-func MustRun(cred *syscall.Credential, extraEnv []string, command ...string) {
- cmd := exec.Command(command[0], command[1:]...)
- cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: syscall.SIGKILL,
- Credential: cred,
- }
- if len(extraEnv) != 0 {
- cmd.Env = append(cmd.Environ(), extraEnv...)
- }
- if err := cmd.Run(); err != nil {
- log.Fatal(err)
- }
-}
-
-// ErrUnexpectedSuccess is returned for processes expected to exit with a
-// non-zero code, but failed to do so.
-var ErrUnexpectedSuccess = errors.New("process unexpectedly exited with code 0")
-
-// MustFail runs command and terminates the testsuite if the program fails to
-// start or exits with code 0.
-func MustFail(cred *syscall.Credential, extraEnv []string, command ...string) {
- cmd := exec.Command(command[0], command[1:]...)
- cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: syscall.SIGKILL,
- Credential: cred,
- }
- if len(extraEnv) != 0 {
- cmd.Env = append(cmd.Environ(), extraEnv...)
- }
- if err := cmd.Run(); err == nil {
- log.Fatal(ErrUnexpectedSuccess)
- } else if e, ok := errors.AsType[*exec.ExitError](err); !ok {
- log.Fatal(err)
- } else if !e.Exited() {
- log.Fatal(e)
- }
-}
-
-// MustStart starts cmd and returns a channel delivering its wait error.
-func MustStart(cmd *exec.Cmd) (done <-chan error) {
- if err := cmd.Start(); err != nil {
- log.Fatal(err)
- }
- d := make(chan error)
- go func() { d <- cmd.Wait() }()
- return d
-}
-
-// MustStartWith wraps [MustStart] and creates the [exec.Cmd] object internally.
-func MustStartWith(
- ctx context.Context,
- cred *syscall.Credential,
- extraEnv []string,
- files []*os.File,
- command ...string,
-) (proc *os.Process, done <-chan error) {
- cmd := exec.CommandContext(ctx, command[0], command[1:]...)
- cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
- cmd.ExtraFiles = files
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: syscall.SIGTERM,
- Credential: cred,
- }
- if len(extraEnv) != 0 {
- cmd.Env = append(cmd.Environ(), extraEnv...)
- }
- return cmd.Process, MustStart(cmd)
-}
-
-// MustCheckFilter is like [CheckFilter], but terminates the test suite if a
-// non-nil error is returned. Otherwise, the tracee is terminated after it
-// resumes.
-func MustCheckFilter(pid int, sum [sha512.Size]byte) {
- // podman installs its own filter
- if err := CheckFilter(pid, 1, sum); err != nil {
- log.Fatal(err)
- } else if err = syscall.Kill(pid, syscall.SIGTERM); err != nil {
- log.Fatalf("cannot terminate tracee: %v", err)
- }
-}
-
-// FilterTerminated returns a non-nil error if err is not an [exec.ExitError]
-// describing a process terminated by a syscall.SIGTERM signal.
-func FilterTerminated(err error) error {
- if err == nil {
- return ErrUnexpectedSuccess
- }
-
- e, ok := errors.AsType[*exec.ExitError](err)
- if !ok {
- return err
- }
-
- if e.ExitCode() == 0x80+int(syscall.SIGTERM) {
- return nil
- }
- return e
-}
-
-// Poll repeatedly runs command until it succeeds.
-func Poll(
- d time.Duration,
- cred *syscall.Credential,
- extraEnv []string,
- command ...string,
-) {
- for range time.NewTicker(d).C {
- cmd := exec.Command(command[0], command[1:]...)
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Pdeathsig: syscall.SIGKILL,
- Credential: cred,
- }
- if len(extraEnv) != 0 {
- cmd.Env = append(cmd.Environ(), extraEnv...)
- }
- if err := cmd.Run(); err != nil {
- if e, ok := errors.AsType[*exec.ExitError](err); ok && e.Exited() {
- continue
- }
- log.Fatal(err)
- }
- break
- }
-}
-
-const (
- // XDGRuntimeDir is the hardcoded XDG runtime directory for the user
- // described by [GetUser].
- XDGRuntimeDir = "/var/run/user/1000"
-
- // XDGRuntimeEnv is the environment variable string for XDG_RUNTIME_DIR.
- XDGRuntimeEnv = "XDG_RUNTIME_DIR=" + XDGRuntimeDir
-)
-
-// MustStartSessionBus starts a session bus that is never explicitly terminated.
-// The test suite is terminated if the session bus daemon terminates.
-func MustStartSessionBus(cred *syscall.Credential) (dbusEnv string) {
- r, w, err := os.Pipe()
- if err != nil {
- log.Fatal(err)
- }
-
- // this is never explicitly terminated
- _, done := MustStartWith(
- context.Background(), cred, nil, []*os.File{w},
- "dbus-daemon",
- "--print-address=3",
- "--address=unix:path="+XDGRuntimeDir+"/dbus",
- "--session",
- "--nofork",
- "--nopidfile",
- )
-
- go func() {
- if _err := <-done; _err != nil {
- log.Fatal(_err)
- }
- log.Fatal("session bus terminated unexpectedly")
- }()
-
- dbusEnv, err = bufio.NewReader(r).ReadString('\n')
- if err != nil {
- log.Fatal(err)
- }
- dbusEnv = dbusEnv[:len(dbusEnv)-1]
- log.Printf("dbus listening on %s", dbusEnv)
- dbusEnv = "DBUS_SESSION_BUS_ADDRESS=" + dbusEnv
-
- if err = r.Close(); err != nil {
- log.Fatal(err)
- }
- return
-}
-
-const (
- // SwayEnv is the environment variable string for the sway IPC socket.
- SwayEnv = "SWAYSOCK=" + XDGRuntimeDir + "/sway"
- // WaylandEnv is the environment variable string for the wayland display.
- WaylandEnv = "WAYLAND_DISPLAY=wayland-1"
-)
-
-// MustStartSway starts the sway wayland display server which must be terminated
-// by calling [TerminateSway].
-func MustStartSway(
- wg *sync.WaitGroup,
- cred *syscall.Credential,
- dbusEnv string,
-) {
- wg.Go(func() {
- // this is terminated via swaymsg
- _, done := MustStartWith(
- context.Background(), cred, []string{
- "WLR_BACKENDS=headless",
- XDGRuntimeEnv,
- SwayEnv,
- dbusEnv,
- }, nil,
- "sway",
- )
- if err := <-done; err != nil {
- log.Fatal(err)
- }
- })
-
- Poll(
- 50*time.Millisecond,
- cred,
- []string{SwayEnv},
- "swaymsg",
- )
- log.Printf("sway available via %s", SwayEnv)
-}
-
-// TerminateSway requests for the sway server to terminate via sway IPC.
-func TerminateSway(cred *syscall.Credential) {
- MustFail(cred, []string{SwayEnv}, "swaymsg", "exit")
-}
-
-// MustStartPipeWire starts a PipeWire server that is never explicitly
-// terminated. The test suite is terminated if the PipeWire server terminates.
-func MustStartPipeWire(cred *syscall.Credential, dbusEnv string) {
- // this is never explicitly terminated
- _, done := MustStartWith(
- context.Background(), cred, []string{
- XDGRuntimeEnv,
- dbusEnv,
- }, nil,
- "pipewire",
- )
-
- go func() {
- if _err := <-done; _err != nil {
- log.Fatal(_err)
- }
- log.Fatal("pipewire terminated unexpectedly")
- }()
-
- Poll(50*time.Millisecond, cred, []string{
- XDGRuntimeEnv,
- dbusEnv,
- },
- "wpctl",
- "status",
- )
-
- _, _done := MustStartWith(
- context.Background(), cred, []string{
- XDGRuntimeEnv,
- dbusEnv,
- }, nil,
- "wireplumber",
- )
-
- go func() {
- if _err := <-_done; _err != nil {
- log.Fatal(_err)
- }
- log.Fatal("wireplumber terminated unexpectedly")
- }()
-}