using System.Linq; using System.Reactive.Linq; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Wabbajack.Common.CSP; namespace Wabbajack.Test.CSP { [TestClass] public class ChannelTests { [TestMethod] public async Task PutThenTakeNoBuffer() { var chan = Channel.Create(); var putter = chan.Put(42); var taker = chan.Take(); Assert.IsTrue(await putter); Assert.AreEqual((true, 42), await taker); } [TestMethod] public async Task TakeThenPushNoBuffer() { var chan = Channel.Create(); var taker = chan.Take(); var putter = chan.Put(42); Assert.IsTrue(await putter); Assert.AreEqual((true, 42), await taker); } [TestMethod] public async Task TakeFromBufferAfterPut() { var chan = Channel.Create(1); var putter = chan.Put(42); var taker = chan.Take(); Assert.IsTrue(await putter); Assert.AreEqual((true, 42), await taker); } [TestMethod] public async Task TakeFromBufferBeforePut() { var chan = Channel.Create(1); var taker = chan.Take(); var putter = chan.Put(42); Assert.IsTrue(await putter); Assert.AreEqual((true, 42), await taker); } [TestMethod] public async Task TakesAreReleasedAfterClose() { var chan = Channel.Create(); var taker = chan.Take(); chan.Close(); Assert.AreEqual((false, 0), await taker); } [TestMethod] public async Task ExpandingTransformsReleaseMultipleTakes() { var chan = Channel.Create(1, i => i.SelectMany(len => Enumerable.Range(0, len))); var take1 = chan.Take(); var take2 = chan.Take(); await chan.Put(2); Assert.AreEqual((true, 0), await take1); Assert.AreEqual((true, 1), await take2); } [TestMethod] public async Task TransformsCanCloseChannel() { var chan = Channel.Create(1, i => i.Take(1)); var take1 = chan.Take(); var take2 = chan.Take(); await chan.Put(1); await chan.Put(2); Assert.IsTrue(chan.IsClosed); Assert.AreEqual((true, 1), await take1); Assert.AreEqual((false, 0), await take2); } [TestMethod] public async Task TransformsCanCloseDuringExpand() { var chan = Channel.Create(1, i => i.SelectMany(len => Enumerable.Range(1, len)).Take(1)); var take1 = chan.Take(); var take2 = chan.Take(); await chan.Put(2); Assert.IsTrue(chan.IsClosed); Assert.AreEqual((true, 1), await take1); Assert.AreEqual((false, 0), await take2); } [TestMethod] public async Task TransformsCanFilterTakeFirst() { var chan = Channel.Create(1, i => i.Where(x => x == 2)); var take1 = chan.Take(); var take2 = chan.Take(); await chan.Put(1); await chan.Put(2); chan.Close(); Assert.IsTrue(chan.IsClosed); Assert.AreEqual((true, 2), await take1); Assert.AreEqual((false, 0), await take2); } [TestMethod] public async Task TransformsCanReturnNothingTakeFirst() { var chan = Channel.Create(1, i => i.Take(0)); var take1 = chan.Take(); var take2 = chan.Take(); await chan.Put(1); Assert.IsTrue(chan.IsClosed); Assert.AreEqual((false, 0), await take1); Assert.AreEqual((false, 0), await take2); } [TestMethod] public async Task TransformsCanFilterTakeAfter() { var chan = Channel.Create(1, i => i.Where(x => x == 2)); await chan.Put(1); await chan.Put(2); var take1 = chan.Take(); var take2 = chan.Take(); chan.Close(); Assert.IsTrue(chan.IsClosed); Assert.AreEqual((true, 2), await take1); Assert.AreEqual((false, 0), await take2); } [TestMethod] public async Task TransformsCanReturnNothingTakeAfter() { var chan = Channel.Create(1, i => i.Take(0)); await chan.Put(1); var take1 = chan.Take(); var take2 = chan.Take(); Assert.IsTrue(chan.IsClosed); Assert.AreEqual((false, 0), await take1); Assert.AreEqual((false, 0), await take2); } [TestMethod] public void TooManyTakesCausesException() { var chan = Channel.Create(); Assert.ThrowsException.TooManyHanldersException>(() => { for (var x = 0; x < ManyToManyChannel.MAX_QUEUE_SIZE + 1; x++) chan.Take(); }); } [TestMethod] public void TooManyPutsCausesException() { var chan = Channel.Create(); Assert.ThrowsException.TooManyHanldersException>(() => { for (var x = 0; x < ManyToManyChannel.MAX_QUEUE_SIZE + 1; x++) chan.Put(x); }); } [TestMethod] public async Task BlockingPutsGoThroughTransform() { var chan = Channel.Create(1, i => i.Take(2)); var put1 = chan.Put(1); var put2 = chan.Put(2); var put3 = chan.Put(3); var put4 = chan.Put(4); var take1 = chan.Take(); var take2 = chan.Take(); var take3 = chan.Take(); Assert.AreEqual((true, 1), await take1); Assert.AreEqual((true, 2), await take2); Assert.AreEqual((false, 0), await take3); Assert.IsTrue(await put1); Assert.IsTrue(await put2); Assert.IsFalse(await put3); Assert.IsFalse(await put4); Assert.IsTrue(chan.IsClosed); } } }