[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Internal / AsyncInvocationRegion.cs
1 // ***********************************************************************
2 // Copyright (c) 2013 Charlie Poole
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
23 #define PORTABLE
24 #define TIZEN
25 #define NUNIT_FRAMEWORK
26 #define NUNITLITE
27 #define NET_4_5
28 #define PARALLEL
29 #if NET_4_0 || NET_4_5 || PORTABLE
30 using System;
31 using System.Collections.Generic;
32 using System.Linq;
33 using System.Reflection;
34 using System.Threading;
35 using NUnit.Compatibility;
36
37 #if NET_4_5 || PORTABLE
38 using System.Runtime.ExceptionServices;
39 #endif
40
41 namespace NUnit.Framework.Internal
42 {
43     internal abstract class AsyncInvocationRegion : IDisposable
44     {
45         private const string TaskTypeName = "System.Threading.Tasks.Task";
46         private const string AsyncAttributeTypeName = "System.Runtime.CompilerServices.AsyncStateMachineAttribute";
47
48         private AsyncInvocationRegion()
49         {
50         }
51
52         public static AsyncInvocationRegion Create(Delegate @delegate)
53         {
54 #if PORTABLE
55             return Create(@delegate.GetMethodInfo());
56 #else
57             return Create(@delegate.Method);
58 #endif
59         }
60
61         public static AsyncInvocationRegion Create(MethodInfo method)
62         {
63             if (!IsAsyncOperation(method))
64                 throw new ArgumentException(@"Either asynchronous support is not available or an attempt 
65 at wrapping a non-async method invocation in an async region was done");
66
67             if (method.ReturnType == typeof(void))
68                 throw new ArgumentException("'async void' methods are not supported, please use 'async Task' instead");
69
70             return new AsyncTaskInvocationRegion();
71         }
72
73         public static bool IsAsyncOperation(MethodInfo method)
74         {
75             var name = method.ReturnType.FullName;
76             if (name == null) return false;
77             return name.StartsWith(TaskTypeName) ||
78                    method.GetCustomAttributes(false).Any(attr => AsyncAttributeTypeName == attr.GetType().FullName);
79         }
80
81         public static bool IsAsyncOperation(Delegate @delegate)
82         {
83 #if PORTABLE
84             return IsAsyncOperation(@delegate.GetMethodInfo());
85 #else
86             return IsAsyncOperation(@delegate.Method);
87 #endif
88         }
89
90         /// <summary>
91         /// Waits for pending asynchronous operations to complete, if appropriate,
92         /// and returns a proper result of the invocation by unwrapping task results
93         /// </summary>
94         /// <param name="invocationResult">The raw result of the method invocation</param>
95         /// <returns>The unwrapped result, if necessary</returns>
96         public abstract object WaitForPendingOperationsToComplete(object invocationResult);
97
98         public virtual void Dispose()
99         { }
100
101         private class AsyncTaskInvocationRegion : AsyncInvocationRegion
102         {
103             private const string TaskWaitMethod = "Wait";
104             private const string TaskResultProperty = "Result";
105             private const string VoidTaskResultType = "VoidTaskResult";
106             private const string SystemAggregateException = "System.AggregateException";
107             private const string InnerExceptionsProperty = "InnerExceptions";
108             private const BindingFlags TaskResultPropertyBindingFlags = BindingFlags.Instance | BindingFlags.Public;
109
110             public override object WaitForPendingOperationsToComplete(object invocationResult)
111             {
112                 try
113                 {
114                     invocationResult.GetType().GetMethod(TaskWaitMethod, new Type[0]).Invoke(invocationResult, null);
115                 }
116                 catch (TargetInvocationException e)
117                 {
118                     IList<Exception> innerExceptions = GetAllExceptions(e.InnerException);
119                     ExceptionHelper.Rethrow(innerExceptions[0]);
120                 }
121                 var args = invocationResult.GetType().GetGenericArguments();
122                 if (args != null && args.Length == 1 && args[0].Name == VoidTaskResultType)
123                 {
124                     return null;
125                 }
126
127                 PropertyInfo taskResultProperty = invocationResult.GetType().GetProperty(TaskResultProperty, TaskResultPropertyBindingFlags);
128
129                 return taskResultProperty != null ? taskResultProperty.GetValue(invocationResult, null) : invocationResult;
130             }
131
132             private static IList<Exception> GetAllExceptions(Exception exception)
133             {
134                 if (SystemAggregateException.Equals(exception.GetType().FullName))
135                     return (IList<Exception>)exception.GetType().GetProperty(InnerExceptionsProperty).GetValue(exception, null);
136
137                 return new Exception[] { exception };
138             }
139         }
140     }
141 }
142 #endif