1 // DataflowBlockTest.cs
2 //
3 // Author:
4 //       Petr Onderka <gsvick@gmail.com>
5 //
6 // Copyright (c) 2012 Petr Onderka
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 // THE SOFTWARE.
25 
26 using System;
27 using System.Threading;
28 using System.Threading.Tasks;
29 using System.Threading.Tasks.Dataflow;
30 using NUnit.Framework;
31 
32 namespace MonoTests.System.Threading.Tasks.Dataflow {
33 	[TestFixture]
34 	public class ChooseTest {
35 		[Test]
BasicTest()36 		public void BasicTest ()
37 		{
38 			var source1 = new BufferBlock<int> ();
39 			var source2 = new BufferBlock<long> ();
40 
41 			bool action1 = false;
42 			bool action2 = false;
43 			var completion = DataflowBlock.Choose (
44 				source1, _ => action1 = true,
45 				source2, _ => action2 = true);
46 
47 			source1.Post (42);
48 
49 			Assert.IsTrue (completion.Wait (1000));
50 			Assert.AreEqual (0, completion.Result);
51 			Assert.IsTrue (action1);
52 			Assert.IsFalse (action2);
53 		}
54 
55 		[Test]
OnlyOneConsumedTest()56 		public void OnlyOneConsumedTest ()
57 		{
58 			var source1 = new BufferBlock<int> ();
59 			var source2 = new BufferBlock<long> ();
60 
61 			int action1 = 0;
62 			int action2 = 0;
63 			var completion = DataflowBlock.Choose (
64 				source1, _ => action1++,
65 				source2, _ => action2++);
66 
67 			source1.Post (42);
68 			source1.Post (43);
69 
70 			Assert.IsTrue (completion.Wait (1000));
71 			Assert.AreEqual (0, completion.Result);
72 			Assert.AreEqual (1, action1);
73 			Assert.AreEqual (0, action2);
74 
75 			int item;
76 			Assert.IsTrue (source1.TryReceive (out item));
77 			Assert.AreEqual (43, item);
78 		}
79 
80 		[Test]
RaceTest()81 		public void RaceTest ()
82 		{
83 			var source1 = new BufferBlock<int> ();
84 			var source2 = new BufferBlock<int> ();
85 
86 			int action1 = 0;
87 			int action2 = 0;
88 			var completion = DataflowBlock.Choose (
89 				source1, _ => action1++,
90 				source2, _ => action2++);
91 
92 			var barrier = new Barrier (2);
93 
94 			var t1 = Task.Run (() =>
95 			{
96 				barrier.SignalAndWait ();
97 				source1.Post (10);
98 			});
99 			var t2 = Task.Run (() =>
100 			{
101 				barrier.SignalAndWait ();
102 				source2.Post (20);
103 			});
104 
105 			Task.WaitAll (t1, t2);
106 
107 			Assert.IsTrue (completion.Wait (1000));
108 			Assert.AreEqual (1, action1 + action2);
109 
110 			int item;
111 			Assert.IsTrue (source1.TryReceive (out item) || source2.TryReceive (out item));
112 		}
113 
114 		[Test]
BlockCompletionTest()115 		public void BlockCompletionTest ()
116 		{
117 			var source1 = new BufferBlock<int> ();
118 			var source2 = new BufferBlock<long> ();
119 
120 			var completion = DataflowBlock.Choose (
121 				source1, _ => { }, source2, _ => { });
122 
123 			Assert.IsFalse (completion.IsCanceled);
124 
125 			((IDataflowBlock)source1).Fault (new Exception ());
126 			source2.Complete ();
127 
128 			Thread.Sleep (100);
129 
130 			Assert.IsTrue (completion.IsCanceled);
131 		}
132 
133 		[Test]
CancellationTest()134 		public void CancellationTest ()
135 		{
136 			var source1 = new BufferBlock<int> ();
137 			var source2 = new BufferBlock<long> ();
138 
139 			var tokenSource = new CancellationTokenSource ();
140 			var options = new DataflowBlockOptions
141 			{ CancellationToken = tokenSource.Token };
142 
143 			var completion = DataflowBlock.Choose (
144 				source1, _ => { }, source2, _ => { }, options);
145 
146 			Assert.IsFalse (completion.IsCanceled);
147 
148 			tokenSource.Cancel ();
149 
150 			Thread.Sleep (100);
151 
152 			Assert.IsTrue (completion.IsCanceled);
153 		}
154 
155 		[Test]
ConsumeToAcceptTest()156 		public void ConsumeToAcceptTest ()
157 		{
158 			var source1 = new BroadcastBlock<int> (_ => 42);
159 			var source2 = new BufferBlock<int> ();
160 
161 			int action1 = 0;
162 			int action2 = 0;
163 			var completion = DataflowBlock.Choose (
164 				source1, i => action1 = i,
165 				source2, i => action2 = i);
166 
167 			source1.Post (10);
168 
169 			Assert.IsTrue (completion.Wait (1000));
170 			Assert.AreEqual (0, completion.Result);
171 			Assert.AreEqual (42, action1);
172 			Assert.AreEqual (0, action2);
173 		}
174 
175 		[Test]
ExceptionTest()176 		public void ExceptionTest ()
177 		{
178 			var source1 = new BufferBlock<int> ();
179 			var source2 = new BufferBlock<long> ();
180 
181 			var exception = new Exception ();
182 			var completion = DataflowBlock.Choose (
183 				source1, _ => { throw exception; },
184 				source2, _ => { });
185 
186 			source1.Post (42);
187 
188 			var ae = AssertEx.Throws<AggregateException> (() => completion.Wait (1000));
189 			Assert.AreEqual (1, ae.InnerExceptions.Count);
190 			Assert.AreSame (exception, ae.InnerException);
191 		}
192 
193 		[Test]
BasicTest_3()194 		public void BasicTest_3 ()
195 		{
196 			var source1 = new BufferBlock<int> ();
197 			var source2 = new BufferBlock<long> ();
198 			var source3 = new BufferBlock<object> ();
199 
200 			bool action1 = false;
201 			bool action2 = false;
202 			bool action3 = false;
203 			var completion = DataflowBlock.Choose (
204 				source1, _ => action1 = true,
205 				source2, _ => action2 = true,
206 				source3, _ => action3 = true);
207 
208 			source3.Post (new object ());
209 
210 			Assert.IsTrue (completion.Wait (1000));
211 			Assert.AreEqual (2, completion.Result);
212 			Assert.IsFalse (action1);
213 			Assert.IsFalse (action2);
214 			Assert.IsTrue (action3);
215 		}
216 	}
217 }