Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.26923.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Net.Security.Tests", "tests\FunctionalTests\System.Net.Security.Tests.csproj", "{A55A2B9A-830F-4330-A0E7-02A9FB30ABD2}"
ProjectSection(ProjectDependencies) = postProject
@@ -57,4 +57,7 @@ Global
{89F37791-6254-4D60-AB96-ACD3CCA0E771} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
{A7488FC0-9A8F-4EF9-BC3E-C5EBA47E13F8} = {2E666815-2EDB-464B-9DF6-380BF4789AD4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {72DFF69F-F9E9-4112-91E8-5FC8169B6F1F}
EndGlobalSection
EndGlobal

View File

@@ -18,10 +18,11 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System\PinnableBufferCache.cs" />
<Compile Include="System\Net\CertificateValidationPal.cs" />
<Compile Include="System\Net\FixedSizeReader.cs" />
<Compile Include="System\Net\HelperAsyncResults.cs" />
<Compile Include="System\Net\Logging\NetEventSource.cs" />
<Compile Include="System\Net\Security\SslStreamInternal.Adapters.cs" />
<Compile Include="System\Net\SslStreamContext.cs" />
<Compile Include="System\Net\Security\AuthenticatedStream.cs" />
<Compile Include="System\Net\Security\NetEventSource.Security.cs" />
@@ -163,6 +164,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\SChannel\UnmanagedCertificateContext.cs">
<Link>Common\Interop\Windows\SChannel\UnmanagedCertificateContext.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\SChannel\UnmanagedCertificateContext.IntPtr.cs">
<Link>Common\Interop\Windows\SChannel\UnmanagedCertificateContext.IntPtr.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\sspicli\SecPkgContext_Bindings.cs">
<Link>Common\Interop\Windows\sspicli\SecPkgContext_Bindings.cs</Link>
</Compile>
@@ -386,6 +390,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Win32.Primitives" />
<Reference Include="System.Buffers" />
<Reference Include="System.Collections" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Collections.NonGeneric" />

View File

@@ -0,0 +1,28 @@
// 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.Tracing;
using System.Runtime.CompilerServices;
namespace System.Net
{
internal sealed partial class NetEventSource : EventSource
{
/// <summary>Logs the contents of a buffer </summary>
/// <param name="thisOrContextObject">`this`, or another object that serves to provide context for the operation.</param>
/// <param name="buffer">The buffer to be logged.</param>
/// <param name="memberName">The calling member.</param>
[NonEvent]
public static void DumpBuffer(object thisOrContextObject, ReadOnlyMemory<byte> buffer, [CallerMemberName] string memberName = null)
{
if (IsEnabled)
{
int count = Math.Min(buffer.Length, MaxDumpSize);
byte[] slice = buffer.Slice(0, count).ToArray();
Log.DumpBuffer(IdOf(thisOrContextObject), memberName, slice);
}
}
}
}

View File

@@ -897,41 +897,19 @@ namespace System.Net.Security
size -
output - Encrypted bytes
--*/
internal SecurityStatusPal Encrypt(byte[] buffer, int offset, int size, ref byte[] output, out int resultSize)
internal SecurityStatusPal Encrypt(ReadOnlyMemory<byte> buffer, ref byte[] output, out int resultSize)
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Enter(this, buffer, offset, size);
NetEventSource.DumpBuffer(this, buffer, 0, Math.Min(buffer.Length, 128));
NetEventSource.Enter(this, buffer, buffer.Length);
NetEventSource.DumpBuffer(this, buffer);
}
byte[] writeBuffer = output;
try
{
if (offset < 0 || offset > (buffer == null ? 0 : buffer.Length))
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if (size < 0 || size > (buffer == null ? 0 : buffer.Length - offset))
{
throw new ArgumentOutOfRangeException(nameof(size));
}
resultSize = 0;
}
catch (Exception e) when (!ExceptionCheck.IsFatal(e))
{
NetEventSource.Fail(this, "Arguments out of range.");
throw;
}
SecurityStatusPal secStatus = SslStreamPal.EncryptMessage(
_securityContext,
buffer,
offset,
size,
_headerSize,
_trailerSize,
ref writeBuffer,

View File

@@ -37,7 +37,7 @@ namespace System.Net.Security
DataKeySize = dataKeySize;
DataHashKeySize = dataHashKeySize;
//Openssl does not provide a way to return a exchange key size.
//Openssl does not provide a way to return an exchange key size.
//It internally does calculate the key size before generating key to exchange
//It is not a constant (Algorthim specific) either that we can hardcode and return.
KeyExchKeySize = 0;

View File

@@ -479,10 +479,10 @@ namespace System.Net.Security
}
}
internal SecurityStatusPal EncryptData(byte[] buffer, int offset, int count, ref byte[] outBuffer, out int outSize)
internal SecurityStatusPal EncryptData(ReadOnlyMemory<byte> buffer, ref byte[] outBuffer, out int outSize)
{
CheckThrow(true);
return Context.Encrypt(buffer, offset, count, ref outBuffer, out outSize);
return Context.Encrypt(buffer, ref outBuffer, out outSize);
}
internal SecurityStatusPal DecryptData(byte[] buffer, ref int offset, ref int count)
@@ -1279,10 +1279,31 @@ namespace System.Net.Security
}
}
// Returns:
// true - operation queued
// false - operation can proceed
internal bool CheckEnqueueWrite(AsyncProtocolRequest asyncRequest)
internal Task CheckEnqueueWriteAsync()
{
// Clear previous request.
int lockState = Interlocked.CompareExchange(ref _lockWriteState, LockWrite, LockNone);
if (lockState != LockHandshake)
{
return Task.CompletedTask;
}
lock (this)
{
if (_lockWriteState != LockHandshake)
{
CheckThrow(authSuccessCheck: true);
return Task.CompletedTask;
}
_lockWriteState = LockPendingWrite;
TaskCompletionSource<int> completionSource = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
_queuedWriteStateRequest = completionSource;
return completionSource.Task;
}
}
internal void CheckEnqueueWrite()
{
// Clear previous request.
_queuedWriteStateRequest = null;
@@ -1290,7 +1311,7 @@ namespace System.Net.Security
if (lockState != LockHandshake)
{
// Proceed with write.
return false;
return;
}
LazyAsyncResult lazyResult = null;
@@ -1299,27 +1320,20 @@ namespace System.Net.Security
if (_lockWriteState != LockHandshake)
{
// Handshake has completed before we grabbed the lock.
CheckThrow(true);
return false;
CheckThrow(authSuccessCheck: true);
return;
}
_lockWriteState = LockPendingWrite;
// Still pending, wait or enqueue.
if (asyncRequest != null)
{
_queuedWriteStateRequest = asyncRequest;
return true;
}
lazyResult = new LazyAsyncResult(null, null, /*must be */null);
_queuedWriteStateRequest = lazyResult;
}
// Need to exit from lock before waiting.
lazyResult.InternalWaitForCompletion();
CheckThrow(true);
return false;
CheckThrow(authSuccessCheck: true);
return;
}
internal void FinishWrite()
@@ -1332,25 +1346,27 @@ namespace System.Net.Security
lock (this)
{
object obj = _queuedWriteStateRequest;
if (obj == null)
{
// A repeated call.
return;
}
HandleWriteCallback();
}
}
_queuedWriteStateRequest = null;
if (obj is LazyAsyncResult)
{
// Sync handshake is waiting on other thread.
((LazyAsyncResult)obj).InvokeCallback();
}
else
{
// Async handshake is pending, start it on other thread.
// Consider: we could start it in on this thread but that will delay THIS write completion
private void HandleWriteCallback()
{
object obj = _queuedWriteStateRequest;
_queuedWriteStateRequest = null;
switch (obj)
{
case null:
break;
case LazyAsyncResult lazy:
lazy.InvokeCallback();
break;
case TaskCompletionSource<int> tsc:
tsc.SetResult(0);
break;
default:
ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncResumeHandshake), obj);
}
break;
}
}
@@ -1411,26 +1427,7 @@ namespace System.Net.Security
}
_lockWriteState = LockWrite;
object obj = _queuedWriteStateRequest;
if (obj == null)
{
// We finished before Write has grabbed the lock.
return;
}
_queuedWriteStateRequest = null;
if (obj is LazyAsyncResult)
{
// Sync write is waiting on other thread.
((LazyAsyncResult)obj).InvokeCallback();
}
else
{
// Async write is pending, start it on other thread.
// Consider: we could start it in on this thread but that will delay THIS handshake completion
ThreadPool.QueueUserWorkItem(new WaitCallback(CompleteRequestWaitCallback), obj);
}
HandleWriteCallback();
}
}
finally

