示例#1
0
        /// <summary>
        /// Gets a copy of the AppSettings with a standard set of formatting options (e.g. lower
        /// case for everything).
        /// </summary>
        /// <returns>New app settings object.</returns>
        private AppSettings CreateNormalizedSettings()
        {
            AppSettings settings = AppSettings.Global.GetCopy();

            // Override all asm formatting options.  We can ignore ShiftBeforeAdjust and the
            // pseudo-op names because those are set by the generators.
            settings.SetBool(AppSettings.FMT_UPPER_HEX_DIGITS, false);
            settings.SetBool(AppSettings.FMT_UPPER_OP_MNEMONIC, false);
            settings.SetBool(AppSettings.FMT_UPPER_PSEUDO_OP_MNEMONIC, false);
            settings.SetBool(AppSettings.FMT_UPPER_OPERAND_A, true);
            settings.SetBool(AppSettings.FMT_UPPER_OPERAND_S, true);
            settings.SetBool(AppSettings.FMT_UPPER_OPERAND_XY, false);
            settings.SetBool(AppSettings.FMT_ADD_SPACE_FULL_COMMENT, false);

            // Don't show the assembler ident line.  You can make a case for this being
            // mandatory, since the generated code is only guaranteed to work with the
            // assembler for which it was targeted, but I expect we'll quickly get to a
            // place where we don't have to work around assembler bugs, and this will just
            // become a nuisance.
            settings.SetBool(AppSettings.SRCGEN_ADD_IDENT_COMMENT, false);

            // Don't break lines with long labels.  That way we can redefine "long"
            // without breaking our tests.  (This is purely cosmetic.)
            settings.SetBool(AppSettings.SRCGEN_LONG_LABEL_NEW_LINE, false);

            // This could be on or off.  Off seems less distracting.
            settings.SetBool(AppSettings.SRCGEN_SHOW_CYCLE_COUNTS, false);

            // Disable label localization.  We want to be able to play with this a bit
            // without disrupting all the other tests.  Use a test-only feature to enable
            // it for the localization test.
            settings.SetBool(AppSettings.SRCGEN_DISABLE_LABEL_LOCALIZATION, true);

            IEnumerator <AssemblerInfo> iter = AssemblerInfo.GetInfoEnumerator();

            while (iter.MoveNext())
            {
                AssemblerInfo.Id asmId     = iter.Current.AssemblerId;
                AssemblerConfig  curConfig =
                    AssemblerConfig.GetConfig(settings, asmId);
                AssemblerConfig defConfig =
                    AssemblerInfo.GetAssembler(asmId).GetDefaultConfig();

                // Merge the two together.  We want the default assembler config for most
                // things, but the executable path from the current config.
                defConfig.ExecutablePath = curConfig.ExecutablePath;

                // Write it into the test settings.
                AssemblerConfig.SetConfig(settings, asmId, defConfig);
            }

            return(settings);
        }
