7
7
package topology
8
8
9
9
import (
10
- "github.com/stretchr/testify/require "
10
+ "reflect "
11
11
"sync/atomic"
12
12
"testing"
13
13
"time"
14
+
15
+ "github.com/google/go-cmp/cmp"
16
+ "go.mongodb.org/mongo-driver/internal/testutil/assert"
14
17
)
15
18
19
+ // rsrc is a mock resource used in resource pool tests.
20
+ // This type should not be used other test files.
16
21
type rsrc struct {
17
22
closed bool
18
23
}
@@ -35,8 +40,9 @@ func neverExpired(_ interface{}) bool {
35
40
36
41
// expiredCounter is used to implement an expiredFunc that will return true a fixed number of times.
37
42
type expiredCounter struct {
38
- total , expiredCalled , closeCalled int32
39
- closeChan chan struct {}
43
+ expiredCalled , closeCalled int32 // must be loaded/stored using atomic.*Int32 functions
44
+ total int32
45
+ closeChan chan struct {}
40
46
}
41
47
42
48
func newExpiredCounter (total int32 ) expiredCounter {
@@ -48,17 +54,27 @@ func newExpiredCounter(total int32) expiredCounter {
48
54
49
55
func (ec * expiredCounter ) expired (_ interface {}) bool {
50
56
atomic .AddInt32 (& ec .expiredCalled , 1 )
51
- return ec .expiredCalled <= ec .total
57
+ return ec .getExpiredCalled () <= ec .total
52
58
}
53
59
54
60
func (ec * expiredCounter ) close (_ interface {}) {
55
61
atomic .AddInt32 (& ec .closeCalled , 1 )
56
- if ec .closeCalled == ec .total {
62
+ if ec .getCloseCalled () == ec .total {
57
63
ec .closeChan <- struct {}{}
58
64
}
59
65
}
60
66
67
+ func (ec * expiredCounter ) getExpiredCalled () int32 {
68
+ return atomic .LoadInt32 (& ec .expiredCalled )
69
+ }
70
+
71
+ func (ec * expiredCounter ) getCloseCalled () int32 {
72
+ return atomic .LoadInt32 (& ec .closeCalled )
73
+ }
74
+
61
75
func initPool (t * testing.T , minSize uint64 , expFn expiredFunc , closeFn closeFunc , initFn initFunc , pruneInterval time.Duration ) * resourcePool {
76
+ t .Helper ()
77
+
62
78
rpc := resourcePoolConfig {
63
79
MinSize : minSize ,
64
80
MaintainInterval : pruneInterval ,
@@ -67,70 +83,60 @@ func initPool(t *testing.T, minSize uint64, expFn expiredFunc, closeFn closeFunc
67
83
InitFn : initFn ,
68
84
}
69
85
rp , err := newResourcePool (rpc )
70
- require . NoError (t , err , "error creating new resource pool" )
86
+ assert . Nil (t , err , "error creating new resource pool: %v" , err )
71
87
rp .initialize ()
72
88
rp .maintainTimer .Reset (rp .maintainInterval )
73
89
return rp
74
90
}
75
91
76
92
func TestResourcePool (t * testing.T ) {
93
+ // register a cmp equality function for the rsrc type that will do a pointer comparison
94
+ assert .RegisterOpts (reflect .TypeOf (& rsrc {}), cmp .Comparer (func (r1 , r2 * rsrc ) bool {
95
+ return r1 == r2
96
+ }))
97
+
77
98
t .Run ("get" , func (t * testing.T ) {
78
99
t .Run ("remove stale resources" , func (t * testing.T ) {
79
100
ec := newExpiredCounter (5 )
80
101
rp := initPool (t , 1 , ec .expired , ec .close , initRsrc , time .Minute )
81
102
rp .maintainTimer .Stop ()
82
103
83
- if got := rp .Get (); got != nil {
84
- t .Fatalf ("resource mismatch; expected nil, got %v" , got )
85
- }
86
- if rp .size != 0 {
87
- t .Fatalf ("length mismatch; expected 0, got %d" , rp .size )
88
- }
89
- if ec .expiredCalled != 1 {
90
- t .Fatalf ("incorrect number of expire checks, expected 1, got %v" , ec .expiredCalled )
91
- }
92
- if ec .closeCalled != 1 {
93
- t .Fatalf ("incorrect number of closes called, expected 1, got %v" , ec .closeCalled )
94
- }
104
+ got := rp .Get ()
105
+ assert .Nil (t , got , "expected nil, got %v" , got )
106
+ assert .Equal (t , uint64 (0 ), rp .size , "expected size 0, got %d" , rp .size )
107
+
108
+ expiredCalled := ec .getExpiredCalled ()
109
+ assert .Equal (t , int32 (1 ), expiredCalled , "expected expire to be called 1 time, got %v" , expiredCalled )
110
+ closeCalled := ec .getCloseCalled ()
111
+ assert .Equal (t , int32 (1 ), closeCalled , "expected close to be called 1 time, got %v" , closeCalled )
95
112
})
96
113
t .Run ("recycle resources" , func (t * testing.T ) {
97
114
rp := initPool (t , 1 , neverExpired , closeRsrc , initRsrc , time .Minute )
98
115
rp .maintainTimer .Stop ()
99
116
for i := 0 ; i < 5 ; i ++ {
100
117
got := rp .Get ()
101
- if got == nil {
102
- t .Fatalf ("resource mismatch; expected a resource but got nil" )
103
- }
104
- if rp .size != 0 {
105
- t .Fatalf ("length mismatch; expected 0, got %d" , rp .size )
106
- }
118
+ assert .NotNil (t , got , "expected resource, got nil" )
119
+ assert .Equal (t , uint64 (0 ), rp .size , "expected size 0, got %v" , rp .size )
120
+
107
121
rp .Put (got )
108
- if rp .size != 1 {
109
- t .Fatalf ("length mismatch; expected 1, got %d" , rp .size )
110
- }
122
+ assert .Equal (t , uint64 (1 ), rp .size , "expected size 1, got %v" , rp .size )
111
123
}
112
124
})
113
125
})
114
126
t .Run ("Put" , func (t * testing.T ) {
115
127
t .Run ("returned resources are returned to front of pool" , func (t * testing.T ) {
116
128
rp := initPool (t , 0 , neverExpired , closeRsrc , initRsrc , time .Minute )
117
129
ret := & rsrc {}
118
- if ! rp .Put (ret ) {
119
- t .Fatal ("return value mismatch; expected true, got false" )
120
- }
121
- if rp .size != 1 {
122
- t .Fatalf ("length mismatch; expected 1, got %d" , rp .size )
123
- }
124
- if headVal := rp .Get (); headVal != ret {
125
- t .Fatalf ("resource mismatch; expected %v at head of pool, got %v" , ret , headVal )
126
- }
130
+ assert .True (t , rp .Put (ret ), "expected Put to return true, got false" )
131
+ assert .Equal (t , uint64 (1 ), rp .size , "expected size 1, got %v" , rp .size )
132
+
133
+ headVal := rp .Get ()
134
+ assert .Equal (t , ret , headVal , "expected resource %v at head of pool, got %v" , ret , headVal )
127
135
})
128
136
t .Run ("stale resource not returned" , func (t * testing.T ) {
129
137
rp := initPool (t , 1 , alwaysExpired , closeRsrc , initRsrc , time .Minute )
130
138
ret := & rsrc {}
131
- if rp .Put (ret ) {
132
- t .Fatal ("return value mismatch; expected false, got true" )
133
- }
139
+ assert .False (t , rp .Put (ret ), "expected Put to return false, got true" )
134
140
})
135
141
})
136
142
t .Run ("Prune" , func (t * testing.T ) {
@@ -141,16 +147,14 @@ func TestResourcePool(t *testing.T) {
141
147
ret := & rsrc {}
142
148
_ = rp .Put (ret )
143
149
}
150
+
144
151
rp .Maintain ()
145
- if rp .size != 2 {
146
- t .Fatalf ("length mismatch; expected 2, got %d" , rp .size )
147
- }
148
- if ec .expiredCalled != 7 {
149
- t .Fatalf ("count mismatch; expected ec.stale to be called 7 times, got %v" , ec .expiredCalled )
150
- }
151
- if ec .closeCalled != 3 {
152
- t .Fatalf ("count mismatch; expected ex.closeConnection to be called 3 times, got %v" , ec .closeCalled )
153
- }
152
+ assert .Equal (t , uint64 (2 ), rp .size , "expected size 2, got %v" , rp .size )
153
+
154
+ expiredCalled := ec .getExpiredCalled ()
155
+ assert .Equal (t , int32 (7 ), expiredCalled , "expected expire to be called 7 times, got %v" , expiredCalled )
156
+ closeCalled := ec .getCloseCalled ()
157
+ assert .Equal (t , int32 (3 ), closeCalled , "expected close to be called 3 times, got %v" , closeCalled )
154
158
})
155
159
})
156
160
t .Run ("Background cleanup" , func (t * testing.T ) {
@@ -174,12 +178,10 @@ func TestResourcePool(t *testing.T) {
174
178
t .Fatalf ("value was not read on closeChan after 5 seconds" )
175
179
}
176
180
177
- if atomic .LoadInt32 (& ec .expiredCalled ) != 5 {
178
- t .Fatalf ("count mismatch; expected ec.stale to be called 5 times, got %v" , ec .expiredCalled )
179
- }
180
- if atomic .LoadInt32 (& ec .closeCalled ) != 3 {
181
- t .Fatalf ("count mismatch; expected ec.closeConnection to be called 5 times, got %v" , ec .closeCalled )
182
- }
181
+ expiredCalled := ec .getExpiredCalled ()
182
+ assert .Equal (t , int32 (5 ), expiredCalled , "expected expire to be called 5 times, got %v" , expiredCalled )
183
+ closeCalled := ec .getCloseCalled ()
184
+ assert .Equal (t , int32 (3 ), closeCalled , "expected close to be called 3 times, got %v" , closeCalled )
183
185
})
184
186
})
185
187
}
0 commit comments