diff --git a/dotnet/samples/GettingStartedWithAgents/Step04_KernelFunctionStrategies.cs b/dotnet/samples/GettingStartedWithAgents/Step04_KernelFunctionStrategies.cs index 4c7930bd2533..f924793951aa 100644 --- a/dotnet/samples/GettingStartedWithAgents/Step04_KernelFunctionStrategies.cs +++ b/dotnet/samples/GettingStartedWithAgents/Step04_KernelFunctionStrategies.cs @@ -70,11 +70,11 @@ public async Task UseKernelFunctionStrategiesWithAgentGroupChatAsync() Determine which participant takes the next turn in a conversation based on the the most recent participant. State only the name of the participant to take the next turn. No participant should take more than one turn in a row. - + Choose only from these participants: - {{{ReviewerName}}} - {{{CopyWriterName}}} - + Always follow these rules when selecting the next participant: - After {{{CopyWriterName}}}, it is {{{ReviewerName}}}'s turn. - After {{{ReviewerName}}}, it is {{{CopyWriterName}}}'s turn. @@ -133,9 +133,9 @@ No participant should take more than one turn in a row. chat.AddChatMessage(message); this.WriteAgentChatMessage(message); - await foreach (ChatMessageContent responese in chat.InvokeAsync()) + await foreach (ChatMessageContent response in chat.InvokeAsync()) { - this.WriteAgentChatMessage(responese); + this.WriteAgentChatMessage(response); } Console.WriteLine($"\n[IS COMPLETED: {chat.IsComplete}]"); diff --git a/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchBasicFilterTests.cs index 9683543d3e98..6a7e8a1df408 100644 --- a/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchBasicFilterTests.cs @@ -1,13 +1,24 @@ // Copyright (c) Microsoft. All rights reserved. +using AzureAISearchIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; namespace AzureAISearchIntegrationTests.Filter; -public class AzureAISearchBasicFilterTests(AzureAISearchFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture +public class AzureAISearchBasicFilterTests(AzureAISearchBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture { // Azure AI Search only supports search.in() over strings public override Task Contains_over_inline_int_array() => Assert.ThrowsAsync(() => base.Contains_over_inline_int_array()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => AzureAISearchTestStore.Instance; + + // Azure AI search only supports lowercase letters, digits or dashes. + protected override string CollectionName => "filter-tests"; + } } diff --git a/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchFilterFixture.cs deleted file mode 100644 index a5ec5df341dd..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/AzureAISearchIntegrationTests/Filter/AzureAISearchFilterFixture.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using AzureAISearchIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace AzureAISearchIntegrationTests.Filter; - -public class AzureAISearchFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => AzureAISearchTestStore.Instance; - - // Azure AI search only supports lowercase letters, digits or dashes. - protected override string StoreName => "filter-tests"; -} diff --git a/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoBasicFilterTests.cs index 33d14908f537..f7e52a5ec19a 100644 --- a/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoBasicFilterTests.cs @@ -1,12 +1,15 @@ // Copyright (c) Microsoft. All rights reserved. +using MongoDBIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using VectorDataSpecificationTests.Xunit; using Xunit; namespace MongoDBIntegrationTests.Filter; -public class CosmosMongoBasicFilterTests(CosmosMongoFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture +public class CosmosMongoBasicFilterTests(CosmosMongoBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture { // Specialized MongoDB syntax for NOT over Contains ($nin) [ConditionalFact] @@ -56,4 +59,12 @@ public override Task Legacy_AnyTagEqualTo_array() [Obsolete("Legacy filter support")] public override Task Legacy_AnyTagEqualTo_List() => Assert.ThrowsAsync(() => base.Legacy_AnyTagEqualTo_List()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => CosmosMongoDBTestStore.Instance; + + protected override string IndexKind => Microsoft.Extensions.VectorData.IndexKind.IvfFlat; + protected override string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance; + } } diff --git a/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoFilterFixture.cs deleted file mode 100644 index 129c7b0cc337..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/CosmosMongoDBIntegrationTests/Filter/CosmosMongoFilterFixture.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using MongoDBIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace MongoDBIntegrationTests.Filter; - -public class CosmosMongoFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => CosmosMongoDBTestStore.Instance; - - protected override string IndexKind => Microsoft.Extensions.VectorData.IndexKind.IvfFlat; - protected override string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance; -} diff --git a/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLBasicFilterTests.cs index b67141d82e6c..4058ea8674a7 100644 --- a/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLBasicFilterTests.cs @@ -1,8 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. +using CosmosNoSQLIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; namespace CosmosNoSQLIntegrationTests.Filter; -public class CosmosNoSQLBasicFilterTests(CosmosNoSQLFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture; +public class CosmosNoSQLBasicFilterTests(CosmosNoSQLBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture +{ + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => CosmosNoSqlTestStore.Instance; + } +} diff --git a/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLFilterFixture.cs deleted file mode 100644 index 8aaf6b86d4f9..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/CosmosNoSQLIntegrationTests/Filter/CosmosNoSQLFilterFixture.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using CosmosNoSQLIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace CosmosNoSQLIntegrationTests.Filter; - -public class CosmosNoSQLFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => CosmosNoSqlTestStore.Instance; -} diff --git a/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryBasicFilterTests.cs index 32adf75e9017..198178aae1a1 100644 --- a/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryBasicFilterTests.cs @@ -1,8 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. +using InMemoryIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; namespace PostgresIntegrationTests.Filter; -public class InMemoryBasicFilterTests(InMemoryFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture; +public class InMemoryBasicFilterTests(InMemoryBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture +{ + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => InMemoryTestStore.Instance; + } +} diff --git a/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryFilterFixture.cs deleted file mode 100644 index 7952d1dffad3..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/InMemoryIntegrationTests/Filter/InMemoryFilterFixture.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using InMemoryIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace PostgresIntegrationTests.Filter; - -public class InMemoryFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => InMemoryTestStore.Instance; -} diff --git a/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBBasicFilterTests.cs index a6ad4378f7a1..885c1503f5f7 100644 --- a/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBBasicFilterTests.cs @@ -1,12 +1,15 @@ // Copyright (c) Microsoft. All rights reserved. +using MongoDBIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using VectorDataSpecificationTests.Xunit; using Xunit; namespace MongoDBIntegrationTests.Filter; -public class MongoDBBasicFilterTests(MongoDBFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture +public class MongoDBBasicFilterTests(MongoDBBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture { // Specialized MongoDB syntax for NOT over Contains ($nin) [ConditionalFact] @@ -56,4 +59,9 @@ public override Task Legacy_AnyTagEqualTo_array() [Obsolete("Legacy filter support")] public override Task Legacy_AnyTagEqualTo_List() => Assert.ThrowsAsync(() => base.Legacy_AnyTagEqualTo_List()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => MongoDBTestStore.Instance; + } } diff --git a/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBFilterFixture.cs deleted file mode 100644 index 8774018ffabf..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/MongoDBIntegrationTests/Filter/MongoDBFilterFixture.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using MongoDBIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace MongoDBIntegrationTests.Filter; - -public class MongoDBFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => MongoDBTestStore.Instance; -} diff --git a/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresBasicFilterTests.cs index 4fad76458700..955d920cbde6 100644 --- a/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresBasicFilterTests.cs @@ -1,12 +1,15 @@ // Copyright (c) Microsoft. All rights reserved. +using PostgresIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; using Xunit.Sdk; namespace PostgresIntegrationTests.Filter; -public class PostgresBasicFilterTests(PostgresFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture +public class PostgresBasicFilterTests(PostgresBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture { public override async Task Not_over_Or() { @@ -29,4 +32,9 @@ public override async Task NotEqual_with_string() [Obsolete("Legacy filter support")] public override Task Legacy_AnyTagEqualTo_array() => Assert.ThrowsAsync(() => base.Legacy_AnyTagEqualTo_array()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => PostgresTestStore.Instance; + } } diff --git a/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresFilterFixture.cs deleted file mode 100644 index c65b37177003..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/PostgresIntegrationTests/Filter/PostgresFilterFixture.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using PostgresIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace PostgresIntegrationTests.Filter; - -public class PostgresFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => PostgresTestStore.Instance; -} diff --git a/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantBasicFilterTests.cs index 11593833dddf..13ed231a3207 100644 --- a/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantBasicFilterTests.cs @@ -1,8 +1,20 @@ // Copyright (c) Microsoft. All rights reserved. +using QdrantIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; namespace QdrantIntegrationTests.Filter; -public class QdrantBasicFilterTests(QdrantFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture; +public class QdrantBasicFilterTests(QdrantBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture +{ + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => QdrantTestStore.Instance; + + // Qdrant doesn't support the default Flat index kind + protected override string IndexKind => Microsoft.Extensions.VectorData.IndexKind.Hnsw; + } +} diff --git a/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantFilterFixture.cs deleted file mode 100644 index 8c8a6528b4f8..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/QdrantIntegrationTests/Filter/QdrantFilterFixture.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using QdrantIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace QdrantIntegrationTests.Filter; - -public class QdrantFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => QdrantTestStore.Instance; - - // Qdrant doesn't support the default Flat index kind - protected override string IndexKind => Microsoft.Extensions.VectorData.IndexKind.Hnsw; -} diff --git a/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisBasicFilterTests.cs index d0017e3a510c..978aa8d95484 100644 --- a/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisBasicFilterTests.cs @@ -1,12 +1,17 @@ // Copyright (c) Microsoft. All rights reserved. +using Microsoft.Extensions.VectorData; +using Microsoft.SemanticKernel.Connectors.Redis; +using RedisIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; using Xunit.Sdk; namespace RedisIntegrationTests.Filter; -public abstract class RedisBasicFilterTests(FilterFixtureBase fixture) : BasicFilterTestsBase(fixture) +public abstract class RedisBasicFilterTests(BasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture) { #region Equality with null @@ -51,9 +56,32 @@ public override Task Contains_over_captured_string_array() #endregion } -public class RedisJsonCollectionBasicFilterTests(RedisJsonCollectionFilterFixture fixture) : RedisBasicFilterTests(fixture), IClassFixture; +public class RedisJsonCollectionBasicFilterTests(RedisJsonCollectionBasicFilterTests.Fixture fixture) + : RedisBasicFilterTests(fixture), IClassFixture +{ + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => RedisTestStore.Instance; + + protected override string CollectionName => "JsonCollectionFilterTests"; + + // Override to remove the bool property, which isn't (currently) supported on Redis/JSON + protected override VectorStoreRecordDefinition GetRecordDefinition() + => new() + { + Properties = base.GetRecordDefinition().Properties.Where(p => p.PropertyType != typeof(bool)).ToList() + }; + + protected override IVectorStoreRecordCollection CreateCollection() + => new RedisJsonVectorStoreRecordCollection( + RedisTestStore.Instance.Database, + this.CollectionName, + new() { VectorStoreRecordDefinition = this.GetRecordDefinition() }); + } +} -public class RedisHashSetCollectionBasicFilterTests(RedisHashSetCollectionFilterFixture fixture) : RedisBasicFilterTests(fixture), IClassFixture +public class RedisHashSetCollectionBasicFilterTests(RedisHashSetCollectionBasicFilterTests.Fixture fixture) + : RedisBasicFilterTests(fixture), IClassFixture { // Null values are not supported in Redis HashSet public override Task Equal_with_null_reference_type() @@ -82,4 +110,40 @@ public override Task Legacy_AnyTagEqualTo_array() [Obsolete("Legacy filter support")] public override Task Legacy_AnyTagEqualTo_List() => Assert.ThrowsAsync(() => base.Legacy_AnyTagEqualTo_List()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => RedisTestStore.Instance; + + protected override string CollectionName => "HashSetCollectionFilterTests"; + + // Override to remove the bool property, which isn't (currently) supported on Redis + protected override VectorStoreRecordDefinition GetRecordDefinition() + => new() + { + Properties = base.GetRecordDefinition().Properties.Where(p => + p.PropertyType != typeof(bool) && + p.PropertyType != typeof(string[]) && + p.PropertyType != typeof(List)).ToList() + }; + + protected override IVectorStoreRecordCollection CreateCollection() + => new RedisHashSetVectorStoreRecordCollection( + RedisTestStore.Instance.Database, + this.CollectionName, + new() { VectorStoreRecordDefinition = this.GetRecordDefinition() }); + + protected override List BuildTestData() + { + var testData = base.BuildTestData(); + + foreach (var record in testData) + { + // Null values are not supported in Redis hashsets + record.String ??= string.Empty; + } + + return testData; + } + } } diff --git a/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisFilterFixture.cs deleted file mode 100644 index de751f36ca4e..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/RedisIntegrationTests/Filter/RedisFilterFixture.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Extensions.VectorData; -using Microsoft.SemanticKernel.Connectors.Redis; -using RedisIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace RedisIntegrationTests.Filter; - -public class RedisJsonCollectionFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => RedisTestStore.Instance; - - protected override string StoreName => "JsonCollectionFilterTests"; - - // Override to remove the bool property, which isn't (currently) supported on Redis/JSON - protected override VectorStoreRecordDefinition GetRecordDefinition() - => new() - { - Properties = base.GetRecordDefinition().Properties.Where(p => p.PropertyType != typeof(bool)).ToList() - }; - - protected override IVectorStoreRecordCollection> CreateCollection() - => new RedisJsonVectorStoreRecordCollection>( - RedisTestStore.Instance.Database, - this.StoreName, - new() { VectorStoreRecordDefinition = this.GetRecordDefinition() }); -} - -public class RedisHashSetCollectionFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => RedisTestStore.Instance; - - protected override string StoreName => "HashSetCollectionFilterTests"; - - // Override to remove the bool property, which isn't (currently) supported on Redis - protected override VectorStoreRecordDefinition GetRecordDefinition() - => new() - { - Properties = base.GetRecordDefinition().Properties.Where(p => - p.PropertyType != typeof(bool) && - p.PropertyType != typeof(string[]) && - p.PropertyType != typeof(List)).ToList() - }; - - protected override IVectorStoreRecordCollection> CreateCollection() - => new RedisHashSetVectorStoreRecordCollection>( - RedisTestStore.Instance.Database, - this.StoreName, - new() { VectorStoreRecordDefinition = this.GetRecordDefinition() }); - - protected override List> BuildTestData() - { - var testData = base.BuildTestData(); - - foreach (var record in testData) - { - // Null values are not supported in Redis hashsets - record.String ??= string.Empty; - } - - return testData; - } -} diff --git a/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteBasicFilterTests.cs index 9ca7878a414e..10570cc109c5 100644 --- a/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteBasicFilterTests.cs @@ -1,12 +1,16 @@ // Copyright (c) Microsoft. All rights reserved. +using Microsoft.Extensions.VectorData; +using SqliteIntegrationTests.Support; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; using Xunit; using Xunit.Sdk; namespace SqliteIntegrationTests.Filter; -public class SqliteBasicFilterTests(SqliteFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture +public class SqliteBasicFilterTests(SqliteBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture { public override async Task Not_over_Or() { @@ -42,4 +46,18 @@ public override Task Legacy_AnyTagEqualTo_array() [Obsolete("Legacy filter support")] public override Task Legacy_AnyTagEqualTo_List() => Assert.ThrowsAsync(() => base.Legacy_AnyTagEqualTo_List()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => SqliteTestStore.Instance; + + protected override string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance; + + // Override to remove the string array property, which isn't (currently) supported on SQLite + protected override VectorStoreRecordDefinition GetRecordDefinition() + => new() + { + Properties = base.GetRecordDefinition().Properties.Where(p => p.PropertyType != typeof(string[]) && p.PropertyType != typeof(List)).ToList() + }; + } } diff --git a/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteFilterFixture.cs deleted file mode 100644 index 3dc9a0d10dad..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/SqliteIntegrationTests/Filter/SqliteFilterFixture.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Extensions.VectorData; -using SqliteIntegrationTests.Support; -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; - -namespace SqliteIntegrationTests.Filter; - -public class SqliteFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => SqliteTestStore.Instance; - - protected override string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance; - - // Override to remove the string array property, which isn't (currently) supported on SQLite - protected override VectorStoreRecordDefinition GetRecordDefinition() - => new() - { - Properties = base.GetRecordDefinition().Properties.Where(p => p.PropertyType != typeof(string[]) && p.PropertyType != typeof(List)).ToList() - }; -} diff --git a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/BasicFilterTestsBase.cs b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/BasicFilterTests.cs similarity index 63% rename from dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/BasicFilterTestsBase.cs rename to dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/BasicFilterTests.cs index f2022a2e7c60..138f3863a5d4 100644 --- a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/BasicFilterTestsBase.cs +++ b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/BasicFilterTests.cs @@ -2,12 +2,13 @@ using System.Linq.Expressions; using Microsoft.Extensions.VectorData; +using VectorDataSpecificationTests.Support; using VectorDataSpecificationTests.Xunit; using Xunit; namespace VectorDataSpecificationTests.Filter; -public abstract class BasicFilterTestsBase(FilterFixtureBase fixture) +public abstract class BasicFilterTests(BasicFilterTests.Fixture fixture) where TKey : notnull { #region Equality @@ -214,7 +215,7 @@ public virtual Task Legacy_AnyTagEqualTo_List() #endregion Legacy filter support protected virtual async Task TestFilterAsync( - Expression, bool>> filter, + Expression> filter, bool expectZeroResults = false, bool expectAllResults = false) { @@ -249,7 +250,7 @@ protected virtual async Task TestFilterAsync( [Obsolete("Legacy filter support")] protected virtual async Task TestLegacyFilterAsync( VectorSearchFilter legacyFilter, - Expression, bool>> expectedFilter, + Expression> expectedFilter, bool expectZeroResults = false, bool expectAllResults = false) { @@ -280,4 +281,118 @@ protected virtual async Task TestLegacyFilterAsync( e.String == a.String && e.Int2 == a.Int2); } + +#pragma warning disable CS1819 // Properties should not return arrays +#pragma warning disable CA1819 // Properties should not return arrays + public class FilterRecord + { + public TKey Key { get; set; } = default!; + public ReadOnlyMemory? Vector { get; set; } + + public int Int { get; set; } + public string? String { get; set; } + public bool Bool { get; set; } + public int Int2 { get; set; } + public string[] StringArray { get; set; } = null!; + public List StringList { get; set; } = null!; + } +#pragma warning restore CA1819 // Properties should not return arrays +#pragma warning restore CS1819 + + public abstract class Fixture : VectorStoreCollectionFixture + { + protected override string CollectionName => "FilterTests"; + + protected override VectorStoreRecordDefinition GetRecordDefinition() + => new() + { + Properties = + [ + new VectorStoreRecordKeyProperty(nameof(FilterRecord.Key), typeof(TKey)), + new VectorStoreRecordVectorProperty(nameof(FilterRecord.Vector), typeof(ReadOnlyMemory?)) + { + Dimensions = 3, + DistanceFunction = this.DistanceFunction, + IndexKind = this.IndexKind + }, + + new VectorStoreRecordDataProperty(nameof(FilterRecord.Int), typeof(int)) { IsFilterable = true }, + new VectorStoreRecordDataProperty(nameof(FilterRecord.String), typeof(string)) { IsFilterable = true }, + new VectorStoreRecordDataProperty(nameof(FilterRecord.Bool), typeof(bool)) { IsFilterable = true }, + new VectorStoreRecordDataProperty(nameof(FilterRecord.Int2), typeof(int)) { IsFilterable = true }, + new VectorStoreRecordDataProperty(nameof(FilterRecord.StringArray), typeof(string[])) { IsFilterable = true }, + new VectorStoreRecordDataProperty(nameof(FilterRecord.StringList), typeof(List)) { IsFilterable = true } + ] + }; + + protected override List BuildTestData() + { + // All records have the same vector - this fixture is about testing criteria filtering only + var vector = new ReadOnlyMemory([1, 2, 3]); + + return + [ + new() + { + Key = this.GenerateNextKey(), + Int = 8, + String = "foo", + Bool = true, + Int2 = 80, + StringArray = ["x", "y"], + StringList = ["x", "y"], + Vector = vector + }, + new() + { + Key = this.GenerateNextKey(), + Int = 9, + String = "bar", + Bool = false, + Int2 = 90, + StringArray = ["a", "b"], + StringList = ["a", "b"], + Vector = vector + }, + new() + { + Key = this.GenerateNextKey(), + Int = 9, + String = "foo", + Bool = true, + Int2 = 9, + StringArray = ["x"], + StringList = ["x"], + Vector = vector + }, + new() + { + Key = this.GenerateNextKey(), + Int = 10, + String = null, + Bool = false, + Int2 = 100, + StringArray = ["x", "y", "z"], + StringList = ["x", "y", "z"], + Vector = vector + }, + new() + { + Key = this.GenerateNextKey(), + Int = 11, + Bool = true, + String = """with some special"characters'and\stuff""", + Int2 = 101, + StringArray = ["y", "z"], + StringList = ["y", "z"], + Vector = vector + } + ]; + } + + // In some databases (Azure AI Search), the data shows up but the filtering index isn't yet updated, + // so filtered searches show empty results. Add a filter to the seed data check below. + protected override Task WaitForDataAsync() + => this.TestStore.WaitForDataAsync(this.Collection, recordCount: this.TestData.Count, r => r.Int > 0); + } } diff --git a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/FilterFixtureBase.cs b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/FilterFixtureBase.cs deleted file mode 100644 index 436d1453d552..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Filter/FilterFixtureBase.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using System.Globalization; -using Microsoft.Extensions.VectorData; -using VectorDataSpecificationTests.Support; -using Xunit; - -namespace VectorDataSpecificationTests.Filter; - -public abstract class FilterFixtureBase : IAsyncLifetime - where TKey : notnull -{ - private int _nextKeyValue = 1; - private List>? _testData; - - protected virtual string StoreName => "FilterTests"; - - protected abstract TestStore TestStore { get; } - - protected virtual string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineSimilarity; - protected virtual string IndexKind => Microsoft.Extensions.VectorData.IndexKind.Flat; - - protected virtual IVectorStoreRecordCollection> CreateCollection() - => this.TestStore.DefaultVectorStore.GetCollection>(this.StoreName, this.GetRecordDefinition()); - - public virtual async Task InitializeAsync() - { - await this.TestStore.ReferenceCountingStartAsync(); - - this.Collection = this.CreateCollection(); - - if (await this.Collection.CollectionExistsAsync()) - { - await this.Collection.DeleteCollectionAsync(); - } - - await this.Collection.CreateCollectionAsync(); - await this.SeedAsync(); - - // Some databases upsert asynchronously, meaning that our seed data may not be visible immediately to tests. - // Check and loop until it is. - for (var i = 0; i < 20; i++) - { - var results = await this.Collection.VectorizedSearchAsync( - new ReadOnlyMemory([1, 2, 3]), - new() - { - Top = this.TestData.Count, - NewFilter = r => r.Int > 0 - }); - var count = await results.Results.CountAsync(); - if (count == this.TestData.Count) - { - break; - } - - await Task.Delay(TimeSpan.FromMilliseconds(100)); - } - } - - protected virtual VectorStoreRecordDefinition GetRecordDefinition() - => new() - { - Properties = - [ - new VectorStoreRecordKeyProperty(nameof(FilterRecord.Key), typeof(TKey)), - new VectorStoreRecordVectorProperty(nameof(FilterRecord.Vector), typeof(ReadOnlyMemory?)) - { - Dimensions = 3, - DistanceFunction = this.DistanceFunction, - IndexKind = this.IndexKind - }, - - new VectorStoreRecordDataProperty(nameof(FilterRecord.Int), typeof(int)) { IsFilterable = true }, - new VectorStoreRecordDataProperty(nameof(FilterRecord.String), typeof(string)) { IsFilterable = true }, - new VectorStoreRecordDataProperty(nameof(FilterRecord.Bool), typeof(bool)) { IsFilterable = true }, - new VectorStoreRecordDataProperty(nameof(FilterRecord.Int2), typeof(int)) { IsFilterable = true }, - new VectorStoreRecordDataProperty(nameof(FilterRecord.StringArray), typeof(string[])) { IsFilterable = true }, - new VectorStoreRecordDataProperty(nameof(FilterRecord.StringList), typeof(List)) { IsFilterable = true } - ] - }; - - public virtual IVectorStoreRecordCollection> Collection { get; private set; } = null!; - - public List> TestData => this._testData ??= this.BuildTestData(); - - protected virtual List> BuildTestData() - { - // All records have the same vector - this fixture is about testing criteria filtering only - var vector = new ReadOnlyMemory([1, 2, 3]); - - return - [ - new() - { - Key = this.GenerateNextKey(), - Int = 8, - String = "foo", - Bool = true, - Int2 = 80, - StringArray = ["x", "y"], - StringList = ["x", "y"], - Vector = vector - }, - new() - { - Key = this.GenerateNextKey(), - Int = 9, - String = "bar", - Bool = false, - Int2 = 90, - StringArray = ["a", "b"], - StringList = ["a", "b"], - Vector = vector - }, - new() - { - Key = this.GenerateNextKey(), - Int = 9, - String = "foo", - Bool = true, - Int2 = 9, - StringArray = ["x"], - StringList = ["x"], - Vector = vector - }, - new() - { - Key = this.GenerateNextKey(), - Int = 10, - String = null, - Bool = false, - Int2 = 100, - StringArray = ["x", "y", "z"], - StringList = ["x", "y", "z"], - Vector = vector - }, - new() - { - Key = this.GenerateNextKey(), - Int = 11, - Bool = true, - String = """with some special"characters'and\stuff""", - Int2 = 101, - StringArray = ["y", "z"], - StringList = ["y", "z"], - Vector = vector - } - ]; - } - - protected virtual async Task SeedAsync() - { - // TODO: UpsertBatchAsync returns IAsyncEnumerable (to support server-generated keys?), but this makes it quite hard to use: - await foreach (var _ in this.Collection.UpsertBatchAsync(this.TestData)) - { - } - } - - protected virtual TKey GenerateNextKey() - => typeof(TKey) switch - { - _ when typeof(TKey) == typeof(int) => (TKey)(object)this._nextKeyValue++, - _ when typeof(TKey) == typeof(long) => (TKey)(object)(long)this._nextKeyValue++, - _ when typeof(TKey) == typeof(ulong) => (TKey)(object)(ulong)this._nextKeyValue++, - _ when typeof(TKey) == typeof(string) => (TKey)(object)(this._nextKeyValue++).ToString(CultureInfo.InvariantCulture), - _ when typeof(TKey) == typeof(Guid) => (TKey)(object)new Guid($"00000000-0000-0000-0000-00{this._nextKeyValue++:0000000000}"), - - _ => throw new NotSupportedException($"Unsupported key of type '{typeof(TKey).Name}', override {nameof(this.GenerateNextKey)}") - }; - - public virtual Task DisposeAsync() - => this.TestStore.ReferenceCountingStopAsync(); -} - -#pragma warning disable CS1819 // Properties should not return arrays -#pragma warning disable CA1819 // Properties should not return arrays -public class FilterRecord -{ - public TKey Key { get; set; } = default!; - public ReadOnlyMemory? Vector { get; set; } - - public int Int { get; set; } - public string? String { get; set; } - public bool Bool { get; set; } - public int Int2 { get; set; } - public string[] StringArray { get; set; } = null!; - public List StringList { get; set; } = null!; -} -#pragma warning restore CA1819 // Properties should not return arrays -#pragma warning restore CS1819 diff --git a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/TestStore.cs b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/TestStore.cs index de7c0d252062..3facbed3c916 100644 --- a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/TestStore.cs +++ b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/TestStore.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All rights reserved. +using System.Globalization; +using System.Linq.Expressions; using Microsoft.Extensions.VectorData; namespace VectorDataSpecificationTests.Support; @@ -11,11 +13,16 @@ public abstract class TestStore private readonly SemaphoreSlim _lock = new(1, 1); private int _referenceCount; + public virtual string DefaultDistanceFunction => DistanceFunction.CosineSimilarity; + public virtual string DefaultIndexKind => IndexKind.Flat; + protected abstract Task StartAsync(); protected virtual Task StopAsync() => Task.CompletedTask; + public abstract IVectorStore DefaultVectorStore { get; } + public virtual async Task ReferenceCountingStartAsync() { await this._lock.WaitAsync(); @@ -48,5 +55,46 @@ public virtual async Task ReferenceCountingStopAsync() } } - public abstract IVectorStore DefaultVectorStore { get; } + public virtual TKey GenerateKey(int value) + => typeof(TKey) switch + { + _ when typeof(TKey) == typeof(int) => (TKey)(object)value, + _ when typeof(TKey) == typeof(long) => (TKey)(object)(long)value, + _ when typeof(TKey) == typeof(ulong) => (TKey)(object)(ulong)value, + _ when typeof(TKey) == typeof(string) => (TKey)(object)value.ToString(CultureInfo.InvariantCulture), + _ when typeof(TKey) == typeof(Guid) => (TKey)(object)new Guid($"00000000-0000-0000-0000-00{value:0000000000}"), + + _ => throw new NotSupportedException($"Unsupported key of type '{typeof(TKey).Name}', override {nameof(TestStore)}.{nameof(this.GenerateKey)}") + }; + + /// Loops until the expected number of records is visible in the given collection. + /// Some databases upsert asynchronously, meaning that our seed data may not be visible immediately to tests. + public virtual async Task WaitForDataAsync( + IVectorStoreRecordCollection collection, + int recordCount, + Expression>? filter = null) + where TKey : notnull + { + for (var i = 0; i < 20; i++) + { + var results = await collection.VectorizedSearchAsync( + new ReadOnlyMemory([1, 2, 3]), + new() + { + Top = recordCount, + // In some databases (Azure AI Search), the data shows up but the filtering index isn't yet updated, + // so filtered searches show empty results. Add a filter to the seed data check below. + NewFilter = filter + }); + var count = await results.Results.CountAsync(); + if (count == recordCount) + { + return; + } + + await Task.Delay(TimeSpan.FromMilliseconds(100)); + } + + throw new InvalidOperationException("Data did not appear in the collection within the expected time."); + } } diff --git a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/VectorStoreCollectionFixture.cs b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/VectorStoreCollectionFixture.cs new file mode 100644 index 000000000000..f6506b6fa5de --- /dev/null +++ b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/VectorStoreCollectionFixture.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Extensions.VectorData; + +namespace VectorDataSpecificationTests.Support; + +/// +/// A test fixture that sets up a single collection in the test vector store, with a specific record definition +/// and test data. +/// +public abstract class VectorStoreCollectionFixture : VectorStoreFixture + where TKey : notnull +{ + private List? _testData; + + protected abstract string CollectionName { get; } + protected abstract VectorStoreRecordDefinition GetRecordDefinition(); + protected abstract List BuildTestData(); + + protected virtual string DistanceFunction => this.TestStore.DefaultDistanceFunction; + protected virtual string IndexKind => this.TestStore.DefaultIndexKind; + + protected virtual IVectorStoreRecordCollection CreateCollection() + => this.TestStore.DefaultVectorStore.GetCollection(this.CollectionName, this.GetRecordDefinition()); + + public override async Task InitializeAsync() + { + await base.InitializeAsync(); + + this.Collection = this.CreateCollection(); + + if (await this.Collection.CollectionExistsAsync()) + { + await this.Collection.DeleteCollectionAsync(); + } + + await this.Collection.CreateCollectionAsync(); + await this.SeedAsync(); + } + + public virtual IVectorStoreRecordCollection Collection { get; private set; } = null!; + + public List TestData => this._testData ??= this.BuildTestData(); + + protected virtual async Task SeedAsync() + { + // TODO: UpsertBatchAsync returns IAsyncEnumerable (to support server-generated keys?), but this makes it quite hard to use: + await foreach (var _ in this.Collection.UpsertBatchAsync(this.TestData)) + { + } + + await this.WaitForDataAsync(); + } + + protected virtual Task WaitForDataAsync() + => this.TestStore.WaitForDataAsync(this.Collection, recordCount: this.TestData.Count); +} diff --git a/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/VectorStoreFixture.cs b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/VectorStoreFixture.cs new file mode 100644 index 000000000000..af4d97e95a29 --- /dev/null +++ b/dotnet/src/VectorDataIntegrationTests/VectorDataIntegrationTests/Support/VectorStoreFixture.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Xunit; + +namespace VectorDataSpecificationTests.Support; + +public abstract class VectorStoreFixture : IAsyncLifetime +{ + private int _nextKeyValue = 1; + + public abstract TestStore TestStore { get; } + + public virtual string DefaultDistanceFunction => this.TestStore.DefaultDistanceFunction; + public virtual string DefaultIndexKind => this.TestStore.DefaultIndexKind; + + public virtual Task InitializeAsync() + => this.TestStore.ReferenceCountingStartAsync(); + + public virtual Task DisposeAsync() + => this.TestStore.ReferenceCountingStopAsync(); + + public virtual TKey GenerateNextKey() + => this.TestStore.GenerateKey(this._nextKeyValue++); +} diff --git a/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateBasicFilterTests.cs b/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateBasicFilterTests.cs index 2880d1b93859..6238ca6d9b6a 100644 --- a/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateBasicFilterTests.cs +++ b/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateBasicFilterTests.cs @@ -2,12 +2,15 @@ using Microsoft.Extensions.VectorData; using VectorDataSpecificationTests.Filter; +using VectorDataSpecificationTests.Support; +using WeaviateIntegrationTests.Support; using Xunit; using Xunit.Sdk; namespace WeaviateIntegrationTests.Filter; -public class WeaviateBasicFilterTests(WeaviateFilterFixture fixture) : BasicFilterTestsBase(fixture), IClassFixture +public class WeaviateBasicFilterTests(WeaviateBasicFilterTests.Fixture fixture) + : BasicFilterTests(fixture), IClassFixture { #region Filter by null @@ -59,4 +62,11 @@ public override Task Contains_over_inline_string_array_with_weird_chars() // (https://weaviate.io/developers/weaviate/api/graphql/filters#multi-word-queries-in-equal-filters) public override Task Equal_with_string_is_not_Contains() => Assert.ThrowsAsync(() => base.Equal_with_string_is_not_Contains()); + + public new class Fixture : BasicFilterTests.Fixture + { + public override TestStore TestStore => WeaviateTestStore.Instance; + + protected override string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance; + } } diff --git a/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateFilterFixture.cs b/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateFilterFixture.cs deleted file mode 100644 index f00b884780c2..000000000000 --- a/dotnet/src/VectorDataIntegrationTests/WeaviateIntegrationTests/Filter/WeaviateFilterFixture.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using VectorDataSpecificationTests.Filter; -using VectorDataSpecificationTests.Support; -using WeaviateIntegrationTests.Support; - -namespace WeaviateIntegrationTests.Filter; - -public class WeaviateFilterFixture : FilterFixtureBase -{ - protected override TestStore TestStore => WeaviateTestStore.Instance; - - protected override string DistanceFunction => Microsoft.Extensions.VectorData.DistanceFunction.CosineDistance; -}