Files
microsoft--semantic-kernel/dotnet/test/VectorData/AzureAISearch.UnitTests/AzureAISearchCollectionCreateMappingTests.cs
T
wehub-resource-sync b957a53def
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:21:23 +08:00

223 lines
8.1 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.Generic;
using Azure.Search.Documents.Indexes.Models;
using Microsoft.Extensions.VectorData;
using Microsoft.Extensions.VectorData.ProviderServices;
using Microsoft.SemanticKernel.Connectors.AzureAISearch;
using Xunit;
namespace SemanticKernel.Connectors.AzureAISearch.UnitTests;
/// <summary>
/// Contains tests for the <see cref="AzureAISearchCollectionCreateMapping"/> class.
/// </summary>
public class AzureAISearchCollectionCreateMappingTests
{
[Fact]
public void MapKeyFieldCreatesSearchableField()
{
// Arrange
var keyProperty = new KeyPropertyModel("testkey", typeof(string)) { StorageName = "test_key" };
// Act
var result = AzureAISearchCollectionCreateMapping.MapKeyField(keyProperty);
// Assert
Assert.NotNull(result);
Assert.Equal("test_key", result.Name);
Assert.True(result.IsKey);
Assert.True(result.IsFilterable);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void MapFilterableStringDataFieldCreatesSimpleField(bool isFilterable)
{
// Arrange
var dataProperty = new DataPropertyModel("testdata", typeof(string))
{
IsIndexed = isFilterable,
StorageName = "test_data"
};
// Act
var result = AzureAISearchCollectionCreateMapping.MapDataField(dataProperty);
// Assert
Assert.NotNull(result);
Assert.IsType<SimpleField>(result);
Assert.Equal("test_data", result.Name);
Assert.False(result.IsKey);
Assert.Equal(isFilterable, result.IsFilterable);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void MapFullTextSearchableStringDataFieldCreatesSearchableField(bool isFilterable)
{
// Arrange
var dataProperty = new DataPropertyModel("testdata", typeof(string))
{
IsIndexed = isFilterable,
IsFullTextIndexed = true,
StorageName = "test_data"
};
// Act
var result = AzureAISearchCollectionCreateMapping.MapDataField(dataProperty);
// Assert
Assert.NotNull(result);
Assert.IsType<SearchableField>(result);
Assert.Equal("test_data", result.Name);
Assert.False(result.IsKey);
Assert.Equal(isFilterable, result.IsFilterable);
}
[Fact]
public void MapFullTextSearchableStringDataFieldThrowsForInvalidType()
{
// Arrange
var dataProperty = new DataPropertyModel("testdata", typeof(int))
{
IsFullTextIndexed = true,
StorageName = "test_data"
};
// Act & Assert
Assert.Throws<InvalidOperationException>(() => AzureAISearchCollectionCreateMapping.MapDataField(dataProperty));
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void MapDataFieldCreatesSimpleField(bool isFilterable)
{
// Arrange
var dataProperty = new DataPropertyModel("testdata", typeof(int))
{
IsIndexed = isFilterable,
StorageName = "test_data"
};
// Act
var result = AzureAISearchCollectionCreateMapping.MapDataField(dataProperty);
// Assert
Assert.NotNull(result);
Assert.IsType<SimpleField>(result);
Assert.Equal("test_data", result.Name);
Assert.Equal(SearchFieldDataType.Int32, result.Type);
Assert.False(result.IsKey);
Assert.Equal(isFilterable, result.IsFilterable);
}
[Fact]
public void MapVectorFieldCreatesVectorSearchField()
{
// Arrange
var vectorProperty = new VectorPropertyModel("testvector", typeof(ReadOnlyMemory<float>))
{
Dimensions = 10,
IndexKind = IndexKind.Flat,
DistanceFunction = DistanceFunction.DotProductSimilarity,
StorageName = "test_vector"
};
// Act
var (vectorSearchField, algorithmConfiguration, vectorSearchProfile) = AzureAISearchCollectionCreateMapping.MapVectorField(vectorProperty);
// Assert
Assert.NotNull(vectorSearchField);
Assert.NotNull(algorithmConfiguration);
Assert.NotNull(vectorSearchProfile);
Assert.Equal("test_vector", vectorSearchField.Name);
Assert.Equal(vectorProperty.Dimensions, vectorSearchField.VectorSearchDimensions);
Assert.Equal("test_vectorAlgoConfig", algorithmConfiguration.Name);
Assert.IsType<ExhaustiveKnnAlgorithmConfiguration>(algorithmConfiguration);
var flatConfig = algorithmConfiguration as ExhaustiveKnnAlgorithmConfiguration;
Assert.Equal(VectorSearchAlgorithmMetric.DotProduct, flatConfig!.Parameters.Metric);
Assert.Equal("test_vectorProfile", vectorSearchProfile.Name);
Assert.Equal("test_vectorAlgoConfig", vectorSearchProfile.AlgorithmConfigurationName);
}
[Theory]
[InlineData(IndexKind.Hnsw, typeof(HnswAlgorithmConfiguration))]
[InlineData(IndexKind.Flat, typeof(ExhaustiveKnnAlgorithmConfiguration))]
public void MapVectorFieldCreatesExpectedAlgoConfigTypes(string indexKind, Type algoConfigType)
{
// Arrange
var vectorProperty = new VectorPropertyModel("testvector", typeof(ReadOnlyMemory<float>))
{
Dimensions = 10,
IndexKind = indexKind,
DistanceFunction = DistanceFunction.DotProductSimilarity,
StorageName = "test_vector"
};
// Act
var (vectorSearchField, algorithmConfiguration, vectorSearchProfile) = AzureAISearchCollectionCreateMapping.MapVectorField(vectorProperty);
// Assert
Assert.Equal("test_vectorAlgoConfig", algorithmConfiguration.Name);
Assert.Equal(algoConfigType, algorithmConfiguration.GetType());
}
[Fact]
public void MapVectorFieldDefaultsToHsnwAndCosine()
{
// Arrange
var vectorProperty = new VectorPropertyModel("testvector", typeof(ReadOnlyMemory<float>)) { Dimensions = 10 };
// Act
var (vectorSearchField, algorithmConfiguration, vectorSearchProfile) = AzureAISearchCollectionCreateMapping.MapVectorField(vectorProperty);
// Assert
Assert.IsType<HnswAlgorithmConfiguration>(algorithmConfiguration);
var hnswConfig = algorithmConfiguration as HnswAlgorithmConfiguration;
Assert.Equal(VectorSearchAlgorithmMetric.Cosine, hnswConfig!.Parameters.Metric);
}
[Fact]
public void MapVectorFieldThrowsForUnsupportedDistanceFunction()
{
// Arrange
var vectorProperty = new VectorPropertyModel("testvector", typeof(ReadOnlyMemory<float>))
{
Dimensions = 10,
DistanceFunction = DistanceFunction.ManhattanDistance,
};
// Act & Assert
Assert.Throws<NotSupportedException>(() => AzureAISearchCollectionCreateMapping.MapVectorField(vectorProperty));
}
[Theory]
[MemberData(nameof(DataTypeMappingOptions))]
public void GetSDKFieldDataTypeMapsTypesCorrectly(Type propertyType, SearchFieldDataType searchFieldDataType)
{
// Act & Assert
Assert.Equal(searchFieldDataType, AzureAISearchCollectionCreateMapping.GetSDKFieldDataType(propertyType));
}
public static IEnumerable<object[]> DataTypeMappingOptions()
{
yield return new object[] { typeof(string), SearchFieldDataType.String };
yield return new object[] { typeof(bool), SearchFieldDataType.Boolean };
yield return new object[] { typeof(int), SearchFieldDataType.Int32 };
yield return new object[] { typeof(long), SearchFieldDataType.Int64 };
yield return new object[] { typeof(float), SearchFieldDataType.Double };
yield return new object[] { typeof(double), SearchFieldDataType.Double };
yield return new object[] { typeof(DateTimeOffset), SearchFieldDataType.DateTimeOffset };
yield return new object[] { typeof(string[]), SearchFieldDataType.Collection(SearchFieldDataType.String) };
yield return new object[] { typeof(List<string>), SearchFieldDataType.Collection(SearchFieldDataType.String) };
}
}