Skip to content

Commit

Permalink
feat(runtimex): add the TryN functions (#1047)
Browse files Browse the repository at this point in the history
These functions are syntactic sugar to wrote runtimex.PanicOnError
code more compactly. This change is made possible by generics.

Part of ooni/probe#2401
  • Loading branch information
bassosimone authored Jan 25, 2023
1 parent 7008845 commit c4fc1fc
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
23 changes: 23 additions & 0 deletions internal/runtimex/runtimex.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
99 changes: 99 additions & 0 deletions internal/runtimex/runtimex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
})
})
}

0 comments on commit c4fc1fc

Please sign in to comment.