/
githubmirror
/
aspnetcore
Обзор
Документация
Войти
/
githubmirror
/
aspnetcore
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Shared/test/Shared.Tests/Buffers/RefPooledArrayBufferWriterTests.cs
310 строк
8 KB
Korolev Dmitry
feat: "Spanify" DataProtector with IBufferWriter<byte> (#64262)
05 дек 2025, 22:26
Не верифицирован
05 дек 2025, 22:26
249b29c
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; using System.Diagnostics; namespace Microsoft.AspNetCore.Shared.Tests.Buffers; public class RefPooledArrayBufferWriterTests { [Theory] [InlineData(16)] [InlineData(256)] [InlineData(1024)] public void Constructor_WithInitialBuffer_InitializesCorrectly(int initialCapacity) { Span<byte> initialBuffer = stackalloc byte[initialCapacity]; var writer = new RefPooledArrayBufferWriter<byte>(initialBuffer); var span = writer.GetSpan(); Assert.True(span.Length >= initialCapacity); writer.Dispose(); } [Theory] [InlineData(-1)] [InlineData(-100)] public void Advance_WithNegativeCount_Throws(int negativeCount) { Span<byte> buffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); // ref struct cannot be captured in lambda, so using try-catch try { writer.Advance(negativeCount); Assert.Fail("Expected ArgumentOutOfRangeException"); } catch (ArgumentOutOfRangeException) { // Expected } finally { writer.Dispose(); } } [Fact] public void Advance_BeyondCapacity_Throws() { Span<byte> buffer = stackalloc byte[10]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); // ref struct cannot be captured in lambda, use try-catch try { writer.Advance(20); Assert.Fail("Expected InvalidOperationException"); } catch (InvalidOperationException) { // Expected } finally { writer.Dispose(); } } [Fact] public void GetSpan_WithInvalidSizeHint_Throws() { Span<byte> buffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); // ref struct cannot be captured in lambda, use try-catch try { writer.GetSpan(-1); Assert.Fail("Expected ArgumentOutOfRangeException"); } catch (ArgumentOutOfRangeException) { // Expected } finally { writer.Dispose(); } } [Fact] public void GetMemory_ThrowsNotSupported() { Span<byte> buffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); // ref struct cannot be captured in lambda, use try-catch try { writer.GetMemory(); Assert.Fail("Expected NotSupportedException or UnreachableException"); } #if NET catch (UnreachableException) { // Expected (for .NET Core) } #else catch (NotSupportedException) { // Expected (for .NET Framework and older versions) } #endif finally { writer.Dispose(); } } [Theory] [InlineData(0)] [InlineData(10)] [InlineData(100)] [InlineData(1000)] public void GetSpan_WithSizeHint_ResizesBufferIfNeeded(int sizeHint) { Span<byte> buffer = stackalloc byte[10]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); var span = writer.GetSpan(sizeHint); Assert.True(span.Length >= sizeHint && span.Length > 0); writer.Dispose(); } [Fact] public void WrittenSpan_ReturnsSpanOfWrittenData() { Span<byte> buffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); var span = writer.GetSpan(); span[0] = 42; span[1] = 99; writer.Advance(2); var writtenSpan = writer.WrittenSpan; Assert.Equal(2, writtenSpan.Length); Assert.Equal(42, writtenSpan[0]); Assert.Equal(99, writtenSpan[1]); writer.Dispose(); } [Fact] public void BufferPreservesContentOnGrowth_FromStackToPooledBuffer() { var initialCapacity = 10; Span<byte> initialBuffer = stackalloc byte[initialCapacity]; var writer = new RefPooledArrayBufferWriter<byte>(initialBuffer); var span = writer.GetSpan(); span[0] = 42; span[1] = 99; writer.Advance(2); var contentBefore = writer.WrittenSpan.ToArray(); // Force buffer growth from stack to pooled array span = writer.GetSpan(100); var contentAfter = writer.WrittenSpan.ToArray(); Assert.Equal(contentBefore, contentAfter); // Verify we can write at least 92 more bytes (100 - 8 bytes remaining) for (var i = 0; i < 92; i++) { span[i] = (byte)(i % 256); } writer.Advance(92); Assert.Equal(94, writer.WrittenSpan.Length); writer.Dispose(); } [Fact] public void Buffer_AdvancesOnBoundaryLimits() { Span<byte> initialBuffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(initialBuffer); _ = writer.GetSpan(); writer.Advance(256); // should not throw Assert.Equal(256, writer.WrittenSpan.Length); } [Fact] public void BufferPreservesContentOnGrowth_PooledToLargerPooledBuffer() { Span<byte> initialBuffer = stackalloc byte[16]; var writer = new RefPooledArrayBufferWriter<byte>(initialBuffer); // Force initial growth to pooled buffer var span = writer.GetSpan(100); for (var i = 0; i < 50; i++) { span[i] = (byte)(i % 256); } writer.Advance(50); var contentBefore = writer.WrittenSpan.ToArray(); // Force second growth from pooled to larger pooled span = writer.GetSpan(500); var contentAfter = writer.WrittenSpan.ToArray(); Assert.Equal(contentBefore, contentAfter); // Verify content integrity for (var i = 0; i < 50; i++) { Assert.Equal((byte)(i % 256), contentAfter[i]); } writer.Dispose(); } [Fact] public void MultipleWrites_WorkCorrectly() { Span<byte> buffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); // First write var span = writer.GetSpan(); span[0] = 1; span[1] = 2; writer.Advance(2); // Second write span = writer.GetSpan(); span[0] = 3; span[1] = 4; writer.Advance(2); // Third write span = writer.GetSpan(); span[0] = 5; writer.Advance(1); var written = writer.WrittenSpan; Assert.Equal(5, written.Length); Assert.Equal(new byte[] { 1, 2, 3, 4, 5 }, written.ToArray()); writer.Dispose(); } [Fact] public void GetSpan_ReturnsConsistentReference_BeforeAdvance() { Span<byte> buffer = stackalloc byte[256]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); var span1 = writer.GetSpan(); span1[0] = 42; var span2 = writer.GetSpan(); Assert.Equal(42, span2[0]); // Should see the same buffer writer.Advance(1); Assert.Equal(42, writer.WrittenSpan[0]); writer.Dispose(); } [Theory] [InlineData(1)] [InlineData(10)] [InlineData(100)] public void LargeWrite_AcrossGrowthBoundary_PreservesData(int iterations) { Span<byte> buffer = stackalloc byte[8]; var writer = new RefPooledArrayBufferWriter<byte>(buffer); for (int i = 0; i < iterations; i++) { var span = writer.GetSpan(10); for (int j = 0; j < 10; j++) { span[j] = (byte)((i * 10 + j) % 256); } writer.Advance(10); } var written = writer.WrittenSpan; Assert.Equal(iterations * 10, written.Length); // Verify all data for (int i = 0; i < iterations * 10; i++) { Assert.Equal((byte)(i % 256), written[i]); } writer.Dispose(); } }