Example #1
0
    /// <summary>
    /// Gets visual studio default format for specific configuration.
    /// </summary>
    /// <param name="confName">configuration name (E.g. Debug|Win32) for which to query, null if use this configuration</param>
    /// <returns>Default value</returns>
    public EDebugInformationFormat getDebugInformationFormatDefault(String confName)
    {
        String platform;

        if (confName != null)
        {
            platform = confName.Split('|')[1];
        }
        else
        {
            platform = this.confName.Split('|')[1];
        }

        if (platform.ToLower() == "win32" || platform == "x86")
        {
            return(EDebugInformationFormat.EditAndContinue);
        }

        if (platform == "x64")
        {
            return(EDebugInformationFormat.ProgramDatabase);
        }

        // Android projects does not have "default" configuration, so they needs to be specified anyway.
        if (platform == "ARM" || platform == "ARM64")
        {
            return(EDebugInformationFormat.Invalid);
        }

        if (SolutionProjectBuilder.isDeveloper())
        {
            // Default needs to be checked from Visual studio.
            Debugger.Break();
        }

        return(EDebugInformationFormat.ProgramDatabase);
    }
Example #2
0
    override public void InvokeTest(bool isLastMethod, TestResults localTestResults)
    {
        String testsDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Tests");

        if (diffExe == null)
        {
            //
            // We use TortoiseMerge.exe if we have one (can copy paste changes in merge tool itself)
            //
            diffExe = @"C:\Program Files\TortoiseSVN\bin\TortoiseMerge.exe";
            bool bTortoiseDiff = true;

            if (!File.Exists(diffExe))
            {
                diffExe       = Path.Combine(testsDir, "ExamDiff.exe");
                bTortoiseDiff = false;
            }

            if (!File.Exists(diffExe))
            {
                throw new Exception("Diff tool does not exists '" + diffExe + "'");
            }

            //
            // Launch diff viewer.
            //
            if (!bTortoiseDiff)
            {
                // Change background color of comparison.
                RegistryKey key = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.CurrentUser, RegistryView.Registry64).CreateSubKey(@"Software\PrestoSoft\ExamDiff\Settings");
                if (key != null && key.GetValue("TestInitialized") as String != "1")
                {
                    key.SetValue("TestInitialized", "1");
                    key.SetValue("Back Changed Color", 0xb7b7ff);
                }
            }
        }

        int    error     = 0;
        String test      = sourceCodePath;
        String dir       = Path.GetDirectoryName(test);
        String logActual = "";

        UpdateInfo.lastUpdateInfo = null;
        UpdateInfo.bTesting       = true;

        //
        // We launch test via direct Invoke currently - it's just simpler to debug if there is a problem,
        // but this requires initializing static global variables back to default state.
        //
        // I've left here ExecCmd - but main problem is that even MessageBox shown from console application
        // is closed without any clear reason.
        //
        bool   bIsBat   = Path.GetExtension(test).ToLower() == ".bat";
        String toolName = "syncProj";

        if (bIsBat)
        {
            // Requires Android stuff preinstalled, we want to focus on syncProj testing.
            String[] excludeBats = new string[] { "gradlew", "getsigninfo" };
            if (Array.IndexOf(excludeBats, Path.GetFileNameWithoutExtension(test).ToLower()) != -1)
            {
                return;
            }

            error    = ExecCmd(test + " -x", ref logActual);
            toolName = "Batch";
        }
        else
        {
            ConsoleWriter cw = new ConsoleWriter();
            SolutionProjectBuilder.resetStatics();
            var co = Console.Out;
            Console.SetOut(cw);
            error = syncProj.Main(new String[] { "-x", "-p", "out_", test });

            bool bIsScript = Path.GetExtension(test).ToLower() == ".cs";
            if (bIsScript)  // By default it's executed by default destructor, here we need to launch it manually.
            {
                SolutionProjectBuilder.SaveGenerated();
            }

            cw.Flush();
            Console.SetOut(co);
            logActual = cw.sb.ToString();
        }

        String errMsg;

        // Add command line tool error code into log itself.
        if (error == 0)
        {
            errMsg = toolName + " exited with no error";
        }
        else
        {
            errMsg = toolName + " exited with ERROR: " + error;
        }

        logActual = errMsg + "\r\n" + logActual;

        Regex         reOutFile   = new Regex("\\\\" + Regex.Escape("out_" + Path.GetFileNameWithoutExtension(test)) + "(\\.|_cs)");
        List <String> verifyFiles = Directory.GetFiles(dir, "*", SearchOption.AllDirectories).Where(x => reOutFile.Match(x).Success).ToList();

        verifyFiles.Insert(0, test + ".accepted_log.txt");
        Dictionary <String, bool> testedFiles = new Dictionary <string, bool>();

        //
        //  Collect all information about which files syncProj tried to save or check if they are up-to-date.
        //
        if (UpdateInfo.lastUpdateInfo != null)
        {
            verifyFiles.AddRange(UpdateInfo.lastUpdateInfo.filesUpdated);
            verifyFiles.AddRange(UpdateInfo.lastUpdateInfo.filesUpToDate);
        }

        //
        // iFile == 0 only for output of command line execution - rest of files are actually compared files.
        //
        for (int iFile = 0; iFile < verifyFiles.Count; iFile++)
        {
            String file = verifyFiles[iFile];

            // Pick up only two last file extensions. test.sln.accepted_log.txt => "test.sln" + ".accepted_log.txt"
            var    re = Regex.Match(file, @"(.*\\[^\\]+?)(\.[^\\\.]*\.[^\\\.]*)$");
            String fPathBase;
            String dblExt;
            String ext = Path.GetExtension(file).ToLower();

            if (re.Success)
            {
                fPathBase = re.Groups[1].ToString();
                dblExt    = re.Groups[2].ToString().ToLower();
            }
            else
            {
                fPathBase = Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file);
                dblExt    = Path.GetExtension(file).ToLower();
            }

            String logAcceptedFile = "";
            String logActualFile   = "";

            if (ext == ".accepted")
            {
                // file which is expected to be generated
                logAcceptedFile = file;
                logActualFile   = file.Substring(0, file.Length - ext.Length);
            }
            else
            {
                if (dblExt == ".accepted_log.txt")
                {
                    // tool output
                    logAcceptedFile = file;
                    logActualFile   = fPathBase + ".actual_log.txt";
                }
                else
                {
                    // actual file generated
                    logAcceptedFile = file + ".accepted";
                    logActualFile   = file;
                }
            } //if-else

            if (testedFiles.ContainsKey(logAcceptedFile))
            {
                continue;
            }

            testedFiles[logAcceptedFile] = true;

            String testNameShort = test.Substring(testsDir.Length + 1);

            if (iFile != 0)
            {
                testNameShort += " for file '" + Path.GetFileName(file) + "'";
            }

            //
            //  Until we have decision made by developer.
            //
            while (true)
            {
                String logAccepted = "";
                String errorMessage;
                bool   bAcceptedFileExists = File.Exists(logAcceptedFile);

                if (!bAcceptedFileExists)
                {
                    // First time acceptance
                    errorMessage = "Test results for '" + testNameShort + "' does not yet exists.";
                }
                else
                {
                    // Second time acceptance
                    errorMessage = "Test on '" + testNameShort + "' failed, results differ.";
                    logAccepted  = File.ReadAllText(logAcceptedFile);
                }

                if (iFile != 0)
                {
                    logActual = File.ReadAllText(logActualFile);
                }

                if (logActual == logAccepted)
                {
                    localTestResults.files++;
                    break;
                }

                DialogResult dr = MessageBox.Show(
                    errorMessage + "\r\n" +
                    "\r\n" +
                    "Press:\r\n" +
                    "- 'Yes' to accept current changes\r\n" +
                    "- 'No' to view full file comparison\r\n" +
                    "- 'Cancel' to abort and fix code\r\n"
                    , "Test failed - " + testNameShort, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button3);

                if (dr == DialogResult.Cancel)
                {
                    throw new OperationCanceledException("Testing aborted");
                }

                // If first file (console output), save log file before performing move
                if (iFile == 0)
                {
                    File.WriteAllText(logActualFile, logActual);
                }

                if (dr == DialogResult.Yes)
                {
                    File.Copy(logActualFile, logAcceptedFile, true);
                }
                else
                {
                    if (!bAcceptedFileExists)   // Just a dummy file so comparison tool would not mind.
                    {
                        File.WriteAllText(logAcceptedFile, "");
                    }

                    Process.Start(diffExe, "\"" + logAcceptedFile + "\" \"" + logActualFile + "\"").WaitForExit();
                    logActual = File.ReadAllText(logActualFile);
                } //if-else
            }     //while (file is not the same)

            if (File.Exists(logActualFile))
            {
                File.Delete(logActualFile);
            }
        } //for file
    }
