b06a287aef857da8e814fce35c1ed1706a95809e
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Devel.Tests.Ubuntu / nunit.framework / Internal / Execution / CompositeWorkItem.cs
1 // ***********************************************************************
2 // Copyright (c) 2012 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.Threading;
32 using System.Reflection;
33 using NUnit.Compatibility;
34 using NUnit.Framework.Internal.Commands;
35 using NUnit.Framework.Interfaces;
36 using NUnit.Framework.TUnit;
37 using System.Collections.Concurrent;
38 using System.Threading.Tasks;
39
40 namespace NUnit.Framework.Internal.Execution
41 {
42     /// <summary>
43     /// A CompositeWorkItem represents a test suite and
44     /// encapsulates the execution of the suite as well
45     /// as all its child tests.
46     /// </summary>
47     public class CompositeWorkItem : WorkItem
48     {
49         //        static Logger log = InternalTrace.GetLogger("CompositeWorkItem");
50
51         private TestSuite _suite;
52         private TestSuiteResult _suiteResult;
53         private ITestFilter _childFilter;
54         private TestCommand _setupCommand;
55         private TestCommand _teardownCommand;
56         private List<WorkItem> _children;
57         private TSettings tsettings;
58
59         /// <summary>
60         /// List of Child WorkItems
61         /// </summary>
62         public List<WorkItem> Children
63         {
64             get { return _children; }
65             private set { _children = value; }
66         }
67
68         /// <summary>
69         /// A count of how many tests in the work item have a value for the Order Property
70         /// </summary>
71         private int _countOrder;
72
73         private CountdownEvent _childTestCountdown;
74
75         /// <summary>
76         /// Construct a CompositeWorkItem for executing a test suite
77         /// using a filter to select child tests.
78         /// </summary>
79         /// <param name="suite">The TestSuite to be executed</param>
80         /// <param name="childFilter">A filter used to select child tests</param>
81         public CompositeWorkItem(TestSuite suite, ITestFilter childFilter)
82             : base(suite)
83         {
84             _suite = suite;
85             _suiteResult = Result as TestSuiteResult;
86             _childFilter = childFilter;
87             _countOrder = 0;
88             tsettings = TSettings.GetInstance();
89         }
90
91         /// <summary>
92         /// Method that actually performs the work. Overridden
93         /// in CompositeWorkItem to do setup, run all child
94         /// items and then do teardown.
95         /// </summary>
96         protected override void PerformWork()
97         {
98             // Inititialize actions, setup and teardown
99             // We can't do this in the constructor because
100             // the context is not available at that point.
101             InitializeSetUpAndTearDownCommands();
102
103             if (!CheckForCancellation())
104                 // [tronghieu.d] - Add more conditions for check slave mode
105                 if (Test.TestType.Equals("Assembly") || !tsettings.IsSlaveMode || tsettings.Testcase_ID.Contains(Test.FullName))
106                     // [tronghieu.d] - end
107                     if (Test.RunState == RunState.Explicit && !_childFilter.IsExplicitMatch(Test))
108                         SkipFixture(ResultState.Explicit, GetSkipReason(), null);
109                     else
110                         switch (Test.RunState)
111                         {
112                             default:
113                             case RunState.Runnable:
114                             case RunState.Explicit:
115                                 // Assume success, since the result will be inconclusive
116                                 // if there is no setup method to run or if the
117                                 // context initialization fails.
118                                 Result.SetResult(ResultState.Success);
119
120                                 if (_children == null)
121                                     CreateChildWorkItems();
122
123                                 if (_children.Count > 0)
124                                 {
125                                     PerformOneTimeSetUp();
126
127                                     if (!CheckForCancellation())
128                                         switch (Result.ResultState.Status)
129                                         {
130                                             case TestStatus.Passed:
131                                                 RunChildren();
132                                                 return;
133                                             // Just return: completion event will take care
134                                             // of TestFixtureTearDown when all tests are done.
135
136                                             case TestStatus.Skipped:
137                                             case TestStatus.Inconclusive:
138                                             case TestStatus.Failed:
139                                                 SkipChildren(_suite, Result.ResultState.WithSite(FailureSite.Parent), "OneTimeSetUp: " + Result.Message);
140                                                 break;
141                                         }
142
143                                     // Directly execute the OneTimeFixtureTearDown for tests that
144                                     // were skipped, failed or set to inconclusive in one time setup
145                                     // unless we are aborting.
146                                     if (Context.ExecutionStatus != TestExecutionStatus.AbortRequested)
147                                         PerformOneTimeTearDown();
148                                 }
149                                 break;
150
151                             case RunState.Skipped:
152                                 SkipFixture(ResultState.Skipped, GetSkipReason(), null);
153                                 break;
154
155                             case RunState.Ignored:
156                                 SkipFixture(ResultState.Ignored, GetSkipReason(), null);
157                                 break;
158
159                             case RunState.NotRunnable:
160                                 SkipFixture(ResultState.NotRunnable, GetSkipReason(), GetProviderStackTrace());
161                                 break;
162                         }
163
164             // Fall through in case nothing was run.
165             // Otherwise, this is done in the completion event.
166             WorkItemComplete();
167
168         }
169
170         #region Helper Methods
171
172         private bool CheckForCancellation()
173         {
174             if (Context.ExecutionStatus != TestExecutionStatus.Running)
175             {
176                 Result.SetResult(ResultState.Cancelled, "Test cancelled by user");
177                 return true;
178             }
179
180             return false;
181         }
182
183         private void InitializeSetUpAndTearDownCommands()
184         {
185             List<SetUpTearDownItem> setUpTearDownItems = _suite.TypeInfo != null
186                 ? CommandBuilder.BuildSetUpTearDownList(_suite.TypeInfo.Type, typeof(OneTimeSetUpAttribute), typeof(OneTimeTearDownAttribute))
187                 : new List<SetUpTearDownItem>();
188
189             var actionItems = new List<TestActionItem>();
190             foreach (ITestAction action in Actions)
191             {
192                 // Special handling here for ParameterizedMethodSuite is a bit ugly. However,
193                 // it is needed because Tests are not supposed to know anything about Action
194                 // Attributes (or any attribute) and Attributes don't know where they were
195                 // initially applied unless we tell them.
196                 //
197                 // ParameterizedMethodSuites and individual test cases both use the same
198                 // MethodInfo as a source of attributes. We handle the Test and Default targets
199                 // in the test case, so we don't want to doubly handle it here.
200                 bool applyToSuite = (action.Targets & ActionTargets.Suite) == ActionTargets.Suite
201                     || action.Targets == ActionTargets.Default && !(Test is ParameterizedMethodSuite);
202
203                 bool applyToTest = (action.Targets & ActionTargets.Test) == ActionTargets.Test
204                     && !(Test is ParameterizedMethodSuite);
205
206                 if (applyToSuite)
207                     actionItems.Add(new TestActionItem(action));
208
209                 if (applyToTest)
210                     Context.UpstreamActions.Add(action);
211             }
212
213             _setupCommand = CommandBuilder.MakeOneTimeSetUpCommand(_suite, setUpTearDownItems, actionItems);
214             _teardownCommand = CommandBuilder.MakeOneTimeTearDownCommand(_suite, setUpTearDownItems, actionItems);
215         }
216
217         private void PerformOneTimeSetUp()
218         {
219             try
220             {
221                 _setupCommand.Execute(Context);
222
223                 // SetUp may have changed some things in the environment
224                 Context.UpdateContextFromEnvironment();
225             }
226             catch (Exception ex)
227             {
228                 if (ex is NUnitException || ex is TargetInvocationException)
229                     ex = ex.InnerException;
230
231                 Result.RecordException(ex, FailureSite.SetUp);
232             }
233         }
234
235         private void RunChildren()
236         {
237             int childCount = _children.Count;
238             if (childCount == 0)
239                 throw new InvalidOperationException("RunChildren called but item has no children");
240
241             _childTestCountdown = new CountdownEvent(childCount);
242
243             foreach (WorkItem child in _children)
244             {
245                 if (CheckForCancellation())
246                     break;
247
248
249                 #region tronghieu.d - testkit-stub
250 #if TIZEN
251                 if (child is CompositeWorkItem || !tsettings.IsManual
252                     || child.Test.FullName.Equals(tsettings.Testcase_ID))
253 #endif
254                 #endregion
255                 {
256                     if (child is SimpleWorkItem && tsettings.IsSlaveMode && !child.Test.FullName.Equals(tsettings.Testcase_ID)) continue;
257                     child.Completed += new EventHandler(OnChildCompleted);
258                     if (child.Context == null)
259                     {
260                         child.InitializeContext(new TestExecutionContext(Context));
261                     }
262                     Context.Dispatcher.Dispatch(child);
263                     childCount--;
264                 }
265             }
266
267             if (childCount > 0)
268             {
269                 while (childCount-- > 0)
270                     CountDownChildTest();
271             }
272         }
273
274         private void CreateChildWorkItems()
275         {
276             _children = new List<WorkItem>();
277
278             foreach (ITest test in _suite.Tests)
279             {
280                 if (_childFilter.Pass(test))
281                 {
282                     var child = WorkItem.CreateWorkItem(test, _childFilter);
283                     child.WorkerId = this.WorkerId;
284
285 #if !PORTABLE && !SILVERLIGHT && !NETCF
286                     if (child.TargetApartment == ApartmentState.Unknown && TargetApartment != ApartmentState.Unknown)
287                         child.TargetApartment = TargetApartment;
288 #endif
289
290                     if (test.Properties.ContainsKey(PropertyNames.Order))
291                     {
292                         _children.Insert(0, child);
293                         _countOrder++;
294                     }
295                     else
296                     {
297                         _children.Add(child);
298                     }
299                 }
300             }
301
302             if (_countOrder != 0) SortChildren();
303         }
304
305         private class WorkItemOrderComparer : IComparer<WorkItem>
306         {
307             /// <summary>
308             /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
309             /// </summary>
310             /// <returns>
311             /// A signed integer that indicates the relative values of <paramref name="x"/> and <paramref name="y"/>, as shown in the following table.Value Meaning Less than zero<paramref name="x"/> is less than <paramref name="y"/>.Zero<paramref name="x"/> equals <paramref name="y"/>.Greater than zero<paramref name="x"/> is greater than <paramref name="y"/>.
312             /// </returns>
313             /// <param name="x">The first object to compare.</param><param name="y">The second object to compare.</param>
314             public int Compare(WorkItem x, WorkItem y)
315             {
316                 var xKey = int.MaxValue;
317                 var yKey = int.MaxValue;
318
319                 if (x.Test.Properties.ContainsKey(PropertyNames.Order))
320                     xKey = (int)x.Test.Properties[PropertyNames.Order][0];
321
322                 if (y.Test.Properties.ContainsKey(PropertyNames.Order))
323                     yKey = (int)y.Test.Properties[PropertyNames.Order][0];
324
325                 return xKey.CompareTo(yKey);
326             }
327         }
328
329         /// <summary>
330         /// Sorts tests under this suite.
331         /// </summary>
332         private void SortChildren()
333         {
334             _children.Sort(0, _countOrder, new WorkItemOrderComparer());
335         }
336
337         private void SkipFixture(ResultState resultState, string message, string stackTrace)
338         {
339             Result.SetResult(resultState.WithSite(FailureSite.SetUp), message, StackFilter.Filter(stackTrace));
340             SkipChildren(_suite, resultState.WithSite(FailureSite.Parent), "OneTimeSetUp: " + message);
341         }
342
343         private void SkipChildren(TestSuite suite, ResultState resultState, string message)
344         {
345             foreach (Test child in suite.Tests)
346             {
347                 if (_childFilter.Pass(child))
348                 {
349                     TestResult childResult = child.MakeTestResult();
350                     childResult.SetResult(resultState, message);
351                     _suiteResult.AddResult(childResult);
352 #if TIZEN
353                     //[tronghieu.d] - return FAIL TC in case it is skipped.
354                     if (tsettings.IsSlaveMode && childResult.FullName.Equals(tsettings.Testcase_ID))
355                     {
356                         tsettings.TCResult = "FAIL";
357                         tsettings.TCMessage = childResult.Message;
358                         string json = "case_id=" + tsettings.Testcase_ID + "&result=" + tsettings.TCResult + "&msg=" + tsettings.TCMessage + "\n" + childResult.StackTrace;
359                         if (!tsettings.IsManual)
360                         {
361                             tsettings.RequestPOST("commit_result", json);
362                             tsettings.NextStepRequest();
363                         }
364                         else
365                             tsettings.RequestPOST("commit_manual_result", json);
366                     }
367 #endif
368                     // Some runners may depend on getting the TestFinished event
369                     // even for tests that have been skipped at a higher level.
370                     Context.Listener.TestFinished(childResult);
371
372                     if (child.IsSuite)
373                         SkipChildren((TestSuite)child, resultState, message);
374                 }
375             }
376         }
377
378         private void PerformOneTimeTearDown()
379         {
380             // Our child tests or even unrelated tests may have
381             // executed on the same thread since the time that
382             // this test started, so we have to re-establish
383             // the proper execution environment
384             this.Context.EstablishExecutionEnvironment();
385             _teardownCommand.Execute(this.Context);
386         }
387
388         private string GetSkipReason()
389         {
390             return (string)Test.Properties.Get(PropertyNames.SkipReason);
391         }
392
393         private string GetProviderStackTrace()
394         {
395             return (string)Test.Properties.Get(PropertyNames.ProviderStackTrace);
396         }
397
398         private object _completionLock = new object();
399
400         private void OnChildCompleted(object sender, EventArgs e)
401         {
402             lock (_completionLock)
403             {
404                 WorkItem childTask = sender as WorkItem;
405                 if (childTask != null)
406                 {
407                     childTask.Completed -= new EventHandler(OnChildCompleted);
408 #if !TIZEN
409                     _suiteResult.AddResult(childTask.Result);
410 #else
411                     #region tronghieu.d - testkit-stub
412                     if (!tsettings.IsSlaveMode && !tsettings.IsManual)
413                         _suiteResult.AddResult(childTask.Result);
414                     else
415                     {
416                         if (!_suiteResult.HasChildren)
417                             _suiteResult.AddResult(childTask.Result);
418                         else
419                         {
420                             ITestResult[] children;
421 #if PARALLEL
422                             var childrenAsConcurrentQueue = _suiteResult.Children as ConcurrentQueue<ITestResult>;
423                             if (childrenAsConcurrentQueue != null)
424                                 children = childrenAsConcurrentQueue.ToArray();
425                             else
426 #endif
427                             {
428                                 var childrenAsIList = Children as IList<ITestResult>;
429                                 if (childrenAsIList != null)
430                                     children = (ITestResult[])childrenAsIList;
431                                 else
432                                     throw new NotSupportedException("cannot add results to Children");
433
434                             }
435                             bool exist = false;
436                             for (int i = 0; i < children.Length; i++)
437                             {
438                                 if (children[i].FullName.Equals(childTask.Result.FullName))
439                                 {
440                                     exist = true;
441                                     break;
442                                 }
443                             }
444                             if (!exist)
445                                 _suiteResult.AddResult(childTask.Result);
446                         }
447                         if (childTask is SimpleWorkItem)
448                         {
449                             string result = childTask.Result.ResultState.Status.ToString();
450                             if (tsettings.IsManual && tsettings.TCResult.Length != 0)
451                             {
452
453                             }
454                             else
455                             {
456                                 result = result.Substring(0, result.Length - 2);
457                                 tsettings.TCResult = result.ToUpper();
458                             }
459                             tsettings.Testcase_ID = childTask.Result.FullName;
460                             tsettings.TCMessage = childTask.Result.Message;
461                             TLogger.Write("##### Result of [" + tsettings.Testcase_ID + "] TC : " + tsettings.TCResult + " With Message: " + tsettings.TCMessage);
462
463                             if (tsettings.IsSlaveMode)
464                             {
465                                 string json = "case_id=" + tsettings.Testcase_ID + "&result=" + tsettings.TCResult + "&msg=" + tsettings.TCMessage + "\n" + childTask.Result.StackTrace;
466                                 if (!tsettings.IsManual)
467                                 {
468                                     tsettings.RequestPOST("commit_result", json);
469                                     tsettings.NextStepRequest();
470                                 }
471                                 else
472                                     tsettings.RequestPOST("commit_manual_result", json);
473                             }
474                         }
475                     }
476                     #endregion
477 #endif
478
479                     if (Context.StopOnError && childTask.Result.ResultState.Status == TestStatus.Failed)
480                         Context.ExecutionStatus = TestExecutionStatus.StopRequested;
481
482                     // Check to see if all children completed
483                     CountDownChildTest();
484                 }
485             }
486         }
487
488         private void CountDownChildTest()
489         {
490             _childTestCountdown.Signal();
491             if (_childTestCountdown.CurrentCount == 0)
492             {
493                 if (Context.ExecutionStatus != TestExecutionStatus.AbortRequested)
494                     PerformOneTimeTearDown();
495
496                 foreach (var childResult in _suiteResult.Children)
497                     if (childResult.ResultState == ResultState.Cancelled)
498                     {
499                         this.Result.SetResult(ResultState.Cancelled, "Cancelled by user");
500                         break;
501                     }
502                 WorkItemComplete();
503             }
504         }
505
506         private static bool IsStaticClass(Type type)
507         {
508             return type.GetTypeInfo().IsAbstract && type.GetTypeInfo().IsSealed;
509         }
510
511         private object cancelLock = new object();
512
513         /// <summary>
514         /// Cancel (abort or stop) a CompositeWorkItem and all of its children
515         /// </summary>
516         /// <param name="force">true if the CompositeWorkItem and all of its children should be aborted, false if it should allow all currently running tests to complete</param>
517         public override void Cancel(bool force)
518         {
519             lock (cancelLock)
520             {
521                 if (_children == null)
522                     return;
523
524                 foreach (var child in _children)
525                 {
526                     var ctx = child.Context;
527                     if (ctx != null)
528                         ctx.ExecutionStatus = force ? TestExecutionStatus.AbortRequested : TestExecutionStatus.StopRequested;
529
530                     if (child.State == WorkItemState.Running)
531                         child.Cancel(force);
532                 }
533             }
534         }
535
536         private string GetCaseID(string TCID)
537         {
538             string[] delimiter = { "." };
539             string[] stringPieces;
540             string ClassName = "";
541             string MethodName = "";
542             stringPieces = TCID.Split(delimiter, StringSplitOptions.None);
543             for (int i = 0; i < stringPieces.Length; i++)
544             {
545                 if (i == stringPieces.Length - 1)
546                     MethodName = stringPieces[i];
547                 else if (i == stringPieces.Length - 2)
548                     ClassName = stringPieces[i];
549             }
550
551             return ClassName + "." + MethodName;
552         }
553
554         #endregion
555     }
556 }