public bool CopyBuild(DirectoryReference InstallPath) { CommandUtils.LogInformation("Installing shared cooked build from manifest: {0} to {1}", Manifest.FullName, InstallPath.FullName); DirectoryReference PlatformInstallPath = DirectoryReference.Combine(InstallPath, Platform.ToString()); FileReference PreviousManifest = FileReference.Combine(PlatformInstallPath, ".build", "Current.manifest"); FileReference BPTI = FileReference.Combine(CommandUtils.RootDirectory, "Engine", "Binaries", "Win64", "NotForLicensees", "BuildPatchToolInstaller.exe"); if (!FileReference.Exists(BPTI)) { CommandUtils.LogInformation("Could not locate BuildPatchToolInstaller.exe"); return false; } bool PreviousManifestExists = FileReference.Exists(PreviousManifest); if (!PreviousManifestExists && DirectoryReference.Exists(PlatformInstallPath)) { DirectoryReference.Delete(PlatformInstallPath, true); } IProcessResult Result = CommandUtils.Run(BPTI.FullName, string.Format("-Manifest={0} -OutputDir={1} -stdout -GenericConsoleOutput", Manifest.FullName, PlatformInstallPath.FullName), null, CommandUtils.ERunOptions.Default); if (Result.ExitCode != 0) { CommandUtils.LogWarning("Failed to install manifest {0} to {1}", Manifest.FullName, PlatformInstallPath.FullName); return false; } FileReference SyncedBuildFile = new FileReference(CommandUtils.CombinePaths(PlatformInstallPath.FullName, SyncedBuildFileName)); FileReference.WriteAllLines(SyncedBuildFile, new string[] { CL.ToString(), Manifest.FullName }); return true; }
/// <summary> /// Runs external program and writes the output to a logfile. /// </summary> /// <param name="App">Executable to run</param> /// <param name="CommandLine">Commandline to pass on to the executable</param> /// <param name="Logfile">Full path to the logfile, where the application output should be written to.</param> /// <param name="Input">Optional Input for the program (will be provided as stdin)</param> /// <param name="Options">Defines the options how to run. See ERunOptions.</param> /// <param name="FilterCallback">Callback to filter log spew before output.</param> public static string RunAndLog(string App, string CommandLine, string Logfile = null, int MaxSuccessCode = 0, string Input = null, ERunOptions Options = ERunOptions.Default, Dictionary <string, string> EnvVars = null, ProcessResult.SpewFilterCallbackType SpewFilterCallback = null) { IProcessResult Result = Run(App, CommandLine, Input, Options, EnvVars, SpewFilterCallback); if (Result.Output.Length > 0 && Logfile != null) { WriteToFile(Logfile, Result.Output); } else if (Logfile == null) { Logfile = "[No logfile specified]"; } else { Logfile = "[None!, no output produced]"; } if (Result.ExitCode > MaxSuccessCode || Result.ExitCode < 0) { throw new CommandFailedException((ExitCode)Result.ExitCode, String.Format("Command failed (Result:{3}): {0} {1}. See logfile for details: '{2}' ", App, CommandLine, Path.GetFileName(Logfile), Result.ExitCode)); } if (Result.Output.Length > 0) { return(Result.Output); } return(""); }
int XcodeBuild(string Arguments) { string XcodeBuildPath = "/usr/bin/xcodebuild"; IProcessResult Result = CommandUtils.Run(XcodeBuildPath, Arguments); return(Result.ExitCode); }
/// <summary> /// Attempts to detect source control server address from environment variables. /// </summary> /// <returns>Source control server address.</returns> private static string DetectP4Port() { string P4Port = null; // If it's not set, spawn Perforce to get the current server port setting IProcessResult Result = CommandUtils.Run(HostPlatform.Current.P4Exe, "set P4PORT", null, CommandUtils.ERunOptions.NoLoggingOfRunCommand); if (Result.ExitCode == 0) { const string KeyName = "P4PORT="; if (Result.Output.StartsWith(KeyName)) { int LastIdx = Result.Output.IndexOfAny(new char[] { ' ', '\n', '\r' }); if (LastIdx == -1) { LastIdx = Result.Output.Length; } P4Port = Result.Output.Substring(KeyName.Length, LastIdx - KeyName.Length); } } // Otherwise fallback to the uebp variables, or the default if (String.IsNullOrEmpty(P4Port)) { Log.TraceWarning("P4PORT is not set. Using perforce:1666"); P4Port = "perforce:1666"; } return(P4Port); }
public override void ExecuteBuild() { string Version = ParseParamValue("Version"); if (Version == null) { throw new AutomationException("Missing -Version=... parameter"); } IProcessResult Result = Run("xcodebuild", "-version"); if (Result.ExitCode != 0) { throw new AutomationException("Unable to query version number from xcodebuild (exit code={0})", Result.ExitCode); } Match Match = Regex.Match(Result.Output, "^Xcode ([0-9.]+)", RegexOptions.Multiline); if (!Match.Success) { throw new AutomationException("Missing version number from xcodebuild output:\n{0}", Result.Output); } if (Match.Groups[1].Value != Version) { LogWarning("Installed Xcode version is {0} - expected {1}", Match.Groups[1].Value, Version); } }
public IAppInstance Run(IAppInstall App) { LuminAppInstall LuminInstall = App as LuminAppInstall; if (LuminInstall == null) { throw new Exception("AppInstance is of incorrect type!"); } string QualifiedPackageName = GetQualifiedProjectName(LuminInstall.Name); // wake the device - we can install while its asleep but not run PowerOn(); // kill any currently running instance: KillRunningProcess(QualifiedPackageName); Log.Info("Launching {0} on '{1}' ", QualifiedPackageName, ToString()); Log.Verbose("\t{0}", LuminInstall.CommandLine); // Clear the device's log in preparation for the test.. RunMldbDeviceCommand("log -c"); // start the app on device! string CommandLine = "launch --auto-net-privs " + QualifiedPackageName + " -i \"" + LuminInstall.CommandLine + "\""; IProcessResult Process = RunMldbDeviceCommand(CommandLine, false, true); return new LuminAppInstance(this, LuminInstall, Process); }
public IAppInstance Run(IAppInstall App) { MacAppInstall MacInstall = App as MacAppInstall; if (MacInstall == null) { throw new AutomationException("Invalid install type!"); } IProcessResult Result = null; lock (Globals.MainLock) { string NewWorkingDir = string.IsNullOrEmpty(MacInstall.WorkingDirectory) ? MacInstall.LocalPath : MacInstall.WorkingDirectory; string OldWD = Environment.CurrentDirectory; Environment.CurrentDirectory = NewWorkingDir; Log.Info("Launching {0} on {1}", App.Name, ToString()); Log.Verbose("\t{0}", MacInstall.CommandArguments); Result = CommandUtils.Run(MacInstall.ExecutablePath, MacInstall.CommandArguments, Options: MacInstall.RunOptions); if (Result.HasExited && Result.ExitCode != 0) { throw new AutomationException("Failed to launch {0}. Error {1}", MacInstall.ExecutablePath, Result.ExitCode); } Environment.CurrentDirectory = OldWD; } return(new MacAppInstance(MacInstall, Result)); }
/// <summary> /// Updates cached activity log by running a shell command returning the full log from device (possibly over wifi) /// The result is cached and updated at ActivityLogDelta frequency /// </summary> private void UpdateCachedLog(bool ForceUpdate = false) { if (!ForceUpdate && (ActivityLogTime == DateTime.MinValue || ((DateTime.UtcNow - ActivityLogTime) < ActivityLogDelta))) { return; } if (Install.LuminDevice != null && Install.LuminDevice.Disposed) { Log.Warning("Attempting to cache log using disposed Lumin device"); return; } string GetLogCommand = string.Format("log -d"); IProcessResult LogQuery = Install.LuminDevice.RunMldbDeviceCommand(GetLogCommand, true, false); if (LogQuery.ExitCode != 0) { Log.VeryVerbose("Unable to query activity stdout on device {0}", Install.LuminDevice.Name); } else { ActivityLogCached = LogQuery.Output; } ActivityLogTime = DateTime.UtcNow; // the activity has exited, mark final log sentinel if (ActivityExited) { ActivityLogTime = DateTime.MinValue; } }
/// <summary> /// Checks on device whether the activity is running, this is an expensive shell with output operation /// the result is cached, with checks at ActivityCheckDelta seconds /// </summary> private bool IsActivityRunning() { if (ActivityExited) { return(true); } if ((DateTime.UtcNow - ActivityCheckTime) < ActivityCheckDelta) { return(false); } ActivityCheckTime = DateTime.UtcNow; // get activities filtered by our package name IProcessResult ActivityQuery = AndroidDevice.RunAdbDeviceCommand("shell dumpsys activity -p " + Install.AndroidPackageName + " a"); // We have exited if our activity doesn't appear in the activity query or is not the focused activity. bool bActivityPresent = ActivityQuery.Output.Contains(Install.AndroidPackageName); bool bActivityInForeground = ActivityQuery.Output.Contains("mResumedActivity"); bool bHasExited = !bActivityPresent || !bActivityInForeground; if (bHasExited) { ActivityExited = true; Log.VeryVerbose("{0}: process exited, Activity running={1}, Activity in foreground={2} ", ToString(), bActivityPresent.ToString(), bActivityInForeground.ToString()); } return(bHasExited); }
// IPA handling using ditto command, which is capable of handling IPA's > 4GB/Zip64 internal static bool ExecuteIPADittoCommand(String Arguments, out String Output, String ShouldExist = "") { using (new ScopedSuspendECErrorParsing()) { IProcessResult Result = ExecuteCommand("ditto", Arguments); Output = Result.Output; if (Result.ExitCode != 0) { if (!String.IsNullOrEmpty(ShouldExist)) { if (!File.Exists(ShouldExist) && !Directory.Exists(ShouldExist)) { Log.Error(String.Format("ditto encountered an error or warning procesing IPA, {0} missing", ShouldExist)); return(false); } } Log.Error(String.Format("ditto encountered an issue procesing IPA")); return(false); } } return(true); }
/// <summary> /// Detects the current code changelist the workspace is synced to. /// </summary> /// <param name="ClientRootPath">Workspace path.</param> /// <returns>Changelist number as a string.</returns> private static string DetectCurrentCodeCL(P4Connection Connection, string ClientRootPath) { CommandUtils.LogVerbose("uebp_CodeCL not set, detecting last code CL..."); // Retrieve the current changelist StringBuilder P4Cmd = new StringBuilder("changes -m 1"); string[] CodeExtensions = { ".cs", ".h", ".cpp", ".inl", ".usf", ".ush", ".uproject", ".uplugin" }; foreach (string CodeExtension in CodeExtensions) { P4Cmd.AppendFormat(" \"{0}/...{1}#have\"", CommandUtils.CombinePaths(PathSeparator.Depot, ClientRootPath), CodeExtension); } IProcessResult P4Result = Connection.P4(P4Cmd.ToString(), AllowSpew: false); // Loop through all the lines of the output. Even though we requested one result, we'll get one for each search pattern. int CL = 0; foreach (string Line in P4Result.Output.Split('\n')) { string[] Tokens = Line.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (Tokens.Length >= 2) { int LineCL = Int32.Parse(Tokens[1]); CL = Math.Max(CL, LineCL); } } return(CL.ToString()); }
public override void ExecuteBuild() { LogInformation("************************* ShooterGameRun"); string MapToRun = ParseParamValue("map", "/game/maps/sanctuary"); PushDir(CombinePaths(CmdEnv.LocalRoot, @"Engine/Binaries/Win64/")); // string GameServerExe = CombinePaths(CmdEnv.LocalRoot, @"ShooterGame/Binaries/Win64/ShooterGameServer.exe"); // string GameExe = CombinePaths(CmdEnv.LocalRoot, @"ShooterGame/Binaries/Win64/ShooterGame.exe"); string EditorExe = CombinePaths(CmdEnv.LocalRoot, @"Engine/Binaries/Win64/UE4Editor.exe"); string ServerLogFile = CombinePaths(CmdEnv.LogFolder, "Server.log"); string ServerApp = EditorExe; string OtherArgs = String.Format("{0} -server -abslog={1} -log", MapToRun, ServerLogFile); string StartArgs = "ShooterGame "; string ServerCmdLine = StartArgs + OtherArgs; IProcessResult ServerProcess = Run(ServerApp, ServerCmdLine, null, ERunOptions.AllowSpew | ERunOptions.NoWaitForExit | ERunOptions.AppMustExist | ERunOptions.NoStdOutRedirect); LogFileReaderProcess(ServerLogFile, ServerProcess, (string Output) => { if (String.IsNullOrEmpty(Output) == false) { Console.Write(Output); } return(true); // keep reading }); }
/// <summary> /// Checks whether version of deployed bundle matches local IPA /// </summary> bool CheckDeployedIPA(IOSBuild Build) { try { Log.Verbose("Checking deployed IPA hash"); string CommandLine = String.Format("--bundle_id {0} --download={1} --to {2}", Build.PackageName, "/Documents/IPAHash.txt", LocalCachePath); IProcessResult Result = ExecuteIOSDeployCommand(CommandLine, 120); if (Result.ExitCode != 0) { return(false); } string Hash = File.ReadAllText(LocalCachePath + "/Documents/IPAHash.txt").Trim(); string StoredHash = File.ReadAllText(IPAHashFilename).Trim(); if (Hash == StoredHash) { Log.Verbose("Deployed app hash matched cached IPA hash"); return(true); } } catch (Exception Ex) { if (!Ex.Message.Contains("is denied")) { Log.Verbose("Unable to pull cached IPA cache from device, cached file may not exist: {0}", Ex.Message); } } Log.Verbose("Deployed app hash doesn't match, IPA will be installed"); return(false); }
/// <summary> /// Starts compiling the provided project file and returns the process. Caller should check HasExited /// or call WaitForExit() to get results /// </summary> /// <param name="ProjectFile"></param> /// <returns></returns> private static bool CompileAutomationProject(FileReference ProjectFile, Dictionary <string, string> Properties) { if (!ProjectFile.HasExtension(".csproj")) { throw new AutomationException(String.Format("Unable to build Project {0}. Not a valid .csproj file.", ProjectFile)); } if (!FileReference.Exists(ProjectFile)) { throw new AutomationException(String.Format("Unable to build Project {0}. Project file not found.", ProjectFile)); } string CmdLine = String.Format("\"{0}\" /verbosity:quiet /nologo /target:Build {1} /p:TreatWarningsAsErrors=false /p:NoWarn=\"612,618,672,1591\" /p:BuildProjectReferences=true", ProjectFile, GetMsBuildPropertyArguments(Properties)); // Compile the project IProcessResult Result = CommandUtils.Run(CommandUtils.CmdEnv.MsBuildExe, CmdLine); if (Result.ExitCode != 0) { throw new AutomationException(String.Format("Failed to build \"{0}\":{1}{2}", ProjectFile, Environment.NewLine, Result.Output)); } else { // Remove .Automation.csproj and copy to target dir Log.TraceVerbose("Successfully compiled {0}", ProjectFile); } return(Result.ExitCode == 0); }
/// <summary> /// Runs UBT with the specified commandline. Automatically creates a logfile. When /// no LogName is specified, the executable name is used as logfile base name. /// </summary> /// <param name="Env">Environment to use.</param> /// <param name="CommandLine">Commandline to pass on to UBT.</param> /// <param name="LogName">Optional logfile name.</param> public static void RunUBT(CommandEnvironment Env, string UBTExecutable, string CommandLine) { if (!FileExists(UBTExecutable)) { throw new AutomationException("Unable to find UBT executable: " + UBTExecutable); } string BaseLogName = String.Format("UBT-{0}", String.Join("-", SharedUtils.ParseCommandLine(CommandLine).Where(x => !x.Contains('/') && !x.Contains('\\') && !x.StartsWith("-")))); string LogName; for (int Attempt = 1;; Attempt++) { LogName = String.Format("{0}.txt", (Attempt == 1)? BaseLogName : String.Format("{0}_{1}", BaseLogName, Attempt)); FileReference LogLocation = FileReference.Combine(new DirectoryReference(Env.LogFolder), LogName); if (!FileReference.Exists(LogLocation)) { CommandLine += String.Format(" -log=\"{0}\"", LogLocation); break; } if (Attempt >= 50) { throw new AutomationException("Unable to find name for UBT log file after {0} attempts", Attempt); } } IProcessResult Result = Run(UBTExecutable, CommandLine, Options: ERunOptions.AllowSpew | ERunOptions.NoStdOutCapture); if (Result.ExitCode != 0) { throw new AutomationException((ExitCode)Result.ExitCode, "UnrealBuildTool failed. See log for more details. ({0})", CommandUtils.CombinePaths(Env.FinalLogFolder, LogName)); } }
public IAppInstance Run(IAppInstall App) { AndroidAppInstall DroidAppInstall = App as AndroidAppInstall; if (DroidAppInstall == null) { throw new Exception("AppInstance is of incorrect type!"); } // wake the device - we can install while its asleep but not run PowerOn(); // kill any currently running instance: KillRunningProcess(DroidAppInstall.AndroidPackageName); string LaunchActivity = AndroidPlatform.GetLaunchableActivityName(); Log.Info("Launching {0} on '{1}' ", DroidAppInstall.AndroidPackageName + "/" + LaunchActivity, ToString()); Log.Verbose("\t{0}", DroidAppInstall.CommandLine); // Clear the device's logcat in preparation for the test.. RunAdbDeviceCommand("logcat --clear"); // start the app on device! string CommandLine = "shell am start -W -S -n " + DroidAppInstall.AndroidPackageName + "/" + LaunchActivity; IProcessResult Process = RunAdbDeviceCommand(CommandLine, false, true); return(new AndroidAppInstance(this, DroidAppInstall, Process)); }
private async Task ProcessRequest(HttpListenerContext context) { IProcessResult <ContentResult> response = default; var textWriter = new StreamWriter(context.Response.OutputStream); try { response = await handleClientRequest .Invoke(context.Request, textWriter); if (!response.Successful) { throw response.Exception; } await textWriter.FlushAsync(); context.Response.StatusCode = response.Result.StatusCode; context.Response.StatusDescription = response.Result.StatusDescription; context.Response.ContentType = response.Result.ContentType; context.Response.Close(); } catch (Exception exception) { var result = await(handleClientException?.Invoke(exception, textWriter) ?? Task.FromResult <ContentResult>(default));
/// <summary> /// Runs an ADB command at the global scope /// </summary> /// <param name="Args"></param> /// <param name="Wait"></param> /// <returns></returns> public static IProcessResult RunAdbGlobalCommand(string Args, bool Wait = true, bool bShouldLogCommand = false) { CommandUtils.ERunOptions RunOptions = CommandUtils.ERunOptions.AppMustExist | CommandUtils.ERunOptions.NoWaitForExit; if (Log.IsVeryVerbose) { RunOptions |= CommandUtils.ERunOptions.AllowSpew; } else { RunOptions |= CommandUtils.ERunOptions.NoLoggingOfRunCommand; } if (bShouldLogCommand) { Log.Verbose("Running ADB Command: adb {0}", Args); } IProcessResult Process = AndroidPlatform.RunAdbCommand(null, null, Args, null, RunOptions); if (Wait) { Process.WaitForExit(); } return(Process); }
public override IProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params) { // look for browser string BrowserPath = Params.Devices[0].Replace("HTML5@", ""); // open the webpage Int32 ServerPort = 8000; var ConfigCache = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", Path.GetDirectoryName(Params.RawProjectPath.FullName), CombinePaths(CmdEnv.LocalRoot, "Engine")); ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort); string WorkingDirectory = Path.GetDirectoryName(ClientApp); string url = Path.GetFileName(ClientApp) + ".html"; // Are we running via cook on the fly server? // find our http url - This is awkward because RunClient doesn't have real information that NFS is running or not. bool IsCookOnTheFly = false; // 9/24/2014 @fixme - All this is convoluted, clean up. // looks like cookonthefly commandline stopped adding protocol or the port :/ hard coding to DEFAULT_TCP_FILE_SERVING_PORT+1 (DEFAULT_HTTP_FILE_SERVING_PORT) // This will fail if the NFS server is started with a different port - we need to modify driver .cs script to pass in IP/Port data correctly. if (ClientCmdLine.Contains("filehostip")) { IsCookOnTheFly = true; url = "http://127.0.0.1:41898/" + url; } if (IsCookOnTheFly) { url += "?cookonthefly=true"; } else { url = String.Format("http://localhost:{0}/{1}", ServerPort, url); } // Check HTML5LaunchHelper source for command line args var LowerBrowserPath = BrowserPath.ToLower(); var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory().FullName, "UE4_HTML5", "user"); string BrowserCommandline = url; if (LowerBrowserPath.Contains("chrome")) { BrowserCommandline += " " + String.Format("--user-data-dir=\\\"{0}\\\" --enable-logging --no-first-run", Path.Combine(ProfileDirectory, "chrome")); } else if (LowerBrowserPath.Contains("firefox")) { BrowserCommandline += " " + String.Format("-no-remote -profile \\\"{0}\\\"", Path.Combine(ProfileDirectory, "firefox")); } string LauncherArguments = string.Format(" -Browser=\"{0}\" + -BrowserCommandLine=\"{1}\" -ServerPort=\"{2}\" -ServerRoot=\"{3}\" ", new object[] { BrowserPath, BrowserCommandline, ServerPort, WorkingDirectory }); var LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"); IProcessResult BrowserProcess = Run(LaunchHelperPath, LauncherArguments, null, ClientRunFlags | ERunOptions.NoWaitForExit); return(BrowserProcess); }
public IProcessResult ExecuteIOSDeployCommand(String CommandLine, int WaitTime = 60, bool WarnOnTimeout = true, bool UseDeviceID = true) { if (UseDeviceID && !IsDefaultDevice) { CommandLine = String.Format("--id {0} {1}", DeviceName, CommandLine); } String IOSDeployPath = Path.Combine(Globals.UE4RootDir, "Engine/Extras/ThirdPartyNotUE/ios-deploy/bin/ios-deploy"); if (!File.Exists(IOSDeployPath)) { throw new AutomationException("Unable to run ios-deploy binary at {0}", IOSDeployPath); } CommandUtils.ERunOptions RunOptions = CommandUtils.ERunOptions.NoWaitForExit; if (Log.IsVeryVerbose) { RunOptions |= CommandUtils.ERunOptions.AllowSpew; } else { RunOptions |= CommandUtils.ERunOptions.NoLoggingOfRunCommand; } Log.Verbose("ios-deploy executing '{0}'", CommandLine); IProcessResult Result = CommandUtils.Run(IOSDeployPath, CommandLine, Options: RunOptions); if (WaitTime > 0) { DateTime StartTime = DateTime.Now; Result.ProcessObject.WaitForExit(WaitTime * 1000); if (Result.HasExited == false) { if ((DateTime.Now - StartTime).TotalSeconds >= WaitTime) { string Message = String.Format("IOSDeployPath timeout after {0} secs: {1}, killing process", WaitTime, CommandLine); if (WarnOnTimeout) { Log.Warning(Message); } else { Log.Info(Message); } Result.ProcessObject.Kill(); // wait up to 15 seconds for process exit Result.ProcessObject.WaitForExit(15000); } } } return(Result); }
public static void Deploy(ProjectParams Params) { Params.ValidateAndLog(); if (!Params.Deploy) { return; } Log("********** DEPLOY COMMAND STARTED **********"); if (!Params.NoClient) { var DeployContextList = CreateDeploymentContext(Params, false, false); foreach (var SC in DeployContextList) { if (SC.StageTargetPlatform.DeployViaUFE) { string ClientCmdLine = "-run=Deploy "; ClientCmdLine += "-Device=" + string.Join("+", Params.Devices) + " "; ClientCmdLine += "-Targetplatform=" + SC.StageTargetPlatform.PlatformType.ToString() + " "; ClientCmdLine += "-SourceDir=\"" + CombinePaths(Params.BaseStageDirectory, SC.StageTargetPlatform.PlatformType.ToString()) + "\" "; string ClientApp = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/Win64/UnrealFrontend.exe"); Log("Deploying via UFE:"); Log("\tClientCmdLine: " + ClientCmdLine + ""); //@todo UAT: Consolidate running of external applications like UFE (See 'RunProjectCommand' for other instances) PushDir(Path.GetDirectoryName(ClientApp)); // Always start client process and don't wait for exit. IProcessResult ClientProcess = Run(ClientApp, ClientCmdLine, null, ERunOptions.NoWaitForExit); PopDir(); if (ClientProcess != null) { do { Thread.Sleep(100); }while (ClientProcess.HasExited == false); } } else { SC.StageTargetPlatform.Deploy(Params, SC); } } } if (Params.DedicatedServer) { ProjectParams ServerParams = new ProjectParams(Params); ServerParams.Devices = new ParamList <string>(ServerParams.ServerDevice); var DeployContextList = CreateDeploymentContext(ServerParams, true, false); foreach (var SC in DeployContextList) { SC.StageTargetPlatform.Deploy(ServerParams, SC); } } Log("********** DEPLOY COMMAND COMPLETED **********"); }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> public override void Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { IProcessResult Result = CommandUtils.Run(Parameters.Exe, Parameters.Arguments); if (Result.ExitCode < 0 || Result.ExitCode >= Parameters.ErrorLevel) { throw new AutomationException("{0} terminated with an exit code indicating an error ({1})", Path.GetFileName(Parameters.Exe), Result.ExitCode); } }
public IOSClientProcess(IProcessResult inChildProcess, string inDeviceID) { childProcess = inChildProcess; // Startup another thread that collect device console logs processConsoleLogs = true; consoleLogWorker = new Thread(() => ProcessConsoleOutput(inDeviceID)); consoleLogWorker.Start(); }
private static void RunInternal(ProjectParams Params, string ServerLogFile, string ClientLogFile) { // Setup server process if required. if (Params.DedicatedServer && !Params.SkipServer) { if (Params.ServerTargetPlatforms.Count > 0) { TargetPlatformDescriptor ServerPlatformDesc = Params.ServerTargetPlatforms[0]; ServerProcess = RunDedicatedServer(Params, ServerLogFile, Params.RunCommandline); // With dedicated server, the client connects to local host to load a map. if (ServerPlatformDesc.Type == UnrealTargetPlatform.Linux) { Params.MapToRun = Params.ServerDeviceAddress; } else { Params.MapToRun = "127.0.0.1"; } } else { throw new AutomationException("Failed to run, server target platform not specified"); } } else if (Params.FileServer && !Params.SkipServer) { ServerProcess = RunFileServer(Params, ServerLogFile, Params.RunCommandline); } if (ServerProcess != null) { Log("Waiting a few seconds for the server to start..."); Thread.Sleep(5000); } if (!Params.NoClient) { Log("Starting Client...."); var SC = CreateDeploymentContext(Params, false); ERunOptions ClientRunFlags; string ClientApp; string ClientCmdLine; SetupClientParams(SC, Params, ClientLogFile, out ClientRunFlags, out ClientApp, out ClientCmdLine); // Run the client. if (ServerProcess != null) { RunClientWithServer(SC, ServerLogFile, ServerProcess, ClientApp, ClientCmdLine, ClientRunFlags, ClientLogFile, Params); } else { RunStandaloneClient(SC, ClientLogFile, ClientRunFlags, ClientApp, ClientCmdLine, Params); } } }
IEnumerable <string> EnumerateBuildFolders(string Target, string Configuration, string Platform, bool DebugRun) { FileReference OutputFile = FileReference.Combine(CommandUtils.EngineDirectory, "Intermediate", "Build", "ThirdParty.json"); IProcessResult Result = Run(UE4Build.GetUBTExecutable(), String.Format("{0} {1} {2} -jsonexport=\"{3}\" -skipbuild", Target, Configuration, Platform, OutputFile.FullName), Options: DebugRun ? ERunOptions.Default : ERunOptions.NoLoggingOfRunCommand); if (Result.ExitCode != 0) { throw new AutomationException("Failed to run UBT"); } JsonObject Object = JsonObject.Read(OutputFile); // local function that takes a RuntimeDependency path and resolves it (replacing Env vars that we support) Func <string, DirectoryReference> ResolveRuntimeDependencyFolder = (string DependencyPath) => { return(new DirectoryReference(Path.GetDirectoryName( // Regex to replace the env vars we support $(EngineDir|ProjectDir), ignoring case Regex.Replace(DependencyPath, @"\$\((?<Type>Engine|Project)Dir\)", M => M.Groups["Type"].Value.Equals("Engine", StringComparison.InvariantCultureIgnoreCase) ? CommandUtils.EngineDirectory.FullName : new FileReference(Object.GetStringField("ProjectFile")).Directory.FullName, RegexOptions.IgnoreCase)))); }; JsonObject Modules = Object.GetObjectField("Modules"); // Create a set of directories used for each binary List <DirectoryReference> DirectoriesToScan = Modules // get all directories that the module uses (source folder and any runtime dependencies) .KeyNames.Select(KeyName => Modules.GetObjectField(KeyName)) .SelectMany(Module => Module // resolve any runtime dependency folders and add them. .GetObjectArrayField("RuntimeDependencies").Select(Dependency => ResolveRuntimeDependencyFolder(Dependency.GetStringField("Path"))) // Add on the module source directory .Concat(new[] { new DirectoryReference(Module.GetStringField("Directory")) })) // remove any duplicate folders since some modules may be from the same plugin .Distinct() // Project to a list as we need to do an O(n^2) operation below. .ToList(); List <string> FinalDirs = DirectoriesToScan.Where(RemovalCandidate => // O(n^2) search to remove subfolders of any we are already searching. // look for directories that aren't subdirectories of any other directory in the list. !DirectoriesToScan.Any(DirectoryToScan => // != check because this inner loop will eventually check against itself RemovalCandidate != DirectoryToScan && RemovalCandidate.IsUnderDirectory(DirectoryToScan))) // grab the full name .Select(Dir => Dir.FullName) // sort the final output .OrderBy(Dir => Dir) // log the folders .ToList(); return(FinalDirs); }
private static string GetBundleIdentifier(string SourceIPA) { // Get a list of files in the IPA IProcessResult Result = ExecuteCommand("unzip", String.Format("-Z1 {0}", SourceIPA)); if (Result.ExitCode != 0) { Log.Warning(String.Format("Unable to list files for IPA {0}", SourceIPA)); return(null); } string[] Filenames = Regex.Split(Result.Output, "\r\n|\r|\n"); string PList = Filenames.Where(F => F.ToLower().Contains("info.plist")).FirstOrDefault(); if (String.IsNullOrEmpty(PList)) { Log.Warning(String.Format("Unable to find plist for IPA {0}", SourceIPA)); return(null); } // Get the plist info Result = ExecuteCommand("unzip", String.Format("-p '{0}' '{1}'", SourceIPA, PList)); if (Result.ExitCode != 0) { Log.Warning(String.Format("Unable to extract plist data for IPA {0}", SourceIPA)); return(null); } string PlistInfo = Result.Output; // todo: plist parsing, could be better string PackageName = null; string KeyString = "<key>CFBundleIdentifier</key>"; int KeyIndex = PlistInfo.IndexOf(KeyString); if (KeyIndex > 0) { int StartIdx = PlistInfo.IndexOf("<string>", KeyIndex + KeyString.Length) + "<string>".Length; int EndIdx = PlistInfo.IndexOf("</string>", StartIdx); if (StartIdx > 0 && EndIdx > StartIdx) { PackageName = PlistInfo.Substring(StartIdx, EndIdx - StartIdx); } } if (String.IsNullOrEmpty(PackageName)) { Log.Warning(String.Format("Unable to find CFBundleIdentifier in plist info for IPA {0}", SourceIPA)); return(null); } Log.Verbose("Found bundle id: {0}", PackageName); return(PackageName); }
/// <summary> /// Run the client application on the platform /// </summary> /// <param name="ClientRunFlags"></param> /// <param name="ClientApp"></param> /// <param name="ClientCmdLine"></param> public virtual IProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params) { PushDir(Path.GetDirectoryName(ClientApp)); // Always start client process and don't wait for exit. IProcessResult ClientProcess = Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit); PopDir(); return(ClientProcess); }
protected bool RunEditorAndWaitForMapLoad(bool bIsWarming) { string ProjectArg = ProjectFile != null?ProjectFile.ToString() : ""; string EditorPath = HostPlatform.Current.GetUE4ExePath("UE4Editor.exe"); string LogArg = string.Format("-log={0}.log", MakeValidFileName(GetFullTaskName()).Replace(" ", "_")); string Arguments = string.Format("{0} {1} -execcmds=\"automation runtest System.Maps.PIE;Quit\" -stdout -FullStdOutLogOutput -unattended {2}", ProjectArg, EditorArgs, LogArg); if (TaskOptions.HasFlag(DDCTaskOptions.NoSharedDDC)) { Arguments += (" -ddc=noshared"); } if (!bIsWarming && TaskOptions.HasFlag(DDCTaskOptions.NoShaderDDC)) { Arguments += (" -noshaderddc"); } if (TaskOptions.HasFlag(DDCTaskOptions.NoXGE)) { Arguments += (" -noxgeshadercompile"); } var RunOptions = CommandUtils.ERunOptions.AllowSpew | CommandUtils.ERunOptions.NoWaitForExit; var SpewDelegate = new ProcessResult.SpewFilterCallbackType(EndOnMapCheckFilter); //TestCompleted = false; LastStdOutTime = DateTime.Now; CurrentProcess = CommandUtils.Run(EditorPath, Arguments, Options: RunOptions, SpewFilterCallback: SpewDelegate); DateTime StartTime = DateTime.Now; int MaxWaitMins = 90; while (!CurrentProcess.HasExited) { Thread.Sleep(5 * 1000); lock (CurrentProcess) { if ((LastStdOutTime - StartTime).TotalMinutes >= MaxWaitMins) { Log.TraceError("Gave up waiting for task after {0} minutes of no output", MaxWaitMins); CurrentProcess.ProcessObject.Kill(); } } } int ExitCode = CurrentProcess.ExitCode; CurrentProcess = null; return(ExitCode == 0); }
/// <summary> /// Runs UBT with the specified commandline. Automatically creates a logfile. When /// no LogName is specified, the executable name is used as logfile base name. /// </summary> /// <param name="Env">Environment to use.</param> /// <param name="CommandLine">Commandline to pass on to UBT.</param> /// <param name="LogName">Optional logfile name.</param> public static void RunUBT(CommandEnvironment Env, string UBTExecutable, string CommandLine) { if (!FileExists(UBTExecutable)) { throw new AutomationException("Unable to find UBT executable: " + UBTExecutable); } if (GlobalCommandLine.VS2015) { CommandLine += " -2015"; } if (!IsBuildMachine && UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealBuildTool.UnrealTargetPlatform.Mac) { CommandLine += " -nocreatestub"; } CommandLine += " -NoHotReload"; if (bJunkDeleted || GlobalCommandLine.IgnoreJunk) { // UBT has already deleted junk files, make sure it doesn't do it again CommandLine += " -ignorejunk"; } else { // UBT will delete junk on first run bJunkDeleted = true; } string BaseLogName = String.Format("UBT-{0}", String.Join("-", SharedUtils.ParseCommandLine(CommandLine).Where(x => !x.Contains('/') && !x.Contains('\\') && !x.StartsWith("-")))); string LogName; for (int Attempt = 1;; Attempt++) { LogName = String.Format("{0}.txt", (Attempt == 1)? BaseLogName : String.Format("{0}_{1}", BaseLogName, Attempt)); FileReference LogLocation = FileReference.Combine(new DirectoryReference(Env.LogFolder), LogName); if (!FileReference.Exists(LogLocation)) { CommandLine += String.Format(" -log=\"{0}\"", LogLocation); break; } if (Attempt >= 50) { throw new AutomationException("Unable to find name for UBT log file after {0} attempts", Attempt); } } IProcessResult Result = Run(UBTExecutable, CommandLine, Options: ERunOptions.AllowSpew | ERunOptions.NoStdOutCapture); if (Result.ExitCode != 0) { throw new AutomationException((ExitCode)Result.ExitCode, "UnrealBuildTool failed. See log for more details. ({0})", CommandUtils.CombinePaths(Env.FinalLogFolder, LogName)); } }
private string GetUrlComponent(string code) { IProcessResult processResult = jarRunner.RunJarWithInput(code, "-encodeurl", "-pipe"); if (processResult.ExitCode != 0) { string message = UTF8.GetString(processResult.Error); throw new RenderingException(code, message); } return(UTF8.GetString(processResult.Output)); }
public LocalAppProcess(IProcessResult InProcess, string InCommandLine, string InProcessLogFile = null) { this.CommandLine = InCommandLine; this.ProcessResult = InProcess; this.ProcessLogFile = InProcessLogFile; // start reader thread if logging to a file if (!string.IsNullOrEmpty(InProcessLogFile)) { new System.Threading.Thread(LogFileReaderThread).Start(); } }
/// <summary> /// Allow platform specific clean-up or detection after client has run /// </summary> /// <param name="ClientRunFlags"></param> public virtual void PostRunClient(IProcessResult Result, ProjectParams Params) { // do nothing in the default case }
/// <summary> /// Keeps reading a log file as it's being written to by another process until it exits. /// </summary> /// <param name="LogFilename">Name of the log file.</param> /// <param name="LogProcess">Process that writes to the log file.</param> /// <param name="OnLogRead">Callback used to process the recently read log contents.</param> protected static void LogFileReaderProcess(string LogFilename, IProcessResult LogProcess, ProcessLog OnLogRead = null) { while (!FileExists(LogFilename) && !LogProcess.HasExited) { Log("Waiting for logging process to start..."); Thread.Sleep(2000); } Thread.Sleep(1000); using (FileStream ProcessLog = File.Open(LogFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { StreamReader LogReader = new StreamReader(ProcessLog); bool bKeepReading = true; // Read until the process has exited. while (!LogProcess.HasExited && bKeepReading) { while (!LogReader.EndOfStream && bKeepReading) { string Output = LogReader.ReadToEnd(); if (Output != null && OnLogRead != null) { bKeepReading = OnLogRead(Output); } } while (LogReader.EndOfStream && !LogProcess.HasExited && bKeepReading) { Thread.Sleep(250); // Tick the callback so that it can respond to external events if (OnLogRead != null) { bKeepReading = OnLogRead(null); } } } } }
public override IServiceResult ParseResult(VersionControlArguments args, IProcessResult processResult) { var serializer = new VaultResultSerializer(); var vaultResult = serializer.Deserialize(processResult.StandardOutput); if (!vaultResult.Success) { return new ServiceResult(ServiceResultCode.Error); } var result = new ServiceResult(ServiceResultCode.Success); switch (args.Operation) { case VersionControlOperation.GetLocalVersion: // Find the file we were trying to get the version for foreach (var file in vaultResult.Folder.Files) { if (args.SourcePath.EndsWith(file.Name)) { result.ResultValue = file.Version; } } break; default: throw new ArgumentOutOfRangeException(); } return result; }
/// <summary> /// Parses the result of executing the VCS executable. /// </summary> /// <param name="args"></param> /// <param name="processResult"></param> /// <returns></returns> public abstract IServiceResult ParseResult(VersionControlArguments args, IProcessResult processResult);
private static void RunClientWithServer(List<DeploymentContext> DeployContextList, string ServerLogFile, IProcessResult ServerProcess, string ClientApp, string ClientCmdLine, ERunOptions ClientRunFlags, string ClientLogFile, ProjectParams Params) { IProcessResult ClientProcess = null; var OtherClients = new List<IProcessResult>(); bool WelcomedCorrectly = false; int NumClients = Params.NumClients; string AllClientOutput = ""; int LastAutoFailIndex = -1; if (Params.Unattended) { string LookFor = "Bringing up level for play took"; if (Params.DedicatedServer) { LookFor = "Welcomed by server"; } else if (Params.RunAutomationTest != "") { LookFor = "Automation Test Succeeded"; } else if (Params.RunAutomationTests) { LookFor = "Automation Test Queue Empty"; } { while (!FileExists(ServerLogFile) && !ServerProcess.HasExited) { Log("Waiting for logging process to start..."); Thread.Sleep(2000); } Thread.Sleep(1000); string AllServerOutput = ""; using (FileStream ProcessLog = File.Open(ServerLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { StreamReader LogReader = new StreamReader(ProcessLog); bool bKeepReading = true; FileStream ClientProcessLog = null; StreamReader ClientLogReader = null; // Read until the process has exited. while (!ServerProcess.HasExited && bKeepReading) { while (!LogReader.EndOfStream && bKeepReading && ClientProcess == null) { string Output = LogReader.ReadToEnd(); if (!String.IsNullOrEmpty(Output)) { AllServerOutput += Output; if (ClientProcess == null && (AllServerOutput.Contains("Game Engine Initialized") || AllServerOutput.Contains("Unreal Network File Server is ready"))) { Log("Starting Client for unattended test...."); ClientProcess = Run(ClientApp, ClientCmdLine + " -FORCELOGFLUSH -testexit=\"" + LookFor + "\"", null, ClientRunFlags | ERunOptions.NoWaitForExit); //@todo no testing is done on these if (NumClients > 1 && NumClients < 9) { for (int i = 1; i < NumClients; i++) { Log("Starting Extra Client...."); OtherClients.Add(Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit)); } } while (!FileExists(ClientLogFile) && !ClientProcess.HasExited) { Log("Waiting for client logging process to start...{0}", ClientLogFile); Thread.Sleep(2000); } if (!ClientProcess.HasExited) { Thread.Sleep(2000); Log("Client logging process started...{0}", ClientLogFile); ClientProcessLog = File.Open(ClientLogFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); ClientLogReader = new StreamReader(ClientProcessLog); } } else if (ClientProcess == null && !ServerProcess.HasExited) { Log("Waiting for server to start...."); Thread.Sleep(2000); } if (ClientProcess != null && ClientProcess.HasExited) { ServerProcess.StopProcess(); throw new AutomationException("Client exited before we asked it to."); } } } if (ClientLogReader != null) { if (ClientProcess.HasExited) { ServerProcess.StopProcess(); throw new AutomationException("Client exited or closed the log before we asked it to."); } while (!ClientProcess.HasExited && !ServerProcess.HasExited && bKeepReading) { while (!ClientLogReader.EndOfStream && bKeepReading && !ServerProcess.HasExited && !ClientProcess.HasExited) { string ClientOutput = ClientLogReader.ReadToEnd(); if (!String.IsNullOrEmpty(ClientOutput)) { AllClientOutput += ClientOutput; Console.Write(ClientOutput); if (AllClientOutput.LastIndexOf(LookFor) > AllClientOutput.IndexOf(LookFor)) { if (Params.FakeClient) { Log("Welcomed by server or client loaded, lets wait ten minutes..."); Thread.Sleep(60000 * 10); } else { Log("Welcomed by server or client loaded, lets wait 30 seconds..."); Thread.Sleep(30000); } WelcomedCorrectly = true; bKeepReading = false; } else if (Params.RunAutomationTests) { int FailIndex = AllClientOutput.LastIndexOf("Automation Test Failed"); int ParenIndex = AllClientOutput.LastIndexOf(")"); if (FailIndex >= 0 && ParenIndex > FailIndex && FailIndex > LastAutoFailIndex) { string Tail = AllClientOutput.Substring(FailIndex); int CloseParenIndex = Tail.IndexOf(")"); int OpenParenIndex = Tail.IndexOf("("); string Test = ""; if (OpenParenIndex >= 0 && CloseParenIndex > OpenParenIndex) { Test = Tail.Substring(OpenParenIndex + 1, CloseParenIndex - OpenParenIndex - 1); LogError("Automated test failed ({0}).", Test); LastAutoFailIndex = FailIndex; } } } } } } } } } } } else { LogFileReaderProcess(ServerLogFile, ServerProcess, (string Output) => { bool bKeepReading = true; if (ClientProcess == null && !String.IsNullOrEmpty(Output)) { AllClientOutput += Output; if (ClientProcess == null && (AllClientOutput.Contains("Game Engine Initialized") || AllClientOutput.Contains("Unreal Network File Server is ready"))) { Log("Starting Client...."); var SC = DeployContextList[0]; ClientProcess = SC.StageTargetPlatform.RunClient(ClientRunFlags | ERunOptions.NoWaitForExit, ClientApp, ClientCmdLine, Params); // ClientProcess = Run(ClientApp, ClientCmdLine, null, ClientRunFlags | ERunOptions.NoWaitForExit); if (NumClients > 1 && NumClients < 9) { for (int i = 1; i < NumClients; i++) { Log("Starting Extra Client...."); IProcessResult NewClient = SC.StageTargetPlatform.RunClient(ClientRunFlags | ERunOptions.NoWaitForExit, ClientApp, ClientCmdLine, Params); OtherClients.Add(NewClient); } } } } else if (ClientProcess == null && !ServerProcess.HasExited) { Log("Waiting for server to start...."); Thread.Sleep(2000); } if (String.IsNullOrEmpty(Output) == false) { Console.Write(Output); } if (ClientProcess != null && ClientProcess.HasExited) { Log("Client exited, stopping server...."); if (!GlobalCommandLine.NoKill) { ServerProcess.StopProcess(); } bKeepReading = false; } return bKeepReading; // Keep reading }); } Log("Server exited...."); if (ClientProcess != null && !ClientProcess.HasExited) { ClientProcess.StopProcess(); } foreach (var OtherClient in OtherClients) { if (OtherClient != null && !OtherClient.HasExited) { OtherClient.StopProcess(); } } if (Params.Unattended) { if (!WelcomedCorrectly) { throw new AutomationException("Server or client exited before we asked it to."); } } }
public override void PostRunClient(IProcessResult Result, ProjectParams Params) { if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { string LaunchTracePath = Params.BaseStageDirectory + "/" + PlatformName + "/launch.trace"; Console.WriteLine ("Deleting " + LaunchTracePath); if (Directory.Exists(LaunchTracePath)) { Directory.Delete (LaunchTracePath, true); } switch (Result.ExitCode) { case 253: throw new AutomationException(ExitCode.Error_DeviceNotSetupForDevelopment, "Launch Failure"); case 255: throw new AutomationException(ExitCode.Error_DeviceOSNewerThanSDK, "Launch Failure"); } } }