1
0
mirror of https://github.com/oliverbooth/X10D synced 2024-11-22 23:58:48 +00:00

Merge branch 'develop' into main

This commit is contained in:
Oliver Booth 2023-03-07 17:30:15 +00:00 committed by GitHub
commit a685d6ec39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
213 changed files with 17478 additions and 183 deletions

View File

@ -211,3 +211,4 @@ dotnet_diagnostic.SA1633.severity = silent
# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1090.md
dotnet_diagnostic.CA2007.severity = silent
dotnet_diagnostic.RCS1090.severity = silent
dotnet_diagnostic.CA1805.severity = none

View File

@ -32,6 +32,8 @@ jobs:
run: |
mkdir build
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.DSharpPlus -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Hosting -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
- name: Push NuGet Package to GitHub

View File

@ -32,6 +32,8 @@ jobs:
run: |
mkdir build
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.DSharpPlus -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Hosting -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
- name: Push NuGet Package to GitHub

View File

@ -32,6 +32,8 @@ jobs:
run: |
mkdir build
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
dotnet pack X10D.DSharpPlus -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
dotnet pack X10D.Hosting -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
dotnet pack X10D.Unity -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
- name: Push NuGet Package to GitHub

View File

@ -40,7 +40,7 @@ jobs:
cp -r ./X10D.Unity/bin/Release/netstandard2.1/X10D.Unity.dll ./X10D.Unity.Tests/Assets/Libraries/X10D.Unity.dll
- name: Unity - Test runner
uses: game-ci/unity-test-runner@v2.0.2
uses: game-ci/unity-test-runner@v2.1.0
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}

View File

