Moved all UnitTests to a single project. Implemented parts of AspNetCore UnitTests.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class CryptographyHelperExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnMd5Hash()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
string strHash = str.Md5();
|
||||
string byteHash = bytes.Md5();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("ed076287532e86365e841e92bfc50d8c", strHash);
|
||||
Assert.AreEqual("63c983de427ce9e2430ba8554d2a822f", byteHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSha1Hash()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
string strHash = str.Sha1();
|
||||
string byteHash = bytes.Sha1();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("2ef7bde608ce5404e97d5f042f95f89f1c232871", strHash);
|
||||
Assert.AreEqual("ec2c39d500316044fa49f6c8f471ddec8b4fb9d1", byteHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSha256Hash()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
string strHash = str.Sha256();
|
||||
string byteHash = bytes.Sha256();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", strHash);
|
||||
Assert.AreEqual("4e0da689dc7a51957be426d6cfb1bd860169cb25dd1ac946a2f141228217804a", byteHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSha512Hash()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
string strHash = str.Sha512();
|
||||
string byteHash = bytes.Sha512();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8", strHash);
|
||||
Assert.AreEqual("591098c5d470a09f0ff48a4fdb7769ab89f803eae9e23b6f9f69dd228cca46c074bbc11a5fceaa8a5f48d14d2bf19a83a629266c2c5b7d9ef34623b64cb2f8e7", byteHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
355
UnitTests/Common/Extensions/DateTimeExtensionsTests.cs
Normal file
355
UnitTests/Common/Extensions/DateTimeExtensionsTests.cs
Normal file
@@ -0,0 +1,355 @@
|
||||
using System;
|
||||
using UnitTests.Common.Utils;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class DateTimeExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnUtc()
|
||||
{
|
||||
// arrange
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin");
|
||||
using var _ = TimeZoneInfoLocalMock.Create(timeZoneInfo);
|
||||
|
||||
var utc = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Utc);
|
||||
var local = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Local);
|
||||
var unspecified = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Unspecified);
|
||||
|
||||
// act
|
||||
var utcCorrected = utc.AsUtc();
|
||||
var localCorrected = local.AsUtc();
|
||||
var unspecifiedCorrected = unspecified.AsUtc();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(DateTimeKind.Utc, utcCorrected.Kind);
|
||||
Assert.AreEqual(DateTimeKind.Utc, localCorrected.Kind);
|
||||
Assert.AreEqual(DateTimeKind.Utc, unspecifiedCorrected.Kind);
|
||||
|
||||
Assert.AreEqual(utc, utcCorrected);
|
||||
Assert.AreEqual(utc.AddHours(-1), localCorrected);
|
||||
Assert.AreEqual(utc, unspecifiedCorrected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnLocal()
|
||||
{
|
||||
// arrange
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin");
|
||||
using var _ = TimeZoneInfoLocalMock.Create(timeZoneInfo);
|
||||
|
||||
var utc = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Utc);
|
||||
var local = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Local);
|
||||
var unspecified = new DateTime(2021, 11, 15, 11, 22, 33, DateTimeKind.Unspecified);
|
||||
|
||||
// act
|
||||
var utcCorrected = utc.AsLocal();
|
||||
var localCorrected = local.AsLocal();
|
||||
var unspecifiedCorrected = unspecified.AsLocal();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(DateTimeKind.Local, utcCorrected.Kind);
|
||||
Assert.AreEqual(DateTimeKind.Local, localCorrected.Kind);
|
||||
Assert.AreEqual(DateTimeKind.Local, unspecifiedCorrected.Kind);
|
||||
|
||||
Assert.AreEqual(local.AddHours(1), utcCorrected);
|
||||
Assert.AreEqual(local, localCorrected);
|
||||
Assert.AreEqual(local, unspecifiedCorrected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnCorrectUtcAlignmentDaylightSavingEnd()
|
||||
{
|
||||
// arrange
|
||||
var dateTime = new DateTime(2021, 10, 30, 12, 15, 30, 45, DateTimeKind.Utc);
|
||||
|
||||
var intervalThreeSeconds = TimeSpan.FromSeconds(3);
|
||||
var intervalSixMinutes = TimeSpan.FromMinutes(6);
|
||||
var intervalTwoHours = TimeSpan.FromHours(2);
|
||||
var intervalDay = TimeSpan.FromDays(1);
|
||||
|
||||
var offsetTwoMinutes = TimeSpan.FromMinutes(2);
|
||||
var offsetFourHours = TimeSpan.FromHours(4);
|
||||
|
||||
// act
|
||||
var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(dateTime);
|
||||
var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(dateTime);
|
||||
var diffTwoHours = intervalTwoHours.GetAlignedInterval(dateTime);
|
||||
var diffDay = intervalDay.GetAlignedInterval(dateTime);
|
||||
|
||||
var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(dateTime, offsetTwoMinutes);
|
||||
var diffDayOffset = intervalDay.GetAlignedInterval(dateTime, offsetFourHours);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds);
|
||||
Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes);
|
||||
Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours);
|
||||
Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay);
|
||||
|
||||
Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset);
|
||||
Assert.AreEqual(TimeSpan.Parse("15:44:29.955"), diffDayOffset); // must be the same whether daylight saving has ended
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnCorrectUtcAlignmentDaylightSavingStart()
|
||||
{
|
||||
// arrange
|
||||
var dateTime = new DateTime(2022, 3, 26, 12, 15, 30, 45, DateTimeKind.Utc);
|
||||
|
||||
var intervalThreeSeconds = TimeSpan.FromSeconds(3);
|
||||
var intervalSixMinutes = TimeSpan.FromMinutes(6);
|
||||
var intervalTwoHours = TimeSpan.FromHours(2);
|
||||
var intervalDay = TimeSpan.FromDays(1);
|
||||
|
||||
var offsetTwoMinutes = TimeSpan.FromMinutes(2);
|
||||
var offsetFourHours = TimeSpan.FromHours(4);
|
||||
|
||||
// act
|
||||
var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(dateTime);
|
||||
var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(dateTime);
|
||||
var diffTwoHours = intervalTwoHours.GetAlignedInterval(dateTime);
|
||||
var diffDay = intervalDay.GetAlignedInterval(dateTime);
|
||||
|
||||
var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(dateTime, offsetTwoMinutes);
|
||||
var diffDayOffset = intervalDay.GetAlignedInterval(dateTime, offsetFourHours);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds);
|
||||
Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes);
|
||||
Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours);
|
||||
Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay);
|
||||
|
||||
Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset);
|
||||
Assert.AreEqual(TimeSpan.Parse("15:44:29.955"), diffDayOffset); // must be the same whether daylight saving has started
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnCorrectLocalAlignmentDaylightSavingEnd()
|
||||
{
|
||||
// arrange
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin");
|
||||
using var _ = TimeZoneInfoLocalMock.Create(timeZoneInfo);
|
||||
|
||||
var dateTime = new DateTime(2021, 10, 30, 12, 15, 30, 45, DateTimeKind.Local);
|
||||
|
||||
var intervalThreeSeconds = TimeSpan.FromSeconds(3);
|
||||
var intervalSixMinutes = TimeSpan.FromMinutes(6);
|
||||
var intervalTwoHours = TimeSpan.FromHours(2);
|
||||
var intervalDay = TimeSpan.FromDays(1);
|
||||
|
||||
var offsetTwoMinutes = TimeSpan.FromMinutes(2);
|
||||
var offsetFourHours = TimeSpan.FromHours(4);
|
||||
|
||||
// act
|
||||
var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(dateTime);
|
||||
var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(dateTime);
|
||||
var diffTwoHours = intervalTwoHours.GetAlignedInterval(dateTime);
|
||||
var diffDay = intervalDay.GetAlignedInterval(dateTime);
|
||||
|
||||
var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(dateTime, offsetTwoMinutes);
|
||||
var diffDayOffset = intervalDay.GetAlignedInterval(dateTime, offsetFourHours);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds);
|
||||
Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes);
|
||||
Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours);
|
||||
Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay);
|
||||
|
||||
Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset);
|
||||
Assert.AreEqual(TimeSpan.Parse("14:44:29.955"), diffDayOffset); // has to be minus one hour due to daylight saving ended
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnCorrectLocalAlignmentDaylightSavingStart()
|
||||
{
|
||||
// arrange
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin");
|
||||
using var _ = TimeZoneInfoLocalMock.Create(timeZoneInfo);
|
||||
|
||||
var dateTime = new DateTime(2022, 3, 26, 12, 15, 30, 45, DateTimeKind.Local);
|
||||
|
||||
var intervalThreeSeconds = TimeSpan.FromSeconds(3);
|
||||
var intervalSixMinutes = TimeSpan.FromMinutes(6);
|
||||
var intervalTwoHours = TimeSpan.FromHours(2);
|
||||
var intervalDay = TimeSpan.FromDays(1);
|
||||
|
||||
var offsetTwoMinutes = TimeSpan.FromMinutes(2);
|
||||
var offsetFourHours = TimeSpan.FromHours(4);
|
||||
|
||||
// act
|
||||
var diffThreeSeconds = intervalThreeSeconds.GetAlignedInterval(dateTime);
|
||||
var diffSixMinutes = intervalSixMinutes.GetAlignedInterval(dateTime);
|
||||
var diffTwoHours = intervalTwoHours.GetAlignedInterval(dateTime);
|
||||
var diffDay = intervalDay.GetAlignedInterval(dateTime);
|
||||
|
||||
var diffTwoHoursOffset = intervalTwoHours.GetAlignedInterval(dateTime, offsetTwoMinutes);
|
||||
var diffDayOffset = intervalDay.GetAlignedInterval(dateTime, offsetFourHours);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(TimeSpan.Parse("00:00:02.955"), diffThreeSeconds);
|
||||
Assert.AreEqual(TimeSpan.Parse("00:02:29.955"), diffSixMinutes);
|
||||
Assert.AreEqual(TimeSpan.Parse("01:44:29.955"), diffTwoHours);
|
||||
Assert.AreEqual(TimeSpan.Parse("11:44:29.955"), diffDay);
|
||||
|
||||
Assert.AreEqual(TimeSpan.Parse("01:46:29.955"), diffTwoHoursOffset);
|
||||
Assert.AreEqual(TimeSpan.Parse("16:44:29.955"), diffDayOffset); // has to be plus one hour due to daylight saving started
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnCorrectAlignment()
|
||||
{
|
||||
// arrange
|
||||
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin");
|
||||
using var _ = TimeZoneInfoLocalMock.Create(timeZoneInfo);
|
||||
|
||||
var interval = TimeSpan.FromDays(1);
|
||||
|
||||
// act
|
||||
var intervalUtc = interval.GetAlignedIntervalUtc();
|
||||
var intervalLocal = interval.GetAlignedIntervalLocal();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(DateTime.UtcNow.TimeOfDay.RoundToSecond(), (interval - intervalUtc).RoundToSecond());
|
||||
Assert.AreEqual(DateTime.Now.TimeOfDay.RoundToSecond(), (interval - intervalLocal).RoundToSecond());
|
||||
|
||||
Assert.AreEqual((DateTime.Now - DateTime.UtcNow).RoundToSecond(), (intervalUtc - intervalLocal).RoundToSecond());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnCorrectShortStringForTimeSpan()
|
||||
{
|
||||
// arrange
|
||||
var timeSpan = TimeSpan.Parse("1.10:11:12.345");
|
||||
var negativeTimeSpan = TimeSpan.FromDays(-1.234);
|
||||
|
||||
// act
|
||||
string shortString = timeSpan.ToShortString(withMilliseconds: false);
|
||||
string shortStringWithMillis = timeSpan.ToShortString(withMilliseconds: true);
|
||||
string shortStringNegative = negativeTimeSpan.ToShortString(withMilliseconds: true);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("1d 10h 11m 12s", shortString);
|
||||
Assert.AreEqual("1d 10h 11m 12s 345ms", shortStringWithMillis);
|
||||
Assert.AreEqual("-1d 5h 36m 57s 600ms", shortStringNegative);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRoundToSecond()
|
||||
{
|
||||
// arrange
|
||||
var timestampUp = new DateTime(2021, 11, 16, 20, 15, 30, 500);
|
||||
var timestampDown = new DateTime(2021, 11, 16, 20, 15, 30, 499);
|
||||
|
||||
var timespanUp = new TimeSpan(1, 2, 3, 4, 500);
|
||||
var timespanDown = new TimeSpan(1, 2, 3, 4, 499);
|
||||
|
||||
// act
|
||||
var timestampUpRounded = timestampUp.RoundToSecond();
|
||||
var timestampDownRounded = timestampDown.RoundToSecond();
|
||||
|
||||
var timespanUpRounded = timespanUp.RoundToSecond();
|
||||
var timespanDownRounded = timespanDown.RoundToSecond();
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(timestampUp, timestampUpRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 20:15:31.000"), timestampUpRounded);
|
||||
Assert.AreNotEqual(timestampDown, timestampDownRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 20:15:30.000"), timestampDownRounded);
|
||||
|
||||
Assert.AreNotEqual(timespanUp, timespanUpRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.02:03:05.000"), timespanUpRounded);
|
||||
Assert.AreNotEqual(timespanDown, timespanDownRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.02:03:04.000"), timespanDownRounded);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRoundToMinute()
|
||||
{
|
||||
// arrange
|
||||
var timestampUp = new DateTime(2021, 11, 16, 20, 15, 30, 0);
|
||||
var timestampDown = new DateTime(2021, 11, 16, 20, 15, 29, 999);
|
||||
|
||||
var timespanUp = new TimeSpan(1, 2, 3, 30, 0);
|
||||
var timespanDown = new TimeSpan(1, 2, 3, 29, 999);
|
||||
|
||||
// act
|
||||
var timestampUpRounded = timestampUp.RoundToMinute();
|
||||
var timestampDownRounded = timestampDown.RoundToMinute();
|
||||
|
||||
var timespanUpRounded = timespanUp.RoundToMinute();
|
||||
var timespanDownRounded = timespanDown.RoundToMinute();
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(timestampUp, timestampUpRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 20:16:00.000"), timestampUpRounded);
|
||||
Assert.AreNotEqual(timestampDown, timestampDownRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 20:15:00.000"), timestampDownRounded);
|
||||
|
||||
Assert.AreNotEqual(timespanUp, timespanUpRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.02:04:00.000"), timespanUpRounded);
|
||||
Assert.AreNotEqual(timespanDown, timespanDownRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.02:03:00.000"), timespanDownRounded);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRoundToHour()
|
||||
{
|
||||
// arrange
|
||||
var timestampUp = new DateTime(2021, 11, 16, 20, 30, 0, 0);
|
||||
var timestampDown = new DateTime(2021, 11, 16, 20, 29, 59, 999);
|
||||
|
||||
var timespanUp = new TimeSpan(1, 2, 30, 0, 0);
|
||||
var timespanDown = new TimeSpan(1, 2, 29, 59, 999);
|
||||
|
||||
// act
|
||||
var timestampUpRounded = timestampUp.RoundToHour();
|
||||
var timestampDownRounded = timestampDown.RoundToHour();
|
||||
|
||||
var timespanUpRounded = timespanUp.RoundToHour();
|
||||
var timespanDownRounded = timespanDown.RoundToHour();
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(timestampUp, timestampUpRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 21:00:00.000"), timestampUpRounded);
|
||||
Assert.AreNotEqual(timestampDown, timestampDownRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 20:00:00.000"), timestampDownRounded);
|
||||
|
||||
Assert.AreNotEqual(timespanUp, timespanUpRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.03:00:00.000"), timespanUpRounded);
|
||||
Assert.AreNotEqual(timespanDown, timespanDownRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.02:00:00.000"), timespanDownRounded);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRoundToDay()
|
||||
{
|
||||
// arrange
|
||||
var timestampUp = new DateTime(2021, 11, 16, 12, 0, 0, 0);
|
||||
var timestampDown = new DateTime(2021, 11, 16, 11, 59, 59, 999);
|
||||
|
||||
var timespanUp = new TimeSpan(1, 12, 0, 0, 0);
|
||||
var timespanDown = new TimeSpan(1, 11, 59, 59, 999);
|
||||
|
||||
// act
|
||||
var timestampUpRounded = timestampUp.RoundToDay();
|
||||
var timestampDownRounded = timestampDown.RoundToDay();
|
||||
|
||||
var timespanUpRounded = timespanUp.RoundToDay();
|
||||
var timespanDownRounded = timespanDown.RoundToDay();
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(timestampUp, timestampUpRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-17 00:00:00.000"), timestampUpRounded);
|
||||
Assert.AreNotEqual(timestampDown, timestampDownRounded);
|
||||
Assert.AreEqual(DateTime.Parse("2021-11-16 00:00:00.000"), timestampDownRounded);
|
||||
|
||||
Assert.AreNotEqual(timespanUp, timespanUpRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("2.00:00:00.000"), timespanUpRounded);
|
||||
Assert.AreNotEqual(timespanDown, timespanDownRounded);
|
||||
Assert.AreEqual(TimeSpan.Parse("1.00:00:00.000"), timespanDownRounded);
|
||||
}
|
||||
}
|
||||
}
|
||||
121
UnitTests/Common/Extensions/EnumExtensionsTests.cs
Normal file
121
UnitTests/Common/Extensions/EnumExtensionsTests.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnitTests.Common.Utils;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using DescriptionAttribute = System.ComponentModel.DescriptionAttribute;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class EnumExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyList()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Two;
|
||||
|
||||
// act
|
||||
var customList = enumValue.GetAttributes<CustomMultipleAttribute>();
|
||||
var descriptionList = enumValue.GetAttributes<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(customList);
|
||||
Assert.IsFalse(customList.Any());
|
||||
Assert.IsNotNull(descriptionList);
|
||||
Assert.IsFalse(descriptionList.Any());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnList()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Zero;
|
||||
|
||||
// act
|
||||
var customList = enumValue.GetAttributes<CustomMultipleAttribute>();
|
||||
var descriptionList = enumValue.GetAttributes<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(customList);
|
||||
Assert.IsTrue(customList.Any());
|
||||
Assert.AreEqual(2, customList.Count());
|
||||
Assert.IsNotNull(descriptionList);
|
||||
Assert.IsTrue(descriptionList.Any());
|
||||
Assert.AreEqual(1, descriptionList.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnNothing()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Two;
|
||||
|
||||
// act
|
||||
var customAttribute = enumValue.GetAttribute<CustomMultipleAttribute>();
|
||||
var descriptionAttribute = enumValue.GetAttribute<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNull(customAttribute);
|
||||
Assert.IsNull(descriptionAttribute);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnFirstAttribute()
|
||||
{
|
||||
// arrange
|
||||
var enumValue = TestEnum.Zero;
|
||||
|
||||
// act
|
||||
var customAttribute = enumValue.GetAttribute<CustomMultipleAttribute>();
|
||||
var descriptionAttribute = enumValue.GetAttribute<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(customAttribute);
|
||||
Assert.AreEqual("nix", customAttribute.Name);
|
||||
Assert.IsNotNull(descriptionAttribute);
|
||||
Assert.AreEqual("Null", descriptionAttribute.Description);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnDescriptionOrStringRepresentation()
|
||||
{
|
||||
// arrange
|
||||
var enumWithDescription = TestEnum.One;
|
||||
var enumWithoutDescripton = TestEnum.Two;
|
||||
|
||||
// act
|
||||
string description = enumWithDescription.GetDescription();
|
||||
string noDescription = enumWithoutDescripton.GetDescription();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Eins", description);
|
||||
Assert.AreEqual(enumWithoutDescripton.ToString(), noDescription);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyListOnNotDefinedEnumValue()
|
||||
{
|
||||
// arrange
|
||||
var notDefinedEnum = (TestEnum)10;
|
||||
|
||||
// act
|
||||
var list = notDefinedEnum.GetAttributes<DescriptionAttribute>();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(list.Any());
|
||||
}
|
||||
|
||||
internal enum TestEnum
|
||||
{
|
||||
[CustomMultiple("nix")]
|
||||
[CustomMultiple("Null")]
|
||||
[Description("Null")]
|
||||
Zero,
|
||||
[Description("Eins")]
|
||||
One,
|
||||
Two,
|
||||
}
|
||||
}
|
||||
}
|
||||
75
UnitTests/Common/Extensions/ExceptionExtensionsTests.cs
Normal file
75
UnitTests/Common/Extensions/ExceptionExtensionsTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class ExceptionExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnExceptionMessage()
|
||||
{
|
||||
// arrange
|
||||
var exception = new Exception("This is a message.");
|
||||
|
||||
// act
|
||||
string message = exception.GetMessage();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(exception.Message, message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnInnerExceptionMessage()
|
||||
{
|
||||
// arrange
|
||||
var innerException = new Exception("Message from the inner side.");
|
||||
var outerException = new Exception("Message from the outer side.", innerException);
|
||||
|
||||
// act
|
||||
string message = outerException.GetMessage();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(innerException.Message, message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnRecursiveExceptionMessageFoInnerException()
|
||||
{
|
||||
// arrange
|
||||
var innerException = new Exception("Message from the inner side.");
|
||||
var outerException = new Exception("Message from the outer side. See the inner exception for details.", innerException);
|
||||
string expectedMessage = $"Message from the outer side. Message from the inner side.";
|
||||
|
||||
// act
|
||||
string message = outerException.GetRecursiveMessage();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(expectedMessage, message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnRecursiveExceptionMessageFoInnerExceptions()
|
||||
{
|
||||
// arrange
|
||||
var innerExceptions = new List<Exception>
|
||||
{
|
||||
new Exception("Inner Exception 1."),
|
||||
new Exception("Inner Exception 2. See the inner exception for details.", new Exception("Inner Exception of Exception 2.")),
|
||||
new Exception("Inner Exception 3."),
|
||||
new Exception("Inner Exception 4."),
|
||||
new Exception("Inner Exception 5.")
|
||||
};
|
||||
var aggregateException = new AggregateException("Lots of exceptions.", innerExceptions);
|
||||
string expectedMessage = "Inner Exception 1. Inner Exception 2. Inner Exception of Exception 2. Inner Exception 3.";
|
||||
|
||||
// act
|
||||
string message = aggregateException.GetRecursiveMessage();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(expectedMessage, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
341
UnitTests/Common/Extensions/JsonExtensionsTests.cs
Normal file
341
UnitTests/Common/Extensions/JsonExtensionsTests.cs
Normal file
@@ -0,0 +1,341 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnitTests.Common.Utils;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class JsonExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnJson()
|
||||
{
|
||||
// arrange
|
||||
var testObject = new JsonTestClass();
|
||||
string expected = @"{""stringValue"":""Hello World!"",""isBoolTrue"":true,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":42.21,""localTimestamp"":""2021-11-16T20:15:34+01:00"",""utcTimestamp"":""2021-11-16T20:15:34Z"",""object"":{""integerValue"":42,""stringValue"":""Foo-Bar""}}";
|
||||
|
||||
// act
|
||||
string json = testObject.SerializeJson();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(json));
|
||||
Assert.AreEqual(expected, json);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnJsonIndented()
|
||||
{
|
||||
// arrange
|
||||
var testObject = new JsonTestClass();
|
||||
string expected = @"{
|
||||
""stringValue"": ""Hello World!"",
|
||||
""isBoolTrue"": true,
|
||||
""floatValue"": 12.34,
|
||||
""doubleValue"": 21.42,
|
||||
""decimalValue"": 42.21,
|
||||
""localTimestamp"": ""2021-11-16T20:15:34+01:00"",
|
||||
""utcTimestamp"": ""2021-11-16T20:15:34Z"",
|
||||
""object"": {
|
||||
""integerValue"": 42,
|
||||
""stringValue"": ""Foo-Bar""
|
||||
}
|
||||
}";
|
||||
|
||||
// act
|
||||
string json = testObject.SerializeJson(indented: true);
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(json));
|
||||
Assert.AreEqual(expected.Replace("\r", ""), json.Replace("\r", ""));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnJsonWithSingleQuotes()
|
||||
{
|
||||
// arrange
|
||||
var testObject = new JsonTestClass
|
||||
{
|
||||
StringValue = "Sam's Pub"
|
||||
};
|
||||
string expected = "{'stringValue':'Sam\\'s Pub','isBoolTrue':true,'floatValue':12.34,'doubleValue':21.42,'decimalValue':42.21,'localTimestamp':'2021-11-16T20:15:34+01:00','utcTimestamp':'2021-11-16T20:15:34Z','object':{'integerValue':42,'stringValue':'Foo-Bar'}}";
|
||||
|
||||
// act
|
||||
string json = testObject.SerializeJson(useSingleQuotes: true);
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(json));
|
||||
Assert.AreEqual(expected, json);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnJsonWithoutCamelCase()
|
||||
{
|
||||
// arrange
|
||||
var testObject = new JsonTestClass();
|
||||
string expected = @"{""StringValue"":""Hello World!"",""IsBoolTrue"":true,""FloatValue"":12.34,""DoubleValue"":21.42,""DecimalValue"":42.21,""LocalTimestamp"":""2021-11-16T20:15:34+01:00"",""UtcTimestamp"":""2021-11-16T20:15:34Z"",""Object"":{""IntegerValue"":42,""StringValue"":""Foo-Bar""}}";
|
||||
|
||||
// act
|
||||
string json = testObject.SerializeJson(useCamelCase: false);
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(json));
|
||||
Assert.AreEqual(expected, json);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnJsonWithType()
|
||||
{
|
||||
// arrange
|
||||
var testObject = new JsonTestClass();
|
||||
string expected = @"{""$type"":""UnitTests.Common.Utils.JsonTestClass, UnitTests"",""stringValue"":""Hello World!"",""isBoolTrue"":true,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":42.21,""localTimestamp"":""2021-11-16T20:15:34+01:00"",""utcTimestamp"":""2021-11-16T20:15:34Z"",""object"":{""$type"":""UnitTests.Common.Utils.JsonTestSubClass, UnitTests"",""integerValue"":42,""stringValue"":""Foo-Bar""}}";
|
||||
|
||||
// act
|
||||
string json = testObject.SerializeJson(includeType: true);
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(json));
|
||||
Assert.AreEqual(expected, json);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDeserializeWithoutFallback()
|
||||
{
|
||||
// arrange
|
||||
string workingJson = @"{""stringValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21,""stringValue"":""FooBar""}}";
|
||||
string brokenJson = @"{""strValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21.12,""stringValue"":""FooBar""}}";
|
||||
string emptyString = "";
|
||||
|
||||
// act
|
||||
var workingObj = workingJson.DeserializeJson<JsonTestClass>();
|
||||
var emptyObj = emptyString.DeserializeJson<JsonTestClass>();
|
||||
|
||||
try
|
||||
{
|
||||
var brokenObj = brokenJson.DeserializeJson<JsonTestClass>();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (JsonReaderException)
|
||||
{ }
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(workingObj);
|
||||
Assert.IsNull(emptyObj);
|
||||
|
||||
Assert.AreEqual("Some fancy string", workingObj.StringValue);
|
||||
Assert.IsFalse(workingObj.IsBoolTrue);
|
||||
Assert.AreEqual(123.45m, workingObj.DecimalValue);
|
||||
Assert.AreEqual(DateTimeKind.Local, workingObj.LocalTimestamp.Kind);
|
||||
Assert.AreEqual("15.11.2021 20:15:34", workingObj.LocalTimestamp.ToString("dd.MM.yyyy HH:mm:ss"));
|
||||
Assert.AreEqual(DateTimeKind.Utc, workingObj.UtcTimestamp.Kind);
|
||||
Assert.AreEqual("16.10.2021 20:15:34", workingObj.UtcTimestamp.ToString("dd.MM.yyyy HH:mm:ss"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDeserializeWithFallback()
|
||||
{
|
||||
// arrange
|
||||
string workingJson = @"{""stringValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21,""stringValue"":""FooBar""}}";
|
||||
string brokenJson = @"{""strValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21.12,""stringValue"":""FooBar""}}";
|
||||
string emptyString = "";
|
||||
var fallback = new JsonTestClass
|
||||
{
|
||||
DoubleValue = 0.815
|
||||
};
|
||||
|
||||
// act
|
||||
var workingObj = workingJson.DeserializeJson(fallback);
|
||||
var brokenObj = brokenJson.DeserializeJson(fallback);
|
||||
var emptyObj = emptyString.DeserializeJson(fallback);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(workingObj);
|
||||
Assert.IsNotNull(brokenObj);
|
||||
Assert.IsNull(emptyObj);
|
||||
|
||||
Assert.AreEqual("Some fancy string", workingObj.StringValue);
|
||||
Assert.IsFalse(workingObj.IsBoolTrue);
|
||||
Assert.AreEqual(123.45m, workingObj.DecimalValue);
|
||||
Assert.AreEqual(21.42, workingObj.DoubleValue);
|
||||
Assert.AreEqual(DateTimeKind.Local, workingObj.LocalTimestamp.Kind);
|
||||
Assert.AreEqual("15.11.2021 20:15:34", workingObj.LocalTimestamp.ToString("dd.MM.yyyy HH:mm:ss"));
|
||||
Assert.AreEqual(DateTimeKind.Utc, workingObj.UtcTimestamp.Kind);
|
||||
Assert.AreEqual("16.10.2021 20:15:34", workingObj.UtcTimestamp.ToString("dd.MM.yyyy HH:mm:ss"));
|
||||
|
||||
Assert.AreEqual(fallback.StringValue, brokenObj.StringValue);
|
||||
Assert.AreEqual(fallback.IsBoolTrue, brokenObj.IsBoolTrue);
|
||||
Assert.AreEqual(fallback.DecimalValue, brokenObj.DecimalValue);
|
||||
Assert.AreEqual(fallback.DoubleValue, brokenObj.DoubleValue);
|
||||
Assert.AreEqual(fallback.LocalTimestamp.Kind, brokenObj.LocalTimestamp.Kind);
|
||||
Assert.AreEqual(fallback.LocalTimestamp, brokenObj.LocalTimestamp);
|
||||
Assert.AreEqual(fallback.UtcTimestamp.Kind, brokenObj.UtcTimestamp.Kind);
|
||||
Assert.AreEqual(fallback.UtcTimestamp, brokenObj.UtcTimestamp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDeserializeUsingPopulate()
|
||||
{
|
||||
// arrange
|
||||
string json = @"{""stringValue"":""Some fancy string"",""isBoolTrue"":false,""floatValue"":12.34,""doubleValue"":21.42,""decimalValue"":123.45,""localTimestamp"":""2021-11-15T20:15:34+01:00"",""utcTimestamp"":""2021-10-16T20:15:34Z"",""object"":{""integerValue"":21,""stringValue"":""FooBar""}}";
|
||||
var obj = new JsonTestClass();
|
||||
|
||||
// act
|
||||
obj.DeserializeJson(json);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Some fancy string", obj.StringValue);
|
||||
Assert.IsFalse(obj.IsBoolTrue);
|
||||
Assert.AreEqual(123.45m, obj.DecimalValue);
|
||||
Assert.AreEqual(21.42, obj.DoubleValue);
|
||||
Assert.AreEqual(DateTimeKind.Local, obj.LocalTimestamp.Kind);
|
||||
Assert.AreEqual("15.11.2021 20:15:34", obj.LocalTimestamp.ToString("dd.MM.yyyy HH:mm:ss"));
|
||||
Assert.AreEqual(DateTimeKind.Utc, obj.UtcTimestamp.Kind);
|
||||
Assert.AreEqual("16.10.2021 20:15:34", obj.UtcTimestamp.ToString("dd.MM.yyyy HH:mm:ss"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldConvertToJObject()
|
||||
{
|
||||
// arrange
|
||||
var obj = new JsonTestClass
|
||||
{
|
||||
StringValue = "Hello JSON",
|
||||
DecimalValue = 0.815m
|
||||
};
|
||||
|
||||
// act
|
||||
var jObj = obj.ConvertToJObject();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(jObj);
|
||||
Assert.AreEqual(typeof(JObject), jObj.GetType());
|
||||
Assert.AreEqual(obj.StringValue, jObj.Value<string>("stringValue"));
|
||||
Assert.AreEqual(obj.DecimalValue, jObj.Value<decimal>("decimalValue"));
|
||||
Assert.AreEqual(obj.LocalTimestamp.Kind, jObj.Value<DateTime>("localTimestamp").Kind);
|
||||
Assert.AreEqual(obj.LocalTimestamp, jObj.Value<DateTime>("localTimestamp"));
|
||||
Assert.AreEqual(obj.UtcTimestamp.Kind, jObj.Value<DateTime>("utcTimestamp").Kind);
|
||||
Assert.AreEqual(obj.UtcTimestamp, jObj.Value<DateTime>("utcTimestamp"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldConvertToJArray()
|
||||
{
|
||||
// arrange
|
||||
string[] stringArray = new[] { "one", "two", "three" };
|
||||
var objectArray = new[]
|
||||
{
|
||||
new JsonTestClass { StringValue = "One" },
|
||||
new JsonTestClass { StringValue = "Two" },
|
||||
new JsonTestClass { StringValue = "Three" }
|
||||
};
|
||||
|
||||
// act
|
||||
var stringJArray = stringArray.ConvertToJArray();
|
||||
var objectJArray = objectArray.ConvertToJArray();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(stringJArray);
|
||||
Assert.AreEqual(typeof(JArray), stringJArray.GetType());
|
||||
Assert.AreEqual(stringArray[0], stringJArray[0]);
|
||||
Assert.AreEqual(stringArray[1], stringJArray[1]);
|
||||
Assert.AreEqual(stringArray[2], stringJArray[2]);
|
||||
|
||||
Assert.IsNotNull(objectJArray);
|
||||
Assert.AreEqual(typeof(JArray), objectJArray.GetType());
|
||||
Assert.AreEqual(objectArray[0].StringValue, objectJArray[0].Value<string>("stringValue"));
|
||||
Assert.AreEqual(objectArray[1].StringValue, objectJArray[1].Value<string>("stringValue"));
|
||||
Assert.AreEqual(objectArray[2].StringValue, objectJArray[2].Value<string>("stringValue"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRunJsonTreeWithoutDefault()
|
||||
{
|
||||
// arrange
|
||||
var obj = new JsonTestClass { StringValue = "Running Json", Object = new JsonTestSubClass { IntegerValue = 4711 } };
|
||||
var jObj = obj.ConvertToJObject();
|
||||
|
||||
// act
|
||||
string topLevelString = jObj.GetValue<string>("stringValue");
|
||||
decimal topLevelDecimal = jObj.GetValue<decimal>("decimalValue");
|
||||
int subLevelInteger = jObj.GetValue<int>("object:integerValue");
|
||||
string subLevelString = jObj.GetValue<string>("object:stringValue");
|
||||
|
||||
string notExistingOnTopLevel = jObj.GetValue<string>("fancyValue");
|
||||
string notExistingOnSubLevel = jObj.GetValue<string>("object:fancyValue");
|
||||
int? notExistingLevel = jObj.GetValue<int?>("fancy:int");
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(obj.StringValue, topLevelString);
|
||||
Assert.AreEqual(obj.DecimalValue, topLevelDecimal);
|
||||
Assert.AreEqual(obj.Object.IntegerValue, subLevelInteger);
|
||||
Assert.AreEqual(obj.Object.StringValue, subLevelString);
|
||||
|
||||
Assert.IsNull(notExistingOnTopLevel);
|
||||
Assert.IsNull(notExistingOnSubLevel);
|
||||
Assert.IsNull(notExistingLevel);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRunJsonTreeWithDefault()
|
||||
{
|
||||
// arrange
|
||||
var obj = new JsonTestClass { StringValue = "Running Json", Object = new JsonTestSubClass { IntegerValue = 4711 } };
|
||||
var jObj = obj.ConvertToJObject();
|
||||
|
||||
// act
|
||||
string topLevelString = jObj.GetValue("stringValue", "Test String");
|
||||
decimal topLevelDecimal = jObj.GetValue("decimalValue", 13.24m);
|
||||
int subLevelInteger = jObj.GetValue("object:integerValue", 55);
|
||||
string subLevelString = jObj.GetValue("object:stringValue", "Yeah!");
|
||||
|
||||
string notExistingOnTopLevel = jObj.GetValue("fancyValue", "Party!");
|
||||
string notExistingOnSubLevel = jObj.GetValue("object:fancyValue", "Well Done");
|
||||
int? notExistingLevel = jObj.GetValue<int?>("fancy:int", 13);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(obj.StringValue, topLevelString);
|
||||
Assert.AreEqual(obj.DecimalValue, topLevelDecimal);
|
||||
Assert.AreEqual(obj.Object.IntegerValue, subLevelInteger);
|
||||
Assert.AreEqual(obj.Object.StringValue, subLevelString);
|
||||
|
||||
Assert.AreEqual("Party!", notExistingOnTopLevel);
|
||||
Assert.AreEqual("Well Done", notExistingOnSubLevel);
|
||||
Assert.AreEqual(13, notExistingLevel);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnNull()
|
||||
{
|
||||
// arrange
|
||||
object obj = null;
|
||||
IEnumerable list = null;
|
||||
JObject jObj = null;
|
||||
|
||||
// act
|
||||
var objTest = obj.ConvertToJObject();
|
||||
var listTest = list.ConvertToJArray();
|
||||
object getTest = jObj.GetValue<object>("Nothing");
|
||||
|
||||
// assert
|
||||
Assert.IsNull(objTest);
|
||||
Assert.IsNull(listTest);
|
||||
Assert.IsNull(getTest);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldHandleSerializationError()
|
||||
{
|
||||
// arrange
|
||||
var obj = new JsonErrorClass();
|
||||
|
||||
// act
|
||||
string json = obj.SerializeJson();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("{}", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class ReaderWriterLockSlimExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldEnterReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
|
||||
// act
|
||||
using var disposable = rwLock.GetReadLock();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(disposable);
|
||||
Assert.IsTrue(rwLock.IsReadLockHeld);
|
||||
Assert.IsFalse(rwLock.IsUpgradeableReadLockHeld);
|
||||
Assert.IsFalse(rwLock.IsWriteLockHeld);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEnterUpgradeableReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
|
||||
// act
|
||||
using var disposable = rwLock.GetUpgradeableReadLock();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(disposable);
|
||||
Assert.IsFalse(rwLock.IsReadLockHeld);
|
||||
Assert.IsTrue(rwLock.IsUpgradeableReadLockHeld);
|
||||
Assert.IsFalse(rwLock.IsWriteLockHeld);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldAllowWriteLockAfterUpgradableReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLockUsing = new ReaderWriterLockSlim();
|
||||
var rwLockClassic = new ReaderWriterLockSlim();
|
||||
|
||||
// act
|
||||
using var disposableReadUsing = rwLockUsing.GetUpgradeableReadLock();
|
||||
using (rwLockUsing.GetWriteLock())
|
||||
{
|
||||
// assert
|
||||
Assert.IsTrue(rwLockUsing.IsUpgradeableReadLockHeld);
|
||||
Assert.IsTrue(rwLockUsing.IsWriteLockHeld);
|
||||
}
|
||||
// assert
|
||||
Assert.IsTrue(rwLockUsing.IsUpgradeableReadLockHeld);
|
||||
Assert.IsFalse(rwLockUsing.IsWriteLockHeld);
|
||||
|
||||
// act
|
||||
using (rwLockClassic.GetUpgradeableReadLock())
|
||||
{
|
||||
rwLockClassic.EnterWriteLock();
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(rwLockClassic.IsUpgradeableReadLockHeld);
|
||||
Assert.IsTrue(rwLockClassic.IsWriteLockHeld);
|
||||
}
|
||||
// assert
|
||||
Assert.IsFalse(rwLockClassic.IsUpgradeableReadLockHeld);
|
||||
Assert.IsFalse(rwLockClassic.IsWriteLockHeld);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEnterWriteLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
|
||||
// act
|
||||
using var disposable = rwLock.GetWriteLock();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(disposable);
|
||||
Assert.IsFalse(rwLock.IsReadLockHeld);
|
||||
Assert.IsFalse(rwLock.IsUpgradeableReadLockHeld);
|
||||
Assert.IsTrue(rwLock.IsWriteLockHeld);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldNotAllowWriteLockAfterReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
|
||||
// act
|
||||
using var disposableRead = rwLock.GetReadLock();
|
||||
try
|
||||
{
|
||||
using var disposaleWrite = rwLock.GetWriteLock();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (LockRecursionException)
|
||||
{ }
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(disposableRead);
|
||||
Assert.IsTrue(rwLock.IsReadLockHeld);
|
||||
Assert.IsFalse(rwLock.IsUpgradeableReadLockHeld);
|
||||
Assert.IsFalse(rwLock.IsWriteLockHeld);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldAllowWriteLockAfterUpgradeableReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
|
||||
// act
|
||||
using var disposableRead = rwLock.GetUpgradeableReadLock();
|
||||
using var disposableWrite = rwLock.GetWriteLock();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(disposableRead);
|
||||
Assert.IsNotNull(disposableWrite);
|
||||
Assert.IsFalse(rwLock.IsReadLockHeld);
|
||||
Assert.IsTrue(rwLock.IsUpgradeableReadLockHeld);
|
||||
Assert.IsTrue(rwLock.IsWriteLockHeld);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldGetTimeoutOnReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
bool isTimeout = false;
|
||||
|
||||
// act
|
||||
using var disposableRead = rwLock.GetWriteLock();
|
||||
var awaitableTask = Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var disposableRead = rwLock.GetReadLock(10);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
isTimeout = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{ /* keep it quiet */ }
|
||||
});
|
||||
Task.WaitAll(awaitableTask);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(isTimeout);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldGetTimeoutOnUpgradeableReadLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
bool isTimeout = false;
|
||||
|
||||
// act
|
||||
using var disposableRead = rwLock.GetWriteLock();
|
||||
var awaitableTask = Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var disposableRead = rwLock.GetUpgradeableReadLock(10);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
isTimeout = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{ /* keep it quiet */ }
|
||||
});
|
||||
Task.WaitAll(awaitableTask);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(isTimeout);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldGetTimeoutOnWriteLock()
|
||||
{
|
||||
// arrange
|
||||
var rwLock = new ReaderWriterLockSlim();
|
||||
bool isTimeout = false;
|
||||
|
||||
// act
|
||||
using var disposableRead = rwLock.GetReadLock();
|
||||
var awaitableTask = Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using var disposableRead = rwLock.GetWriteLock(10);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
isTimeout = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{ /* keep it quiet */ }
|
||||
});
|
||||
Task.WaitAll(awaitableTask);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(isTimeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
139
UnitTests/Common/Extensions/StreamExtensionsTests.cs
Normal file
139
UnitTests/Common/Extensions/StreamExtensionsTests.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class StreamExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReadLineFromStreamSynchronous()
|
||||
{
|
||||
// arrange
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("First Line");
|
||||
sb.AppendLine("Second Line");
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(sb.ToString().Trim());
|
||||
var stream = new MemoryStream(buffer);
|
||||
|
||||
// act
|
||||
string line = stream.ReadLine();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("First Line", line);
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReadUntilEndAsLineSynchronous()
|
||||
{
|
||||
// arrange
|
||||
byte[] buffer = Encoding.UTF8.GetBytes("Single Line");
|
||||
var stream = new MemoryStream(buffer);
|
||||
|
||||
// act
|
||||
string line = stream.ReadLine();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Single Line", line);
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnNullWhenNotReadableSynchronous()
|
||||
{
|
||||
// arrange
|
||||
var stream = new WriteOnlyStream();
|
||||
|
||||
// act
|
||||
string line = stream.ReadLine();
|
||||
|
||||
// assert
|
||||
Assert.IsNull(line);
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldReadLineFromStreamAsynchronous()
|
||||
{
|
||||
// arrange
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("First Line");
|
||||
sb.AppendLine("Second Line");
|
||||
byte[] buffer = Encoding.UTF8.GetBytes(sb.ToString().Trim());
|
||||
var stream = new MemoryStream(buffer);
|
||||
|
||||
// act
|
||||
string line = await stream.ReadLineAsync();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("First Line", line);
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldReadUntilEndAsLineAsynchronous()
|
||||
{
|
||||
// arrange
|
||||
byte[] buffer = Encoding.UTF8.GetBytes("Single Line");
|
||||
var stream = new MemoryStream(buffer);
|
||||
|
||||
// act
|
||||
string line = await stream.ReadLineAsync();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Single Line", line);
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldReturnNullWhenNotReadableAsynchronous()
|
||||
{
|
||||
// arrange
|
||||
var stream = new WriteOnlyStream();
|
||||
|
||||
// act
|
||||
string line = await stream.ReadLineAsync();
|
||||
|
||||
// assert
|
||||
Assert.IsNull(line);
|
||||
|
||||
stream.Dispose();
|
||||
}
|
||||
|
||||
private class WriteOnlyStream : Stream
|
||||
{
|
||||
public override bool CanRead => false;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override long Length => 0;
|
||||
|
||||
public override long Position { get => 0; set => throw new NotImplementedException(); }
|
||||
|
||||
public override void Flush()
|
||||
{ }
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) => 0;
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin) => 0;
|
||||
|
||||
public override void SetLength(long value)
|
||||
{ }
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
353
UnitTests/Common/Extensions/StringExtensionsTests.cs
Normal file
353
UnitTests/Common/Extensions/StringExtensionsTests.cs
Normal file
@@ -0,0 +1,353 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Extensions
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class StringExtensionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyList()
|
||||
{
|
||||
// arrange
|
||||
string hex = "";
|
||||
|
||||
// act
|
||||
var bytes = hex.HexToBytes();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(bytes);
|
||||
Assert.IsFalse(bytes.Any());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyListWhenInvalid()
|
||||
{
|
||||
// arrange
|
||||
string hex1 = "aff";
|
||||
string hex2 = "de:ad:be:e";
|
||||
string hex3 = "hell";
|
||||
|
||||
// act
|
||||
var bytes1 = hex1.HexToBytes();
|
||||
var bytes2 = hex2.HexToBytes(":");
|
||||
var bytes3 = hex3.HexToBytes();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(bytes1);
|
||||
Assert.IsFalse(bytes1.Any());
|
||||
|
||||
Assert.IsNotNull(bytes2);
|
||||
Assert.IsFalse(bytes2.Any());
|
||||
|
||||
Assert.IsNotNull(bytes3);
|
||||
Assert.IsFalse(bytes3.Any());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldConvertHexToBytes()
|
||||
{
|
||||
// arrange
|
||||
string hex = "deadbeef";
|
||||
|
||||
// act
|
||||
var bytes = hex.HexToBytes();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(bytes);
|
||||
Assert.AreEqual(4, bytes.Count());
|
||||
Assert.AreEqual(0xde, bytes.ElementAt(0));
|
||||
Assert.AreEqual(0xad, bytes.ElementAt(1));
|
||||
Assert.AreEqual(0xbe, bytes.ElementAt(2));
|
||||
Assert.AreEqual(0xef, bytes.ElementAt(3));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldConvertHexToBytesWithDelimiter()
|
||||
{
|
||||
// arrange
|
||||
string hex = "af:fe";
|
||||
|
||||
// act
|
||||
var bytes = hex.HexToBytes(":");
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(bytes);
|
||||
Assert.AreEqual(2, bytes.Count());
|
||||
Assert.AreEqual(0xaf, bytes.ElementAt(0));
|
||||
Assert.AreEqual(0xfe, bytes.ElementAt(1));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnNullWhenInvalid()
|
||||
{
|
||||
// arrange
|
||||
byte[] bytes1 = null;
|
||||
byte[] bytes2 = Array.Empty<byte>();
|
||||
|
||||
// act
|
||||
string hex1 = bytes1.BytesToHex();
|
||||
string hex2 = bytes2.BytesToHex();
|
||||
|
||||
// assert
|
||||
Assert.IsNull(hex1);
|
||||
Assert.IsNull(hex2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnHexString()
|
||||
{
|
||||
// arrange
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
string hex = bytes.BytesToHex();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(hex);
|
||||
Assert.AreEqual("affe", hex);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnHexStringWithDelimiter()
|
||||
{
|
||||
// arrange
|
||||
byte[] bytes = new byte[] { 0xde, 0xad, 0xbe, 0xef };
|
||||
|
||||
// act
|
||||
string hex = bytes.BytesToHex("_");
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(hex);
|
||||
Assert.AreEqual("de_ad_be_ef", hex);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncodeStringToHex()
|
||||
{
|
||||
// arrange
|
||||
string plain = "Hello";
|
||||
|
||||
// act
|
||||
string hex1 = plain.HexEncode();
|
||||
string hex2 = plain.HexEncode(Encoding.Default);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("48656c6c6f", hex1);
|
||||
Assert.AreEqual("48656c6c6f", hex2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDecodeStringFromHex()
|
||||
{
|
||||
// arrange
|
||||
string hex = "48656c6c6f";
|
||||
|
||||
// act
|
||||
string plain1 = hex.HexDecode();
|
||||
string plain2 = hex.HexDecode(Encoding.Default);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Hello", plain1);
|
||||
Assert.AreEqual("Hello", plain2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncodeStringToBase64()
|
||||
{
|
||||
// arrange
|
||||
string plain = "Hello";
|
||||
|
||||
// act
|
||||
string base641 = plain.Base64Encode();
|
||||
string base642 = plain.Base64Encode(Encoding.Default);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("SGVsbG8=", base641);
|
||||
Assert.AreEqual("SGVsbG8=", base642);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDecodeStringFromBase64()
|
||||
{
|
||||
// arrange
|
||||
string base64 = "SGVsbG8=";
|
||||
|
||||
// act
|
||||
string plain1 = base64.Base64Decode();
|
||||
string plain2 = base64.Base64Decode(Encoding.Default);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("Hello", plain1);
|
||||
Assert.AreEqual("Hello", plain2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReplaceStart()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
|
||||
// act
|
||||
string test1 = str.ReplaceStart("Hello", "Bye");
|
||||
string test2 = str.ReplaceStart("World!", "Mars?");
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(str, test1);
|
||||
Assert.AreEqual("Bye World!", test1);
|
||||
|
||||
Assert.AreEqual(str, test2);
|
||||
Assert.AreNotEqual("Hello Mars?", test2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReplaceEnd()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
|
||||
// act
|
||||
string test1 = str.ReplaceEnd("Hello", "Bye");
|
||||
string test2 = str.ReplaceEnd("World!", "Mars?");
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(str, test1);
|
||||
Assert.AreNotEqual("Bye World!", test1);
|
||||
|
||||
Assert.AreNotEqual(str, test2);
|
||||
Assert.AreEqual("Hello Mars?", test2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldParseDecimal()
|
||||
{
|
||||
// arrange
|
||||
decimal number = 1234.56m;
|
||||
string stringNumberEn = "1234.56";
|
||||
string stringNumberDe = "1234,56";
|
||||
|
||||
// act
|
||||
decimal numberEn = stringNumberEn.ParseDecimal();
|
||||
decimal numberDe = stringNumberDe.ParseDecimal();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(number, numberEn);
|
||||
Assert.AreEqual(number, numberDe);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldParseDecimalWithThousandsSeparator()
|
||||
{
|
||||
// arrange
|
||||
decimal number = 1234.56m;
|
||||
string stringNumberEn = "1,234.56";
|
||||
string stringNumberDe = "1.234,56";
|
||||
|
||||
// act
|
||||
decimal numberEn = stringNumberEn.ParseDecimal();
|
||||
decimal numberDe = stringNumberDe.ParseDecimal();
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(number, numberEn);
|
||||
Assert.AreEqual(number, numberDe);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldValidateEmailAddressWithoutRecordCheck()
|
||||
{
|
||||
// arrange
|
||||
string validEmailWithoutTag = "test@gmail.com";
|
||||
string validEmailWithTag = "test+tag@not.exists";
|
||||
string invalidEmailWithoutTag = "<Test Account> test@gmail.com";
|
||||
string invalidEmailWithTag = "<Test Account> test+tag@not.exists";
|
||||
string nullStr = null;
|
||||
|
||||
// act
|
||||
bool validWithoutTag = validEmailWithoutTag.IsValidEmailAddress(checkRecordExists: false);
|
||||
bool validWithTag = validEmailWithTag.IsValidEmailAddress(checkRecordExists: false);
|
||||
bool invalidWithoutTag = !invalidEmailWithoutTag.IsValidEmailAddress(checkRecordExists: false);
|
||||
bool invalidWithTag = !invalidEmailWithTag.IsValidEmailAddress(checkRecordExists: false);
|
||||
bool nullTest = nullStr.IsValidEmailAddress(checkRecordExists: false);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(validWithoutTag);
|
||||
Assert.IsTrue(validWithTag);
|
||||
Assert.IsTrue(invalidWithoutTag);
|
||||
Assert.IsTrue(invalidWithTag);
|
||||
Assert.IsFalse(nullTest);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldValidateEmailAddressWithRecordCheck()
|
||||
{
|
||||
// arrange
|
||||
string validEmail = "test@gmail.com";
|
||||
string invalidEmail = "test@not.exists";
|
||||
|
||||
// act
|
||||
bool valid = validEmail.IsValidEmailAddress(checkRecordExists: true);
|
||||
bool invalid = !invalidEmail.IsValidEmailAddress(checkRecordExists: true);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(valid);
|
||||
Assert.IsTrue(invalid);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldValidateEmailAddressWithRecordCheckDefinedNameservers()
|
||||
{
|
||||
// arrange
|
||||
string validEmail = "test@gmail.com";
|
||||
string invalidEmail = "test@not.exists";
|
||||
var nameserver = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 53);
|
||||
|
||||
// act
|
||||
bool valid = validEmail.IsValidEmailAddress(new[] { nameserver });
|
||||
bool invalid = !invalidEmail.IsValidEmailAddress(new[] { nameserver });
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(valid);
|
||||
Assert.IsTrue(invalid);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldWorkWithNullOrEmptyString()
|
||||
{
|
||||
// arrange
|
||||
string nullStr = null;
|
||||
string emptyStr = "";
|
||||
|
||||
// act
|
||||
string hexEncodeNull = nullStr.HexEncode();
|
||||
string hexEncodeEmpty = emptyStr.HexEncode();
|
||||
string hexDecodeNull = nullStr.HexDecode();
|
||||
string hexDecodeEmpty = emptyStr.HexDecode();
|
||||
|
||||
// assert
|
||||
Assert.IsNull(hexEncodeNull);
|
||||
Assert.AreEqual("", hexEncodeEmpty);
|
||||
Assert.IsNull(hexDecodeNull);
|
||||
Assert.AreEqual("", hexDecodeEmpty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldAddCustomLineTermination()
|
||||
{
|
||||
// arrange
|
||||
string value = "abc";
|
||||
var sb = new StringBuilder();
|
||||
|
||||
// act
|
||||
sb.AppendLine(value, "\r");
|
||||
sb.AppendLine(value, "\r");
|
||||
|
||||
// assert
|
||||
Assert.AreEqual($"{value}\r{value}\r", sb.ToString());
|
||||
Assert.IsFalse(sb.ToString().Contains('\n'));
|
||||
}
|
||||
}
|
||||
}
|
||||
635
UnitTests/Common/Utilities/CryptographyHelperTests.cs
Normal file
635
UnitTests/Common/Utilities/CryptographyHelperTests.cs
Normal file
@@ -0,0 +1,635 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnitTests.Common.Utils;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Utilities
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class CryptographyHelperTests
|
||||
{
|
||||
private string keyFile;
|
||||
private CryptographyHelper cryptoHelper;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
keyFile = Path.GetTempFileName();
|
||||
cryptoHelper = new CryptographyHelper(keyFile);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
File.Delete(keyFile);
|
||||
}
|
||||
|
||||
#region Static
|
||||
|
||||
#region Encryption
|
||||
|
||||
#region AES
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptAesWithoutSalt() // required to test the encryption itself
|
||||
{
|
||||
// arrange
|
||||
using var _ = CryptographyHelperSaltMock.Create(0);
|
||||
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
string str = "ABC";
|
||||
string password1 = "P@ssw0rd!";
|
||||
string password2 = "P@ssw0rd";
|
||||
|
||||
byte[] expectedBytes = new byte[] { 0x7c, 0x7b, 0x77, 0x56, 0x91, 0x1a, 0xd9, 0xc0, 0x72, 0x70, 0x36, 0x88, 0x9f, 0xb4, 0xb5, 0xbc };
|
||||
|
||||
// act
|
||||
byte[] cipherBytes1 = CryptographyHelper.AesEncrypt(bytes, password1);
|
||||
string cipherStr1 = CryptographyHelper.AesEncrypt(str, password1);
|
||||
byte[] cipherBytes2 = CryptographyHelper.AesEncrypt(bytes, password2);
|
||||
string cipherStr2 = CryptographyHelper.AesEncrypt(str, password2);
|
||||
|
||||
// assert
|
||||
CollectionAssert.AreEqual(expectedBytes, cipherBytes1);
|
||||
Assert.AreEqual("ueLuhFNpCuYmx8v3hczHtg==", cipherStr1);
|
||||
|
||||
CollectionAssert.AreNotEqual(expectedBytes, cipherBytes2);
|
||||
Assert.AreNotEqual("ueLuhFNpCuYmx8v3hczHtg==", cipherStr2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDecryptAesWithoutSalt() // required to test the decryption itself
|
||||
{
|
||||
// arrange
|
||||
using var _ = CryptographyHelperSaltMock.Create(0);
|
||||
|
||||
string cipherStr = "ueLuhFNpCuYmx8v3hczHtg==";
|
||||
byte[] cipherBytes = new byte[] { 0x7c, 0x7b, 0x77, 0x56, 0x91, 0x1a, 0xd9, 0xc0, 0x72, 0x70, 0x36, 0x88, 0x9f, 0xb4, 0xb5, 0xbc };
|
||||
|
||||
string password1 = "P@ssw0rd!";
|
||||
string password2 = "P@ssw0rd";
|
||||
|
||||
byte[] expectedBytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
byte[] plainBytes1 = CryptographyHelper.AesDecrypt(cipherBytes, password1);
|
||||
string plainStr1 = CryptographyHelper.AesDecrypt(cipherStr, password1);
|
||||
|
||||
try
|
||||
{
|
||||
CryptographyHelper.AesDecrypt(cipherBytes, password2);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
CryptographyHelper.AesDecrypt(cipherStr, password2);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{ }
|
||||
|
||||
// assert
|
||||
CollectionAssert.AreEqual(expectedBytes, plainBytes1);
|
||||
Assert.AreEqual("ABC", plainStr1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptDecryptAesBytes()
|
||||
{
|
||||
// arrange
|
||||
byte[] plain = new byte[] { 0xaf, 0xfe };
|
||||
string password = "P@ssw0rd!";
|
||||
|
||||
// act
|
||||
byte[] cipher1 = CryptographyHelper.AesEncrypt(plain, password);
|
||||
byte[] cipher2 = CryptographyHelper.AesEncrypt(plain, password);
|
||||
|
||||
byte[] plain1 = CryptographyHelper.AesDecrypt(cipher1, password);
|
||||
byte[] plain2 = CryptographyHelper.AesDecrypt(cipher2, password);
|
||||
|
||||
// assert
|
||||
CollectionAssert.AreNotEqual(cipher1, cipher2);
|
||||
Assert.AreEqual(24, cipher1.Length);
|
||||
Assert.AreEqual(24, cipher2.Length);
|
||||
CollectionAssert.AreEqual(plain, plain1);
|
||||
CollectionAssert.AreEqual(plain, plain2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptDecryptAesString()
|
||||
{
|
||||
// arrange
|
||||
string plain = "ABC";
|
||||
string password = "P@ssw0rd!";
|
||||
|
||||
// act
|
||||
string cipher1 = CryptographyHelper.AesEncrypt(plain, password);
|
||||
string cipher2 = CryptographyHelper.AesEncrypt(plain, password);
|
||||
|
||||
string plain1 = CryptographyHelper.AesDecrypt(cipher1, password);
|
||||
string plain2 = CryptographyHelper.AesDecrypt(cipher2, password);
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(cipher1, cipher2);
|
||||
Assert.AreEqual(32, cipher1.Length);
|
||||
Assert.AreEqual(32, cipher2.Length);
|
||||
Assert.AreEqual(plain, plain1);
|
||||
Assert.AreEqual(plain, plain2);
|
||||
}
|
||||
|
||||
#endregion AES
|
||||
|
||||
#region TripleDES
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptTdesWithoutSalt() // required to test the encryption itself
|
||||
{
|
||||
// arrange
|
||||
using var _ = CryptographyHelperSaltMock.Create(0);
|
||||
|
||||
byte[] bytes = new byte[] { 0xaf, 0xfe };
|
||||
string str = "ABC";
|
||||
string password1 = "P@ssw0rd!";
|
||||
string password2 = "P@ssw0rd";
|
||||
|
||||
byte[] expectedBytes = new byte[] { 0xbf, 0x59, 0x1f, 0x48, 0x69, 0xab, 0x18, 0xc7 };
|
||||
|
||||
// act
|
||||
byte[] cipherBytes1 = CryptographyHelper.TripleDesEncrypt(bytes, password1);
|
||||
string cipherStr1 = CryptographyHelper.TripleDesEncrypt(str, password1);
|
||||
byte[] cipherBytes2 = CryptographyHelper.TripleDesEncrypt(bytes, password2);
|
||||
string cipherStr2 = CryptographyHelper.TripleDesEncrypt(str, password2);
|
||||
|
||||
// assert
|
||||
CollectionAssert.AreEqual(expectedBytes, cipherBytes1);
|
||||
Assert.AreEqual("1l74soBuuEI=", cipherStr1);
|
||||
|
||||
CollectionAssert.AreNotEqual(expectedBytes, cipherBytes2);
|
||||
Assert.AreNotEqual("1l74soBuuEI=", cipherStr2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDecryptTdesWithoutSalt() // required to test the decryption itself
|
||||
{
|
||||
// arrange
|
||||
using var _ = CryptographyHelperSaltMock.Create(0);
|
||||
|
||||
string cipherStr = "1l74soBuuEI=";
|
||||
byte[] cipherBytes = new byte[] { 0xbf, 0x59, 0x1f, 0x48, 0x69, 0xab, 0x18, 0xc7 };
|
||||
|
||||
string password1 = "P@ssw0rd!";
|
||||
string password2 = "P@ssw0rd";
|
||||
|
||||
byte[] expectedBytes = new byte[] { 0xaf, 0xfe };
|
||||
|
||||
// act
|
||||
byte[] plainBytes1 = CryptographyHelper.TripleDesDecrypt(cipherBytes, password1);
|
||||
string plainStr1 = CryptographyHelper.TripleDesDecrypt(cipherStr, password1);
|
||||
|
||||
try
|
||||
{
|
||||
CryptographyHelper.TripleDesDecrypt(cipherBytes, password2);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
CryptographyHelper.TripleDesDecrypt(cipherStr, password2);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{ }
|
||||
|
||||
// assert
|
||||
CollectionAssert.AreEqual(expectedBytes, plainBytes1);
|
||||
Assert.AreEqual("ABC", plainStr1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptDecryptTdesBytes()
|
||||
{
|
||||
// arrange
|
||||
byte[] plain = new byte[] { 0xaf, 0xfe };
|
||||
string password = "P@ssw0rd!";
|
||||
|
||||
// act
|
||||
byte[] cipher1 = CryptographyHelper.TripleDesEncrypt(plain, password);
|
||||
byte[] cipher2 = CryptographyHelper.TripleDesEncrypt(plain, password);
|
||||
|
||||
byte[] plain1 = CryptographyHelper.TripleDesDecrypt(cipher1, password);
|
||||
byte[] plain2 = CryptographyHelper.TripleDesDecrypt(cipher2, password);
|
||||
|
||||
// assert
|
||||
CollectionAssert.AreNotEqual(cipher1, cipher2);
|
||||
Assert.AreEqual(16, cipher1.Length);
|
||||
Assert.AreEqual(16, cipher2.Length);
|
||||
CollectionAssert.AreEqual(plain, plain1);
|
||||
CollectionAssert.AreEqual(plain, plain2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptDecryptTdesString()
|
||||
{
|
||||
// arrange
|
||||
string plain = "ABC";
|
||||
string password = "P@ssw0rd!";
|
||||
|
||||
// act
|
||||
string cipher1 = CryptographyHelper.TripleDesEncrypt(plain, password);
|
||||
string cipher2 = CryptographyHelper.TripleDesEncrypt(plain, password);
|
||||
|
||||
string plain1 = CryptographyHelper.TripleDesDecrypt(cipher1, password);
|
||||
string plain2 = CryptographyHelper.TripleDesDecrypt(cipher2, password);
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(cipher1, cipher2);
|
||||
Assert.AreEqual(24, cipher1.Length);
|
||||
Assert.AreEqual(24, cipher2.Length);
|
||||
Assert.AreEqual(plain, plain1);
|
||||
Assert.AreEqual(plain, plain2);
|
||||
}
|
||||
|
||||
#endregion TripleDES
|
||||
|
||||
#endregion Encryption
|
||||
|
||||
#region Hash
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnMd5Hash()
|
||||
{
|
||||
// arrange
|
||||
string text = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xde, 0xad, 0xbe, 0xef };
|
||||
string fileName = Path.GetTempFileName();
|
||||
|
||||
// act
|
||||
string textHash = CryptographyHelper.Md5(text);
|
||||
string bytesHash = CryptographyHelper.Md5(bytes);
|
||||
|
||||
File.WriteAllText(fileName, text);
|
||||
string fileHash = CryptographyHelper.Md5File(fileName);
|
||||
File.Delete(fileName);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("ed076287532e86365e841e92bfc50d8c", textHash);
|
||||
Assert.AreEqual("2f249230a8e7c2bf6005ccd2679259ec", bytesHash);
|
||||
Assert.AreEqual("ed076287532e86365e841e92bfc50d8c", fileHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSha1Hash()
|
||||
{
|
||||
// arrange
|
||||
string text = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xde, 0xad, 0xbe, 0xef };
|
||||
string fileName = Path.GetTempFileName();
|
||||
|
||||
// act
|
||||
string textHash = CryptographyHelper.Sha1(text);
|
||||
string bytesHash = CryptographyHelper.Sha1(bytes);
|
||||
|
||||
File.WriteAllText(fileName, text);
|
||||
string fileHash = CryptographyHelper.Sha1File(fileName);
|
||||
File.Delete(fileName);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("2ef7bde608ce5404e97d5f042f95f89f1c232871", textHash);
|
||||
Assert.AreEqual("d78f8bb992a56a597f6c7a1fb918bb78271367eb", bytesHash);
|
||||
Assert.AreEqual("2ef7bde608ce5404e97d5f042f95f89f1c232871", fileHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSha256Hash()
|
||||
{
|
||||
// arrange
|
||||
string text = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xde, 0xad, 0xbe, 0xef };
|
||||
string fileName = Path.GetTempFileName();
|
||||
|
||||
// act
|
||||
string textHash = CryptographyHelper.Sha256(text);
|
||||
string bytesHash = CryptographyHelper.Sha256(bytes);
|
||||
|
||||
File.WriteAllText(fileName, text);
|
||||
string fileHash = CryptographyHelper.Sha256File(fileName);
|
||||
File.Delete(fileName);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", textHash);
|
||||
Assert.AreEqual("5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953", bytesHash);
|
||||
Assert.AreEqual("7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", fileHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSha512Hash()
|
||||
{
|
||||
// arrange
|
||||
string text = "Hello World!";
|
||||
byte[] bytes = new byte[] { 0xde, 0xad, 0xbe, 0xef };
|
||||
string fileName = Path.GetTempFileName();
|
||||
|
||||
// act
|
||||
string textHash = CryptographyHelper.Sha512(text);
|
||||
string bytesHash = CryptographyHelper.Sha512(bytes);
|
||||
|
||||
File.WriteAllText(fileName, text);
|
||||
string fileHash = CryptographyHelper.Sha512File(fileName);
|
||||
File.Delete(fileName);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual("861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8", textHash);
|
||||
Assert.AreEqual("1284b2d521535196f22175d5f558104220a6ad7680e78b49fa6f20e57ea7b185d71ec1edb137e70eba528dedb141f5d2f8bb53149d262932b27cf41fed96aa7f", bytesHash);
|
||||
Assert.AreEqual("861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8", fileHash);
|
||||
}
|
||||
|
||||
#endregion Hash
|
||||
|
||||
#region Random
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnRandomBytes()
|
||||
{
|
||||
// arrange
|
||||
int length1 = 12;
|
||||
int length2 = 12;
|
||||
int length3 = 42;
|
||||
|
||||
// act
|
||||
byte[] bytes1 = CryptographyHelper.GetRandomBytes(length1);
|
||||
byte[] bytes2 = CryptographyHelper.GetRandomBytes(length2);
|
||||
byte[] bytes3 = CryptographyHelper.GetRandomBytes(length3);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(length1, bytes1.Length);
|
||||
Assert.AreEqual(length2, bytes2.Length);
|
||||
Assert.AreEqual(length3, bytes3.Length);
|
||||
|
||||
Assert.IsTrue(bytes1.Length == bytes2.Length);
|
||||
CollectionAssert.AreNotEqual(bytes1, bytes2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnRandomString()
|
||||
{
|
||||
// arrange
|
||||
int length1 = 12;
|
||||
int length2 = 12;
|
||||
int length3 = 42;
|
||||
|
||||
// act
|
||||
string str1 = CryptographyHelper.GetRandomString(length1);
|
||||
string str2 = CryptographyHelper.GetRandomString(length2);
|
||||
string str3 = CryptographyHelper.GetRandomString(length3);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(length1, str1.Length);
|
||||
Assert.AreEqual(length2, str2.Length);
|
||||
Assert.AreEqual(length3, str3.Length);
|
||||
|
||||
Assert.IsTrue(str1.Length == str2.Length);
|
||||
Assert.IsFalse(str1 == str2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnRandomStringWithPool()
|
||||
{
|
||||
// arrange
|
||||
int length = 12;
|
||||
string pool = "0123456789abcdef";
|
||||
|
||||
// act
|
||||
string str1 = CryptographyHelper.GetRandomString(length, pool);
|
||||
string str2 = CryptographyHelper.GetRandomString(length, pool);
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(length, str1.Length);
|
||||
Assert.AreEqual(length, str2.Length);
|
||||
Assert.IsFalse(str1 == str2);
|
||||
Assert.IsFalse(Regex.IsMatch(str1, "[^0-9a-f]"));
|
||||
Assert.IsFalse(Regex.IsMatch(str2, "[^0-9a-f]"));
|
||||
}
|
||||
|
||||
#endregion Random
|
||||
|
||||
#region Secure probing
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldTakeSameTimeToCompareString()
|
||||
{
|
||||
// arrange
|
||||
string str1 = "Hello World!";
|
||||
string str2 = "Hello World!";
|
||||
string str3 = "Hallo World!";
|
||||
string str4 = "Hello World?";
|
||||
string nullStr = null;
|
||||
string strLen = "Hello World";
|
||||
|
||||
var sw = new Stopwatch();
|
||||
|
||||
// act
|
||||
bool nullCompare = CryptographyHelper.SecureEquals(nullStr, str1);
|
||||
bool lenCompare = CryptographyHelper.SecureEquals(strLen, str1);
|
||||
|
||||
sw.Start();
|
||||
bool compare1 = CryptographyHelper.SecureEquals(str1, str2);
|
||||
long time1 = sw.ElapsedMilliseconds;
|
||||
|
||||
bool compare2 = CryptographyHelper.SecureEquals(str1, str3);
|
||||
long time2 = sw.ElapsedMilliseconds;
|
||||
|
||||
bool compare3 = CryptographyHelper.SecureEquals(str1, str4);
|
||||
long time3 = sw.ElapsedMilliseconds;
|
||||
sw.Stop();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(nullCompare);
|
||||
Assert.IsFalse(lenCompare);
|
||||
Assert.IsTrue(compare1);
|
||||
Assert.IsFalse(compare2);
|
||||
Assert.IsFalse(compare3);
|
||||
|
||||
Assert.AreEqual(time1, time2);
|
||||
Assert.AreEqual(time1, time3);
|
||||
Assert.AreEqual(time2, time3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldTakeSameTimeToCompareBytes()
|
||||
{
|
||||
// arrange
|
||||
byte[] bytes1 = CryptographyHelper.GetRandomBytes(200);
|
||||
byte[] bytes2 = new byte[bytes1.Length];
|
||||
byte[] bytes3 = new byte[bytes1.Length];
|
||||
byte[] bytes4 = new byte[bytes1.Length];
|
||||
byte[] nullBytes = null;
|
||||
byte[] lenBytes = new byte[bytes1.Length + 1];
|
||||
|
||||
Array.Copy(bytes1, bytes2, bytes1.Length);
|
||||
Array.Copy(bytes1, bytes3, bytes1.Length);
|
||||
Array.Copy(bytes1, bytes4, bytes1.Length);
|
||||
|
||||
bytes3[10] = (byte)(bytes1[10] + 1);
|
||||
bytes4[190] = (byte)(bytes1[190] + 1);
|
||||
|
||||
var sw = new Stopwatch();
|
||||
|
||||
// act
|
||||
bool nullCompare = CryptographyHelper.SecureEquals(nullBytes, bytes1);
|
||||
bool lenCompare = CryptographyHelper.SecureEquals(lenBytes, bytes1);
|
||||
|
||||
sw.Start();
|
||||
bool compare1 = CryptographyHelper.SecureEquals(bytes1, bytes2);
|
||||
long time1 = sw.ElapsedMilliseconds;
|
||||
|
||||
bool compare2 = CryptographyHelper.SecureEquals(bytes1, bytes3);
|
||||
long time2 = sw.ElapsedMilliseconds;
|
||||
|
||||
bool compare3 = CryptographyHelper.SecureEquals(bytes1, bytes4);
|
||||
long time3 = sw.ElapsedMilliseconds;
|
||||
sw.Stop();
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(nullCompare);
|
||||
Assert.IsFalse(lenCompare);
|
||||
Assert.IsTrue(compare1);
|
||||
Assert.IsFalse(compare2);
|
||||
Assert.IsFalse(compare3);
|
||||
|
||||
Assert.AreEqual(time1, time2);
|
||||
Assert.AreEqual(time1, time3);
|
||||
Assert.AreEqual(time2, time3);
|
||||
}
|
||||
|
||||
#endregion Secure probing
|
||||
|
||||
#endregion Static
|
||||
|
||||
#region Instance
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldCreateDefaultFile()
|
||||
{
|
||||
// arrange
|
||||
string executingAssemblyDir = AppContext.BaseDirectory;
|
||||
string filePath = Path.Combine(executingAssemblyDir, "crypto.key");
|
||||
|
||||
// act
|
||||
bool fileExistsBefore = File.Exists(filePath);
|
||||
var helper = new CryptographyHelper();
|
||||
bool fileExistsAfter = File.Exists(filePath);
|
||||
string content = fileExistsAfter ? File.ReadAllText(filePath) : null;
|
||||
File.Delete(filePath);
|
||||
|
||||
// assert
|
||||
Assert.IsFalse(fileExistsBefore);
|
||||
Assert.IsNotNull(helper);
|
||||
Assert.IsTrue(fileExistsAfter);
|
||||
Assert.IsTrue(!string.IsNullOrWhiteSpace(content));
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptAesUsingKeyFile()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = CryptographyHelper.GetRandomBytes(32);
|
||||
|
||||
string password = File.ReadAllText(keyFile);
|
||||
|
||||
// act
|
||||
string cipherStr = cryptoHelper.EncryptAes(str);
|
||||
byte[] cipherBytes = cryptoHelper.EncryptAes(bytes);
|
||||
|
||||
string plainStr = CryptographyHelper.AesDecrypt(cipherStr, password);
|
||||
byte[] plainBytes = CryptographyHelper.AesDecrypt(cipherBytes, password);
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(str, cipherStr);
|
||||
Assert.AreEqual(str, plainStr);
|
||||
CollectionAssert.AreNotEqual(bytes, cipherBytes);
|
||||
CollectionAssert.AreEqual(bytes, plainBytes);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDecryptAesUsingKeyFile()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = CryptographyHelper.GetRandomBytes(32);
|
||||
|
||||
string password = File.ReadAllText(keyFile);
|
||||
|
||||
// act
|
||||
string cipherStr = CryptographyHelper.AesEncrypt(str, password);
|
||||
byte[] cipherBytes = CryptographyHelper.AesEncrypt(bytes, password);
|
||||
|
||||
string plainStr = cryptoHelper.DecryptAes(cipherStr);
|
||||
byte[] plainBytes = cryptoHelper.DecryptAes(cipherBytes);
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(str, cipherStr);
|
||||
Assert.AreEqual(str, plainStr);
|
||||
CollectionAssert.AreNotEqual(bytes, cipherBytes);
|
||||
CollectionAssert.AreEqual(bytes, plainBytes);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldEncryptTdesUsingKeyFile()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = CryptographyHelper.GetRandomBytes(32);
|
||||
|
||||
string password = File.ReadAllText(keyFile);
|
||||
|
||||
// act
|
||||
string cipherStr = cryptoHelper.EncryptTripleDes(str);
|
||||
byte[] cipherBytes = cryptoHelper.EncryptTripleDes(bytes);
|
||||
|
||||
string plainStr = CryptographyHelper.TripleDesDecrypt(cipherStr, password);
|
||||
byte[] plainBytes = CryptographyHelper.TripleDesDecrypt(cipherBytes, password);
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(str, cipherStr);
|
||||
Assert.AreEqual(str, plainStr);
|
||||
CollectionAssert.AreNotEqual(bytes, cipherBytes);
|
||||
CollectionAssert.AreEqual(bytes, plainBytes);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldDecryptTdesUsingKeyFile()
|
||||
{
|
||||
// arrange
|
||||
string str = "Hello World!";
|
||||
byte[] bytes = CryptographyHelper.GetRandomBytes(32);
|
||||
|
||||
string password = File.ReadAllText(keyFile);
|
||||
|
||||
// act
|
||||
string cipherStr = CryptographyHelper.TripleDesEncrypt(str, password);
|
||||
byte[] cipherBytes = CryptographyHelper.TripleDesEncrypt(bytes, password);
|
||||
|
||||
string plainStr = cryptoHelper.DecryptTripleDes(cipherStr);
|
||||
byte[] plainBytes = cryptoHelper.DecryptTripleDes(cipherBytes);
|
||||
|
||||
// assert
|
||||
Assert.AreNotEqual(str, cipherStr);
|
||||
Assert.AreEqual(str, plainStr);
|
||||
CollectionAssert.AreNotEqual(bytes, cipherBytes);
|
||||
CollectionAssert.AreEqual(bytes, plainBytes);
|
||||
}
|
||||
|
||||
#endregion Instance
|
||||
}
|
||||
}
|
||||
288
UnitTests/Common/Utilities/DelayedTaskTests.cs
Normal file
288
UnitTests/Common/Utilities/DelayedTaskTests.cs
Normal file
@@ -0,0 +1,288 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Common.Utilities;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Utilities
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class DelayedTaskTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldCreateNewDelayedTaskNotStarting()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
var delayedTask = DelayedTask.Create(action, delay);
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(0, executionCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldCreateNewDelayedTaskStarting()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
var delayedTask = DelayedTask.Run(action, delay);
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldRunOnceAfterReset()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
var delayedTask = DelayedTask.Create(action, delay);
|
||||
delayedTask.Reset();
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldCancelWaitingTask()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
var delayedTask = DelayedTask.Run(action, delay);
|
||||
delayedTask.Cancel();
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(0, executionCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldResetRunningDelay()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var sw = new Stopwatch();
|
||||
|
||||
var delay = TimeSpan.FromMilliseconds(200);
|
||||
var action = () => { sw.Stop(); executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
sw.Start();
|
||||
var delayedTask = DelayedTask.Run(action, delay);
|
||||
await Task.Delay(50);
|
||||
delayedTask.Reset();
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
// delta of 60ms as the precision below 50ms is really bad for System.Timer
|
||||
Assert.AreEqual(250, sw.ElapsedMilliseconds, 60);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldNotExecutedImmediateOnCreated()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var sw = new Stopwatch();
|
||||
|
||||
var delay = TimeSpan.FromMilliseconds(200);
|
||||
var action = () => { sw.Stop(); executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
sw.Start();
|
||||
var delayedTask = DelayedTask.Create(action, delay);
|
||||
await Task.Delay(50);
|
||||
bool isSuccess = delayedTask.ExecutePending();
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
sw.Stop();
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(0, executionCount);
|
||||
// delta of 60ms as the precision below 50ms is really bad for System.Timer
|
||||
Assert.AreEqual(1250, sw.ElapsedMilliseconds, 60);
|
||||
Assert.IsFalse(isSuccess);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldExecuteImmediateOnExecutePendingWhenRunning()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var sw = new Stopwatch();
|
||||
|
||||
var delay = TimeSpan.FromMilliseconds(200);
|
||||
var action = () => { sw.Stop(); executionCount++; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
sw.Start();
|
||||
var delayedTask = DelayedTask.Run(action, delay);
|
||||
await Task.Delay(50);
|
||||
bool isSuccess = delayedTask.ExecutePending();
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.AreEqual(delay, delayedTask.Delay);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
// delta of 60ms as the precision below 50ms is really bad for System.Timer
|
||||
Assert.AreEqual(50, sw.ElapsedMilliseconds, 60);
|
||||
Assert.IsTrue(isSuccess);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnAnAwaiter()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { executionCount++; };
|
||||
var delayedTask = DelayedTask.Create(action, delay);
|
||||
|
||||
// act
|
||||
delayedTask.Reset();
|
||||
var awaiter = delayedTask.GetAwaiter();
|
||||
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.IsNotNull(awaiter);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTask.Exception);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldHaveAnExceptionSet()
|
||||
{
|
||||
// arrange
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { throw new Exception("TEST :D"); };
|
||||
|
||||
// act
|
||||
var delayedTask = DelayedTask.Run(action, delay);
|
||||
|
||||
var awaiter = delayedTask.GetAwaiter();
|
||||
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNotNull(delayedTask.Exception);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldUseExceptionHandler()
|
||||
{
|
||||
// arrange
|
||||
string exceptionText = null;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { throw new Exception("TEST :D"); };
|
||||
var exceptionHandler = (Exception ex) =>
|
||||
{
|
||||
exceptionText = ex.Message;
|
||||
};
|
||||
|
||||
// act
|
||||
var delayedTask = DelayedTask.Run(action, delay)
|
||||
.WithExceptionHandler(exceptionHandler);
|
||||
|
||||
var awaiter = delayedTask.GetAwaiter();
|
||||
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.IsNotNull(delayedTask.Exception);
|
||||
Assert.AreEqual("TEST :D", exceptionText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldReturnNormalTask()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var action = () => { executionCount++; };
|
||||
var delayedTask = DelayedTask.Create(action, delay);
|
||||
|
||||
// act
|
||||
delayedTask.Reset();
|
||||
var task = delayedTask.Task;
|
||||
await task;
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTask);
|
||||
Assert.IsNotNull(task);
|
||||
Assert.IsInstanceOfType(task, typeof(Task));
|
||||
Assert.IsFalse(delayedTask.IsRunning);
|
||||
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, task.Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
134
UnitTests/Common/Utilities/DelayedTaskWithResultTests.cs
Normal file
134
UnitTests/Common/Utilities/DelayedTaskWithResultTests.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AMWD.Common.Utilities;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Utilities
|
||||
{
|
||||
[TestClass]
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
public class DelayedTaskWithResultTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldCreateNewDelayedTaskNotStarting()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var function = () => { executionCount++; return new[] { 42, 21 }; };
|
||||
|
||||
// act
|
||||
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
||||
var delayedTaskWithResult = DelayedTask.Create(function, delay);
|
||||
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTaskWithResult);
|
||||
Assert.AreEqual(delay, delayedTaskWithResult.Delay);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsRunning);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTaskWithResult.Exception);
|
||||
Assert.AreEqual(0, executionCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldCreateNewDelayedTaskStarting()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var function = () => { executionCount++; return new[] { 42, 21 }; };
|
||||
|
||||
// act
|
||||
var delayedTaskWithResult = DelayedTask.Run(function, delay);
|
||||
int[] result = await delayedTaskWithResult;
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTaskWithResult);
|
||||
Assert.AreEqual(delay, delayedTaskWithResult.Delay);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsRunning);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsWaitingToRun);
|
||||
Assert.IsNull(delayedTaskWithResult.Exception);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
CollectionAssert.AreEqual(new[] { 42, 21 }, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldHaveAnExceptionSet()
|
||||
{
|
||||
// arrange
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
#pragma warning disable CS0162 // Unreachable Code detected.
|
||||
var function = () => { throw new Exception("TEST :D"); return new[] { 42, 21 }; };
|
||||
#pragma warning restore CS0162 // Unreachable Code detected
|
||||
|
||||
// act
|
||||
var delayedTaskWithResult = DelayedTask.Run(function, delay);
|
||||
|
||||
var awaiter = delayedTaskWithResult.GetAwaiter();
|
||||
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTaskWithResult);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsRunning);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsWaitingToRun);
|
||||
Assert.IsNotNull(delayedTaskWithResult.Exception);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldUseExceptionHandler()
|
||||
{
|
||||
// arrange
|
||||
string exceptionText = null;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
#pragma warning disable CS0162 // Unreachable Code detected.
|
||||
var function = () => { throw new Exception("TEST :D"); return new[] { 42, 21 }; };
|
||||
#pragma warning restore CS0162 // Unreachable Code detected
|
||||
var exceptionHandler = (Exception ex) =>
|
||||
{
|
||||
exceptionText = ex.Message;
|
||||
};
|
||||
|
||||
// act
|
||||
var delayedTaskWithResult = DelayedTask.Run(function, delay)
|
||||
.WithExceptionHandler(exceptionHandler);
|
||||
|
||||
var awaiter = delayedTaskWithResult.GetAwaiter();
|
||||
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTaskWithResult);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsRunning);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsWaitingToRun);
|
||||
Assert.IsNotNull(delayedTaskWithResult.Exception);
|
||||
Assert.AreEqual("TEST :D", exceptionText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ShouldReturnNormalTask()
|
||||
{
|
||||
// arrange
|
||||
int executionCount = 0;
|
||||
var delay = TimeSpan.FromMilliseconds(100);
|
||||
var function = () => { executionCount++; return new[] { 42, 21 }; };
|
||||
var delayedTaskWithResult = DelayedTask.Create(function, delay);
|
||||
|
||||
// act
|
||||
delayedTaskWithResult.Reset();
|
||||
var task = delayedTaskWithResult.Task;
|
||||
int[] result = await task;
|
||||
|
||||
// assert
|
||||
Assert.IsNotNull(delayedTaskWithResult);
|
||||
Assert.IsNotNull(task);
|
||||
Assert.IsInstanceOfType(task, typeof(Task));
|
||||
Assert.IsFalse(delayedTaskWithResult.IsRunning);
|
||||
Assert.IsFalse(delayedTaskWithResult.IsWaitingToRun);
|
||||
Assert.AreEqual(1, executionCount);
|
||||
Assert.AreEqual(TaskStatus.RanToCompletion, task.Status);
|
||||
CollectionAssert.AreEqual(new int[] { 42, 21 }, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
UnitTests/Common/Utils/CryptographyHelperSaltMock.cs
Normal file
27
UnitTests/Common/Utils/CryptographyHelperSaltMock.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using ReflectionMagic;
|
||||
|
||||
namespace UnitTests.Common.Utils
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
internal class CryptographyHelperSaltMock : IDisposable
|
||||
{
|
||||
private readonly int saltLength;
|
||||
|
||||
private CryptographyHelperSaltMock(int saltLength)
|
||||
{
|
||||
this.saltLength = typeof(CryptographyHelper).AsDynamicType().saltLength;
|
||||
SetSaltLength(saltLength);
|
||||
}
|
||||
|
||||
public static IDisposable Create(int saltLength)
|
||||
=> new CryptographyHelperSaltMock(saltLength);
|
||||
|
||||
public void Dispose()
|
||||
=> SetSaltLength(saltLength);
|
||||
|
||||
private static void SetSaltLength(int length)
|
||||
=> typeof(CryptographyHelper).AsDynamicType().saltLength = length;
|
||||
}
|
||||
}
|
||||
16
UnitTests/Common/Utils/CustomMultipleAttribute.cs
Normal file
16
UnitTests/Common/Utils/CustomMultipleAttribute.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace UnitTests.Common.Utils
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
|
||||
internal class CustomMultipleAttribute : Attribute
|
||||
{
|
||||
public CustomMultipleAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
50
UnitTests/Common/Utils/JsonTestClass.cs
Normal file
50
UnitTests/Common/Utils/JsonTestClass.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
|
||||
namespace UnitTests.Common.Utils
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
internal class JsonTestClass
|
||||
{
|
||||
public string StringValue { get; set; } = "Hello World!";
|
||||
|
||||
public bool IsBoolTrue { get; set; } = true;
|
||||
|
||||
public float FloatValue { get; set; } = 12.34f;
|
||||
|
||||
public double DoubleValue { get; set; } = 21.42;
|
||||
|
||||
public decimal DecimalValue { get; set; } = 42.21m;
|
||||
|
||||
public DateTime LocalTimestamp { get; set; } = new(2021, 11, 16, 20, 15, 34, DateTimeKind.Local);
|
||||
|
||||
public DateTime UtcTimestamp { get; set; } = new(2021, 11, 16, 20, 15, 34, DateTimeKind.Utc);
|
||||
|
||||
public JsonTestSubClass Object { get; set; } = new();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
internal class JsonTestSubClass
|
||||
{
|
||||
public int IntegerValue { get; set; } = 42;
|
||||
|
||||
public string StringValue { get; set; } = "Foo-Bar";
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
internal class JsonErrorClass
|
||||
{
|
||||
private int? number;
|
||||
|
||||
public int Number
|
||||
{
|
||||
get
|
||||
{
|
||||
if (number.HasValue)
|
||||
return number.Value;
|
||||
|
||||
throw new Exception("Null value");
|
||||
}
|
||||
set { number = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
26
UnitTests/Common/Utils/TimeZoneInfoLocalMock.cs
Normal file
26
UnitTests/Common/Utils/TimeZoneInfoLocalMock.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using ReflectionMagic;
|
||||
|
||||
namespace UnitTests.Common.Utils
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
||||
internal class TimeZoneInfoLocalMock : IDisposable
|
||||
{
|
||||
private readonly TimeZoneInfo localTimeZoneInfo;
|
||||
|
||||
private TimeZoneInfoLocalMock(TimeZoneInfo timeZoneInfo)
|
||||
{
|
||||
localTimeZoneInfo = TimeZoneInfo.Local;
|
||||
SetLocalTimeZone(timeZoneInfo);
|
||||
}
|
||||
|
||||
public static IDisposable Create(TimeZoneInfo mockTimeZoneInfo)
|
||||
=> new TimeZoneInfoLocalMock(mockTimeZoneInfo);
|
||||
|
||||
public void Dispose()
|
||||
=> SetLocalTimeZone(localTimeZoneInfo);
|
||||
|
||||
private static void SetLocalTimeZone(TimeZoneInfo timeZoneInfo)
|
||||
=> typeof(TimeZoneInfo).AsDynamicType().s_cachedData._localTimeZone = timeZoneInfo;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user