Imported Upstream version 5.16.0.100

Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-08-07 15:19:03 +00:00
parent 0a9828183b
commit 7d7f676260
4419 changed files with 170950 additions and 90273 deletions

View File

@@ -2,8 +2,11 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<HarvestIncludePath Include="ref\netstandard1.1;ref\netstandard2.0">
<SupportedFramework>netcore45;netcoreapp1.0;wpa81;$(AllXamarinFrameworks)</SupportedFramework>
</HarvestIncludePath>
<ProjectReference Include="..\ref\System.Buffers.csproj">
<SupportedFramework>net45;netcore45;netcoreapp1.0;wpa81;$(AllXamarinFrameworks)</SupportedFramework>
<SupportedFramework>net45</SupportedFramework>
</ProjectReference>
<ProjectReference Include="..\src\System.Buffers.csproj" />
@@ -11,14 +14,8 @@
therefore it cannot reference NETStandard.Library -->
<SuppressMetaPackage Include="NETStandard.Library" />
<!-- Since UAP and .NETCoreApp are package based we still want to enable
OOBing libraries that happen to overlap with their framework package.
This avoids us having to lock the API in our NuGet packages just
to match what shipped inbox: since we can provide a new library
we can update it to add API without raising the netstandard version. -->
<ValidatePackageSuppression Include="TreatAsOutOfBox">
<Value>.NETCoreApp;UAP</Value>
</ValidatePackageSuppression>
<InboxOnTargetFramework Include="netcoreapp2.0" />
<InboxOnTargetFramework Include="uap10.0.16299" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -1,9 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
<PackageConfigurations>
netstandard;
netstandard1.1;
net45;
</PackageConfigurations>
<BuildConfigurations>
$(PackageConfigurations);
uap;
netfx;
</BuildConfigurations>
</PropertyGroup>
</Project>
</Project>

View File

@@ -3,16 +3,31 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{11AE73F7-3532-47B9-8FF6-B4F22D76456C}</ProjectGuid>
<!-- Must match version supported by frameworks which support 4.0.* inbox.
Can be removed when API is added and this assembly is versioned to 4.1.* -->
<AssemblyVersion Condition="'$(TargetsNetFx)' != 'true'">4.0.2.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net45-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net45-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.1-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.1-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System.Buffers.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.1'">
<ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.1' Or '$(TargetGroup)' == 'uap10.0.16299'">
<Reference Include="System.Runtime" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'uap'">
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsNetFx)' == 'true'">
<Reference Include="mscorlib" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -4,15 +4,13 @@
<PackageConfigurations>
netstandard1.1;
netstandard;
netcoreapp2.0-Windows_NT;
netcoreapp2.0-Unix;
uap-Windows_NT;
uapaot-Windows_NT;
</PackageConfigurations>
<BuildConfigurations>
$(PackageConfigurations);
netcoreapp-Windows_NT;
netcoreapp-Unix;
uap-Windows_NT;
uapaot-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@@ -5,17 +5,13 @@
<ProjectGuid>{2ADDB484-6F57-4D71-A3FE-A57EC6329A2B}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>$(OutputPath)$(MSBuildProjectName).xml</DocumentationFile>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' != 'netstandard' and '$(TargetGroup)' != 'netstandard1.1'">true</IsPartialFacadeAssembly>
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' != 'netstandard' and '$(TargetGroup)' != 'netstandard1.1' and '$(TargetGroup)' != 'uap10.0.16299'">true</IsPartialFacadeAssembly>
<ExcludeResourcesImport Condition="'$(IsPartialFacadeAssembly)'=='true'">true</ExcludeResourcesImport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp2.0-Unix-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp2.0-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp2.0-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp2.0-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard1.1-Debug|AnyCPU'" />
@@ -42,4 +38,4 @@
<Reference Include="System.Threading" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>

View File

