File: TagSetTests.cs
Web Access
Project: src\test\Libraries\Microsoft.Extensions.Caching.Hybrid.Tests\Microsoft.Extensions.Caching.Hybrid.Tests.csproj (Microsoft.Extensions.Caching.Hybrid.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.Extensions.Caching.Hybrid.Internal;
 
namespace Microsoft.Extensions.Caching.Hybrid.Tests;
public class TagSetTests
{
    [Fact]
    public void DefaultEmpty()
    {
        var tags = TagSet.Empty;
        Assert.Equal(0, tags.Count);
        Assert.True(tags.IsEmpty);
        Assert.False(tags.IsArray);
        Assert.Equal("(no tags)", tags.ToString());
        tags.CopyTo(default);
    }
 
    [Fact]
    public void EmptyArray()
    {
        var tags = TagSet.Create([]);
        Assert.Equal(0, tags.Count);
        Assert.True(tags.IsEmpty);
        Assert.False(tags.IsArray);
        Assert.Equal("(no tags)", tags.ToString());
        tags.CopyTo(default);
    }
 
    [Fact]
    public void EmptyCustom()
    {
        var tags = TagSet.Create(Custom());
        Assert.Equal(0, tags.Count);
        Assert.True(tags.IsEmpty);
        Assert.False(tags.IsArray);
        Assert.Equal("(no tags)", tags.ToString());
        tags.CopyTo(default);
 
        static IEnumerable<string> Custom()
        {
            yield break;
        }
    }
 
    [Fact]
    public void SingleFromArray()
    {
        string[] arr = ["abc"];
        var tags = TagSet.Create(arr);
        arr.AsSpan().Clear(); // to check defensive copy
        Assert.Equal(1, tags.Count);
        Assert.False(tags.IsEmpty);
        Assert.False(tags.IsArray);
        Assert.Equal("abc", tags.ToString());
        var scratch = tags.ToArray();
        Assert.Equal("abc", scratch[0]);
    }
 
    [Fact]
    public void SingleFromCustom()
    {
        var tags = TagSet.Create(Custom());
        Assert.Equal(1, tags.Count);
        Assert.False(tags.IsEmpty);
        Assert.False(tags.IsArray);
        Assert.Equal("abc", tags.ToString());
        var scratch = tags.ToArray();
        Assert.Equal("abc", scratch[0]);
 
        static IEnumerable<string> Custom()
        {
            yield return "abc";
        }
    }
 
    [Fact]
    public void MultipleFromArray()
    {
        string[] arr = ["abc", "def", "ghi"];
        var tags = TagSet.Create(arr);
        arr.AsSpan().Clear(); // to check defensive copy
        Assert.Equal(3, tags.Count);
        Assert.False(tags.IsEmpty);
        Assert.True(tags.IsArray);
        Assert.Equal("abc, def, ghi", tags.ToString());
        var scratch = tags.ToArray();
        Assert.Equal("abc", scratch[0]);
        Assert.Equal("def", scratch[1]);
        Assert.Equal("ghi", scratch[2]);
    }
 
    [Fact]
    public void MultipleFromCustom()
    {
        var tags = TagSet.Create(Custom());
        Assert.Equal(3, tags.Count);
        Assert.False(tags.IsEmpty);
        Assert.True(tags.IsArray);
        Assert.Equal("abc, def, ghi", tags.ToString());
        var scratch = tags.ToArray();
        Assert.Equal("abc", scratch[0]);
        Assert.Equal("def", scratch[1]);
        Assert.Equal("ghi", scratch[2]);
 
        static IEnumerable<string> Custom()
        {
            yield return "abc";
            yield return "def";
            yield return "ghi";
        }
    }
 
    [Fact]
    public void ManyFromArray()
    {
        string[] arr = LongCustom().ToArray();
        var tags = TagSet.Create(arr);
        arr.AsSpan().Clear(); // to check defensive copy
        Assert.Equal(128, tags.Count);
        Assert.False(tags.IsEmpty);
        Assert.True(tags.IsArray);
        var scratch = tags.ToArray();
        Assert.Equal(128, scratch.Length);
    }
 
    [Fact]
    public void ManyFromCustom()
    {
        var tags = TagSet.Create(LongCustom());
        Assert.Equal(128, tags.Count);
        Assert.False(tags.IsEmpty);
        Assert.True(tags.IsArray);
        var scratch = tags.ToArray();
        Assert.Equal(128, scratch.Length);
    }
 
    [Fact]
    public void InvalidEmpty()
    {
        var ex = Assert.Throws<ArgumentException>(() => TagSet.Create(["abc", "", "ghi"]));
        Assert.Equal("tags", ex.ParamName);
        Assert.StartsWith("Tags cannot be empty.", ex.Message);
    }
 
    [Fact]
    public void InvalidReserved()
    {
        var ex = Assert.Throws<ArgumentException>(() => TagSet.Create(["abc", "*", "ghi"]));
        Assert.Equal("tags", ex.ParamName);
        Assert.StartsWith("The tag '*' is reserved and cannot be used in this context.", ex.Message);
    }
 
    private static IEnumerable<string> LongCustom()
    {
        var rand = new Random();
        for (int i = 0; i < 128; i++)
        {
            yield return Create();
        }
 
        string Create()
        {
            const string Alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
            var len = rand.Next(3, 8);
#if NET462
            char[] chars = new char[len];
#else
            Span<char> chars = stackalloc char[len];
#endif
            for (int i = 0; i < chars.Length; i++)
            {
                chars[i] = Alphabet[rand.Next(0, Alphabet.Length)];
            }
 
            return new string(chars);
        }
    }
}