[NUI] Rebase develnui (DevelNUI only patches --> master) (#3910)
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Api / FrameworkController.cs
1 // ***********************************************************************
2 // Copyright (c) 2009-2014 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.Linq;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Diagnostics;
34 using System.Globalization;
35 using System.IO;
36 using System.Reflection;
37 using System.Web.UI;
38 using NUnit.Common;
39 using NUnit.Compatibility;
40 using NUnit.Framework.Interfaces;
41 using NUnit.Framework.Internal;
42
43 namespace NUnit.Framework.Api
44 {
45     /// <summary>
46     /// FrameworkController provides a facade for use in loading, browsing 
47     /// and running tests without requiring a reference to the NUnit 
48     /// framework. All calls are encapsulated in constructors for
49     /// this class and its nested classes, which only require the
50     /// types of the Common Type System as arguments.
51     /// 
52     /// The controller supports four actions: Load, Explore, Count and Run.
53     /// They are intended to be called by a driver, which should allow for
54     /// proper sequencing of calls. Load must be called before any of the 
55     /// other actions. The driver may support other actions, such as
56     /// reload on run, by combining these calls.
57     /// </summary>
58     //[Serializable]
59     public class FrameworkController : LongLivedMarshalByRefObject
60     {
61 #if !PORTABLE && !SILVERLIGHT
62         private const string LOG_FILE_FORMAT = "InternalTrace.{0}.{1}.log";
63 #endif
64
65         // Pre-loaded test assembly, if passed in constructor
66         private readonly Assembly _testAssembly;
67
68         #region Constructors
69
70         /// <summary>
71         /// Construct a FrameworkController using the default builder and runner.
72         /// </summary>
73         /// <param name="assemblyNameOrPath">The AssemblyName or path to the test assembly</param>
74         /// <param name="idPrefix">A prefix used for all test ids created under this controller.</param>
75         /// <param name="settings">A Dictionary of settings to use in loading and running the tests</param>
76         public FrameworkController(string assemblyNameOrPath, string idPrefix, IDictionary settings)
77         {
78             this.Builder = new DefaultTestAssemblyBuilder();
79             this.Runner = new NUnitTestAssemblyRunner(this.Builder);
80
81             Test.IdPrefix = idPrefix;
82             Initialize(assemblyNameOrPath, settings);
83         }
84
85         /// <summary>
86         /// Construct a FrameworkController using the default builder and runner.
87         /// </summary>
88         /// <param name="assembly">The test assembly</param>
89         /// <param name="idPrefix">A prefix used for all test ids created under this controller.</param>
90         /// <param name="settings">A Dictionary of settings to use in loading and running the tests</param>
91         public FrameworkController(Assembly assembly, string idPrefix, IDictionary settings)
92             : this(assembly.FullName, idPrefix, settings)
93         {
94             _testAssembly = assembly;
95         }
96
97         /// <summary>
98         /// Construct a FrameworkController, specifying the types to be used
99         /// for the runner and builder. This constructor is provided for
100         /// purposes of development.
101         /// </summary>
102         /// <param name="assemblyNameOrPath">The full AssemblyName or the path to the test assembly</param>
103         /// <param name="idPrefix">A prefix used for all test ids created under this controller.</param>
104         /// <param name="settings">A Dictionary of settings to use in loading and running the tests</param>
105         /// <param name="runnerType">The Type of the test runner</param>
106         /// <param name="builderType">The Type of the test builder</param>
107         public FrameworkController(string assemblyNameOrPath, string idPrefix, IDictionary settings, string runnerType, string builderType)
108         {
109             Builder = (ITestAssemblyBuilder)Reflect.Construct(Type.GetType(builderType));
110             Runner = (ITestAssemblyRunner)Reflect.Construct(Type.GetType(runnerType), new object[] { Builder });
111
112             Test.IdPrefix = idPrefix ?? "";
113             Initialize(assemblyNameOrPath, settings);
114         }
115
116         /// <summary>
117         /// Construct a FrameworkController, specifying the types to be used
118         /// for the runner and builder. This constructor is provided for
119         /// purposes of development.
120         /// </summary>
121         /// <param name="assembly">The test assembly</param>
122         /// <param name="idPrefix">A prefix used for all test ids created under this controller.</param>
123         /// <param name="settings">A Dictionary of settings to use in loading and running the tests</param>
124         /// <param name="runnerType">The Type of the test runner</param>
125         /// <param name="builderType">The Type of the test builder</param>
126         public FrameworkController(Assembly assembly, string idPrefix, IDictionary settings, string runnerType, string builderType)
127             : this(assembly.FullName, idPrefix, settings, runnerType, builderType)
128         {
129             _testAssembly = assembly;
130         }
131
132         private void Initialize(string assemblyPath, IDictionary settings)
133         {
134             AssemblyNameOrPath = assemblyPath;
135
136             var newSettings = settings as IDictionary<string, object>;
137             Settings = newSettings ?? settings.Cast<DictionaryEntry>().ToDictionary(de => (string)de.Key, de => de.Value);
138
139             if (Settings.ContainsKey(PackageSettings.InternalTraceLevel))
140             {
141                 var traceLevel = (InternalTraceLevel)Enum.Parse(typeof(InternalTraceLevel), (string)Settings[PackageSettings.InternalTraceLevel], true);
142
143                 if (Settings.ContainsKey(PackageSettings.InternalTraceWriter))
144                     InternalTrace.Initialize((TextWriter)Settings[PackageSettings.InternalTraceWriter], traceLevel);
145 #if !PORTABLE && !SILVERLIGHT
146                 else
147                 {
148                     var workDirectory = Settings.ContainsKey(PackageSettings.WorkDirectory) ? (string)Settings[PackageSettings.WorkDirectory] : Env.DefaultWorkDirectory;
149                     var logName = string.Format(LOG_FILE_FORMAT, Process.GetCurrentProcess().Id, Path.GetFileName(assemblyPath));
150                     InternalTrace.Initialize(Path.Combine(workDirectory, logName), traceLevel);
151                 }
152 #endif
153             }
154         }
155
156         #endregion
157
158         #region Properties
159
160         /// <summary>
161         /// Gets the ITestAssemblyBuilder used by this controller instance.
162         /// </summary>
163         /// <value>The builder.</value>
164         public ITestAssemblyBuilder Builder { get; private set; }
165
166         /// <summary>
167         /// Gets the ITestAssemblyRunner used by this controller instance.
168         /// </summary>
169         /// <value>The runner.</value>
170         public ITestAssemblyRunner Runner { get; private set; }
171
172         /// <summary>
173         /// Gets the AssemblyName or the path for which this FrameworkController was created
174         /// </summary>
175         public string AssemblyNameOrPath { get; private set; }
176
177         /// <summary>
178         /// Gets the Assembly for which this
179         /// </summary>
180         public Assembly Assembly { get; private set; }
181
182         /// <summary>
183         /// Gets a dictionary of settings for the FrameworkController
184         /// </summary>
185         internal IDictionary<string, object> Settings { get; private set; }
186
187         #endregion
188
189         #region Public Action methods Used by nunit.driver for running portable tests
190
191         /// <summary>
192         /// Loads the tests in the assembly
193         /// </summary>
194         /// <returns></returns>
195         public string LoadTests()
196         {
197             if (_testAssembly != null)
198                 Runner.Load(_testAssembly, Settings);
199             else
200                 Runner.Load(AssemblyNameOrPath, Settings);
201
202             return Runner.LoadedTest.ToXml(false).OuterXml;
203         }
204
205         /// <summary>
206         /// Returns info about the tests in an assembly
207         /// </summary>
208         /// <param name="filter">A string containing the XML representation of the filter to use</param>
209         /// <returns>The XML result of exploring the tests</returns>
210         public string ExploreTests(string filter)
211         {
212             Guard.ArgumentNotNull(filter, "filter");
213
214             if (Runner.LoadedTest == null)
215                 throw new InvalidOperationException("The Explore method was called but no test has been loaded");
216
217             // TODO: Make use of the filter
218             return Runner.LoadedTest.ToXml(true).OuterXml;
219         }
220
221         /// <summary>
222         /// Runs the tests in an assembly
223         /// </summary>
224         /// <param name="filter">A string containing the XML representation of the filter to use</param>
225         /// <returns>The XML result of the test run</returns>
226         public string RunTests(string filter)
227         {
228             Guard.ArgumentNotNull(filter, "filter");
229
230             TNode result = Runner.Run(new TestProgressReporter(null), TestFilter.FromXml(filter)).ToXml(true);
231
232             // Insert elements as first child in reverse order
233             if (Settings != null) // Some platforms don't have settings
234                 InsertSettingsElement(result, Settings);
235 #if !PORTABLE && !SILVERLIGHT
236             InsertEnvironmentElement(result);
237 #endif
238
239             // Ensure that the CallContext of the thread is not polluted
240             // by our TestExecutionContext, which is not serializable.
241             TestExecutionContext.ClearCurrentContext();
242
243             return result.OuterXml;
244         }
245
246 #if !NET_2_0
247
248         class ActionCallback : ICallbackEventHandler
249         {
250             readonly Action<string> _callback;
251
252             public ActionCallback(Action<string> callback)
253             {
254                 _callback = callback;
255             }
256
257             public string GetCallbackResult()
258             {
259                 throw new NotImplementedException();
260             }
261
262             public void RaiseCallbackEvent(string report)
263             {
264                 if(_callback != null)
265                     _callback.Invoke(report);
266             }
267         }
268
269         /// <summary>
270         /// Runs the tests in an assembly syncronously reporting back the test results through the callback
271         /// or through the return value
272         /// </summary>
273         /// <param name="callback">The callback that receives the test results</param>
274         /// <param name="filter">A string containing the XML representation of the filter to use</param>
275         /// <returns>The XML result of the test run</returns>
276         public string RunTests(Action<string> callback, string filter)
277         {
278             Guard.ArgumentNotNull(filter, "filter");
279
280             var handler = new ActionCallback(callback);
281
282             TNode result = Runner.Run(new TestProgressReporter(handler), TestFilter.FromXml(filter)).ToXml(true);
283
284             // Insert elements as first child in reverse order
285             if (Settings != null) // Some platforms don't have settings
286                 InsertSettingsElement(result, Settings);
287 #if !PORTABLE && !SILVERLIGHT
288             InsertEnvironmentElement(result);
289 #endif
290
291             // Ensure that the CallContext of the thread is not polluted
292             // by our TestExecutionContext, which is not serializable.
293             TestExecutionContext.ClearCurrentContext();
294
295             return result.OuterXml;
296         }
297
298         /// <summary>
299         /// Runs the tests in an assembly asyncronously reporting back the test results through the callback
300         /// </summary>
301         /// <param name="callback">The callback that receives the test results</param>
302         /// <param name="filter">A string containing the XML representation of the filter to use</param>
303         private void RunAsync(Action<string> callback, string filter)
304         {
305             Guard.ArgumentNotNull(filter, "filter");
306
307             var handler = new ActionCallback(callback);
308
309             Runner.RunAsync(new TestProgressReporter(handler), TestFilter.FromXml(filter));
310         }
311 #endif
312
313         /// <summary>
314         /// Stops the test run
315         /// </summary>
316         /// <param name="force">True to force the stop, false for a cooperative stop</param>
317         public void StopRun(bool force)
318         {
319             Runner.StopRun(force);
320         }
321
322         /// <summary>
323         /// Counts the number of test cases in the loaded TestSuite
324         /// </summary>
325         /// <param name="filter">A string containing the XML representation of the filter to use</param>
326         /// <returns>The number of tests</returns>
327         public int CountTests(string filter)
328         {
329             Guard.ArgumentNotNull(filter, "filter");
330
331             return Runner.CountTestCases(TestFilter.FromXml(filter));
332         }
333
334         #endregion
335
336         #region Private Action Methods Used by Nested Classes
337
338         private void LoadTests(ICallbackEventHandler handler)
339         {
340             handler.RaiseCallbackEvent(LoadTests());
341         }
342
343         private void ExploreTests(ICallbackEventHandler handler, string filter)
344         {
345             Guard.ArgumentNotNull(filter, "filter");
346
347             if (Runner.LoadedTest == null)
348                 throw new InvalidOperationException("The Explore method was called but no test has been loaded");
349
350             // TODO: Make use of the filter
351             handler.RaiseCallbackEvent(Runner.LoadedTest.ToXml(true).OuterXml);
352         }
353
354         private void RunTests(ICallbackEventHandler handler, string filter)
355         {
356             Guard.ArgumentNotNull(filter, "filter");
357
358             TNode result = Runner.Run(new TestProgressReporter(handler), TestFilter.FromXml(filter)).ToXml(true);
359
360             // Insert elements as first child in reverse order
361             if (Settings != null) // Some platforms don't have settings
362                 InsertSettingsElement(result, Settings);
363 #if !PORTABLE && !SILVERLIGHT
364             InsertEnvironmentElement(result);
365 #endif
366
367             // Ensure that the CallContext of the thread is not polluted
368             // by our TestExecutionContext, which is not serializable.
369             TestExecutionContext.ClearCurrentContext();
370
371             handler.RaiseCallbackEvent(result.OuterXml);
372         }
373
374         private void RunAsync(ICallbackEventHandler handler, string filter)
375         {
376             Guard.ArgumentNotNull(filter, "filter");
377
378             Runner.RunAsync(new TestProgressReporter(handler), TestFilter.FromXml(filter));
379         }
380
381         private void StopRun(ICallbackEventHandler handler, bool force)
382         {
383             StopRun(force);
384         }
385
386         private void CountTests(ICallbackEventHandler handler, string filter)
387         {
388             handler.RaiseCallbackEvent(CountTests(filter).ToString());
389         }
390
391 #if !PORTABLE && !SILVERLIGHT
392         /// <summary>
393         /// Inserts environment element
394         /// </summary>
395         /// <param name="targetNode">Target node</param>
396         /// <returns>The new node</returns>
397         public static TNode InsertEnvironmentElement(TNode targetNode)
398         {
399             TNode env = new TNode("environment");
400             targetNode.ChildNodes.Insert(0, env);
401
402             env.AddAttribute("framework-version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
403             env.AddAttribute("clr-version", Environment.Version.ToString());
404             env.AddAttribute("os-version", Environment.OSVersion.ToString());
405             env.AddAttribute("platform", Environment.OSVersion.Platform.ToString());
406 #if !NETCF
407             env.AddAttribute("cwd", Environment.CurrentDirectory);
408             env.AddAttribute("machine-name", Environment.MachineName);
409             env.AddAttribute("user", Environment.UserName);
410             env.AddAttribute("user-domain", Environment.UserDomainName);
411 #endif
412             env.AddAttribute("culture", CultureInfo.CurrentCulture.ToString());
413             env.AddAttribute("uiculture", CultureInfo.CurrentUICulture.ToString());
414             env.AddAttribute("os-architecture", GetProcessorArchitecture());
415
416             return env;
417         }
418
419         private static string GetProcessorArchitecture()
420         {
421             return IntPtr.Size == 8 ? "x64" : "x86";
422         }
423 #endif
424
425         /// <summary>
426         /// Inserts settings element
427         /// </summary>
428         /// <param name="targetNode">Target node</param>
429         /// <param name="settings">Settings dictionary</param>
430         /// <returns>The new node</returns>
431         public static TNode InsertSettingsElement(TNode targetNode, IDictionary<string, object> settings)
432         {
433             TNode settingsNode = new TNode("settings");
434             targetNode.ChildNodes.Insert(0, settingsNode);
435
436             foreach (string key in settings.Keys)
437                 AddSetting(settingsNode, key, settings[key]);
438
439 #if PARALLEL
440             // Add default values for display
441             if (!settings.ContainsKey(PackageSettings.NumberOfTestWorkers))
442                 AddSetting(settingsNode, PackageSettings.NumberOfTestWorkers, NUnitTestAssemblyRunner.DefaultLevelOfParallelism);
443 #endif
444
445                 return settingsNode;
446         }
447
448         private static void AddSetting(TNode settingsNode, string name, object value)
449         {
450             TNode setting = new TNode("setting");
451             setting.AddAttribute("name", name);
452             setting.AddAttribute("value", value.ToString());
453
454             settingsNode.ChildNodes.Add(setting);
455         }
456
457         #endregion
458
459         #region Nested Action Classes
460
461         #region TestContollerAction
462
463         /// <summary>
464         /// FrameworkControllerAction is the base class for all actions
465         /// performed against a FrameworkController.
466         /// </summary>
467         public abstract class FrameworkControllerAction : LongLivedMarshalByRefObject
468         {
469         }
470
471         #endregion
472
473         #region LoadTestsAction
474
475         /// <summary>
476         /// LoadTestsAction loads a test into the FrameworkController
477         /// </summary>
478         public class LoadTestsAction : FrameworkControllerAction
479         {
480             /// <summary>
481             /// LoadTestsAction loads the tests in an assembly.
482             /// </summary>
483             /// <param name="controller">The controller.</param>
484             /// <param name="handler">The callback handler.</param>
485             public LoadTestsAction(FrameworkController controller, object handler)
486             {
487                 controller.LoadTests((ICallbackEventHandler)handler);
488             }
489         }
490
491         #endregion
492
493         #region ExploreTestsAction
494
495         /// <summary>
496         /// ExploreTestsAction returns info about the tests in an assembly
497         /// </summary>
498         public class ExploreTestsAction : FrameworkControllerAction
499         {
500             /// <summary>
501             /// Initializes a new instance of the <see cref="ExploreTestsAction"/> class.
502             /// </summary>
503             /// <param name="controller">The controller for which this action is being performed.</param>
504             /// <param name="filter">Filter used to control which tests are included (NYI)</param>
505             /// <param name="handler">The callback handler.</param>
506             public ExploreTestsAction(FrameworkController controller, string filter, object handler)
507             {
508                 controller.ExploreTests((ICallbackEventHandler)handler, filter);
509             }
510         }
511
512         #endregion
513
514         #region CountTestsAction
515
516         /// <summary>
517         /// CountTestsAction counts the number of test cases in the loaded TestSuite
518         /// held by the FrameworkController.
519         /// </summary>
520         public class CountTestsAction : FrameworkControllerAction
521         {
522             /// <summary>
523             /// Construct a CountsTestAction and perform the count of test cases.
524             /// </summary>
525             /// <param name="controller">A FrameworkController holding the TestSuite whose cases are to be counted</param>
526             /// <param name="filter">A string containing the XML representation of the filter to use</param>
527             /// <param name="handler">A callback handler used to report results</param>
528             public CountTestsAction(FrameworkController controller, string filter, object handler) 
529             {
530                 controller.CountTests((ICallbackEventHandler)handler, filter);
531             }
532         }
533
534         #endregion
535
536         #region RunTestsAction
537
538         /// <summary>
539         /// RunTestsAction runs the loaded TestSuite held by the FrameworkController.
540         /// </summary>
541         public class RunTestsAction : FrameworkControllerAction
542         {
543             /// <summary>
544             /// Construct a RunTestsAction and run all tests in the loaded TestSuite.
545             /// </summary>
546             /// <param name="controller">A FrameworkController holding the TestSuite to run</param>
547             /// <param name="filter">A string containing the XML representation of the filter to use</param>
548             /// <param name="handler">A callback handler used to report results</param>
549             public RunTestsAction(FrameworkController controller, string filter, object handler) 
550             {
551                 controller.RunTests((ICallbackEventHandler)handler, filter);
552             }
553         }
554
555         #endregion
556
557         #region RunAsyncAction
558
559         /// <summary>
560         /// RunAsyncAction initiates an asynchronous test run, returning immediately
561         /// </summary>
562         public class RunAsyncAction : FrameworkControllerAction
563         {
564             /// <summary>
565             /// Construct a RunAsyncAction and run all tests in the loaded TestSuite.
566             /// </summary>
567             /// <param name="controller">A FrameworkController holding the TestSuite to run</param>
568             /// <param name="filter">A string containing the XML representation of the filter to use</param>
569             /// <param name="handler">A callback handler used to report results</param>
570             public RunAsyncAction(FrameworkController controller, string filter, object handler) 
571             {
572                 controller.RunAsync((ICallbackEventHandler)handler, filter);
573             }
574         }
575
576         #endregion
577
578         #region StopRunAction
579
580         /// <summary>
581         /// StopRunAction stops an ongoing run.
582         /// </summary>
583         public class StopRunAction : FrameworkControllerAction
584         {
585             /// <summary>
586             /// Construct a StopRunAction and stop any ongoing run. If no
587             /// run is in process, no error is raised.
588             /// </summary>
589             /// <param name="controller">The FrameworkController for which a run is to be stopped.</param>
590             /// <param name="force">True the stop should be forced, false for a cooperative stop.</param>
591             /// <param name="handler">>A callback handler used to report results</param>
592             /// <remarks>A forced stop will cause threads and processes to be killed as needed.</remarks>
593             public StopRunAction(FrameworkController controller, bool force, object handler)
594             {
595                 controller.StopRun((ICallbackEventHandler)handler, force);
596             }
597         }
598
599         #endregion
600
601         #endregion
602     }
603 }