@@ -34,14 +34,26 @@ namespace System.Buffers
internal unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId)
{
EventData* payload = stackalloc EventData[4];
payload[0].Size = sizeof(int);
payload[0].DataPointer = ((IntPtr)(&bufferId));
payload[1].Size = sizeof(int);
payload[1].DataPointer = ((IntPtr)(&bufferSize));
payload[2].Size = sizeof(int);
payload[2].DataPointer = ((IntPtr)(&poolId));
payload[3].Size = sizeof(int);
payload[3].DataPointer = ((IntPtr)(&bucketId));
payload[0] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&bufferId))
};
payload[1] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&bufferSize))
};
payload[2] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&poolId))
};
payload[3] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&bucketId))
};
WriteEventCore(1, 4, payload);
}
@@ -54,16 +66,31 @@ namespace System.Buffers
internal unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason)
{
EventData* payload = stackalloc EventData[5];
payload[0].Size = sizeof(int);
payload[0].DataPointer = ((IntPtr)(&bufferId));
payload[1].Size = sizeof(int);
payload[1].DataPointer = ((IntPtr)(&bufferSize));
payload[2].Size = sizeof(int);
payload[2].DataPointer = ((IntPtr)(&poolId));
payload[3].Size = sizeof(int);
payload[3].DataPointer = ((IntPtr)(&bucketId));
payload[4].Size = sizeof(BufferAllocatedReason);
payload[4].DataPointer = ((IntPtr)(&reason));
payload[0] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&bufferId))
};
payload[1] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&bufferSize))
};
payload[2] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&poolId))
};
payload[3] = new EventData
{
Size = sizeof(int),
DataPointer = ((IntPtr)(&bucketId))
};
payload[4] = new EventData
{
Size = sizeof(BufferAllocatedReason),
DataPointer = ((IntPtr)(&reason))
};
WriteEventCore(2, 5, payload);
}

View File

@@ -0,0 +1,60 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Threading;
namespace System.Buffers.ArrayPool.Tests
{
public abstract class ArrayPoolTest : RemoteExecutorTestBase
{
protected const string TrimSwitchName = "DOTNET_SYSTEM_BUFFERS_ARRAYPOOL_TRIMSHARED";
protected static class EventIds
{
public const int BufferRented = 1;
public const int BufferAllocated = 2;
public const int BufferReturned = 3;
public const int BufferTrimmed = 4;
public const int BufferTrimPoll = 5;
}
protected static int RunWithListener(Action body, EventLevel level, Action<EventWrittenEventArgs> callback)
{
using (TestEventListener listener = new TestEventListener("System.Buffers.ArrayPoolEventSource", level))
{
int count = 0;
listener.RunWithCallback(e =>
{
Interlocked.Increment(ref count);
callback(e);
}, body);
return count;
}
}
protected static void RemoteInvokeWithTrimming(Action action, bool trim = false)
{
RemoteInvokeOptions options = new RemoteInvokeOptions();
options.StartInfo.UseShellExecute = false;
options.StartInfo.EnvironmentVariables.Add(TrimSwitchName, trim.ToString());
RemoteInvoke(action).Dispose();
}
protected static void RemoteInvokeWithTrimming(Func<string, int> method, bool trim = false, int timeout = FailWaitTimeoutMilliseconds)
{
RemoteInvokeOptions options = new RemoteInvokeOptions
{
TimeOut = timeout
};
options.StartInfo.UseShellExecute = false;
options.StartInfo.EnvironmentVariables.Add(TrimSwitchName, trim.ToString());
RemoteInvoke(method, trim.ToString(), options).Dispose();
}
}
}

View File

