File: WindowsSingleInstanceTests.cs
Web Access
Project: src\tests\Aspire.Tray.Tests\Aspire.Tray.Tests.csproj (Aspire.Tray.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.Runtime.Versioning;
using System.Security.Principal;
 
namespace Aspire.Tray.Tests;
 
public class WindowsSingleInstanceTests
{
    public static bool SupportsWindows => OperatingSystem.IsWindows();
 
    [Fact(Skip = "The state directory and SID are Windows-specific.", SkipUnless = nameof(SupportsWindows))]
    [SupportedOSPlatform("windows")]
    public void StateAndActivationArePerUserAndVersionIndependent()
    {
        using var identity = WindowsIdentity.GetCurrent();
        Assert.Equal(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Aspire", "Tray"),
            WindowsSingleInstance.DirectoryPath);
        Assert.Equal($"Aspire.Tray.User.{identity.User!.Value}.control-v1", WindowsSingleInstance.ActivationPipeName);
    }
 
    [Fact(Skip = "The mutex uses Windows current-user ACLs.", SkipUnless = nameof(SupportsWindows))]
    [SupportedOSPlatform("windows")]
    public void MutexOwnershipIsExclusiveUntilReleasedOnItsOwningThread()
    {
        var name = $"Aspire.Tray.Tests.{Guid.NewGuid():N}";
        using (var owner = WindowsSingleInstance.TryAcquire(name))
        {
            Assert.NotNull(owner);
            Exception? failure = null;
            var contender = new Thread(() =>
            {
                try
                {
                    using var competing = WindowsSingleInstance.TryAcquire(name);
                    Assert.Null(competing);
                }
                catch (Exception ex)
                {
                    failure = ex;
                }
            });
            contender.Start();
            Assert.True(contender.Join(TimeSpan.FromSeconds(10)));
            Assert.Null(failure);
        }
 
        using var nextOwner = WindowsSingleInstance.TryAcquire(name);
        Assert.NotNull(nextOwner);
    }
}