Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,107 @@
//
// ActionBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class ActionBlockTest {
[Test]
public void BasicUsageTest ()
{
bool[] array = new bool[3];
var evt = new CountdownEvent (array.Length);
var block = new ActionBlock<int> (i => { array[i] = true; evt.Signal (); });
for (int i = 0; i < array.Length; ++i)
Assert.IsTrue (block.Post (i), "Not accepted");
Assert.IsTrue (evt.Wait (500));
Assert.IsTrue (array.All (b => b), "Some false");
}
[Test]
public void CompleteTest ()
{
var block = new ActionBlock<int> (i => Thread.Sleep (100));
for (int i = 0; i < 10; i++)
Assert.IsTrue (block.Post (i), "Not Accepted");
block.Complete ();
// Still element to be processed so Completion should be false
Assert.IsFalse (block.Completion.IsCompleted);
block.Completion.Wait ();
Assert.IsTrue (block.Completion.IsCompleted);
}
[Test]
public void AsyncNullTest()
{
var scheduler = new TestScheduler ();
var block = new ActionBlock<int> (
i => null,
new ExecutionDataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsTrue (block.Post (1));
scheduler.ExecuteAll ();
Assert.IsFalse (block.Completion.Wait (100));
block.Complete ();
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void AsyncCancelledTest()
{
var scheduler = new TestScheduler ();
var block = new ActionBlock<int> (
i =>
{
var tcs = new TaskCompletionSource<int> ();
tcs.SetCanceled ();
return tcs.Task;
}, new ExecutionDataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsTrue (block.Post (1));
scheduler.ExecuteAll ();
Assert.IsFalse (block.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,452 @@
//
// BatchBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class BatchBlockTest {
[Test]
public void BasicUsageTest ()
{
int[] array = null;
var evt = new ManualResetEventSlim (false);
var buffer = new BatchBlock<int> (10);
var block = new ActionBlock<int[]> (i =>
{
array = i;
evt.Set ();
});
buffer.LinkTo<int[]> (block);
for (int i = 0; i < 9; i++)
Assert.IsTrue (buffer.Post (i));
Assert.IsFalse (evt.Wait (100));
Assert.IsNull (array);
Assert.IsTrue (buffer.Post (42));
Assert.IsTrue (evt.Wait (100));
Assert.IsNotNull (array);
CollectionAssert.AreEqual (new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 42 }, array);
}
[Test]
public void TriggerBatchTest ()
{
int[] array = null;
var evt = new ManualResetEventSlim (false);
var buffer = new BatchBlock<int> (10);
var block = new ActionBlock<int[]> (i =>
{
array = i;
evt.Set ();
});
buffer.LinkTo (block);
for (int i = 0; i < 9; i++)
Assert.IsTrue (buffer.Post (i));
buffer.TriggerBatch ();
evt.Wait ();
Assert.IsNotNull (array);
Assert.IsTrue (buffer.Post (42));
evt.Wait (1600);
CollectionAssert.AreEquivalent (new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
array);
}
[Test]
public void TriggerBatchLateBinding ()
{
int[] array = null;
var evt = new ManualResetEventSlim (false);
var buffer = new BatchBlock<int> (10);
var block = new ActionBlock<int[]> (i =>
{
array = i;
evt.Set ();
});
for (int i = 0; i < 9; i++)
Assert.IsTrue (buffer.Post (i));
buffer.TriggerBatch ();
buffer.LinkTo (block);
evt.Wait ();
Assert.IsNotNull (array);
CollectionAssert.AreEquivalent (new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
array);
}
[Test]
public void LateTriggerBatchKeepCountTest ()
{
int[] array = null;
var evt = new ManualResetEventSlim (false);
var buffer = new BatchBlock<int> (15);
var block = new ActionBlock<int[]> (i =>
{
array = i;
evt.Set ();
});
for (int i = 0; i < 9; i++)
Assert.IsTrue (buffer.Post (i));
buffer.TriggerBatch ();
Assert.IsTrue (buffer.Post (42));
buffer.LinkTo (block);
evt.Wait ();
Assert.IsNotNull (array);
CollectionAssert.AreEquivalent (new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
array);
}
[Test]
public void TriggerBatchWhenEmpty ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (5,
new GroupingDataflowBlockOptions { TaskScheduler = scheduler });
block.TriggerBatch ();
scheduler.ExecuteAll ();
int[] batch;
Assert.IsFalse (block.TryReceive (out batch));
Assert.IsNull (batch);
}
[Test]
public void NonGreedyBatchWithBoundedCapacityTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (2,
new GroupingDataflowBlockOptions
{ Greedy = false, BoundedCapacity = 2, TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block));
Assert.IsNotNull (source2.LinkTo (block));
Assert.IsTrue (source1.Post (11));
Assert.IsTrue (source2.Post (21));
scheduler.ExecuteAll ();
Assert.IsTrue (source1.Post (12));
Assert.IsTrue (source2.Post (22));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.AreEqual (12, i);
Assert.IsTrue (source1.Post (13));
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 11, 21 }, batch);
scheduler.ExecuteAll ();
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 13, 22 }, batch);
}
[Test]
public void GreedyBatchWithBoundedCapacityTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (3,
new GroupingDataflowBlockOptions
{ Greedy = true, BoundedCapacity = 3, TaskScheduler = scheduler });
Assert.IsTrue (block.Post (1));
Assert.IsTrue (block.Post (2));
block.TriggerBatch ();
scheduler.ExecuteAll ();
Assert.IsTrue (block.Post (3));
Assert.IsFalse (block.Post (4));
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEqual (new[] { 1, 2 }, batch);
Assert.IsTrue (block.Post (5));
Assert.IsTrue (block.Post (6));
}
[Test]
public void NonGreedyBatchWithBoundedCapacityTriggerTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (3,
new GroupingDataflowBlockOptions
{ Greedy = false, BoundedCapacity = 3, TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block));
Assert.IsNotNull (source2.LinkTo (block));
// trigger 2 and then trigger 1 with capacity of 3
Assert.IsTrue (source1.Post (11));
Assert.IsTrue (source2.Post (21));
block.TriggerBatch ();
scheduler.ExecuteAll ();
Assert.IsTrue (source1.Post (12));
block.TriggerBatch ();
scheduler.ExecuteAll ();
int i;
Assert.IsFalse (source1.TryReceive (out i));
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 11, 21 }, batch);
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 12 }, batch);
}
[Test]
public void NonGreedyBatchWithBoundedCapacityTriggerTest2 ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (3,
new GroupingDataflowBlockOptions
{ Greedy = false, BoundedCapacity = 3, TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block));
Assert.IsNotNull (source2.LinkTo (block));
// trigger 2, then trigger another 2 and then trigger 2 once more
// while havaing capacity of 3
Assert.IsTrue (source1.Post (11));
Assert.IsTrue (source2.Post (21));
block.TriggerBatch ();
scheduler.ExecuteAll ();
Assert.IsTrue (source1.Post (12));
Assert.IsTrue (source2.Post (22));
block.TriggerBatch ();
scheduler.ExecuteAll ();
Assert.IsTrue (source1.Post (13));
Assert.IsTrue (source2.Post (23));
block.TriggerBatch ();
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.AreEqual (13, i);
Assert.IsTrue (source2.TryReceive (out i));
Assert.AreEqual (23, i);
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 11, 21 }, batch);
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 12, 22 }, batch);
Assert.IsFalse (block.TryReceive (out batch));
}
[Test]
public void MaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (2,
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 2, TaskScheduler = scheduler });
Assert.IsTrue (block.Post (1));
Assert.IsTrue (block.Post (2));
Assert.IsTrue (block.Post (3));
Assert.IsTrue (block.Post (4));
Assert.IsFalse (block.Post (5));
scheduler.ExecuteAll ();
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEqual (new[] { 1, 2 }, batch);
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEqual (new[] { 3, 4 }, batch);
scheduler.ExecuteAll ();
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void CompletionWithTriggerTest ()
{
var block = new BatchBlock<int> (2);
Assert.IsTrue (block.Post (1));
block.TriggerBatch ();
block.Complete ();
CollectionAssert.AreEqual (new[] { 1 },
block.Receive (TimeSpan.FromMilliseconds (200)));
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void CompletionWithoutTriggerTest ()
{
var block = new BatchBlock<int> (2);
Assert.IsTrue (block.Post (1));
Assert.IsTrue (block.Post (2));
block.Complete ();
CollectionAssert.AreEqual (new[] { 1, 2 },
block.Receive (TimeSpan.FromMilliseconds (200)));
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void CompleteTriggersBatchTest ()
{
var block = new BatchBlock<int> (2);
Assert.IsTrue (block.Post (1));
block.Complete ();
CollectionAssert.AreEqual (new[] { 1 },
block.Receive (TimeSpan.FromMilliseconds (200)));
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void NonGreedyCompleteDoesnTriggerBatchTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (2,
new GroupingDataflowBlockOptions
{ Greedy = false, TaskScheduler = scheduler });
var source =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source.LinkTo (block));
Assert.IsTrue (source.Post (1));
block.Complete ();
int[] batch;
Assert.IsFalse (block.TryReceive (out batch));
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void NonGreedyMaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (2,
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 1, Greedy = false, TaskScheduler = scheduler });
ITargetBlock<int> target = block;
var source1 = new TestSourceBlock<int> ();
var source2 = new TestSourceBlock<int> ();
var header1 = new DataflowMessageHeader (1);
source1.AddMessage (header1, 11);
source2.AddMessage (header1, 21);
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header1, 11, source1, false));
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header1, 21, source2, false));
scheduler.ExecuteAll ();
Assert.IsTrue (source1.WasConsumed (header1));
Assert.IsTrue (source2.WasConsumed (header1));
var header2 = new DataflowMessageHeader (2);
Assert.AreEqual (DataflowMessageStatus.DecliningPermanently,
target.OfferMessage (header2, 21, source1, false));
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 11, 21 }, batch);
Assert.IsTrue (block.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,149 @@
// BatchedJoinBlockTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class BatchedJoinBlockTest {
[Test]
public void BasicUsageTest()
{
Tuple<IList<int>, IList<int>> result = null;
var evt = new ManualResetEventSlim (false);
var actionBlock = new ActionBlock<Tuple<IList<int>, IList<int>>> (r =>
{
result = r;
evt.Set ();
});
var block = new BatchedJoinBlock<int, int> (2);
block.LinkTo (actionBlock);
// both targets once
Assert.IsTrue (block.Target1.Post (1));
Assert.IsFalse(evt.Wait(100));
Assert.IsNull (result);
Assert.IsTrue (block.Target2.Post (2));
Assert.IsTrue (evt.Wait (100));
Assert.IsNotNull (result);
CollectionAssert.AreEqual (new[] { 1 }, result.Item1);
CollectionAssert.AreEqual (new[] { 2 }, result.Item2);
result = null;
evt.Reset ();
// target 1 twice
Assert.IsTrue (block.Target1.Post (3));
Assert.IsFalse(evt.Wait(100));
Assert.IsNull (result);
Assert.IsTrue (block.Target1.Post (4));
Assert.IsTrue (evt.Wait (100));
Assert.IsNotNull (result);
CollectionAssert.AreEqual (new[] { 3, 4 }, result.Item1);
CollectionAssert.IsEmpty (result.Item2);
result = null;
evt.Reset ();
// target 2 twice
Assert.IsTrue (block.Target2.Post (5));
Assert.IsFalse(evt.Wait(100));
Assert.IsNull (result);
Assert.IsTrue (block.Target2.Post (6));
Assert.IsTrue (evt.Wait (100));
Assert.IsNotNull (result);
CollectionAssert.IsEmpty (result.Item1);
CollectionAssert.AreEqual (new[] { 5, 6 }, result.Item2);
}
[Test]
public void BoundedCapacityTest ()
{
AssertEx.Throws<ArgumentException> (
() =>
new BatchedJoinBlock<int, int> (2,
new GroupingDataflowBlockOptions { BoundedCapacity = 3 }));
}
[Test]
public void CompletionTest ()
{
var block = new BatchedJoinBlock<int, int> (2);
Assert.IsTrue (block.Target1.Post (1));
block.Complete ();
Tuple<IList<int>, IList<int>> batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEqual (new[] { 1 }, batch.Item1);
CollectionAssert.IsEmpty (batch.Item2);
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void MaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchedJoinBlock<int, int> (1,
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 2, TaskScheduler = scheduler });
Assert.IsTrue (block.Target1.Post (1));
Assert.IsTrue (block.Target2.Post (2));
Assert.IsFalse (block.Target2.Post (3));
Assert.IsFalse (block.Target1.Post (4));
Tuple<IList<int>, IList<int>> batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEqual (new[] { 1 }, batch.Item1);
CollectionAssert.IsEmpty (batch.Item2);
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.IsEmpty (batch.Item1);
CollectionAssert.AreEqual (new[] { 2 }, batch.Item2);
scheduler.ExecuteAll ();
Assert.IsTrue (block.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,131 @@
// BatchedJoinBlockTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class BatchedJoinBlock3Test {
[Test]
public void BasicUsageTest ()
{
Tuple<IList<int>, IList<int>, IList<string>> result = null;
var evt = new ManualResetEventSlim (false);
var actionBlock =
new ActionBlock<Tuple<IList<int>, IList<int>, IList<string>>> (r =>
{
result = r;
evt.Set ();
});
var block = new BatchedJoinBlock<int, int, string> (3);
block.LinkTo (actionBlock);
// all targets once
Assert.IsTrue (block.Target1.Post (1));
Assert.IsTrue (block.Target2.Post (2));
Assert.IsFalse (evt.Wait (100));
Assert.IsNull (result);
Assert.IsTrue (block.Target3.Post ("foo"));
Assert.IsTrue (evt.Wait (100));
Assert.IsNotNull (result);
CollectionAssert.AreEqual (new[] { 1 }, result.Item1);
CollectionAssert.AreEqual (new[] { 2 }, result.Item2);
CollectionAssert.AreEqual (new[] { "foo" }, result.Item3);
}
[Test]
public void BoundedCapacityTest ()
{
AssertEx.Throws<ArgumentException> (
() =>
new BatchedJoinBlock<int, int> (2,
new GroupingDataflowBlockOptions { BoundedCapacity = 3 }));
}
[Test]
public void CompletionTest ()
{
var block = new BatchedJoinBlock<int, int, int> (2);
Assert.IsTrue (block.Target1.Post (1));
block.Complete ();
Tuple<IList<int>, IList<int>, IList<int>> batch;
Assert.IsTrue (block.TryReceive (out batch), batch.ToString ());
CollectionAssert.AreEqual (new[] { 1 }, batch.Item1);
CollectionAssert.IsEmpty (batch.Item2);
CollectionAssert.IsEmpty (batch.Item3);
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void MaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchedJoinBlock<int, int, int> (1,
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 3, TaskScheduler = scheduler });
Assert.IsTrue (block.Target1.Post (1));
Assert.IsTrue (block.Target2.Post (2));
Assert.IsTrue (block.Target3.Post (3));
Assert.IsFalse (block.Target3.Post (4));
Assert.IsFalse (block.Target2.Post (5));
Assert.IsFalse (block.Target1.Post (6));
Tuple<IList<int>, IList<int>, IList<int>> batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEqual (new[] { 1 }, batch.Item1);
CollectionAssert.IsEmpty (batch.Item2);
CollectionAssert.IsEmpty (batch.Item3);
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.IsEmpty (batch.Item1);
CollectionAssert.AreEqual (new[] { 2 }, batch.Item2);
CollectionAssert.IsEmpty (batch.Item3);
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.IsEmpty (batch.Item1);
CollectionAssert.IsEmpty (batch.Item2);
CollectionAssert.AreEqual (new[] { 3 }, batch.Item3);
scheduler.ExecuteAll ();
Assert.IsTrue (block.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,321 @@
// BoundedCapacityTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class BoundedCapacityTest {
[Test]
public void PostTest ()
{
var block =
new BufferBlock<int> (new DataflowBlockOptions { BoundedCapacity = 1 });
Assert.IsTrue (block.Post (1));
Assert.IsFalse (block.Post (2));
Assert.AreEqual (1, block.Receive ());
Assert.IsTrue (block.Post (3));
Assert.AreEqual (3, block.Receive ());
}
[Test]
public void OfferMessageTest ()
{
var block =
new BufferBlock<int> (new DataflowBlockOptions { BoundedCapacity = 1 });
ITargetBlock<int> target = block;
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (new DataflowMessageHeader (1), 42, null, false));
Assert.AreEqual (DataflowMessageStatus.Declined,
target.OfferMessage (new DataflowMessageHeader (2), 43, null, false));
Assert.AreEqual (42, block.Receive ());
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (new DataflowMessageHeader (3), 44, null, false));
Assert.AreEqual (44, block.Receive ());
}
[Test]
public void OfferMessageWithSourceTest ()
{
var block =
new BufferBlock<int> (new DataflowBlockOptions { BoundedCapacity = 1 });
ITargetBlock<int> target = block;
var source = new TestSourceBlock<int> ();
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (new DataflowMessageHeader (1), 42, source, false));
var header = new DataflowMessageHeader (2);
source.AddMessage (header, 43);
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header, 43, source, false));
Assert.AreEqual (42, block.Receive (TimeSpan.FromMilliseconds (100)));
Assert.IsFalse (block.Completion.Wait (100));
Assert.IsTrue (source.WasConsumed (header));
Assert.AreEqual (43, block.Receive (TimeSpan.FromMilliseconds (100)));
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (new DataflowMessageHeader (3), 44, source, false));
Assert.AreEqual (44, block.Receive ());
}
[Test]
public void TransformManyBlockTest ()
{
var block = new TransformManyBlock<int, int> (
i => new[] { -i, i },
new ExecutionDataflowBlockOptions { BoundedCapacity = 1 });
Assert.IsTrue (block.Post (1));
Assert.IsFalse (block.Post (2));
Assert.IsFalse (block.Completion.Wait (100));
Assert.IsFalse (block.Post (3));
Assert.AreEqual (-1, block.Receive ());
Assert.IsFalse (block.Post (4));
Assert.AreEqual (1, block.Receive ());
Assert.IsTrue (block.Post (5));
Assert.AreEqual (-5, block.Receive ());
Assert.AreEqual (5, block.Receive ());
}
[Test]
public void TransformFullTest ()
{
var scheduler = new TestScheduler ();
int n = 0;
var transform = new TransformBlock<int, int> (
i => Interlocked.Increment (ref n),
new ExecutionDataflowBlockOptions
{ BoundedCapacity = 2, TaskScheduler = scheduler });
Assert.IsTrue (transform.Post (1));
Assert.IsTrue (transform.Post (2));
Assert.GreaterOrEqual (scheduler.ExecuteAll (), 1);
Assert.AreEqual (2, Thread.VolatileRead (ref n));
}
[Test]
public void TransformManyOverfullTest ()
{
var scheduler = new TestScheduler ();
int n = 0;
var transform = new TransformManyBlock<int, int> (
i =>
{
Interlocked.Increment (ref n);
return new[] { -i, i };
},
new ExecutionDataflowBlockOptions
{ BoundedCapacity = 2, TaskScheduler = scheduler });
Assert.IsTrue (transform.Post (1));
Assert.IsTrue (transform.Post (2));
Assert.GreaterOrEqual (scheduler.ExecuteAll (), 1);
Assert.AreEqual (2, Thread.VolatileRead (ref n));
}
int n;
[Test]
public void TransformManyOverfullTest2 ()
{
var scheduler = new TestScheduler ();
n = 0;
var transform = new TransformManyBlock<int, int> (
i => ComputeResults (),
new ExecutionDataflowBlockOptions
{ BoundedCapacity = 100, TaskScheduler = scheduler });
for (int i = 0; i < 100; i++)
Assert.IsTrue (transform.Post (i));
Assert.IsFalse (transform.Post (101));
Assert.GreaterOrEqual (scheduler.ExecuteAll (), 1);
Assert.IsFalse (transform.Post (102));
Assert.AreEqual (10000, Thread.VolatileRead (ref n));
}
IEnumerable<int> ComputeResults ()
{
for (int j = 0; j < 100; j++)
yield return Interlocked.Increment (ref n);
}
[Test]
public void MultipleOffersTest ()
{
var scheduler = new TestScheduler ();
var block = new BufferBlock<int> (
new DataflowBlockOptions { BoundedCapacity = 1, TaskScheduler = scheduler });
var target = (ITargetBlock<int>)block;
var source = new TestSourceBlock<int> ();
var header1 = new DataflowMessageHeader (1);
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (header1, 41, source, false));
var header2 = new DataflowMessageHeader (2);
source.AddMessage (header2, 42);
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header2, 42, source, false));
var header3 = new DataflowMessageHeader (3);
source.AddMessage (header3, 43);
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header3, 43, source, false));
Assert.AreEqual (41, block.Receive ());
scheduler.ExecuteAll ();
Assert.IsTrue (source.WasConsumed (header3));
Assert.IsFalse (source.WasConsumed (header2));
}
[Test]
public void DontConsumePostponedAfterCompleteTest ()
{
var scheduler = new TestScheduler ();
var block = new BufferBlock<int> (
new DataflowBlockOptions { BoundedCapacity = 1, TaskScheduler = scheduler });
var target = (ITargetBlock<int>)block;
var source = new TestSourceBlock<int> ();
Assert.IsTrue (block.Post (11));
var header = new DataflowMessageHeader (1);
source.AddMessage (header, 12);
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header, 12, source, false));
block.Complete ();
Assert.AreEqual (11, block.Receive ());
scheduler.ExecuteAll ();
Assert.IsFalse (source.WasConsumed (header));
}
}
class TestSourceBlock<T> : ISourceBlock<T> {
readonly Dictionary<DataflowMessageHeader, T> messages =
new Dictionary<DataflowMessageHeader, T> ();
readonly HashSet<DataflowMessageHeader> consumed =
new HashSet<DataflowMessageHeader> ();
readonly HashSet<DataflowMessageHeader> reserved =
new HashSet<DataflowMessageHeader> ();
public void Complete ()
{
throw new NotImplementedException ();
}
public void Fault (Exception exception)
{
throw new NotImplementedException ();
}
public Task Completion { get; private set; }
public void AddMessage (DataflowMessageHeader header, T item)
{
messages.Add (header, item);
}
public bool WasConsumed (DataflowMessageHeader header)
{
return consumed.Contains (header);
}
public bool WasReserved (DataflowMessageHeader header)
{
return reserved.Contains (header);
}
public Action ConsumeWaiter { get; set; }
public T ConsumeMessage (DataflowMessageHeader messageHeader,
ITargetBlock<T> target, out bool messageConsumed)
{
T item;
if (messages.TryGetValue (messageHeader, out item)) {
if (ConsumeWaiter != null)
ConsumeWaiter ();
messages.Remove (messageHeader);
consumed.Add (messageHeader);
messageConsumed = true;
return item;
}
messageConsumed = false;
return default(T);
}
public IDisposable LinkTo (ITargetBlock<T> target,
DataflowLinkOptions linkOptions)
{
throw new NotImplementedException ();
}
public bool ReserveMessage (DataflowMessageHeader messageHeader,
ITargetBlock<T> target)
{
reserved.Add (messageHeader);
return messages.ContainsKey (messageHeader);
}
public void ReleaseReservation (DataflowMessageHeader messageHeader,
ITargetBlock<T> target)
{
throw new NotImplementedException ();
}
}
}

