/Src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs
C# | 7065 lines | 6589 code | 370 blank | 106 comment | 117 complexity | 65b60a20701d305e57ea57ce19e17487 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- // Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using Microsoft.CodeAnalysis.CSharp.Symbols;
- using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
- using Microsoft.CodeAnalysis.Test.Utilities;
- using Roslyn.Test.Utilities;
- using Roslyn.Utilities;
- using Xunit;
- namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
- {
- public class CodeGenAsyncTests : EmitMetadataTestBase
- {
- private CSharpCompilation CreateCompilation(string source, IEnumerable<MetadataReference> references = null, CSharpCompilationOptions compOptions = null)
- {
- SynchronizationContext.SetSynchronizationContext(null);
- compOptions = compOptions ?? TestOptions.OptimizedExe;
- IEnumerable<MetadataReference> asyncRefs = new[] { SystemRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929, CSharpRef };
- references = (references != null) ? references.Concat(asyncRefs) : asyncRefs;
- return CreateCompilationWithMscorlib45(source, compOptions: compOptions, references: references);
- }
- private CompilationVerifier CompileAndVerify(string source, string expectedOutput, IEnumerable<MetadataReference> references = null, EmitOptions emitOptions = EmitOptions.All, CSharpCompilationOptions compOptions = null, bool emitPdb = false)
- {
- SynchronizationContext.SetSynchronizationContext(null);
- var compilation = this.CreateCompilation(source, references: references, compOptions: compOptions);
- return base.CompileAndVerify(compilation, expectedOutput: expectedOutput, emitOptions: emitOptions, emitPdb: emitPdb);
- }
- [Fact]
- public void StructVsClass()
- {
- var source = @"
- using System.Threading;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task F(int a)
- {
- await Task.Factory.StartNew(() => { System.Console.WriteLine(a); });
- }
- public static void Main()
- {
- F(123).Wait();
- }
- }";
- var c = CreateCompilationWithMscorlib45(source);
- CompilationOptions options;
- options = TestOptions.OptimizedExe;
- Assert.False(options.EnableEditAndContinue);
- CompileAndVerify(c.WithOptions(options), symbolValidator: module =>
- {
- var stateMachine = module.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<NamedTypeSymbol>("<F>d__1");
- Assert.Equal(TypeKind.Struct, stateMachine.TypeKind);
- }, expectedOutput: "123");
- options = TestOptions.UnoptimizedExe;
- Assert.False(options.EnableEditAndContinue);
- CompileAndVerify(c.WithOptions(options), symbolValidator: module =>
- {
- var stateMachine = module.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<NamedTypeSymbol>("<F>d__1");
- Assert.Equal(TypeKind.Struct, stateMachine.TypeKind);
- }, expectedOutput: "123");
- options = TestOptions.OptimizedExe.WithDebugInformationKind(DebugInformationKind.Full);
- Assert.False(options.EnableEditAndContinue);
- CompileAndVerify(c.WithOptions(options), symbolValidator: module =>
- {
- var stateMachine = module.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<NamedTypeSymbol>("<F>d__1");
- Assert.Equal(TypeKind.Struct, stateMachine.TypeKind);
- }, expectedOutput: "123");
- options = TestOptions.UnoptimizedExe.WithDebugInformationKind(DebugInformationKind.PdbOnly);
- Assert.False(options.EnableEditAndContinue);
- CompileAndVerify(c.WithOptions(options), symbolValidator: module =>
- {
- var stateMachine = module.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<NamedTypeSymbol>("<F>d__1");
- Assert.Equal(TypeKind.Struct, stateMachine.TypeKind);
- }, expectedOutput: "123");
- options = TestOptions.UnoptimizedExe.WithDebugInformationKind(DebugInformationKind.Full);
- Assert.True(options.EnableEditAndContinue);
- CompileAndVerify(c.WithOptions(options), symbolValidator: module =>
- {
- var stateMachine = module.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<NamedTypeSymbol>("<F>d__1");
- Assert.Equal(TypeKind.Class, stateMachine.TypeKind);
- }, expectedOutput: "123");
- }
- [Fact]
- public void VoidReturningAsync()
- {
- var source = @"
- using System;
- using System.Diagnostics;
- using System.Threading;
- using System.Threading.Tasks;
- class Test
- {
- static int i = 0;
- public static async void F(AutoResetEvent handle)
- {
- try
- {
- await Task.Factory.StartNew(() =>
- {
- Interlocked.Increment(ref Test.i);
- });
- }
- finally
- {
- handle.Set();
- }
- }
- public static void Main()
- {
- var handle = new AutoResetEvent(false);
- F(handle);
- handle.WaitOne(1000 * 60);
- Console.WriteLine(i);
- }
- }";
- var expected = @"
- 1
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- [WorkItem(624970, "DevDiv")]
- public void AsyncWithEH()
- {
- var source = @"
- using System;
- using System.Diagnostics;
- using System.Threading;
- using System.Threading.Tasks;
- class Test
- {
- static int awaitCount = 0;
- static int finallyCount = 0;
- static void LogAwait()
- {
- Interlocked.Increment(ref awaitCount);
- }
- static void LogException()
- {
- Interlocked.Increment(ref finallyCount);
- }
- public static async void F(AutoResetEvent handle)
- {
- try
- {
- await Task.Factory.StartNew(LogAwait);
- try
- {
- await Task.Factory.StartNew(LogAwait);
- try
- {
- await Task.Factory.StartNew(LogAwait);
- try
- {
- await Task.Factory.StartNew(LogAwait);
- throw new Exception();
- }
- catch (Exception)
- {
- }
- finally
- {
- LogException();
- }
- await Task.Factory.StartNew(LogAwait);
- throw new Exception();
- }
- catch (Exception)
- {
- }
- finally
- {
- LogException();
- }
- await Task.Factory.StartNew(LogAwait);
- throw new Exception();
- }
- catch (Exception)
- {
- }
- finally
- {
- LogException();
- }
- await Task.Factory.StartNew(LogAwait);
- }
- finally
- {
- handle.Set();
- }
- }
- public static void Main2(int i)
- {
- try
- {
- awaitCount = 0;
- finallyCount = 0;
- var handle = new AutoResetEvent(false);
- F(handle);
- var completed = handle.WaitOne(1000 * 60);
- if (completed)
- {
- if (awaitCount != 7 || finallyCount != 3)
- {
- throw new Exception(""failed at i="" + i);
- }
- }
- else
- {
- Console.WriteLine(""Test did not complete in time."");
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(""unexpected exception thrown:"");
- Console.WriteLine(ex.ToString());
- }
- }
- public static void Main()
- {
- for (int i = 0; i < 1500; i++)
- {
- Main2(i);
- }
- }
- }";
- var expected = @"";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact, WorkItem(855080, "DevDiv")]
- public void GenericCatchVariableInAsyncMethod()
- {
- var source = @"
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace ConsoleApplication1
- {
- class Program
- {
- static void Main(string[] args)
- {
- Console.WriteLine(Bar().Result);
- }
- static async Task<int> Bar()
- {
- NotImplementedException ex = await Foo<NotImplementedException>();
- return 3;
- }
- public static async Task<T> Foo<T>() where T : Exception
- {
- Task<int> task = null;
- if (task != null) await task;
- T result = null;
- try
- {
- }
- catch (T ex)
- {
- result = ex;
- }
- return result;
- }
- }
- }
- ";
- CompileAndVerify(source, expectedOutput: "3");
- }
- [Fact]
- public void TaskReturningAsync()
- {
- var source = @"
- using System;
- using System.Diagnostics;
- using System.Threading.Tasks;
- class Test
- {
- static int i = 0;
- public static async Task F()
- {
- await Task.Factory.StartNew(() =>
- {
- Test.i = 42;
- });
- }
- public static void Main()
- {
- Task t = F();
- t.Wait(1000 * 60);
- Console.WriteLine(Test.i);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void GenericTaskReturningAsync()
- {
- var source = @"
- using System;
- using System.Diagnostics;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<string> F()
- {
- return await Task.Factory.StartNew(() => { return ""O brave new world...""; });
- }
- public static void Main()
- {
- Task<string> t = F();
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- O brave new world...
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithLocals()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> F(int x)
- {
- return await Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(int x)
- {
- int c = 0;
- await F(x);
- c += x;
- await F(x);
- c += x;
- return c;
- }
- public static void Main()
- {
- Task<int> t = G(21);
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithTernary()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static Task<T> F<T>(T x)
- {
- Console.WriteLine(""F("" + x + "")"");
- return Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(bool b1, bool b2)
- {
- int c = 0;
- c = c + (b1 ? 1 : await F(2));
- c = c + (b2 ? await F(4) : 8);
- return await F(c);
- }
- public static int H(bool b1, bool b2)
- {
- Task<int> t = G(b1, b2);
- t.Wait(1000 * 60);
- return t.Result;
- }
- public static void Main()
- {
- Console.WriteLine(H(false, false));
- Console.WriteLine(H(false, true));
- Console.WriteLine(H(true, false));
- Console.WriteLine(H(true, true));
- }
- }";
- var expected = @"
- F(2)
- F(10)
- 10
- F(2)
- F(4)
- F(6)
- 6
- F(9)
- 9
- F(4)
- F(5)
- 5
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithAnd()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static Task<T> F<T>(T x)
- {
- Console.WriteLine(""F("" + x + "")"");
- return Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(bool b1, bool b2)
- {
- bool x1 = b1 && await F(true);
- bool x2 = b1 && await F(false);
- bool x3 = b2 && await F(true);
- bool x4 = b2 && await F(false);
- int c = 0;
- if (x1) c += 1;
- if (x2) c += 2;
- if (x3) c += 4;
- if (x4) c += 8;
- return await F(c);
- }
- public static int H(bool b1, bool b2)
- {
- Task<int> t = G(b1, b2);
- t.Wait(1000 * 60);
- return t.Result;
- }
- public static void Main()
- {
- Console.WriteLine(H(false, true));
- }
- }";
- var expected = @"
- F(True)
- F(False)
- F(4)
- 4
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithOr()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static Task<T> F<T>(T x)
- {
- Console.WriteLine(""F("" + x + "")"");
- return Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(bool b1, bool b2)
- {
- bool x1 = b1 || await F(true);
- bool x2 = b1 || await F(false);
- bool x3 = b2 || await F(true);
- bool x4 = b2 || await F(false);
- int c = 0;
- if (x1) c += 1;
- if (x2) c += 2;
- if (x3) c += 4;
- if (x4) c += 8;
- return await F(c);
- }
- public static int H(bool b1, bool b2)
- {
- Task<int> t = G(b1, b2);
- t.Wait(1000 * 60);
- return t.Result;
- }
- public static void Main()
- {
- Console.WriteLine(H(false, true));
- }
- }";
- var expected = @"
- F(True)
- F(False)
- F(13)
- 13
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithCoalesce()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static Task<string> F(string x)
- {
- Console.WriteLine(""F("" + (x ?? ""null"") + "")"");
- return Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<string> G(string s1, string s2)
- {
- var result = await F(s1) ?? await F(s2);
- Console.WriteLine("" "" + (result ?? ""null""));
- return result;
- }
- public static string H(string s1, string s2)
- {
- Task<string> t = G(s1, s2);
- t.Wait(1000 * 60);
- return t.Result;
- }
- public static void Main()
- {
- H(null, null);
- H(null, ""a"");
- H(""b"", null);
- H(""c"", ""d"");
- }
- }";
- var expected = @"
- F(null)
- F(null)
- null
- F(null)
- F(a)
- a
- F(b)
- b
- F(c)
- c
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithParam()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> G(int x)
- {
- await Task.Factory.StartNew(() => { return x; });
- x += 21;
- await Task.Factory.StartNew(() => { return x; });
- x += 21;
- return x;
- }
- public static void Main()
- {
- Task<int> t = G(0);
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AwaitInExpr()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> F()
- {
- return await Task.Factory.StartNew(() => 21);
- }
- public static async Task<int> G()
- {
- int c = 0;
- c = (await F()) + 21;
- return c;
- }
- public static void Main()
- {
- Task<int> t = G();
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithParamsAndLocals_UnHoisted()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> F(int x)
- {
- return await Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(int x)
- {
- int c = 0;
- c = await F(x);
- return c;
- }
- public static void Main()
- {
- Task<int> t = G(21);
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 21
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithParamsAndLocals_Hoisted()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> F(int x)
- {
- return await Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(int x)
- {
- int c = 0;
- c = await F(x);
- return c;
- }
- public static void Main()
- {
- Task<int> t = G(21);
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 21
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithParamsAndLocals_DoubleAwait_Spilling()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> F(int x)
- {
- return await Task.Factory.StartNew(() => { return x; });
- }
- public static async Task<int> G(int x)
- {
- int c = 0;
- c = (await F(x)) + c;
- c = (await F(x)) + c;
- return c;
- }
- public static void Main()
- {
- Task<int> t = G(21);
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- // When the local 'c' gets hoisted, the statement:
- // c = (await F(x)) + c;
- // Gets rewritten to:
- // this.c_field = (await F(x)) + this.c_field;
- //
- // The code-gen for the assignment is something like this:
- // ldarg0 // load the 'this' reference to the stack
- // <emitted await expression>
- // stfld
- //
- // What we really want is to evaluate any parts of the lvalue that have side-effects (which is this case is
- // nothing), and then defer loading the address for the field reference until after the await expression:
- // <emitted await expression>
- // <store to tmp>
- // ldarg0
- // <load tmp>
- // stfld
- //
- // So this case actually requires stack spilling, which is not yet implemented. This has the unfortunate
- // consequence of preventing await expressions from being assigned to hoisted locals.
- //
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithDynamic()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- public static async Task<int> F(dynamic t)
- {
- return await t;
- }
- public static void Main()
- {
- Task<int> t = F(Task.Factory.StartNew(() => { return 42; }));
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected, references: new[] { CSharpRef });
- }
- [Fact]
- public void AsyncWithThisRef()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class C
- {
- int x = 42;
- public async Task<int> F()
- {
- int c = this.x;
- return await Task.Factory.StartNew(() => c);
- }
- }
- class Test
- {
- public static void Main()
- {
- Task<int> t = new C().F();
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithBaseRef()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class B
- {
- protected int x = 42;
- }
- class C : B
- {
- public async Task<int> F()
- {
- int c = base.x;
- return await Task.Factory.StartNew(() => c);
- }
- }
- class Test
- {
- public static void Main()
- {
- Task<int> t = new C().F();
- t.Wait(1000 * 60);
- Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithException1()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- throw new Exception();
- }
- static async Task<int> G()
- {
- try
- {
- return await F();
- }
- catch(Exception)
- {
- return -1;
- }
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- -1
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncWithException2()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- throw new Exception();
- }
- static async Task<int> H()
- {
- return await F();
- }
- public static void Main()
- {
- Task<int> t1 = H();
- try
- {
- t1.Wait(1000 * 60);
- }
- catch (AggregateException)
- {
- Console.WriteLine(""exception"");
- }
- }
- }";
- var expected = @"
- exception
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInFinally001()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- return 2;
- }
- static async Task<int> G()
- {
- int x = 42;
- try
- {
- }
- finally
- {
- x = await F();
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected).
- VerifyIL("Test.<G>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
- {
- // Code size 229 (0xe5)
- .maxstack 3
- .locals init (int V_0,
- int V_1,
- object V_2,
- System.Runtime.CompilerServices.TaskAwaiter<int> V_3,
- object V_4,
- System.Exception V_5)
- IL_0000: ldarg.0
- IL_0001: ldfld ""int Test.<G>d__1.<>1__state""
- IL_0006: stloc.0
- .try
- {
- IL_0007: ldloc.0
- IL_0008: brfalse.s IL_000e
- IL_000a: ldloc.0
- IL_000b: ldc.i4.1
- IL_000c: beq.s IL_005f
- IL_000e: ldarg.0
- IL_000f: ldnull
- IL_0010: stfld ""object Test.<G>d__1.<>7__wrap1""
- IL_0015: ldarg.0
- IL_0016: ldc.i4.0
- IL_0017: stfld ""int Test.<G>d__1.<>7__wrap2""
- .try
- {
- IL_001c: leave.s IL_0028
- }
- catch object
- {
- IL_001e: stloc.2
- IL_001f: ldarg.0
- IL_0020: ldloc.2
- IL_0021: stfld ""object Test.<G>d__1.<>7__wrap1""
- IL_0026: leave.s IL_0028
- }
- IL_0028: call ""System.Threading.Tasks.Task<int> Test.F()""
- IL_002d: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
- IL_0032: stloc.3
- IL_0033: ldloca.s V_3
- IL_0035: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
- IL_003a: brtrue.s IL_007b
- IL_003c: ldarg.0
- IL_003d: ldc.i4.1
- IL_003e: dup
- IL_003f: stloc.0
- IL_0040: stfld ""int Test.<G>d__1.<>1__state""
- IL_0045: ldarg.0
- IL_0046: ldloc.3
- IL_0047: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__$awaiter0""
- IL_004c: ldarg.0
- IL_004d: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
- IL_0052: ldloca.s V_3
- IL_0054: ldarg.0
- IL_0055: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<G>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<G>d__1)""
- IL_005a: leave IL_00e4
- IL_005f: ldarg.0
- IL_0060: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__$awaiter0""
- IL_0065: stloc.3
- IL_0066: ldarg.0
- IL_0067: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__$awaiter0""
- IL_006c: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
- IL_0072: ldarg.0
- IL_0073: ldc.i4.m1
- IL_0074: dup
- IL_0075: stloc.0
- IL_0076: stfld ""int Test.<G>d__1.<>1__state""
- IL_007b: ldloca.s V_3
- IL_007d: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
- IL_0082: ldloca.s V_3
- IL_0084: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
- IL_008a: ldarg.0
- IL_008b: ldfld ""object Test.<G>d__1.<>7__wrap1""
- IL_0090: stloc.s V_4
- IL_0092: ldloc.s V_4
- IL_0094: brfalse.s IL_00ad
- IL_0096: ldloc.s V_4
- IL_0098: isinst ""System.Exception""
- IL_009d: dup
- IL_009e: brtrue.s IL_00a3
- IL_00a0: ldloc.s V_4
- IL_00a2: throw
- IL_00a3: call ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
- IL_00a8: callvirt ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
- IL_00ad: ldarg.0
- IL_00ae: ldnull
- IL_00af: stfld ""object Test.<G>d__1.<>7__wrap1""
- IL_00b4: stloc.1
- IL_00b5: leave.s IL_00d0
- }
- catch System.Exception
- {
- IL_00b7: stloc.s V_5
- IL_00b9: ldarg.0
- IL_00ba: ldc.i4.s -2
- IL_00bc: stfld ""int Test.<G>d__1.<>1__state""
- IL_00c1: ldarg.0
- IL_00c2: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
- IL_00c7: ldloc.s V_5
- IL_00c9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
- IL_00ce: leave.s IL_00e4
- }
- IL_00d0: ldarg.0
- IL_00d1: ldc.i4.s -2
- IL_00d3: stfld ""int Test.<G>d__1.<>1__state""
- IL_00d8: ldarg.0
- IL_00d9: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
- IL_00de: ldloc.1
- IL_00df: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
- IL_00e4: ret
- }
- ");
- }
- [Fact]
- public void AsyncInFinally002()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- System.Console.Write(""F"");
- return 2;
- }
- static async Task G()
- {
- int x = 0;
- try
- {
- throw new Exception(""hello"");
- }
- finally
- {
- x += await F();
- }
- }
- public static void Main()
- {
- Task t2 = G();
- try
- {
- t2.Wait(1000 * 60);
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- }";
- var expected = @"FOne or more errors occurred.
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInFinally003()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- return 2;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- x = await F();
- return x;
- }
- finally
- {
- x += await F();
- }
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInFinally004()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- return 2;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- throw new Exception();
- }
- finally
- {
- x += await F();
- }
- }
- catch
- {
- return x;
- }
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInFinallyNested001()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F(int a)
- {
- await Task.Yield();
- return a;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- x = await F(1);
- goto L1;
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- x += await F(2);
- }
- }
- finally
- {
- try
- {
- x += await F(4);
- }
- finally
- {
- x += await F(8);
- }
- }
- System.Console.WriteLine(""FAIL"");
- L1:
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"15";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInFinallyNested002()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F(int a)
- {
- await Task.Yield();
- return a;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- try
- {
- x = await F(1);
- throw new Exception(""hello"");
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- x += await F(2);
- }
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- try
- {
- x += await F(4);
- }
- finally
- {
- x += await F(8);
- }
- }
- System.Console.WriteLine(""FAIL"");
- }
- catch(Exception ex)
- {
- System.Console.WriteLine(ex.Message);
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"hello
- 15";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInFinallyNested003()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F(int a)
- {
- await Task.Yield();
- return a;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- try
- {
- x = await F(1);
- throw new Exception(""hello"");
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- x += await F(2);
- }
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- try
- {
- x += await F(4);
- }
- finally
- {
- x += await F(8);
- throw new Exception(""bye"");
- }
- }
- System.Console.WriteLine(""FAIL"");
- }
- catch(Exception ex)
- {
- System.Console.WriteLine(ex.Message);
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"bye
- 15";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInCatch001()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- return 2;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- x = x / x;
- }
- catch
- {
- x = await F();
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected).
- VerifyIL("Test.<G>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
- {
- // Code size 182 (0xb6)
- .maxstack 3
- .locals init (int V_0,
- int V_1,
- int V_2, //x
- int V_3,
- System.Runtime.CompilerServices.TaskAwaiter<int> V_4,
- System.Exception V_5)
- IL_0000: ldarg.0
- IL_0001: ldfld ""int Test.<G>d__1.<>1__state""
- IL_0006: stloc.0
- .try
- {
- IL_0007: ldloc.0
- IL_0008: brfalse.s IL_000e
- IL_000a: ldloc.0
- IL_000b: ldc.i4.1
- IL_000c: beq.s IL_0057
- IL_000e: ldc.i4.0
- IL_000f: stloc.2
- IL_0010: ldc.i4.0
- IL_0011: stloc.3
- .try
- {
- IL_0012: ldloc.2
- IL_0013: dup
- IL_0014: div
- IL_0015: stloc.2
- IL_0016: leave.s IL_001d
- }
- catch object
- {
- IL_0018: pop
- IL_0019: ldc.i4.1
- IL_001a: stloc.3
- IL_001b: leave.s IL_001d
- }
- IL_001d: ldloc.3
- IL_001e: ldc.i4.1
- IL_001f: bne.un.s IL_0084
- IL_0021: call ""System.Threading.Tasks.Task<int> Test.F()""
- IL_0026: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
- IL_002b: stloc.s V_4
- IL_002d: ldloca.s V_4
- IL_002f: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
- IL_0034: brtrue.s IL_0074
- IL_0036: ldarg.0
- IL_0037: ldc.i4.1
- IL_0038: dup
- IL_0039: stloc.0
- IL_003a: stfld ""int Test.<G>d__1.<>1__state""
- IL_003f: ldarg.0
- IL_0040: ldloc.s V_4
- IL_0042: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__$awaiter0""
- IL_0047: ldarg.0
- IL_0048: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
- IL_004d: ldloca.s V_4
- IL_004f: ldarg.0
- IL_0050: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<G>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<G>d__1)""
- IL_0055: leave.s IL_00b5
- IL_0057: ldarg.0
- IL_0058: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__$awaiter0""
- IL_005d: stloc.s V_4
- IL_005f: ldarg.0
- IL_0060: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<G>d__1.<>u__$awaiter0""
- IL_0065: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
- IL_006b: ldarg.0
- IL_006c: ldc.i4.m1
- IL_006d: dup
- IL_006e: stloc.0
- IL_006f: stfld ""int Test.<G>d__1.<>1__state""
- IL_0074: ldloca.s V_4
- IL_0076: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
- IL_007b: ldloca.s V_4
- IL_007d: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
- IL_0083: stloc.2
- IL_0084: ldloc.2
- IL_0085: stloc.1
- IL_0086: leave.s IL_00a1
- }
- catch System.Exception
- {
- IL_0088: stloc.s V_5
- IL_008a: ldarg.0
- IL_008b: ldc.i4.s -2
- IL_008d: stfld ""int Test.<G>d__1.<>1__state""
- IL_0092: ldarg.0
- IL_0093: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
- IL_0098: ldloc.s V_5
- IL_009a: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
- IL_009f: leave.s IL_00b5
- }
- IL_00a1: ldarg.0
- IL_00a2: ldc.i4.s -2
- IL_00a4: stfld ""int Test.<G>d__1.<>1__state""
- IL_00a9: ldarg.0
- IL_00aa: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<G>d__1.<>t__builder""
- IL_00af: ldloc.1
- IL_00b0: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
- IL_00b5: ret
- }
- ");
- }
- [Fact]
- public void AsyncInCatchRethrow()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- await Task.Yield();
- return 2;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- x = x / x;
- }
- catch
- {
- x = await F();
- throw;
- }
- }
- catch(DivideByZeroException ex)
- {
- x = await F();
- System.Console.WriteLine(ex.Message);
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- Attempted to divide by zero.
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInCatchFilter()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- await Task.Yield();
- return 2;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- x = x / x;
- }
- catch if(x != 0)
- {
- x = await F();
- throw;
- }
- }
- catch(Exception ex) if(x == 0 && ((ex = new Exception(""hello"")) != null))
- {
- x = await F();
- System.Console.WriteLine(ex.Message);
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- hello
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInCatchFilterLifted()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F()
- {
- await Task.Yield();
- return 2;
- }
- static bool T(Func<bool> f, ref Exception ex)
- {
- var result = f();
- ex = new Exception(result.ToString());
- return result;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- x = x / x;
- }
- catch(Exception ex) if(T(()=>ex.Message == null, ref ex))
- {
- x = await F();
- System.Console.WriteLine(ex.Message);
- }
- catch(Exception ex) if(T(()=>ex.Message != null, ref ex))
- {
- x = await F();
- System.Console.WriteLine(ex.Message);
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"True
- 2
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInCatchFinallyMixed()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F(int x)
- {
- await Task.Yield();
- return x;
- }
- static async Task<int> G()
- {
- int x = 0;
- try
- {
- try
- {
- for (int i = 0; i < 5; i++)
- {
- try
- {
- try
- {
- x = x / await F(0);
- }
- catch (DivideByZeroException) if (i < 3)
- {
- await Task.Yield();
- continue;
- }
- catch (DivideByZeroException)
- {
- x = 2 + await F(x);
- throw;
- }
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- x = await F(x) + 3;
- if (i >= 3)
- {
- throw new Exception(""hello"");
- }
- }
- }
- }
- finally
- {
- x = 11 + await F(x);
- }
- }
- catch (Exception ex)
- {
- x = await F(x) + 17;
- System.Console.WriteLine(ex.Message);
- }
- return x;
- }
- public static void Main()
- {
- Task<int> t2 = G();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- hello
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInCatchFinallyMixed_InAsyncLambda()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- class Test
- {
- static async Task<int> F(int x)
- {
- await Task.Yield();
- return x;
- }
- static Func<Task<int>> G()
- {
- int x = 0;
- return async () =>
- {
- try
- {
- try
- {
- for (int i = 0; i < 5; i++)
- {
- try
- {
- try
- {
- x = x / await F(0);
- }
- catch (DivideByZeroException) if (i < 3)
- {
- await Task.Yield();
- continue;
- }
- catch (DivideByZeroException)
- {
- x = 2 + await F(x);
- throw;
- }
- System.Console.WriteLine(""FAIL"");
- }
- finally
- {
- x = await F(x) + 3;
- if (i >= 3)
- {
- throw new Exception(""hello"");
- }
- }
- }
- }
- finally
- {
- x = 11 + await F(x);
- }
- }
- catch (Exception ex)
- {
- x = await F(x) + 17;
- System.Console.WriteLine(ex.Message);
- }
- return x;
- };
- }
- public static void Main()
- {
- Task<int> t2 = G()();
- t2.Wait(1000 * 60);
- Console.WriteLine(t2.Result);
- }
- }";
- var expected = @"
- hello
- 42
- ";
- CompileAndVerify(source, expectedOutput: expected);
- }
- [Fact]
- public void AsyncInConditionalAccess()
- {
- var source = @"
- using System;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- class Test
- {
- class C1
- {
- public int M(int x)
- {
- return x;
- }
- }
- public static int Get(int x)
- {
- Console.WriteLine(""> "" + x);
- return x;
- }
- public static async Task<int> F(int x)
- {
- return await Task.Factory.StartNew(() => x);
- }
- public static async Task<int?> G()
- {
- var c = new C1();
- return c?.M(await F(Get(42)));
- }
- public static void Main()
- {
- var t = G();
- System.Console.WriteLine(t.Result);
- }
- }";
- var expected = @"
- > 42
- 42";
- CompileAndVerifyExperimental(source, expected);
- }
- [Fact]
- public void Conformance_Awaiting_Methods_Generic01()
- {
- var source = @"
- using System;
- using System.Runtime.CompilerServices;
- using System.Threading;
- //Implementation of you own async pattern
- public class MyTask<T>
- {
- public MyTaskAwaiter<T> GetAwaiter()
- {
- return new MyTaskAwaiter<T>();
- }
- public async void Run<U>(U u) where U : MyTask<int>, new()
- {
- try
- {
- int tests = 0;
- tests++;
- var rez = await u;
- if (rez == 0)
- Driver.Count++;
- Driver.Result = Driver.Count - tests;
- }
- finally
- {
- //When test complete, set the flag.
- Driver.CompletedSignal.Set();
- }
- }
- }
- public class MyTaskAwaiter<T> : INotifyCompletion
- {
- public void OnCompleted(Action continuationAction)
- {
- }
- public T GetResult()
- {
- return default(T);
- }
- public bool IsCompleted { get { return true; } }
- }
- //-------------------------------------
- class Driver
- {
- public static int Result = -1;
- public static int Count = 0;
- public static AutoResetEvent CompletedSignal = new AutoResetEvent(false);
- static void Main()
- {
- new MyTask<int>().Run<MyTask<int>>(new MyTask<int>());
- CompletedSignal.WaitOne();
- // 0 - success
- // 1 - failed (test completed)
- // -1 - failed (test incomplete - deadlock, etc)
- Console.WriteLine(Driver.Result);
- }
- }";
- CompileAndVerify(source, "0");
- }
- [Fact]
- public void Conformance_Awaiting_Methods_Method01()
- {
- var source = @"
- using System.Threading;
- using System.Threading.Tasks;
- using System;
- public interface IExplicit
- {
- Task Method(int x = 4);
- }
- class C1 : IExplicit
- {
- Task IExplicit.Method(int x)
- {
- //This will fail until Run and RunEx are merged back together
- return Task.Run(async () =>
- {
- await Task.Delay(1);
- Driver.Count++;
- });
- }
- }
- class TestCase
- {
- public async void Run()
- {
- try
- {
- int tests = 0;
- tests++;
- C1 c = new C1();
- IExplicit e = (IExplicit)c;
- await e.Method();
- Driver.Result = Driver.Count - tests;
- }
- finally
- {
- //When test complete, set the flag.
- Driver.CompletedSignal.Set();
- }
- }
- }
- class Driver
- {
- public static int Result = -1;
- public static int Count = 0;
- public static AutoResetEvent CompletedSignal = new AutoResetEvent(false);
- static void Main()
- {
- var t = new TestCase();
- t.Run();
- CompletedSignal.WaitOne();
- // 0 - success
- // 1 - failed (test completed)
- // -1 - failed (test incomplete - deadlock, etc)
- Console.WriteLine(Driver.Result);
- }
- }";
- CompileAndVerify(source, "0");
- }
- [Fact]
- public void DoFinallyBodies()
- {
- var source = @"
- using System.Threading.Tasks;
- using System;
- class Driver
- {
- public static int finally_count = 0;
- static async Task F()
- {
- try
- {
- await Task.Factory.StartNew(() => { });
- }
- finally
- {
- Driver.finally_count++;
- }
- }
-
- static void Main()
- {
- var t = F();
- t.Wait();
- Console.WriteLine(Driver.finally_count);
- }
- }";
- var expected = @"
- 1
- ";
- CompileAndVerify(source, expected);
- }
- [Fact]
- public void Conformance_Awaiting_Methods_Parameter003()
- {
- var source = @"
- using System;
- using System.Threading.Tasks;
- using System.Collections.Generic;
- using System.Threading;
- class TestCase
- {
- public static int Count = 0;
- public static T Foo<T>(T t)
- {
- return t;
- }
- public async static Task<T> Bar<T>(T t)
- {
- await Task.Delay(1);
- return t;
- }
- public static async void Run()
- {
- try
- …
Large files files are truncated, but you can click here to view the full file