[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Internal / Builders / NUnitTestFixtureBuilder.cs
1 // ***********************************************************************
2 // Copyright (c) 2014-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;
31 using System.Reflection;
32 using NUnit.Compatibility;
33 using NUnit.Framework.Interfaces;
34
35 namespace NUnit.Framework.Internal.Builders
36 {
37     /// <summary>
38     /// NUnitTestFixtureBuilder is able to build a fixture given
39     /// a class marked with a TestFixtureAttribute or an unmarked
40     /// class containing test methods. In the first case, it is
41     /// called by the attribute and in the second directly by
42     /// NUnitSuiteBuilder.
43     /// </summary>
44     public class NUnitTestFixtureBuilder
45     {
46         #region Static Fields
47
48         static readonly string NO_TYPE_ARGS_MSG =
49             "Fixture type contains generic parameters. You must either provide " +
50             "Type arguments or specify constructor arguments that allow NUnit " +
51             "to deduce the Type arguments.";
52
53         #endregion
54
55         #region Instance Fields
56
57         private ITestCaseBuilder _testBuilder = new DefaultTestCaseBuilder();
58
59         #endregion
60
61         #region Public Methods
62
63         /// <summary>
64         /// Build a TestFixture from type provided. A non-null TestSuite
65         /// must always be returned, since the method is generally called
66         /// because the user has marked the target class as a fixture.
67         /// If something prevents the fixture from being used, it should
68         /// be returned nonetheless, labelled as non-runnable.
69         /// </summary>
70         /// <param name="typeInfo">An ITypeInfo for the fixture to be used.</param>
71         /// <returns>A TestSuite object or one derived from TestSuite.</returns>
72         // TODO: This should really return a TestFixture, but that requires changes to the Test hierarchy.
73         public TestSuite BuildFrom(ITypeInfo typeInfo)
74         {
75             var fixture = new TestFixture(typeInfo);
76
77             if (fixture.RunState != RunState.NotRunnable)
78                 CheckTestFixtureIsValid(fixture);
79
80             fixture.ApplyAttributesToTest(typeInfo.Type.GetTypeInfo());
81
82             AddTestCasesToFixture(fixture);
83
84             return fixture;
85         }
86
87         /// <summary>
88         /// Overload of BuildFrom called by tests that have arguments.
89         /// Builds a fixture using the provided type and information 
90         /// in the ITestFixtureData object.
91         /// </summary>
92         /// <param name="typeInfo">The TypeInfo for which to construct a fixture.</param>
93         /// <param name="testFixtureData">An object implementing ITestFixtureData or null.</param>
94         /// <returns></returns>
95         public TestSuite BuildFrom(ITypeInfo typeInfo, ITestFixtureData testFixtureData)
96         {
97             Guard.ArgumentNotNull(testFixtureData, "testFixtureData");
98
99             object[] arguments = testFixtureData.Arguments;
100
101             if (typeInfo.ContainsGenericParameters)
102             {
103                 Type[] typeArgs = testFixtureData.TypeArgs;
104                 if (typeArgs.Length == 0)
105                 {
106                     int cnt = 0;
107                     foreach (object o in arguments)
108                         if (o is Type) cnt++;
109                         else break;
110
111                     typeArgs = new Type[cnt];
112                     for (int i = 0; i < cnt; i++)
113                         typeArgs[i] = (Type)arguments[i];
114
115                     if (cnt > 0)
116                     {
117                         object[] args = new object[arguments.Length - cnt];
118                         for (int i = 0; i < args.Length; i++)
119                             args[i] = arguments[cnt + i];
120
121                         arguments = args;
122                     }
123                 }
124
125                 if (typeArgs.Length > 0 ||
126                     TypeHelper.CanDeduceTypeArgsFromArgs(typeInfo.Type, arguments, ref typeArgs))
127                 {
128                     typeInfo = typeInfo.MakeGenericType(typeArgs);
129                 }
130             }
131
132             var fixture = new TestFixture(typeInfo);
133             
134             if (arguments != null && arguments.Length > 0)
135             {
136                 string name = fixture.Name = typeInfo.GetDisplayName(arguments);
137                 string nspace = typeInfo.Namespace;
138                 fixture.FullName = nspace != null && nspace != ""
139                     ? nspace + "." + name
140                     : name;
141                 fixture.Arguments = arguments;
142             }
143
144             if (fixture.RunState != RunState.NotRunnable)
145                 fixture.RunState = testFixtureData.RunState;
146
147             foreach (string key in testFixtureData.Properties.Keys)
148                 foreach (object val in testFixtureData.Properties[key])
149                     fixture.Properties.Add(key, val);
150
151             if (fixture.RunState != RunState.NotRunnable)
152                 CheckTestFixtureIsValid(fixture);
153
154             fixture.ApplyAttributesToTest(typeInfo.Type.GetTypeInfo());
155
156             AddTestCasesToFixture(fixture);
157
158             return fixture;
159         }
160
161         #endregion
162
163         #region Helper Methods
164
165         /// <summary>
166         /// Method to add test cases to the newly constructed fixture.
167         /// </summary>
168         /// <param name="fixture">The fixture to which cases should be added</param>
169         private void AddTestCasesToFixture(TestFixture fixture)
170         {
171             // TODO: Check this logic added from Neil's build.
172             if (fixture.TypeInfo.ContainsGenericParameters)
173             {
174                 fixture.RunState = RunState.NotRunnable;
175                 fixture.Properties.Set(PropertyNames.SkipReason, NO_TYPE_ARGS_MSG);
176                 return;
177             }
178
179             var methods = fixture.TypeInfo.GetMethods(
180                 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
181
182             foreach (IMethodInfo method in methods)
183             {
184                 Test test = BuildTestCase(method, fixture);
185
186                 if (test != null)
187                 {
188                     fixture.Add(test);
189                 }
190             }
191         }
192
193         /// <summary>
194         /// Method to create a test case from a MethodInfo and add
195         /// it to the fixture being built. It first checks to see if
196         /// any global TestCaseBuilder addin wants to build the
197         /// test case. If not, it uses the internal builder
198         /// collection maintained by this fixture builder.
199         /// 
200         /// The default implementation has no test case builders.
201         /// Derived classes should add builders to the collection
202         /// in their constructor.
203         /// </summary>
204         /// <param name="method">The method for which a test is to be created</param>
205         /// <param name="suite">The test suite being built.</param>
206         /// <returns>A newly constructed Test</returns>
207         private Test BuildTestCase(IMethodInfo method, TestSuite suite)
208         {
209             return _testBuilder.CanBuildFrom(method, suite)
210                 ? _testBuilder.BuildFrom(method, suite)
211                 : null;
212         }
213
214         private static void CheckTestFixtureIsValid(TestFixture fixture)
215         {
216             if (fixture.TypeInfo.ContainsGenericParameters)
217             {
218                 fixture.RunState = RunState.NotRunnable;
219                 fixture.Properties.Set(PropertyNames.SkipReason, NO_TYPE_ARGS_MSG);
220             }
221             else if (!fixture.TypeInfo.IsStaticClass)
222             {
223                 Type[] argTypes = Reflect.GetTypeArray(fixture.Arguments);
224
225                 if (!fixture.TypeInfo.HasConstructor(argTypes))
226                 {
227                     fixture.RunState = RunState.NotRunnable;
228                     fixture.Properties.Set(PropertyNames.SkipReason, "No suitable constructor was found");
229                 }
230             }
231         }
232
233         private static bool IsStaticClass(Type type)
234         {
235             return type.GetTypeInfo().IsAbstract && type.GetTypeInfo().IsSealed;
236         }
237
238         #endregion
239     }
240 }