1
0
mirror of https://github.com/oliverbooth/X10D synced 2024-10-18 04:36:10 +00:00

3.0.0 Update (#43)

For a full list of changes, see [CHANGELOG.md](CHANGELOG.md)
This commit is contained in:
Oliver Booth 2022-04-30 14:13:16 +01:00 committed by GitHub
parent 32cd57dfb4
commit b16e5a9de9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
249 changed files with 20349 additions and 4703 deletions

12
.config/dotnet-tools.json Normal file
View File

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-stryker": {
"version": "1.3.1",
"commands": [
"dotnet-stryker"
]
}
}
}

View File

@ -23,10 +23,10 @@ dotnet_separate_import_directive_groups=false
dotnet_sort_system_directives_first=true
# this. and Me. preferences
dotnet_style_qualification_for_event=true:suggestion
dotnet_style_qualification_for_field=true:suggestion
dotnet_style_qualification_for_method=true:suggestion
dotnet_style_qualification_for_property=true:suggestion
dotnet_style_qualification_for_event=false:warning
dotnet_style_qualification_for_field=false:warning
dotnet_style_qualification_for_method=false:warning
dotnet_style_qualification_for_property=false:warning
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members=true:warning
@ -65,9 +65,7 @@ dotnet_code_quality_unused_parameters=all:suggestion
#### C# Coding Conventions ####
# var preferences
csharp_style_var_elsewhere=true:warning
csharp_style_var_when_type_is_apparent=true:warning
csharp_style_var_for_built_in_types=true:warning
# Expression-bodied members
csharp_style_expression_bodied_accessors=true:suggestion
@ -107,7 +105,7 @@ csharp_style_unused_value_assignment_preference=discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference=discard_variable:silent
# 'using' directive preferences
csharp_using_directive_placement=inside_namespace:suggestion
csharp_using_directive_placement=outside_namespace:error
#### C# Formatting Rules ####

33
.github/workflows/dotnet.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: .NET
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
name: "Build & Test"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Add NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Test
run: dotnet test --no-build --verbosity normal --configuration Release

View File

@ -1,25 +0,0 @@
name: .NET Core
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.101
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-restore --verbosity normal

41
.github/workflows/nightly.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Publish Nightly
on:
push:
branches:
- master
- develop
jobs:
nightly:
runs-on: ubuntu-latest
if: "!contains(format('{0} {1}', github.event.head_commit.message, github.event.pull_request.title), '[ci-skip]')"
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Debug
- name: Build NuGet package
run: |
mkdir build
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='nightly' -p:BuildNumber=${{ github.run_number }}
- name: Push NuGet Package to GitHub
run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
- name: Push NuGet Package to nuget.org
run: dotnet nuget push "build/*" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate

46
.github/workflows/prerelease.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: Tagged Pre-Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+-*"
jobs:
prerelease:
name: "Tagged Pre-Release"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
- name: Restore dependencies
run: dotnet restore
- name: Publish
run: dotnet publish -c Release -r linux-x64 --self-contained true
- name: Build NuGet package
run: |
mkdir build
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build -p:VersionSuffix='prerelease' -p:BuildNumber=${{ github.run_number }}
- name: Push NuGet Package to GitHub
run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
- name: Push NuGet Package to nuget.org
run: dotnet nuget push "build/*" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate
- name: Create Release
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: true

46
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: Tagged Release
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
jobs:
release:
name: "Tagged Release"
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
- name: Restore dependencies
run: dotnet restore
- name: Publish
run: dotnet publish -c Release -r linux-x64 --self-contained true
- name: Build NuGet package
run: |
mkdir build
dotnet pack X10D -p:SymbolPackageFormat=snupkg --include-symbols --include-source -o build
- name: Push NuGet Package to GitHub
run: dotnet nuget push "build/*" --source "github" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
- name: Push NuGet Package to nuget.org
run: dotnet nuget push "build/*" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate
- name: Create Release
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
prerelease: false

36
.github/workflows/source_validator.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: Source Validator
on:
push:
branches:
- master
- develop
pull_request:
types: [opened, synchronize, reopened]
jobs:
source_validator:
runs-on: ubuntu-latest
if: "!contains(format('{0} {1}', github.event.head_commit.message, github.event.pull_request.title), '[ci-skip]')"
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Add GitHub NuGet source
run: dotnet nuget add source --username oliverbooth --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/oliverbooth/index.json"
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Debug
- name: Run Source Validation
run: dotnet run --project X10D.SourceValidator ./X10D/src

349
.gitignore vendored
View File

@ -1,22 +1,22 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
*.swp
*.*~
project.lock.json
.DS_Store
*.pyc
nupkg/
# Visual Studio Code
.vscode
# Rider
.idea
# User-specific files
*.idea
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
@ -24,327 +24,14 @@ mono_crash.*
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
build/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Oo]ut/
msbuild.log
msbuild.err
msbuild.wrn
# Visual Studio 2015/2017 cache/options directory
# Visual Studio 2015
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/

View File

