File: WeakReferenceHelpersTests.cs
Web Access
Project: src\src\DataProtection\Cryptography.Internal\test\Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj (Microsoft.AspNetCore.Cryptography.Internal.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 Xunit;
 
namespace Microsoft.AspNetCore.Cryptography;
 
public class WeakReferenceHelpersTests
{
    [Fact]
    public void GetSharedInstance_ExistingWeakRefHasBeenGCed_CreatesNew()
    {
        // Arrange
        WeakReference<MyDisposable> wrOriginal = new WeakReference<MyDisposable>(null);
        WeakReference<MyDisposable> wr = wrOriginal;
        MyDisposable newInstance = new MyDisposable();
 
        // Act
        var retVal = WeakReferenceHelpers.GetSharedInstance(ref wr, () => newInstance);
 
        // Assert
        Assert.NotNull(wr);
        Assert.NotSame(wrOriginal, wr);
        Assert.True(wr.TryGetTarget(out var target));
        Assert.Same(newInstance, target);
        Assert.Same(newInstance, retVal);
        Assert.False(newInstance.HasBeenDisposed);
    }
 
    [Fact]
    public void GetSharedInstance_ExistingWeakRefIsNull_CreatesNew()
    {
        // Arrange
        WeakReference<MyDisposable> wr = null;
        MyDisposable newInstance = new MyDisposable();
 
        // Act
        var retVal = WeakReferenceHelpers.GetSharedInstance(ref wr, () => newInstance);
 
        // Assert
        Assert.NotNull(wr);
        Assert.True(wr.TryGetTarget(out var target));
        Assert.Same(newInstance, target);
        Assert.Same(newInstance, retVal);
        Assert.False(newInstance.HasBeenDisposed);
    }
 
    [Fact]
    public void GetSharedInstance_ExistingWeakRefIsNull_AnotherThreadCreatesInstanceWhileOurFactoryRuns_ReturnsExistingInstanceAndDisposesNewInstance()
    {
        // Arrange
        WeakReference<MyDisposable> wr = null;
        MyDisposable instanceThatWillBeCreatedFirst = new MyDisposable();
        MyDisposable instanceThatWillBeCreatedSecond = new MyDisposable();
 
        // Act
        var retVal = WeakReferenceHelpers.GetSharedInstance(ref wr, () =>
        {
            // mimic another thread creating the instance while our factory is being invoked
            WeakReferenceHelpers.GetSharedInstance(ref wr, () => instanceThatWillBeCreatedFirst);
            return instanceThatWillBeCreatedSecond;
        });
 
        // Assert
        Assert.NotNull(wr);
        Assert.True(wr.TryGetTarget(out var target));
        Assert.Same(instanceThatWillBeCreatedFirst, target);
        Assert.Same(instanceThatWillBeCreatedFirst, retVal);
        Assert.False(instanceThatWillBeCreatedFirst.HasBeenDisposed);
        Assert.True(instanceThatWillBeCreatedSecond.HasBeenDisposed);
    }
 
    private sealed class MyDisposable : IDisposable
    {
        public bool HasBeenDisposed { get; private set; }
 
        public void Dispose()
        {
            HasBeenDisposed = true;
        }
    }
}