Emit better code for binary await expression with constants
[mono-project.git] / mcs / tests / test-async-13.cs
blob54aabc3f37b478ce6e1137a45cbb8080fc779ea7
1 using System;
2 using System.Threading.Tasks;
3 using System.Threading;
4 using System.Reflection;
5 using System.Linq;
6 using System.Runtime.CompilerServices;
8 struct S
10 public int Value;
12 public S (int a1, string a2)
14 Value = a1;
17 public void SetValue (int value)
19 Value = value;
22 public static implicit operator S (Base b)
24 return new S (400, "a");
27 public static S operator + (S a, S b)
29 return new S () {
30 Value = a.Value + b.Value
35 enum E
37 E_1 = 1
40 class Base
42 public volatile int field_int;
43 protected int field_this;
44 protected int property_this_counter;
46 public event Action Event;
48 public Base ()
52 public Base (int arg, int arg2)
54 field_int = arg;
57 public bool PropertyBool {
58 get {
59 return true;
63 public int PropertyInt {
64 get {
65 return field_int;
67 set {
68 field_int += value;
72 protected Base PropertyThis {
73 get {
74 ++property_this_counter;
75 return this;
79 public int this [int arg] {
80 get {
81 return field_this;
83 set {
84 field_this += value * arg;
88 public static bool operator true (Base a)
90 return true;
93 public static bool operator false (Base a)
95 return false;
98 public static Base operator & (Base a, Base b)
100 return new Base () {
101 field_int = 100
105 public static Base operator | (Base a, Base b)
107 return new Base () {
108 field_int = 200
112 protected int Call (int arg1, int arg2, int arg3)
114 if (arg1 != 5)
115 return 1;
117 if (arg2 != -3)
118 return 2;
120 if (arg3 != 6)
121 return 3;
123 return 0;
126 protected int Call(ref char ch, int arg)
128 ch = 'z';
129 return arg;
132 public void CallBool (bool b)
136 public int CallS (S s)
138 return s.Value;
141 public T[] CreateArray<T> (int size)
143 return new T [size];
146 protected static void CallRefParams (ref int i, params int[] i2)
148 i = 5;
151 protected int CallNamed (int a, int b)
153 return a - b;
156 protected void CallEvent ()
158 Event ();
162 class Tester : Base
164 async Task<bool> ArrayAccessTest_1 ()
166 bool[] b = new bool[1];
167 b [0] = await Task.Factory.StartNew (() => true);
168 return b[await Task.Factory.StartNew (() => 0)];
171 async Task<int> ArrayAccessTest_2 ()
173 double[] b = new double[2];
174 b [await Task.Factory.StartNew (() => 1)] = 5.5;
175 if (b [1] != 5.5)
176 return 1;
178 var d = b [await Task.Factory.StartNew (() => 1)] = 2.5;
179 if (b [1] != 2.5)
180 return 2;
182 if (d != 2.5)
183 return 3;
185 d = b [await Task.Factory.StartNew (() => 1)] = await Task.Factory.StartNew (() => 4.4);
186 if (d != 4.4)
187 return 4;
189 return 0;
192 async Task<int> ArrayAccessTest_3 ()
194 decimal[] d = new decimal [4];
195 d[1] = 4;
197 var r = ++d[await Task.Factory.StartNew (() => 1)];
198 if (r != 5)
199 return 1;
201 d [1] = 6;
202 d [await Task.Factory.StartNew (() => 1)] += await Task.Factory.StartNew (() => 9.9m);
203 if (d [1] != 15.9m)
204 return 2;
206 d [1] = 6;
207 r = d [await Task.Factory.StartNew (() => 1)] -= await Task.Factory.StartNew (() => 5.9m);
208 if (d [1] != 0.1m)
209 return 3;
211 return 0;
214 async Task<bool> ArrayAccessTest_4 ()
216 string[] s = new string [4];
217 s[1] = "a";
219 s [await Task.Factory.StartNew (() => 1)] += await Task.Factory.StartNew (() => "b");
220 return s [1] == "ab";
223 async Task<bool> ArrayAccessTest_5 ()
225 int[][] a = new int[3][];
226 a [1] = new int [5];
227 int index = 1;
228 CallRefParams (ref a[await Task.Factory.StartNew (() => index++)][0], await Task.Factory.StartNew (() => 3));
229 return a [1][0] == 5;
232 async Task<int> ArrayAccessTest_6 ()
234 int value = -6;
235 int[] a = new int[3] { 3, 6, 9 };
236 return a [await Task.Factory.StartNew (() => (long)1)] + value;
239 async Task<bool> ArrayAccessTest_7 ()
241 short?[] s = new short?[] { 3, 2, 1 };
242 var r = s [await Task.Factory.StartNew (() => 1)]++;
243 return r == 2;
246 async Task<int> ArrayAccessTest_8 ()
248 var s = new byte?[] { 3, 2, 1 };
249 var r = s [await Task.Factory.StartNew (() => 1)] += await Task.Factory.StartNew (() => (byte)30);
250 if (r != 32)
251 return 1;
253 if (s [1] != 32)
254 return 2;
256 return 0;
259 async Task<int> ArrayAccessTest_9 ()
261 var s = new Base ();
262 s.CreateArray<int> (await Task.Factory.StartNew (() => 5)) [2] += 9;
263 s.CreateArray<int> (await Task.Factory.StartNew (() => 5)) [2] += await Task.Factory.StartNew (() => 9);
265 var res = s.CreateArray<int> (await Task.Factory.StartNew (() => 5)) [2] += await Task.Factory.StartNew (() => 9);
266 if (res != 9)
267 return 1;
269 s.CreateArray<S> (await Task.Factory.StartNew (() => 5)) [2] += await Task.Factory.StartNew (() => new S () { Value = 4 });
270 return 0;
273 async Task<int> AssignTest_1 ()
275 field_int = await Task.Factory.StartNew (() => 0);
276 return field_int;
279 async Task<bool> AssignTest_2 ()
281 long? l = await Task.Factory.StartNew<sbyte?> (() => null);
282 return l == null;
285 async Task<int> AssignTest_3 ()
287 int a = await Task.Factory.StartNew (() => 1), b = await Task.Factory.StartNew (() => 2);
288 if (a != 1)
289 return 1;
290 if (b != 2)
291 return b;
293 return 0;
296 async Task<int> BinaryTest_1 ()
298 return await Task.Factory.StartNew (() => { Thread.Sleep (10); return 5; }) +
299 await Task.Factory.StartNew (() => -3) +
300 await Task.Factory.StartNew (() => -2);
303 async Task<int> BinaryTest_2 ()
305 int i = 1;
306 var b = await Task.Factory.StartNew (() => { i += 3; return true; }) &&
307 await Task.Factory.StartNew (() => { i += 4; return false; }) &&
308 await Task.Factory.StartNew (() => { i += 5; return true; });
310 return b ? -1 : i == 8 ? 0 : i;
313 async Task<int> BinaryTest_3 ()
315 var r = await Task.Factory.StartNew<bool?> (() => true) & await Task.Factory.StartNew<bool?> (() => null);
316 if (r != null)
317 return 1;
319 r = await Task.Factory.StartNew<bool?> (() => null) | await Task.Factory.StartNew<bool?> (() => true);
320 if (r != true)
321 return 2;
323 r = await Task.Factory.StartNew<bool?> (() => null) != await Task.Factory.StartNew<bool?> (() => true);
324 if (r != true)
325 return 3;
327 return 0;
330 async Task<int> BinaryTest_4 ()
332 var r1 = await Task.Factory.StartNew<short?> (() => 2) * await Task.Factory.StartNew<byte?> (() => null);
333 if (r1 != null)
334 return 1;
336 var r2 = await Task.Factory.StartNew<decimal?> (() => 100) / await Task.Factory.StartNew<decimal?> (() => null);
337 if (r2 != null)
338 return 2;
340 return 0;
343 async Task<int> BinaryTest_5 ()
345 var r1 = await Task.FromResult (1) == 9;
346 if (r1)
347 return 1;
349 var r2 = 1 == await Task.FromResult (1);
350 if (!r2)
351 return 2;
353 return 0;
356 async Task<int> CallTest_1 ()
358 return Call (
359 await Task.Factory.StartNew (() => { Thread.Sleep (10); return 5; }),
360 await Task.Factory.StartNew (() => -3),
361 await Task.Factory.StartNew (() => 6));
364 async Task<bool> CallTest_2 ()
366 char ch = 'a';
367 var r = Call (
368 ref ch,
369 await Task.Factory.StartNew (() => { Thread.Sleep (10); return 5; }));
371 return ch == 'z' && r == 5;
374 async Task<int> CallTest_3 ()
376 S s = new S ();
377 s.SetValue (await Task.Factory.StartNew (() => 10));
378 return s.Value - 10;
381 async Task<bool> CallTest_4 ()
383 return E.E_1.Equals (unchecked (await Task.Factory.StartNew (() => E.E_1)));
386 async Task<int> CallTest_5 ()
388 int value = 9;
389 return CallNamed (
390 b: await Task.Factory.StartNew (() => value++),
391 a: value) - 1;
394 async Task<bool> CastTest_1 ()
396 decimal value = 67;
397 return (value - await Task.Factory.StartNew (() => 66m)) == 1;
400 async Task<bool> CastTest_2 ()
402 var t = new Tester ();
403 return t.CallS (await Task.Factory.StartNew (() => this)) == 400;
406 async Task<bool> CoalescingTest_1 ()
408 var r = await Task.Factory.StartNew<string> (() => null) ?? await Task.Factory.StartNew (() => "x");
409 return r == "x";
412 async Task<bool> CoalescingTest_2 ()
414 var r = await Task.Factory.StartNew<short?> (() => null) ?? await Task.Factory.StartNew<byte> (() => 2);
415 return r == 2;
418 async Task<int> ConditionalTest_1 ()
420 return true ? await Task.Factory.StartNew (() => 0) : await Task.Factory.StartNew (() => 1);
423 async Task<int> ConditionalTest_2 ()
425 return PropertyBool ? await Task.Factory.StartNew (() => 0) : await Task.Factory.StartNew (() => 1);
428 async Task<int> ConditionalTest_3 ()
430 int v = 5;
431 return v * (await Task.Factory.StartNew (() => true) ? 0 : await Task.Factory.StartNew (() => 1));
434 async Task<int> ConditionalTest_4 ()
436 int v = 5;
437 return v * (v == 2 ? 3 : await Task.Factory.StartNew (() => 0));
440 async Task<int> DelegateInvoke_4 ()
442 Func<int, int> d = l => l - 3;
443 int value = 1;
444 return value + d (await Task.Factory.StartNew (() => 2));
447 async Task<int> EventInvoke_1 ()
449 int value = 0;
450 Event += await Task.Factory.StartNew (() => {
451 Action a = () => { value = 5; };
452 return a;
455 CallEvent ();
456 return value - 5;
459 async Task<int> FieldTest_1 ()
461 var s = new Base ();
462 s.field_int = 3;
463 s.field_int += await Task.Factory.StartNew (() => 6);
464 if (s.field_int != 9)
465 return 1;
467 var r = s.field_int -= await Task.Factory.StartNew (() => 5);
468 if (r != 4)
469 return 2;
471 if (s.field_int != 4)
472 return 3;
473 return 0;
476 async Task<bool> IndexerTest_1 ()
478 this[2] = await Task.Factory.StartNew (() => 6);
479 return this[2] == 12;
482 async Task<bool> IndexerTest_2 ()
484 this[await Task.Factory.StartNew (() => 3)] = await Task.Factory.StartNew (() => 6);
485 return this[3] == 18;
488 async Task<int> IndexerTest_3 ()
490 int value = -5;
491 this[await Task.Factory.StartNew (() => value++)] += await Task.Factory.StartNew (() => 5);
492 return this[3] + 25;
495 async Task<int> IndexerTest_4 ()
497 int value = 3;
498 PropertyThis[await Task.Factory.StartNew (() => value++)] += await Task.Factory.StartNew (() => -5);
499 return PropertyThis[3] + value + 11;
502 async Task<int> IndexerTest_5 ()
504 int value = 3;
505 field_this = 6;
506 int res = PropertyThis[await Task.Factory.StartNew (() => value++)]++;
507 if (res != 6)
508 return 1;
510 if (PropertyThis[0] != 27)
511 return 2;
513 return PropertyThis[5] -= await Task.Factory.StartNew (() => 27);
516 async Task<int> IndexerTest_6 ()
518 var r = this[3] = await Task.Factory.StartNew (() => 9);
519 if (r != 9)
520 return 1;
522 var r2 = this[await Task.Factory.StartNew (() => 55)] = await Task.Factory.StartNew (() => 8);
524 if (r2 != 8)
525 return 2;
527 return 0;
530 async Task<bool> IndexerTest_7 ()
532 int value = -5;
533 var res = ++this[await Task.Factory.StartNew (() => value++)];
534 return res == 1;
537 async Task<bool> IsTest_1 ()
539 new Tester ().CallBool (await Task.Factory.StartNew (() => new Tester ()) is Base);
540 return true;
543 async Task<bool> IsTest_2 ()
545 var r = await Task.Factory.StartNew<uint?> (() => 1) is uint;
546 return r;
549 async Task<bool> LogicalUserOperator_1 ()
551 var r = await Task.Factory.StartNew (() => new Base ()) && await Task.Factory.StartNew (() => new Base ());
552 return r.field_int == 100;
555 async Task<bool> LogicalUserOperator_2 ()
557 var r = new Base () && await Task.Factory.StartNew (() => new Base ());
558 return r.field_int == 100;
561 async Task<bool> LogicalUserOperator_3 ()
563 var r = await Task.Factory.StartNew (() => new Base ()) || await Task.Factory.StartNew (() => new Base ());
564 return r.field_int == 0;
567 async Task<bool> NewTest_1 ()
569 int value = 9;
570 var b = new Base (value, await Task.Factory.StartNew (() => 33));
571 return b.field_int == 9;
574 async Task<bool> NewTest_2 ()
576 var s = new S (await Task.Factory.StartNew (() => 77), await Task.Factory.StartNew (() => "b"));
577 return s.Value == 77;
580 async Task<int> NewInitTest_1 ()
582 int value = 9;
584 var b = new Base (value, await Task.Factory.StartNew (() => 33)) { };
585 if (b.field_int != 9)
586 return 1;
588 b = new Base (value, await Task.Factory.StartNew (() => 11)) {
589 field_int = await Task.Factory.StartNew (() => 12),
590 PropertyInt = await Task.Factory.StartNew (() => 13)
593 if (b.field_int != 25)
594 return 2;
596 b = new Base () {
597 field_int = await Task.Factory.StartNew (() => 12),
598 PropertyInt = await Task.Factory.StartNew (() => 13)
601 if (b.field_int != 25)
602 return 3;
604 return 0;
607 async Task<int> NewInitTest_2 ()
609 int value = 9;
611 var s = new S (value, await Task.Factory.StartNew (() => "x")) { };
612 if (s.Value != 9)
613 return 1;
615 s = new S (value, await Task.Factory.StartNew (() => "y")) {
616 Value = await Task.Factory.StartNew (() => 12)
619 if (s.Value != 12)
620 return 2;
622 s = new S () {
623 Value = await Task.Factory.StartNew (() => 13)
626 if (s.Value != 13)
627 return 3;
629 return 0;
632 async Task<bool> NewArrayInitTest_1 ()
634 var a = new int[await Task.Factory.StartNew (() => 5)];
635 return a.Length == 5;
638 async Task<bool> NewArrayInitTest_2 ()
640 var a = new short[await Task.Factory.StartNew (() => 3), await Task.Factory.StartNew (() => 4)];
641 return a.Length == 12;
644 async Task<int> NewArrayInitTest_3 ()
646 var a = new byte[] { await Task.Factory.StartNew (() => (byte)5) };
647 return a [0] - 5;
650 async Task<bool> NewArrayInitTest_4 ()
652 var a = new ushort[,] {
653 { await Task.Factory.StartNew (() => (ushort) 5), 50 },
654 { 30, await Task.Factory.StartNew (() => (ushort) 3) }
657 return a [0, 0] * a [1, 1] == 15;
660 async Task<int> NewArrayInitTest_5 ()
662 var a = new S[] { await Task.Factory.StartNew (() => new S () { Value = 4 }) };
663 return a [0].Value - 4;
666 async Task<bool> NewArrayInitTest_6 ()
668 var a = new int[] { 2, 3, 2, 3, 5, 6, 7, 2, 4, await Task.Factory.StartNew (() => 5), 11, 23, 45 };
669 return a.Length == 13;
672 async Task<bool> PropertyTest_1 ()
674 PropertyInt = await Task.Factory.StartNew (() => 6);
675 return PropertyInt == 6;
678 async Task<int> PropertyTest_2 ()
680 PropertyThis.PropertyInt += await Task.Factory.StartNew (() => 6);
681 if (property_this_counter != 1)
682 return 1;
684 return PropertyInt - 6;
687 async Task<int> PropertyTest_3 ()
689 var r = PropertyThis.PropertyInt = await Task.Factory.StartNew (() => 9);
690 if (r != 9)
691 return 1;
693 PropertyThis.PropertyInt = 4;
694 int[] a = new int[4];
695 a [await Task.Factory.StartNew (() => 1)] = PropertyThis.PropertyInt += await Task.Factory.StartNew (() => 8);
696 if (a[1] != 21)
697 return 2;
699 if (PropertyThis.PropertyInt != 34)
700 return 3;
702 return 0;
705 async Task<bool> StringConcatTest_1 ()
707 return (await Task.Factory.StartNew (() => "a") +
708 await Task.Factory.StartNew (() => "b") +
709 await Task.Factory.StartNew (() => (string) null) == "ab");
712 async Task<bool> UnaryTest_1 ()
714 long a = 1;
715 return (a + checked (-await Task.Factory.StartNew (() => 2))) == -1;
718 async Task<bool> UnaryTest_2 ()
720 short? s = 2;
721 int value = 2;
722 return (value * ~await Task.Factory.StartNew (() => s)) == -6;
725 async Task<bool> UnaryTest_3 ()
727 var d = new decimal? [2];
728 d[1] = 4;
729 var r = ++d[await Task.Factory.StartNew (() => 1)];
730 return r == 5;
733 async Task<bool> VariableInitializer_1 ()
735 int a = 2, b = await Task.Factory.StartNew (() => 1), c = await Task.Factory.StartNew (() => 1);
736 return a == (b + c);
739 static bool RunTest (MethodInfo test)
741 Console.Write ("Running test {0, -25}", test.Name);
742 try {
743 Task t = test.Invoke (new Tester (), null) as Task;
744 if (!Task.WaitAll (new[] { t }, 1000)) {
745 Console.WriteLine ("FAILED (Timeout)");
746 return false;
749 var ti = t as Task<int>;
750 if (ti != null) {
751 if (ti.Result != 0) {
752 Console.WriteLine ("FAILED (Result={0})", ti.Result);
753 return false;
755 } else {
756 var tb = t as Task<bool>;
757 if (tb != null) {
758 if (!tb.Result) {
759 Console.WriteLine ("FAILED (Result={0})", tb.Result);
760 return false;
765 Console.WriteLine ("OK");
766 return true;
767 } catch (Exception e) {
768 Console.WriteLine ("FAILED");
769 Console.WriteLine (e.ToString ());
770 return false;
774 public static int Main ()
776 var tests = from test in typeof (Tester).GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)
777 where test.GetParameters ().Length == 0 && !test.IsDefined (typeof (CompilerGeneratedAttribute), false)
778 orderby test.Name
779 select RunTest (test);
781 int failures = tests.Count (a => !a);
782 Console.WriteLine (failures + " tests failed");
783 return failures;