View File

@@ -281,7 +281,7 @@ namespace System.Net.Security
public virtual Task ShutdownAsync() =>
Task.Factory.FromAsync(
(callback, state) => ((SslStream)state).BeginShutdown(callback, state),
iar => ((SslStream)iar.AsyncState).EndShutdown(iar),
iar => ((SslStream)iar.AsyncState).EndShutdown(iar),
this);
#endregion
@@ -565,5 +565,15 @@ namespace System.Net.Security
{
_sslState.SecureStream.EndWrite(asyncResult);
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _sslState.SecureStream.WriteAsync(buffer, offset, count, cancellationToken);
}
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
{
return _sslState.SecureStream.WriteAsync(source, cancellationToken);
}
}
}

View File

@@ -0,0 +1,53 @@
// 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.Threading;
using System.Threading.Tasks;
namespace System.Net.Security
{
// This contains adapters to allow a single code path for sync/async logic
internal partial class SslStreamInternal
{
private interface ISslWriteAdapter
{
Task LockAsync();
Task WriteAsync(byte[] buffer, int offset, int count);
}
private struct SslWriteAsync : ISslWriteAdapter
{
private readonly SslState _sslState;
private readonly CancellationToken _cancellationToken;
public SslWriteAsync(SslState sslState, CancellationToken cancellationToken)
{
_sslState = sslState;
_cancellationToken = cancellationToken;
}
public Task LockAsync() => _sslState.CheckEnqueueWriteAsync();
public Task WriteAsync(byte[] buffer, int offset, int count) => _sslState.InnerStream.WriteAsync(buffer, offset, count, _cancellationToken);
}
private struct SslWriteSync : ISslWriteAdapter
{
private readonly SslState _sslState;
public SslWriteSync(SslState sslState) => _sslState = sslState;
public Task LockAsync()
{
_sslState.CheckEnqueueWrite();
return Task.CompletedTask;
}
public Task WriteAsync(byte[] buffer, int offset, int count)
{
_sslState.InnerStream.Write(buffer, offset, count);
return Task.CompletedTask;
}
}
}
}