@ -1,5 +1,130 @@
# Changelog
## 3.2.0
### Added
- Added new library X10D.DSharpPlus
- Added new library X10D.Hosting
- Added .NET 7 target
- X10D: Added `MathUtility.InverseLerp(float, float, float)` and `MathUtility.InverseLerp(double, double, double)`
- X10D: Added `MathUtility.ScaleRange(float, float, float, float, float)` and `MathUtility.ScaleRange(double, double, double, double, double)`
- X10D: Added `Circle`, `CircleF`, `Cuboid`, `Ellipse`, `EllipseF`, `Line3D`, `Line`, `LineF`, `Polygon`, `PolygonF`, `Polyhedron`, and `Sphere`, to complement System.Drawing structs such as `Point` and `Rectangle`
- X10D: Added `Color.Deconstruct()` - with optional alpha parameter
- X10D: Added `Color.GetClosestConsoleColor()`
- X10D: Added `DateTime.GetIso8601WeekOfYear()` and `DateTimeOffset.GetIso8601WeekOfYear()`
- X10D: Added `DirectoryInfo.Clear()`
- X10D: Added `double.LinearToGamma([gamma])` and `float.LinearToGamma([gamma])` (#60)
- X10D: Added `double.GammaToLinear([gamma])` and `float.GammaToLinear([gamma])` (#60)
- X10D: Added `GreatestCommonFactor` for built-in integer types
- X10D: Added `IEnumerable<T>.CountWhereNot(Func<T, bool>)`
- X10D: Added `IEnumerable<T>.FirstWhereNot(Func<T, bool>)`
- X10D: Added `IEnumerable<T>.FirstWhereNotOrDefault(Func<T, bool>)`
- X10D: Added `IEnumerable<T>.LastWhereNot(Func<T, bool>)`
- X10D: Added `IEnumerable<T>.LastWhereNotOrDefault(Func<T, bool>)`
- X10D: Added `IEnumerable<T>.WhereNot(Func<T, bool>)`
- X10D: Added `IEnumerable<T>.WhereNotNull()`
- X10D: Added `IList<T>.RemoveRange(Range)`
- X10D: Added `IList<T>.Swap(IList<T>)` (#62)
- X10D: Added `IReadOnlyList<T>.IndexOf(T[, int[, int]])`
- X10D: Added `IReadOnlyList<T>.Slice(int[, int]])`
- X10D: Added `Wrap(T[, T])` for built-in numeric types (#60)
- X10D: Added `Nullable<T>.TryGetValue(out T)` (#61)
- X10D: Added `Point.IsOnLine(LineF)`, `Point.IsOnLine(PointF, PointF)`, and `Point.IsOnLine(Vector2, Vector2)`
- X10D: Added `PointF.IsOnLine(LineF)`, `PointF.IsOnLine(PointF, PointF)`, and `PointF.IsOnLine(Vector2, Vector2)`
- X10D: Added `Point.ToSize()`
- X10D: Added `Point.ToSizeF()`
- X10D: Added `Point.ToVector2()`
- X10D: Added `PointF.Round([float])`
- X10D: Added `PointF.ToSizeF()`
- X10D: Added `PointF.ToVector2()` for .NET < 6
- X10D: Added `PopCount()` for built-in integer types
- X10D: Added `Quaternion.ToAxisAngle(out float, out float)`
- X10D: Added `Quaternion.ToVector3()`
- X10D: Added `Random.NextFrom(Span<T>)` and `Random.NextFrom(ReadOnlySpan<T>)`
- X10D: Added `ReadOnlySpan<char>.CountSubstring(char)`
- X10D: Added `ReadOnlySpan<char>.CountSubstring(ReadOnlySpan<char>[, StringComparison])`
- X10D: Added `ReadOnlySpan<char>.ToTimeSpan()`
- X10D: Added `ReadOnlySpan<T>.Split(T)`
- X10D: Added `ReadOnlySpan<T>.Split(ReadOnlySpan<T>)`
- X10D: Added `RoundUpToPowerOf2()` for built-in integer types
- X10D: Added `Size.ToPoint()`
- X10D: Added `Size.ToPointF()`
- X10D: Added `Size.ToVector2()`
- X10D: Added `Span<char>.CountSubstring(char)`
- X10D: Added `Span<char>.CountSubstring(Span<char>[, StringComparison])`
- X10D: Added `Span<T>.Split(T)`
- X10D: Added `Span<T>.Split(Span<T>)`
- X10D: Added `string.CountSubstring(char)`
- X10D: Added `string.CountSubstring(string[, StringComparison])`
- X10D: Added `string.IsEmpty()`
- X10D: Added `string.IsWhiteSpace()`
- X10D: Added `string.IsNullOrEmpty()`
- X10D: Added `string.IsNullOrWhiteSpace()`
- X10D: Added `TimeSpan.TryParse(ReadOnlySpan<char>, out TimeSpan)`
- X10D: Added `Quaternion.Multiply(Vector3)` - this functions as an equivalent to Unity's `Quaternion * Vector3` operator
- X10D: Added `Vector2.Deconstruct()`
- X10D: Added `Vector2.IsOnLine(LineF)`, `Vector2.IsOnLine(PointF, PointF)`, and `Vector2.IsOnLine(Vector2, Vector2)`
- X10D: Added `Vector2.Round([float])`
- X10D: Added `Vector2.ToPointF()`
- X10D: Added `Vector2.ToSizeF()`
- X10D: Added `Vector3.Deconstruct()`
- X10D: Added `Vector3.Round([float])`
- X10D: Added `Vector4.Deconstruct()`
- X10D: Added `Vector4.Round([float])`
- X10D.Unity: Added `DebugEx`, which mimics `UnityEngine.Debug` while offering more useful primitive drawing methods
- X10D.Unity: Added `System.Drawing.Color.ToUnityColor()`
- X10D.Unity: Added `System.Drawing.Color.ToUnityColor32()`
- X10D.Unity: Added `Color.Deconstruct()` - with optional alpha parameter
- X10D.Unity: Added `Color.GetClosestConsoleColor()`
- X10D.Unity: Added `Color.ToSystemDrawingColor()`
- X10D.Unity: Added `Color32.Deconstruct()` - with optional alpha parameter
- X10D.Unity: Added `Color32.GetClosestConsoleColor()`
- X10D.Unity: Added `Color32.ToSystemDrawingColor()`
- X10D.Unity: Added `Point.ToUnityVector2()`
- X10D.Unity: Added `Point.ToUnityVector2Int()`
- X10D.Unity: Added `PointF.ToUnityVector2()`
- X10D.Unity: Added `Rect.ToSystemRectangleF()`
- X10D.Unity: Added `RectInt.ToSystemRectangle()`
- X10D.Unity: Added `RectInt.ToSystemRectangleF()`
- X10D.Unity: Added `Rectangle.ToUnityRect()`
- X10D.Unity: Added `Rectangle.ToUnityRectInt()`
- X10D.Unity: Added `RectangleF.ToUnityRect()`
- X10D.Unity: Added `Size.ToUnityVector2()`
- X10D.Unity: Added `Size.ToUnityVector2Int()`
- X10D.Unity: Added `SizeF.ToUnityVector2()`
- X10D.Unity: Added `Vector2.Deconstruct()`
- X10D.Unity: Added `Vector2.IsOnLine(LineF)`, `Vector2.IsOnLine(PointF, PointF)`, and `Vector2.IsOnLine(Vector2, Vector2)`
- X10D.Unity: Added `Vector2Int.IsOnLine(LineF)`, `Vector2Int.IsOnLine(PointF, PointF)`, `Vector2Int.IsOnLine(Vector2, Vector2)`, and `Vector2Int.IsOnLine(Vector2Int, Vector2Int)`
- X10D.Unity: Added `Vector2.Round([float])`
- X10D.Unity: Added `Vector2.ToSystemPointF()`
- X10D.Unity: Added `Vector2.ToSystemSizeF()`
- X10D.Unity: Added `Vector2Int.Deconstruct()`
- X10D.Unity: Added `Vector2Int.ToSystemPoint()`
- X10D.Unity: Added `Vector2Int.ToSystemSize()`
- X10D.Unity: Added `Vector2Int.ToSystemVector()`
- X10D.Unity: Added `Vector2Int.WithX()`
- X10D.Unity: Added `Vector2Int.WithY()`
- X10D.Unity: Added `Vector3.Deconstruct()`
- X10D.Unity: Added `Vector3.Round([float])`
- X10D.Unity: Added `Vector3Int.Deconstruct()`
- X10D.Unity: Added `Vector3Int.ToSystemVector()`
- X10D.Unity: Added `Vector3Int.WithX()`
- X10D.Unity: Added `Vector3Int.WithY()`
- X10D.Unity: Added `Vector3Int.WithZ()`
- X10D.Unity: Added `Vector4.Deconstruct()`
- X10D.Unity: Added `Vector4.Round([float])`
- X10D.Unity: Added `WaitForFrames` yield instruction
- X10D.Unity: Added `WaitForKeyDown` yield instruction
- X10D.Unity: Added `WaitForKeyUp` yield instruction
- X10D.Unity: Added `WaitForSecondsNoAlloc` yield instruction
- X10D.Unity: Added `WaitForSecondsRealtimeNoAlloc` yield instruction
- X10D.Unity: Added `WaitForTimeSpanNoAlloc` yield instruction
- X10D.Unity: Added `WaitForTimeSpanRealtimeNoAlloc` yield instruction
### Changed
- X10D: `TimeSpanParser.TryParse` now accepts a nullable string, and returns false if this input is null or empty
- X10D.Unity: `Singleton<T>` now caches instance where possible
## [3.1.0]
### Added
- Reintroduced Unity support

View File

@ -1,12 +1,12 @@
<h1 align="center"><img src="https://raw.githubusercontent.com/oliverbooth/X10D/develop/banner.png"></h1>
<p align="center">
<a href="https://github.com/oliverbooth/X10D/actions?query=workflow%3A%22.NET+Core%22"><img src="https://img.shields.io/github/workflow/status/oliverbooth/X10D/.NET%20Core" alt="GitHub Workflow Status" title="GitHub Workflow Status"></a>
<a href="https://github.com/oliverbooth/X10D/issues"><img src="https://img.shields.io/github/issues/oliverbooth/X10D" alt="GitHub Issues" title="GitHub Issues"></a>
<a href="https://sonarcloud.io/dashboard?id=oliverbooth_X10D"><img src="https://img.shields.io/sonar/coverage/oliverbooth_X10D?server=https%3A%2F%2Fsonarcloud.io" alt="Coverage"></a>
<a href="https://www.nuget.org/packages/X10D/"><img src="https://img.shields.io/nuget/dt/X10D" alt="NuGet Downloads" title="NuGet Downloads"></a>
<a href="https://www.nuget.org/packages/X10D/"><img src="https://img.shields.io/nuget/v/X10D?label=stable" alt="Stable Version" title="Stable Version"></a>
<a href="https://www.nuget.org/packages/X10D/"><img src="https://img.shields.io/nuget/vpre/X10D?label=nightly" alt="Nightly Version" title="Nightly Version"></a>
<a href="https://github.com/oliverbooth/X10D/blob/master/LICENSE.md"><img src="https://img.shields.io/github/license/oliverbooth/X10D" alt="MIT License" title="MIT License"></a>
<a href="https://github.com/oliverbooth/X10D/actions/workflows/dotnet.yml"><img src="https://img.shields.io/github/actions/workflow/status/oliverbooth/X10D/dotnet.yml?style=flat-square" alt="GitHub Workflow Status" title="GitHub Workflow Status"></a>
<a href="https://github.com/oliverbooth/X10D/issues"><img src="https://img.shields.io/github/issues/oliverbooth/X10D?style=flat-square" alt="GitHub Issues" title="GitHub Issues"></a>
<a href="https://sonarcloud.io/dashboard?id=oliverbooth_X10D"><img src="https://img.shields.io/sonar/coverage/oliverbooth_X10D?server=https%3A%2F%2Fsonarcloud.io&style=flat-square" alt="Coverage"></a>
<a href="https://www.nuget.org/packages/X10D/"><img src="https://img.shields.io/nuget/dt/X10D?style=flat-square" alt="NuGet Downloads" title="NuGet Downloads"></a>
<a href="https://www.nuget.org/packages/X10D/"><img src="https://img.shields.io/nuget/v/X10D?label=stable&style=flat-square" alt="Stable Version" title="Stable Version"></a>
<a href="https://www.nuget.org/packages/X10D/"><img src="https://img.shields.io/nuget/vpre/X10D?label=nightly&style=flat-square" alt="Nightly Version" title="Nightly Version"></a>
<a href="https://github.com/oliverbooth/X10D/blob/master/LICENSE.md"><img src="https://img.shields.io/github/license/oliverbooth/X10D?style=flat-square" alt="MIT License" title="MIT License"></a>
</p>
### About

View File

@ -0,0 +1,65 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net6.0;netstandard2.1</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<Optimize>true</Optimize>
<ImplicitUsings>true</ImplicitUsings>
<Authors>Oliver Booth</Authors>
<NeutralLanguage>en</NeutralLanguage>
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Description>Extension methods on crack.</Description>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl/>
<PackageTags>dotnet extension-methods</PackageTags>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<VersionPrefix>3.2.0</VersionPrefix>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' == ''">
<Version>$(VersionPrefix)-$(VersionSuffix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">
<Version>$(VersionPrefix)-$(VersionSuffix).$(BuildNumber)</Version>
<AssemblyVersion>$(VersionPrefix).$(BuildNumber)</AssemblyVersion>
<FileVersion>$(VersionPrefix).$(BuildNumber)</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' == ''">
<Version>$(VersionPrefix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DSharpPlus" Version="4.3.0" PrivateAssets="All"/>
</ItemGroup>
<ItemGroup>
<None Include="..\icon.png">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\LICENSE.md">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\CHANGELOG.md">
<Pack>True</Pack>
<PackagePath/>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1 @@
[assembly: CLSCompliant(false)]

View File

@ -0,0 +1,80 @@
using DSharpPlus;
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordChannel" />.
/// </summary>
public static class DiscordChannelExtensions
{
/// <summary>
/// Gets the category of this channel.
/// </summary>
/// <param name="channel">The channel whose category to retrieve.</param>
/// <returns>
/// The category of <paramref name="channel" />, or <paramref name="channel" /> itself if it is already a category;
/// <see langword="null" /> if this channel is not defined in a category.
/// </returns>
/// <exception cref="ArgumentNullException"><paramref name="channel" /> is <see langword="null" />.</exception>
public static DiscordChannel? GetCategory(this DiscordChannel channel)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(channel);
#else
if (channel is null)
{
throw new ArgumentNullException(nameof(channel));
}
#endif
while (true)
{
if (channel.IsCategory)
{
return channel;
}
if (channel.Parent is not { } parent)
{
return null;
}
channel = parent;
}
}
/// <summary>
/// Normalizes a <see cref="DiscordChannel" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="channel">The <see cref="DiscordChannel" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordChannel" /> whose public values will match <paramref name="channel" />, but whose internal client
/// is <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="channel" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordChannel> NormalizeClientAsync(this DiscordChannel channel, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(channel);
ArgumentNullException.ThrowIfNull(client);
#else
if (channel is null)
{
throw new ArgumentNullException(nameof(channel));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
return await client.GetChannelAsync(channel.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,79 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordClient" />.
/// </summary>
public static class DiscordClientExtensions
{
/// <summary>
/// Instructs the client to automatically join all existing threads, and any newly-created threads.
/// </summary>
/// <param name="client">The <see cref="DiscordClient" /> whose events should be subscribed.</param>
/// <param name="rejoinIfRemoved">
/// <see langword="true" /> to automatically rejoin a thread if this client was removed; otherwise,
/// <see langword="false" />.
/// </param>
/// <exception cref="ArgumentNullException"><paramref name="client" /> is <see langword="null" />.</exception>
public static void AutoJoinThreads(this DiscordClient client, bool rejoinIfRemoved = true)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(client);
#else
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
client.GuildAvailable += (_, args) => args.Guild.JoinAllThreadsAsync();
client.ThreadCreated += (_, args) => args.Thread.JoinThreadAsync();
if (rejoinIfRemoved)
{
client.ThreadMembersUpdated += (_, args) =>
{
if (args.RemovedMembers.Any(m => m.Id == client.CurrentUser.Id))
return args.Thread.JoinThreadAsync();
return Task.CompletedTask;
};
}
}
/// <summary>
/// Gets a user by their ID. If the user is not found, <see langword="null" /> is returned instead of
/// <see cref="NotFoundException" /> being thrown.
/// </summary>
/// <param name="client">The Discord client.</param>
/// <param name="userId">The ID of the user to retrieve.</param>
/// <exception cref="ArgumentNullException"><paramref name="client" /> is <see langword="null" />.</exception>
public static async Task<DiscordUser?> GetUserOrNullAsync(this DiscordClient client, ulong userId)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(client);
#else
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
try
{
// we should never use exceptions for flow control but this is D#+ we're talking about.
// NotFoundException isn't even documented, and yet it gets thrown when a user doesn't exist.
// so this method should hopefully clearly express that - and at least using exceptions for flow control *here*,
// removes the need to do the same in consumer code.
// god I hate this.
return await client.GetUserAsync(userId).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
}

View File

@ -0,0 +1,239 @@
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordEmbedBuilder" />.
/// </summary>
public static class DiscordEmbedBuilderExtensions
{
/// <summary>
/// Adds a field of any value type to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="value">The value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="builder" /> is <see langword="null" />.</exception>
public static DiscordEmbedBuilder AddField<T>(
this DiscordEmbedBuilder builder,
string name,
T? value,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
#endif
return builder.AddField(name, value?.ToString(), inline);
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="condition">The condition whose value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="value">The value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="builder" /> is <see langword="null" />.</exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
bool condition,
string name,
T? value,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
#endif
if (condition)
{
builder.AddField(name, value?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="predicate">The predicate whose return value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="value">The value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="predicate" /> is <see langword="null" />.</para>
/// </exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
Func<bool> predicate,
string name,
T? value,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(predicate);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (predicate is null)
{
throw new ArgumentNullException(nameof(predicate));
}
#endif
if (predicate.Invoke())
{
builder.AddField(name, value?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="predicate">The predicate whose return value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="valueFactory">The delegate whose return value will be used as the value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The return type of <paramref name="valueFactory" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="predicate" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="valueFactory" /> is <see langword="null" />.</para>
/// </exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
Func<bool> predicate,
string name,
Func<T?> valueFactory,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(predicate);
ArgumentNullException.ThrowIfNull(valueFactory);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (predicate is null)
{
throw new ArgumentNullException(nameof(predicate));
}
if (valueFactory is null)
{
throw new ArgumentNullException(nameof(valueFactory));
}
#endif
if (predicate.Invoke())
{
builder.AddField(name, valueFactory.Invoke()?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Conditionally adds a field to the embed.
/// </summary>
/// <param name="builder">The <see cref="DiscordEmbedBuilder" /> to modify.</param>
/// <param name="condition">The condition whose value is used to determine whether the field will be added.</param>
/// <param name="name">The name of the embed field.</param>
/// <param name="valueFactory">The delegate whose return value will be used as the value of the embed field.</param>
/// <param name="inline"><see langword="true" /> to display this field inline; otherwise, <see langword="false" />.</param>
/// <typeparam name="T">The return type of <paramref name="valueFactory" />.</typeparam>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />; that is, <paramref name="builder" />.</returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="builder" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="valueFactory" /> is <see langword="null" />.</para>
/// </exception>
public static DiscordEmbedBuilder AddFieldIf<T>(
this DiscordEmbedBuilder builder,
bool condition,
string name,
Func<T?> valueFactory,
bool inline = false)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(valueFactory);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (valueFactory is null)
{
throw new ArgumentNullException(nameof(valueFactory));
}
#endif
if (condition)
{
builder.AddField(name, valueFactory.Invoke()?.ToString(), inline);
}
return builder;
}
/// <summary>
/// Sets the embed's author.
/// </summary>
/// <param name="builder">The embed builder to modify.</param>
/// <param name="user">The author.</param>
/// <returns>The current instance of <see cref="DiscordEmbedBuilder" />.</returns>
public static DiscordEmbedBuilder WithAuthor(this DiscordEmbedBuilder builder, DiscordUser user)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(builder);
ArgumentNullException.ThrowIfNull(user);
#else
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
#endif
return builder.WithAuthor(user.GetUsernameWithDiscriminator(), iconUrl: user.AvatarUrl);
}
}

View File

@ -0,0 +1,97 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordGuild" />.
/// </summary>
public static class DiscordGuildExtensions
{
/// <summary>
/// Joins all active threads in the guild that this client has permission to view.
/// </summary>
/// <param name="guild">The guild whose active threads to join.</param>
/// <exception cref="ArgumentNullException"><paramref name="guild" /> is <see langword="null" />.</exception>
public static async Task JoinAllThreadsAsync(this DiscordGuild guild)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(guild);
#else
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
await Task.WhenAll(guild.Threads.Values.Select(t => t.JoinThreadAsync())).ConfigureAwait(false);
}
/// <summary>
/// Gets a guild member by their ID. If the member is not found, <see langword="null" /> is returned instead of
/// <see cref="NotFoundException" /> being thrown.
/// </summary>
/// <param name="guild">The guild whose member list to search.</param>
/// <param name="userId">The ID of the member to retrieve.</param>
/// <exception cref="ArgumentNullException"><paramref name="guild" /> is <see langword="null" />.</exception>
public static async Task<DiscordMember?> GetMemberOrNullAsync(this DiscordGuild guild, ulong userId)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(guild);
#else
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
try
{
// we should never use exceptions for flow control but this is D#+ we're talking about.
// NotFoundException isn't even documented, and yet it gets thrown when a member doesn't exist.
// so this method should hopefully clearly express that - and at least using exceptions for flow control *here*,
// removes the need to do the same in consumer code.
// god I hate this.
return await guild.GetMemberAsync(userId).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
/// <summary>
/// Normalizes a <see cref="DiscordGuild" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="guild">The <see cref="DiscordGuild" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordGuild" /> whose public values will match <paramref name="guild" />, but whose internal client is
/// <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="guild" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordGuild> NormalizeClientAsync(this DiscordGuild guild, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(guild);
ArgumentNullException.ThrowIfNull(client);
#else
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
return await client.GetGuildAsync(guild.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,73 @@
using DSharpPlus;
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordMember" />.
/// </summary>
public static class DiscordMemberExtensions
{
/// <summary>
/// Returns a value indicating whether this member has the specified role.
/// </summary>
/// <param name="member">The member whose roles to search.</param>
/// <param name="role">The role for which to check.</param>
/// <returns>
/// <see langword="true" /> if <paramref name="member" /> has the role; otherwise, <see langword="false" />.
/// </returns>
public static bool HasRole(this DiscordMember member, DiscordRole role)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(member);
ArgumentNullException.ThrowIfNull(role);
#else
if (member is null)
{
throw new ArgumentNullException(nameof(member));
}
if (role is null)
{
throw new ArgumentNullException(nameof(role));
}
#endif
return member.Roles.Contains(role);
}
/// <summary>
/// Normalizes a <see cref="DiscordMember" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="member">The <see cref="DiscordMember" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordMember" /> whose public values will match <paramref name="member" />, but whose internal client
/// is <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="member" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordMember> NormalizeClientAsync(this DiscordMember member, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(member);
ArgumentNullException.ThrowIfNull(client);
#else
if (member is null)
{
throw new ArgumentNullException(nameof(member));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
DiscordGuild guild = await member.Guild.NormalizeClientAsync(client).ConfigureAwait(false);
return await guild.GetMemberAsync(member.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,89 @@
using DSharpPlus;
using DSharpPlus.Entities;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordMessage" />.
/// </summary>
public static class DiscordMessageExtensions
{
/// <summary>
/// Deletes this message after a specified delay.
/// </summary>
/// <param name="message">The message to delete.</param>
/// <param name="delay">The delay before deletion.</param>
/// <param name="reason">The reason for the deletion.</param>
/// <exception cref="ArgumentNullException"><paramref name="message" /> is <see langword="null" />.</exception>
public static async Task DeleteAfterAsync(this DiscordMessage message, TimeSpan delay, string? reason = null)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(message);
#else
if (message is null)
{
throw new ArgumentNullException(nameof(message));
}
#endif
await Task.Delay(delay).ConfigureAwait(false);
await message.DeleteAsync(reason).ConfigureAwait(false);
}
/// <summary>
/// Deletes the message as created by this task after a specified delay.
/// </summary>
/// <param name="task">The task whose <see cref="DiscordMessage" /> result should be deleted.</param>
/// <param name="delay">The delay before deletion.</param>
/// <param name="reason">The reason for the deletion.</param>
/// <exception cref="ArgumentNullException"><paramref name="task" /> is <see langword="null" />.</exception>
public static async Task DeleteAfterAsync(this Task<DiscordMessage> task, TimeSpan delay, string? reason = null)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(task);
#else
if (task is null)
{
throw new ArgumentNullException(nameof(task));
}
#endif
DiscordMessage message = await task.ConfigureAwait(false);
await message.DeleteAfterAsync(delay, reason).ConfigureAwait(false);
}
/// <summary>
/// Normalizes a <see cref="DiscordMessage" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="message">The <see cref="DiscordMessage" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordMessage" /> whose public values will match <paramref name="message" />, but whose internal client
/// is <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="message" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordMessage> NormalizeClientAsync(this DiscordMessage message, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(message);
ArgumentNullException.ThrowIfNull(client);
#else
if (message is null)
{
throw new ArgumentNullException(nameof(message));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
DiscordChannel channel = await message.Channel.NormalizeClientAsync(client).ConfigureAwait(false);
return await channel.GetMessageAsync(message.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,158 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
namespace X10D.DSharpPlus;
/// <summary>
/// Extension methods for <see cref="DiscordUser" />.
/// </summary>
public static class DiscordUserExtensions
{
/// <summary>
/// Returns the current <see cref="DiscordUser" /> as a member of the specified guild.
/// </summary>
/// <param name="user">The user to transform.</param>
/// <param name="guild">The guild whose member list to search.</param>
/// <returns>
/// A <see cref="DiscordMember" /> whose <see cref="DiscordMember.Guild" /> is equal to <paramref name="guild" />, or
/// <see langword="null" /> if this user is not in the specified <paramref name="guild" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="user" /> is <see langword="null" />.</para>
/// -or-
/// <para><paramref name="guild" /> is <see langword="null" />.</para>
/// </exception>
public static async Task<DiscordMember?> GetAsMemberOfAsync(this DiscordUser user, DiscordGuild guild)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
ArgumentNullException.ThrowIfNull(guild);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
if (user is DiscordMember member && member.Guild == guild)
{
return member;
}
if (guild.Members.TryGetValue(user.Id, out member!))
{
return member;
}
try
{
return await guild.GetMemberAsync(user.Id).ConfigureAwait(false);
}
catch (NotFoundException)
{
return null;
}
}
/// <summary>
/// Returns the user's username with the discriminator, in the format <c>username#discriminator</c>.
/// </summary>
/// <param name="user">The user whose username and discriminator to retrieve.</param>
/// <returns>A string in the format <c>username#discriminator</c></returns>
/// <exception cref="ArgumentNullException"><paramref name="user" /> is <see langword="null" />.</exception>
public static string GetUsernameWithDiscriminator(this DiscordUser user)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
#endif
return $"{user.Username}#{user.Discriminator}";
}
/// <summary>
/// Returns a value indicating whether the current user is in the specified guild.
/// </summary>
/// <param name="user">The user to check.</param>
/// <param name="guild">The guild whose member list to search.</param>
/// <returns>
/// <see langword="true" /> if <paramref name="user" /> is a member of <paramref name="guild" />; otherwise,
/// <see langword="false" />.
/// </returns>
public static async Task<bool> IsInGuildAsync(this DiscordUser user, DiscordGuild guild)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
ArgumentNullException.ThrowIfNull(guild);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
if (guild is null)
{
throw new ArgumentNullException(nameof(guild));
}
#endif
if (guild.Members.TryGetValue(user.Id, out _))
{
return true;
}
try
{
DiscordMember? member = await guild.GetMemberAsync(user.Id).ConfigureAwait(false);
return member is not null;
}
catch (NotFoundException)
{
return false;
}
}
/// <summary>
/// Normalizes a <see cref="DiscordUser" /> so that the internal client is assured to be a specified value.
/// </summary>
/// <param name="user">The <see cref="DiscordUser" /> to normalize.</param>
/// <param name="client">The target client.</param>
/// <returns>
/// A <see cref="DiscordUser" /> whose public values will match <paramref name="user" />, but whose internal client is
/// <paramref name="client" />.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="user" /> is <see langword="null" /></para>
/// -or-
/// <para><paramref name="client" /> is <see langword="null" /></para>
/// </exception>
public static async Task<DiscordUser> NormalizeClientAsync(this DiscordUser user, DiscordClient client)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(user);
ArgumentNullException.ThrowIfNull(client);
#else
if (user is null)
{
throw new ArgumentNullException(nameof(user));
}
if (client is null)
{
throw new ArgumentNullException(nameof(client));
}
#endif
return await client.GetUserAsync(user.Id).ConfigureAwait(false);
}
}

View File

@ -0,0 +1,329 @@
using System.Globalization;
namespace X10D.DSharpPlus;
/// <summary>
/// Provides methods for encoding and decoding Discord mention strings.
/// </summary>
/// <remarks>
/// The implementations in this class are designed to resemble <c>MentionUtils</c> as provided by Discord.NET. The source is
/// available
/// <a href="https://github.com/discord-net/Discord.Net/blob/dev/src/Discord.Net.Core/Utils/MentionUtils.cs">
/// here
/// </a>.
/// </remarks>
public static class MentionUtility
{
/// <summary>
/// Returns a channel mention string built from the specified channel ID.
/// </summary>
/// <param name="id">The ID of the channel to mention.</param>
/// <returns>A channel mention string in the format <c>&lt;#123&gt;</c>.</returns>
public static string MentionChannel(decimal id)
{
return $"<#{id:N0}>";
}
/// <summary>
/// Returns a channel mention string built from the specified channel ID.
/// </summary>
/// <param name="id">The ID of the channel to mention.</param>
/// <returns>A channel mention string in the format <c>&lt;#123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionChannel(ulong id)
{
return $"<#{id}>";
}
/// <summary>
/// Returns a role mention string built from the specified channel ID.
/// </summary>
/// <param name="id">The ID of the role to mention.</param>
/// <returns>A role mention string in the format <c>&lt;@&amp;123&gt;</c>.</returns>
public static string MentionRole(decimal id)
{
return $"<@&{id:N0}>";
}
/// <summary>
/// Returns a role mention string built from the specified role ID.
/// </summary>
/// <param name="id">The ID of the role to mention.</param>
/// <returns>A role mention string in the format <c>&lt;@&amp;123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionRole(ulong id)
{
return $"<@&{id}>";
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <returns>A user mention string in the format <c>&lt;@123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionUser(decimal id)
{
return MentionUser(id, false);
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <param name="nickname">
/// <see langword="true" /> if the mention string should account for nicknames; otherwise, <see langword="false" />.
/// </param>
/// <returns>
/// A user mention string in the format <c>&lt;@!123&gt;</c> if <paramref name="nickname" /> is <see langword="true" />,
/// or in the format <c>&lt;@123&gt;</c> if <paramref name="nickname" /> is <see langword="false" />.
/// </returns>
[CLSCompliant(false)]
public static string MentionUser(decimal id, bool nickname)
{
return nickname ? $"<@!{id:N0}>" : $"<@{id:N0}>";
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <returns>A user mention string in the format <c>&lt;@123&gt;</c>.</returns>
[CLSCompliant(false)]
public static string MentionUser(ulong id)
{
return MentionUser(id, false);
}
/// <summary>
/// Returns a user mention string built from the specified user ID.
/// </summary>
/// <param name="id">The ID of the user to mention.</param>
/// <param name="nickname">
/// <see langword="true" /> if the mention string should account for nicknames; otherwise, <see langword="false" />.
/// </param>
/// <returns>
/// A user mention string in the format <c>&lt;@!123&gt;</c> if <paramref name="nickname" /> is <see langword="true" />,
/// or in the format <c>&lt;@123&gt;</c> if <paramref name="nickname" /> is <see langword="false" />.
/// </returns>
[CLSCompliant(false)]
public static string MentionUser(ulong id, bool nickname)
{
return nickname ? $"<@!{id}>" : $"<@{id}>";
}
/// <summary>
/// Parses a provided channel mention string to a decimal value representing the channel ID. A return value indicates
/// whether the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;#123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the decimal value representing the channel ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
public static bool TryParseChannel(string? value, out decimal result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '#' || value[^1] != '>')
{
return false;
}
value = value.Substring(2, value.Length - 3); // <#123>
if (!ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong actual))
{
return false;
}
result = actual;
return true;
}
/// <summary>
/// Parses a provided channel mention string to a 64-bit unsigned integer representing the channel ID. A return value
/// indicates whether the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;#123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the 64-bit unsigned integer value representing the channel ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
[CLSCompliant(false)]
public static bool TryParseChannel(string? value, out ulong result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '#' || value[^1] != '>')
{
return false;
}
value = value.Substring(2, value.Length - 3); // <#123>
return ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
/// <summary>
/// Parses a provided role mention string to a decimal value representing the role ID. A return value indicates whether
/// the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;@&amp;123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the decimal value representing the role ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
public static bool TryParseRole(string? value, out decimal result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 4 || value[0] != '<' || value[1] != '@' || value[2] != '&' || value[^1] != '>')
{
return false;
}
value = value.Substring(3, value.Length - 4); // <@&123>
if (!ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong actual))
{
return false;
}
result = actual;
return true;
}
/// <summary>
/// Parses a provided role mention string to a 64-bit unsigned integer representing the role ID. A return value indicates
/// whether the parse succeeded.
/// </summary>
/// <param name="value">A string containing a mention string to parse, in the format <c>&lt;@&amp;123&gt;</c>.</param>
/// <param name="result">
/// When this method returns, contains the 64-bit unsigned integer value representing the role ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
[CLSCompliant(false)]
public static bool TryParseRole(string? value, out ulong result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 4 || value[0] != '<' || value[1] != '@' || value[2] != '&' || value[^1] != '>')
{
return false;
}
value = value.Substring(3, value.Length - 4); // <@&123>
return ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
/// <summary>
/// Parses a provided user mention string to a decimal value representing the user ID. A return value indicates whether
/// the parse succeeded.
/// </summary>
/// <param name="value">
/// A string containing a mention string to parse, in the format <c>&lt;@123&gt;</c> or <c>&lt;@!123&gt;</c>.
/// </param>
/// <param name="result">
/// When this method returns, contains the decimal value representing the user ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
public static bool TryParseUser(string? value, out decimal result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '@' || value[^1] != '>')
{
return false;
}
if (value.Length >= 4 && value[2] == '!')
{
value = value.Substring(3, value.Length - 4); // <@!123>
}
else
{
value = value.Substring(2, value.Length - 3); // <@123>
}
if (!ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong actual))
{
return false;
}
result = actual;
return true;
}
/// <summary>
/// Parses a provided user mention string to a 64-bit unsigned integer representing the user ID. A return value indicates
/// whether the parse succeeded.
/// </summary>
/// <param name="value">
/// A string containing a mention string to parse, in the format <c>&lt;@123&gt;</c> or <c>&lt;@!123&gt;</c>.
/// </param>
/// <param name="result">
/// When this method returns, contains the 64-bit unsigned integer value representing the user ID contained within
/// <paramref name="value" />, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the
/// <paramref name="value" /> parameter is <see langword="null" /> or <see cref="string.Empty" />, is not of the correct
/// format, or represents a number less than <see cref="ulong.MinValue" /> or greater than <see cref="ulong.MaxValue" />.
/// </param>
/// <returns><see langword="true" /> if the parse was successful; otherwise, <see langword="false" />.</returns>
[CLSCompliant(false)]
public static bool TryParseUser(string? value, out ulong result)
{
result = 0;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
if (value.Length < 3 || value[0] != '<' || value[1] != '@' || value[^1] != '>')
{
return false;
}
if (value.Length >= 4 && value[2] == '!')
{
value = value.Substring(3, value.Length - 4); // <@!123>
}
else
{
value = value.Substring(2, value.Length - 3); // <@123>
}
return ulong.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
}

View File

@ -0,0 +1,65 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0;net6.0;netstandard2.1</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<Optimize>true</Optimize>
<ImplicitUsings>true</ImplicitUsings>
<Authors>Oliver Booth</Authors>
<NeutralLanguage>en</NeutralLanguage>
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Description>Extension methods on crack.</Description>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl/>
<PackageTags>dotnet extension-methods</PackageTags>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<VersionPrefix>3.2.0</VersionPrefix>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' == ''">
<Version>$(VersionPrefix)-$(VersionSuffix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''">
<Version>$(VersionPrefix)-$(VersionSuffix).$(BuildNumber)</Version>
<AssemblyVersion>$(VersionPrefix).$(BuildNumber)</AssemblyVersion>
<FileVersion>$(VersionPrefix).$(BuildNumber)</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(VersionSuffix)' == ''">
<Version>$(VersionPrefix)</Version>
<AssemblyVersion>$(VersionPrefix).0</AssemblyVersion>
<FileVersion>$(VersionPrefix).0</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0"/>
</ItemGroup>
<ItemGroup>
<None Include="..\icon.png">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\LICENSE.md">
<Pack>True</Pack>
<PackagePath/>
</None>
<None Include="..\CHANGELOG.md">
<Pack>True</Pack>
<PackagePath/>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1 @@
[assembly: CLSCompliant(true)]

View File

@ -0,0 +1,35 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace X10D.Hosting.DependencyInjection;
/// <summary>
/// Dependency injection extensions for <see cref="IServiceCollection" />.
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds an <see cref="IHostedService" /> registration for the given type, while simultaneously adding it as a singleton.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add the service to.</param>
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <returns>A reference to this instance after the operation has completed.</returns>
public static IServiceCollection AddHostedSingleton<TService>(this IServiceCollection services)
where TService : class, IHostedService
{
services.AddSingleton<TService>();
return services.AddSingleton<IHostedService, TService>(provider => provider.GetRequiredService<TService>());
}
/// <summary>
/// Adds an <see cref="IHostedService" /> registration for the given type, while simultaneously adding it as a singleton.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add the service to.</param>
/// <param name="type">The type of the service to register and the implementation to use.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
public static IServiceCollection AddHostedSingleton(this IServiceCollection services, Type type)
{
services.AddSingleton(type);
return services.AddSingleton(provider => (IHostedService)provider.GetRequiredService(type));
}
}

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.1;net6.0</TargetFrameworks>
<TargetFrameworks>net7.0;net6.0;netstandard2.1</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>

View File

@ -1,11 +1,40 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
using X10D.Core;
namespace X10D.Tests.Collections;
[TestClass]
public class EnumerableTests
{
[TestMethod]
public void CountWhereNot_ShouldReturnCorrectCount_GivenSequence()
{
var enumerable = new[] {2, 4, 6, 7, 8, 9, 10};
int count = enumerable.CountWhereNot(x => x % 2 == 0);
Assert.AreEqual(2, count);
}
[TestMethod]
public void CountWhereNot_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IEnumerable<int>?)null)!.CountWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void CountWhereNot_ShouldThrowOverflowException_GivenLargeSource()
{
IEnumerable<byte> GetValues()
{
while (true)
{
yield return 1;
}
}
Assert.ThrowsException<OverflowException>(() => GetValues().CountWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void DisposeAll_ShouldDispose_GivenCollection()
{
@ -36,6 +65,72 @@ public class EnumerableTests
await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => await collection!.DisposeAllAsync());
}
[TestMethod]
public void FirstWhereNot_ShouldReturnCorrectElements_GivenSequence()
{
var enumerable = new[] {2, 4, 6, 7, 8, 9, 10};
int result = enumerable.FirstWhereNot(x => x % 2 == 0);
Assert.AreEqual(7, result);
}
[TestMethod]
public void FirstWhereNot_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IEnumerable<int>?)null)!.FirstWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void FirstWhereNot_ShouldThrowArgumentNullException_GivenNullPredicate()
{
Assert.ThrowsException<ArgumentNullException>(() => Array.Empty<int>().FirstWhereNotOrDefault(null!));
}
[TestMethod]
public void FirstWhereNot_ShouldThrowInvalidOperationException_GivenEmptySource()
{
Assert.ThrowsException<InvalidOperationException>(() => Array.Empty<int>().FirstWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void FirstWhereNot_ShouldThrowInvalidOperationException_GivenSourceWithNoMatchingElements()
{
Assert.ThrowsException<InvalidOperationException>(() => 2.AsArrayValue().FirstWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void FirstWhereNotOrDefault_ShouldReturnCorrectElements_GivenSequence()
{
var enumerable = new[] {2, 4, 6, 7, 8, 9, 10};
int result = enumerable.FirstWhereNotOrDefault(x => x % 2 == 0);
Assert.AreEqual(7, result);
}
[TestMethod]
public void FirstWhereNotOrDefault_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IEnumerable<int>?)null)!.FirstWhereNotOrDefault(x => x % 2 == 0));
}
[TestMethod]
public void FirstWhereNotOrDefault_ShouldThrowArgumentNullException_GivenNullPredicate()
{
Assert.ThrowsException<ArgumentNullException>(() => Array.Empty<int>().FirstWhereNotOrDefault(null!));
}
[TestMethod]
public void FirstWhereNotOrDefault_ShouldReturnDefault_GivenEmptySource()
{
int result = Array.Empty<int>().FirstWhereNotOrDefault(x => x % 2 == 0);
Assert.AreEqual(default, result);
}
[TestMethod]
public void FirstWhereNotOrDefault_ShouldReturnDefault_GivenSourceWithNoMatchingElements()
{
int result = 2.AsArrayValue().FirstWhereNotOrDefault(x => x % 2 == 0);
Assert.AreEqual(default, result);
}
[TestMethod]
public void For_ShouldTransform_GivenTransformationDelegate()
{
@ -94,6 +189,72 @@ public class EnumerableTests
Assert.ThrowsException<ArgumentNullException>(() => source.ForEach(null!));
}
[TestMethod]
public void LastWhereNot_ShouldReturnCorrectElements_GivenSequence()
{
var enumerable = new[] {2, 4, 6, 7, 8, 9, 10};
int result = enumerable.LastWhereNot(x => x % 2 == 0);
Assert.AreEqual(9, result);
}
[TestMethod]
public void LastWhereNot_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IEnumerable<int>?)null)!.LastWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void LastWhereNot_ShouldThrowArgumentNullException_GivenNullPredicate()
{
Assert.ThrowsException<ArgumentNullException>(() => Array.Empty<int>().LastWhereNot(null!));
}
[TestMethod]
public void LastWhereNot_ShouldThrowInvalidOperationException_GivenEmptySource()
{
Assert.ThrowsException<InvalidOperationException>(() => Array.Empty<int>().LastWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void LastWhereNot_ShouldThrowInvalidOperationException_GivenSourceWithNoMatchingElements()
{
Assert.ThrowsException<InvalidOperationException>(() => 2.AsArrayValue().LastWhereNot(x => x % 2 == 0));
}
[TestMethod]
public void LastWhereNotOrDefault_ShouldReturnCorrectElements_GivenSequence()
{
var enumerable = new[] {2, 4, 6, 7, 8, 9, 10};
int result = enumerable.LastWhereNotOrDefault(x => x % 2 == 0);
Assert.AreEqual(9, result);
}
[TestMethod]
public void LastWhereNotOrDefault_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IEnumerable<int>?)null)!.LastWhereNotOrDefault(x => x % 2 == 0));
}
[TestMethod]
public void LastWhereNotOrDefault_ShouldThrowArgumentNullException_GivenNullPredicate()
{
Assert.ThrowsException<ArgumentNullException>(() => Array.Empty<int>().LastWhereNotOrDefault(null!));
}
[TestMethod]
public void LastWhereNotOrDefault_ShouldReturnDefault_GivenEmptySource()
{
int result = Array.Empty<int>().LastWhereNotOrDefault(x => x % 2 == 0);
Assert.AreEqual(default, result);
}
[TestMethod]
public void LastWhereNotOrDefault_ShouldReturnDefault_GivenSourceWithNoMatchingElements()
{
int result = 2.AsArrayValue().LastWhereNotOrDefault(x => x % 2 == 0);
Assert.AreEqual(default, result);
}
[TestMethod]
public void Shuffled_ShouldThrow_GivenNull()
{
@ -112,6 +273,41 @@ public class EnumerableTests
CollectionAssert.AreNotEqual(array, shuffled);
}
[TestMethod]
public void WhereNot_ShouldReturnCorrectElements_GivenSequence()
{
var enumerable = new[] {2, 4, 6, 7, 8, 9, 10};
IEnumerable<int> result = enumerable.WhereNot(x => x % 2 == 0);
CollectionAssert.AreEqual(new[] {7, 9}, result.ToArray());
}
[TestMethod]
public void WhereNot_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IEnumerable<int>?)null)!.WhereNot(x => x % 2 == 0));
}
[TestMethod]
public void WhereNotNull_ShouldContainNoNullElements()
{
object?[] array = Enumerable.Repeat(new object(), 10).ToArray();
array[1] = null;
array[2] = null;
array[8] = null;
array[9] = null;
const int expectedCount = 6;
var actualCount = 0;
foreach (object o in array.WhereNotNull())
{
Assert.IsNotNull(o);
actualCount++;
}
Assert.AreEqual(expectedCount, actualCount);
}
private class DummyClass
{
public int Value { get; set; }

View File

@ -10,7 +10,7 @@ public class Int16Tests
public void UnpackBits_ShouldUnpackToArrayCorrectly()
{
bool[] bits = ((short)0b11010100).Unpack();
Assert.AreEqual(16, bits.Length);
Assert.IsFalse(bits[0]);

View File

@ -10,7 +10,7 @@ public class Int32Tests
public void UnpackBits_ShouldUnpackToArrayCorrectly()
{
bool[] bits = 0b11010100.Unpack();
Assert.AreEqual(32, bits.Length);
Assert.IsFalse(bits[0]);

View File

@ -79,6 +79,124 @@ public class ListTests
Assert.ThrowsException<ArgumentNullException>(() => list!.Fill(0, 0, 0));
}
[TestMethod]
public void IndexOf_ShouldReturnCorrectValue_FromStartOfList()
{
int[] array = {0, 1, 2, 3, 4};
Assert.AreEqual(2, array.IndexOf(2));
Assert.AreEqual(2, array.IndexOf(2, 0));
Assert.AreEqual(2, array.IndexOf(2, 0, 5));
}
[TestMethod]
public void IndexOf_ShouldReturnCorrectValue_GivenSubRange()
{
int[] array = {0, 1, 2, 3, 4, 0};
Assert.AreEqual(0, array.IndexOf(0));
Assert.AreEqual(0, array.IndexOf(0, 0));
Assert.AreEqual(0, array.IndexOf(0, 0, 5));
Assert.AreEqual(5, array.IndexOf(0, 1));
Assert.AreEqual(5, array.IndexOf(0, 1, 5));
}
[TestMethod]
public void IndexOf_ShouldReturnNegative1_ForEmptyList()
{
int[] array = Array.Empty<int>();
Assert.AreEqual(-1, array.IndexOf(0));
Assert.AreEqual(-1, array.IndexOf(0, 0));
Assert.AreEqual(-1, array.IndexOf(0, 0, 0));
}
[TestMethod]
public void IndexOf_ShouldThrowArgumentNullException_GivenNullList()
{
int[]? array = null;
Assert.ThrowsException<ArgumentNullException>(() => array!.IndexOf(0));
Assert.ThrowsException<ArgumentNullException>(() => array!.IndexOf(0, 0));
Assert.ThrowsException<ArgumentNullException>(() => array!.IndexOf(0, 0, 0));
}
[TestMethod]
public void IndexOf_ShouldThrowArgumentOutOfRangeException_GivenNegativeCount()
{
int[] array = Array.Empty<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.IndexOf(0, 0, -1));
}
[TestMethod]
public void IndexOf_ShouldThrowArgumentOutOfRangeException_GivenNegativeStartIndex()
{
int[] array = Array.Empty<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.IndexOf(0, -1));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.IndexOf(0, -1, 0));
}
[TestMethod]
public void IndexOf_ShouldThrowArgumentOutOfRangeException_GivenInvalidStartIndexCountPair()
{
int[] array = {0, 1, 2};
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.IndexOf(0, 2, 4));
}
[TestMethod]
public void Random_ShouldReturnContainedObject_GivenNotNull()
{
var list = new List<int>(Enumerable.Range(1, 52)); // 52! chance of being shuffled to the same order
int random = list.Random();
Assert.IsTrue(list.Contains(random));
}
[TestMethod]
public void Random_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((List<int>?)null)!.Random());
}
[TestMethod]
public void RemoveRange_ShouldThrowArgumentNullException_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((List<int>?)null)!.RemoveRange(new Range()));
}
[TestMethod]
public void RemoveRange_ShouldThrowArgumentException_GivenEndIndexLessThanStart()
{
Assert.ThrowsException<ArgumentException>(() => new List<int>().RemoveRange(2..0));
}
[TestMethod]
public void RemoveRange_ShouldThrowArgumentOutOfRangeException_GivenEndIndexGreaterThanOrEqualToCount()
{
Assert.ThrowsException<ArgumentOutOfRangeException>(() => new List<int>().RemoveRange(..0));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => new List<int> {1}.RemoveRange(..2));
}
[TestMethod]
public void RemoveRange_ShouldRemoveElements_GivenList()
{
var list = new List<int>
{
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
};
Assert.AreEqual(10, list.Count);
list.RemoveRange(2..5);
Assert.AreEqual(6, list.Count);
CollectionAssert.AreEqual(new[] {1, 2, 7, 8, 9, 10}, list);
}
[TestMethod]
public void Shuffle_ShouldReorder_GivenNotNull()
{
@ -99,17 +217,107 @@ public class ListTests
}
[TestMethod]
public void Random_ShouldReturnContainedObject_GivenNotNull()
public void Slice_ShouldReturnCorrectValue_GivenStartIndex()
{
var list = new List<int>(Enumerable.Range(1, 52)); // 52! chance of being shuffled to the same order
int random = list.Random();
Assert.IsTrue(list.Contains(random));
int[] array = {0, 1, 2, 3, 4, 5};
CollectionAssert.AreEqual(new[] {2, 3, 4, 5}, array.Slice(2).ToArray());
}
[TestMethod]
public void Random_ShouldThrow_GivenNull()
public void Slice_ShouldReturnCorrectValue_GivenStartIndexAndLength()
{
Assert.ThrowsException<ArgumentNullException>(() => ((List<int>?)null)!.Random());
int[] array = {0, 1, 2, 3, 4, 5};
CollectionAssert.AreEqual(new[] {2, 3, 4}, array.Slice(2, 3).ToArray());
}
[TestMethod]
public void Slice_ShouldReturnEmptyList_ForEmptyList()
{
int[] array = Array.Empty<int>();
CollectionAssert.AreEqual(Array.Empty<int>(), array.Slice(0).ToArray());
CollectionAssert.AreEqual(Array.Empty<int>(), array.Slice(0, 0).ToArray());
}
[TestMethod]
public void Slice_ShouldThrowArgumentNullException_GivenNullList()
{
int[]? array = null;
Assert.ThrowsException<ArgumentNullException>(() => array!.Slice(0));
Assert.ThrowsException<ArgumentNullException>(() => array!.Slice(0, 0));
}
[TestMethod]
public void Slice_ShouldThrowArgumentOutOfRangeException_GivenNegativeCount()
{
int[] array = Array.Empty<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(0, -1));
}
[TestMethod]
public void Slice_ShouldThrowArgumentOutOfRangeException_GivenNegativeStartIndex()
{
int[] array = Array.Empty<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(-1));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(-1, 0));
}
[TestMethod]
public void Slice_ShouldThrowArgumentOutOfRangeException_GivenInvalidStartIndexCountPair()
{
int[] array = {0, 1, 2};
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Slice(2, 4));
}
[TestMethod]
public void Swap_ShouldThrowArgumentNullException_GivenNullSource()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IList<int>?)null)!.Swap(new List<int>()));
}
[TestMethod]
public void Swap_ShouldThrowArgumentNullException_GivenNullTarget()
{
Assert.ThrowsException<ArgumentNullException>(() => new List<int>().Swap(null!));
}
[TestMethod]
public void Swap_ShouldSwapElements_GivenMatchingElementCount()
{
var first = new List<int> {1, 2, 3};
var second = new List<int> {4, 5, 6};
first.Swap(second);
CollectionAssert.AreEqual(new[] {4, 5, 6}, first, string.Join(' ', first));
CollectionAssert.AreEqual(new[] {1, 2, 3}, second, string.Join(' ', second));
first.Swap(second);
CollectionAssert.AreEqual(new[] {1, 2, 3}, first, string.Join(' ', first));
CollectionAssert.AreEqual(new[] {4, 5, 6}, second, string.Join(' ', second));
}
[TestMethod]
public void Swap_ShouldSwapElements_GivenDifferentElementCount()
{
var first = new List<int>
{
1,
2,
3,
4,
5
};
var second = new List<int> {6, 7};
first.Swap(second);
CollectionAssert.AreEqual(new[] {6, 7}, first, string.Join(' ', first));
CollectionAssert.AreEqual(new[] {1, 2, 3, 4, 5}, second, string.Join(' ', second));
first.Swap(second);
CollectionAssert.AreEqual(new[] {1, 2, 3, 4, 5}, first, string.Join(' ', first));
CollectionAssert.AreEqual(new[] {6, 7}, second, string.Join(' ', second));
}
}

