Re-lock the mailbox window on lost phase instead of anchoring blind: one loop goroutine per module owns all transport, windows edge-locked from first touch, bringup verifies both modules before either AN restart; corrected charges and link-down reads print raw registers; harness -fuzz repeats lifecycles judging by exit status (30/30 module-clean)
This commit is contained in:
+44
-3
@@ -5,9 +5,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"image/png"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -20,19 +22,58 @@ import (
|
||||
const (
|
||||
shotsDir = "shots"
|
||||
grace = 3 * time.Second
|
||||
// The framebuffer's DRM master can outlive the process group by a moment;
|
||||
// an immediate next run finds the device busy.
|
||||
fuzzGap = 2 * time.Second
|
||||
)
|
||||
|
||||
func main() {
|
||||
runFor := flag.Duration("for", 15*time.Second, "how long to let cabletest run")
|
||||
at := flag.String("at", "", "offsets to capture the panel at, comma separated, e.g. 3s,10s")
|
||||
fuzzN := flag.Int("fuzz", 0, "repeat the whole lifecycle this many times; full output only for runs that fail or log module events")
|
||||
flag.Parse()
|
||||
|
||||
if err := run(*runFor, *at, flag.Args()); err != nil {
|
||||
var err error
|
||||
if *fuzzN > 0 {
|
||||
err = fuzz(*fuzzN, *runFor, flag.Args())
|
||||
} else {
|
||||
err = run(*runFor, *at, os.Stdout, flag.Args())
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func fuzz(n int, runFor time.Duration, args []string) error {
|
||||
failed := 0
|
||||
for i := 1; i <= n; i++ {
|
||||
if i > 1 {
|
||||
time.Sleep(fuzzGap)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
start := time.Now()
|
||||
err := run(runFor, "", &buf, args)
|
||||
dur := time.Since(start).Round(100 * time.Millisecond)
|
||||
if err != nil {
|
||||
failed++
|
||||
name := fmt.Sprintf("fuzz-run%02d.log", i)
|
||||
if werr := os.WriteFile(name, buf.Bytes(), 0o644); werr != nil {
|
||||
name = fmt.Sprintf("unsaved: %v", werr)
|
||||
}
|
||||
fmt.Printf("run %02d/%02d: FAILED (%s): %v [%s]\n", i, n, dur, err, name)
|
||||
os.Stdout.Write(buf.Bytes())
|
||||
continue
|
||||
}
|
||||
fmt.Printf("run %02d/%02d: ok (%s)\n", i, n, dur)
|
||||
}
|
||||
fmt.Printf("fuzz: %d/%d ok, %d failed\n", n-failed, n, failed)
|
||||
if failed > 0 {
|
||||
return fmt.Errorf("%d/%d runs failed", failed, n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseShots(s string, runFor time.Duration) ([]time.Duration, error) {
|
||||
if s == "" {
|
||||
return nil, nil
|
||||
@@ -52,7 +93,7 @@ func parseShots(s string, runFor time.Duration) ([]time.Duration, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func run(runFor time.Duration, at string, args []string) error {
|
||||
func run(runFor time.Duration, at string, out io.Writer, args []string) error {
|
||||
if os.Geteuid() != 0 {
|
||||
return fmt.Errorf("needs root for the raw sockets and the framebuffer: sudo go run ./harness")
|
||||
}
|
||||
@@ -67,7 +108,7 @@ func run(runFor time.Duration, at string, args []string) error {
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", append([]string{"run", "."}, args...)...)
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
cmd.Stdout, cmd.Stderr = out, out
|
||||
// Its own process group: go run's compiled child is reparented rather than
|
||||
// killed when go run dies, and an orphan holding the wire poisons every
|
||||
// measurement after it.
|
||||
|
||||
Reference in New Issue
Block a user