コード例 #1
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
 /// <summary>
 /// Reports execution time details, provided, it is allowed
 /// </summary>
 /// <param name="label">Report entry label</param>
 /// <param name="testItem">Test item</param>
 /// <param name="watch">Watch measuring time</param>
 private void ReportTimeDetail(string label, TestItemBase testItem, Stopwatch watch)
 {
     if (Package.Options.VerboseTestExecutionLogging && watch != null)
     {
         testItem.Log($"{label} {watch.Elapsed.TotalSeconds:####0.####} seconds");
     }
 }
コード例 #2
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
 /// <summary>
 /// Set the state of the specified sub tree
 /// </summary>
 /// <param name="node">Subtree root node</param>
 /// <param name="state">State to set</param>
 /// <param name="except">Optional node to ignore</param>
 public void SetSubTreeState(TestItemBase node, TestState state, TestItemBase except = null)
 {
     if (node == except)
     {
         return;
     }
     node.State = state;
     foreach (var child in node.ChildItems)
     {
         SetSubTreeState(child, state, except);
     }
 }
コード例 #3
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
        /// <summary>
        /// Reports the result of a test or test case
        /// </summary>
        /// <param name="item"></param>
        private void ReportTestResult(TestItemBase item)
        {
            switch (item.State)
            {
            case TestState.Inconclusive:
                item.Log("Test is inconclusive", LogEntryType.Fail);
                break;

            case TestState.Failed:
                item.Log("Test failed", LogEntryType.Fail);
                break;

            case TestState.Success:
                item.Log("Test succeded", LogEntryType.Success);
                break;
            }
        }
コード例 #4
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
        private static void SetTestItemState(TestItemBase root, IEnumerable <TestItemBase> children)
        {
            if (root.State == TestState.Aborted)
            {
                return;
            }
            var childList = children.ToList();

            if (childList.Any(i => i.State == TestState.Aborted || i.State == TestState.Inconclusive))
            {
                root.State = TestState.Inconclusive;
            }
            else if (childList.Any(i => i.State == TestState.Running))
            {
                root.State = TestState.Running;
            }
            else
            {
                root.State = childList.Any(i => i.State == TestState.Failed)
                    ? TestState.Failed
                    : TestState.Success;
            }
        }
コード例 #5
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
        /// <summary>
        /// Handle exceptions during testing
        /// </summary>
        /// <param name="item">Test item that raised the exception</param>
        /// <param name="ex">Exception raised</param>
        private static void HandleException(TestItemBase item, Exception ex)
        {
            if (ex is HandledTestExecutionException)
            {
                throw ex;
            }

            var handled = true;

            item.State = TestState.Aborted;
            string message;

            switch (ex)
            {
            case TaskCanceledException _:
                message = "The test has been cancelled by the user.";
                break;

            case TestExecutionException testEx:
                message = testEx.Message;
                break;

            default:
                message = $"The test engined detected an internal exception: {ex.Message}.";
                handled = false;
                break;
            }

            if (message.Length > 0)
            {
                message += " ";
            }
            message += "Test aborted.";
            item.Log(message, LogEntryType.Fail);
            throw handled ? new HandledTestExecutionException() : throw ex;
        }
コード例 #6
0
 /// <summary>
 /// Initializes the tree node with the specified parent
 /// </summary>
 /// <param name="vm">Parent view model</param>
 /// <param name="parent">Parent node</param>
 protected TestItemBase(TestExplorerToolWindowViewModel vm, TestItemBase parent)
 {
     Parent = parent;
     Vm     = vm ?? throw new ArgumentNullException(nameof(vm));
 }
