package windows import ( "context" "errors" "testing" "time" ) type fakePIDHandle struct { exited bool waitErr error closed bool } func (handle *fakePIDHandle) Wait(time.Duration) (bool, error) { return handle.exited, handle.waitErr } func (handle *fakePIDHandle) Close() error { handle.closed = true; return nil } func TestWaitForProcessExitReturnsOnlyWhenHandleSignals(t *testing.T) { handle := &fakePIDHandle{exited: true} err := waitForProcessExit(context.Background(), 9, time.Second, func(pid int) (pidWaitHandle, error) { if pid != 9 { t.Fatalf("PID = %d, want 9", pid) } return handle, nil }) if err != nil || !handle.closed { t.Fatalf("wait error = %v, closed = %v", err, handle.closed) } } func TestWaitForProcessExitPropagatesOpenWaitCancelAndTimeout(t *testing.T) { openErr := errors.New("access denied") if err := waitForProcessExit(context.Background(), 3, time.Second, func(int) (pidWaitHandle, error) { return nil, openErr }); !errors.Is(err, openErr) { t.Fatalf("open error = %v", err) } waitErr := errors.New("wait failed") if err := waitForProcessExit(context.Background(), 3, time.Second, func(int) (pidWaitHandle, error) { return &fakePIDHandle{waitErr: waitErr}, nil }); !errors.Is(err, waitErr) { t.Fatalf("wait error = %v", err) } ctx, cancel := context.WithCancel(context.Background()) cancel() if err := waitForProcessExit(ctx, 3, time.Second, func(int) (pidWaitHandle, error) { return &fakePIDHandle{}, nil }); !errors.Is(err, context.Canceled) { t.Fatalf("cancel error = %v", err) } if err := waitForProcessExit(context.Background(), 3, time.Millisecond, func(int) (pidWaitHandle, error) { return &fakePIDHandle{}, nil }); !errors.Is(err, context.DeadlineExceeded) { t.Fatalf("timeout error = %v", err) } }