public void Authentication_succeeds_with_MONGODB_X509_mechanism( [Values(false, true)] bool async) { RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH", isDefined: true); RequireEnvironment.Check().EnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD", isDefined: true); RequireServer.Check().Tls(required: true); var pathToClientCertificate = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH"); var password = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD"); var clientCertificate = new X509Certificate2(pathToClientCertificate, password); var userName = GetRfc2253FormattedUsernameFromX509ClientCertificate(clientCertificate); DropDatabaseUser(DriverTestConfiguration.Client, database: "$external", userName); CreateX509DatabaseUser(DriverTestConfiguration.Client, userName); var settings = DriverTestConfiguration.GetClientSettings().Clone(); var serverVersion = CoreTestConfiguration.ServerVersion; if (Feature.ServerExtractsUsernameFromX509Certificate.IsSupported(serverVersion)) { settings.Credential = MongoCredential.CreateMongoX509Credential(); } else { settings.Credential = MongoCredential.CreateMongoX509Credential(userName); } settings.SslSettings = settings.SslSettings.Clone(); settings.SslSettings.ClientCertificates = new[] { clientCertificate }; AssertAuthenticationSucceeds(settings, async, speculativeAuthenticatationShouldSucceedIfPossible: true); }
public void Should_call_custom_server_selector() { var eventCapturer = new EventCapturer() .Capture <ClusterSelectingServerEvent>() .Capture <ClusterSelectedServerEvent>(); var customServerSelector = new CustomServerSelector(); using (var client = DriverTestConfiguration.CreateDisposableClient( clientSettings => clientSettings.ClusterConfigurator = c => { c.ConfigureCluster(s => s.With(postServerSelector: customServerSelector)); c.Subscribe(eventCapturer); }, logger: null)) { var collection = client .GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName) .GetCollection <BsonDocument>(DriverTestConfiguration.CollectionNamespace.CollectionName) .WithReadPreference(ReadPreference.Nearest); customServerSelector.CustomSelectorWasCalled = false; eventCapturer.Clear(); collection.CountDocuments(new BsonDocument()); customServerSelector.CustomSelectorWasCalled.Should().BeTrue(); eventCapturer.Next().Should().BeOfType <ClusterSelectingServerEvent>(); eventCapturer.Next().Should().BeOfType <ClusterSelectedServerEvent>(); } }
private void AssertAuthenticationSucceeds( MongoClientSettings settings, bool async, bool speculativeAuthenticatationShouldSucceedIfPossible = true) { // If we don't use a DisposableClient, the second run of AuthenticationSucceedsWithMongoDB_X509_mechanism // will fail because the backing Cluster's connections will be associated with a dropped user using (var client = DriverTestConfiguration.CreateDisposableclient(settings)) { // The first command executed with the MongoClient triggers either the sync or async variation of the // MongoClient's IAuthenticator if (async) { _ = client.ListDatabaseNamesAsync().GetAwaiter().GetResult().ToList(); } else { _ = client.ListDatabaseNames().ToList(); } if (Feature.SpeculativeAuthentication.IsSupported(CoreTestConfiguration.ServerVersion) && speculativeAuthenticatationShouldSucceedIfPossible) { var cancellationToken = CancellationToken.None; var serverSelector = new ReadPreferenceServerSelector(settings.ReadPreference); var server = client.Cluster.SelectServer(serverSelector, cancellationToken); var channel = server.GetChannel(cancellationToken); var isMasterResult = channel.ConnectionDescription.IsMasterResult; isMasterResult.SpeculativeAuthenticate.Should().NotBeNull(); } } }
public void KillCursor_should_actually_work() { RequireServer.Check().Supports(Feature.KillCursorsCommand); var eventCapturer = new EventCapturer().Capture <CommandSucceededEvent>(x => x.CommandName.Equals("killCursors")); using (var client = DriverTestConfiguration.CreateDisposableClient(eventCapturer)) { IAsyncCursor <BsonDocument> cursor; var database = client.GetDatabase("test"); var collection = database.GetCollection <BsonDocument>(GetType().Name); var documents = new List <BsonDocument>(); for (int i = 0; i < 1000; i++) { documents.Add(new BsonDocument("x", i)); } collection.InsertMany(documents); cursor = collection.FindSync("{}"); cursor.MoveNext(); var cursorId = ((AsyncCursor <BsonDocument>)cursor)._cursorId(); cursorId.Should().NotBe(0); cursor.Dispose(); var desiredResult = BsonDocument.Parse($"{{ \"cursorsKilled\" : [{cursorId}], \"cursorsNotFound\" : [], " + $"\"cursorsAlive\" : [], \"cursorsUnknown\" : [], \"ok\" : 1.0 }}"); var result = ((CommandSucceededEvent)eventCapturer.Events[0]).Reply; result.IsSameOrEqualTo(desiredResult); } }
private DisposableMongoClient CreateDisposableClient(EventCapturer eventCapturer, bool useMultipleShardRouters) { return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings settings) => { settings.ClusterConfigurator = c => c.Subscribe(eventCapturer); }, useMultipleShardRouters)); }
// private methods private DisposableMongoClient CreateDisposableClient(EventCapturer eventCapturer, ReadPreference readPreference) { return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings settings) => { settings.ClusterConfigurator = c => c.Subscribe(eventCapturer); settings.ReadPreference = readPreference; })); }
private DisposableMongoClient GetClient(Action <ClusterBuilder> clusterConfigurator) { return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings clientSettings) => { clientSettings.ClusterConfigurator = clusterConfigurator; clientSettings.RetryWrites = true; })); }
private DisposableMongoClient CreateDisposableClient(EventCapturer capturedEvents) { return(DriverTestConfiguration.CreateDisposableClient( settings => { settings.RetryWrites = false; settings.ClusterConfigurator = c => { c.Subscribe(capturedEvents); }; })); }
private DisposableMongoClient GetClient(Action <ClusterBuilder> clusterConfigurator, bool retryWrites = true) { return(DriverTestConfiguration.CreateDisposableClient((MongoClientSettings clientSettings) => { clientSettings.ClusterConfigurator = clusterConfigurator; clientSettings.RetryWrites = retryWrites; }, logger: CreateLogger <DisposableMongoClient>())); }
public void ListDatabases_should_invoke_the_correct_operation( [Values(false, true)] bool usingSession, [Values(false, true)] bool async) { var operationExecutor = new MockOperationExecutor(); var subject = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings()); var session = CreateClientSession(); var cancellationToken = new CancellationTokenSource().Token; var filterDocument = BsonDocument.Parse("{ name : \"awesome\" }"); var filterDefinition = (FilterDefinition <BsonDocument>)filterDocument; var nameOnly = true; var options = new ListDatabasesOptions { Filter = filterDefinition, NameOnly = nameOnly }; if (usingSession) { if (async) { subject.ListDatabasesAsync(session, options, cancellationToken).GetAwaiter().GetResult(); } else { subject.ListDatabases(session, options, cancellationToken); } } else { if (async) { subject.ListDatabasesAsync(options, cancellationToken).GetAwaiter().GetResult(); } else { subject.ListDatabases(options, cancellationToken); } } var call = operationExecutor.GetReadCall <IAsyncCursor <BsonDocument> >(); if (usingSession) { call.SessionId.Should().BeSameAs(session.ServerSession.Id); } else { call.UsedImplicitSession.Should().BeTrue(); } call.CancellationToken.Should().Be(cancellationToken); var operation = call.Operation.Should().BeOfType <ListDatabasesOperation>().Subject; operation.Filter.Should().Be(filterDocument); operation.NameOnly.Should().Be(nameOnly); }
private DisposableMongoClient CreateDisposableClient(EventCapturer capturedEvents) { return(DriverTestConfiguration.CreateDisposableClient( settings => { settings.HeartbeatInterval = TimeSpan.FromMilliseconds(5); // the default value for spec tests settings.RetryWrites = false; settings.ClusterConfigurator = c => { c.Subscribe(capturedEvents); }; })); }
public void DropDatabase_should_invoke_the_correct_operation( [Values(false, true)] bool usingSession, [Values(false, true)] bool async) { var operationExecutor = new MockOperationExecutor(); var writeConcern = new WriteConcern(1); var subject = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings()).WithWriteConcern(writeConcern); var session = CreateClientSession(); var cancellationToken = new CancellationTokenSource().Token; if (usingSession) { if (async) { subject.DropDatabaseAsync(session, "awesome", cancellationToken).GetAwaiter().GetResult(); } else { subject.DropDatabase(session, "awesome", cancellationToken); } } else { if (async) { subject.DropDatabaseAsync("awesome", cancellationToken).GetAwaiter().GetResult(); } else { subject.DropDatabase("awesome", cancellationToken); } } var call = operationExecutor.GetWriteCall <BsonDocument>(); if (usingSession) { call.SessionId.Should().BeSameAs(session.ServerSession.Id); } else { call.UsedImplicitSession.Should().BeTrue(); } call.CancellationToken.Should().Be(cancellationToken); var dropDatabaseOperation = call.Operation.Should().BeOfType <DropDatabaseOperation>().Subject; dropDatabaseOperation.DatabaseNamespace.Should().Be(new DatabaseNamespace("awesome")); dropDatabaseOperation.WriteConcern.Should().BeSameAs(writeConcern); }
private DisposableMongoClient CreateDisposableClient(EventCapturer eventCapturer, bool useMultipleShardRouters) { // Increase localThresholdMS and wait until all nodes are discovered to avoid false positives. var client = DriverTestConfiguration.CreateDisposableClient((MongoClientSettings settings) => { settings.ClusterConfigurator = c => c.Subscribe(eventCapturer); settings.LocalThreshold = TimeSpan.FromMilliseconds(1000); }, useMultipleShardRouters); var timeOut = TimeSpan.FromSeconds(60); SpinWait.SpinUntil(() => client.Cluster.Description.Type != ClusterType.Unknown, timeOut).Should().BeTrue(); return(client); }
public static MongoServer GetServer( bool?retryWrites = null) { var settings = DriverTestConfiguration.GetClientSettings(); if (retryWrites.HasValue) { settings.RetryWrites = retryWrites.Value; } var client = new MongoClient(settings); #pragma warning disable 618 return(client.GetServer()); #pragma warning restore 618 }
private void AssertAuthenticationFails(MongoClientSettings settings, bool async) { using (var client = DriverTestConfiguration.CreateDisposableclient(settings)) { Exception exception; if (async) { exception = Record.Exception(() => client.ListDatabaseNamesAsync().GetAwaiter().GetResult().ToList()); } else { exception = Record.Exception(() => client.ListDatabaseNames().ToList()); } exception.Should().BeOfType <MongoAuthenticationException>(); } }
public void ListDatabases_should_invoke_the_correct_operation( [Values(false, true)] bool usingSession, [Values(false, true)] bool async) { var operationExecutor = new MockOperationExecutor(); var subject = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings()); var session = CreateClientSession(); var cancellationToken = new CancellationTokenSource().Token; if (usingSession) { if (async) { subject.ListDatabasesAsync(session, cancellationToken).GetAwaiter().GetResult(); } else { subject.ListDatabases(session, cancellationToken); } } else { if (async) { subject.ListDatabasesAsync(cancellationToken).GetAwaiter().GetResult(); } else { subject.ListDatabases(cancellationToken); } } var call = operationExecutor.GetReadCall <IAsyncCursor <BsonDocument> >(); if (usingSession) { call.SessionId.Should().BeSameAs(session.ServerSession.Id); } else { call.UsedImplicitSession.Should().BeTrue(); } call.CancellationToken.Should().Be(cancellationToken); call.Operation.Should().BeOfType <ListDatabasesOperation>(); }
// private methods /* We can't use DriverTestConfiguration.CreateDisposableClient because that results in a call to check * the cluster type, which fails because a connection cannot be established to the mongod when testing * the revoked certificate case */ private DisposableMongoClient CreateDisposableMongoClient(bool tlsInsecure) { var settings = DriverTestConfiguration.GetClientSettings().Clone(); settings.SslSettings = new SslSettings { CheckCertificateRevocation = true }; // setting AllowInsecureTls= true will automatically set CheckCertificateRevocation to false settings.AllowInsecureTls = tlsInsecure; /* We want the heartbeat to fire so that we can get the HeartBeat exception in the cluster description * in the exception that will be thrown when testing invalid certificates */ settings.HeartbeatInterval = TimeSpan.FromMilliseconds(500); /* We lower the server selection timeout to speed up tests, but choosing a value <=5s may * result in the driver being unable to perform OCSP endpoint checking in time, causing a * ServerSelectionTimeout that does include a certificate revocation status error message. */ settings.ServerSelectionTimeout = TimeSpan.FromSeconds(5 * 2); // must be > 5s // settings.SdamLogFilename = @"C:\temp\sdam" + $"{tlsInsecure}.log"; return(new DisposableMongoClient(new MongoClient(settings))); }
public void Connection_pool_should_not_be_cleared_when_replSetStepDown_and_GetMore([Values(false, true)] bool async) { RequireServer.Check().Supports(Feature.KeepConnectionPoolWhenReplSetStepDown).ClusterType(ClusterType.ReplicaSet); var eventCapturer = new EventCapturer().Capture <ConnectionPoolClearedEvent>(); using (var client = CreateDisposableClient(eventCapturer)) { var database = client.GetDatabase(_databaseName, new MongoDatabaseSettings { WriteConcern = WriteConcern.WMajority }); database.DropCollection(_databaseName); var collection = database.GetCollection <BsonDocument>(_collectionName, new MongoCollectionSettings { WriteConcern = WriteConcern.WMajority }); var adminDatabase = client.GetDatabase("admin").WithWriteConcern(WriteConcern.W1); collection.InsertMany( new[] { new BsonDocument("x", 1), new BsonDocument("x", 2), new BsonDocument("x", 3), new BsonDocument("x", 4), new BsonDocument("x", 5), }); eventCapturer.Clear(); var cursor = collection.FindSync(FilterDefinition <BsonDocument> .Empty, new FindOptions <BsonDocument> { BatchSize = 2 }); cursor.MoveNext(); foreach (var secondary in client.Cluster.Description.Servers.Where(c => c.Type == ServerType.ReplicaSetSecondary)) { RunOnSecondary(client, secondary.EndPoint, BsonDocument.Parse("{ replSetFreeze : 0 }")); } var replSetStepDownCommand = BsonDocument.Parse("{ replSetStepDown : 30, force : true }"); BsonDocument replSetStepDownResult; if (async) { replSetStepDownResult = adminDatabase.RunCommandAsync <BsonDocument>(replSetStepDownCommand).GetAwaiter().GetResult(); } else { replSetStepDownResult = adminDatabase.RunCommand <BsonDocument>(replSetStepDownCommand); } replSetStepDownResult.Should().NotBeNull(); replSetStepDownResult.GetValue("ok", false).ToBoolean().Should().BeTrue(); cursor.MoveNext(); eventCapturer.Events.Should().BeEmpty(); // it also means that no new PoolClearedEvent } void RunOnSecondary(IMongoClient primaryClient, EndPoint secondaryEndpoint, BsonDocument command) { var secondarySettings = primaryClient.Settings.Clone(); secondarySettings.ClusterConfigurator = null; #pragma warning disable CS0618 // Type or member is obsolete secondarySettings.ConnectionMode = ConnectionMode.Direct; #pragma warning restore CS0618 // Type or member is obsolete var secondaryDnsEndpoint = (DnsEndPoint)secondaryEndpoint; secondarySettings.Server = new MongoServerAddress(secondaryDnsEndpoint.Host, secondaryDnsEndpoint.Port); using (var secondaryClient = DriverTestConfiguration.CreateDisposableClient(secondarySettings)) { var adminDatabase = secondaryClient.GetDatabase(DatabaseNamespace.Admin.DatabaseName); adminDatabase.RunCommand <BsonDocument>(command); } } }
public void ListDatabaseNames_should_invoke_the_correct_operation( [Values(false, true)] bool usingSession, [Values(false, true)] bool async) { var operationExecutor = new MockOperationExecutor(); var subject = new MongoClient(operationExecutor, DriverTestConfiguration.GetClientSettings()); var session = CreateClientSession(); var cancellationToken = new CancellationTokenSource().Token; var listDatabaseNamesResult = @" { ""databases"" : [ { ""name"" : ""admin"", ""sizeOnDisk"" : 131072, ""empty"" : false }, { ""name"" : ""blog"", ""sizeOnDisk"" : 11669504, ""empty"" : false }, { ""name"" : ""test-chambers"", ""sizeOnDisk"" : 222883840, ""empty"" : false }, { ""name"" : ""recipes"", ""sizeOnDisk"" : 73728, ""empty"" : false }, { ""name"" : ""employees"", ""sizeOnDisk"" : 225280, ""empty"" : false } ], ""totalSize"" : 252534784, ""ok"" : 1 }"; var operationResult = BsonDocument.Parse(listDatabaseNamesResult); operationExecutor.EnqueueResult(CreateListDatabasesOperationCursor(operationResult)); IList <string> databaseNames; if (async) { if (usingSession) { databaseNames = subject.ListDatabaseNamesAsync(session, cancellationToken).GetAwaiter().GetResult().ToList(); } else { databaseNames = subject.ListDatabaseNamesAsync(cancellationToken).GetAwaiter().GetResult().ToList(); } } else { if (usingSession) { databaseNames = subject.ListDatabaseNames(session, cancellationToken).ToList(); } else { databaseNames = subject.ListDatabaseNames(cancellationToken).ToList(); } } var call = operationExecutor.GetReadCall <IAsyncCursor <BsonDocument> >(); if (usingSession) { call.SessionId.Should().BeSameAs(session.ServerSession.Id); } else { call.UsedImplicitSession.Should().BeTrue(); } call.CancellationToken.Should().Be(cancellationToken); var operation = call.Operation.Should().BeOfType <ListDatabasesOperation>().Subject; operation.NameOnly.Should().Be(true); databaseNames.Should().Equal(operationResult["databases"].AsBsonArray.Select(record => record["name"].AsString)); }
public void Watch_should_invoke_the_correct_operation( [Values(false, true)] bool usingSession, [Values(false, true)] bool async) { var operationExecutor = new MockOperationExecutor(); var clientSettings = DriverTestConfiguration.GetClientSettings(); var subject = new MongoClient(operationExecutor, clientSettings); var session = usingSession ? CreateClientSession() : null; var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <BsonDocument> >().Limit(1); var options = new ChangeStreamOptions { BatchSize = 123, Collation = new Collation("en-us"), FullDocument = ChangeStreamFullDocumentOption.UpdateLookup, MaxAwaitTime = TimeSpan.FromSeconds(123), ResumeAfter = new BsonDocument(), StartAtOperationTime = new BsonTimestamp(1, 2) }; var cancellationToken = new CancellationTokenSource().Token; var renderedPipeline = new[] { BsonDocument.Parse("{ $limit : 1 }") }; if (usingSession) { if (async) { subject.WatchAsync(session, pipeline, options, cancellationToken).GetAwaiter().GetResult(); } else { subject.Watch(session, pipeline, options, cancellationToken); } } else { if (async) { subject.WatchAsync(pipeline, options, cancellationToken).GetAwaiter().GetResult(); } else { subject.Watch(pipeline, options, cancellationToken); } } var call = operationExecutor.GetReadCall <IAsyncCursor <ChangeStreamDocument <BsonDocument> > >(); if (usingSession) { call.SessionId.Should().BeSameAs(session.ServerSession.Id); } else { call.UsedImplicitSession.Should().BeTrue(); } call.CancellationToken.Should().Be(cancellationToken); var changeStreamOperation = call.Operation.Should().BeOfType <ChangeStreamOperation <ChangeStreamDocument <BsonDocument> > >().Subject; changeStreamOperation.BatchSize.Should().Be(options.BatchSize); changeStreamOperation.Collation.Should().BeSameAs(options.Collation); changeStreamOperation.CollectionNamespace.Should().BeNull(); changeStreamOperation.DatabaseNamespace.Should().BeNull(); changeStreamOperation.FullDocument.Should().Be(options.FullDocument); changeStreamOperation.MaxAwaitTime.Should().Be(options.MaxAwaitTime); changeStreamOperation.MessageEncoderSettings.Should().NotBeNull(); changeStreamOperation.Pipeline.Should().Equal(renderedPipeline); changeStreamOperation.ReadConcern.Should().Be(clientSettings.ReadConcern); changeStreamOperation.ResultSerializer.Should().BeOfType <ChangeStreamDocumentSerializer <BsonDocument> >(); changeStreamOperation.ResumeAfter.Should().Be(options.ResumeAfter); changeStreamOperation.StartAtOperationTime.Should().Be(options.StartAtOperationTime); }
private DisposableMongoClient GetClient(EventCapturer capturer) { return(DriverTestConfiguration.CreateDisposableClient(capturer)); }