From 4a123a93d2977bcf79c5a3c166c795d7d9d88188 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 01:25:07 +0000 Subject: [PATCH] test: add coverage-gap tests for Frac, Pow, Divide, and Clamp - Frac: 5 tests (fractional parts for positive, negative, integer, zero; and parity check against FractionalPart) - Pow: negative-exponent guard (ArgumentOutOfRangeException) and zero-exponent returns One - Divide(long): zero-divisor guard (DivideByZeroException) - Clamp: min-exceeds-max guard (ArgumentException) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FixedPointNanoCoverageGapTests.cs | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs diff --git a/tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs b/tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs new file mode 100644 index 0000000..0c9ede2 --- /dev/null +++ b/tests/FixedPointNano.Tests/FixedPointNanoCoverageGapTests.cs @@ -0,0 +1,84 @@ +using System; +using Seerstone; + +namespace Seerstone.Tests; + +/// +/// Covers behaviours not exercised by the other test fixtures: +/// Frac, Pow negative-exponent guard, Divide(long) zero guard, +/// and Clamp invalid-range guard. +/// +[TestFixture] +public sealed class FixedPointNanoCoverageGapTests +{ + // ----------------------------------------------------------------------------------------- + // Frac + // ----------------------------------------------------------------------------------------- + + [TestCase(1.75, 0.75, Description = "Positive fractional part")] + [TestCase(1.0, 0.0, Description = "Exact integer has zero Frac")] + [TestCase(-1.25, -0.25, Description = "Negative fractional part keeps sign")] + [TestCase(0.0, 0.0, Description = "Zero has zero Frac")] + public void FracShouldReturnFractionalPart(double input, double expected) + { + var value = FixedPointNano.FromDouble(input); + Assert.That(FixedPointNano.Frac(value).ToDouble(), Is.EqualTo(expected).Within(1e-9)); + } + + [Test] + public void FracShouldMatchFractionalPart() + { + var values = new[] { 1.5, -3.25, 0.0, 42.0, -0.999999999 }; + foreach (var d in values) + { + var v = FixedPointNano.FromDouble(d); + Assert.That(FixedPointNano.Frac(v), Is.EqualTo(FixedPointNano.FractionalPart(v)), + $"Frac and FractionalPart differ for {d}"); + } + } + + // ----------------------------------------------------------------------------------------- + // Pow – negative exponent guard + // ----------------------------------------------------------------------------------------- + + [Test] + public void PowShouldThrowForNegativeExponent() + { + Assert.That( + () => FixedPointNano.Pow(FixedPointNano.One, -1), + Throws.TypeOf()); + } + + [Test] + public void PowZeroExponentShouldReturnOne() + { + var value = FixedPointNano.FromDecimal(7.5m); + Assert.That(FixedPointNano.Pow(value, 0), Is.EqualTo(FixedPointNano.One)); + } + + // ----------------------------------------------------------------------------------------- + // Divide(FixedPointNano, long) – zero-divisor guard + // ----------------------------------------------------------------------------------------- + + [Test] + public void DivideByLongZeroShouldThrowDivideByZeroException() + { + Assert.That( + () => FixedPointNano.Divide(FixedPointNano.One, 0L), + Throws.TypeOf()); + } + + // ----------------------------------------------------------------------------------------- + // Clamp – invalid range guard + // ----------------------------------------------------------------------------------------- + + [Test] + public void ClampShouldThrowWhenMinExceedsMax() + { + var min = FixedPointNano.FromDecimal(5m); + var max = FixedPointNano.FromDecimal(1m); + Assert.That( + () => FixedPointNano.Clamp(FixedPointNano.Zero, min, max), + Throws.TypeOf()); + } +}