Browse Source

Made test of cancellation of engine execution more robust (#1984)

tomatosalat0 9 tháng trước cách đây
mục cha
commit
af0845f384
1 tập tin đã thay đổi với 32 bổ sung7 xóa
  1. 32 7
      Jint.Tests/Runtime/ExecutionConstraintTests.cs

+ 32 - 7
Jint.Tests/Runtime/ExecutionConstraintTests.cs

@@ -35,18 +35,38 @@ public class ExecutionConstraintTests
         Assert.Throws<ExecutionCanceledException>(
             () =>
             {
-                using (var tcs = new CancellationTokenSource())
+                using (var cts = new CancellationTokenSource())
                 using (var waitHandle = new ManualResetEvent(false))
+                using (var cancellationTokenSet = new ManualResetEvent(initialState: false))
                 {
-                    var engine = new Engine(cfg => cfg.CancellationToken(tcs.Token));
-
-                    ThreadPool.QueueUserWorkItem(state =>
+                    var engine = new Engine(cfg => cfg.CancellationToken(cts.Token));
+
+                    /*
+                     * To ensure that the action "threadPoolAction" has actually been called by the ThreadPool
+                     * (which can happen very late, depending on the ThreadPool usage, etc.), the
+                     * "cancellationTokenSet" event will be an indicator for that.
+                     *
+                     * 1. The "cancellationTokenSet" will be set after the "cts" has been cancelled.
+                     * 2. Within the JS, the "test" code will only start as soon as the "cancellationTokenSet"
+                     *    event will be set.
+                     * 3. The cancellationToken and its source has not been used on purpose for this test to
+                     *    not mix "test infrastructure" and "test code".
+                     * 4. To verify that this test still works under heavy load, you can add
+                     *    a "Thread.Sleep(10000)" call anywhere within the "threadPoolAction" action.
+                     */
+
+                    WaitCallback threadPoolAction = _ =>
                     {
                         waitHandle.WaitOne();
-                        tcs.Cancel();
-                    });
+                        cts.Cancel();
+                        cancellationTokenSet.Set();
+                    };
+                    ThreadPool.QueueUserWorkItem(threadPoolAction);
 
                     engine.SetValue("waitHandle", waitHandle);
+                    engine.SetValue("waitForTokenToBeSet", new Action(() => cancellationTokenSet.WaitOne()));
+                    engine.SetValue("mustNotBeCalled", new Action(() =>
+                        throw new InvalidOperationException("A cancellation of the script execution has been requested, but the script did continue to run.")));
                     engine.Evaluate(@"
                             function sleep(millisecondsTimeout) {
                                 var totalMilliseconds = new Date().getTime() + millisecondsTimeout;
@@ -56,11 +76,16 @@ public class ExecutionConstraintTests
 
                             sleep(100);
                             waitHandle.Set();
+                            waitForTokenToBeSet();
+
+                            // Now it is ensured that the cancellationToken has been cancelled. 
+                            // The following JS code execution should get aborted by the engine.
                             sleep(1000);
                             sleep(1000);
                             sleep(1000);
                             sleep(1000);
                             sleep(1000);
+                            mustNotBeCalled();
                         ");
                 }
             }
@@ -376,4 +401,4 @@ myarr[0](0);
             Console.WriteLine(logMessage);
         }
     }
-}
+}