Esempio n. 1
0
        public void CreateCommand_should_include_read_concern_when_appropriate(
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel?readConcernLevel)
        {
            var readConcern    = new ReadConcern(readConcernLevel);
            var mapFunction    = "function() { emit(this.x, this.v); }";
            var reduceFunction = "function(key, values) { var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; }; return sum; }";
            var subject        = new MapReduceLegacyOperation(_collectionNamespace, mapFunction, reduceFunction, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.ReadConcern.FirstSupportedVersion);
            var session = OperationTestHelper.CreateSession();

            var result = subject.CreateCommand(connectionDescription, session);

            if (readConcern.IsServerDefault)
            {
                result.Contains("readConcern").Should().BeFalse();
            }
            else
            {
                result["readConcern"].Should().Be(readConcern.ToBsonDocument());
            }
        }
        public void CreateCommand_should_return_the_expected_result_when_ReadConcern_is_set(
            [Values(null, ReadConcernLevel.Linearizable)]
            ReadConcernLevel?level)
        {
            var readConcern = new ReadConcern(level);
            var subject     = new AggregateOperation <BsonDocument>(_collectionNamespace, __pipeline, __resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.ReadConcern.FirstSupportedVersion);
            var session = OperationTestHelper.CreateSession();

            var result = subject.CreateCommand(connectionDescription, session);

            var expectedResult = new BsonDocument
            {
                { "aggregate", _collectionNamespace.CollectionName },
                { "pipeline", new BsonArray(__pipeline) },
                { "readConcern", () => readConcern.ToBsonDocument(), level != null },
                { "cursor", new BsonDocument() }
            };

            result.Should().Be(expectedResult);
        }
Esempio n. 3
0
        public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set(
            [Values(null, ReadConcernLevel.Linearizable, ReadConcernLevel.Local)]
            ReadConcernLevel?level)
        {
            var readConcern = new ReadConcern(level);
            var subject     = new GeoNearOperation <BsonDocument>(_collectionNamespace, _near, _resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.ReadConcern.FirstSupportedVersion);
            var session = OperationTestHelper.CreateSession();

            var result = subject.CreateCommand(connectionDescription, session);

            var expectedResult = new BsonDocument
            {
                { "geoNear", _collectionNamespace.CollectionName },
                { "near", new BsonArray {
                      1, 2
                  } },
                { "readConcern", () => readConcern.ToBsonDocument(), !readConcern.IsServerDefault }
            };

            result.Should().Be(expectedResult);
        }
        public void ToBsonDocument_should_return_expected_result(ReadConcernLevel? level, string json)
        {
            var subject = new ReadConcern(level);
            var result = subject.ToBsonDocument();

            result.Should().Be(json);
        }
Esempio n. 5
0
        public void CreateCommand_should_return_the_expected_result_when_using_causal_consistency(
            [Values(null, ReadConcernLevel.Linearizable, ReadConcernLevel.Local)]
            ReadConcernLevel?level)
        {
            var readConcern = new ReadConcern(level);
            var subject     = new GeoNearOperation <BsonDocument>(_collectionNamespace, _near, _resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(supportsSessions: true);
            var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100));

            var result = subject.CreateCommand(connectionDescription, session);

            var expectedReadConcernDocument = readConcern.ToBsonDocument();

            expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100);

            var expectedResult = new BsonDocument
            {
                { "geoNear", _collectionNamespace.CollectionName },
                { "near", new BsonArray {
                      1, 2
                  } },
                { "readConcern", expectedReadConcernDocument }
            };

            result.Should().Be(expectedResult);
        }
Esempio n. 6
0
        private void ValidateReadConcern(BsonDocument definition)
        {
            Exception   parseException = null;
            ReadConcern readConcern    = null;

            try
            {
                readConcern = ReadConcern.FromBsonDocument((BsonDocument)definition["readConcern"]);
            }
            catch (Exception ex)
            {
                parseException = ex;
            }

            if (parseException == null)
            {
                if (!(bool)definition["valid"])
                {
                    throw new AssertionException($"Should be invalid: {definition["readConcern"]}.");
                }

                var expectedDocument = (BsonDocument)definition["readConcernDocument"];
                var document         = readConcern.ToBsonDocument();
                document.Should().Be(expectedDocument);

                readConcern.IsServerDefault.Should().Be((bool)definition["isServerDefault"]);
            }
            else
            {
                if ((bool)definition["valid"])
                {
                    throw new AssertionException($"Should be valid: {definition["readConcern"]}.");
                }
            }
        }
        public void CreateCommand_should_return_the_expected_result_when_using_causal_consistency(
            [Values(null, ReadConcernLevel.Linearizable)]
            ReadConcernLevel?level)
        {
            var readConcern = new ReadConcern(level);
            var subject     = new AggregateOperation <BsonDocument>(_collectionNamespace, __pipeline, __resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.ReadConcern.FirstSupportedVersion, supportsSessions: true);
            var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100));

            var result = subject.CreateCommand(connectionDescription, session);

            var expectedReadConcernDocument = readConcern.ToBsonDocument();

            expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100);

            var expectedResult = new BsonDocument
            {
                { "aggregate", _collectionNamespace.CollectionName },
                { "pipeline", new BsonArray(__pipeline) },
                { "readConcern", expectedReadConcernDocument },
                { "cursor", new BsonDocument() }
            };

            result.Should().Be(expectedResult);
        }
