public void Sched_AC_Current_TaskScheduler()
        {
            UnitTestSchedulingContext context = new UnitTestSchedulingContext();
            OrleansTaskScheduler orleansTaskScheduler = orleansTaskScheduler = TestHelper.InitializeSchedulerForTesting(context);
            ActivationTaskScheduler activationScheduler = orleansTaskScheduler.GetWorkItemGroup(context).TaskRunner;

            // RuntimeContext.InitializeThread(masterScheduler);

            mainDone = false;

            var result = new TaskCompletionSource<bool>();

            Task wrapper = null;
            Task finalPromise = null;
            orleansTaskScheduler.QueueWorkItem(new ClosureWorkItem(() =>
            {
                Log(1, "Outer ClosureWorkItem " + Task.CurrentId + " starting");
                Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #0");

                Log(2, "Starting wrapper Task");
                wrapper = Task.Factory.StartNew(() =>
                {
                    Log(3, "Inside wrapper Task Id=" + Task.CurrentId);
                    Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #1");

                    Log(4, "Wrapper Task " + Task.CurrentId + " creating AC chain");
                    Task promise1 = Task.Factory.StartNew(() =>
                    {
                        Log(5, "#1 Inside AC Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #1");
                        SubProcess1(1);
                    });
                    Task promise2 = promise1.ContinueWith((_) =>
                    {
                        Log(6, "#2 Inside AC Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #2");
                        SubProcess1(2);
                    });
                    finalPromise = promise2.ContinueWith((_) =>
                    {
                        Log(7, "#3 Inside final AC Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #3");
                        SubProcess1(3);
                        result.SetResult(true);
                    });
                    finalPromise.Ignore();

                    Log(8, "Wrapper Task Id=" + Task.CurrentId + " sleeping");
                    Thread.Sleep(TimeSpan.FromSeconds(1));

                    Log(9, "Wrapper Task Id=" + Task.CurrentId + " finished");
                });

                Log(10, "Outer ClosureWorkItem Task Id=" + Task.CurrentId + " sleeping");
                Thread.Sleep(TimeSpan.FromSeconds(1));
                Log(11, "Outer ClosureWorkItem Task Id=" + Task.CurrentId + " awake");

                Log(12, "Finished Outer TaskWorkItem Task Id=" + wrapper.Id);
                mainDone = true;
            }), context);

            Log(13, "Waiting for ClosureWorkItem to spawn wrapper Task");
            for (int i = 0; i < 5 * waitFactor; i++)
            {
                if (wrapper != null) break;
                Thread.Sleep(TimeSpan.FromSeconds(1).Multiply(waitFactor));
            }
            Assert.IsNotNull(wrapper, "Wrapper Task was not created");

            Log(14, "Waiting for wrapper Task Id=" + wrapper.Id + " to complete");
            bool finished = wrapper.Wait(TimeSpan.FromSeconds(2 * waitFactor));
            Log(15, "Done waiting for wrapper Task Id=" + wrapper.Id + " Finished=" + finished);
            if (!finished) throw new TimeoutException();
            Assert.IsFalse(wrapper.IsFaulted, "Wrapper Task faulted: " + wrapper.Exception);
            Assert.IsTrue(wrapper.IsCompleted, "Wrapper Task should be completed");

            Log(16, "Waiting for TaskWorkItem to complete");
            for (int i = 0; i < 15 * waitFactor; i++)
            {
                if (mainDone) break;
                Thread.Sleep(1000 * waitFactor);
            }
            Log(17, "Done waiting for TaskWorkItem to complete MainDone=" + mainDone);
            Assert.IsTrue(mainDone, "Main Task should be completed");
            Assert.IsNotNull(finalPromise, "AC chain not created");

            Log(18, "Waiting for final AC promise to complete");
            finalPromise.Wait(TimeSpan.FromSeconds(4 * waitFactor));
            Log(19, "Done waiting for final promise");
            Assert.IsFalse(finalPromise.IsFaulted, "Final AC faulted: " + finalPromise.Exception);
            Assert.IsTrue(finalPromise.IsCompleted, "Final AC completed");
            Assert.IsTrue(result.Task.Result, "Timeout-1");

            Assert.AreNotEqual(0, stageNum1, "Work items did not get executed-1");
            Assert.AreEqual(3, stageNum1, "Work items executed out of order-1");
        }
        public void Sched_Task_SchedulingContext()
        {
            UnitTestSchedulingContext context = new UnitTestSchedulingContext();
            orleansTaskScheduler = TestHelper.InitializeSchedulerForTesting(context);
            ActivationTaskScheduler scheduler = orleansTaskScheduler.GetWorkItemGroup(context).TaskRunner;

            var result = new TaskCompletionSource<bool>();
            Task endOfChain = null;
            int n = 0;

            Task wrapper = new Task(() =>
            {
                CheckRuntimeContext(context);

                // ReSharper disable AccessToModifiedClosure
                Task task1 = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("===> 1a ");
                    CheckRuntimeContext(context);
                    Thread.Sleep(1000); 
                    n = n + 3; 
                    Console.WriteLine("===> 1b");
                    CheckRuntimeContext(context);
                });
                Task task2 = task1.ContinueWith(task =>
                {
                    Console.WriteLine("===> 2");
                    CheckRuntimeContext(context);
                    n = n * 5; 
                });
                Task task3 = task2.ContinueWith(task => 
                {
                    Console.WriteLine("===> 3");
                    n = n / 5;
                    CheckRuntimeContext(context);
                });
                Task task4 = task3.ContinueWith(task => 
                {
                    Console.WriteLine("===> 4"); 
                    n = n - 2;
                    result.SetResult(true);
                    CheckRuntimeContext(context);
                });
                // ReSharper restore AccessToModifiedClosure
                endOfChain = task4.ContinueWith(task =>
                {
                    Console.WriteLine("Done Faulted={0}", task.IsFaulted);
                    CheckRuntimeContext(context);
                    Assert.IsFalse(task.IsFaulted, "Faulted with Exception=" + task.Exception);
                });
            });
            wrapper.Start(scheduler);
            bool ok = wrapper.Wait(TimeSpan.FromSeconds(1));
            if (!ok) throw new TimeoutException();

            Assert.IsFalse(wrapper.IsFaulted, "Wrapper Task Faulted with Exception=" + wrapper.Exception);
            Assert.IsTrue(wrapper.IsCompleted, "Wrapper Task completed");
            bool finished = result.Task.Wait(TimeSpan.FromSeconds(2));
            Assert.IsNotNull(endOfChain, "End of chain Task created successfully");
            Assert.IsFalse(endOfChain.IsFaulted, "Task chain Faulted with Exception=" + endOfChain.Exception);
            Assert.IsTrue(finished, "Wrapper Task completed ok");
            Assert.IsTrue(n != 0, "Work items did not get executed");
            Assert.AreEqual(1, n, "Work items executed out of order");
        }
        public void Sched_Task_Turn_Execution_Order()
        {
            // A unit test that checks that any turn is indeed run till completion before any other turn? 
            // For example, you have a long running main turn and in the middle it spawns a lot of short CWs (on Done promise) and StartNew. 
            // You test that no CW/StartNew runs until the main turn is fully done. And run in stress.

            UnitTestSchedulingContext context = new UnitTestSchedulingContext();
            OrleansTaskScheduler masterScheduler = orleansTaskScheduler = TestHelper.InitializeSchedulerForTesting(context);
            WorkItemGroup workItemGroup = orleansTaskScheduler.GetWorkItemGroup(context);
            ActivationTaskScheduler activationScheduler = workItemGroup.TaskRunner;

            mainDone = false;
            stageNum1 = stageNum2 = 0;

            var result1 = new TaskCompletionSource<bool>();
            var result2 = new TaskCompletionSource<bool>();

            Task wrapper = null;
            Task finalTask1 = null;
            Task finalPromise2 = null;
            masterScheduler.QueueWorkItem(new ClosureWorkItem(() =>
            {
                Log(1, "Outer ClosureWorkItem " + Task.CurrentId + " starting");
                Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #0");

                Log(2, "Starting wrapper Task");
                wrapper = Task.Factory.StartNew(() =>
                {
                    Log(3, "Inside wrapper Task Id=" + Task.CurrentId);
                    Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #1");

                    // Execution chain #1
                    Log(4, "Wrapper Task Id=" + Task.CurrentId + " creating Task chain");
                    Task task1 = Task.Factory.StartNew(() =>
                    {
                        Log(5, "#11 Inside sub-Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #11");
                        SubProcess1(11);
                    });
                    Task task2 = task1.ContinueWith((Task task) =>
                    {
                        Log(6, "#12 Inside continuation Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #12");
                        if (task.IsFaulted) throw task.Exception.Flatten();
                        SubProcess1(12);
                    });
                    Task task3 = task2.ContinueWith(task =>
                    {
                        Log(7, "#13 Inside continuation Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #13");
                        if (task.IsFaulted) throw task.Exception.Flatten();
                        SubProcess1(13);
                    });
                    finalTask1 = task3.ContinueWith(task =>
                    {
                        Log(8, "#14 Inside final continuation Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #14");
                        if (task.IsFaulted) throw task.Exception.Flatten();
                        SubProcess1(14);
                        result1.SetResult(true);
                    });

                    // Execution chain #2
                    Log(9, "Wrapper Task " + Task.CurrentId + " creating AC chain");
                    Task promise2 = Task.Factory.StartNew(() =>
                    {
                        Log(10, "#21 Inside sub-Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #21");
                        SubProcess2(21);
                    });
                    finalPromise2 = promise2.ContinueWith((_) =>
                    {
                        Log(11, "#22 Inside final continuation Task Id=" + Task.CurrentId);
                        Assert.AreEqual(activationScheduler, TaskScheduler.Current, "TaskScheduler.Current #22");
                        SubProcess2(22);
                        result2.SetResult(true);
                    });
                    finalPromise2.Ignore();

                    Log(12, "Wrapper Task Id=" + Task.CurrentId + " sleeping #2");
                    Thread.Sleep(TimeSpan.FromSeconds(1));

                    Log(13, "Wrapper Task Id=" + Task.CurrentId + " finished");
                });

                Log(14, "Outer ClosureWorkItem Task Id=" + Task.CurrentId + " sleeping");
                Thread.Sleep(TimeSpan.FromSeconds(1));
                Log(15, "Outer ClosureWorkItem Task Id=" + Task.CurrentId + " awake");

                Log(16, "Finished Outer ClosureWorkItem Task Id=" + wrapper.Id);
                mainDone = true;
            }), context);

            Log(17, "Waiting for ClosureWorkItem to spawn wrapper Task");
            for (int i = 0; i < 5 * waitFactor; i++)
            {
                if (wrapper != null) break;
                Thread.Sleep(TimeSpan.FromSeconds(1).Multiply(waitFactor));
            }
            Assert.IsNotNull(wrapper, "Wrapper Task was not created");

            Log(18, "Waiting for wrapper Task Id=" + wrapper.Id + " to complete");
            bool finished = wrapper.Wait(TimeSpan.FromSeconds(2 * waitFactor));
            Log(19, "Done waiting for wrapper Task Id=" + wrapper.Id + " Finished=" + finished);
            if (!finished) throw new TimeoutException();
            Assert.IsFalse(wrapper.IsFaulted, "Wrapper Task faulted: " + wrapper.Exception);
            Assert.IsTrue(wrapper.IsCompleted, "Wrapper Task should be completed");

            Log(20, "Waiting for TaskWorkItem to complete");
            for (int i = 0; i < 15 * waitFactor; i++)
            {
                if (mainDone) break;
                Thread.Sleep(1000 * waitFactor);
            }
            Log(21, "Done waiting for TaskWorkItem to complete MainDone=" + mainDone);
            Assert.IsTrue(mainDone, "Main Task should be completed");
            Assert.IsNotNull(finalTask1, "Task chain #1 not created");
            Assert.IsNotNull(finalPromise2, "Task chain #2 not created");

            Log(22, "Waiting for final task #1 to complete");
            bool ok = finalTask1.Wait(TimeSpan.FromSeconds(4 * waitFactor));
            Log(23, "Done waiting for final task #1 complete Ok=" + ok);
            if (!ok) throw new TimeoutException();
            Assert.IsFalse(finalTask1.IsFaulted, "Final Task faulted: " + finalTask1.Exception);
            Assert.IsTrue(finalTask1.IsCompleted, "Final Task completed");
            Assert.IsTrue(result1.Task.Result, "Timeout-1");

            Log(24, "Waiting for final promise #2 to complete");
            finalPromise2.Wait(TimeSpan.FromSeconds(4 * waitFactor));
            Log(25, "Done waiting for final promise #2");
            Assert.IsFalse(finalPromise2.IsFaulted, "Final Task faulted: " + finalPromise2.Exception);
            Assert.IsTrue(finalPromise2.IsCompleted, "Final Task completed");
            Assert.IsTrue(result2.Task.Result, "Timeout-2");

            Assert.AreNotEqual(0, stageNum1, "Work items did not get executed-1");
            Assert.AreEqual(14, stageNum1, "Work items executed out of order-1");
            Assert.AreNotEqual(0, stageNum2, "Work items did not get executed-2");
            Assert.AreEqual(22, stageNum2, "Work items executed out of order-2");
        }