chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,6 @@
# Suppressing errors for Test projects under dotnet folder
[*.cs]
dotnet_diagnostic.CA2007.severity = none # Do not directly await a Task
dotnet_diagnostic.VSTHRD111.severity = none # Use .ConfigureAwait(bool) is hidden by default, set to none to prevent IDE from changing on autosave
dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member
dotnet_diagnostic.IDE1006.severity = warning # Naming rule violations
@@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>SemanticKernel.Connectors.InMemory.UnitTests</AssemblyName>
<RootNamespace>SemanticKernel.Connectors.InMemory.UnitTests</RootNamespace>
<TargetFramework>net10.0</TargetFramework>
<IsTestProject>true</IsTestProject>
<Nullable>enable</Nullable>
<ImplicitUsings>disable</ImplicitUsings>
<IsPackable>false</IsPackable>
<NoWarn>$(NoWarn);CA2007,CA1806,CA1869,CA1861,IDE0300,VSTHRD111,SKEXP0001</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
<PackageReference Include="Moq"/>
<PackageReference Include="xunit"/>
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)/dotnet/src/InternalUtilities/test/AssertExtensions.cs"
Link="%(RecursiveDir)%(Filename)%(Extension)"/>
<Compile Include="$(RepoRoot)/dotnet/src/InternalUtilities/test/HttpMessageHandlerStub.cs"
Link="%(RecursiveDir)%(Filename)%(Extension)"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\VectorData\InMemory\InMemory.csproj" />
<ProjectReference Include="..\..\..\src\SemanticKernel.Core\SemanticKernel.Core.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,70 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.InMemory;
using Xunit;
namespace SemanticKernel.Connectors.InMemory.UnitTests;
/// <summary>
/// Contains tests for the <see cref="InMemoryServiceCollectionExtensions"/> class.
/// </summary>
public class InMemoryServiceCollectionExtensionsTests
{
private readonly IServiceCollection _serviceCollection;
public InMemoryServiceCollectionExtensionsTests()
{
this._serviceCollection = new ServiceCollection();
}
[Fact]
public void AddVectorStoreRegistersClass()
{
// Act.
this._serviceCollection.AddInMemoryVectorStore();
// Assert.
var serviceProvider = this._serviceCollection.BuildServiceProvider();
var vectorStore = serviceProvider.GetRequiredService<VectorStore>();
Assert.NotNull(vectorStore);
Assert.IsType<InMemoryVectorStore>(vectorStore);
}
[Fact]
public void AddVectorStoreRecordCollectionRegistersClass()
{
// Act.
this._serviceCollection.AddInMemoryVectorStoreRecordCollection<string, TestRecord>("testcollection");
// Assert.
this.AssertVectorStoreRecordCollectionCreated();
}
private void AssertVectorStoreRecordCollectionCreated()
{
var serviceProvider = this._serviceCollection.BuildServiceProvider();
var collection = serviceProvider.GetRequiredService<VectorStoreCollection<string, TestRecord>>();
Assert.NotNull(collection);
Assert.IsType<InMemoryCollection<string, TestRecord>>(collection);
var vectorizedSearch = serviceProvider.GetRequiredService<IVectorSearchable<TestRecord>>();
Assert.NotNull(vectorizedSearch);
Assert.IsType<InMemoryCollection<string, TestRecord>>(vectorizedSearch);
}
#pragma warning disable CA1812 // Avoid uninstantiated internal classes
private sealed class TestRecord
#pragma warning restore CA1812 // Avoid uninstantiated internal classes
{
[VectorStoreKey]
public string Id { get; set; } = string.Empty;
[VectorStoreVector(4)]
public ReadOnlyMemory<float> Vector { get; set; }
}
}
@@ -0,0 +1,166 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;
using Xunit;
namespace SemanticKernel.Connectors.InMemory.UnitTests;
public class InMemoryVectorStoreExtensionsTests
{
[Fact]
public async Task SerializeAndDeserializeCollectionRoundtripWorks()
{
// Arrange
using var vectorStore = new InMemoryVectorStore();
var collectionName = "test-collection";
var collection = vectorStore.GetCollection<Guid, TestRecord>(collectionName);
var record1 = new TestRecord
{
Key = Guid.NewGuid(),
Text = "First record",
Embedding = new ReadOnlyMemory<float>(new float[] { 0.1f, 0.2f, 0.3f })
};
var record2 = new TestRecord
{
Key = Guid.NewGuid(),
Text = "Second record",
Embedding = new ReadOnlyMemory<float>(new float[] { 0.4f, 0.5f, 0.6f })
};
await collection.EnsureCollectionExistsAsync();
await collection.UpsertAsync(new[] { record1, record2 });
// Act
using var memStream = new MemoryStream();
await vectorStore.SerializeCollectionAsJsonAsync<Guid, TestRecord>(collectionName, memStream);
memStream.Position = 0;
// Simulate loading into a new store
using var newVectorStore = new InMemoryVectorStore();
var deserializedCollection = await newVectorStore.DeserializeCollectionFromJsonAsync<Guid, TestRecord>(memStream);
// Assert
Assert.NotNull(deserializedCollection);
var loadedRecord1 = await deserializedCollection.GetAsync(record1.Key);
var loadedRecord2 = await deserializedCollection.GetAsync(record2.Key);
Assert.NotNull(loadedRecord1);
Assert.NotNull(loadedRecord2);
Assert.Equal(record1.Text, loadedRecord1.Text);
Assert.Equal(record2.Text, loadedRecord2.Text);
Assert.Equal(record1.Embedding, loadedRecord1.Embedding);
Assert.Equal(record2.Embedding, loadedRecord2.Embedding);
}
[Fact]
public async Task SerializeAndDeserializeCollectionRoundtripWithBuiltInEmbeddingGenerationWorks()
{
// Arrange
using var vectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = new FakeEmbeddingGenerator() });
var collectionName = "test-collection";
var collection = vectorStore.GetCollection<Guid, TestRecordAutoEmbed>(collectionName);
var record1 = new TestRecordAutoEmbed
{
Key = Guid.NewGuid(),
Text = "First record",
};
var record2 = new TestRecordAutoEmbed
{
Key = Guid.NewGuid(),
Text = "Second record",
};
await collection.EnsureCollectionExistsAsync();
await collection.UpsertAsync(new[] { record1, record2 });
// Act
using var memStream = new MemoryStream();
await vectorStore.SerializeCollectionAsJsonAsync<Guid, TestRecordAutoEmbed>(collectionName, memStream);
memStream.Position = 0;
// Simulate loading into a new store
using var newVectorStore = new InMemoryVectorStore(new() { EmbeddingGenerator = new FakeEmbeddingGenerator() });
var deserializedCollection = await newVectorStore.DeserializeCollectionFromJsonAsync<Guid, TestRecordAutoEmbed>(memStream);
// Assert
Assert.NotNull(deserializedCollection);
var loadedRecord1 = await deserializedCollection.GetAsync(record1.Key);
var loadedRecord2 = await deserializedCollection.GetAsync(record2.Key);
Assert.NotNull(loadedRecord1);
Assert.NotNull(loadedRecord2);
Assert.Equal(record1.Text, loadedRecord1.Text);
Assert.Equal(record2.Text, loadedRecord2.Text);
}
[Fact]
public async Task DeserializeCollectionFromJsonAsyncThrowsOnInvalidJson()
{
using var vectorStore = new InMemoryVectorStore();
using var memStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("{ invalid json }"));
await Assert.ThrowsAsync<JsonException>(async () =>
{
await vectorStore.DeserializeCollectionFromJsonAsync<Guid, TestRecord>(memStream);
});
}
private sealed class TestRecord
{
[VectorStoreKey]
public Guid Key { get; init; }
[VectorStoreData]
public string Text { get; init; } = string.Empty;
[VectorStoreVector(3)]
public ReadOnlyMemory<float> Embedding { get; init; }
}
private sealed class TestRecordAutoEmbed
{
[VectorStoreKey]
public Guid Key { get; init; }
[VectorStoreData]
public string Text { get; init; } = string.Empty;
[VectorStoreVector(3)]
public string Embedding => this.Text;
}
private sealed class FakeEmbeddingGenerator() : IEmbeddingGenerator<string, Embedding<float>>
{
public Task<GeneratedEmbeddings<Embedding<float>>> GenerateAsync(
IEnumerable<string> values,
EmbeddingGenerationOptions? options = null,
CancellationToken cancellationToken = default)
{
var results = new GeneratedEmbeddings<Embedding<float>>();
foreach (var value in values)
{
results.Add(new Embedding<float>(new float[] { 0.1f, 0.2f, 0.3f }));
}
return Task.FromResult(results);
}
public object? GetService(Type serviceType, object? serviceKey = null)
=> null;
public void Dispose()
{
}
}
}
@@ -0,0 +1,83 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;
using Xunit;
namespace SemanticKernel.Connectors.InMemory.UnitTests;
/// <summary>
/// Contains tests for the <see cref="InMemoryVectorStore"/> class.
/// </summary>
public class InMemoryVectorStoreTests
{
private const string TestCollectionName = "testcollection";
[Fact]
public void GetCollectionReturnsCollection()
{
// Arrange.
using var sut = new InMemoryVectorStore();
// Act.
var actual = sut.GetCollection<string, SinglePropsModel<string>>(TestCollectionName);
// Assert.
Assert.NotNull(actual);
Assert.IsType<InMemoryCollection<string, SinglePropsModel<string>>>(actual);
}
[Fact]
public void GetCollectionReturnsCollectionWithNonStringKey()
{
// Arrange.
using var sut = new InMemoryVectorStore();
// Act.
var actual = sut.GetCollection<int, SinglePropsModel<int>>(TestCollectionName);
// Assert.
Assert.NotNull(actual);
Assert.IsType<InMemoryCollection<int, SinglePropsModel<int>>>(actual);
}
[Fact]
public async Task GetCollectionDoesNotAllowADifferentDataTypeThanPreviouslyUsedAsync()
{
// Arrange.
using var sut = new InMemoryVectorStore();
var stringKeyCollection = sut.GetCollection<string, SinglePropsModel<string>>(TestCollectionName);
await stringKeyCollection.EnsureCollectionExistsAsync();
// Act and assert.
var exception = Assert.Throws<InvalidOperationException>(() => sut.GetCollection<string, SecondModel>(TestCollectionName));
Assert.Equal($"Collection '{TestCollectionName}' already exists and with data type 'SinglePropsModel`1' so cannot be re-created with data type 'SecondModel'.", exception.Message);
}
#pragma warning disable CA1812 // Classes are used as generic arguments
private sealed class SinglePropsModel<TKey>
{
[VectorStoreKey]
public required TKey Key { get; set; }
[VectorStoreData]
public string Data { get; set; } = string.Empty;
[VectorStoreVector(4)]
public ReadOnlyMemory<float>? Vector { get; set; }
public string? NotAnnotated { get; set; }
}
private sealed class SecondModel
{
[VectorStoreKey]
public required int Key { get; set; }
[VectorStoreData]
public string Data { get; set; } = string.Empty;
}
#pragma warning restore CA1812
}