Skip to content

Commit

Permalink
Merge pull request #4316 from mr-russ/fix_4308
Browse files Browse the repository at this point in the history
Handle wraparound for Random and Distinct
  • Loading branch information
stevenaw committed Mar 23, 2023
2 parents e6204f1 + 3f7a51f commit f5fbb0c
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 8 deletions.
40 changes: 32 additions & 8 deletions src/NUnitFramework/framework/Attributes/RandomAttribute.cs
Expand Up @@ -348,7 +348,10 @@ protected override int GetNext(Randomizer randomizer, int min, int max)

protected override bool CanBeDistinct(int min, int max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + count > min) && (min + count <= max);
}
}

Expand All @@ -374,7 +377,10 @@ protected override uint GetNext(Randomizer randomizer, uint min, uint max)

protected override bool CanBeDistinct(uint min, uint max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + count > min) && (min + count <= max);
}
}

Expand All @@ -400,7 +406,10 @@ protected override long GetNext(Randomizer randomizer, long min, long max)

protected override bool CanBeDistinct(long min, long max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + (long)count > min) && (min + (long)count <= max);
}
}

Expand All @@ -426,7 +435,10 @@ protected override ulong GetNext(Randomizer randomizer, ulong min, ulong max)

protected override bool CanBeDistinct(ulong min, ulong max, int count)
{
return (uint)count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > int.MaxValue
// a complicated comparison is required.
return (count >= 0) && (min + (ulong)count > min) && (min + (ulong)count <= max);
}
}

Expand All @@ -452,7 +464,10 @@ protected override short GetNext(Randomizer randomizer, short min, short max)

protected override bool CanBeDistinct(short min, short max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + count > min) && (min + count <= max);
}
}

Expand All @@ -478,7 +493,10 @@ protected override ushort GetNext(Randomizer randomizer, ushort min, ushort max)

protected override bool CanBeDistinct(ushort min, ushort max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + count > min) && (min + count <= max);
}
}

Expand Down Expand Up @@ -556,7 +574,10 @@ protected override byte GetNext(Randomizer randomizer, byte min, byte max)

protected override bool CanBeDistinct(byte min, byte max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + count > min) && (min + count <= max);
}
}

Expand All @@ -582,7 +603,10 @@ protected override sbyte GetNext(Randomizer randomizer, sbyte min, sbyte max)

protected override bool CanBeDistinct(sbyte min, sbyte max, int count)
{
return count <= max - min;
// To avoid wraparound when min is very large or
// the gap between min and max is > MaxValue
// a complicated comparison is required.
return (min + count > min) && (min + count <= max);
}
}

Expand Down
58 changes: 58 additions & 0 deletions src/NUnitFramework/testdata/RandomAttributeFixture.cs
Expand Up @@ -33,6 +33,11 @@ public void RandomInt_IntRange_Distinct([Random(1, 4, COUNT, Distinct = true)] i
previousIntValues.Add(x);
}

[Test]
public void RandomInt_IntRange_DistinctNoWrap([Random(int.MinValue / 2, int.MaxValue / 2 + 1, COUNT, Distinct = true)] int x)
{
Assert.That(x, Is.InRange(int.MinValue / 2, int.MaxValue / 2 + 1));
}
#endregion