@ -1,57 +1,229 @@
# Changelog
## [2.6.0] - 2020-10-20
# Added
- Add `string.AsNullIfEmpty()`
- Returns the current string, or `null` if the current string is null or empty.
- Add `string.AsNullIfWhiteSpace()`
- Returns the current string, or `null` if the current string is null, empty, or consists of only whitespace.
- Add `string.Reverse()`
- Reverses the current string
- Add `string.WithAlternative()`
- Returns the current string, or an alternative value if the current string is null or empty, or optionally if the current string consists of only whitespace.
## [3.0.0]
In the midst of writing these release notes, I may have missed some important changes. If you notice an API change that is not documented here,
please [open an issue](https://github.com/oliverbooth/X10D/issues)!
### Added
- Added `T.AsArrayValue()`
- Added `T.AsEnumerableValue()`
- Added `T.RepeatValue(int)`
- Added `T.ToJson([JsonSerializerOptions])`
- Added `string.FromJson([JsonSerializerOptions])`
- Added `T[].AsReadOnly()`
- Added `T[].Clear([Range])` and `T[].Clear(int, int)`
- Added `DateTime.IsLeapYear()`
- Added `DateTimeOffset.IsLeapYear()`
- Added `Endianness` enum
- Added `FileInfo.GetHash<T>()`
- Added `FileInfo.TryWriteHash<T>(Span<byte>, out int)`
- Added `IComparable<T>.Clamp(T, T)` - this supersedes `Clamp` defined for hard-coded numeric types (#24)
- Added `IComparable<T1>.GreaterThan(T2)` (#22)
- Added `IComparable<T1>.GreaterThanOrEqualTo(T2)` (#22)
- Added `IComparable<T1>.LessThan(T2)` (#22)
- Added `IComparable<T1>.LessThanOrEqualTo(T2)` (#22)
- Added `IComparable<T1>.Max(T)` (#23)
- Added `IComparable<T1>.Min(T)` (#23)
- Added `IDictionary<TKey, TValue>.AddOrUpdate()`
- Added `IEnumerable<TSource>.Product()` and `IEnumerable<TSource>.Product<TResult>(Func<TSource>, TResult)` for all built-in numeric types, computing the product of all (optionally transformed) elements
- Added `IList<T>.Fill(T)` and `IList<T>.Fill(T, int, int)`
- Added `IPAddress.IsIPv4()` and `IPAddress.IsIPv6()`
- Added `IReadOnlyList<byte>.Pack8Bit()`
- Added `IReadOnlyList<byte>.Pack16Bit()`
- Added `IReadOnlyList<byte>.Pack32Bit()`
- Added `IReadOnlyList<byte>.Pack64Bit()`
- Added `MemberInfo.HasCustomAttribute<T>()` and `MemberInfo.HasCustomAttribute(Type)`
- Added `defaultValue` overload for `MemberInfo.SelectFromCustomAttribute<TAttr, TReturn>()`
- Added `Random.Next<T>()` (returns a random field from a specified enum type)
- Added `Random.NextByte([byte[, byte]])`
- Added `Random.NextColorArgb()`, returning a random color in RGB space, including random alpha
- Added `Random.NextColorRgb()`, returning a random color in RGB space with alpha 255
- Added `Random.NextDouble(double[, double])`
- Added `Random.NextInt16([short[, short]])`
- Added `Random.NextSingle(float[, float])` (#34)
- Added `Random.NextUnitVector2()`
- Added `Random.NextUnitVector3()`
- Added `Random.NextRotation()`
- Added `Rune.Repeat(int)`
- Added `byte.IsEven()`
- Added `byte.IsOdd()`
- Added `byte.IsPrime()`
- Added `byte.UnpackBits()`
- Added `byte.RangeTo(byte)`, `byte.RangeTo(short)`, `byte.RangeTo(int)`, and `byte.RangeTo(long)`
- Added `int.Mod(int)`
- Added `int.RangeTo(int)`, and `int.RangeTo(long)`
- Added `int.UnpackBits()`
- Added `long.Mod(long)`
- Added `long.RangeTo(long)`
- Added `long.UnpackBits()`
- Added `sbyte.IsEven()`
- Added `sbyte.IsOdd()`
- Added `sbyte.IsPrime()`
- Added `sbyte.Mod(sbyte)`
- Added `short.IsEven()`
- Added `short.IsOdd()`
- Added `short.Mod(short)`
- Added `short.RangeTo(short)`, `short.RangeTo(int)`, and `short.RangeTo(long)`
- Added `short.UnpackBits()`
- Added `string.IsPalindrome()`
- Added `Stream.GetHash<T>()`
- Added `Stream.TryWriteHash<T>(Span<byte>, out int)`
- Added `Stream.ReadInt16([Endian])`
- Added `Stream.ReadInt32([Endian])`
- Added `Stream.ReadInt64([Endian])`
- Added `Stream.ReadUInt16([Endian])`
- Added `Stream.ReadUInt32([Endian])`
- Added `Stream.ReadUInt64([Endian])`
- Added `Stream.Write(short, [Endian])`
- Added `Stream.Write(int, [Endian])`
- Added `Stream.Write(long, [Endian])`
- Added `Stream.Write(ushort, [Endian])`
- Added `Stream.Write(uint, [Endian])`
- Added `Stream.Write(ulong, [Endian])`
- Added `TimeSpan.Ago()`
- Added `TimeSpan.FromNow()`
- Added `TimeSpanParser.TryParse` which supersedes `TimeSpanParser.Parse`
- Added `Sqrt()` and `ComplexSqrt()` for all built-in decimal types
- Added `All()` and `Any()` for `Span<T>` and `ReadOnlySpan<T>`, mimicking the corresponding methods in `System.Linq`
- Added `Sign()` for built-in numeric types. For unsigned types, this never returns -1
- Added `Type.Implements<T>()` and `Type.Implements(Type)` (#25)
- Added `Type.Inherits<T>()` and `Type.Inherits(Type)` (#25)
- Added `DigitalRoot` function for built-in integer types
- Added `Factorial` function for built-in integer types
- Added `HostToNetworkOrder` and `NetworkToHostOrder` for `short`, `int`, and `long`
- Added `IsLeapYear` function for `DateTime` and `DateTimeOffset`, as well as built-in numeric types
- Added `MultiplicativePersistence` function for built-in integer types
- Added `RotateLeft` and `RotateRight` for built-in integer types
- Added trigonometric functions for built-in numeric types, including `Acos()`, `Asin()`, `Atan()`, `Atan2()`, `Cos()`, `Sin()`, `Tan()` (#49)
- Added time-related extension methods for built-in numeric types, including `Milliseconds()`, `Seconds()`, `Minutes()`, `Hours()`, `Days()`, and `Weeks()`. `Ticks()` is also available, but only for integers; not floating point
- Added `StringBuilderReader` (inheriting `TextReader`) which allows reading from a `StringBuilder` without consuming the underlying string
- Added extension methods for `System.Decimal`
### Changed
- Updated to .NET 6 (#45)
- Methods defined to accept `byte[]` have been changed accept `IReadOnlyList<byte>`
- Extension methods are now defined in appropriate child namespaces to reduce the risk of name collisions (#7)
- `char[].Random(int)`, `char[].Random(int, int)`, `IEnumerable<char>.Random(int)`, and `IEnumerable<char>.Random(int, int)` have been redefined as `Random.NextString(IReadOnlyList<char>, int)`
- `IComparable<T>.Between(T, T)` has been redefined as `IComparable<T1>.Between(T2, T3, [InclusiveOptions])` to allow comparison of disparate yet comparable types, and also offers inclusivity options
- `DateTime` extensions now wrap `DateTimeOffset` extensions
- `DateTime.ToUnixTimestamp([bool])` has been redefined as `DateTime.ToUnixTimeMilliseconds()` and `DateTime.ToUnixTimeSeconds()`
- `Dictionary<T1, T2>.ToGetParameters()`, `IDictionary<T1, T2>.ToGetParameters()`, and `IReadOnlyDictionary<T1, T2>.ToGetParameters()`, has been redefined as `IEnumerable<KeyValuePair<T1, T2>>.ToGetParameters()`
- `Dictionary<T1, T2>.ToConnectionString()`, `IDictionary<T1, T2>.ToConnectionString()`, and `IReadOnlyDictionary<T1, T2>.ToConnectionString()`, has been redefined as `IEnumerable<KeyValuePair<T1, T2>>.ToConnectionString()`
- `IList<T>.OneOf([Random])` and `IEnumerable<T>.OneOf([Random])` have been redefined as `Random.NextFrom<T>(IEnumerable<T>)` to fall in line with the naming convention of `System.Random` (#21)
- `IList<T>.Shuffle([Random])` now uses a Fisher-Yates shuffle implementation
- `IList<T>.Shuffle([Random])` has been repurposed to shuffle the list in place, rather than returning a new enumerable
- `IEnumerable<T>.Shuffle([Random])` has been renamed to `IEnumerable<T>.Shuffled([Random])` to avoid confusion with `IList<T>.Shuffle([Random])`
- `Random.CoinToss()` has been redefined as `Random.NextBoolean()` to fall in line with the naming convention of `System.Random`
- `Random.OneOf<T>(T[])` and `Random.OneOf<T>(IList<T>)` have been redefined as `Random.NextFrom<T>(IEnumerable<T>)` to fall in line with the naming convention of `System.Random`
- `Enum.Next([bool])` and `Enum.Previous([bool])` have been redefined as `Enum.Next()`, `Enum.Previous()`, `Enum.NextUnchecked()`, `Enum.PreviousUnchecked()`. The `Unchecked` variants of these methods do not perform index validation, and will throw `IndexOutOfRangeException` when attempting to access an invalid index. The checked variants will perform a modulo to wrap the index
- Seperated `string.WithAlternative(string, [bool])` to `string.WithEmptyAlternative(string)` and `string.WithWhiteSpaceAlternative(string)`
- `string.AsNullIfEmpty()` and `string.AsNullIfWhiteSpace()` now accept a nullable `string`
- `IEnumerable<byte>.GetString([Encoding])` has been renamed to `IReadOnlyList<byte>.ToString` and its `Encoding` parameter has
been made non-optional
- Fixed a bug where `IEnumerable<KeyValuePair<K,V>>.ToConnectionString()` would not sanitize types with custom `ToString()`
implementation (#20)
Renamed `string.Random(int[, Random])` to `string.Randomize(int[, Random])`
- Redefined `char[].Random(int)`, `char[].Random(int, Random)`, `IEnumerable<char>.Random(int)`, and `IEnumerable<char>.Random(int, Random)`, as `Random.NextString(IReadOnlyList<char>, int)`
- Improved performance for:
- `string.IsLower()`
- `string.IsUpper()`
- `string.Reverse()`
- `TimeSpanParser`
### Removed
- Indefinitely suspended Unity support, until such a time that Unity can be updated to a newer version of .NET. See: https://forum.unity.com/threads/unity-future-net-development-status.1092205/
- Removed `bool.And(bool)`
- Removed `bool.NAnd(bool)`
- Removed `bool.NOr(bool)`
- Removed `bool.Not(bool)`
- Removed `bool.Or(bool)`
- Removed `bool.ToByte()`
- Removed `bool.ToInt16()`
- Removed `bool.ToInt64()`
- Removed `bool.XNOr()`
- Removed `bool.XOr()`
- Removed `IConvertible.To<T>([IFormatProvider])` (#13)
- Removed `IConvertible.ToOrDefault<T>([IFormatProvider])` (#13)
- Removed `IConvertible.ToOrDefault<T>(out T, [IFormatProvider])` (#13)
- Removed `IConvertible.ToOrNull<T>([IFormatProvider])` (#13)
- Removed `IConvertible.ToOrNull<T>(out T, [IFormatProvider])` (#13)
- Removed `IConvertible.ToOrOther<T>(T, [IFormatProvider])` (#13)
- Removed `IConvertible.ToOrOther<T>(out T, T, [IFormatProvider])` (#13)
- Removed `IEnumerable<T>.Split(int)` - this functionality is now provided by .NET in the form of the `Chunk` method. See: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.chunk?view=net-6.0
- Removed `MemberInfo.GetDefaultValue()` (use `SelectFromCustomAttribute()` instead)
- Removed `MemberInfo.GetDescription()` (use `SelectFromCustomAttribute()` instead)
- Removed `int.ToBoolean()`
- Removed `long.ToBoolean()`
- Removed `short.ToBoolean()`
- Removed `uint.ToBoolean()`
- Removed `ushort.ToBoolean()`
- Removed `ulong.ToBoolean()`
- Removed `WaitHandle.WaitOneAsync()`. For suspensions of execution during asynchronous operations, favour `TaskCompletionSource` or `TaskCompletionSource<T>`. See: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource?view=net-6.0 and https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=net-6.0
## [2.6.0] - 2020-10-20
### Added
- Add `string.AsNullIfEmpty()`
- Returns the current string, or `null` if the current string is null or empty.
- Add `string.AsNullIfWhiteSpace()`
- Returns the current string, or `null` if the current string is null, empty, or consists of only whitespace.
- Add `string.Reverse()`
- Reverses the current string
- Add `string.WithAlternative()`
- Returns the current string, or an alternative value if the current string is null or empty, or optionally if the current
string consists of only whitespace.
### Changed
- n/a
### Removed
- n/a
## [2.5.0] - 2020-07-15
### Added
- `WaitHandle.WaitOneAsync()`
- Wraps `WaitHandle.WaitOne` as a `Task`
- Wraps `WaitHandle.WaitOne` as a `Task`
- Add support for Unity 2019.4.3f1
- Add `GameObject.LookAt(GameObject)`
- Rotates the Transform on the current GameObject so that it faces the Transform on another GameObject
- Add `GameObject.LookAt(Transform)`
- Rotates the Transform on the current GameObject so that it faces another transform
- Add `Transform.LookAt(GameObject)`
- Rotates the current Transform so that it faces the Transform on another GameObject
- Add `Vector3.Round([float])`
- Returns a rounded Vector3 by calling `float.Round()` on each component
- Add `Vector3.WithX(float)`
- Returns a Vector3 with a new X component value
- Add `Vector3.WithY(float)`
- Returns a Vector3 with a new Y component value
- Add `Vector3.WithZ(float)`
- Returns a Vector3 with a new Z component value
- Add `Vector3.WithXY(float, float)`
- Returns a Vector3 with new X and Y component values
- Add `Vector3.WithXZ(float, float)`
- Returns a Vector3 with new X and Z component values
- Add `Vector3.WithYZ(float, float)`
- Returns a Vector3 with new Y and Z component values
- Add `BetterBehavior` (experimental wrapper over `MonoBehaviour`)
- Add `GameObject.LookAt(GameObject)`
- Rotates the Transform on the current GameObject so that it faces the Transform on another GameObject
- Add `GameObject.LookAt(Transform)`
- Rotates the Transform on the current GameObject so that it faces another transform
- Add `Transform.LookAt(GameObject)`
- Rotates the current Transform so that it faces the Transform on another GameObject
- Add `Vector3.Round([float])`
- Returns a rounded Vector3 by calling `float.Round()` on each component
- Add `Vector3.WithX(float)`
- Returns a Vector3 with a new X component value
- Add `Vector3.WithY(float)`
- Returns a Vector3 with a new Y component value
- Add `Vector3.WithZ(float)`
- Returns a Vector3 with a new Z component value
- Add `Vector3.WithXY(float, float)`
- Returns a Vector3 with new X and Y component values
- Add `Vector3.WithXZ(float, float)`
- Returns a Vector3 with new X and Z component values
- Add `Vector3.WithYZ(float, float)`
- Returns a Vector3 with new Y and Z component values
- Add `BetterBehavior` (experimental wrapper over `MonoBehaviour`)
### Changed
- n/a
### Removed
- n/a
## [2.2.0] - 2020-04-21
### Added
- Add `string.ChangeEncoding(Encoding, Encoding)`
- Converts this string from one encoding to another
- Add `string.IsLower()`
@ -62,19 +234,24 @@
- Various extension methods with regards to reflection:
- `GetDefaultValue` and `GetDefaultValue<T>` - gets the value stored in the member's `DefaultValue` attribute
- `GetDescription`- gets the value stored in the member's `Description` attribute
- `SelectFromCustomAttribute<T1, T2>` - Internally calls `GetCustomAttribute<T1>` and passes it to a `Func<T1, T2>` so that specific members may be selected
- `SelectFromCustomAttribute<T1, T2>` - Internally calls `GetCustomAttribute<T1>` and passes it to a `Func<T1, T2>` so that
specific members may be selected
### Changed
- n/a
### Removed
- n/a
## [2.1.0] - 2020-04-18
### Added
- Add `bool bool.And(bool)`
- Performs logical AND
- Add `bool bool.Or(bool)`
- Add `bool bool.Or(bool)`
- Performs logical OR
- Add `bool bool.Not(bool)`
- Performs logical NOT
@ -94,29 +271,35 @@
- 1 if `true`, 0 otherwise
### Changed
- n/a
### Removed
- n/a
## [2.0.0] - 2020-04-18
### Added
- Add `IEnumerable<T>.Split(int)`
- Performs the same operation as the previously defined `IEnumerable<byte>.Chunkify(int)`, except now accepts any type `T`
### Changed
- Fix `DateTime.Last(DayOfWeek)` implementation
- Now returns the correct date/time for a given day of the week
### Removed
- Remove `IEnumerable<byte>.Chunkify(int)`
- Replaced by a method of the same behaviour `IEnumerable<T>.Split(int)`
## Earlier versions
### ***Not documented***
[Unreleased]: https://github.com/oliverbooth/X10D/tree/HEAD
[3.0.0]: https://github.com/oliverbooth/X10D/releases/tag/3.0.0
[2.6.0]: https://github.com/oliverbooth/X10D/releases/tag/2.6.0
[2.5.0]: https://github.com/oliverbooth/X10D/releases/tag/2.5.0
[2.2.0]: https://github.com/oliverbooth/X10D/releases/tag/2.2.0

View File

@ -2,25 +2,25 @@
Contributions to this project are always welcome. If you spot a bug, or want to request a new extension method, open a new issue or submit a pull request.
### Pull request guidelines
This project uses C# 8.0 language features, and adheres to the following analyzers:
- Rozlynator
- FxCop
- StyleCop
There is an `.editorconfig` and an analyzer `ruleset` file included in this repository. For quick and painless pull requests, ensure that these analyzers do not throw warnings.
This project uses C# 9.0 language features, and adheres to the FxCop analyzer.
There is an `.editorconfig` included in this repository. For quick and painless pull requests, ensure that the analyzer does not throw warnings.
### Code style
Below are a few pointers to which you may refer, but keep in mind this is not an exhaustive list:
- Use C# 8.0 features where possible
- Try to ensure code is CLS-compliant
- Use C# 9.0 features where possible
- Try to ensure code is CLS-compliant. Where this is not possible, decorate methods with `CLSCompliantAttribute` and pass `false`
- Follow all .NET guidelines for naming conventions
- Make full use of XMLDoc and be thorough - but concise - with all documentation.
- Ensure that no line exceeds 120 characters in length
- Make full use of XMLDoc and be thorough - but concise - with all documentation
- Ensure that no line exceeds 130 characters in length
- Do NOT include file headers in any form
- Declare `using` directives within namespace scope
- Try to avoid using exceptions for flow control
- Declare `using` directives outside of namespace scope
- Avoid using exceptions for flow control where possible
- Use braces, even for single-statement bodies
- Use implicit type when the type is apparent or not important
- Use U.S. English throughout the codebase and documentation
When in doubt, follow .NET guidelines for styling.
### Tests
When introducing a new extension method, you must ensure that you have also defined a unit test that asserts its correct behavior. The code style guidelines and code-analysis rules apply to the `X10D.Tests` equally as much as `X10D`, although documentation may be briefer. Refer to existing tests as a guideline.

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Oliver Booth
Copyright (c) 2019-2022 Oliver Booth
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

267
README.md
View File

@ -1,259 +1,46 @@
# X10D
## Extension methods on crack
[<img src="https://img.shields.io/github/workflow/status/oliverbooth/X10D/.NET%20Core">](https://github.com/oliverbooth/X10D/actions?query=workflow%3A%22.NET+Core%22)
[<img src="https://img.shields.io/github/issues/oliverbooth/X10D">](https://github.com/oliverbooth/X10D/issues)
[<img src="https://img.shields.io/nuget/v/X10D">](https://www.nuget.org/packages/X10D/)
[<img src="https://img.shields.io/github/license/oliverbooth/X10D">](https://github.com/oliverbooth/X10D/blob/master/LICENSE.md)
<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>
</p>
### About
X10D (pronounced *extend*), is a class library that provides extension methods for numerous .NET types. The purpose of this library is to simplify a codebase by reducing the need for repeated code when performing common operations. Simplify your codebase. Take advantage of .NET. Use extension methods.
X10D (pronounced *extend*), is a .NET package that provides extension methods for numerous types. The purpose of this library is to simplify a codebase by reducing the need for repeated code when performing common operations. Simplify your codebase. Take advantage of .NET. Use extension methods.
*(I'm also [dogfooding](https://www.pcmag.com/encyclopedia/term/dogfooding) this library, so there's that.)*
### Table of contents
- [Install](#install)
- [Installation](#installation)
- [Unity installation](#unity-installation)
- [NuGet installation](#nuget-installation)
- [Features](#features)
- [Numeric](#numeric)
- [String](#string)
- [DateTime](#datetime)
- [Enumerable](#enumerable)
- [Enum](#enum)
- [Conversion](#conversion)
- [Random](#random)
- [Contributing](#contributing)
- [License](#license)
You can find the list of classes that have extension methods by viewing the `README.md` file in any of the respective library folders.
## Install
Install X10D with NuGet via the following command:
## Installation
### NuGet installation
```ps
Install-Package X10D -Version 2.6.0
Install-Package X10D -Version 3.0.0
```
or by downloading the [latest release](https://github.com/oliverbooth/X10D/releases/latest) from this repository.
### Manual installation
Download the [latest release](https://github.com/oliverbooth/X10D/releases/latest) from this repository and adding a direct assembly reference for your chosen platform.
### What happened to X10D.Unity?
I decided it was time for X10D to be migrated to .NET 6. Unity currently supports .NET Framework 4.x / .NET Standard 2.1, and as such is not compatible with X10D at this time.
Unity have announced official support for .NET 6 in the future (see [this forum post](https://forum.unity.com/threads/unity-future-net-development-status.1092205/) for more details),
but until such a time that Unity supports .NET 6, X10D.Unity will not be maintained or innovated upon.
## Features
### Numeric extensions
> 👍 ProTip: *Most* of the extensions available for `int` will also exist for `short`, `long`, and their unsigned counterparts!
#### `bool` &lt;-&gt; `int`
Convert a `bool` to an `int` by using `ToInt32`. The value returned is 1 if the input is `true`, and 0 if it's `false`.
```cs
bool b = true;
int i = b.ToInt32(); // 1
```
The same also works in reverse. Using `ToBoolean` on an `int` will return `false` if the input is 0, and `true`if the input is anything else.
```cs
int zero = 0;
long nonZero = 1;
bool b1 = zero.ToBoolean(); // false
bool b2 = nonZero.ToBoolean(); // true
```
#### Between
Determine if a value is between other values using `Between` like so:
```cs
int i = 3;
if (i.Between(2, 4))
{
// i is between 2 and 4!
}
```
Since the signature of this method is defined with a generic constraint of `IComparable<T>`, this will also work for any object that is `IComparable<T>` - not just numeric types!
```cs
bool Between<T>(this T actual, T lower, T upper) where T : IComparable<T>
```
#### IsEven (*and IsOdd*)
As the names suggest, this method determines if the input value is evenly divisible by 2.
```cs
int i = 5;
bool b = i.IsEven(); // false
```
There is also an `IsOdd` extension method, which will return the opposite of that returned by `IsEven`.
#### IsPrime
Determine if an integral is a prime number by using `IsPrime`.
```cs
bool b = 43.IsPrime(); // true
```
#### Clamp
Clamp a value between an upper and lower bound
```cs
int i = 5.Clamp(0, 3); // 3
```
#### Convert degrees &lt;-&gt; radians
Easily convert between radians and degrees
```cs
double rad = 2 * Math.PI;
double deg = rad.RadiansToDegrees(); // 360
rad = deg.DegreesToRadians(); // back to 2*pi
```
#### Round
Round a value to the nearest whole number:
```cs
var d = 2.75;
var rounded = d.Round(); // 3
```
Or specify a value to have it round to the nearest multiple of `x`:
```cs
double a = 8.0.Round(10); // 10
double b = 2.0.Round(10); // 0
```
### String
#### Repeat value
Repeat a string or a char a specific number of times using `Repeat`
```cs
var c = '-';
var str = "foo";
string repeatedC = c.Repeat(10); // ----------
string repeatedStr = str.Repeat(5); // foofoofoofoofoo
```
#### Base-64 encode/decode
```cs
var base64 = "Hello World".Base64Encode(); // SGVsbG8gV29ybGQ=
var str = "SGVsbG8gV29ybGQ=".Base64Decode(); // Hello World
```
### DateTime
#### Age
Get a rounded integer representing the number of years since a given date. i.e. easily calculate someone's age:
```cs
var dateOfBirth = new DateTime(1960, 7, 16);
int age = dateOfBirth.Age(); // the age as of today
```
You can also specify a date at which to stop counting the years, by passing an `asOf` date:
```cs
var dateOfBirth = new DateTime(1960, 7, 16);
int age = dateOfBirth.Age(new DateTime(1970, 7, 16)); // 10, the age as of 1970
```
#### To/From Unix Timestamp
Convert to/from a Unix timestamp represented in seconds using `FromUnixTimestamp` on a numeric type, and `ToUnixTimestamp` on a `DateTime`.
```cs
long sec = 1587223415;
DateTime time = sec.FromUnixTimestamp(); // 2020-04-18 15:23:35
long unix = time.ToUnixTimestamp();
```
or represent it with milliseconds by passing `true` for the `isMillis` argument:
```cs
long millis = 1587223415500;
DateTime time = millis.FromUnixTimestamp(true); // 2020-04-18 15:23:35.50
long unix = time.ToUnixTimestamp(true);
```
#### Get first/last day of month
Get the first or last day of the month by using `FirstDayOfMonth` and `LastDayOfMonth`
```cs
var dt = new DateTime(2016, 2, 4);
DateTime first = dt.FirstDayOfMonth(); // 2016-02-01
DateTime last = dt.LastDayOfMonth(); // 2016-02-29 (2016 is a leap year)
```
You can also use `First` or `Last` to get the first or final occurrence of a specific day of the week in a given month:
```cs
var dt = new DateTime(2019, 4, 14);
DateTime theLastFriday = dt.Last(DayOfWeek.Friday); // 2019-04-24
DateTime theLastThursday = dt.Last(DayOfWeek.Thursday); // 2019-04-40
```
### Enumerable
#### Split into chunks
Split an `IEnumerable<T>` into an `IEnumerable<IEnumerable<T>>`, essentially "chunking" the original IEnumerable into a specific size
```cs
var arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
var chunks = arr.Split(2); // split into chunks of 2
foreach (var chunk in chunks)
{
Console.WriteLine(string.Join(", ", chunk));
}
// Output:
// 1, 2
// 3, 4
// 5, 6
// 7, 8
```
This also works for `string`:
```cs
var str = "Hello World";
var chunks = str.Split(2); // split string into chunks of 2
foreach (var chunk in chunks)
{
Console.WriteLine(string.Join(string.Empty, chunk));
}
// Output:
// He
// ll
// o <-- space is included
// Wo
// rl
// d <-- no space! end of string
```
### Enum
#### Parse string into enum
You can use the `EnumParse` method to convert a string into a value from an enum, while optionally ignoring case:
```cs
enum Number
{
Zero,
One,
Two,
Three,
}
Number num = "two".EnumParse<Number>(true); // num == Number.Two
```
#### `Next` / `Previous` enum cycling
Cycle through the values in an enum with `Next` and `Previous`:
```cs
Number two = Number.Two;
Number one = two.Previous();
Number three = two.Next();
```
### Conversion
Easily convert between types using `To`, `ToOrNull`, `ToOrDefault`, or `ToOrOther`, thereby shortening the call to `Convert.ChangeType` or `Convert.ToX`:
```CS
int i = "43".To<int>();
int j = "a".ToOrDefault<int>(); // 0
int k = "a".ToOrOther<int>(100); // 100
```
### Random
Do more with Random including flip a coin, randomly select an element in an array, or shuffle the array entirely.
```cs
var random = new Random();
// flip a coin
bool heads = random.CoinToss();
// randomly choose an item
var arr = new int[] { 1, 2, 3, 4 };
var item = random.OneOf(arr);
// shuffle an array or list
var shuffled = arr.Shuffle(random);
```
I'm planning on writing complete and extensive documentation in the near future. As of this time, feel free to browse the source or the API using your favourite IDE.
For those familiar with the 2.6.0 API, please read [CHANGELOG.md](CHANGELOG.md) for a complete list of changes. **3.0.0 is a major release and introduces many breaking changes.**
## Contributing
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).

View File

@ -0,0 +1,64 @@
using System.Text;
var directories = new Stack<string>(Directory.GetDirectories(args[0]));
var problems = 0;
var files = 0;
while (directories.Count > 0)
{
string path = Path.GetFullPath(directories.Pop());
foreach (string directory in Directory.EnumerateDirectories(path))
{
directories.Push(directory);
}
foreach (string file in Directory.EnumerateFiles(path, "*.cs"))
{
files++;
await using var stream = File.OpenRead(file);
using var reader = new StreamReader(stream, Encoding.UTF8);
var blankLine = false;
var lineNumber = 1;
while (await reader.ReadLineAsync() is { } line)
{
if (string.IsNullOrWhiteSpace(line))
{
if (blankLine)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Out.WriteLine($"{file}({lineNumber}): Double blank line");
Console.ResetColor();
problems++;
}
blankLine = true;
}
else
{
blankLine = false;
}
if (line.Length > 130)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Out.WriteLine($"{file}({lineNumber}): Line is too long ({line.Length})");
Console.ResetColor();
problems++;
}
else if (line.Length > 0 && char.IsWhiteSpace(line[^1]))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Out.WriteLine($"{file}({lineNumber}): Line contains trailing whitespace");
Console.ResetColor();
problems++;
}
lineNumber++;
}
}
}
Console.Out.WriteLine($"Finished scanning {files} files, {problems} problems encountered.");
return problems;

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\X10D\X10D.csproj"/>
</ItemGroup>
</Project>

1000
X10D.Tests/1000primes.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
<CodeAnalysisRuleSet>..\X10D.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0"/>
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10"/>
<PackageReference Include="MSTest.TestFramework" Version="2.2.10"/>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
<PackageReference Include="Roslynator.Analyzers" Version="2.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Unity3D.SDK" Version="2019.4.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\X10D.Unity\X10D.Unity.csproj" />
<ProjectReference Include="..\X10D\X10D.csproj" />
<ProjectReference Include="..\X10D\X10D.csproj"/>
</ItemGroup>
</Project>
<ItemGroup>
<None Remove="1000primes.txt"/>
<EmbeddedResource Include="1000primes.txt"/>
</ItemGroup>
</Project>

View File

@ -1,3 +1 @@
using System;
[assembly: CLSCompliant(true)]
[assembly: CLSCompliant(true)]

View File

@ -0,0 +1,48 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class ArrayTests
{
[TestMethod]
public void AsReadOnlyShouldBeReadOnly()
{
var array = new object[] {1, "f", true};
var readOnly = array.AsReadOnly();
Assert.IsNotNull(readOnly);
Assert.IsTrue(readOnly.Count == 3);
// ReSharper disable once ConvertTypeCheckToNullCheck
Assert.IsTrue(readOnly is IReadOnlyCollection<object>);
}
[TestMethod]
public void AsReadOnlyNullShouldThrow()
{
object[]? array = null;
Assert.ThrowsException<ArgumentNullException>(array!.AsReadOnly);
}
[TestMethod]
[DataRow]
[DataRow(1)]
[DataRow(1, 2, 3)]
[DataRow(1, 2, 3, 4, 5)]
public void ClearShouldFillDefault(params int[] args)
{
args.Clear();
int[] clearedArray = Enumerable.Repeat(0, args.Length).ToArray();
CollectionAssert.AreEqual(clearedArray, args);
}
[TestMethod]
public void ClearNullShouldThrow()
{
int[]? array = null;
Assert.ThrowsException<ArgumentNullException>(array!.Clear);
Assert.ThrowsException<ArgumentNullException>(() => array!.Clear(0, 0));
}
}

View File

@ -0,0 +1,56 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class BoolListTests
{
[TestMethod]
public void Pack8Bit_Should_Pack_Correctly()
{
var array = new[] {true, false, true, false, true, false, true, false};
Assert.AreEqual(85, array.PackByte()); // 01010101
}
[TestMethod]
public void Pack16Bit_Should_Pack_Correctly()
{
var array = new[] {true, false, true, false, true, false, true, false, true, true, false, true};
Assert.AreEqual(2901, array.PackInt16()); // 101101010101
}
[TestMethod]
public void Pack32Bit_Should_Pack_Correctly()
{
var array = new[] {true, false, true, false, true, false, true, false, true, true, false, true};
Assert.AreEqual(2901, array.PackInt32()); // 101101010101
}
[TestMethod]
public void Pack64Bit_Should_Pack_Correctly()
{
var array = new[] {true, false, true, false, true, false, true, false, true, true, false, true};
Assert.AreEqual(2901, array.PackInt64()); // 101101010101
}
[TestMethod]
public void Pack_ShouldThrow_GivenLargeArray()
{
bool[] array = Enumerable.Repeat(false, 65).ToArray();
Assert.ThrowsException<ArgumentException>(() => array.PackByte());
Assert.ThrowsException<ArgumentException>(() => array.PackInt16());
Assert.ThrowsException<ArgumentException>(() => array.PackInt32());
Assert.ThrowsException<ArgumentException>(() => array.PackInt64());
}
[TestMethod]
public void Pack_ShouldThrow_GivenNull()
{
bool[]? array = null;
Assert.ThrowsException<ArgumentNullException>(() => array!.PackByte());
Assert.ThrowsException<ArgumentNullException>(() => array!.PackInt16());
Assert.ThrowsException<ArgumentNullException>(() => array!.PackInt32());
Assert.ThrowsException<ArgumentNullException>(() => array!.PackInt64());
}
}

View File

@ -0,0 +1,57 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class ByteTests
{
[TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly()
{
bool[] bits = ((byte)0b11010100).Unpack();
Assert.AreEqual(8, bits.Length);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
}
[TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly()
{
Span<bool> bits = stackalloc bool[8];
((byte)0b11010100).Unpack(bits);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
}
[TestMethod]
public void UnpackBits_ShouldRepackEqually()
{
Assert.AreEqual(0b11010100, ((byte)0b11010100).Unpack().PackByte());
}
[TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
{
Assert.ThrowsException<ArgumentException>(() =>
{
Span<bool> bits = stackalloc bool[0];
((byte)0b11010100).Unpack(bits);
});
}
}

View File

@ -0,0 +1,189 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class DictionaryTests
{
[TestMethod]
public void AddOrUpdate_ShouldAddNewKey_IfNotExists()
{
var dictionary = new Dictionary<int, string>();
Assert.IsFalse(dictionary.ContainsKey(1));
dictionary.AddOrUpdate(1, "one", (_, _) => string.Empty);
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("one", dictionary[1]);
dictionary.Clear();
Assert.IsFalse(dictionary.ContainsKey(1));
dictionary.AddOrUpdate(1, _ => "one", (_, _) => string.Empty);
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("one", dictionary[1]);
dictionary.Clear();
Assert.IsFalse(dictionary.ContainsKey(1));
dictionary.AddOrUpdate(1, (_, _) => "one", (_, _, _) => string.Empty, 0);
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("one", dictionary[1]);
}
[TestMethod]
public void AddOrUpdate_ShouldUpdateKey_IfExists()
{
var dictionary = new Dictionary<int, string> {[1] = "one"};
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("one", dictionary[1]);
dictionary.AddOrUpdate(1, string.Empty, (_, _) => "two");
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("two", dictionary[1]);
dictionary.Clear();
Assert.IsFalse(dictionary.ContainsKey(1));
dictionary[1] = "one";
dictionary.AddOrUpdate(1, _ => string.Empty, (_, _) => "two");
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("two", dictionary[1]);
dictionary.Clear();
Assert.IsFalse(dictionary.ContainsKey(1));
dictionary[1] = "one";
dictionary.AddOrUpdate(1, (_, _) => string.Empty, (_, _, _) => "two", 0);
Assert.IsTrue(dictionary.ContainsKey(1));
Assert.AreEqual("two", dictionary[1]);
}
[TestMethod]
public void AddOrUpdate_ShouldThrow_GivenNullDictionary()
{
Dictionary<int, string>? dictionary = null;
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.AddOrUpdate(1, string.Empty, (_, _) => string.Empty));
Assert.ThrowsException<ArgumentNullException>(() =>
dictionary!.AddOrUpdate(1, _ => string.Empty, (_, _) => string.Empty));
Assert.ThrowsException<ArgumentNullException>(() =>
dictionary!.AddOrUpdate(1, (_, _) => string.Empty, (_, _, _) => string.Empty, 0));
}
[TestMethod]
public void AddOrUpdate_ShouldThrow_GivenNullUpdateValueFactory()
{
var dictionary = new Dictionary<int, string>();
Assert.ThrowsException<ArgumentNullException>(() => dictionary.AddOrUpdate(1, string.Empty, null!));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.AddOrUpdate(1, _ => string.Empty, null!));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.AddOrUpdate(1, (_, _) => string.Empty, null!, 0));
}
[TestMethod]
public void AddOrUpdate_ShouldThrow_GivenNullAddValueFactory()
{
var dictionary = new Dictionary<int, string>();
Func<int, string>? addValueFactory = null;
Assert.ThrowsException<ArgumentNullException>(() => dictionary.AddOrUpdate(1, addValueFactory!, (_, _) => "one"));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.AddOrUpdate(1, null!, (_, _, _) => "one", 0));
}
[TestMethod]
public void ToConnectionString_ShouldReturnConnectionString()
{
var dictionary = new Dictionary<string, string?>
{
["Data Source"] = "localhost", ["Initial Catalog"] = "test", ["Integrated Security"] = "True", ["Foobar"] = null
};
string connectionString = dictionary.ToConnectionString();
Assert.AreEqual("Data Source=localhost;Initial Catalog=test;Integrated Security=True;Foobar=", connectionString);
}
[TestMethod]
public void ToConnectionString_ShouldReturnTransformedValueConnectionString()
{
var dictionary = new Dictionary<string, string?>
{
["Data Source"] = "localhost", ["Initial Catalog"] = "test", ["Integrated Security"] = "True", ["Foobar"] = null
};
string connectionString = dictionary.ToConnectionString(v => v?.ToUpperInvariant());
Assert.AreEqual("Data Source=LOCALHOST;Initial Catalog=TEST;Integrated Security=TRUE;Foobar=", connectionString);
}
[TestMethod]
public void ToConnectionString_ShouldReturnTransformedKeyValueConnectionString()
{
var dictionary = new Dictionary<string, string?>
{
["Data Source"] = "localhost", ["Initial Catalog"] = "test", ["Integrated Security"] = "True", ["Foobar"] = null
};
string connectionString = dictionary.ToConnectionString(k => k.ToUpper(), v => v?.ToUpperInvariant());
Assert.AreEqual("DATA SOURCE=LOCALHOST;INITIAL CATALOG=TEST;INTEGRATED SECURITY=TRUE;FOOBAR=", connectionString);
}
[TestMethod]
public void ToConnectionString_ShouldThrow_GivenNullSource()
{
Dictionary<string, string>? dictionary = null;
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.ToConnectionString());
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.ToConnectionString(null!));
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.ToConnectionString(null!, null!));
}
[TestMethod]
public void ToConnectionString_ShouldThrow_GivenNullSelector()
{
var dictionary = new Dictionary<string, string>();
Assert.ThrowsException<ArgumentNullException>(() => dictionary.ToConnectionString(null!));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.ToConnectionString(null!, _ => _));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.ToConnectionString(_ => _, null!));
}
[TestMethod]
public void ToGetParameters_ShouldReturnParameters()
{
var dictionary = new Dictionary<string, string> {["id"] = "1", ["user"] = "hello world", ["foo"] = "bar"};
string queryString = dictionary.ToGetParameters();
Assert.AreEqual("id=1&user=hello+world&foo=bar", queryString);
}
[TestMethod]
public void ToGetParameters_ShouldReturnTransformedValueParameters()
{
var dictionary = new Dictionary<string, string?> {["id"] = "1", ["user"] = "hello world", ["foo"] = null};
string queryString = dictionary.ToGetParameters(v => v?.ToUpper());
Assert.AreEqual("id=1&user=HELLO+WORLD&foo=", queryString);
}
[TestMethod]
public void ToGetParameters_ShouldReturnTransformedKeyValueParameters()
{
var dictionary = new Dictionary<string, string?> {["id"] = "1", ["user"] = "hello world", ["foo"] = null};
string queryString = dictionary.ToGetParameters(k => k.ToUpper(), v => v?.ToUpper());
Assert.AreEqual("ID=1&USER=HELLO+WORLD&FOO=", queryString);
}
[TestMethod]
public void ToGetParameters_ShouldThrow_GivenNullSource()
{
Dictionary<string, string>? dictionary = null;
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.ToGetParameters());
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.ToGetParameters(null!));
Assert.ThrowsException<ArgumentNullException>(() => dictionary!.ToGetParameters(null!, null!));
}
[TestMethod]
public void ToGetParameters_ShouldThrow_GivenNullSelector()
{
var dictionary = new Dictionary<string, string>();
Assert.ThrowsException<ArgumentNullException>(() => dictionary.ToGetParameters(null!));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.ToGetParameters(null!, _ => _));
Assert.ThrowsException<ArgumentNullException>(() => dictionary.ToGetParameters(_ => _, null!));
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class EnumerableTests
{
[TestMethod]
public void Shuffled_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((List<int>?)null)!.Shuffled());
}
[TestMethod]
public void Shuffled_ShouldReorder_GivenNotNull()
{
int[] array = Enumerable.Range(1, 52).ToArray(); // 52! chance of being shuffled to the same order
int[] shuffled = array[..];
CollectionAssert.AreEqual(array, shuffled);
shuffled = array.Shuffled().ToArray();
CollectionAssert.AreNotEqual(array, shuffled);
}
}

View File

@ -0,0 +1,67 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly()
{
bool[] bits = ((short)0b11010100).Unpack();
Assert.AreEqual(16, bits.Length);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 16; index++)
{
Assert.IsFalse(bits[index]);
}
}
[TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly()
{
Span<bool> bits = stackalloc bool[16];
((short)0b11010100).Unpack(bits);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 16; index++)
{
Assert.IsFalse(bits[index]);
}
}
[TestMethod]
public void UnpackBits_ShouldRepackEqually()
{
Assert.AreEqual(0b11010100, ((short)0b11010100).Unpack().PackInt16());
}
[TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
{
Assert.ThrowsException<ArgumentException>(() =>
{
Span<bool> bits = stackalloc bool[0];
((short)0b11010100).Unpack(bits);
});
}
}

View File

@ -0,0 +1,67 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly()
{
bool[] bits = 0b11010100.Unpack();
Assert.AreEqual(32, bits.Length);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 32; index++)
{
Assert.IsFalse(bits[index]);
}
}
[TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly()
{
Span<bool> bits = stackalloc bool[32];
0b11010100.Unpack(bits);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 32; index++)
{
Assert.IsFalse(bits[index]);
}
}
[TestMethod]
public void UnpackBits_ShouldRepackEqually()
{
Assert.AreEqual(0b11010100, 0b11010100.Unpack().PackInt32());
}
[TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
{
Assert.ThrowsException<ArgumentException>(() =>
{
Span<bool> bits = stackalloc bool[0];
0b11010100.Unpack(bits);
});
}
}

View File

@ -0,0 +1,71 @@
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void UnpackBits_ShouldUnpackToArrayCorrectly()
{
bool[] bits = 0b11010100L.Unpack();
Assert.AreEqual(64, bits.Length);
Trace.WriteLine(Convert.ToString(0b11010100L, 2));
Trace.WriteLine(string.Join("", bits.Select(b => b ? "1" : "0")));
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 64; index++)
{
Assert.IsFalse(bits[index], index.ToString());
}
}
[TestMethod]
public void UnpackBits_ShouldUnpackToSpanCorrectly()
{
Span<bool> bits = stackalloc bool[64];
0b11010100L.Unpack(bits);
Assert.IsFalse(bits[0]);
Assert.IsFalse(bits[1]);
Assert.IsTrue(bits[2]);
Assert.IsFalse(bits[3]);
Assert.IsTrue(bits[4]);
Assert.IsFalse(bits[5]);
Assert.IsTrue(bits[6]);
Assert.IsTrue(bits[7]);
for (var index = 8; index < 64; index++)
{
Assert.IsFalse(bits[index], index.ToString());
}
}
[TestMethod]
public void UnpackBits_ShouldRepackEqually()
{
Assert.AreEqual(0b11010100L, 0b11010100L.Unpack().PackInt64());
}
[TestMethod]
public void UnpackBits_ShouldThrow_GivenTooSmallSpan()
{
Assert.ThrowsException<ArgumentException>(() =>
{
Span<bool> bits = stackalloc bool[0];
0b11010100L.Unpack(bits);
});
}
}

View File

@ -0,0 +1,113 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Collections;
namespace X10D.Tests.Collections;
[TestClass]
public class ListTests
{
[TestMethod]
[DataRow(1)]
[DataRow(1, 2, 3)]
[DataRow(1, 2, 3, 4, 5)]
public void Fill_ShouldGiveHomogenousList_GivenValue(params int[] args)
{
int[] all42 = Enumerable.Repeat(42, args.Length).ToArray();
var list = new List<int>(args);
CollectionAssert.AreEqual(args, list);
args.Fill(42);
list.Fill(42);
CollectionAssert.AreEqual(args, list);
CollectionAssert.AreEqual(all42, args);
CollectionAssert.AreEqual(all42, list);
}
[TestMethod]
[DataRow(1)]
[DataRow(1, 2, 3)]
[DataRow(1, 2, 3, 4, 5)]
public void SlicedFill_ShouldLeaveFirstElement_GivenStartIndex1(params int[] args)
{
int first = args[0];
args.Fill(1, 1, args.Length - 1);
int[] comparison = Enumerable.Repeat(1, args.Length - 1).ToArray();
Assert.AreEqual(first, args[0]);
CollectionAssert.AreEqual(comparison, args[1..]);
}
[TestMethod]
public void Fill_ShouldThrow_GivenExceededCount()
{
int[] array = Array.Empty<int>();
var list = new List<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Fill(0, 0, 1));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list.Fill(0, 0, 1));
}
[TestMethod]
public void Fill_ShouldThrow_GivenNegativeCount()
{
int[] array = Array.Empty<int>();
var list = new List<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Fill(0, 0, -1));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list.Fill(0, 0, -1));
}
[TestMethod]
public void Fill_ShouldThrow_GivenNegativeStartIndex()
{
int[] array = Array.Empty<int>();
var list = new List<int>();
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.Fill(0, -1, 0));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list.Fill(0, -1, 0));
}
[TestMethod]
public void Fill_ShouldThrow_GivenNull()
{
int[]? array = null;
List<int>? list = null;
Assert.ThrowsException<ArgumentNullException>(() => array!.Fill(0));
Assert.ThrowsException<ArgumentNullException>(() => list!.Fill(0));
Assert.ThrowsException<ArgumentNullException>(() => array!.Fill(0, 0, 0));
Assert.ThrowsException<ArgumentNullException>(() => list!.Fill(0, 0, 0));
}
[TestMethod]
public void Shuffle_ShouldReorder_GivenNotNull()
{
var list = new List<int>(Enumerable.Range(1, 52)); // 52! chance of being shuffled to the same order
var shuffled = new List<int>(list);
CollectionAssert.AreEqual(list, shuffled);
shuffled.Shuffle();
CollectionAssert.AreNotEqual(list, shuffled);
}
[TestMethod]
public void Shuffle_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((List<int>?)null)!.Shuffle());
}
[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());
}
}

View File

@ -1,214 +0,0 @@
namespace X10D.Tests.Core
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="BooleanExtensions" />.
/// </summary>
[TestClass]
public class BooleanTests
{
/// <summary>
/// Tests for <see cref="BooleanExtensions.And" />.
/// </summary>
[TestMethod]
public void And()
{
const bool a = true;
const bool b = true;
const bool c = false;
const bool d = false;
Assert.IsTrue(a);
Assert.IsTrue(b);
Assert.IsFalse(c);
Assert.IsFalse(d);
Assert.IsTrue(a.And(b));
Assert.IsFalse(b.And(c));
Assert.IsFalse(c.And(d));
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.NAnd" />.
/// </summary>
[TestMethod]
public void NAnd()
{
const bool a = true;
const bool b = true;
const bool c = false;
const bool d = false;
Assert.IsTrue(a);
Assert.IsTrue(b);
Assert.IsFalse(c);
Assert.IsFalse(d);
Assert.IsFalse(a.NAnd(b));
Assert.IsTrue(b.NAnd(c));
Assert.IsTrue(c.NAnd(d));
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.NOr" />.
/// </summary>
[TestMethod]
public void NOr()
{
const bool a = true;
const bool b = true;
const bool c = false;
const bool d = false;
Assert.IsTrue(a);
Assert.IsTrue(b);
Assert.IsFalse(c);
Assert.IsFalse(d);
Assert.IsFalse(a.NOr(b));
Assert.IsFalse(b.NOr(c));
Assert.IsTrue(c.NOr(d));
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.Not" />.
/// </summary>
[TestMethod]
public void Not()
{
const bool a = true;
const bool b = false;
Assert.IsTrue(a);
Assert.IsFalse(b);
Assert.IsFalse(a.Not());
Assert.IsTrue(b.Not());
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.Or" />.
/// </summary>
[TestMethod]
public void Or()
{
const bool a = true;
const bool b = true;
const bool c = false;
const bool d = false;
Assert.IsTrue(a);
Assert.IsTrue(b);
Assert.IsFalse(c);
Assert.IsFalse(d);
Assert.IsTrue(a.Or(b));
Assert.IsTrue(b.Or(c));
Assert.IsFalse(c.Or(d));
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.ToByte" />.
/// </summary>
[TestMethod]
public void ToByte()
{
const bool a = true;
const bool b = false;
const byte c = 1;
const byte d = 0;
Assert.IsTrue(a);
Assert.IsFalse(b);
Assert.AreEqual(c, a.ToByte());
Assert.AreEqual(d, b.ToByte());
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.ToInt16" />.
/// </summary>
[TestMethod]
public void ToInt16()
{
const bool a = true;
const bool b = false;
Assert.IsTrue(a);
Assert.IsFalse(b);
Assert.AreEqual(1, a.ToInt16());
Assert.AreEqual(0, b.ToInt16());
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.ToInt32" />.
/// </summary>
[TestMethod]
public void ToInt32()
{
const bool a = true;
const bool b = false;
Assert.IsTrue(a);
Assert.IsFalse(b);
Assert.AreEqual(1, a.ToInt32());
Assert.AreEqual(0, b.ToInt32());
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.ToInt64" />.
/// </summary>
[TestMethod]
public void ToInt64()
{
const bool a = true;
const bool b = false;
Assert.IsTrue(a);
Assert.IsFalse(b);
Assert.AreEqual(1L, a.ToInt64());
Assert.AreEqual(0L, b.ToInt64());
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.XNOr" />.
/// </summary>
[TestMethod]
public void XNOr()
{
const bool a = true;
const bool b = true;
const bool c = false;
const bool d = false;
Assert.IsTrue(a);
Assert.IsTrue(b);
Assert.IsFalse(c);
Assert.IsFalse(d);
Assert.IsTrue(a.XNOr(b));
Assert.IsFalse(b.XNOr(c));
Assert.IsTrue(c.XNOr(d));
}
/// <summary>
/// Tests for <see cref="BooleanExtensions.XOr" />.
/// </summary>
[TestMethod]
public void XOr()
{
const bool a = true;
const bool b = true;
const bool c = false;
const bool d = false;
Assert.IsTrue(a);
Assert.IsTrue(b);
Assert.IsFalse(c);
Assert.IsFalse(d);
Assert.IsFalse(a.XOr(b));
Assert.IsTrue(b.XOr(c));
Assert.IsFalse(c.XOr(d));
}
}
}

View File

@ -1,103 +0,0 @@
namespace X10D.Tests.Core
{
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="ByteExtensions" />.
/// </summary>
[TestClass]
public class ByteTests
{
/// <summary>
/// Tests for <see cref="ByteExtensions.AsString" />.
/// </summary>
[TestMethod]
public void AsString()
{
byte[] a = { 0x00, 0x73, 0xc6, 0xff };
Assert.AreEqual("00-73-C6-FF", a.AsString());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetInt16" />.
/// </summary>
[TestMethod]
public void GetInt16()
{
byte[] a = { 0xF3, 0x3F };
Assert.AreEqual(16371, a.GetInt16());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetInt32" />.
/// </summary>
[TestMethod]
public void GetInt32()
{
byte[] a = { 0xB0, 0x0B, 0x13, 0x5F };
Assert.AreEqual(1595083696, a.GetInt32());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetInt64" />.
/// </summary>
[TestMethod]
public void GetInt64()
{
byte[] a = { 0xB0, 0x0B, 0x13, 0x50, 0x05, 0x31, 0xB0, 0x0B };
Assert.AreEqual(842227029206305712L, a.GetInt64());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetString(IEnumerable{byte})" />.
/// </summary>
[TestMethod]
public void GetString()
{
byte[] a = { 0x48, 0xc3, 0xa9, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64 };
Assert.AreEqual("H\u00e9llo World", a.GetString());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetString(IEnumerable{byte}, Encoding)" />.
/// </summary>
[TestMethod]
public void GetStringAscii()
{
byte[] a = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64 };
Assert.AreEqual("Hello World", a.GetString(Encoding.ASCII));
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetUInt16" />.
/// </summary>
[TestMethod]
public void GetUInt16()
{
byte[] a = { 0xF3, 0x3F };
Assert.AreEqual(16371, a.GetUInt16());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetUInt32" />.
/// </summary>
[TestMethod]
public void GetUInt32()
{
byte[] a = { 0xB0, 0x0B, 0x13, 0x5F };
Assert.AreEqual(1595083696U, a.GetUInt32());
}
/// <summary>
/// Tests for <see cref="ByteExtensions.GetUInt64" />.
/// </summary>
[TestMethod]
public void GetUInt64()
{
byte[] a = { 0xB0, 0x0B, 0x13, 0x50, 0x05, 0x31, 0xB0, 0x0B };
Assert.AreEqual(842227029206305712UL, a.GetUInt64());
}
}
}

View File

@ -1,35 +0,0 @@
namespace X10D.Tests.Core
{
using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="CharExtensions" />.
/// </summary>
[TestClass]
public class CharTests
{
/// <summary>
/// Tests for <see cref="CharExtensions.Repeat" />.
/// </summary>
[TestMethod]
public void Random()
{
var set = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
var random = set.Random(20);
Assert.IsTrue(random.All(c => Array.IndexOf(set, c) >= 0));
Assert.IsFalse(random.Any(c => Array.IndexOf(set, c) < -1));
}
/// <summary>
/// Tests for <see cref="CharExtensions.Repeat" />.
/// </summary>
[TestMethod]
public void Repeat()
{
Assert.AreEqual("aaaaaaaaaa", 'a'.Repeat(10));
}
}
}

View File

@ -1,22 +0,0 @@
namespace X10D.Tests.Core
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="ComparableExtensions" />.
/// </summary>
[TestClass]
public class ComparableTests
{
/// <summary>
/// Tests for <see cref="ComparableExtensions.Between{T}" />.
/// </summary>
[TestMethod]
public void Between()
{
Assert.IsTrue(5.Between(2, 7));
Assert.IsTrue(10.Between(9, 11));
Assert.IsFalse(100.Between(80, 99));
}
}
}

View File

@ -1,58 +0,0 @@
namespace X10D.Tests.Core
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="ConvertibleExtensions" />.
/// </summary>
[TestClass]
public class ConvertibleTests
{
/// <summary>
/// Tests for <see cref="ConvertibleExtensions.To{T}" />.
/// </summary>
[TestMethod]
public void To()
{
Assert.AreEqual(2, "2".To<int>());
Assert.AreEqual("12.5", 12.50.To<string>());
Assert.IsTrue("True".To<bool>());
}
/// <summary>
/// Tests for <see cref="ConvertibleExtensions.ToOrDefault{T}(System.IConvertible, System.IFormatProvider)" />.
/// </summary>
[TestMethod]
public void ToOrDefault()
{
Assert.AreEqual(2, "2".ToOrDefault<int>());
Assert.AreEqual("12.5", 12.50.ToOrDefault<string>());
Assert.IsTrue("True".ToOrDefault<bool>());
Assert.ThrowsException<FormatException>(() => "Foo".ToOrDefault<double>());
Assert.IsTrue("1.5".ToOrDefault(out float f));
Assert.AreEqual(1.5f, f);
}
/// <summary>
/// Tests for <see cref="ConvertibleExtensions.ToOrNull{T}(System.IConvertible, System.IFormatProvider)" />.
/// </summary>
[TestMethod]
public void ToOrNull()
{
Assert.IsFalse("foo".ToOrNull(out ConvertibleTests t));
Assert.IsNull(t);
}
/// <summary>
/// Tests for <see cref="ConvertibleExtensions.ToOrOther{T}(System.IConvertible, T, System.IFormatProvider)" />.
/// </summary>
[TestMethod]
public void ToOrOther()
{
Assert.AreEqual(2.0, "Foo".ToOrOther(2.0));
Assert.IsFalse("Foo".ToOrOther(out var d, 2.0));
Assert.AreEqual(2.0, d);
}
}
}

View File

@ -0,0 +1,76 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
namespace X10D.Tests.Core;
[TestClass]
public class CoreTests
{
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void AsArrayValue_ShouldBeLength1_GivenValue(object o)
{
object[] array = o.AsArrayValue()!;
Assert.IsNotNull(array);
Assert.IsTrue(array.Length == 1);
}
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void AsArrayValue_ShouldContainValue_Given_Value(object o)
{
object[] array = o.AsArrayValue()!;
Assert.IsNotNull(array);
Assert.AreEqual(o, array[0]);
}
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void AsEnumerableValue_ShouldBeLength1_GivenValue(object o)
{
IEnumerable<object> enumerable = o.AsEnumerableValue()!;
Assert.IsNotNull(enumerable);
Assert.IsTrue(enumerable.Count() == 1);
}
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void AsEnumerableValue_ShouldContainValue_Given_Value(object o)
{
IEnumerable<object> enumerable = o.AsEnumerableValue()!;
Assert.IsNotNull(enumerable);
Assert.AreEqual(o, enumerable.ElementAt(0));
}
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void RepeatValue_ShouldContainRepeatedValue_GivenValue(object o)
{
IEnumerable<object> enumerable = o.RepeatValue(10);
Assert.IsNotNull(enumerable);
object[] array = enumerable.ToArray();
Assert.AreEqual(10, array.Length);
CollectionAssert.AreEqual(new[] {o, o, o, o, o, o, o, o, o, o}, array);
}
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void RepeatValue_ShouldThrow_GivenNegativeCount(object o)
{
// we must force enumeration via ToArray() to ensure the exception is thrown
Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.RepeatValue(-1).ToArray());
}
}

View File

@ -1,107 +0,0 @@
namespace X10D.Tests.Core
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="DateTimeExtensions" />.
/// </summary>
[TestClass]
public class DateTimeTests
{
/// <summary>
/// Tests for <see cref="DateTimeExtensions.Age(DateTime)" />.
/// </summary>
[TestMethod]
public void Age()
{
// no choice but to create dynamic based on today's date.
// age varies with time
var now = DateTime.Now;
var dt = new DateTime(now.Year - 18, 1, 1);
Assert.AreEqual(18, dt.Age());
}
/// <summary>
/// Tests for <see cref="DateTimeExtensions.First" />.
/// </summary>
[TestMethod]
public void First()
{
var dt = new DateTime(2018, 6, 20);
Assert.AreEqual(4, dt.First(DayOfWeek.Monday).Day);
}
/// <summary>
/// Tests for <see cref="DateTimeExtensions.FirstDayOfMonth" />.
/// </summary>
[TestMethod]
public void FirstDayOfMonth()
{
var dt = new DateTime(2018, 6, 20);
var first = dt.FirstDayOfMonth();
Assert.AreEqual(dt.Year, first.Year);
Assert.AreEqual(dt.Month, first.Month);
Assert.AreEqual(1, first.Day);
}
/// <summary>
/// Tests for <see cref="DateTimeExtensions.Last" />.
/// </summary>
[TestMethod]
public void Last()
{
{
var dt = new DateTime(2019, 12, 1);
var last = dt.Last(DayOfWeek.Wednesday);
Assert.AreEqual(dt.Year, last.Year);
Assert.AreEqual(dt.Month, last.Month);
Assert.AreEqual(25, last.Day);
}
{
var dt = new DateTime(2020, 4, 14);
var last = dt.Last(DayOfWeek.Friday);
Assert.AreEqual(dt.Year, last.Year);
Assert.AreEqual(dt.Month, last.Month);
Assert.AreEqual(24, last.Day);
last = dt.Last(DayOfWeek.Thursday);
Assert.AreEqual(dt.Year, last.Year);
Assert.AreEqual(dt.Month, last.Month);
Assert.AreEqual(30, last.Day);
}
}
/// <summary>
/// Tests for <see cref="DateTimeExtensions.LastDayOfMonth" />.
/// </summary>
[TestMethod]
public void LastDayOfMonth()
{
var dt = new DateTime(2016, 2, 4);
var last = dt.LastDayOfMonth();
Assert.AreEqual(dt.Year, last.Year);
Assert.AreEqual(dt.Month, last.Month);
Assert.AreEqual(29, last.Day); // 2016 is a leap year
}
/// <summary>
/// Tests for <see cref="DateTimeExtensions.ToUnixTimeStamp" />.
/// </summary>
[TestMethod]
public void ToUnixTimestamp()
{
var dt = new DateTime(2015, 10, 21, 1, 0, 0, DateTimeKind.Utc);
var unix = dt.ToUnixTimeStamp();
Assert.AreEqual(1445389200L, unix);
}
}
}

View File

@ -1,42 +0,0 @@
namespace X10D.Tests.Core
{
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="DictionaryExtensions" />.
/// </summary>
[TestClass]
public class DictionaryTests
{
/// <summary>
/// Tests for <see cref="DictionaryExtensions.ToConnectionString{T1,T2}(IDictionary{T1,T2})" />.
/// </summary>
[TestMethod]
public void ToConnectionString()
{
var dictionary = new Dictionary<string, object>
{
{ "username", "Foo" }, { "password", "Foo Bar" }, { "port", 3306 },
};
var connectionString = dictionary.ToConnectionString();
Assert.AreEqual("username=Foo;password=\"Foo Bar\";port=3306", connectionString);
}
/// <summary>
/// Tests for <see cref="DictionaryExtensions.ToGetParameters{T1,T2}(IDictionary{T1,T2})" />.
/// </summary>
[TestMethod]
public void ToGetParameters()
{
var dictionary = new Dictionary<string, object>
{
{ "username", "Foo" }, { "password", "Foo Bar" }, { "port", 3306 },
};
var getParameterString = dictionary.ToGetParameters();
Assert.AreEqual("username=Foo&password=Foo+Bar&port=3306", getParameterString);
}
}
}

View File

@ -1,84 +0,0 @@
namespace X10D.Tests.Core
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="DoubleExtensions" />.
/// </summary>
[TestClass]
public class DoubleTests
{
/// <summary>
/// Tests for <see cref="DoubleExtensions.Clamp" />.
/// </summary>
[TestMethod]
public void Clamp()
{
Assert.AreEqual(2.0, 3.0.Clamp(1.0, 2.0));
Assert.AreEqual(1.0, (-3.0).Clamp(1.0, 2.0));
}
/// <summary>
/// Tests for <see cref="DoubleExtensions.DegreesToRadians" />.
/// </summary>
[TestMethod]
public void DegreesToRadians()
{
Assert.AreEqual(Math.PI, 180.0.DegreesToRadians());
Assert.AreEqual(Math.PI * 1.5, 270.0.DegreesToRadians());
}
/// <summary>
/// Tests for <see cref="DoubleExtensions.GetBytes" />.
/// </summary>
[TestMethod]
public void GetBytes()
{
CollectionAssert.AreEqual(
new byte[] { 0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40 },
Math.PI.GetBytes());
}
/// <summary>
/// Tests for <see cref="DoubleExtensions.IsEven" />.
/// </summary>
[TestMethod]
public void IsEven()
{
Assert.IsTrue(2.0.IsEven());
Assert.IsFalse(1.0.IsEven());
}
/// <summary>
/// Tests for <see cref="DoubleExtensions.IsOdd" />.
/// </summary>
[TestMethod]
public void IsOdd()
{
Assert.IsFalse(2.0.IsOdd());
Assert.IsTrue(1.0.IsOdd());
}
/// <summary>
/// Tests for <see cref="DoubleExtensions.RadiansToDegrees" />.
/// </summary>
[TestMethod]
public void RadiansToDegrees()
{
Assert.AreEqual(180.0, Math.PI.RadiansToDegrees());
Assert.AreEqual(360.0, (2.0 * Math.PI).RadiansToDegrees());
}
/// <summary>
/// Tests for <see cref="DoubleExtensions.Round" />.
/// </summary>
[TestMethod]
public void Round()
{
Assert.AreEqual(5.0, 3.5.Round(5));
Assert.AreEqual(5.0, 7.0.Round(5));
Assert.AreEqual(10.0, 7.5.Round(5));
}
}
}

View File

@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
namespace X10D.Tests.Core;
[TestClass]
public class EnumTests
{
// Microsoft wrongfully decided to have Sunday be 0, Monday be 1, etc.
// I personally hate this, Sunday is not the first day of the week.
// 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()
{
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Sunday.Next());
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Monday.Next());
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Tuesday.Next());
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Wednesday.Next());
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Thursday.Next());
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()
{
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Sunday.NextUnchecked());
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Monday.NextUnchecked());
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Tuesday.NextUnchecked());
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Wednesday.NextUnchecked());
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Thursday.NextUnchecked());
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Friday.NextUnchecked());
Assert.ThrowsException<IndexOutOfRangeException>(() => DayOfWeek.Saturday.NextUnchecked());
}
[TestMethod]
public void Previous()
{
Assert.AreEqual(DayOfWeek.Saturday, DayOfWeek.Sunday.Previous()); // Sunday is the "first" day. wrap to "last"
Assert.AreEqual(DayOfWeek.Sunday, DayOfWeek.Monday.Previous());
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Tuesday.Previous());
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Wednesday.Previous());
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Thursday.Previous());
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Friday.Previous());
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Saturday.Previous());
}
[TestMethod]
public void PreviousUnchecked()
{
Assert.AreEqual(DayOfWeek.Sunday, DayOfWeek.Monday.PreviousUnchecked());
Assert.AreEqual(DayOfWeek.Monday, DayOfWeek.Tuesday.PreviousUnchecked());
Assert.AreEqual(DayOfWeek.Tuesday, DayOfWeek.Wednesday.PreviousUnchecked());
Assert.AreEqual(DayOfWeek.Wednesday, DayOfWeek.Thursday.PreviousUnchecked());
Assert.AreEqual(DayOfWeek.Thursday, DayOfWeek.Friday.PreviousUnchecked());
Assert.AreEqual(DayOfWeek.Friday, DayOfWeek.Saturday.PreviousUnchecked());
Assert.ThrowsException<IndexOutOfRangeException>(() => DayOfWeek.Sunday.PreviousUnchecked());
}
}

View File

@ -1,55 +1,20 @@
namespace X10D.Tests.Core
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
namespace X10D.Tests.Core;
[TestClass]
public class EnumerableTests
{
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="EnumerableExtensions" />.
/// </summary>
[TestClass]
public class EnumerableTests
[TestMethod]
[DataRow(1)]
[DataRow("f")]
[DataRow(true)]
public void AsEnumerable_ShouldWrapElement_GivenValue(object o)
{
/// <summary>
/// Tests for <see cref="EnumerableExtensions.Split{T}" /> using an array of <see cref="byte" />.
/// </summary>
[TestMethod]
public void SplitByte()
{
byte[] foo = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
IEnumerable<IEnumerable<byte>> chunks = foo.Split(2).ToArray();
Assert.AreEqual(4, chunks.Count());
CollectionAssert.AreEqual(new byte[] { 0x01, 0x02 }, chunks.ElementAt(0).ToList());
CollectionAssert.AreEqual(new byte[] { 0x03, 0x04 }, chunks.ElementAt(1).ToList());
CollectionAssert.AreEqual(new byte[] { 0x05, 0x06 }, chunks.ElementAt(2).ToList());
CollectionAssert.AreEqual(new byte[] { 0x07, 0x08 }, chunks.ElementAt(3).ToList());
// test exceeding chunk size
chunks = foo.Split(foo.Length + 10).ToArray();
Assert.AreEqual(1, chunks.Count());
CollectionAssert.AreEqual(foo, chunks.SelectMany(c => c).ToList());
}
/// <summary>
/// Tests for <see cref="EnumerableExtensions.Split{T}" /> using an array of <see cref="int" />.
/// </summary>
[TestMethod]
public void SplitInt32()
{
int[] foo = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
IEnumerable<IEnumerable<int>> chunks = foo.Split(2).ToArray();
Assert.AreEqual(4, chunks.Count());
CollectionAssert.AreEqual(new[] { 0x01, 0x02 }, chunks.ElementAt(0).ToList());
CollectionAssert.AreEqual(new[] { 0x03, 0x04 }, chunks.ElementAt(1).ToList());
CollectionAssert.AreEqual(new[] { 0x05, 0x06 }, chunks.ElementAt(2).ToList());
CollectionAssert.AreEqual(new[] { 0x07, 0x08 }, chunks.ElementAt(3).ToList());
// test exceeding chunk size
chunks = foo.Split(foo.Length + 10).ToArray();
Assert.AreEqual(1, chunks.Count());
CollectionAssert.AreEqual(foo, chunks.SelectMany(c => c).ToList());
}
IEnumerable<object?> array = o.AsEnumerableValue().ToArray(); // prevent multiple enumeration of IEnumerable
Assert.IsNotNull(array);
Assert.IsTrue(array.Count() == 1);
Assert.AreEqual(o, array.ElementAt(0));
}
}

View File

@ -0,0 +1,245 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Core;
namespace X10D.Tests.Core;
[TestClass]
public class RandomTests
{
[TestMethod]
public void NextBoolean_ShouldBeFalse_GivenSeed1234()
{
var random = new Random(1234);
Assert.IsFalse(random.NextBoolean());
}
[TestMethod]
public void NextBoolean_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextBoolean());
}
[TestMethod]
public void NextByte_ShouldBe101_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(101, random.NextByte());
}
[TestMethod]
public void NextByte_WithMax10_ShouldBe3_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3, random.NextByte(10));
}
[TestMethod]
public void NextByte_WithMin0Max10_ShouldBe3_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3, random.NextByte(0, 10));
}
[TestMethod]
public void NextByte_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextByte());
Assert.ThrowsException<ArgumentNullException>(() => random!.NextByte(10));
Assert.ThrowsException<ArgumentNullException>(() => random!.NextByte(0, 10));
}
[TestMethod]
public void NextDouble_WithMax10_ShouldBe3point9908097935797695_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3.9908097935797695, random.NextDouble(10));
}
[TestMethod]
public void NextDouble_WithMin0Max10_ShouldBe3point9908097935797695_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3.9908097935797695, random.NextDouble(0, 10));
}
[TestMethod]
public void NextDouble_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextDouble(10));
Assert.ThrowsException<ArgumentNullException>(() => random!.NextDouble(0, 10));
}
[TestMethod]
public void NextDouble_ShouldThrow_GivenMaxLessThan0()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentOutOfRangeException>(() => random.NextDouble(-1));
}
[TestMethod]
public void NextDouble_ShouldThrow_GivenMaxLessThanMin()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentException>(() => random.NextDouble(0, -1));
}
[TestMethod]
public void NextEnum_ShouldBeTuesday_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(DayOfWeek.Tuesday, random.Next<DayOfWeek>());
}
[TestMethod]
public void NextEnum_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.Next<DayOfWeek>());
}
[TestMethod]
public void NextFrom_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextFrom(""));
}
[TestMethod]
public void NextFrom_ShouldThrow_GivenNullSource()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentNullException>(() => random.NextFrom((string?)null!));
}
[TestMethod]
public void NextFrom_ShouldEnumerate_GivenNonList()
{
IEnumerable<int> Source()
{
yield return 0;
}
var random = new Random(1234);
Assert.AreEqual(0, random.NextFrom(Source()));
}
[TestMethod]
public void NextInt16_ShouldBe13076_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(13076, random.NextInt16());
}
[TestMethod]
public void NextInt16_WithMax10_ShouldBe3_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3, random.NextInt16(10));
}
[TestMethod]
public void NextInt16_WithMin0Max10_ShouldBe3_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3, random.NextInt16(0, 10));
}
[TestMethod]
public void NextInt16_ShouldThrow_GivenMaxLessThan0()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentOutOfRangeException>(() => random.NextInt16(-1));
}
[TestMethod]
public void NextInt16_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextInt16());
Assert.ThrowsException<ArgumentNullException>(() => random!.NextInt16(10));
Assert.ThrowsException<ArgumentNullException>(() => random!.NextInt16(0, 10));
}
[TestMethod]
public void NextSingle_WithMax10_ShouldBe3point99081_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3.99081f, random.NextSingle(10));
}
[TestMethod]
public void NextSingle_WithMin0Max10_ShouldBe3point99081_GivenSeed1234()
{
var random = new Random(1234);
Assert.AreEqual(3.99081f, random.NextSingle(0, 10));
}
[TestMethod]
public void NextSingle_ShouldThrow_GivenNull()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextSingle(10));
Assert.ThrowsException<ArgumentNullException>(() => random!.NextSingle(0, 10));
}
[TestMethod]
public void NextSingle_ShouldThrow_GivenMaxLessThan0()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentOutOfRangeException>(() => random.NextSingle(-1));
}
[TestMethod]
public void NextSingle_ShouldThrow_GivenMaxLessThanMin()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentException>(() => random.NextSingle(0, -1));
}
[TestMethod]
public void NextString_ShouldBe_kxiyiyvnqi_GivenSeed1234()
{
const string alphabet = "abcdefghijklmnopqrstuvwxyz";
var random = new Random(1234);
Assert.AreEqual("kxiyiyvnqi", random.NextString(alphabet.ToCharArray(), 10));
}
[TestMethod]
public void NextString_ShouldBeEmpty_GivenLength0()
{
var random = new Random(1234);
Assert.AreEqual(string.Empty, random.NextString(ArraySegment<char>.Empty, 0));
}
[TestMethod]
public void NextString_ShouldBeLength1_GivenLength1()
{
var random = new Random(1234);
Assert.AreEqual(1, random.NextString("hello world".ToCharArray(), 1).Length);
}
[TestMethod]
public void NextString_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextString(ArraySegment<char>.Empty, 0));
}
[TestMethod]
public void NextString_ShouldThrow_GivenNullSource()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentNullException>(() => random.NextString(null!, 0));
}
[TestMethod]
public void NextString_ShouldThrow_GivenNegativeLength()
{
var random = new Random(1234);
Assert.ThrowsException<ArgumentOutOfRangeException>(() => random.NextString(ArraySegment<char>.Empty, -1));
}
}