コード例 #7
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
        /// <summary>
        /// Invokes the code and waits for its completion within the specified
        /// timeout limits.
        /// </summary>
        /// <param name="testItem">Test item that invokes this method</param>
        /// <param name="invokePlan">Invokation plan</param>
        /// <param name="timeout">Timeout in milliseconds</param>
        /// <param name="token">Token to cancel test run</param>
        /// <param name="watch">Optional stopwatch for diagnostics</param>
        /// <returns>True, if code completed; otherwise, false</returns>
        private async Task <bool> InvokeCodeAsync(TestItemBase testItem, InvokePlanBase invokePlan, int timeout, CancellationToken token,
                                                  Stopwatch watch = null)
        {
            if (invokePlan == null)
            {
                return(true);
            }
            if (!(Package.MachineViewModel.SpectrumVm is ISpectrumVmRunCodeSupport runCodeSupport))
            {
                return(false);
            }

            // --- Prepare code invocation
            ExecuteCycleOptions runOptions;
            bool removeFromHalt = false;
            var  spectrumVm     = Package.MachineViewModel.SpectrumVm;
            var  timeoutTacts   = timeout * spectrumVm.BaseClockFrequency
                                  * spectrumVm.ClockMultiplier / 1000;

            if (invokePlan is CallPlan callPlan)
            {
                // --- Obtain Call stub address
                TestSetPlan testSetPlan = null;
                switch (testItem)
                {
                case TestSetItem set:
                    testSetPlan = set.Plan;
                    break;

                case TestItem item:
                    testSetPlan = item.Plan.TestSet;
                    break;

                case TestCaseItem caseItem:
                    testSetPlan = caseItem.Plan.TestBlock.TestSet;
                    break;
                }

                var callStubAddress = testSetPlan?.CallStubAddress ?? DEFAULT_CALL_STUB_ADDRESS;

                // --- Create CALL stub
                Package.MachineViewModel.SpectrumVm.Cpu.Registers.PC = callStubAddress;
                runCodeSupport.InjectCodeToMemory(callStubAddress, new byte[] { 0xCD, (byte)callPlan.Address, (byte)(callPlan.Address >> 8) });
                runOptions = new ExecuteCycleOptions(EmulationMode.UntilExecutionPoint,
                                                     terminationPoint: (ushort)(callStubAddress + 3),
                                                     fastVmMode: true,
                                                     timeoutTacts: timeout * spectrumVm.BaseClockFrequency
                                                     * spectrumVm.ClockMultiplier / 1000);
            }
            else if (invokePlan is StartPlan startPlan)
            {
                spectrumVm.Cpu.Registers.PC = startPlan.Address;
                if (startPlan.StopAddress == null)
                {
                    // --- Start and run until halt
                    runOptions     = new ExecuteCycleOptions(EmulationMode.UntilHalt, fastVmMode: true, timeoutTacts: timeoutTacts);
                    removeFromHalt = true;
                }
                else
                {
                    // --- Start and run until the stop address is reached
                    runOptions = new ExecuteCycleOptions(EmulationMode.UntilExecutionPoint,
                                                         terminationPoint: startPlan.StopAddress.Value,
                                                         fastVmMode: true,
                                                         timeoutTacts: timeoutTacts);
                }
            }
            else
            {
                return(false);
            }

            // --- Prepare the machine to run the code
            var initialTacts = Package.MachineViewModel.SpectrumVm.Cpu.Tacts;
            var machine      = Package.MachineViewModel.Machine;
            var cpuSupport   = Package.MachineViewModel.SpectrumVm.Cpu as IZ80CpuTestSupport;

            cpuSupport.ExecutionFlowStatus.ClearAll();
            cpuSupport.MemoryReadStatus.ClearAll();
            cpuSupport.MemoryWriteStatus.ClearAll();
            Package.MachineViewModel.NoToolRefreshMode = true;

            // --- Start the machine
            machine.Start(runOptions);
            ReportTimeDetail("Start VM:", testItem, watch);

            // --- Waith for completion
            var   completion = machine.CompletionTask;
            await completion;

            // --- Report outcome
            ReportTimeDetail("Complete VM:", testItem, watch);
            var endTacts = Package.MachineViewModel.SpectrumVm.Cpu.Tacts;

            if (Package.Options.TestTStateExecutionLogging)
            {
                testItem.Log($"#of T-States consumed: {endTacts - initialTacts}");
            }

            // --- Check if code ran successfully
            var success = !completion.IsFaulted &&
                          !completion.IsCanceled &&
                          !token.IsCancellationRequested &&
                          machine.ExecutionCycleResult;

            // --- Take care the VM is paused
            await machine.Pause();

            ReportTimeDetail("Pause VM:", testItem, watch);

            // --- If the CPU was halted, it should be removed from this state for the next run
            if (removeFromHalt)
            {
                var cpu = Package.MachineViewModel.SpectrumVm.Cpu as IZ80CpuTestSupport;
                cpu?.RemoveFromHaltedState();
            }

            // --- Handle user cancellation/Timeout
            if (!success)
            {
                if (token.IsCancellationRequested)
                {
                    throw new TaskCanceledException();
                }
                testItem.State = TestState.Aborted;
                testItem.Log("Timeout expired. Test aborted.", LogEntryType.Fail);
            }
            return(success);
        }
