Skip to content

.Net: Fix integration test and bugs #12135

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ public sealed class CosmosNoSqlDynamicCollection : CosmosNoSqlCollection<object,
[RequiresUnreferencedCode("The Cosmos NoSQL provider is currently incompatible with trimming.")]
[RequiresDynamicCode("The Cosmos NoSQL provider is currently incompatible with NativeAOT.")]
public CosmosNoSqlDynamicCollection(Database database, string name, CosmosNoSqlCollectionOptions options)
: base(new(database.Client, ownsClient: false), _ => database, name, options)
: this(
new(database.Client, ownsClient: false),
_ => database,
name,
options)
{
}

Expand All @@ -44,8 +48,8 @@ public CosmosNoSqlDynamicCollection(
string collectionName,
CosmosClientOptions? clientOptions = null,
CosmosNoSqlCollectionOptions? options = null)
: base(
new ClientWrapper(new CosmosClient(connectionString, clientOptions), ownsClient: true),
: this(
new(new CosmosClient(connectionString, clientOptions), ownsClient: true),
client => client.GetDatabase(databaseName),
collectionName,
options)
Expand Down
24 changes: 13 additions & 11 deletions dotnet/src/Connectors/Connectors.Memory.SqliteVec/SqliteMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,19 @@ public TRecord MapFromStorageToDataModel(Dictionary<string, object?> storageMode

var memory = SqlitePropertyMapping.MapVectorForDataModel(vectorBytes);

property.SetValueAsObject(record, property.Type switch
{
var t when t == typeof(ReadOnlyMemory<float>) => memory,
var t when t == typeof(Embedding<float>) => new Embedding<float>(memory),
var t when t == typeof(float[])
=> MemoryMarshal.TryGetArray(memory, out ArraySegment<float> segment) && segment.Count == segment.Array!.Length
? segment.Array
: memory.ToArray(),

_ => throw new UnreachableException()
});
property.SetValueAsObject(
record,
(Nullable.GetUnderlyingType(property.Type) ?? property.Type) switch
{
var t when t == typeof(ReadOnlyMemory<float>) => memory,
var t when t == typeof(Embedding<float>) => new Embedding<float>(memory),
var t when t == typeof(float[])
=> MemoryMarshal.TryGetArray(memory, out ArraySegment<float> segment) && segment.Count == segment.Array!.Length
? segment.Array
: memory.ToArray(),

_ => throw new UnreachableException()
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,9 @@ private static string BuildLegacyFilter(
throw new InvalidOperationException($"Property name '{propertyName}' provided as part of the filter clause is not a valid property name.");
}

var operand = $$"""{ path: ["{{property.StorageName}}"], operator: {{filterOperator}}, {{filterValueType}}: {{propertyValue}} }""";
var storageName = property is KeyPropertyModel ? WeaviateConstants.ReservedKeyPropertyName : property.StorageName;

var operand = $$"""{ path: ["{{storageName}}"], operator: {{filterOperator}}, {{filterValueType}}: {{propertyValue}} }""";

operands.Add(operand);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
{
Definition = fixture.VectorStoreRecordDefinition
};
using var sut = new AzureAISearchCollection<object, Dictionary<string, object?>>(fixture.SearchIndexClient, fixture.TestIndexName, options);
using var sut = new AzureAISearchDynamicCollection(fixture.SearchIndexClient, fixture.TestIndexName, options);

// Act
var baseSetGetResult = await sut.GetAsync("BaseSet-1", new RecordRetrievalOptions { IncludeVectors = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
Definition = fixture.HotelVectorStoreRecordDefinition
};

using var sut = new CosmosMongoCollection<object, Dictionary<string, object?>>(fixture.MongoDatabase, fixture.TestCollection, options);
using var sut = new CosmosMongoDynamicCollection(fixture.MongoDatabase, fixture.TestCollection, options);

// Act
await sut.UpsertAsync(new Dictionary<string, object?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ public async Task ItCanUpsertRecordAsync()
// Act
record.HotelName = "Updated name";
record.HotelRating = 10;
await sut.UpsertAsync(record);

getResult = await sut.GetAsync(HotelId);

Expand Down Expand Up @@ -352,7 +353,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
Definition = this.GetTestHotelRecordDefinition()
};

using var sut = new CosmosNoSqlCollection<object, Dictionary<string, object?>>(fixture.Database!, "dynamic-mapper", options);
using var sut = new CosmosNoSqlDynamicCollection(fixture.Database!, "dynamic-mapper", options);

await sut.EnsureCollectionExistsAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace SemanticKernel.IntegrationTests.Connectors.Memory.CosmosNoSql;
/// <summary>
/// Integration tests for <see cref="CosmosNoSqlVectorStore"/>.
/// </summary>
[Collection("CosmosNoSqlVectorStoreCollection")]
[Collection("CosmosNoSqlCollection")]
[CosmosNoSqlConnectionStringSetCondition]
public sealed class CosmosNoSqlVectorStoreTests(CosmosNoSqlVectorStoreFixture fixture)
#pragma warning disable CA2000 // Dispose objects before losing scope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
Definition = fixture.HotelVectorStoreRecordDefinition
};

using var sut = new MongoCollection<object, Dictionary<string, object?>>(fixture.MongoDatabase, fixture.TestCollection, options);
using var sut = new MongoDynamicCollection(fixture.MongoDatabase, fixture.TestCollection, options);

// Act
await sut.UpsertAsync(new Dictionary<string, object?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ public VectorStoreCollection<TKey, TRecord> GetCollection<TKey, TRecord>(
return vectorStore.GetCollection<TKey, TRecord>(collectionName, recordDefinition);
}

public VectorStoreCollection<object, Dictionary<string, object?>> GetDynamicCollection(
string collectionName,
VectorStoreRecordDefinition recordDefinition)
{
var vectorStore = this.VectorStore;
return vectorStore.GetDynamicCollection(collectionName, recordDefinition);
}

/// <summary>
/// Create / Recreate postgres docker container and run it.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,15 @@ public async Task ItCanGetAndDeleteRecordAsync<TKey>(Type idType, TKey? key)
var collectionName = "DeleteRecord";
var sut = this.GetCollection(idType, collectionName);

await sut.CreateCollectionAsync();
await sut.EnsureCollectionExistsAsync();

try
{
var record = this.CreateRecord<TKey>(idType, key!);
var recordKey = record.HotelId;
var upsertResult = await sut.UpsertAsync(record);
await sut.UpsertAsync(record);
var getResult = await sut.GetAsync(recordKey);

Assert.Equal(key, upsertResult);
Assert.NotNull(getResult);

// Act
Expand All @@ -172,7 +171,7 @@ public async Task ItCanGetAndDeleteRecordAsync<TKey>(Type idType, TKey? key)
finally
{
// Cleanup
await sut.DeleteCollectionAsync();
await sut.EnsureCollectionDeletedAsync();
}
}

Expand Down Expand Up @@ -282,7 +281,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
{
const int HotelId = 5;

var sut = fixture.GetCollection<object, Dictionary<string, object?>>("DynamicMapperWithNumericKey", GetVectorStoreRecordDefinition<int>());
var sut = fixture.GetDynamicCollection("DynamicMapperWithNumericKey", GetVectorStoreRecordDefinition<int>());

await sut.EnsureCollectionExistsAsync();

Expand Down Expand Up @@ -448,10 +447,7 @@ public async Task ItCanUpsertAndGetEnumerableTypesAsync()
{
Id = 1,
ListInts = new() { 1, 2, 3 },
CollectionInts = new HashSet<int>() { 4, 5, 6 },
EnumerableInts = [7, 8, 9],
ReadOnlyCollectionInts = new List<int> { 10, 11, 12 },
ReadOnlyListInts = new List<int> { 13, 14, 15 }
ArrayInts = new[] { 4, 5, 6 },
};

// Act
Expand All @@ -467,27 +463,11 @@ public async Task ItCanUpsertAndGetEnumerableTypesAsync()
Assert.Equal(1, getResult.ListInts![0]);
Assert.Equal(2, getResult.ListInts![1]);
Assert.Equal(3, getResult.ListInts![2]);
Assert.NotNull(getResult.CollectionInts);
Assert.Equal(3, getResult.CollectionInts!.Count);
Assert.Contains(4, getResult.CollectionInts);
Assert.Contains(5, getResult.CollectionInts);
Assert.Contains(6, getResult.CollectionInts);
Assert.NotNull(getResult.EnumerableInts);
Assert.Equal(3, getResult.EnumerableInts!.Count());
Assert.Equal(7, getResult.EnumerableInts.ElementAt(0));
Assert.Equal(8, getResult.EnumerableInts.ElementAt(1));
Assert.Equal(9, getResult.EnumerableInts.ElementAt(2));
Assert.NotNull(getResult.ReadOnlyCollectionInts);
Assert.Equal(3, getResult.ReadOnlyCollectionInts!.Count);
var readOnlyCollectionIntsList = getResult.ReadOnlyCollectionInts.ToList();
Assert.Equal(10, readOnlyCollectionIntsList[0]);
Assert.Equal(11, readOnlyCollectionIntsList[1]);
Assert.Equal(12, readOnlyCollectionIntsList[2]);
Assert.NotNull(getResult.ReadOnlyListInts);
Assert.Equal(3, getResult.ReadOnlyListInts!.Count);
Assert.Equal(13, getResult.ReadOnlyListInts[0]);
Assert.Equal(14, getResult.ReadOnlyListInts[1]);
Assert.Equal(15, getResult.ReadOnlyListInts[2]);
Assert.NotNull(getResult.ArrayInts);
Assert.Equal(3, getResult.ArrayInts!.Length);
Assert.Equal(4, getResult.ArrayInts![0]);
Assert.Equal(5, getResult.ArrayInts![1]);
Assert.Equal(6, getResult.ArrayInts![2]);
}

#region private ==================================================================================
Expand Down Expand Up @@ -549,16 +529,7 @@ private sealed class RecordWithEnumerables
public List<int>? ListInts { get; set; }

[VectorStoreData]
public ICollection<int>? CollectionInts { get; set; }

[VectorStoreData]
public IEnumerable<int>? EnumerableInts { get; set; }

[VectorStoreData]
public IReadOnlyCollection<int>? ReadOnlyCollectionInts { get; set; }

[VectorStoreData]
public IReadOnlyList<int>? ReadOnlyListInts { get; set; }
public int[]? ArrayInts { get; set; }
}
#pragma warning restore CA1812, CA1859

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
{
Definition = fixture.HotelVectorStoreRecordDefinition
};
using var sut = new QdrantCollection<object, Dictionary<string, object?>>(fixture.QdrantClient, "singleVectorHotels", ownsClient: false, options);
using var sut = new QdrantDynamicCollection(fixture.QdrantClient, "singleVectorHotels", ownsClient: false, options);

// Act
var baseSetGetResult = await sut.GetAsync(11ul, new RecordRetrievalOptions { IncludeVectors = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
PrefixCollectionNameToKeyNames = true,
Definition = fixture.BasicVectorStoreRecordDefinition
};
using var sut = new RedisHashSetCollection<object, Dictionary<string, object?>>(fixture.Database, TestCollectionName, options);
using var sut = new RedisHashSetDynamicCollection(fixture.Database, TestCollectionName, options);

// Act
var baseSetGetResult = await sut.GetAsync("HBaseSet-1", new RecordRetrievalOptions { IncludeVectors = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace SemanticKernel.IntegrationTests.Connectors.Memory.Redis;
public sealed class RedisJsonVectorStoreRecordCollectionTests(ITestOutputHelper output, RedisVectorStoreFixture fixture)
{
// If null, all tests will be enabled
private const string SkipReason = null;
private const string SkipReason = "Redis tests fail intermittently on build server";

private const string TestCollectionName = "jsonhotels";

Expand Down Expand Up @@ -67,7 +67,7 @@ public async Task ItCanCreateACollectionUpsertGetAndSearchAsync(bool useRecordDe
var searchResults = await sut.SearchAsync(
new ReadOnlyMemory<float>(new[] { 30f, 31f, 32f, 33f }),
top: 3,
new() { OldFilter = new VectorSearchFilter().EqualTo("HotelCode", 10) }).ToListAsync();
new() { OldFilter = new VectorSearchFilter().EqualTo("HotelCode", 10), IncludeVectors = true }).ToListAsync();

// Assert
var collectionExistResult = await sut.CollectionExistsAsync();
Expand Down Expand Up @@ -434,7 +434,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperAsync()
PrefixCollectionNameToKeyNames = true,
Definition = fixture.VectorStoreRecordDefinition
};
using var sut = new RedisJsonCollection<object, Dictionary<string, object?>>(fixture.Database, TestCollectionName, options);
using var sut = new RedisJsonDynamicCollection(fixture.Database, TestCollectionName, options);

// Act
var baseSetGetResult = await sut.GetAsync("BaseSet-1", new RecordRetrievalOptions { IncludeVectors = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ public SqliteCollection<TKey, TRecord> GetCollection<TKey, TRecord>(
SqliteCollectionOptions? options = default)
where TKey : notnull
where TRecord : class
{
return new SqliteCollection<TKey, TRecord>(
=> new(
this.ConnectionString,
collectionName,
options);

public SqliteDynamicCollection GetDynamicCollection(
string collectionName,
SqliteCollectionOptions options)
=> new(
this.ConnectionString,
collectionName,
options);
}

public void Dispose()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace SemanticKernel.IntegrationTests.Connectors.Memory.SqliteVec;
[Collection("SqliteVectorStoreCollection")]
public sealed class SqliteVectorStoreRecordCollectionTests(SqliteVectorStoreFixture fixture)
{
private const string? SkipReason = "SQLite vector search extension is required";
private const string? SkipReason = null;

[Theory(Skip = SkipReason)]
[InlineData(true)]
Expand All @@ -41,6 +41,9 @@ public async Task CollectionExistsReturnsCollectionStateAsync(bool createCollect

// Assert
Assert.Equal(createCollection, collectionExists);

// Cleanup
await sut.EnsureCollectionDeletedAsync();
}

[Fact(Skip = SkipReason)]
Expand Down Expand Up @@ -439,7 +442,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperWithNumericKeyAsync
Definition = GetVectorStoreRecordDefinition<long>()
};

using var sut = fixture.GetCollection<object, Dictionary<string, object?>>("DynamicMapperWithNumericKey", options);
using var sut = fixture.GetDynamicCollection("DynamicMapperWithNumericKey", options);

await sut.EnsureCollectionExistsAsync();

Expand Down Expand Up @@ -479,7 +482,7 @@ public async Task ItCanUpsertAndRetrieveUsingTheDynamicMapperWithStringKeyAsync(
Definition = GetVectorStoreRecordDefinition<string>()
};

using var sut = fixture.GetCollection<object, Dictionary<string, object?>>("DynamicMapperWithStringKey", options)
using var sut = fixture.GetDynamicCollection("DynamicMapperWithStringKey", options)
as VectorStoreCollection<object, Dictionary<string, object?>>;

await sut.EnsureCollectionExistsAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ public async Task ItCanUpsertAndRetrieveUsingDynamicMappingAsync()
Definition = this.GetTestHotelRecordDefinition()
};

using var sut = new WeaviateCollection<object, Dictionary<string, object?>>(fixture.HttpClient!, "TestDynamicMapper", options);
using var sut = new WeaviateDynamicCollection(fixture.HttpClient!, "TestDynamicMapper", options);

await sut.EnsureCollectionExistsAsync();

Expand Down
Loading
Loading