summaryrefslogtreecommitdiff
path: root/src/SMAPI.Tests/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI.Tests/Utilities')
-rw-r--r--src/SMAPI.Tests/Utilities/KeybindListTests.cs20
-rw-r--r--src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs181
-rw-r--r--src/SMAPI.Tests/Utilities/SDateTests.cs31
-rw-r--r--src/SMAPI.Tests/Utilities/SemanticVersionTests.cs66
4 files changed, 157 insertions, 141 deletions
diff --git a/src/SMAPI.Tests/Utilities/KeybindListTests.cs b/src/SMAPI.Tests/Utilities/KeybindListTests.cs
index 0bd6ec17..c4c086de 100644
--- a/src/SMAPI.Tests/Utilities/KeybindListTests.cs
+++ b/src/SMAPI.Tests/Utilities/KeybindListTests.cs
@@ -21,12 +21,12 @@ namespace SMAPI.Tests.Utilities
public void TryParse_SimpleValue(SButton button)
{
// act
- bool success = KeybindList.TryParse($"{button}", out KeybindList parsed, out string[] errors);
+ bool success = KeybindList.TryParse($"{button}", out KeybindList? parsed, out string[] errors);
// assert
Assert.IsTrue(success, "Parsing unexpectedly failed.");
Assert.IsNotNull(parsed, "The parsed result should not be null.");
- Assert.AreEqual(parsed.ToString(), $"{button}");
+ Assert.AreEqual(parsed!.ToString(), $"{button}");
Assert.IsNotNull(errors, message: "The errors should never be null.");
Assert.IsEmpty(errors, message: "The input bindings incorrectly reported errors.");
}
@@ -44,17 +44,17 @@ namespace SMAPI.Tests.Utilities
[TestCase(",", ExpectedResult = "None")]
[TestCase("A,", ExpectedResult = "A")]
[TestCase(",A", ExpectedResult = "A")]
- public string TryParse_MultiValues(string input)
+ public string TryParse_MultiValues(string? input)
{
// act
- bool success = KeybindList.TryParse(input, out KeybindList parsed, out string[] errors);
+ bool success = KeybindList.TryParse(input, out KeybindList? parsed, out string[] errors);
// assert
Assert.IsTrue(success, "Parsing unexpectedly failed.");
Assert.IsNotNull(parsed, "The parsed result should not be null.");
Assert.IsNotNull(errors, message: "The errors should never be null.");
Assert.IsEmpty(errors, message: "The input bindings incorrectly reported errors.");
- return parsed.ToString();
+ return parsed!.ToString();
}
/// <summary>Assert invalid values are rejected.</summary>
@@ -67,7 +67,7 @@ namespace SMAPI.Tests.Utilities
public void TryParse_InvalidValues(string input, string expectedError)
{
// act
- bool success = KeybindList.TryParse(input, out KeybindList parsed, out string[] errors);
+ bool success = KeybindList.TryParse(input, out KeybindList? parsed, out string[] errors);
// assert
Assert.IsFalse(success, "Parsing unexpectedly succeeded.");
@@ -98,13 +98,15 @@ namespace SMAPI.Tests.Utilities
public SButtonState GetState(string input, string stateMap)
{
// act
- bool success = KeybindList.TryParse(input, out KeybindList parsed, out string[] errors);
+ bool success = KeybindList.TryParse(input, out KeybindList? parsed, out string[] errors);
if (success && parsed?.Keybinds != null)
{
- foreach (var keybind in parsed.Keybinds)
+ foreach (Keybind? keybind in parsed.Keybinds)
+ {
#pragma warning disable 618 // method is marked obsolete because it should only be used in unit tests
keybind.GetButtonState = key => this.GetStateFromMap(key, stateMap);
#pragma warning restore 618
+ }
}
// assert
@@ -112,7 +114,7 @@ namespace SMAPI.Tests.Utilities
Assert.IsNotNull(parsed, "The parsed result should not be null.");
Assert.IsNotNull(errors, message: "The errors should never be null.");
Assert.IsEmpty(errors, message: "The input bindings incorrectly reported errors.");
- return parsed.GetState();
+ return parsed!.GetState();
}
diff --git a/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs b/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs
index ab4c2618..3219d89d 100644
--- a/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs
+++ b/src/SMAPI.Tests/Utilities/PathUtilitiesTests.cs
@@ -1,3 +1,4 @@
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using NUnit.Framework;
using StardewModdingAPI.Toolkit.Utilities;
@@ -6,6 +7,7 @@ namespace SMAPI.Tests.Utilities
{
/// <summary>Unit tests for <see cref="PathUtilities"/>.</summary>
[TestFixture]
+ [SuppressMessage("ReSharper", "StringLiteralTypo", Justification = "These are standard game install paths.")]
internal class PathUtilitiesTests
{
/*********
@@ -14,136 +16,125 @@ namespace SMAPI.Tests.Utilities
/// <summary>Sample paths used in unit tests.</summary>
public static readonly SamplePath[] SamplePaths = {
// Windows absolute path
- new SamplePath
- {
- OriginalPath = @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley",
+ new(
+ OriginalPath: @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley",
- Segments = new[] { "C:", "Program Files (x86)", "Steam", "steamapps", "common", "Stardew Valley" },
- SegmentsLimit3 = new [] { "C:", "Program Files (x86)", @"Steam\steamapps\common\Stardew Valley" },
+ Segments: new[] { "C:", "Program Files (x86)", "Steam", "steamapps", "common", "Stardew Valley" },
+ SegmentsLimit3: new [] { "C:", "Program Files (x86)", @"Steam\steamapps\common\Stardew Valley" },
- NormalizedOnWindows = @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley",
- NormalizedOnUnix = @"C:/Program Files (x86)/Steam/steamapps/common/Stardew Valley"
- },
+ NormalizedOnWindows: @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley",
+ NormalizedOnUnix: @"C:/Program Files (x86)/Steam/steamapps/common/Stardew Valley"
+ ),
// Windows absolute path (with trailing slash)
- new SamplePath
- {
- OriginalPath = @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley\",
+ new(
+ OriginalPath: @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley\",
- Segments = new[] { "C:", "Program Files (x86)", "Steam", "steamapps", "common", "Stardew Valley" },
- SegmentsLimit3 = new [] { "C:", "Program Files (x86)", @"Steam\steamapps\common\Stardew Valley\" },
+ Segments: new[] { "C:", "Program Files (x86)", "Steam", "steamapps", "common", "Stardew Valley" },
+ SegmentsLimit3: new [] { "C:", "Program Files (x86)", @"Steam\steamapps\common\Stardew Valley\" },
- NormalizedOnWindows = @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley\",
- NormalizedOnUnix = @"C:/Program Files (x86)/Steam/steamapps/common/Stardew Valley/"
- },
+ NormalizedOnWindows: @"C:\Program Files (x86)\Steam\steamapps\common\Stardew Valley\",
+ NormalizedOnUnix: @"C:/Program Files (x86)/Steam/steamapps/common/Stardew Valley/"
+ ),
// Windows relative path
- new SamplePath
- {
- OriginalPath = @"Content\Characters\Dialogue\Abigail",
+ new(
+ OriginalPath: @"Content\Characters\Dialogue\Abigail",
- Segments = new [] { "Content", "Characters", "Dialogue", "Abigail" },
- SegmentsLimit3 = new [] { "Content", "Characters", @"Dialogue\Abigail" },
+ Segments: new [] { "Content", "Characters", "Dialogue", "Abigail" },
+ SegmentsLimit3: new [] { "Content", "Characters", @"Dialogue\Abigail" },
- NormalizedOnWindows = @"Content\Characters\Dialogue\Abigail",
- NormalizedOnUnix = @"Content/Characters/Dialogue/Abigail"
- },
+ NormalizedOnWindows: @"Content\Characters\Dialogue\Abigail",
+ NormalizedOnUnix: @"Content/Characters/Dialogue/Abigail"
+ ),
// Windows relative path (with directory climbing)
- new SamplePath
- {
- OriginalPath = @"..\..\Content",
+ new(
+ OriginalPath: @"..\..\Content",
- Segments = new [] { "..", "..", "Content" },
- SegmentsLimit3 = new [] { "..", "..", "Content" },
+ Segments: new [] { "..", "..", "Content" },
+ SegmentsLimit3: new [] { "..", "..", "Content" },
- NormalizedOnWindows = @"..\..\Content",
- NormalizedOnUnix = @"../../Content"
- },
+ NormalizedOnWindows: @"..\..\Content",
+ NormalizedOnUnix: @"../../Content"
+ ),
// Windows UNC path
- new SamplePath
- {
- OriginalPath = @"\\unc\path",
+ new(
+ OriginalPath: @"\\unc\path",
- Segments = new [] { "unc", "path" },
- SegmentsLimit3 = new [] { "unc", "path" },
+ Segments: new [] { "unc", "path" },
+ SegmentsLimit3: new [] { "unc", "path" },
- NormalizedOnWindows = @"\\unc\path",
- NormalizedOnUnix = "/unc/path" // there's no good way to normalize this on Unix since UNC paths aren't supported; path normalization is meant for asset names anyway, so this test only ensures it returns some sort of sane value
- },
+ NormalizedOnWindows: @"\\unc\path",
+ NormalizedOnUnix: "/unc/path" // there's no good way to normalize this on Unix since UNC paths aren't supported; path normalization is meant for asset names anyway, so this test only ensures it returns some sort of sane value
+ ),
// Linux absolute path
- new SamplePath
- {
- OriginalPath = @"/home/.steam/steam/steamapps/common/Stardew Valley",
+ new(
+ OriginalPath: @"/home/.steam/steam/steamapps/common/Stardew Valley",
- Segments = new [] { "home", ".steam", "steam", "steamapps", "common", "Stardew Valley" },
- SegmentsLimit3 = new [] { "home", ".steam", "steam/steamapps/common/Stardew Valley" },
+ Segments: new [] { "home", ".steam", "steam", "steamapps", "common", "Stardew Valley" },
+ SegmentsLimit3: new [] { "home", ".steam", "steam/steamapps/common/Stardew Valley" },
- NormalizedOnWindows = @"\home\.steam\steam\steamapps\common\Stardew Valley",
- NormalizedOnUnix = @"/home/.steam/steam/steamapps/common/Stardew Valley"
- },
+ NormalizedOnWindows: @"\home\.steam\steam\steamapps\common\Stardew Valley",
+ NormalizedOnUnix: @"/home/.steam/steam/steamapps/common/Stardew Valley"
+ ),
// Linux absolute path (with trailing slash)
- new SamplePath
- {
- OriginalPath = @"/home/.steam/steam/steamapps/common/Stardew Valley/",
+ new(
+ OriginalPath: @"/home/.steam/steam/steamapps/common/Stardew Valley/",
- Segments = new [] { "home", ".steam", "steam", "steamapps", "common", "Stardew Valley" },
- SegmentsLimit3 = new [] { "home", ".steam", "steam/steamapps/common/Stardew Valley/" },
+ Segments: new [] { "home", ".steam", "steam", "steamapps", "common", "Stardew Valley" },
+ SegmentsLimit3: new [] { "home", ".steam", "steam/steamapps/common/Stardew Valley/" },
- NormalizedOnWindows = @"\home\.steam\steam\steamapps\common\Stardew Valley\",
- NormalizedOnUnix = @"/home/.steam/steam/steamapps/common/Stardew Valley/"
- },
+ NormalizedOnWindows: @"\home\.steam\steam\steamapps\common\Stardew Valley\",
+ NormalizedOnUnix: @"/home/.steam/steam/steamapps/common/Stardew Valley/"
+ ),
// Linux absolute path (with ~)
- new SamplePath
- {
- OriginalPath = @"~/.steam/steam/steamapps/common/Stardew Valley",
+ new(
+ OriginalPath: @"~/.steam/steam/steamapps/common/Stardew Valley",
- Segments = new [] { "~", ".steam", "steam", "steamapps", "common", "Stardew Valley" },
- SegmentsLimit3 = new [] { "~", ".steam", "steam/steamapps/common/Stardew Valley" },
+ Segments: new [] { "~", ".steam", "steam", "steamapps", "common", "Stardew Valley" },
+ SegmentsLimit3: new [] { "~", ".steam", "steam/steamapps/common/Stardew Valley" },
- NormalizedOnWindows = @"~\.steam\steam\steamapps\common\Stardew Valley",
- NormalizedOnUnix = @"~/.steam/steam/steamapps/common/Stardew Valley"
- },
+ NormalizedOnWindows: @"~\.steam\steam\steamapps\common\Stardew Valley",
+ NormalizedOnUnix: @"~/.steam/steam/steamapps/common/Stardew Valley"
+ ),
// Linux relative path
- new SamplePath
- {
- OriginalPath = @"Content/Characters/Dialogue/Abigail",
+ new(
+ OriginalPath: @"Content/Characters/Dialogue/Abigail",
- Segments = new [] { "Content", "Characters", "Dialogue", "Abigail" },
- SegmentsLimit3 = new [] { "Content", "Characters", "Dialogue/Abigail" },
+ Segments: new [] { "Content", "Characters", "Dialogue", "Abigail" },
+ SegmentsLimit3: new [] { "Content", "Characters", "Dialogue/Abigail" },
- NormalizedOnWindows = @"Content\Characters\Dialogue\Abigail",
- NormalizedOnUnix = @"Content/Characters/Dialogue/Abigail"
- },
+ NormalizedOnWindows: @"Content\Characters\Dialogue\Abigail",
+ NormalizedOnUnix: @"Content/Characters/Dialogue/Abigail"
+ ),
// Linux relative path (with directory climbing)
- new SamplePath
- {
- OriginalPath = @"../../Content",
+ new(
+ OriginalPath: @"../../Content",
- Segments = new [] { "..", "..", "Content" },
- SegmentsLimit3 = new [] { "..", "..", "Content" },
+ Segments: new [] { "..", "..", "Content" },
+ SegmentsLimit3: new [] { "..", "..", "Content" },
- NormalizedOnWindows = @"..\..\Content",
- NormalizedOnUnix = @"../../Content"
- },
+ NormalizedOnWindows: @"..\..\Content",
+ NormalizedOnUnix: @"../../Content"
+ ),
// Mixed directory separators
- new SamplePath
- {
- OriginalPath = @"C:\some/mixed\path/separators",
+ new(
+ OriginalPath: @"C:\some/mixed\path/separators",
- Segments = new [] { "C:", "some", "mixed", "path", "separators" },
- SegmentsLimit3 = new [] { "C:", "some", @"mixed\path/separators" },
+ Segments: new [] { "C:", "some", "mixed", "path", "separators" },
+ SegmentsLimit3: new [] { "C:", "some", @"mixed\path/separators" },
- NormalizedOnWindows = @"C:\some\mixed\path\separators",
- NormalizedOnUnix = @"C:/some/mixed/path/separators"
- },
+ NormalizedOnWindows: @"C:\some\mixed\path\separators",
+ NormalizedOnUnix: @"C:/some/mixed/path/separators"
+ )
};
@@ -281,14 +272,14 @@ namespace SMAPI.Tests.Utilities
/*********
** Private classes
*********/
- public class SamplePath
+ /// <summary>A sample path in multiple formats.</summary>
+ /// <param name="OriginalPath">The original path to pass to the <see cref="PathUtilities"/>.</param>
+ /// <param name="Segments">The normalized path segments.</param>
+ /// <param name="SegmentsLimit3">The normalized path segments, if we stop segmenting after the second one.</param>
+ /// <param name="NormalizedOnWindows">The normalized form on Windows.</param>
+ /// <param name="NormalizedOnUnix">The normalized form on Linux or macOS.</param>
+ public record SamplePath(string OriginalPath, string[] Segments, string[] SegmentsLimit3, string NormalizedOnWindows, string NormalizedOnUnix)
{
- public string OriginalPath { get; set; }
- public string[] Segments { get; set; }
- public string[] SegmentsLimit3 { get; set; }
- public string NormalizedOnWindows { get; set; }
- public string NormalizedOnUnix { get; set; }
-
public override string ToString()
{
return this.OriginalPath;
diff --git a/src/SMAPI.Tests/Utilities/SDateTests.cs b/src/SMAPI.Tests/Utilities/SDateTests.cs
index 0461952e..b9c3d202 100644
--- a/src/SMAPI.Tests/Utilities/SDateTests.cs
+++ b/src/SMAPI.Tests/Utilities/SDateTests.cs
@@ -16,9 +16,12 @@ namespace SMAPI.Tests.Utilities
/*********
** Fields
*********/
- /// <summary>All valid seasons.</summary>
+ /// <summary>The valid seasons.</summary>
private static readonly string[] ValidSeasons = { "spring", "summer", "fall", "winter" };
+ /// <summary>Sample user inputs for season names.</summary>
+ private static readonly string[] SampleSeasonValues = SDateTests.ValidSeasons.Concat(new[] { " WIntEr " }).ToArray();
+
/// <summary>All valid days of a month.</summary>
private static readonly int[] ValidDays = Enumerable.Range(1, 28).ToArray();
@@ -55,19 +58,18 @@ namespace SMAPI.Tests.Utilities
** Constructor
****/
[Test(Description = "Assert that the constructor sets the expected values for all valid dates.")]
- public void Constructor_SetsExpectedValues([ValueSource(nameof(SDateTests.ValidSeasons))] string season, [ValueSource(nameof(SDateTests.ValidDays))] int day, [Values(1, 2, 100)] int year)
+ public void Constructor_SetsExpectedValues([ValueSource(nameof(SDateTests.SampleSeasonValues))] string season, [ValueSource(nameof(SDateTests.ValidDays))] int day, [Values(1, 2, 100)] int year)
{
// act
- SDate date = new SDate(day, season, year);
+ SDate date = new(day, season, year);
// assert
Assert.AreEqual(day, date.Day);
- Assert.AreEqual(season, date.Season);
+ Assert.AreEqual(season.Trim().ToLowerInvariant(), date.Season);
Assert.AreEqual(year, date.Year);
}
[Test(Description = "Assert that the constructor throws an exception if the values are invalid.")]
- [TestCase(01, "Spring", 1)] // seasons are case-sensitive
[TestCase(01, "springs", 1)] // invalid season name
[TestCase(-1, "spring", 1)] // day < 0
[TestCase(0, "spring", 1)] // day zero
@@ -252,9 +254,9 @@ namespace SMAPI.Tests.Utilities
{
foreach (int day in SDateTests.ValidDays)
{
- SDate date = new SDate(day, season, year);
+ SDate date = new(day, season, year);
int hash = date.GetHashCode();
- if (hashes.TryGetValue(hash, out SDate otherDate))
+ if (hashes.TryGetValue(hash, out SDate? otherDate))
Assert.Fail($"Received identical hash code {hash} for dates {otherDate} and {date}.");
if (hash < lastHash)
Assert.Fail($"Received smaller hash code for date {date} ({hash}) relative to {hashes[lastHash]} ({lastHash}).");
@@ -294,7 +296,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(Dates.Now, Dates.NextDay, ExpectedResult = false)]
[TestCase(Dates.Now, Dates.NextMonth, ExpectedResult = false)]
[TestCase(Dates.Now, Dates.NextYear, ExpectedResult = false)]
- public bool Operators_Equals(string now, string other)
+ public bool Operators_Equals(string? now, string other)
{
return this.GetDate(now) == this.GetDate(other);
}
@@ -308,7 +310,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(Dates.Now, Dates.NextDay, ExpectedResult = true)]
[TestCase(Dates.Now, Dates.NextMonth, ExpectedResult = true)]
[TestCase(Dates.Now, Dates.NextYear, ExpectedResult = true)]
- public bool Operators_NotEquals(string now, string other)
+ public bool Operators_NotEquals(string? now, string other)
{
return this.GetDate(now) != this.GetDate(other);
}
@@ -322,7 +324,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(Dates.Now, Dates.NextDay, ExpectedResult = true)]
[TestCase(Dates.Now, Dates.NextMonth, ExpectedResult = true)]
[TestCase(Dates.Now, Dates.NextYear, ExpectedResult = true)]
- public bool Operators_LessThan(string now, string other)
+ public bool Operators_LessThan(string? now, string other)
{
return this.GetDate(now) < this.GetDate(other);
}
@@ -336,7 +338,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(Dates.Now, Dates.NextDay, ExpectedResult = true)]
[TestCase(Dates.Now, Dates.NextMonth, ExpectedResult = true)]
[TestCase(Dates.Now, Dates.NextYear, ExpectedResult = true)]
- public bool Operators_LessThanOrEqual(string now, string other)
+ public bool Operators_LessThanOrEqual(string? now, string other)
{
return this.GetDate(now) <= this.GetDate(other);
}
@@ -350,7 +352,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(Dates.Now, Dates.NextDay, ExpectedResult = false)]
[TestCase(Dates.Now, Dates.NextMonth, ExpectedResult = false)]
[TestCase(Dates.Now, Dates.NextYear, ExpectedResult = false)]
- public bool Operators_MoreThan(string now, string other)
+ public bool Operators_MoreThan(string? now, string other)
{
return this.GetDate(now) > this.GetDate(other);
}
@@ -364,7 +366,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(Dates.Now, Dates.NextDay, ExpectedResult = false)]
[TestCase(Dates.Now, Dates.NextMonth, ExpectedResult = false)]
[TestCase(Dates.Now, Dates.NextYear, ExpectedResult = false)]
- public bool Operators_MoreThanOrEqual(string now, string other)
+ public bool Operators_MoreThanOrEqual(string? now, string other)
{
return this.GetDate(now) > this.GetDate(other);
}
@@ -375,7 +377,8 @@ namespace SMAPI.Tests.Utilities
*********/
/// <summary>Convert a string date into a game date, to make unit tests easier to read.</summary>
/// <param name="dateStr">The date string like "dd MMMM yy".</param>
- private SDate GetDate(string dateStr)
+ [return: NotNullIfNotNull("dateStr")]
+ private SDate? GetDate(string? dateStr)
{
if (dateStr == null)
return null;
diff --git a/src/SMAPI.Tests/Utilities/SemanticVersionTests.cs b/src/SMAPI.Tests/Utilities/SemanticVersionTests.cs
index ac4ef39b..fedadba6 100644
--- a/src/SMAPI.Tests/Utilities/SemanticVersionTests.cs
+++ b/src/SMAPI.Tests/Utilities/SemanticVersionTests.cs
@@ -61,10 +61,10 @@ namespace SMAPI.Tests.Utilities
[TestCase("apple")]
[TestCase("-apple")]
[TestCase("-5")]
- public void Constructor_FromString_WithInvalidValues(string input)
+ public void Constructor_FromString_WithInvalidValues(string? input)
{
if (input == null)
- this.AssertAndLogException<ArgumentNullException>(() => new SemanticVersion(input));
+ this.AssertAndLogException<ArgumentNullException>(() => new SemanticVersion(input!));
else
this.AssertAndLogException<FormatException>(() => new SemanticVersion(input));
}
@@ -91,7 +91,7 @@ namespace SMAPI.Tests.Utilities
[TestCase("1.2.3.4-some-tag.4 ")]
public void Constructor_FromString_Standard_DisallowsNonStandardVersion(string input)
{
- Assert.Throws<FormatException>(() => new SemanticVersion(input));
+ Assert.Throws<FormatException>(() => _ = new SemanticVersion(input));
}
/// <summary>Assert the parsed version when constructed from standard parts.</summary>
@@ -110,7 +110,7 @@ namespace SMAPI.Tests.Utilities
[TestCase(1, 2, 3, "some-tag.4 ", null, ExpectedResult = "1.2.3-some-tag.4")]
[TestCase(1, 2, 3, "some-tag.4 ", "build.004", ExpectedResult = "1.2.3-some-tag.4+build.004")]
[TestCase(1, 2, 0, null, "3.4.5-build.004", ExpectedResult = "1.2.0+3.4.5-build.004")]
- public string Constructor_FromParts(int major, int minor, int patch, string prerelease, string build)
+ public string Constructor_FromParts(int major, int minor, int patch, string? prerelease, string? build)
{
// act
ISemanticVersion version = new SemanticVersion(major, minor, patch, prerelease, build);
@@ -217,11 +217,16 @@ namespace SMAPI.Tests.Utilities
[TestCase("1.0-beta.2", "1.0-beta.1", ExpectedResult = 1)]
[TestCase("1.0-beta.10", "1.0-beta.2", ExpectedResult = 1)]
[TestCase("1.0-beta-10", "1.0-beta-2", ExpectedResult = 1)]
- public int CompareTo(string versionStrA, string versionStrB)
+
+ // null
+ [TestCase("1.0.0", null, ExpectedResult = 1)] // null is always less than any value per CompareTo remarks
+ public int CompareTo(string versionStrA, string? versionStrB)
{
// arrange
ISemanticVersion versionA = new SemanticVersion(versionStrA);
- ISemanticVersion versionB = new SemanticVersion(versionStrB);
+ ISemanticVersion? versionB = versionStrB != null
+ ? new SemanticVersion(versionStrB)
+ : null;
// assert
return versionA.CompareTo(versionB);
@@ -260,14 +265,19 @@ namespace SMAPI.Tests.Utilities
[TestCase("1.0-beta.2", "1.0-beta.1", ExpectedResult = false)]
[TestCase("1.0-beta.10", "1.0-beta.2", ExpectedResult = false)]
[TestCase("1.0-beta-10", "1.0-beta-2", ExpectedResult = false)]
- public bool IsOlderThan(string versionStrA, string versionStrB)
+
+ // null
+ [TestCase("1.0.0", null, ExpectedResult = false)] // null is always less than any value per CompareTo remarks
+ public bool IsOlderThan(string versionStrA, string? versionStrB)
{
// arrange
ISemanticVersion versionA = new SemanticVersion(versionStrA);
- ISemanticVersion versionB = new SemanticVersion(versionStrB);
+ ISemanticVersion? versionB = versionStrB != null
+ ? new SemanticVersion(versionStrB)
+ : null;
// assert
- Assert.AreEqual(versionA.IsOlderThan(versionB), versionA.IsOlderThan(versionB.ToString()), "The two signatures returned different results.");
+ Assert.AreEqual(versionA.IsOlderThan(versionB), versionA.IsOlderThan(versionB?.ToString()), "The two signatures returned different results.");
return versionA.IsOlderThan(versionB);
}
@@ -304,14 +314,19 @@ namespace SMAPI.Tests.Utilities
[TestCase("1.0-beta.2", "1.0-beta.1", ExpectedResult = true)]
[TestCase("1.0-beta.10", "1.0-beta.2", ExpectedResult = true)]
[TestCase("1.0-beta-10", "1.0-beta-2", ExpectedResult = true)]
- public bool IsNewerThan(string versionStrA, string versionStrB)
+
+ // null
+ [TestCase("1.0.0", null, ExpectedResult = true)] // null is always less than any value per CompareTo remarks
+ public bool IsNewerThan(string versionStrA, string? versionStrB)
{
// arrange
ISemanticVersion versionA = new SemanticVersion(versionStrA);
- ISemanticVersion versionB = new SemanticVersion(versionStrB);
+ ISemanticVersion? versionB = versionStrB != null
+ ? new SemanticVersion(versionStrB)
+ : null;
// assert
- Assert.AreEqual(versionA.IsNewerThan(versionB), versionA.IsNewerThan(versionB.ToString()), "The two signatures returned different results.");
+ Assert.AreEqual(versionA.IsNewerThan(versionB), versionA.IsNewerThan(versionB?.ToString()), "The two signatures returned different results.");
return versionA.IsNewerThan(versionB);
}
@@ -322,7 +337,7 @@ namespace SMAPI.Tests.Utilities
/// <param name="versionStr">The main version.</param>
/// <param name="lowerStr">The lower version number.</param>
/// <param name="upperStr">The upper version number.</param>
- [Test(Description = "Assert that version.IsNewerThan returns the expected value.")]
+ [Test(Description = "Assert that version.IsBetween returns the expected value.")]
// is between
[TestCase("0.5.7-beta.3", "0.5.7-beta.3", "0.5.7-beta.3", ExpectedResult = true)]
[TestCase("1.0", "1.0", "1.1", ExpectedResult = true)]
@@ -330,6 +345,7 @@ namespace SMAPI.Tests.Utilities
[TestCase("1.0", "0.5", "1.1", ExpectedResult = true)]
[TestCase("1.0-beta.2", "1.0-beta.1", "1.0-beta.3", ExpectedResult = true)]
[TestCase("1.0-beta-2", "1.0-beta-1", "1.0-beta-3", ExpectedResult = true)]
+ [TestCase("1.0.0", null, "1.0.0", ExpectedResult = true)] // null is always less than any value per CompareTo remarks
// is not between
[TestCase("1.0-beta", "1.0", "1.1", ExpectedResult = false)]
@@ -337,15 +353,20 @@ namespace SMAPI.Tests.Utilities
[TestCase("1.0-beta.2", "1.1", "1.0", ExpectedResult = false)]
[TestCase("1.0-beta.2", "1.0-beta.10", "1.0-beta.3", ExpectedResult = false)]
[TestCase("1.0-beta-2", "1.0-beta-10", "1.0-beta-3", ExpectedResult = false)]
- public bool IsBetween(string versionStr, string lowerStr, string upperStr)
+ [TestCase("1.0.0", "1.0.0", null, ExpectedResult = false)] // null is always less than any value per CompareTo remarks
+ public bool IsBetween(string versionStr, string? lowerStr, string? upperStr)
{
// arrange
- ISemanticVersion lower = new SemanticVersion(lowerStr);
- ISemanticVersion upper = new SemanticVersion(upperStr);
+ ISemanticVersion? lower = lowerStr != null
+ ? new SemanticVersion(lowerStr)
+ : null;
+ ISemanticVersion? upper = upperStr != null
+ ? new SemanticVersion(upperStr)
+ : null;
ISemanticVersion version = new SemanticVersion(versionStr);
// assert
- Assert.AreEqual(version.IsBetween(lower, upper), version.IsBetween(lower.ToString(), upper.ToString()), "The two signatures returned different results.");
+ Assert.AreEqual(version.IsBetween(lower, upper), version.IsBetween(lower?.ToString(), upper?.ToString()), "The two signatures returned different results.");
return version.IsBetween(lower, upper);
}
@@ -395,7 +416,7 @@ namespace SMAPI.Tests.Utilities
public void GameVersion(string versionStr)
{
// act
- GameVersion version = new GameVersion(versionStr);
+ GameVersion version = new(versionStr);
// assert
Assert.AreEqual(versionStr, version.ToString(), "The game version did not round-trip to the same value.");
@@ -413,7 +434,7 @@ namespace SMAPI.Tests.Utilities
/// <param name="prerelease">The prerelease tag.</param>
/// <param name="build">The build metadata.</param>
/// <param name="nonStandard">Whether the version should be marked as non-standard.</param>
- private void AssertParts(ISemanticVersion version, int major, int minor, int patch, string prerelease, string build, bool nonStandard)
+ private void AssertParts(ISemanticVersion version, int major, int minor, int patch, string? prerelease, string? build, bool nonStandard)
{
Assert.AreEqual(major, version.MajorVersion, "The major version doesn't match.");
Assert.AreEqual(minor, version.MinorVersion, "The minor version doesn't match.");
@@ -426,9 +447,8 @@ namespace SMAPI.Tests.Utilities
/// <summary>Assert that the expected exception type is thrown, and log the action output and thrown exception.</summary>
/// <typeparam name="T">The expected exception type.</typeparam>
/// <param name="action">The action which may throw the exception.</param>
- /// <param name="message">The message to log if the expected exception isn't thrown.</param>
[SuppressMessage("ReSharper", "UnusedParameter.Local", Justification = "The message argument is deliberately only used in precondition checks since this is an assertion method.")]
- private void AssertAndLogException<T>(Func<object> action, string message = null)
+ private void AssertAndLogException<T>(Func<object> action)
where T : Exception
{
this.AssertAndLogException<T>(() =>
@@ -443,7 +463,7 @@ namespace SMAPI.Tests.Utilities
/// <param name="action">The action which may throw the exception.</param>
/// <param name="message">The message to log if the expected exception isn't thrown.</param>
[SuppressMessage("ReSharper", "UnusedParameter.Local", Justification = "The message argument is deliberately only used in precondition checks since this is an assertion method.")]
- private void AssertAndLogException<T>(Action action, string message = null)
+ private void AssertAndLogException<T>(Action action, string? message = null)
where T : Exception
{
try
@@ -455,7 +475,7 @@ namespace SMAPI.Tests.Utilities
TestContext.WriteLine($"Exception thrown:\n{ex}");
return;
}
- catch (Exception ex) when (!(ex is AssertionException))
+ catch (Exception ex) when (ex is not AssertionException)
{
TestContext.WriteLine($"Exception thrown:\n{ex}");
Assert.Fail(message ?? $"Didn't throw the expected exception; expected {typeof(T).FullName}, got {ex.GetType().FullName}.");