View File

@ -0,0 +1,91 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class SpanTest
{
[TestMethod]
public void Split_OnEmptySpan_ShouldYieldNothing()
{
ReadOnlySpan<char> span = ReadOnlySpan<char>.Empty;
var index = 0;
foreach (ReadOnlySpan<char> unused in span.Split(' '))
{
index++;
}
Assert.AreEqual(0, index);
}
[TestMethod]
public void Split_OnOneWord_ShouldYieldLength1()
{
ReadOnlySpan<char> span = "Hello ".AsSpan();
var index = 0;
foreach (ReadOnlySpan<char> subSpan in span.Split(' '))
{
if (index == 0)
{
Assert.AreEqual("Hello", subSpan.ToString());
}
index++;
}
Assert.AreEqual(1, index);
}
[TestMethod]
public void Split_OnTwoWords_ShouldYieldLength2()
{
ReadOnlySpan<char> span = "Hello World ".AsSpan();
var index = 0;
foreach (ReadOnlySpan<char> subSpan in span.Split(' '))
{
if (index == 0)
{
Assert.AreEqual("Hello", subSpan.ToString());
}
else if (index == 1)
{
Assert.AreEqual("World", subSpan.ToString());
}
index++;
}
Assert.AreEqual(2, index);
}
[TestMethod]
public void Split_OnThreeWords_ShouldYieldLength3()
{
ReadOnlySpan<char> span = "Hello, the World ".AsSpan();
var index = 0;
foreach (ReadOnlySpan<char> subSpan in span.Split(' '))
{
if (index == 0)
{
Assert.AreEqual("Hello,", subSpan.ToString());
}
else if (index == 1)
{
Assert.AreEqual("the", subSpan.ToString());
}
else if (index == 2)
{
Assert.AreEqual("World", subSpan.ToString());
}
index++;
}
Assert.AreEqual(3, index);
}
}

View File