@@ -0,0 +1,194 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using Xunit;
namespace System.Buffers.ArrayPool.Tests
{
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)]
public class CollectionTests : ArrayPoolTest
{
[OuterLoop("This is a long running test (over 2 minutes)")]
[Theory,
InlineData(true),
InlineData(false)]
public void BuffersAreCollectedWhenStale(bool trim)
{
RemoteInvokeWithTrimming((trimString) =>
{
// Check that our environment is as we expect
Assert.Equal(trimString, Environment.GetEnvironmentVariable(TrimSwitchName));
const int BufferCount = 8;
const int BufferSize = 1025;
// Get the pool and check our trim setting
var pool = ArrayPool<int>.Shared;
bool parsedTrim = ValidateTrimState(pool, trimString);
List<int[]> rentedBuffers = new List<int[]>();
// Rent and return a set of buffers
for (int i = 0; i < BufferCount; i++)
{
rentedBuffers.Add(pool.Rent(BufferSize));
}
for (int i = 0; i < BufferCount; i++)
{
pool.Return(rentedBuffers[i]);
}
// Rent what we returned and ensure they are the same
for (int i = 0; i < BufferCount; i++)
{
var buffer = pool.Rent(BufferSize);
Assert.Contains(rentedBuffers, item => ReferenceEquals(item, buffer));
}
for (int i = 0; i < BufferCount; i++)
{
pool.Return(rentedBuffers[i]);
}
// Now wait a little over a minute and force a GC to get some buffers returned
Console.WriteLine("Waiting a minute for buffers to go stale...");
Thread.Sleep(61 * 1000);
GC.Collect(2);
GC.WaitForPendingFinalizers();
bool foundNewBuffer = false;
for (int i = 0; i < BufferCount; i++)
{
var buffer = pool.Rent(BufferSize);
if (!rentedBuffers.Any(item => ReferenceEquals(item, buffer)))
{
foundNewBuffer = true;
}
}
// Should only have found a new buffer if we're trimming
Assert.Equal(parsedTrim, foundNewBuffer);
return SuccessExitCode;
}, trim, 3 * 60 * 1000); // This test has to wait for the buffers to go stale (give it three minutes)
}
// This test can cause problems for other tests run in parallel (from other assemblies) as
// it pushes the physical memory usage above 80% temporarily.
[ConditionalTheory(typeof(TestEnvironment), nameof(TestEnvironment.IsStressModeEnabled)),
InlineData(true),
InlineData(false)]
public unsafe void ThreadLocalIsCollectedUnderHighPressure(bool trim)
{
RemoteInvokeWithTrimming((trimString) =>
{
// Check that our environment is as we expect
Assert.Equal(trimString, Environment.GetEnvironmentVariable(TrimSwitchName));
// Get the pool and check our trim setting
var pool = ArrayPool<byte>.Shared;
bool parsedTrim = ValidateTrimState(pool, trimString);
// Create our buffer, return it, re-rent it and ensure we have the same one
const int BufferSize = 4097;
var buffer = pool.Rent(BufferSize);
pool.Return(buffer);
Assert.Same(buffer, pool.Rent(BufferSize));
// Return it and put memory pressure on to get it cleared
pool.Return(buffer);
const int AllocSize = 1024 * 1024 * 64;
int PageSize = Environment.SystemPageSize;
var pressureMethod = pool.GetType().GetMethod("GetMemoryPressure", BindingFlags.Static | BindingFlags.NonPublic);
do
{
Span<byte> native = new Span<byte>(Marshal.AllocHGlobal(AllocSize).ToPointer(), AllocSize);
// Touch the pages to bring them into physical memory
for (int i = 0; i < native.Length; i += PageSize)
{
native[i] = 0xEF;
}
GC.Collect(2);
} while ((int)pressureMethod.Invoke(null, null) != 2);
GC.WaitForPendingFinalizers();
if (parsedTrim)
{
// Should have a new buffer now
Assert.NotSame(buffer, pool.Rent(BufferSize));
}
else
{
// Disabled, should not have trimmed buffer
Assert.Same(buffer, pool.Rent(BufferSize));
}
return SuccessExitCode;
}, trim);
}
private static bool ValidateTrimState(object pool, string trimString)
{
Assert.StartsWith("TlsOverPerCoreLockedStacksArrayPool", pool.GetType().Name);
bool parsedTrim = bool.Parse(trimString);
var trimField = pool.GetType().GetField("s_trimBuffers", BindingFlags.Static | BindingFlags.NonPublic);
Assert.Equal(parsedTrim, (bool)trimField.GetValue(null));
return parsedTrim;
}
[Theory,
InlineData(true),
InlineData(false)]
public void PollingEventFires(bool trim)
{
RemoteInvokeWithTrimming((trimString) =>
{
var pool = ArrayPool<float>.Shared;
bool parsedTrim = ValidateTrimState(pool, trimString);
bool pollEventFired = false;
var buffer = pool.Rent(10);
// Polling doesn't start until the thread locals are created for a pool.
// Try before the return then after.
RunWithListener(() =>
{
GC.Collect(2);
GC.WaitForPendingFinalizers();
},
EventLevel.Informational,
e =>
{
if (e.EventId == EventIds.BufferTrimPoll)
pollEventFired = true;
});
Assert.False(pollEventFired, "collection isn't hooked up until the first item is returned");
pool.Return(buffer);
RunWithListener(() =>
{
GC.Collect(2);
GC.WaitForPendingFinalizers();
},
EventLevel.Informational,
e =>
{
if (e.EventId == EventIds.BufferTrimPoll)
pollEventFired = true;
});
// Polling events should only fire when trimming is enabled
Assert.Equal(parsedTrim, pollEventFired);
return SuccessExitCode;
}, trim);
}
}
}