Example #3
0
    /// <summary>
    /// Saves solution into .sln file. Where to save is defined by path.
    /// </summary>
    /// <param name="_path">path to .sln, null if use from 'path' variable.</param>
    /// <param name="uinfo">Update information</param>
    public void SaveSolution(UpdateInfo uinfo, String _path = null)
    {
        String slnPath = _path;

        if (_path == null)
        {
            slnPath = path;
        }

        //
        //  For all projects which does not have uuid, we generated uuid based on project name.
        //
        SolutionProjectBuilder.externalproject(null);   // Release any active project if we have one.

        if (fileFormatVersion >= 2017 && String.IsNullOrEmpty(SolutionGuid))
        {
            SolutionProjectBuilder.uuid(name + "_solution" /* Add some uniqueness - just not to collise with project guids. */);
        }

        foreach (Project p in projects)
        {
            if (String.IsNullOrEmpty(p.ProjectGuid))
            {
                SolutionProjectBuilder.m_project = p;
                SolutionProjectBuilder.uuid(p.ProjectName);
                SolutionProjectBuilder.m_project = null;
            }
        } //foreach

        StringBuilder o = new StringBuilder();

        o.AppendLine();

        int verTag = fileFormatVersion;

        if (verTag == 0)
        {
            verTag = 2015;
        }

        String formatVersion = "12.00";

        if (verTag <= 2010)
        {
            formatVersion = "11.00";
        }

        o.AppendLine("Microsoft Visual Studio Solution File, Format Version " + formatVersion);

        int verTag2;

        switch (verTag)
        {
        case 2015: verTag2 = 14; break;

        case 2017: verTag2 = 15; break;

        case 2019: verTag2 = 16; break;

        default:
            // Try to predict the future here...
            verTag2 = 14 + (verTag - 2015) / 2;
            break;
        }

        if (verTag2 >= 16)
        {
            o.AppendLine("# Visual Studio Version " + verTag2.ToString());
        }
        else
        {
            o.AppendLine("# Visual Studio " + verTag2.ToString());
        }

        // Must be specified, otherwise Visual studio will try to save project after load.
        if (fileFormatVersion >= 2017)
        {
            // Those numbers are pretty ugly to hardcode, but no other choice at the moment.
            String ver = VisualStudioVersion;
            if (ver == null)
            {
                switch (fileFormatVersion)
                {
                case 2017: ver = "15.0.28307.136"; break;

                default:
                case 2019: ver = "16.0.28315.86"; break;
                }
            }

            o.AppendLine("VisualStudioVersion = " + ver);
        }

        // Must be specified, otherwise Visual studio will try to save project after load.
        if (fileFormatVersion >= 2015)
        {
            String ver = MinimumVisualStudioVersion;
            if (ver == null)
            {
                ver = "10.0.40219.1";
            }
            o.AppendLine("MinimumVisualStudioVersion = " + ver);
        }

        // Visual studio 2015 itself dumps also VisualStudioVersion & MinimumVisualStudioVersion - but we cannot support it, as it's targetted per visual studio toolset version.

        //
        // Dump projects.
        //
        foreach (Project p in projects)
        {
            o.AppendLine("Project(\"" + p.ProjectHostGuid + "\") = \"" + p.ProjectName + "\", \"" + p.getRelativePath() + "\", \"" + p.ProjectGuid.ToUpper() + "\"");

            //
            // Dump project dependencies.
            //
            if (p.ProjectDependencies != null)
            {
                o.AppendLine("	ProjectSection(ProjectDependencies) = postProject");
                foreach (String depProjName in p.ProjectDependencies)
                {
                    String guid = null;

                    // Dependency specified by {guid}
                    if (SolutionProjectBuilder.guidMatcher.Match(depProjName).Success)
                    {
                        guid = depProjName;
                    }
                    else
                    {
                        // Dependency specified by project name
                        Project dproj = projects.Where(x => x.ProjectName == depProjName).FirstOrDefault();
                        if (dproj != null)
                        {
                            guid = dproj.ProjectGuid.ToUpper();
                        }
                    }

                    if (guid != null)
                    {
                        o.AppendLine("		"+ guid + " = " + guid);
                    }
                }
                o.AppendLine("	EndProjectSection");
            } //if

            o.AppendLine("EndProject");
        }


        List <String> sortedConfs = Project.getSortedConfigurations(configurations, false, null, true);

        //
        // Dump configurations.
        //
        o.AppendLine("Global");
        o.AppendLine("	GlobalSection(SolutionConfigurationPlatforms) = preSolution");
        foreach (String cfg in sortedConfs)
        {
            o.AppendLine("		"+ cfg + " = " + cfg);
        }
        o.AppendLine("	EndGlobalSection");


        //
        // Dump solution to project configuration mapping and whether or not to build specific project.
        //
        o.AppendLine("	GlobalSection(ProjectConfigurationPlatforms) = postSolution");
        foreach (Project p in projects)
        {
            if (p.IsSubFolder())        // If sub-folder no need to list it here.
            {
                continue;
            }

            List <String> projConfs     = p.getConfigurationNames();
            List <String> projPlatforms = p.getPlatforms();

            foreach (String conf in sortedConfs)
            {
                int    iConf      = configurations.IndexOf(conf);
                String mappedConf = conf;

                bool bPeformBuild   = true;
                bool?bPerformDeploy = null;

                if (p.bIsPackagingProject)
                {
                    bPerformDeploy = true;
                }

                if (p.slnConfigurations != null && iConf < p.slnConfigurations.Count)
                {
                    // Mapped configuration item is specified.
                    mappedConf = p.slnConfigurations[iConf];
                }
                else
                {
                    if (p.bDefinedAsExternal)
                    {
                        // Hack - assume one to one mapping for timebeing.
                        mappedConf = conf;
                    }
                    else
                    {
                        //
                        // Try to map configuration by ourselfs. Map x86 to Win32 automatically.
                        //
                        if (!p.configurations.Contains(conf))
                        {
                            String[] confPlat = conf.Split('|');

                            if (projConfs.Contains(confPlat[0]) && confPlat[1] == "x86" && projPlatforms.Contains("Win32"))
                            {
                                mappedConf = confPlat[0] + '|' + "Win32";
                            }
                            else
                            {
                                // Configuration cannot be mapped (E.g. Solution has "Debug|Arm", project supports only "Debug|Win32".
                                // We disable project build, but try to map configuration anyway - otherwise Visual Studio will
                                // try to save solution by itself.
                                bPeformBuild   = false;
                                bPerformDeploy = null;

                                mappedConf = p.configurations.Where(x => x.StartsWith(confPlat[0])).FirstOrDefault();
                                if (mappedConf == null)
                                {
                                    mappedConf = p.configurations[0];
                                }
                            } //if-else
                        }     //if
                    }
                }

                if (p.slnBuildProject != null && iConf < p.slnBuildProject.Count)
                {
                    bPeformBuild = p.slnBuildProject[iConf];
                }

                if (p.slnDeployProject != null && iConf < p.slnConfigurations.Count)
                {
                    bPerformDeploy = p.slnDeployProject[iConf];
                }

                o.AppendLine("		"+ p.ProjectGuid.ToUpper() + "." + conf + ".ActiveCfg = " + mappedConf);
                if (bPeformBuild)
                {
                    o.AppendLine("		"+ p.ProjectGuid.ToUpper() + "." + conf + ".Build.0 = " + mappedConf);
                }

                if (bPerformDeploy.HasValue && bPerformDeploy.Value)
                {
                    o.AppendLine("		"+ p.ProjectGuid.ToUpper() + "." + conf + ".Deploy.0 = " + mappedConf);
                }
            } //for
        }     //foreach
        o.AppendLine("	EndGlobalSection");
        o.AppendLine("	GlobalSection(SolutionProperties) = preSolution");
        o.AppendLine("		HideSolutionNode = FALSE");
        o.AppendLine("	EndGlobalSection");

        //
        // Dump project dependency hierarchy.
        //
        Project root = projects.FirstOrDefault();

        if (root != null)
        {
            while (root.parent != null)
            {
                root = root.parent;
            }

            //
            // Flatten tree without recursion.
            //
            int            treeIndex = 0;
            List <Project> projects2 = new List <Project>();
            projects2.AddRange(root.nodes);

            for (; treeIndex < projects2.Count; treeIndex++)
            {
                if (projects2[treeIndex].nodes.Count == 0)
                {
                    continue;
                }
                projects2.AddRange(projects2[treeIndex].nodes);
            }

            bool bDump = projects2.Count(x => x.parent.parent != null) != 0;

            if (bDump)
            {
                o.AppendLine("	GlobalSection(NestedProjects) = preSolution");
            }

            foreach (Project p in projects2)
            {
                if (p.parent.parent == null)
                {
                    continue;
                }
                o.AppendLine("		"+ p.ProjectGuid.ToUpper() + " = " + p.parent.ProjectGuid.ToUpper());
            }

            if (bDump)
            {
                o.AppendLine("	EndGlobalSection");
            }
        } //if

        if (SolutionGuid != null)
        {
            o.AppendLine("	GlobalSection(ExtensibilityGlobals) = postSolution");
            o.AppendLine("		SolutionGuid = "+ SolutionGuid);
            o.AppendLine("	EndGlobalSection");
        }

        o.AppendLine("EndGlobal");

        String currentSln = "";

        if (File.Exists(slnPath))
        {
            currentSln = File.ReadAllText(slnPath);
        }

        String newSln = o.ToString();

        //
        // Save only if needed.
        //
        if (currentSln == newSln)
        {
            uinfo.MarkFileUpdated(slnPath, false);
        }
        else
        {
            if (SolutionProjectBuilder.isDeveloper() && File.Exists(slnPath))
            {
                File.Copy(slnPath, slnPath + ".bkp", true);
            }
            File.WriteAllText(slnPath, newSln, Encoding.UTF8);
            uinfo.MarkFileUpdated(slnPath, true);
        } //if-else
    }     //SaveSolution