Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
566 changes: 557 additions & 9 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
services:
mongodb:
image: mongo:8
container_name: mongodb-test
command: >
mongod
--replSet rs0
--bind_ip_all
--setParameter enableTestCommands=1
ports:
- "56665:27017"
volumes:
- mongodb_data:/data/db
healthcheck:
test: |
mongosh --quiet --eval "
try {
rs.status();
print('Replica set initialized');
} catch(e) {
print('Initializing replica set...');
rs.initiate({
_id: 'rs0',
members: [{ _id: 0, host: 'localhost:27017' }]
});
}
"
interval: 5s
timeout: 10s
retries: 10
start_period: 10s

volumes:
mongodb_data:
driver: local
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ internal sealed class AutoEncryptionProviderRegistry : IAutoEncryptionProviderRe

public void Register(Func<IMongoClient, AutoEncryptionOptions, IAutoEncryptionLibMongoCryptController> factory)
{
if(ReferenceEquals(factory, _autoCryptClientControllerFactory))
{
return;
}

if (_autoCryptClientControllerFactory != null)
{
throw new MongoConfigurationException("AutoEncryption Provider already registered.");
}

_autoCryptClientControllerFactory = factory;
}

Expand Down
102 changes: 102 additions & 0 deletions start-mongodb.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/bin/bash

# MongoDB Test Environment Startup Script
# Starts MongoDB with single-node replica set and test commands enabled

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Function to print colored messages
print_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}

print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}

print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}

# Check if Docker is installed
if ! command -v docker &> /dev/null; then
print_error "Docker is not installed. Please install Docker first."
exit 1
fi

# Check if Docker Compose is available
if ! docker compose version &> /dev/null; then
print_error "Docker Compose is not available. Please install Docker Compose."
exit 1
fi

# Check if docker-compose.yml exists
if [ ! -f "docker-compose.yml" ]; then
print_error "docker-compose.yml not found in current directory."
exit 1
fi

print_info "Starting MongoDB with test commands enabled..."

# Stop any existing containers
docker compose down 2>/dev/null || true

# Start MongoDB
docker compose up -d

print_info "Waiting for MongoDB to be ready..."

# Wait for container to be healthy
max_attempts=30
attempt=0
while [ $attempt -lt $max_attempts ]; do
if docker compose ps | grep -q "healthy"; then
print_success "MongoDB is ready!"
break
fi

attempt=$((attempt + 1))
if [ $attempt -eq $max_attempts ]; then
print_error "MongoDB failed to start within expected time."
print_info "Showing container logs:"
docker compose logs
exit 1
fi

echo -n "."
sleep 2
done

echo ""

# Display connection information
print_success "MongoDB is running with the following configuration:"
echo ""
echo " • Single-node replica set: rs0"
echo " • Test commands: ENABLED"
echo " • Port: 56665"
echo ""
echo "Connection String:"
echo " mongodb://localhost:56665/?replicaSet=rs0&directConnection=true"
echo ""
echo "C# Driver Connection String:"
echo ' var connectionString = "mongodb://localhost:56665/?replicaSet=rs0&directConnection=true";'
echo ' var client = new MongoClient(connectionString);'
echo ""
print_info "To stop MongoDB, run:"
echo " docker compose down"
echo ""
print_info "To view logs, run:"
echo " docker compose logs -f"
echo ""
3 changes: 3 additions & 0 deletions tests/AtlasConnectivity.Tests/ConnectivityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Core.TestHelpers.Logging;
using MongoDB.TestHelpers.XunitExtensions;
using Xunit;
using Xunit.Abstractions;

Expand Down Expand Up @@ -46,6 +47,8 @@ public ConnectivityTests(ITestOutputHelper testOutputHelper)
[InlineData("ATLAS_SRV_TLS12")]
public void Connection_to_Atlas_should_work(string environmentVariableName)
{
RequireEnvironment.Check().EnvironmentVariable(environmentVariableName);

var connectionString = Environment.GetEnvironmentVariable(environmentVariableName);
connectionString.Should().NotBeNull();

Expand Down
4 changes: 4 additions & 0 deletions tests/AtlasConnectivity.Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,9 @@
*/

using System.Runtime.InteropServices;
using MongoDB.TestHelpers.XunitExtensions;
using Xunit;

[assembly: ComVisible(false)]

[assembly: TestFramework(XunitExtensionsConstants.TimeoutEnforcingXunitFramework, XunitExtensionsConstants.TimeoutEnforcingFrameworkAssembly)]
11 changes: 4 additions & 7 deletions tests/MongoDB.Driver.Examples/CausalConsistencyExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,10 @@ public void Causal_Consistency_Example_3()
DropCollection(CreateClient(), "myDatabase", "myCollection");

// Start Tunable Consistency Controls Example
var connectionString = "mongodb://localhost/?readPreference=secondaryPreferred";
var clientSettings = MongoClientSettings.FromConnectionString(CoreTestConfiguration.ConnectionString.ToString());
clientSettings.ReadPreference = ReadPreference.SecondaryPreferred;

var client = new MongoClient(connectionString);
var client = new MongoClient(clientSettings);
var database = client.GetDatabase("myDatabase");
var collection = database.GetCollection<BsonDocument>("myCollection");

Expand All @@ -147,11 +148,7 @@ public void Causal_Consistency_Example_3()
result.Should().Be("{ name: 'John' }");
}

private IMongoClient CreateClient()
{
var connectionString = CoreTestConfiguration.ConnectionString.ToString();
return new MongoClient(connectionString);
}
private IMongoClient CreateClient() => new MongoClient(CoreTestConfiguration.ConnectionString.ToString());