View File

@ -1,70 +0,0 @@
namespace X10D.Tests.Core
{
using System;
using System.ComponentModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="ReflectionExtensions" />.
/// </summary>
[TestClass]
public class ReflectionTests
{
/// <summary>
/// Test for <see cref="ReflectionExtensions.GetDefaultValue{T}(System.Reflection.MemberInfo)" />.
/// </summary>
[TestMethod]
public void GetDefaultValue()
{
var klass = new TestClass();
foreach (var property in klass.GetType().GetProperties())
{
Assert.AreEqual("Foo", property.GetDefaultValue<string>());
}
}
/// <summary>
/// Test for <see cref="ReflectionExtensions.GetDescription(System.Reflection.MemberInfo)" />.
/// </summary>
[TestMethod]
public void GetDescription()
{
var klass = new TestClass();
foreach (var property in klass.GetType().GetProperties())
{
Assert.AreEqual("Test description", property.GetDescription());
}
}
/// <summary>
/// Test for <see cref="ReflectionExtensions.GetDescription(System.Reflection.MemberInfo)" />.
/// </summary>
[TestMethod]
public void SelectFromCustomAttribute()
{
var klass = new TestClass();
foreach (var property in klass.GetType().GetProperties())
{
var value = property.SelectFromCustomAttribute<TestAttribute, string>(a => a.TestValue);
Assert.AreEqual("Bar", value);
}
}
[AttributeUsage(AttributeTargets.Property)]
private sealed class TestAttribute : Attribute
{
public string TestValue { get; set; }
}
private sealed class TestClass
{
[System.ComponentModel.Description("Test description")]
[DefaultValue("Foo")]
[Test(TestValue = "Bar")]
public string TestProperty { get; set; }
}
}
}

