Skip to content

Commit e51b43f

Browse files
author
Divjot Arora
authored
GODRIVER-526 Unskip keys in command monitoring assertions (#482)
1 parent 9958c4b commit e51b43f

File tree

6 files changed

+101
-52
lines changed

6 files changed

+101
-52
lines changed

mongo/collection.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ func (coll *Collection) insert(ctx context.Context, documents []interface{},
279279
Session(sess).WriteConcern(wc).CommandMonitor(coll.client.monitor).
280280
ServerSelector(selector).ClusterClock(coll.client.clock).
281281
Database(coll.db.name).Collection(coll.name).
282-
Deployment(coll.client.deployment).Crypt(coll.client.crypt)
282+
Deployment(coll.client.deployment).Crypt(coll.client.crypt).Ordered(true)
283283
imo := options.MergeInsertManyOptions(opts...)
284284
if imo.BypassDocumentValidation != nil && *imo.BypassDocumentValidation {
285285
op = op.BypassDocumentValidation(*imo.BypassDocumentValidation)
@@ -454,7 +454,7 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn
454454
Session(sess).WriteConcern(wc).CommandMonitor(coll.client.monitor).
455455
ServerSelector(selector).ClusterClock(coll.client.clock).
456456
Database(coll.db.name).Collection(coll.name).
457-
Deployment(coll.client.deployment).Crypt(coll.client.crypt)
457+
Deployment(coll.client.deployment).Crypt(coll.client.crypt).Ordered(true)
458458
if do.Hint != nil {
459459
op = op.Hint(true)
460460
}
@@ -551,7 +551,7 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc
551551
ServerSelector(selector).ClusterClock(coll.client.clock).
552552
Database(coll.db.name).Collection(coll.name).
553553
Deployment(coll.client.deployment).Crypt(coll.client.crypt).Hint(uo.Hint != nil).
554-
ArrayFilters(uo.ArrayFilters != nil)
554+
ArrayFilters(uo.ArrayFilters != nil).Ordered(true)
555555

556556
if uo.BypassDocumentValidation != nil && *uo.BypassDocumentValidation {
557557
op = op.BypassDocumentValidation(*uo.BypassDocumentValidation)

mongo/database.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@ func (db *Database) ListCollections(ctx context.Context, filter interface{}, opt
363363
if lco.NameOnly != nil {
364364
op = op.NameOnly(*lco.NameOnly)
365365
}
366+
if lco.BatchSize != nil {
367+
op = op.BatchSize(*lco.BatchSize)
368+
}
369+
366370
retry := driver.RetryNone
367371
if db.client.retryReads {
368372
retry = driver.RetryOncePerCommand

mongo/integration/cmd_monitoring_helpers_test.go

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,26 +253,21 @@ func compareStartedEvent(mt *mtest.T, expectation *expectation, id0, id1 bson.Ra
253253
key := elem.Key()
254254
val := elem.Value()
255255

256-
actualVal := evt.Command.Lookup(key)
256+
actualVal, err := evt.Command.LookupErr(key)
257257

258258
// Keys that may be nil
259259
if val.Type == bson.TypeNull {
260-
if actualVal.Type != 0 || len(actualVal.Value) > 0 {
261-
return fmt.Errorf("expected value for key %s to be nil but got %s", key, actualVal)
262-
}
263-
continue
264-
}
265-
if key == "ordered" || key == "cursor" || key == "batchSize" {
266-
// TODO: some tests specify that "ordered" must be a key in the event but ordered isn't a valid option for
267-
// some of these cases (e.g. insertOne)
268-
// TODO: some FLE tests specify "cursor" subdocument for listCollections
269-
// TODO: find.json cmd monitoring tests expect different batch sizes for find/getMore commands based on an
270-
// optional limit
260+
assert.NotNil(mt, err, "expected key %q to be omitted but got %q", key, actualVal)
271261
continue
272262
}
263+
assert.Nil(mt, err, "expected command to contain key %q", key)
273264

274-
if err = actualVal.Validate(); err != nil {
275-
return fmt.Errorf("error validatinmg value for key %s: %s", key, err)
265+
if key == "batchSize" {
266+
// Some command monitoring tests expect that the driver will send a lower batch size if the required batch
267+
// size is lower than the operation limit. We only do this for legacy servers <= 3.0 because those server
268+
// versions do not support the limit option, but not for 3.2+. We've already validated that the command
269+
// contains a batchSize field above and we can skip the actual value comparison below.
270+
continue
276271
}
277272

278273
switch key {

mongo/integration/database_test.go

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -137,45 +137,66 @@ func TestDatabase(t *testing.T) {
137137
})
138138

139139
mt.RunOpts("list collections", noClientOpts, func(mt *mtest.T) {
140-
testCases := []struct {
141-
name string
142-
expectedTopology mtest.TopologyKind
143-
cappedOnly bool
144-
}{
145-
{"standalone no filter", mtest.Single, false},
146-
{"standalone filter", mtest.Single, true},
147-
{"replica set no filter", mtest.ReplicaSet, false},
148-
{"replica set filter", mtest.ReplicaSet, true},
149-
{"sharded no filter", mtest.Sharded, false},
150-
{"sharded filter", mtest.Sharded, true},
151-
}
152-
for _, tc := range testCases {
153-
tcOpts := mtest.NewOptions().Topologies(tc.expectedTopology)
154-
mt.RunOpts(tc.name, tcOpts, func(mt *mtest.T) {
155-
mt.CreateCollection(mtest.Collection{Name: listCollUncapped}, true)
156-
mt.CreateCollection(mtest.Collection{
157-
Name: listCollCapped,
158-
CreateOpts: bson.D{{"capped", true}, {"size", 64 * 1024}},
159-
}, true)
140+
mt.RunOpts("verify results", noClientOpts, func(mt *mtest.T) {
141+
testCases := []struct {
142+
name string
143+
expectedTopology mtest.TopologyKind
144+
cappedOnly bool
145+
}{
146+
{"standalone no filter", mtest.Single, false},
147+
{"standalone filter", mtest.Single, true},
148+
{"replica set no filter", mtest.ReplicaSet, false},
149+
{"replica set filter", mtest.ReplicaSet, true},
150+
{"sharded no filter", mtest.Sharded, false},
151+
{"sharded filter", mtest.Sharded, true},
152+
}
153+
for _, tc := range testCases {
154+
tcOpts := mtest.NewOptions().Topologies(tc.expectedTopology)
155+
mt.RunOpts(tc.name, tcOpts, func(mt *mtest.T) {
156+
mt.CreateCollection(mtest.Collection{Name: listCollUncapped}, true)
157+
mt.CreateCollection(mtest.Collection{
158+
Name: listCollCapped,
159+
CreateOpts: bson.D{{"capped", true}, {"size", 64 * 1024}},
160+
}, true)
160161

161-
filter := bson.D{}
162-
if tc.cappedOnly {
163-
filter = bson.D{{"options.capped", true}}
164-
}
162+
filter := bson.D{}
163+
if tc.cappedOnly {
164+
filter = bson.D{{"options.capped", true}}
165+
}
165166

166-
var err error
167-
for i := 0; i < 1; i++ {
168-
cursor, err := mt.DB.ListCollections(mtest.Background, filter)
169-
assert.Nil(mt, err, "ListCollections error (iteration %v): %v", i, err)
167+
var err error
168+
for i := 0; i < 1; i++ {
169+
cursor, err := mt.DB.ListCollections(mtest.Background, filter)
170+
assert.Nil(mt, err, "ListCollections error (iteration %v): %v", i, err)
170171

171-
err = verifyListCollections(cursor, tc.cappedOnly)
172-
if err == nil {
173-
return
172+
err = verifyListCollections(cursor, tc.cappedOnly)
173+
if err == nil {
174+
return
175+
}
174176
}
175-
}
176-
mt.Fatalf("error verifying list collections result: %v", err)
177-
})
178-
}
177+
mt.Fatalf("error verifying list collections result: %v", err)
178+
})
179+
}
180+
})
181+
mt.RunOpts("batch size", mtest.NewOptions().MinServerVersion("3.0"), func(mt *mtest.T) {
182+
// Create two new collections so there will be three total.
183+
for i := 0; i < 2; i++ {
184+
mt.CreateCollection(mtest.Collection{
185+
Name: fmt.Sprintf("list-collections-batchSize-%d", i),
186+
}, true)
187+
}
188+
189+
mt.ClearEvents()
190+
lcOpts := options.ListCollections().SetBatchSize(2)
191+
_, err := mt.DB.ListCollectionNames(mtest.Background, bson.D{}, lcOpts)
192+
assert.Nil(mt, err, "ListCollectionNames error: %v", err)
193+
194+
evt := mt.GetStartedEvent()
195+
assert.Equal(mt, "listCollections", evt.CommandName, "expected 'listCollections' command to be sent, got %q",
196+
evt.CommandName)
197+
_, err = evt.Command.LookupErr("cursor", "batchSize")
198+
assert.Nil(mt, err, "expected command %s to contain key 'batchSize'", evt.Command)
199+
})
179200
})
180201

181202
mt.RunOpts("list collection specifications", noClientOpts, func(mt *mtest.T) {

mongo/options/listcollectionsoptions.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ package options
1010
type ListCollectionsOptions struct {
1111
// If true, each collection document will only contain a field for the collection name. The default value is false.
1212
NameOnly *bool
13+
14+
// The maximum number of documents to be included in each batch returned by the server.
15+
BatchSize *int32
1316
}
1417

1518
// ListCollections creates a new ListCollectionsOptions instance.
@@ -23,6 +26,12 @@ func (lc *ListCollectionsOptions) SetNameOnly(b bool) *ListCollectionsOptions {
2326
return lc
2427
}
2528

29+
// SetBatchSize sets the value for the BatchSize field.
30+
func (lc *ListCollectionsOptions) SetBatchSize(size int32) *ListCollectionsOptions {
31+
lc.BatchSize = &size
32+
return lc
33+
}
34+
2635
// MergeListCollectionsOptions combines the given ListCollectionsOptions instances into a single *ListCollectionsOptions
2736
// in a last-one-wins fashion.
2837
func MergeListCollectionsOptions(opts ...*ListCollectionsOptions) *ListCollectionsOptions {
@@ -34,6 +43,9 @@ func MergeListCollectionsOptions(opts ...*ListCollectionsOptions) *ListCollectio
3443
if opt.NameOnly != nil {
3544
lc.NameOnly = opt.NameOnly
3645
}
46+
if opt.BatchSize != nil {
47+
lc.BatchSize = opt.BatchSize
48+
}
3749
}
3850

3951
return lc

x/mongo/driver/operation/list_collections.go

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)