[2020-02] Bump msbuild to track mono-2019-12 (#19661)
[mono-project.git] / sdks / wasm / incrementalrunner.cs
blobc43816bf0cf39ee87dde35e94bde39fcda9661c6
1 using System;
2 using System.Reflection;
3 using System.Collections;
4 using System.Collections.Generic;
5 using System.Runtime.InteropServices;
6 using System.Runtime.CompilerServices;
7 using System.Diagnostics;
10 using NUnit.Framework;
11 using NUnit.Framework.Internal;
12 using NUnit.Framework.Api;
13 using NUnit.Framework.Internal.Filters;
14 using NUnitLite.Runner;
17 public class MyListener : ITestListener
19 int scount, count;
20 public void TestStarted(ITest test)
22 if (test.IsSuite)
23 ++scount;
24 else
25 ++count;
26 if (!test.IsSuite)
27 Console.WriteLine ("{0} {1}/{2}", test.FullName, scount, count);
30 public void TestFinished(ITestResult result)
34 public void TestOutput(TestOutput testOutput)
39 class AbstractAction {
40 internal TestExecutionContext context, initialCtx;
41 internal TestResult testResult;
42 internal IncrementalTestRunner runner;
43 Test test;
44 AbstractAction parent;
46 internal AbstractAction (Test test, AbstractAction parent, IncrementalTestRunner runner)
48 this.test = test;
49 this.runner = runner;
50 this.parent = parent;
51 this.initialCtx = parent.context;
52 this.testResult = test.MakeTestResult ();
55 internal AbstractAction (Test test, TestExecutionContext initialCtx, IncrementalTestRunner runner)
57 this.test = test;
58 this.runner = runner;
59 this.initialCtx = initialCtx;
60 this.testResult = test.MakeTestResult ();
63 protected void SetupContext () {
64 this.context = new TestExecutionContext (this.initialCtx);
65 this.context.CurrentTest = this.test;
66 this.context.CurrentResult = this.testResult;
67 ((ITestListener)IncrementalTestRunner.listener.GetValue (this.context)).TestStarted (this.test);
68 this.context.StartTime = DateTime.Now;
70 IncrementalTestRunner.setCurrentContext.Invoke (null, new object[] { this.context });
72 long startTicks = Stopwatch.GetTimestamp();
73 runner.finallyDelegate.Set (context, startTicks, testResult);
76 protected void WorkItemComplete ()
78 if (this.parent != null)
79 this.parent.testResult.AddResult (testResult);
81 runner.finallyDelegate.Complete ();
82 // _state = WorkItemState.Complete;
83 // if (Completed != null)
84 // Completed(this, EventArgs.Empty);
88 class TestAction : AbstractAction {
89 TestMethod test;
91 public TestAction (TestMethod test, AbstractAction parent, IncrementalTestRunner runner) : base (test, parent, runner)
93 this.test = test;
96 public void PerformWork () {
97 SetupContext ();
98 try
100 if (IncrementalTestRunner.testSkipCount > 0) {
101 --IncrementalTestRunner.testSkipCount;
102 testResult = ((Test)test).MakeTestResult ();
103 testResult.SetResult (ResultState.Success);
104 } else {
105 testResult = test.MakeTestCommand ().Execute(this.context);
108 finally
110 WorkItemComplete ();
115 class TestSuiteAction : AbstractAction {
116 TestSuite testSuite;
117 List<ITest> children;
119 public TestSuiteAction (TestSuite test, AbstractAction parent, IncrementalTestRunner runner) : base (test, parent, runner)
121 this.testSuite = test;
124 public TestSuiteAction (TestSuite test, TestExecutionContext initialCtx, IncrementalTestRunner runner) : base (test, initialCtx, runner)
126 this.testSuite = test;
129 void EnqueueChildren () {
130 foreach (var t in children) {
131 if (t is TestSuite) {
132 var a = new TestSuiteAction ((TestSuite)t, this, runner);
133 runner.actions.Enqueue (a.PerformWork);
134 } else {
135 var a = new TestAction ((TestMethod)t, this, runner);
136 runner.actions.Enqueue (a.PerformWork);
141 private void SkipChildren ()
143 foreach (var t in children) {
144 TestResult result = ((Test)t).MakeTestResult ();
145 if (testResult.ResultState.Status == TestStatus.Failed)
146 result.SetResult (ResultState.Failure, "TestFixtureSetUp Failed");
147 else
148 result.SetResult (testResult.ResultState, testResult.Message);
149 testResult.AddResult (result);
153 void SkipFixture (ResultState resultState, string message, string stackTrace)
155 testResult.SetResult (resultState, message, stackTrace);
156 SkipChildren ();
159 private string GetSkipReason()
161 return (string)testSuite.Properties.Get(PropertyNames.SkipReason);
164 private string GetProviderStackTrace()
166 return (string)testSuite.Properties.Get(PropertyNames.ProviderStackTrace);
169 public void PerformWork () {
170 SetupContext ();
172 children = new List <ITest> ();
174 if (testSuite.HasChildren) {
175 foreach (Test test in testSuite.Tests) {
176 if (runner.filter.Pass(test))
177 children.Add (test);
181 switch (testSuite.RunState) {
182 default:
183 case RunState.Runnable:
184 case RunState.Explicit:
185 testResult.SetResult (ResultState.Success);
186 PerformOneTimeSetUp ();
188 if (children.Count > 0) {
189 switch (testResult.ResultState.Status)
191 case TestStatus.Passed:
192 EnqueueChildren ();
193 break;
195 case TestStatus.Skipped:
196 case TestStatus.Inconclusive:
197 case TestStatus.Failed:
198 SkipChildren ();
199 break;
203 //all action enqueuing actions have already run, now it's ok to enqueue this.
204 runner.actions.Enqueue (() => runner.actions.Enqueue (this.PerformOneTimeTearDown));
205 break;
207 case RunState.Skipped:
208 SkipFixture (ResultState.Skipped, GetSkipReason(), null);
209 break;
211 case RunState.Ignored:
212 SkipFixture (ResultState.Ignored, GetSkipReason(), null);
213 break;
215 case RunState.NotRunnable:
216 SkipFixture (ResultState.NotRunnable, GetSkipReason(), GetProviderStackTrace());
217 break;
220 //all action enqueuing actions have already run, now it's ok to enqueue this.
221 runner.actions.Enqueue (() => runner.actions.Enqueue (this.WorkItemComplete));
224 private void PerformOneTimeTearDown ()
226 IncrementalTestRunner.setCurrentContext.Invoke (null, new object[] { this.context });
227 testSuite.GetOneTimeTearDownCommand ().Execute(this.context);
230 private void PerformOneTimeSetUp ()
234 testSuite.GetOneTimeSetUpCommand().Execute(this.context);
236 // SetUp may have changed some things
237 this.context.UpdateContext();
239 catch (Exception ex)
241 if (ex is NUnitException || ex is System.Reflection.TargetInvocationException)
242 ex = ex.InnerException;
244 testResult.RecordException (ex);
249 public class IncrementalTestRunner {
250 internal static PropertyInfo listener = typeof (TestExecutionContext).GetProperty ("Listener", BindingFlags.Instance | BindingFlags.NonPublic);
251 internal static MethodInfo setCurrentContext = typeof (TestExecutionContext).GetMethod ("SetCurrentContext", BindingFlags.Static | BindingFlags.NonPublic);
253 IDictionary loadOptions;
254 internal ITestFilter filter = TestFilter.Empty;
255 UnhandledExceptionEventHandler crashHandler;
257 internal FinallyDelegate finallyDelegate;
258 ITestAssemblyBuilder builder;
259 // ITestAssemblyRunner runner;
261 public IncrementalTestRunner () {
262 this.finallyDelegate = new FinallyDelegate();
263 this.builder = new NUnitLiteTestAssemblyBuilder();
264 // this.runner = new NUnitLiteTestAssemblyRunner(new NUnitLiteTestAssemblyBuilder(), finallyDelegate);
266 this.loadOptions = new Hashtable ();
270 TestSuite testSuite;
272 public void Add (Assembly assembly) {
273 testSuite = builder.Build (assembly, loadOptions);
274 if (testSuite == null)
275 throw new Exception ("Could not load " + assembly);
276 // if (!runner.Load (assembly, loadOptions))
277 // throw new Exception ("Could not load " + assembly);
280 public void Exclude (string categories) {
281 var excludeFilter = new NotFilter (new SimpleCategoryExpression(categories).Filter);
282 filter = And (filter, excludeFilter);
285 public void RunOnly (string testName) {
286 var nameFilter = new SimpleNameFilter (testName);
287 filter = And (filter, nameFilter);
290 internal Queue<Action> actions = new Queue<Action> ();
291 int test_step_count;
292 string test_status;
293 internal static int testSkipCount;
295 public string Status {
296 get { return test_status; }
299 TestSuiteAction rootAction;
300 void QueueActions (TestSuite suite) {
301 TestExecutionContext context = new TestExecutionContext ();
302 if (this.loadOptions.Contains ("WorkDirectory"))
303 context.WorkDirectory = (string)this.loadOptions ["WorkDirectory"];
304 else
305 context.WorkDirectory = Environment.CurrentDirectory;
307 listener.SetValue (context, new MyListener ());
308 rootAction = new TestSuiteAction (suite, context, this);
309 actions.Enqueue (rootAction.PerformWork);
312 public void SkipFirst (int tsc) {
313 testSkipCount = tsc;
316 public void Start (int step) {
317 if (actions.Count > 0)
318 throw new Exception ("Test already started");
320 crashHandler = new UnhandledExceptionEventHandler(TopLevelHandler);
321 AppDomain.CurrentDomain.UnhandledException += crashHandler;
323 this.test_step_count = step;
324 QueueActions (testSuite);
327 public bool Step () {
328 int remaining = test_step_count;
330 while (actions.Count > 0 && remaining > 0) {
331 var a = actions.Dequeue ();
332 a ();
333 --remaining;
336 if (actions.Count == 0) {
337 var res = new ResultReporter (rootAction.testResult, Console.Out);
338 if ((res.Summary.FailureCount + res.Summary.ErrorCount) > 0)
339 test_status = "FAIL";
340 else
341 test_status = "PASS";
343 res.ReportResults ();
344 return false;
347 return true;
350 void TopLevelHandler(object sender, UnhandledExceptionEventArgs e)
352 // Make sure that the test harness knows this exception was thrown
353 if (finallyDelegate != null)
354 finallyDelegate.HandleUnhandledExc(e.ExceptionObject as Exception);
357 static ITestFilter And (ITestFilter filter, ITestFilter other) {
358 if (filter.IsEmpty)
359 filter = other;
360 else if (filter is AndFilter)
361 ((AndFilter)filter).Add(other);
362 else
363 filter = new AndFilter(filter, other);
364 return filter;