diff --git a/internal/runtimex/runtimex.go b/internal/runtimex/runtimex.go index 29e3c80832..334bc6728f 100644 --- a/internal/runtimex/runtimex.go +++ b/internal/runtimex/runtimex.go @@ -86,3 +86,26 @@ func PanicIfTrue(assertion bool, message string) { func PanicIfNil(v any, message string) { PanicIfTrue(v == nil, message) } + +// Try0 calls [runtimex.PanicOnError] if err is not nil. +func Try0(err error) { + PanicOnError(err, "Try0") +} + +// Try1 is like [Try0] but supports functions returning one values and an error. +func Try1[T1 any](v1 T1, err error) T1 { + PanicOnError(err, "Try1") + return v1 +} + +// Try2 is like [Try1] but supports functions returning two values and an error. +func Try2[T1, T2 any](v1 T1, v2 T2, err error) (T1, T2) { + PanicOnError(err, "Try2") + return v1, v2 +} + +// Try3 is like [Try2] but supports functions returning three values and an error. +func Try3[T1, T2, T3 any](v1 T1, v2 T2, v3 T3, err error) (T1, T2, T3) { + PanicOnError(err, "Try3") + return v1, v2, v3 +} diff --git a/internal/runtimex/runtimex_test.go b/internal/runtimex/runtimex_test.go index ee0c56eebc..edfc0b3cef 100644 --- a/internal/runtimex/runtimex_test.go +++ b/internal/runtimex/runtimex_test.go @@ -146,3 +146,102 @@ func TestBuildInfoRecord_setall(t *testing.T) { }) } } + +func TestTry(t *testing.T) { + t.Run("Try0", func(t *testing.T) { + t.Run("on success", func(t *testing.T) { + Try0(nil) + }) + + t.Run("on failure", func(t *testing.T) { + expected := errors.New("mocked error") + var got error + func() { + defer func() { + if r := recover(); r != nil { + got = r.(error) + } + }() + Try0(expected) + }() + if !errors.Is(got, expected) { + t.Fatal("unexpected error") + } + }) + }) + + t.Run("Try1", func(t *testing.T) { + t.Run("on success", func(t *testing.T) { + v1 := Try1(17, nil) + if v1 != 17 { + t.Fatal("unexpected value") + } + }) + + t.Run("on failure", func(t *testing.T) { + expected := errors.New("mocked error") + var got error + func() { + defer func() { + if r := recover(); r != nil { + got = r.(error) + } + }() + Try1(17, expected) + }() + if !errors.Is(got, expected) { + t.Fatal("unexpected error") + } + }) + }) + + t.Run("Try2", func(t *testing.T) { + t.Run("on success", func(t *testing.T) { + v1, v2 := Try2(17, true, nil) + if v1 != 17 || !v2 { + t.Fatal("unexpected value") + } + }) + + t.Run("on failure", func(t *testing.T) { + expected := errors.New("mocked error") + var got error + func() { + defer func() { + if r := recover(); r != nil { + got = r.(error) + } + }() + Try2(17, true, expected) + }() + if !errors.Is(got, expected) { + t.Fatal("unexpected error") + } + }) + }) + + t.Run("Try3", func(t *testing.T) { + t.Run("on success", func(t *testing.T) { + v1, v2, v3 := Try3(17, true, 44.0, nil) + if v1 != 17 || !v2 || v3 != 44.0 { + t.Fatal("unexpected value") + } + }) + + t.Run("on failure", func(t *testing.T) { + expected := errors.New("mocked error") + var got error + func() { + defer func() { + if r := recover(); r != nil { + got = r.(error) + } + }() + Try3(17, true, 44.0, expected) + }() + if !errors.Is(got, expected) { + t.Fatal("unexpected error") + } + }) + }) +}