View File

@ -0,0 +1,352 @@
//
// BroadcastBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class BroadcastBlockTest {
[Test]
public void BasicUsageTest ()
{
bool act1 = false, act2 = false;
var evt = new CountdownEvent (2);
var broadcast = new BroadcastBlock<int> (null);
var action1 = new ActionBlock<int> (i =>
{
act1 = i == 42;
evt.Signal ();
});
var action2 = new ActionBlock<int> (i =>
{
act2 = i == 42;
evt.Signal ();
});
broadcast.LinkTo (action1);
broadcast.LinkTo (action2);
Assert.IsTrue (broadcast.Post (42));
Assert.IsTrue (evt.Wait (100));
Assert.IsTrue (act1);
Assert.IsTrue (act2);
}
[Test]
public void LinkAfterPostTest ()
{
bool act = false;
var evt = new ManualResetEventSlim ();
var broadcast = new BroadcastBlock<int> (null);
var action = new ActionBlock<int> (i =>
{
act = i == 42;
evt.Set ();
});
Assert.IsTrue (broadcast.Post (42));
broadcast.LinkTo (action);
Assert.IsTrue (evt.Wait (100));
Assert.IsTrue (act);
}
[Test]
public void PostponedTest ()
{
var broadcast = new BroadcastBlock<int> (null);
var target = new BufferBlock<int> (
new DataflowBlockOptions { BoundedCapacity = 1 });
broadcast.LinkTo (target);
Assert.IsTrue (target.Post (1));
Assert.IsTrue (broadcast.Post (2));
Assert.AreEqual (1, target.Receive (TimeSpan.FromMilliseconds (0)));
Assert.AreEqual (2, target.Receive (TimeSpan.FromMilliseconds (100)));
}
[Test]
public void ConsumeChangedTest ()
{
var scheduler = new TestScheduler ();
var broadcast = new BroadcastBlock<int> (null,
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new TestTargetBlock<int> { Postpone = true };
broadcast.LinkTo (target);
Assert.IsFalse (target.HasPostponed);
Assert.IsTrue (broadcast.Post (1));
scheduler.ExecuteAll ();
Assert.IsTrue (target.HasPostponed);
Assert.IsTrue (broadcast.Post (2));
scheduler.ExecuteAll ();
int value;
Assert.IsTrue (target.RetryPostponed (out value));
Assert.AreEqual (2, value);
}
[Test]
public void ReserveConsumeChangedTest ()
{
var scheduler = new TestScheduler ();
var broadcast = new BroadcastBlock<int> (null,
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new TestTargetBlock<int> { Postpone = true };
broadcast.LinkTo (target);
Assert.IsFalse (target.HasPostponed);
Assert.IsTrue (broadcast.Post (1));
scheduler.ExecuteAll ();
Assert.IsTrue (target.HasPostponed);
Assert.IsTrue (target.ReservePostponed ());
Assert.IsTrue (broadcast.Post (2));
scheduler.ExecuteAll ();
int value;
Assert.IsTrue (target.RetryPostponed (out value));
Assert.AreEqual (1, value);
}
[Test]
public void ReserveChangedTest ()
{
var scheduler = new TestScheduler ();
var broadcast = new BroadcastBlock<int> (null,
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new TestTargetBlock<int> { Postpone = true };
broadcast.LinkTo (target);
Assert.IsFalse (target.HasPostponed);
Assert.IsTrue (broadcast.Post (1));
scheduler.ExecuteAll ();
Assert.IsTrue (target.HasPostponed);
Assert.IsTrue(broadcast.Post(2));
scheduler.ExecuteAll ();
Assert.IsTrue (target.ReservePostponed ());
int value;
Assert.IsTrue (target.RetryPostponed (out value));
Assert.AreEqual (2, value);
}
[Test]
public void QueuedMessagesTest ()
{
var scheduler = new TestScheduler ();
var broadcast = new BroadcastBlock<int> (null,
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int> ();
broadcast.LinkTo (target);
Assert.IsTrue (broadcast.Post (1));
Assert.IsTrue (broadcast.Post (2));
AssertEx.Throws<TimeoutException> (
() => target.Receive (TimeSpan.FromMilliseconds (100)));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (1, item);
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (2, item);
}
[Test]
public void BoundedQueuedTest ()
{
var scheduler = new TestScheduler ();
var broadcast = new BroadcastBlock<int> (
null,
new DataflowBlockOptions { TaskScheduler = scheduler, BoundedCapacity = 1 });
Assert.IsTrue (broadcast.Post (1));
Assert.IsFalse (broadcast.Post (2));
}
[Test]
public void BoundedPostponedTest ()
{
var scheduler = new TestScheduler ();
var broadcast = new BroadcastBlock<int> (
null,
new DataflowBlockOptions { TaskScheduler = scheduler, BoundedCapacity = 1 });
ITargetBlock<int> target = broadcast;
var source = new TestSourceBlock<int> ();
Assert.IsTrue (broadcast.Post (1));
var header = new DataflowMessageHeader (1);
source.AddMessage (header, 2);
Assert.AreEqual (DataflowMessageStatus.Postponed,
target.OfferMessage (header, 2, source, false));
Assert.IsFalse (source.WasConsumed (header));
scheduler.ExecuteAll ();
Assert.IsTrue (source.WasConsumed (header));
}
[Test]
public void CloningTest ()
{
object act1 = null, act2 = null;
var evt = new CountdownEvent (2);
object source = new object ();
var broadcast = new BroadcastBlock<object> (o => new object ());
var action1 = new ActionBlock<object> (i =>
{
act1 = i;
evt.Signal ();
});
var action2 = new ActionBlock<object> (i =>
{
act2 = i;
evt.Signal ();
});
broadcast.LinkTo (action1);
broadcast.LinkTo (action2);
Assert.IsTrue (broadcast.Post (source));
Assert.IsTrue (evt.Wait (100));
Assert.IsNotNull (act1);
Assert.IsNotNull (act2);
Assert.IsFalse (source.Equals (act1));
Assert.IsFalse (source.Equals (act2));
Assert.IsFalse (act2.Equals (act1));
}
[Test]
public void TryReceiveTest()
{
var scheduler = new TestScheduler();
var block = new BroadcastBlock<int>(i => i * 10, new DataflowBlockOptions { TaskScheduler = scheduler });
int item;
Assert.IsFalse(block.TryReceive(null, out item));
Assert.IsTrue(block.Post(1));
Assert.IsTrue(block.Post(2));
scheduler.ExecuteAll();
Assert.IsTrue(block.TryReceive(null, out item));
Assert.AreEqual(20, item);
// predicate is tested on original value, but returned is cloned
Assert.IsTrue(block.TryReceive(i => i < 10, out item));
Assert.AreEqual(20, item);
}
[Test]
public void TryReceiveAllTest()
{
var scheduler = new TestScheduler();
var block = new BroadcastBlock<int>(null, new DataflowBlockOptions { TaskScheduler = scheduler });
IReceivableSourceBlock<int> source = block;
Assert.IsTrue(block.Post(1));
Assert.IsTrue(block.Post(2));
scheduler.ExecuteAll();
IList<int> items;
Assert.IsTrue(source.TryReceiveAll(out items));
CollectionAssert.AreEqual(new[] { 2 }, items);
}
[Test]
public void DontOfferTwiceTest()
{
var scheduler = new TestScheduler ();
var block = new BroadcastBlock<int> (null,
new DataflowBlockOptions { TaskScheduler = scheduler });
var target =
new TestTargetBlock<int> { Postpone = true };
block.LinkTo (target);
Assert.IsFalse (target.HasPostponed);
Assert.IsTrue (block.Post (1));
scheduler.ExecuteAll();
Assert.IsTrue (target.HasPostponed);
target.Postpone = false;
int value;
Assert.IsTrue(target.RetryPostponed(out value));
Assert.AreEqual(1, value);
block.LinkTo(new BufferBlock<int>());
scheduler.ExecuteAll();
Assert.AreEqual(default(int), target.DirectlyAccepted);
}
}
}

View File

@ -0,0 +1,123 @@
//
// BufferBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class BufferBlockTest {
[Test]
public void BasicUsageTest ()
{
int data = -1;
var evt = new ManualResetEventSlim (false);
var buffer = new BufferBlock<int> ();
var action = new ActionBlock<int> (i =>
{
data = i;
evt.Set ();
});
buffer.LinkTo (action);
Assert.IsTrue (buffer.Post (42));
evt.Wait ();
Assert.AreEqual (42, data);
}
[Test]
public void LateBindingTest ()
{
var buffer = new BufferBlock<int> ();
var evt = new CountdownEvent (10);
for (int i = 0; i < 10; i++)
Assert.IsTrue (buffer.Post (i));
var block = new ActionBlock<int> (i => evt.Signal ());
buffer.LinkTo (block);
evt.Wait ();
}
[Test]
public void MultipleBindingTest ()
{
var buffer = new BufferBlock<int> ();
var evt = new CountdownEvent (10);
int count = 0;
var block = new ActionBlock<int> (i =>
{
Interlocked.Decrement (ref count);
evt.Signal ();
});
IDisposable bridge = buffer.LinkTo (block);
for (int i = 0; i < 10; i++)
Assert.IsTrue (buffer.Post (i));
evt.Wait ();
Assert.AreEqual (-10, count);
count = 0;
evt.Reset ();
bridge.Dispose ();
var block2 = new ActionBlock<int> (i =>
{
Interlocked.Increment (ref count);
evt.Signal ();
});
buffer.LinkTo (block2);
for (int i = 0; i < 10; i++)
Assert.IsTrue (buffer.Post (i));
evt.Wait ();
Assert.AreEqual (10, count);
}
[Test]
public void ConsumeToAcceptTest ()
{
var source = new TestSourceBlock<int> ();
var buffer = new BufferBlock<int> ();
var target = (ITargetBlock<int>)buffer;
var header = new DataflowMessageHeader (1);
source.AddMessage (header, 1);
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (header, 1, source, true));
Assert.IsTrue (source.WasConsumed (header));
Assert.IsFalse (source.WasReserved (header));
}
}
}