#region Unsigned Int
Expand All @@ -58,6 +63,12 @@ public void RandomUInt_UIntRange_Distinct([Random(1u, 4u, COUNT, Distinct = true
previousUIntValues.Add(x);
}

[Test]
public void RandomUInt_UIntRange_DistinctNoWrap([Random(uint.MinValue / 2, uint.MaxValue / 2 + 1, COUNT, Distinct = true)] uint x)
{
Assert.That(x, Is.InRange(uint.MinValue / 2, uint.MaxValue / 2 + 1));
}

#endregion

#region Short
Expand Down Expand Up @@ -89,6 +100,12 @@ public void RandomShort_ShortRange_Distinct([Random((short)1, (short)4, COUNT, D
previousShortValues.Add(x);
}

[Test]
public void RandomShort_ShortRange_DistinctNoWrap([Random(short.MinValue / 2, short.MaxValue / 2 + 1, COUNT, Distinct = true)] short x)
{
Assert.That(x, Is.InRange(short.MinValue / 2, short.MaxValue / 2 + 1));
}

#endregion

#region Unsigned Short
Expand Down Expand Up @@ -120,6 +137,11 @@ public void RandomShort_UShortRange_Distinct([Random((ushort)1, (ushort)4, COUNT
previousUShortValues.Add(x);
}

[Test]
public void RandomUShort_UShortRange_DistinctNoWrap([Random(ushort.MinValue / 2, ushort.MaxValue / 2 + 1, COUNT, Distinct = true)] ushort x)
{
Assert.That(x, Is.InRange(ushort.MinValue / 2, ushort.MaxValue / 2 + 1));
}
#endregion

#region Long
Expand All @@ -145,6 +167,12 @@ public void RandomLong_LongRange_Distinct([Random(1L, 4L, COUNT, Distinct = true
previousLongValues.Add(x);
}

[Test]
public void RandomLong_LongRange_DistinctNoWrap([Random(long.MinValue / 2, long.MaxValue / 2 + 1, COUNT, Distinct = true)] long x)
{
Assert.That(x, Is.InRange(long.MinValue / 2, long.MaxValue / 2 + 1));
}

#endregion

#region Unsigned Long
Expand All @@ -170,6 +198,12 @@ public void RandomULong_ULongRange_Distinct([Random(1uL, 4uL, COUNT, Distinct =
previousULongValues.Add(x);
}

[Test]
public void RandomULong_ULongRange_DistinctNoWrap([Random(ulong.MinValue / 2, ulong.MaxValue / 2 + 1, COUNT, Distinct = true)] ulong x)
{
Assert.That(x, Is.InRange(ulong.MinValue / 2, ulong.MaxValue / 2 + 1));
}

#endregion

#region Double
Expand Down Expand Up @@ -293,6 +327,12 @@ public void RandomByte_ByteRange([Random((byte)7, (byte)47, COUNT)] byte x)
Assert.That(x, Is.InRange((byte)7, (byte)46));
}

[Test]
public void RandomByte_ByteRange_DistinctNoWrap([Random((byte)0, (byte)255, COUNT, Distinct = true)] byte x)
{
Assert.That(x, Is.InRange((byte)0, (byte)255));
}

[Test]
public void RandomByte_IntRange([Random(7, 47, COUNT)] byte x)
{
Expand All @@ -306,6 +346,12 @@ public void RandomByte_IntRange_Distinct([Random(1, 4, COUNT, Distinct = true)]
previousByteValues.Add(x);
}

[Test]
public void RandomByte_IntRange_DistinctNoWrap([Random(0, 255, COUNT, Distinct = true)] byte x)
{
Assert.That(x, Is.InRange((byte)0, (byte)255));
}

#endregion

#region SByte
Expand All @@ -324,6 +370,12 @@ public void RandomSByte_SByteRange([Random((sbyte)7, (sbyte)47, COUNT)] sbyte x)
Assert.That(x, Is.InRange((sbyte)7, (sbyte)46));
}

[Test]
public void RandomSByte_SbyteRange_DistinctNoWrap([Random((sbyte)-128, (sbyte)127, COUNT, Distinct = true)] sbyte x)
{
Assert.That(x, Is.InRange((sbyte)-128, (sbyte)127));
}

[Test]
public void RandomSByte_IntRange([Random(7, 47, COUNT)] sbyte x)
{
Expand All @@ -337,6 +389,12 @@ public void RandomSByte_IntRange_Distinct([Random(1, 4, COUNT, Distinct = true)]
previousSByteValues.Add(x);
}

[Test]
public void RandomSByte_IntRange_DistinctNoWrap([Random(-128, 127, COUNT, Distinct = true)] sbyte x)
{
Assert.That(x, Is.InRange((sbyte)-128, (sbyte)127));
}

#endregion

#region Guid
Expand Down

0 comments on commit f5fbb0c

Please sign in to comment.