1package capture
2
3import (
4 "context"
5 "os"
6 "testing"
7 "time"
8
9 "github.com/bnema/neferwl/internal/ports"
10 "golang.org/x/sys/unix"
11)
12
13func TestFailClosesBeforeReplyAndUsesMonotonic(t *testing.T) {
14 f, err := os.CreateTemp(t.TempDir(), "capture")
15 if err != nil {
16 t.Fatal(err)
17 }
18 replies := make(chan ports.CaptureDone, 1)
19 Fail(context.Background(), ports.CaptureRequest{Dst: ports.SHMBuffer{File: f}}, nil, replies)
20 done := <-replies
21 if _, err := f.Stat(); err == nil {
22 t.Fatal("fd open at reply")
23 }
24 var now unix.Timespec
25 if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &now); err != nil {
26 t.Fatal(err)
27 }
28 if d := time.Unix(now.Sec, now.Nsec).Sub(done.Time); d < 0 || d > time.Second {
29 t.Fatalf("non-monotonic capture time: %v", d)
30 }
31}
32
33func TestFailCancelledStillDeliversReadyReply(t *testing.T) {
34 ctx, cancel := context.WithCancel(context.Background())
35 cancel()
36 replies := make(chan ports.CaptureDone, 1)
37 for id := range uint64(100) {
38 f, err := os.CreateTemp(t.TempDir(), "capture")
39 if err != nil {
40 t.Fatal(err)
41 }
42 Fail(ctx, ports.CaptureRequest{ID: id, Dst: ports.SHMBuffer{File: f}}, nil, replies)
43 select {
44 case result := <-replies:
45 if result.ID != id {
46 t.Fatalf("reply ID %d, want %d", result.ID, id)
47 }
48 default:
49 t.Fatal("cancelled output lost ready completion")
50 }
51 if _, err := f.Stat(); err == nil {
52 t.Fatal("descriptor open at reply")
53 }
54 }
55}
56
57func TestFailCancelledWithFullReplies(t *testing.T) {
58 ctx, cancel := context.WithCancel(context.Background())
59 cancel()
60 replies := make(chan ports.CaptureDone, 1)
61 replies <- ports.CaptureDone{}
62 f, err := os.CreateTemp(t.TempDir(), "capture")
63 if err != nil {
64 t.Fatal(err)
65 }
66 done := make(chan struct{})
67 go func() { Fail(ctx, ports.CaptureRequest{Dst: ports.SHMBuffer{File: f}}, nil, replies); close(done) }()
68 select {
69 case <-done:
70 case <-time.After(2 * time.Second):
71 t.Fatal("blocked")
72 }
73 if _, err := f.Stat(); err == nil {
74 t.Fatal("fd still open")
75 }
76}