View File

@ -0,0 +1,217 @@
// DataflowBlockTest.cs
//
// Author:
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class ChooseTest {
[Test]
public void BasicTest ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<long> ();
bool action1 = false;
bool action2 = false;
var completion = DataflowBlock.Choose (
source1, _ => action1 = true,
source2, _ => action2 = true);
source1.Post (42);
Assert.IsTrue (completion.Wait (500));
Assert.AreEqual (0, completion.Result);
Assert.IsTrue (action1);
Assert.IsFalse (action2);
}
[Test]
public void OnlyOneConsumedTest ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<long> ();
int action1 = 0;
int action2 = 0;
var completion = DataflowBlock.Choose (
source1, _ => action1++,
source2, _ => action2++);
source1.Post (42);
source1.Post (43);
Assert.IsTrue (completion.Wait (500));
Assert.AreEqual (0, completion.Result);
Assert.AreEqual (1, action1);
Assert.AreEqual (0, action2);
int item;
Assert.IsTrue (source1.TryReceive (out item));
Assert.AreEqual (43, item);
}
[Test]
public void RaceTest ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<int> ();
int action1 = 0;
int action2 = 0;
var completion = DataflowBlock.Choose (
source1, _ => action1++,
source2, _ => action2++);
var barrier = new Barrier (2);
var t1 = Task.Run (() =>
{
barrier.SignalAndWait ();
source1.Post (10);
});
var t2 = Task.Run (() =>
{
barrier.SignalAndWait ();
source2.Post (20);
});
Task.WaitAll (t1, t2);
Assert.IsTrue (completion.Wait (500));
Assert.AreEqual (1, action1 + action2);
int item;
Assert.IsTrue (source1.TryReceive (out item) || source2.TryReceive (out item));
}
[Test]
public void BlockCompletionTest ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<long> ();
var completion = DataflowBlock.Choose (
source1, _ => { }, source2, _ => { });
Assert.IsFalse (completion.IsCanceled);
((IDataflowBlock)source1).Fault (new Exception ());
source2.Complete ();
Thread.Sleep (100);
Assert.IsTrue (completion.IsCanceled);
}
[Test]
public void CancellationTest ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<long> ();
var tokenSource = new CancellationTokenSource ();
var options = new DataflowBlockOptions
{ CancellationToken = tokenSource.Token };
var completion = DataflowBlock.Choose (
source1, _ => { }, source2, _ => { }, options);
Assert.IsFalse (completion.IsCanceled);
tokenSource.Cancel ();
Thread.Sleep (100);
Assert.IsTrue (completion.IsCanceled);
}
[Test]
public void ConsumeToAcceptTest ()
{
var source1 = new BroadcastBlock<int> (_ => 42);
var source2 = new BufferBlock<int> ();
int action1 = 0;
int action2 = 0;
var completion = DataflowBlock.Choose (
source1, i => action1 = i,
source2, i => action2 = i);
source1.Post (10);
Assert.IsTrue (completion.Wait (500));
Assert.AreEqual (0, completion.Result);
Assert.AreEqual (42, action1);
Assert.AreEqual (0, action2);
}
[Test]
public void ExceptionTest ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<long> ();
var exception = new Exception ();
var completion = DataflowBlock.Choose (
source1, _ => { throw exception; },
source2, _ => { });
source1.Post (42);
var ae = AssertEx.Throws<AggregateException> (() => completion.Wait (500));
Assert.AreEqual (1, ae.InnerExceptions.Count);
Assert.AreSame (exception, ae.InnerException);
}
[Test]
public void BasicTest_3 ()
{
var source1 = new BufferBlock<int> ();
var source2 = new BufferBlock<long> ();
var source3 = new BufferBlock<object> ();
bool action1 = false;
bool action2 = false;
bool action3 = false;
var completion = DataflowBlock.Choose (
source1, _ => action1 = true,
source2, _ => action2 = true,
source3, _ => action3 = true);
source3.Post (new object ());
Assert.IsTrue (completion.Wait (500));
Assert.AreEqual (2, completion.Result);
Assert.IsFalse (action1);
Assert.IsFalse (action2);
Assert.IsTrue (action3);
}
}
}

View File

@ -0,0 +1,81 @@
//
// CompletionHelperTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow
{
[TestFixture]
public class CompletionHelperTest
{
CompletionHelper helper;
[SetUp]
public void Setup ()
{
helper = CompletionHelper.GetNew (null);
}
[Test]
public void InitialStateTest ()
{
Task completed = helper.Completion;
Assert.IsNotNull (completed);
Assert.IsFalse (completed.IsCompleted);
}
[Test]
public void FaultedTest ()
{
Exception ex = new ApplicationException ("Foobar");
helper.RequestFault (ex);
Task completed = helper.Completion;
Assert.IsNotNull (completed);
Assert.IsTrue (completed.IsCompleted);
Assert.AreEqual (TaskStatus.Faulted, completed.Status);
Assert.AreEqual (ex, completed.Exception.InnerExceptions.First ());
}
[Test]
public void CompleteTest ()
{
helper.Complete ();
Task completed = helper.Completion;
Assert.IsNotNull (completed);
Assert.IsTrue (completed.IsCompleted);
Assert.IsFalse (completed.IsFaulted);
Assert.IsFalse (completed.IsCanceled);
}
}
}

View File

