Files
RobustToolbox/Robust.Shared.Tests/Random/RandomExtensionsTests.cs
PJB3005 788e9386fd Split up test project
Robust.UnitTesting was both ALL tests for RT, and also API surface for content tests.

Tests are now split into separate projects as appropriate, and the API side has also been split off.
2025-12-16 01:36:53 +01:00

280 lines
8.8 KiB
C#

using Moq;
using NUnit.Framework;
using Robust.Shared.Collections;
using Robust.Shared.Random;
namespace Robust.Shared.Tests.Random;
/// <summary> Instantiable tests for <see cref="RandomExtensions.GetItems{T}(IRobustRandom,IList{T},int,bool)"/>. </summary>
[TestFixture]
internal sealed class RandomExtensionsGetItemsWithListTests : RandomExtensionsTests<IList<string>>
{
/// <inheritdoc />
protected override IList<string> CreateCollection()
=> new List<string>(CollectionForTests);
/// <inheritdoc />
protected override IReadOnlyCollection<string> Invoke(IList<string> collection, int count, bool allowDuplicates)
=> _underlyingRandom.GetItems(collection, count, allowDuplicates);
}
/// <summary> Instantiable tests for <see cref="RandomExtensions.GetItems{T}(IRobustRandom,Span{T},int,bool)"/>. </summary>
[TestFixture]
internal sealed class RandomExtensionsGetItemsWithSpanTests : RandomExtensionsTests<string[]>
{
/// <inheritdoc />
protected override string[] CreateCollection()
=> CollectionForTests;
/// <inheritdoc />
protected override IReadOnlyCollection<string> Invoke(string[] collection, int count, bool allowDuplicates)
{
var span = new Span<string>(collection);
return _underlyingRandom.GetItems(span, count, allowDuplicates)
.ToArray();
}
}
/// <summary> Instantiable tests for <see cref="RandomExtensions.GetItems{T}(IRobustRandom,ValueList{T},int,bool)"/>. </summary>
[TestFixture]
internal sealed class RandomExtensionsGetItemsWithValueListTests : RandomExtensionsTests<ValueList<string>>
{
/// <inheritdoc />
protected override ValueList<string> CreateCollection()
=> new ValueList<string>(CollectionForTests);
/// <inheritdoc />
protected override IReadOnlyCollection<string> Invoke(ValueList<string> collection, int count, bool allowDuplicates)
=> _underlyingRandom.GetItems(collection, count, allowDuplicates)
.ToArray();
}
[TestFixture]
internal abstract class RandomExtensionsTests<T>
{
protected IRobustRandom _underlyingRandom = default!;
protected readonly string[] CollectionForTests = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
private T _collection = default!;
private int Count => CollectionForTests.Length;
[SetUp]
public void Setup()
{
_underlyingRandom = Mock.Of<IRobustRandom>();
_collection = CreateCollection();
}
[Test]
public void GetItems_PickOneFromList_ReturnOfRandomizedIndex()
{
// Arrange
Mock.Get(_underlyingRandom)
.Setup(x => x.Next(Count))
.Returns(8);
// Act
var result = Invoke(_collection, 1, true);
// Assert
Assert.That(result.Count, Is.EqualTo(1));
Assert.That(result.Single(), Is.EqualTo("8"));
}
[Test]
public void GetItems_PickOneFromListWithoutDuplicates_ReturnOfRandomizedIndex()
{
// Arrange
Mock.Get(_underlyingRandom)
.Setup(x => x.Next(Count))
.Returns(8);
// Act
var result = Invoke(_collection, 1, allowDuplicates: false);
// Assert
Assert.That(result.Count, Is.EqualTo(1));
Assert.That(result.Single(), Is.EqualTo("8"));
}
[Test]
public void GetItems_PickSomeFromList_ReturnOfRandomizedIndex()
{
// Arrange
Mock.Get(_underlyingRandom)
.SetupSequence(x => x.Next(Count))
.Returns(8)
.Returns(3)
.Returns(2);
// Act
var result = Invoke(_collection, 3, true);
// Assert
Assert.That(result, Is.EqualTo(new[] { "8", "3", "2" }));
}
[Test]
public void GetItems_PickSomeFromListWhileRollingDuplicates_ReturnWithDuplicates()
{
// Arrange
Mock.Get(_underlyingRandom)
.SetupSequence(x => x.Next(Count))
.Returns(8)
.Returns(2)
.Returns(2)
.Returns(2);
// Act
var result = Invoke(_collection, 4, allowDuplicates: true);
// Assert
Assert.That(result, Is.EqualTo(new[] { "8", "2", "2", "2" }));
}
[Test]
public void GetItems_PickSameAmountAsOriginalCollection_ReturnWithDuplicates()
{
// Arrange
Mock.Get(_underlyingRandom)
.SetupSequence(x => x.Next(Count))
.Returns(0)
.Returns(2)
.Returns(2)
.Returns(4)
.Returns(6)
.Returns(5)
.Returns(4)
.Returns(3)
.Returns(2)
.Returns(1)
.Returns(0);
// Act
var result = Invoke(_collection, 11, allowDuplicates: true);
// Assert
Assert.That(result, Is.EqualTo(new[] { "0", "2", "2", "4", "6", "5", "4", "3", "2", "1", "0" }));
}
[Test]
public void GetItems_PickMoreItemsThenOriginalCollectionHave_ReturnWithDuplicates()
{
// Arrange
Mock.Get(_underlyingRandom)
.SetupSequence(x => x.Next(Count))
.Returns(0)
.Returns(2)
.Returns(2)
.Returns(4)
.Returns(6)
.Returns(5)
.Returns(4)
.Returns(3)
.Returns(2)
.Returns(1)
.Returns(9)
.Returns(9);
// Act
var result = Invoke(_collection, 12, allowDuplicates: true);
// Assert
Assert.That(result, Is.EqualTo(new[] { "0", "2", "2", "4", "6", "5", "4", "3", "2", "1", "9", "9" }));
}
[Test]
public void GetItems_PickSomeItemsWithoutDuplicates_ReturnWithoutDuplicates()
{
// Arrange
var mock = Mock.Get(_underlyingRandom);
mock.Setup(x => x.Next(Count)).Returns(1);
mock.Setup(x => x.Next(Count - 1)).Returns(1);
mock.Setup(x => x.Next(Count - 2)).Returns(6);
// Act
var result = Invoke(_collection, 3, allowDuplicates: false);
// Assert
Assert.That(result, Is.EqualTo(new[] { "1", "10", "6" }));
}
[Test]
public void GetItems_PickOneLessItemsThenOriginalCollectionHaveWithoutDuplicates_ReturnWithoutDuplicates()
{
// Arrange
var mock = Mock.Get(_underlyingRandom);
mock.Setup(x => x.Next(Count)).Returns(1);
mock.Setup(x => x.Next(Count - 1)).Returns(1);
mock.Setup(x => x.Next(Count - 2)).Returns(6);
mock.Setup(x => x.Next(Count - 3)).Returns(6);
mock.Setup(x => x.Next(Count - 4)).Returns(3);
mock.Setup(x => x.Next(Count - 5)).Returns(4);
mock.Setup(x => x.Next(Count - 6)).Returns(4);
mock.Setup(x => x.Next(Count - 7)).Returns(3);
mock.Setup(x => x.Next(Count - 8)).Returns(1);
mock.Setup(x => x.Next(Count - 9)).Returns(1);
// Act
var result = Invoke(_collection, 10, allowDuplicates: false);
// Assert
Assert.That(result, Is.EqualTo(new[] { "1", "10", "6", "8", "3", "4", "5", "7", "9", "2" }));
}
[Test]
public void GetItems_PickAllItemsWithoutDuplicates_ReturnOriginalCollectionShuffledWithoutDuplicates()
{
// Arrange
var shuffled = new[] { "9", "0", "4", "2", "3", "7", "5", "8", "6", "10", "1" };
Mock.Get(_underlyingRandom)
.Setup(x => x.Shuffle(It.IsAny<IList<string>>()))
.Callback<IList<string>>(x =>
{
for (int i = 0; i < shuffled.Length; i++)
{
x[i] = shuffled[i];
}
});
// Act
var result = Invoke(_collection, 11, allowDuplicates: false);
// Assert
Assert.That(result, Is.EqualTo(shuffled));
Mock.Get(_underlyingRandom).Verify(x => x.Next(It.IsAny<int>()), Times.Never);
}
[Test]
public void GetItems_PickMoreItemsThenOriginalHaveWithoutDuplicates_ReturnOriginalShuffledOriginalCollectionWithoutDuplicates()
{
// Arrange
var shuffled = new[] { "9", "0", "4", "2", "3", "7", "5", "8", "6", "10", "1" };
Mock.Get(_underlyingRandom)
.Setup(x => x.Shuffle(It.IsAny<IList<string>>()))
.Callback<IList<string>>(x =>
{
for (int i = 0; i < shuffled.Length; i++)
{
x[i] = shuffled[i];
}
});
// Act
var result = Invoke(_collection, 30, allowDuplicates: false);
// Assert
Assert.That(result, Is.EqualTo(shuffled));
Mock.Get(_underlyingRandom).Verify(x => x.Next(It.IsAny<int>()), Times.Never);
}
/// <summary> Create concrete collection for tests. </summary>
protected abstract T CreateCollection();
/// <summary> Invoke method under test. Separate implementation types will have different overrides to be tested. </summary>
protected abstract IReadOnlyCollection<string> Invoke(T collection, int count, bool allowDuplicates);
}