first commit
This commit is contained in:
162
Nitrox.Test/Model/DataStructures/ThreadSafeListTest.cs
Normal file
162
Nitrox.Test/Model/DataStructures/ThreadSafeListTest.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace NitroxModel.DataStructures
|
||||
{
|
||||
[TestClass]
|
||||
public class ThreadSafeListTest
|
||||
{
|
||||
private ThreadSafeList<string> list;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
list = new ThreadSafeList<string>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
list.Add($"test {i}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Insert()
|
||||
{
|
||||
list.Insert(5, "derp");
|
||||
list[5].Should().Be("derp");
|
||||
list[0] = "Hello world!";
|
||||
list[0].Should().Be("Hello world!");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RemoveAt()
|
||||
{
|
||||
list.RemoveAt(5);
|
||||
foreach (string item in list)
|
||||
{
|
||||
item.Should().NotBe("test 5");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Remove()
|
||||
{
|
||||
list.Remove("test 0");
|
||||
list[0].Should().Be("test 1");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Find()
|
||||
{
|
||||
list.Find(s => s == "test 1").Should().Be("test 1");
|
||||
list.Find(s => s == "tesT 1").Should().BeNull();
|
||||
list.Find(s => s == "test 1361").Should().BeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReadAndWriteSimultaneous()
|
||||
{
|
||||
int iterations = 500000;
|
||||
|
||||
ThreadSafeList<int> comeGetMe = new(iterations);
|
||||
List<long> countsRead = new();
|
||||
long addCount = 0;
|
||||
|
||||
Random r = new Random();
|
||||
DoReaderWriter(() =>
|
||||
{
|
||||
countsRead.Add(Interlocked.Read(ref addCount));
|
||||
},
|
||||
i =>
|
||||
{
|
||||
comeGetMe.Add(r.Next());
|
||||
Interlocked.Increment(ref addCount);
|
||||
},
|
||||
iterations);
|
||||
|
||||
addCount.Should().Be(iterations);
|
||||
countsRead.Count.Should().BeGreaterThan(0);
|
||||
countsRead.Last().Should().Be(iterations);
|
||||
comeGetMe.Count.Should().Be(iterations);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IterateAndAddSimultaneous()
|
||||
{
|
||||
int iterations = 500000;
|
||||
|
||||
ThreadSafeList<int> comeGetMe = new(iterations);
|
||||
long addCount = 0;
|
||||
long iterationsReadMany = 0;
|
||||
|
||||
Random r = new Random();
|
||||
DoReaderWriter(() =>
|
||||
{
|
||||
foreach (int unused in comeGetMe)
|
||||
{
|
||||
Interlocked.Increment(ref iterationsReadMany);
|
||||
}
|
||||
},
|
||||
i =>
|
||||
{
|
||||
comeGetMe.Add(r.Next());
|
||||
Interlocked.Increment(ref addCount);
|
||||
},
|
||||
iterations);
|
||||
|
||||
addCount.Should().Be(iterations);
|
||||
iterationsReadMany.Should().BePositive();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IterateAndAdd()
|
||||
{
|
||||
ThreadSafeList<int> nums = new()
|
||||
{
|
||||
1,2,3,4,5
|
||||
};
|
||||
|
||||
foreach (int num in nums)
|
||||
{
|
||||
if (num == 3)
|
||||
{
|
||||
nums.Add(10);
|
||||
}
|
||||
}
|
||||
|
||||
nums.Count.Should().Be(6);
|
||||
nums.Last().Should().Be(10);
|
||||
}
|
||||
|
||||
private void DoReaderWriter(Action reader, Action<int> writer, int iterators)
|
||||
{
|
||||
ManualResetEventSlim barrier = new(false);
|
||||
Thread readerThread = new(() =>
|
||||
{
|
||||
while (!barrier.IsSet)
|
||||
{
|
||||
reader();
|
||||
Thread.Yield();
|
||||
}
|
||||
|
||||
// Read one last time after writer finishes
|
||||
reader();
|
||||
});
|
||||
Thread writerThread = new(() =>
|
||||
{
|
||||
for (int i = 0; i < iterators; i++)
|
||||
{
|
||||
writer(i);
|
||||
}
|
||||
barrier.Set();
|
||||
});
|
||||
|
||||
readerThread.Start();
|
||||
writerThread.Start();
|
||||
barrier.Wait();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user