@ -0,0 +1,382 @@
//
// CompletionTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
using System.Linq;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class CompletionTest {
[Test]
public void WithElementsStillLingering ()
{
var block = new BufferBlock<int> ();
Assert.IsTrue (block.Post (42));
block.Complete ();
Assert.IsFalse (block.Completion.Wait (100));
Assert.IsFalse (block.Completion.IsCompleted);
Assert.AreEqual (TaskStatus.WaitingForActivation, block.Completion.Status);
Assert.AreEqual (42, block.Receive ());
Assert.IsTrue (block.Completion.Wait (100));
Assert.IsTrue (block.Completion.IsCompleted);
Assert.AreEqual (TaskStatus.RanToCompletion, block.Completion.Status);
}
[Test]
public void WithElementsStillLingeringButFaulted ()
{
var block = new BufferBlock<int> ();
Assert.IsTrue (block.Post (42));
((IDataflowBlock)block).Fault (new Exception ());
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.IsTrue (block.Completion.IsCompleted);
Assert.AreEqual (TaskStatus.Faulted, block.Completion.Status);
Assert.IsFalse (block.Post (43));
}
[Test]
public void WithElementsStillLingeringButCancelled ()
{
var tokenSource = new CancellationTokenSource ();
var block = new BufferBlock<int> (
new DataflowBlockOptions { CancellationToken = tokenSource.Token });
Assert.IsTrue (block.Post (42));
tokenSource.Cancel ();
var ae = AssertEx.Throws<AggregateException> (
() => block.Completion.Wait (100));
Assert.AreEqual (1, ae.InnerExceptions.Count);
Assert.AreEqual (typeof(TaskCanceledException), ae.InnerException.GetType ());
Assert.IsTrue (block.Completion.IsCompleted);
Assert.AreEqual (TaskStatus.Canceled, block.Completion.Status);
Assert.IsFalse (block.Post (43));
}
static IEnumerable<Tuple<IDataflowBlock, ITargetBlock<T>>>
GetJoinBlocksWithTargets<T> ()
{
Func<IDataflowBlock, ITargetBlock<T>, Tuple<IDataflowBlock, ITargetBlock<T>>>
createTuple = Tuple.Create;
var joinBlock = new JoinBlock<T, T> ();
yield return createTuple (joinBlock, joinBlock.Target1);
var joinBlock3 = new JoinBlock<T, T, T> ();
yield return createTuple (joinBlock3, joinBlock3.Target1);
var batchedJoinBlock = new BatchedJoinBlock<T, T> (2);
yield return createTuple (batchedJoinBlock, batchedJoinBlock.Target1);
var batchedJoinBlock3 = new BatchedJoinBlock<T, T, T> (2);
yield return createTuple (batchedJoinBlock3, batchedJoinBlock3.Target1);
}
[Test]
public void JoinTargetCompletitionTest ()
{
foreach (var tuple in GetJoinBlocksWithTargets<int> ()) {
AssertEx.Throws<NotSupportedException> (
() => { var x = tuple.Item2.Completion; });
Assert.IsTrue (tuple.Item2.Post (1));
tuple.Item2.Complete ();
Assert.IsFalse (tuple.Item2.Post (2));
}
foreach (var tuple in GetJoinBlocksWithTargets<int> ()) {
Assert.IsTrue (tuple.Item2.Post (1));
tuple.Item1.Complete ();
Assert.IsFalse (tuple.Item2.Post (2));
}
}
[Test]
public void MultipleFaultsTest ()
{
IDataflowBlock block = new BufferBlock<int> ();
block.Fault (new Exception ("1"));
// second exception should be ignored
block.Fault (new Exception ("2"));
Thread.Sleep (100);
Assert.IsTrue (block.Completion.IsFaulted);
var exception = block.Completion.Exception;
Assert.IsNotNull (exception);
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual ("1", exception.InnerException.Message);
}
[Test]
public void MultipleFaultsWhileExecutingTest ()
{
var evt = new ManualResetEventSlim ();
var actionBlock = new ActionBlock<int> (_ => evt.Wait ());
IDataflowBlock dataflowBlock = actionBlock;
actionBlock.Post (1);
Thread.Sleep (100);
dataflowBlock.Fault (new Exception ("1"));
// second exception should still be ignored
dataflowBlock.Fault (new Exception ("2"));
Thread.Sleep (100);
Assert.IsFalse (actionBlock.Completion.IsCompleted);
evt.Set ();
Thread.Sleep (100);
Assert.IsTrue (actionBlock.Completion.IsFaulted);
var exception = actionBlock.Completion.Exception;
Assert.IsNotNull (exception);
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual ("1", exception.InnerException.Message);
}
[Test]
public void MultipleExceptionsTest ()
{
// use barrier to make sure both threads have time to start
var barrier = new Barrier (2);
var block = new ActionBlock<int> (
_ =>
{
barrier.SignalAndWait ();
throw new Exception ();
},
// strictly speaking, the actions are not guaranteed to run in parallel,
// but there is no way to test this otherwise
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = -1 });
block.Post (1);
block.Post (2);
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (1000));
Assert.AreEqual (2, exception.InnerExceptions.Count);
}
[Test]
public void ExceptionAndFaultTest ()
{
var block = new ActionBlock<int> (
_ => { throw new Exception ("action"); },
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = -1 });
block.Post (1);
Thread.Sleep (100);
((IDataflowBlock)block).Fault (new Exception ("fault"));
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual ("action", exception.InnerException.Message);
}
[Test]
public void FaultAndExceptionTest ()
{
var evt = new ManualResetEventSlim ();
var block = new ActionBlock<int> (
_ =>
{
evt.Wait ();
throw new Exception ("action");
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = -1 });
block.Post (1);
Thread.Sleep (100);
((IDataflowBlock)block).Fault (new Exception ("fault1"));
((IDataflowBlock)block).Fault (new Exception ("fault2"));
evt.Set ();
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (2, exception.InnerExceptions.Count);
CollectionAssert.AreEqual (new[] { "fault1", "action" },
exception.InnerExceptions.Select (e => e.Message).ToArray ());
}
[Test]
public void ExceptionAndCancelTest ()
{
var tokenSource = new CancellationTokenSource ();
var block = new ActionBlock<int> (
_ => { throw new Exception ("action"); },
new ExecutionDataflowBlockOptions
{ MaxDegreeOfParallelism = -1, CancellationToken = tokenSource.Token });
block.Post (1);
Thread.Sleep (100);
tokenSource.Cancel ();
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual ("action", exception.InnerException.Message);
}
[Test]
public void CancelAndExceptionTest ()
{
var tokenSource = new CancellationTokenSource ();
var evt = new ManualResetEventSlim ();
var block = new ActionBlock<int> (
_ =>
{
evt.Wait ();
throw new Exception ("action");
},
new ExecutionDataflowBlockOptions
{ MaxDegreeOfParallelism = -1, CancellationToken = tokenSource.Token });
block.Post (1);
Thread.Sleep (100);
tokenSource.Cancel ();
evt.Set ();
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual ("action", exception.InnerException.Message);
}
[Test]
public void CancelAndFaultTest ()
{
var tokenSource = new CancellationTokenSource ();
var block = new BufferBlock<int> (
new DataflowBlockOptions { CancellationToken = tokenSource.Token });
tokenSource.Cancel ();
Thread.Sleep (100);
((IDataflowBlock)block).Fault (new Exception ("fault"));
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual (typeof(TaskCanceledException),
exception.InnerException.GetType ());
}
[Test]
public void CancelAndFaultWhileExecutingTest ()
{
var tokenSource = new CancellationTokenSource ();
var evt = new ManualResetEventSlim ();
var block = new ActionBlock<int> (
_ => evt.Wait (),
new ExecutionDataflowBlockOptions
{ MaxDegreeOfParallelism = -1, CancellationToken = tokenSource.Token });
block.Post (1);
Thread.Sleep (100);
tokenSource.Cancel ();
Thread.Sleep (100);
((IDataflowBlock)block).Fault (new Exception ("fault"));
evt.Set ();
Thread.Sleep (100);
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual (typeof(TaskCanceledException),
exception.InnerException.GetType ());
}
[Test]
public void FaultAndCancelWhileExecutingTest ()
{
var tokenSource = new CancellationTokenSource ();
var evt = new ManualResetEventSlim ();
var block = new ActionBlock<int> (
_ => evt.Wait (),
new ExecutionDataflowBlockOptions
{ MaxDegreeOfParallelism = -1, CancellationToken = tokenSource.Token });
block.Post (1);
Thread.Sleep (100);
((IDataflowBlock)block).Fault (new Exception ("fault"));
Thread.Sleep (100);
tokenSource.Cancel ();
evt.Set ();
Thread.Sleep (100);
var exception =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, exception.InnerExceptions.Count);
Assert.AreEqual ("fault", exception.InnerException.Message);
}
}
}

View File

