示例#1
0
 /// <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
        /// <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;
            }
        }
示例#3
0
        /// <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;
        }
示例#4
0
        /// <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);
        }
示例#5
0
 /// <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");
 }