From 09374b3ba249d187e2520b5f0f90a19a0845efc9 Mon Sep 17 00:00:00 2001 From: kucherenkovova Date: Sat, 4 Jan 2025 13:15:08 +0200 Subject: [PATCH] [xerrors] implement `IsTimeout` helper function (#7) --- go.work | 3 ++- xerrors/errors.go | 21 +++++++++++++++++++++ xerrors/errors_test.go | 35 +++++++++++++++++++++++++++++++++++ xerrors/go.mod | 3 +++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 xerrors/errors.go create mode 100644 xerrors/errors_test.go create mode 100644 xerrors/go.mod diff --git a/go.work b/go.work index f646d06..a9e9551 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,7 @@ -go 1.22.2 +go 1.23.4 use ( + ./xerrors ./xmaps ./xmath ./xnet/xhttp diff --git a/xerrors/errors.go b/xerrors/errors.go new file mode 100644 index 0000000..8b0b4a9 --- /dev/null +++ b/xerrors/errors.go @@ -0,0 +1,21 @@ +package xerrors + +import ( + "errors" +) + +// IsTimeout reports whether the provided error indicates a timeout condition. +func IsTimeout(err error) bool { + if err == nil { + return false + } + + e, ok := err.(interface{ Timeout() bool }) + if ok && e.Timeout() { + return true + } + + inner := errors.Unwrap(err) + + return inner != nil && IsTimeout(inner) +} diff --git a/xerrors/errors_test.go b/xerrors/errors_test.go new file mode 100644 index 0000000..f63edb2 --- /dev/null +++ b/xerrors/errors_test.go @@ -0,0 +1,35 @@ +package xerrors_test + +import ( + "context" + "fmt" + "testing" + + "github.com/kucherenkovova/gopypaste/xerrors" +) + +type customTimeoutError struct{} + +func (e customTimeoutError) Error() string { return "timeout" } + +func (e customTimeoutError) Timeout() bool { return true } + +func TestIsTimeout(t *testing.T) { + tests := []struct { + name string + err error + want bool + }{ + {name: "nil", err: nil, want: false}, + {name: "context timeout", err: context.DeadlineExceeded, want: true}, + {name: "wrapped context timeout", err: fmt.Errorf("bad stuff: %w", context.DeadlineExceeded), want: true}, + {name: "custom timeout", err: customTimeoutError{}, want: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := xerrors.IsTimeout(tt.err); got != tt.want { + t.Errorf("IsTimeout() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/xerrors/go.mod b/xerrors/go.mod new file mode 100644 index 0000000..619d9b8 --- /dev/null +++ b/xerrors/go.mod @@ -0,0 +1,3 @@ +module github.com/kucherenkovova/gopypaste/xerrors + +go 1.23.4