View File

@ -1,81 +0,0 @@
namespace X10D.Tests.Core
{
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="StringExtensions" />.
/// </summary>
[TestClass]
public class StringTests
{
/// <summary>
/// Tests for <see cref="StringExtensions.AsNullIfEmpty" />.
/// </summary>
[TestMethod]
public void AsNullIfEmpty()
{
Assert.AreEqual(null, string.Empty.AsNullIfEmpty());
Assert.AreEqual(null, ((string)null).AsNullIfEmpty());
Assert.AreEqual(" ", " ".AsNullIfEmpty());
Assert.AreEqual("foo", "foo".AsNullIfEmpty());
}
/// <summary>
/// Tests for <see cref="StringExtensions.AsNullIfWhiteSpace" />.
/// </summary>
[TestMethod]
public void AsNullIfWhiteSpace()
{
Assert.AreEqual(null, string.Empty.AsNullIfWhiteSpace());
Assert.AreEqual(null, ((string)null).AsNullIfWhiteSpace());
Assert.AreEqual(null, " ".AsNullIfWhiteSpace());
Assert.AreEqual("foo", "foo".AsNullIfWhiteSpace());
}
/// <summary>
/// Tests for <see cref="StringExtensions.Repeat" />.
/// </summary>
[TestMethod]
public void Repeat()
{
Assert.AreEqual("foofoofoofoofoo", "foo".Repeat(5));
}
/// <summary>
/// Tests for <see cref="StringExtensions.Reverse" />.
/// </summary>
[TestMethod]
public void Reverse()
{
Assert.AreEqual("dlroW olleH", StringExtensions.Reverse("Hello World"));
Assert.AreEqual("Foobar", StringExtensions.Reverse("rabooF"));
}
/// <summary>
/// Tests for <see cref="StringExtensions.Split" />.
/// </summary>
[TestMethod]
public void Split()
{
const string str = "Hello World";
// ReSharper disable once SuggestVarOrType_Elsewhere
var arr = str.Split(2).ToArray();
CollectionAssert.AreEqual(new[] { "He", "ll", "o ", "Wo", "rl", "d" }, arr);
}
/// <summary>
/// Tests for <see cref="StringExtensions.WithAlternative" />.
/// </summary>
[TestMethod]
public void WithAlternative()
{
Assert.AreEqual("Hello", "Hello".WithAlternative("Discarded"));
Assert.AreEqual("Alternative", string.Empty.WithAlternative("Alternative"));
Assert.AreEqual(" ", " ".WithAlternative("Discarded"));
Assert.AreEqual("Alternative", " ".WithAlternative("Alternative", true));
Assert.AreEqual("Alternative", ((string)null).WithAlternative("Alternative"));
}
}
}

View File

@ -1,26 +0,0 @@
namespace X10D.Tests.Core
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
/// <summary>
/// Tests for <see cref="TimeSpanParser" />.
/// </summary>
[TestClass]
public class TimeSpanParserTests
{
/// <summary>
/// Tests for <see cref="TimeSpanParser.Parse" />.
/// </summary>
[TestMethod]
public void TestParser()
{
Assert.AreEqual(TimeSpan.FromHours(3), "3h".ToTimeSpan());
Assert.AreEqual(TimeSpan.FromMinutes(2.5), "2.5m".ToTimeSpan());
Assert.AreEqual(TimeSpan.FromHours(1), "60m".ToTimeSpan());
Assert.AreEqual(TimeSpan.FromDays(1), "1d".ToTimeSpan());
Assert.AreEqual(TimeSpan.FromDays(8), "1w 1d".ToTimeSpan());
Assert.AreEqual(TimeSpan.FromDays(8), "1w1d".ToTimeSpan());
}
}
}

View File

@ -0,0 +1,37 @@
using System.Drawing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Drawing;
namespace X10D.Tests.Drawing;
[TestClass]
public class RandomTests
{
[TestMethod]
public void NextColorArgb_ShouldReturn331515e5_GivenSeed1234()
{
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()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextColorRgb());
}
}

View File

@ -0,0 +1,32 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class BooleanTests
{
[TestMethod]
public void GetBytes_ReturnsArrayContaining1()
{
const bool value = true;
CollectionAssert.AreEqual(new byte[] {1}, value.GetBytes());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanContaining1_GivenLargeEnoughSpan()
{
const bool value = true;
Span<byte> buffer = stackalloc byte[1];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(new byte[] {1}, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const bool value = true;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,32 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class ByteTests
{
[TestMethod]
public void GetBytes_ReturnsArrayContainingItself()
{
const byte value = 0xFF;
CollectionAssert.AreEqual(new[] {value}, value.GetBytes());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanContainingItself_GivenLargeEnoughSpan()
{
const byte value = 0xFF;
Span<byte> buffer = stackalloc byte[1];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(new[] {value}, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const byte value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,66 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class DoubleTests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const double value = 42.5;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0, 0, 0, 0, 0, 0x40, 0x45, 0x40}
: new byte[] {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const double value = 42.5;
byte[] littleEndian = {0, 0, 0, 0, 0, 0x40, 0x45, 0x40};
byte[] bigEndian = {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const double value = 42.5;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0, 0, 0, 0, 0, 0x40, 0x45, 0x40}
: new byte[] {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
Span<byte> buffer = stackalloc byte[8];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const double value = 42.5;
byte[] littleEndian = {0, 0, 0, 0, 0, 0x40, 0x45, 0x40};
byte[] bigEndian = {0x40, 0x45, 0x40, 0, 0, 0, 0, 0};
Span<byte> buffer = stackalloc byte[8];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const double value = 42.5;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,93 @@
using System.Security.Cryptography;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class FileInfoTests
{
[TestMethod]
public void GetHashSha1ShouldBeCorrect()
{
string fileName = $"temp.{DateTimeOffset.Now.ToUnixTimeSeconds()}.bin";
if (File.Exists(fileName))
{
Assert.Fail("Temporary file already exists");
}
File.WriteAllText(fileName, "Hello World");
Assert.IsTrue(File.Exists(fileName));
// SHA-1
byte[] expectedHash =
{
0x0A, 0x4D, 0x55, 0xA8, 0xD7, 0x78, 0xE5, 0x02, 0x2F, 0xAB, 0x70, 0x19, 0x77, 0xC5, 0xD8, 0x40, 0xBB, 0xC4, 0x86,
0xD0
};
try
{
byte[] hash = new FileInfo(fileName).GetHash<SHA1>();
CollectionAssert.AreEqual(expectedHash, hash);
}
finally
{
File.Delete(fileName); // cleanup is important
}
}
[TestMethod]
public void TryWriteHashSha1ShouldBeCorrect()
{
string fileName = $"temp.{DateTimeOffset.Now.ToUnixTimeSeconds()}.bin";
if (File.Exists(fileName))
{
Assert.Fail("Temporary file already exists");
}
File.WriteAllText(fileName, "Hello World");
Assert.IsTrue(File.Exists(fileName));
// SHA-1
byte[] expectedHash =
{
0x0A, 0x4D, 0x55, 0xA8, 0xD7, 0x78, 0xE5, 0x02, 0x2F, 0xAB, 0x70, 0x19, 0x77, 0xC5, 0xD8, 0x40, 0xBB, 0xC4, 0x86,
0xD0
};
try
{
Span<byte> hash = stackalloc byte[20];
new FileInfo(fileName).TryWriteHash<SHA1>(hash, out int bytesWritten);
Assert.AreEqual(expectedHash.Length, bytesWritten);
CollectionAssert.AreEqual(expectedHash, hash.ToArray());
}
finally
{
File.Delete(fileName); // cleanup is important
}
}
[TestMethod]
public void GetHashNullShouldThrow()
{
// any HashAlgorithm will do, but SHA1 is used above. so to remain consistent, we use it here
Assert.ThrowsException<ArgumentNullException>(() => ((FileInfo?)null)!.GetHash<SHA1>());
Assert.ThrowsException<ArgumentNullException>(() => ((FileInfo?)null)!.TryWriteHash<SHA1>(Span<byte>.Empty, out _));
}
[TestMethod]
public void GetHashInvalidFileShouldThrow()
{
string fileName = $"temp.{DateTimeOffset.Now.ToUnixTimeSeconds()}.bin";
if (File.Exists(fileName))
{
Assert.Fail("Temporary file already exists");
}
// any HashAlgorithm will do, but SHA1 is used above. so to remain consistent, we use it here
Assert.ThrowsException<FileNotFoundException>(() => new FileInfo(fileName).GetHash<SHA1>());
Assert.ThrowsException<FileNotFoundException>(() => new FileInfo(fileName).TryWriteHash<SHA1>(Span<byte>.Empty, out _));
}
}

View File

@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const short value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0} : new byte[] {0, 0x0F};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const short value = 0x0F;
byte[] littleEndian = {0x0F, 0};
byte[] bigEndian = {0, 0x0F};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const short value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0} : new byte[] {0, 0x0F};
Span<byte> buffer = stackalloc byte[2];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const short value = 0x0F;
byte[] littleEndian = {0x0F, 0};
byte[] bigEndian = {0, 0x0F};
Span<byte> buffer = stackalloc byte[2];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const short value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const int value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0, 0, 0} : new byte[] {0, 0, 0, 0x0F};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const int value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0x0F};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const int value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0, 0, 0} : new byte[] {0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[4];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const int value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[4];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const int value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,66 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const long value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0x0F, 0, 0, 0, 0, 0, 0, 0}
: new byte[] {0, 0, 0, 0, 0, 0, 0, 0x0F};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const long value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0, 0, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0, 0, 0, 0, 0x0F};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const long value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0x0F, 0, 0, 0, 0, 0, 0, 0}
: new byte[] {0, 0, 0, 0, 0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[8];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const long value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0, 0, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0, 0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[8];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const long value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,168 @@
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class ListOfByteTests
{
[TestMethod]
public void AsString_ShouldReturnBytes_GivenBytes()
{
var bytes = new byte[] {0x01, 0x02, 0x03, 0x04, 0x05};
Assert.AreEqual("01-02-03-04-05", bytes.AsString());
}
[TestMethod]
public void AsString_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.AsString());
}
[TestMethod]
public void ToDouble_ShouldReturnDouble_GivenBytes()
{
var bytes = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x40};
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
Assert.AreEqual(420.0, bytes.ToDouble(), 1e-6);
}
[TestMethod]
public void ToDouble_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToDouble());
}
[TestMethod]
public void ToInt16_ShouldReturnInt16_GivenBytes()
{
var bytes = new byte[] {0xA4, 0x01};
Assert.AreEqual(420, bytes.ToInt16());
}
[TestMethod]
public void ToInt16_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToInt16());
}
[TestMethod]
public void ToInt32_ShouldReturnInt32_GivenBytes()
{
var bytes = new byte[] {0xA4, 0x01, 0x00, 0x00};
Assert.AreEqual(420, bytes.ToInt32());
}
[TestMethod]
public void ToInt32_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToInt32());
}
[TestMethod]
public void ToInt64_ShouldReturnInt32_GivenBytes()
{
var bytes = new byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Assert.AreEqual(420L, bytes.ToInt64());
}
[TestMethod]
public void ToInt64_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToInt64());
}
[TestMethod]
public void ToSingle_ShouldReturnDouble_GivenBytes()
{
var bytes = new byte[] {0x00, 0x00, 0xD2, 0x43};
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
Assert.AreEqual(420.0, bytes.ToSingle(), 1e-6);
}
[TestMethod]
public void ToSingle_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToSingle());
}
[TestMethod]
public void ToString_ShouldReturnHelloWorld_GivenUTF8()
{
var bytes = new byte[] {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
Assert.AreEqual("Hello World", bytes.ToString(Encoding.UTF8));
}
[TestMethod]
public void ToString_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToString(Encoding.UTF8));
}
[TestMethod]
public void ToString_ShouldThrow_GivenNullEncoding()
{
var bytes = new byte[] {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
Assert.ThrowsException<ArgumentNullException>(() => bytes.ToString(null!));
}
[TestMethod]
public void ToUInt16_ShouldReturnInt16_GivenBytes()
{
var bytes = new byte[] {0xA4, 0x01};
Assert.AreEqual((ushort)420, bytes.ToUInt16());
}
[TestMethod]
public void ToUInt16_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToUInt16());
}
[TestMethod]
public void ToUInt32_ShouldReturnInt32_GivenBytes()
{
var bytes = new byte[] {0xA4, 0x01, 0x00, 0x00};
Assert.AreEqual(420U, bytes.ToUInt32());
}
[TestMethod]
public void ToUInt32_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToUInt32());
}
[TestMethod]
public void ToUInt64_ShouldReturnInt32_GivenBytes()
{
var bytes = new byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Assert.AreEqual(420UL, bytes.ToUInt64());
}
[TestMethod]
public void ToUInt64_ShouldThrow_GivenNullArray()
{
byte[]? bytes = null;
Assert.ThrowsException<ArgumentNullException>(() => bytes!.ToUInt64());
}
}

