private CommandElements PrepareMavenTestngXmlExecutionCommand()
        {
            CommandElements command = new CommandElements();

            command.WorkingFolder    = MavenProjectFolderPath;
            command.ExecuterFilePath = string.Format("\"{0}\"", MavenCmdFullPath);

            //Mvn arguments
            if (PerformMavenInstall)
            {
                command.Arguments = " clean install test";
            }
            else
            {
                command.Arguments = " clean test";
            }

            //TestNG XML path
            command.Arguments += string.Format(" -Dsurefire.suiteXmlFiles=\"{0}\"", TestNgSuiteXMLObj.XmlFilePath);

            return(command);
        }
        private CommandElements PrepareTestngXmlExecutionCommand()
        {
            CommandElements command = new CommandElements();

            //if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            //{
            //    command.WorkingFolder = Path.GetDirectoryName(JavaExeFullPath);
            //}

            command.ExecuterFilePath = string.Format("\"{0}\"", JavaExeFullPath);
            command.Arguments        = string.Format(" -cp \"{0}\"{1}\"{2}\"", JavaProjectBinPath, General.GetOSFoldersSeperator(), JavaProjectResourcesPath);

            //testng test arguments
            command.Arguments += " org.testng.TestNG";

            //TestNG XML path
            command.Arguments += string.Format(" \"{0}\"", TestNgSuiteXMLObj.XmlFilePath);

            //Report output path
            command.Arguments += string.Format(" -d \"{0}\"", TestngResultsXmlFolderPath);

            return(command);
        }
        private bool ExecuteCommand(CommandElements commandVals)
        {
            try
            {
                Process process = new Process();

                if (commandVals.WorkingFolder != null)
                {
                    process.StartInfo.WorkingDirectory = commandVals.WorkingFolder;
                }

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    process.StartInfo.FileName  = commandVals.ExecuterFilePath;
                    process.StartInfo.Arguments = commandVals.Arguments;
                }
                else//Linux
                {
                    var escapedExecuter = commandVals.ExecuterFilePath.Replace("\"", "\\\"");
                    var escapedArgs     = commandVals.Arguments.Replace("\"", "\\\"");
                    process.StartInfo.FileName  = "bash";//" / bin/bash";
                    process.StartInfo.Arguments = $"-c \"{escapedExecuter} {escapedArgs}\"";
                }

                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                mCommandOutputBuffer        = string.Empty;
                mCommandOutputErrorBuffer   = string.Empty;
                process.OutputDataReceived += (proc, outLine) => { AddCommandOutput(outLine.Data); };
                process.ErrorDataReceived  += (proc, outLine) => { AddCommandOutputError(outLine.Data); };
                process.Exited             += Process_Exited;

                General.AddInfoToConsole("--Staring process");
                Stopwatch stopwatch = Stopwatch.StartNew();
                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                int maxWaitingTime = 1000 * 60 * 60;//1 hour

                process.WaitForExit(maxWaitingTime);
                General.AddInfoToConsole("--Process done");
                stopwatch.Stop();

                if (stopwatch.ElapsedMilliseconds >= maxWaitingTime)
                {
                    General.AddErrorToConsoleAndAction(GingerAction, string.Format("Command processing timeout has reached!"));
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                General.AddErrorToConsoleAndAction(GingerAction, string.Format("Failed to execute the command, Error is: '{0}'", ex.Message));
                return(false);
            }
            finally
            {
                General.AddInfoToConsole("--Exiting execute command");
            }
        }
        private CommandElements PrepareFreeCommand()
        {
            CommandElements command = new CommandElements();

            if (JavaProjectType == eJavaProjectType.Regular)
            {
                if (string.IsNullOrEmpty(JavaWorkingFolder) == false)
                {
                    command.WorkingFolder = JavaWorkingFolder;
                }
                command.ExecuterFilePath = string.Format("\"{0}\"", JavaExeFullPath);
            }
            else//maven
            {
                command.WorkingFolder    = MavenProjectFolderPath;
                command.ExecuterFilePath = string.Format("\"{0}\"", MavenCmdFullPath);
            }

            if (OverwriteOriginalTestngXml == false && TestngXmlParametersToOverwrite != null && TestngXmlParametersToOverwrite.Count > 0)
            {
                //need to update the path of the xml in the command arguments to point the customized one
                string xmlName      = Path.GetFileName(mOriginalTestngXmlPath);
                int    fileNameIndx = FreeCommandArguments.IndexOf(xmlName);
                if (fileNameIndx > 0)
                {
                    int rightIndx = fileNameIndx + xmlName.Length;
                    if (rightIndx < FreeCommandArguments.Length && FreeCommandArguments[rightIndx] == '\"')
                    {
                        rightIndx++;
                    }
                    int leftIndx = fileNameIndx;
                    while (leftIndx > 0 && FreeCommandArguments[leftIndx - 1] != '=')
                    {
                        leftIndx--;
                    }
                    if (leftIndx <= 0)//'=' not found so probably used the TestNG command like "org.testng.TestNG src/test/resources/fit/testng.xml"
                    {
                        leftIndx = fileNameIndx;
                        while (leftIndx > 0 && FreeCommandArguments.Substring(leftIndx - 8, 8).ToUpper() != ".TESTNG ")
                        {
                            leftIndx--;
                        }
                    }

                    if (rightIndx > leftIndx && rightIndx > 0 && leftIndx > 0)
                    {
                        string fullXmlPathArgument = FreeCommandArguments.Substring(leftIndx, rightIndx - leftIndx);
                        FreeCommandArguments = FreeCommandArguments.Replace(fullXmlPathArgument, string.Format("\"{0}\"", TestngXmlPath));
                    }
                    else
                    {
                        General.AddErrorToConsoleAndAction(GingerAction, string.Format("Failed to replace the original TestNG XML path '{0}' with the customized one '{1}' in the command arguments", mOriginalTestngXmlPath, TestngXmlPath));
                    }
                }
                else
                {
                    General.AddErrorToConsoleAndAction(GingerAction, string.Format("Failed to replace the original TestNG XML path '{0}' with the customized one '{1}' in the command arguments", mOriginalTestngXmlPath, TestngXmlPath));
                }
            }

            command.Arguments = string.Format(" {0}", FreeCommandArguments);

            return(command);
        }
        public void Execute()
        {
            General.AddInfoToConsole("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Execution Started %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
            General.AddInfoToConsole("############################# Validating / Preparing Execution Configurations");
            if (!ValidateAndPrepareConfigs())
            {
                return;
            }

            //prepare the customized xml
            General.AddInfoToConsole("############################# Prepare TestNG Xml for Execution");
            if (!PrepareTestNGXmlForExecution())
            {
                return;
            }

            //prepare the command
            General.AddInfoToConsole("############################# Prepare Execution Command");
            CommandElements command = null;

            try
            {
                switch (ExecutionMode)
                {
                case eExecutionMode.XML:
                    if (JavaProjectType == eJavaProjectType.Regular)
                    {
                        command = PrepareTestngXmlExecutionCommand();
                    }
                    else    //Maven
                    {
                        command = PrepareMavenTestngXmlExecutionCommand();
                    }
                    break;

                case eExecutionMode.FreeCommand:
                    if (JavaProjectType == eJavaProjectType.Regular)
                    {
                        command = PrepareFreeCommand();
                    }
                    else    //Maven
                    {
                        command = PrepareFreeCommand();
                    }
                    break;
                }

                General.AddInfoToConsoleAndAction(GingerAction, string.Format("Full Command: '{0}'", command.FullCommand));
            }
            catch (Exception ex)
            {
                General.AddErrorToConsoleAndAction(GingerAction, string.Format("Failed to prepare the command to execute, Error: '{0}'", ex.Message));
                return;
            }

            if (command != null)
            {
                //execute the command
                General.AddInfoToConsole("############################# Executing Command");
                if (ExecuteCommand(command))
                {
                    //parse output
                    if (ParseConsoleOutputs)
                    {
                        General.AddInfoToConsole("############################# Parsing Command Outputs");
                        ParseCommandOutput();
                    }

                    //parse report
                    if (ParseTestngResultsXml)
                    {
                        General.AddInfoToConsole("############################# Parsing TestNG Results XML");
                        //parse the TestNG output result XML
                        string testNgReportPath = Path.Combine(TestngResultsXmlFolderPath, "testng-results.xml");
                        General.AddInfoToConsoleAndAction(GingerAction, String.Format("TestNG Results XML full path: '{0}'", testNgReportPath));
                        TestNGReportXML ngReport = new TestNGReportXML(testNgReportPath);
                        if (string.IsNullOrEmpty(ngReport.LoadError) == true)
                        {
                            ngReport.ParseTestNGReport(GingerAction, FailActionDueToTestngResultsXmlFailures);
                        }
                        else
                        {
                            General.AddErrorToConsoleAndAction(GingerAction, "TestNG Output Results XML parsing failed");
                        }
                    }
                }
            }
            else
            {
                General.AddErrorToConsoleAndAction(GingerAction, "No command found to exeucte");
            }

            General.AddInfoToConsole("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Execution Ended %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
        }