chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.Extensions.VectorData.ProviderServices;
|
||||
using StackExchange.Redis;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SemanticKernel.Connectors.Redis.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Contains dynamic mapping tests for the <see cref="RedisHashSetMapper{TConsumerDataModel}"/> class.
|
||||
/// </summary>
|
||||
public class RedisHashSetDynamicMappingTests
|
||||
{
|
||||
private static readonly CollectionModel s_model = BuildModel(RedisHashSetMappingTestHelpers.s_definition);
|
||||
|
||||
private static readonly float[] s_floatVector = new float[] { 1.0f, 2.0f, 3.0f, 4.0f };
|
||||
private static readonly double[] s_doubleVector = new double[] { 5.0d, 6.0d, 7.0d, 8.0d };
|
||||
|
||||
[Fact]
|
||||
public void MapFromDataToStorageModelMapsAllSupportedTypes()
|
||||
{
|
||||
// Arrange.
|
||||
var sut = new RedisHashSetMapper<Dictionary<string, object?>>(s_model);
|
||||
var dataModel = new Dictionary<string, object?>
|
||||
{
|
||||
["Key"] = "key",
|
||||
|
||||
["StringData"] = "data 1",
|
||||
["IntData"] = 1,
|
||||
["UIntData"] = 2u,
|
||||
["LongData"] = 3L,
|
||||
["ULongData"] = 4ul,
|
||||
["DoubleData"] = 5.5d,
|
||||
["FloatData"] = 6.6f,
|
||||
["NullableIntData"] = 7,
|
||||
["NullableUIntData"] = 8u,
|
||||
["NullableLongData"] = 9L,
|
||||
["NullableULongData"] = 10ul,
|
||||
["NullableDoubleData"] = 11.1d,
|
||||
["NullableFloatData"] = 12.2f,
|
||||
|
||||
["FloatVector"] = new ReadOnlyMemory<float>(s_floatVector),
|
||||
["DoubleVector"] = new ReadOnlyMemory<double>(s_doubleVector),
|
||||
};
|
||||
|
||||
// Act.
|
||||
var storageModel = sut.MapFromDataToStorageModel(dataModel, recordIndex: 0, generatedEmbeddings: null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("key", storageModel.Key);
|
||||
RedisHashSetMappingTestHelpers.VerifyHashSet(storageModel.HashEntries);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapFromDataToStorageModelMapsNullValues()
|
||||
{
|
||||
// Arrange
|
||||
CollectionModel model = BuildModel(new()
|
||||
{
|
||||
Properties =
|
||||
[
|
||||
new VectorStoreKeyProperty("Key", typeof(string)),
|
||||
new VectorStoreDataProperty("StringData", typeof(string)) { StorageName = "storage_string_data" },
|
||||
new VectorStoreDataProperty("NullableIntData", typeof(int?)),
|
||||
new VectorStoreVectorProperty("FloatVector", typeof(ReadOnlyMemory<float>?), 10),
|
||||
],
|
||||
});
|
||||
|
||||
var dataModel = new Dictionary<string, object?>
|
||||
{
|
||||
["Key"] = "key",
|
||||
["StringData"] = null,
|
||||
["NullableIntData"] = null,
|
||||
["FloatVector"] = null,
|
||||
};
|
||||
|
||||
var sut = new RedisHashSetMapper<Dictionary<string, object?>>(model);
|
||||
|
||||
// Act
|
||||
var storageModel = sut.MapFromDataToStorageModel(dataModel, recordIndex: 0, generatedEmbeddings: null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("key", storageModel.Key);
|
||||
|
||||
Assert.Equal("storage_string_data", storageModel.HashEntries[0].Name.ToString());
|
||||
Assert.True(storageModel.HashEntries[0].Value.IsNull);
|
||||
|
||||
Assert.Equal("NullableIntData", storageModel.HashEntries[1].Name.ToString());
|
||||
Assert.True(storageModel.HashEntries[1].Value.IsNull);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapFromStorageToDataModelMapsAllSupportedTypes()
|
||||
{
|
||||
// Arrange.
|
||||
var hashSet = RedisHashSetMappingTestHelpers.CreateHashSet();
|
||||
var sut = new RedisHashSetMapper<Dictionary<string, object?>>(s_model);
|
||||
|
||||
// Act.
|
||||
var dataModel = sut.MapFromStorageToDataModel(("key", hashSet), includeVectors: true);
|
||||
|
||||
// Assert.
|
||||
Assert.Equal("key", dataModel["Key"]);
|
||||
Assert.Equal("data 1", dataModel["StringData"]);
|
||||
Assert.Equal(1, dataModel["IntData"]);
|
||||
Assert.Equal(2u, dataModel["UIntData"]);
|
||||
Assert.Equal(3L, dataModel["LongData"]);
|
||||
Assert.Equal(4ul, dataModel["ULongData"]);
|
||||
Assert.Equal(5.5d, dataModel["DoubleData"]);
|
||||
Assert.Equal(6.6f, dataModel["FloatData"]);
|
||||
Assert.Equal(7, dataModel["NullableIntData"]);
|
||||
Assert.Equal(8u, dataModel["NullableUIntData"]);
|
||||
Assert.Equal(9L, dataModel["NullableLongData"]);
|
||||
Assert.Equal(10ul, dataModel["NullableULongData"]);
|
||||
Assert.Equal(11.1d, dataModel["NullableDoubleData"]);
|
||||
Assert.Equal(12.2f, dataModel["NullableFloatData"]);
|
||||
Assert.Equal(new float[] { 1, 2, 3, 4 }, ((ReadOnlyMemory<float>)dataModel["FloatVector"]!).ToArray());
|
||||
Assert.Equal(new double[] { 5, 6, 7, 8 }, ((ReadOnlyMemory<double>)dataModel["DoubleVector"]!).ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapFromStorageToDataModelMapsNullValues()
|
||||
{
|
||||
// Arrange
|
||||
var model = BuildModel(new()
|
||||
{
|
||||
Properties =
|
||||
[
|
||||
new VectorStoreKeyProperty("Key", typeof(string)),
|
||||
new VectorStoreDataProperty("StringData", typeof(string)) { StorageName = "storage_string_data" },
|
||||
new VectorStoreDataProperty("NullableIntData", typeof(int?)),
|
||||
new VectorStoreVectorProperty("FloatVector", typeof(ReadOnlyMemory<float>?), 10),
|
||||
]
|
||||
});
|
||||
|
||||
var hashSet = new HashEntry[]
|
||||
{
|
||||
new("storage_string_data", RedisValue.Null),
|
||||
new("NullableIntData", RedisValue.Null),
|
||||
new("FloatVector", RedisValue.Null),
|
||||
};
|
||||
|
||||
var sut = new RedisHashSetMapper<Dictionary<string, object?>>(model);
|
||||
|
||||
// Act
|
||||
var dataModel = sut.MapFromStorageToDataModel(("key", hashSet), includeVectors: true);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("key", dataModel["Key"]);
|
||||
Assert.Null(dataModel["StringData"]);
|
||||
Assert.Null(dataModel["NullableIntData"]);
|
||||
Assert.Null(dataModel["FloatVector"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapFromDataToStorageModelSkipsMissingProperties()
|
||||
{
|
||||
// Arrange.
|
||||
var model = BuildModel(new()
|
||||
{
|
||||
Properties =
|
||||
[
|
||||
new VectorStoreKeyProperty("Key", typeof(string)),
|
||||
new VectorStoreDataProperty("StringData", typeof(string)) { StorageName = "storage_string_data" },
|
||||
new VectorStoreDataProperty("NullableIntData", typeof(int?)),
|
||||
new VectorStoreVectorProperty("FloatVector", typeof(ReadOnlyMemory<float>?), 10),
|
||||
]
|
||||
});
|
||||
|
||||
var sut = new RedisHashSetMapper<Dictionary<string, object?>>(model);
|
||||
var dataModel = new Dictionary<string, object?> { ["Key"] = "key" };
|
||||
|
||||
// Act.
|
||||
var storageModel = sut.MapFromDataToStorageModel(dataModel, recordIndex: 0, generatedEmbeddings: null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("key", storageModel.Key);
|
||||
|
||||
Assert.Equal("storage_string_data", storageModel.HashEntries[0].Name.ToString());
|
||||
Assert.True(storageModel.HashEntries[0].Value.IsNull);
|
||||
|
||||
Assert.Equal("NullableIntData", storageModel.HashEntries[1].Name.ToString());
|
||||
Assert.True(storageModel.HashEntries[1].Value.IsNull);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MapFromStorageToDataModelSkipsMissingProperties()
|
||||
{
|
||||
// Arrange.
|
||||
var hashSet = Array.Empty<HashEntry>();
|
||||
|
||||
var sut = new RedisHashSetMapper<Dictionary<string, object?>>(s_model);
|
||||
|
||||
// Act.
|
||||
var dataModel = sut.MapFromStorageToDataModel(("key", hashSet), includeVectors: true);
|
||||
|
||||
// Assert.
|
||||
Assert.Single(dataModel);
|
||||
Assert.Equal("key", dataModel["Key"]);
|
||||
}
|
||||
|
||||
private static CollectionModel BuildModel(VectorStoreCollectionDefinition definition)
|
||||
=> new RedisModelBuilder(RedisHashSetCollection<object, Dictionary<string, object?>>.ModelBuildingOptions)
|
||||
.BuildDynamic(definition, defaultEmbeddingGenerator: null);
|
||||
}
|
||||
Reference in New Issue
Block a user