View File

@ -0,0 +1,33 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
[CLSCompliant(false)]
public class SByteTests
{
[TestMethod]
public void GetBytes_ReturnsArrayContainingItself()
{
const sbyte value = 0x0F;
CollectionAssert.AreEqual(new[] {(byte)value}, value.GetBytes());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanContainingItself_GivenLargeEnoughSpan()
{
const sbyte value = 0x0F;
Span<byte> buffer = stackalloc byte[1];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(new[] {(byte)value}, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const sbyte value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,66 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class SingleTests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const float value = 42.5f;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0, 0, 0x2A, 0x42}
: new byte[] {0x42, 0x2A, 0, 0};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const float value = 42.5f;
byte[] littleEndian = {0, 0, 0x2A, 0x42};
byte[] bigEndian = {0x42, 0x2A, 0, 0};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const float value = 42.5f;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0, 0, 0x2A, 0x42}
: new byte[] {0x42, 0x2A, 0, 0};
Span<byte> buffer = stackalloc byte[4];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const float value = 42.5f;
byte[] littleEndian = {0, 0, 0x2A, 0x42};
byte[] bigEndian = {0x42, 0x2A, 0, 0};
Span<byte> buffer = stackalloc byte[4];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const float value = 42.5f;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,526 @@
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
public class StreamTests
{
[TestMethod]
public void GetHashSha1ShouldBeCorrect()
{
// SHA-1
byte[] expectedHash =
{
0x0A, 0x4D, 0x55, 0xA8, 0xD7, 0x78, 0xE5, 0x02, 0x2F, 0xAB, 0x70, 0x19, 0x77, 0xC5, 0xD8, 0x40, 0xBB, 0xC4, 0x86,
0xD0
};
using var stream = new MemoryStream();
stream.Write(Encoding.UTF8.GetBytes("Hello World"));
stream.Position = 0;
byte[] hash = stream.GetHash<SHA1>();
Trace.WriteLine($"Hash: {BitConverter.ToString(hash)}");
Trace.WriteLine($"Expected: {BitConverter.ToString(expectedHash)}");
CollectionAssert.AreEqual(expectedHash, hash);
}
[TestMethod]
public void GetHashNullShouldThrow()
{
// any HashAlgorithm will do, but SHA1 is used above. so to remain consistent, we use it here
Assert.ThrowsException<ArgumentNullException>(() => ((Stream?)null)!.GetHash<SHA1>());
Assert.ThrowsException<ArgumentNullException>(() => ((Stream?)null)!.TryWriteHash<SHA1>(Span<byte>.Empty, out _));
}
[TestMethod]
public void TryWriteHashSha1_ShouldBeCorrect()
{
// SHA-1
byte[] expectedHash =
{
0x0A, 0x4D, 0x55, 0xA8, 0xD7, 0x78, 0xE5, 0x02, 0x2F, 0xAB, 0x70, 0x19, 0x77, 0xC5, 0xD8, 0x40, 0xBB, 0xC4, 0x86,
0xD0
};
using var stream = new MemoryStream();
stream.Write(Encoding.UTF8.GetBytes("Hello World"));
stream.Position = 0;
Span<byte> hash = stackalloc byte[20];
stream.TryWriteHash<SHA1>(hash, out int bytesWritten);
Assert.AreEqual(expectedHash.Length, bytesWritten);
CollectionAssert.AreEqual(expectedHash, hash.ToArray());
}
[TestMethod]
public void GetHash_TryWriteHash_ShouldThrow_GivenNonReadableStream()
{
Assert.ThrowsException<IOException>(() =>
{
using var stream = new DummyStream();
stream.GetHash<SHA1>();
});
Assert.ThrowsException<IOException>(() =>
{
using var stream = new DummyStream();
stream.TryWriteHash<SHA1>(Span<byte>.Empty, out _);
});
}
[TestMethod]
public void LargeStreamShouldThrow()
{
Assert.ThrowsException<ArgumentException>(() =>
{
using var stream = new DummyStream(true);
stream.TryWriteHash<SHA1>(Span<byte>.Empty, out _);
});
}
[TestMethod]
public void NullCreateMethodShouldThrow()
{
Assert.ThrowsException<TypeInitializationException>(() => Stream.Null.GetHash<HashAlgorithmTestClass>());
Assert.ThrowsException<TypeInitializationException>(() =>
Stream.Null.TryWriteHash<HashAlgorithmTestClass>(Span<byte>.Empty, out _));
}
[TestMethod]
public void NoCreateMethodShouldThrow()
{
Assert.ThrowsException<TypeInitializationException>(() => Stream.Null.GetHash<HashAlgorithmTestClassNoCreateMethod>());
Assert.ThrowsException<TypeInitializationException>(() =>
Stream.Null.TryWriteHash<HashAlgorithmTestClassNoCreateMethod>(Span<byte>.Empty, out _));
}
[TestMethod]
public void Write_ShouldThrow_GivenUndefinedEndianness()
{
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0.0f, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0.0, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0.0m, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write((short)0, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0L, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write((ushort)0, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0U, (Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.Write(0UL, (Endianness)(-1));
});
}
[TestMethod]
public void Read_ShouldThrow_GivenNullStream()
{
Stream? stream = null;
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadSingle());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadDouble());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadDecimal());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadInt16());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadInt32());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadInt64());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadUInt16());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadUInt32());
Assert.ThrowsException<ArgumentNullException>(() => stream!.ReadUInt64());
}
[TestMethod]
public void Write_ShouldThrow_GivenNullStream()
{
Stream? stream = null;
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0.0f, Endianness.LittleEndian));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0.0, Endianness.LittleEndian));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0.0m, Endianness.LittleEndian));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write((short)0));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0L));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write((ushort)0));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0U));
Assert.ThrowsException<ArgumentNullException>(() => stream!.Write(0UL));
}
[TestMethod]
public void Read_ShouldThrow_GivenUndefinedEndianness()
{
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadSingle((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadDouble((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadDecimal((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadInt16((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadInt32((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadInt64((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadUInt16((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadUInt32((Endianness)(-1));
});
Assert.ThrowsException<ArgumentOutOfRangeException>(() =>
{
using var stream = new MemoryStream();
return stream.ReadUInt64((Endianness)(-1));
});
}
[TestMethod]
public void ReadDouble_WriteDouble_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420.0, BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420.0, stream.ReadDouble(), 1e-6);
stream.Position = 0;
stream.Write(420.0, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420.0, stream.ReadDouble(Endianness.LittleEndian), 1e-6);
stream.Position = 0;
stream.Write(420.0, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420.0, stream.ReadDouble(Endianness.BigEndian), 1e-6);
}
[TestMethod]
public void ReadDecimal_WriteSingle_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420.0m, BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420.0m, stream.ReadDecimal());
stream.Position = 0;
stream.Write(420.0m, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420.0m, stream.ReadDecimal(Endianness.LittleEndian));
stream.Position = 0;
stream.Write(420.0m, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420.0m, stream.ReadDecimal(Endianness.BigEndian));
}
[TestMethod]
public void ReadSingle_WriteSingle_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420.0f, BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420.0f, stream.ReadSingle(), 1e-6f);
stream.Position = 0;
stream.Write(420.0f, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420.0f, stream.ReadSingle(Endianness.LittleEndian), 1e-6f);
stream.Position = 0;
stream.Write(420.0f, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420.0f, stream.ReadSingle(Endianness.BigEndian), 1e-6f);
}
[TestMethod]
public void ReadInt16_WriteInt16_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write((short)420);
stream.Position = 0;
Assert.AreEqual(420, stream.ReadInt16());
stream.Position = 0;
stream.Write((short)420, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420, stream.ReadInt16(Endianness.LittleEndian));
stream.Position = 0;
stream.Write((short)420, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420, stream.ReadInt16(Endianness.BigEndian));
}
[TestMethod]
public void ReadInt32_WriteInt32_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420);
stream.Position = 0;
Assert.AreEqual(420, stream.ReadInt32());
stream.Position = 0;
stream.Write(420, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420, stream.ReadInt32(Endianness.LittleEndian));
stream.Position = 0;
stream.Write(420, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420, stream.ReadInt32(Endianness.BigEndian));
}
[TestMethod]
public void ReadInt64_WriteInt64_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420L);
stream.Position = 0;
Assert.AreEqual(420L, stream.ReadInt64());
stream.Position = 0;
stream.Write(420L, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420L, stream.ReadInt64(Endianness.LittleEndian));
stream.Position = 0;
stream.Write(420L, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420L, stream.ReadInt64(Endianness.BigEndian));
}
[TestMethod]
[CLSCompliant(false)]
public void ReadUInt16_WriteUInt16_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write((ushort)420);
stream.Position = 0;
Assert.AreEqual((ushort)420, stream.ReadUInt16());
stream.Position = 0;
stream.Write((ushort)420, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual((ushort)420, stream.ReadUInt16(Endianness.LittleEndian));
stream.Position = 0;
stream.Write((ushort)420, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual((ushort)420, stream.ReadUInt16(Endianness.BigEndian));
}
[TestMethod]
[CLSCompliant(false)]
public void ReadUInt32_WriteUInt32_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420U);
stream.Position = 0;
Assert.AreEqual(420U, stream.ReadUInt32());
stream.Position = 0;
stream.Write(420U, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420U, stream.ReadUInt32(Endianness.LittleEndian));
stream.Position = 0;
stream.Write(420U, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420U, stream.ReadUInt32(Endianness.BigEndian));
}
[TestMethod]
[CLSCompliant(false)]
public void ReadUInt64_WriteUInt64_ShouldBeSymmetric()
{
using var stream = new MemoryStream();
stream.Write(420UL);
stream.Position = 0;
Assert.AreEqual(420UL, stream.ReadUInt64());
stream.Position = 0;
stream.Write(420UL, Endianness.LittleEndian);
stream.Position = 0;
Assert.AreEqual(420UL, stream.ReadUInt64(Endianness.LittleEndian));
stream.Position = 0;
stream.Write(420UL, Endianness.BigEndian);
stream.Position = 0;
Assert.AreEqual(420UL, stream.ReadUInt64(Endianness.BigEndian));
}
private class DummyStream : Stream
{
public DummyStream(bool readable = false)
{
CanRead = readable;
CanSeek = readable;
CanWrite = readable;
}
public override void Flush()
{
}
public override int Read(byte[] buffer, int offset, int count)
{
return 0;
}
public override long Seek(long offset, SeekOrigin origin)
{
return 0;
}
public override void SetLength(long value)
{
}
public override void Write(byte[] buffer, int offset, int count)
{
}
public override bool CanRead { get; }
public override bool CanSeek { get; }
public override bool CanWrite { get; }
public override long Length
{
get => long.MaxValue;
}
public override long Position
{
get => 0;
set { }
}
}
private class HashAlgorithmTestClass : HashAlgorithm
{
public static new HashAlgorithmTestClass? Create()
{
return null;
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
throw new NotImplementedException();
}
protected override byte[] HashFinal()
{
throw new NotImplementedException();
}
public override void Initialize()
{
throw new NotImplementedException();
}
}
private class HashAlgorithmTestClassNoCreateMethod : HashAlgorithm
{
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
throw new NotImplementedException();
}
protected override byte[] HashFinal()
{
throw new NotImplementedException();
}
public override void Initialize()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,63 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
[CLSCompliant(false)]
public class UInt16Tests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const ushort value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0} : new byte[] {0, 0x0F};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const ushort value = 0x0F;
byte[] littleEndian = {0x0F, 0};
byte[] bigEndian = {0, 0x0F};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const ushort value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0} : new byte[] {0, 0x0F};
Span<byte> buffer = stackalloc byte[2];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const ushort value = 0x0F;
byte[] littleEndian = {0x0F, 0};
byte[] bigEndian = {0, 0x0F};
Span<byte> buffer = stackalloc byte[2];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const ushort value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,63 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
[CLSCompliant(false)]
public class UInt32Tests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const uint value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0, 0, 0} : new byte[] {0, 0, 0, 0x0F};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const uint value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0x0F};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const uint value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian ? new byte[] {0x0F, 0, 0, 0} : new byte[] {0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[4];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const uint value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[4];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const uint value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,67 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.IO;
namespace X10D.Tests.IO;
[TestClass]
[CLSCompliant(false)]
public class UInt64Tests
{
[TestMethod]
public void GetBytes_ReturnsCorrectValue()
{
const ulong value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0x0F, 0, 0, 0, 0, 0, 0, 0}
: new byte[] {0, 0, 0, 0, 0, 0, 0, 0x0F};
CollectionAssert.AreEqual(bytes, value.GetBytes());
}
[TestMethod]
public void GetBytes_ReturnsCorrectValue_WithEndianness()
{
const ulong value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0, 0, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0, 0, 0, 0, 0x0F};
CollectionAssert.AreEqual(littleEndian, value.GetBytes(Endianness.LittleEndian));
CollectionAssert.AreEqual(bigEndian, value.GetBytes(Endianness.BigEndian));
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan()
{
const ulong value = 0x0F;
byte[] bytes = BitConverter.IsLittleEndian
? new byte[] {0x0F, 0, 0, 0, 0, 0, 0, 0}
: new byte[] {0, 0, 0, 0, 0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[8];
Assert.IsTrue(value.TryWriteBytes(buffer));
CollectionAssert.AreEqual(bytes, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsTrue_FillsSpanCorrectly_GivenLargeEnoughSpan_WithEndianness()
{
const ulong value = 0x0F;
byte[] littleEndian = {0x0F, 0, 0, 0, 0, 0, 0, 0};
byte[] bigEndian = {0, 0, 0, 0, 0, 0, 0, 0x0F};
Span<byte> buffer = stackalloc byte[8];
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.LittleEndian));
CollectionAssert.AreEqual(littleEndian, buffer.ToArray());
Assert.IsTrue(value.TryWriteBytes(buffer, Endianness.BigEndian));
CollectionAssert.AreEqual(bigEndian, buffer.ToArray());
}
[TestMethod]
public void TryWriteBytes_ReturnsFalse_GivenSmallSpan()
{
const ulong value = 0x0F;
Span<byte> buffer = stackalloc byte[0];
Assert.IsFalse(value.TryWriteBytes(buffer));
}
}

View File

@ -0,0 +1,96 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class ByteTests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
byte Cast(int i) => (byte)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());
Assert.AreEqual(6, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120, Enumerable.Range(1, 5).Select(Cast).Product());
// 6! will overflow for byte
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
byte Double(int i) => (byte)(i * 2);
Assert.AreEqual(0, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48, Enumerable.Range(1, 3).Product(Double));
// Π_(i=1)^n (2i) will overflow at i=4 for byte
}
[TestMethod]
public void RangeTo_Byte_ShouldYieldCorrectValues()
{
const byte start = 1;
const byte end = 10;
byte current = 1;
foreach (byte value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
[TestMethod]
public void RangeTo_Int16_ShouldYieldCorrectValues()
{
const byte start = 1;
const short end = 10;
short current = 1;
foreach (short value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
[TestMethod]
public void RangeTo_Int32_ShouldYieldCorrectValues()
{
const byte start = 1;
const int end = 10;
int current = 1;
foreach (int value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
[TestMethod]
public void RangeTo_Int64_ShouldYieldCorrectValues()
{
const byte start = 1;
const long end = 10;
long current = 1;
foreach (long value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class DecimalTests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
decimal Cast(int i) => i;
Assert.AreEqual(0m, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1m, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2m, Enumerable.Range(1, 2).Select(Cast).Product());
Assert.AreEqual(6m, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24m, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120m, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720m, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040m, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320m, Enumerable.Range(1, 8).Select(Cast).Product());
Assert.AreEqual(362880m, Enumerable.Range(1, 9).Select(Cast).Product());
Assert.AreEqual(3628800m, Enumerable.Range(1, 10).Select(Cast).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
decimal Double(int i) => i * 2m;
Assert.AreEqual(0m, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2m, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8m, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48m, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384m, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840m, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080m, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120m, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920m, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560m, Enumerable.Range(1, 9).Product(Double));
Assert.AreEqual(3715891200m, Enumerable.Range(1, 10).Product(Double));
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class DoubleTests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
double Cast(int i) => i;
Assert.AreEqual(0.0, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1.0, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2.0, Enumerable.Range(1, 2).Select(Cast).Product());
Assert.AreEqual(6.0, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24.0, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120.0, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720.0, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040.0, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320.0, Enumerable.Range(1, 8).Select(Cast).Product());
Assert.AreEqual(362880.0, Enumerable.Range(1, 9).Select(Cast).Product());
Assert.AreEqual(3628800.0, Enumerable.Range(1, 10).Select(Cast).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
double Double(int i) => i * 2.0;
Assert.AreEqual(0.0, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2.0, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8.0, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48.0, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384.0, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840.0, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080.0, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120.0, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920.0, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560.0, Enumerable.Range(1, 9).Product(Double));
Assert.AreEqual(3715891200.0, Enumerable.Range(1, 10).Product(Double));
}
}

View File

@ -0,0 +1,85 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class Int16Tests
{
[TestMethod]
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());
Assert.AreEqual(6, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040, Enumerable.Range(1, 7).Select(Cast).Product());
// 8! will overflow for short
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
short Double(int i) => (short)(i * 2);
Assert.AreEqual(0, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840, Enumerable.Range(1, 5).Product(Double));
// Π_(i=1)^n (2i) will overflow at i=6 for short
}
[TestMethod]
public void RangeTo_Int16_ShouldYieldCorrectValues()
{
const short start = 1;
const short end = 10;
short current = 1;
foreach (short value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
[TestMethod]
public void RangeTo_Int32_ShouldYieldCorrectValues()
{
const short start = 1;
const int end = 10;
int current = 1;
foreach (int value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
[TestMethod]
public void RangeTo_Int64_ShouldYieldCorrectValues()
{
const short start = 1;
const long end = 10;
long current = 1;
foreach (long value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
}

View File

@ -0,0 +1,73 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
Assert.AreEqual(0, Enumerable.Range(0, 10).Product());
Assert.AreEqual(1, Enumerable.Range(1, 1).Product());
Assert.AreEqual(2, Enumerable.Range(1, 2).Product());
Assert.AreEqual(6, Enumerable.Range(1, 3).Product());
Assert.AreEqual(24, Enumerable.Range(1, 4).Product());
Assert.AreEqual(120, Enumerable.Range(1, 5).Product());
Assert.AreEqual(720, Enumerable.Range(1, 6).Product());
Assert.AreEqual(5040, Enumerable.Range(1, 7).Product());
Assert.AreEqual(40320, Enumerable.Range(1, 8).Product());
Assert.AreEqual(362880, Enumerable.Range(1, 9).Product());
Assert.AreEqual(3628800, Enumerable.Range(1, 10).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
int Double(int i) => i * 2;
Assert.AreEqual(0, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560, Enumerable.Range(1, 9).Product(Double));
// Π_(i=1)^n (2i) will overflow at i=10 for int
}
[TestMethod]
public void RangeTo_Int32_ShouldYieldCorrectValues()
{
const int start = 1;
const int end = 10;
int current = 1;
foreach (int value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
[TestMethod]
public void RangeTo_Int64_ShouldYieldCorrectValues()
{
const int start = 1;
const long end = 10;
long current = 1;
foreach (long value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
}

View File

@ -0,0 +1,59 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
long Cast(int i) => 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());
Assert.AreEqual(6, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320, Enumerable.Range(1, 8).Select(Cast).Product());
Assert.AreEqual(362880, Enumerable.Range(1, 9).Select(Cast).Product());
Assert.AreEqual(3628800, Enumerable.Range(1, 10).Select(Cast).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
long Double(int i) => i * 2;
Assert.AreEqual(0, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560, Enumerable.Range(1, 9).Product(Double));
Assert.AreEqual(3715891200, Enumerable.Range(1, 10).Product(Double));
}
[TestMethod]
public void RangeTo_Int64_ShouldYieldCorrectValues()
{
const long start = 1;
const long end = 10;
long current = 1;
foreach (long value in start.RangeTo(end))
{
Assert.AreEqual(current++, value);
}
Assert.AreEqual(current, end);
}
}

View File

@ -0,0 +1,58 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class ReadOnlySpanTests
{
[TestMethod]
public void AllShouldReturnTrueForEmptySpan()
{
var span = new ReadOnlySpan<int>();
Assert.IsTrue(span.All(x => x > 0));
}
[TestMethod]
public void AllShouldBeCorrect()
{
var span = new ReadOnlySpan<int>(new[] {2, 4, 6, 8, 10});
Assert.IsTrue(span.All(x => x % 2 == 0));
Assert.IsFalse(span.All(x => x % 2 == 1));
}
[TestMethod]
public void AnyShouldReturnFalseForEmptySpan()
{
var span = new ReadOnlySpan<int>();
Assert.IsFalse(span.Any(x => x > 0));
}
[TestMethod]
public void AnyShouldBeCorrect()
{
var span = new ReadOnlySpan<int>(new[] {2, 4, 6, 8, 10});
Assert.IsTrue(span.Any(x => x % 2 == 0));
Assert.IsFalse(span.Any(x => x % 2 == 1));
}
[TestMethod]
public void AllNullPredicateShouldThrow()
{
Assert.ThrowsException<ArgumentNullException>(() =>
{
var span = new ReadOnlySpan<int>();
return span.All(null!);
});
}
[TestMethod]
public void AnyNullPredicateShouldThrow()
{
Assert.ThrowsException<ArgumentNullException>(() =>
{
var span = new ReadOnlySpan<int>();
return span.Any(null!);
});
}
}

View File

@ -0,0 +1,37 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
[CLSCompliant(false)]
public class SByteTests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
sbyte Cast(int i) => (sbyte)i;
Assert.AreEqual(0, Enumerable.Range(0, 10).Product());
Assert.AreEqual(1, Enumerable.Range(1, 1).Product());
Assert.AreEqual(2, Enumerable.Range(1, 2).Product());
Assert.AreEqual(6, Enumerable.Range(1, 3).Product());
Assert.AreEqual(24, Enumerable.Range(1, 4).Product());
Assert.AreEqual(120, Enumerable.Range(1, 5).Product());
// 6! will overflow for sbyte
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
sbyte Double(int i) => (sbyte)(i * 2);
Assert.AreEqual(0, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48, Enumerable.Range(1, 3).Product(Double));
// Π_(i=1)^(n(i*2)) will overflow at i=4 for sbyte
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class SingleTests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
float Cast(int i) => i;
Assert.AreEqual(0f, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1f, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2f, Enumerable.Range(1, 2).Select(Cast).Product());
Assert.AreEqual(6f, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24f, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120f, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720f, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040f, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320f, Enumerable.Range(1, 8).Select(Cast).Product());
Assert.AreEqual(362880f, Enumerable.Range(1, 9).Select(Cast).Product());
Assert.AreEqual(3628800f, Enumerable.Range(1, 10).Select(Cast).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
float Double(int i) => i * 2f;
Assert.AreEqual(0f, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2f, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8f, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48f, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384f, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840f, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080f, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120f, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920f, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560f, Enumerable.Range(1, 9).Product(Double));
Assert.AreEqual(3715891200f, Enumerable.Range(1, 10).Product(Double));
}
}

View File

@ -0,0 +1,58 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
public class SpanTests
{
[TestMethod]
public void AllShouldReturnTrueForEmptySpan()
{
var span = new Span<int>();
Assert.IsTrue(span.All(x => x > 0));
}
[TestMethod]
public void AllShouldBeCorrect()
{
var span = new Span<int>(new[] {2, 4, 6, 8, 10});
Assert.IsTrue(span.All(x => x % 2 == 0));
Assert.IsFalse(span.All(x => x % 2 == 1));
}
[TestMethod]
public void AnyShouldReturnFalseForEmptySpan()
{
var span = new Span<int>();
Assert.IsFalse(span.Any(x => x > 0));
}
[TestMethod]
public void AnyShouldBeCorrect()
{
var span = new Span<int>(new[] {2, 4, 6, 8, 10});
Assert.IsTrue(span.Any(x => x % 2 == 0));
Assert.IsFalse(span.Any(x => x % 2 == 1));
}
[TestMethod]
public void AllNullPredicateShouldThrow()
{
Assert.ThrowsException<ArgumentNullException>(() =>
{
var span = new Span<int>();
return span.All(null!);
});
}
[TestMethod]
public void AnyNullPredicateShouldThrow()
{
Assert.ThrowsException<ArgumentNullException>(() =>
{
var span = new Span<int>();
return span.Any(null!);
});
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
[CLSCompliant(false)]
public class UInt16Tests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
ushort Cast(int i) => (ushort)i;
Assert.AreEqual(0U, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1U, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2U, Enumerable.Range(1, 2).Select(Cast).Product());
Assert.AreEqual(6U, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24U, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120U, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720U, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040U, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320U, Enumerable.Range(1, 8).Select(Cast).Product());
// 9! will overflow for ushort
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
ushort Double(int i) => (ushort)(i * 2);
Assert.AreEqual(0U, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2U, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8U, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48U, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384U, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840U, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080U, Enumerable.Range(1, 6).Product(Double));
// Π_(i=1)^n (2i) will overflow at i=7 for ushort
}
}

View File

@ -0,0 +1,45 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
[CLSCompliant(false)]
public class UInt32Tests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
ulong Cast(int i) => (ulong)i;
Assert.AreEqual(0U, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1U, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2U, Enumerable.Range(1, 2).Select(Cast).Product());
Assert.AreEqual(6U, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24U, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120U, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720U, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040U, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320U, Enumerable.Range(1, 8).Select(Cast).Product());
Assert.AreEqual(362880U, Enumerable.Range(1, 9).Select(Cast).Product());
Assert.AreEqual(3628800U, Enumerable.Range(1, 10).Select(Cast).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
uint Double(int i) => (uint)i * 2;
Assert.AreEqual(0U, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2U, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8U, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48U, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384U, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840U, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080U, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120U, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920U, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560U, Enumerable.Range(1, 9).Product(Double));
Assert.AreEqual(3715891200U, Enumerable.Range(1, 10).Product(Double));
}
}

View File

@ -0,0 +1,45 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Linq;
namespace X10D.Tests.Linq;
[TestClass]
[CLSCompliant(false)]
public class UInt64Tests
{
[TestMethod]
public void ProductShouldBeCorrect()
{
ulong Cast(int i) => (ulong)i;
Assert.AreEqual(0UL, Enumerable.Range(0, 10).Select(Cast).Product());
Assert.AreEqual(1UL, Enumerable.Range(1, 1).Select(Cast).Product());
Assert.AreEqual(2UL, Enumerable.Range(1, 2).Select(Cast).Product());
Assert.AreEqual(6UL, Enumerable.Range(1, 3).Select(Cast).Product());
Assert.AreEqual(24UL, Enumerable.Range(1, 4).Select(Cast).Product());
Assert.AreEqual(120UL, Enumerable.Range(1, 5).Select(Cast).Product());
Assert.AreEqual(720UL, Enumerable.Range(1, 6).Select(Cast).Product());
Assert.AreEqual(5040UL, Enumerable.Range(1, 7).Select(Cast).Product());
Assert.AreEqual(40320UL, Enumerable.Range(1, 8).Select(Cast).Product());
Assert.AreEqual(362880UL, Enumerable.Range(1, 9).Select(Cast).Product());
Assert.AreEqual(3628800UL, Enumerable.Range(1, 10).Select(Cast).Product());
}
[TestMethod]
public void ProductOfDoublesShouldBeCorrect()
{
ulong Double(int i) => (ulong)i * 2;
Assert.AreEqual(0UL, Enumerable.Range(0, 10).Product(Double));
Assert.AreEqual(2UL, Enumerable.Range(1, 1).Product(Double));
Assert.AreEqual(8UL, Enumerable.Range(1, 2).Product(Double));
Assert.AreEqual(48UL, Enumerable.Range(1, 3).Product(Double));
Assert.AreEqual(384UL, Enumerable.Range(1, 4).Product(Double));
Assert.AreEqual(3840UL, Enumerable.Range(1, 5).Product(Double));
Assert.AreEqual(46080UL, Enumerable.Range(1, 6).Product(Double));
Assert.AreEqual(645120UL, Enumerable.Range(1, 7).Product(Double));
Assert.AreEqual(10321920UL, Enumerable.Range(1, 8).Product(Double));
Assert.AreEqual(185794560UL, Enumerable.Range(1, 9).Product(Double));
Assert.AreEqual(3715891200UL, Enumerable.Range(1, 10).Product(Double));
}
}

View File

@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class ByteTests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const byte value = 238;
Assert.AreEqual(4, value.DigitalRoot());
Assert.AreEqual(4, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, ((byte)0).Factorial());
Assert.AreEqual(1L, ((byte)1).Factorial());
Assert.AreEqual(2L, ((byte)2).Factorial());
Assert.AreEqual(6L, ((byte)3).Factorial());
Assert.AreEqual(24L, ((byte)4).Factorial());
Assert.AreEqual(120L, ((byte)5).Factorial());
Assert.AreEqual(720L, ((byte)6).Factorial());
Assert.AreEqual(5040L, ((byte)7).Factorial());
Assert.AreEqual(40320L, ((byte)8).Factorial());
Assert.AreEqual(362880L, ((byte)9).Factorial());
Assert.AreEqual(3628800L, ((byte)10).Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const byte one = 1;
const byte two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const byte one = 1;
const byte two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, ((byte)0).MultiplicativePersistence());
Assert.AreEqual(1, ((byte)10).MultiplicativePersistence());
Assert.AreEqual(2, ((byte)25).MultiplicativePersistence());
Assert.AreEqual(3, ((byte)39).MultiplicativePersistence());
Assert.AreEqual(4, ((byte)77).MultiplicativePersistence());
}
}

View File

@ -0,0 +1,201 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class ComparableTests
{
private class ComparableTestClass : IComparable<ComparableTestClass>
{
public int CompareTo(ComparableTestClass? other)
{
return 0;
}
}
private readonly int _lower = 1;
private readonly int _upper = 10;
private readonly int _value = 5;
[TestMethod]
public void Between_5_1_10_ShouldBeTrue()
{
Assert.IsTrue(_value.Between(_lower, _upper));
}
[TestMethod]
public void Between_1_1_10_ShouldBeFalse()
{
// default option is exclusive
Assert.IsFalse(_lower.Between(_lower, _upper));
}
[TestMethod]
public void Between_1_1_10_Inclusive_ShouldBeTrue()
{
Assert.IsTrue(_lower.Between(_lower, _upper, InclusiveOptions.Inclusive));
Assert.IsTrue(_lower.Between(_lower, _upper, InclusiveOptions.LowerInclusive));
Assert.IsFalse(_lower.Between(_lower, _upper, InclusiveOptions.UpperInclusive));
}
[TestMethod]
public void Between_10_1_10_ShouldBeFalse()
{
// default option is exclusive
Assert.IsFalse(_upper.Between(_lower, _upper));
}
[TestMethod]
public void Between_10_1_10_Inclusive_ShouldBeTrue()
{
Assert.IsTrue(_upper.Between(_lower, _upper, InclusiveOptions.Inclusive));
Assert.IsTrue(_upper.Between(_lower, _upper, InclusiveOptions.UpperInclusive));
Assert.IsFalse(_upper.Between(_lower, _upper, InclusiveOptions.LowerInclusive));
}
[TestMethod]
public void Between_1_10_5_ShouldThrow()
{
Assert.ThrowsException<ArgumentException>(() => _lower.Between(_upper, _value));
}
[TestMethod]
public void Between_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => ((ComparableTestClass?)null)!.Between(nullPointer!, nullPointer!));
}
[TestMethod]
public void Clamp_3_1_5_ShouldBe3()
{
Assert.AreEqual(3, 3.Clamp(1, 5));
}
[TestMethod]
public void Clamp_10_1_5_ShouldBe5()
{
Assert.AreEqual(5, 10.Clamp(1, 5));
}
[TestMethod]
public void Clamp_n_6_5_ShouldThrow()
{
Assert.ThrowsException<ArgumentException>(() => 0.Clamp(6, 5));
}
[TestMethod]
public void GreaterThan_5_6_ShouldBeFalse()
{
Assert.IsFalse(5.GreaterThan(6));
}
[TestMethod]
public void GreaterThan_6_5_ShouldBeTrue()
{
Assert.IsTrue(6.GreaterThan(5));
}
[TestMethod]
public void GreaterThan_5_5_ShouldBeFalse()
{
Assert.IsFalse(5.LessThan(5));
}
[TestMethod]
public void GreaterThan_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => nullPointer!.GreaterThan(nullPointer!));
}
[TestMethod]
public void GreaterThanOrEqualTo_5_5_ShouldBeTrue()
{
Assert.IsTrue(5.GreaterThanOrEqualTo(5));
}
[TestMethod]
public void GreaterThanOrEqualTo_6_5_ShouldBeTrue()
{
Assert.IsTrue(6.GreaterThanOrEqualTo(5));
}
[TestMethod]
public void GreaterThanOrEqualTo_5_6_ShouldBeFalse()
{
Assert.IsFalse(5.GreaterThanOrEqualTo(6));
}
[TestMethod]
public void GreaterThanOrEqualTo_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => nullPointer!.GreaterThanOrEqualTo(nullPointer!));
}
[TestMethod]
public void LessThan_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => nullPointer!.LessThan(nullPointer!));
}
[TestMethod]
public void LessThan_6_5_ShouldBeFalse()
{
Assert.IsFalse(6.LessThan(5));
}
[TestMethod]
public void LessThan_5_6_ShouldBeTrue()
{
Assert.IsTrue(5.LessThan(6));
}
[TestMethod]
public void LessThan_5_5_ShouldBeFalse()
{
Assert.IsFalse(5.LessThan(5));
}
[TestMethod]
public void LessThanOrEqualTo_5_5_ShouldBeTrue()
{
Assert.IsTrue(5.LessThanOrEqualTo(5));
}
[TestMethod]
public void LessThanOrEqualTo_5_6_ShouldBeTrue()
{
Assert.IsTrue(5.LessThanOrEqualTo(6));
}
[TestMethod]
public void LessThanOrEqualTo_6_5_ShouldBeFalse()
{
Assert.IsFalse(6.LessThanOrEqualTo(5));
}
[TestMethod]
public void LessThanOrEqualTo_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => nullPointer!.LessThanOrEqualTo(nullPointer!));
}
[TestMethod]
public void Max_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => nullPointer!.Max(nullPointer!));
}
[TestMethod]
public void Min_Null_ShouldThrow()
{
ComparableTestClass? nullPointer = null;
Assert.ThrowsException<ArgumentNullException>(() => nullPointer!.Min(nullPointer!));
}
}

