[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Attributes / TestCaseAttribute.cs
1 // ***********************************************************************
2 // Copyright (c) 2008-2015 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 using System;
30 using System.Collections.Generic;
31 using System.Reflection;
32 using NUnit.Compatibility;
33 using NUnit.Framework.Interfaces;
34 using NUnit.Framework.Internal;
35 using NUnit.Framework.Internal.Builders;
36
37 namespace NUnit.Framework
38 {
39     /// <summary>
40     /// TestCaseAttribute is used to mark parameterized test cases
41     /// and provide them with their arguments.
42     /// </summary>
43     [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited=false)]
44     public class TestCaseAttribute : NUnitAttribute, ITestBuilder, ITestCaseData, IImplyFixture
45     {
46         #region Constructors
47
48         /// <summary>
49         /// Construct a TestCaseAttribute with a list of arguments.
50         /// This constructor is not CLS-Compliant
51         /// </summary>
52         /// <param name="arguments"></param>
53         public TestCaseAttribute(params object[] arguments)
54         {
55             RunState = RunState.Runnable;
56             
57             if (arguments == null)
58                 Arguments = new object[] { null };
59             else
60                 Arguments = arguments;
61
62             Properties = new PropertyBag();
63         }
64
65         /// <summary>
66         /// Construct a TestCaseAttribute with a single argument
67         /// </summary>
68         /// <param name="arg"></param>
69         public TestCaseAttribute(object arg)
70         {
71             RunState = RunState.Runnable;                       
72             Arguments = new object[] { arg };
73             Properties = new PropertyBag();
74         }
75
76         /// <summary>
77         /// Construct a TestCaseAttribute with a two arguments
78         /// </summary>
79         /// <param name="arg1"></param>
80         /// <param name="arg2"></param>
81         public TestCaseAttribute(object arg1, object arg2)
82         {
83             RunState = RunState.Runnable;                       
84             Arguments = new object[] { arg1, arg2 };
85             Properties = new PropertyBag();
86         }
87
88         /// <summary>
89         /// Construct a TestCaseAttribute with a three arguments
90         /// </summary>
91         /// <param name="arg1"></param>
92         /// <param name="arg2"></param>
93         /// <param name="arg3"></param>
94         public TestCaseAttribute(object arg1, object arg2, object arg3)
95         {
96             RunState = RunState.Runnable;                       
97             Arguments = new object[] { arg1, arg2, arg3 };
98             Properties = new PropertyBag();
99         }
100
101         #endregion
102
103         #region ITestData Members
104
105         /// <summary>
106         /// Gets or sets the name of the test.
107         /// </summary>
108         /// <value>The name of the test.</value>
109         public string TestName { get; set; }
110
111         /// <summary>
112         /// Gets or sets the RunState of this test case.
113         /// </summary>
114         public RunState RunState { get; private set; }
115
116         /// <summary>
117         /// Gets the list of arguments to a test case
118         /// </summary>
119         public object[] Arguments { get; private set; }
120
121         /// <summary>
122         /// Gets the properties of the test case
123         /// </summary>
124         public IPropertyBag Properties { get; private set; }
125
126         #endregion
127
128         #region ITestCaseData Members
129
130         /// <summary>
131         /// Gets or sets the expected result.
132         /// </summary>
133         /// <value>The result.</value>
134         public object ExpectedResult
135         {
136             get { return _expectedResult; }
137             set
138             {
139                 _expectedResult = value;
140                 HasExpectedResult = true;
141             }
142         }
143         private object _expectedResult;
144
145         /// <summary>
146         /// Returns true if the expected result has been set
147         /// </summary>
148         public bool HasExpectedResult { get; private set; }
149
150         #endregion
151
152         #region Other Properties
153
154         /// <summary>
155         /// Gets or sets the description.
156         /// </summary>
157         /// <value>The description.</value>
158         public string Description
159         {
160             get { return Properties.Get(PropertyNames.Description) as string; }
161             set { Properties.Set(PropertyNames.Description, value); }
162         }
163
164         /// <summary>
165         /// The author of this test
166         /// </summary>
167         public string Author
168         {
169             get { return Properties.Get(PropertyNames.Author) as string; }
170             set { Properties.Set(PropertyNames.Author, value); }
171         }
172
173         /// <summary>
174         /// The type that this test is testing
175         /// </summary>
176         public Type TestOf
177         {
178             get { return _testOf; }
179             set
180             {
181                 _testOf = value;
182                 Properties.Set(PropertyNames.TestOf, value.FullName);
183             }
184         }
185         private Type _testOf;
186
187         /// <summary>
188         /// Gets or sets the reason for ignoring the test
189         /// </summary>
190         public string Ignore 
191         { 
192             get { return IgnoreReason; }
193             set { IgnoreReason = value; } 
194         }
195
196         /// <summary>
197         /// Gets or sets a value indicating whether this <see cref="NUnit.Framework.TestCaseAttribute"/> is explicit.
198         /// </summary>
199         /// <value>
200         /// <c>true</c> if explicit; otherwise, <c>false</c>.
201         /// </value>
202         public bool Explicit
203         {
204             get { return RunState == RunState.Explicit; }
205             set { RunState = value ? RunState.Explicit : RunState.Runnable; }
206         }
207
208         /// <summary>
209         /// Gets or sets the reason for not running the test.
210         /// </summary>
211         /// <value>The reason.</value>
212         public string Reason 
213         { 
214             get { return Properties.Get(PropertyNames.SkipReason) as string; }
215             set { Properties.Set(PropertyNames.SkipReason, value); }
216         }
217
218         /// <summary>
219         /// Gets or sets the ignore reason. When set to a non-null
220         /// non-empty value, the test is marked as ignored.
221         /// </summary>
222         /// <value>The ignore reason.</value>
223         public string IgnoreReason
224         {
225             get { return Reason; }
226             set
227             {
228                 RunState = RunState.Ignored;
229                 Reason = value;
230             }
231         }
232         
233 #if !PORTABLE
234         /// <summary>
235         /// Comma-delimited list of platforms to run the test for
236         /// </summary>
237         public string IncludePlatform { get; set; }
238
239         /// <summary>
240         /// Comma-delimited list of platforms to not run the test for
241         /// </summary>
242         public string ExcludePlatform { get; set; }
243 #endif
244
245         /// <summary>
246         /// Gets and sets the category for this test case.
247         /// May be a comma-separated list of categories.
248         /// </summary>
249         public string Category
250         {
251             get { return Properties.Get(PropertyNames.Category) as string; }
252             set 
253             { 
254                 foreach (string cat in value.Split(new char[] { ',' }) )
255                     Properties.Add(PropertyNames.Category, cat); 
256             }
257         }
258  
259         #endregion
260
261         #region Helper Methods
262
263         private TestCaseParameters GetParametersForTestCase(IMethodInfo method)
264         {
265             TestCaseParameters parms;
266
267             try
268             {
269 #if NETCF
270                 var tmethod = method.MakeGenericMethodEx(Arguments);
271                 if (tmethod == null)
272                     throw new NotSupportedException("Cannot determine generic types from probing");
273                 method = tmethod;
274 #endif
275
276                 IParameterInfo[] parameters = method.GetParameters();
277                 int argsNeeded = parameters.Length;
278                 int argsProvided = Arguments.Length;
279
280                 parms = new TestCaseParameters(this);
281
282                 // Special handling for params arguments
283                 if (argsNeeded > 0 && argsProvided >= argsNeeded - 1)
284                 {
285                     IParameterInfo lastParameter = parameters[argsNeeded - 1];
286                     Type lastParameterType = lastParameter.ParameterType;
287                     Type elementType = lastParameterType.GetElementType();
288
289                     if (lastParameterType.IsArray && lastParameter.IsDefined<ParamArrayAttribute>(false))
290                     {
291                         if (argsProvided == argsNeeded)
292                         {
293                             Type lastArgumentType = parms.Arguments[argsProvided - 1].GetType();
294                             if (!lastParameterType.GetTypeInfo().IsAssignableFrom(lastArgumentType.GetTypeInfo()))
295                             {
296                                 Array array = Array.CreateInstance(elementType, 1);
297                                 array.SetValue(parms.Arguments[argsProvided - 1], 0);
298                                 parms.Arguments[argsProvided - 1] = array;
299                             }
300                         }
301                         else
302                         {
303                             object[] newArglist = new object[argsNeeded];
304                             for (int i = 0; i < argsNeeded && i < argsProvided; i++)
305                                 newArglist[i] = parms.Arguments[i];
306
307                             int length = argsProvided - argsNeeded + 1;
308                             Array array = Array.CreateInstance(elementType, length);
309                             for (int i = 0; i < length; i++)
310                                 array.SetValue(parms.Arguments[argsNeeded + i - 1], i);
311
312                             newArglist[argsNeeded - 1] = array;
313                             parms.Arguments = newArglist;
314                             argsProvided = argsNeeded;
315                         }
316                     }
317                 }
318
319 #if !NETCF
320                 //Special handling for optional parameters
321                 if (parms.Arguments.Length < argsNeeded)
322                 {
323                     object[] newArgList = new object[parameters.Length];
324                     Array.Copy(parms.Arguments, newArgList, parms.Arguments.Length);
325
326                     for (var i = 0; i < parameters.Length; i++)
327                     {
328                         if (parameters[i].IsOptional)
329                             newArgList[i] = Type.Missing;
330                         else
331                         {
332                             if (i < parms.Arguments.Length)
333                                 newArgList[i] = parms.Arguments[i];
334                             else
335                                 throw new TargetParameterCountException("Incorrect number of parameters specified for TestCase");
336                         }
337                     }
338                     parms.Arguments = newArgList;
339                 }
340 #endif
341
342                 //if (method.GetParameters().Length == 1 && method.GetParameters()[0].ParameterType == typeof(object[]))
343                 //    parms.Arguments = new object[]{parms.Arguments};
344
345                 // Special handling when sole argument is an object[]
346                 if (argsNeeded == 1 && method.GetParameters()[0].ParameterType == typeof(object[]))
347                 {
348                     if (argsProvided > 1 ||
349                         argsProvided == 1 && parms.Arguments[0].GetType() != typeof(object[]))
350                     {
351                         parms.Arguments = new object[] { parms.Arguments };
352                     }
353                 }
354
355                 if (argsProvided == argsNeeded)
356                     PerformSpecialConversions(parms.Arguments, parameters);
357             }
358             catch (Exception ex)
359             {
360                 parms = new TestCaseParameters(ex);
361             }
362
363             return parms;
364         }
365
366         /// <summary>
367         /// Performs several special conversions allowed by NUnit in order to
368         /// permit arguments with types that cannot be used in the constructor
369         /// of an Attribute such as TestCaseAttribute or to simplify their use.
370         /// </summary>
371         /// <param name="arglist">The arguments to be converted</param>
372         /// <param name="parameters">The ParameterInfo array for the method</param>
373         private static void PerformSpecialConversions(object[] arglist, IParameterInfo[] parameters)
374         {
375             for (int i = 0; i < arglist.Length; i++)
376             {
377                 object arg = arglist[i];
378                 Type targetType = parameters[i].ParameterType;
379
380                 if (arg == null)
381                     continue;
382
383                 if (arg is SpecialValue && (SpecialValue)arg == SpecialValue.Null)
384                 {
385                     arglist[i] = null;
386                     continue;
387                 }
388
389                 if (targetType.IsAssignableFrom(arg.GetType()))
390                     continue;
391 #if !PORTABLE
392                 if (arg is DBNull)
393                 {
394                     arglist[i] = null;
395                     continue;
396                 }
397 #endif
398                 bool convert = false;
399
400                 if (targetType == typeof(short) || targetType == typeof(byte) || targetType == typeof(sbyte) ||
401                     targetType == typeof(short?) || targetType == typeof(byte?) || targetType == typeof(sbyte?) || targetType == typeof(double?))
402                 {
403                     convert = arg is int;
404                 }
405                 else if (targetType == typeof(decimal) || targetType == typeof(decimal?))
406                 {
407                     convert = arg is double || arg is string || arg is int;
408                 }
409                 else if (targetType == typeof(DateTime) || targetType == typeof(DateTime?))
410                 {
411                     convert = arg is string;
412                 }
413
414                 if (convert)
415                 {
416                     Type convertTo = targetType.GetTypeInfo().IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>) ? 
417                         targetType.GetGenericArguments()[0] : targetType;
418                     arglist[i] = Convert.ChangeType(arg, convertTo, System.Globalization.CultureInfo.InvariantCulture);
419                 }
420                 else
421                 // Convert.ChangeType doesn't work for TimeSpan from string
422                 if ((targetType == typeof(TimeSpan) || targetType == typeof(TimeSpan?)) && arg is string)
423                 {
424                     arglist[i] = TimeSpan.Parse((string)arg);
425                 }
426             }
427         }
428         #endregion
429
430         #region ITestBuilder Members
431
432         /// <summary>
433         /// Construct one or more TestMethods from a given MethodInfo,
434         /// using available parameter data.
435         /// </summary>
436         /// <param name="method">The MethodInfo for which tests are to be constructed.</param>
437         /// <param name="suite">The suite to which the tests will be added.</param>
438         /// <returns>One or more TestMethods</returns>
439         public IEnumerable<TestMethod> BuildFrom(IMethodInfo method, Test suite)
440         {
441             TestMethod test = new NUnitTestCaseBuilder().BuildTestMethod(method, suite, GetParametersForTestCase(method));
442             
443 #if !PORTABLE
444             if (test.RunState != RunState.NotRunnable &&
445                 test.RunState != RunState.Ignored)
446             {
447                 PlatformHelper platformHelper = new PlatformHelper();
448                 
449                 if (!platformHelper.IsPlatformSupported(this))
450                 {
451                     test.RunState = RunState.Skipped;
452                     test.Properties.Add(PropertyNames.SkipReason, platformHelper.Reason);
453                 }
454             }
455 #endif
456
457             yield return test;
458         }
459
460         #endregion
461     }
462 }