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 subTaskMsgs = new string[]{"0", "1", "2"}; IList 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 subTasks = null; IList subTaskMsgs = new string[]{"0", "1", "2"}; int blockCount = 0; Action[] funcs = new Action[] { 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 subTasks = null; IList subTaskMsgs = new string[]{"0", "1"}; List blockPass = new List(); Action[] funcs = new Action[] { 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 subTaskMsgs = new string[]{"0", "1"}; IList subTasks = null; List taskEventList = new List(); List subtaskEventList = new List(); Action 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 taskEventHandler = delegate(object sender, TaskEventArgs e) { Assert.AreEqual(task, sender); taskEventList.Add(e); }; EventHandler 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 subTaskMsgs = new string[]{"0"}; IList subTasks = null; Action 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.IsTrue(task.Done); // すでにキャンセルしているものにはキャンセルはできない 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(task.Done); Assert.IsTrue(((ASubTaskForEventTest) subTasks[0]).Cancelled); Assert.IsFalse(((ASubTaskForEventTest) subTasks[0]).Cancelable); Assert.IsTrue(cancelBlockPassed); } [Test] public void RaiseTaskSetQueryEvent() { IList subTaskMsgs = new string[]{"0"}; ATaskSetForTest task = null; Action subTaskBody = null; IList 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; /// /// コンストラクタ /// /// ジャンプ先のサブタスクID public JumpTaskException(int id) { subTaskId = id; } } private class ATaskSetForTest : NaGetTaskSet2 { public event Action OnCancelCalled; public ATaskSetForTest(IList subTaskMsgs, IList 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(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 func = null; public ASubTaskForEventTest(Action 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 } }