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)); }
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)); }
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) { NullAppInstall NullApp = App as NullAppInstall; if (NullApp == null) { throw new DeviceException("AppInstance is of incorrect type!"); } Log.Info("Launching {0} on {1}", App.Name, ToString()); Log.Info("\t{0}", NullApp.CommandLine); return(new NullAppInstance(this)); }
protected void TestInstallThenRun(UnrealBuildSource Build, UnrealTargetRole ProcessType, ITargetDevice Device, UnrealTargetConfiguration Config, UnrealOptions InOptions = null) { // create a config based on the passed in params UnrealSessionRole Role = new UnrealSessionRole(ProcessType, Device.Platform, Config, InOptions); Log.Info("Testing {0}", Role); UnrealAppConfig AppConfig = Build.CreateConfiguration(Role); if (!CheckResult(AppConfig != null, "Could not create config for {0} {1} with platform {2} from build.", Config, ProcessType, Device)) { MarkComplete(); return; } // Install the app on this device IAppInstall AppInstall = Device.InstallApplication(AppConfig); CheckResult(AppConfig != null, "Could not create AppInstall for {0} {1} with platform {2} from build.", Config, ProcessType, Device); DateTime StartTime = DateTime.Now; // Run the app and wait for either a timeout or it to exit IAppInstance AppProcess = AppInstall.Run(); while (AppProcess.HasExited == false) { if ((DateTime.Now - StartTime).TotalSeconds > 60) { break; } Thread.Sleep(1000); } // Check it didn't exit unexpectedly CheckResult(AppProcess.HasExited == false, "Failed to run {0} {1} with platform {2}", Config, ProcessType, Device); // but kill it AppProcess.Kill(); // Check that it left behind some artifacts (minimum should be a log) int ArtifactCount = new DirectoryInfo(AppProcess.ArtifactPath).GetFiles("*", SearchOption.AllDirectories).Length; CheckResult(ArtifactCount > 0, "No artifacts on device!"); }
public IAppInstance Run(IAppInstall App) { IOSAppInstall IOSApp = App as IOSAppInstall; if (IOSApp == null) { throw new DeviceException("AppInstance is of incorrect type!"); } string CommandLine = IOSApp.CommandLine.Replace("\"", "\\\""); Log.Info("Launching {0} on {1}", App.Name, ToString()); Log.Verbose("\t{0}", CommandLine); // ios-deploy notes: -L launches detached, -I non-interactive (exits when app exits), -r uninstalls before install (removes app Documents folder) // -t <seconds> number of seconds to wait for device to be connected // setup symbols if available string DSymBundle = ""; string DSymDir = Path.Combine(GauntletAppCache, "Symbols"); if (Directory.Exists(DSymDir)) { DSymBundle = Directory.GetDirectories(DSymDir).Where(D => Path.GetExtension(D).ToLower() == ".dsym").FirstOrDefault(); DSymBundle = string.IsNullOrEmpty(DSymBundle) ? "" : DSymBundle = " -S \"" + DSymBundle + "\""; } string CL = "--noinstall -I" + DSymBundle + " -b \"" + LocalAppBundle + "\" --args '" + CommandLine.Trim() + "'"; IProcessResult Result = ExecuteIOSDeployCommand(CL, 0); Thread.Sleep(5000); // Give ios-deploy a chance to throw out any errors... if (Result.HasExited) { Log.Warning("ios-deploy exited early: " + Result.Output); throw new DeviceException("Failed to launch on {0}. {1}", Name, Result.Output); } return(new IOSAppInstance(IOSApp, Result, IOSApp.CommandLine)); }
public IAppInstance Run(IAppInstall App) { WindowsAppInstall WinApp = App as WindowsAppInstall; if (WinApp == null) { throw new DeviceException("AppInstance is of incorrect type!"); } if (File.Exists(WinApp.ExecutablePath) == false) { throw new DeviceException("Specified path {0} not found!", WinApp.ExecutablePath); } IProcessResult Result = null; lock (Globals.MainLock) { string ExePath = Path.GetDirectoryName(WinApp.ExecutablePath); string NewWorkingDir = string.IsNullOrEmpty(WinApp.WorkingDirectory) ? ExePath : WinApp.WorkingDirectory; string OldWD = Environment.CurrentDirectory; Environment.CurrentDirectory = NewWorkingDir; Log.Info("Launching {0} on {1}", App.Name, ToString()); Log.Verbose("\t{0}", WinApp.CommandArguments); Result = CommandUtils.Run(WinApp.ExecutablePath, WinApp.CommandArguments, Options: WinApp.RunOptions); if (Result.HasExited && Result.ExitCode != 0) { throw new AutomationException("Failed to launch {0}. Error {1}", WinApp.ExecutablePath, Result.ExitCode); } Environment.CurrentDirectory = OldWD; } return(new WindowsAppInstance(WinApp, Result)); }
/// <summary> /// Installs and launches all of our roles and returns an UnrealSessonInstance that represents the aggregate /// of all of these processes. Will perform retries if errors with devices are encountered so this is a "best /// attempt" at running with the devices provided /// </summary> /// <returns></returns> public UnrealSessionInstance LaunchSession() { SessionInstance = null; // tries to find devices and launch our session. Will loop until we succeed, we run out of devices/retries, or // something fatal occurs.. while (SessionInstance == null && Globals.CancelSignalled == false) { int Retries = 5; int RetryWait = 120; IEnumerable <UnrealSessionRole> RolesNeedingDevices = SessionRoles.Where(R => R.IsNullRole() == false); while (ReservedDevices.Count() < RolesNeedingDevices.Count()) { // get devices TryReserveDevices(); if (Globals.CancelSignalled) { break; } // if we failed to get enough devices, show a message and wait if (ReservedDevices.Count() != SessionRoles.Count()) { if (Retries == 0) { throw new AutomationException("Unable to acquire all devices for test."); } Log.Info("\nUnable to find enough device(s). Waiting {0} secs (retries left={1})\n", RetryWait, --Retries); Thread.Sleep(RetryWait * 1000); } } if (Globals.CancelSignalled) { return(null); } Dictionary <IAppInstall, UnrealSessionRole> InstallsToRoles = new Dictionary <IAppInstall, UnrealSessionRole>(); // create a copy of our list IEnumerable <ITargetDevice> DevicesToInstallOn = ReservedDevices.ToArray(); bool InstallSuccess = true; #if !__MonoCS__ // count how many desktop clients IEnumerable <UnrealSessionRole> DesktopClients = SessionRoles.Where(R => R.Platform == BuildHostPlatform.Current.Platform).Where(R => R.RoleType.IsClient()); if (DesktopClients.Count() > 1) { int NumClientRows = (int)Math.Ceiling(DesktopClients.Count() / 2.0); var ScreenRect = System.Windows.Forms.Screen.PrimaryScreen.Bounds; double Ratio = 16.0 / 9.0; // pick width int DesiredWidth = ScreenRect.Width / 2; // height at 16:9 aspect int DesiredHeight = (int)(DesiredWidth / Ratio); // constrain width if the screen can't have that many rows if (DesiredHeight * NumClientRows > ScreenRect.Height) { DesiredHeight = ScreenRect.Height / NumClientRows; DesiredWidth = (int)(DesiredHeight * Ratio); } // now set all these params and disable the regular params that pick windowed stuff for (int i = 0; i < DesktopClients.Count(); i++) { UnrealSessionRole Role = DesktopClients.ElementAt(i); int Row = i / 2; int Column = i - (Row * 2); // this is hacky, but not sure if a better way to do it right now without changing interfaces in a TBD way UnrealTestConfiguration ConfigOptions = Role.Options as UnrealTestConfiguration; if (ConfigOptions != null) { ConfigOptions.IgnoreDefaultResolutionAndWindowMode = true; } Role.CommandLine += string.Format(" -WinX={0} -WinY={1} -ResX={2} -ResY={3} -windowed", Column * DesiredWidth, Row * DesiredHeight, DesiredWidth, DesiredHeight); } } #endif // sort by constraints, so that we pick constrained devices first List <UnrealSessionRole> SortedRoles = SessionRoles.OrderBy(R => R.Constraint.IsIdentity() ? 1 : 0).ToList(); // first install all roles on these devices foreach (var Role in SortedRoles) { ITargetDevice Device = null; if (Role.IsNullRole() == false) { Device = DevicesToInstallOn.Where(D => D.IsConnected && D.Platform == Role.Platform && (Role.Constraint.IsIdentity() || DevicePool.Instance.GetConstraint(D) == Role.Constraint)).First(); DevicesToInstallOn = DevicesToInstallOn.Where(D => D != Device); } else { Device = new TargetDeviceNull(string.Format("Null{0}", Role.RoleType)); } var OtherRoles = SortedRoles.Where(R => R != Role); // create a config from the build source (this also applies the role options) UnrealAppConfig AppConfig = BuildSource.CreateConfiguration(Role, OtherRoles); // todo - should this be elsewhere? AppConfig.Sandbox = Sandbox; IAppInstall Install = null; try { Install = Device.InstallApplication(AppConfig); } catch (System.Exception Ex) { // Warn, ignore the device, and do not continue Log.Info("Failed to install app onto device {0} for role {1}. {2}. Will retry with new device", Device, Role, Ex); MarkProblemDevice(Device); InstallSuccess = false; break; } if (Globals.CancelSignalled) { break; } // Device has app installed, give role a chance to configure device Role.ConfigureDevice?.Invoke(Device); InstallsToRoles[Install] = Role; } if (InstallSuccess == false) { // release all devices ReleaseDevices(); } if (InstallSuccess && Globals.CancelSignalled == false) { List <UnrealSessionInstance.RoleInstance> RunningRoles = new List <UnrealSessionInstance.RoleInstance>(); // Now try to run all installs on their devices foreach (var InstallRoleKV in InstallsToRoles) { IAppInstall CurrentInstall = InstallRoleKV.Key; bool Success = false; try { IAppInstance Instance = CurrentInstall.Run(); if (Instance != null || Globals.CancelSignalled) { RunningRoles.Add(new UnrealSessionInstance.RoleInstance(InstallRoleKV.Value, Instance)); } Success = true; } catch (DeviceException Ex) { // shutdown all Log.Warning("Device {0} threw an exception during launch. \nException={1}", CurrentInstall.Device, Ex.Message); Success = false; } if (Success == false) { Log.Warning("Failed to start build on {0}. Marking as problem device and retrying with new set", CurrentInstall.Device); // terminate anything that's running foreach (UnrealSessionInstance.RoleInstance RunningRole in RunningRoles) { Log.Info("Shutting down {0}", RunningRole.AppInstance.Device); RunningRole.AppInstance.Kill(); RunningRole.AppInstance.Device.Disconnect(); } // mark that device as a problem MarkProblemDevice(CurrentInstall.Device); // release all devices ReleaseDevices(); break; // do not continue loop } } if (RunningRoles.Count() == SessionRoles.Count()) { SessionInstance = new UnrealSessionInstance(RunningRoles.ToArray()); } } } return(SessionInstance); }
void TestClientPlatform(UnrealTargetPlatform Platform) { string GameName = this.ProjectFile.FullName; string BuildPath = this.BuildPath; string DevKit = this.DevkitName; if (GameName.Equals("OrionGame", StringComparison.OrdinalIgnoreCase) == false) { Log.Info("Skipping test {0} due to non-Orion project!", this); MarkComplete(); return; } // create a new build UnrealBuildSource Build = new UnrealBuildSource(ProjectFile, this.UnrealPath, UsesSharedBuildType, BuildPath); // check it's valid if (!CheckResult(Build.BuildCount > 0, "staged build was invalid")) { MarkComplete(); return; } // Create devices to run the client and server ITargetDevice ServerDevice = new TargetDeviceWindows("PC Server", Gauntlet.Globals.TempDir); ITargetDevice ClientDevice = null; if (Platform == UnrealTargetPlatform.PS4) { //ClientDevice = new TargetDevicePS4(this.PS4Name); } else { ClientDevice = new TargetDeviceWindows("PC Client", Gauntlet.Globals.TempDir); } UnrealAppConfig ServerConfig = Build.CreateConfiguration(new UnrealSessionRole(UnrealTargetRole.Server, ServerDevice.Platform, UnrealTargetConfiguration.Development)); UnrealAppConfig ClientConfig = Build.CreateConfiguration(new UnrealSessionRole(UnrealTargetRole.Client, ClientDevice.Platform, UnrealTargetConfiguration.Development)); if (!CheckResult(ServerConfig != null && ServerConfig != null, "Could not create configs!")) { MarkComplete(); return; } ShortSoloOptions Options = new ShortSoloOptions(); Options.ApplyToConfig(ClientConfig); Options.ApplyToConfig(ServerConfig); IAppInstall ClientInstall = ClientDevice.InstallApplication(ClientConfig); IAppInstall ServerInstall = ServerDevice.InstallApplication(ServerConfig); if (!CheckResult(ServerConfig != null && ServerConfig != null, "Could not create configs!")) { MarkComplete(); return; } IAppInstance ClientInstance = ClientInstall.Run(); IAppInstance ServerInstance = ServerInstall.Run(); DateTime StartTime = DateTime.Now; bool RunWasSuccessful = true; while (ClientInstance.HasExited == false) { if ((DateTime.Now - StartTime).TotalSeconds > 800) { RunWasSuccessful = false; break; } } ClientInstance.Kill(); ServerInstance.Kill(); UnrealLogParser LogParser = new UnrealLogParser(ClientInstance.StdOut); UnrealLogParser.CallstackMessage ErrorInfo = LogParser.GetFatalError(); if (ErrorInfo != null) { CheckResult(false, "FatalError - {0}", ErrorInfo.Message); } RunWasSuccessful = LogParser.HasRequestExit(); CheckResult(RunWasSuccessful, "Failed to run for platform {0}", Platform); }
public IAppInstance Run(IAppInstall App) { WindowsAppInstall WinApp = App as WindowsAppInstall; if (WinApp == null) { throw new DeviceException("AppInstance is of incorrect type!"); } if (File.Exists(WinApp.ExecutablePath) == false) { throw new DeviceException("Specified path {0} not found!", WinApp.ExecutablePath); } IProcessResult Result = null; string ProcessLogFile = null; lock (Globals.MainLock) { string ExePath = Path.GetDirectoryName(WinApp.ExecutablePath); string NewWorkingDir = string.IsNullOrEmpty(WinApp.WorkingDirectory) ? ExePath : WinApp.WorkingDirectory; string OldWD = Environment.CurrentDirectory; Environment.CurrentDirectory = NewWorkingDir; Log.Info("Launching {0} on {1}", App.Name, ToString()); string CmdLine = WinApp.CommandArguments; // Look in app parameters if abslog is specified, if so use it Regex CLRegex = new Regex(@"(--?[a-zA-Z]+)[:\s=]?([A-Z]:(?:\\[\w\s-]+)+\\?(?=\s-)|\""[^\""]*\""|[^-][^\s]*)?"); foreach (Match M in CLRegex.Matches(CmdLine)) { if (M.Groups.Count == 3 && M.Groups[1].Value == "-abslog") { ProcessLogFile = M.Groups[2].Value; } } // explicitly set log file when not already defined if (string.IsNullOrEmpty(ProcessLogFile)) { string LogFolder = string.Format(@"{0}\Logs", WinApp.ArtifactPath); if (!Directory.Exists(LogFolder)) { Directory.CreateDirectory(LogFolder); } ProcessLogFile = string.Format("{0}\\{1}.log", LogFolder, WinApp.ProjectName); CmdLine = string.Format("{0} -abslog=\"{1}\"", CmdLine, ProcessLogFile); } // cleanup any existing log file try { if (File.Exists(ProcessLogFile)) { File.Delete(ProcessLogFile); } } catch (Exception Ex) { throw new AutomationException("Unable to delete existing log file {0} {1}", ProcessLogFile, Ex.Message); } Log.Verbose("\t{0}", CmdLine); Result = CommandUtils.Run(WinApp.ExecutablePath, CmdLine, Options: WinApp.RunOptions | (ProcessLogFile != null ? CommandUtils.ERunOptions.NoStdOutRedirect : 0)); if (Result.HasExited && Result.ExitCode != 0) { throw new AutomationException("Failed to launch {0}. Error {1}", WinApp.ExecutablePath, Result.ExitCode); } Environment.CurrentDirectory = OldWD; } return(new WindowsAppInstance(WinApp, Result, ProcessLogFile)); }
/// <summary> /// Installs and launches all of our roles and returns an UnrealSessonInstance that represents the aggregate /// of all of these processes. Will perform retries if errors with devices are encountered so this is a "best /// attempt" at running with the devices provided /// </summary> /// <returns></returns> public UnrealSessionInstance LaunchSession() { SessionInstance = null; // tries to find devices and launch our session. Will loop until we succeed, we run out of devices/retries, or // something fatal occurs.. while (SessionInstance == null && Globals.CancelSignalled == false) { int Retries = 5; int RetryWait = 120; IEnumerable <UnrealSessionRole> RolesNeedingDevices = SessionRoles.Where(R => R.IsNullRole() == false); while (ReservedDevices.Count() < RolesNeedingDevices.Count()) { // get devices TryReserveDevices(); if (Globals.CancelSignalled) { break; } // if we failed to get enough devices, show a message and wait if (ReservedDevices.Count() != SessionRoles.Count()) { if (Retries == 0) { throw new AutomationException("Unable to acquire all devices for test."); } Log.Info("\nUnable to find enough device(s). Waiting {0} secs (retries left={1})\n", RetryWait, --Retries); Thread.Sleep(RetryWait * 1000); } } if (Globals.CancelSignalled) { return(null); } Dictionary <IAppInstall, UnrealSessionRole> InstallsToRoles = new Dictionary <IAppInstall, UnrealSessionRole>(); // create a copy of our list IEnumerable <ITargetDevice> DevicesToInstallOn = ReservedDevices.ToArray(); bool InstallSuccess = true; // sort by constraints, so that we pick constrained devices first List <UnrealSessionRole> SortedRoles = SessionRoles.OrderBy(R => R.Constraint.IsIdentity() ? 1 : 0).ToList(); // first install all roles on these devices foreach (var Role in SortedRoles) { ITargetDevice Device = null; if (Role.IsNullRole() == false) { Device = DevicesToInstallOn.Where(D => D.IsConnected && D.Platform == Role.Platform && (Role.Constraint.IsIdentity() || DevicePool.Instance.GetConstraint(D) == Role.Constraint)).First(); DevicesToInstallOn = DevicesToInstallOn.Where(D => D != Device); } else { Device = new TargetDeviceNull(string.Format("Null{0}", Role.RoleType)); } // create a config from the build source (this also applies the role options) UnrealAppConfig AppConfig = BuildSource.CreateConfiguration(Role); // todo - should this be elsewhere? AppConfig.Sandbox = Sandbox; IAppInstall Install = null; try { Install = Device.InstallApplication(AppConfig); } catch (System.Exception Ex) { // Warn, ignore the device, and do not continue Log.Info("Failed to install app onto device {0} for role {1}. {2}. Will retry with new device", Device, Role, Ex); MarkProblemDevice(Device); InstallSuccess = false; break; } if (Globals.CancelSignalled) { break; } InstallsToRoles[Install] = Role; } if (InstallSuccess == false) { // release all devices ReleaseDevices(); } if (InstallSuccess && Globals.CancelSignalled == false) { List <UnrealSessionInstance.RoleInstance> RunningRoles = new List <UnrealSessionInstance.RoleInstance>(); // Now try to run all installs on their devices foreach (var InstallRoleKV in InstallsToRoles) { IAppInstall CurrentInstall = InstallRoleKV.Key; bool Success = false; try { IAppInstance Instance = CurrentInstall.Run(); if (Instance != null || Globals.CancelSignalled) { RunningRoles.Add(new UnrealSessionInstance.RoleInstance(InstallRoleKV.Value, Instance)); } Success = true; } catch (DeviceException Ex) { // shutdown all Log.Warning("Device {0} threw an exception during launch. \nException={1}", CurrentInstall.Device, Ex.Message); Success = false; } if (Success == false) { Log.Warning("Failed to start build on {0}. Marking as problem device and retrying with new set", CurrentInstall.Device); // terminate anything that's running foreach (UnrealSessionInstance.RoleInstance RunningRole in RunningRoles) { Log.Info("Shutting down {0}", RunningRole.AppInstance.Device); RunningRole.AppInstance.Kill(); RunningRole.AppInstance.Device.Disconnect(); } // mark that device as a problem MarkProblemDevice(CurrentInstall.Device); // release all devices ReleaseDevices(); break; // do not continue loop } } if (RunningRoles.Count() == SessionRoles.Count()) { SessionInstance = new UnrealSessionInstance(RunningRoles.ToArray()); } } } return(SessionInstance); }