View File

@ -0,0 +1,122 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class DecimalTests
{
[TestMethod]
public void ComplexSqrt_ShouldBeCorrect_GivenReal()
{
Assert.AreEqual(0.0, 0.0m.ComplexSqrt());
Assert.AreEqual(1.4142135623730951, 2.0m.ComplexSqrt());
Assert.AreEqual(3.0, 9.0m.ComplexSqrt());
Assert.AreEqual(4.0, 16.0m.ComplexSqrt());
Assert.AreEqual(100.0, 10000.0m.ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeImaginary_GivenNegativeValue()
{
Assert.AreEqual(new Complex(0, 1), (-1.0m).ComplexSqrt());
Assert.AreEqual(new Complex(0, 1.4142135623730951), (-2.0m).ComplexSqrt());
Assert.AreEqual(new Complex(0, 3.0), (-9.0m).ComplexSqrt());
Assert.AreEqual(new Complex(0, 4.0), (-16.0m).ComplexSqrt());
}
[TestMethod]
public void IsEven_ShouldBeFalse_GivenOddNumber()
{
Assert.IsFalse((-3.0m).IsEven());
Assert.IsFalse((-1.0m).IsEven());
Assert.IsFalse(1.0m.IsEven());
Assert.IsFalse(3.0m.IsEven());
}
[TestMethod]
public void IsEven_ShouldBeTrue_GivenOddNumber()
{
Assert.IsTrue((-4.0m).IsEven());
Assert.IsTrue((-2.0m).IsEven());
Assert.IsTrue(0.0m.IsEven());
Assert.IsTrue(2.0m.IsEven());
Assert.IsTrue(4.0m.IsEven());
}
[TestMethod]
public void IsOdd_ShouldBeFalse_GivenEvenNumber()
{
Assert.IsFalse((-4.0m).IsOdd());
Assert.IsFalse((-2.0m).IsOdd());
Assert.IsFalse(0.0m.IsOdd());
Assert.IsFalse(2.0m.IsOdd());
Assert.IsFalse(4.0m.IsOdd());
}
[TestMethod]
public void IsOdd_ShouldBeTrue_GivenOddNumber()
{
Assert.IsTrue((-3.0m).IsOdd());
Assert.IsTrue((-1.0m).IsOdd());
Assert.IsTrue(1.0m.IsOdd());
Assert.IsTrue(3.0m.IsOdd());
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger()
{
Assert.AreEqual(4.0m, 3.5m.Round());
Assert.AreEqual(7.0m, 6.8m.Round());
Assert.AreEqual(7.0m, 7.2m.Round());
}
[TestMethod]
public void Round_ShouldRoundToNearestMultiple()
{
Assert.AreEqual(5.0m, 3.5m.Round(5));
Assert.AreEqual(5.0m, 7.0m.Round(5));
Assert.AreEqual(10.0m, 7.5m.Round(5));
}
[TestMethod]
public void Sign_ShouldBeMinus1_GivenNegative()
{
Assert.AreEqual(-1, -1.0m.Sign());
Assert.AreEqual(-1, -2.0m.Sign());
Assert.AreEqual(-1, -3.0m.Sign());
}
[TestMethod]
public void Sign_ShouldBe0_Given0()
{
Assert.AreEqual(0, 0.0m.Sign());
}
[TestMethod]
public void Sign_ShouldBe1_GivenPositive()
{
Assert.AreEqual(1, 1.0m.Sign());
Assert.AreEqual(1, 2.0m.Sign());
Assert.AreEqual(1, 3.0m.Sign());
}
[TestMethod]
public void Sqrt_ShouldBeCorrect_GivenValue()
{
Assert.AreEqual(0.0m, 0.0m.Sqrt());
Assert.AreEqual(1.4142135623730950488016887242m, 2.0m.Sqrt());
Assert.AreEqual(3.0m, 9.0m.Sqrt());
Assert.AreEqual(4.0m, 16.0m.Sqrt());
Assert.AreEqual(100.0m, 10000.0m.Sqrt());
}
[TestMethod]
public void Sqrt_ShouldThrow_GivenNegativeValue()
{
Assert.ThrowsException<ArgumentException>(() => (-1.0m).Sqrt());
Assert.ThrowsException<ArgumentException>(() => (-2.0m).Sqrt());
Assert.ThrowsException<ArgumentException>(() => (-3.0m).Sqrt());
}
}

View File

@ -0,0 +1,242 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class DoubleTests
{
[TestMethod]
public void DegreesToRadians_ShouldBeCorrect()
{
Assert.AreEqual(System.Math.PI, 180.0.DegreesToRadians(), 1e-6);
Assert.AreEqual(System.Math.PI * 1.5, 270.0.DegreesToRadians(), 1e-6);
Assert.AreEqual(0.0, 0.0.DegreesToRadians(), 1e-6);
Assert.AreEqual(0.017453292519943295, 1.0.DegreesToRadians(), 1e-6);
Assert.AreEqual(0.10471975511965978, 6.0.DegreesToRadians(), 1e-6);
Assert.AreEqual(0.20943951023931956, 12.0.DegreesToRadians(), 1e-6);
}
[TestMethod]
public void RadiansToDegrees_ShouldBeCorrect()
{
Assert.AreEqual(180.0, System.Math.PI.RadiansToDegrees(), 1e-6);
Assert.AreEqual(360.0, (2.0 * System.Math.PI).RadiansToDegrees(), 1e-6);
Assert.AreEqual(0.0, 0.0.RadiansToDegrees(), 1e-6);
Assert.AreEqual(1.0, 0.017453292519943295.RadiansToDegrees(), 1e-6);
Assert.AreEqual(6.000000000000001, 0.10471975511965978.RadiansToDegrees(), 1e-6); // rounding errors are fun
Assert.AreEqual(12.0, 0.20943951023931953.RadiansToDegrees(), 1e-6);
}
[TestMethod]
public void ComplexSqrt_ShouldBeCorrect_GivenReal()
{
Assert.AreEqual(0.0, 0.0.ComplexSqrt());
Assert.AreEqual(1.4142135623730951, 2.0.ComplexSqrt());
Assert.AreEqual(3.0, 9.0.ComplexSqrt());
Assert.AreEqual(4.0, 16.0.ComplexSqrt());
Assert.AreEqual(100.0, 10000.0.ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeImaginary_GivenNegativeValue()
{
Assert.AreEqual(new Complex(0, 1), (-1.0).ComplexSqrt());
Assert.AreEqual(new Complex(0, 1.4142135623730951), (-2.0).ComplexSqrt());
Assert.AreEqual(new Complex(0, 3.0), (-9.0).ComplexSqrt());
Assert.AreEqual(new Complex(0, 4.0), (-16.0).ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeComplexInfinity_GivenInfinity()
{
Assert.AreEqual(Complex.Infinity, double.NegativeInfinity.ComplexSqrt());
Assert.AreEqual(Complex.Infinity, double.PositiveInfinity.ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeNaN_GivenNaN()
{
Assert.AreEqual(Complex.NaN, double.NaN.ComplexSqrt());
}
[TestMethod]
public void IsEven_ShouldBeFalse_GivenOddNumber()
{
Assert.IsFalse((-3.0).IsEven());
Assert.IsFalse((-1.0).IsEven());
Assert.IsFalse(1.0.IsEven());
Assert.IsFalse(3.0.IsEven());
}
[TestMethod]
public void IsEven_ShouldBeTrue_GivenOddNumber()
{
Assert.IsTrue((-4.0).IsEven());
Assert.IsTrue((-2.0).IsEven());
Assert.IsTrue(0.0.IsEven());
Assert.IsTrue(2.0.IsEven());
Assert.IsTrue(4.0.IsEven());
}
[TestMethod]
public void IsOdd_ShouldBeFalse_GivenEvenNumber()
{
Assert.IsFalse((-4.0).IsOdd());
Assert.IsFalse((-2.0).IsOdd());
Assert.IsFalse(0.0.IsOdd());
Assert.IsFalse(2.0.IsOdd());
Assert.IsFalse(4.0.IsOdd());
}
[TestMethod]
public void IsOdd_ShouldBeTrue_GivenOddNumber()
{
Assert.IsTrue((-3.0).IsOdd());
Assert.IsTrue((-1.0).IsOdd());
Assert.IsTrue(1.0.IsOdd());
Assert.IsTrue(3.0.IsOdd());
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger()
{
Assert.AreEqual(4.0, 3.5.Round(), 1e-6);
Assert.AreEqual(7.0, 6.8.Round(), 1e-6);
Assert.AreEqual(7.0, 7.2.Round(), 1e-6);
}
[TestMethod]
public void Round_ShouldRoundToNearestMultiple()
{
Assert.AreEqual(5.0, 3.5.Round(5), 1e-6);
Assert.AreEqual(5.0, 7.0.Round(5), 1e-6);
Assert.AreEqual(10.0, 7.5.Round(5), 1e-6);
}
[TestMethod]
public void Sign_ShouldBeMinus1_GivenNegative()
{
Assert.AreEqual(-1, -1.0.Sign());
Assert.AreEqual(-1, -2.0.Sign());
Assert.AreEqual(-1, -3.0.Sign());
}
[TestMethod]
public void Sign_ShouldBe0_Given0()
{
Assert.AreEqual(0, 0.0.Sign());
}
[TestMethod]
public void Sign_ShouldBe1_GivenPositive()
{
Assert.AreEqual(1, 1.0.Sign());
Assert.AreEqual(1, 2.0.Sign());
Assert.AreEqual(1, 3.0.Sign());
}
[TestMethod]
public void Sqrt_ShouldBeCorrect_GivenValue()
{
Assert.AreEqual(0.0, 0.0.Sqrt(), 1e-6);
Assert.AreEqual(1.414213562373095, 2.0.Sqrt(), 1e-6);
Assert.AreEqual(3.0, 9.0.Sqrt(), 1e-6);
Assert.AreEqual(4.0, 16.0.Sqrt(), 1e-6);
Assert.AreEqual(100.0, 10000.0.Sqrt(), 1e-6);
}
[TestMethod]
public void Sqrt_ShouldBeNaN_GivenNaN()
{
Assert.AreEqual(double.NaN, double.NaN.Sqrt());
}
[TestMethod]
public void Sqrt_ShouldBeNaN_GivenNegativeValue()
{
Assert.AreEqual(double.NaN, (-1.0).Sqrt());
Assert.AreEqual(double.NaN, (-2.0).Sqrt());
Assert.AreEqual(double.NaN, (-3.0).Sqrt());
Assert.AreEqual(double.NaN, double.NegativeInfinity.Sqrt());
}
[TestMethod]
public void Sqrt_ShouldBePositiveInfinity_GivenPositiveInfinity()
{
Assert.AreEqual(double.PositiveInfinity, double.PositiveInfinity.Sqrt());
}
[TestMethod]
public void Acos_ShouldBeCorrect()
{
Assert.AreEqual(1.0471975511965979, 0.5.Acos(), 1e-6);
}
[TestMethod]
public void Acosh_ShouldBeCorrect()
{
Assert.AreEqual(0.9624236501192069, 1.5.Acosh(), 1e-6);
}
[TestMethod]
public void Asin_ShouldBeCorrect()
{
Assert.AreEqual(0.5235987755982989, 0.5.Asin(), 1e-6);
}
[TestMethod]
public void Asinh_ShouldBeCorrect()
{
Assert.AreEqual(1.1947632172871094, 1.5.Asinh(), 1e-6);
}
[TestMethod]
public void Atan_ShouldBeCorrect()
{
Assert.AreEqual(0.4636476090008061, 0.5.Atan(), 1e-6);
}
[TestMethod]
public void Atanh_ShouldBeCorrect()
{
Assert.AreEqual(0.5493061443340549, 0.5.Atanh(), 1e-6);
}
[TestMethod]
public void Cos_ShouldBeCorrect()
{
Assert.AreEqual(0.8775825618903728, 0.5.Cos(), 1e-6);
}
[TestMethod]
public void Cosh_ShouldBeCorrect()
{
Assert.AreEqual(2.352409615243247, 1.5.Cosh(), 1e-6);
}
[TestMethod]
public void Sin_ShouldBeCorrect()
{
Assert.AreEqual(0.479425538604203, 0.5.Sin(), 1e-6);
}
[TestMethod]
public void Sinh_ShouldBeCorrect()
{
Assert.AreEqual(2.1292794550948173, 1.5.Sinh(), 1e-6);
}
[TestMethod]
public void Tan_ShouldBeCorrect()
{
Assert.AreEqual(0.5463024898437905, 0.5.Tan(), 1e-6);
}
[TestMethod]
public void Tanh_ShouldBeCorrect()
{
Assert.AreEqual(0.46211715726000974, 0.5.Tanh(), 1e-6);
}
}

View File

@ -0,0 +1,80 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const short value = 238;
Assert.AreEqual(4, value.DigitalRoot());
Assert.AreEqual(4, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, ((short)0).Factorial());
Assert.AreEqual(1L, ((short)1).Factorial());
Assert.AreEqual(2L, ((short)2).Factorial());
Assert.AreEqual(6L, ((short)3).Factorial());
Assert.AreEqual(24L, ((short)4).Factorial());
Assert.AreEqual(120L, ((short)5).Factorial());
Assert.AreEqual(720L, ((short)6).Factorial());
Assert.AreEqual(5040L, ((short)7).Factorial());
Assert.AreEqual(40320L, ((short)8).Factorial());
Assert.AreEqual(362880L, ((short)9).Factorial());
Assert.AreEqual(3628800L, ((short)10).Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const short one = 1;
const short two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const short one = 1;
const short two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, ((short)0).MultiplicativePersistence());
Assert.AreEqual(1, ((short)10).MultiplicativePersistence());
Assert.AreEqual(2, ((short)25).MultiplicativePersistence());
Assert.AreEqual(3, ((short)39).MultiplicativePersistence());
Assert.AreEqual(4, ((short)77).MultiplicativePersistence());
Assert.AreEqual(5, ((short)679).MultiplicativePersistence());
Assert.AreEqual(6, ((short)6788).MultiplicativePersistence());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => ((short)-1).Factorial());
}
[TestMethod]
public void SignShouldBeCorrect()
{
const short one = 1;
const short zero = 0;
Assert.AreEqual(one, one.Sign());
Assert.AreEqual(zero, zero.Sign());
Assert.AreEqual(-one, (-one).Sign());
}
}

View File

@ -0,0 +1,83 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const int value = 238;
Assert.AreEqual(4, value.DigitalRoot());
Assert.AreEqual(4, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, 0.Factorial());
Assert.AreEqual(1L, 1.Factorial());
Assert.AreEqual(2L, 2.Factorial());
Assert.AreEqual(6L, 3.Factorial());
Assert.AreEqual(24L, 4.Factorial());
Assert.AreEqual(120L, 5.Factorial());
Assert.AreEqual(720L, 6.Factorial());
Assert.AreEqual(5040L, 7.Factorial());
Assert.AreEqual(40320L, 8.Factorial());
Assert.AreEqual(362880L, 9.Factorial());
Assert.AreEqual(3628800L, 10.Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const int one = 1;
const int two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const int one = 1;
const int two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, 0.MultiplicativePersistence());
Assert.AreEqual(1, 10.MultiplicativePersistence());
Assert.AreEqual(2, 25.MultiplicativePersistence());
Assert.AreEqual(3, 39.MultiplicativePersistence());
Assert.AreEqual(4, 77.MultiplicativePersistence());
Assert.AreEqual(5, 679.MultiplicativePersistence());
Assert.AreEqual(6, 6788.MultiplicativePersistence());
Assert.AreEqual(7, 68889.MultiplicativePersistence());
Assert.AreEqual(8, 2677889.MultiplicativePersistence());
Assert.AreEqual(9, 26888999.MultiplicativePersistence());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => (-1).Factorial());
}
[TestMethod]
public void SignShouldBeCorrect()
{
const int one = 1;
const int zero = 0;
Assert.AreEqual(one, one.Sign());
Assert.AreEqual(zero, zero.Sign());
Assert.AreEqual(-one, (-one).Sign());
}
}

View File

@ -0,0 +1,85 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const long value = 238;
Assert.AreEqual(4, value.DigitalRoot());
Assert.AreEqual(4, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, 0L.Factorial());
Assert.AreEqual(1L, 1L.Factorial());
Assert.AreEqual(2L, 2L.Factorial());
Assert.AreEqual(6L, 3L.Factorial());
Assert.AreEqual(24L, 4L.Factorial());
Assert.AreEqual(120L, 5L.Factorial());
Assert.AreEqual(720L, 6L.Factorial());
Assert.AreEqual(5040L, 7L.Factorial());
Assert.AreEqual(40320L, 8L.Factorial());
Assert.AreEqual(362880L, 9L.Factorial());
Assert.AreEqual(3628800L, 10L.Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const long one = 1;
const long two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const long one = 1;
const long two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, 0L.MultiplicativePersistence());
Assert.AreEqual(1, 10L.MultiplicativePersistence());
Assert.AreEqual(2, 25L.MultiplicativePersistence());
Assert.AreEqual(3, 39L.MultiplicativePersistence());
Assert.AreEqual(4, 77L.MultiplicativePersistence());
Assert.AreEqual(5, 679L.MultiplicativePersistence());
Assert.AreEqual(6, 6788L.MultiplicativePersistence());
Assert.AreEqual(7, 68889L.MultiplicativePersistence());
Assert.AreEqual(8, 2677889L.MultiplicativePersistence());
Assert.AreEqual(9, 26888999L.MultiplicativePersistence());
Assert.AreEqual(10, 3778888999L.MultiplicativePersistence());
Assert.AreEqual(11, 277777788888899L.MultiplicativePersistence());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => (-1L).Factorial());
}
[TestMethod]
public void SignShouldBeCorrect()
{
const long one = 1;
const long zero = 0;
Assert.AreEqual(one, one.Sign());
Assert.AreEqual(zero, zero.Sign());
Assert.AreEqual(-one, (-one).Sign());
}
}

View File

@ -0,0 +1,154 @@
using System.Reflection;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class IsPrimeTests
{
private IReadOnlyList<int> _primeNumbers = ArraySegment<int>.Empty;
[TestInitialize]
public void Initialize()
{
_primeNumbers = LoadPrimes();
Assert.AreEqual(1000, _primeNumbers.Count);
}
[TestMethod]
public void First1000Primes()
{
for (var index = 0; index < _primeNumbers.Count; index++)
{
int value = _primeNumbers[index];
Assert.IsTrue(value.IsPrime());
Assert.IsTrue(((long)value).IsPrime());
if (value is >= byte.MinValue and <= byte.MaxValue)
{
Assert.IsTrue(((byte)value).IsPrime());
}
if (value is >= short.MinValue and <= short.MaxValue)
{
Assert.IsTrue(((short)value).IsPrime());
}
if (value is >= byte.MinValue and <= byte.MaxValue)
{
Assert.IsTrue(((byte)value).IsPrime());
}
if (value is >= ushort.MinValue and <= ushort.MaxValue)
{
Assert.IsTrue(((ushort)value).IsPrime());
}
if (value is >= sbyte.MinValue and <= sbyte.MaxValue)
{
Assert.IsTrue(((sbyte)value).IsPrime());
}
if (value >= 0)
{
Assert.IsTrue(((uint)value).IsPrime());
Assert.IsTrue(((ulong)value).IsPrime());
}
}
}
[TestMethod]
public void Negatives()
{
for (var value = short.MinValue; value < 0; value++)
{
Assert.IsFalse(value.IsPrime());
Assert.IsFalse(((int)value).IsPrime());
Assert.IsFalse(((long)value).IsPrime());
if (value is >= sbyte.MinValue and <= sbyte.MaxValue)
{
Assert.IsFalse(((sbyte)value).IsPrime());
}
}
}
[TestMethod]
public void LessThan2()
{
for (var value = 0; value < 2; value++)
{
Assert.IsFalse(value.IsPrime());
Assert.IsFalse(((byte)value).IsPrime());
Assert.IsFalse(((short)value).IsPrime());
Assert.IsFalse(((long)value).IsPrime());
Assert.IsFalse(((sbyte)value).IsPrime());
Assert.IsFalse(((ushort)value).IsPrime());
Assert.IsFalse(((uint)value).IsPrime());
Assert.IsFalse(((ulong)value).IsPrime());
}
}
[TestMethod]
public void ZeroTo7919()
{
for (var value = 0; value < 7920; value++)
{
bool expected = _primeNumbers.Contains(value);
Assert.AreEqual(expected, ((short)value).IsPrime());
Assert.AreEqual(expected, value.IsPrime());
Assert.AreEqual(expected, ((long)value).IsPrime());
Assert.AreEqual(expected, ((ushort)value).IsPrime());
Assert.AreEqual(expected, ((uint)value).IsPrime());
Assert.AreEqual(expected, ((ulong)value).IsPrime());
}
}
[TestMethod]
public void ZeroToByteMaxValue()
{
for (byte value = 0; value < byte.MaxValue; value++)
{
bool expected = _primeNumbers.Contains(value);
Assert.AreEqual(expected, value.IsPrime());
Assert.AreEqual(expected, ((short)value).IsPrime());
Assert.AreEqual(expected, ((int)value).IsPrime());
Assert.AreEqual(expected, ((long)value).IsPrime());
Assert.AreEqual(expected, ((ushort)value).IsPrime());
Assert.AreEqual(expected, ((uint)value).IsPrime());
Assert.AreEqual(expected, ((ulong)value).IsPrime());
if (value < sbyte.MaxValue)
{
Assert.AreEqual(expected, ((sbyte)value).IsPrime());
}
}
}
private static IReadOnlyList<int> LoadPrimes()
{
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("X10D.Tests.1000primes.txt");
Assert.IsNotNull(stream);
using var reader = new StreamReader(stream, Encoding.UTF8);
var primes = new List<int>();
while (reader.ReadLine() is { } line)
{
if (int.TryParse(line, out int prime))
{
primes.Add(prime);
}
}
return primes.AsReadOnly();
}
}

View File

@ -0,0 +1,79 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class SByteTests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const sbyte value = 127; // sbyte.MaxValue. can't use 238 like the other tests
Assert.AreEqual(1, value.DigitalRoot());
Assert.AreEqual(1, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1L, ((sbyte)0).Factorial());
Assert.AreEqual(1L, ((sbyte)1).Factorial());
Assert.AreEqual(2L, ((sbyte)2).Factorial());
Assert.AreEqual(6L, ((sbyte)3).Factorial());
Assert.AreEqual(24L, ((sbyte)4).Factorial());
Assert.AreEqual(120L, ((sbyte)5).Factorial());
Assert.AreEqual(720L, ((sbyte)6).Factorial());
Assert.AreEqual(5040L, ((sbyte)7).Factorial());
Assert.AreEqual(40320L, ((sbyte)8).Factorial());
Assert.AreEqual(362880L, ((sbyte)9).Factorial());
Assert.AreEqual(3628800L, ((sbyte)10).Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const sbyte one = 1;
const sbyte two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const sbyte one = 1;
const sbyte two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, ((sbyte)0).MultiplicativePersistence());
Assert.AreEqual(1, ((sbyte)10).MultiplicativePersistence());
Assert.AreEqual(2, ((sbyte)25).MultiplicativePersistence());
Assert.AreEqual(3, ((sbyte)39).MultiplicativePersistence());
Assert.AreEqual(4, ((sbyte)77).MultiplicativePersistence());
}
[TestMethod]
public void NegativeFactorialShouldThrow()
{
Assert.ThrowsException<ArithmeticException>(() => ((sbyte)-1).Factorial());
}
[TestMethod]
public void SignShouldBeCorrect()
{
const sbyte one = 1;
const sbyte zero = 0;
Assert.AreEqual(one, one.Sign());
Assert.AreEqual(zero, zero.Sign());
Assert.AreEqual(-one, (-one).Sign());
}
}

