Mercurial > pub > ImplabNet
comparison Implab.Test/AsyncTests.cs @ 192:f1da3afc3521 release v2.1
Слияние с v2
author | cin |
---|---|
date | Fri, 22 Apr 2016 13:10:34 +0300 |
parents | ec91a6dfa5b3 |
children | 8200ab154c8a |
comparison
equal
deleted
inserted
replaced
71:1714fd8678ef | 192:f1da3afc3521 |
---|---|
1 using System; | 1 using System; |
2 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
3 using System.Reflection; | 2 using System.Reflection; |
4 using System.Threading; | 3 using System.Threading; |
5 using Implab.Parallels; | 4 using Implab.Parallels; |
5 | |
6 #if MONO | |
7 | |
8 using NUnit.Framework; | |
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute; | |
10 using TestMethodAttribute = NUnit.Framework.TestAttribute; | |
11 | |
12 #else | |
13 | |
14 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
15 | |
16 #endif | |
6 | 17 |
7 namespace Implab.Test { | 18 namespace Implab.Test { |
8 [TestClass] | 19 [TestClass] |
9 public class AsyncTests { | 20 public class AsyncTests { |
10 [TestMethod] | 21 [TestMethod] |
21 public void RejectTest() { | 32 public void RejectTest() { |
22 int res = -1; | 33 int res = -1; |
23 Exception err = null; | 34 Exception err = null; |
24 | 35 |
25 var p = new Promise<int>(); | 36 var p = new Promise<int>(); |
26 p.Then(x => res = x, e => err = e); | 37 p.Then( |
38 x => res = x, | |
39 e => { | |
40 err = e; | |
41 return -2; | |
42 } | |
43 ); | |
27 p.Reject(new ApplicationException("error")); | 44 p.Reject(new ApplicationException("error")); |
28 | 45 |
29 Assert.AreEqual(res, -1); | 46 Assert.AreEqual(res, -1); |
30 Assert.AreEqual(err.Message, "error"); | 47 Assert.AreEqual(err.Message, "error"); |
31 | 48 |
49 } | |
50 | |
51 [TestMethod] | |
52 public void CancelExceptionTest() { | |
53 var p = new Promise<bool>(); | |
54 p.CancelOperation(null); | |
55 | |
56 var p2 = p.Then(x => x, null, reason => { | |
57 throw new ApplicationException("CANCELLED"); | |
58 }); | |
59 | |
60 try { | |
61 p2.Join(); | |
62 Assert.Fail(); | |
63 } catch (ApplicationException err) { | |
64 Assert.AreEqual("CANCELLED", err.InnerException.Message); | |
65 } | |
66 | |
67 } | |
68 | |
69 [TestMethod] | |
70 public void ContinueOnCancelTest() { | |
71 var p = new Promise<bool>(); | |
72 p.CancelOperation(null); | |
73 | |
74 var p2 = p | |
75 .Then(x => x, null, reason => { | |
76 throw new ApplicationException("CANCELLED"); | |
77 }) | |
78 .Then(x => x, e => true); | |
79 | |
80 Assert.AreEqual(true, p2.Join()); | |
32 } | 81 } |
33 | 82 |
34 [TestMethod] | 83 [TestMethod] |
35 public void JoinSuccessTest() { | 84 public void JoinSuccessTest() { |
36 var p = new Promise<int>(); | 85 var p = new Promise<int>(); |
55 | 104 |
56 [TestMethod] | 105 [TestMethod] |
57 public void MapTest() { | 106 public void MapTest() { |
58 var p = new Promise<int>(); | 107 var p = new Promise<int>(); |
59 | 108 |
60 var p2 = p.Map(x => x.ToString()); | 109 var p2 = p.Then(x => x.ToString()); |
61 p.Resolve(100); | 110 p.Resolve(100); |
62 | 111 |
63 Assert.AreEqual(p2.Join(), "100"); | 112 Assert.AreEqual(p2.Join(), "100"); |
64 } | 113 } |
65 | 114 |
66 [TestMethod] | 115 [TestMethod] |
67 public void FixErrorTest() { | 116 public void FixErrorTest() { |
68 var p = new Promise<int>(); | 117 var p = new Promise<int>(); |
69 | 118 |
70 var p2 = p.Error(e => 101); | 119 var p2 = p.Then(x => x, e => 101); |
71 | 120 |
72 p.Reject(new Exception()); | 121 p.Reject(new Exception()); |
73 | 122 |
74 Assert.AreEqual(p2.Join(), 101); | 123 Assert.AreEqual(p2.Join(), 101); |
75 } | 124 } |
88 | 137 |
89 Assert.AreEqual(p3.Join(), "100"); | 138 Assert.AreEqual(p3.Join(), "100"); |
90 } | 139 } |
91 | 140 |
92 [TestMethod] | 141 [TestMethod] |
142 public void ChainFailTest() { | |
143 var p1 = new Promise<int>(); | |
144 | |
145 var p3 = p1.Chain(x => { | |
146 var p2 = new Promise<string>(); | |
147 p2.Reject(new Exception("DIE!!!")); | |
148 return p2; | |
149 }); | |
150 | |
151 p1.Resolve(100); | |
152 | |
153 Assert.IsTrue(p3.IsResolved); | |
154 } | |
155 | |
156 [TestMethod] | |
93 public void PoolTest() { | 157 public void PoolTest() { |
94 var pid = Thread.CurrentThread.ManagedThreadId; | 158 var pid = Thread.CurrentThread.ManagedThreadId; |
95 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId); | 159 var p = AsyncPool.Invoke(() => Thread.CurrentThread.ManagedThreadId); |
96 | 160 |
97 Assert.AreNotEqual(pid, p.Join()); | 161 Assert.AreNotEqual(pid, p.Join()); |
98 } | 162 } |
99 | 163 |
100 [TestMethod] | 164 [TestMethod] |
101 public void WorkerPoolSizeTest() { | 165 public void WorkerPoolSizeTest() { |
102 var pool = new WorkerPool(5, 10, 0); | 166 var pool = new WorkerPool(5, 10, 1); |
103 | 167 |
104 Assert.AreEqual(5, pool.PoolSize); | 168 Assert.AreEqual(5, pool.PoolSize); |
105 | 169 |
106 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | 170 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); |
107 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); | 171 pool.Invoke(() => { Thread.Sleep(100000000); return 10; }); |
119 | 183 |
120 [TestMethod] | 184 [TestMethod] |
121 public void WorkerPoolCorrectTest() { | 185 public void WorkerPoolCorrectTest() { |
122 var pool = new WorkerPool(0,1000,100); | 186 var pool = new WorkerPool(0,1000,100); |
123 | 187 |
124 int iterations = 1000; | 188 const int iterations = 1000; |
125 int pending = iterations; | 189 int pending = iterations; |
126 var stop = new ManualResetEvent(false); | 190 var stop = new ManualResetEvent(false); |
127 | 191 |
128 var count = 0; | 192 var count = 0; |
129 for (int i = 0; i < iterations; i++) { | 193 for (int i = 0; i < iterations; i++) { |
130 pool | 194 pool |
131 .Invoke(() => 1) | 195 .Invoke(() => 1) |
132 .Then(x => Interlocked.Add(ref count, x)) | 196 .Then(x => Interlocked.Add(ref count, x)) |
133 .Then(x => Math.Log10(x)) | 197 .Then(x => Math.Log10(x)) |
134 .Anyway(() => { | 198 .On(() => { |
135 Interlocked.Decrement(ref pending); | 199 Interlocked.Decrement(ref pending); |
136 if (pending == 0) | 200 if (pending == 0) |
137 stop.Set(); | 201 stop.Set(); |
138 }); | 202 }, PromiseEventType.All); |
139 } | 203 } |
140 | 204 |
141 stop.WaitOne(); | 205 stop.WaitOne(); |
142 | 206 |
143 Assert.AreEqual(iterations, count); | 207 Assert.AreEqual(iterations, count); |
177 int writers = 0; | 241 int writers = 0; |
178 int readers = 0; | 242 int readers = 0; |
179 var stop = new ManualResetEvent(false); | 243 var stop = new ManualResetEvent(false); |
180 int total = 0; | 244 int total = 0; |
181 | 245 |
182 int itemsPerWriter = 1000; | 246 const int itemsPerWriter = 10000; |
183 int writersCount = 3; | 247 const int writersCount = 10; |
184 | 248 |
185 for (int i = 0; i < writersCount; i++) { | 249 for (int i = 0; i < writersCount; i++) { |
186 Interlocked.Increment(ref writers); | 250 Interlocked.Increment(ref writers); |
187 var wn = i; | |
188 AsyncPool | 251 AsyncPool |
189 .InvokeNewThread(() => { | 252 .RunThread(() => { |
190 for (int ii = 0; ii < itemsPerWriter; ii++) { | 253 for (int ii = 0; ii < itemsPerWriter; ii++) { |
191 queue.Enqueue(1); | 254 queue.Enqueue(1); |
192 } | 255 } |
193 return 1; | 256 return 1; |
194 }) | 257 }) |
195 .Anyway(() => Interlocked.Decrement(ref writers)); | 258 .On(() => Interlocked.Decrement(ref writers), PromiseEventType.All); |
196 } | 259 } |
197 | 260 |
198 for (int i = 0; i < 10; i++) { | 261 for (int i = 0; i < 10; i++) { |
199 Interlocked.Increment(ref readers); | 262 Interlocked.Increment(ref readers); |
200 var wn = i; | |
201 AsyncPool | 263 AsyncPool |
202 .InvokeNewThread(() => { | 264 .RunThread(() => { |
203 int t; | 265 int t; |
204 do { | 266 do { |
205 while (queue.TryDequeue(out t)) | 267 while (queue.TryDequeue(out t)) |
206 Interlocked.Add(ref total, t); | 268 Interlocked.Add(ref total, t); |
207 } while (writers > 0); | 269 } while (writers > 0); |
208 return 1; | 270 return 1; |
209 }) | 271 }) |
210 .Anyway(() => { | 272 .On(() => { |
211 Interlocked.Decrement(ref readers); | 273 Interlocked.Decrement(ref readers); |
212 if (readers == 0) | 274 if (readers == 0) |
213 stop.Set(); | 275 stop.Set(); |
214 }); | 276 }, PromiseEventType.All); |
215 } | 277 } |
216 | 278 |
217 stop.WaitOne(); | 279 stop.WaitOne(); |
218 | 280 |
219 Assert.AreEqual(itemsPerWriter * writersCount, total); | 281 Assert.AreEqual(100000, total); |
282 } | |
283 | |
284 [TestMethod] | |
285 public void AsyncQueueTest() { | |
286 var queue = new AsyncQueue<int>(); | |
287 int res; | |
288 | |
289 queue.Enqueue(10); | |
290 Assert.IsTrue(queue.TryDequeue(out res)); | |
291 Assert.AreEqual(10, res); | |
292 Assert.IsFalse(queue.TryDequeue(out res)); | |
293 | |
294 for (int i = 0; i < 1000; i++) | |
295 queue.Enqueue(i); | |
296 | |
297 for (int i = 0; i < 1000; i++) { | |
298 queue.TryDequeue(out res); | |
299 Assert.AreEqual(i, res); | |
300 } | |
301 | |
302 const int count = 10000000; | |
303 | |
304 int res1 = 0, res2 = 0; | |
305 var t1 = Environment.TickCount; | |
306 | |
307 AsyncPool.RunThread( | |
308 () => { | |
309 for (var i = 0; i < count; i++) | |
310 queue.Enqueue(1); | |
311 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1); | |
312 }, | |
313 () => { | |
314 for (var i = 0; i < count; i++) | |
315 queue.Enqueue(2); | |
316 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1); | |
317 }, | |
318 () => { | |
319 int temp; | |
320 int i = 0; | |
321 while (i < count) | |
322 if (queue.TryDequeue(out temp)) { | |
323 i++; | |
324 res1 += temp; | |
325 } | |
326 Console.WriteLine("done reader #1: {0} ms", Environment.TickCount - t1); | |
327 }, | |
328 () => { | |
329 int temp; | |
330 int i = 0; | |
331 while (i < count) | |
332 if (queue.TryDequeue(out temp)) { | |
333 i++; | |
334 res2 += temp; | |
335 } | |
336 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1); | |
337 } | |
338 ) | |
339 .Bundle() | |
340 .Join(); | |
341 | |
342 Assert.AreEqual(count * 3, res1 + res2); | |
343 | |
344 Console.WriteLine( | |
345 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}", | |
346 Environment.TickCount - t1, | |
347 res1, | |
348 res2, | |
349 res1 + res2, | |
350 count | |
351 ); | |
352 } | |
353 | |
354 [TestMethod] | |
355 public void AsyncQueueBatchTest() { | |
356 var queue = new AsyncQueue<int>(); | |
357 | |
358 const int wBatch = 29; | |
359 const int wCount = 400000; | |
360 const int total = wBatch * wCount * 2; | |
361 const int summ = wBatch * wCount * 3; | |
362 | |
363 int r1 = 0, r2 = 0; | |
364 const int rBatch = 111; | |
365 int read = 0; | |
366 | |
367 var t1 = Environment.TickCount; | |
368 | |
369 AsyncPool.RunThread( | |
370 () => { | |
371 var buffer = new int[wBatch]; | |
372 for(int i = 0; i<wBatch; i++) | |
373 buffer[i] = 1; | |
374 | |
375 for(int i =0; i < wCount; i++) | |
376 queue.EnqueueRange(buffer,0,wBatch); | |
377 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1); | |
378 }, | |
379 () => { | |
380 var buffer = new int[wBatch]; | |
381 for(int i = 0; i<wBatch; i++) | |
382 buffer[i] = 2; | |
383 | |
384 for(int i =0; i < wCount; i++) | |
385 queue.EnqueueRange(buffer,0,wBatch); | |
386 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1); | |
387 }, | |
388 () => { | |
389 var buffer = new int[rBatch]; | |
390 | |
391 while(read < total) { | |
392 int actual; | |
393 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) { | |
394 for(int i=0; i< actual; i++) | |
395 r1 += buffer[i]; | |
396 Interlocked.Add(ref read, actual); | |
397 } | |
398 } | |
399 | |
400 Console.WriteLine("done reader #1: {0} ms", Environment.TickCount - t1); | |
401 }, | |
402 () => { | |
403 var buffer = new int[rBatch]; | |
404 | |
405 while(read < total) { | |
406 int actual; | |
407 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) { | |
408 for(int i=0; i< actual; i++) | |
409 r2 += buffer[i]; | |
410 Interlocked.Add(ref read, actual); | |
411 } | |
412 } | |
413 | |
414 Console.WriteLine("done reader #2: {0} ms", Environment.TickCount - t1); | |
415 } | |
416 ) | |
417 .Bundle() | |
418 .Join(); | |
419 | |
420 Assert.AreEqual(summ , r1 + r2); | |
421 | |
422 Console.WriteLine( | |
423 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}", | |
424 Environment.TickCount - t1, | |
425 r1, | |
426 r2, | |
427 r1 + r2, | |
428 total | |
429 ); | |
430 } | |
431 | |
432 [TestMethod] | |
433 public void AsyncQueueChunkDequeueTest() { | |
434 var queue = new AsyncQueue<int>(); | |
435 | |
436 const int wBatch = 31; | |
437 const int wCount = 200000; | |
438 const int total = wBatch * wCount * 3; | |
439 const int summ = wBatch * wCount * 6; | |
440 | |
441 int r1 = 0, r2 = 0; | |
442 const int rBatch = 1024; | |
443 int read = 0; | |
444 | |
445 var t1 = Environment.TickCount; | |
446 | |
447 AsyncPool.RunThread( | |
448 () => { | |
449 var buffer = new int[wBatch]; | |
450 for(int i = 0; i<wBatch; i++) | |
451 buffer[i] = 1; | |
452 | |
453 for(int i =0; i < wCount; i++) | |
454 queue.EnqueueRange(buffer,0,wBatch); | |
455 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1); | |
456 }, | |
457 () => { | |
458 var buffer = new int[wBatch]; | |
459 for(int i = 0; i<wBatch; i++) | |
460 buffer[i] = 2; | |
461 | |
462 for(int i =0; i < wCount; i++) | |
463 queue.EnqueueRange(buffer,0,wBatch); | |
464 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1); | |
465 }, | |
466 () => { | |
467 var buffer = new int[wBatch]; | |
468 for(int i = 0; i<wBatch; i++) | |
469 buffer[i] = 3; | |
470 | |
471 for(int i =0; i < wCount; i++) | |
472 queue.EnqueueRange(buffer,0,wBatch); | |
473 Console.WriteLine("done writer #3: {0} ms", Environment.TickCount - t1); | |
474 }, | |
475 () => { | |
476 var buffer = new int[rBatch]; | |
477 int count = 1; | |
478 double avgchunk = 0; | |
479 while(read < total) { | |
480 int actual; | |
481 if (queue.TryDequeueChunk(buffer,0,rBatch,out actual)) { | |
482 for(int i=0; i< actual; i++) | |
483 r2 += buffer[i]; | |
484 Interlocked.Add(ref read, actual); | |
485 avgchunk = avgchunk*(count-1)/count + actual/(double)count; | |
486 count ++; | |
487 } | |
488 } | |
489 | |
490 Console.WriteLine("done reader #2: {0} ms, avg chunk size: {1}", Environment.TickCount - t1, avgchunk); | |
491 } | |
492 ) | |
493 .Bundle() | |
494 .Join(); | |
495 | |
496 Assert.AreEqual(summ , r1 + r2); | |
497 | |
498 Console.WriteLine( | |
499 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}", | |
500 Environment.TickCount - t1, | |
501 r1, | |
502 r2, | |
503 r1 + r2, | |
504 total | |
505 ); | |
506 } | |
507 | |
508 [TestMethod] | |
509 public void AsyncQueueDrainTest() { | |
510 var queue = new AsyncQueue<int>(); | |
511 | |
512 const int wBatch = 11; | |
513 const int wCount = 200000; | |
514 const int total = wBatch * wCount * 3; | |
515 const int summ = wBatch * wCount * 3; | |
516 | |
517 int r1 = 0, r2 = 0; | |
518 const int rBatch = 11; | |
519 int read = 0; | |
520 | |
521 var t1 = Environment.TickCount; | |
522 | |
523 AsyncPool.RunThread( | |
524 () => { | |
525 var buffer = new int[wBatch]; | |
526 for(int i = 0; i<wBatch; i++) | |
527 buffer[i] = 1; | |
528 | |
529 for(int i =0; i < wCount; i++) | |
530 queue.EnqueueRange(buffer,0,wBatch); | |
531 Console.WriteLine("done writer #1: {0} ms", Environment.TickCount - t1); | |
532 }, | |
533 () => { | |
534 for(int i =0; i < wCount * wBatch; i++) | |
535 queue.Enqueue(1); | |
536 Console.WriteLine("done writer #2: {0} ms", Environment.TickCount - t1); | |
537 }, | |
538 () => { | |
539 var buffer = new int[wBatch]; | |
540 for(int i = 0; i<wBatch; i++) | |
541 buffer[i] = 1; | |
542 | |
543 for(int i =0; i < wCount; i++) | |
544 queue.EnqueueRange(buffer,0,wBatch); | |
545 Console.WriteLine("done writer #3: {0} ms", Environment.TickCount - t1); | |
546 }, | |
547 /*() => { | |
548 int temp; | |
549 int count = 0; | |
550 while (read < total) | |
551 if (queue.TryDequeue(out temp)) { | |
552 count++; | |
553 r1 += temp; | |
554 Interlocked.Increment(ref read); | |
555 } | |
556 Console.WriteLine("done reader #1: {0} ms, {1} count", Environment.TickCount - t1, count); | |
557 },*/ | |
558 /*() => { | |
559 var buffer = new int[rBatch]; | |
560 var count = 0; | |
561 while(read < total) { | |
562 int actual; | |
563 if (queue.TryDequeueRange(buffer,0,rBatch,out actual)) { | |
564 for(int i=0; i< actual; i++) | |
565 r1 += buffer[i]; | |
566 Interlocked.Add(ref read, actual); | |
567 count += actual; | |
568 } | |
569 } | |
570 | |
571 Console.WriteLine("done reader #1: {0} ms, {1} items", Environment.TickCount - t1, count); | |
572 },*/ | |
573 () => { | |
574 var count = 0; | |
575 while(read < total) { | |
576 var buffer = queue.Drain(); | |
577 for(int i=0; i< buffer.Length; i++) | |
578 r1 += buffer[i]; | |
579 Interlocked.Add(ref read, buffer.Length); | |
580 count += buffer.Length; | |
581 } | |
582 Console.WriteLine("done reader #1: {0} ms, {1} items", Environment.TickCount - t1, count); | |
583 }, | |
584 () => { | |
585 var count = 0; | |
586 while(read < total) { | |
587 var buffer = queue.Drain(); | |
588 for(int i=0; i< buffer.Length; i++) | |
589 r2 += buffer[i]; | |
590 Interlocked.Add(ref read, buffer.Length); | |
591 count += buffer.Length; | |
592 } | |
593 Console.WriteLine("done reader #2: {0} ms, {1} items", Environment.TickCount - t1, count); | |
594 } | |
595 ) | |
596 .Bundle() | |
597 .Join(); | |
598 | |
599 Assert.AreEqual(summ , r1 + r2); | |
600 | |
601 Console.WriteLine( | |
602 "done: {0} ms, summ#1: {1}, summ#2: {2}, total: {3}, count: {4}", | |
603 Environment.TickCount - t1, | |
604 r1, | |
605 r2, | |
606 r1 + r2, | |
607 total | |
608 ); | |
220 } | 609 } |
221 | 610 |
222 [TestMethod] | 611 [TestMethod] |
223 public void ParallelMapTest() { | 612 public void ParallelMapTest() { |
224 | 613 |
225 int count = 100000; | 614 const int count = 100000; |
226 | 615 |
227 double[] args = new double[count]; | 616 var args = new double[count]; |
228 var rand = new Random(); | 617 var rand = new Random(); |
229 | 618 |
230 for (int i = 0; i < count; i++) | 619 for (int i = 0; i < count; i++) |
231 args[i] = rand.NextDouble(); | 620 args[i] = rand.NextDouble(); |
232 | 621 |
242 } | 631 } |
243 | 632 |
244 [TestMethod] | 633 [TestMethod] |
245 public void ChainedMapTest() { | 634 public void ChainedMapTest() { |
246 | 635 |
247 using (var pool = new WorkerPool(0,100,100)) { | 636 using (var pool = new WorkerPool()) { |
248 int count = 10000; | 637 const int count = 10000; |
249 | 638 |
250 double[] args = new double[count]; | 639 var args = new double[count]; |
251 var rand = new Random(); | 640 var rand = new Random(); |
252 | 641 |
253 for (int i = 0; i < count; i++) | 642 for (int i = 0; i < count; i++) |
254 args[i] = rand.NextDouble(); | 643 args[i] = rand.NextDouble(); |
255 | 644 |
256 var t = Environment.TickCount; | 645 var t = Environment.TickCount; |
257 var res = args | 646 var res = args |
258 .ChainedMap( | 647 .ChainedMap( |
648 // Analysis disable once AccessToDisposedClosure | |
259 x => pool.Invoke( | 649 x => pool.Invoke( |
260 () => Math.Sin(x * x) | 650 () => Math.Sin(x * x) |
261 ), | 651 ), |
262 4 | 652 4 |
263 ) | 653 ) |
274 } | 664 } |
275 | 665 |
276 [TestMethod] | 666 [TestMethod] |
277 public void ParallelForEachTest() { | 667 public void ParallelForEachTest() { |
278 | 668 |
279 int count = 100000; | 669 const int count = 100000; |
280 | 670 |
281 int[] args = new int[count]; | 671 var args = new int[count]; |
282 var rand = new Random(); | 672 var rand = new Random(); |
283 | 673 |
284 for (int i = 0; i < count; i++) | 674 for (int i = 0; i < count; i++) |
285 args[i] = (int)(rand.NextDouble() * 100); | 675 args[i] = (int)(rand.NextDouble() * 100); |
286 | 676 |
304 public void ComplexCase1Test() { | 694 public void ComplexCase1Test() { |
305 var flags = new bool[3]; | 695 var flags = new bool[3]; |
306 | 696 |
307 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map) | 697 // op1 (aync 200ms) => op2 (async 200ms) => op3 (sync map) |
308 | 698 |
309 var p = PromiseHelper | 699 var step1 = PromiseHelper |
310 .Sleep(200, "Alan") | 700 .Sleep(200, "Alan") |
311 .Cancelled(() => flags[0] = true) | 701 .On(() => flags[0] = true, PromiseEventType.Cancelled); |
702 var p = step1 | |
312 .Chain(x => | 703 .Chain(x => |
313 PromiseHelper | 704 PromiseHelper |
314 .Sleep(200, "Hi, " + x) | 705 .Sleep(200, "Hi, " + x) |
315 .Map(y => y) | 706 .Then(y => y) |
316 .Cancelled(() => flags[1] = true) | 707 .On(() => flags[1] = true, PromiseEventType.Cancelled) |
317 ) | 708 ) |
318 .Cancelled(() => flags[2] = true); | 709 .On(() => flags[2] = true, PromiseEventType.Cancelled); |
319 Thread.Sleep(300); | 710 step1.Join(); |
320 p.Cancel(); | 711 p.Cancel(); |
321 try { | 712 try { |
322 Assert.AreEqual(p.Join(), "Hi, Alan"); | 713 Assert.AreEqual(p.Join(), "Hi, Alan"); |
323 Assert.Fail("Shouldn't get here"); | 714 Assert.Fail("Shouldn't get here"); |
324 } catch (OperationCanceledException) { | 715 } catch (OperationCanceledException) { |
329 Assert.IsTrue(flags[2]); | 720 Assert.IsTrue(flags[2]); |
330 } | 721 } |
331 | 722 |
332 [TestMethod] | 723 [TestMethod] |
333 public void ChainedCancel1Test() { | 724 public void ChainedCancel1Test() { |
334 // | 725 // при отмене сцепленной асинхронной операции все обещание должно |
335 // OperationCanceledException | 726 // завершаться ошибкой OperationCanceledException |
336 var p = PromiseHelper | 727 var p = PromiseHelper |
337 .Sleep(1, "Hi, HAL!") | 728 .Sleep(1, "Hi, HAL!") |
338 .Chain(x => { | 729 .Then(x => { |
339 // | 730 // запускаем две асинхронные операции |
340 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!"); | 731 var result = PromiseHelper.Sleep(1000, "HEM ENABLED!!!"); |
341 // | 732 // вторая операция отменяет первую до завершения |
342 PromiseHelper | 733 PromiseHelper |
343 .Sleep(100, "HAL, STOP!") | 734 .Sleep(100, "HAL, STOP!") |
344 .Then(() => result.Cancel()); | 735 .Then(result.Cancel); |
345 return result; | 736 return result; |
346 }); | 737 }); |
347 try { | 738 try { |
348 p.Join(); | 739 p.Join(); |
349 } catch (TargetInvocationException err) { | 740 } catch (TargetInvocationException err) { |
351 } | 742 } |
352 } | 743 } |
353 | 744 |
354 [TestMethod] | 745 [TestMethod] |
355 public void ChainedCancel2Test() { | 746 public void ChainedCancel2Test() { |
356 // , | 747 // при отмене цепочки обещаний, вложенные операции также должны отменяться |
357 IPromiseBase p = null; | |
358 var pSurvive = new Promise<bool>(); | 748 var pSurvive = new Promise<bool>(); |
359 var hemStarted = new ManualResetEvent(false); | 749 var hemStarted = new Signal(); |
360 p = PromiseHelper | 750 var p = PromiseHelper |
361 .Sleep(1, "Hi, HAL!") | 751 .Sleep(1, "Hi, HAL!") |
362 .Chain(x => { | 752 .Chain(() => { |
363 hemStarted.Set(); | 753 hemStarted.Set(); |
364 // | 754 // запускаем две асинхронные операции |
365 var result = PromiseHelper | 755 var result = PromiseHelper |
366 .Sleep(1000, "HEM ENABLED!!!") | 756 .Sleep(2000, "HEM ENABLED!!!") |
367 .Then(s => pSurvive.Resolve(false)); | 757 .Then(() => pSurvive.Resolve(false)); |
368 | 758 |
369 result | 759 result |
370 .Cancelled(() => pSurvive.Resolve(true)); | 760 .On(() => pSurvive.Resolve(true), PromiseEventType.Cancelled); |
371 | 761 |
372 return result; | 762 return result; |
373 }); | 763 }); |
374 | 764 |
375 hemStarted.WaitOne(); | 765 hemStarted.Wait(); |
376 p.Cancel(); | 766 p.Cancel(); |
377 | 767 |
378 try { | 768 try { |
379 p.Join(); | 769 p.Join(); |
770 Assert.Fail(); | |
380 } catch (OperationCanceledException) { | 771 } catch (OperationCanceledException) { |
381 Assert.IsTrue(pSurvive.Join()); | 772 } |
382 } | 773 Assert.IsTrue(pSurvive.Join()); |
383 } | 774 } |
775 | |
776 [TestMethod] | |
777 public void SharedLockTest() { | |
778 var l = new SharedLock(); | |
779 int shared = 0; | |
780 int exclusive = 0; | |
781 var s1 = new Signal(); | |
782 var log = new AsyncQueue<string>(); | |
783 | |
784 try { | |
785 AsyncPool.RunThread( | |
786 () => { | |
787 log.Enqueue("Reader #1 started"); | |
788 try { | |
789 l.LockShared(); | |
790 log.Enqueue("Reader #1 lock got"); | |
791 if (Interlocked.Increment(ref shared) == 2) | |
792 s1.Set(); | |
793 s1.Wait(); | |
794 log.Enqueue("Reader #1 finished"); | |
795 Interlocked.Decrement(ref shared); | |
796 } finally { | |
797 l.Release(); | |
798 log.Enqueue("Reader #1 lock released"); | |
799 } | |
800 }, | |
801 () => { | |
802 log.Enqueue("Reader #2 started"); | |
803 | |
804 try { | |
805 l.LockShared(); | |
806 log.Enqueue("Reader #2 lock got"); | |
807 | |
808 if (Interlocked.Increment(ref shared) == 2) | |
809 s1.Set(); | |
810 s1.Wait(); | |
811 log.Enqueue("Reader #2 upgrading to writer"); | |
812 Interlocked.Decrement(ref shared); | |
813 l.Upgrade(); | |
814 log.Enqueue("Reader #2 upgraded"); | |
815 | |
816 Assert.AreEqual(1, Interlocked.Increment(ref exclusive)); | |
817 Assert.AreEqual(0, shared); | |
818 log.Enqueue("Reader #2 finished"); | |
819 Interlocked.Decrement(ref exclusive); | |
820 } finally { | |
821 l.Release(); | |
822 log.Enqueue("Reader #2 lock released"); | |
823 } | |
824 }, | |
825 () => { | |
826 log.Enqueue("Writer #1 started"); | |
827 try { | |
828 l.LockExclusive(); | |
829 log.Enqueue("Writer #1 got the lock"); | |
830 Assert.AreEqual(1, Interlocked.Increment(ref exclusive)); | |
831 Interlocked.Decrement(ref exclusive); | |
832 log.Enqueue("Writer #1 is finished"); | |
833 } finally { | |
834 l.Release(); | |
835 log.Enqueue("Writer #1 lock released"); | |
836 } | |
837 } | |
838 ).Bundle().Join(1000); | |
839 log.Enqueue("Done"); | |
840 } catch(Exception error) { | |
841 log.Enqueue(error.Message); | |
842 throw; | |
843 } finally { | |
844 foreach (var m in log) | |
845 Console.WriteLine(m); | |
846 } | |
847 } | |
848 | |
849 #if NET_4_5 | |
850 | |
851 [TestMethod] | |
852 public async void TaskInteropTest() { | |
853 var promise = new Promise<int>(); | |
854 promise.Resolve(10); | |
855 var res = await promise; | |
856 | |
857 Assert.AreEqual(10, res); | |
858 } | |
859 | |
860 #endif | |
384 } | 861 } |
385 } | 862 } |
386 | 863 |