package signals import ( "context" "fmt" "os" "syscall" "testing" "time" ) func ExampleWithSignals() { ctx := WithSignals(context.Background(), syscall.SIGUSR1) go func() { time.Sleep(500 * time.Millisecond) // after some time SIGUSR1 is sent // mimicking a signal from the outside syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) }() <-ctx.Done() fmt.Println("finished") // Output: // finished } func Example_withUnregisteredSignals() { dctx, cancel := context.WithTimeout(context.TODO(), time.Millisecond*100) defer cancel() ctx := WithSignals(dctx, syscall.SIGUSR1) go func() { time.Sleep(10 * time.Millisecond) // after some time SIGUSR2 is sent // mimicking a signal from the outside, WithSignals will not handle it syscall.Kill(syscall.Getpid(), syscall.SIGUSR2) }() <-ctx.Done() fmt.Println("finished") // Output: // finished } func TestWithSignals(t *testing.T) { tests := []struct { name string ctx context.Context sigs []os.Signal wantSignal bool }{ { name: "sending signal SIGUSR2 should exit context.", ctx: context.Background(), sigs: []os.Signal{syscall.SIGUSR2}, wantSignal: true, }, { name: "sending signal SIGUSR2 should NOT exit context.", ctx: context.Background(), sigs: []os.Signal{syscall.SIGUSR1}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx := WithSignals(tt.ctx, tt.sigs...) syscall.Kill(syscall.Getpid(), syscall.SIGUSR2) timer := time.NewTimer(500 * time.Millisecond) select { case <-ctx.Done(): if !tt.wantSignal { t.Errorf("unexpected exit with signal") } case <-timer.C: if tt.wantSignal { t.Errorf("expected to exit with signal but did not") } } }) } }