diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericCollectionWrapper.cs b/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericCollectionWrapper.cs index ec5b3c41bb..edfa22205b 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericCollectionWrapper.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericCollectionWrapper.cs @@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.SystemWebAdapters.Internal { internal class NonGenericCollectionWrapper : ICollection { + private object? _syncRoot; private readonly ICollection _collection; public NonGenericCollectionWrapper(ICollection collection) @@ -18,9 +19,9 @@ public NonGenericCollectionWrapper(ICollection collection) public int Count => _collection.Count; - public bool IsSynchronized => false; + public bool IsSynchronized => (_collection as ICollection)?.IsSynchronized ?? false; - public object SyncRoot => null!; + public object SyncRoot => _syncRoot ??= (_collection as ICollection)?.SyncRoot ?? new object(); public void CopyTo(Array array, int index) { diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericDictionaryWrapper.cs b/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericDictionaryWrapper.cs index 79d8fbd81c..2ddeca5f56 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericDictionaryWrapper.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters/Internal/NonGenericDictionaryWrapper.cs @@ -11,6 +11,7 @@ internal class NonGenericDictionaryWrapper : IDictionary { private readonly IDictionary _original; + private object? _syncRoot; private ICollection? _keys; private ICollection? _values; @@ -57,9 +58,9 @@ public ICollection Values public int Count => _original.Count; - public bool IsSynchronized => false; + public bool IsSynchronized => (_original as ICollection)?.IsSynchronized ?? false; - public object SyncRoot => null!; + public object SyncRoot => _syncRoot ??= (_original as ICollection)?.SyncRoot ?? new object(); public void Add(object key, object? value) => _original.Add(key, value); diff --git a/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericCollectionWrapperTests.cs b/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericCollectionWrapperTests.cs index af06103292..bad6bd4a6d 100644 --- a/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericCollectionWrapperTests.cs +++ b/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericCollectionWrapperTests.cs @@ -1,7 +1,10 @@ using System; +using System.Collections; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using AutoFixture; +using Moq; using Xunit; namespace Microsoft.AspNetCore.SystemWebAdapters.Internal @@ -34,13 +37,74 @@ public void Empty() Assert.Empty(wrapped); } + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void IsSynchronized(bool? isSynchronized) + { + // Arrange + var original = new Mock>(); + + if (isSynchronized.HasValue) + { + var collection = original.As(); + collection.Setup(c => c.IsSynchronized).Returns(isSynchronized.Value); + } + + var wrapped = new NonGenericCollectionWrapper(original.Object); + + // Act + var result = wrapped.IsSynchronized; + + // Assert + Assert.Equal(isSynchronized ?? false, result); + } + + [Fact] + public void NoSyncRoot() + { + // Arrange + var original = new Mock>(); + var wrapped = new NonGenericCollectionWrapper(original.Object); + + // Act + var result1 = wrapped.SyncRoot; + var result2 = wrapped.SyncRoot; + + // Assert + Assert.Same(result1, result2); + } + + [Fact] + public void HasSyncRoot() + { + // Arrange + var original = new Mock>(); + var syncRoot = new object(); + + var collection = original.As(); + collection.Setup(c => c.SyncRoot).Returns(syncRoot); + + var wrapped = new NonGenericCollectionWrapper(original.Object); + + // Act + var result1 = wrapped.SyncRoot; + var result2 = wrapped.SyncRoot; + + // Assert + Assert.Same(syncRoot, result1); + Assert.Same(syncRoot, result2); + } + [Fact] public void SyncProperties() { - var wrapped = new NonGenericCollectionWrapper(Array.Empty()); + var list = new List(); + var wrapped = new NonGenericCollectionWrapper(list); Assert.False(wrapped.IsSynchronized); - Assert.Null(wrapped.SyncRoot); + Assert.Equal(((ICollection)list).SyncRoot, wrapped.SyncRoot); } [Fact] diff --git a/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericDictionaryWrapperTests.cs b/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericDictionaryWrapperTests.cs index d44c4f0dbc..78f4f78031 100644 --- a/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericDictionaryWrapperTests.cs +++ b/test/Microsoft.AspNetCore.SystemWebAdapters.Tests/Internal/NonGenericDictionaryWrapperTests.cs @@ -18,6 +18,7 @@ public NonGenericDictionaryWrapperTests() _fixture = new Fixture(); } + [Fact] public void IsFixedSize() { @@ -27,22 +28,64 @@ public void IsFixedSize() Assert.False(wrapped.IsFixedSize); } + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void IsSynchronized(bool? isSynchronized) + { + // Arrange + var dictionary = new Mock>(); + + if (isSynchronized.HasValue) + { + var collection = dictionary.As(); + collection.Setup(c => c.IsSynchronized).Returns(isSynchronized.Value); + } + + var wrapped = new NonGenericDictionaryWrapper(dictionary.Object); + + // Act + var result = wrapped.IsSynchronized; + + // Assert + Assert.Equal(isSynchronized ?? false, result); + } + [Fact] - public void IsSynchronized() + public void NoSyncRoot() { - var dictionary = new Dictionary(); - var wrapped = new NonGenericDictionaryWrapper(dictionary); + // Arrange + var dictionary = new Mock>(); + var wrapped = new NonGenericDictionaryWrapper(dictionary.Object); + + // Act + var result1 = wrapped.SyncRoot; + var result2 = wrapped.SyncRoot; - Assert.False(wrapped.IsSynchronized); + // Assert + Assert.Same(result1, result2); } [Fact] - public void SyncRoot() + public void HasSyncRoot() { - var dictionary = new Dictionary(); - var wrapped = new NonGenericDictionaryWrapper(dictionary); + // Arrange + var dictionary = new Mock>(); + var syncRoot = new object(); + + var collection = dictionary.As(); + collection.Setup(c => c.SyncRoot).Returns(syncRoot); + + var wrapped = new NonGenericDictionaryWrapper(dictionary.Object); + + // Act + var result1 = wrapped.SyncRoot; + var result2 = wrapped.SyncRoot; - Assert.Null(wrapped.SyncRoot); + // Assert + Assert.Same(syncRoot, result1); + Assert.Same(syncRoot, result2); } [Theory]