View File

@@ -2,14 +2,15 @@
// 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.Buffers;
using System.ComponentModel;
using System.Diagnostics;
using System.Security.Authentication;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
using PAL_TlsHandshakeState=Interop.AppleCrypto.PAL_TlsHandshakeState;
using PAL_TlsIo=Interop.AppleCrypto.PAL_TlsIo;
using PAL_TlsHandshakeState = Interop.AppleCrypto.PAL_TlsHandshakeState;
using PAL_TlsIo = Interop.AppleCrypto.PAL_TlsIo;
namespace System.Net.Security
{
@@ -76,9 +77,7 @@ namespace System.Net.Security
public static SecurityStatusPal EncryptMessage(
SafeDeleteContext securityContext,
byte[] input,
int offset,
int size,
ReadOnlyMemory<byte> input,
int headerSize,
int trailerSize,
ref byte[] output,
@@ -86,7 +85,7 @@ namespace System.Net.Security
{
resultSize = 0;
Debug.Assert(size > 0, $"{nameof(size)} > 0 since {nameof(CanEncryptEmptyMessage)} is false");
Debug.Assert(input.Length > 0, $"{nameof(input.Length)} > 0 since {nameof(CanEncryptEmptyMessage)} is false");
try
{
@@ -95,10 +94,10 @@ namespace System.Net.Security
unsafe
{
fixed (byte* offsetInput = &input[offset])
MemoryHandle memHandle = input.Retain(pin: true);
try
{
int written;
PAL_TlsIo status = Interop.AppleCrypto.SslWrite(sslHandle, offsetInput, size, out written);
PAL_TlsIo status = Interop.AppleCrypto.SslWrite(sslHandle, (byte*)memHandle.PinnedPointer, input.Length, out int written);
if (status < 0)
{
@@ -128,6 +127,10 @@ namespace System.Net.Security
return new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError);
}
}
finally
{
memHandle.Dispose();
}
}
}
catch (Exception e)

View File

@@ -36,12 +36,12 @@ namespace System.Net.Security
public static SecurityStatusPal InitializeSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context,
string targetName, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer)
{
{
return HandshakeInternal(credential, ref context, inputBuffer, outputBuffer, false, false);
}
public static SecurityStatusPal InitializeSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer)
{
{
Debug.Assert(inputBuffers.Length == 2);
Debug.Assert(inputBuffers[1].token == null);
return HandshakeInternal(credential, ref context, inputBuffers[0], outputBuffer, false, false);
@@ -53,16 +53,15 @@ namespace System.Net.Security
return new SafeFreeSslCredentials(certificate, protocols, policy);
}
public static SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] input, int offset, int size, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
public static SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, ReadOnlyMemory<byte> input, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
{
return EncryptDecryptHelper(securityContext, input, offset, size, true, ref output, out resultSize);
return EncryptDecryptHelper(securityContext, input, offset:0, size: 0, encrypt: true, output: ref output, resultSize: out resultSize);
}
public static SecurityStatusPal DecryptMessage(SafeDeleteContext securityContext, byte[] buffer, ref int offset, ref int count)
{
int resultSize;
SecurityStatusPal retVal = EncryptDecryptHelper(securityContext, buffer, offset, count, false, ref buffer, out resultSize);
if (retVal.ErrorCode == SecurityStatusPalErrorCode.OK ||
SecurityStatusPal retVal = EncryptDecryptHelper(securityContext, buffer, offset, count, false, ref buffer, out int resultSize);
if (retVal.ErrorCode == SecurityStatusPalErrorCode.OK ||
retVal.ErrorCode == SecurityStatusPalErrorCode.Renegotiate)
{
count = resultSize;
@@ -136,11 +135,11 @@ namespace System.Net.Security
}
catch (Exception exc)
{
return new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc);
return new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc);
}
}
private static SecurityStatusPal EncryptDecryptHelper(SafeDeleteContext securityContext, byte[] input, int offset, int size, bool encrypt, ref byte[] output, out int resultSize)
private static SecurityStatusPal EncryptDecryptHelper(SafeDeleteContext securityContext, ReadOnlyMemory<byte> input, int offset, int size, bool encrypt, ref byte[] output, out int resultSize)
{
resultSize = 0;
try
@@ -150,12 +149,11 @@ namespace System.Net.Security
if (encrypt)
{
resultSize = Interop.OpenSsl.Encrypt(scHandle, input, offset, size, ref output, out errorCode);
resultSize = Interop.OpenSsl.Encrypt(scHandle, input, ref output, out errorCode);
}
else
{
Debug.Assert(ReferenceEquals(input, output), "Expected input==output when decrypting");
resultSize = Interop.OpenSsl.Decrypt(scHandle, input, offset, size, out errorCode);
resultSize = Interop.OpenSsl.Decrypt(scHandle, output, offset, size, out errorCode);
}
switch (errorCode)

View File

@@ -131,13 +131,13 @@ namespace System.Net.Security
return AcquireCredentialsHandle(direction, secureCredential);
}
public static unsafe SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] input, int offset, int size, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
public static unsafe SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, ReadOnlyMemory<byte> input, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
{
// Ensure that there is sufficient space for the message output.
int bufferSizeNeeded;
try
{
bufferSizeNeeded = checked(size + headerSize + trailerSize);
bufferSizeNeeded = checked(input.Length + headerSize + trailerSize);
}
catch
{
@@ -150,8 +150,8 @@ namespace System.Net.Security
}
// Copy the input into the output buffer to prepare for SCHANNEL's expectations
Buffer.BlockCopy(input, offset, output, headerSize, size);
input.Span.CopyTo(new Span<byte>(output, headerSize, input.Length));
const int NumSecBuffers = 4; // header + data + trailer + empty
var unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[NumSecBuffers];
var sdcInOut = new Interop.SspiCli.SecBufferDesc(NumSecBuffers);
@@ -166,11 +166,11 @@ namespace System.Net.Security
Interop.SspiCli.SecBuffer* dataSecBuffer = &unmanagedBuffer[1];
dataSecBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA;
dataSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize);
dataSecBuffer->cbBuffer = size;
dataSecBuffer->cbBuffer = input.Length;
Interop.SspiCli.SecBuffer* trailerSecBuffer = &unmanagedBuffer[2];
trailerSecBuffer->BufferType = SecurityBufferType.SECBUFFER_STREAM_TRAILER;
trailerSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize + size);
trailerSecBuffer->pvBuffer = (IntPtr)(outputPtr + headerSize + input.Length);
trailerSecBuffer->cbBuffer = trailerSize;
Interop.SspiCli.SecBuffer* emptySecBuffer = &unmanagedBuffer[3];

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -73,7 +74,6 @@ namespace System.Net.Security.Tests
// Clear the credentials
var startInfo = new ProcessStartInfo(KDestroyCmd);
startInfo.UseShellExecute = true;
startInfo.CreateNoWindow = true;
startInfo.Arguments = "-A";
using (Process clearCreds = Process.Start(startInfo))

