Skip to content

Commit ba93be3

Browse files
Add TimeoutWithinContext to mongoutil
1 parent 0317669 commit ba93be3

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

internal/mongoutil/mongoutil.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
package mongoutil
88

99
import (
10+
"context"
1011
"reflect"
12+
"time"
1113

1214
"go.mongodb.org/mongo-driver/v2/mongo/options"
1315
)
@@ -83,3 +85,17 @@ func HostsFromURI(uri string) ([]string, error) {
8385

8486
return opts.Hosts, nil
8587
}
88+
89+
// TimeoutWithinContext will return true if the provided timeout is nil or if
90+
// it is less than the context deadline. If the context does not have a
91+
// deadline, it will return true.
92+
func TimeoutWithinContext(ctx context.Context, timeout time.Duration) bool {
93+
deadline, ok := ctx.Deadline()
94+
if !ok {
95+
return true
96+
}
97+
98+
ctxTimeout := time.Until(deadline)
99+
100+
return ctxTimeout <= 0 || timeout < ctxTimeout
101+
}

internal/mongoutil/mongoutil_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77
package mongoutil
88

99
import (
10+
"context"
1011
"strings"
1112
"testing"
13+
"time"
1214

15+
"go.mongodb.org/mongo-driver/v2/internal/assert"
16+
"go.mongodb.org/mongo-driver/v2/internal/ptrutil"
1317
"go.mongodb.org/mongo-driver/v2/mongo/options"
1418
)
1519

@@ -32,3 +36,71 @@ func BenchmarkNewOptions(b *testing.B) {
3236
}
3337
})
3438
}
39+
40+
func TestValidChangeStreamTimeouts(t *testing.T) {
41+
tests := []struct {
42+
name string
43+
ctxTimeout *time.Duration
44+
timeout time.Duration
45+
wantTimeout time.Duration
46+
want bool
47+
}{
48+
{
49+
name: "Timeout shorter than context deadline",
50+
ctxTimeout: ptrutil.Ptr(10 * time.Second),
51+
timeout: 1 * time.Second,
52+
want: true,
53+
},
54+
{
55+
name: "Timeout equal to context deadline",
56+
ctxTimeout: ptrutil.Ptr(1 * time.Second),
57+
timeout: 1 * time.Second,
58+
want: false,
59+
},
60+
{
61+
name: "Timeout greater than context deadline",
62+
ctxTimeout: ptrutil.Ptr(1 * time.Second),
63+
timeout: 10 * time.Second,
64+
want: false,
65+
},
66+
{
67+
name: "Context deadline already expired",
68+
ctxTimeout: ptrutil.Ptr(-1 * time.Second),
69+
timeout: 1 * time.Second,
70+
want: true, // *timeout <= 0 branch in code
71+
},
72+
{
73+
name: "Timeout is zero, context deadline in future",
74+
ctxTimeout: ptrutil.Ptr(10 * time.Second),
75+
timeout: 0 * time.Second,
76+
want: true,
77+
},
78+
{
79+
name: "Timeout is negative, context deadline in future",
80+
ctxTimeout: ptrutil.Ptr(10 * time.Second),
81+
timeout: -1 * time.Second,
82+
want: true,
83+
},
84+
{
85+
name: "Timeout provided, context has no deadline",
86+
ctxTimeout: nil,
87+
timeout: 1 * time.Second,
88+
want: true,
89+
},
90+
}
91+
92+
for _, test := range tests {
93+
t.Run(test.name, func(t *testing.T) {
94+
ctx := context.Background()
95+
if test.ctxTimeout != nil {
96+
var cancel context.CancelFunc
97+
98+
ctx, cancel = context.WithTimeout(ctx, *test.ctxTimeout)
99+
defer cancel()
100+
}
101+
102+
got := TimeoutWithinContext(ctx, test.timeout)
103+
assert.Equal(t, test.want, got)
104+
})
105+
}
106+
}

0 commit comments

Comments
 (0)