main shinobi / tests / runner / testhelp / main.go
  1package main
  2
  3import (
  4	"fmt"
  5	"os"
  6	"path/filepath"
  7	"strconv"
  8	"syscall"
  9	"time"
 10)
 11//this is a replacement for GNU's thelp.pl from their test suite.
 12
 13func main() {
 14	args := os.Args[1:]
 15	quiet := false
 16	timeout := 10 * time.Second
 17
 18	if len(args) > 0 && args[0] == "-q" {
 19		quiet = true
 20		args = args[1:]
 21	}
 22
 23	for len(args) > 0 {
 24		if len(args) < 2 {
 25			die("Missing value for " + args[0])
 26		}
 27		op, arg := args[0], args[1]
 28		args = args[2:]
 29
 30		nextTimeout, handled := runOp(quiet, timeout, op, arg)
 31		timeout = nextTimeout
 32		if handled {
 33			continue
 34		}
 35		die(fmt.Sprintf("Invalid command: %s %s", op, arg))
 36	}
 37}
 38
 39func runOp(quiet bool, timeout time.Duration, op, arg string) (time.Duration, bool) {
 40	switch op {
 41	case "out":
 42		fmt.Println(arg)
 43	case "raw":
 44		fmt.Print(arg)
 45	case "env":
 46		if !quiet {
 47			fmt.Printf("%s=", arg)
 48		}
 49		if value, ok := os.LookupEnv(arg); ok {
 50			fmt.Println(value)
 51		} else {
 52			fmt.Println("<unset>")
 53		}
 54	case "file":
 55		if !quiet {
 56			fmt.Printf("file %s\n", arg)
 57		}
 58		f, err := os.Create(arg)
 59		if err != nil {
 60			die(fmt.Sprintf("%s: open: %v", arg, err))
 61		}
 62		if err := f.Close(); err != nil {
 63			die(fmt.Sprintf("%s: close: %v", arg, err))
 64		}
 65	case "exist":
 66		if _, err := os.Stat(arg); err != nil {
 67			die(fmt.Sprintf("%s: file should exist: %v", arg, err))
 68		}
 69		if !quiet {
 70			fmt.Printf("exist %s\n", arg)
 71		}
 72	case "noexist":
 73		if _, err := os.Stat(arg); err == nil {
 74			die(fmt.Sprintf("%s: file exists", arg))
 75		} else if !os.IsNotExist(err) {
 76			die(fmt.Sprintf("%s: stat: %v", arg, err))
 77		}
 78		if !quiet {
 79			fmt.Printf("noexist %s\n", arg)
 80		}
 81	case "dir":
 82		if !quiet {
 83			fmt.Printf("dir %s\n", arg)
 84		}
 85		if err := os.Mkdir(arg, 0o755); err != nil {
 86			die(fmt.Sprintf("%s: mkdir: %v", arg, err))
 87		}
 88	case "rm":
 89		info, err := os.Stat(arg)
 90		if err != nil {
 91			die(fmt.Sprintf("%s: not file or directory: %v", arg, err))
 92		}
 93		if info.IsDir() {
 94			if err := os.Remove(arg); err != nil {
 95				die(fmt.Sprintf("%s: rmdir: %v", arg, err))
 96			}
 97		} else {
 98			if err := os.Remove(arg); err != nil {
 99				die(fmt.Sprintf("%s: unlink: %v", arg, err))
100			}
101		}
102		if !quiet {
103			fmt.Printf("rm %s\n", arg)
104		}
105	case "tmout":
106		secs, err := strconv.Atoi(arg)
107		if err != nil {
108			die(fmt.Sprintf("tmout %s: %v", arg, err))
109		}
110		if !quiet {
111			fmt.Printf("tmout %s\n", arg)
112		}
113		return time.Duration(secs) * time.Second, true
114	case "wait":
115		deadline := time.Now().Add(timeout)
116		for {
117			if _, err := os.Stat(arg); err == nil {
118				if !quiet {
119					fmt.Printf("wait %s\n", arg)
120				}
121				return timeout, true
122			}
123			if time.Now().After(deadline) {
124				die(fmt.Sprintf("wait %s: timeout after %d seconds", arg, int(timeout/time.Second)-1))
125			}
126			time.Sleep(100 * time.Millisecond)
127		}
128	case "sleep":
129		secs, err := strconv.Atoi(arg)
130		if err != nil {
131			die(fmt.Sprintf("sleep %s: %v", arg, err))
132		}
133		time.Sleep(time.Duration(secs) * time.Second)
134		if !quiet {
135			fmt.Printf("sleep %s\n", arg)
136		}
137	case "term":
138		pid, err := strconv.Atoi(arg)
139		if err != nil {
140			die(fmt.Sprintf("term %s: %v", arg, err))
141		}
142		if !quiet {
143			fmt.Printf("term %s\n", arg)
144		}
145		proc, err := os.FindProcess(pid)
146		if err != nil {
147			die(fmt.Sprintf("term %s: %v", arg, err))
148		}
149		if err := proc.Signal(syscall.SIGTERM); err != nil {
150			die(fmt.Sprintf("term %s: %v", arg, err))
151		}
152	case "fail":
153		code, err := strconv.Atoi(arg)
154		if err != nil {
155			die(fmt.Sprintf("fail %s: %v", arg, err))
156		}
157		if !quiet {
158			fmt.Printf("fail %s\n", arg)
159		}
160		os.Exit(code)
161	default:
162		return timeout, false
163	}
164	return timeout, true
165}
166
167func die(message string) {
168	fmt.Fprintln(os.Stderr, filepath.ToSlash(message))
169	os.Exit(1)
170}