From 62103707d531de92c557eb5c4e461838a03ef7cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 01:37:14 +0000 Subject: [PATCH] test: add Parse/TryParse tests and Round invalid-mode test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds FixedPointNanoParseTests.cs with 24 tests covering: - Parse(string) with valid, negative, and zero values - Parse(string) throws FormatException on invalid input - Parse(string) throws ArgumentNullException for null - Parse(ReadOnlySpan) valid and invalid cases - TryParse(string?, IFormatProvider, out) — true/false cases including null, invalid, and out-of-range values - TryParse(string?, out) — invariant culture shorthand - TryParse(ReadOnlySpan, IFormatProvider, out) — valid and invalid - TryParse(ReadOnlySpan, out) — invariant culture shorthand - Round with invalid MidpointRounding mode throws ArgumentOutOfRangeException - Parse/TryParse round-trip with 6 test case values 1426 → 1450 tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FixedPointNanoParseTests.cs | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 tests/FixedPointNano.Tests/FixedPointNanoParseTests.cs diff --git a/tests/FixedPointNano.Tests/FixedPointNanoParseTests.cs b/tests/FixedPointNano.Tests/FixedPointNanoParseTests.cs new file mode 100644 index 0000000..ef8e715 --- /dev/null +++ b/tests/FixedPointNano.Tests/FixedPointNanoParseTests.cs @@ -0,0 +1,198 @@ +using System; +using System.Globalization; +using Seerstone; + +namespace Seerstone.Tests; + +[TestFixture] +public sealed class FixedPointNanoParseTests +{ + // ----------------------------------------------------------------------------------------- + // Parse(string, IFormatProvider?) + // ----------------------------------------------------------------------------------------- + + [Test] + public void ParseStringShouldReturnCorrectValue() + { + var result = FixedPointNano.Parse("1.5", CultureInfo.InvariantCulture); + Assert.That(result.ToDecimal(), Is.EqualTo(1.5m)); + } + + [Test] + public void ParseStringShouldHandleNegativeValue() + { + var result = FixedPointNano.Parse("-42.000000001", CultureInfo.InvariantCulture); + Assert.That(result.ToDecimal(), Is.EqualTo(-42.000000001m)); + } + + [Test] + public void ParseStringShouldHandleZero() + { + var result = FixedPointNano.Parse("0", CultureInfo.InvariantCulture); + Assert.That(result, Is.EqualTo(FixedPointNano.Zero)); + } + + [Test] + public void ParseStringShouldUseInvariantCultureWhenProviderIsNull() + { + // Invariant culture uses '.' as decimal separator + var result = FixedPointNano.Parse("3.14"); + Assert.That(result.ToDecimal(), Is.EqualTo(3.14m)); + } + + [Test] + public void ParseStringShouldThrowFormatExceptionOnInvalidInput() + { + Assert.That(() => FixedPointNano.Parse("not-a-number", CultureInfo.InvariantCulture), + Throws.TypeOf()); + } + + [Test] + public void ParseStringShouldThrowArgumentNullExceptionForNull() + { + Assert.That(() => FixedPointNano.Parse(null!, CultureInfo.InvariantCulture), + Throws.TypeOf()); + } + + // ----------------------------------------------------------------------------------------- + // Parse(ReadOnlySpan, IFormatProvider?) + // ----------------------------------------------------------------------------------------- + + [Test] + public void ParseSpanShouldReturnCorrectValue() + { + ReadOnlySpan span = "1234.567890123"; + var result = FixedPointNano.Parse(span, CultureInfo.InvariantCulture); + Assert.That(result.ToDecimal(), Is.EqualTo(1234.567890123m)); + } + + [Test] + public void ParseSpanShouldThrowFormatExceptionOnInvalidInput() + { + Assert.That(() => FixedPointNano.Parse("xyz".AsSpan(), CultureInfo.InvariantCulture), + Throws.TypeOf()); + } + + // ----------------------------------------------------------------------------------------- + // TryParse(string?, IFormatProvider, out FixedPointNano) + // ----------------------------------------------------------------------------------------- + + [Test] + public void TryParseStringWithProviderShouldReturnTrueForValidInput() + { + var succeeded = FixedPointNano.TryParse("1.25", CultureInfo.InvariantCulture, out var result); + Assert.That(succeeded, Is.True); + Assert.That(result.ToDecimal(), Is.EqualTo(1.25m)); + } + + [Test] + public void TryParseStringWithProviderShouldReturnFalseForNull() + { + var succeeded = FixedPointNano.TryParse(null, CultureInfo.InvariantCulture, out var result); + Assert.That(succeeded, Is.False); + Assert.That(result, Is.EqualTo(default(FixedPointNano))); + } + + [Test] + public void TryParseStringWithProviderShouldReturnFalseForInvalidInput() + { + var succeeded = FixedPointNano.TryParse("garbage", CultureInfo.InvariantCulture, out var result); + Assert.That(succeeded, Is.False); + Assert.That(result, Is.EqualTo(default(FixedPointNano))); + } + + [Test] + public void TryParseStringWithProviderShouldReturnFalseForOutOfRangeValue() + { + // Value too large to fit in FixedPointNano (exceeds long.MaxValue / Scale) + const string tooLarge = "99999999999999999999"; + var succeeded = FixedPointNano.TryParse(tooLarge, CultureInfo.InvariantCulture, out var result); + Assert.That(succeeded, Is.False); + Assert.That(result, Is.EqualTo(default(FixedPointNano))); + } + + // ----------------------------------------------------------------------------------------- + // TryParse(string?, out FixedPointNano) — invariant culture shorthand + // ----------------------------------------------------------------------------------------- + + [Test] + public void TryParseStringInvariantShouldReturnTrueForValidInput() + { + var succeeded = FixedPointNano.TryParse("0.000000001", out var result); + Assert.That(succeeded, Is.True); + Assert.That(result, Is.EqualTo(FixedPointNano.Epsilon)); + } + + [Test] + public void TryParseStringInvariantShouldReturnFalseForNull() + { + var succeeded = FixedPointNano.TryParse((string?)null, out var result); + Assert.That(succeeded, Is.False); + Assert.That(result, Is.EqualTo(default(FixedPointNano))); + } + + // ----------------------------------------------------------------------------------------- + // TryParse(ReadOnlySpan, IFormatProvider, out FixedPointNano) + // ----------------------------------------------------------------------------------------- + + [Test] + public void TryParseSpanShouldReturnTrueForValidInput() + { + ReadOnlySpan span = "-1.5"; + var succeeded = FixedPointNano.TryParse(span, CultureInfo.InvariantCulture, out var result); + Assert.That(succeeded, Is.True); + Assert.That(result.ToDecimal(), Is.EqualTo(-1.5m)); + } + + [Test] + public void TryParseSpanShouldReturnFalseForInvalidInput() + { + ReadOnlySpan span = "!bad!"; + var succeeded = FixedPointNano.TryParse(span, CultureInfo.InvariantCulture, out var result); + Assert.That(succeeded, Is.False); + Assert.That(result, Is.EqualTo(default(FixedPointNano))); + } + + // ----------------------------------------------------------------------------------------- + // TryParse(ReadOnlySpan, out FixedPointNano) — invariant culture shorthand + // ----------------------------------------------------------------------------------------- + + [Test] + public void TryParseSpanInvariantShouldReturnTrueForValidInput() + { + ReadOnlySpan span = "100.5"; + var succeeded = FixedPointNano.TryParse(span, out var result); + Assert.That(succeeded, Is.True); + Assert.That(result.ToDecimal(), Is.EqualTo(100.5m)); + } + + // ----------------------------------------------------------------------------------------- + // Round with invalid MidpointRounding mode + // ----------------------------------------------------------------------------------------- + + [Test] + public void RoundWithInvalidMidpointRoundingModeShouldThrow() + { + var value = FixedPointNano.FromDecimal(1.5m); + var invalidMode = (MidpointRounding)999; + Assert.That(() => FixedPointNano.Round(value, 0, invalidMode), + Throws.TypeOf()); + } + + // ----------------------------------------------------------------------------------------- + // Parse/TryParse round-trip + // ----------------------------------------------------------------------------------------- + + [TestCase("0")] + [TestCase("0.000000001")] + [TestCase("-0.000000001")] + [TestCase("1.234567890")] + [TestCase("-1234.567890123")] + [TestCase("1000000.000000001")] + public void ParseThenToStringShouldRoundTrip(string input) + { + var value = FixedPointNano.Parse(input, CultureInfo.InvariantCulture); + var reparsed = FixedPointNano.Parse(value.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); + Assert.That(reparsed, Is.EqualTo(value)); + } +}