Skip to content

Commit 7d7071f

Browse files
committed
CSHARP-2280: Added JSON driven tests for change streams.
1 parent bc38879 commit 7d7071f

27 files changed

+3192
-88
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ internal BsonDocument CreateCommand(ConnectionDescription connectionDescription,
333333

334334
private ReadCommandOperation<AggregateResult> CreateOperation(IChannel channel, IBinding binding)
335335
{
336+
var databaseNamespace = _collectionNamespace == null ? _databaseNamespace : _collectionNamespace.DatabaseNamespace;
336337
var command = CreateCommand(channel.ConnectionDescription, binding.Session);
337338
var serializer = new AggregateResultDeserializer(_resultSerializer);
338-
return new ReadCommandOperation<AggregateResult>(CollectionNamespace.DatabaseNamespace, command, serializer, MessageEncoderSettings);
339+
return new ReadCommandOperation<AggregateResult>(databaseNamespace, command, serializer, MessageEncoderSettings);
339340
}
340341

341342
private AsyncCursor<TResult> CreateCursor(IChannelSourceHandle channelSource, IChannelHandle channel, BsonDocument command, AggregateResult result)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ private BsonDocument CreateChangeStreamStage()
332332
{
333333
var changeStreamOptions = new BsonDocument
334334
{
335-
{ "allChangesForCluster", true, _collectionNamespace == null && _databaseNamespace == null },
336335
{ "fullDocument", ToString(_fullDocument) },
336+
{ "allChangesForCluster", true, _collectionNamespace == null && _databaseNamespace == null },
337337
{ "startAtOperationTime", _startAtOperationTime, _startAtOperationTime != null },
338338
{ "resumeAfter", _resumeAfter, _resumeAfter != null }
339339
};

src/MongoDB.Driver/PipelineStageDefinitionBuilder.cs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -339,20 +339,13 @@ public static PipelineStageDefinition<TInput, ChangeStreamDocument<TInput>> Chan
339339
operatorName,
340340
(s, sr) =>
341341
{
342-
var renderedOptions = new BsonDocument();
343-
if (options.AllChangesForCluster ?? false)
342+
var renderedOptions = new BsonDocument
344343
{
345-
renderedOptions.Add("allChangesForCluster", true);
346-
}
347-
renderedOptions.Add("fullDocument", MongoUtils.ToCamelCase(options.FullDocument.ToString()));
348-
if (options.StartAtOperationTime != null)
349-
{
350-
renderedOptions.Add("startAtOperationTime", options.StartAtOperationTime);
351-
}
352-
if (options.ResumeAfter != null)
353-
{
354-
renderedOptions.Add("resumeAfter", options.ResumeAfter);
355-
}
344+
{ "fullDocument", MongoUtils.ToCamelCase(options.FullDocument.ToString()) },
345+
{ "allChangesForCluster", true, options.AllChangesForCluster ?? false },
346+
{ "resumeAfter", options.ResumeAfter, options.ResumeAfter != null },
347+
{ "startAtOperationTime", options.StartAtOperationTime, options.StartAtOperationTime != null }
348+
};
356349
var document = new BsonDocument(operatorName, renderedOptions);
357350
var outputSerializer = new ChangeStreamDocumentSerializer<TInput>(s);
358351
return new RenderedPipelineStageDefinition<ChangeStreamDocument<TInput>>(

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

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,68 @@ public class AggregateOperationTests : OperationTestBase
3535
private static IBsonSerializer<BsonDocument> __resultSerializer = BsonDocumentSerializer.Instance;
3636

3737
[Fact]
38-
public void Constructor_should_create_a_valid_instance()
38+
public void Constructor_with_database_should_create_a_valid_instance()
39+
{
40+
var subject = new AggregateOperation<BsonDocument>(_databaseNamespace, __pipeline, __resultSerializer, _messageEncoderSettings);
41+
42+
subject.CollectionNamespace.Should().BeNull();
43+
subject.DatabaseNamespace.Should().BeSameAs(_databaseNamespace);
44+
subject.Pipeline.Should().Equal(__pipeline);
45+
subject.ResultSerializer.Should().BeSameAs(__resultSerializer);
46+
subject.MessageEncoderSettings.Should().BeSameAs(_messageEncoderSettings);
47+
48+
subject.AllowDiskUse.Should().NotHaveValue();
49+
subject.BatchSize.Should().NotHaveValue();
50+
subject.Collation.Should().BeNull();
51+
subject.MaxAwaitTime.Should().NotHaveValue();
52+
subject.MaxTime.Should().NotHaveValue();
53+
subject.ReadConcern.IsServerDefault.Should().BeTrue();
54+
subject.UseCursor.Should().NotHaveValue();
55+
}
56+
57+
[Fact]
58+
public void Constructor_with_database_should_throw_when_databaseNamespace_is_null()
59+
{
60+
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>((DatabaseNamespace)null, __pipeline, __resultSerializer, _messageEncoderSettings));
61+
62+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
63+
argumentNullException.ParamName.Should().Be("databaseNamespace");
64+
}
65+
66+
[Fact]
67+
public void Constructor_with_database_should_throw_when_pipeline_is_null()
68+
{
69+
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>(_databaseNamespace, null, __resultSerializer, _messageEncoderSettings));
70+
71+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
72+
argumentNullException.ParamName.Should().Be("pipeline");
73+
}
74+
75+
[Fact]
76+
public void Constructor_with_database_should_throw_when_resultSerializer_is_null()
77+
{
78+
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>(_databaseNamespace, __pipeline, null, _messageEncoderSettings));
79+
80+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
81+
argumentNullException.ParamName.Should().Be("resultSerializer");
82+
}
83+
84+
[Fact]
85+
public void Constructor_with_database_should_throw_when_messageEncoderSettings_is_null()
86+
{
87+
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>(_databaseNamespace, __pipeline, __resultSerializer, null));
88+
89+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
90+
argumentNullException.ParamName.Should().Be("messageEncoderSettings");
91+
}
92+
93+
[Fact]
94+
public void Constructor_with_collection_should_create_a_valid_instance()
3995
{
4096
var subject = new AggregateOperation<BsonDocument>(_collectionNamespace, __pipeline, __resultSerializer, _messageEncoderSettings);
4197

4298
subject.CollectionNamespace.Should().Be(_collectionNamespace);
99+
subject.DatabaseNamespace.Should().BeNull();
43100
subject.Pipeline.Should().Equal(__pipeline);
44101
subject.ResultSerializer.Should().BeSameAs(__resultSerializer);
45102
subject.MessageEncoderSettings.Should().BeSameAs(_messageEncoderSettings);
@@ -54,7 +111,7 @@ public void Constructor_should_create_a_valid_instance()
54111
}
55112

