diff --git a/mongo/integration/crud_prose_test.go b/mongo/integration/crud_prose_test.go index b4c752e0ce..518f456891 100644 --- a/mongo/integration/crud_prose_test.go +++ b/mongo/integration/crud_prose_test.go @@ -416,10 +416,10 @@ func TestErrorsCodeNamePropagated(t *testing.T) { } func TestClientBulkWrite(t *testing.T) { - mtOpts := mtest.NewOptions().MinServerVersion("8.0").AtlasDataLake(false).CreateClient(false).ClientType(mtest.Pinned) + mtOpts := mtest.NewOptions().MinServerVersion("8.0").AtlasDataLake(false).ClientType(mtest.Pinned) mt := mtest.New(t, mtOpts) - mt.Run("input with greater than maxWriteBatchSize", func(mt *mtest.T) { + mt.Run("bulkWrite batch splits a writeModels input with greater than maxWriteBatchSize operations", func(mt *mtest.T) { var opsCnt []int monitor := &event.CommandMonitor{ Started: func(_ context.Context, e *event.CommandStartedEvent) { @@ -437,23 +437,25 @@ func TestClientBulkWrite(t *testing.T) { var hello struct { MaxWriteBatchSize int } - require.NoError(mt, mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello), "Hello error") + err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) + require.NoError(mt, err, "Hello error: %v", err) models := &mongo.ClientWriteModels{} - for i := 0; i < hello.MaxWriteBatchSize+1; i++ { + numModels := hello.MaxWriteBatchSize + 1 + for i := 0; i < numModels; i++ { models. AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"a", "b"}}, }) } result, err := mt.Client.BulkWrite(context.Background(), models) - require.NoError(mt, err, "BulkWrite error", err) - assert.Equal(mt, hello.MaxWriteBatchSize+1, int(result.InsertedCount), "expected InsertedCount: %d, got %d", hello.MaxWriteBatchSize+1, int(result.InsertedCount)) - require.Len(mt, opsCnt, 2, "expected 2 bulkWrite commands") - assert.Equal(mt, hello.MaxWriteBatchSize, opsCnt[0], "expected %d firstEvent.command.ops, got: %d", hello.MaxWriteBatchSize, opsCnt[0]) - assert.Equal(mt, 1, opsCnt[1], "expected %d secondEvent.command.ops, got %d", 1, opsCnt[1]) + require.NoError(mt, err, "BulkWrite error: %v", err) + assert.Equal(mt, numModels, int(result.InsertedCount), "expected InsertedCount: %d, got %d", numModels, result.InsertedCount) + require.Len(mt, opsCnt, 2, "expected %d bulkWrite commands, got: %d", 2, len(opsCnt)) + assert.Equal(mt, numModels-1, opsCnt[0], "expected %d firstEvent.command.ops, got: %d", numModels-1, opsCnt[0]) + assert.Equal(mt, 1, opsCnt[1], "expected %d secondEvent.command.ops, got: %d", 1, opsCnt[1]) }) - mt.Run("input with greater than maxMessageSizeBytes", func(mt *mtest.T) { + mt.Run("bulkWrite batch splits when an ops payload exceeds maxMessageSizeBytes", func(mt *mtest.T) { var opsCnt []int monitor := &event.CommandMonitor{ Started: func(_ context.Context, e *event.CommandStartedEvent) { @@ -472,7 +474,8 @@ func TestClientBulkWrite(t *testing.T) { MaxBsonObjectSize int MaxMessageSizeBytes int } - require.NoError(mt, mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello), "Hello error") + err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) + require.NoError(mt, err, "Hello error: %v", err) models := &mongo.ClientWriteModels{} numModels := hello.MaxMessageSizeBytes/hello.MaxBsonObjectSize + 1 for i := 0; i < numModels; i++ { @@ -482,20 +485,28 @@ func TestClientBulkWrite(t *testing.T) { }) } result, err := mt.Client.BulkWrite(context.Background(), models) - require.NoError(mt, err, "BulkWrite error", err) - assert.Equal(mt, numModels, int(result.InsertedCount), "expected InsertedCount: %d, got: %d", numModels, int(result.InsertedCount)) - require.Len(mt, opsCnt, 2, "expected 2 bulkWrite commands") - assert.Equal(mt, numModels-1, opsCnt[0], "expected %d firstEvent.command.ops, got %d", numModels-1, opsCnt[0]) + require.NoError(mt, err, "BulkWrite error: %v", err) + assert.Equal(mt, numModels, int(result.InsertedCount), "expected InsertedCount: %d, got: %d", numModels, result.InsertedCount) + require.Len(mt, opsCnt, 2, "expected %d bulkWrite commands, got: %d", 2, len(opsCnt)) + assert.Equal(mt, numModels-1, opsCnt[0], "expected %d firstEvent.command.ops, got: %d", numModels-1, opsCnt[0]) assert.Equal(mt, 1, opsCnt[1], "expected %d secondEvent.command.ops, got: %d", 1, opsCnt[1]) }) mt.Run("bulkWrite collects WriteConcernErrors across batches", func(mt *mtest.T) { - mt.ResetClient(options.Client().SetRetryWrites(false)) + var eventCnt int + monitor := &event.CommandMonitor{ + Started: func(_ context.Context, e *event.CommandStartedEvent) { + if e.CommandName == "bulkWrite" { + eventCnt++ + } + }, + } + mt.ResetClient(options.Client().SetRetryWrites(false).SetMonitor(monitor)) var hello struct { MaxWriteBatchSize int } err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + require.NoError(mt, err, "Hello error: %v", err) mt.SetFailPoint(mtest.FailPoint{ ConfigureFailPoint: "failCommand", @@ -512,29 +523,25 @@ func TestClientBulkWrite(t *testing.T) { }) models := &mongo.ClientWriteModels{} - for i := 0; i < hello.MaxWriteBatchSize+1; i++ { + numModels := hello.MaxWriteBatchSize + 1 + for i := 0; i < numModels; i++ { models. AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"a", "b"}}, }) } _, err = mt.Client.BulkWrite(context.Background(), models) - require.Error(mt, err) + require.Error(mt, err, "expected a BulkWrite error") bwe, ok := err.(mongo.ClientBulkWriteException) require.True(mt, ok, "expected a BulkWriteException, got %T: %v", err, err) - assert.Len(mt, bwe.WriteConcernErrors, 2, "expected writeConcernErrors: %d, got: %d", 2, len(bwe.WriteConcernErrors)) + assert.Len(mt, bwe.WriteConcernErrors, 2, "expected %d writeConcernErrors, got: %d", 2, len(bwe.WriteConcernErrors)) require.NotNil(mt, bwe.PartialResult) - assert.Equal(mt, hello.MaxWriteBatchSize+1, int(bwe.PartialResult.InsertedCount), - "expected InsertedCount: %d, got: %d", hello.MaxWriteBatchSize+1, int(bwe.PartialResult.InsertedCount)) + assert.Equal(mt, numModels, int(bwe.PartialResult.InsertedCount), + "expected InsertedCount: %d, got: %d", numModels, bwe.PartialResult.InsertedCount) + require.Equal(mt, 2, eventCnt, "expected %d bulkWrite commands, got: %d", 2, eventCnt) }) mt.Run("bulkWrite handles individual WriteErrors across batches", func(mt *mtest.T) { - coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) - err := coll.Drop(context.Background()) - require.NoError(mt, err, "Drop error") - _, err = coll.InsertOne(context.Background(), bson.D{{"_id", 1}}) - require.NoError(mt, err, "InsertOne error") - var eventCnt int monitor := &event.CommandMonitor{ Started: func(_ context.Context, e *event.CommandStartedEvent) { @@ -544,13 +551,22 @@ func TestClientBulkWrite(t *testing.T) { }, } + mt.ResetClient(options.Client()) var hello struct { MaxWriteBatchSize int } - err = mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) + require.NoError(mt, err, "Hello error: %v", err) + + coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) + err = coll.Drop(context.Background()) + require.NoError(mt, err, "Drop error: %v", err) + _, err = coll.InsertOne(context.Background(), bson.D{{"_id", 1}}) + require.NoError(mt, err, "InsertOne error: %v", err) + models := &mongo.ClientWriteModels{} - for i := 0; i < hello.MaxWriteBatchSize+1; i++ { + numModels := hello.MaxWriteBatchSize + 1 + for i := 0; i < numModels; i++ { models. AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"_id", 1}}, @@ -561,29 +577,25 @@ func TestClientBulkWrite(t *testing.T) { eventCnt = 0 mt.ResetClient(options.Client().SetMonitor(monitor)) _, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetOrdered(false)) - require.Error(mt, err) + require.Error(mt, err, "expected a BulkWrite error") bwe, ok := err.(mongo.ClientBulkWriteException) require.True(mt, ok, "expected a BulkWriteException, got %T: %v", err, err) - assert.Len(mt, bwe.WriteErrors, hello.MaxWriteBatchSize+1, "expected %d writeErrors, got %d", hello.MaxWriteBatchSize+1, len(bwe.WriteErrors)) - require.Equal(mt, 2, eventCnt, "expected %d bulkWrite commands, got %d", 2, eventCnt) + assert.Len(mt, bwe.WriteErrors, numModels, "expected %d writeErrors, got %d", numModels, len(bwe.WriteErrors)) + require.Equal(mt, 2, eventCnt, "expected %d bulkWrite commands, got: %d", 2, eventCnt) }) mt.Run("ordered", func(mt *mtest.T) { eventCnt = 0 mt.ResetClient(options.Client().SetMonitor(monitor)) _, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetOrdered(true)) - require.Error(mt, err) + require.Error(mt, err, "expected a BulkWrite error") bwe, ok := err.(mongo.ClientBulkWriteException) require.True(mt, ok, "expected a BulkWriteException, got %T: %v", err, err) - assert.Len(mt, bwe.WriteErrors, 1, "expected writeErrors: %d, got: %d", 1, len(bwe.WriteErrors)) - require.Equal(mt, 1, eventCnt, "expected %d bulkWrite commands, got %d", 1, eventCnt) + assert.Len(mt, bwe.WriteErrors, 1, "expected %d writeErrors, got: %d", 1, len(bwe.WriteErrors)) + require.Equal(mt, 1, eventCnt, "expected %d bulkWrite commands, got: %d", 1, eventCnt) }) }) mt.Run("bulkWrite handles a cursor requiring a getMore", func(mt *mtest.T) { - coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) - err := coll.Drop(context.Background()) - require.NoError(mt, err, "Drop error") - var getMoreCalled int monitor := &event.CommandMonitor{ Started: func(_ context.Context, e *event.CommandStartedEvent) { @@ -596,8 +608,13 @@ func TestClientBulkWrite(t *testing.T) { var hello struct { MaxBsonObjectSize int } - err = mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) + require.NoError(mt, err, "Hello error: %v", err) + + coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) + err = coll.Drop(context.Background()) + require.NoError(mt, err, "Drop error: %v", err) + upsert := true models := (&mongo.ClientWriteModels{}). AppendUpdateOne("db", "coll", &mongo.ClientUpdateOneModel{ @@ -611,56 +628,61 @@ func TestClientBulkWrite(t *testing.T) { Upsert: &upsert, }) result, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetVerboseResults(true)) - require.NoError(mt, err, "BulkWrite error") - assert.Equal(mt, 2, int(result.UpsertedCount), "expected InsertedCount: %d, got: %d", 2, result.UpsertedCount) - assert.Len(mt, result.UpdateResults, 2, "expected UpdateResults: %d, got: %d", 2, len(result.UpdateResults)) + require.NoError(mt, err, "BulkWrite error: %v", err) + assert.Equal(mt, int64(2), result.UpsertedCount, "expected InsertedCount: %d, got: %d", 2, result.UpsertedCount) + assert.Len(mt, result.UpdateResults, 2, "expected %d UpdateResults, got: %d", 2, len(result.UpdateResults)) assert.Equal(mt, 1, getMoreCalled, "expected %d getMore call, got %d", 1, getMoreCalled) }) - mt.Run("bulkWrite handles a cursor requiring a getMore within a transaction", func(mt *mtest.T) { - coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) - err := coll.Drop(context.Background()) - require.NoError(mt, err, "Drop error") + mt.RunOpts("bulkWrite handles a cursor requiring a getMore within a transaction", + mtest.NewOptions().MinServerVersion("8.0").AtlasDataLake(false).ClientType(mtest.Pinned). + Topologies(mtest.ReplicaSet, mtest.Sharded, mtest.LoadBalanced, mtest.ShardedReplicaSet), + func(mt *mtest.T) { + var getMoreCalled int + monitor := &event.CommandMonitor{ + Started: func(_ context.Context, e *event.CommandStartedEvent) { + if e.CommandName == "getMore" { + getMoreCalled++ + } + }, + } + mt.ResetClient(options.Client().SetMonitor(monitor)) + var hello struct { + MaxBsonObjectSize int + } + err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) + require.NoError(mt, err, "Hello error: %v", err) - var getMoreCalled int - monitor := &event.CommandMonitor{ - Started: func(_ context.Context, e *event.CommandStartedEvent) { - if e.CommandName == "getMore" { - getMoreCalled++ - } - }, - } - mt.ResetClient(options.Client().SetMonitor(monitor)) - var hello struct { - MaxBsonObjectSize int - } - err = mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") - session, err := mt.Client.StartSession() - require.NoError(mt, err, "StartSession error") - defer session.EndSession(context.Background()) - upsert := true - models := (&mongo.ClientWriteModels{}). - AppendUpdateOne("db", "coll", &mongo.ClientUpdateOneModel{ - Filter: bson.D{{"_id", strings.Repeat("a", hello.MaxBsonObjectSize/2)}}, - Update: bson.D{{"$set", bson.D{{"x", 1}}}}, - Upsert: &upsert, - }). - AppendUpdateOne("db", "coll", &mongo.ClientUpdateOneModel{ - Filter: bson.D{{"_id", strings.Repeat("b", hello.MaxBsonObjectSize/2)}}, - Update: bson.D{{"$set", bson.D{{"x", 1}}}}, - Upsert: &upsert, + coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) + err = coll.Drop(context.Background()) + require.NoError(mt, err, "Drop error: %v", err) + + session, err := mt.Client.StartSession() + require.NoError(mt, err, "StartSession error: %v", err) + defer session.EndSession(context.Background()) + + upsert := true + models := (&mongo.ClientWriteModels{}). + AppendUpdateOne("db", "coll", &mongo.ClientUpdateOneModel{ + Filter: bson.D{{"_id", strings.Repeat("a", hello.MaxBsonObjectSize/2)}}, + Update: bson.D{{"$set", bson.D{{"x", 1}}}}, + Upsert: &upsert, + }). + AppendUpdateOne("db", "coll", &mongo.ClientUpdateOneModel{ + Filter: bson.D{{"_id", strings.Repeat("b", hello.MaxBsonObjectSize/2)}}, + Update: bson.D{{"$set", bson.D{{"x", 1}}}}, + Upsert: &upsert, + }) + result, err := session.WithTransaction(context.Background(), func(ctx mongo.SessionContext) (interface{}, error) { + return mt.Client.BulkWrite(ctx, models, options.ClientBulkWrite().SetVerboseResults(true)) }) - result, err := session.WithTransaction(context.Background(), func(mongo.SessionContext) (interface{}, error) { - return mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetVerboseResults(true)) + require.NoError(mt, err, "BulkWrite error: %v", err) + cbwResult, ok := result.(*mongo.ClientBulkWriteResult) + require.True(mt, ok, "expected a ClientBulkWriteResult, got %T", result) + assert.Equal(mt, int64(2), cbwResult.UpsertedCount, "expected InsertedCount: %d, got: %d", 2, cbwResult.UpsertedCount) + assert.Len(mt, cbwResult.UpdateResults, 2, "expected %d UpdateResults, got: %d", 2, len(cbwResult.UpdateResults)) + assert.Equal(mt, 1, getMoreCalled, "expected %d getMore call, got %d", 1, getMoreCalled) }) - require.NoError(mt, err, "BulkWrite error") - cbwResult, ok := result.(*mongo.ClientBulkWriteResult) - require.True(mt, ok, "expected a ClientBulkWriteResult") - assert.Equal(mt, 2, int(cbwResult.UpsertedCount), "expected InsertedCount: %d, got: %d", 2, cbwResult.UpsertedCount) - assert.Len(mt, cbwResult.UpdateResults, 2, "expected UpdateResults: %d, got: %d", 2, len(cbwResult.UpdateResults)) - assert.Equal(mt, 1, getMoreCalled, "expected %d getMore call, got %d", 1, getMoreCalled) - }) mt.Run("bulkWrite handles a getMore error", func(mt *mtest.T) { var getMoreCalled int @@ -680,7 +702,7 @@ func TestClientBulkWrite(t *testing.T) { MaxBsonObjectSize int } err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + require.NoError(mt, err, "Hello error: %v", err) mt.SetFailPoint(mtest.FailPoint{ ConfigureFailPoint: "failCommand", @@ -695,7 +717,7 @@ func TestClientBulkWrite(t *testing.T) { coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) err = coll.Drop(context.Background()) - require.NoError(mt, err, "Drop error") + require.NoError(mt, err, "Drop error: %v", err) upsert := true models := (&mongo.ClientWriteModels{}). @@ -710,14 +732,14 @@ func TestClientBulkWrite(t *testing.T) { Upsert: &upsert, }) _, err = mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetVerboseResults(true)) - assert.Error(mt, err) + assert.Error(mt, err, "expected a BulkWrite error") bwe, ok := err.(mongo.ClientBulkWriteException) require.True(mt, ok, "expected a BulkWriteException, got %T: %v", err, err) - require.NotNil(mt, bwe.PartialResult) require.NotNil(mt, bwe.TopLevelError) assert.Equal(mt, 8, bwe.TopLevelError.Code, "expected top level error code: %d, got; %d", 8, bwe.TopLevelError.Code) + require.NotNil(mt, bwe.PartialResult) assert.Equal(mt, int64(2), bwe.PartialResult.UpsertedCount, "expected UpsertedCount: %d, got: %d", 2, bwe.PartialResult.UpsertedCount) - assert.Len(mt, bwe.PartialResult.UpdateResults, 1, "expected UpdateResults: %d, got: %d", 1, len(bwe.PartialResult.UpdateResults)) + assert.Len(mt, bwe.PartialResult.UpdateResults, 1, "expected %d UpdateResults, got: %d", 1, len(bwe.PartialResult.UpdateResults)) assert.Equal(mt, 1, getMoreCalled, "expected %d getMore call, got %d", 1, getMoreCalled) assert.Equal(mt, 1, killCursorsCalled, "expected %d killCursors call, got %d", 1, killCursorsCalled) }) @@ -728,7 +750,7 @@ func TestClientBulkWrite(t *testing.T) { MaxBsonObjectSize int } err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + require.NoError(mt, err, "Hello error: %v", err) mt.Run("insert", func(mt *mtest.T) { models := (&mongo.ClientWriteModels{}). AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ @@ -761,17 +783,18 @@ func TestClientBulkWrite(t *testing.T) { if e.CommandName == "bulkWrite" { var c cmd err := bson.Unmarshal(e.Command, &c) - require.NoError(mt, err) + require.NoError(mt, err, "Unmarshal error: %v", err) bwCmd = append(bwCmd, c) } }, } + mt.ResetClient(options.Client()) var hello struct { MaxBsonObjectSize int MaxMessageSizeBytes int } err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + require.NoError(mt, err, "Hello error: %v", err) newModels := func() (int, *mongo.ClientWriteModels) { maxBsonObjectSize := hello.MaxBsonObjectSize @@ -803,12 +826,12 @@ func TestClientBulkWrite(t *testing.T) { models.AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"a", "b"}}, }) - result, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite()) - require.NoError(mt, err) + result, err := mt.Client.BulkWrite(context.Background(), models) + require.NoError(mt, err, "BulkWrite error: %v", err) assert.Equal(mt, numModels+1, int(result.InsertedCount), "expected insertedCound: %d, got: %d", numModels+1, result.InsertedCount) require.Len(mt, bwCmd, 1, "expected %d bulkWrite call, got %d", 1, len(bwCmd)) - assert.Len(mt, bwCmd[0].Ops, numModels+1, "expected ops: %d, got: %d", numModels+1, len(bwCmd[0].Ops)) + assert.Len(mt, bwCmd[0].Ops, numModels+1, "expected %d ops, got: %d", numModels+1, len(bwCmd[0].Ops)) require.Len(mt, bwCmd[0].NsInfo, 1, "expected %d nsInfo, got: %d", 1, len(bwCmd[0].NsInfo)) assert.Equal(mt, "db.coll", bwCmd[0].NsInfo[0].Ns, "expected namespace: %s, got: %s", "db.coll", bwCmd[0].NsInfo[0].Ns) }) @@ -821,41 +844,42 @@ func TestClientBulkWrite(t *testing.T) { models.AppendInsertOne("db", coll, &mongo.ClientInsertOneModel{ Document: bson.D{{"a", "b"}}, }) - result, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite()) - require.NoError(mt, err) + result, err := mt.Client.BulkWrite(context.Background(), models) + require.NoError(mt, err, "BulkWrite error: %v", err) assert.Equal(mt, numModels+1, int(result.InsertedCount), "expected insertedCound: %d, got: %d", numModels+1, result.InsertedCount) require.Len(mt, bwCmd, 2, "expected %d bulkWrite calls, got %d", 2, len(bwCmd)) - assert.Len(mt, bwCmd[0].Ops, numModels, "expected ops: %d, got: %d", numModels, len(bwCmd[0].Ops)) + assert.Len(mt, bwCmd[0].Ops, numModels, "expected %d ops, got: %d", numModels, len(bwCmd[0].Ops)) require.Len(mt, bwCmd[0].NsInfo, 1, "expected %d nsInfo, got: %d", 1, len(bwCmd[0].NsInfo)) assert.Equal(mt, "db.coll", bwCmd[0].NsInfo[0].Ns, "expected namespace: %s, got: %s", "db.coll", bwCmd[0].NsInfo[0].Ns) - assert.Len(mt, bwCmd[1].Ops, 1, "expected ops: %d, got: %d", 1, len(bwCmd[1].Ops)) + assert.Len(mt, bwCmd[1].Ops, 1, "expected %d ops, got: %d", 1, len(bwCmd[1].Ops)) require.Len(mt, bwCmd[1].NsInfo, 1, "expected %d nsInfo, got: %d", 1, len(bwCmd[1].NsInfo)) assert.Equal(mt, "db."+coll, bwCmd[1].NsInfo[0].Ns, "expected namespace: %s, got: %s", "db."+coll, bwCmd[1].NsInfo[0].Ns) }) }) mt.Run("bulkWrite returns an error if no operations can be added to ops", func(mt *mtest.T) { + mt.ResetClient(options.Client()) var hello struct { MaxMessageSizeBytes int } err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") + require.NoError(mt, err, "Hello error: %v", err) mt.Run("document too large", func(mt *mtest.T) { models := (&mongo.ClientWriteModels{}). AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"a", strings.Repeat("b", hello.MaxMessageSizeBytes)}}, }) - _, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetOrdered(false).SetWriteConcern(writeconcern.Unacknowledged())) + _, err := mt.Client.BulkWrite(context.Background(), models) require.EqualError(mt, err, driver.ErrDocumentTooLarge.Error()) }) - mt.Run("document too large", func(mt *mtest.T) { + mt.Run("namespace too large", func(mt *mtest.T) { models := (&mongo.ClientWriteModels{}). AppendInsertOne("db", strings.Repeat("c", hello.MaxMessageSizeBytes), &mongo.ClientInsertOneModel{ Document: bson.D{{"a", "b"}}, }) - _, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetOrdered(false).SetWriteConcern(writeconcern.Unacknowledged())) + _, err := mt.Client.BulkWrite(context.Background(), models) require.EqualError(mt, err, driver.ErrDocumentTooLarge.Error()) }) }) @@ -878,7 +902,7 @@ func TestClientBulkWrite(t *testing.T) { AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"a", "b"}}, }) - _, err := mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetOrdered(false).SetWriteConcern(writeconcern.Unacknowledged())) + _, err := mt.Client.BulkWrite(context.Background(), models) require.ErrorContains(mt, err, "bulkWrite does not currently support automatic encryption") }) @@ -895,45 +919,44 @@ func TestClientBulkWrite(t *testing.T) { if e.CommandName == "bulkWrite" { var c cmd err := bson.Unmarshal(e.Command, &c) - require.NoError(mt, err) + require.NoError(mt, err, "Unmarshal error: %v", err) bwCmd = append(bwCmd, c) } }, } + mt.ResetClient(options.Client().SetMonitor(monitor)) var hello struct { MaxBsonObjectSize int MaxMessageSizeBytes int } err := mt.DB.RunCommand(context.Background(), bson.D{{"hello", 1}}).Decode(&hello) - require.NoError(mt, err, "Hello error") - - mt.ResetClient(options.Client().SetMonitor(monitor)) + require.NoError(mt, err, "Hello error: %v", err) coll := mt.CreateCollection(mtest.Collection{DB: "db", Name: "coll"}, false) err = coll.Drop(context.Background()) - require.NoError(mt, err, "Drop error") + require.NoError(mt, err, "Drop error: %v", err) - numModels := hello.MaxMessageSizeBytes / hello.MaxBsonObjectSize + numModels := hello.MaxMessageSizeBytes/hello.MaxBsonObjectSize + 1 models := &mongo.ClientWriteModels{} - for i := 0; i < numModels+1; i++ { + for i := 0; i < numModels; i++ { models. AppendInsertOne("db", "coll", &mongo.ClientInsertOneModel{ Document: bson.D{{"a", strings.Repeat("b", hello.MaxBsonObjectSize-500)}}, }) } _, err = mt.Client.BulkWrite(context.Background(), models, options.ClientBulkWrite().SetOrdered(false).SetWriteConcern(writeconcern.Unacknowledged())) - require.NoError(mt, err) + require.NoError(mt, err, "BulkWrite error: %v", err) require.Len(mt, bwCmd, 2, "expected %d bulkWrite calls, got %d", 2, len(bwCmd)) - assert.Len(mt, bwCmd[0].Ops, numModels, "expected ops: %d, got: %d", numModels, len(bwCmd[0].Ops)) + assert.Len(mt, bwCmd[0].Ops, numModels-1, "expected %d ops, got: %d", numModels-1, len(bwCmd[0].Ops)) assert.Equal(mt, int32(0), bwCmd[0].WriteConcern.W, "expected writeConcern: %d, got: %v", 0, bwCmd[0].WriteConcern.W) - assert.Len(mt, bwCmd[1].Ops, 1, "expected ops: %d, got: %d", 1, len(bwCmd[1].Ops)) + assert.Len(mt, bwCmd[1].Ops, 1, "expected %d ops, got: %d", 1, len(bwCmd[1].Ops)) assert.Equal(mt, int32(0), bwCmd[1].WriteConcern.W, "expected writeConcern: %d, got: %v", 0, bwCmd[1].WriteConcern.W) n, err := coll.CountDocuments(context.Background(), bson.D{}) - require.NoError(mt, err) - assert.Equal(mt, numModels+1, int(n), "expected %d documents, got %d", numModels+1, n) + require.NoError(mt, err, "CountDocuments error: %v", err) + assert.Equal(mt, numModels, int(n), "expected %d documents, got %d", numModels, n) }) } diff --git a/mongo/integration/unified/error.go b/mongo/integration/unified/error.go index d967c35a38..66b357f58d 100644 --- a/mongo/integration/unified/error.go +++ b/mongo/integration/unified/error.go @@ -150,7 +150,7 @@ func verifyOperationError(ctx context.Context, expected *expectedError, result * if expected.WriteErrors != nil { var exception mongo.ClientBulkWriteException if !errors.As(result.Err, &exception) { - return fmt.Errorf("expected a ClientBulkWriteException, got %T", result.Err) + return fmt.Errorf("expected a ClientBulkWriteException, got %T: %v", result.Err, result.Err) } if len(expected.WriteErrors) != len(exception.WriteErrors) { return fmt.Errorf("expected errors: %v, got: %v", expected.WriteErrors, exception.WriteErrors) @@ -167,7 +167,7 @@ func verifyOperationError(ctx context.Context, expected *expectedError, result * if expected.WriteConcernErrors != nil { var exception mongo.ClientBulkWriteException if !errors.As(result.Err, &exception) { - return fmt.Errorf("expected a ClientBulkWriteException, got %T", result.Err) + return fmt.Errorf("expected a ClientBulkWriteException, got %T: %v", result.Err, result.Err) } if len(expected.WriteConcernErrors) != len(exception.WriteConcernErrors) { return fmt.Errorf("expected errors: %v, got: %v", expected.WriteConcernErrors, exception.WriteConcernErrors)