Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / class / System.Threading.Tasks.Dataflow / Test / System.Threading.Tasks.Dataflow / WriteOnceBlockTest.cs
1 // WriteOnceBlockTest.cs
2 //  
3 // Author:
4 //       Jérémie "garuma" Laval <jeremie.laval@gmail.com>
5 //       Petr Onderka <gsvick@gmail.com>
6 // 
7 // Copyright (c) 2011 Jérémie "garuma" Laval
8 // Copyright (c) 2012 Petr Onderka
9 // 
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27
28 using System;
29 using System.Threading;
30 using System.Collections.Generic;
31 using System.Threading.Tasks.Dataflow;
32 using NUnit.Framework;
33
34 namespace MonoTests.System.Threading.Tasks.Dataflow {
35         [TestFixture]
36         public class WriteOnceBlockTest {
37                 [Test]
38                 public void BasicUsageTest ()
39                 {
40                         bool act1 = false, act2 = false;
41                         var evt = new CountdownEvent (2);
42
43                         var block = new WriteOnceBlock<int> (null);
44                         var action1 = new ActionBlock<int> (i =>
45                         {
46                                 act1 = i == 42;
47                                 evt.Signal ();
48                         });
49                         var action2 = new ActionBlock<int> (i =>
50                         {
51                                 act2 = i == 42;
52                                 evt.Signal ();
53                         });
54
55                         block.LinkTo (action1);
56                         block.LinkTo (action2);
57
58                         Assert.IsTrue (block.Post (42));
59                         Assert.IsFalse (block.Post (43));
60
61                         Assert.IsTrue (evt.Wait (100));
62
63                         Assert.IsTrue (act1);
64                         Assert.IsTrue (act2);
65                 }
66
67                 [Test]
68                 public void LinkAfterPostTest ()
69                 {
70                         bool act = false;
71                         var evt = new ManualResetEventSlim ();
72
73                         var block = new WriteOnceBlock<int> (null);
74                         var action = new ActionBlock<int> (i =>
75                         {
76                                 act = i == 42;
77                                 evt.Set ();
78                         });
79
80                         Assert.IsTrue (block.Post (42));
81
82                         block.LinkTo (action);
83
84                         Assert.IsTrue (evt.Wait (100));
85
86                         Assert.IsTrue (act);
87                 }
88
89                 [Test]
90                 public void PostponedTest ()
91                 {
92                         var block = new WriteOnceBlock<int> (null);
93                         var target = new BufferBlock<int> (
94                                 new DataflowBlockOptions { BoundedCapacity = 1 });
95                         block.LinkTo (target);
96
97                         Assert.IsTrue (target.Post (1));
98
99                         Assert.IsTrue (block.Post (2));
100
101                         Assert.AreEqual (1, target.Receive (TimeSpan.FromMilliseconds (100)));
102                         Assert.AreEqual (2, target.Receive (TimeSpan.FromMilliseconds (100)));
103                 }
104
105                 [Test]
106                 public void QueuedMessageTest ()
107                 {
108                         var scheduler = new TestScheduler ();
109                         var block = new WriteOnceBlock<int> (null,
110                                 new DataflowBlockOptions { TaskScheduler = scheduler });
111                         var target = new BufferBlock<int> ();
112                         block.LinkTo (target);
113
114                         Assert.IsTrue (block.Post (1));
115
116                         AssertEx.Throws<TimeoutException> (
117                                 () => target.Receive (TimeSpan.FromMilliseconds (100)));
118
119                         scheduler.ExecuteAll ();
120
121                         int item;
122                         Assert.IsTrue (target.TryReceive (out item));
123                         Assert.AreEqual (1, item);
124                 }
125
126                 [Test]
127                 public void CloningTest ()
128                 {
129                         object act1 = null, act2 = null;
130                         var evt = new CountdownEvent (2);
131
132                         object source = new object ();
133                         var block = new WriteOnceBlock<object> (o => new object ());
134                         var action1 = new ActionBlock<object> (i =>
135                         {
136                                 act1 = i;
137                                 evt.Signal ();
138                         });
139                         var action2 = new ActionBlock<object> (i =>
140                         {
141                                 act2 = i;
142                                 evt.Signal ();
143                         });
144
145                         block.LinkTo (action1);
146                         block.LinkTo (action2);
147
148                         Assert.IsTrue (block.Post (source));
149
150                         Assert.IsTrue (evt.Wait (100));
151
152                         Assert.IsNotNull (act1);
153                         Assert.IsNotNull (act2);
154
155                         Assert.IsFalse (source.Equals (act1));
156                         Assert.IsFalse (source.Equals (act2));
157                         Assert.IsFalse (act2.Equals (act1));
158                 }
159
160                 [Test]
161                 public void WriteOnceBehaviorTest ()
162                 {
163                         bool act1 = false, act2 = false;
164                         var evt = new CountdownEvent (2);
165
166                         var broadcast = new WriteOnceBlock<int> (null);
167                         var action1 = new ActionBlock<int> (i =>
168                         {
169                                 act1 = i == 42;
170                                 evt.Signal ();
171                         });
172                         var action2 = new ActionBlock<int> (i =>
173                         {
174                                 act2 = i == 42;
175                                 evt.Signal ();
176                         });
177
178                         broadcast.LinkTo (action1);
179                         broadcast.LinkTo (action2);
180
181                         Assert.IsTrue (broadcast.Post (42));
182
183                         Assert.IsTrue (evt.Wait (100));
184
185                         Assert.IsTrue (act1);
186                         Assert.IsTrue (act2);
187
188                         Assert.IsFalse (broadcast.Post (24));
189                         Thread.Sleep (300);
190
191                         Assert.IsTrue (act1);
192                         Assert.IsTrue (act2);
193                 }
194
195                 [Test]
196                 public void TryReceiveBehaviorTest ()
197                 {
198                         var block = new WriteOnceBlock<int> (null);
199                         int foo;
200                         Assert.IsFalse (block.TryReceive (null, out foo));
201                         block.Post (42);
202                         Assert.IsTrue (block.TryReceive (null, out foo));
203                         Assert.AreEqual (42, foo);
204                         Assert.IsTrue (block.TryReceive (null, out foo));
205                         Assert.IsFalse (block.TryReceive (i => i == 0, out foo));
206                         IList<int> bar;
207                         Assert.IsTrue (((IReceivableSourceBlock<int>)block).TryReceiveAll (out bar));
208                         CollectionAssert.AreEqual (new[] { 42 }, bar);
209                 }
210
211                 [Test]
212                 public void DontOfferTwiceTest ()
213                 {
214                         var scheduler = new TestScheduler ();
215                         var block = new WriteOnceBlock<int> (null,
216                                 new DataflowBlockOptions { TaskScheduler = scheduler });
217                         var target =
218                                 new TestTargetBlock<int> { Postpone = true };
219                         block.LinkTo (target);
220
221                         Assert.IsFalse (target.HasPostponed);
222
223                         Assert.IsTrue (block.Post (1));
224
225                         scheduler.ExecuteAll ();
226
227                         Assert.IsTrue (target.HasPostponed);
228
229                         target.Postpone = false;
230
231                         int value;
232                         Assert.IsTrue (target.RetryPostponed (out value));
233                         Assert.AreEqual (1, value);
234
235                         block.LinkTo (new BufferBlock<int> ());
236
237                         scheduler.ExecuteAll ();
238
239                         Assert.AreEqual (default(int), target.DirectlyAccepted);
240                 }
241         }
242 }