using Moq; using NUnit.Framework; using Robust.Shared.Collections; using Robust.Shared.Random; namespace Robust.Shared.Tests.Random; /// Instantiable tests for . [TestFixture] internal sealed class RandomExtensionsGetItemsWithListTests : RandomExtensionsTests> { /// protected override IList CreateCollection() => new List(CollectionForTests); /// protected override IReadOnlyCollection Invoke(IList collection, int count, bool allowDuplicates) => _underlyingRandom.GetItems(collection, count, allowDuplicates); } /// Instantiable tests for . [TestFixture] internal sealed class RandomExtensionsGetItemsWithSpanTests : RandomExtensionsTests { /// protected override string[] CreateCollection() => CollectionForTests; /// protected override IReadOnlyCollection Invoke(string[] collection, int count, bool allowDuplicates) { var span = new Span(collection); return _underlyingRandom.GetItems(span, count, allowDuplicates) .ToArray(); } } /// Instantiable tests for . [TestFixture] internal sealed class RandomExtensionsGetItemsWithValueListTests : RandomExtensionsTests> { /// protected override ValueList CreateCollection() => new ValueList(CollectionForTests); /// protected override IReadOnlyCollection Invoke(ValueList collection, int count, bool allowDuplicates) => _underlyingRandom.GetItems(collection, count, allowDuplicates) .ToArray(); } [TestFixture] internal abstract class RandomExtensionsTests { 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(); _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>())) .Callback>(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()), 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>())) .Callback>(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()), Times.Never); } /// Create concrete collection for tests. protected abstract T CreateCollection(); /// Invoke method under test. Separate implementation types will have different overrides to be tested. protected abstract IReadOnlyCollection Invoke(T collection, int count, bool allowDuplicates); }