View File

@ -0,0 +1,242 @@
using System.Numerics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
public class SingleTests
{
[TestMethod]
public void DegreesToRadians_ShouldBeCorrect()
{
Assert.AreEqual(MathF.PI, 180.0f.DegreesToRadians(), 1e-6f);
Assert.AreEqual(MathF.PI * 1.5f, 270.0f.DegreesToRadians(), 1e-6f);
Assert.AreEqual(0.0f, 0.0f.DegreesToRadians(), 1e-6f);
Assert.AreEqual(0.017453292f, 1.0f.DegreesToRadians(), 1e-6f);
Assert.AreEqual(0.10471976f, 6.0f.DegreesToRadians(), 1e-6f);
Assert.AreEqual(0.20943952f, 12.0f.DegreesToRadians(), 1e-6f);
}
[TestMethod]
public void RadiansToDegrees_ShouldBeCorrect()
{
Assert.AreEqual(180.0f, MathF.PI.RadiansToDegrees(), 1e-6f);
Assert.AreEqual(270.0f, (MathF.PI * 1.5f).RadiansToDegrees(), 1e-6f);
Assert.AreEqual(0.0, 0.0f.RadiansToDegrees(), 1e-6f);
Assert.AreEqual(0.99999994f, 0.017453292f.RadiansToDegrees(), 1e-6f); // rounding errors are fun
Assert.AreEqual(6.0f, 0.10471976f.RadiansToDegrees(), 1e-6f);
Assert.AreEqual(12.0f, 0.20943952f.RadiansToDegrees(), 1e-6f);
}
[TestMethod]
public void ComplexSqrt_ShouldBeCorrect_GivenReal()
{
Assert.AreEqual(0.0f, 0.0f.ComplexSqrt());
Assert.AreEqual(1.4142135f, 2.0f.ComplexSqrt());
Assert.AreEqual(3.0f, 9.0f.ComplexSqrt());
Assert.AreEqual(4.0f, 16.0f.ComplexSqrt());
Assert.AreEqual(100.0f, 10000.0f.ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeImaginary_GivenNegativeValue()
{
Assert.AreEqual(new Complex(0, 1), (-1.0f).ComplexSqrt());
Assert.AreEqual(new Complex(0, 1.4142135f), (-2.0f).ComplexSqrt());
Assert.AreEqual(new Complex(0, 3.0f), (-9.0f).ComplexSqrt());
Assert.AreEqual(new Complex(0, 4.0f), (-16.0f).ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeComplexInfinity_GivenInfinity()
{
Assert.AreEqual(Complex.Infinity, float.NegativeInfinity.ComplexSqrt());
Assert.AreEqual(Complex.Infinity, float.PositiveInfinity.ComplexSqrt());
}
[TestMethod]
public void ComplexSqrt_ShouldBeNaN_GivenNaN()
{
Assert.AreEqual(Complex.NaN, float.NaN.ComplexSqrt());
}
[TestMethod]
public void IsEven_ShouldBeFalse_GivenOddNumber()
{
Assert.IsFalse((-3.0f).IsEven());
Assert.IsFalse((-1.0f).IsEven());
Assert.IsFalse(1.0f.IsEven());
Assert.IsFalse(3.0f.IsEven());
}
[TestMethod]
public void IsEven_ShouldBeTrue_GivenOddNumber()
{
Assert.IsTrue((-4.0f).IsEven());
Assert.IsTrue((-2.0f).IsEven());
Assert.IsTrue(0.0f.IsEven());
Assert.IsTrue(2.0f.IsEven());
Assert.IsTrue(4.0f.IsEven());
}
[TestMethod]
public void IsOdd_ShouldBeFalse_GivenEvenNumber()
{
Assert.IsFalse((-4.0f).IsOdd());
Assert.IsFalse((-2.0f).IsOdd());
Assert.IsFalse(0.0f.IsOdd());
Assert.IsFalse(2.0f.IsOdd());
Assert.IsFalse(4.0f.IsOdd());
}
[TestMethod]
public void IsOdd_ShouldBeTrue_GivenOddNumber()
{
Assert.IsTrue((-3.0f).IsOdd());
Assert.IsTrue((-1.0f).IsOdd());
Assert.IsTrue(1.0f.IsOdd());
Assert.IsTrue(3.0f.IsOdd());
}
[TestMethod]
public void Round_ShouldRoundToNearestInteger()
{
Assert.AreEqual(4.0f, 3.5f.Round(), 1e-6f);
Assert.AreEqual(7.0f, 6.8f.Round(), 1e-6f);
Assert.AreEqual(7.0f, 7.2f.Round(), 1e-6f);
}
[TestMethod]
public void Round_ShouldRoundToNearestMultiple()
{
Assert.AreEqual(5.0f, 3.5f.Round(5), 1e-6f);
Assert.AreEqual(5.0f, 7.0f.Round(5), 1e-6f);
Assert.AreEqual(10.0f, 7.5f.Round(5), 1e-6f);
}
[TestMethod]
public void Sign_ShouldBeMinus1_GivenNegative()
{
Assert.AreEqual(-1, -1.0f.Sign());
Assert.AreEqual(-1, -2.0f.Sign());
Assert.AreEqual(-1, -3.0f.Sign());
}
[TestMethod]
public void Sign_ShouldBe0_Given0()
{
Assert.AreEqual(0, 0.0f.Sign());
}
[TestMethod]
public void Sign_ShouldBe1_GivenPositive()
{
Assert.AreEqual(1, 1.0f.Sign());
Assert.AreEqual(1, 2.0f.Sign());
Assert.AreEqual(1, 3.0f.Sign());
}
[TestMethod]
public void Sqrt_ShouldBeCorrect_GivenValue()
{
Assert.AreEqual(0.0f, 0.0f.Sqrt(), 1e-6f);
Assert.AreEqual(1.4142135f, 2.0f.Sqrt(), 1e-6f);
Assert.AreEqual(3.0f, 9.0f.Sqrt(), 1e-6f);
Assert.AreEqual(4.0f, 16.0f.Sqrt(), 1e-6f);
Assert.AreEqual(100.0f, 10000.0f.Sqrt(), 1e-6f);
}
[TestMethod]
public void Sqrt_ShouldBeNaN_GivenNaN()
{
Assert.AreEqual(float.NaN, float.NaN.Sqrt());
}
[TestMethod]
public void Sqrt_ShouldBeNaN_GivenNegativeValue()
{
Assert.AreEqual(float.NaN, (-1.0f).Sqrt());
Assert.AreEqual(float.NaN, (-2.0f).Sqrt());
Assert.AreEqual(float.NaN, (-3.0f).Sqrt());
Assert.AreEqual(float.NaN, float.NegativeInfinity.Sqrt());
}
[TestMethod]
public void Sqrt_ShouldBePositiveInfinity_GivenPositiveInfinity()
{
Assert.AreEqual(float.PositiveInfinity, float.PositiveInfinity.Sqrt());
}
[TestMethod]
public void Acos_ShouldBeCorrect()
{
Assert.AreEqual(1.0471975803375244f, 0.5f.Acos(), 1e-6f);
}
[TestMethod]
public void Acosh_ShouldBeCorrect()
{
Assert.AreEqual(0.9624236822128296f, 1.5f.Acosh(), 1e-6f);
}
[TestMethod]
public void Asin_ShouldBeCorrect()
{
Assert.AreEqual(0.5235987901687622f, 0.5f.Asin(), 1e-6f);
}
[TestMethod]
public void Asinh_ShouldBeCorrect()
{
Assert.AreEqual(1.19476318359375f, 1.5f.Asinh(), 1e-6f);
}
[TestMethod]
public void Atan_ShouldBeCorrect()
{
Assert.AreEqual(0.46364760398864746, 0.5f.Atan(), 1e-6f);
}
[TestMethod]
public void Atanh_ShouldBeCorrect()
{
Assert.AreEqual(0.5493061542510986f, 0.5f.Atanh(), 1e-6f);
}
[TestMethod]
public void Cos_ShouldBeCorrect()
{
Assert.AreEqual(0.8775825500488281f, 0.5f.Cos(), 1e-6f);
}
[TestMethod]
public void Cosh_ShouldBeCorrect()
{
Assert.AreEqual(2.352409601211548f, 1.5f.Cosh(), 1e-6f);
}
[TestMethod]
public void Sin_ShouldBeCorrect()
{
Assert.AreEqual(0.4794255495071411, 0.5f.Sin(), 1e-6f);
}
[TestMethod]
public void Sinh_ShouldBeCorrect()
{
Assert.AreEqual(2.129279375076294f, 1.5f.Sinh(), 1e-6f);
}
[TestMethod]
public void Tan_ShouldBeCorrect()
{
Assert.AreEqual(0.4794255495071411f, 0.5f.Tan(), 1e-6f);
}
[TestMethod]
public void Tanh_ShouldBeCorrect()
{
Assert.AreEqual(0.46211716532707214f, 0.5f.Tanh(), 1e-6f);
}
}

View File

@ -0,0 +1,65 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class UInt16Tests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const ushort value = 238;
Assert.AreEqual(4, value.DigitalRoot());
Assert.AreEqual(4, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1UL, ((ushort)0).Factorial());
Assert.AreEqual(1UL, ((ushort)1).Factorial());
Assert.AreEqual(2UL, ((ushort)2).Factorial());
Assert.AreEqual(6UL, ((ushort)3).Factorial());
Assert.AreEqual(24UL, ((ushort)4).Factorial());
Assert.AreEqual(120UL, ((ushort)5).Factorial());
Assert.AreEqual(720UL, ((ushort)6).Factorial());
Assert.AreEqual(5040UL, ((ushort)7).Factorial());
Assert.AreEqual(40320UL, ((ushort)8).Factorial());
Assert.AreEqual(362880UL, ((ushort)9).Factorial());
Assert.AreEqual(3628800UL, ((ushort)10).Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const ushort one = 1;
const ushort two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const ushort one = 1;
const ushort two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, ((ushort)0).MultiplicativePersistence());
Assert.AreEqual(1, ((ushort)10).MultiplicativePersistence());
Assert.AreEqual(2, ((ushort)25).MultiplicativePersistence());
Assert.AreEqual(3, ((ushort)39).MultiplicativePersistence());
Assert.AreEqual(4, ((ushort)77).MultiplicativePersistence());
Assert.AreEqual(5, ((ushort)679).MultiplicativePersistence());
Assert.AreEqual(6, ((ushort)6788).MultiplicativePersistence());
}
}

View File

@ -0,0 +1,69 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class UInt32Tests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const uint value = 238;
Assert.AreEqual(4U, value.DigitalRoot());
Assert.AreEqual(4U, (-value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1UL, 0U.Factorial());
Assert.AreEqual(1UL, 1U.Factorial());
Assert.AreEqual(2UL, 2U.Factorial());
Assert.AreEqual(6UL, 3U.Factorial());
Assert.AreEqual(24UL, 4U.Factorial());
Assert.AreEqual(120UL, 5U.Factorial());
Assert.AreEqual(720UL, 6U.Factorial());
Assert.AreEqual(5040UL, 7U.Factorial());
Assert.AreEqual(40320UL, 8U.Factorial());
Assert.AreEqual(362880UL, 9U.Factorial());
Assert.AreEqual(3628800UL, 10U.Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const uint one = 1;
const uint two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const uint one = 1;
const uint two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, 0U.MultiplicativePersistence());
Assert.AreEqual(1, 10U.MultiplicativePersistence());
Assert.AreEqual(2, 25U.MultiplicativePersistence());
Assert.AreEqual(3, 39U.MultiplicativePersistence());
Assert.AreEqual(4, 77U.MultiplicativePersistence());
Assert.AreEqual(5, 679U.MultiplicativePersistence());
Assert.AreEqual(6, 6788U.MultiplicativePersistence());
Assert.AreEqual(7, 68889U.MultiplicativePersistence());
Assert.AreEqual(8, 2677889U.MultiplicativePersistence());
Assert.AreEqual(9, 26888999U.MultiplicativePersistence());
Assert.AreEqual(10, 3778888999U.MultiplicativePersistence());
}
}

View File

@ -0,0 +1,74 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Math;
namespace X10D.Tests.Math;
[TestClass]
[CLSCompliant(false)]
public class UInt64Tests
{
[TestMethod]
public void DigitalRootShouldBeCorrect()
{
const ulong value = 238;
Assert.AreEqual(4U, value.DigitalRoot());
// -ulong operator not defined because it might exceed long.MinValue,
// so instead, cast to long and then negate.
// HAX.
Assert.AreEqual(4U, (-(long)value).DigitalRoot());
}
[TestMethod]
public void FactorialShouldBeCorrect()
{
Assert.AreEqual(1UL, 0UL.Factorial());
Assert.AreEqual(1UL, 1UL.Factorial());
Assert.AreEqual(2UL, 2UL.Factorial());
Assert.AreEqual(6UL, 3UL.Factorial());
Assert.AreEqual(24UL, 4UL.Factorial());
Assert.AreEqual(120UL, 5UL.Factorial());
Assert.AreEqual(720UL, 6UL.Factorial());
Assert.AreEqual(5040UL, 7UL.Factorial());
Assert.AreEqual(40320UL, 8UL.Factorial());
Assert.AreEqual(362880UL, 9UL.Factorial());
Assert.AreEqual(3628800UL, 10UL.Factorial());
}
[TestMethod]
public void IsEvenShouldBeCorrect()
{
const ulong one = 1;
const ulong two = 2;
Assert.IsFalse(one.IsEven());
Assert.IsTrue(two.IsEven());
}
[TestMethod]
public void IsOddShouldBeCorrect()
{
const ulong one = 1;
const ulong two = 2;
Assert.IsTrue(one.IsOdd());
Assert.IsFalse(two.IsOdd());
}
[TestMethod]
public void MultiplicativePersistence_ShouldBeCorrect_ForRecordHolders()
{
Assert.AreEqual(0, 0UL.MultiplicativePersistence());
Assert.AreEqual(1, 10UL.MultiplicativePersistence());
Assert.AreEqual(2, 25UL.MultiplicativePersistence());
Assert.AreEqual(3, 39UL.MultiplicativePersistence());
Assert.AreEqual(4, 77UL.MultiplicativePersistence());
Assert.AreEqual(5, 679UL.MultiplicativePersistence());
Assert.AreEqual(6, 6788UL.MultiplicativePersistence());
Assert.AreEqual(7, 68889UL.MultiplicativePersistence());
Assert.AreEqual(8, 2677889UL.MultiplicativePersistence());
Assert.AreEqual(9, 26888999UL.MultiplicativePersistence());
Assert.AreEqual(10, 3778888999UL.MultiplicativePersistence());
Assert.AreEqual(11, 277777788888899UL.MultiplicativePersistence());
}
}

View File

@ -0,0 +1,76 @@
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Net;
namespace X10D.Tests.Net;
[TestClass]
public class EndPointTests
{
[TestMethod]
public void GetHost_ShouldBeLocalhost_GivenLocalhostDnsEndPoint()
{
var endPoint = new DnsEndPoint("localhost", 1234);
Assert.AreEqual("localhost", endPoint.GetHost());
}
[TestMethod]
public void GetHost_ShouldBe127001_GivenLoopbackIPEndPoint()
{
var endPoint = new IPEndPoint(IPAddress.Loopback, 1234);
Assert.AreEqual("127.0.0.1", endPoint.GetHost());
}
[TestMethod]
public void GetHost_ShouldBeColonColon1_GivenIPv6LoopBackIPEndPoint()
{
var endPoint = new IPEndPoint(IPAddress.IPv6Loopback, 1234);
Assert.AreEqual("::1", endPoint.GetHost());
}
[TestMethod]
public void GetHost_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IPEndPoint?)null)!.GetHost());
Assert.ThrowsException<ArgumentNullException>(() => ((DnsEndPoint?)null)!.GetHost());
}
[TestMethod]
public void GetPort_ShouldBe1234_Given1234IPEndPoint()
{
var endPoint = new IPEndPoint(IPAddress.Loopback, 1234);
Assert.AreEqual(1234, endPoint.GetPort());
}
[TestMethod]
public void GetPort_ShouldBe1234_Given1234DnsEndPoint()
{
var endPoint = new DnsEndPoint("localhost", 1234);
Assert.AreEqual(1234, endPoint.GetPort());
}
[TestMethod]
public void GetPort_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => ((IPEndPoint?)null)!.GetPort());
Assert.ThrowsException<ArgumentNullException>(() => ((DnsEndPoint?)null)!.GetPort());
}
[TestMethod]
public void GetHost_ShouldBeEmpty_GivenInvalidEndPoint()
{
var endPoint = new DummyEndPoint();
Assert.AreEqual(string.Empty, endPoint.GetHost());
}
[TestMethod]
public void GetPort_ShouldBe0_GivenInvalidEndPoint()
{
var endPoint = new DummyEndPoint();
Assert.AreEqual(0, endPoint.GetPort());
}
private class DummyEndPoint : EndPoint
{
}
}