@ -0,0 +1,324 @@
// DataflowBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class DataflowBlockTest {
[Test]
public void TryReceiveTest ()
{
var block = new BufferBlock<int> ();
int value = -1;
block.Post (42);
Thread.Sleep (500);
Assert.IsTrue (block.TryReceive (out value));
Assert.AreEqual (42, value);
}
[Test]
public void ReceiveTest ()
{
var block = new BufferBlock<int> ();
Task.Factory.StartNew (() => { Thread.Sleep (300); block.Post (42); });
Assert.AreEqual (42, block.Receive ());
}
[Test]
public void ReceiveCompletedTest ()
{
var block = new BufferBlock<int> ();
block.Complete ();
AssertEx.Throws<InvalidOperationException> (
() => block.Receive (TimeSpan.FromMilliseconds (100)));
}
[Test]
public void ReceiveTimeoutTest ()
{
var block = new BufferBlock<int> ();
AssertEx.Throws<TimeoutException> (
() => block.Receive (TimeSpan.FromMilliseconds (100)));
}
[Test]
public void ReceiveCancelledTest ()
{
var block = new BufferBlock<int> ();
var tokenSource = new CancellationTokenSource (200);
AssertEx.Throws<OperationCanceledException> (
() => block.Receive (tokenSource.Token));
}
[Test]
public void AsyncReceiveTest ()
{
int result = -1;
var mre = new ManualResetEventSlim (false);
var block = new WriteOnceBlock<int> (null);
block.ReceiveAsync ().ContinueWith (i =>
{
result = i.Result;
mre.Set ();
});
Task.Factory.StartNew (() =>
{
Thread.Sleep (100);
block.Post (42);
});
Assert.IsTrue (mre.Wait (1000));
Assert.AreEqual (42, result);
}
[Test]
public void AsyncReceiveTestCanceled ()
{
var src = new CancellationTokenSource ();
var block = new WriteOnceBlock<int> (null);
var task = block.ReceiveAsync (src.Token);
Task.Factory.StartNew (() =>
{
Thread.Sleep (800);
block.Post (42);
});
Thread.Sleep (50);
src.Cancel ();
AggregateException ex = null;
try {
task.Wait ();
} catch (AggregateException e) {
ex = e;
}
Assert.IsNotNull (ex);
Assert.IsNotNull (ex.InnerException);
Assert.IsInstanceOfType (typeof(OperationCanceledException),
ex.InnerException);
Assert.IsTrue (task.IsCompleted);
Assert.AreEqual (TaskStatus.Canceled, task.Status);
}
[Test]
public void SendAsyncAcceptedTest ()
{
var target = new BufferBlock<int> ();
var task = target.SendAsync (1);
Assert.IsTrue (task.Wait (0));
Assert.IsTrue (task.Result);
}
[Test]
public void SendAsyncDeclinedTest ()
{
var target = new BufferBlock<int> ();
target.Complete ();
var task = target.SendAsync (1);
Assert.IsTrue (task.Wait (0));
Assert.IsFalse (task.Result);
}
[Test]
public void SendAsyncPostponedAcceptedTest ()
{
var target =
new BufferBlock<int> (new DataflowBlockOptions { BoundedCapacity = 1 });
Assert.IsTrue (target.Post (1));
var task = target.SendAsync (1);
Assert.IsFalse (task.Wait (100));
Assert.AreEqual (1, target.Receive ());
Assert.IsTrue (task.Wait (100));
Assert.IsTrue (task.Result);
}
[Test]
public void SendAsyncPostponedDeclinedTest ()
{
var target =
new BufferBlock<int> (new DataflowBlockOptions { BoundedCapacity = 1 });
Assert.IsTrue (target.Post (1));
var task = target.SendAsync (1);
Assert.IsFalse (task.Wait (100));
target.Complete ();
Assert.IsTrue (task.Wait (100));
Assert.IsFalse (task.Result);
}
[Test]
public void LinkToPredicateTest ()
{
var scheduler = new TestScheduler ();
var source = new BufferBlock<int> (
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int> ();
source.LinkTo (target, i => i % 2 == 1);
Assert.IsTrue (source.Post (1));
Assert.IsTrue (source.Post (2));
Assert.IsTrue (source.Post (3));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (1, item);
Assert.IsFalse (target.TryReceive (out item));
Assert.IsTrue (source.TryReceive (out item));
Assert.AreEqual (2, item);
scheduler.ExecuteAll ();
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (3, item);
}
[Test]
public void LinkToPredicateMaxMessagesTest ()
{
var scheduler = new TestScheduler ();
var source = new BufferBlock<int> (
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int> ();
source.LinkTo (target, new DataflowLinkOptions { MaxMessages = 1 },
i => i % 2 == 1);
Assert.IsTrue (source.Post (2));
Assert.IsTrue (source.Post (1));
Assert.IsTrue (source.Post (3));
scheduler.ExecuteAll ();
int item;
Assert.IsFalse (target.TryReceive (out item));
Assert.IsTrue (source.TryReceive (out item));
Assert.AreEqual (2, item);
scheduler.ExecuteAll ();
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (1, item);
scheduler.ExecuteAll ();
Assert.IsFalse (target.TryReceive (out item));
}
[Test]
public void LinkToPredicatePostponed ()
{
var scheduler = new TestScheduler ();
var source = new BufferBlock<int> (
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int> (
new DataflowBlockOptions { BoundedCapacity = 1, TaskScheduler = scheduler });
source.LinkTo (target, i => true);
Assert.IsTrue (target.Post (1));
Assert.IsTrue (source.Post (2));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (1, item);
scheduler.ExecuteAll ();
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (2, item);
}
[Test]
public void LinkToPredicateClonerTest ()
{
var scheduler = new TestScheduler ();
var source = new BroadcastBlock<int> (i => i * 10,
new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int> ();
source.LinkTo (target, i => i < 10);
Assert.IsTrue (source.Post (1));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (10, item);
}
[Test]
public void NullTargetTest ()
{
var target = DataflowBlock.NullTarget<int> ();
Assert.IsTrue (target.Post (1));
var source = new TestSourceBlock<int> ();
var header = new DataflowMessageHeader (1);
source.AddMessage (header, 2);
Assert.IsFalse (source.WasConsumed (header));
Assert.AreEqual (DataflowMessageStatus.Accepted,
target.OfferMessage (header, 2, source, true));
Assert.IsTrue (source.WasConsumed (header));
Assert.IsFalse (target.Completion.Wait (100));
target.Complete ();
Assert.IsFalse (target.Completion.Wait (100));
target.Fault (new Exception ());
Assert.IsFalse (target.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,71 @@
//
// DataflowMessageHeaderTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow
{
[TestFixture]
public class DataflowMessageHeaderTest
{
[Test]
public void EqualityTest ()
{
var header1 = new DataflowMessageHeader (2);
var header2 = new DataflowMessageHeader (5);
var header3 = new DataflowMessageHeader (2);
Assert.AreEqual (header1, header1);
Assert.AreEqual (header1.GetHashCode (), header1.GetHashCode ());
Assert.AreEqual (header1, header3);
Assert.AreEqual (header1.GetHashCode (), header3.GetHashCode ());
Assert.AreNotEqual (header1, header2);
Assert.AreNotEqual (header1.GetHashCode (), header2.GetHashCode ());
}
[Test]
public void ValidityTest ()
{
var header1 = new DataflowMessageHeader ();
var header2 = new DataflowMessageHeader (2);
var header3 = new DataflowMessageHeader (-2);
Assert.IsFalse (header1.IsValid);
Assert.IsTrue (header2.IsValid);
Assert.IsTrue (header3.IsValid);
}
[Test]
public void ZeroIdTest ()
{
AssertEx.Throws<ArgumentException> (() => new DataflowMessageHeader (0));
Assert.AreEqual (0, new DataflowMessageHeader ().Id);
}
}
}

View File

@ -0,0 +1,130 @@
// EncapsulateTest.cs
//
// Author:
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class EncapsulateTest {
[Test]
public void CompletionTest ()
{
var target = new CompletionCheckerBlock<int, int> ();
var source = new CompletionCheckerBlock<int, int> ();
var encapsulated = DataflowBlock.Encapsulate (target, source);
Assert.AreSame (source.Completion, encapsulated.Completion);
}
[Test]
public void CompleteTest ()
{
var target = new CompletionCheckerBlock<int, int> ();
var source = new CompletionCheckerBlock<int, int> ();
var encapsulated = DataflowBlock.Encapsulate (target, source);
encapsulated.Complete ();
Assert.IsFalse (source.WasCompleted);
Assert.IsTrue (target.WasCompleted);
Assert.AreSame (source.Completion, encapsulated.Completion);
}
[Test]
public void FaultTest ()
{
var target = new CompletionCheckerBlock<int, int> ();
var source = new CompletionCheckerBlock<int, int> ();
var encapsulated = DataflowBlock.Encapsulate (target, source);
encapsulated.Fault (new Exception ());
Assert.IsFalse (source.WasFaulted);
Assert.IsTrue (target.WasFaulted);
Assert.AreSame (source.Completion, encapsulated.Completion);
}
}
class CompletionCheckerBlock<TInput, TOutput> :
IPropagatorBlock<TInput, TOutput> {
readonly Task completion = Task.FromResult (true);
public DataflowMessageStatus OfferMessage (
DataflowMessageHeader messageHeader, TInput messageValue,
ISourceBlock<TInput> source, bool consumeToAccept)
{
throw new NotImplementedException ();
}
public void Complete ()
{
WasCompleted = true;
}
public bool WasCompleted { get; private set; }
public void Fault (Exception exception)
{
WasFaulted = true;
}
public bool WasFaulted { get; private set; }
public Task Completion
{
get { return completion; }
}
public IDisposable LinkTo (ITargetBlock<TOutput> target,
DataflowLinkOptions linkOptions)
{
throw new NotImplementedException ();
}
public TOutput ConsumeMessage (DataflowMessageHeader messageHeader,
ITargetBlock<TOutput> target,
out bool messageConsumed)
{
throw new NotImplementedException ();
}
public bool ReserveMessage (DataflowMessageHeader messageHeader,
ITargetBlock<TOutput> target)
{
throw new NotImplementedException ();
}
public void ReleaseReservation (DataflowMessageHeader messageHeader,
ITargetBlock<TOutput> target)
{
throw new NotImplementedException ();
}
}
}

View File

@ -0,0 +1,199 @@
// ExecutionBlocksTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class ExecutionBlocksTest {
static IEnumerable<ITargetBlock<int>> GetExecutionBlocksWithAction(Action action)
{
yield return new ActionBlock<int> (i => action());
yield return new TransformBlock<int, int> (i =>
{
action ();
return i;
});
yield return new TransformManyBlock<int, int> (i =>
{
action ();
return Enumerable.Empty<int> ();
});
}
static IEnumerable<ITargetBlock<int>> GetExecutionBlocksWithAsyncAction (
Func<int, Task> action, ExecutionDataflowBlockOptions options)
{
yield return new ActionBlock<int> (action, options);
yield return new TransformBlock<int, int> (
i => action (i).ContinueWith (
t =>
{
t.Wait ();
return i;
}), options);
yield return new TransformManyBlock<int, int> (
i => action (i).ContinueWith (
t =>
{
t.Wait ();
return Enumerable.Empty<int> ();
}), options);
}
[Test]
public void ExceptionTest ()
{
var exception = new Exception ();
var blocks = GetExecutionBlocksWithAction (() => { throw exception; });
foreach (var block in blocks) {
Assert.IsFalse (block.Completion.Wait (100));
block.Post (1);
var ae =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, ae.InnerExceptions.Count);
Assert.AreSame (exception, ae.InnerException);
}
}
[Test]
public void NoProcessingAfterFaultTest ()
{
int shouldRun = 1;
int ranAfterFault = 0;
var evt = new ManualResetEventSlim ();
var blocks = GetExecutionBlocksWithAction (() =>
{
if (Thread.VolatileRead (ref shouldRun) == 0) {
ranAfterFault++;
return;
}
evt.Wait ();
});
foreach (var block in blocks) {
shouldRun = 1;
ranAfterFault = 0;
evt.Reset ();
Assert.IsTrue (block.Post (1));
Assert.IsTrue (block.Post (2));
Assert.IsFalse (block.Completion.Wait (100));
Assert.AreEqual (0, ranAfterFault);
block.Fault (new Exception ());
Assert.IsFalse (block.Completion.Wait (100));
shouldRun = 0;
evt.Set ();
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Thread.Sleep (100);
Assert.AreEqual (0, Thread.VolatileRead (ref ranAfterFault));
}
}
[Test]
public void AsyncTest ()
{
var tcs = new TaskCompletionSource<int> ();
int result = 0;
var scheduler = new TestScheduler ();
var blocks = GetExecutionBlocksWithAsyncAction (
i =>
tcs.Task.ContinueWith (t => Thread.VolatileWrite (ref result, i + t.Result)),
new ExecutionDataflowBlockOptions { TaskScheduler = scheduler });
foreach (var block in blocks) {
Assert.IsTrue (block.Post (1));
scheduler.ExecuteAll ();
Thread.Sleep (100);
Thread.MemoryBarrier ();
Assert.AreEqual (0, result);
tcs.SetResult (10);
Thread.Sleep (100);
// the continuation should be executed on the configured TaskScheduler
Assert.AreEqual (0, result);
scheduler.ExecuteAll ();
Assert.AreEqual (11, result);
tcs = new TaskCompletionSource<int> ();
Thread.VolatileWrite (ref result, 0);
}
}
[Test]
public void AsyncExceptionTest ()
{
var scheduler = new TestScheduler ();
var exception = new Exception ();
var blocks = GetExecutionBlocksWithAsyncAction (
i =>
{
var tcs = new TaskCompletionSource<int> ();
tcs.SetException (exception);
return tcs.Task;
},
new ExecutionDataflowBlockOptions { TaskScheduler = scheduler });
foreach (var block in blocks) {
Assert.IsTrue (block.Post (1));
// the task should be executed on the configured TaskScheduler
Assert.IsFalse (block.Completion.Wait (100));
scheduler.ExecuteAll ();
var ae =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100)).
Flatten ();
Assert.AreEqual (1, ae.InnerExceptions.Count);
Assert.AreSame (exception, ae.InnerException);
}
}
}
}

View File

