From 62361d8965c79dc89ed032d808661560c1db49ea Mon Sep 17 00:00:00 2001 From: TSR Berry <20988865+TSRBerry@users.noreply.github.com> Date: Sun, 16 Jul 2023 02:58:37 +0200 Subject: [PATCH] CombinatorialRangeAttribute: Add uint support --- .../CombinatorialRangeAttribute.cs | 65 +++++++++++++++++++ .../CombinatorialRangeAttributeTests.cs | 57 ++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/src/Xunit.Combinatorial/CombinatorialRangeAttribute.cs b/src/Xunit.Combinatorial/CombinatorialRangeAttribute.cs index 2ec749e..b21295f 100644 --- a/src/Xunit.Combinatorial/CombinatorialRangeAttribute.cs +++ b/src/Xunit.Combinatorial/CombinatorialRangeAttribute.cs @@ -78,6 +78,71 @@ public CombinatorialRangeAttribute(int from, int to, int step) this.Values = values; } + /// + /// Initializes a new instance of the class. + /// + /// The value at the beginning of the range. + /// + /// The quantity of consecutive integer values to include. + /// Cannot be less than 1, which would conceptually result in zero test cases. + /// + public CombinatorialRangeAttribute(uint from, uint count) + { + if (count < 1) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + + object[] values = new object[count]; + for (uint i = 0; i < count; i++) + { + values[i] = from + i; + } + + this.Values = values; + } + + /// + /// Initializes a new instance of the class. + /// + /// The value at the beginning of the range. + /// + /// The value at the end of the range. + /// Cannot be less than "from" parameter. + /// When "to" and "from" are equal, CombinatorialValues is more appropriate. + /// + /// + /// The number of unsigned integers to step for each value in result. + /// Cannot be less than one. Stepping zero is not useful. + /// Stepping over "to" does not add another value to the range. + /// + public CombinatorialRangeAttribute(uint from, uint to, uint step) + { + if (step == 0) + { + throw new ArgumentOutOfRangeException(nameof(step)); + } + + var values = new List(); + + if (from < to) + { + for (uint i = from; i <= to; i += step) + { + values.Add(i); + } + } + else + { + for (uint i = from; i >= to && i <= from; i -= step) + { + values.Add(i); + } + } + + this.Values = values.Cast().ToArray(); + } + /// /// Gets the values that should be passed to this parameter on the test method. /// diff --git a/test/Xunit.Combinatorial.Tests/CombinatorialRangeAttributeTests.cs b/test/Xunit.Combinatorial.Tests/CombinatorialRangeAttributeTests.cs index a8cdce0..0e3c0c2 100644 --- a/test/Xunit.Combinatorial.Tests/CombinatorialRangeAttributeTests.cs +++ b/test/Xunit.Combinatorial.Tests/CombinatorialRangeAttributeTests.cs @@ -42,9 +42,40 @@ public void IntegerStep_InvalidIntervalAndStep_ArgOutOfRange(int from, int to, i Assert.Throws(() => new CombinatorialRangeAttribute(from, to, step)); } + [Theory] + [InlineData(0u, 5u)] + public void CountOfUnsignedIntegers_HappyPath_SetsAttributeWithRange(uint from, uint count) + { + object[] values = UnsignedSequence(from, from + count - 1u, 1u).Cast().ToArray(); + var attribute = new CombinatorialRangeAttribute(from, count); + Assert.Equal(values, attribute.Values); + } + + [Theory] + [InlineData(0u, 0u)] + public void CountOfUnsignedIntegers_ZeroCount_ArgOutOfRange(uint from, uint count) + { + Assert.Throws(() => new CombinatorialRangeAttribute(from, count)); + } + + [Theory] + [InlineData(0u, 7u, 2u)] + [InlineData(0u, 8u, 2u)] + [InlineData(7u, 0u, 2u)] + public void UnsignedIntegerStep_HappyPath_SetsAttributeWithRange(uint from, uint to, uint step) + { + object[] expectedValues = UnsignedSequence(from, to, step).Cast().ToArray(); + + var attribute = new CombinatorialRangeAttribute(from, to, step); + Assert.Equal(expectedValues, attribute.Values); + } + internal static IEnumerable Sequence(int from, int to, int step) => step >= 0 ? SequenceIterator(from, to, step) : SequenceReverseIterator(from, to, step); + internal static IEnumerable UnsignedSequence(uint from, uint to, uint step) + => from < to ? UnsignedSequenceIterator(from, to, step) : UnsignedSequenceReverseIterator(from, to, step); + private static IEnumerable SequenceIterator(int from, int to, int step) { int value = from; @@ -70,4 +101,30 @@ private static IEnumerable SequenceReverseIterator(int from, int to, int st } } } + + private static IEnumerable UnsignedSequenceIterator(uint from, uint to, uint step) + { + uint value = from; + while (value <= to) + { + yield return value; + unchecked + { + value += step; + } + } + } + + private static IEnumerable UnsignedSequenceReverseIterator(uint from, uint to, uint step) + { + uint value = from; + while (value >= to && value <= from) + { + yield return value; + unchecked + { + value -= step; + } + } + } }