View File

@ -0,0 +1,43 @@
using System.Net;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Net;
namespace X10D.Tests.Net;
[TestClass]
public class IPAddressTests
{
private IPAddress _ipv4Address = null!;
private IPAddress _ipv6Address = null!;
[TestInitialize]
public void Initialize()
{
_ipv4Address = IPAddress.Parse("127.0.0.1");
_ipv6Address = IPAddress.Parse("::1");
}
[TestMethod]
public void IsIPv4_ShouldBeTrue_GivenIPv4()
{
Assert.IsTrue(_ipv4Address.IsIPv4());
}
[TestMethod]
public void IsIPv4_ShouldBeFalse_GivenIPv6()
{
Assert.IsFalse(_ipv6Address.IsIPv4());
}
[TestMethod]
public void IsIPv6_ShouldBeFalse_GivenIPv4()
{
Assert.IsFalse(_ipv4Address.IsIPv6());
}
[TestMethod]
public void IsIPv6_ShouldBeTrue_GivenIPv6()
{
Assert.IsTrue(_ipv6Address.IsIPv6());
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Net;
namespace X10D.Tests.Net;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void HostToNetworkOrder_ReturnsCorrectValue()
{
const short hostOrder = 0x0102;
const short networkOrder = 0x0201;
Assert.AreEqual(BitConverter.IsLittleEndian ? networkOrder : hostOrder, hostOrder.HostToNetworkOrder());
}
[TestMethod]
public void NetworkToHostOrder_ReturnsCorrectValue()
{
const short hostOrder = 0x0102;
const short networkOrder = 0x0201;
Assert.AreEqual(BitConverter.IsLittleEndian ? hostOrder : networkOrder, networkOrder.NetworkToHostOrder());
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Net;
namespace X10D.Tests.Net;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void HostToNetworkOrder_ReturnsCorrectValue()
{
const int hostOrder = 0x01020304;
const int networkOrder = 0x04030201;
Assert.AreEqual(BitConverter.IsLittleEndian ? networkOrder : hostOrder, hostOrder.HostToNetworkOrder());
}
[TestMethod]
public void NetworkToHostOrder_ReturnsCorrectValue()
{
const int hostOrder = 0x01020304;
const int networkOrder = 0x04030201;
Assert.AreEqual(BitConverter.IsLittleEndian ? hostOrder : networkOrder, networkOrder.NetworkToHostOrder());
}
}

View File

@ -0,0 +1,26 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Net;
namespace X10D.Tests.Net;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void HostToNetworkOrder_ReturnsCorrectValue()
{
const long hostOrder = 0x0102030405060708;
const long networkOrder = 0x0807060504030201;
Assert.AreEqual(BitConverter.IsLittleEndian ? networkOrder : hostOrder, hostOrder.HostToNetworkOrder());
}
[TestMethod]
public void NetworkToHostOrder_ReturnsCorrectValue()
{
const long hostOrder = 0x0102030405060708;
const long networkOrder = 0x0807060504030201;
Assert.AreEqual(BitConverter.IsLittleEndian ? hostOrder : networkOrder, networkOrder.NetworkToHostOrder());
}
}

View File

@ -0,0 +1,42 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class ByteTests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const byte value = 181; // 10110101
const byte expected = 91; // 01011011
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(4));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const byte value = 181; // 10110101
Assert.AreEqual(value, value.RotateLeft(8));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const byte value = 181; // 10110101
const byte expected = 91; // 01011011
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(4));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const byte value = 181; // 10110101
Assert.AreEqual(value, value.RotateRight(8));
}
}

View File

@ -0,0 +1,44 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class Int16Tests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const short value = 2896; // 00001011 01010000
const short expected = 27137; // 01101010 00000001
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(5));
Assert.AreEqual(value, value.RotateLeft(16));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const short value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateLeft(16));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const short value = 2896; // 00001011 01010000
const short expected = -32678; // 01111111 10100110
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(5));
Assert.AreEqual(value, value.RotateRight(16));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const short value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateRight(16));
}
}

View File

@ -0,0 +1,42 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class Int32Tests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const int value = 284719; // 00000000 00000100 01011000 00101111
const int expected = -1336016888; // 10110000 01011110 00000000 00001000
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(17));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const int value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateLeft(32));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const int value = 284719; // 00000000 00000100 01011000 00101111
const int expected = 739737602; // 00101100 00010111 10000000 00000010
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(17));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const int value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateRight(32));
}
}

View File

@ -0,0 +1,42 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class Int64Tests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const long value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
const long expected = -1588168355691398970; // 11101001 11110101 10110001 01001011 10000011 01111111 01111000 11000110
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(42));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const long value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateLeft(64));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const long value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
const long expected = -608990218894919625; // 11110111 10001100 01101110 10011111 01011011 00010100 10111000 00110111
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(42));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const long value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateRight(64));
}
}

View File

@ -0,0 +1,68 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
public class RandomTests
{
[TestMethod]
public void NextUnitVector2_ShouldReturnVector_WithMagnitude1()
{
var random = new Random();
var vector = random.NextUnitVector2();
Assert.AreEqual(1, vector.Length(), 1e-6);
}
[TestMethod]
public void NextUnitVector2_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextUnitVector2());
}
[TestMethod]
public void NextUnitVector3_ShouldReturnVector_WithMagnitude1()
{
var random = new Random();
var vector = random.NextUnitVector3();
Assert.AreEqual(1, vector.Length(), 1e-6);
}
[TestMethod]
public void NextUnitVector3_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextUnitVector3());
}
[TestMethod]
public void NextRotation_ShouldReturnQuaternion_WithMagnitude1()
{
var random = new Random();
var rotation = random.NextRotation();
Assert.AreEqual(1, rotation.Length(), 1e-6);
}
[TestMethod]
public void NextRotation_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextRotation());
}
[TestMethod]
public void NextRotationUniform_ShouldReturnQuaternion_WithMagnitude1()
{
var random = new Random();
var rotation = random.NextRotationUniform();
Assert.AreEqual(1, rotation.Length(), 1e-6);
}
[TestMethod]
public void NextRotationUniform_ShouldThrow_GivenNullRandom()
{
Random? random = null;
Assert.ThrowsException<ArgumentNullException>(() => random!.NextRotationUniform());
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
[CLSCompliant(false)]
public class SByteTests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const sbyte value = 117; // 01110101
const sbyte expected = 87; // 01010111
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(4));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const sbyte value = 117; // 01110101
Assert.AreEqual(value, value.RotateLeft(8));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const sbyte value = 117; // 01110101
const sbyte expected = 87; // 01010111
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(4));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const sbyte value = 117; // 01110101
Assert.AreEqual(value, value.RotateRight(8));
}
}

View File

@ -0,0 +1,45 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
[CLSCompliant(false)]
public class UInt16Tests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const ushort value = 2896; // 00001011 01010000
const ushort expected = 27137; // 01101010 00000001
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(5));
Assert.AreEqual(value, value.RotateLeft(16));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const ushort value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateLeft(16));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const ushort value = 2896; // 00001011 01010000
const ushort expected = 32858; // 10000000 01011010
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(5));
Assert.AreEqual(value, value.RotateRight(16));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const ushort value = 2896; // 00001011 01010000
Assert.AreEqual(value, value.RotateRight(16));
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
[CLSCompliant(false)]
public class UInt32Tests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const uint value = 284719; // 00000000 00000100 01011000 00101111
const uint expected = 2958950408; // 10110000 01011110 00000000 00001000
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(17));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const uint value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateLeft(32));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const uint value = 284719; // 00000000 00000100 01011000 00101111
const uint expected = 739737602; // 00101100 00010111 10000000 00000010
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(17));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const uint value = 284719; // 00000000 00000100 01011000 00101111
Assert.AreEqual(value, value.RotateRight(32));
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Numerics;
namespace X10D.Tests.Numerics;
[TestClass]
[CLSCompliant(false)]
public class UInt64Tests
{
[TestMethod]
public void RotateLeft_ShouldRotateCorrectly()
{
const ulong value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
const ulong expected = 16858575718018152646; // 11101001 11110101 10110001 01001011 10000011 01111111 01111000 11000110
Assert.AreEqual(value, value.RotateLeft(0));
Assert.AreEqual(expected, value.RotateLeft(42));
}
[TestMethod]
public void RotateLeft_ShouldModForLargeCount()
{
const ulong value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateLeft(64));
}
[TestMethod]
public void RotateRight_ShouldRotateCorrectly()
{
const ulong value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
const ulong expected = 17837753854814631991; // 11110111 10001100 01101110 10011111 01011011 00010100 10111000 00110111
Assert.AreEqual(value, value.RotateRight(0));
Assert.AreEqual(expected, value.RotateRight(42));
}
[TestMethod]
public void RotateRight_ShouldModForLargeCount()
{
const ulong value = 5972019251303316844; // 01010010 11100000 11011111 11011110 00110001 10111010 01111101 01101100
Assert.AreEqual(value, value.RotateRight(64));
}
}

View File

@ -0,0 +1,78 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Reflection;
namespace X10D.Tests.Reflection;
[TestClass]
public class MemberInfoTests
{
[TestMethod]
public void HasCustomAttribute_ShouldBeTrue_GivenCLSCompliantAttributeOnUnsignedTypes()
{
Assert.IsTrue(typeof(sbyte).HasCustomAttribute(typeof(CLSCompliantAttribute))); // okay, sbyte is signed. I know.
Assert.IsTrue(typeof(ushort).HasCustomAttribute(typeof(CLSCompliantAttribute)));
Assert.IsTrue(typeof(uint).HasCustomAttribute(typeof(CLSCompliantAttribute)));
Assert.IsTrue(typeof(ulong).HasCustomAttribute(typeof(CLSCompliantAttribute)));
}
[TestMethod]
public void HasCustomAttribute_ShouldBeTrue_GivenCLSCompliantAttributeOnUnsignedTypes_Generic()
{
Assert.IsTrue(typeof(sbyte).HasCustomAttribute<CLSCompliantAttribute>()); // okay, sbyte is signed. I know.
Assert.IsTrue(typeof(ushort).HasCustomAttribute<CLSCompliantAttribute>());
Assert.IsTrue(typeof(uint).HasCustomAttribute<CLSCompliantAttribute>());
Assert.IsTrue(typeof(ulong).HasCustomAttribute<CLSCompliantAttribute>());
}
[TestMethod]
public void HasCustomAttribute_ShouldThrow_GivenNull()
{
Type? type = null;
Assert.ThrowsException<ArgumentNullException>(() => type!.HasCustomAttribute<CLSCompliantAttribute>());
Assert.ThrowsException<ArgumentNullException>(() => type!.HasCustomAttribute(typeof(CLSCompliantAttribute)));
Assert.ThrowsException<ArgumentNullException>(() => typeof(object).HasCustomAttribute(null!));
}
[TestMethod]
public void HasCustomAttribute_ShouldThrow_GivenNonAttribute()
{
Assert.ThrowsException<ArgumentException>(() => typeof(object).HasCustomAttribute(typeof(object)));
}
[TestMethod]
public void SelectFromCustomAttribute_ShouldBeFalse_GivenCLSCompliantAttributeOnUnsignedTypes()
{
Assert.IsFalse(typeof(sbyte).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant));
Assert.IsFalse(typeof(ushort).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant));
Assert.IsFalse(typeof(uint).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant));
Assert.IsFalse(typeof(ulong).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant));
}
[TestMethod]
public void SelectFromCustomAttribute_ShouldBeTrue_GivenCLSCompliantAttributeOnSignedTypes()
{
Assert.IsTrue(typeof(byte).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant, true));
Assert.IsTrue(typeof(short).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant, true));
Assert.IsTrue(typeof(int).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant, true));
Assert.IsTrue(typeof(long).SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant, true));
}
[TestMethod]
public void SelectFromCustomAttribute_ShouldThrow_GivenNull()
{
Type? type = null;
Assert.ThrowsException<ArgumentNullException>(() =>
(type!.SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant)));
Assert.ThrowsException<ArgumentNullException>(() =>
(type!.SelectFromCustomAttribute((CLSCompliantAttribute attribute) => attribute.IsCompliant, true)));
Assert.ThrowsException<ArgumentNullException>(() =>
{
Func<CLSCompliantAttribute, bool>? selector = null;
typeof(int).SelectFromCustomAttribute(selector!);
});
}
}

View File

@ -0,0 +1,59 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Reflection;
namespace X10D.Tests.Reflection;
[TestClass]
public class TypeTests
{
[TestMethod]
public void Inherits_ShouldBeTrue_GivenStringInheritsObject()
{
Assert.IsTrue(typeof(string).Inherits(typeof(object)));
Assert.IsTrue(typeof(string).Inherits<object>());
}
[TestMethod]
public void Inherits_ShouldBeFalse_GivenObjectInheritsString()
{
Assert.IsFalse(typeof(object).Inherits(typeof(string)));
Assert.IsFalse(typeof(object).Inherits<string>());
}
[TestMethod]
public void Inherits_ShouldThrow_GivenValueType()
{
Assert.ThrowsException<ArgumentException>(() => typeof(int).Inherits(typeof(object)));
Assert.ThrowsException<ArgumentException>(() => typeof(object).Inherits(typeof(int)));
}
[TestMethod]
public void Inherits_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => typeof(object).Inherits(null!));
Assert.ThrowsException<ArgumentNullException>(() => ((Type?)null)!.Inherits(typeof(object)));
}
[TestMethod]
public void Implements_ShouldBeTrue_GivenInt32ImplementsIComparable()
{
Assert.IsTrue(typeof(int).Implements<IComparable>());
Assert.IsTrue(typeof(int).Implements<IComparable<int>>());
Assert.IsTrue(typeof(int).Implements(typeof(IComparable)));
Assert.IsTrue(typeof(int).Implements(typeof(IComparable<int>)));
}
[TestMethod]
public void Implements_ShouldThrow_GivenNull()
{
Assert.ThrowsException<ArgumentNullException>(() => typeof(object).Implements(null!));
Assert.ThrowsException<ArgumentNullException>(() => ((Type?)null)!.Implements(typeof(object)));
}
[TestMethod]
public void Implements_ShouldThrow_GivenNonInterface()
{
Assert.ThrowsException<ArgumentException>(() => typeof(string).Implements<object>());
Assert.ThrowsException<ArgumentException>(() => typeof(string).Implements(typeof(object)));
}
}

View File

@ -0,0 +1,37 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Text;
namespace X10D.Tests.Text;
[TestClass]
public class CharTests
{
[TestMethod]
public void RepeatShouldBeCorrect()
{
const string expected = "aaaaaaaaaa";
string actual = 'a'.Repeat(10);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void RepeatOneCountShouldBeLength1String()
{
string repeated = 'a'.Repeat(1);
Assert.AreEqual(1, repeated.Length);
Assert.AreEqual("a", repeated);
}
[TestMethod]
public void RepeatZeroCountShouldBeEmpty()
{
Assert.AreEqual(string.Empty, 'a'.Repeat(0));
}
[TestMethod]
public void RepeatNegativeCountShouldThrow()
{
Assert.ThrowsException<ArgumentOutOfRangeException>(() => 'a'.Repeat(-1));
}
}

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