Skip to content

Commit 73be5a7

Browse files
committed
tests: add test to compare ctx canceled errors
Add test TestComparableCanceledContextErrors checking comparabily. Refactored and satisfied review. Fixes (#457)
1 parent dc57834 commit 73be5a7

File tree

5 files changed

+44
-21
lines changed

5 files changed

+44
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1515
### Changed
1616

1717
- Required Go version is `1.24` now (#456).
18-
- Now `connection.newFuture()` in case `<-ctx.Done()` returns wrapped error
19-
provided by `ctx.Cause()`. Allows you compare it using `errors.Is/As` (#457).
18+
- Now cases of `<-ctx.Done()` returns wrapped error provided by `ctx.Cause()`.
19+
Allows you compare it using `errors.Is/As` (#457).
2020

2121
### Fixed
2222

connection.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ func (conn *Connection) newFuture(req Request) (fut *Future) {
984984
if ctx != nil {
985985
select {
986986
case <-ctx.Done():
987-
fut.SetError(fmt.Errorf("context is done (request ID %d) (%w)",
987+
fut.SetError(fmt.Errorf("context is done (request ID %d): %w",
988988
fut.requestId, context.Cause(ctx)))
989989
shard.rmut.Unlock()
990990
return
@@ -1027,7 +1027,8 @@ func (conn *Connection) contextWatchdog(fut *Future, ctx context.Context) {
10271027
case <-fut.done:
10281028
return
10291029
default:
1030-
conn.cancelFuture(fut, fmt.Errorf("context is done (request ID %d)", fut.requestId))
1030+
conn.cancelFuture(fut, fmt.Errorf("context is done (request ID %d): %w",
1031+
fut.requestId, context.Cause(ctx)))
10311032
}
10321033
}
10331034

errors.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type ClientError struct {
3131

3232
// Error converts a ClientError to a string.
3333
func (clierr ClientError) Error() string {
34-
return fmt.Sprintf("%s (%#x)", clierr.Msg, clierr.Code)
34+
return fmt.Sprintf("%s (0x%x)", clierr.Msg, clierr.Code)
3535
}
3636

3737
// Temporary returns true if next attempt to perform request may succeeded.
@@ -54,12 +54,11 @@ func (clierr ClientError) Temporary() bool {
5454

5555
// Tarantool client error codes.
5656
const (
57-
ErrConnectionNotReady uint32 = 0x4000 + iota
58-
ErrConnectionClosed
59-
ErrProtocolError
60-
ErrTimeouted
61-
ErrRateLimited
62-
ErrConnectionShutdown
63-
ErrIoError
64-
ErrCancelledCtx
57+
ErrConnectionNotReady = 0x4000 + iota
58+
ErrConnectionClosed = 0x4000 + iota
59+
ErrProtocolError = 0x4000 + iota
60+
ErrTimeouted = 0x4000 + iota
61+
ErrRateLimited = 0x4000 + iota
62+
ErrConnectionShutdown = 0x4000 + iota
63+
ErrIoError = 0x4000 + iota
6564
)

example_test.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package tarantool_test
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"net"
87
"regexp"
@@ -166,11 +165,9 @@ func ExamplePingRequest_Context() {
166165
data, err := conn.Do(req).Get()
167166
fmt.Println("Ping Resp data", data)
168167
fmt.Println("Ping Error", regexp.MustCompile("[0-9]+").ReplaceAllString(err.Error(), "N"))
169-
fmt.Println(errors.Is(err, context.DeadlineExceeded))
170168
// Output:
171169
// Ping Resp data []
172-
// Ping Error context is done (request ID N) (context deadline exceeded)
173-
// true
170+
// Ping Error context is done (request ID N): context deadline exceeded
174171
}
175172

176173
func ExampleSelectRequest() {

tarantool_test.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type Member struct {
5050
}
5151

5252
var contextDoneErrRegexp = regexp.MustCompile(
53-
fmt.Sprintf(`^context is done \(request ID [0-9]+\) \(%s\)$`, "context canceled"))
53+
`^context is done \(request ID [0-9]+\): context canceled$`)
5454

5555
func (m *Member) EncodeMsgpack(e *msgpack.Encoder) error {
5656
if err := e.EncodeArrayLen(2); err != nil {
@@ -2739,13 +2739,40 @@ func TestClientRequestObjectsWithPassedCanceledContext(t *testing.T) {
27392739
if !contextDoneErrRegexp.Match([]byte(err.Error())) {
27402740
t.Fatalf("Failed to catch an error from done context")
27412741
}
2742-
// Checking that we could use errors.Is to get known about error.
2743-
require.True(t, errors.Is(err, context.Canceled))
27442742
if resp != nil {
27452743
t.Fatalf("Response is not nil after the occurred error")
27462744
}
27472745
}
27482746

2747+
func TestComparableCanceledContextErrors(t *testing.T) {
2748+
conn := test_helpers.ConnectWithValidation(t, dialer, opts)
2749+
defer conn.Close()
2750+
2751+
// Checking comparable with simple context.WithCancel.
2752+
ctx, cancel := context.WithCancel(context.Background())
2753+
req := NewPingRequest().Context(ctx)
2754+
cancel()
2755+
_, err := conn.Do(req).Get()
2756+
require.True(t, errors.Is(err, context.Canceled), err.Error())
2757+
2758+
// Checking comparable with simple context.WithTimeout.
2759+
timeout := time.Nanosecond
2760+
ctx, cancel = context.WithTimeout(context.Background(), timeout)
2761+
req = NewPingRequest().Context(ctx)
2762+
defer cancel()
2763+
_, err = conn.Do(req).Get()
2764+
require.True(t, errors.Is(err, context.DeadlineExceeded), err.Error())
2765+
2766+
// Checking comparable with context.WithCancelCause.
2767+
// Shows ability to compare with custom errors (also with ClientError).
2768+
ctxCause, cancelCause := context.WithCancelCause(context.Background())
2769+
req = NewPingRequest().Context(ctxCause)
2770+
cancelCause(ClientError{ErrConnectionClosed, "something went wrong"})
2771+
_, err = conn.Do(req).Get()
2772+
var tmpErr ClientError
2773+
require.True(t, errors.As(err, &tmpErr), tmpErr.Error())
2774+
}
2775+
27492776
// waitCtxRequest waits for the WaitGroup in Body() call and returns
27502777
// the context from Ctx() call. The request helps us to make sure that
27512778
// the context's cancel() call is called before a response received.
@@ -3302,7 +3329,6 @@ func TestClientIdRequestObjectWithPassedCanceledContext(t *testing.T) {
33023329
resp, err := conn.Do(req).Get()
33033330
require.Nilf(t, resp, "Response is empty")
33043331
require.NotNilf(t, err, "Error is not empty")
3305-
require.True(t, errors.Is(err, context.Canceled))
33063332
require.Regexp(t, contextDoneErrRegexp, err.Error())
33073333
}
33083334

0 commit comments

Comments
 (0)