chore: import upstream snapshot with attribution
This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0;net472</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<IsPackable>false</IsPackable>
|
||||
<RootNamespace>AzureAI.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="Azure.Identity"/>
|
||||
<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"/>
|
||||
<PackageReference Include="System.Linq.AsyncEnumerable" />
|
||||
<PackageReference Include="Humanizer" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\VectorData\AzureAISearch\AzureAISearch.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>
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchAllSupportedTypesTests(AzureAISearchFixture fixture) : IClassFixture<AzureAISearchFixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public async Task AllTypesBatchGetAsync()
|
||||
{
|
||||
var collection = fixture.TestStore.DefaultVectorStore.GetCollection<string, AzureAISearchAllTypes>("all-types", AzureAISearchAllTypes.GetRecordDefinition());
|
||||
await collection.EnsureCollectionExistsAsync();
|
||||
|
||||
List<AzureAISearchAllTypes> records =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Id = "all-types-1",
|
||||
BoolProperty = true,
|
||||
NullableBoolProperty = false,
|
||||
StringProperty = "string prop 1",
|
||||
NullableStringProperty = "nullable prop 1",
|
||||
IntProperty = 1,
|
||||
NullableIntProperty = 10,
|
||||
LongProperty = 100L,
|
||||
NullableLongProperty = 1000L,
|
||||
FloatProperty = 10.5f,
|
||||
NullableFloatProperty = 100.5f,
|
||||
DoubleProperty = 23.75d,
|
||||
NullableDoubleProperty = 233.75d,
|
||||
DateTimeOffsetProperty = DateTimeOffset.UtcNow,
|
||||
NullableDateTimeOffsetProperty = DateTimeOffset.UtcNow,
|
||||
StringArray = ["one", "two"],
|
||||
StringList = ["eleven", "twelve"],
|
||||
BoolArray = [true, false],
|
||||
BoolList = [true, false],
|
||||
IntArray = [1, 2],
|
||||
IntList = [11, 12],
|
||||
LongArray = [100L, 200L],
|
||||
LongList = [1100L, 1200L],
|
||||
FloatArray = [1.5f, 2.5f],
|
||||
FloatList = [11.5f, 12.5f],
|
||||
DoubleArray = [1.5d, 2.5d],
|
||||
DoubleList = [11.5d, 12.5d],
|
||||
DateTimeOffsetArray = [DateTimeOffset.UtcNow, DateTimeOffset.UtcNow],
|
||||
DateTimeOffsetList = [DateTimeOffset.UtcNow, DateTimeOffset.UtcNow],
|
||||
Embedding = new ReadOnlyMemory<float>([1.5f, 2.5f, 3.5f, 4.5f, 5.5f, 6.5f, 7.5f, 8.5f])
|
||||
},
|
||||
new()
|
||||
{
|
||||
Id = "all-types-2",
|
||||
BoolProperty = false,
|
||||
NullableBoolProperty = null,
|
||||
StringProperty = "string prop 2",
|
||||
NullableStringProperty = null,
|
||||
IntProperty = 2,
|
||||
NullableIntProperty = null,
|
||||
LongProperty = 200L,
|
||||
NullableLongProperty = null,
|
||||
FloatProperty = 20.5f,
|
||||
NullableFloatProperty = null,
|
||||
DoubleProperty = 43.75,
|
||||
NullableDoubleProperty = null,
|
||||
Embedding = ReadOnlyMemory<float>.Empty,
|
||||
// From https://learn.microsoft.com/en-us/rest/api/searchservice/supported-data-types:
|
||||
// "All of the above types are nullable, except for collections of primitive and complex types, for example, Collection(Edm.String)"
|
||||
// So for collections, we can't use nulls.
|
||||
StringArray = [],
|
||||
StringList = [],
|
||||
BoolArray = [],
|
||||
BoolList = [],
|
||||
IntArray = [],
|
||||
IntList = [],
|
||||
LongArray = [],
|
||||
LongList = [],
|
||||
FloatArray = [],
|
||||
FloatList = [],
|
||||
DoubleArray = [],
|
||||
DoubleList = [],
|
||||
DateTimeOffsetArray = [],
|
||||
DateTimeOffsetList = [],
|
||||
}
|
||||
];
|
||||
|
||||
try
|
||||
{
|
||||
await collection.UpsertAsync(records);
|
||||
|
||||
var allTypes = await collection.GetAsync(records.Select(r => r.Id), new RecordRetrievalOptions { IncludeVectors = true }).ToListAsync();
|
||||
|
||||
var allTypes1 = allTypes.Single(x => x.Id == records[0].Id);
|
||||
var allTypes2 = allTypes.Single(x => x.Id == records[1].Id);
|
||||
|
||||
records[0].AssertEqual(allTypes1);
|
||||
records[1].AssertEqual(allTypes2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await collection.EnsureCollectionDeletedAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchCollectionManagementTests(AzureAISearchFixture fixture)
|
||||
: CollectionManagementTests<string>(fixture), IClassFixture<AzureAISearchFixture>;
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure;
|
||||
using Azure.Search.Documents.Indexes;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Connectors.AzureAISearch;
|
||||
using VectorData.ConformanceTests;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchDependencyInjectionTests
|
||||
: DependencyInjectionTests<AzureAISearchVectorStore, AzureAISearchCollection<string, DependencyInjectionTests<string>.Record>, string, DependencyInjectionTests<string>.Record>
|
||||
{
|
||||
private static readonly Uri s_endpoint = new("https://localhost");
|
||||
private static readonly AzureKeyCredential s_keyCredential = new("fakeKey");
|
||||
|
||||
protected override void PopulateConfiguration(ConfigurationManager configuration, object? serviceKey = null)
|
||||
=> configuration.AddInMemoryCollection(
|
||||
[
|
||||
new(CreateConfigKey("AzureAI", serviceKey, "Endpoint"), "https://localhost"),
|
||||
new(CreateConfigKey("AzureAI", serviceKey, "Key"), "fakeKey"),
|
||||
]);
|
||||
|
||||
private static Uri EndpointProvider(IServiceProvider sp, object? serviceKey = null)
|
||||
=> new(sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("AzureAI", serviceKey, "Endpoint")).Value!);
|
||||
|
||||
private static AzureKeyCredential KeyProvider(IServiceProvider sp, object? serviceKey = null)
|
||||
=> new(sp.GetRequiredService<IConfiguration>().GetRequiredSection(CreateConfigKey("AzureAI", serviceKey, "Key")).Value!);
|
||||
|
||||
public override IEnumerable<Func<IServiceCollection, object?, string, ServiceLifetime, IServiceCollection>> CollectionDelegates
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddAzureAISearchCollection<Record>(name,
|
||||
sp => new SearchIndexClient(EndpointProvider(sp), KeyProvider(sp)), lifetime: lifetime)
|
||||
: services
|
||||
.AddKeyedAzureAISearchCollection<Record>(serviceKey, name,
|
||||
sp => new SearchIndexClient(EndpointProvider(sp, serviceKey), KeyProvider(sp, serviceKey)), lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddSingleton<SearchIndexClient>(sp => new SearchIndexClient(s_endpoint, s_keyCredential))
|
||||
.AddAzureAISearchCollection<Record>(name, lifetime: lifetime)
|
||||
: services
|
||||
.AddSingleton<SearchIndexClient>(sp => new SearchIndexClient(s_endpoint, s_keyCredential))
|
||||
.AddKeyedAzureAISearchCollection<Record>(serviceKey, name, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, name, lifetime) => serviceKey is null
|
||||
? services.AddAzureAISearchCollection<Record>(
|
||||
name, s_endpoint, s_keyCredential, lifetime: lifetime)
|
||||
: services.AddKeyedAzureAISearchCollection<Record>(
|
||||
serviceKey, name, s_endpoint, s_keyCredential, lifetime: lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
public override IEnumerable<Func<IServiceCollection, object?, ServiceLifetime, IServiceCollection>> StoreDelegates
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddAzureAISearchVectorStore(sp => new SearchIndexClient(EndpointProvider(sp), KeyProvider(sp)), lifetime: lifetime)
|
||||
: services
|
||||
.AddKeyedAzureAISearchVectorStore(serviceKey, sp => new SearchIndexClient(EndpointProvider(sp, serviceKey), KeyProvider(sp, serviceKey)), lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services.AddAzureAISearchVectorStore(
|
||||
s_endpoint, s_keyCredential, lifetime: lifetime)
|
||||
: services.AddKeyedAzureAISearchVectorStore(
|
||||
serviceKey, s_endpoint, s_keyCredential, lifetime: lifetime);
|
||||
|
||||
yield return (services, serviceKey, lifetime) => serviceKey is null
|
||||
? services
|
||||
.AddSingleton<SearchIndexClient>(sp => new SearchIndexClient(s_endpoint, s_keyCredential))
|
||||
.AddAzureAISearchVectorStore(lifetime: lifetime)
|
||||
: services
|
||||
.AddSingleton<SearchIndexClient>(sp => new SearchIndexClient(s_endpoint, s_keyCredential))
|
||||
.AddKeyedAzureAISearchVectorStore(serviceKey, lifetime: lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EndpointCantBeNull()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddAzureAISearchCollection<Record>(
|
||||
name: "notNull", endpoint: null!, s_keyCredential));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedAzureAISearchCollection<Record>(
|
||||
serviceKey: "notNull", name: "notNull", endpoint: null!, s_keyCredential));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void KeyCredentialCantBeNull()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddAzureAISearchCollection<Record>(
|
||||
name: "notNull", s_endpoint, keyCredential: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedAzureAISearchCollection<Record>(
|
||||
serviceKey: "notNull", name: "notNull", s_endpoint, keyCredential: null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TokenCredentialCantBeNull()
|
||||
{
|
||||
IServiceCollection services = new ServiceCollection();
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddAzureAISearchCollection<Record>(
|
||||
name: "notNull", s_endpoint, tokenCredential: null!));
|
||||
Assert.Throws<ArgumentNullException>(() => services.AddKeyedAzureAISearchCollection<Record>(
|
||||
serviceKey: "notNull", name: "notNull", s_endpoint, tokenCredential: null!));
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchDistanceFunctionTests(AzureAISearchDistanceFunctionTests.Fixture fixture)
|
||||
: DistanceFunctionTests<string>(fixture), IClassFixture<AzureAISearchDistanceFunctionTests.Fixture>
|
||||
{
|
||||
public override Task CosineDistance() => Assert.ThrowsAsync<NotSupportedException>(base.CosineDistance);
|
||||
public override Task NegativeDotProductSimilarity() => Assert.ThrowsAsync<NotSupportedException>(base.NegativeDotProductSimilarity);
|
||||
public override Task EuclideanSquaredDistance() => Assert.ThrowsAsync<NotSupportedException>(base.EuclideanSquaredDistance);
|
||||
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 => AzureAISearchTestStore.Instance;
|
||||
|
||||
// AzureAISearch does not return the expected standard mathematical result for each distance function
|
||||
public override bool AssertScores => false;
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchEmbeddingGenerationTests(AzureAISearchEmbeddingGenerationTests.StringVectorFixture stringVectorFixture, AzureAISearchEmbeddingGenerationTests.RomOfFloatVectorFixture romOfFloatVectorFixture)
|
||||
: EmbeddingGenerationTests<string>(stringVectorFixture, romOfFloatVectorFixture), IClassFixture<AzureAISearchEmbeddingGenerationTests.StringVectorFixture>, IClassFixture<AzureAISearchEmbeddingGenerationTests.RomOfFloatVectorFixture>
|
||||
{
|
||||
// SearchAsync without a generator delegates to the service for AzureAISearch
|
||||
public override Task SearchAsync_string_without_generator_throws()
|
||||
=> Task.CompletedTask;
|
||||
|
||||
public new class StringVectorFixture : EmbeddingGenerationTests<string>.StringVectorFixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
|
||||
public override VectorStore CreateVectorStore(IEmbeddingGenerator? embeddingGenerator)
|
||||
=> AzureAISearchTestStore.Instance.GetVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionStoreRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(AzureAISearchTestStore.Instance.Client)
|
||||
.AddAzureAISearchVectorStore()
|
||||
];
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionCollectionRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(AzureAISearchTestStore.Instance.Client)
|
||||
.AddAzureAISearchCollection<RecordWithAttributes>(this.CollectionName)
|
||||
];
|
||||
}
|
||||
|
||||
public new class RomOfFloatVectorFixture : EmbeddingGenerationTests<string>.RomOfFloatVectorFixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
|
||||
public override VectorStore CreateVectorStore(IEmbeddingGenerator? embeddingGenerator)
|
||||
=> AzureAISearchTestStore.Instance.GetVectorStore(new() { EmbeddingGenerator = embeddingGenerator });
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionStoreRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(AzureAISearchTestStore.Instance.Client)
|
||||
.AddAzureAISearchVectorStore()
|
||||
];
|
||||
|
||||
public override Func<IServiceCollection, IServiceCollection>[] DependencyInjectionCollectionRegistrationDelegates =>
|
||||
[
|
||||
services => services
|
||||
.AddSingleton(AzureAISearchTestStore.Instance.Client)
|
||||
.AddAzureAISearchCollection<RecordWithAttributes>(this.CollectionName)
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchFilterTests(AzureAISearchFilterTests.Fixture fixture)
|
||||
: FilterTests<string>(fixture), IClassFixture<AzureAISearchFilterTests.Fixture>
|
||||
{
|
||||
// Azure AI Search only supports search.in() over strings
|
||||
public override Task Contains_over_inline_int_array()
|
||||
=> Assert.ThrowsAsync<NotSupportedException>(() => base.Contains_over_inline_int_array());
|
||||
|
||||
public new class Fixture : FilterTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchHybridSearchTests(
|
||||
AzureAISearchHybridSearchTests.VectorAndStringFixture vectorAndStringFixture,
|
||||
AzureAISearchHybridSearchTests.MultiTextFixture multiTextFixture)
|
||||
: HybridSearchTests<string>(vectorAndStringFixture, multiTextFixture),
|
||||
IClassFixture<AzureAISearchHybridSearchTests.VectorAndStringFixture>,
|
||||
IClassFixture<AzureAISearchHybridSearchTests.MultiTextFixture>
|
||||
{
|
||||
public new class VectorAndStringFixture : HybridSearchTests<string>.VectorAndStringFixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
|
||||
public new class MultiTextFixture : HybridSearchTests<string>.MultiTextFixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchIndexKindTests(AzureAISearchIndexKindTests.Fixture fixture)
|
||||
: IndexKindTests<string>(fixture), IClassFixture<AzureAISearchIndexKindTests.Fixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public virtual Task Hnsw()
|
||||
=> this.Test(IndexKind.Hnsw);
|
||||
|
||||
public new class Fixture() : IndexKindTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests;
|
||||
|
||||
public class AzureAISearchTestSuiteImplementationTests : TestSuiteImplementationTests;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.ModelTests;
|
||||
|
||||
public class AzureAISearchBasicModelTests(AzureAISearchBasicModelTests.Fixture fixture)
|
||||
: BasicModelTests<string>(fixture), IClassFixture<AzureAISearchBasicModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : BasicModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.ModelTests;
|
||||
|
||||
public class AzureAISearchDynamicModelTests(AzureAISearchDynamicModelTests.Fixture fixture)
|
||||
: DynamicModelTests<string>(fixture), IClassFixture<AzureAISearchDynamicModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : DynamicModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.ModelTests;
|
||||
|
||||
public class AzureAISearchMultiVectorModelTests(AzureAISearchMultiVectorModelTests.Fixture fixture)
|
||||
: MultiVectorModelTests<string>(fixture), IClassFixture<AzureAISearchMultiVectorModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : MultiVectorModelTests<string>.Fixture
|
||||
{
|
||||
public override string CollectionName => "multi-vector-" + AzureAISearchTestEnvironment.TestIndexPostfix;
|
||||
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.ModelTests;
|
||||
|
||||
public class AzureAISearchNoDataModelTests(AzureAISearchNoDataModelTests.Fixture fixture)
|
||||
: NoDataModelTests<string>(fixture), IClassFixture<AzureAISearchNoDataModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : NoDataModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.ModelTests;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.ModelTests;
|
||||
|
||||
public class AzureAISearchNoVectorModelTests(AzureAISearchNoVectorModelTests.Fixture fixture)
|
||||
: NoVectorModelTests<string>(fixture), IClassFixture<AzureAISearchNoVectorModelTests.Fixture>
|
||||
{
|
||||
public new class Fixture : NoVectorModelTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
[assembly: AzureAISearch.ConformanceTests.Support.AzureAISearchUrlRequiredAttribute]
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.Support;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
|
||||
public class AzureAISearchAllTypes
|
||||
{
|
||||
[VectorStoreKey]
|
||||
public string Id { get; set; }
|
||||
|
||||
[VectorStoreData]
|
||||
public bool BoolProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public bool? NullableBoolProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public string StringProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public string? NullableStringProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public int IntProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public int? NullableIntProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public long LongProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public long? NullableLongProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public float FloatProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public float? NullableFloatProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public double DoubleProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public double? NullableDoubleProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public DateTimeOffset DateTimeOffsetProperty { get; set; }
|
||||
[VectorStoreData]
|
||||
public DateTimeOffset? NullableDateTimeOffsetProperty { get; set; }
|
||||
|
||||
[VectorStoreData]
|
||||
public string[] StringArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<string> StringList { get; set; }
|
||||
[VectorStoreData]
|
||||
public bool[] BoolArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<bool> BoolList { get; set; }
|
||||
[VectorStoreData]
|
||||
public int[] IntArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<int> IntList { get; set; }
|
||||
[VectorStoreData]
|
||||
public long[] LongArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<long> LongList { get; set; }
|
||||
[VectorStoreData]
|
||||
public float[] FloatArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<float> FloatList { get; set; }
|
||||
[VectorStoreData]
|
||||
public double[] DoubleArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<double> DoubleList { get; set; }
|
||||
[VectorStoreData]
|
||||
public DateTimeOffset[] DateTimeOffsetArray { get; set; }
|
||||
[VectorStoreData]
|
||||
public List<DateTimeOffset> DateTimeOffsetList { get; set; }
|
||||
|
||||
[VectorStoreVector(Dimensions: 8, DistanceFunction = DistanceFunction.DotProductSimilarity)]
|
||||
public ReadOnlyMemory<float>? Embedding { get; set; }
|
||||
|
||||
internal void AssertEqual(AzureAISearchAllTypes other)
|
||||
{
|
||||
Assert.Equal(this.Id, other.Id);
|
||||
Assert.Equal(this.BoolProperty, other.BoolProperty);
|
||||
Assert.Equal(this.NullableBoolProperty, other.NullableBoolProperty);
|
||||
Assert.Equal(this.StringProperty, other.StringProperty);
|
||||
Assert.Equal(this.NullableStringProperty, other.NullableStringProperty);
|
||||
Assert.Equal(this.IntProperty, other.IntProperty);
|
||||
Assert.Equal(this.NullableIntProperty, other.NullableIntProperty);
|
||||
Assert.Equal(this.LongProperty, other.LongProperty);
|
||||
Assert.Equal(this.NullableLongProperty, other.NullableLongProperty);
|
||||
Assert.Equal(this.FloatProperty, other.FloatProperty);
|
||||
Assert.Equal(this.NullableFloatProperty, other.NullableFloatProperty);
|
||||
Assert.Equal(this.DoubleProperty, other.DoubleProperty);
|
||||
Assert.Equal(this.NullableDoubleProperty, other.NullableDoubleProperty);
|
||||
AssertEqual(this.DateTimeOffsetProperty, other.DateTimeOffsetProperty);
|
||||
Assert.Equal(this.NullableDateTimeOffsetProperty.HasValue, other.NullableDateTimeOffsetProperty.HasValue);
|
||||
if (this.NullableDateTimeOffsetProperty.HasValue && other.NullableDateTimeOffsetProperty.HasValue)
|
||||
{
|
||||
AssertEqual(this.NullableDateTimeOffsetProperty.Value, other.NullableDateTimeOffsetProperty.Value);
|
||||
}
|
||||
|
||||
Assert.Equal(this.StringArray, other.StringArray);
|
||||
Assert.Equal(this.StringList, other.StringList);
|
||||
Assert.Equal(this.BoolArray, other.BoolArray);
|
||||
Assert.Equal(this.BoolList, other.BoolList);
|
||||
Assert.Equal(this.IntArray, other.IntArray);
|
||||
Assert.Equal(this.IntList, other.IntList);
|
||||
Assert.Equal(this.LongArray, other.LongArray);
|
||||
Assert.Equal(this.LongList, other.LongList);
|
||||
Assert.Equal(this.FloatArray, other.FloatArray);
|
||||
Assert.Equal(this.FloatList, other.FloatList);
|
||||
Assert.Equal(this.DoubleArray, other.DoubleArray);
|
||||
Assert.Equal(this.DoubleList, other.DoubleList);
|
||||
Assert.Equal(this.DateTimeOffsetArray.Length, other.DateTimeOffsetArray.Length);
|
||||
for (int i = 0; i < this.DateTimeOffsetArray.Length; i++)
|
||||
{
|
||||
AssertEqual(this.DateTimeOffsetArray[i], other.DateTimeOffsetArray[i]);
|
||||
}
|
||||
Assert.Equal(this.DateTimeOffsetList.Count, other.DateTimeOffsetList.Count);
|
||||
for (int i = 0; i < this.DateTimeOffsetList.Count; i++)
|
||||
{
|
||||
AssertEqual(this.DateTimeOffsetList[i], other.DateTimeOffsetList[i]);
|
||||
}
|
||||
|
||||
Assert.Equal(this.Embedding!.Value.ToArray(), other.Embedding!.Value.ToArray());
|
||||
|
||||
static void AssertEqual(DateTimeOffset expected, DateTimeOffset actual)
|
||||
{
|
||||
Assert.Equal(expected, actual, TimeSpan.FromSeconds(0.01));
|
||||
}
|
||||
}
|
||||
|
||||
internal static VectorStoreCollectionDefinition GetRecordDefinition()
|
||||
=> new()
|
||||
{
|
||||
Properties =
|
||||
[
|
||||
new VectorStoreKeyProperty(nameof(AzureAISearchAllTypes.Id), typeof(string)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.BoolProperty), typeof(bool)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableBoolProperty), typeof(bool?)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.StringProperty), typeof(string)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableStringProperty), typeof(string)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.IntProperty), typeof(int)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableIntProperty), typeof(int?)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.LongProperty), typeof(long)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableLongProperty), typeof(long?)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.FloatProperty), typeof(float)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableFloatProperty), typeof(float?)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.DoubleProperty), typeof(double)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableDoubleProperty), typeof(double?)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.DateTimeOffsetProperty), typeof(DateTimeOffset)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.NullableDateTimeOffsetProperty), typeof(DateTimeOffset?)),
|
||||
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.StringArray), typeof(string[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.StringList), typeof(List<string>)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.BoolArray), typeof(bool[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.BoolList), typeof(List<bool>)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.IntArray), typeof(int[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.IntList), typeof(List<int>)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.LongArray), typeof(long[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.LongList), typeof(List<long>)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.FloatArray), typeof(float[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.FloatList), typeof(List<float>)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.DoubleArray), typeof(double[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.DoubleList), typeof(List<double>)),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.DateTimeOffsetArray), typeof(DateTimeOffset[])),
|
||||
new VectorStoreDataProperty(nameof(AzureAISearchAllTypes.DateTimeOffsetList), typeof(List<DateTimeOffset>)),
|
||||
|
||||
new VectorStoreVectorProperty(nameof(AzureAISearchAllTypes.Embedding), typeof(ReadOnlyMemory<float>?), 8) { DistanceFunction = Microsoft.Extensions.VectorData.DistanceFunction.DotProductSimilarity }
|
||||
]
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.Support;
|
||||
|
||||
public class AzureAISearchFixture : VectorStoreFixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.Support;
|
||||
|
||||
#pragma warning disable CA1810 // Initialize all static fields when those fields are declared
|
||||
|
||||
internal static class AzureAISearchTestEnvironment
|
||||
{
|
||||
#pragma warning disable CA1308 // Normalize strings to uppercase
|
||||
public static readonly string TestIndexPostfix = '-' + new Regex("[^a-zA-Z0-9]").Replace(Environment.MachineName.ToLowerInvariant(), "");
|
||||
#pragma warning restore CA1308 // Normalize strings to uppercase
|
||||
|
||||
public static readonly string? ServiceUrl, ApiKey;
|
||||
|
||||
public static bool IsConnectionInfoDefined => ServiceUrl is not null;
|
||||
|
||||
static AzureAISearchTestEnvironment()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile(path: "testsettings.json", optional: true)
|
||||
.AddJsonFile(path: "testsettings.development.json", optional: true)
|
||||
.AddEnvironmentVariables()
|
||||
.AddUserSecrets<AzureAISearchUrlRequiredAttribute>()
|
||||
.Build();
|
||||
|
||||
var azureAISearchSection = configuration.GetSection("AzureAISearch");
|
||||
ServiceUrl = azureAISearchSection?["ServiceUrl"];
|
||||
ApiKey = azureAISearchSection?["ApiKey"];
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Linq.Expressions;
|
||||
using Azure;
|
||||
using Azure.Identity;
|
||||
using Azure.Search.Documents.Indexes;
|
||||
using Humanizer;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.AzureAISearch;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.Support;
|
||||
|
||||
internal sealed class AzureAISearchTestStore : TestStore
|
||||
{
|
||||
public static AzureAISearchTestStore Instance { get; } = new();
|
||||
|
||||
private SearchIndexClient? _client;
|
||||
|
||||
public SearchIndexClient Client
|
||||
=> this._client ?? throw new InvalidOperationException("Call InitializeAsync() first");
|
||||
|
||||
public AzureAISearchVectorStore GetVectorStore(AzureAISearchVectorStoreOptions options)
|
||||
=> new(this.Client, options);
|
||||
|
||||
private AzureAISearchTestStore()
|
||||
{
|
||||
}
|
||||
|
||||
protected override Task StartAsync()
|
||||
{
|
||||
(string? serviceUrl, string? apiKey) = (AzureAISearchTestEnvironment.ServiceUrl, AzureAISearchTestEnvironment.ApiKey);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(serviceUrl))
|
||||
{
|
||||
throw new InvalidOperationException("Service URL is not configured, set AzureAISearch:ServiceUrl (and AzureAISearch:ApiKey if you want)");
|
||||
}
|
||||
|
||||
this._client = string.IsNullOrWhiteSpace(apiKey)
|
||||
? new SearchIndexClient(new Uri(serviceUrl), new DefaultAzureCredential())
|
||||
: new SearchIndexClient(new Uri(serviceUrl), new AzureKeyCredential(apiKey));
|
||||
|
||||
this.DefaultVectorStore = new AzureAISearchVectorStore(this._client);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Azure AI search only supports lowercase letters, digits or dashes.
|
||||
// Also, add a suffix containing machine name to allow multiple developers to work against the same cloud instance.
|
||||
public override string AdjustCollectionName(string baseName)
|
||||
=> baseName.Kebaberize() + AzureAISearchTestEnvironment.TestIndexPostfix;
|
||||
|
||||
public override async Task WaitForDataAsync<TKey, TRecord>(
|
||||
VectorStoreCollection<TKey, TRecord> collection,
|
||||
int recordCount,
|
||||
Expression<Func<TRecord, bool>>? filter = null,
|
||||
Expression<Func<TRecord, object?>>? vectorProperty = null,
|
||||
int? vectorSize = null,
|
||||
object? dummyVector = null)
|
||||
{
|
||||
await base.WaitForDataAsync(collection, recordCount, filter, vectorProperty, vectorSize, dummyVector);
|
||||
|
||||
// There seems to be some asynchronicity/race condition specific to Azure AI Search which isn't taken care
|
||||
// of by the generic retry loop in the base implementation.
|
||||
// TODO: Investigate this and remove
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(1000));
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
|
||||
namespace AzureAISearch.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 AzureAISearchUrlRequiredAttribute : Attribute, ITestCondition
|
||||
{
|
||||
public ValueTask<bool> IsMetAsync() => new(AzureAISearchTestEnvironment.IsConnectionInfoDefined);
|
||||
|
||||
public string Skip { get; set; } = "Service URL is not configured, set AzureAISearch:ServiceUrl (and AzureAISearch:ApiKey if you don't use managed identity).";
|
||||
|
||||
public string SkipReason
|
||||
=> this.Skip;
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.TypeTests;
|
||||
|
||||
public class AzureAISearchDataTypeTests(AzureAISearchDataTypeTests.Fixture fixture)
|
||||
: DataTypeTests<string, AzureAISearchDataTypeTests.Fixture.AzureAISearchRecord>(fixture),
|
||||
IClassFixture<AzureAISearchDataTypeTests.Fixture>
|
||||
{
|
||||
[ConditionalFact(Skip = "Issues around empty collection initialization")]
|
||||
public override Task String_array() => Task.CompletedTask;
|
||||
|
||||
protected override object? GenerateEmptyProperty(VectorStoreProperty property)
|
||||
=> property.Type switch
|
||||
{
|
||||
null => throw new InvalidOperationException($"Property '{property.Name}' has no type defined."),
|
||||
|
||||
// In Azure AI Search, array fields must be non-null (at least for now)
|
||||
var t when t.IsArray => Array.CreateInstance(t.GetElementType()!, 0),
|
||||
|
||||
_ => base.GenerateEmptyProperty(property)
|
||||
};
|
||||
|
||||
public new class Fixture : DataTypeTests<string, Fixture.AzureAISearchRecord>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
|
||||
public override IList<VectorStoreDataProperty> GetDataProperties()
|
||||
=> base.GetDataProperties().Where(p =>
|
||||
p.Type != typeof(byte)
|
||||
&& p.Type != typeof(short)
|
||||
&& p.Type != typeof(decimal)
|
||||
&& p.Type != typeof(Guid)
|
||||
#if NET
|
||||
&& p.Type != typeof(TimeOnly)
|
||||
#endif
|
||||
).ToList();
|
||||
|
||||
public override Type[] UnsupportedDefaultTypes { get; } =
|
||||
[
|
||||
typeof(byte),
|
||||
typeof(short),
|
||||
typeof(decimal),
|
||||
typeof(Guid),
|
||||
#if NET
|
||||
typeof(TimeOnly)
|
||||
#endif
|
||||
];
|
||||
|
||||
public class AzureAISearchRecord : RecordBase
|
||||
{
|
||||
public int Int { get; set; }
|
||||
public long Long { get; set; }
|
||||
public float Float { get; set; }
|
||||
public double Double { get; set; }
|
||||
|
||||
public string? String { get; set; }
|
||||
public bool Bool { get; set; }
|
||||
|
||||
public DateTime DateTime { get; set; }
|
||||
public DateTimeOffset DateTimeOffset { get; set; }
|
||||
|
||||
#if NET
|
||||
public DateOnly DateOnly { get; set; }
|
||||
#endif
|
||||
|
||||
public string[] StringArray { get; set; } = null!;
|
||||
|
||||
public int? NullableInt { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using Xunit;
|
||||
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.TypeTests;
|
||||
|
||||
public class AzureAISearchEmbeddingTypeTests(AzureAISearchEmbeddingTypeTests.Fixture fixture)
|
||||
: EmbeddingTypeTests<string>(fixture), IClassFixture<AzureAISearchEmbeddingTypeTests.Fixture>
|
||||
{
|
||||
public new class Fixture : EmbeddingTypeTests<string>.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using AzureAISearch.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.Support;
|
||||
using VectorData.ConformanceTests.TypeTests;
|
||||
using VectorData.ConformanceTests.Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace AzureAISearch.ConformanceTests.TypeTests;
|
||||
|
||||
public class AzureAISearchKeyTypeTests(AzureAISearchKeyTypeTests.Fixture fixture)
|
||||
: KeyTypeTests(fixture), IClassFixture<AzureAISearchKeyTypeTests.Fixture>
|
||||
{
|
||||
[ConditionalFact]
|
||||
public virtual Task String() => this.Test<string>("foo", "bar");
|
||||
|
||||
public new class Fixture : KeyTypeTests.Fixture
|
||||
{
|
||||
public override TestStore TestStore => AzureAISearchTestStore.Instance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user