View File

@@ -47,9 +47,6 @@
<Compile Include="NegotiateStreamKerberosTest.cs" />
<!-- Common test files -->
<Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
<Link>Common\System\PlatformDetection.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\Net\Capability.Security.cs">
<Link>Common\System\Net\Capability.Security.cs</Link>
</Compile>

View File

@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace System.Net.Security
{
@@ -30,6 +32,8 @@ namespace System.Net.Security
public abstract bool IsEncrypted { get; }
public abstract bool IsSigned { get; }
public abstract bool IsServer { get; }
public abstract Task WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken token);
}
}

View File

@@ -268,8 +268,8 @@ namespace System.Net.Security
{
throw new NotImplementedException();
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
public Task WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
@@ -16,11 +16,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Windows_NT-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="SslStreamAllowedProtocolsTest.cs" />
<Compile Include="System\Security\Authentication\ExtendedProtection\ExtendedProtectionPolicyTest.cs" />
<Compile Include="System\PinnableBufferCacheTest.cs" />
<Compile Include="TlsAlertsMatchWindowsInterop.cs" />
<!-- Fakes -->
<Compile Include="Fakes\FakeSslState.cs" />
@@ -33,9 +31,6 @@
</ItemGroup>
<ItemGroup>
<!-- Production code references -->
<Compile Include="..\..\src\System\PinnableBufferCache.cs">
<Link>ProductionCode\System\PinnableBufferCache.cs</Link>
</Compile>
<Compile Include="..\..\src\System\Net\Security\SslStream.cs">
<Link>ProductionCode\System\Net\Security\SslStream.cs</Link>
</Compile>

View File

@@ -1,27 +0,0 @@
// 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 Xunit;
namespace System.Net.Security.Tests
{
public class PinnableBufferCacheTest
{
[Fact]
public void PinnableBufferCache_AllocateBuffer_Ok()
{
string cacheName = "Test";
int numberOfElements = 5;
PinnableBufferCache p = new PinnableBufferCache(cacheName, numberOfElements);
byte[] a = p.AllocateBuffer();
Assert.Equal(numberOfElements, a.Length);
foreach (byte t in a)
{
Assert.Equal(0, t);
}
}
}
}