示例#2
0
        private void RunAssemblerButton_Click(object sender, RoutedEventArgs e)
        {
            IAssembler asm = AssemblerInfo.GetAssembler(mSelectedAssemblerId);

            if (asm == null)
            {
                Debug.WriteLine("Unable to get assembler for " + mSelectedAssemblerId);
                return;
            }

            asm.Configure(mGenerationResults, mWorkDirectory);

            AsmWorker    aw  = new AsmWorker(asm);
            WorkProgress dlg = new WorkProgress(this, aw, true);

            dlg.ShowDialog();
            //Debug.WriteLine("Dialog returned: " + dlg.DialogResult);
            if (dlg.DialogResult != true)
            {
                // Canceled, or failed to even run the assembler.
                return;
            }

            AssemblerResults results = aw.Results;

            if (results == null)
            {
                Debug.WriteLine("Dialog returned OK, but no assembler results found");
                Debug.Assert(false);
                return;
            }

            StringBuilder sb =
                new StringBuilder(results.Stdout.Length + results.Stderr.Length + 200);

            sb.Append(results.CommandLine);
            sb.Append("\r\n");
            sb.AppendFormat("ExitCode={0} - ", results.ExitCode);
            if (results.ExitCode == 0)
            {
                FileInfo fi = new FileInfo(results.OutputPathName);
                if (!fi.Exists)
                {
                    MessageBox.Show(this, Res.Strings.ASM_OUTPUT_NOT_FOUND,
                                    Res.Strings.ASM_MISMATCH_CAPTION,
                                    MessageBoxButton.OK, MessageBoxImage.Error);
                    sb.Append(Res.Strings.ASM_MATCH_FAILURE);
                }
                else if (!CommonUtil.FileUtil.CompareBinaryFile(mProject.FileData,
                                                                results.OutputPathName, out int offset, out byte fileVal))
                {
                    if (fi.Length != mProject.FileData.Length &&
                        offset == fi.Length || offset == mProject.FileData.Length)
                    {
                        // The files matched up to the point where one ended.
                        string msg = string.Format(Res.Strings.ASM_MISMATCH_LENGTH_FMT,
                                                   fi.Length, mProject.FileData.Length);
                        MessageBox.Show(msg, Res.Strings.ASM_MISMATCH_CAPTION,
                                        MessageBoxButton.OK, MessageBoxImage.Error);
                        sb.Append(msg);
                    }
                    else
                    {
                        string msg = string.Format(Res.Strings.ASM_MISMATCH_DATA_FMT,
                                                   offset, fileVal, mProject.FileData[offset]);
                        MessageBox.Show(msg, Res.Strings.ASM_MISMATCH_CAPTION,
                                        MessageBoxButton.OK, MessageBoxImage.Error);
                        sb.Append(msg);
                    }
                }
                else
                {
                    sb.Append(Res.Strings.ASM_MATCH_SUCCESS);
                }
            }
示例#3
0
        /// <summary>
        /// Generates source code for the specified test case, assembles it, and compares
        /// the output of both steps to expected values.  The process is repeated for every
        /// known assembler.
        ///
        /// If an assembler is known but not configured, the assembly step is skipped, and
        /// does not count as a failure.
        /// </summary>
        /// <param name="pathName">Full path to test case.</param>
        /// <returns>True if all assemblers worked as expected.</returns>
        private bool GenerateAndAssemble(string pathName)
        {
            ReportProgress(Path.GetFileName(pathName) + "...\r\n");

            // Create DisasmProject object, either as a new project for a plain data file,
            // or from a project file.
            DisasmProject project = InstantiateProject(pathName,
                                                       out FileLoadReport projectLoadReport);

            if (project == null)
            {
                ReportFailure();
                return(false);
            }

            int testNum = GetTestNum(pathName);

            // Create a temporary directory to work in.
            string workDir = CreateWorkDirectory(pathName);

            if (string.IsNullOrEmpty(workDir))
            {
                ReportFailure();
                project.Cleanup();
                return(false);
            }

            AppSettings settings = CreateNormalizedSettings();

            ApplyProjectSettings(settings, project);

            // Iterate through all known assemblers.
            bool didFail = false;

            foreach (AssemblerInfo.Id asmId in
                     (AssemblerInfo.Id[])Enum.GetValues(typeof(AssemblerInfo.Id)))
            {
                if (asmId == AssemblerInfo.Id.Unknown)
                {
                    continue;
                }

                string    fileName = Path.GetFileName(pathName);
                TaskTimer timer    = new TaskTimer();
                timer.StartTask("Full Test Duration");

                // Create results object and add it to the list.  We'll add stuff to it for
                // as far as we get.
                GenTestResults results = new GenTestResults(pathName, asmId);
                mResults.Add(results);
                results.ProjectLoadReport = projectLoadReport;

                // Generate source code.
                ReportProgress("  " + asmId.ToString() + " generate...");
                IGenerator gen = AssemblerInfo.GetGenerator(asmId);
                if (gen == null)
                {
                    ReportErrMsg("generator unavailable");
                    ReportProgress("\r\n");
                    //didFail = true;
                    continue;
                }
                timer.StartTask("Generate Source");
                gen.Configure(project, workDir, fileName,
                              AssemblerVersionCache.GetVersion(asmId), settings);
                List <string> genPathNames = gen.GenerateSource(mWorker);
                timer.EndTask("Generate Source");
                if (mWorker.CancellationPending)
                {
                    // The generator will stop early if a cancellation is requested.  If we
                    // don't break here, the compare function will report a failure, which
                    // isn't too problematic but looks funny.
                    break;
                }

                ReportProgress(" verify...");
                timer.StartTask("Compare Source to Expected");
                bool match = CompareGeneratedToExpected(pathName, genPathNames);
                timer.EndTask("Compare Source to Expected");
                if (match)
                {
                    ReportSuccess();
                    results.GenerateOkay = true;
                }
                else
                {
                    ReportFailure();
                    didFail = true;

                    // The fact that it doesn't match the expected sources doesn't mean it's
                    // invalid.  Go ahead and try to build it.
                    //continue;
                }

                // Assemble code.
                ReportProgress("  " + asmId.ToString() + " assemble...");
                IAssembler asm = AssemblerInfo.GetAssembler(asmId);
                if (asm == null)
                {
                    ReportErrMsg("assembler unavailable");
                    ReportProgress("\r\n");
                    continue;
                }

                timer.StartTask("Assemble Source");
                asm.Configure(genPathNames, workDir);
                AssemblerResults asmResults = asm.RunAssembler(mWorker);
                timer.EndTask("Assemble Source");
                if (asmResults == null)
                {
                    ReportErrMsg("unable to run assembler");
                    ReportFailure();
                    didFail = true;
                    continue;
                }
                if (asmResults.ExitCode != 0)
                {
                    ReportErrMsg("assembler returned code=" + asmResults.ExitCode);
                    ReportFailure();
                    didFail = true;
                    continue;
                }

                results.AsmResults = asmResults;

                ReportProgress(" verify...");
                timer.StartTask("Compare Binary to Expected");
                FileInfo fi = new FileInfo(asmResults.OutputPathName);
                if (!fi.Exists)
                {
                    // This can happen if the assembler fails to generate output but doesn't
                    // report an error code (e.g. Merlin 32 in certain situations).
                    ReportErrMsg("asm output missing");
                    ReportFailure();
                    didFail = true;
                    continue;
                }
                else if (fi.Length != project.FileData.Length)
                {
                    ReportErrMsg("asm output mismatch: length is " + fi.Length + ", expected " +
                                 project.FileData.Length);
                    ReportFailure();
                    didFail = true;
                    continue;
                }
                else if (!FileUtil.CompareBinaryFile(project.FileData, asmResults.OutputPathName,
                                                     out int badOffset, out byte badFileVal))
                {
                    ReportErrMsg("asm output mismatch: offset +" + badOffset.ToString("x6") +
                                 " has value $" + badFileVal.ToString("x2") + ", expected $" +
                                 project.FileData[badOffset].ToString("x2"));
                    ReportFailure();
                    didFail = true;
                    continue;
                }
                timer.EndTask("Compare Binary to Expected");

                // Victory!
                results.AssembleOkay = true;
                ReportSuccess();

                timer.EndTask("Full Test Duration");
                results.Timer = timer;

                // We don't scrub the directory on success at this point.  We could, but we'd
                // need to remove only those files associated with the currently assembler.
                // Otherwise, a failure followed by a success would wipe out the unsuccessful
                // temporaries.
            }

            // If something failed, leave the bits around for examination.  Otherwise, try to
            // remove the directory and all its contents.
            if (!didFail && !RetainOutput)
            {
                ScrubWorkDirectory(workDir, testNum);
                RemoveWorkDirectory(workDir);
            }

            project.Cleanup();
            return(!didFail);
        }