Esempio n. 8
0
        // methods
        internal BsonDocument CreateCommand(SemanticVersion serverVersion)
        {
            Feature.ReadConcern.ThrowIfNotSupported(serverVersion, _readConcern);

            return(new BsonDocument
            {
                { "parallelCollectionScan", _collectionNamespace.CollectionName },
                { "numCursors", _numberOfCursors },
                { "readConcern", _readConcern.ToBsonDocument(), !_readConcern.IsServerDefault }
            });
        }
        // private methods
        internal BsonDocument CreateCommand(SemanticVersion serverVersion)
        {
            _readConcern.ThrowIfNotSupported(serverVersion);

            return(new BsonDocument
            {
                { "distinct", _collectionNamespace.CollectionName },
                { "key", _fieldName },
                { "query", _filter, _filter != null },
                { "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
                { "readConcern", () => _readConcern.ToBsonDocument(), !_readConcern.IsServerDefault }
            });
        }
        /// <inheritdoc/>
        protected internal override BsonDocument CreateCommand(SemanticVersion serverVersion)
        {
            _readConcern.ThrowIfNotSupported(serverVersion);

            var command = base.CreateCommand(serverVersion);

            if (!_readConcern.IsServerDefault)
            {
                command["readConcern"] = _readConcern.ToBsonDocument();
            }

            return(command);
        }
        public void CreateCommand_should_create_the_correct_command(
            [Values("3.0.0", "3.2.0")] string serverVersionString,
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel?readConcernLevel)
        {
            var serverVersion = SemanticVersion.Parse(serverVersionString);
            var filter        = new BsonDocument("x", 1);
            var limit         = 10;
            var maxDistance   = 30;
            var maxTime       = TimeSpan.FromMilliseconds(50);
            var near          = new BsonArray {
                10, 20
            };
            var readConcern = new ReadConcern(readConcernLevel);
            var subject     = new GeoSearchOperation <BsonDocument>(_collectionNamespace, near, BsonDocumentSerializer.Instance, _messageEncoderSettings)
            {
                Search      = filter,
                Limit       = limit,
                MaxDistance = maxDistance,
                MaxTime     = maxTime,
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(serverVersion);
            var session = OperationTestHelper.CreateSession();

            if (!readConcern.IsServerDefault && !Feature.ReadConcern.IsSupported(serverVersion))
            {
                var exception = Record.Exception(() => subject.CreateCommand(connectionDescription, session));

                exception.Should().BeOfType <MongoClientException>();
            }
            else
            {
                var result = subject.CreateCommand(connectionDescription, session);

                var expectedResult = new BsonDocument
                {
                    { "geoSearch", _collectionNamespace.CollectionName },
                    { "near", near },
                    { "limit", limit },
                    { "maxDistance", maxDistance },
                    { "search", filter },
                    { "maxTimeMS", (int)maxTime.TotalMilliseconds },
                    { "readConcern", () => readConcern.ToBsonDocument(), !readConcern.IsServerDefault }
                };
                result.Should().Be(expectedResult);
                result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32);
            }
        }
        internal BsonDocument CreateCommand(SemanticVersion serverVersion)
        {
            Feature.ReadConcern.ThrowIfNotSupported(serverVersion, _readConcern);

            return(new BsonDocument
            {
                { "geoSearch", _collectionNamespace.CollectionName },
                { "near", _near, _near != null },
                { "limit", () => _limit.Value, _limit.HasValue },
                { "maxDistance", () => _maxDistance.Value, _maxDistance.HasValue },
                { "search", _search, _search != null },
                { "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
                { "readConcern", _readConcern.ToBsonDocument(), !_readConcern.IsServerDefault }
            });
        }
        public static void AppendReadConcern(BsonDocument document, ReadConcern readConcern, ConnectionDescription connectionDescription, ICoreSession session)
        {
            var sessionsAreSupported         = connectionDescription.IsMasterResult.LogicalSessionTimeout != null;
            var shouldAppendAfterClusterTime = session.IsCausallyConsistent && session.OperationTime != null && sessionsAreSupported;
            var shouldAppendReadConcern      = !readConcern.IsServerDefault || shouldAppendAfterClusterTime;

            if (shouldAppendReadConcern)
            {
                var readConcernDocument = readConcern.ToBsonDocument();
                if (shouldAppendAfterClusterTime)
                {
                    readConcernDocument.Add("afterClusterTime", session.OperationTime);
                }
                document.Add("readConcern", readConcernDocument);
            }
        }
        // methods
        internal BsonDocument CreateCommand(SemanticVersion serverVersion)
        {
            Feature.ReadConcern.ThrowIfNotSupported(serverVersion, _readConcern);
            Feature.Collation.ThrowIfNotSupported(serverVersion, _collation);

            return(new BsonDocument
            {
                { "count", _collectionNamespace.CollectionName },
                { "query", _filter, _filter != null },
                { "limit", () => _limit.Value, _limit.HasValue },
                { "skip", () => _skip.Value, _skip.HasValue },
                { "hint", _hint, _hint != null },
                { "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
                { "readConcern", () => _readConcern.ToBsonDocument(), !_readConcern.IsServerDefault },
                { "collation", () => _collation.ToBsonDocument(), _collation != null }
            });
        }
Esempio n. 15
0
        // private static methods
        private static BsonDocument ToBsonDocument(ICoreSession session, ConnectionDescription connectionDescription, ReadConcern readConcern)
        {
            // causal consistency
            var shouldSendAfterClusterTime = AreSessionsSupported(connectionDescription) && session.IsCausallyConsistent && session.OperationTime != null;
            var shouldSendReadConcern      = !readConcern.IsServerDefault || shouldSendAfterClusterTime;

            if (shouldSendReadConcern)
            {
                var readConcernDocument = readConcern.ToBsonDocument();
                if (shouldSendAfterClusterTime)
                {
                    readConcernDocument.Add("afterClusterTime", session.OperationTime);
                }
                return(readConcernDocument);
            }

            return(null);
        }
Esempio n. 16
0
        internal BsonDocument CreateCommand(SemanticVersion serverVersion)
        {
            _readConcern.ThrowIfNotSupported(serverVersion);

            return(new BsonDocument
            {
                { "geoNear", _collectionNamespace.CollectionName },
                { "near", _near, _near != null },
                { "limit", () => _limit.Value, _limit.HasValue },
                { "maxDistance", () => _maxDistance.Value, _maxDistance.HasValue },
                { "query", _filter, _filter != null },
                { "spherical", () => _spherical.Value, _spherical.HasValue },
                { "distanceMultiplier", () => _distanceMultiplier.Value, _distanceMultiplier.HasValue },
                { "includeLocs", () => _includeLocs.Value, _includeLocs.HasValue },
                { "uniqueDocs", () => _uniqueDocs.Value, _uniqueDocs.HasValue },
                { "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
                { "readConcern", _readConcern.ToBsonDocument(), !_readConcern.IsServerDefault }
            });
        }
        public void CreateCommand_should_create_the_correct_command(
            [Values(WireVersion.Server30, WireVersion.Server32)] int maxWireVersion,
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel?readConcernLevel)
        {
            var filter      = new BsonDocument("x", 1);
            var limit       = 10;
            var maxDistance = 30;
            var maxTime     = TimeSpan.FromMilliseconds(50);
            var near        = new BsonArray {
                10, 20
            };
            var readConcern = new ReadConcern(readConcernLevel);
            var subject     = new GeoSearchOperation <BsonDocument>(_collectionNamespace, near, BsonDocumentSerializer.Instance, _messageEncoderSettings)
            {
                Search      = filter,
                Limit       = limit,
                MaxDistance = maxDistance,
                MaxTime     = maxTime,
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(maxWireVersion);
            var session = OperationTestHelper.CreateSession();

            var result = subject.CreateCommand(connectionDescription, session);

            var expectedResult = new BsonDocument
            {
                { "geoSearch", _collectionNamespace.CollectionName },
                { "near", near },
                { "limit", limit },
                { "maxDistance", maxDistance },
                { "search", filter },
                { "maxTimeMS", (int)maxTime.TotalMilliseconds },
                { "readConcern", () => readConcern.ToBsonDocument(), !readConcern.IsServerDefault }
            };

            result.Should().Be(expectedResult);
            result["maxTimeMS"].BsonType.Should().Be(BsonType.Int32);
        }
Esempio n. 18
0
        public void CreateCommand_should_include_read_concern_when_appropriate(
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel?readConcernLevel)
        {
            var readConcern    = new ReadConcern(readConcernLevel);
            var mapFunction    = "function() { emit(this.x, this.v); }";
            var reduceFunction = "function(key, values) { var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; }; return sum; }";
            var subject        = new MapReduceOperation <BsonDocument>(_collectionNamespace, mapFunction, reduceFunction, _resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var command = subject.CreateCommand(new SemanticVersion(3, 2, 0));

            if (readConcern.IsServerDefault)
            {
                command.Contains("readConcern").Should().BeFalse();
            }
            else
            {
                command["readConcern"].Should().Be(readConcern.ToBsonDocument());
            }
        }
Esempio n. 19
0
        public void CreateCommand_should_include_readConcern_when_using_causal_consistency(
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel?readConcernLevel)
        {
            var readConcern    = new ReadConcern(readConcernLevel);
            var mapFunction    = "function() { emit(this.x, this.v); }";
            var reduceFunction = "function(key, values) { var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; }; return sum; }";
            var subject        = new MapReduceLegacyOperation(_collectionNamespace, mapFunction, reduceFunction, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var connectionDescription = OperationTestHelper.CreateConnectionDescription(Feature.ReadConcern.FirstSupportedVersion, supportsSessions: true);
            var session = OperationTestHelper.CreateSession(true, new BsonTimestamp(100));

            var result = subject.CreateCommand(connectionDescription, session);

            var expectedReadConcernDocument = readConcern.ToBsonDocument();

            expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100);

            result["readConcern"].Should().Be(expectedReadConcernDocument);
        }
Esempio n. 20
0
        // methods
        private BsonDocument CreateCommand(ServerDescription serverDescription, ReadPreference readPreference)
        {
            _readConcern.ThrowIfNotSupported(serverDescription.Version);

            var firstBatchSize         = _firstBatchSize ?? (_batchSize > 0 ? _batchSize : null);
            var readPreferenceDocument = QueryHelper.CreateReadPreferenceDocument(serverDescription.Type, readPreference);
            var isShardRouter          = serverDescription.Type == ServerType.ShardRouter;

            var command = new BsonDocument
            {
                { "find", _collectionNamespace.CollectionName },
                { "filter", _filter, _filter != null },
                { "sort", _sort, _sort != null },
                { "projection", _projection, _projection != null },
                { "hint", _hint, _hint != null },
                { "skip", () => _skip.Value, _skip.HasValue },
                { "limit", () => Math.Abs(_limit.Value), _limit.HasValue&& _limit != 0 },
                { "batchSize", () => firstBatchSize.Value, firstBatchSize.HasValue },
                { "singleBatch", () => _limit < 0 || _singleBatch.Value, _limit < 0 || _singleBatch.HasValue },
                { "comment", _comment, _comment != null },
                { "maxScan", () => _maxScan.Value, _maxScan.HasValue },
                { "maxTimeMS", () => _maxTime.Value.TotalMilliseconds, _maxTime.HasValue },
                { "readPreference", readPreferenceDocument, readPreferenceDocument != null },
                { "max", _max, _max != null },
                { "min", _min, _min != null },
                { "returnKey", () => _returnKey.Value, _returnKey.HasValue },
                { "showRecordId", () => _showRecordId.Value, _showRecordId.HasValue },
                { "snapshot", () => _snapshot.Value, _snapshot.HasValue },
                { "tailable", true, _cursorType == CursorType.Tailable || _cursorType == CursorType.TailableAwait },
                { "oplogReplay", () => _oplogReplay.Value, _oplogReplay.HasValue },
                { "noCursorTimeout", () => _noCursorTimeout.Value, _noCursorTimeout.HasValue },
                { "awaitData", true, _cursorType == CursorType.TailableAwait },
                { "allowPartialResults", () => _allowPartialResults.Value, _allowPartialResults.HasValue&& isShardRouter },
                { "readConcern", () => _readConcern.ToBsonDocument(), !_readConcern.IsServerDefault }
            };

            return(command);
        }
        public void CreateCommand_should_include_readConcern_when_using_causal_consistency(
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel?readConcernLevel)
        {
            var readConcern    = new ReadConcern(readConcernLevel);
            var mapFunction    = "function() { emit(this.x, this.v); }";
            var reduceFunction = "function(key, values) { var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; }; return sum; }";

#pragma warning disable CS0618 // Type or member is obsolete
            var subject = new MapReduceLegacyOperation(_collectionNamespace, mapFunction, reduceFunction, _messageEncoderSettings)
#pragma warning restore CS0618 // Type or member is obsolete
            {
                ReadConcern = readConcern
            };

            var session = OperationTestHelper.CreateSession(isCausallyConsistent: true, operationTime: new BsonTimestamp(100));
            var connectionDescription = OperationTestHelper.CreateConnectionDescription();

            var result = subject.CreateCommand(session, connectionDescription);

            var expectedReadConcernDocument = readConcern.ToBsonDocument();
            expectedReadConcernDocument["afterClusterTime"] = new BsonTimestamp(100);

            result["readConcern"].Should().Be(expectedReadConcernDocument);
        }
        public void CreateCommand_should_return_the_expected_result_when_ReadConcern_is_set(
            [Values(null, ReadConcernLevel.Linearizable)]
            ReadConcernLevel? level)
        {
            var readConcern = new ReadConcern(level);
            var subject = new AggregateOperation<BsonDocument>(_collectionNamespace, __pipeline, __resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var result = subject.CreateCommand(Feature.ReadConcern.FirstSupportedVersion);

            var expectedResult = new BsonDocument
            {
                { "aggregate", _collectionNamespace.CollectionName },
                { "pipeline", new BsonArray(__pipeline) },
                { "readConcern", () => readConcern.ToBsonDocument(), level != null },
                { "cursor", new BsonDocument() }
            };
            result.Should().Be(expectedResult);
        }
        public void CreateCommand_should_create_the_correct_command(
            [Values("3.0.0", "3.2.0")] string serverVersionString,
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel? readConcernLevel)
        {
            var serverVersion = SemanticVersion.Parse(serverVersionString);
            var filter = new BsonDocument("x", 1);
            var limit = 10;
            var maxDistance = 30;
            var maxTime = TimeSpan.FromMilliseconds(50);
            var near = new BsonArray { 10, 20 };
            var readConcern = new ReadConcern(readConcernLevel);
            var subject = new GeoSearchOperation<BsonDocument>(_collectionNamespace, near, BsonDocumentSerializer.Instance, _messageEncoderSettings)
            {
                Search = filter,
                Limit = limit,
                MaxDistance = maxDistance,
                MaxTime = maxTime,
                ReadConcern = readConcern
            };

            if (!readConcern.IsServerDefault && !Feature.ReadConcern.IsSupported(serverVersion))
            {
                var exception = Record.Exception(() => subject.CreateCommand(serverVersion));

                exception.Should().BeOfType<MongoClientException>();
            }
            else
            {
                var result = subject.CreateCommand(serverVersion);

                var expectedResult = new BsonDocument
                {
                    { "geoSearch", _collectionNamespace.CollectionName },
                    { "near", near },
                    { "limit", limit },
                    { "maxDistance", maxDistance },
                    { "search", filter },
                    { "maxTimeMS", maxTime.TotalMilliseconds },
                    { "readConcern", () => readConcern.ToBsonDocument(), !readConcern.IsServerDefault }
                };
                result.Should().Be(expectedResult);

            }
        }
        public void CreateCommand_should_include_read_concern_when_appropriate(
            [Values(null, ReadConcernLevel.Local, ReadConcernLevel.Majority)] ReadConcernLevel? readConcernLevel)
        {
            var readConcern = new ReadConcern(readConcernLevel);
            var mapFunction = "function() { emit(this.x, this.v); }";
            var reduceFunction = "function(key, values) { var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; }; return sum; }";
            var subject = new MapReduceLegacyOperation(_collectionNamespace, mapFunction, reduceFunction, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var command = subject.CreateCommand(new SemanticVersion(3, 2, 0));

            if (readConcern.IsServerDefault)
            {
                command.Contains("readConcern").Should().BeFalse();
            }
            else
            {
                command["readConcern"].Should().Be(readConcern.ToBsonDocument());
            }
        }
        public void CreateCommand_should_return_expected_result_when_ReadConcern_is_set(
            [Values(null, ReadConcernLevel.Linearizable, ReadConcernLevel.Local)]
            ReadConcernLevel? level)
        {
            var readConcern = new ReadConcern(level);
            var subject = new GeoNearOperation<BsonDocument>(_collectionNamespace, _near, _resultSerializer, _messageEncoderSettings)
            {
                ReadConcern = readConcern
            };

            var result = subject.CreateCommand(Feature.ReadConcern.FirstSupportedVersion);

            var expectedResult = new BsonDocument
            {
                { "geoNear", _collectionNamespace.CollectionName },
                { "near", new BsonArray { 1, 2 } },
                { "readConcern", () => readConcern.ToBsonDocument(), !readConcern.IsServerDefault }
            };
            result.Should().Be(expectedResult);
        }