@ -0,0 +1,349 @@
// GreedyTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class GreedyTest {
[Test]
public void GreedyJoinTest ()
{
var scheduler = new TestScheduler ();
var block =
new JoinBlock<int, int> (new GroupingDataflowBlockOptions
{ TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block.Target1));
Assert.IsNotNull (source2.LinkTo (block.Target2));
Assert.IsTrue (source1.Post (1));
scheduler.ExecuteAll ();
int i;
Assert.IsFalse (source1.TryReceive (out i));
Assert.IsTrue (source2.Post (11));
scheduler.ExecuteAll ();
Assert.IsFalse (source2.TryReceive (out i));
Tuple<int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (1, 11), tuple);
}
[Test]
public void GreedyJoin3Test ()
{
var scheduler = new TestScheduler ();
var block =
new JoinBlock<int, int, int> (new GroupingDataflowBlockOptions
{ TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source3 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block.Target1));
Assert.IsNotNull (source2.LinkTo (block.Target2));
Assert.IsNotNull (source3.LinkTo (block.Target3));
Assert.IsTrue (source1.Post (1));
scheduler.ExecuteAll ();
int i;
Assert.IsFalse (source1.TryReceive (out i));
Assert.IsTrue (source2.Post (11));
Assert.IsTrue (source3.Post (21));
scheduler.ExecuteAll ();
Assert.IsFalse (source2.TryReceive (out i));
Assert.IsFalse (source3.TryReceive (out i));
Tuple<int, int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (1, 11, 21), tuple);
}
[Test]
public void NonGreedyJoinTest ()
{
var scheduler = new TestScheduler ();
var block =
new JoinBlock<int, int> (new GroupingDataflowBlockOptions
{ TaskScheduler = scheduler, Greedy = false });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block.Target1));
Assert.IsNotNull (source2.LinkTo (block.Target2));
Assert.IsTrue (source1.Post (1));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.IsTrue (source1.Post (2));
Assert.IsTrue (source2.Post (11));
scheduler.ExecuteAll ();
Assert.IsFalse (source1.TryReceive (out i));
Assert.IsFalse (source2.TryReceive (out i));
Tuple<int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (2, 11), tuple);
}
[Test]
public void NonGreedyJoin3Test ()
{
var scheduler = new TestScheduler ();
var block =
new JoinBlock<int, int, int> (new GroupingDataflowBlockOptions
{ TaskScheduler = scheduler, Greedy = false });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source3 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block.Target1));
Assert.IsNotNull (source2.LinkTo (block.Target2));
Assert.IsNotNull (source3.LinkTo (block.Target3));
Assert.IsTrue (source1.Post (1));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.IsTrue (source1.Post (2));
Assert.IsTrue (source2.Post (11));
Assert.IsTrue (source3.Post (21));
scheduler.ExecuteAll ();
Assert.IsFalse (source1.TryReceive (out i));
Assert.IsFalse (source2.TryReceive (out i));
Assert.IsFalse (source3.TryReceive (out i));
Tuple<int, int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (2, 11, 21), tuple);
}
[Test]
public void NonGreedyJoinWithPostTest ()
{
var block =
new JoinBlock<int, int> (new GroupingDataflowBlockOptions { Greedy = false });
Assert.IsFalse (block.Target1.Post (42));
}
[Test]
public void NonGreedyBatchTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (3,
new GroupingDataflowBlockOptions
{ Greedy = false, TaskScheduler = scheduler });
Assert.IsFalse (block.Post (42));
var source =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source.LinkTo (block));
Assert.IsTrue (source.Post (43));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source.TryReceive (null, out i));
Assert.AreEqual (43, i);
Assert.IsTrue (source.Post (44));
Assert.IsTrue (source.Post (45));
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source2.LinkTo (block));
Assert.IsTrue (source2.Post (142));
scheduler.ExecuteAll ();
int[] batch;
Assert.IsFalse (block.TryReceive (null, out batch));
Assert.IsNull (batch);
block.TriggerBatch ();
scheduler.ExecuteAll ();
Assert.IsTrue (block.TryReceive (null, out batch));
CollectionAssert.AreEquivalent (new[] { 44, 142 }, batch);
}
[Test]
public void NonGreedyBatchWithMoreSourcesTest ()
{
var scheduler = new TestScheduler ();
var block = new BatchBlock<int> (2,
new GroupingDataflowBlockOptions
{ Greedy = false, TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block));
Assert.IsNotNull (source2.LinkTo (block));
Assert.IsTrue (source1.Post (43));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.AreEqual (43, i);
Assert.IsTrue (source1.Post (44));
Assert.IsTrue (source2.Post (45));
scheduler.ExecuteAll ();
int[] batch;
Assert.IsTrue (block.TryReceive (out batch));
CollectionAssert.AreEquivalent (new[] { 44, 45 }, batch);
}
[Test]
public void NonGreedyBatchedJoinTest ()
{
AssertEx.Throws<ArgumentException> (
() => new BatchedJoinBlock<int, int> (2,
new GroupingDataflowBlockOptions { Greedy = false }));
}
[Test]
public void NonGreedyBatchedJoin3Test ()
{
AssertEx.Throws<ArgumentException> (
() => new BatchedJoinBlock<int, int, int> (2,
new GroupingDataflowBlockOptions { Greedy = false }));
}
[Test]
public void NonGreedyJoinWithBoundedCapacityTest ()
{
var scheduler = new TestScheduler ();
var block = new JoinBlock<int, int> (
new GroupingDataflowBlockOptions
{ Greedy = false, BoundedCapacity = 1, TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block.Target1));
Assert.IsNotNull (source2.LinkTo (block.Target2));
Assert.IsTrue (source1.Post (11));
Assert.IsTrue (source2.Post (21));
scheduler.ExecuteAll ();
Assert.IsTrue (source1.Post (12));
Assert.IsTrue (source2.Post (22));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.AreEqual (12, i);
Assert.IsTrue (source1.Post (13));
Tuple<int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (11, 21), tuple);
scheduler.ExecuteAll ();
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (13, 22), tuple);
}
[Test]
public void NonGreedyJoin3WithBoundedCapacityTest ()
{
var scheduler = new TestScheduler ();
var block = new JoinBlock<int, int, int> (
new GroupingDataflowBlockOptions
{ Greedy = false, BoundedCapacity = 1, TaskScheduler = scheduler });
var source1 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source2 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var source3 =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (source1.LinkTo (block.Target1));
Assert.IsNotNull (source2.LinkTo (block.Target2));
Assert.IsNotNull (source3.LinkTo (block.Target3));
Assert.IsTrue (source1.Post (11));
Assert.IsTrue (source2.Post (21));
Assert.IsTrue (source3.Post (31));
scheduler.ExecuteAll ();
Assert.IsTrue (source1.Post (12));
Assert.IsTrue (source2.Post (22));
Assert.IsTrue (source3.Post (32));
scheduler.ExecuteAll ();
int i;
Assert.IsTrue (source1.TryReceive (out i));
Assert.AreEqual (12, i);
Assert.IsTrue (source1.Post (13));
Tuple<int, int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (11, 21, 31), tuple);
scheduler.ExecuteAll ();
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (13, 22, 32), tuple);
}
}
}

View File

@ -0,0 +1,470 @@
// InvalidArgumentsTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class InvalidArgumentsTest {
[Test]
public void FaultNullTest()
{
foreach (var block in Blocks.CreateBlocks ()) {
AssertEx.Throws<ArgumentNullException> (() => block.Fault (null));
}
}
[Test]
public void ActionBlockTest ()
{
AssertEx.Throws<ArgumentNullException> (
() => new ActionBlock<int> ((Action<int>)null));
AssertEx.Throws<ArgumentNullException> (
() => new ActionBlock<int> (i => { }, null));
}
[Test]
public void BatchBlockTest()
{
AssertEx.Throws<ArgumentOutOfRangeException> (() => new BatchBlock<int> (0));
AssertEx.Throws<ArgumentOutOfRangeException> (() => new BatchBlock<int> (-1));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => new BatchBlock<int> (2,
new GroupingDataflowBlockOptions { BoundedCapacity = 1 }));
AssertEx.Throws<ArgumentNullException> (() => new BatchBlock<int> (2, null));
}
[Test]
public void BatchedJoinBlockTest()
{
AssertEx.Throws<ArgumentOutOfRangeException> (() => new BatchedJoinBlock<int, int> (0));
AssertEx.Throws<ArgumentOutOfRangeException> (() => new BatchedJoinBlock<int, int> (-1));
AssertEx.Throws<ArgumentException> (
() => new BatchedJoinBlock<int, int> (1,
new GroupingDataflowBlockOptions { BoundedCapacity = 1 }));
AssertEx.Throws<ArgumentException> (
() => new BatchedJoinBlock<int, int> (1,
new GroupingDataflowBlockOptions { Greedy = false }));
AssertEx.Throws<ArgumentNullException> (() => new BatchedJoinBlock<int, int> (2, null));
}
[Test]
public void BatchedJoinBlock3Test()
{
AssertEx.Throws<ArgumentOutOfRangeException> (() => new BatchedJoinBlock<int, int, int> (0));
AssertEx.Throws<ArgumentOutOfRangeException> (() => new BatchedJoinBlock<int, int, int> (-1));
AssertEx.Throws<ArgumentException> (
() => new BatchedJoinBlock<int, int, int> (1,
new GroupingDataflowBlockOptions { BoundedCapacity = 1 }));
AssertEx.Throws<ArgumentException> (
() => new BatchedJoinBlock<int, int, int> (1,
new GroupingDataflowBlockOptions { Greedy = false }));
AssertEx.Throws<ArgumentNullException> (() => new BatchedJoinBlock<int, int, int> (2, null));
}
[Test]
public void BroadcastBlock()
{
// null is valid argument for BroadcastBlock, so this shouldn't throw
new BroadcastBlock<int> (null);
AssertEx.Throws<ArgumentNullException> (() => new BroadcastBlock<int> (i => i, null));
}
[Test]
public void BufferBlockTest()
{
AssertEx.Throws<ArgumentNullException> (() => new BufferBlock<int> (null));
}
[Test]
public void JoinBlockTest()
{
AssertEx.Throws<ArgumentNullException> (() => new JoinBlock<int, int> (null));
}
[Test]
public void JoinBlock3Test()
{
AssertEx.Throws<ArgumentNullException> (() => new JoinBlock<int, int, int> (null));
}
[Test]
public void TransformBlockTest()
{
AssertEx.Throws<ArgumentNullException> (
() => new TransformBlock<int, int> ((Func<int, int>)null));
AssertEx.Throws<ArgumentNullException> (
() => new TransformBlock<int, int> ((Func<int, int>)null,
new ExecutionDataflowBlockOptions ()));
AssertEx.Throws<ArgumentNullException> (
() => new TransformBlock<int, int> (i => i, null));
}
[Test]
public void TransformManyBlockTest()
{
AssertEx.Throws<ArgumentNullException> (
() => new TransformManyBlock<int, int> ((Func<int, IEnumerable<int>>)null));
AssertEx.Throws<ArgumentNullException> (
() => new TransformManyBlock<int, int> ((Func<int, IEnumerable<int>>)null,
new ExecutionDataflowBlockOptions ()));
AssertEx.Throws<ArgumentNullException> (
() => new TransformManyBlock<int, int> (i => new int[0], null));
}
[Test]
public void WriteOnceBlock()
{
// null is valid argument for WriteOnceBlock, so this shouldn't throw
new WriteOnceBlock<int> (null);
AssertEx.Throws<ArgumentNullException> (() => new WriteOnceBlock<int> (i => i, null));
}
[Test]
public void SourceBlockTest()
{
foreach (var block in Blocks.CreateSimpleSourceBlocks<int> ())
SourceBlockTestInternal (block);
SourceBlockTestInternal (new BatchBlock<int>(5));
SourceBlockTestInternal (new BatchedJoinBlock<int, int>(5));
SourceBlockTestInternal (new BatchedJoinBlock<int, int, int>(5));
SourceBlockTestInternal (new JoinBlock<int, int> ());
SourceBlockTestInternal (new JoinBlock<int, int, int> ());
}
static void SourceBlockTestInternal<T>(ISourceBlock<T> block)
{
var target = new BufferBlock<T> ();
bool consumed;
// invalid header
AssertEx.Throws<ArgumentException> (
() =>
block.ConsumeMessage (new DataflowMessageHeader (), target, out consumed));
// header that wasn't sent by the block doesn't throw
block.ConsumeMessage (new DataflowMessageHeader (1), target, out consumed);
AssertEx.Throws<ArgumentNullException> (
() =>
block.ConsumeMessage (new DataflowMessageHeader (1), null, out consumed));
AssertEx.Throws<ArgumentException> (
() =>
block.ReserveMessage (new DataflowMessageHeader (), target));
// header that wasn't sent by the block doesn't throw
block.ReserveMessage (new DataflowMessageHeader (1), target);
AssertEx.Throws<ArgumentNullException> (
() =>
block.ReserveMessage (new DataflowMessageHeader (1), null));
AssertEx.Throws<ArgumentException> (
() =>
block.ReleaseReservation (new DataflowMessageHeader (), target));
AssertEx.Throws<ArgumentNullException>(() => block.LinkTo(null, new DataflowLinkOptions()));
AssertEx.Throws<ArgumentNullException>(() => block.LinkTo(target, null));
}
[Test]
public void TargetBlockTest()
{
foreach (var block in Blocks.CreateTargetBlocks<int> ()) {
// invalid header
AssertEx.Throws<ArgumentException> (
() => block.OfferMessage (new DataflowMessageHeader (), 42, null, false));
// consumeToAccept with null source
AssertEx.Throws<ArgumentException> (
() => block.OfferMessage (new DataflowMessageHeader (1), 42, null, true));
}
}
[Test]
public void ReactiveTest()
{
IPropagatorBlock<int, int> block = null;
AssertEx.Throws<ArgumentNullException> (() => block.AsObservable ());
AssertEx.Throws<ArgumentNullException> (() => block.AsObserver ());
}
[Test]
public void ChooseTest()
{
ISourceBlock<int> nullSource = null;
var realSource = new BufferBlock<int> ();
var options = new DataflowBlockOptions ();
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (nullSource, i => { }, realSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, null, realSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, nullSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, null));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (nullSource, i => { }, realSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, null, realSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, nullSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, null, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, i => { }, null));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (nullSource, i => { }, realSource, i => { }, realSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, null, realSource, i => { }, realSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, nullSource, i => { }, realSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, null, realSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (nullSource, i => { }, realSource, i => { }, nullSource, i => { }));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (nullSource, i => { }, realSource, i => { }, realSource, null));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (nullSource, i => { }, realSource, i => { }, realSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, null, realSource, i => { }, realSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, nullSource, i => { }, realSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, null, realSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, i => { }, nullSource, i => { }, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, i => { }, realSource, null, options));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Choose (realSource, i => { }, realSource, i => { }, realSource, i => { }, null));
}
[Test]
public void EncapsulateTest()
{
AssertEx.Throws<ArgumentNullException> (
() =>
DataflowBlock.Encapsulate ((ITargetBlock<int>)null, new BufferBlock<int> ()));
AssertEx.Throws<ArgumentNullException> (
() =>
DataflowBlock.Encapsulate (new BufferBlock<int> (), (ISourceBlock<int>)null));
}
[Test]
public void LinkToTest()
{
IPropagatorBlock<int, int> nullBlock = null;
var realBlock = new BufferBlock<int> ();
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (nullBlock, realBlock));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (realBlock, nullBlock));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (nullBlock, realBlock, i => true));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (realBlock, nullBlock, i => true));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (realBlock, realBlock, null));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (nullBlock, realBlock, new DataflowLinkOptions (), i => true));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (realBlock, nullBlock, new DataflowLinkOptions (), i => true));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (realBlock, realBlock, null, i => true));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.LinkTo (realBlock, realBlock, new DataflowLinkOptions (), null));
}
[Test]
public void PostTest()
{
AssertEx.Throws<ArgumentNullException> (() => DataflowBlock.Post (null, 42));
}
[Test]
public void ReceiveTest()
{
var source = new BufferBlock<int> ();
source.Post(1);
source.Post(2);
source.Post(3);
source.Post(4);
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Receive ((ISourceBlock<int>)null));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Receive ((ISourceBlock<int>)null,
new CancellationToken (false)));
AssertEx.Throws<OperationCanceledException> (
() => DataflowBlock.Receive (source, new CancellationToken (true)));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Receive ((ISourceBlock<int>)null,
TimeSpan.FromMinutes (1)));
// shouldn't throw
DataflowBlock.Receive (source, TimeSpan.FromMilliseconds (-1));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.Receive (source, TimeSpan.FromMilliseconds (-2)));
// shouldn't throw
DataflowBlock.Receive (source, TimeSpan.FromMilliseconds (int.MaxValue));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.Receive (source,
TimeSpan.FromMilliseconds (int.MaxValue + 1L)));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.Receive ((ISourceBlock<int>)null,
TimeSpan.FromMinutes (1), new CancellationToken(false)));
AssertEx.Throws<OperationCanceledException> (
() => DataflowBlock.Receive (source, TimeSpan.FromMinutes (1),
new CancellationToken (true)));
// shouldn't throw
DataflowBlock.Receive (source, TimeSpan.FromMilliseconds (-1),
new CancellationToken (false));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.Receive (source, TimeSpan.FromMilliseconds (-2),
new CancellationToken (false)));
// shouldn't throw
DataflowBlock.Receive (source, TimeSpan.FromMilliseconds (int.MaxValue),
new CancellationToken (false));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.Receive (source,
TimeSpan.FromMilliseconds (int.MaxValue + 1L),
new CancellationToken (false)));
}
[Test]
public void ReceiveAsyncTest()
{
var source = new BufferBlock<int> ();
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.ReceiveAsync ((ISourceBlock<int>)null));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.ReceiveAsync ((ISourceBlock<int>)null,
new CancellationToken (false)));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.ReceiveAsync ((ISourceBlock<int>)null,
TimeSpan.FromMinutes (1)));
// shouldn't throw
DataflowBlock.ReceiveAsync (source, TimeSpan.FromMilliseconds (-1));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.ReceiveAsync (source, TimeSpan.FromMilliseconds (-2)));
// shouldn't throw
DataflowBlock.ReceiveAsync (source, TimeSpan.FromMilliseconds (int.MaxValue));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.ReceiveAsync (source,
TimeSpan.FromMilliseconds (int.MaxValue + 1L)));
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.ReceiveAsync ((ISourceBlock<int>)null,
TimeSpan.FromMinutes (1), new CancellationToken(false)));
// shouldn't throw
DataflowBlock.ReceiveAsync (source, TimeSpan.FromMilliseconds (-1),
new CancellationToken (false));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.ReceiveAsync (source, TimeSpan.FromMilliseconds (-2),
new CancellationToken (false)));
// shouldn't throw
DataflowBlock.ReceiveAsync (source, TimeSpan.FromMilliseconds (int.MaxValue),
new CancellationToken (false));
AssertEx.Throws<ArgumentOutOfRangeException> (
() => DataflowBlock.ReceiveAsync (source,
TimeSpan.FromMilliseconds (int.MaxValue + 1L),
new CancellationToken (false)));
}
[Test]
public void TryReceiveTest()
{
int i;
AssertEx.Throws<ArgumentNullException> (
() => DataflowBlock.TryReceive (null, out i));
}
[Test]
public void DataflowBlockOptionsTest()
{
var options = new DataflowBlockOptions ();
AssertEx.Throws<ArgumentOutOfRangeException>(() => options.BoundedCapacity = -2);
AssertEx.Throws<ArgumentOutOfRangeException>(() => options.MaxMessagesPerTask = -2);
AssertEx.Throws<ArgumentNullException>(() => options.NameFormat = null);
// shouldn't throw
options.NameFormat = "{2}";
new BufferBlock<int>(options).ToString();
AssertEx.Throws<ArgumentNullException>(() => options.TaskScheduler = null);
}
[Test]
public void ExecutionDataflowBlockOptionsTest()
{
var options = new ExecutionDataflowBlockOptions ();
AssertEx.Throws<ArgumentOutOfRangeException>(() => options.MaxDegreeOfParallelism = -2);
}
[Test]
public void GroupingDataflowBlockOptionsTest()
{
var options = new GroupingDataflowBlockOptions ();
AssertEx.Throws<ArgumentOutOfRangeException>(() => options.MaxNumberOfGroups = -2);
}
[Test]
public void DataflowLinkOptionsTest()
{
var options = new DataflowLinkOptions ();
AssertEx.Throws<ArgumentOutOfRangeException>(() => options.MaxMessages = -2);
}
}
}

