package executor import ( "errors" "sync/atomic" "testing") type lifecycleRecorder struct { closeFn func() error} func (r *lifecycleRecorder) Bind(closeFn func() error) error { r.closeFn = closeFn return nil} func (*lifecycleRecorder) End(string) {} type lifecycleCloser struct { calls atomic.Int32} func (c *lifecycleCloser) Close() error { c.calls.Add(1) return nil} func TestBindExecutionResourceClosesResourceOnce(t *testing.T) { lifecycle := &lifecycleRecorder{} closer := &lifecycleCloser{} if errBind := BindExecutionResource(Options{ExecutionLifecycle: lifecycle}, closer); errBind != nil { t.Fatalf("BindExecutionResource() error = %v", errBind) } if lifecycle.closeFn == nil { t.Fatal("BindExecutionResource() did not bind a closer") } if errClose := lifecycle.closeFn(); errClose != nil { t.Fatalf("first close error = %v", errClose) } if errClose := lifecycle.closeFn(); errClose != nil { t.Fatalf("second close error = %v", errClose) } if got := closer.calls.Load(); got != 1 { t.Fatalf("closer calls = %d, want 1", got) }} func TestBindExecutionResourceClosesWhenBindFails(t *testing.T) { want := errors.New("selection ended") lifecycle := &failingLifecycle{err: want} closer := &lifecycleCloser{} errBind := BindExecutionResource(Options{ExecutionLifecycle: lifecycle}, closer) if !errors.Is(errBind, want) { t.Fatalf("BindExecutionResource() error = %v, want %v", errBind, want) } if got := closer.calls.Load(); got != 1 { t.Fatalf("closer calls = %d, want 1", got) }} type failingLifecycle struct { err error} func (l *failingLifecycle) Bind(func() error) error { return l.err }func (*failingLifecycle) End(string) {}
package executor
import (
"errors"
"sync/atomic"
"testing"
)
type lifecycleRecorder struct {
closeFn func() error
}
func (r *lifecycleRecorder) Bind(closeFn func() error) error {
r.closeFn = closeFn
return nil
}
func (*lifecycleRecorder) End(string) {}
type lifecycleCloser struct {
calls atomic.Int32
}
func (c *lifecycleCloser) Close() error {
c.calls.Add(1)
return nil
}
func TestBindExecutionResourceClosesResourceOnce(t *testing.T) {
lifecycle := &lifecycleRecorder{}
closer := &lifecycleCloser{}
if errBind := BindExecutionResource(Options{ExecutionLifecycle: lifecycle}, closer); errBind != nil {
t.Fatalf("BindExecutionResource() error = %v", errBind)
}
if lifecycle.closeFn == nil {
t.Fatal("BindExecutionResource() did not bind a closer")
}
if errClose := lifecycle.closeFn(); errClose != nil {
t.Fatalf("first close error = %v", errClose)
}
if errClose := lifecycle.closeFn(); errClose != nil {
t.Fatalf("second close error = %v", errClose)
}
if got := closer.calls.Load(); got != 1 {
t.Fatalf("closer calls = %d, want 1", got)
}
}
func TestBindExecutionResourceClosesWhenBindFails(t *testing.T) {
want := errors.New("selection ended")
lifecycle := &failingLifecycle{err: want}
closer := &lifecycleCloser{}
errBind := BindExecutionResource(Options{ExecutionLifecycle: lifecycle}, closer)
if !errors.Is(errBind, want) {
t.Fatalf("BindExecutionResource() error = %v, want %v", errBind, want)
}
if got := closer.calls.Load(); got != 1 {
t.Fatalf("closer calls = %d, want 1", got)
}
}
type failingLifecycle struct {
err error
}
func (l *failingLifecycle) Bind(func() error) error { return l.err }
func (*failingLifecycle) End(string) {}