Mercurial > pub > ImplabNet
annotate Implab.Test/AsyncTests.cs @ 33:b255e4aeef17
removed the reference to the parent from the promise object this allows
resolved promises to release parents and results they are holding.
Added complete set of operations to IPromiseBase interface
Subscribing to the cancellation event of the promise should not affect it's
IsExclusive property
More tests.
author | cin |
---|---|
date | Thu, 10 Apr 2014 02:39:29 +0400 |
parents | 2fad2d1f4b03 |
children | dabf79fde388 |
rev | line source |
---|---|
4 | 1 using System; |
2 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
3 using System.Reflection; | |
4 using System.Threading; | |
11 | 5 using Implab.Parallels; |
4 | 6 |
15 | 7 namespace Implab.Test { |
8 [TestClass] | |
9 public class AsyncTests { | |
10 [TestMethod] | |
11 public void ResolveTest() { | |
12 int res = -1; | |
13 var p = new Promise<int>(); | |
14 p.Then(x => res = x); | |
15 p.Resolve(100); | |
4 | 16 |
19
e3935fdf59a2
Promise is rewritten to use interlocked operations instead of locks
cin
parents:
17
diff
changeset
|
17 Assert.AreEqual(100, res); |
15 | 18 } |
0 | 19 |
4 | 20 [TestMethod] |
15 | 21 public void RejectTest() { |
22 int res = -1; | |
23 Exception err = null; | |
4 | 24 |
15 | 25 var p = new Promise<int>(); |
26 p.Then(x => res = x, e => err = e); | |
27 p.Reject(new ApplicationException("error")); | |
4 | 28 |
15 | 29 Assert.AreEqual(res, -1); |
30 Assert.AreEqual(err.Message, "error"); | |
4 | 31 |
15 | 32 } |
0 | 33 |
4 | 34 [TestMethod] |
15 | 35 public void JoinSuccessTest() { |
36 var p = new Promise<int>(); | |
37 p.Resolve(100); | |
38 Assert.AreEqual(p.Join(), 100); | |
39 } | |
0 | 40 |
4 | 41 [TestMethod] |
15 | 42 public void JoinFailTest() { |
43 var p = new Promise<int>(); | |
44 p.Reject(new ApplicationException("failed")); | |
4 | 45 |
15 | 46 try { |
47 p.Join(); | |
48 throw new ApplicationException("WRONG!"); | |
49 } catch (TargetInvocationException err) { | |
50 Assert.AreEqual(err.InnerException.Message, "failed"); | |
51 } catch { | |
52 Assert.Fail("Got wrong excaption"); | |
53 } | |
54 } | |
0 | 55 |
4 | 56 [TestMethod] |
15 | 57 public void MapTest() { |
58 var p = new Promise<int>(); | |
4 | 59 |
15 | 60 var p2 = p.Map(x => x.ToString()); |
61 p.Resolve(100); | |
4 | 62 |
15 | 63 Assert.AreEqual(p2.Join(), "100"); |
64 } | |
0 | 65 |
4 | 66 [TestMethod] |
11 | 67 public void FixErrorTest() { |
68 var p = new Promise<int>(); | |
69 | |
70 var p2 = p.Error(e => 101); | |
71 | |
72 p.Reject(new Exception()); | |
73 | |
74 Assert.AreEqual(p2.Join(), 101); | |
75 } | |
76 | |
77 [TestMethod] | |
15 | 78 public void ChainTest() { |
79 var p1 = new Promise<int>(); | |
4 | 80 |
15 | 81 var p3 = p1.Chain(x => { |
82 var p2 = new Promise<string>(); | |
83 p2.Resolve(x.ToString()); | |
84 return p2; | |
85 }); | |
4 | 86 |
15 | 87 p1.Resolve(100); |
4 | 88 |
15 | 89 Assert.AreEqual(p3.Join(), "100"); |
90 } | |
0 | 91 |
4 | 92 [TestMethod] |
15 | 93 public void PoolTest() { |
94 var pid = Thread.CurrentThread.ManagedThreadId; | |
95 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId); | |
4 | 96 |
15 | 97 Assert.AreNotEqual(pid, p.Join()); |
98 } | |
10 | 99 |
100 [TestMethod] | |
13 | 101 public void WorkerPoolSizeTest() { |
17 | 102 var pool = new WorkerPool(5, 10, 0); |
13 | 103 |
20 | 104 Assert.AreEqual(5, pool.PoolSize); |
13 | 105 |
22 | 106 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); |
107 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
108 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | |
13 | 109 |
20 | 110 Assert.AreEqual(5, pool.PoolSize); |
13 | 111 |
112 for (int i = 0; i < 100; i++) | |
22 | 113 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); |
114 Thread.Sleep(200); | |
20 | 115 Assert.AreEqual(10, pool.PoolSize); |
15 | 116 |
117 pool.Dispose(); | |
13 | 118 } |
119 | |
120 [TestMethod] | |
121 public void WorkerPoolCorrectTest() { | |
17 | 122 var pool = new WorkerPool(0,1000,100); |
15 | 123 |
124 int iterations = 1000; | |
125 int pending = iterations; | |
126 var stop = new ManualResetEvent(false); | |
13 | 127 |
128 var count = 0; | |
15 | 129 for (int i = 0; i < iterations; i++) { |
13 | 130 pool |
131 .Invoke(() => 1) | |
15 | 132 .Then(x => Interlocked.Add(ref count, x)) |
133 .Then(x => Math.Log10(x)) | |
134 .Anyway(() => { | |
135 Interlocked.Decrement(ref pending); | |
136 if (pending == 0) | |
137 stop.Set(); | |
138 }); | |
139 } | |
140 | |
141 stop.WaitOne(); | |
13 | 142 |
15 | 143 Assert.AreEqual(iterations, count); |
144 Console.WriteLine("Max threads: {0}", pool.MaxRunningThreads); | |
145 pool.Dispose(); | |
146 | |
147 } | |
148 | |
149 [TestMethod] | |
150 public void WorkerPoolDisposeTest() { | |
151 var pool = new WorkerPool(5, 20); | |
20 | 152 Assert.AreEqual(5, pool.PoolSize); |
15 | 153 pool.Dispose(); |
21
6a56df4ec59e
DispatchPool works again, but performance is poor in some cases
cin
parents:
20
diff
changeset
|
154 Thread.Sleep(500); |
20 | 155 Assert.AreEqual(0, pool.PoolSize); |
15 | 156 pool.Dispose(); |
13 | 157 } |
158 | |
159 [TestMethod] | |
14 | 160 public void MTQueueTest() { |
161 var queue = new MTQueue<int>(); | |
162 int res; | |
163 | |
164 queue.Enqueue(10); | |
165 Assert.IsTrue(queue.TryDequeue(out res)); | |
166 Assert.AreEqual(10, res); | |
167 Assert.IsFalse(queue.TryDequeue(out res)); | |
168 | |
169 for (int i = 0; i < 1000; i++) | |
170 queue.Enqueue(i); | |
171 | |
172 for (int i = 0; i < 1000; i++) { | |
173 queue.TryDequeue(out res); | |
174 Assert.AreEqual(i, res); | |
175 } | |
176 | |
177 int writers = 0; | |
178 int readers = 0; | |
179 var stop = new ManualResetEvent(false); | |
180 int total = 0; | |
181 | |
182 int itemsPerWriter = 1000; | |
183 int writersCount = 3; | |
184 | |
185 for (int i = 0; i < writersCount; i++) { | |
186 Interlocked.Increment(ref writers); | |
187 var wn = i; | |
188 AsyncPool | |
189 .InvokeNewThread(() => { | |
190 for (int ii = 0; ii < itemsPerWriter; ii++) { | |
191 queue.Enqueue(1); | |
192 } | |
193 return 1; | |
194 }) | |
15 | 195 .Anyway(() => Interlocked.Decrement(ref writers)); |
14 | 196 } |
15 | 197 |
14 | 198 for (int i = 0; i < 10; i++) { |
199 Interlocked.Increment(ref readers); | |
200 var wn = i; | |
201 AsyncPool | |
202 .InvokeNewThread(() => { | |
203 int t; | |
204 do { | |
205 while (queue.TryDequeue(out t)) | |
206 Interlocked.Add(ref total, t); | |
207 } while (writers > 0); | |
208 return 1; | |
209 }) | |
15 | 210 .Anyway(() => { |
14 | 211 Interlocked.Decrement(ref readers); |
212 if (readers == 0) | |
213 stop.Set(); | |
214 }); | |
215 } | |
216 | |
217 stop.WaitOne(); | |
218 | |
219 Assert.AreEqual(itemsPerWriter * writersCount, total); | |
220 } | |
221 | |
222 [TestMethod] | |
15 | 223 public void ParallelMapTest() { |
224 | |
225 int count = 100000; | |
226 | |
227 double[] args = new double[count]; | |
228 var rand = new Random(); | |
229 | |
230 for (int i = 0; i < count; i++) | |
231 args[i] = rand.NextDouble(); | |
232 | |
233 var t = Environment.TickCount; | |
234 var res = args.ParallelMap(x => Math.Sin(x*x), 4).Join(); | |
235 | |
236 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t); | |
237 | |
238 t = Environment.TickCount; | |
239 for (int i = 0; i < count; i++) | |
240 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]); | |
241 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t); | |
242 } | |
243 | |
244 [TestMethod] | |
16 | 245 public void ChainedMapTest() { |
246 | |
24 | 247 using (var pool = new WorkerPool(0,100,0)) { |
16 | 248 int count = 10000; |
249 | |
250 double[] args = new double[count]; | |
251 var rand = new Random(); | |
252 | |
253 for (int i = 0; i < count; i++) | |
254 args[i] = rand.NextDouble(); | |
255 | |
256 var t = Environment.TickCount; | |
257 var res = args | |
30 | 258 .ChainedMap( |
16 | 259 x => pool.Invoke( |
260 () => Math.Sin(x * x) | |
261 ), | |
262 4 | |
263 ) | |
264 .Join(); | |
265 | |
266 Console.WriteLine("Map complete in {0} ms", Environment.TickCount - t); | |
267 | |
268 t = Environment.TickCount; | |
269 for (int i = 0; i < count; i++) | |
270 Assert.AreEqual(Math.Sin(args[i] * args[i]), res[i]); | |
271 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t); | |
272 Console.WriteLine("Max workers: {0}", pool.MaxRunningThreads); | |
273 } | |
274 } | |
275 | |
276 [TestMethod] | |
15 | 277 public void ParallelForEachTest() { |
278 | |
279 int count = 100000; | |
280 | |
281 int[] args = new int[count]; | |
282 var rand = new Random(); | |
283 | |
284 for (int i = 0; i < count; i++) | |
285 args[i] = (int)(rand.NextDouble() * 100); | |
286 | |
287 int result = 0; | |
288 | |
289 var t = Environment.TickCount; | |
290 args.ParallelForEach(x => Interlocked.Add(ref result, x), 4).Join(); | |
291 | |
292 Console.WriteLine("Iteration complete in {0} ms, result: {1}", Environment.TickCount - t, result); | |
293 | |
294 int result2 = 0; | |
295 | |
296 t = Environment.TickCount; | |
297 for (int i = 0; i < count; i++) | |
298 result2 += args[i]; | |
299 Assert.AreEqual(result2, result); | |
300 Console.WriteLine("Verified in {0} ms", Environment.TickCount - t); | |
301 } | |
302 | |
303 [TestMethod] | |
10 | 304 public void ComplexCase1Test() { |
305 var flags = new bool[3]; | |
306 | |
307 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map) | |
308 | |
309 var p = PromiseHelper | |
310 .Sleep(200, "Alan") | |
311 .Cancelled(() => flags[0] = true) | |
312 .Chain(x => | |
313 PromiseHelper | |
314 .Sleep(200, "Hi, " + x) | |
15 | 315 .Map(y => y) |
10 | 316 .Cancelled(() => flags[1] = true) |
317 ) | |
318 .Cancelled(() => flags[2] = true); | |
319 Thread.Sleep(300); | |
320 p.Cancel(); | |
321 try { | |
322 Assert.AreEqual(p.Join(), "Hi, Alan"); | |
323 Assert.Fail("Shouldn't get here"); | |
15 | 324 } catch (OperationCanceledException) { |
10 | 325 } |
326 | |
327 Assert.IsFalse(flags[0]); | |
328 Assert.IsTrue(flags[1]); | |
329 Assert.IsTrue(flags[2]); | |
330 } | |
33
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
331 |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
332 [TestMethod] |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
333 public void ChainedCancel1Test() { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
334 // при отмене сцепленной асинхронной операции все обещание должно |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
335 // завершаться ошибкой OperationCanceledException |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
336 var p = PromiseHelper |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
337 .Sleep(1, "Hi, HAL!") |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
338 .Chain(x => { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
339 // запускаем две асинхронные операции |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
340 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!"); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
341 // вторая операция отменяет первую до завершения |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
342 PromiseHelper |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
343 .Sleep(100, "HAL, STOP!") |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
344 .Then(() => result.Cancel()); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
345 return result; |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
346 }); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
347 try { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
348 p.Join(); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
349 } catch (TargetInvocationException err) { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
350 Assert.IsTrue(err.InnerException is OperationCanceledException); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
351 } |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
352 } |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
353 |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
354 [TestMethod] |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
355 public void ChainedCancel2Test() { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
356 // при отмене цепочки обещаний, вложенные операции также должны отменяться |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
357 IPromiseBase p = null; |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
358 var pSurvive = new Promise<bool>(); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
359 var hemStarted = new ManualResetEvent(false); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
360 p = PromiseHelper |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
361 .Sleep(1, "Hi, HAL!") |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
362 .Chain(x => { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
363 hemStarted.Set(); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
364 // запускаем две асинхронные операции |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
365 var result = PromiseHelper |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
366 .Sleep(1000, "HEM ENABLED!!!") |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
367 .Then(s => pSurvive.Resolve(false)); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
368 |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
369 result |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
370 .Cancelled(() => pSurvive.Resolve(true)); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
371 |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
372 return result; |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
373 }); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
374 |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
375 hemStarted.WaitOne(); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
376 p.Cancel(); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
377 |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
378 try { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
379 p.Join(); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
380 } catch (OperationCanceledException) { |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
381 Assert.IsTrue(pSurvive.Join()); |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
382 } |
b255e4aeef17
removed the reference to the parent from the promise object this allows
cin
parents:
30
diff
changeset
|
383 } |
15 | 384 } |
4 | 385 } |
386 |