56113
[Fact]
57-
public void Constructor_should_throw_when_collectionNamespace_is_null()
114+
public void Constructor_with_collection_should_throw_when_collectionNamespace_is_null()
58115
{
59116
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>((CollectionNamespace)null, __pipeline, __resultSerializer, _messageEncoderSettings));
60117

@@ -63,7 +120,7 @@ public void Constructor_should_throw_when_collectionNamespace_is_null()
63120
}
64121

65122
[Fact]
66-
public void Constructor_should_throw_when_pipeline_is_null()
123+
public void Constructor_with_collection_should_throw_when_pipeline_is_null()
67124
{
68125
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>(_collectionNamespace, null, __resultSerializer, _messageEncoderSettings));
69126

@@ -72,7 +129,7 @@ public void Constructor_should_throw_when_pipeline_is_null()
72129
}
73130

74131
[Fact]
75-
public void Constructor_should_throw_when_resultSerializer_is_null()
132+
public void Constructor_with_collection_should_throw_when_resultSerializer_is_null()
76133
{
77134
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>(_collectionNamespace, __pipeline, null, _messageEncoderSettings));
78135

@@ -81,7 +138,7 @@ public void Constructor_should_throw_when_resultSerializer_is_null()
81138
}
82139

83140
[Fact]
84-
public void Constructor_should_throw_when_messageEncoderSettings_is_null()
141+
public void Constructor_with_collection_should_throw_when_messageEncoderSettings_is_null()
85142
{
86143
var exception = Record.Exception(() => new AggregateOperation<BsonDocument>(_collectionNamespace, __pipeline, __resultSerializer, null));
87144

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

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,91 @@ namespace MongoDB.Driver.Core.Operations
3838
public class ChangeStreamOperationTests : OperationTestBase
3939
{
4040
[Fact]
41-
public void constructor_should_initialize_instance()
41+
public void constructor_with_database_should_initialize_instance()
42+
{
43+
var databaseNamespace = new DatabaseNamespace("foo");
44+
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
45+
var resultSerializer = BsonDocumentSerializer.Instance;
46+
var messageEncoderSettings = new MessageEncoderSettings();
47+
48+
var subject = new ChangeStreamOperation<BsonDocument>(databaseNamespace, pipeline, resultSerializer, messageEncoderSettings);
49+
50+
subject.BatchSize.Should().NotHaveValue();
51+
subject.Collation.Should().BeNull();
52+
subject.CollectionNamespace.Should().BeNull();
53+
subject.DatabaseNamespace.Should().Be(databaseNamespace);
54+
subject.FullDocument.Should().Be(ChangeStreamFullDocumentOption.Default);
55+
subject.MaxAwaitTime.Should().NotHaveValue();
56+
subject.MessageEncoderSettings.Should().BeSameAs(messageEncoderSettings);
57+
subject.Pipeline.Should().Equal(pipeline);
58+
subject.ReadConcern.Should().Be(ReadConcern.Default);
59+
subject.ResultSerializer.Should().BeSameAs(resultSerializer);
60+
subject.ResumeAfter.Should().BeNull();
61+
subject.StartAtOperationTime.Should().BeNull();
62+
}
63+
64+
[Fact]
65+
public void constructor_with_database_should_throw_when_databaseNamespace_is_null()
66+
{
67+
DatabaseNamespace databaseNamespace = null;
68+
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
69+
var resultSerializer = BsonDocumentSerializer.Instance;
70+
var messageEncoderSettings = new MessageEncoderSettings();
71+
72+
73+
var exception = Record.Exception(() => new ChangeStreamOperation<BsonDocument>(databaseNamespace, pipeline, resultSerializer, messageEncoderSettings));
74+
75+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
76+
argumentNullException.ParamName.Should().Be("databaseNamespace");
77+
}
78+
79+
[Fact]
80+
public void constructor_with_database_should_throw_when_pipeline_is_null()
81+
{
82+
var databaseNamespace = new DatabaseNamespace("foo");
83+
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
84+
IBsonSerializer<BsonDocument> resultSerializer = null;
85+
var messageEncoderSettings = new MessageEncoderSettings();
86+
87+
88+
var exception = Record.Exception(() => new ChangeStreamOperation<BsonDocument>(databaseNamespace, pipeline, resultSerializer, messageEncoderSettings));
89+
90+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
91+
argumentNullException.ParamName.Should().Be("resultSerializer");
92+
}
93+
94+
[Fact]
95+
public void constructor_with_database_should_throw_when_messageEncoderSettings_is_null()
96+
{
97+
var databaseNamespace = new DatabaseNamespace("foo");
98+
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
99+
var resultSerializer = BsonDocumentSerializer.Instance;
100+
MessageEncoderSettings messageEncoderSettings = null;
101+
102+
103+
var exception = Record.Exception(() => new ChangeStreamOperation<BsonDocument>(databaseNamespace, pipeline, resultSerializer, messageEncoderSettings));
104+
105+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
106+
argumentNullException.ParamName.Should().Be("messageEncoderSettings");
107+
}
108+
109+
[Fact]
110+
public void constructor_with_database_should_throw_when_resultSerializer_is_null()
111+
{
112+
var databaseNamespace = new DatabaseNamespace("foo");
113+
List<BsonDocument> pipeline = null;
114+
var resultSerializer = BsonDocumentSerializer.Instance;
115+
var messageEncoderSettings = new MessageEncoderSettings();
116+
117+
118+
var exception = Record.Exception(() => new ChangeStreamOperation<BsonDocument>(databaseNamespace, pipeline, resultSerializer, messageEncoderSettings));
119+
120+
var argumentNullException = exception.Should().BeOfType<ArgumentNullException>().Subject;
121+
argumentNullException.ParamName.Should().Be("pipeline");
122+
}
123+
124+
[Fact]
125+
public void constructor_with_collection_should_initialize_instance()
42126
{
43127
var collectionNamespace = new CollectionNamespace(new DatabaseNamespace("foo"), "bar");
44128
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
@@ -50,17 +134,19 @@ public void constructor_should_initialize_instance()
50134
subject.BatchSize.Should().NotHaveValue();
51135
subject.Collation.Should().BeNull();
52136
subject.CollectionNamespace.Should().BeSameAs(collectionNamespace);
137+
subject.DatabaseNamespace.Should().BeNull();
53138
subject.FullDocument.Should().Be(ChangeStreamFullDocumentOption.Default);
54139
subject.MaxAwaitTime.Should().NotHaveValue();
55140
subject.MessageEncoderSettings.Should().BeSameAs(messageEncoderSettings);
56141
subject.Pipeline.Should().Equal(pipeline);
57142
subject.ReadConcern.Should().Be(ReadConcern.Default);
58143
subject.ResultSerializer.Should().BeSameAs(resultSerializer);
59144
subject.ResumeAfter.Should().BeNull();
145+
subject.StartAtOperationTime.Should().BeNull();
60146
}
61147

62148
[Fact]
63-
public void constructor_should_throw_when_collectionNamespace_is_null()
149+
public void constructor_with_collection_should_throw_when_collectionNamespace_is_null()
64150
{
65151
CollectionNamespace collectionNamespace = null;
66152
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
@@ -75,7 +161,7 @@ public void constructor_should_throw_when_collectionNamespace_is_null()
75161
}
76162

77163
[Fact]
78-
public void constructor_should_throw_when_pipeline_is_null()
164+
public void constructor_with_collection_should_throw_when_pipeline_is_null()
79165
{
80166
var collectionNamespace = new CollectionNamespace(new DatabaseNamespace("foo"), "bar");
81167
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
@@ -90,7 +176,7 @@ public void constructor_should_throw_when_pipeline_is_null()
90176
}
91177

92178
[Fact]
93-
public void constructor_should_throw_when_messageEncoderSettings_is_null()
179+
public void constructor_with_collection_should_throw_when_messageEncoderSettings_is_null()
94180
{
95181
var collectionNamespace = new CollectionNamespace(new DatabaseNamespace("foo"), "bar");
96182
var pipeline = new List<BsonDocument> { BsonDocument.Parse("{ $match : { operationType : \"insert\" } }") };
@@ -105,7 +191,7 @@ public void constructor_should_throw_when_messageEncoderSettings_is_null()
105191
}
106192

107193
[Fact]
108-
public void constructor_should_throw_when_resultSerializer_is_null()
194+
public void constructor_with_collection_should_throw_when_resultSerializer_is_null()
109195
{
110196
var collectionNamespace = new CollectionNamespace(new DatabaseNamespace("foo"), "bar");
111197
List<BsonDocument> pipeline = null;
@@ -259,6 +345,20 @@ public void ResumeAfter_get_and_set_should_work(
259345
result.Should().Be(value);
260346
}
261347

348+
[Theory]
349+
[InlineData(null, null)]
350+
[InlineData(1, 2)]
351+
public void StartAtOperationTime_get_and_set_should_work(int? t, int? i)
352+
{
353+
var subject = CreateSubject();
354+
var value = t.HasValue ? new BsonTimestamp(t.Value, i.Value) : null;
355+
356+
subject.StartAtOperationTime = value;
357+
var result = subject.StartAtOperationTime;
358+
359+
result.Should().Be(value);
360+
}
361+
262362
[SkippableTheory]
263363
[ParameterAttributeData]
264364
public void Execute_should_return_expected_results_for_drop_collection(

0 commit comments

Comments
 (0)