Skip to content

Commit 45fba77

Browse files
committed
Run goleak tests on replica set and sharded. Run change streams. Add comments.
1 parent e339231 commit 45fba77

File tree

2 files changed

+54
-23
lines changed

2 files changed

+54
-23
lines changed

.evergreen/config.yml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,8 @@ tasks:
14311431
- func: bootstrap-mongo-orchestration
14321432
- func: run-docker-test
14331433

1434-
- name: test-goroutine-leaks
1434+
- name: test-goroutine-leaks-replicaset
1435+
tags: ["goleak"]
14351436
commands:
14361437
- func: bootstrap-mongo-orchestration
14371438
vars:
@@ -1440,6 +1441,16 @@ tasks:
14401441
SSL: "nossl"
14411442
- func: run-goleak-test
14421443

1444+
- name: test-goroutine-leaks-sharded
1445+
tags: ["goleak"]
1446+
commands:
1447+
- func: bootstrap-mongo-orchestration
1448+
vars:
1449+
TOPOLOGY: "sharded_cluster"
1450+
AUTH: "noauth"
1451+
SSL: "nossl"
1452+
- func: run-goleak-test
1453+
14431454
- name: test-load-balancer-noauth-nossl
14441455
tags: ["load-balancer"]
14451456
commands:
@@ -2567,7 +2578,7 @@ buildvariants:
25672578
expansions:
25682579
GO_DIST: "/opt/golang/go1.22"
25692580
tasks:
2570-
- name: "test-goroutine-leaks"
2581+
- name: ".goleak"
25712582

25722583
- matrix_name: "tests-rhel-36-with-zlib-support"
25732584
tags: ["pullrequest"]

internal/test/goleak/goleak_test.go

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,77 +22,97 @@ import (
2222

2323
var dbName = fmt.Sprintf("goleak-%d", time.Now().Unix())
2424

25-
func TestMain(m *testing.M) {
26-
goleak.VerifyTestMain(m)
27-
}
28-
2925
// TestGoroutineLeak creates clients with various client configurations, runs
3026
// some operations with each one, then disconnects the client. It asserts that
3127
// no goroutines were leaked after the client is disconnected.
3228
func TestGoroutineLeak(t *testing.T) {
33-
uri := "mongodb://localhost:27017"
34-
if u := os.Getenv("MONGODB_URI"); u != "" {
35-
uri = u
36-
}
37-
3829
testCases := []struct {
3930
desc string
4031
opts *options.ClientOptions
4132
}{
4233
{
4334
desc: "base",
44-
opts: options.Client().ApplyURI(uri),
35+
opts: options.Client(),
4536
},
4637
{
4738
desc: "compressors=snappy",
48-
opts: options.Client().ApplyURI(uri).SetCompressors([]string{"snappy"}),
39+
opts: options.Client().SetCompressors([]string{"snappy"}),
4940
},
5041
{
5142
desc: "compressors=zlib",
52-
opts: options.Client().ApplyURI(uri).SetCompressors([]string{"zlib"}),
43+
opts: options.Client().SetCompressors([]string{"zlib"}),
5344
},
5445
{
5546
desc: "compressors=zstd",
56-
opts: options.Client().ApplyURI(uri).SetCompressors([]string{"zstd"}),
47+
opts: options.Client().SetCompressors([]string{"zstd"}),
5748
},
5849
{
5950
desc: "minPoolSize=10",
60-
opts: options.Client().ApplyURI(uri).SetMinPoolSize(10),
51+
opts: options.Client().SetMinPoolSize(10),
6152
},
6253
{
6354
desc: "serverMonitoringMode=poll",
64-
opts: options.Client().ApplyURI(uri).SetServerMonitoringMode(options.ServerMonitoringModePoll),
55+
opts: options.Client().SetServerMonitoringMode(options.ServerMonitoringModePoll),
6556
},
6657
}
58+
6759
for _, tc := range testCases {
6860
// These can't be run in parallel because goleak currently can't filter
6961
// out goroutines from other parallel subtests.
7062
t.Run(tc.desc, func(t *testing.T) {
7163
defer goleak.VerifyNone(t)
7264

73-
client, err := mongo.Connect(context.Background(), tc.opts)
65+
base := options.Client()
66+
if u := os.Getenv("MONGODB_URI"); u != "" {
67+
base.ApplyURI(u)
68+
}
69+
client, err := mongo.Connect(context.Background(), base, tc.opts)
7470
require.NoError(t, err)
7571

7672
defer func() {
7773
err = client.Disconnect(context.Background())
7874
require.NoError(t, err)
7975
}()
8076

81-
coll := client.Database(dbName).Collection(collectionName(t))
77+
db := client.Database(dbName)
8278
defer func() {
83-
err := coll.Drop(context.Background())
79+
err := db.Drop(context.Background())
8480
require.NoError(t, err)
8581
}()
8682

87-
_, err = coll.InsertOne(context.Background(), bson.M{"x": 123})
83+
coll := db.Collection(collectionName(t))
84+
85+
// Start a change stream to simulate a change listener workload.
86+
cs, err := coll.Watch(context.Background(), mongo.Pipeline{})
8887
require.NoError(t, err)
88+
defer cs.Close(context.Background())
89+
90+
// Run some Insert and FindOne operations to simulate a writing and
91+
// reading workload. Run 50 iterations to increase the probability
92+
// that a goroutine leak will happen if a problem exists.
93+
for i := 0; i < 50; i++ {
94+
_, err = coll.InsertOne(context.Background(), bson.M{"x": 123})
95+
require.NoError(t, err)
8996

90-
for i := 0; i < 20; i++ {
9197
var res bson.D
9298
err = coll.FindOne(context.Background(), bson.D{}).Decode(&res)
9399
require.NoError(t, err)
94-
time.Sleep(50 * time.Millisecond)
95100
}
101+
102+
// Intentionally cause some timeouts. Ignore any errors.
103+
for i := 0; i < 50; i++ {
104+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Microsecond)
105+
coll.FindOne(ctx, bson.D{}).Err()
106+
cancel()
107+
}
108+
109+
// Finish simulating the change listener workload. Use "Next" to
110+
// fetch at least one change stream document batch and decode the
111+
// first document.
112+
cs.Next(context.Background())
113+
var res bson.D
114+
err = cs.Decode(&res)
115+
require.NoError(t, err)
96116
})
97117
}
98118
}

0 commit comments

Comments
 (0)