1
2
3
4
5
6
7 package integration
8
9 import (
10 "context"
11 "errors"
12 "testing"
13 "time"
14
15 "github.com/google/go-cmp/cmp"
16 "go.mongodb.org/mongo-driver/bson"
17 "go.mongodb.org/mongo-driver/internal/assert"
18 "go.mongodb.org/mongo-driver/mongo"
19 "go.mongodb.org/mongo-driver/mongo/integration/mtest"
20 "go.mongodb.org/mongo-driver/mongo/options"
21 "go.mongodb.org/mongo-driver/mongo/writeconcern"
22 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
23 )
24
25 type index struct {
26 Key bson.D
27 Name string
28 }
29
30 func TestIndexView(t *testing.T) {
31 mt := mtest.New(t, noClientOpts)
32
33 var pbool = func(b bool) *bool { return &b }
34 var pint32 = func(i int32) *int32 { return &i }
35
36 mt.Run("list", func(mt *mtest.T) {
37 createIndexes := func(mt *mtest.T, numIndexes int) {
38 mt.Helper()
39
40 models := make([]mongo.IndexModel, 0, numIndexes)
41 for i, key := 0, 'a'; i < numIndexes; i, key = i+1, key+1 {
42 models = append(models, mongo.IndexModel{
43 Keys: bson.M{string(key): 1},
44 })
45 }
46
47 _, err := mt.Coll.Indexes().CreateMany(context.Background(), models)
48 assert.Nil(mt, err, "CreateMany error: %v", err)
49 }
50
51
52
53 cmdName := "listIndexes"
54 if mtest.CompareServerVersions(mtest.ServerVersion(), "3.0") < 0 {
55 cmdName = "find"
56 }
57
58 mt.Run("_id index is always listed", func(mt *mtest.T) {
59 verifyIndexExists(mt, mt.Coll.Indexes(), index{
60 Key: bson.D{{"_id", int32(1)}},
61 Name: "_id_",
62 })
63 })
64 mt.Run("getMore commands are monitored", func(mt *mtest.T) {
65 createIndexes(mt, 2)
66 assertGetMoreCommandsAreMonitored(mt, cmdName, func() (*mongo.Cursor, error) {
67 return mt.Coll.Indexes().List(context.Background(), options.ListIndexes().SetBatchSize(2))
68 })
69 })
70 mt.Run("killCursors commands are monitored", func(mt *mtest.T) {
71 createIndexes(mt, 2)
72 assertKillCursorsCommandsAreMonitored(mt, cmdName, func() (*mongo.Cursor, error) {
73 return mt.Coll.Indexes().List(context.Background(), options.ListIndexes().SetBatchSize(2))
74 })
75 })
76 })
77 mt.RunOpts("create one", noClientOpts, func(mt *mtest.T) {
78 mt.Run("name not specified", func(mt *mtest.T) {
79 iv := mt.Coll.Indexes()
80 keysDoc := bson.D{
81 {"foo", int32(1)},
82 {"bar", int32(-1)},
83 }
84 expectedName := "foo_1_bar_-1"
85
86 indexName, err := iv.CreateOne(context.Background(), mongo.IndexModel{
87 Keys: keysDoc,
88 })
89 assert.Nil(mt, err, "CreateOne error: %v", err)
90 assert.Equal(mt, expectedName, indexName, "expected name %q, got %q", expectedName, indexName)
91
92 verifyIndexExists(mt, iv, index{
93 Key: keysDoc,
94 Name: indexName,
95 })
96 })
97 mt.Run("specify name", func(mt *mtest.T) {
98 iv := mt.Coll.Indexes()
99 keysDoc := bson.D{{"foo", int32(-1)}}
100 name := "testname"
101
102 indexName, err := iv.CreateOne(context.Background(), mongo.IndexModel{
103 Keys: keysDoc,
104 Options: options.Index().SetName(name),
105 })
106 assert.Nil(mt, err, "CreateOne error: %v", err)
107 assert.Equal(mt, name, indexName, "expected returned name %q, got %q", name, indexName)
108
109 verifyIndexExists(mt, iv, index{
110 Key: keysDoc,
111 Name: indexName,
112 })
113 })
114 mt.Run("all options", func(mt *mtest.T) {
115 opts := options.Index().
116 SetBackground(false).
117 SetExpireAfterSeconds(10).
118 SetName("a").
119 SetSparse(false).
120 SetUnique(false).
121 SetVersion(1).
122 SetDefaultLanguage("english").
123 SetLanguageOverride("english").
124 SetTextVersion(1).
125 SetWeights(bson.D{}).
126 SetSphereVersion(1).
127 SetBits(2).
128 SetMax(10).
129 SetMin(1).
130 SetPartialFilterExpression(bson.D{}).
131 SetStorageEngine(bson.D{
132 {"wiredTiger", bson.D{
133 {"configString", "block_compressor=zlib"},
134 }},
135 })
136
137
138 if mtest.CompareServerVersions(mtest.ServerVersion(), "4.9") < 0 {
139 opts.SetBucketSize(1)
140 }
141
142 _, err := mt.Coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
143 Keys: bson.D{{"foo", "text"}},
144 Options: opts,
145 })
146 assert.Nil(mt, err, "CreateOne error: %v", err)
147 })
148 mt.RunOpts("collation", mtest.NewOptions().MinServerVersion("3.4"), func(mt *mtest.T) {
149
150 _, err := mt.Coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
151 Keys: bson.D{{"bar", "text"}},
152 Options: options.Index().SetCollation(&options.Collation{
153 Locale: "simple",
154 }),
155 })
156 assert.Nil(mt, err, "CreateOne error: %v", err)
157 })
158 mt.RunOpts("wildcard", mtest.NewOptions().MinServerVersion("4.1").CreateClient(false), func(mt *mtest.T) {
159 keysDoc := bson.D{{"$**", int32(1)}}
160
161 mt.Run("no options", func(mt *mtest.T) {
162 iv := mt.Coll.Indexes()
163 indexName, err := iv.CreateOne(context.Background(), mongo.IndexModel{
164 Keys: keysDoc,
165 })
166 assert.Nil(mt, err, "CreateOne error: %v", err)
167 verifyIndexExists(mt, iv, index{
168 Key: keysDoc,
169 Name: indexName,
170 })
171 })
172 mt.Run("wildcard projection", func(mt *mtest.T) {
173 iv := mt.Coll.Indexes()
174
175
176
177
178
179 proj := bson.D{{"a", true}, {"_id", false}}
180 _, err := iv.CreateOne(context.Background(), mongo.IndexModel{
181 Keys: keysDoc,
182 Options: options.Index().SetWildcardProjection(proj),
183 })
184 assert.Nil(mt, err, "CreateOne error: %v", err)
185
186 indexDoc := getIndexDoc(mt, iv, keysDoc)
187 assert.NotNil(mt, indexDoc, "expected to find keys document %v but was not found", keysDoc)
188 checkIndexDocContains(mt, indexDoc, bson.E{
189 Key: "wildcardProjection",
190 Value: proj,
191 })
192 })
193 })
194 mt.RunOpts("hidden", mtest.NewOptions().MinServerVersion("4.4"), func(mt *mtest.T) {
195 iv := mt.Coll.Indexes()
196 keysDoc := bson.D{{"x", int32(1)}}
197 model := mongo.IndexModel{
198 Keys: keysDoc,
199 Options: options.Index().SetHidden(true),
200 }
201
202 _, err := iv.CreateOne(context.Background(), model)
203 assert.Nil(mt, err, "CreateOne error: %v", err)
204
205 indexDoc := getIndexDoc(mt, iv, keysDoc)
206 assert.NotNil(mt, indexDoc, "index with keys document %v was not found", keysDoc)
207 checkIndexDocContains(mt, indexDoc, bson.E{
208 Key: "hidden",
209 Value: true,
210 })
211 })
212 mt.Run("nil keys", func(mt *mtest.T) {
213 _, err := mt.Coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
214 Keys: nil,
215 })
216 assert.NotNil(mt, err, "expected CreateOne error, got nil")
217 })
218
219 mt.RunOpts("commit quorum", mtest.NewOptions().Topologies(mtest.ReplicaSet).CreateClient(false), func(mt *mtest.T) {
220 intVal := options.CreateIndexes().SetCommitQuorumInt(1)
221 stringVal := options.CreateIndexes().SetCommitQuorumString("majority")
222 majority := options.CreateIndexes().SetCommitQuorumMajority()
223 votingMembers := options.CreateIndexes().SetCommitQuorumVotingMembers()
224
225 indexModel := mongo.IndexModel{
226 Keys: bson.D{{"x", 1}},
227 }
228
229 testCases := []struct {
230 name string
231 opts *options.CreateIndexesOptions
232 expectError bool
233 expectedValue interface{}
234 minServerVersion string
235 maxServerVersion string
236 }{
237 {"error on server versions before 4.4", majority, true, nil, "", "4.2"},
238 {"integer value", intVal, false, int32(1), "4.4", ""},
239 {"string value", stringVal, false, "majority", "4.4", ""},
240 {"majority", majority, false, "majority", "4.4", ""},
241 {"votingMembers", votingMembers, false, "votingMembers", "4.4", ""},
242 }
243 for _, tc := range testCases {
244 mtOpts := mtest.NewOptions().MinServerVersion(tc.minServerVersion).MaxServerVersion(tc.maxServerVersion)
245 mt.RunOpts(tc.name, mtOpts, func(mt *mtest.T) {
246 mt.ClearEvents()
247 _, err := mt.Coll.Indexes().CreateOne(context.Background(), indexModel, tc.opts)
248 if tc.expectError {
249 assert.NotNil(mt, err, "expected CreateOne error, got nil")
250 return
251 }
252
253 assert.Nil(mt, err, "CreateOne error: %v", err)
254 cmd := mt.GetStartedEvent().Command
255 sentBSONValue, err := cmd.LookupErr("commitQuorum")
256 assert.Nil(mt, err, "expected commitQuorum in command %s", cmd)
257
258 var sentValue interface{}
259 err = sentBSONValue.Unmarshal(&sentValue)
260 assert.Nil(mt, err, "Unmarshal error: %v", err)
261
262 assert.Equal(mt, tc.expectedValue, sentValue, "expected commitQuorum value %v, got %v",
263 tc.expectedValue, sentValue)
264 })
265 }
266 })
267 unackClientOpts := options.Client().
268 SetWriteConcern(writeconcern.New(writeconcern.W(0)))
269 unackMtOpts := mtest.NewOptions().
270 ClientOptions(unackClientOpts).
271 MinServerVersion("3.6")
272 mt.RunOpts("unacknowledged write", unackMtOpts, func(mt *mtest.T) {
273 _, err := mt.Coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{Keys: bson.D{{"x", 1}}})
274 if !errors.Is(err, mongo.ErrUnacknowledgedWrite) {
275
276
277 mt.Fatalf("expected CreateOne error %v, got %v", mongo.ErrUnacknowledgedWrite, err)
278 }
279 })
280
281 mt.RunOpts("replace error", mtest.NewOptions().Topologies(mtest.ReplicaSet).MinServerVersion("4.0"), func(mt *mtest.T) {
282 mt.SetFailPoint(mtest.FailPoint{
283 ConfigureFailPoint: "failCommand",
284 Mode: "alwaysOn",
285 Data: mtest.FailPointData{
286 FailCommands: []string{"createIndexes"},
287 ErrorCode: 100,
288 },
289 })
290
291 _, err := mt.Coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{Keys: bson.D{{"x", 1}}})
292 assert.NotNil(mt, err, "expected CreateOne error, got nil")
293 cmdErr, ok := err.(mongo.CommandError)
294 assert.True(mt, ok, "expected mongo.CommandError, got %T", err)
295 assert.Equal(mt, int32(100), cmdErr.Code, "expected error code 100, got %v", cmdErr.Code)
296
297 })
298 mt.Run("multi-key map", func(mt *mtest.T) {
299 iv := mt.Coll.Indexes()
300
301 _, err := iv.CreateOne(context.Background(), mongo.IndexModel{
302 Keys: bson.M{"foo": 1, "bar": -1},
303 })
304 assert.NotNil(mt, err, "expected CreateOne error, got nil")
305 assert.Equal(mt, mongo.ErrMapForOrderedArgument{"keys"}, err, "expected error %v, got %v", mongo.ErrMapForOrderedArgument{"key"}, err)
306 })
307 mt.Run("single key map", func(mt *mtest.T) {
308 iv := mt.Coll.Indexes()
309 expectedName := "foo_1"
310
311 indexName, err := iv.CreateOne(context.Background(), mongo.IndexModel{
312 Keys: bson.M{"foo": 1},
313 })
314 assert.Nil(mt, err, "CreateOne error: %v", err)
315 assert.Equal(mt, expectedName, indexName, "expected name %q, got %q", expectedName, indexName)
316
317 verifyIndexExists(mt, iv, index{
318 Key: bson.D{{"foo", int32(1)}},
319 Name: indexName,
320 })
321 })
322 })
323 mt.Run("create many", func(mt *mtest.T) {
324 mt.Run("success", func(mt *mtest.T) {
325 iv := mt.Coll.Indexes()
326 firstKeysDoc := bson.D{{"foo", int32(-1)}}
327 secondKeysDoc := bson.D{{"bar", int32(1)}, {"baz", int32(-1)}}
328 expectedNames := []string{"foo_-1", "bar_1_baz_-1"}
329 indexNames, err := iv.CreateMany(context.Background(), []mongo.IndexModel{
330 {
331 Keys: firstKeysDoc,
332 },
333 {
334 Keys: secondKeysDoc,
335 },
336 })
337 assert.Nil(mt, err, "CreateMany error: %v", err)
338 assert.Equal(mt, expectedNames, indexNames, "expected returned names %v, got %v", expectedNames, indexNames)
339
340 verifyIndexExists(mt, iv, index{
341 Key: firstKeysDoc,
342 Name: indexNames[0],
343 })
344 verifyIndexExists(mt, iv, index{
345 Key: secondKeysDoc,
346 Name: indexNames[1],
347 })
348 })
349 wc := writeconcern.New(writeconcern.W(1))
350 wcMtOpts := mtest.NewOptions().CollectionOptions(options.Collection().SetWriteConcern(wc))
351 mt.RunOpts("uses writeconcern", wcMtOpts, func(mt *mtest.T) {
352 iv := mt.Coll.Indexes()
353 _, err := iv.CreateMany(context.Background(), []mongo.IndexModel{
354 {
355 Keys: bson.D{{"foo", -1}},
356 },
357 {
358 Keys: bson.D{{"bar", 1}, {"baz", -1}},
359 },
360 })
361 assert.Nil(mt, err, "CreateMany error: %v", err)
362
363 evt := mt.GetStartedEvent()
364 assert.NotNil(mt, evt, "expected CommandStartedEvent, got nil")
365
366 assert.Equal(mt, "createIndexes", evt.CommandName, "command name mismatch; expected createIndexes, got %s", evt.CommandName)
367
368 actual, err := evt.Command.LookupErr("writeConcern", "w")
369 assert.Nil(mt, err, "error getting writeConcern.w: %s", err)
370
371 wcVal := numberFromValue(mt, actual)
372 assert.Equal(mt, int64(1), wcVal, "expected writeConcern to be 1, got: %v", wcVal)
373 })
374
375 mt.RunOpts("commit quorum", mtest.NewOptions().Topologies(mtest.ReplicaSet).CreateClient(false), func(mt *mtest.T) {
376 intVal := options.CreateIndexes().SetCommitQuorumInt(1)
377 stringVal := options.CreateIndexes().SetCommitQuorumString("majority")
378 majority := options.CreateIndexes().SetCommitQuorumMajority()
379 votingMembers := options.CreateIndexes().SetCommitQuorumVotingMembers()
380
381 indexModel1 := mongo.IndexModel{
382 Keys: bson.D{{"x", 1}},
383 }
384 indexModel2 := mongo.IndexModel{
385 Keys: bson.D{{"y", 1}},
386 }
387
388 testCases := []struct {
389 name string
390 opts *options.CreateIndexesOptions
391 expectError bool
392 expectedValue interface{}
393 minServerVersion string
394 maxServerVersion string
395 }{
396 {"error on server versions before 4.4", majority, true, nil, "", "4.2"},
397 {"integer value", intVal, false, int32(1), "4.4", ""},
398 {"string value", stringVal, false, "majority", "4.4", ""},
399 {"majority", majority, false, "majority", "4.4", ""},
400 {"votingMembers", votingMembers, false, "votingMembers", "4.4", ""},
401 }
402 for _, tc := range testCases {
403 mtOpts := mtest.NewOptions().MinServerVersion(tc.minServerVersion).MaxServerVersion(tc.maxServerVersion)
404 mt.RunOpts(tc.name, mtOpts, func(mt *mtest.T) {
405 mt.ClearEvents()
406 _, err := mt.Coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{indexModel1, indexModel2}, tc.opts)
407 if tc.expectError {
408 assert.NotNil(mt, err, "expected CreateMany error, got nil")
409 return
410 }
411
412 assert.Nil(mt, err, "CreateMany error: %v", err)
413 cmd := mt.GetStartedEvent().Command
414 sentBSONValue, err := cmd.LookupErr("commitQuorum")
415 assert.Nil(mt, err, "expected commitQuorum in command %s", cmd)
416
417 var sentValue interface{}
418 err = sentBSONValue.Unmarshal(&sentValue)
419 assert.Nil(mt, err, "Unmarshal error: %v", err)
420
421 assert.Equal(mt, tc.expectedValue, sentValue, "expected commitQuorum value %v, got %v",
422 tc.expectedValue, sentValue)
423 })
424 }
425 })
426
427 mt.RunOpts("replace error", mtest.NewOptions().Topologies(mtest.ReplicaSet).MinServerVersion("4.0"), func(mt *mtest.T) {
428 mt.SetFailPoint(mtest.FailPoint{
429 ConfigureFailPoint: "failCommand",
430 Mode: "alwaysOn",
431 Data: mtest.FailPointData{
432 FailCommands: []string{"createIndexes"},
433 ErrorCode: 100,
434 },
435 })
436
437 _, err := mt.Coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
438 {
439 Keys: bson.D{{"foo", int32(-1)}},
440 },
441 {
442 Keys: bson.D{{"bar", int32(1)}, {"baz", int32(-1)}},
443 },
444 })
445 assert.NotNil(mt, err, "expected CreateMany error, got nil")
446 cmdErr, ok := err.(mongo.CommandError)
447 assert.True(mt, ok, "expected mongo.CommandError, got %T", err)
448 assert.Equal(mt, int32(100), cmdErr.Code, "expected error code 100, got %v", cmdErr.Code)
449
450 })
451 mt.Run("multi-key map", func(mt *mtest.T) {
452 iv := mt.Coll.Indexes()
453 _, err := iv.CreateMany(context.Background(), []mongo.IndexModel{
454 {
455 Keys: bson.M{"foo": 1, "bar": -1},
456 },
457 {
458 Keys: bson.D{{"bar", int32(1)}, {"baz", int32(-1)}},
459 },
460 })
461 assert.NotNil(mt, err, "expected CreateOne error, got nil")
462 assert.Equal(mt, mongo.ErrMapForOrderedArgument{"keys"}, err, "expected error %v, got %v", mongo.ErrMapForOrderedArgument{"keys"}, err)
463 })
464 mt.Run("single key map", func(mt *mtest.T) {
465 iv := mt.Coll.Indexes()
466 firstKeysDoc := bson.M{"foo": -1}
467 secondKeysDoc := bson.D{{"bar", int32(1)}, {"baz", int32(-1)}}
468 expectedNames := []string{"foo_-1", "bar_1_baz_-1"}
469 indexNames, err := iv.CreateMany(context.Background(), []mongo.IndexModel{
470 {
471 Keys: firstKeysDoc,
472 },
473 {
474 Keys: secondKeysDoc,
475 },
476 })
477 assert.Nil(mt, err, "CreateMany error: %v", err)
478 assert.Equal(mt, expectedNames, indexNames, "expected returned names %v, got %v", expectedNames, indexNames)
479
480 verifyIndexExists(mt, iv, index{
481 Key: bson.D{{"foo", int32(-1)}},
482 Name: indexNames[0],
483 })
484 verifyIndexExists(mt, iv, index{
485 Key: secondKeysDoc,
486 Name: indexNames[1],
487 })
488 })
489 })
490 mt.RunOpts("list specifications", noClientOpts, func(mt *mtest.T) {
491 mt.Run("verify results", func(mt *mtest.T) {
492
493 _, err := mt.Coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
494 {
495 Keys: bson.D{{"foo", int32(-1)}},
496 Options: options.Index().SetUnique(true),
497 },
498 {
499 Keys: bson.D{{"bar", int32(1)}},
500 Options: options.Index().SetExpireAfterSeconds(120),
501 },
502 {
503 Keys: bson.D{{"baz", int32(1)}},
504 Options: options.Index().SetSparse(true),
505 },
506 {
507 Keys: bson.D{{"bar", int32(1)}, {"baz", int32(-1)}},
508 },
509 })
510 assert.Nil(mt, err, "CreateMany error: %v", err)
511
512 expectedSpecs := []*mongo.IndexSpecification{
513 {
514 Name: "_id_",
515 Namespace: mt.DB.Name() + "." + mt.Coll.Name(),
516 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("_id", 1).Build()),
517 Version: 2,
518 ExpireAfterSeconds: nil,
519 Sparse: nil,
520
521 Unique: nil,
522 },
523 {
524 Name: "foo_-1",
525 Namespace: mt.DB.Name() + "." + mt.Coll.Name(),
526 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("foo", -1).Build()),
527 Version: 2,
528 ExpireAfterSeconds: nil,
529 Sparse: nil,
530 Unique: pbool(true),
531 },
532 {
533 Name: "bar_1",
534 Namespace: mt.DB.Name() + "." + mt.Coll.Name(),
535 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("bar", 1).Build()),
536 Version: 2,
537 ExpireAfterSeconds: pint32(120),
538 Sparse: nil,
539 Unique: nil,
540 },
541 {
542 Name: "baz_1",
543 Namespace: mt.DB.Name() + "." + mt.Coll.Name(),
544 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("baz", 1).Build()),
545 Version: 2,
546 ExpireAfterSeconds: nil,
547 Sparse: pbool(true),
548 Unique: nil,
549 },
550 {
551 Name: "bar_1_baz_-1",
552 Namespace: mt.DB.Name() + "." + mt.Coll.Name(),
553 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("bar", 1).AppendInt32("baz", -1).Build()),
554 Version: 2,
555 ExpireAfterSeconds: nil,
556 Sparse: nil,
557 Unique: nil,
558 },
559 }
560 if mtest.CompareServerVersions(mtest.ServerVersion(), "3.4") < 0 {
561 for _, expectedSpec := range expectedSpecs {
562 expectedSpec.Version = 1
563 }
564 }
565
566 specs, err := mt.Coll.Indexes().ListSpecifications(context.Background())
567 assert.Nil(mt, err, "ListSpecifications error: %v", err)
568 assert.Equal(mt, len(expectedSpecs), len(specs), "expected %d specification, got %d", len(expectedSpecs), len(specs))
569 assert.True(mt, cmp.Equal(specs, expectedSpecs), "expected specifications to match: %v", cmp.Diff(specs, expectedSpecs))
570 })
571 mt.RunOpts("options passed to listIndexes", mtest.NewOptions().MinServerVersion("3.0"), func(mt *mtest.T) {
572 opts := options.ListIndexes().SetMaxTime(100 * time.Millisecond)
573 _, err := mt.Coll.Indexes().ListSpecifications(context.Background(), opts)
574 assert.Nil(mt, err, "ListSpecifications error: %v", err)
575
576 evt := mt.GetStartedEvent()
577 assert.Equal(mt, evt.CommandName, "listIndexes", "expected %q command to be sent, got %q", "listIndexes",
578 evt.CommandName)
579 maxTimeMS, ok := evt.Command.Lookup("maxTimeMS").Int64OK()
580 assert.True(mt, ok, "expected command %v to contain %q field", evt.Command, "maxTimeMS")
581 assert.Equal(mt, int64(100), maxTimeMS, "expected maxTimeMS value to be 100, got %d", maxTimeMS)
582 })
583 })
584 mt.Run("drop one", func(mt *mtest.T) {
585 iv := mt.Coll.Indexes()
586 indexNames, err := iv.CreateMany(context.Background(), []mongo.IndexModel{
587 {
588 Keys: bson.D{{"foo", -1}},
589 },
590 {
591 Keys: bson.D{{"bar", 1}, {"baz", -1}},
592 },
593 })
594 assert.Nil(mt, err, "CreateMany error: %v", err)
595 assert.Equal(mt, 2, len(indexNames), "expected 2 index names, got %v", len(indexNames))
596
597 _, err = iv.DropOne(context.Background(), indexNames[1])
598 assert.Nil(mt, err, "DropOne error: %v", err)
599
600 cursor, err := iv.List(context.Background())
601 assert.Nil(mt, err, "List error: %v", err)
602 for cursor.Next(context.Background()) {
603 var idx index
604 err = cursor.Decode(&idx)
605 assert.Nil(mt, err, "Decode error: %v (document %v)", err, cursor.Current)
606 assert.NotEqual(mt, indexNames[1], idx.Name, "found index %v after dropping", indexNames[1])
607 }
608 assert.Nil(mt, cursor.Err(), "cursor error: %v", cursor.Err())
609 })
610 mt.Run("drop all", func(mt *mtest.T) {
611 iv := mt.Coll.Indexes()
612 names, err := iv.CreateMany(context.Background(), []mongo.IndexModel{
613 {
614 Keys: bson.D{{"foo", -1}},
615 },
616 {
617 Keys: bson.D{{"bar", 1}, {"baz", -1}},
618 },
619 })
620 assert.Nil(mt, err, "CreateMany error: %v", err)
621 assert.Equal(mt, 2, len(names), "expected 2 index names, got %v", len(names))
622 _, err = iv.DropAll(context.Background())
623 assert.Nil(mt, err, "DropAll error: %v", err)
624
625 cursor, err := iv.List(context.Background())
626 assert.Nil(mt, err, "List error: %v", err)
627 for cursor.Next(context.Background()) {
628 var idx index
629 err = cursor.Decode(&idx)
630 assert.Nil(mt, err, "Decode error: %v (document %v)", err, cursor.Current)
631 assert.NotEqual(mt, names[0], idx.Name, "found index %v, after dropping", names[0])
632 assert.NotEqual(mt, names[1], idx.Name, "found index %v, after dropping", names[1])
633 }
634 assert.Nil(mt, cursor.Err(), "cursor error: %v", cursor.Err())
635 })
636 mt.RunOpts("clustered indexes", mtest.NewOptions().MinServerVersion("5.3"), func(mt *mtest.T) {
637 const name = "clustered"
638 clustered := mt.CreateCollection(mtest.Collection{
639 Name: name,
640 CreateOpts: options.CreateCollection().SetClusteredIndex(bson.D{{"key", bson.D{{"_id", 1}}}, {"unique", true}}),
641 }, true)
642 mt.Run("create one", func(mt *mtest.T) {
643 _, err := clustered.Indexes().CreateOne(context.Background(), mongo.IndexModel{
644 Keys: bson.D{{"foo", int32(-1)}},
645 })
646 assert.Nil(mt, err, "CreateOne error: %v", err)
647 specs, err := clustered.Indexes().ListSpecifications(context.Background())
648 assert.Nil(mt, err, "ListSpecifications error: %v", err)
649 expectedSpecs := []*mongo.IndexSpecification{
650 {
651 Name: "_id_",
652 Namespace: mt.DB.Name() + "." + name,
653 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("_id", 1).Build()),
654 Version: 2,
655 Unique: func(b bool) *bool { return &b }(true),
656 Clustered: func(b bool) *bool { return &b }(true),
657 },
658 {
659 Name: "foo_-1",
660 Namespace: mt.DB.Name() + "." + name,
661 KeysDocument: bson.Raw(bsoncore.NewDocumentBuilder().AppendInt32("foo", -1).Build()),
662 Version: 2,
663 },
664 }
665 assert.True(mt, cmp.Equal(specs, expectedSpecs), "expected specifications to match: %v", cmp.Diff(specs, expectedSpecs))
666 })
667 })
668 }
669
670 func getIndexDoc(mt *mtest.T, iv mongo.IndexView, expectedKeyDoc bson.D) bson.D {
671 c, err := iv.List(context.Background())
672 assert.Nil(mt, err, "List error: %v", err)
673
674 for c.Next(context.Background()) {
675 var index bson.D
676 err = c.Decode(&index)
677 assert.Nil(mt, err, "Decode error: %v", err)
678
679 for _, elem := range index {
680 if elem.Key != "key" {
681 continue
682 }
683
684 if cmp.Equal(expectedKeyDoc, elem.Value.(bson.D)) {
685 return index
686 }
687 }
688 }
689 return nil
690 }
691
692 func checkIndexDocContains(mt *mtest.T, indexDoc bson.D, expectedElem bson.E) {
693 for _, elem := range indexDoc {
694 if elem.Key != expectedElem.Key {
695 continue
696 }
697
698 assert.Equal(mt, expectedElem, elem, "expected element %v, got %v", expectedElem, elem)
699 return
700 }
701
702 mt.Fatalf("no element matching %v found", expectedElem)
703 }
704
705 func verifyIndexExists(mt *mtest.T, iv mongo.IndexView, expected index) {
706 mt.Helper()
707
708 cursor, err := iv.List(context.Background())
709 assert.Nil(mt, err, "List error: %v", err)
710
711 var found bool
712 for cursor.Next(context.Background()) {
713 var idx index
714 err = cursor.Decode(&idx)
715 assert.Nil(mt, err, "Decode error: %v", err)
716
717 if idx.Name == expected.Name {
718 if expected.Key != nil {
719 assert.Equal(mt, expected.Key, idx.Key, "key document mismatch; expected %v, got %v", expected.Key, idx.Key)
720 }
721 found = true
722 }
723 }
724 assert.Nil(mt, cursor.Err(), "cursor error: %v", err)
725 assert.True(mt, found, "expected to find index %v but was not found", expected.Name)
726 }
727
View as plain text