270 lines
8.6 KiB
C#
270 lines
8.6 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using Microsoft.AspNetCore.Testing;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.DataProtection
|
|
{
|
|
public unsafe class SecretTests
|
|
{
|
|
[Fact]
|
|
public void Ctor_ArraySegment_Default_Throws()
|
|
{
|
|
// Act & assert
|
|
ExceptionAssert.ThrowsArgument(
|
|
testCode: () => new Secret(default(ArraySegment<byte>)),
|
|
paramName: "array",
|
|
exceptionMessage: null);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_ArraySegment_Success()
|
|
{
|
|
// Arrange
|
|
var input = new ArraySegment<byte>(new byte[] { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60 }, 1, 3);
|
|
|
|
// Act
|
|
var secret = new Secret(input);
|
|
input.Array[2] = 0xFF; // mutate original array - secret shouldn't be modified
|
|
|
|
// Assert - length
|
|
Assert.Equal(3, secret.Length);
|
|
|
|
// Assert - managed buffer
|
|
var outputSegment = new ArraySegment<byte>(new byte[7], 2, 3);
|
|
secret.WriteSecretIntoBuffer(outputSegment);
|
|
Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputSegment.AsStandaloneArray());
|
|
|
|
// Assert - unmanaged buffer
|
|
var outputBuffer = new byte[3];
|
|
fixed (byte* pOutputBuffer = outputBuffer)
|
|
{
|
|
secret.WriteSecretIntoBuffer(pOutputBuffer, 3);
|
|
}
|
|
Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputBuffer);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Buffer_Success()
|
|
{
|
|
// Arrange
|
|
var input = new byte[] { 0x20, 0x30, 0x40 };
|
|
|
|
// Act
|
|
var secret = new Secret(input);
|
|
input[1] = 0xFF; // mutate original array - secret shouldn't be modified
|
|
|
|
// Assert - length
|
|
Assert.Equal(3, secret.Length);
|
|
|
|
// Assert - managed buffer
|
|
var outputSegment = new ArraySegment<byte>(new byte[7], 2, 3);
|
|
secret.WriteSecretIntoBuffer(outputSegment);
|
|
Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputSegment.AsStandaloneArray());
|
|
|
|
// Assert - unmanaged buffer
|
|
var outputBuffer = new byte[3];
|
|
fixed (byte* pOutputBuffer = outputBuffer)
|
|
{
|
|
secret.WriteSecretIntoBuffer(pOutputBuffer, 3);
|
|
}
|
|
Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputBuffer);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Buffer_ZeroLength_Success()
|
|
{
|
|
// Act
|
|
var secret = new Secret(new byte[0]);
|
|
|
|
// Assert - none of these methods should throw
|
|
Assert.Equal(0, secret.Length);
|
|
secret.WriteSecretIntoBuffer(new ArraySegment<byte>(new byte[0]));
|
|
byte dummy;
|
|
secret.WriteSecretIntoBuffer(&dummy, 0);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Pointer_WithNullPointer_ThrowsArgumentNull()
|
|
{
|
|
// Act & assert
|
|
ExceptionAssert.ThrowsArgumentNull(
|
|
testCode: () => new Secret(null, 0),
|
|
paramName: "secret");
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Pointer_WithNegativeLength_ThrowsArgumentOutOfRange()
|
|
{
|
|
// Act & assert
|
|
ExceptionAssert.ThrowsArgumentOutOfRange(
|
|
testCode: () =>
|
|
{
|
|
byte dummy;
|
|
new Secret(&dummy, -1);
|
|
},
|
|
paramName: "secretLength",
|
|
exceptionMessage: Resources.Common_ValueMustBeNonNegative);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Pointer_ZeroLength_Success()
|
|
{
|
|
// Arrange
|
|
byte input;
|
|
|
|
// Act
|
|
var secret = new Secret(&input, 0);
|
|
|
|
// Assert - none of these methods should throw
|
|
Assert.Equal(0, secret.Length);
|
|
secret.WriteSecretIntoBuffer(new ArraySegment<byte>(new byte[0]));
|
|
byte dummy;
|
|
secret.WriteSecretIntoBuffer(&dummy, 0);
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Pointer_Success()
|
|
{
|
|
// Arrange
|
|
byte* input = stackalloc byte[3];
|
|
input[0] = 0x20;
|
|
input[1] = 0x30;
|
|
input[2] = 0x40;
|
|
|
|
// Act
|
|
var secret = new Secret(input, 3);
|
|
input[1] = 0xFF; // mutate original buffer - secret shouldn't be modified
|
|
|
|
// Assert - length
|
|
Assert.Equal(3, secret.Length);
|
|
|
|
// Assert - managed buffer
|
|
var outputSegment = new ArraySegment<byte>(new byte[7], 2, 3);
|
|
secret.WriteSecretIntoBuffer(outputSegment);
|
|
Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputSegment.AsStandaloneArray());
|
|
|
|
// Assert - unmanaged buffer
|
|
var outputBuffer = new byte[3];
|
|
fixed (byte* pOutputBuffer = outputBuffer)
|
|
{
|
|
secret.WriteSecretIntoBuffer(pOutputBuffer, 3);
|
|
}
|
|
Assert.Equal(new byte[] { 0x20, 0x30, 0x40 }, outputBuffer);
|
|
}
|
|
|
|
[Fact]
|
|
public void Random_ZeroLength_Success()
|
|
{
|
|
// Act
|
|
var secret = Secret.Random(0);
|
|
|
|
// Assert
|
|
Assert.Equal(0, secret.Length);
|
|
}
|
|
|
|
[Fact]
|
|
public void Random_LengthIsMultipleOf16_Success()
|
|
{
|
|
// Act
|
|
var secret = Secret.Random(32);
|
|
|
|
// Assert
|
|
Assert.Equal(32, secret.Length);
|
|
Guid* pGuids = stackalloc Guid[2];
|
|
secret.WriteSecretIntoBuffer((byte*)pGuids, 32);
|
|
Assert.NotEqual(Guid.Empty, pGuids[0]);
|
|
Assert.NotEqual(Guid.Empty, pGuids[1]);
|
|
Assert.NotEqual(pGuids[0], pGuids[1]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Random_LengthIsNotMultipleOf16_Success()
|
|
{
|
|
// Act
|
|
var secret = Secret.Random(31);
|
|
|
|
// Assert
|
|
Assert.Equal(31, secret.Length);
|
|
Guid* pGuids = stackalloc Guid[2];
|
|
secret.WriteSecretIntoBuffer((byte*)pGuids, 31);
|
|
Assert.NotEqual(Guid.Empty, pGuids[0]);
|
|
Assert.NotEqual(Guid.Empty, pGuids[1]);
|
|
Assert.NotEqual(pGuids[0], pGuids[1]);
|
|
Assert.Equal(0, ((byte*)pGuids)[31]); // last byte shouldn't have been overwritten
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteSecretIntoBuffer_ArraySegment_IncorrectlySizedBuffer_Throws()
|
|
{
|
|
// Arrange
|
|
var secret = Secret.Random(16);
|
|
|
|
// Act & assert
|
|
ExceptionAssert.ThrowsArgument(
|
|
testCode: () => secret.WriteSecretIntoBuffer(new ArraySegment<byte>(new byte[100])),
|
|
paramName: "buffer",
|
|
exceptionMessage: Resources.FormatCommon_BufferIncorrectlySized(100, 16));
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteSecretIntoBuffer_ArraySegment_Disposed_Throws()
|
|
{
|
|
// Arrange
|
|
var secret = Secret.Random(16);
|
|
secret.Dispose();
|
|
|
|
// Act & assert
|
|
Assert.Throws<ObjectDisposedException>(
|
|
testCode: () => secret.WriteSecretIntoBuffer(new ArraySegment<byte>(new byte[16])));
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteSecretIntoBuffer_Pointer_NullBuffer_Throws()
|
|
{
|
|
// Arrange
|
|
var secret = Secret.Random(16);
|
|
|
|
// Act & assert
|
|
ExceptionAssert.ThrowsArgumentNull(
|
|
testCode: () => secret.WriteSecretIntoBuffer(null, 100),
|
|
paramName: "buffer");
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteSecretIntoBuffer_Pointer_IncorrectlySizedBuffer_Throws()
|
|
{
|
|
// Arrange
|
|
var secret = Secret.Random(16);
|
|
|
|
// Act & assert
|
|
ExceptionAssert.ThrowsArgument(
|
|
testCode: () =>
|
|
{
|
|
byte* pBuffer = stackalloc byte[100];
|
|
secret.WriteSecretIntoBuffer(pBuffer, 100);
|
|
},
|
|
paramName: "bufferLength",
|
|
exceptionMessage: Resources.FormatCommon_BufferIncorrectlySized(100, 16));
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteSecretIntoBuffer_Pointer_Disposed_Throws()
|
|
{
|
|
// Arrange
|
|
var secret = Secret.Random(16);
|
|
secret.Dispose();
|
|
|
|
// Act & assert
|
|
Assert.Throws<ObjectDisposedException>(
|
|
testCode: () =>
|
|
{
|
|
byte* pBuffer = stackalloc byte[16];
|
|
secret.WriteSecretIntoBuffer(pBuffer, 16);
|
|
});
|
|
}
|
|
}
|
|
}
|