View File

@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
@@ -12,7 +11,7 @@ using Xunit;
namespace System.Buffers.ArrayPool.Tests
{
public partial class ArrayPoolUnitTests
public partial class ArrayPoolUnitTests : ArrayPoolTest
{
private const int MaxEventWaitTimeoutInMs = 200;
@@ -399,82 +398,87 @@ namespace System.Buffers.ArrayPool.Tests
Assert.Equal(64, pool.Rent(63).Length); // still get original size
}
private static int RunWithListener(Action body, EventLevel level, Action<EventWrittenEventArgs> callback)
{
using (TestEventListener listener = new TestEventListener("System.Buffers.ArrayPoolEventSource", level))
{
int count = 0;
listener.RunWithCallback(e =>
{
Interlocked.Increment(ref count);
callback(e);
}, body);
return count;
}
}
[Fact]
public static void RentBufferFiresRentedDiagnosticEvent()
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
byte[] buffer = pool.Rent(16);
pool.Return(buffer);
Assert.Equal(1, RunWithListener(() => pool.Rent(16), EventLevel.Verbose, e =>
RemoteInvokeWithTrimming(() =>
{
Assert.Equal(1, e.EventId);
Assert.Equal(buffer.GetHashCode(), e.Payload[0]);
Assert.Equal(buffer.Length, e.Payload[1]);
Assert.Equal(pool.GetHashCode(), e.Payload[2]);
}));
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
byte[] buffer = pool.Rent(16);
pool.Return(buffer);
Assert.Equal(1, RunWithListener(() => pool.Rent(16), EventLevel.Verbose, e =>
{
Assert.Equal(1, e.EventId);
Assert.Equal(buffer.GetHashCode(), e.Payload[0]);
Assert.Equal(buffer.Length, e.Payload[1]);
Assert.Equal(pool.GetHashCode(), e.Payload[2]);
}));
});
}
[Fact]
public static void ReturnBufferFiresDiagnosticEvent()
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
byte[] buffer = pool.Rent(16);
Assert.Equal(1, RunWithListener(() => pool.Return(buffer), EventLevel.Verbose, e =>
RemoteInvokeWithTrimming(() =>
{
Assert.Equal(3, e.EventId);
Assert.Equal(buffer.GetHashCode(), e.Payload[0]);
Assert.Equal(buffer.Length, e.Payload[1]);
Assert.Equal(pool.GetHashCode(), e.Payload[2]);
}));
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
byte[] buffer = pool.Rent(16);
Assert.Equal(1, RunWithListener(() => pool.Return(buffer), EventLevel.Verbose, e =>
{
Assert.Equal(3, e.EventId);
Assert.Equal(buffer.GetHashCode(), e.Payload[0]);
Assert.Equal(buffer.Length, e.Payload[1]);
Assert.Equal(pool.GetHashCode(), e.Payload[2]);
}));
});
}
[Fact]
public static void RentingNonExistentBufferFiresAllocatedDiagnosticEvent()
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
Assert.Equal(1, RunWithListener(() => pool.Rent(16), EventLevel.Informational, e => Assert.Equal(2, e.EventId)));
RemoteInvokeWithTrimming(() =>
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
Assert.Equal(1, RunWithListener(() => pool.Rent(16), EventLevel.Informational, e => Assert.Equal(2, e.EventId)));
});
}
[Fact]
public static void RentingBufferOverConfiguredMaximumSizeFiresDiagnosticEvent()
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
Assert.Equal(1, RunWithListener(() => pool.Rent(64), EventLevel.Informational, e => Assert.Equal(2, e.EventId)));
RemoteInvokeWithTrimming(() =>
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 1);
Assert.Equal(1, RunWithListener(() => pool.Rent(64), EventLevel.Informational, e => Assert.Equal(2, e.EventId)));
});
}
[Fact]
public static void RentingManyBuffersFiresExpectedDiagnosticEvents()
{
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 10);
var list = new List<EventWrittenEventArgs>();
Assert.Equal(60, RunWithListener(() =>
RemoteInvokeWithTrimming(() =>
{
for (int i = 0; i < 10; i++) pool.Return(pool.Rent(16)); // 10 rents + 10 allocations, 10 returns
for (int i = 0; i < 10; i++) pool.Return(pool.Rent(0)); // 0 events for empty arrays
for (int i = 0; i < 10; i++) pool.Rent(16); // 10 rents
for (int i = 0; i < 10; i++) pool.Rent(16); // 10 rents + 10 allocations
}, EventLevel.Verbose, list.Add));
ArrayPool<byte> pool = ArrayPool<byte>.Create(maxArrayLength: 16, maxArraysPerBucket: 10);
var list = new List<EventWrittenEventArgs>();
Assert.Equal(30, list.Where(e => e.EventId == 1).Count()); // rents
Assert.Equal(20, list.Where(e => e.EventId == 2).Count()); // allocations
Assert.Equal(10, list.Where(e => e.EventId == 3).Count()); // returns
Assert.Equal(60, RunWithListener(() =>
{
for (int i = 0; i < 10; i++)
pool.Return(pool.Rent(16)); // 10 rents + 10 allocations, 10 returns
for (int i = 0; i < 10; i++)
pool.Return(pool.Rent(0)); // 0 events for empty arrays
for (int i = 0; i < 10; i++)
pool.Rent(16); // 10 rents
for (int i = 0; i < 10; i++)
pool.Rent(16); // 10 rents + 10 allocations
}, EventLevel.Verbose, list.Add));
Assert.Equal(30, list.Where(e => e.EventId == 1).Count()); // rents
Assert.Equal(20, list.Where(e => e.EventId == 2).Count()); // allocations
Assert.Equal(10, list.Where(e => e.EventId == 3).Count()); // returns
});
}
[Theory]

View File

@@ -3,12 +3,24 @@
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{62E2AD5F-C8D0-45FB-B6A5-AED2C77F198C}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'">
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'">
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="ArrayPool\ArrayPoolTest.cs" />
<Compile Include="ArrayPool\CollectionTests.cs" />
<Compile Include="ArrayPool\UnitTests.cs" />
<Compile Include="$(CommonTestPath)\System\Diagnostics\Tracing\TestEventListener.cs" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
<ProjectReference Include="$(CommonTestPath)\System\Diagnostics\RemoteExecutorConsoleApp\RemoteExecutorConsoleApp.csproj">
<Project>{69e46a6f-9966-45a5-8945-2559fe337827}</Project>
<Name>RemoteExecutorConsoleApp</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>