chore: import upstream snapshot with attribution
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0;net472</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>CosmosNoSql.ConformanceTests</RootNamespace>
|
||||
<UserSecretsId>b7762d10-e29b-4bb1-8b74-b6d69a667dd4</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\VectorData\CosmosNoSql\CosmosNoSql.csproj"/>
|
||||
<ProjectReference Include="..\VectorData.ConformanceTests\VectorData.ConformanceTests.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="testsettings.json" Condition="Exists('testsettings.json')">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="testsettings.development.json" Condition="Exists('testsettings.development.json')">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlCollectionManagementTests(CosmosNoSqlFixture fixture)
|
||||
: CollectionManagementTests<string>(fixture), IClassFixture<CosmosNoSqlFixture>
|
||||
{
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.CosmosNoSql;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
[CosmosConnectionStringRequired]
|
||||
public sealed class CosmosNoSqlCollectionOptionsTests(CosmosNoSqlCollectionOptionsTests.Fixture fixture)
|
||||
: IClassFixture<CosmosNoSqlCollectionOptionsTests.Fixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public async Task Collection_supports_partition_key_composite_key()
|
||||
{
|
||||
var store = (CosmosNoSqlTestStore)fixture.TestStore;
|
||||
var collectionName = fixture.TestStore.AdjustCollectionName("PartitionKeyCompositeKey");
|
||||
|
||||
// The key type for operations is CosmosNoSqlKey (containing both document ID and partition key).
|
||||
using var collection = new CosmosNoSqlCollection<CosmosNoSqlKey, PartitionedHotel>(
|
||||
store.Database,
|
||||
collectionName,
|
||||
new() { PartitionKeyProperties = [nameof(PartitionedHotel.HotelName)] });
|
||||
|
||||
await collection.EnsureCollectionExistsAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var record = new PartitionedHotel
|
||||
{
|
||||
HotelId = "hotel-1",
|
||||
HotelName = "Hotel A",
|
||||
Description = "Partitioned",
|
||||
Embedding = new([1f, 2f, 3f])
|
||||
};
|
||||
|
||||
await collection.UpsertAsync(record);
|
||||
var key = new CosmosNoSqlKey(record.HotelId, record.HotelName);
|
||||
|
||||
var fetched = await collection.GetAsync(key, new() { IncludeVectors = true });
|
||||
Assert.NotNull(fetched);
|
||||
|
||||
await collection.DeleteAsync(key);
|
||||
Assert.Null(await collection.GetAsync(key));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await collection.EnsureCollectionDeletedAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalTheory]
|
||||
[InlineData(IndexingMode.Consistent)]
|
||||
[InlineData(IndexingMode.Lazy)]
|
||||
[InlineData(IndexingMode.None)]
|
||||
public async Task Collection_supports_indexing_mode(IndexingMode indexingMode)
|
||||
{
|
||||
var store = (CosmosNoSqlTestStore)fixture.TestStore;
|
||||
var collectionName = fixture.TestStore.AdjustCollectionName($"IndexingMode_{indexingMode}");
|
||||
|
||||
using var collection = new CosmosNoSqlCollection<string, IndexingModeHotel>(
|
||||
store.Database,
|
||||
collectionName,
|
||||
new() { IndexingMode = indexingMode, Automatic = indexingMode != IndexingMode.None });
|
||||
|
||||
await collection.EnsureCollectionExistsAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var record = new IndexingModeHotel
|
||||
{
|
||||
HotelId = "hotel-2",
|
||||
HotelName = "Hotel B",
|
||||
Embedding = new([1f, 0f, 0f])
|
||||
};
|
||||
|
||||
await collection.UpsertAsync(record);
|
||||
var fetched = await collection.GetAsync(record.HotelId);
|
||||
|
||||
Assert.NotNull(fetched);
|
||||
|
||||
await collection.DeleteAsync(record.HotelId);
|
||||
Assert.Null(await collection.GetAsync(record.HotelId));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await collection.EnsureCollectionDeletedAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Fixture : VectorStoreFixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
|
||||
private sealed class PartitionedHotel
|
||||
{
|
||||
[VectorStoreKey]
|
||||
public string HotelId { get; set; } = string.Empty;
|
||||
|
||||
[VectorStoreData]
|
||||
public string HotelName { get; set; } = string.Empty;
|
||||
|
||||
[VectorStoreData]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[VectorStoreVector(Dimensions: 3)]
|
||||
public ReadOnlyMemory<float> Embedding { get; set; }
|
||||
}
|
||||
|
||||
private sealed class IndexingModeHotel
|
||||
{
|
||||
[VectorStoreKey]
|
||||
public string HotelId { get; set; } = string.Empty;
|
||||
|
||||
[VectorStoreData]
|
||||
public string HotelName { get; set; } = string.Empty;
|
||||
|
||||
[VectorStoreVector(Dimensions: 3)]
|
||||
public ReadOnlyMemory<float> Embedding { get; set; }
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text.Json;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Connectors.CosmosNoSql;
|
||||
using VectorData.ConformanceTests;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.DependencyInjection;
|
||||
|
||||
public class CosmosNoSqlDependencyInjectionTests
|
||||
: DependencyInjectionTests<CosmosNoSqlVectorStore, CosmosNoSqlCollection<string, DependencyInjectionTests<string>.Record>, string, DependencyInjectionTests<string>.Record>
|
||||
{
|
||||
protected const string ConnectionString = "AccountEndpoint=https://test.documents.azure.com:443/;AccountKey=mock;";
|
||||
protected const string DatabaseName = "dbName";
|
||||
|
||||
private static readonly CosmosClientOptions s_clientOptions = new()
|
||||
{
|
||||
UseSystemTextJsonSerializerWithOptions = JsonSerializerOptions.Default
|
||||
};
|
||||
|
||||
protected override void PopulateConfiguration(ConfigurationManager configuration, object? serviceKey = null)
|
||||
=> configuration.AddInMemoryCollection(
|
||||
[
|
||||
new(CreateConfigKey("CosmosNoSql", serviceKey, "ConnectionString"), ConnectionString),
|
||||
new(CreateConfigKey("CosmosNoSql", serviceKey, "DatabaseName"), DatabaseName),
|
||||
]);
|
||||
|
||||
private static string ConnectionStringProvider(IServiceProvider sp)
|
||||
=> sp.GetRequiredService<IConfiguration>().GetRequiredSection("CosmosNoSql:ConnectionString").Value!;
|
||||
|
||||
private static string ConnectionStringProvider(IServiceProvider sp, object serviceKey)
|
||||
=> sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("CosmosNoSql", serviceKey, "ConnectionString")).Value!;
|
||||
|
||||
private static string DatabaseNameProvider(IServiceProvider sp)
|
||||
=> sp.GetRequiredService<IConfiguration>().GetRequiredSection("CosmosNoSql:DatabaseName").Value!;
|
||||
|
||||
private static string DatabaseNameProvider(IServiceProvider sp, object serviceKey)
|
||||
=> sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("CosmosNoSql", serviceKey, "DatabaseName")).Value!;
|
||||
|
||||
public override IEnumerable<Func<IServiceCollection, object?, string, ServiceLifetime, IServiceCollection>> CollectionDelegates
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddSingleton<CosmosClient>(sp => new CosmosClient(ConnectionString, s_clientOptions))
|
||||
.AddSingleton<Database>(sp => sp.GetRequiredService<CosmosClient>().GetDatabase(DatabaseName))
|
||||
.AddCosmosNoSqlCollection<string, Record>(name, lifetime: lifetime)
|
||||
: services
|
||||
.AddSingleton<CosmosClient>(sp => new CosmosClient(ConnectionString, s_clientOptions))
|
||||
.AddSingleton<Database>(sp => sp.GetRequiredService<CosmosClient>().GetDatabase(DatabaseName))
|
||||
.AddKeyedCosmosNoSqlCollection<string, Record>(serviceKey, name, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name, ConnectionString, DatabaseName, lifetime: lifetime)
|
||||
: services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey, name, ConnectionString, DatabaseName, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name, ConnectionStringProvider, DatabaseNameProvider, lifetime: lifetime)
|
||||
: services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey, name, sp => ConnectionStringProvider(sp, serviceKey), sp => DatabaseNameProvider(sp, serviceKey), lifetime: lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Func<IServiceCollection, object?, ServiceLifetime, IServiceCollection>> StoreDelegates
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services.AddCosmosNoSqlVectorStore(
|
||||
ConnectionString, DatabaseName, lifetime: lifetime)
|
||||
: services.AddKeyedCosmosNoSqlVectorStore(
|
||||
serviceKey, ConnectionString, DatabaseName, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddSingleton<CosmosClient>(sp => new CosmosClient(ConnectionString, s_clientOptions))
|
||||
.AddSingleton<Database>(sp => sp.GetRequiredService<CosmosClient>().GetDatabase(DatabaseName))
|
||||
.AddCosmosNoSqlVectorStore(lifetime: lifetime)
|
||||
: services
|
||||
.AddSingleton<CosmosClient>(sp => new CosmosClient(ConnectionString, s_clientOptions))
|
||||
.AddSingleton<Database>(sp => sp.GetRequiredService<CosmosClient>().GetDatabase(DatabaseName))
|
||||
.AddKeyedCosmosNoSqlVectorStore(serviceKey, lifetime: lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConnectionStringProviderCantBeNull()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name: "notNull", connectionStringProvider: null!, databaseNameProvider: DatabaseNameProvider));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey: "notNull", name: "notNull", connectionStringProvider: null!, databaseNameProvider: DatabaseNameProvider));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatabaseNameProviderCantBeNull()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name: "notNull", connectionStringProvider: ConnectionStringProvider, databaseNameProvider: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey: "notNull", name: "notNull", connectionStringProvider: ConnectionStringProvider, databaseNameProvider: null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConnectionStringCantBeNullOrEmpty()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddCosmosNoSqlVectorStore(connectionString: null!, DatabaseName));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedCosmosNoSqlVectorStore(serviceKey: "notNull", connectionString: null!, DatabaseName));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name: "notNull", connectionString: null!, DatabaseName));
|
||||
Assert.Throws<ArgumentException>(() => services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name: "notNull", connectionString: "", DatabaseName));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey: "notNull", name: "notNull", connectionString: null!, DatabaseName));
|
||||
Assert.Throws<ArgumentException>(() => services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey: "notNull", name: "notNull", connectionString: "", DatabaseName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatabaseNameCantBeNullOrEmpty()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddCosmosNoSqlVectorStore(ConnectionString, databaseName: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedCosmosNoSqlVectorStore(serviceKey: "notNull", ConnectionString, databaseName: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name: "notNull", ConnectionString, databaseName: null!));
|
||||
Assert.Throws<ArgumentException>(() => services.AddCosmosNoSqlCollection<string, Record>(
|
||||
name: "notNull", ConnectionString, databaseName: ""));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey: "notNull", name: "notNull", ConnectionString, databaseName: null!));
|
||||
Assert.Throws<ArgumentException>(() => services.AddKeyedCosmosNoSqlCollection<string, Record>(
|
||||
serviceKey: "notNull", name: "notNull", ConnectionString, databaseName: ""));
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlDistanceFunctionTests(CosmosNoSqlDistanceFunctionTests.Fixture fixture)
|
||||
: DistanceFunctionTests<string>(fixture), IClassFixture<CosmosNoSqlDistanceFunctionTests.Fixture>
|
||||
{
|
||||
public override Task CosineDistance() => Assert.ThrowsAsync<NotSupportedException>(base.CosineDistance);
|
||||
public override Task EuclideanSquaredDistance() => Assert.ThrowsAsync<NotSupportedException>(base.EuclideanSquaredDistance);
|
||||
public override Task NegativeDotProductSimilarity() => Assert.ThrowsAsync<NotSupportedException>(base.NegativeDotProductSimilarity);
|
||||
public override Task HammingDistance() => Assert.ThrowsAsync<NotSupportedException>(base.HammingDistance);
|
||||
public override Task ManhattanDistance() => Assert.ThrowsAsync<NotSupportedException>(base.ManhattanDistance);
|
||||
|
||||
public new class Fixture() : DistanceFunctionTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlEmbeddingGenerationTests(CosmosNoSqlEmbeddingGenerationTests.StringVectorFixture stringVectorFixture, CosmosNoSqlEmbeddingGenerationTests.RomOfFloatVectorFixture romOfFloatVectorFixture)
|
||||
: EmbeddingGenerationTests<string>(stringVectorFixture, romOfFloatVectorFixture), IClassFixture<CosmosNoSqlEmbeddingGenerationTests.StringVectorFixture>, IClassFixture<CosmosNoSqlEmbeddingGenerationTests.RomOfFloatVectorFixture>
|
||||
{
|
||||
public new class StringVectorFixture : EmbeddingGenerationTests<string>.StringVectorFixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
|
||||
public override VectorStore CreateVectorStore(IEmbeddingGenerator? embeddingGenerator)
|
||||
=> CosmosNoSqlTestStore.Instance.GetVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionStoreRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(CosmosNoSqlTestStore.Instance.Database)
|
||||
.AddCosmosNoSqlVectorStore()
|
||||
];
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionCollectionRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(CosmosNoSqlTestStore.Instance.Database)
|
||||
.AddCosmosNoSqlCollection<string, RecordWithAttributes>(this.CollectionName)
|
||||
];
|
||||
}
|
||||
|
||||
public new class RomOfFloatVectorFixture : EmbeddingGenerationTests<string>.RomOfFloatVectorFixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
|
||||
public override VectorStore CreateVectorStore(IEmbeddingGenerator? embeddingGenerator)
|
||||
=> CosmosNoSqlTestStore.Instance.GetVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionStoreRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(CosmosNoSqlTestStore.Instance.Database)
|
||||
.AddCosmosNoSqlVectorStore()
|
||||
];
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionCollectionRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(CosmosNoSqlTestStore.Instance.Database)
|
||||
.AddCosmosNoSqlCollection<string, RecordWithAttributes>(this.CollectionName)
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlFilterTests(CosmosNoSqlFilterTests.Fixture fixture)
|
||||
: FilterTests<string>(fixture), IClassFixture<CosmosNoSqlFilterTests.Fixture>
|
||||
{
|
||||
public new class Fixture : FilterTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlHybridSearchTests(
|
||||
CosmosNoSqlHybridSearchTests.VectorAndStringFixture vectorAndStringFixture,
|
||||
CosmosNoSqlHybridSearchTests.MultiTextFixture multiTextFixture)
|
||||
: HybridSearchTests<string>(vectorAndStringFixture, multiTextFixture),
|
||||
IClassFixture<CosmosNoSqlHybridSearchTests.VectorAndStringFixture>,
|
||||
IClassFixture<CosmosNoSqlHybridSearchTests.MultiTextFixture>
|
||||
{
|
||||
public new class VectorAndStringFixture : HybridSearchTests<string>.VectorAndStringFixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
|
||||
public new class MultiTextFixture : HybridSearchTests<string>.MultiTextFixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlIndexKindTests(CosmosNoSqlIndexKindTests.Fixture fixture)
|
||||
: IndexKindTests<string>(fixture), IClassFixture<CosmosNoSqlIndexKindTests.Fixture>
|
||||
{
|
||||
[ConditionalFact(Skip = "DiskANN is supported by Cosmos NoSQL, but is not supported on the emulator and needs to be explicitly enabled")]
|
||||
public virtual Task DiskANN()
|
||||
=> this.Test(IndexKind.DiskAnn);
|
||||
|
||||
public new class Fixture() : IndexKindTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests;
|
||||
|
||||
public class CosmosNoSqlTestSuiteImplementationTests : TestSuiteImplementationTests;
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.ModelTests;
|
||||
|
||||
public class CosmosNoSqlBasicModelTests(CosmosNoSqlBasicModelTests.Fixture fixture)
|
||||
: BasicModelTests<string>(fixture), IClassFixture<CosmosNoSqlBasicModelTests.Fixture>
|
||||
{
|
||||
public override async Task GetAsync_with_filter_and_multiple_OrderBys()
|
||||
{
|
||||
// CosmosException: The order by query does not have a corresponding composite index that it can be served from.
|
||||
var exception = await Assert.ThrowsAsync<VectorStoreException>(base.GetAsync_with_filter_and_multiple_OrderBys);
|
||||
Assert.IsType<CosmosException>(exception.InnerException);
|
||||
}
|
||||
|
||||
public new class Fixture : BasicModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.ModelTests;
|
||||
|
||||
public class CosmosNoSqlDynamicModelTests(CosmosNoSqlDynamicModelTests.Fixture fixture)
|
||||
: DynamicModelTests<string>(fixture), IClassFixture<CosmosNoSqlDynamicModelTests.Fixture>
|
||||
{
|
||||
public override async Task GetAsync_with_filter_and_multiple_OrderBys()
|
||||
{
|
||||
// CosmosException: The order by query does not have a corresponding composite index that it can be served from.
|
||||
var exception = await Assert.ThrowsAsync<VectorStoreException>(base.GetAsync_with_filter_and_multiple_OrderBys);
|
||||
Assert.IsType<CosmosException>(exception.InnerException);
|
||||
}
|
||||
|
||||
public new class Fixture : DynamicModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.ModelTests;
|
||||
|
||||
public class CosmosNoSqlMultiVectorModelTests(CosmosNoSqlMultiVectorModelTests.Fixture fixture)
|
||||
: MultiVectorModelTests<string>(fixture), IClassFixture<CosmosNoSqlMultiVectorModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : MultiVectorModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.ModelTests;
|
||||
|
||||
public class CosmosNoSqlNoDataModelTests(CosmosNoSqlNoDataModelTests.Fixture fixture)
|
||||
: NoDataModelTests<string>(fixture), IClassFixture<CosmosNoSqlNoDataModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : NoDataModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.ModelTests;
|
||||
|
||||
public class CosmosNoSqlNoVectorModelTests(CosmosNoSqlNoVectorModelTests.Fixture fixture)
|
||||
: NoVectorModelTests<string>(fixture), IClassFixture<CosmosNoSqlNoVectorModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : NoVectorModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
[assembly: CosmosNoSql.ConformanceTests.Support.CosmosConnectionStringRequired]
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.Support;
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the sqlite_vec extension is properly installed, and skips the test(s) otherwise.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
|
||||
public sealed class CosmosConnectionStringRequiredAttribute : Attribute, ITestCondition
|
||||
{
|
||||
public ValueTask<bool> IsMetAsync() => new(CosmosNoSqlTestEnvironment.IsConnectionStringDefined);
|
||||
|
||||
public string Skip { get; set; } = "The Cosmos connection string hasn't been configured (CosmosNoSql:ConnectionString).";
|
||||
|
||||
public string SkipReason
|
||||
=> this.Skip;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.Support;
|
||||
|
||||
public class CosmosNoSqlFixture : VectorStoreFixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.Support;
|
||||
|
||||
#pragma warning disable CA1810 // Initialize all static fields when those fields are declared
|
||||
|
||||
internal static class CosmosNoSqlTestEnvironment
|
||||
{
|
||||
public static readonly string? ConnectionString;
|
||||
|
||||
public static bool IsConnectionStringDefined => ConnectionString is not null;
|
||||
|
||||
static CosmosNoSqlTestEnvironment()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile(path: "testsettings.json", optional: true)
|
||||
.AddJsonFile(path: "testsettings.development.json", optional: true)
|
||||
.AddEnvironmentVariables()
|
||||
.AddUserSecrets<CosmosConnectionStringRequiredAttribute>()
|
||||
.Build();
|
||||
|
||||
ConnectionString = configuration["CosmosNoSql:ConnectionString"];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#if NET472
|
||||
using System.Net.Http;
|
||||
#endif
|
||||
using System.Text.Json;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Microsoft.SemanticKernel.Connectors.CosmosNoSql;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.Support;
|
||||
|
||||
#pragma warning disable CA1001 // Type owns disposable fields (_connection) but is not disposable
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
|
||||
internal sealed class CosmosNoSqlTestStore : TestStore
|
||||
{
|
||||
public static CosmosNoSqlTestStore Instance { get; } = new();
|
||||
|
||||
private CosmosClient? _client;
|
||||
private Database? _database;
|
||||
|
||||
public override string DefaultIndexKind => Microsoft.Extensions.VectorData.IndexKind.Flat;
|
||||
|
||||
public CosmosClient Client
|
||||
=> this._client ?? throw new InvalidOperationException("Call InitializeAsync() first");
|
||||
|
||||
public Database Database
|
||||
=> this._database ?? throw new InvalidOperationException("Call InitializeAsync() first");
|
||||
|
||||
public CosmosNoSqlVectorStore GetVectorStore(CosmosNoSqlVectorStoreOptions options)
|
||||
=> new(this.Database, options);
|
||||
|
||||
private CosmosNoSqlTestStore()
|
||||
{
|
||||
}
|
||||
|
||||
#pragma warning disable CA5400 // HttpClient may be created without enabling CheckCertificateRevocationList
|
||||
protected override async Task StartAsync()
|
||||
{
|
||||
var connectionString = CosmosNoSqlTestEnvironment.ConnectionString;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(connectionString))
|
||||
{
|
||||
throw new InvalidOperationException("Connection string is not configured, set the CosmosNoSql:ConnectionString environment variable");
|
||||
}
|
||||
|
||||
var options = new CosmosClientOptions
|
||||
{
|
||||
UseSystemTextJsonSerializerWithOptions = JsonSerializerOptions.Default,
|
||||
ConnectionMode = ConnectionMode.Gateway,
|
||||
HttpClientFactory = () => new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator })
|
||||
};
|
||||
|
||||
this._client = new CosmosClient(connectionString, options);
|
||||
this._database = this._client.GetDatabase("VectorDataIntegrationTests");
|
||||
await this._client.CreateDatabaseIfNotExistsAsync("VectorDataIntegrationTests");
|
||||
this.DefaultVectorStore = new CosmosNoSqlVectorStore(this._database);
|
||||
}
|
||||
#pragma warning restore CA5400
|
||||
|
||||
protected override Task StopAsync()
|
||||
{
|
||||
this._client?.Dispose();
|
||||
return base.StopAsync();
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.TypeTests;
|
||||
|
||||
public class CosmosNoSqlDataTypeTests(CosmosNoSqlDataTypeTests.Fixture fixture)
|
||||
: DataTypeTests<string, DataTypeTests<string>.DefaultRecord>(fixture), IClassFixture<CosmosNoSqlDataTypeTests.Fixture>
|
||||
{
|
||||
// Cosmos doesn't support DateTimeOffset with non-zero offset, so we convert it to UTC.
|
||||
// See https://github.com/dotnet/efcore/issues/35310
|
||||
[ConditionalFact(Skip = "Need to convert DateTimeOffset to UTC before sending to Cosmos")]
|
||||
public override Task DateTimeOffset()
|
||||
=> this.Test<DateTimeOffset>(
|
||||
"DateTimeOffset",
|
||||
new DateTimeOffset(2020, 1, 1, 12, 30, 45, TimeSpan.FromHours(2)),
|
||||
new DateTimeOffset(2021, 2, 3, 13, 40, 55, TimeSpan.FromHours(3)),
|
||||
instantiationExpression: () => new DateTimeOffset(2020, 1, 1, 10, 30, 45, TimeSpan.FromHours(0)));
|
||||
|
||||
public new class Fixture : DataTypeTests<string, DataTypeTests<string>.DefaultRecord>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
|
||||
public override Type[] UnsupportedDefaultTypes { get; } =
|
||||
[
|
||||
typeof(byte),
|
||||
typeof(short),
|
||||
typeof(decimal),
|
||||
typeof(Guid),
|
||||
#if NET
|
||||
typeof(TimeOnly)
|
||||
#endif
|
||||
];
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.AI;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.TypeTests;
|
||||
|
||||
public class CosmosNoSqlEmbeddingTypeTests(CosmosNoSqlEmbeddingTypeTests.Fixture fixture)
|
||||
: EmbeddingTypeTests<string>(fixture), IClassFixture<CosmosNoSqlEmbeddingTypeTests.Fixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public virtual Task ReadOnlyMemory_of_byte()
|
||||
=> this.Test<ReadOnlyMemory<byte>>(
|
||||
new ReadOnlyMemory<byte>([1, 2, 3]),
|
||||
new ReadOnlyMemoryEmbeddingGenerator<byte>([1, 2, 3]),
|
||||
vectorEqualityAsserter: (e, a) => Assert.Equal(e.Span.ToArray(), a.Span.ToArray()));
|
||||
|
||||
[ConditionalFact]
|
||||
public virtual Task Embedding_of_byte()
|
||||
=> this.Test<Embedding<byte>>(
|
||||
new Embedding<byte>(new ReadOnlyMemory<byte>([1, 2, 3])),
|
||||
new ReadOnlyMemoryEmbeddingGenerator<byte>([1, 2, 3]),
|
||||
vectorEqualityAsserter: (e, a) => Assert.Equal(e.Vector.Span.ToArray(), a.Vector.Span.ToArray()));
|
||||
|
||||
[ConditionalFact]
|
||||
public virtual Task Array_of_byte()
|
||||
=> this.Test<byte[]>(
|
||||
[1, 2, 3],
|
||||
new ReadOnlyMemoryEmbeddingGenerator<byte>([1, 2, 3]));
|
||||
|
||||
[ConditionalFact]
|
||||
public virtual Task ReadOnlyMemory_of_sbyte()
|
||||
=> this.Test<ReadOnlyMemory<sbyte>>(
|
||||
new ReadOnlyMemory<sbyte>([1, 2, 3]),
|
||||
new ReadOnlyMemoryEmbeddingGenerator<sbyte>([1, 2, 3]),
|
||||
vectorEqualityAsserter: (e, a) => Assert.Equal(e.Span.ToArray(), a.Span.ToArray()));
|
||||
|
||||
[ConditionalFact]
|
||||
public virtual Task Embedding_of_sbyte()
|
||||
=> this.Test<Embedding<sbyte>>(
|
||||
new Embedding<sbyte>(new ReadOnlyMemory<sbyte>([1, 2, 3])),
|
||||
new ReadOnlyMemoryEmbeddingGenerator<sbyte>([1, 2, 3]),
|
||||
vectorEqualityAsserter: (e, a) => Assert.Equal(e.Vector.Span.ToArray(), a.Vector.Span.ToArray()));
|
||||
|
||||
[ConditionalFact]
|
||||
public virtual Task Array_of_sbyte()
|
||||
=> this.Test<sbyte[]>(
|
||||
[1, 2, 3],
|
||||
new ReadOnlyMemoryEmbeddingGenerator<sbyte>([1, 2, 3]));
|
||||
|
||||
public new class Fixture : EmbeddingTypeTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using CosmosNoSql.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace CosmosNoSql.ConformanceTests.TypeTests;
|
||||
|
||||
public class CosmosNoSqlKeyTypeTests(CosmosNoSqlKeyTypeTests.Fixture fixture)
|
||||
: KeyTypeTests(fixture), IClassFixture<CosmosNoSqlKeyTypeTests.Fixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public virtual Task String() => this.Test<string>("foo", "bar");
|
||||
|
||||
public new class Fixture : KeyTypeTests.Fixture
|
||||
{
|
||||
public override TestStore TestStore => CosmosNoSqlTestStore.Instance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user