Default harness runs to unbounded and make the stream page reconnect itself
This commit is contained in:
+15
-6
@@ -1,6 +1,6 @@
|
|||||||
// Runs cabletest for a fixed time, dumps the panel to png, and streams it as
|
// Runs cabletest until interrupted or for -for, dumps the panel to png, and
|
||||||
// png deltas on :8080, since the machine with the display on it is not the
|
// streams it as png deltas on :8080, since the machine with the display on it
|
||||||
// machine looking at it.
|
// is not the machine looking at it.
|
||||||
//
|
//
|
||||||
// sudo go run ./harness -for 20s -at 3s,15s -- -a enp1s0f0np0 -b enp1s0f1np1
|
// sudo go run ./harness -for 20s -at 3s,15s -- -a enp1s0f0np0 -b enp1s0f1np1
|
||||||
package main
|
package main
|
||||||
@@ -35,7 +35,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runFor := flag.Duration("for", 15*time.Second, "how long to let cabletest run")
|
runFor := flag.Duration("for", 0, "how long to let cabletest run; 0 runs until interrupted")
|
||||||
at := flag.String("at", "", "offsets to capture the panel at, comma separated, e.g. 3s,10s")
|
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")
|
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()
|
flag.Parse()
|
||||||
@@ -49,6 +49,11 @@ func main() {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
if *fuzzN > 0 {
|
if *fuzzN > 0 {
|
||||||
|
if *runFor <= 0 {
|
||||||
|
restoreTerm()
|
||||||
|
fmt.Fprintln(os.Stderr, "fuzz needs a bounded -for")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
err = fuzz(*fuzzN, *runFor, flag.Args())
|
err = fuzz(*fuzzN, *runFor, flag.Args())
|
||||||
} else {
|
} else {
|
||||||
err = run(*runFor, *at, os.Stdout, flag.Args())
|
err = run(*runFor, *at, os.Stdout, flag.Args())
|
||||||
@@ -122,7 +127,7 @@ func parseShots(s string, runFor time.Duration) ([]time.Duration, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("bad offset %q: %w", f, err)
|
return nil, fmt.Errorf("bad offset %q: %w", f, err)
|
||||||
}
|
}
|
||||||
if d < 0 || d >= runFor {
|
if d < 0 || (runFor > 0 && d >= runFor) {
|
||||||
return nil, fmt.Errorf("offset %s falls outside the %s run", d, runFor)
|
return nil, fmt.Errorf("offset %s falls outside the %s run", d, runFor)
|
||||||
}
|
}
|
||||||
out = append(out, d)
|
out = append(out, d)
|
||||||
@@ -189,12 +194,16 @@ func run(runFor time.Duration, at string, out io.Writer, args []string) error {
|
|||||||
fmt.Printf("captured %s\n", name)
|
fmt.Printf("captured %s\n", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expire <-chan time.Time
|
||||||
|
if runFor > 0 {
|
||||||
|
expire = time.After(time.Until(start.Add(runFor)))
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case err := <-done:
|
case err := <-done:
|
||||||
return exited(start, err)
|
return exited(start, err)
|
||||||
case <-sigs:
|
case <-sigs:
|
||||||
return interrupted(start, pgid, done)
|
return interrupted(start, pgid, done)
|
||||||
case <-time.After(time.Until(start.Add(runFor))):
|
case <-expire:
|
||||||
}
|
}
|
||||||
return stop(pgid, done)
|
return stop(pgid, done)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-16
@@ -24,23 +24,31 @@ const page = `<!doctype html>
|
|||||||
<script>
|
<script>
|
||||||
(async () => {
|
(async () => {
|
||||||
const cv = document.querySelector('canvas'), g = cv.getContext('2d');
|
const cv = document.querySelector('canvas'), g = cv.getContext('2d');
|
||||||
const rd = (await fetch('frames')).body.getReader();
|
|
||||||
let buf = new Uint8Array(0);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const {value, done} = await rd.read();
|
try {
|
||||||
if (done) return;
|
const res = await fetch('frames');
|
||||||
const b = new Uint8Array(buf.length + value.length);
|
if (res.ok) {
|
||||||
b.set(buf); b.set(value, buf.length); buf = b;
|
const rd = res.body.getReader();
|
||||||
for (;;) {
|
let buf = new Uint8Array(0);
|
||||||
if (buf.length < 12) break;
|
for (;;) {
|
||||||
const dv = new DataView(buf.buffer, buf.byteOffset);
|
const {value, done} = await rd.read();
|
||||||
const x = dv.getUint32(0, true), y = dv.getUint32(4, true), n = dv.getUint32(8, true);
|
if (done) break;
|
||||||
if (buf.length < 12 + n) break;
|
const b = new Uint8Array(buf.length + value.length);
|
||||||
const bmp = await createImageBitmap(new Blob([buf.slice(12, 12 + n)], {type: 'image/png'}));
|
b.set(buf); b.set(value, buf.length); buf = b;
|
||||||
if (x === 0 && y === 0 && cv.width !== bmp.width) { cv.width = bmp.width; cv.height = bmp.height; }
|
for (;;) {
|
||||||
g.drawImage(bmp, x, y);
|
if (buf.length < 12) break;
|
||||||
buf = buf.slice(12 + n);
|
const dv = new DataView(buf.buffer, buf.byteOffset);
|
||||||
}
|
const x = dv.getUint32(0, true), y = dv.getUint32(4, true), n = dv.getUint32(8, true);
|
||||||
|
if (buf.length < 12 + n) break;
|
||||||
|
const bmp = await createImageBitmap(new Blob([buf.slice(12, 12 + n)], {type: 'image/png'}));
|
||||||
|
if (x === 0 && y === 0 && cv.width !== bmp.width) { cv.width = bmp.width; cv.height = bmp.height; }
|
||||||
|
g.drawImage(bmp, x, y);
|
||||||
|
buf = buf.slice(12 + n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
await new Promise(r => setTimeout(r, 1000));
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user