--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using NUnit.Framework;
+using NaGet.SubCommands.SubTask;
+using NaGet.Tasks;
+
+using NaGet.SubCommands;
+
+namespace test_na_get_lib
+{
+ [TestFixture]
+ public class NaGetTaskSet2Test
+ {
+ [Test]
+ public void SubTasks()
+ {
+ IList<string> subTaskMsgs = new string[]{"0", "1", "2"};
+ IList<NaGetSubTask> subTasks = new NaGetSubTask[] {
+ new FunctionalSubTask(null, null),
+ new FunctionalSubTask(null, null),
+ new FunctionalSubTask(null, null),
+ };
+ ATaskSetForTest task = new ATaskSetForTest(subTaskMsgs, subTasks);
+
+ Assert.AreEqual(subTaskMsgs, task.TaskSetNames);
+ }
+
+ [Test]
+ public void NotifyGoToNextSubTask()
+ {
+ ATaskSetForTest task = null;
+ IList<NaGetSubTask> subTasks = null;
+
+ IList<string> subTaskMsgs = new string[]{"0", "1", "2"};
+ int blockCount = 0;
+ Action<object>[] funcs = new Action<object>[] {
+ delegate (object arg) {
+ blockCount ++;
+ Assert.AreEqual(0, task.CurrentTaskSetIndex);
+ Assert.IsTrue(task.Running);
+ Assert.IsTrue(subTasks[0].Running);
+ Assert.IsFalse(subTasks[1].Running);
+ },
+ delegate (object arg) {
+ blockCount ++;
+ Assert.IsTrue(task.Running);
+ Assert.IsTrue(subTasks[0].Done);
+ Assert.IsTrue(subTasks[1].Running);
+ Assert.IsFalse(subTasks[2].Running);
+ },
+ delegate (object arg) {
+ blockCount ++;
+ Assert.IsTrue(task.Running);
+ Assert.IsTrue(subTasks[1].Done);
+ Assert.IsTrue(subTasks[2].Running);
+ }
+ };
+ subTasks = new NaGetSubTask[] {
+ new FunctionalSubTask(funcs[0], null),
+ new FunctionalSubTask(funcs[1], null),
+ new FunctionalSubTask(funcs[2], null),
+ };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ blockCount = 0;
+ task.Run();
+ Assert.IsTrue(task.Done);
+ Assert.IsTrue(subTasks[0].Done);
+ Assert.IsTrue(subTasks[1].Done);
+ Assert.IsTrue(subTasks[2].Done);
+ Assert.AreEqual(3, blockCount);
+ }
+
+ [Test]
+ public void NotifyGoToSubTask()
+ {
+ ATaskSetForTest task = null;
+ IList<NaGetSubTask> subTasks = null;
+
+ IList<string> subTaskMsgs = new string[]{"0", "1"};
+ List<int> blockPass = new List<int>();
+ Action<object>[] funcs = new Action<object>[] {
+ delegate (object arg) {
+ blockPass.Add(0);
+ Assert.AreEqual(0, task.CurrentTaskSetIndex);
+ Assert.IsTrue(task.Running);
+ Assert.IsTrue(subTasks[0].Running);
+ Assert.IsFalse(subTasks[1].Running);
+ },
+ delegate (object arg) {
+ blockPass.Add(1);
+ Assert.IsTrue(task.Running);
+ Assert.IsTrue(subTasks[0].Done);
+ Assert.IsTrue(subTasks[1].Running);
+
+ if (blockPass.Count < 6) {
+ throw new JumpTaskException(0);
+ }
+ }
+ };
+ subTasks = new NaGetSubTask[] {
+ new FunctionalSubTask(funcs[0], null),
+ new FunctionalSubTask(funcs[1], null),
+ };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ blockPass.Clear();
+ task.Run();
+ Assert.IsTrue(task.Done);
+ Assert.AreEqual(new int[]{0, 1, 0, 1, 0, 1}, blockPass.ToArray());
+ }
+
+ [Test]
+ public void TaskEventRaised()
+ {
+ ATaskSetForTest task = null;
+ IList<string> subTaskMsgs = new string[]{"0", "1"};
+ IList<NaGetSubTask> subTasks = null;
+ List<TaskEventArgs> taskEventList = new List<TaskEventArgs>();
+ List<TaskEventArgs> subtaskEventList = new List<TaskEventArgs>();
+
+ Action<ASubTaskForEventTest> subTaskBody = delegate(ASubTaskForEventTest subTask) {
+ subTask.RaiseTaskSetEventExt(TaskEventType.STARTED, "S", -1);
+ subTask.RaiseTaskSetEventExt(TaskEventType.INFO, "I", 0);
+ subTask.RaiseTaskSetEventExt(TaskEventType.PING, "P", 50);
+ subTask.RaiseTaskSetEventExt(TaskEventType.WARNING, "W", 75);
+ subTask.RaiseTaskSetEventExt(TaskEventType.COMPLETED,"C", 100);
+ };
+ subTasks = new NaGetSubTask[] {
+ new ASubTaskForEventTest(subTaskBody),
+ new ASubTaskForEventTest(subTaskBody),
+ };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+
+ EventHandler<TaskEventArgs> taskEventHandler = delegate(object sender, TaskEventArgs e) {
+ Assert.AreEqual(task, sender);
+ taskEventList.Add(e);
+ };
+ EventHandler<TaskEventArgs> subtaskEventHandler = delegate(object sender, TaskEventArgs e) {
+ Assert.AreEqual(subTasks[task.CurrentTaskSetIndex], sender);
+ subtaskEventList.Add(e);
+ };
+
+ // イベントをフックしているときの動作確認
+
+ task.TaskEventRaised += taskEventHandler;
+ task.SubTaskEventRaised += subtaskEventHandler;
+
+ taskEventList.Clear();
+ subtaskEventList.Clear();
+ task.Run();
+ Assert.IsTrue(task.Done);
+
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.STARTED, "", 0), taskEventList[0]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.STARTED_SUBTASK, "0", 0), taskEventList[1]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 0), taskEventList[2]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 25), taskEventList[3]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 37.5f), taskEventList[4]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 50), taskEventList[5]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.COMPLETED_SUBTASK,"0", 50), taskEventList[6]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.STARTED_SUBTASK, "1", 50), taskEventList[7]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 50), taskEventList[8]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 75), taskEventList[9]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 87.5f), taskEventList[10]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, null, 100), taskEventList[11]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.COMPLETED_SUBTASK,"1", 100), taskEventList[12]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.COMPLETED, "", 100), taskEventList[13]);
+ Assert.AreEqual(14, taskEventList.Count);
+
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.STARTED, "S", -1), subtaskEventList[0]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.INFO, "I", 0), subtaskEventList[1]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, "P", 50), subtaskEventList[2]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.WARNING, "W", 75), subtaskEventList[3]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.COMPLETED,"C", 100), subtaskEventList[4]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.STARTED, "S", -1), subtaskEventList[5]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.INFO, "I", 0), subtaskEventList[6]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.PING, "P", 50), subtaskEventList[7]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.WARNING, "W", 75), subtaskEventList[8]);
+ AreSameTaskEventArgs(new TaskEventArgs(TaskEventType.COMPLETED,"C", 100), subtaskEventList[9]);
+ Assert.AreEqual(10, subtaskEventList.Count);
+
+ // イベントをフックしていないときの動作確認
+
+ task.TaskEventRaised -= taskEventHandler;
+ task.SubTaskEventRaised -= subtaskEventHandler;
+
+ taskEventList.Clear();
+ subtaskEventList.Clear();
+ task.Run();
+ Assert.IsTrue(task.Done);
+ }
+
+ [Test]
+ public void Cancel()
+ {
+ ATaskSetForTest task = null;
+ IList<string> subTaskMsgs = new string[]{"0"};
+ IList<NaGetSubTask> subTasks = null;
+
+ Action<ASubTaskForEventTest> subTaskBody = delegate(ASubTaskForEventTest subTask) {
+ subTask.RaiseTaskSetEventExt(TaskEventType.STARTED, "S", 0);
+ Thread.Sleep(50);
+ subTask.RaiseTaskSetEventExt(TaskEventType.COMPLETED,"C", 100);
+ };
+ bool? cancelRetVal = null;
+ ParameterizedThreadStart cancelThread = new ParameterizedThreadStart(
+ delegate (object param) {
+ Thread.Sleep((int) param);
+ cancelRetVal = task.Cancel();
+ }
+ );
+
+ // キャンセル無効なときはキャンセル処理は行われない。
+
+ subTasks = new NaGetSubTask[] { new ASubTaskForEventTest(subTaskBody) };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ task._Cancelable = false;
+ cancelRetVal = null;
+ (new Thread(cancelThread)).Start((object) 10);
+ task.Run();
+ Assert.AreEqual(false, cancelRetVal);
+ Assert.IsTrue(task.Done);
+ Assert.IsFalse(task.Cancelable);
+
+ // すでに終了しているものにはキャンセルはできない
+ Assert.IsFalse(task.Cancel());
+
+ // キャンセル有効なときでキャンセルするとき
+ subTasks = new NaGetSubTask[] { new ASubTaskForEventTest(subTaskBody) };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ task._Cancelable = true;
+ cancelRetVal = null;
+ (new Thread(cancelThread)).Start((object) 10);
+ task.Run();
+ Assert.AreEqual(true, cancelRetVal);
+ Assert.IsTrue(task.Cancelled);
+ Assert.IsFalse(task.Cancelable);
+
+ // すでにキャンセルしているものにはキャンセルはできない
+ Assert.IsFalse(task.Cancel());
+
+ // キャンセルトリガの挙動確認
+ bool cancelBlockPassed = false;
+ subTasks = new NaGetSubTask[] { new ASubTaskForEventTest(subTaskBody) };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ task._Cancelable = true;
+ task.OnCancelCalled += delegate(object arg) {
+ Assert.IsFalse(task.Cancelled);
+ Assert.IsTrue(task.Running);
+ Assert.IsFalse(task.Cancelable);
+ Assert.IsFalse(task.Cancel());
+
+ ASubTaskForEventTest subTask = ((ASubTaskForEventTest) subTasks[0]);
+ Assert.IsFalse(subTask.Cancelled);
+ Assert.IsTrue(subTask.Running);
+ Assert.IsFalse(subTask.Cancelable);
+ Assert.IsFalse(subTask.Cancel());
+
+ cancelBlockPassed = true;
+ };
+ ((ASubTaskForEventTest) subTasks[0])._Cancelable = true;
+ cancelRetVal = null;
+ (new Thread(cancelThread)).Start((object) 10);
+ task.Run();
+ Assert.AreEqual(true, cancelRetVal);
+ Assert.IsTrue(task.Cancelled);
+ Assert.IsFalse(task.Cancelable);
+ Assert.IsTrue(((ASubTaskForEventTest) subTasks[0]).Cancelled);
+ Assert.IsFalse(((ASubTaskForEventTest) subTasks[0]).Cancelable);
+ Assert.IsTrue(cancelBlockPassed);
+ }
+
+ [Test]
+ public void RaiseTaskSetQueryEvent()
+ {
+ IList<string> subTaskMsgs = new string[]{"0"};
+ ATaskSetForTest task = null;
+ Action<object> subTaskBody = null;
+ IList<NaGetSubTask> subTasks = null;
+ bool blockPassed = false;
+
+ subTaskBody = delegate (object arg) {
+ NaGetTaskQueryResult ret;
+ ret = task.RaiseTaskSetQueryEventExt("#1", NaGetTaskQueryResult.CONTINUE);
+ Assert.AreEqual(NaGetTaskQueryResult.CANCELED_AUTOMATICALLY, ret);
+
+ blockPassed = true;
+ };
+ subTasks = new NaGetSubTask[] {
+ new FunctionalSubTask(subTaskBody, null),
+ };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ task.Run();
+ Assert.IsTrue(task.Done);
+ Assert.IsTrue(blockPassed);
+
+
+ subTaskBody = delegate (object arg) {
+ NaGetTaskQueryResult ret;
+ ret = task.RaiseTaskSetQueryEventExt("#1", NaGetTaskQueryResult.CONTINUE);
+ Assert.AreEqual(NaGetTaskQueryResult.CONTINUE, ret);
+ ret = task.RaiseTaskSetQueryEventExt("#2", (NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL));
+ Assert.AreEqual(NaGetTaskQueryResult.RETRY, ret);
+
+ blockPassed = true;
+ };
+ subTasks = new NaGetSubTask[] {
+ new FunctionalSubTask(subTaskBody, null),
+ };
+ task = new ATaskSetForTest(subTaskMsgs, subTasks);
+ task.TaskQueryRaised += delegate (object sender, NaGetTaskQueryArgs e) {
+ if (e.Message == "#1") {
+ Assert.AreEqual(NaGetTaskQueryResult.CONTINUE, e.SelectionFlag);
+ return NaGetTaskQueryResult.CONTINUE;
+ } else {
+ Assert.AreEqual((NaGetTaskQueryResult.RETRY | NaGetTaskQueryResult.CANCEL), e.SelectionFlag);
+ return NaGetTaskQueryResult.RETRY;
+ }
+ };
+ task.Run();
+ Assert.IsTrue(task.Done);
+ Assert.IsTrue(blockPassed);
+ }
+
+ private void AreSameTaskEventArgs(TaskEventArgs expected, TaskEventArgs actual)
+ {
+ string expectedLabel= string.Format("[type={0}, message=\"{1}\", percent={2}%]", expected.Type, expected.TaskMessage, expected.ProgressPercent);
+ string actualLabel = string.Format("[type={0}, message=\"{1}\", percent={2}%]", actual.Type, actual.TaskMessage, actual.ProgressPercent);
+ string failtureMsg = string.Format("Expected: {0}\tBut was: {1}", expectedLabel, actualLabel);
+
+ Assert.AreEqual(expected.Type, actual.Type, failtureMsg);
+ Assert.AreEqual(expected.TaskMessage, actual.TaskMessage, failtureMsg);
+ Assert.AreEqual(expected.ProgressPercent, actual.ProgressPercent, failtureMsg);
+ }
+
+ #region テスト用派生クラス
+
+ private class JumpTaskException : Exception
+ {
+ public int subTaskId = -1;
+
+ /// <summary>
+ /// コンストラクタ
+ /// </summary>
+ /// <param name="id">ジャンプ先のサブタスクID</param>
+ public JumpTaskException(int id)
+ {
+ subTaskId = id;
+ }
+ }
+
+ private class ATaskSetForTest : NaGetTaskSet2
+ {
+ public event Action<object> OnCancelCalled;
+
+ public ATaskSetForTest(IList<string> subTaskMsgs, IList<NaGetSubTask> subTasks)
+ {
+ initSubTask();
+ Assert.IsTrue(subTaskMsgs.Count == subTasks.Count);
+
+ for (int i = 0; i < subTaskMsgs.Count; i++) {
+ registSubTask(subTaskMsgs[i], subTasks[i]);
+ }
+
+ this.onCancelCalled += new Action<object>(delegate (object arg) {
+ if (OnCancelCalled != null) {
+ OnCancelCalled(arg);
+ }
+ });
+ }
+
+ public override void Run()
+ {
+ NotifyStarted();
+ RaiseTaskSetEvent(TaskEventType.STARTED, string.Empty);
+ try {
+ while (hasMoreSubTask) {
+ try {
+ RaiseTaskSetEvent(TaskEventType.STARTED_SUBTASK, currentSubTaskName);
+ currentSubTask.Run();
+ RaiseTaskSetEvent(TaskEventType.COMPLETED_SUBTASK, currentSubTaskName);
+
+ NotifyGoToNextSubTask();
+ } catch (JumpTaskException ex) {
+ NotifyGoToSubTask(ex.subTaskId);
+ }
+ }
+ } finally {
+ if (cancelCalled) {
+ NotifyCancelled();
+ RaiseTaskSetEvent(TaskEventType.CANCELED, string.Empty);
+ } else {
+ NotifyCompleted();
+ RaiseTaskSetEvent(TaskEventType.COMPLETED, string.Empty);
+ }
+ }
+ }
+
+ private bool cancelable = false;
+
+ public override bool Cancelable {
+ get { return cancelable && !cancelCalled && !isCancelled; }
+ }
+
+ public virtual bool _Cancelable {
+ set { cancelable = value; }
+ }
+
+ public NaGetTaskQueryResult RaiseTaskSetQueryEventExt(string message, NaGetTaskQueryResult selection)
+ {
+ return RaiseTaskSetQueryEvent(message, selection);
+ }
+ }
+
+ private class ASubTaskForEventTest : NaGetSubTask
+ {
+ private Action<ASubTaskForEventTest> func = null;
+
+ public ASubTaskForEventTest(Action<ASubTaskForEventTest> func)
+ {
+ this.func = func;
+ }
+
+ public void RaiseTaskSetEventExt(TaskEventType type, string message, float percent)
+ {
+ RaiseTaskSetEvent(type, message, percent);
+ }
+
+ public override void Run()
+ {
+ NotifyStarted();
+ try {
+ this.func(this);
+ } finally {
+ if (cancelCalled) {
+ NotifyCancelled();
+ } else {
+ NotifyCompleted();
+ }
+ }
+ }
+
+ private bool cancelable = false;
+
+ public override bool Cancelable {
+ get { return cancelable && !cancelCalled && !Cancelled; }
+ }
+
+ public virtual bool _Cancelable {
+ set { cancelable = value; }
+ }
+
+ private bool cancelCalled = true;
+
+ public override bool Cancel()
+ {
+ if (Cancelable) {
+ cancelCalled = true;
+ return true;
+ } else {
+ return base.Cancel();
+ }
+ }
+ }
+
+ #endregion
+
+ }
+}