private void DropCollection(IMongoClient client, string databaseName, string collectionName)
{
Expand Down
64 changes: 41 additions & 23 deletions tests/MongoDB.Driver.Examples/ChangeStreamExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using MongoDB.Bson;
using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
Expand All @@ -37,12 +36,13 @@ public void ChangeStreamExample1()
var inventory = database.GetCollection<BsonDocument>("inventory");

var document = new BsonDocument("x", 1);
new Thread(() =>
var thread = new Thread(() =>
{
Thread.Sleep(TimeSpan.FromMilliseconds(100));
inventory.InsertOne(document);
})
.Start();
});

thread.Start();

// Start Changestream Example 1
var cursor = inventory.Watch();
Expand All @@ -52,6 +52,9 @@ public void ChangeStreamExample1()
// End Changestream Example 1

next.FullDocument.Should().Be(document);

// Make sure worker thread is finished before we let the next test run.
thread.Join();
}

[Fact]
Expand All @@ -64,14 +67,15 @@ public void ChangeStreamExample2()

var document = new BsonDocument("x", 1);
inventory.InsertOne(document);
new Thread(() =>
var thread = new Thread(() =>
{
Thread.Sleep(TimeSpan.FromMilliseconds(100));
var filter = new BsonDocument("_id", document["_id"]);
var update = "{ $set : { x : 2 } }";
inventory.UpdateOne(filter, update);
})
.Start();
});

thread.Start();

// Start Changestream Example 2
var options = new ChangeStreamOptions { FullDocument = ChangeStreamFullDocumentOption.UpdateLookup };
Expand All @@ -83,6 +87,9 @@ public void ChangeStreamExample2()

var expectedFullDocument = document.Set("x", 2);
next.FullDocument.Should().Be(expectedFullDocument);

// Make sure worker thread is finished before we let the next test run.
thread.Join();
}

[Fact]
Expand All @@ -101,15 +108,19 @@ public void ChangeStreamExample3()

IChangeStreamCursor<ChangeStreamDocument<BsonDocument>> previousCursor;
{
new Thread(() =>
var thread = new Thread(() =>
{
Thread.Sleep(TimeSpan.FromMilliseconds(100));
inventory.InsertMany(documents);
})
.Start();
});

thread.Start();

previousCursor = inventory.Watch(new ChangeStreamOptions { BatchSize = 1 });
while (previousCursor.MoveNext() && previousCursor.Current.Count() == 0) { } // keep calling MoveNext until we've read the first batch

// Make sure worker thread is finished before we let the next test run.
thread.Join();
}

{
Expand All @@ -135,22 +146,24 @@ public void ChangestreamExample4()
var database = client.GetDatabase("ChangeStreamExamples");
database.DropCollection("inventory");

using var cancelationTokenSource = new CancellationTokenSource();
try
var stopEvent = new ManualResetEventSlim(false);
var document = new BsonDocument("username", "alice");

var thread = new Thread(() =>
{
var document = new BsonDocument("username", "alice");
var inventoryCollection = database.GetCollection<BsonDocument>("inventory");

Task.Run(() =>
while (!stopEvent.IsSet)
{
var inventoryCollection = database.GetCollection<BsonDocument>("inventory");
Thread.Sleep(TimeSpan.FromMilliseconds(100));
document["_id"] = ObjectId.GenerateNewId();
inventoryCollection.InsertOne(document);
}
});

while (!cancelationTokenSource.IsCancellationRequested)
{
Thread.Sleep(TimeSpan.FromMilliseconds(100));
document["_id"] = ObjectId.GenerateNewId();
inventoryCollection.InsertOne(document);
}
}, cancelationTokenSource.Token);
try
{
thread.Start();

// Start Changestream Example 4
var pipeline = new EmptyPipelineDefinition<ChangeStreamDocument<BsonDocument>>()
Expand All @@ -170,7 +183,12 @@ public void ChangestreamExample4()
}
finally
{
cancelationTokenSource.Cancel();
stopEvent.Set();

// Make sure the worker thread is finished before we let the next test run.
// Especially important for this test case since the thread continually inserts documents.
thread.Join();
stopEvent.Dispose();
}
}
}
Expand Down
15 changes: 6 additions & 9 deletions tests/MongoDB.Driver.Examples/ClientEncryptionExamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ public void ClientSideEncryptionSimpleTour()
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var autoEncryptionOptions = new AutoEncryptionOptions(keyVaultNamespace, kmsProviders);

var mongoClientSettings = new MongoClientSettings
{
AutoEncryptionOptions = autoEncryptionOptions
};
var mongoClientSettings = MongoClientSettings.FromConnectionString(InfrastructureUtilities.MongoUri);
mongoClientSettings.AutoEncryptionOptions = autoEncryptionOptions;

var client = new MongoClient(mongoClientSettings);
var database = client.GetDatabase("test");
Expand Down Expand Up @@ -87,7 +85,7 @@ public void ClientSideEncryptionAutoEncryptionSettingsTour()
kmsProviders.Add("local", localKey);

var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var keyVaultMongoClient = new MongoClient();
var keyVaultMongoClient = new MongoClient(InfrastructureUtilities.MongoUri);
var clientEncryptionSettings = new ClientEncryptionOptions(
keyVaultMongoClient,
keyVaultNamespace,
Expand Down Expand Up @@ -124,10 +122,9 @@ public void ClientSideEncryptionAutoEncryptionSettingsTour()
{
{ collectionNamespace.ToString(), BsonDocument.Parse(schemaMap) }
});
var clientSettings = new MongoClientSettings
{
AutoEncryptionOptions = autoEncryptionSettings
};

var clientSettings = MongoClientSettings.FromConnectionString(InfrastructureUtilities.MongoUri);
clientSettings.AutoEncryptionOptions = autoEncryptionSettings;

var client = new MongoClient(clientSettings);
var database = client.GetDatabase("test");
Expand Down
Loading