View File

@ -0,0 +1,181 @@
//
// JoinBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class JoinBlockTest {
[Test]
public void BasicUsageTest ()
{
Tuple<int, int> tuple = null;
var evt = new ManualResetEventSlim (false);
var ablock = new ActionBlock<Tuple<int, int>> (t =>
{
tuple = t;
evt.Set ();
});
var block = new JoinBlock<int, int> ();
block.LinkTo (ablock);
block.Target1.Post (42);
evt.Wait (1000);
Assert.IsNull (tuple);
block.Target2.Post (24);
evt.Wait ();
Assert.IsNotNull (tuple);
Assert.AreEqual (42, tuple.Item1);
Assert.AreEqual (24, tuple.Item2);
}
[Test]
public void DeadlockTest ()
{
Tuple<int, int> tuple = null;
var evt = new ManualResetEventSlim (false);
var ablock = new ActionBlock<Tuple<int, int>> (t =>
{
tuple = t;
evt.Set ();
});
var block = new JoinBlock<int, int> ();
block.LinkTo (ablock);
Task.Factory.StartNew (() => block.Target1.Post (42));
Task.Factory.StartNew (() => block.Target2.Post (24));
Assert.IsTrue (evt.Wait (500));
Assert.IsNotNull (tuple);
Assert.AreEqual (42, tuple.Item1);
Assert.AreEqual (24, tuple.Item2);
}
[Test]
public void BoundedCapacityTest ()
{
var block = new JoinBlock<int, int> (
new GroupingDataflowBlockOptions { BoundedCapacity = 1 });
Assert.IsTrue (block.Target1.Post (1));
Assert.IsFalse (block.Target1.Post (2));
Assert.IsTrue (block.Target2.Post (10));
Assert.IsFalse (block.Target2.Post (11));
Assert.IsFalse (block.Target1.Post (3));
Assert.AreEqual (Tuple.Create (1, 10), block.Receive ());
Assert.IsTrue (block.Target1.Post (4));
}
[Test]
public void CompletionTest ()
{
var block = new JoinBlock<int, int> ();
Assert.IsTrue (block.Target1.Post (1));
block.Complete ();
Tuple<int, int> tuple;
Assert.IsFalse (block.TryReceive (out tuple));
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void MaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new JoinBlock<int, int> (
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 1, TaskScheduler = scheduler });
Assert.IsTrue (block.Target1.Post (1));
Assert.IsFalse (block.Target1.Post (2));
Assert.IsTrue (block.Target2.Post (3));
Assert.IsFalse (block.Target2.Post (4));
Tuple<int, int> batch;
Assert.IsTrue (block.TryReceive (out batch));
Assert.AreEqual (Tuple.Create (1, 3), batch);
Assert.IsFalse (block.TryReceive (out batch));
scheduler.ExecuteAll ();
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void NonGreedyMaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new JoinBlock<int, int> (
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 1, Greedy = false, TaskScheduler = scheduler });
var source1 = new TestSourceBlock<int> ();
var source2 = new TestSourceBlock<int> ();
var header1 = new DataflowMessageHeader (1);
source1.AddMessage (header1, 11);
source2.AddMessage (header1, 21);
Assert.AreEqual (DataflowMessageStatus.Postponed,
block.Target1.OfferMessage (header1, 11, source1, false));
Assert.AreEqual (DataflowMessageStatus.Postponed,
block.Target2.OfferMessage (header1, 21, source2, false));
scheduler.ExecuteAll ();
Assert.IsTrue (source1.WasConsumed (header1));
Assert.IsTrue (source2.WasConsumed (header1));
var header2 = new DataflowMessageHeader (2);
Assert.AreEqual (DataflowMessageStatus.DecliningPermanently,
block.Target1.OfferMessage (header2, 21, source1, false));
Tuple<int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (11, 21), tuple);
Assert.IsTrue (block.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,154 @@
//
// JoinBlockTest.cs
//
// Author:
// Jérémie "garuma" Laval <jeremie.laval@gmail.com>
// Petr Onderka <gsvick@gmail.com>
//
// Copyright (c) 2011 Jérémie "garuma" Laval
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class JoinBlock3Test {
[Test]
public void BasicUsageTest ()
{
Tuple<int, int, int> tuple = null;
var evt = new ManualResetEventSlim (false);
var ablock = new ActionBlock<Tuple<int, int, int>> (t =>
{
tuple = t;
evt.Set ();
});
var block = new JoinBlock<int, int, int> ();
block.LinkTo (ablock);
block.Target1.Post (42);
evt.Wait (500);
Assert.IsNull (tuple);
block.Target2.Post (24);
evt.Wait (500);
Assert.IsNull (tuple);
block.Target3.Post (44);
evt.Wait ();
Assert.IsNotNull (tuple);
Assert.AreEqual (42, tuple.Item1);
Assert.AreEqual (24, tuple.Item2);
Assert.AreEqual (44, tuple.Item3);
}
[Test]
public void CompletionTest ()
{
var block = new JoinBlock<int, int, int> ();
Assert.IsTrue (block.Target1.Post (1));
block.Complete ();
Tuple<int, int, int> tuple;
Assert.IsFalse (block.TryReceive (out tuple));
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void MaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new JoinBlock<int, int, int> (
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 1, TaskScheduler = scheduler });
Assert.IsTrue (block.Target1.Post (1));
Assert.IsFalse (block.Target1.Post (2));
Assert.IsTrue (block.Target2.Post (3));
Assert.IsTrue (block.Target3.Post (4));
Assert.IsFalse (block.Target3.Post (4));
Assert.IsFalse (block.Target2.Post (4));
Tuple<int, int, int> batch;
Assert.IsTrue (block.TryReceive (out batch));
Assert.AreEqual (Tuple.Create (1, 3, 4), batch);
Assert.IsFalse (block.TryReceive (out batch));
scheduler.ExecuteAll ();
Assert.IsTrue (block.Completion.Wait (100));
}
[Test]
public void NonGreedyMaxNumberOfGroupsTest ()
{
var scheduler = new TestScheduler ();
var block = new JoinBlock<int, int, int> (
new GroupingDataflowBlockOptions
{ MaxNumberOfGroups = 1, Greedy = false, TaskScheduler = scheduler });
var source1 = new TestSourceBlock<int> ();
var source2 = new TestSourceBlock<int> ();
var source3 = new TestSourceBlock<int> ();
var header1 = new DataflowMessageHeader (1);
source1.AddMessage (header1, 11);
source2.AddMessage (header1, 21);
source3.AddMessage (header1, 31);
Assert.AreEqual (DataflowMessageStatus.Postponed,
block.Target1.OfferMessage (header1, 11, source1, false));
Assert.AreEqual (DataflowMessageStatus.Postponed,
block.Target2.OfferMessage (header1, 21, source2, false));
Assert.AreEqual (DataflowMessageStatus.Postponed,
block.Target3.OfferMessage (header1, 31, source3, false));
scheduler.ExecuteAll ();
Assert.IsTrue (source1.WasConsumed (header1));
Assert.IsTrue (source2.WasConsumed (header1));
Assert.IsTrue (source3.WasConsumed (header1));
var header2 = new DataflowMessageHeader (2);
Assert.AreEqual (DataflowMessageStatus.DecliningPermanently,
block.Target1.OfferMessage (header2, 21, source1, false));
Tuple<int, int, int> tuple;
Assert.IsTrue (block.TryReceive (out tuple));
Assert.AreEqual (Tuple.Create (11, 21, 31), tuple);
Assert.IsTrue (block.Completion.Wait (100));
}
}
}

View File

