Skip to content

Commit b81b51a

Browse files
CSHARP-3021: GetMore commands are not sent with the namespace returned in the last batch
1 parent 933dae4 commit b81b51a

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

src/MongoDB.Driver.Core/Core/Operations/FindCommandOperation.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using System.Threading;
1818
using System.Threading.Tasks;
1919
using MongoDB.Bson;
20-
using MongoDB.Bson.IO;
2120
using MongoDB.Bson.Serialization;
2221
using MongoDB.Bson.Serialization.Serializers;
2322
using MongoDB.Driver.Core.Bindings;
@@ -468,11 +467,13 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription,
468467
private AsyncCursor<TDocument> CreateCursor(IChannelSourceHandle channelSource, BsonDocument commandResult)
469468
{
470469
var getMoreChannelSource = new ServerChannelSource(channelSource.Server, channelSource.Session.Fork());
471-
var firstBatch = CreateCursorBatch(commandResult);
470+
var cursorDocument = commandResult["cursor"].AsBsonDocument;
471+
var collectionNamespace = CollectionNamespace.FromFullName(cursorDocument["ns"].AsString);
472+
var firstBatch = CreateFirstCursorBatch(cursorDocument);
472473

473474
return new AsyncCursor<TDocument>(
474475
getMoreChannelSource,
475-
_collectionNamespace,
476+
collectionNamespace,
476477
_filter ?? new BsonDocument(),
477478
firstBatch.Documents,
478479
firstBatch.CursorId,
@@ -483,9 +484,8 @@ private AsyncCursor<TDocument> CreateCursor(IChannelSourceHandle channelSource,
483484
_cursorType == CursorType.TailableAwait ? _maxAwaitTime : null);
484485
}
485486

486-
private CursorBatch<TDocument> CreateCursorBatch(BsonDocument commandResult)
487+
private CursorBatch<TDocument> CreateFirstCursorBatch(BsonDocument cursorDocument)
487488
{
488-
var cursorDocument = commandResult["cursor"].AsBsonDocument;
489489
var cursorId = cursorDocument["id"].ToInt64();
490490
var batch = (RawBsonArray)cursorDocument["firstBatch"];
491491

tests/MongoDB.Bson.TestHelpers/Reflector.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@ public static object Invoke<T1>(object obj, string name, T1 arg1)
7070
}
7171
}
7272

73+
public static object Invoke<T1, T2>(object obj, string name, T1 arg1, T2 arg2)
74+
{
75+
var parameterTypes = new[] { typeof(T1), typeof(T2) };
76+
var methodInfo = obj.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
77+
.Where(m => m.Name == name && m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes))
78+
.Single();
79+
try
80+
{
81+
return methodInfo.Invoke(obj, new object[] { arg1, arg2 });
82+
}
83+
catch (TargetInvocationException exception)
84+
{
85+
throw exception.InnerException;
86+
}
87+
}
88+
7389
public static object Invoke<T1, T2>(object obj, string name, out T1 arg1, out T2 arg2)
7490
{
7591
arg1 = default;

tests/MongoDB.Driver.Core.Tests/Core/Operations/FindCommandOperationTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@
1616
using System;
1717
using FluentAssertions;
1818
using MongoDB.Bson;
19+
using MongoDB.Bson.IO;
1920
using MongoDB.Bson.Serialization.Serializers;
21+
using MongoDB.Bson.TestHelpers;
2022
using MongoDB.Bson.TestHelpers.XunitExtensions;
2123
using MongoDB.Driver.Core.Bindings;
2224
using MongoDB.Driver.Core.Clusters;
2325
using MongoDB.Driver.Core.Misc;
2426
using MongoDB.Driver.Core.Servers;
2527
using MongoDB.Driver.Core.TestHelpers;
2628
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
29+
using Moq;
2730
using Xunit;
2831

2932
namespace MongoDB.Driver.Core.Operations
@@ -773,6 +776,36 @@ public void CreateCommand_should_return_the_expected_result_when_using_causal_co
773776
result.Should().Be(expectedResult);
774777
}
775778

779+
[SkippableFact]
780+
public void CreateCursor_should_use_ns_field_instead_of_namespace_passed_in_constructor()
781+
{
782+
var subject = new FindCommandOperation<BsonDocument>(_collectionNamespace, BsonDocumentSerializer.Instance, _messageEncoderSettings);
783+
var firstBatchSlice = new ByteArrayBuffer(new byte[] { 5, 0, 0, 0, 0 }, isReadOnly: true);
784+
var cursorCollectionNamespace = CollectionNamespace.FromFullName("cursors.lkajlkasdf-3980238d908sdf");
785+
var cursorDocument = new BsonDocument
786+
{
787+
{ "id", 0 },
788+
{ "firstBatch", new RawBsonArray(firstBatchSlice) },
789+
{ "ns", cursorCollectionNamespace.FullName }
790+
};
791+
var commandResult = new BsonDocument
792+
{
793+
{ "ok", 1 },
794+
{ "cursor", cursorDocument }
795+
};
796+
var mockServer = new Mock<IServer>();
797+
var mockSession = new Mock<ICoreSessionHandle>();
798+
var mockSessionFork = new Mock<ICoreSessionHandle>();
799+
mockSession.Setup(x => x.Fork()).Returns(mockSessionFork.Object);
800+
var mockChannelSource = new Mock<IChannelSourceHandle>();
801+
mockChannelSource.Setup(x => x.Server).Returns(mockServer.Object);
802+
mockChannelSource.Setup(x => x.Session).Returns(mockSession.Object);
803+
804+
var cursor = subject.CreateCursor(mockChannelSource.Object, commandResult);
805+
806+
cursor._collectionNamespace().Should().Be(cursorCollectionNamespace);
807+
}
808+
776809
[Theory]
777810
[ParameterAttributeData]
778811
public void CursorType_get_and_set_should_work(
@@ -1306,4 +1339,15 @@ private void EnsureTestData()
13061339
});
13071340
}
13081341
}
1342+
1343+
public static class FindCommandOperationReflector
1344+
{
1345+
public static AsyncCursor<BsonDocument> CreateCursor(
1346+
this FindCommandOperation<BsonDocument> obj,
1347+
IChannelSourceHandle channelSource,
1348+
BsonDocument commandResult)
1349+
{
1350+
return (AsyncCursor<BsonDocument>)Reflector.Invoke(obj, nameof(CreateCursor), channelSource, commandResult);
1351+
}
1352+
}
13091353
}

0 commit comments

Comments
 (0)