コード例 #8
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
        /// <summary>
        /// Executes all tests that start with the specified node
        /// </summary>
        /// <param name="vm">Test explorer view model</param>
        /// <param name="node">Root node of the subtree to run the tests for</param>
        /// <param name="token">Token to stop tests</param>
        public Task RunTestsFromNodeAsync(TestExplorerToolWindowViewModel vm, TestItemBase node, CancellationToken token)
        {
            TestRootItem rootToRun = null;

            switch (node)
            {
            case TestRootItem rootNode:
                // --- Prepare all file nodes to run
                rootNode.TestFilesToRun.Clear();
                foreach (var child in rootNode.ChildItems)
                {
                    if (!(child is TestFileItem fileItem))
                    {
                        continue;
                    }
                    rootNode.TestFilesToRun.Add(fileItem);
                    fileItem.CollectAllToRun();
                }
                rootToRun = rootNode;
                break;

            case TestSetItem setNode:
            {
                // --- Prepare this test set to run
                setNode.TestsToRun.Clear();
                setNode.CollectAllToRun();
                var fileItem = setNode.Parent as TestFileItem;
                var root     = rootToRun = fileItem.Parent as TestRootItem;
                root.TestFilesToRun.Clear();
                root.TestFilesToRun.Add(fileItem);
                fileItem.TestSetsToRun.Clear();
                fileItem.TestSetsToRun.Add(setNode);
                break;
            }

            case TestItem testNode:
            {
                // --- Prepare this test to run
                testNode.TestCasesToRun.Clear();
                testNode.CollectAllToRun();
                var setItem  = testNode.Parent as TestSetItem;
                var fileItem = setItem.Parent as TestFileItem;
                var root     = rootToRun = fileItem.Parent as TestRootItem;
                root.TestFilesToRun.Clear();
                root.TestFilesToRun.Add(fileItem);
                fileItem.TestSetsToRun.Clear();
                fileItem.TestSetsToRun.Add(setItem);
                setItem.TestsToRun.Clear();
                setItem.TestsToRun.Add(testNode);
                break;
            }

            case TestCaseItem caseNode:
            {
                // --- Prepare this test case to run
                var testItem = caseNode.Parent as TestItem;
                var setItem  = testItem.Parent as TestSetItem;
                var fileItem = setItem?.Parent as TestFileItem;
                var root     = rootToRun = fileItem.Parent as TestRootItem;
                root.TestFilesToRun.Clear();
                root.TestFilesToRun.Add(fileItem);
                fileItem.TestSetsToRun.Clear();
                fileItem.TestSetsToRun.Add(setItem);
                setItem.TestsToRun.Clear();
                setItem.TestsToRun.Add(testItem);
                testItem.TestCasesToRun.Clear();
                testItem.TestCasesToRun.Add(caseNode);
                break;
            }
            }

            return(rootToRun != null
                ? ExecuteTestTreeAsync(vm, rootToRun, token)
                : Task.FromResult(0));
        }
コード例 #9
0
ファイル: Z80TestManager.cs プロジェクト: rdacomp/spectnetide
 /// <summary>
 /// Reports the ellapsed test time
 /// </summary>
 /// <param name="label">Report entry label</param>
 /// <param name="testItem">Test item</param>
 /// <param name="watch">Watch measuring time</param>
 private void ReportEllapsedTime(string label, TestItemBase testItem, Stopwatch watch)
 {
     testItem.Log($"{label} execution completed in {watch.Elapsed.TotalSeconds:####0.####} seconds");
 }