File: Embeddings\BinaryEmbeddingTests.cs
Web Access
Project: src\test\Libraries\Microsoft.Extensions.AI.Abstractions.Tests\Microsoft.Extensions.AI.Abstractions.Tests.csproj (Microsoft.Extensions.AI.Abstractions.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections;
using System.Linq;
using System.Text.Json;
using Xunit;
 
namespace Microsoft.Extensions.AI;
 
public class BinaryEmbeddingTests
{
    [Fact]
    public void Ctor_Roundtrips()
    {
        BitArray vector = new BitArray(new bool[] { false, true, false, true });
 
        BinaryEmbedding e = new(vector);
        Assert.Same(vector, e.Vector);
        Assert.Null(e.ModelId);
        Assert.Null(e.CreatedAt);
        Assert.Null(e.AdditionalProperties);
    }
 
    [Fact]
    public void Properties_Roundtrips()
    {
        BitArray vector = new BitArray(new bool[] { false, true, false, true });
 
        BinaryEmbedding e = new(vector);
 
        Assert.Same(vector, e.Vector);
        BitArray newVector = new BitArray(new bool[] { true, false, true, false });
        e.Vector = newVector;
        Assert.Same(newVector, e.Vector);
 
        Assert.Null(e.ModelId);
        e.ModelId = "text-embedding-3-small";
        Assert.Equal("text-embedding-3-small", e.ModelId);
 
        Assert.Null(e.CreatedAt);
        DateTimeOffset createdAt = DateTimeOffset.Parse("2022-01-01T00:00:00Z");
        e.CreatedAt = createdAt;
        Assert.Equal(createdAt, e.CreatedAt);
 
        Assert.Null(e.AdditionalProperties);
        AdditionalPropertiesDictionary props = new();
        e.AdditionalProperties = props;
        Assert.Same(props, e.AdditionalProperties);
    }
 
    [Fact]
    public void Serialization_Roundtrips()
    {
        foreach (int length in Enumerable.Range(0, 64).Concat(new[] { 10_000 }))
        {
            bool[] bools = new bool[length];
            Random r = new(42);
            for (int i = 0; i < length; i++)
            {
                bools[i] = r.Next(2) != 0;
            }
 
            BitArray vector = new BitArray(bools);
            BinaryEmbedding e = new(vector);
 
            string json = JsonSerializer.Serialize(e, TestJsonSerializerContext.Default.Embedding);
            Assert.Equal($$"""{"$type":"binary","vector":"{{string.Concat(vector.Cast<bool>().Select(b => b ? '1' : '0'))}}"}""", json);
 
            BinaryEmbedding result = Assert.IsType<BinaryEmbedding>(JsonSerializer.Deserialize(json, TestJsonSerializerContext.Default.Embedding));
            Assert.Equal(e.Vector, result.Vector);
        }
    }
 
    [Fact]
    public void Derialization_SupportsEncodedBits()
    {
        BinaryEmbedding result = Assert.IsType<BinaryEmbedding>(JsonSerializer.Deserialize(
            """{"$type":"binary","vector":"\u0030\u0031\u0030\u0031\u0030\u0031"}"""{"$type":"binary","vector":"\u0030\u0031\u0030\u0031\u0030\u0031"}""",
            TestJsonSerializerContext.Default.Embedding));
 
        Assert.Equal(new BitArray(new[] { false, true, false, true, false, true }), result.Vector);
    }
 
    [Theory]
    [InlineData("""{"$type":"binary","vector":"\u0030\u0032"}"""{"$type":"binary","vector":"\u0030\u0032"}""")]
    [InlineData("""{"$type":"binary","vector":"02"}"""{"$type":"binary","vector":"02"}""")]
    [InlineData("""{"$type":"binary","vector":" "}"""{"$type":"binary","vector":" "}""")]
    [InlineData("""{"$type":"binary","vector":10101}"""{"$type":"binary","vector":10101}""")]
    public void Derialization_InvalidBinaryEmbedding_Throws(string json)
    {
        Assert.Throws<JsonException>(() => JsonSerializer.Deserialize(json, TestJsonSerializerContext.Default.Embedding));
    }
}