@ -11,7 +11,7 @@ public class EnumTests
// it's clearly Monday as defined by ISO 8601.
// but Microsoft can't fix this without breaking compatibility.
// I have feelings...
[TestMethod]
public void Next()
{
@ -23,7 +23,7 @@ public class EnumTests
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Friday.Next());
Assert.AreEqual(DayOfWeek.Sunday, DayOfWeek.Saturday.Next()); // Saturday is the "last" day. wrap to "first"
}
[TestMethod]
public void NextUnchecked()
{
@ -35,7 +35,7 @@ public class EnumTests
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Friday.NextUnchecked());
Assert.ThrowsException<IndexOutOfRangeException>(() => DayOfWeek.Saturday.NextUnchecked());
}
[TestMethod]
public void Previous()
{
@ -47,7 +47,7 @@ public class EnumTests
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Friday.Previous());
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Saturday.Previous());
}
[TestMethod]
public void PreviousUnchecked()
{

View File

@ -0,0 +1,24 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
namespace X10D.Tests.Core;
[TestClass]
public class NullableTests
{
[TestMethod]
public void TryGetValue_ShouldBeTrue_GivenValue()
{
int? value = 42;
Assert.IsTrue(value.TryGetValue(out int returnedValue));
Assert.AreEqual(value, returnedValue);
}
[TestMethod]
public void TryGetValue_ShouldBeFalse_GivenNull()
{
int? value = null;
Assert.IsFalse(value.TryGetValue(out int returnedValue));
Assert.AreEqual(default, returnedValue);
}
}

View File

@ -1,4 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
using X10D.Core;
namespace X10D.Tests.Core;
@ -126,6 +127,48 @@ public class RandomTests
Assert.AreEqual(0, random.NextFrom(Source()));
}
[TestMethod]
public void NextFromSpan_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() =>
{
Span<int> span = stackalloc int[1];
return random!.NextFrom(span);
});
}
[TestMethod]
public void NextFromReadOnlySpan_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() =>
{
Span<int> span = stackalloc int[1];
return random!.NextFrom(span.AsReadOnly());
});
}
[TestMethod]
public void NextFromSpan_ShouldReturnOnlyValue_GivenSpanWithLength1()
{
Span<int> span = stackalloc int[1];
span[0] = 42;
var random = new Random(1234);
Assert.AreEqual(42, random.NextFrom(span));
}
[TestMethod]
public void NextFromReadOnlySpan_ShouldReturnOnlyValue_GivenSpanWithLength1()
{
Span<int> span = stackalloc int[1];
span[0] = 42;
var random = new Random(1234);
Assert.AreEqual(42, random.NextFrom(span.AsReadOnly()));
}
[TestMethod]
public void NextInt16_ShouldBe13076_GivenSeed1234()
{

View File

@ -0,0 +1,151 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class CircleFTests
{
[TestMethod]
public void Area_ShouldBePiRadiusRadius_GivenUnitCircle()
{
var unitCircle = CircleF.Unit;
Assert.AreEqual(MathF.PI, unitCircle.Area);
}
[TestMethod]
public void Circumference_ShouldBe2PiRadius_GivenUnitCircle()
{
var unitCircle = CircleF.Unit;
Assert.AreEqual(2 * MathF.PI, unitCircle.Circumference, 1e-6f);
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenUnitCircleAndEmpty()
{
Assert.AreEqual(-1, CircleF.Empty.CompareTo(CircleF.Unit));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenUnitCircleAndEmpty()
{
Assert.AreEqual(1, CircleF.Unit.CompareTo(CircleF.Empty));
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyCircleAndUnitCircleAsObject()
{
Assert.AreEqual(-1, CircleF.Empty.CompareTo((object)CircleF.Unit));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenNull()
{
Assert.AreEqual(1, CircleF.Unit.CompareTo(null));
}
[TestMethod]
public void CompareTo_ShouldBeZero_GivenUnitCircle()
{
var unitCircle = CircleF.Unit;
Assert.AreEqual(0, unitCircle.CompareTo(unitCircle));
}
[TestMethod]
public void CompareTo_ShouldThrowArgumentException_GivenInvalidType()
{
Assert.ThrowsException<ArgumentException>(() => CircleF.Unit.CompareTo(new object()));
}
[TestMethod]
public void Diameter_ShouldBe2_GivenUnitCircle()
{
Assert.AreEqual(2.0f, CircleF.Unit.Diameter, 1e-6f);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitCircles()
{
var unitCircle1 = CircleF.Unit;
var unitCircle2 = CircleF.Unit;
Assert.AreEqual(unitCircle1, unitCircle2);
Assert.IsTrue(unitCircle1 == unitCircle2);
Assert.IsFalse(unitCircle1 != unitCircle2);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentCircles()
{
Assert.AreNotEqual(CircleF.Unit, CircleF.Empty);
Assert.IsFalse(CircleF.Unit == CircleF.Empty);
Assert.IsTrue(CircleF.Unit != CircleF.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = CircleF.Empty.GetHashCode();
Assert.AreEqual(hashCode, CircleF.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = CircleF.Unit.GetHashCode();
Assert.AreEqual(hashCode, CircleF.Unit.GetHashCode());
}
[TestMethod]
public void op_Explicit_ShouldReturnEquivalentCircle_GivenCircle()
{
CircleF unitCircle = CircleF.Unit;
Circle converted = (Circle)unitCircle;
Assert.AreEqual(unitCircle, converted);
Assert.AreEqual(unitCircle.Radius, converted.Radius);
Assert.AreEqual(unitCircle.Center, converted.Center);
}
[TestMethod]
public void op_GreaterThan_True_GivenUnitAndEmptyCircle()
{
Assert.IsTrue(CircleF.Unit > CircleF.Empty);
Assert.IsTrue(CircleF.Unit >= CircleF.Empty);
Assert.IsFalse(CircleF.Unit < CircleF.Empty);
Assert.IsFalse(CircleF.Unit <= CircleF.Empty);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentCircle_GivenCircle()
{
Circle unitCircle = Circle.Unit;
CircleF converted = unitCircle;
Assert.AreEqual(unitCircle, converted);
Assert.AreEqual(unitCircle.Radius, converted.Radius);
Assert.AreEqual(unitCircle.Center, converted.Center);
}
[TestMethod]
public void op_LessThan_True_GivenEmptyAndUnitCircle()
{
Assert.IsTrue(CircleF.Empty < CircleF.Unit);
Assert.IsTrue(CircleF.Empty <= CircleF.Unit);
Assert.IsFalse(CircleF.Empty > CircleF.Unit);
Assert.IsFalse(CircleF.Empty >= CircleF.Unit);
}
[TestMethod]
public void Radius_ShouldBe0_GivenEmptyCircle()
{
Assert.AreEqual(0.0f, CircleF.Empty.Radius, 1e-6f);
}
[TestMethod]
public void Radius_ShouldBe1_GivenUnitCircle()
{
Assert.AreEqual(1.0f, CircleF.Unit.Radius, 1e-6f);
}
}

View File

@ -0,0 +1,129 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class CircleTests
{
[TestMethod]
public void Area_ShouldBePiRadiusRadius_GivenUnitCircle()
{
var unitCircle = Circle.Unit;
Assert.AreEqual(MathF.PI * unitCircle.Radius * unitCircle.Radius, unitCircle.Area);
}
[TestMethod]
public void Circumference_ShouldBe2PiRadius_GivenUnitCircle()
{
var unitCircle = Circle.Unit;
Assert.AreEqual(2.0f * MathF.PI * unitCircle.Radius, unitCircle.Circumference, 1e-6f);
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenUnitCircleAndEmpty()
{
Assert.AreEqual(-1, Circle.Empty.CompareTo(Circle.Unit));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenUnitCircleAndEmpty()
{
Assert.AreEqual(1, Circle.Unit.CompareTo(Circle.Empty));
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyCircleAndUnitCircleAsObject()
{
Assert.AreEqual(-1, Circle.Empty.CompareTo((object)Circle.Unit));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenNull()
{
Assert.AreEqual(1, Circle.Unit.CompareTo(null));
}
[TestMethod]
public void CompareTo_ShouldBeZero_GivenUnitCircle()
{
var unitCircle = Circle.Unit;
Assert.AreEqual(0, unitCircle.CompareTo(unitCircle));
}
[TestMethod]
public void CompareTo_ShouldThrowArgumentException_GivenInvalidType()
{
Assert.ThrowsException<ArgumentException>(() => Circle.Unit.CompareTo(new object()));
}
[TestMethod]
public void Diameter_ShouldBe2_GivenUnitCircle()
{
Assert.AreEqual(2.0f, Circle.Unit.Diameter, 1e-6f);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitCircles()
{
var unitCircle1 = Circle.Unit;
var unitCircle2 = Circle.Unit;
Assert.AreEqual(unitCircle1, unitCircle2);
Assert.IsTrue(unitCircle1 == unitCircle2);
Assert.IsFalse(unitCircle1 != unitCircle2);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentCircles()
{
Assert.AreNotEqual(Circle.Unit, Circle.Empty);
Assert.IsFalse(Circle.Unit == Circle.Empty);
Assert.IsTrue(Circle.Unit != Circle.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Circle.Empty.GetHashCode();
Assert.AreEqual(hashCode, Circle.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Circle.Unit.GetHashCode();
Assert.AreEqual(hashCode, Circle.Unit.GetHashCode());
}
[TestMethod]
public void op_GreaterThan_True_GivenUnitAndEmptyCircle()
{
Assert.IsTrue(Circle.Unit > Circle.Empty);
Assert.IsTrue(Circle.Unit >= Circle.Empty);
Assert.IsFalse(Circle.Unit < Circle.Empty);
Assert.IsFalse(Circle.Unit <= Circle.Empty);
}
[TestMethod]
public void op_LessThan_True_GivenEmptyAndUnitCircle()
{
Assert.IsTrue(Circle.Empty < Circle.Unit);
Assert.IsTrue(Circle.Empty <= Circle.Unit);
Assert.IsFalse(Circle.Empty > Circle.Unit);
Assert.IsFalse(Circle.Empty >= Circle.Unit);
}
[TestMethod]
public void Radius_ShouldBe0_GivenEmptyCircle()
{
Assert.AreEqual(0, Circle.Empty.Radius);
}
[TestMethod]
public void Radius_ShouldBe1_GivenUnitCircle()
{
Assert.AreEqual(1, Circle.Unit.Radius);
}
}

View File

@ -16,6 +16,155 @@ public class ColorTests
private static readonly Color Magenta = Color.FromArgb(255, 0, 255);
private static readonly Color Yellow = Color.FromArgb(255, 255, 0);
[TestMethod]
public void GetClosestConsoleColor_ShouldReturnClosestColor_GivenValidColor()
{
Assert.AreEqual(ConsoleColor.White, Color.Transparent.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.AliceBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.AntiqueWhite.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.Aqua.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Aquamarine.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Azure.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Beige.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Bisque.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Black, Color.Black.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.BlanchedAlmond.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Blue, Color.Blue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.BlueViolet.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkRed, Color.Brown.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.BurlyWood.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.CadetBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, Color.Chartreuse.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.Chocolate.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.Coral.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.CornflowerBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Cornsilk.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Red, Color.Crimson.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.Cyan.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkBlue, Color.DarkBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.DarkCyan.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.DarkGoldenrod.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.DarkGray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGreen, Color.DarkGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.DarkKhaki.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.DarkMagenta.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.DarkOliveGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.DarkOrange.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.DarkOrchid.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkRed, Color.DarkRed.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.DarkSalmon.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.DarkSeaGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.DarkSlateBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGreen, Color.DarkSlateGray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.DarkTurquoise.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.DarkViolet.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Magenta, Color.DeepPink.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.DeepSkyBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.DimGray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.DodgerBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkRed, Color.Firebrick.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.FloralWhite.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Green, Color.ForestGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Magenta, Color.Fuchsia.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Gainsboro.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.GhostWhite.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, Color.Gold.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.Goldenrod.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.Gray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Green, Color.Green.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, Color.GreenYellow.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Honeydew.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.HotPink.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.IndianRed.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.Indigo.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Ivory.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Khaki.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Lavender.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.LavenderBlush.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, Color.LawnGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.LemonChiffon.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightCoral.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.LightCyan.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.LightGoldenrodYellow.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightGray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightPink.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightSalmon.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.LightSeaGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightSkyBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.LightSlateGray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.LightSteelBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.LightYellow.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Green, Color.Lime.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Green, Color.LimeGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Linen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Magenta, Color.Magenta.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkRed, Color.Maroon.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.MediumAquamarine.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Blue, Color.MediumBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.MediumOrchid.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.MediumPurple.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.MediumSeaGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.MediumSlateBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.MediumSpringGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.MediumTurquoise.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.MediumVioletRed.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkBlue, Color.MidnightBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.MintCream.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.MistyRose.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Moccasin.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.NavajoWhite.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkBlue, Color.Navy.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.OldLace.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.Olive.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.OliveDrab.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.Orange.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Red, Color.OrangeRed.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Orchid.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.PaleGoldenrod.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.PaleGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.PaleTurquoise.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.PaleVioletRed.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.PapayaWhip.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.PeachPuff.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.Peru.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Pink.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Plum.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.PowderBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.Purple.GetClosestConsoleColor());
#if NET6_0_OR_GREATER
Assert.AreEqual(ConsoleColor.DarkMagenta, Color.RebeccaPurple.GetClosestConsoleColor());
#endif
Assert.AreEqual(ConsoleColor.Red, Color.Red.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.RosyBrown.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.RoyalBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkRed, Color.SaddleBrown.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Salmon.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.SandyBrown.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.SeaGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.SeaShell.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkRed, Color.Sienna.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Silver.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.SkyBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.SlateBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.SlateGray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Snow.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.SpringGreen.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.SteelBlue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Tan.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkCyan, Color.Teal.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Thistle.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkYellow, Color.Tomato.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.Turquoise.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.DarkGray, Color.Violet.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.Wheat.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.White.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.WhiteSmoke.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, Color.Yellow.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.YellowGreen.GetClosestConsoleColor());
}
[TestMethod]
public void Inverted_ShouldReturnInvertedColor()
{

View File

@ -0,0 +1,76 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class CuboidTests
{
[TestMethod]
public void Corners_ShouldBeCorrect_GivenCubeOfSize1()
{
Cuboid cube = Cuboid.Cube;
Assert.AreEqual(new Vector3(0.5f, 0.5f, -0.5f), cube.FrontTopRight);
Assert.AreEqual(new Vector3(-0.5f, 0.5f, -0.5f), cube.FrontTopLeft);
Assert.AreEqual(new Vector3(0.5f, -0.5f, -0.5f), cube.FrontBottomRight);
Assert.AreEqual(new Vector3(-0.5f, -0.5f, -0.5f), cube.FrontBottomLeft);
Assert.AreEqual(new Vector3(0.5f, 0.5f, 0.5f), cube.BackTopRight);
Assert.AreEqual(new Vector3(-0.5f, 0.5f, 0.5f), cube.BackTopLeft);
Assert.AreEqual(new Vector3(0.5f, -0.5f, 0.5f), cube.BackBottomRight);
Assert.AreEqual(new Vector3(-0.5f, -0.5f, 0.5f), cube.BackBottomLeft);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoCubesOfSize1()
{
var cube1 = Cuboid.Cube;
var cube2 = Cuboid.Cube;
Assert.AreEqual(cube1, cube2);
Assert.IsTrue(cube1 == cube2);
Assert.IsFalse(cube1 != cube2);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentCubes()
{
Assert.AreNotEqual(Cuboid.Cube, Cuboid.Empty);
Assert.IsFalse(Cuboid.Cube == Cuboid.Empty);
Assert.IsTrue(Cuboid.Cube != Cuboid.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Cuboid.Empty.GetHashCode();
Assert.AreEqual(hashCode, Cuboid.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenCubeOfSize1()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Cuboid.Cube.GetHashCode();
Assert.AreEqual(hashCode, Cuboid.Cube.GetHashCode());
}
[TestMethod]
public void Size_ShouldBeOne_GivenCubeOfSize1()
{
Assert.AreEqual(Vector3.One, Cuboid.Cube.Size);
}
[TestMethod]
public void Size_ShouldBeOne_GivenRotatedCube()
{
Assert.AreEqual(Vector3.One, new Cuboid(0, 0, 0, 1, 1, 1, 90, 0, 0).Size);
}
[TestMethod]
public void Volume_ShouldBe1_GivenCubeOfSize1()
{
Assert.AreEqual(1.0f, Cuboid.Cube.Volume, 1e-6f);
}
}

View File

@ -0,0 +1,150 @@
using System.Drawing;
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class EllipseFTests
{
[TestMethod]
public void Area_ShouldBePiRadiusRadius_GivenUnitEllipse()
{
var unitEllipse = EllipseF.Unit;
Assert.AreEqual(MathF.PI, unitEllipse.Area, 1e-6f);
}
[TestMethod]
public void ApproximateCircumference_ShouldBe2PiRadius_GivenUnitEllipse()
{
var unitEllipse = EllipseF.Unit;
Assert.AreEqual(2 * MathF.PI, unitEllipse.ApproximateCircumference, 1e-6f);
}
[TestMethod]
public void Constructor_ShouldGiveCorrectEllipse()
{
var ellipse = new EllipseF(PointF.Empty, new SizeF(2, 1));
Assert.AreEqual(new PointF(0, 0), ellipse.Center);
Assert.AreEqual(new SizeF(2, 1), ellipse.Radius);
ellipse = new EllipseF(0, 0, 2, 1);
Assert.AreEqual(new PointF(0, 0), ellipse.Center);
Assert.AreEqual(new SizeF(2, 1), ellipse.Radius);
ellipse = new EllipseF(PointF.Empty, new Vector2(2, 1));
Assert.AreEqual(new PointF(0, 0), ellipse.Center);
Assert.AreEqual(new SizeF(2, 1), ellipse.Radius);
ellipse = new EllipseF(Vector2.Zero, new Vector2(2, 1));
Assert.AreEqual(new PointF(0, 0), ellipse.Center);
Assert.AreEqual(new SizeF(2, 1), ellipse.Radius);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitEllipses()
{
var unitEllipse1 = EllipseF.Unit;
var unitEllipse2 = EllipseF.Unit;
Assert.AreEqual(unitEllipse1, unitEllipse2);
Assert.IsTrue(unitEllipse1 == unitEllipse2);
Assert.IsFalse(unitEllipse1 != unitEllipse2);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentEllipses()
{
Assert.AreNotEqual(EllipseF.Unit, EllipseF.Empty);
Assert.IsFalse(EllipseF.Unit == EllipseF.Empty);
Assert.IsTrue(EllipseF.Unit != EllipseF.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyEllipse()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = EllipseF.Empty.GetHashCode();
Assert.AreEqual(hashCode, EllipseF.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitEllipse()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = EllipseF.Unit.GetHashCode();
Assert.AreEqual(hashCode, EllipseF.Unit.GetHashCode());
}
[TestMethod]
public void HorizontalRadius_ShouldBe0_GivenEmptyEllipse()
{
Assert.AreEqual(0, EllipseF.Empty.HorizontalRadius);
}
[TestMethod]
public void HorizontalRadius_ShouldBe1_GivenUnitEllipse()
{
Assert.AreEqual(1, EllipseF.Unit.HorizontalRadius);
}
[TestMethod]
public void op_Explicit_ShouldReturnEquivalentEllipse_GivenEllipse()
{
EllipseF unitEllipse = EllipseF.Unit;
Ellipse converted = (Ellipse)unitEllipse;
Assert.AreEqual(unitEllipse, converted);
Assert.AreEqual(unitEllipse.HorizontalRadius, converted.HorizontalRadius);
Assert.AreEqual(unitEllipse.VerticalRadius, converted.VerticalRadius);
Assert.AreEqual(unitEllipse.Center, converted.Center);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentEllipse_GivenCircle()
{
Circle unitCircle = Circle.Unit;
EllipseF converted = unitCircle;
Assert.AreEqual(unitCircle, converted);
Assert.AreEqual(unitCircle.Radius, converted.HorizontalRadius);
Assert.AreEqual(unitCircle.Radius, converted.VerticalRadius);
Assert.AreEqual(unitCircle.Center, converted.Center);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentEllipse_GivenCircleF()
{
CircleF unitCircle = CircleF.Unit;
EllipseF converted = unitCircle;
Assert.AreEqual(unitCircle, converted);
Assert.AreEqual(unitCircle.Radius, converted.HorizontalRadius);
Assert.AreEqual(unitCircle.Radius, converted.VerticalRadius);
Assert.AreEqual(unitCircle.Center, converted.Center);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentEllipse_GivenEllipse()
{
Ellipse unitEllipse = Ellipse.Unit;
EllipseF converted = unitEllipse;
Assert.AreEqual(unitEllipse, converted);
Assert.AreEqual(unitEllipse.HorizontalRadius, converted.HorizontalRadius);
Assert.AreEqual(unitEllipse.VerticalRadius, converted.VerticalRadius);
Assert.AreEqual(unitEllipse.Center, converted.Center);
}
[TestMethod]
public void VerticalRadius_ShouldBe0_GivenEmptyEllipse()
{
Assert.AreEqual(0, EllipseF.Empty.VerticalRadius);
}
[TestMethod]
public void VerticalRadius_ShouldBe1_GivenUnitEllipse()
{
Assert.AreEqual(1, EllipseF.Unit.VerticalRadius);
}
}

View File

@ -0,0 +1,105 @@
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class EllipseTests
{
[TestMethod]
public void Area_ShouldBePiRadiusRadius_GivenUnitEllipse()
{
var unitEllipse = Ellipse.Unit;
Assert.AreEqual(MathF.PI, unitEllipse.Area, 1e-6f);
}
[TestMethod]
public void ApproximateCircumference_ShouldBe2PiRadius_GivenUnitEllipse()
{
var unitEllipse = Ellipse.Unit;
Assert.AreEqual(2 * MathF.PI, unitEllipse.ApproximateCircumference, 1e-6f);
}
[TestMethod]
public void Constructor_ShouldGiveCorrectEllipse()
{
var ellipse = new Ellipse(Point.Empty, new Size(2, 1));
Assert.AreEqual(new Point(0, 0), ellipse.Center);
Assert.AreEqual(new Size(2, 1), ellipse.Radius);
ellipse = new Ellipse(0, 0, 2, 1);
Assert.AreEqual(new Point(0, 0), ellipse.Center);
Assert.AreEqual(new Size(2, 1), ellipse.Radius);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitEllipses()
{
var unitEllipse1 = Ellipse.Unit;
var unitEllipse2 = Ellipse.Unit;
Assert.AreEqual(unitEllipse1, unitEllipse2);
Assert.IsTrue(unitEllipse1 == unitEllipse2);
Assert.IsFalse(unitEllipse1 != unitEllipse2);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentEllipses()
{
Assert.AreNotEqual(Ellipse.Unit, Ellipse.Empty);
Assert.IsFalse(Ellipse.Unit == Ellipse.Empty);
Assert.IsTrue(Ellipse.Unit != Ellipse.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyEllipse()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Ellipse.Empty.GetHashCode();
Assert.AreEqual(hashCode, Ellipse.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitEllipse()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Ellipse.Unit.GetHashCode();
Assert.AreEqual(hashCode, Ellipse.Unit.GetHashCode());
}
[TestMethod]
public void HorizontalRadius_ShouldBe0_GivenEmptyEllipse()
{
Assert.AreEqual(0, Ellipse.Empty.HorizontalRadius);
}
[TestMethod]
public void HorizontalRadius_ShouldBe1_GivenUnitEllipse()
{
Assert.AreEqual(1, Ellipse.Unit.HorizontalRadius);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentEllipse_GivenCircle()
{
Circle unitCircle = Circle.Unit;
Ellipse converted = unitCircle;
Assert.AreEqual(unitCircle, converted);
Assert.AreEqual(unitCircle.Radius, converted.HorizontalRadius);
Assert.AreEqual(unitCircle.Radius, converted.VerticalRadius);
Assert.AreEqual(unitCircle.Center, converted.Center);
}
[TestMethod]
public void VerticalRadius_ShouldBe0_GivenEmptyEllipse()
{
Assert.AreEqual(0, Ellipse.Empty.VerticalRadius);
}
[TestMethod]
public void VerticalRadius_ShouldBe1_GivenUnitEllipse()
{
Assert.AreEqual(1, Ellipse.Unit.VerticalRadius);
}
}

View File

@ -0,0 +1,182 @@
using System.Drawing;
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class Line3DTests
{
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne()
{
Assert.AreEqual(-1, Line3D.Empty.CompareTo(Line3D.One));
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyLineAndOneLineAsObject()
{
Assert.AreEqual(-1, Line3D.Empty.CompareTo((object)Line3D.One));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenNull()
{
Assert.AreEqual(1, Line3D.One.CompareTo(null));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenOneAndEmpty()
{
Assert.AreEqual(1, Line3D.One.CompareTo(Line3D.Empty));
}
[TestMethod]
public void CompareTo_ShouldBeZero_GivenUnitLine()
{
var unitLine3D = Line3D.One;
Assert.AreEqual(0, unitLine3D.CompareTo(unitLine3D));
}
[TestMethod]
public void CompareTo_ShouldThrowArgumentException_GivenInvalidType()
{
Assert.ThrowsException<ArgumentException>(() => Line3D.Empty.CompareTo(new object()));
}
[TestMethod]
public void Length_ShouldBe0_GivenEmptyLine()
{
Assert.AreEqual(0.0f, Line3D.Empty.Length);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitXLine()
{
Assert.AreEqual(1.0f, Line3D.UnitX.Length, 1e-6f);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitYLine()
{
Assert.AreEqual(1.0f, Line3D.UnitY.Length, 1e-6f);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitZLine()
{
Assert.AreEqual(1.0f, Line3D.UnitZ.Length, 1e-6f);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitLines()
{
Line3D first = Line3D.One;
Line3D second = Line3D.One;
Assert.AreEqual(first, second);
Assert.IsTrue(first == second);
Assert.IsFalse(first != second);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentLines()
{
Assert.AreNotEqual(Line3D.One, Line3D.Empty);
Assert.IsFalse(Line3D.One == Line3D.Empty);
Assert.IsTrue(Line3D.One != Line3D.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyLine()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Line3D.Empty.GetHashCode();
Assert.AreEqual(hashCode, Line3D.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitLine()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Line3D.One.GetHashCode();
Assert.AreEqual(hashCode, Line3D.One.GetHashCode());
}
[TestMethod]
public void op_Explicit_ShouldReturnEquivalentLine_GivenLine()
{
Line3D oneLine = new Line3D(Vector3.Zero, Vector3.UnitX + Vector3.UnitY);
Line converted = (Line)oneLine;
var expectedStart = new Point((int)oneLine.Start.X, (int)oneLine.Start.Y);
var expectedEnd = new Point((int)oneLine.End.X, (int)oneLine.End.Y);
Assert.AreEqual(oneLine.Length, converted.Length);
Assert.AreEqual(expectedStart, converted.Start);
Assert.AreEqual(expectedEnd, converted.End);
}
[TestMethod]
public void op_Explicit_ShouldReturnEquivalentLineF_GivenLine()
{
Line3D oneLine = new Line3D(Vector3.Zero, Vector3.UnitX + Vector3.UnitY);
LineF converted = (LineF)oneLine;
var expectedStart = new PointF(oneLine.Start.X, oneLine.Start.Y);
var expectedEnd = new PointF(oneLine.End.X, oneLine.End.Y);
Assert.AreEqual(oneLine.Length, converted.Length);
Assert.AreEqual(expectedStart, converted.Start);
Assert.AreEqual(expectedEnd, converted.End);
}
[TestMethod]
public void op_GreaterThan_True_GivenUnitAndEmptyCircle()
{
Assert.IsTrue(Line3D.One > Line3D.Empty);
Assert.IsTrue(Line3D.One >= Line3D.Empty);
Assert.IsFalse(Line3D.One < Line3D.Empty);
Assert.IsFalse(Line3D.One <= Line3D.Empty);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentLine_GivenLine()
{
Line oneLine = Line.One;
Line3D converted = oneLine;
var expectedStart = new Vector3(oneLine.Start.X, oneLine.Start.Y, 0.0f);
var expectedEnd = new Vector3(oneLine.End.X, oneLine.End.Y, 0.0f);
Assert.AreEqual(oneLine, converted);
Assert.AreEqual(oneLine.Length, converted.Length);
Assert.AreEqual(expectedStart, converted.Start);
Assert.AreEqual(expectedEnd, converted.End);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentLine_GivenLineF()
{
LineF oneLine = LineF.One;
Line3D converted = oneLine;
var expectedStart = new Vector3(oneLine.Start.X, oneLine.Start.Y, 0.0f);
var expectedEnd = new Vector3(oneLine.End.X, oneLine.End.Y, 0.0f);
Assert.AreEqual(oneLine, converted);
Assert.AreEqual(oneLine.Length, converted.Length);
Assert.AreEqual(expectedStart, converted.Start);
Assert.AreEqual(expectedEnd, converted.End);
}
[TestMethod]
public void op_LessThan_True_GivenEmptyAndUnitCircle()
{
Assert.IsTrue(Line3D.Empty < Line3D.One);
Assert.IsTrue(Line3D.Empty <= Line3D.One);
Assert.IsFalse(Line3D.Empty > Line3D.One);
Assert.IsFalse(Line3D.Empty >= Line3D.One);
}
}

View File

@ -0,0 +1,140 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class LineFTests
{
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne()
{
Assert.AreEqual(-1, LineF.Empty.CompareTo(LineF.One));
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyLineAndOneLineAsObject()
{
Assert.AreEqual(-1, LineF.Empty.CompareTo((object)LineF.One));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenNull()
{
Assert.AreEqual(1, LineF.One.CompareTo(null));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenOneAndEmpty()
{
Assert.AreEqual(1, LineF.One.CompareTo(LineF.Empty));
}
[TestMethod]
public void CompareTo_ShouldBeZero_GivenUnitLine()
{
var unitLineF = LineF.One;
Assert.AreEqual(0, unitLineF.CompareTo(unitLineF));
}
[TestMethod]
public void CompareTo_ShouldThrowArgumentException_GivenInvalidType()
{
Assert.ThrowsException<ArgumentException>(() => LineF.Empty.CompareTo(new object()));
}
[TestMethod]
public void Length_ShouldBe0_GivenEmptyLine()
{
Assert.AreEqual(0.0f, LineF.Empty.Length);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitXLine()
{
Assert.AreEqual(1.0f, LineF.UnitX.Length, 1e-6f);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitYLine()
{
Assert.AreEqual(1.0f, LineF.UnitY.Length, 1e-6f);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitLines()
{
LineF first = LineF.One;
LineF second = LineF.One;
Assert.AreEqual(first, second);
Assert.IsTrue(first == second);
Assert.IsFalse(first != second);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentLines()
{
Assert.AreNotEqual(LineF.One, LineF.Empty);
Assert.IsFalse(LineF.One == LineF.Empty);
Assert.IsTrue(LineF.One != LineF.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyLine()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = LineF.Empty.GetHashCode();
Assert.AreEqual(hashCode, LineF.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitLine()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = LineF.One.GetHashCode();
Assert.AreEqual(hashCode, LineF.One.GetHashCode());
}
[TestMethod]
public void op_Explicit_ShouldReturnEquivalentLine_GivenLine()
{
LineF oneLine = LineF.One;
Line converted = (Line)oneLine;
Assert.AreEqual(oneLine, converted);
Assert.AreEqual(oneLine.Length, converted.Length);
Assert.AreEqual(oneLine.Start, converted.Start);
Assert.AreEqual(oneLine.End, converted.End);
}
[TestMethod]
public void op_GreaterThan_True_GivenUnitAndEmptyCircle()
{
Assert.IsTrue(LineF.One > LineF.Empty);
Assert.IsTrue(LineF.One >= LineF.Empty);
Assert.IsFalse(LineF.One < LineF.Empty);
Assert.IsFalse(LineF.One <= LineF.Empty);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentLine_GivenLine()
{
Line oneLine = Line.One;
LineF converted = oneLine;
Assert.AreEqual(oneLine, converted);
Assert.AreEqual(oneLine.Length, converted.Length);
Assert.AreEqual(oneLine.Start, converted.Start);
Assert.AreEqual(oneLine.End, converted.End);
}
[TestMethod]
public void op_LessThan_True_GivenEmptyAndUnitCircle()
{
Assert.IsTrue(LineF.Empty < LineF.One);
Assert.IsTrue(LineF.Empty <= LineF.One);
Assert.IsFalse(LineF.Empty > LineF.One);
Assert.IsFalse(LineF.Empty >= LineF.One);
}
}

View File

@ -0,0 +1,116 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class LineTests
{
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyAndOne()
{
Assert.AreEqual(-1, Line.Empty.CompareTo(Line.One));
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyLineAndOneLineAsObject()
{
Assert.AreEqual(-1, Line.Empty.CompareTo((object)Line.One));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenNull()
{
Assert.AreEqual(1, Line.One.CompareTo(null));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenOneAndEmpty()
{
Assert.AreEqual(1, Line.One.CompareTo(Line.Empty));
}
[TestMethod]
public void CompareTo_ShouldBeZero_GivenUnitLine()
{
var unitLine = Line.One;
Assert.AreEqual(0, unitLine.CompareTo(unitLine));
}
[TestMethod]
public void CompareTo_ShouldThrowArgumentException_GivenInvalidType()
{
Assert.ThrowsException<ArgumentException>(() => Line.Empty.CompareTo(new object()));
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitLines()
{
Line first = Line.One;
Line second = Line.One;
Assert.AreEqual(first, second);
Assert.IsTrue(first == second);
Assert.IsFalse(first != second);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentLines()
{
Assert.AreNotEqual(Line.One, Line.Empty);
Assert.IsFalse(Line.One == Line.Empty);
Assert.IsTrue(Line.One != Line.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyLine()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Line.Empty.GetHashCode();
Assert.AreEqual(hashCode, Line.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitLine()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Line.One.GetHashCode();
Assert.AreEqual(hashCode, Line.One.GetHashCode());
}
[TestMethod]
public void Length_ShouldBe0_GivenEmptyLine()
{
Assert.AreEqual(0.0f, Line.Empty.Length);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitXLine()
{
Assert.AreEqual(1.0f, Line.UnitX.Length, 1e-6f);
}
[TestMethod]
public void Length_ShouldBe1_GivenUnitYLine()
{
Assert.AreEqual(1.0f, Line.UnitY.Length, 1e-6f);
}
[TestMethod]
public void op_GreaterThan_True_GivenUnitAndEmptyCircle()
{
Assert.IsTrue(Line.One > Line.Empty);
Assert.IsTrue(Line.One >= Line.Empty);
Assert.IsFalse(Line.One < Line.Empty);
Assert.IsFalse(Line.One <= Line.Empty);
}
[TestMethod]
public void op_LessThan_True_GivenEmptyAndUnitCircle()
{
Assert.IsTrue(Line.Empty < Line.One);
Assert.IsTrue(Line.Empty <= Line.One);
Assert.IsFalse(Line.Empty > Line.One);
Assert.IsFalse(Line.Empty >= Line.One);
}
}

View File

@ -0,0 +1,41 @@
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class PointFTests
{
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var point = new PointF(1.5f, 2.6f);
var rounded = point.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var point = new PointF(1.5f, 25.2f);
var rounded = point.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
}
[TestMethod]
public void ToSizeF_ShouldReturnSize_WithEquivalentMembers()
{
var random = new Random();
var point = new PointF(random.NextSingle(), random.NextSingle());
var size = point.ToSizeF();
Assert.AreEqual(point.X, size.Width, 1e-6f);
Assert.AreEqual(point.Y, size.Height, 1e-6f);
}
}

View File

@ -0,0 +1,42 @@
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class PointTests
{
[TestMethod]
public void ToSize_ShouldReturnSize_WithEquivalentMembers()
{
var random = new Random();
var point = new Point(random.Next(), random.Next());
var size = point.ToSize();
Assert.AreEqual(point.X, size.Width);
Assert.AreEqual(point.Y, size.Height);
}
[TestMethod]
public void ToSizeF_ShouldReturnSize_WithEquivalentMembers()
{
var random = new Random();
var point = new Point(random.Next(), random.Next());
var size = point.ToSizeF();
Assert.AreEqual(point.X, size.Width, 1e-6f);
Assert.AreEqual(point.Y, size.Height, 1e-6f);
}
[TestMethod]
public void ToVector2_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var point = new Point(random.Next(), random.Next());
var size = point.ToVector2();
Assert.AreEqual(point.X, size.X, 1e-6f);
Assert.AreEqual(point.Y, size.Y, 1e-6f);
}
}

View File

@ -0,0 +1,204 @@
using System.Drawing;
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class PolygonFTests
{
[TestMethod]
public void AddVertices_ShouldAddVertices()
{
var polygon = PolygonF.Empty;
polygon.AddVertices(new[] {new PointF(1, 2), new PointF(3, 4)});
Assert.AreEqual(2, polygon.VertexCount);
// assert that the empty polygon was not modified
Assert.AreEqual(0, PolygonF.Empty.VertexCount);
}
[TestMethod]
public void ClearVertices_ShouldClearVertices()
{
var polygon = PolygonF.Empty;
polygon.AddVertices(new[] {new Vector2(1, 2), new Vector2(3, 4)});
Assert.AreEqual(2, polygon.VertexCount);
// assert that the empty polygon was not modified
Assert.AreEqual(0, PolygonF.Empty.VertexCount);
polygon.ClearVertices();
Assert.AreEqual(0, polygon.VertexCount);
}
[TestMethod]
public void Constructor_ShouldPopulateVertices_GivenPolygon()
{
var pointPolygon = new PolygonF(new[] {new PointF(1, 2), new PointF(3, 4)});
var vectorPolygon = new PolygonF(new[] {new Vector2(1, 2), new Vector2(3, 4)});
Assert.AreEqual(2, pointPolygon.VertexCount);
Assert.AreEqual(2, vectorPolygon.VertexCount);
}
[TestMethod]
public void CopyConstructor_ShouldCopyVertices_GivenPolygon()
{
var first = PolygonF.Empty;
first.AddVertices(new[] {new PointF(1, 2), new PointF(3, 4)});
var second = new PolygonF(first);
Assert.AreEqual(2, first.VertexCount);
Assert.AreEqual(2, second.VertexCount);
// we cannot use CollectionAssert here for reasons I am not entirely sure of.
// it seems to dislike casting from IReadOnlyList<Point> to ICollection. but okay.
Assert.IsTrue(first.Vertices.SequenceEqual(second.Vertices));
// assert that the empty polygon was not modified
Assert.AreEqual(0, PolygonF.Empty.VertexCount);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoEmptyPolygons()
{
var first = PolygonF.Empty;
var second = PolygonF.Empty;
Assert.AreEqual(first, second);
Assert.AreEqual(second, first);
Assert.IsTrue(first.Equals(second));
Assert.IsTrue(second.Equals(first));
Assert.IsTrue(first == second);
Assert.IsTrue(second == first);
Assert.IsFalse(first != second);
Assert.IsFalse(second != first);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoHexagons()
{
PolygonF first = CreateHexagon();
PolygonF second = CreateHexagon();
Assert.AreEqual(first, second);
Assert.AreEqual(second, first);
Assert.IsTrue(first.Equals(second));
Assert.IsTrue(second.Equals(first));
Assert.IsTrue(first == second);
Assert.IsTrue(second == first);
Assert.IsFalse(first != second);
Assert.IsFalse(second != first);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenHexagonAndEmptyPolygon()
{
PolygonF first = CreateHexagon();
PolygonF second = PolygonF.Empty;
Assert.AreNotEqual(first, second);
Assert.AreNotEqual(second, first);
Assert.IsFalse(first.Equals(second));
Assert.IsFalse(second.Equals(first));
Assert.IsFalse(first == second);
Assert.IsFalse(second == first);
Assert.IsTrue(first != second);
Assert.IsTrue(second != first);
}
[TestMethod]
public void IsConvex_ShouldBeFalse_GivenEmptyPolygon()
{
Assert.IsFalse(PolygonF.Empty.IsConvex);
}
[TestMethod]
public void IsConvex_ShouldBeTrue_GivenHexagon()
{
Assert.IsTrue(CreateHexagon().IsConvex);
}
[TestMethod]
public void IsConvex_ShouldBeFalse_GivenConcavePolygon()
{
Assert.IsFalse(CreateConcavePolygon().IsConvex);
}
[TestMethod]
public void op_Explicit_ShouldReturnEquivalentCircle_GivenCircle()
{
PolygonF polygon = CreateHexagon();
Polygon converted = (Polygon)polygon;
Assert.AreEqual(polygon, converted);
Assert.AreEqual(polygon.IsConvex, converted.IsConvex);
Assert.AreEqual(polygon.VertexCount, converted.VertexCount);
Assert.IsTrue(polygon.Vertices.SequenceEqual(converted.Vertices.Select(p => (PointF)p)));
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentCircle_GivenCircle()
{
Polygon polygon = PolygonTests.CreateHexagon();
PolygonF converted = polygon;
Assert.AreEqual(polygon, converted);
Assert.AreEqual(polygon.IsConvex, converted.IsConvex);
Assert.AreEqual(polygon.VertexCount, converted.VertexCount);
Assert.IsTrue(converted.Vertices.SequenceEqual(polygon.Vertices.Select(p => (PointF)p)));
}
[TestMethod]
public void PointCount_ShouldBe1_GivenPolygonFWith1Point()
{
var polygon = new PolygonF();
polygon.AddVertex(new Point(1, 1));
Assert.AreEqual(1, polygon.VertexCount);
// assert that the empty polygon was not modified
Assert.AreEqual(0, PolygonF.Empty.VertexCount);
}
[TestMethod]
public void PointCount_ShouldBe0_GivenEmptyPolygon()
{
Assert.AreEqual(0, PolygonF.Empty.VertexCount);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = PolygonF.Empty.GetHashCode();
Assert.AreEqual(hashCode, PolygonF.Empty.GetHashCode());
}
internal static PolygonF CreateHexagon()
{
var hexagon = new PolygonF();
hexagon.AddVertex(new Vector2(0, 0));
hexagon.AddVertex(new Vector2(1, 0));
hexagon.AddVertex(new Vector2(1, 1));
hexagon.AddVertex(new Vector2(0, 1));
hexagon.AddVertex(new Vector2(-1, 1));
hexagon.AddVertex(new Vector2(-1, 0));
return hexagon;
}
internal static PolygonF CreateConcavePolygon()
{
var hexagon = new PolygonF();
hexagon.AddVertex(new Vector2(0, 0));
hexagon.AddVertex(new Vector2(2, 0));
hexagon.AddVertex(new Vector2(1, 1));
hexagon.AddVertex(new Vector2(2, 1));
hexagon.AddVertex(new Vector2(0, 1));
return hexagon;
}
}

View File

@ -0,0 +1,168 @@
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class PolygonTests
{
[TestMethod]
public void AddVertices_ShouldAddVertices()
{
var polygon = Polygon.Empty;
polygon.AddVertices(new[] {new Point(1, 2), new Point(3, 4)});
Assert.AreEqual(2, polygon.VertexCount);
// assert that the empty polygon was not modified
Assert.AreEqual(0, Polygon.Empty.VertexCount);
}
[TestMethod]
public void ClearVertices_ShouldClearVertices()
{
var polygon = Polygon.Empty;
polygon.AddVertices(new[] {new Point(1, 2), new Point(3, 4)});
Assert.AreEqual(2, polygon.VertexCount);
// assert that the empty polygon was not modified
Assert.AreEqual(0, PolygonF.Empty.VertexCount);
polygon.ClearVertices();
Assert.AreEqual(0, polygon.VertexCount);
}
[TestMethod]
public void CopyConstructor_ShouldCopyVertices_GivenPolygon()
{
var first = Polygon.Empty;
first.AddVertices(new[] {new Point(1, 2), new Point(3, 4)});
var second = new Polygon(first);
Assert.AreEqual(2, first.VertexCount);
Assert.AreEqual(2, second.VertexCount);
// we cannot use CollectionAssert here for reasons I am not entirely sure of.
// it seems to dislike casting from IReadOnlyList<Point> to ICollection. but okay.
Assert.IsTrue(first.Vertices.SequenceEqual(second.Vertices));
// assert that the empty polygon was not modified
Assert.AreEqual(0, Polygon.Empty.VertexCount);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoEmptyPolygons()
{
var first = Polygon.Empty;
var second = Polygon.Empty;
Assert.AreEqual(first, second);
Assert.AreEqual(second, first);
Assert.IsTrue(first.Equals(second));
Assert.IsTrue(second.Equals(first));
Assert.IsTrue(first == second);
Assert.IsTrue(second == first);
Assert.IsFalse(first != second);
Assert.IsFalse(second != first);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoHexagons()
{
Polygon first = CreateHexagon();
Polygon second = CreateHexagon();
Assert.AreEqual(first, second);
Assert.AreEqual(second, first);
Assert.IsTrue(first.Equals(second));
Assert.IsTrue(second.Equals(first));
Assert.IsTrue(first == second);
Assert.IsTrue(second == first);
Assert.IsFalse(first != second);
Assert.IsFalse(second != first);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenHexagonAndEmptyPolygon()
{
Polygon first = CreateHexagon();
Polygon second = Polygon.Empty;
Assert.AreNotEqual(first, second);
Assert.AreNotEqual(second, first);
Assert.IsFalse(first.Equals(second));
Assert.IsFalse(second.Equals(first));
Assert.IsFalse(first == second);
Assert.IsFalse(second == first);
Assert.IsTrue(first != second);
Assert.IsTrue(second != first);
}
[TestMethod]
public void IsConvex_ShouldBeFalse_GivenEmptyPolygon()
{
Assert.IsFalse(Polygon.Empty.IsConvex);
}
[TestMethod]
public void IsConvex_ShouldBeTrue_GivenHexagon()
{
Assert.IsTrue(CreateHexagon().IsConvex);
}
[TestMethod]
public void IsConvex_ShouldBeFalse_GivenConcavePolygon()
{
Assert.IsFalse(CreateConcavePolygon().IsConvex);
}
[TestMethod]
public void PointCount_ShouldBe1_GivenPolygonWith1Point()
{
var polygon = Polygon.Empty;
polygon.AddVertex(new Point(1, 1));
Assert.AreEqual(1, polygon.VertexCount);
// assert that the empty polygon was not modified
Assert.AreEqual(0, Polygon.Empty.VertexCount);
}
[TestMethod]
public void PointCount_ShouldBe0_GivenEmptyPolygon()
{
Assert.AreEqual(0, Polygon.Empty.VertexCount);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Polygon.Empty.GetHashCode();
Assert.AreEqual(hashCode, Polygon.Empty.GetHashCode());
}
internal static Polygon CreateHexagon()
{
var hexagon = new Polygon();
hexagon.AddVertex(new Point(0, 0));
hexagon.AddVertex(new Point(1, 0));
hexagon.AddVertex(new Point(1, 1));
hexagon.AddVertex(new Point(0, 1));
hexagon.AddVertex(new Point(-1, 1));
hexagon.AddVertex(new Point(-1, 0));
return hexagon;
}
internal static Polygon CreateConcavePolygon()
{
var hexagon = new Polygon();
hexagon.AddVertex(new Point(0, 0));
hexagon.AddVertex(new Point(2, 0));
hexagon.AddVertex(new Point(1, 1));
hexagon.AddVertex(new Point(2, 1));
hexagon.AddVertex(new Point(0, 1));
return hexagon;
}
}

View File

@ -0,0 +1,188 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class PolyhedronTests
{
[TestMethod]
public void AddVertices_ShouldAddVertices()
{
var polyhedron = Polyhedron.Empty;
polyhedron.AddVertices(new[] {new Vector3(1, 2, 3), new Vector3(4, 5, 6)});
Assert.AreEqual(2, polyhedron.VertexCount);
// assert that the empty polyhedron was not modified
Assert.AreEqual(0, Polyhedron.Empty.VertexCount);
}
[TestMethod]
public void ClearVertices_ShouldClearVertices()
{
var polyhedron = Polyhedron.Empty;
polyhedron.AddVertices(new[] {new Vector3(1, 2, 3), new Vector3(4, 5, 6)});
Assert.AreEqual(2, polyhedron.VertexCount);
// assert that the empty polyhedron was not modified
Assert.AreEqual(0, Polyhedron.Empty.VertexCount);
polyhedron.ClearVertices();
Assert.AreEqual(0, polyhedron.VertexCount);
}
[TestMethod]
public void Constructor_ShouldPopulateVertices_GivenPolyhedron()
{
var polyhedron = new Polyhedron(new[] {new Vector3(1, 2, 3), new Vector3(4, 5, 6)});
Assert.AreEqual(2, polyhedron.VertexCount);
}
[TestMethod]
public void CopyConstructor_ShouldCopyVertices_GivenPolyhedron()
{
var first = Polyhedron.Empty;
first.AddVertices(new[] {new Vector3(1, 2, 3), new Vector3(4, 5, 6)});
var second = new Polyhedron(first);
Assert.AreEqual(2, first.VertexCount);
Assert.AreEqual(2, second.VertexCount);
// we cannot use CollectionAssert here for reasons I am not entirely sure of.
// it seems to dislike casting from IReadOnlyList<Point> to ICollection. but okay.
Assert.IsTrue(first.Vertices.SequenceEqual(second.Vertices));
// assert that the empty polyhedron was not modified
Assert.AreEqual(0, Polyhedron.Empty.VertexCount);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoEmptyPolyhedrons()
{
var first = Polyhedron.Empty;
var second = Polyhedron.Empty;
Assert.AreEqual(first, second);
Assert.AreEqual(second, first);
Assert.IsTrue(first.Equals(second));
Assert.IsTrue(second.Equals(first));
Assert.IsTrue(first == second);
Assert.IsTrue(second == first);
Assert.IsFalse(first != second);
Assert.IsFalse(second != first);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoHexagons()
{
Polyhedron first = CreateHexagon();
Polyhedron second = CreateHexagon();
Assert.AreEqual(first, second);
Assert.AreEqual(second, first);
Assert.IsTrue(first.Equals(second));
Assert.IsTrue(second.Equals(first));
Assert.IsTrue(first == second);
Assert.IsTrue(second == first);
Assert.IsFalse(first != second);
Assert.IsFalse(second != first);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenHexagonAndEmptyPolyhedron()
{
Polyhedron first = CreateHexagon();
Polyhedron second = Polyhedron.Empty;
Assert.AreNotEqual(first, second);
Assert.AreNotEqual(second, first);
Assert.IsFalse(first.Equals(second));
Assert.IsFalse(second.Equals(first));
Assert.IsFalse(first == second);
Assert.IsFalse(second == first);
Assert.IsTrue(first != second);
Assert.IsTrue(second != first);
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentPolyhedron_GivenPolyhedron()
{
Polygon polygon = PolygonTests.CreateHexagon();
Polyhedron converted = polygon;
Assert.AreEqual(polygon, converted);
Assert.AreEqual(polygon.VertexCount, converted.VertexCount);
Assert.IsTrue(converted.Vertices.SequenceEqual(polygon.Vertices.Select(p =>
{
var point = p.ToVector2();
return new Vector3(point.X, point.Y, 0);
})));
}
[TestMethod]
public void op_Implicit_ShouldReturnEquivalentPolyhedron_GivenPolyhedronF()
{
PolygonF polygon = PolygonFTests.CreateHexagon();
Polyhedron converted = polygon;
Assert.AreEqual(polygon, converted);
Assert.AreEqual(polygon.VertexCount, converted.VertexCount);
Assert.IsTrue(converted.Vertices.SequenceEqual(polygon.Vertices.Select(v =>
{
var point = v.ToVector2();
return new Vector3(point.X, point.Y, 0);
})));
}
[TestMethod]
public void PointCount_ShouldBe1_GivenPolyhedronWith1Point()
{
var polyhedron = new Polyhedron();
polyhedron.AddVertex(Vector3.One);
Assert.AreEqual(1, polyhedron.VertexCount);
// assert that the empty polyhedron was not modified
Assert.AreEqual(0, Polyhedron.Empty.VertexCount);
}
[TestMethod]
public void PointCount_ShouldBe0_GivenEmptyPolyhedron()
{
Assert.AreEqual(0, Polyhedron.Empty.VertexCount);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Polyhedron.Empty.GetHashCode();
Assert.AreEqual(hashCode, Polyhedron.Empty.GetHashCode());
}
internal static Polyhedron CreateHexagon()
{
var hexagon = new Polyhedron();
hexagon.AddVertex(new Vector3(0, 0, 0));
hexagon.AddVertex(new Vector3(1, 0, 0));
hexagon.AddVertex(new Vector3(1, 1, 0));
hexagon.AddVertex(new Vector3(0, 1, 0));
hexagon.AddVertex(new Vector3(-1, 1, 0));
hexagon.AddVertex(new Vector3(-1, 0, 0));
return hexagon;
}
internal static Polyhedron CreateConcavePolyhedron()
{
var hexagon = new Polyhedron();
hexagon.AddVertex(new Vector3(0, 0, 0));
hexagon.AddVertex(new Vector3(2, 0, 0));
hexagon.AddVertex(new Vector3(2, 1, 0));
hexagon.AddVertex(new Vector3(2, 1, 0));
hexagon.AddVertex(new Vector3(0, 1, 0));
return hexagon;
}
}

View File

@ -13,21 +13,21 @@ public class RandomTests
var random = new Random(1234);
Assert.AreEqual(Color.FromArgb(51, 21, 21, 229), random.NextColorArgb());
}
[TestMethod]
public void NextColorArgb_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextColorArgb());
}
[TestMethod]
public void NextColorRgb_ShouldReturn1515e5_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(Color.FromArgb(255, 21, 21, 229), random.NextColorRgb());
}
[TestMethod]
public void NextColorRgb_ShouldThrow_GivenNull()
{

View File

@ -0,0 +1,42 @@
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class SizeTests
{
[TestMethod]
public void ToPoint_ShouldReturnPoint_WithEquivalentMembers()
{
var random = new Random();
var size = new Size(random.Next(), random.Next());
var point = size.ToPoint();
Assert.AreEqual(size.Width, point.X);
Assert.AreEqual(size.Height, point.Y);
}
[TestMethod]
public void ToPointF_ShouldReturnPoint_WithEquivalentMembers()
{
var random = new Random();
var size = new Size(random.Next(), random.Next());
var point = size.ToPointF();
Assert.AreEqual(size.Width, point.X, 1e-6f);
Assert.AreEqual(size.Height, point.Y, 1e-6f);
}
[TestMethod]
public void ToVector2_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var point = new Size(random.Next(), random.Next());
var size = point.ToVector2();
Assert.AreEqual(point.Width, size.X, 1e-6f);
Assert.AreEqual(point.Height, size.Y, 1e-6f);
}
}

View File

@ -0,0 +1,129 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class SphereTests
{
[TestMethod]
public void Circumference_ShouldBe2PiRadius_GivenUnitCircle()
{
var unitSphere = Sphere.Unit;
Assert.AreEqual(2.0f * MathF.PI * unitSphere.Radius, unitSphere.Circumference, 1e-6f);
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenUnitCircleAndEmpty()
{
Assert.AreEqual(-1, Sphere.Empty.CompareTo(Sphere.Unit));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenUnitCircleAndEmpty()
{
Assert.AreEqual(1, Sphere.Unit.CompareTo(Sphere.Empty));
}
[TestMethod]
public void CompareTo_ShouldBeNegativeOne_GivenEmptyCircleAndUnitCircleAsObject()
{
Assert.AreEqual(-1, Sphere.Empty.CompareTo((object)Sphere.Unit));
}
[TestMethod]
public void CompareTo_ShouldBeOne_GivenNull()
{
Assert.AreEqual(1, Sphere.Unit.CompareTo(null));
}
[TestMethod]
public void CompareTo_ShouldBeZero_GivenUnitCircle()
{
var unitCircle = Sphere.Unit;
Assert.AreEqual(0, unitCircle.CompareTo(unitCircle));
}
[TestMethod]
public void CompareTo_ShouldThrowArgumentException_GivenInvalidType()
{
Assert.ThrowsException<ArgumentException>(() => Sphere.Unit.CompareTo(new object()));
}
[TestMethod]
public void Diameter_ShouldBe2_GivenUnitSphere()
{
Assert.AreEqual(2.0f, Sphere.Unit.Diameter, 1e-6f);
}
[TestMethod]
public void Equals_ShouldBeTrue_GivenTwoUnitCircles()
{
var unitCircle1 = Sphere.Unit;
var unitCircle2 = Sphere.Unit;
Assert.AreEqual(unitCircle1, unitCircle2);
Assert.IsTrue(unitCircle1 == unitCircle2);
Assert.IsFalse(unitCircle1 != unitCircle2);
}
[TestMethod]
public void Equals_ShouldBeFalse_GivenDifferentCircles()
{
Assert.AreNotEqual(Sphere.Unit, Sphere.Empty);
Assert.IsFalse(Sphere.Unit == Sphere.Empty);
Assert.IsTrue(Sphere.Unit != Sphere.Empty);
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenEmptyCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Sphere.Empty.GetHashCode();
Assert.AreEqual(hashCode, Sphere.Empty.GetHashCode());
}
[TestMethod]
public void GetHashCode_ShouldBeCorrect_GivenUnitCircle()
{
// this test is pretty pointless, it exists only for code coverage purposes
int hashCode = Sphere.Unit.GetHashCode();
Assert.AreEqual(hashCode, Sphere.Unit.GetHashCode());
}
[TestMethod]
public void op_GreaterThan_True_GivenUnitAndEmptyCircle()
{
Assert.IsTrue(Sphere.Unit > Sphere.Empty);
Assert.IsTrue(Sphere.Unit >= Sphere.Empty);
Assert.IsFalse(Sphere.Unit < Sphere.Empty);
Assert.IsFalse(Sphere.Unit <= Sphere.Empty);
}
[TestMethod]
public void op_LessThan_True_GivenEmptyAndUnitCircle()
{
Assert.IsTrue(Sphere.Empty < Sphere.Unit);
Assert.IsTrue(Sphere.Empty <= Sphere.Unit);
Assert.IsFalse(Sphere.Empty > Sphere.Unit);
Assert.IsFalse(Sphere.Empty >= Sphere.Unit);
}
[TestMethod]
public void Radius_ShouldBe0_GivenEmptySphere()
{
Assert.AreEqual(0, Sphere.Empty.Radius);
}
[TestMethod]
public void Radius_ShouldBe1_GivenUnitSphere()
{
Assert.AreEqual(1, Sphere.Unit.Radius);
}
[TestMethod]
public void Volume_ShouldBe4Over3TimesPi_GivenUnitCircle()
{
var unitSphere = Sphere.Unit;
Assert.AreEqual(4.0f / 3.0f * MathF.PI, unitSphere.Volume);
}
}

View File

@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class DirectoryInfoTests
{
[TestMethod]
public void Clear_ShouldClear_GivenValidDirectory()
{
string tempPath = Path.GetTempPath();
DirectoryInfo directory;
do
{
string tempDirectory = Path.Combine(tempPath, Guid.NewGuid().ToString());
directory = new DirectoryInfo(tempDirectory);
} while (directory.Exists);
directory.Create();
Assert.IsTrue(directory.Exists);
var file = new FileInfo(Path.Combine(directory.FullName, "file"));
file.Create().Close();
var childDirectory = new DirectoryInfo(Path.Combine(directory.FullName, "child"));
childDirectory.Create();
var childFile = new FileInfo(Path.Combine(childDirectory.FullName, "childFile"));
childFile.Create().Close();
Assert.AreEqual(1, directory.GetFiles().Length);
Assert.AreEqual(1, directory.GetDirectories().Length);
directory.Clear();
Assert.AreEqual(0, directory.GetFiles().Length);
Assert.AreEqual(0, directory.GetDirectories().Length);
Assert.IsTrue(directory.Exists);
directory.Delete();
}
[TestMethod]
public void Clear_ShouldThrowArgumentNullException_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((DirectoryInfo?)null)!.Clear());
}
[TestMethod]
public void Clear_ShouldThrowDirectoryNotFoundException_GivenInvalidDirectory()
{
var directory = new DirectoryInfo(@"123:/@12#3");
Assert.ThrowsException<DirectoryNotFoundException>(() => directory.Clear());
}
[TestMethod]
public void Clear_ShouldThrowDirectoryNotFoundException_GivenNonExistentDirectory()
{
var directory = new DirectoryInfo(@"/@12#3");
Assert.IsFalse(directory.Exists);
Assert.ThrowsException<DirectoryNotFoundException>(() => directory.Clear());
}
}

View File

@ -10,7 +10,7 @@ public class Int16Tests
public void ProductShouldBeCorrect()
{
short Cast(int i) => (short)i;
Assert.AreEqual(0, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2, Enumerable.Range(1, 2).Select(Cast).Product());

View File

@ -30,6 +30,28 @@ public class ByteTests
Assert.AreEqual(3628800L, ((byte)10).Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const byte first = 5;
const byte second = 7;
byte multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const byte first = 12;
const byte second = 18;
byte multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{

View File

@ -30,12 +30,34 @@ public class Int16Tests
Assert.AreEqual(3628800L, ((short)10).Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const short first = 5;
const short second = 7;
short multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const short first = 12;
const short second = 18;
short multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const short one = 1;
const short two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
@ -45,7 +67,7 @@ public class Int16Tests
{
const short one = 1;
const short two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}

View File

@ -30,12 +30,34 @@ public class Int32Tests
Assert.AreEqual(3628800L, 10.Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const int first = 5;
const int second = 7;
int multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const int first = 12;
const int second = 18;
int multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const int one = 1;
const int two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
@ -45,7 +67,7 @@ public class Int32Tests
{
const int one = 1;
const int two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}

View File

@ -30,12 +30,34 @@ public class Int64Tests
Assert.AreEqual(3628800L, 10L.Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const long first = 5L;
const long second = 7L;
long multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1L, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const long first = 12L;
const long second = 18L;
long multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6L, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const long one = 1;
const long two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
@ -45,7 +67,7 @@ public class Int64Tests
{
const long one = 1;
const long two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}

View File

@ -0,0 +1,100 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class MathUtilityTests
{
[TestMethod]
public void GammaToLinear_ShouldReturnQuarter_GivenQuarterAndGamma1()
{
double doubleResult = MathUtility.GammaToLinear(0.25, 1.0);
float floatResult = MathUtility.GammaToLinear(0.25f, 1.0f);
Assert.AreEqual(0.25, doubleResult);
Assert.AreEqual(0.25f, floatResult);
}
[TestMethod]
public void GammaToLinear_ShouldReturn1_Given1AndDefaultGamma()
{
double doubleResult = MathUtility.GammaToLinear(1.0);
float floatResult = MathUtility.GammaToLinear(1.0f);
Assert.AreEqual(1.0, doubleResult);
Assert.AreEqual(1.0f, floatResult);
}
[TestMethod]
public void InverseLerp_ShouldReturn0_5_Given0_5_0_1()
{
double doubleResult = MathUtility.InverseLerp(0.5, 0.0, 1.0);
float floatResult = MathUtility.InverseLerp(0.5f, 0f, 1f);
Assert.AreEqual(0.5, doubleResult, 1e-6);
Assert.AreEqual(0.5f, floatResult, 1e-6f);
}
[TestMethod]
public void InverseLerp_ShouldReturn0_5_Given5_0_10()
{
double doubleResult = MathUtility.InverseLerp(5.0, 0.0, 10.0);
float floatResult = MathUtility.InverseLerp(5f, 0f, 10f);
Assert.AreEqual(0.5, doubleResult, 1e-6);
Assert.AreEqual(0.5f, floatResult, 1e-6f);
}
[TestMethod]
public void InverseLerp_ShouldReturn0_GivenTwoEqualValues()
{
var random = new Random();
double doubleA = random.NextDouble();
double doubleB = random.NextDouble();
float floatA = random.NextSingle();
float floatB = random.NextSingle();
double doubleResult = MathUtility.InverseLerp(doubleA, doubleB, doubleB);
float floatResult = MathUtility.InverseLerp(floatA, floatB, floatB);
Assert.AreEqual(0.0, doubleResult, 1e-6);
Assert.AreEqual(0.0f, floatResult, 1e-6f);
}
[TestMethod]
public void LinearToGamma_ShouldReturnQuarter_GivenQuarterAndGamma1()
{
double doubleResult = MathUtility.LinearToGamma(0.25, 1.0);
float floatResult = MathUtility.LinearToGamma(0.25f, 1.0f);
Assert.AreEqual(0.25, doubleResult);
Assert.AreEqual(0.25f, floatResult);
}
[TestMethod]
public void LinearToGamma_ShouldReturn1_Given1AndDefaultGamma()
{
double doubleResult = MathUtility.LinearToGamma(1.0);
float floatResult = MathUtility.LinearToGamma(1.0f);
Assert.AreEqual(1.0, doubleResult);
Assert.AreEqual(1.0f, floatResult);
}
[TestMethod]
public void ScaleRangeDouble_ShouldScaleRange_GivenItsValues()
{
double result = MathUtility.ScaleRange(0.5, 0.0, 1.0, 5.0, 10.0);
Assert.AreEqual(7.5, result);
}
[TestMethod]
public void ScaleRangeSingle_ShouldScaleRange_GivenItsValues()
{
float result = MathUtility.ScaleRange(0.5f, 0.0f, 1.0f, 5.0f, 10.0f);
Assert.AreEqual(7.5f, result);
}
}

View File

@ -31,6 +31,28 @@ public class SByteTests
Assert.AreEqual(3628800L, ((sbyte)10).Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const sbyte first = 5;
const sbyte second = 7;
sbyte multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const sbyte first = 12;
const sbyte second = 18;
sbyte multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{

View File

@ -14,7 +14,7 @@ public class UInt16Tests
Assert.AreEqual(4, value.DigitalRoot());
Assert.AreEqual(4, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
@ -31,12 +31,34 @@ public class UInt16Tests
Assert.AreEqual(3628800UL, ((ushort)10).Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const ushort first = 5;
const ushort second = 7;
ushort multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const ushort first = 12;
const ushort second = 18;
ushort multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const ushort one = 1;
const ushort two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
@ -46,7 +68,7 @@ public class UInt16Tests
{
const ushort one = 1;
const ushort two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}

View File

@ -31,6 +31,28 @@ public class UInt32Tests
Assert.AreEqual(3628800UL, 10U.Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const uint first = 5U;
const uint second = 7U;
uint multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1U, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const uint first = 12U;
const uint second = 18U;
uint multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6U, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{

View File

@ -35,12 +35,34 @@ public class UInt64Tests
Assert.AreEqual(3628800UL, 10UL.Factorial());
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe1_ForPrimeNumbers()
{
const ulong first = 5UL;
const ulong second = 7UL;
ulong multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(1UL, multiple);
}
[TestMethod]
public void GreatestCommonFactor_ShouldBe6_Given12And18()
{
const ulong first = 12UL;
const ulong second = 18UL;
ulong multiple = first.GreatestCommonFactor(second);
Assert.AreEqual(6UL, multiple);
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const ulong one = 1;
const ulong two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
@ -50,7 +72,7 @@ public class UInt64Tests
{
const ulong one = 1;
const ulong two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}

View File

@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class ByteTests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, ((byte)0).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, ((byte)0b11010101).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe8_Given11111111()
{
Assert.AreEqual(8, ((byte)0b11111111).PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -39,4 +57,29 @@ public class ByteTests
const byte value = 181; // 10110101
Assert.AreEqual(value, value.RotateRight(8));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, ((byte)3).RoundUpToPowerOf2());
Assert.AreEqual(8, ((byte)5).RoundUpToPowerOf2());
Assert.AreEqual(8, ((byte)6).RoundUpToPowerOf2());
Assert.AreEqual(8, ((byte)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (byte)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, ((byte)0).RoundUpToPowerOf2());
}
}

View File

@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, ((short)0).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, ((short)0b11010101).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe15_Given0111111111111111()
{
Assert.AreEqual(15, ((short)0b0111111111111111).PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -41,4 +59,29 @@ public class Int16Tests
const short value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateRight(16));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, ((short)3).RoundUpToPowerOf2());
Assert.AreEqual(8, ((short)5).RoundUpToPowerOf2());
Assert.AreEqual(8, ((short)6).RoundUpToPowerOf2());
Assert.AreEqual(8, ((short)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (short)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, ((short)0).RoundUpToPowerOf2());
}
}

View File

@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, ((uint)0).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, ((uint)0b11010101).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe31_Given11111111111111111111111111111111()
{
Assert.AreEqual(31, 0b01111111111111111111111111111111.PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -39,4 +57,29 @@ public class Int32Tests
const int value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateRight(32));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, 3.RoundUpToPowerOf2());
Assert.AreEqual(8, 5.RoundUpToPowerOf2());
Assert.AreEqual(8, 6.RoundUpToPowerOf2());
Assert.AreEqual(8, 7.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (int)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, 0.RoundUpToPowerOf2());
}
}

View File

@ -6,6 +6,24 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, 0L.PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, 0b11010101L.PopCount());
}
[TestMethod]
public void PopCount_ShouldBe63_Given0111111111111111111111111111111111111111111111111111111111111111()
{
Assert.AreEqual(63, 0b0111111111111111111111111111111111111111111111111111111111111111L.PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -39,4 +57,29 @@ public class Int64Tests
const long value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateRight(64));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4L, 3L.RoundUpToPowerOf2());
Assert.AreEqual(8L, 5L.RoundUpToPowerOf2());
Assert.AreEqual(8L, 6L.RoundUpToPowerOf2());
Assert.AreEqual(8L, 7L.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (long)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0L, 0L.RoundUpToPowerOf2());
}
}

View File

@ -0,0 +1,21 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class QuaternionTests
{
[TestMethod]
public void ToAxisAngle_ShouldGiveAngle180VectorZero_GivenQuaternion()
{
Vector3 axis = Vector3.UnitY;
const float angle = MathF.PI;
var quaternion = Quaternion.CreateFromAxisAngle(axis, angle);
(Vector3 Axis, float Angle) axisAngle = quaternion.ToAxisAngle();
Assert.AreEqual(axis, axisAngle.Axis);
Assert.AreEqual(angle, axisAngle.Angle);
}
}

View File

@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
[CLSCompliant(false)]
public class SByteTests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, ((sbyte)0).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe4_Given01010101()
{
Assert.AreEqual(4, ((sbyte)0b01010101).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe7_Given01111111()
{
Assert.AreEqual(7, ((sbyte)0b01111111).PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -40,4 +58,29 @@ public class SByteTests
const sbyte value = 117; // 01110101
Assert.AreEqual(value, value.RotateRight(8));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4, ((sbyte)3).RoundUpToPowerOf2());
Assert.AreEqual(8, ((sbyte)5).RoundUpToPowerOf2());
Assert.AreEqual(8, ((sbyte)6).RoundUpToPowerOf2());
Assert.AreEqual(8, ((sbyte)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 7; i++)
{
var value = (sbyte)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0, ((sbyte)0).RoundUpToPowerOf2());
}
}

View File

@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
[CLSCompliant(false)]
public class UInt16Tests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, ((ushort)0).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, ((ushort)0b11010101).PopCount());
}
[TestMethod]
public void PopCount_ShouldBe16_Given1111111111111111()
{
Assert.AreEqual(16, ((ushort)0b1111111111111111).PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -42,4 +60,29 @@ public class UInt16Tests
const ushort value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateRight(16));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4U, ((ushort)3).RoundUpToPowerOf2());
Assert.AreEqual(8U, ((ushort)5).RoundUpToPowerOf2());
Assert.AreEqual(8U, ((ushort)6).RoundUpToPowerOf2());
Assert.AreEqual(8U, ((ushort)7).RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (ushort)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0U, ((ushort)0).RoundUpToPowerOf2());
}
}

View File

@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
[CLSCompliant(false)]
public class UInt32Tests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, 0U.PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, 0b11010101U.PopCount());
}
[TestMethod]
public void PopCount_ShouldBe32_Given11111111111111111111111111111111()
{
Assert.AreEqual(32, 0b11111111111111111111111111111111U.PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -40,4 +58,29 @@ public class UInt32Tests
const uint value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateRight(32));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4U, 3U.RoundUpToPowerOf2());
Assert.AreEqual(8U, 5U.RoundUpToPowerOf2());
Assert.AreEqual(8U, 6U.RoundUpToPowerOf2());
Assert.AreEqual(8U, 7U.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (uint)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0U, 0U.RoundUpToPowerOf2());
}
}

View File

@ -7,6 +7,24 @@ namespace X10D.Tests.Numerics;
[CLSCompliant(false)]
public class UInt64Tests
{
[TestMethod]
public void PopCount_ShouldBe0_Given0()
{
Assert.AreEqual(0, 0UL.PopCount());
}
[TestMethod]
public void PopCount_ShouldBe5_Given11010101()
{
Assert.AreEqual(5, 0b11010101UL.PopCount());
}
[TestMethod]
public void PopCount_ShouldBe64_Given1111111111111111111111111111111111111111111111111111111111111111()
{
Assert.AreEqual(64, 0b1111111111111111111111111111111111111111111111111111111111111111UL.PopCount());
}
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
@ -40,4 +58,29 @@ public class UInt64Tests
const ulong value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateRight(64));
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnRoundedValue_GivenValue()
{
Assert.AreEqual(4UL, 3UL.RoundUpToPowerOf2());
Assert.AreEqual(8UL, 5UL.RoundUpToPowerOf2());
Assert.AreEqual(8UL, 6UL.RoundUpToPowerOf2());
Assert.AreEqual(8UL, 7UL.RoundUpToPowerOf2());
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturnSameValue_GivenPowerOf2()
{
for (var i = 0; i < 8; i++)
{
var value = (ulong)System.Math.Pow(2, i);
Assert.AreEqual(value, value.RoundUpToPowerOf2());
}
}
[TestMethod]
public void RoundUpToPowerOf2_ShouldReturn0_Given0()
{
Assert.AreEqual(0UL, 0UL.RoundUpToPowerOf2());
}
}

View File

@ -1,5 +1,7 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
using X10D.Drawing;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
@ -7,6 +9,84 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class Vector2Tests
{
[TestMethod]
public void Deconstruct_ShouldReturnCorrectValues()
{
var vector = new Vector2(1, 2);
(float x, float y) = vector;
Assert.AreEqual(1, x);
Assert.AreEqual(2, y);
}
[TestMethod]
public void IsOnLine_ShouldReturnTrue_ForPointOnLine()
{
Vector2 start = Vector2.Zero;
Vector2 end = Vector2.UnitX;
Vector2 point = new Vector2(0.5f, 0.0f);
var line = new LineF(start, end);
Assert.IsTrue(point.IsOnLine(line));
Assert.IsTrue(point.IsOnLine(line.Start, line.End));
Assert.IsTrue(point.IsOnLine(line.Start.ToVector2(), line.End.ToVector2()));
}
[TestMethod]
public void IsOnLine_ShouldReturnFalse_ForPointNotOnLine()
{
Vector2 start = Vector2.Zero;
Vector2 end = Vector2.UnitX;
Vector2 point = new Vector2(0.5f, 1.0f);
var line = new LineF(start, end);
Assert.IsFalse(point.IsOnLine(line));
Assert.IsFalse(point.IsOnLine(line.Start, line.End));
Assert.IsFalse(point.IsOnLine(line.Start.ToVector2(), line.End.ToVector2()));
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector2(1.5f, 2.6f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector2(1.5f, 25.2f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
}
[TestMethod]
public void ToPointF_ShouldReturnPoint_WithEquivalentMembers()
{
var random = new Random();
var vector = new Vector2(random.NextSingle(), random.NextSingle());
var point = vector.ToPointF();
Assert.AreEqual(vector.X, point.X, 1e-6f);
Assert.AreEqual(vector.Y, point.Y, 1e-6f);
}
[TestMethod]
public void ToSizeF_ShouldReturnSize_WithEquivalentMembers()
{
var random = new Random();
var vector = new Vector2(random.NextSingle(), random.NextSingle());
var size = vector.ToSizeF();
Assert.AreEqual(vector.X, size.Width);
Assert.AreEqual(vector.Y, size.Height);
}
[TestMethod]
public void WithX_ShouldReturnVectorWithNewX_GivenVector()
{

View File

@ -7,6 +7,39 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class Vector3Tests
{
[TestMethod]
public void Deconstruct_ShouldReturnCorrectValues()
{
var vector = new Vector3(1, 2, 3);
(float x, float y, float z) = vector;
Assert.AreEqual(1, x);
Assert.AreEqual(2, y);
Assert.AreEqual(3, z);
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector3(1.5f, 2.6f, -5.2f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
Assert.AreEqual(-5, rounded.Z);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector3(1.5f, 25.2f, -12.5f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
Assert.AreEqual(-10, rounded.Z);
}
[TestMethod]
public void WithX_ShouldReturnVectorWithNewX_GivenVector()
{

View File

@ -7,6 +7,42 @@ namespace X10D.Tests.Numerics;
[TestClass]
public class Vector4Tests
{
[TestMethod]
public void Deconstruct_ShouldReturnCorrectValues()
{
var vector = new Vector4(1, 2, 3, 4);
(float x, float y, float z, float w) = vector;
Assert.AreEqual(1, x);
Assert.AreEqual(2, y);
Assert.AreEqual(3, z);
Assert.AreEqual(4, w);
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger_GivenNoParameters()
{
var vector = new Vector4(1.5f, 2.6f, -5.2f, 0.3f);
var rounded = vector.Round();
Assert.AreEqual(2, rounded.X);
Assert.AreEqual(3, rounded.Y);
Assert.AreEqual(-5, rounded.Z);
Assert.AreEqual(0, rounded.W);
}
[TestMethod]
public void Round_ShouldRoundToNearest10_GivenPrecision10()
{
var vector = new Vector4(1.5f, 25.2f, -12.5f, 101.2f);
var rounded = vector.Round(10);
Assert.AreEqual(0, rounded.X);
Assert.AreEqual(30, rounded.Y);
Assert.AreEqual(-10, rounded.Z);
Assert.AreEqual(100, rounded.W);
}
[TestMethod]
public void WithW_ShouldReturnVectorWithNewW_GivenVector()
{

View File

@ -0,0 +1,39 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Text;
namespace X10D.Tests.Text;
[TestClass]
public class CharSpanTests
{
[TestMethod]
public void CountSubstring_ShouldHonor_StringComparison()
{
Assert.AreEqual(0, "Hello World".AsSpan().CountSubstring('E'));
Assert.AreEqual(0, "Hello World".AsSpan().CountSubstring("E".AsSpan()));
Assert.AreEqual(1, "Hello World".AsSpan().CountSubstring("E".AsSpan(), StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldReturn0_GivenNoInstanceChar()
{
Assert.AreEqual(0, "Hello World".AsSpan().CountSubstring('z'));
Assert.AreEqual(0, "Hello World".AsSpan().CountSubstring("z".AsSpan()));
Assert.AreEqual(0, "Hello World".AsSpan().CountSubstring("z".AsSpan(), StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldReturn1_GivenSingleInstanceChar()
{
Assert.AreEqual(1, "Hello World".AsSpan().CountSubstring('e'));
Assert.AreEqual(1, "Hello World".AsSpan().CountSubstring("e".AsSpan()));
Assert.AreEqual(1, "Hello World".AsSpan().CountSubstring("e".AsSpan(), StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldReturn0_GivenEmptyHaystack()
{
Assert.AreEqual(0, string.Empty.AsSpan().CountSubstring('\0'));
Assert.AreEqual(0, string.Empty.AsSpan().CountSubstring(string.Empty.AsSpan(), StringComparison.OrdinalIgnoreCase));
}
}

View File

@ -1,5 +1,4 @@
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Text;
namespace X10D.Tests.Text;

View File

@ -101,6 +101,47 @@ public class StringTests
Assert.ThrowsException<ArgumentNullException>(() => "Hello World".ChangeEncoding(Encoding.UTF8, null!));
}
[TestMethod]
public void CountSubstring_ShouldHonor_StringComparison()
{
Assert.AreEqual(0, "Hello World".CountSubstring('E'));
Assert.AreEqual(0, "Hello World".CountSubstring("E"));
Assert.AreEqual(1, "Hello World".CountSubstring("E", StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldReturn0_GivenNoInstanceChar()
{
Assert.AreEqual(0, "Hello World".CountSubstring('z'));
Assert.AreEqual(0, "Hello World".CountSubstring("z"));
Assert.AreEqual(0, "Hello World".CountSubstring("z", StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldReturn1_GivenSingleInstanceChar()
{
Assert.AreEqual(1, "Hello World".CountSubstring('e'));
Assert.AreEqual(1, "Hello World".CountSubstring("e"));
Assert.AreEqual(1, "Hello World".CountSubstring("e", StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldReturn0_GivenEmptyHaystack()
{
Assert.AreEqual(0, string.Empty.CountSubstring('\0'));
Assert.AreEqual(0, string.Empty.CountSubstring(string.Empty));
Assert.AreEqual(0, string.Empty.CountSubstring(string.Empty, StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void CountSubstring_ShouldThrow_GivenNullHaystack()
{
Assert.ThrowsException<ArgumentNullException>(() => ((string?)null!).CountSubstring('\0'));
Assert.ThrowsException<ArgumentNullException>(() => ((string?)null!).CountSubstring(string.Empty));
Assert.ThrowsException<ArgumentNullException>(() =>
((string?)null!).CountSubstring(string.Empty, StringComparison.OrdinalIgnoreCase));
}
[TestMethod]
public void EnumParse_ShouldReturnCorrectValue_GivenString()
{
@ -237,6 +278,32 @@ public class StringTests
Assert.IsFalse("World".IsEmoji());
}
[TestMethod]
public void IsEmpty_ShouldReturnTrue_GivenEmptyString()
{
Assert.IsTrue("".IsEmpty());
Assert.IsTrue(string.Empty.IsEmpty());
}
[TestMethod]
public void IsEmpty_ShouldReturnFalse_GivenWhiteSpaceString()
{
Assert.IsFalse(" ".IsEmpty());
}
[TestMethod]
public void IsEmpty_ShouldReturnFalse_GivenNonEmptyString()
{
Assert.IsFalse("Hello World".IsEmpty());
}
[TestMethod]
public void IsEmpty_ShouldThrowArgumentNullException_GivenNullString()
{
string? value = null;
Assert.ThrowsException<ArgumentNullException>(() => value!.IsEmpty());
}
[TestMethod]
public void IsLower_ShouldReturnTrue_GivenLowercaseString()
{
@ -262,6 +329,58 @@ public class StringTests
Assert.ThrowsException<ArgumentNullException>(() => value!.IsLower());
}
[TestMethod]
public void IsNullOrEmpty_ShouldReturnTrue_GivenEmptyString()
{
Assert.IsTrue("".IsNullOrEmpty());
Assert.IsTrue(string.Empty.IsNullOrEmpty());
}
[TestMethod]
public void IsNullOrEmpty_ShouldReturnFalse_GivenWhiteSpaceString()
{
Assert.IsFalse(" ".IsNullOrEmpty());
}
[TestMethod]
public void IsNullOrEmpty_ShouldReturnFalse_GivenNonEmptyString()
{
Assert.IsFalse("Hello World".IsNullOrEmpty());
}
[TestMethod]
public void IsNullOrEmpty_ShouldReturnTrue_GivenNullString()
{
string? value = null;
Assert.IsTrue(value.IsNullOrEmpty());
}
[TestMethod]
public void IsNullOrWhiteSpace_ShouldReturnTrue_GivenEmptyString()
{
Assert.IsTrue("".IsNullOrWhiteSpace());
Assert.IsTrue(string.Empty.IsNullOrWhiteSpace());
}
[TestMethod]
public void IsNullOrWhiteSpace_ShouldReturnTrue_GivenWhiteSpaceString()
{
Assert.IsTrue(" ".IsNullOrWhiteSpace());
}
[TestMethod]
public void IsNullOrWhiteSpace_ShouldReturnFalse_GivenNonEmptyString()
{
Assert.IsFalse("Hello World".IsNullOrWhiteSpace());
}
[TestMethod]
public void IsNullOrWhiteSpace_ShouldReturnTrue_GivenNullString()
{
string? value = null;
Assert.IsTrue(value.IsNullOrWhiteSpace());
}
[TestMethod]
public void IsPalindrome_ShouldBeCorrect_GivenString()
{
@ -317,6 +436,32 @@ public class StringTests
Assert.ThrowsException<ArgumentNullException>(() => value!.IsUpper());
}
[TestMethod]
public void IsWhiteSpace_ShouldReturnTrue_GivenEmptyString()
{
Assert.IsTrue("".IsWhiteSpace());
Assert.IsTrue(string.Empty.IsWhiteSpace());
}
[TestMethod]
public void IsWhiteSpace_ShouldReturnTrue_GivenWhiteSpaceString()
{
Assert.IsTrue(" ".IsWhiteSpace());
}
[TestMethod]
public void IsWhiteSpace_ShouldReturnFalse_GivenNonEmptyString()
{
Assert.IsFalse("Hello World".IsWhiteSpace());
}
[TestMethod]
public void IsWhiteSpace_ShouldThrowArgumentNullException_GivenNullString()
{
string? value = null;
Assert.ThrowsException<ArgumentNullException>(() => value!.IsWhiteSpace());
}
[TestMethod]
public void Randomize_ShouldReorder_GivenString()
{

View File

@ -0,0 +1,31 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Time;
namespace X10D.Tests.Time;
[TestClass]
public class CharSpanTests
{
[TestMethod]
public void ToTimeSpan_ShouldReturnCorrectTimeSpan_GivenSpanOfCharacters()
{
ReadOnlySpan<char> value = "1y 1mo 1w 1d 1h 1m 1s 1ms".AsSpan();
TimeSpan expected = TimeSpan.FromMilliseconds(1);
expected += TimeSpan.FromSeconds(1);
expected += TimeSpan.FromMinutes(1);
expected += TimeSpan.FromHours(1);
expected += TimeSpan.FromDays(1);
expected += TimeSpan.FromDays(7);
expected += TimeSpan.FromDays(30);
expected += TimeSpan.FromDays(365);
Assert.AreEqual(expected, value.ToTimeSpan());
}
[TestMethod]
public void ToTimeSpan_ShouldReturnZero_GivenInvalidSpanOfCharacters()
{
Assert.AreEqual(TimeSpan.Zero, "Hello World".AsSpan().ToTimeSpan());
}
}

View File

@ -7,9 +7,26 @@ namespace X10D.Tests.Time;
public class TimeSpanParserTests
{
[TestMethod]
public void TryParse_ShouldThrow_GivenNullString()
public void TryParse_ShouldReturnTrue_GivenWellFormedTimeSpan()
{
string? value = null;
Assert.ThrowsException<ArgumentNullException>(() => TimeSpanParser.TryParse(value!, out _));
bool result = TimeSpanParser.TryParse("3d6h", out TimeSpan timeSpan);
Assert.IsTrue(result);
Assert.AreEqual(TimeSpan.FromDays(3) + TimeSpan.FromHours(6), timeSpan);
}
[TestMethod]
public void TryParse_ShouldReturnFalse_GivenMalformedTimeSpan()
{
bool result = TimeSpanParser.TryParse("asdf", out TimeSpan timeSpan);
Assert.IsFalse(result);
Assert.AreEqual(default, timeSpan);
}
[TestMethod]
public void TryParse_ShouldReturnFalse_GivenNull()
{
bool result = TimeSpanParser.TryParse(null, out TimeSpan timeSpan);
Assert.IsFalse(result);
Assert.AreEqual(default, timeSpan);
}
}

View File

@ -0,0 +1,354 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 256
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 1
m_PVRDenoiserTypeDirect: 1
m_PVRDenoiserTypeIndirect: 1
m_PVRDenoiserTypeAO: 1
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &192863441
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 192863443}
- component: {fileID: 192863442}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &192863442
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 192863441}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0fac6b15ed0b420ba300fc1ac10ef01a, type: 3}
m_Name:
m_EditorClassIdentifier:
_hexagonPoints:
- {x: -0.5, y: 0.5}
- {x: -0.25, y: 1}
- {x: 0.25, y: 1}
- {x: 0.5, y: 0.5}
- {x: 0.25, y: 0}
- {x: -0.25, y: 0}
--- !u!4 &192863443
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 192863441}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &585803459
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 585803461}
- component: {fileID: 585803460}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &585803460
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 585803459}
m_Enabled: 1
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_UseViewFrustumForShadowCasterCull: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &585803461
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 585803459}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &1189625736
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1189625739}
- component: {fileID: 1189625738}
- component: {fileID: 1189625737}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &1189625737
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1189625736}
m_Enabled: 1
--- !u!20 &1189625738
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1189625736}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1189625739
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1189625736}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f2337eeeb085a25408461d996bb20a9c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,347 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 256
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 1
m_PVRDenoiserTypeDirect: 1
m_PVRDenoiserTypeIndirect: 1
m_PVRDenoiserTypeAO: 1
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 1
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 0}
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &736700400
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 736700402}
- component: {fileID: 736700401}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &736700401
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 736700400}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 67d53e2f993d4a5ba0eb34431d1846cd, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!4 &736700402
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 736700400}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1077233431
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1077233433}
- component: {fileID: 1077233432}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &1077233432
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1077233431}
m_Enabled: 1
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_UseViewFrustumForShadowCasterCull: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &1077233433
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1077233431}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &1698122894
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1698122897}
- component: {fileID: 1698122896}
- component: {fileID: 1698122895}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &1698122895
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1698122894}
m_Enabled: 1
--- !u!20 &1698122896
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1698122894}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1698122897
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1698122894}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b95b5f3924bd65b4bb0b7703abdd4fe5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,40 @@
using UnityEngine;
using X10D.Drawing;
using X10D.Unity.Drawing;
using Color = UnityEngine.Color;
namespace X10D.Unity.Tests
{
internal sealed class DebugExIntegrationTests : MonoBehaviour
{
private void Update()
{
DebugEx.DrawLine(Vector3.zero, Vector3.right, Color.red);
DebugEx.DrawLine(Vector3.zero, Vector3.up, Color.green);
DebugEx.DrawLine(Vector3.zero, Vector3.forward, Color.blue);
DebugEx.DrawWireCube(new Vector3(1.5f, 0.5f, 0), Vector3.one * 0.5f, Color.yellow);
DebugEx.DrawRectangle(new Vector2(-1.5f, 0.5f), Vector2.one * -0.5f, Color.cyan);
var circle = new CircleF(0.0f, 0.0f, 0.5f);
DebugEx.DrawCircle(circle, 25, new Vector2(-3.0f, 0.5f), Color.magenta);
var ellipse = new EllipseF(0.0f, 0.0f, 1.0f, 0.5f);
DebugEx.DrawEllipse(ellipse, 25, new Vector2(0.0f, 1.5f), Color.white);
var hexagon = new PolygonF();
hexagon.AddVertex(new Vector2(-0.5f, 0.5f));
hexagon.AddVertex(new Vector2(-0.25f, 1.0f));
hexagon.AddVertex(new Vector2(0.25f, 1.0f));
hexagon.AddVertex(new Vector2(0.5f, 0.5f));
hexagon.AddVertex(new Vector2(0.25f, 0));
hexagon.AddVertex(new Vector2(-0.25f, 0));
DebugEx.DrawPolygon(hexagon, new Vector2(3.0f, 0.0f), Color.white);
var sphere = new Sphere(System.Numerics.Vector3.Zero, 0.5f);
DebugEx.DrawSphere(sphere, 25, new Vector2(0.0f, -1.5f), Color.white);
DebugEx.Assert(true);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0fac6b15ed0b420ba300fc1ac10ef01a
timeCreated: 1654080788

View File

@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
@ -8,14 +9,53 @@ namespace X10D.Unity.Tests.Drawing
{
public class Color32Tests
{
private static readonly Color32 Black = new(0, 0, 0, 1);
private static readonly Color32 White = new(255, 255, 255, 1);
private static readonly Color32 Red = new(255, 0, 0, 1);
private static readonly Color32 Green = new(0, 255, 0, 1);
private static readonly Color32 Blue = new(0, 0, 255, 1);
private static readonly Color32 Cyan = new(0, 255, 255, 1);
private static readonly Color32 Magenta = new(255, 0, 255, 1);
private static readonly Color32 Yellow = new(255, 255, 0, 1);
private static readonly Color32 Black = new(0, 0, 0, 255);
private static readonly Color32 White = new(255, 255, 255, 255);
private static readonly Color32 Red = new(255, 0, 0, 255);
private static readonly Color32 Green = new(0, 255, 0, 255);
private static readonly Color32 Blue = new(0, 0, 255, 255);
private static readonly Color32 Cyan = new(0, 255, 255, 255);
private static readonly Color32 Magenta = new(255, 0, 255, 255);
private static readonly Color32 Yellow = new(255, 255, 0, 255);
[UnityTest]
public IEnumerator Deconstruct_ShouldDeconstruct_ToCorrectValues()
{
byte a, r, g, b;
(r, g, b) = White;
Assert.AreEqual(255, r);
Assert.AreEqual(255, g);
Assert.AreEqual(255, b);
(a, r, g, b) = Yellow;
Assert.AreEqual(255, a);
Assert.AreEqual(255, r);
Assert.AreEqual(255, g);
Assert.AreEqual(0, b);
yield break;
}
[UnityTest]
public IEnumerator GetClosestConsoleColor_ShouldReturnClosestColor_GivenValidColor()
{
// I know it's just casting... but aim for 100% coverage babyyyy
Assert.AreEqual(ConsoleColor.Red, ((Color32)Color.red).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Green, ((Color32)Color.green).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Blue, ((Color32)Color.blue).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, ((Color32)Color.white).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Black, ((Color32)Color.black).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, ((Color32)Color.yellow).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, ((Color32)Color.cyan).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Magenta, ((Color32)Color.magenta).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, ((Color32)Color.gray).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, ((Color32)Color.grey).GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Black, ((Color32)Color.clear).GetClosestConsoleColor());
yield break;
}
[UnityTest]
public IEnumerator Inverted_ShouldReturnInvertedColor()
@ -43,6 +83,28 @@ namespace X10D.Unity.Tests.Drawing
yield break;
}
[UnityTest]
public IEnumerator ToSystemDrawingColor_ShouldReturnEquivalentColor()
{
System.Drawing.Color expected = System.Drawing.Color.FromArgb(255, 255, 255);
System.Drawing.Color actual = White.ToSystemDrawingColor();
Assert.AreEqual(expected, actual);
yield break;
}
[UnityTest]
public IEnumerator ToUnityColor32_ShouldReturnEquivalentColor()
{
Color32 expected = White;
Color32 actual = System.Drawing.Color.FromArgb(255, 255, 255).ToUnityColor32();
Assert.AreEqual(expected, actual);
yield break;
}
[UnityTest]
public IEnumerator WithA0_ShouldReturnSameColor_GivenWhite()
{

View File

@ -1,4 +1,7 @@
using System.Collections;
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
@ -17,6 +20,43 @@ namespace X10D.Unity.Tests.Drawing
private static readonly Color Magenta = new(1, 0, 1);
private static readonly Color Yellow = new(1, 1, 0);
[UnityTest]
public IEnumerator Deconstruct_ShouldDeconstruct_ToCorrectValues()
{
float a, r, g, b;
(r, g, b) = White;
Assert.AreEqual(1.0f, r);
Assert.AreEqual(1.0f, g);
Assert.AreEqual(1.0f, b);
(a, r, g, b) = Yellow;
Assert.AreEqual(1.0f, a);
Assert.AreEqual(1.0f, r);
Assert.AreEqual(1.0f, g);
Assert.AreEqual(0.0f, b);
yield break;
}
[UnityTest]
public IEnumerator GetClosestConsoleColor_ShouldReturnClosestColor_GivenValidColor()
{
Assert.AreEqual(ConsoleColor.Red, Color.red.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Green, Color.green.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Blue, Color.blue.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.White, Color.white.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Black, Color.black.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Yellow, Color.yellow.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Cyan, Color.cyan.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Magenta, Color.magenta.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.gray.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Gray, Color.grey.GetClosestConsoleColor());
Assert.AreEqual(ConsoleColor.Black, Color.clear.GetClosestConsoleColor());
yield break;
}
[UnityTest]
public IEnumerator Inverted_ShouldReturnInvertedColor()
{
@ -43,6 +83,28 @@ namespace X10D.Unity.Tests.Drawing
yield break;
}
[UnityTest]
public IEnumerator ToSystemDrawingColor_ShouldReturnEquivalentColor()
{
System.Drawing.Color expected = System.Drawing.Color.FromArgb(255, 255, 255);
System.Drawing.Color actual = White.ToSystemDrawingColor();
Assert.AreEqual(expected, actual);
yield break;
}
[UnityTest]
public IEnumerator ToUnityColor_ShouldReturnEquivalentColor()
{
Color expected = White;
Color actual = System.Drawing.Color.FromArgb(255, 255, 255).ToUnityColor();
Assert.AreEqual(expected, actual);
yield break;
}
[UnityTest]
public IEnumerator WithA0_ShouldReturnSameColor_GivenWhite()
{

View File

@ -0,0 +1,26 @@
using System;
using System.Collections;
using System.Drawing;
using NUnit.Framework;
using UnityEngine.TestTools;
using X10D.Core;
using X10D.Unity.Drawing;
namespace X10D.Unity.Tests.Drawing
{
public class PointFTests
{
[UnityTest]
public IEnumerator ToUnityVector2_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var point = new PointF(random.NextSingle(), random.NextSingle());
var vector = point.ToUnityVector2();
Assert.AreEqual(point.X, vector.x, 1e-6f);
Assert.AreEqual(point.Y, vector.y, 1e-6f);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d90695756d1d4760aef2523486b1b41e
timeCreated: 1653743243

View File

@ -0,0 +1,38 @@
using System;
using System.Collections;
using System.Drawing;
using NUnit.Framework;
using UnityEngine.TestTools;
using X10D.Unity.Drawing;
namespace X10D.Unity.Tests.Drawing
{
public class PointTests
{
[UnityTest]
public IEnumerator ToUnityVector2_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var point = new Point(random.Next(), random.Next());
var vector = point.ToUnityVector2();
Assert.AreEqual(point.X, vector.x);
Assert.AreEqual(point.Y, vector.y);
yield break;
}
[UnityTest]
public IEnumerator ToUnityVector2Int_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var point = new Point(random.Next(), random.Next());
var vector = point.ToUnityVector2Int();
Assert.AreEqual(point.X, vector.x);
Assert.AreEqual(point.Y, vector.y);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f465794fdc394d05a34229f34e5199e2
timeCreated: 1653742987

View File

@ -0,0 +1,42 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using X10D.Unity.Drawing;
using Random = System.Random;
namespace X10D.Unity.Tests.Drawing
{
public class RectIntTests
{
[UnityTest]
public IEnumerator ToSystemRectangle_ShouldReturnRectangleF_WithEquivalentMembers()
{
var random = new Random();
var rect = new RectInt(random.Next(), random.Next(), random.Next(), random.Next());
var rectangle = rect.ToSystemRectangle();
Assert.AreEqual(rect.x, rectangle.X);
Assert.AreEqual(rect.y, rectangle.Y);
Assert.AreEqual(rect.width, rectangle.Width);
Assert.AreEqual(rect.height, rectangle.Height);
yield break;
}
[UnityTest]
public IEnumerator ToSystemRectangleF_ShouldReturnRectangleF_WithEquivalentMembers()
{
var random = new Random();
var rect = new RectInt(random.Next(), random.Next(), random.Next(), random.Next());
var rectangle = rect.ToSystemRectangleF();
Assert.AreEqual(rect.x, rectangle.X);
Assert.AreEqual(rect.y, rectangle.Y);
Assert.AreEqual(rect.width, rectangle.Width);
Assert.AreEqual(rect.height, rectangle.Height);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 18f2e8fbc200475ca5fe7857a457a874
timeCreated: 1654077768

View File

@ -0,0 +1,28 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using X10D.Core;
using X10D.Unity.Drawing;
using Random = System.Random;
namespace X10D.Unity.Tests.Drawing
{
public class RectTests
{
[UnityTest]
public IEnumerator ToSystemRectangleF_ShouldReturnRectangleF_WithEquivalentMembers()
{
var random = new Random();
var rect = new Rect(random.NextSingle(), random.NextSingle(), random.NextSingle(), random.NextSingle());
var rectangle = rect.ToSystemRectangleF();
Assert.AreEqual(rect.x, rectangle.X, 1e-6f);
Assert.AreEqual(rect.y, rectangle.Y, 1e-6f);
Assert.AreEqual(rect.width, rectangle.Width, 1e-6f);
Assert.AreEqual(rect.height, rectangle.Height, 1e-6f);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bb1ec5372c354f06b39e03649b9307db
timeCreated: 1653743583

View File

@ -0,0 +1,28 @@
using System.Collections;
using System.Drawing;
using NUnit.Framework;
using UnityEngine.TestTools;
using X10D.Core;
using X10D.Unity.Drawing;
using Random = System.Random;
namespace X10D.Unity.Tests.Drawing
{
public class RectangleFTests
{
[UnityTest]
public IEnumerator ToUnityRect_ShouldReturnRect_WithEquivalentMembers()
{
var random = new Random();
var rectangle = new RectangleF(random.NextSingle(), random.NextSingle(), random.NextSingle(), random.NextSingle());
var rect = rectangle.ToUnityRect();
Assert.AreEqual(rectangle.X, rect.x, 1e-6f);
Assert.AreEqual(rectangle.Y, rect.y, 1e-6f);
Assert.AreEqual(rectangle.Width, rect.width, 1e-6f);
Assert.AreEqual(rectangle.Height, rect.height, 1e-6f);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f38cbc892021405cad2b52de1f960a00
timeCreated: 1653743640

View File

@ -0,0 +1,42 @@
using System.Collections;
using System.Drawing;
using NUnit.Framework;
using UnityEngine.TestTools;
using X10D.Unity.Drawing;
using Random = System.Random;
namespace X10D.Unity.Tests.Drawing
{
public class RectangleTests
{
[UnityTest]
public IEnumerator ToUnityRect_ShouldReturnRect_WithEquivalentMembers()
{
var random = new Random();
var rectangle = new Rectangle(random.Next(), random.Next(), random.Next(), random.Next());
var rect = rectangle.ToUnityRect();
Assert.AreEqual(rectangle.X, rect.x);
Assert.AreEqual(rectangle.Y, rect.y);
Assert.AreEqual(rectangle.Width, rect.width);
Assert.AreEqual(rectangle.Height, rect.height);
yield break;
}
[UnityTest]
public IEnumerator ToUnityRectInt_ShouldReturnRect_WithEquivalentMembers()
{
var random = new Random();
var rectangle = new Rectangle(random.Next(), random.Next(), random.Next(), random.Next());
var rect = rectangle.ToUnityRectInt();
Assert.AreEqual(rectangle.X, rect.x);
Assert.AreEqual(rectangle.Y, rect.y);
Assert.AreEqual(rectangle.Width, rect.width);
Assert.AreEqual(rectangle.Height, rect.height);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9c74177035d1452a8a7ca08c0a27124b
timeCreated: 1653743677

View File

@ -0,0 +1,26 @@
using System;
using System.Collections;
using System.Drawing;
using NUnit.Framework;
using UnityEngine.TestTools;
using X10D.Core;
using X10D.Unity.Drawing;
namespace X10D.Unity.Tests.Drawing
{
public class SizeFTests
{
[UnityTest]
public IEnumerator ToUnityVector2_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var size = new SizeF(random.NextSingle(), random.NextSingle());
var vector = size.ToUnityVector2();
Assert.AreEqual(size.Width, vector.x, 1e-6f);
Assert.AreEqual(size.Height, vector.y, 1e-6f);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b93fe56510de4ddcb9354bde7f10c362
timeCreated: 1653743377

View File

@ -0,0 +1,38 @@
using System;
using System.Collections;
using System.Drawing;
using NUnit.Framework;
using UnityEngine.TestTools;
using X10D.Unity.Drawing;
namespace X10D.Unity.Tests.Drawing
{
public class SizeTests
{
[UnityTest]
public IEnumerator ToUnityVector2_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var size = new Size(random.Next(), random.Next());
var vector = size.ToUnityVector2();
Assert.AreEqual(size.Width, vector.x);
Assert.AreEqual(size.Height, vector.y);
yield break;
}
[UnityTest]
public IEnumerator ToUnityVector2Int_ShouldReturnVector_WithEquivalentMembers()
{
var random = new Random();
var size = new Size(random.Next(), random.Next());
var vector = size.ToUnityVector2Int();
Assert.AreEqual(size.Width, vector.x);
Assert.AreEqual(size.Height, vector.y);
yield break;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c748bfe02fce4b459df7ef2779c2a486
timeCreated: 1653743400

View File

@ -0,0 +1,88 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using X10D.Unity.Numerics;
using Random = System.Random;
namespace X10D.Unity.Tests.Numerics
{
public class Vector2IntTests
{
[UnityTest]
public IEnumerator Deconstruct_ShouldReturnCorrectValues()
{
var vector = new Vector2Int(1, 2);
(int x, int y) = vector;
Assert.AreEqual(1, x);
Assert.AreEqual(2, y);
yield break;
}
[UnityTest]
public IEnumerator ToSystemPoint_ShouldReturnPoint_WithEquivalentMembers()
{
var random = new Random();
int x = random.Next();
int y = random.Next();
var vector = new Vector2Int(x, y);
var point = vector.ToSystemPoint();
Assert.AreEqual(vector.x, point.X);
Assert.AreEqual(vector.y, point.Y);
yield break;
}
[UnityTest]
public IEnumerator ToSystemSize_ShouldReturnSize_WithEquivalentMembers()
{
var random = new Random();
int x = random.Next();
int y = random.Next();
var vector = new Vector2Int(x, y);
var point = vector.ToSystemSize();
Assert.AreEqual(vector.x, point.Width);
Assert.AreEqual(vector.y, point.Height);
yield break;
}
[UnityTest]
public IEnumerator WithX_ShouldReturnVectorWithNewX_GivenVector()
{
Assert.AreEqual(Vector2Int.up, Vector2Int.one.WithX(0));
Assert.AreEqual(Vector2Int.zero, Vector2Int.zero.WithX(0));
Assert.AreEqual(Vector2Int.zero, Vector2Int.right.WithX(0));
Assert.AreEqual(Vector2Int.up, Vector2Int.up.WithX(0));
Assert.AreEqual(Vector2Int.one, Vector2Int.one.WithX(1));
Assert.AreEqual(Vector2Int.right, Vector2Int.zero.WithX(1));
Assert.AreEqual(Vector2Int.right, Vector2Int.right.WithX(1));
Assert.AreEqual(Vector2Int.one, Vector2Int.up.WithX(1));
yield break;
}
[UnityTest]
public IEnumerator WithY_ShouldReturnVectorWithNewY_GivenVector()
{
Assert.AreEqual(Vector2Int.right, Vector2Int.one.WithY(0));
Assert.AreEqual(Vector2Int.zero, Vector2Int.zero.WithY(0));
Assert.AreEqual(Vector2Int.right, Vector2Int.right.WithY(0));
Assert.AreEqual(Vector2Int.zero, Vector2Int.up.WithY(0));
Assert.AreEqual(Vector2Int.one, Vector2Int.one.WithY(1));
Assert.AreEqual(Vector2Int.up, Vector2Int.zero.WithY(1));
Assert.AreEqual(Vector2Int.one, Vector2Int.right.WithY(1));
Assert.AreEqual(Vector2Int.up, Vector2Int.up.WithY(1));
yield break;
}
}
}

Some files were not shown because too many files have changed in this diff Show More