@ -0,0 +1,419 @@
// OptionsTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class OptionsTest {
[Test]
public void NameFormatTest ()
{
var constant = "constant";
foreach (var block in Blocks.CreateBlocksWithNameFormat (constant))
Assert.AreEqual (constant, block.ToString ());
foreach (var block in Blocks.CreateBlocksWithNameFormat ("{0}"))
Assert.AreEqual (block.GetType ().Name, block.ToString ());
foreach (var block in Blocks.CreateBlocksWithNameFormat ("{1}"))
Assert.AreEqual (block.Completion.Id.ToString (), block.ToString ());
}
[Test]
public void CancellationTest ()
{
var source = new CancellationTokenSource ();
var blocks = Blocks.CreateBlocksWithCancellationToken (source.Token).ToArray ();
foreach (var block in blocks)
Assert.IsFalse (block.Completion.Wait (100));
source.Cancel ();
foreach (var block in blocks) {
var ae =
AssertEx.Throws<AggregateException> (() => block.Completion.Wait (100));
Assert.AreEqual (1, ae.InnerExceptions.Count);
Assert.IsInstanceOfType (typeof(TaskCanceledException), ae.InnerExceptions [0]);
Assert.IsTrue (block.Completion.IsCanceled);
}
}
static IEnumerable<int[]> GetTaskIdsForExecutionsOptions (
ExecutionDataflowBlockOptions options)
{
var blockFactories =
new Func<ConcurrentQueue<Tuple<int, int>>, ITargetBlock<int>>[]
{
q => new ActionBlock<int> (
i => q.Enqueue (Tuple.Create (i, Task.CurrentId.Value)), options),
q => new TransformBlock<int, int> (i =>
{
q.Enqueue (Tuple.Create (i, Task.CurrentId.Value));
return i;
}, options),
q => new TransformManyBlock<int, int> (i =>
{
q.Enqueue (Tuple.Create (i, Task.CurrentId.Value));
return new[] { i };
}, options)
};
foreach (var factory in blockFactories) {
var queue = new ConcurrentQueue<Tuple<int, int>> ();
var block = factory (queue);
Assert.IsEmpty (queue);
for (int i = 0; i < 100; i++)
block.Post (i);
block.Complete ();
var source = block as ISourceBlock<int>;
if (source != null) {
Assert.IsFalse (block.Completion.Wait (100));
source.LinkTo (new BufferBlock<int> ());
}
Assert.IsTrue (block.Completion.Wait (500));
CollectionAssert.AreEquivalent (
Enumerable.Range (0, 100), queue.Select (t => t.Item1));
yield return queue.Select (t => t.Item2).ToArray ();
}
}
static int CalculateDegreeOfParallelism(IEnumerable<int> taskIds)
{
var firsts = new Dictionary<int, int> ();
var lasts = new Dictionary<int, int> ();
int i = 0;
foreach (var taskId in taskIds) {
if (!firsts.ContainsKey (taskId))
firsts.Add (taskId, i);
lasts [taskId] = i;
i++;
}
int maxTime = i;
var times =
Enumerable.Repeat (Tuple.Create<int?, int?> (null, null), maxTime).ToArray ();
foreach (var first in firsts)
times [first.Value] = Tuple.Create<int?, int?> (
first.Key, times [first.Value].Item2);
foreach (var last in lasts)
times [last.Value] = Tuple.Create<int?, int?> (
times [last.Value].Item1, last.Key);
int maxDop = 0;
int dop = 0;
foreach (var time in times) {
if (time.Item1 != null)
dop++;
if (dop > maxDop)
maxDop = dop;
if (time.Item2 != null)
dop--;
}
return maxDop;
}
[Test]
public void MaxDegreeOfParallelismTest()
{
// loop to better test for race conditions
// some that showed in this test were quite rare
for (int i = 0; i < 10; i++)
{
var options = new ExecutionDataflowBlockOptions ();
foreach (var taskIds in GetTaskIdsForExecutionsOptions(options))
Assert.AreEqual (1, CalculateDegreeOfParallelism (taskIds));
options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.LessOrEqual (CalculateDegreeOfParallelism (taskIds), 2);
options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.LessOrEqual (CalculateDegreeOfParallelism (taskIds), 4);
options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = -1 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.LessOrEqual (CalculateDegreeOfParallelism (taskIds), taskIds.Length);
}
}
[Test]
public void MaxMessagesPerTaskTest()
{
var options = new ExecutionDataflowBlockOptions ();
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.GreaterOrEqual (taskIds.Distinct ().Count (), 1);
options = new ExecutionDataflowBlockOptions { MaxMessagesPerTask = 1 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.AreEqual (100, taskIds.Distinct ().Count ());
options = new ExecutionDataflowBlockOptions { MaxMessagesPerTask = 2 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.GreaterOrEqual (taskIds.Distinct ().Count (), taskIds.Length / 2);
options = new ExecutionDataflowBlockOptions { MaxMessagesPerTask = 4 };
foreach (var taskIds in GetTaskIdsForExecutionsOptions (options))
Assert.GreaterOrEqual (taskIds.Distinct ().Count (), taskIds.Length / 4);
}
[Test]
public void TaskSchedulerTest ()
{
var scheduler = new TestScheduler ();
int n = 0;
var action = new ActionBlock<int> (
i => Interlocked.Increment (ref n),
new ExecutionDataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsTrue (action.Post (1));
Assert.AreEqual (0, Thread.VolatileRead (ref n));
Assert.AreEqual (1, scheduler.ExecuteAll ());
Assert.AreEqual (1, Thread.VolatileRead (ref n));
}
[Test]
public void DefaultSchedulerIsDefaultTest ()
{
var scheduler = new TestScheduler ();
var factory = new TaskFactory (scheduler);
ActionBlock<int> action = null;
var task = factory.StartNew (() =>
{
Assert.AreEqual (scheduler, TaskScheduler.Current);
action = new ActionBlock<int> (
i => Assert.AreNotEqual (scheduler, TaskScheduler.Current));
Assert.IsTrue (action.Post (1));
action.Complete ();
});
Assert.AreEqual (1, scheduler.ExecuteAll ());
Assert.IsNotNull (action);
Assert.IsTrue (action.Completion.Wait (100));
Assert.IsTrue (task.Wait (0));
}
[Test]
public void MaxMessagesDirectTest ()
{
var scheduler = new TestScheduler ();
var source =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var target =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
Assert.IsNotNull (
source.LinkTo (target, new DataflowLinkOptions { MaxMessages = 1 }));
Assert.IsTrue (source.Post (42));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (null, out item));
Assert.AreEqual (42, item);
Assert.IsTrue (source.Post (43));
scheduler.ExecuteAll ();
Assert.IsFalse (target.TryReceive (null, out item));
Assert.IsTrue (source.TryReceive (null, out item));
Assert.AreEqual (43, item);
}
[Test]
public void MaxMessagesPostponedTest ()
{
var scheduler = new TestScheduler ();
var source =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int> (
new DataflowBlockOptions { TaskScheduler = scheduler, BoundedCapacity = 1 });
Assert.IsNotNull (
source.LinkTo (target, new DataflowLinkOptions { MaxMessages = 2 }));
Assert.IsTrue (source.Post (42));
Assert.IsTrue (source.Post (43));
Assert.IsTrue (source.Post (44));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (null, out item));
Assert.AreEqual (42, item);
Assert.IsFalse (target.TryReceive (null, out item));
scheduler.ExecuteAll ();
Assert.IsTrue (target.TryReceive (null, out item));
Assert.AreEqual (43, item);
scheduler.ExecuteAll ();
Assert.IsFalse (target.TryReceive (null, out item));
Assert.IsTrue (source.TryReceive (null, out item));
Assert.AreEqual (44, item);
}
[Test]
public void MaxMessagesPostponedUnconsumedTest ()
{
var scheduler = new TestScheduler ();
var source =
new BufferBlock<int> (new DataflowBlockOptions { TaskScheduler = scheduler });
var target =
new BufferBlock<int> (
new DataflowBlockOptions { TaskScheduler = scheduler, BoundedCapacity = 1 });
Assert.IsNotNull (
source.LinkTo (target, new DataflowLinkOptions { MaxMessages = 2 }));
Assert.IsTrue (source.Post (42));
Assert.IsTrue (source.Post (43));
Assert.IsTrue (source.Post (44));
Assert.IsTrue (source.Post (45));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (source.TryReceive (null, out item));
Assert.AreEqual (43, item);
Assert.IsTrue (target.TryReceive (null, out item));
Assert.AreEqual (42, item);
Assert.IsFalse (target.TryReceive (null, out item));
scheduler.ExecuteAll ();
Assert.IsTrue (target.TryReceive (null, out item));
Assert.AreEqual (44, item);
scheduler.ExecuteAll ();
Assert.IsFalse (target.TryReceive (null, out item));
Assert.IsTrue (source.TryReceive (null, out item));
Assert.AreEqual (45, item);
}
[Test]
public void MaxMessagesBroadcastTest ()
{
var scheduler = new TestScheduler ();
var source = new BroadcastBlock<int> (
null, new DataflowBlockOptions { TaskScheduler = scheduler });
var target = new BufferBlock<int>(
new DataflowBlockOptions { TaskScheduler = scheduler, BoundedCapacity = 1 });
Assert.IsNotNull (
source.LinkTo (target, new DataflowLinkOptions { MaxMessages = 2 }));
// should be accepted
Assert.IsTrue (source.Post (42));
scheduler.ExecuteAll ();
// should be postponed, but counted into the limit
Assert.IsTrue (source.Post (43));
scheduler.ExecuteAll ();
// shouldn't be even offered for now
Assert.IsTrue (source.Post (44));
scheduler.ExecuteAll ();
int item;
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (42, item);
scheduler.ExecuteAll ();
Assert.IsTrue (target.TryReceive (out item));
Assert.AreEqual (44, item);
}
[Test]
public void MaxNumberOfGroupsWithConsumeToAcceptTest ()
{
ITargetBlock<int> block = new BatchBlock<int> (1,
new GroupingDataflowBlockOptions { MaxNumberOfGroups = 1 });
var evt = new ManualResetEventSlim ();
Func<Task<Tuple<DataflowMessageStatus, bool>>> startTask =
() => Task.Factory.StartNew (
() =>
{
var sourceBlock = new TestSourceBlock<int> { ConsumeWaiter = evt.Wait };
var header = new DataflowMessageHeader (1);
sourceBlock.AddMessage (header, 1);
var status = block.OfferMessage (header, 1, sourceBlock, true);
return Tuple.Create (status, sourceBlock.WasConsumed (header));
});
var task1 = startTask ();
var task2 = startTask ();
Thread.Sleep (100);
Assert.IsFalse (task1.IsCompleted);
Assert.IsFalse (task2.IsCompleted);
evt.Set ();
Assert.IsTrue (Task.WaitAll (new Task[] { task1, task2 }, 100));
CollectionAssert.AreEquivalent (
new[]
{
Tuple.Create (DataflowMessageStatus.Accepted, true),
Tuple.Create (DataflowMessageStatus.DecliningPermanently, false)
},
new[] { task1.Result, task2.Result });
}
}
}

View File

@ -0,0 +1,160 @@
// OutputAvailableTest.cs
//
// Copyright (c) 2012 Petr Onderka
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NUnit.Framework;
namespace MonoTests.System.Threading.Tasks.Dataflow {
[TestFixture]
public class OutputAvailableTest {
[Test]
public void ImmediateTest()
{
var scheduler = new TestScheduler();
var source = new BufferBlock<int>(new DataflowBlockOptions{TaskScheduler = scheduler});
Assert.IsTrue(source.Post(1));
var task = source.OutputAvailableAsync();
// not necessary in MS.NET
scheduler.ExecuteAll();
Assert.IsTrue(task.IsCompleted);
Assert.IsTrue(task.Result);
}
[Test]
public void PostponedTest()
{
var source = new BufferBlock<int>(new DataflowBlockOptions());
var task = source.OutputAvailableAsync();
Assert.IsFalse(task.Wait(100));
Assert.IsTrue(source.Post(1));
Assert.IsTrue(task.Wait(100));
Assert.IsTrue(task.Result);
}
[Test]
public void CompletedImmediateTest()
{
var source = new BufferBlock<int>();
source.Complete();
var task = source.OutputAvailableAsync();
Assert.IsTrue(task.Wait(100));
Assert.IsFalse(task.Result);
}
[Test]
public void CompletedPostponedTest()
{
var source = new BufferBlock<int>(new DataflowBlockOptions());
var task = source.OutputAvailableAsync();
Assert.IsFalse(task.Wait(100));
source.Complete();
Assert.IsTrue(task.Wait(100));
Assert.IsFalse(task.Result);
}
[Test]
public void FaultedImmediateTest()
{
var source = new BufferBlock<int>();
((IDataflowBlock)source).Fault(new Exception());
var task = source.OutputAvailableAsync();
Assert.IsTrue(task.Wait(100));
Assert.IsFalse(task.Result);
}
[Test]
public void FaultedPostponedTest()
{
var source = new BufferBlock<int>();
var task = source.OutputAvailableAsync();
Assert.IsFalse(task.Wait(100));
((IDataflowBlock)source).Fault(new Exception());
Assert.IsTrue(task.Wait(100));
Assert.IsFalse(task.Result);
}
[Test]
public void WithTargetTest()
{
var source = new BufferBlock<int>();
var target = new BufferBlock<int>();
source.LinkTo(target);
var task = source.OutputAvailableAsync();
Assert.IsTrue(source.Post(1));
Assert.IsFalse(task.Wait(100));
}
[Test]
public void WithDecliningTargetTest()
{
var source = new BufferBlock<int>();
var target = new BufferBlock<int>();
source.LinkTo(target, i => false);
var task = source.OutputAvailableAsync();
Assert.IsTrue(source.Post(1));
Assert.IsTrue(task.Wait(100));
Assert.IsTrue(task.Result);
}
[Test]
public void CancellationTest()
{
var source = new BufferBlock<int>();
var tokenSource = new CancellationTokenSource();
var task = source.OutputAvailableAsync(tokenSource.Token);
tokenSource.Cancel();
AssertEx.Throws<AggregateException>(() => task.Wait(100));
Assert.IsTrue(task.IsCanceled);
}
}
}

Some files were not shown because too many files have changed in this diff Show More