Skip to content
Merged
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
3 changes: 1 addition & 2 deletions .github/workflows/mevd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,9 @@ jobs:
fail-fast: false
matrix:
provider: ${{ fromJson(needs.discover.outputs.all_providers) }}
# AzureAISearch and AzureDocumentDB require cloud instances and can't run in CI.
# AzureAISearch requires a cloud instance and can't run in CI.
exclude:
- provider: AzureAISearch
- provider: AzureDocumentDB
steps:
- uses: actions/checkout@v6

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" />
<PackageReference Include="Testcontainers" />
</ItemGroup>

<ItemGroup>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Net.Security;
using System.Security.Authentication;
using CommunityToolkit.VectorData.AzureDocumentDB;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Containers;
using MongoDB.Bson;
using MongoDB.Driver;
using VectorData.ConformanceTests.Support;

Expand All @@ -11,36 +16,80 @@ namespace AzureDocumentDB.ConformanceTests.Support;
public sealed class DocumentDBTestStore : TestStore
#pragma warning restore CA1001
{
private const string Username = "testuser";
private const string Password = "TestPassword123!";
private const ushort DocumentDBPort = 10260;

public static DocumentDBTestStore Instance { get; } = new();

private readonly IContainer _container = new ContainerBuilder("ghcr.io/microsoft/documentdb/documentdb-local:latest")
.WithPortBinding(DocumentDBPort, assignRandomHostPort: true)
.WithEnvironment("USERNAME", Username)
.WithEnvironment("PASSWORD", Password)
.WithWaitStrategy(Wait.ForUnixContainer()
.UntilInternalTcpPortIsAvailable(DocumentDBPort, strategy => strategy.WithTimeout(TimeSpan.FromMinutes(5))))
.Build();
Comment thread
adamsitnik marked this conversation as resolved.

private MongoClient? _client;
private IMongoDatabase? _database;

public MongoClient Client => this._client ?? throw new InvalidOperationException("Not initialized");
public IMongoDatabase Database => this._database ?? throw new InvalidOperationException("Not initialized");
public MongoClient Client => _client ?? throw new InvalidOperationException("Not initialized");
public IMongoDatabase Database => _database ?? throw new InvalidOperationException("Not initialized");

public override string DefaultIndexKind => Microsoft.Extensions.VectorData.IndexKind.IvfFlat;

public override string DefaultDistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance;

public DocumentDBVectorStore GetVectorStore(DocumentDBVectorStoreOptions options)
=> new(this.Database, options);
=> new(Database, options);

private DocumentDBTestStore()
{
}

protected override Task StartAsync()
protected override async Task StartAsync()
{
if (string.IsNullOrWhiteSpace(DocumentDBTestEnvironment.ConnectionString))
await _container.StartAsync();
string connectionString = $"mongodb://{Username}:{Password}@{_container.Hostname}:{_container.GetMappedPublicPort(DocumentDBPort)}/?tls=true";

MongoClientSettings settings = MongoClientSettings.FromConnectionString(connectionString);
settings.SslSettings = new SslSettings
{
throw new InvalidOperationException("Connection string is not configured, set the AzureDocumentDB:ConnectionString environment variable");
}
EnabledSslProtocols = SslProtocols.Tls12,
ServerCertificateValidationCallback = static (_, _, _, _) => true,
};
Comment thread
adamsitnik marked this conversation as resolved.

this._client = new MongoClient(DocumentDBTestEnvironment.ConnectionString);
this._database = this._client.GetDatabase("VectorSearchTests");
this.DefaultVectorStore = new DocumentDBVectorStore(this._database);
_client = new MongoClient(settings);
await WaitForMongoServiceAsync(_client, TimeSpan.FromMinutes(5));
_database = _client.GetDatabase("VectorSearchTests");
DefaultVectorStore = new DocumentDBVectorStore(_database);
}
Comment thread
adamsitnik marked this conversation as resolved.

protected override Task StopAsync()
{
_client?.Dispose();
return _container.StopAsync();
}

private async Task WaitForMongoServiceAsync(MongoClient client, TimeSpan timeout)
{
DateTimeOffset deadline = DateTimeOffset.UtcNow.Add(timeout);
Exception? lastException = null;

while (DateTimeOffset.UtcNow < deadline)
{
try
{
await client.GetDatabase("admin").RunCommandAsync<BsonDocument>(new BsonDocument("ping", 1));
return;
}
catch (Exception ex)
{
lastException = ex;
await Task.Delay(TimeSpan.FromMilliseconds(200));
}
}

return Task.CompletedTask;
throw new TimeoutException($"Timed out waiting for the DocumentDB container to accept MongoDB connections. Last error: {lastException?.Message}", lastException);
}
}