public static void SaveConfig(string key, string value){ if(!isSet) { Set(); } #if UNITY_EDITOR string[] currentKeyVals = GetTextResource(FileResource.TrilleonConfig).Split('\n'); StringBuilder textInfo = new StringBuilder(); for(int kv = 0; kv < currentKeyVals.Length; kv++) { string[] keyVal = currentKeyVals[kv].Split('='); if(keyVal.Length == 1) { textInfo.AppendLine(keyVal[0]); } else if(keyVal[0] == key) { textInfo.AppendLine(string.Format("{0}={1}", keyVal[0], value)); } else { textInfo.AppendLine(string.Format("{0}={1}", keyVal[0], keyVal[1])); } } //Overwrite and save settings to file. SaveTextResource(FileResource.TrilleonConfig, textInfo.ToString()); AssetDatabase.Refresh(); ConfigReader.Refresh(); #endif }
public static string GetNewTestObjectPath(string fileName) { return string.Format("{0}/Automation/{1}/Core/{2}/{3}.cs", Application.dataPath, ConfigReader.GetString("GAME_FOLDER_NAME"), ConfigReader.GetString("GAME_TEST_OBJECTS_FOLDER_NAME"), fileName); }
static void Set() { isSet = true; string basePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); if(Application.platform == RuntimePlatform.WindowsEditor) { if(basePath.Contains(@"\\")) { FILE_PATH_SPLIT = @"\\"; } else { FILE_PATH_SPLIT = @"\"; } } else { FILE_PATH_SPLIT = "/"; } BASE_RESOURCE_PATH = string.Format("{0}{1}Automation{1}Engine{1}Xtra{1}Resources{1}", Application.dataPath.Replace("/", FILE_PATH_SPLIT), FILE_PATH_SPLIT); knownTrilleonResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.TrilleonConfig, "TrilleonConfig")); knownTrilleonResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.ReportJavascript, ConfigReader.GetString("AUTOMATION_RESULTS_REPORT_JAVASCRIPT_USE").Replace("/", FILE_PATH_SPLIT))); knownTrilleonResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.ReportCss, ConfigReader.GetString("AUTOMATION_RESULTS_REPORT_CSS_USE").Replace("/", FILE_PATH_SPLIT))); #if UNITY_EDITOR AssetDatabase.Refresh(); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.LatestTestResults, "nexus_test_manifest_latest_test_results.txt")); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.LaunchInstructions, "nexus_test_manifest_launch_instructions.txt")); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.ManifestGUISettings, "nexus_test_manifest_categories_foldout_bools.txt")); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.BuddyHistory, "nexus_buddy_data_history.txt")); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.NexusTabs, "nexus_tab_preferences.txt")); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.Favorites, "nexus_manifest_favorites.txt")); knownEditorResourceFiles.Add(new KeyValuePair<FileResource,string>(FileResource.FavoritesUnit, "nexus_manifest_favorites_unit.txt")); BASE_NON_UNITY_PATH = string.Empty; if(Application.platform == RuntimePlatform.WindowsEditor) { BASE_NON_UNITY_PATH = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); } else { string[] pathPieces = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Split(new string[] { FILE_PATH_SPLIT }, StringSplitOptions.None); if(pathPieces.Length <= 2) { string error = string.Format("Unrecognized file path encountered. Trilleon cannot interact with local files, and will not be fully functional until the issue is corrected. Path [{0}]", basePath); AutoConsole.PostMessage(error); Debug.Log(error); return; } BASE_NON_UNITY_PATH = string.Format("/{0}/{1}", pathPieces[1], pathPieces[2]); } RESOURCES_DIRECTORY = string.Format("{0}{4}{1}{4}{2}{3}", BASE_NON_UNITY_PATH, TOP_LEVEL_FOLDER_NAME, GameMaster.GAME_NAME, ConfigReader.GetString("EDITOR_RESOURCE_FILES_DIRECTORY").Replace("/", FILE_PATH_SPLIT), FILE_PATH_SPLIT); if(!Directory.Exists(RESOURCES_DIRECTORY)) { Directory.CreateDirectory(Path.GetDirectoryName(RESOURCES_DIRECTORY)); } CONSOLE_LOG_DIRECTORY = string.Format("{0}{4}{1}{4}{2}{3}", BASE_NON_UNITY_PATH, TOP_LEVEL_FOLDER_NAME, GameMaster.GAME_NAME, ConfigReader.GetString("EDITOR_RESOURCE_CONSOLE_LOG_DIRECTORY").Replace("/", FILE_PATH_SPLIT), FILE_PATH_SPLIT); if(!Directory.Exists(CONSOLE_LOG_DIRECTORY)) { Directory.CreateDirectory(Path.GetDirectoryName(CONSOLE_LOG_DIRECTORY)); } REPORTS_DIRECTORY = string.Format("{0}{4}{1}{4}{2}{3}", BASE_NON_UNITY_PATH, TOP_LEVEL_FOLDER_NAME, GameMaster.GAME_NAME, ConfigReader.GetString("EDITOR_RESOURCE_TEST_REPORTS_DIRECTORY").Replace("/", FILE_PATH_SPLIT), FILE_PATH_SPLIT); if(!Directory.Exists(REPORTS_DIRECTORY)) { Directory.CreateDirectory(Path.GetDirectoryName(REPORTS_DIRECTORY)); } SCREENSHOTS_DIRECTORY = string.Format("{0}screenshots{1}", RESOURCES_DIRECTORY, FILE_PATH_SPLIT); if(!Directory.Exists(SCREENSHOTS_DIRECTORY)) { //This is the single report screenshot storage directory. Directory.CreateDirectory(Path.GetDirectoryName(SCREENSHOTS_DIRECTORY)); } string file = string.Format("{0}TrilleonConfig.txt", BASE_RESOURCE_PATH); FileInfo fileInfo = new FileInfo(file); fileInfo.IsReadOnly = false; file = string.Format("{0}{1}.txt", BASE_RESOURCE_PATH, ConfigReader.GetString("AUTOMATION_RESULTS_REPORT_JAVASCRIPT_USE").Replace("/", FILE_PATH_SPLIT), FILE_PATH_SPLIT); fileInfo = new FileInfo(file); fileInfo.IsReadOnly = false; file = string.Format("{0}{1}.txt", BASE_RESOURCE_PATH, ConfigReader.GetString("AUTOMATION_RESULTS_REPORT_CSS_USE").Replace("/", FILE_PATH_SPLIT)); fileInfo = new FileInfo(file); fileInfo.IsReadOnly = false; //Create any missing required files. for(int k = 0; k < knownEditorResourceFiles.Count; k++) { string fileName = string.Format("{0}{1}{2}", RESOURCES_DIRECTORY, FILE_PATH_SPLIT, knownEditorResourceFiles[k].Value); if(!Exists(fileName)) { File.WriteAllText(fileName, string.Empty); } } #endif }
public override void Render() { GUIStyle horizontal = new GUIStyle(); horizontal.margin = new RectOffset(10, 11, 0, 0); GUIStyle statusColor = new GUIStyle(GUI.skin.label); statusColor.margin = new RectOffset(0, 0, 3, 0); statusColor.normal.textColor = AutoConsole.Paused ? Color.red : Nexus.TextGreen; statusColor.fixedWidth = 125; statusColor.fontStyle = FontStyle.Bold; GUILayout.Space(15); EditorGUILayout.BeginHorizontal(horizontal); //For "Running" notification and FPS counter. if (Application.isPlaying && AutomationMaster.Busy) { EditorGUILayout.LabelField("Running Test(s)", statusColor); } else { AutomationMaster.Busy = false; EditorGUILayout.LabelField(string.Empty, statusColor); } if (Application.isPlaying) { if (renderPasses == FPS_SAMPLE_RATE && Application.isPlaying) { fpsSample = Math.Round(1 / Time.deltaTime, 0); renderPasses = 0; } GUIStyle fps = new GUIStyle(GUI.skin.label); fps.fontSize = 26; fps.padding = new RectOffset(0, 0, -8, 0); fps.normal.textColor = GetFpsColor(fpsSample); GUILayout.FlexibleSpace(); EditorGUILayout.LabelField(string.Format("FPS {0}", fpsSample), new GUILayoutOption[] { GUILayout.Width(50) }); EditorGUILayout.LabelField(string.Format("◈", fpsSample), fps, new GUILayoutOption[] { GUILayout.Width(35) }); GUILayout.Space(-18); renderPasses++; } EditorGUILayout.EndHorizontal(); //End for "Running" notification and FPS counter. GUIStyle scrollStatus = new GUIStyle(GUI.skin.button); scrollStatus.margin = new RectOffset(0, 0, 0, 0); scrollStatus.fontStyle = _autoScroll ? FontStyle.Bold : FontStyle.Normal; scrollStatus.normal.background = Swat.ToggleButtonBackgroundSelectedTexture; scrollStatus.normal.textColor = _pubsubMode ? Nexus.TextGreen : Swat.WindowDefaultTextColor; EditorGUILayout.Space(); GUILayout.BeginHorizontal(horizontal); EditorGUILayout.LabelField(string.Format("{0} - {1}", AutoConsole.Paused ? "Paused" : "Active", AutoConsole.FilterLevel == MessageLevel.Verbose ? "Verbose" : "Abridged"), statusColor); EditorGUILayout.Space(); GUILayout.Space(-100); Nexus.Self.Button("Pubsub", "Show received Pubsub messages.", new Nexus.SwatDelegate(delegate() { _pubsubMode = !_pubsubMode; }), scrollStatus, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.Space(0.65f); scrollStatus.normal.textColor = _autoScroll ? Nexus.TextGreen : Color.red; Nexus.Self.Button("Auto Scroll", "Remove all messages in the console.", new Nexus.SwatDelegate(delegate() { _autoScroll = !_autoScroll; }), scrollStatus, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.EndHorizontal(); EditorGUILayout.Space(); GUILayout.BeginHorizontal(horizontal); GUIStyle button = new GUIStyle(GUI.skin.button); button.margin = new RectOffset(0, 0, 0, 0); button.normal.textColor = Swat.ToggleButtonTextColor; button.normal.background = Swat.ToggleButtonBackgroundTexture; Nexus.Self.Button("Clear", "Remove all messages in the console.", new Nexus.SwatDelegate(delegate() { FileBroker.SaveUnboundFile(string.Format("{0}{1}{2}/console_before_start.txt", FileBroker.BASE_NON_UNITY_PATH, ConfigReader.GetString("EDITOR_RESOURCE_CONSOLE_LOG_DIRECTORY"), GameMaster.GAME_NAME), string.Empty); AutoConsole.messageListDisplayed = new List <AutoConsoleMessage>(); AutoConsole.messageListQueued = new List <AutoConsoleMessage>(); _selectedConsoleMessage = null; }), button, new GUILayoutOption[] { GUILayout.Width(60), GUILayout.Height(22) }); GUILayout.Space(0.5f); Nexus.Self.Button(AutoConsole.Paused ? "Resume" : "Pause", "Pause/Continue rendering of new messages in the console. Messages are still received and stored when paused, and will appear immediately when resuming.", new Nexus.SwatDelegate(delegate() { AutoConsole.Paused = !AutoConsole.Paused; }), button, new GUILayoutOption[] { GUILayout.Width(60), GUILayout.Height(22) }); EditorGUILayout.Space(); Nexus.Self.Button("Verbose", "Post ALL messages from the automation framework in the console.", new Nexus.SwatDelegate(delegate() { AutoConsole.FilterLevel = MessageLevel.Verbose; if (_autoScroll) { _scroll.y = 99999; _scroll.x = 0; } }), button, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.Space(0.65f); GUIStyle abridged = new GUIStyle(GUI.skin.button); abridged.margin = new RectOffset(0, 0, 0, 0); abridged.normal.textColor = Swat.ToggleButtonTextColor; abridged.normal.background = Swat.ToggleButtonBackgroundTexture; Nexus.Self.Button("Abridged", "Post only automation messages marked as high priority in the console.", new Nexus.SwatDelegate(delegate() { AutoConsole.FilterLevel = MessageLevel.Abridged; if (_autoScroll) { _scroll.y = 99999; _scroll.x = 0; } }), abridged, new GUILayoutOption[] { GUILayout.Width(75), GUILayout.Height(22) }); GUILayout.EndHorizontal(); float messageHeight = 15; GUIStyle consoleBox = new GUIStyle(GUI.skin.box); consoleBox.fixedHeight = Nexus.Self.position.height - (Application.isPlaying ? 125 : 105); consoleBox.fixedWidth = Nexus.Self.position.width - 20; consoleBox.margin = new RectOffset(10, 0, 0, 10); consoleBox.normal.background = Swat.TabButtonBackgroundTexture; GUILayout.BeginVertical(consoleBox); //Begin box border around console. _scroll = GUILayout.BeginScrollView(_scroll); GUIStyle messageBox = new GUIStyle(GUI.skin.box); messageBox.normal.background = Swat.TabButtonBackgroundSelectedTexture; messageBox.margin = new RectOffset(2, 2, 1, 1); GUIStyle messageBoxText = new GUIStyle(GUI.skin.label); messageBoxText.normal.textColor = Swat.WindowDefaultTextColor; messageBox.fixedWidth = consoleBox.fixedWidth - 10; messageBoxText.fixedWidth = messageBox.fixedWidth - 5; string lastConsoleMessage = string.Empty; int duplicateCount = 0; List <AutoConsoleMessage> consoleMessages = AutoConsole.messageListDisplayed; for (int m = 0; m < consoleMessages.Count; m++) { if ((_pubsubMode && consoleMessages[m].messageType != ConsoleMessageType.Pubsub) || (!_pubsubMode && consoleMessages[m].messageType == ConsoleMessageType.Pubsub)) { continue; } //If this is a new console message, and auto scroll is on, scroll down automatically. if (_autoScroll && m == _lastPassConsoleMessageCount) { _scroll.y = 99999; _scroll.x = 0; } //Render only messages of the requested filter level. if (_pubsubMode || (AutoConsole.FilterLevel == MessageLevel.Abridged && consoleMessages[m].level == MessageLevel.Abridged) || AutoConsole.FilterLevel == MessageLevel.Verbose) { messageBoxText.normal.textColor = AutoConsole.MessageColor(consoleMessages[m].messageType); GUILayout.BeginHorizontal(messageBox, new GUILayoutOption[] { GUILayout.MinWidth(225), GUILayout.MaxHeight(messageHeight) }); if (lastConsoleMessage == consoleMessages[m].message) { duplicateCount++; consoleMessages.RemoveAt(m - 1); } else { lastConsoleMessage = consoleMessages[m].message; duplicateCount = 0; } if (consoleMessages.Count > m) { if (GUILayout.Button(string.Format("{0} {1}", duplicateCount > 0 ?(duplicateCount + 1).ToString() : string.Empty, consoleMessages[m].message), messageBoxText)) { if (_selectedConsoleMessage == consoleMessages[m]) { //If the message has been double-clicked, open this test failure as a single-test, temporary report. if (DateTime.Now.Subtract(_lastConsoleMessageButtonClick).TotalSeconds < 0.75d && !string.IsNullOrEmpty(consoleMessages[m].testMethod)) { if (_consoleAbridgedReportTypes.Contains(consoleMessages[m].messageType)) { _selectedConsoleMessage = null; //Prevents details panel from appearing. We only want it to appear for a single click, not a double click. AutomationReport.BuildTemporaryReportForSingleConsoleFailure(consoleMessages[m].testMethod); System.Diagnostics.Process.Start(string.Format("{0}SingleTestAsReportTemp.html", FileBroker.RESOURCES_DIRECTORY)); OpenedTestReport = DateTime.UtcNow; } } else { ConsoleMessage.Pop(_selectedConsoleMessage.message, Enum.GetName(typeof(ConsoleMessageType), _selectedConsoleMessage.messageType), Enum.GetName(typeof(MessageLevel), _selectedConsoleMessage.level), _selectedConsoleMessage.timestamp.ToString()); _selectedConsoleMessage = null; } } _selectedConsoleMessage = consoleMessages[m]; _lastConsoleMessageButtonClick = DateTime.Now; } } GUILayout.EndHorizontal(); } } _lastPassConsoleMessageCount = consoleMessages.Count; GUILayout.EndScrollView(); GUILayout.EndVertical(); }
public IEnumerator RunBuddySystemTests() { //If a relationship has not yet been established, then cancel BuddySystem execution. This is not used if IgnoreAllBuddyTests flag set. BuddySystemHandlingStarted = true; _isBuddySystemFailure = string.IsNullOrEmpty(BuddyName); if (!AutomationMaster.IgnoreAllBuddyTests) { //If allowed, and Buddy is not yet set, then set Buddy to last-used Buddy. #if UNITY_EDITOR if (ConfigReader.GetBool("EDITOR_DEFAULT_BUDDY_TO_LAST")) { string mostRecentBuddy = AutomationReport.GetMostRecentBuddy(); if (!string.IsNullOrEmpty(mostRecentBuddy)) { BuddyName = mostRecentBuddy; } } #endif if (_isBuddySystemFailure) { _failureReason = "Buddy was not set before BuddySystem test execution started."; } if (!_isBuddySystemFailure) { AutoConsole.PostMessage("Establishing Connection With Buddy", MessageLevel.Abridged); do { if (RoleGridLock) { _isBuddySystemFailure = true; _failureReason = "This client and the associated Buddy client share the same role (primary/secondary). One must be a primary Buddy, and the other a secondary Buddy."; break; } SendBuddyCommunication("buddy_ready_for_tests", IsPrimary ? "primary" : "secondary"); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); time += 5; } while((!_isBuddyReadyForBuddyTests || !HasBuddyAcknowledgedOurReadiness) && time <= timeout); AutoConsole.PostMessage(time > timeout ? "Buddy Connection Failure": "Buddy Connection Established", MessageLevel.Abridged); if (IsPrimary && !BuddyTestRequiredDetails.Any()) { //If this client is the Primary, and has not yet recieved its required information from the Secondary, request it. for (int limit = 30; limit >= 0; limit--) { if (!BuddyTestRequiredDetails.Any()) { break; } SendBuddyCommunication("buddy_requesting_required_details", "0"); yield return(StartCoroutine(Q.driver.WaitRealTime(1))); } } if (time >= timeout || (IsPrimary && !BuddyTestRequiredDetails.Any())) { _isBuddySystemFailure = true; _failureReason = "Timed out waiting for Buddy to be ready for multi-client testing."; } if (!_isBuddySystemFailure) { SendBasicBuddyDetails(); if (_isPrimary) { yield return(StartCoroutine(PrimaryBuddyTestRun())); if (!_isBuddySystemFailure) { ResetBuddySystemValues(); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_switching_roles", "0"); timeout = 300; time = 0; while (!BuddyHasSuccessfullySwitchRoles && time <= timeout) { yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_primary_complete_action_tests", "0"); time += 5; } if (time > timeout) { _isBuddySystemFailure = true; _failureReason = "Timed out waiting for Buddy to switch roles from Secondary to Primary."; } else { AutoConsole.PostMessage("Switching Roles With Buddy", MessageLevel.Abridged); yield return(StartCoroutine(SecondaryBuddyTestRun())); } } } else { yield return(StartCoroutine(SecondaryBuddyTestRun())); if (!_isBuddySystemFailure) { ResetBuddySystemValues(); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_switching_roles", "0"); timeout = 300; time = 0; while (!BuddyHasSuccessfullySwitchRoles && time <= timeout) { yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_secondary_tests_complete", "0"); time += 5; } if (time > timeout) { _isBuddySystemFailure = true; _failureReason = "Timed out waiting for Buddy to switch roles from Primary to Secondary."; } else { AutoConsole.PostMessage("Switching Roles With Buddy", MessageLevel.Abridged); yield return(StartCoroutine(PrimaryBuddyTestRun())); } } } SendBuddyCommunication("buddy_tearing_down", "0"); yield return(StartCoroutine(Q.driver.WaitRealTime(5))); SendBuddyCommunication("buddy_tearing_down", "0"); } } } if (_isBuddySystemFailure || AutomationMaster.IgnoreAllBuddyTests) { //Fail all remaining tests. string errorMessage = string.Format("BuddySystem failure. Reason: {0} Skipping BuddySystem tests.", _failureReason); AutoConsole.PostMessage(errorMessage, MessageLevel.Abridged); for (int f = 0; f < _buddies.Count; f++) { if (!HandledBuddyTests.Contains(_buddies[f].Key.Key)) { AutomationMaster.CurrentTestContext = new TestContext(); if (!AutomationMaster.Methods.KeyValListContainsKey(_buddies[f].Key.Key)) { AutomationMaster.Methods.Add(new KeyValuePair <string, MethodInfo>(_buddies[f].Key.Key, Buddies[f].Key.Value)); } } yield return(StartCoroutine(Master.LaunchSingleTest(_buddies[f].Key, AutomationMaster.Methods.Count - 1, AutomationMaster.IgnoreAllBuddyTests ? TestStatus.Ignore : TestStatus.Fail, errorMessage))); for (int fr = 0; fr < _buddies[f].Value.Count; fr++) { if (HandledBuddyTests.Contains(Buddies[f].Value[fr].Value.Name)) { continue; } AutomationMaster.CurrentTestContext = new TestContext(); if (!AutomationMaster.Methods.KeyValListContainsKey(_buddies[f].Value[fr].Key)) { AutomationMaster.Methods.Add(new KeyValuePair <string, MethodInfo>(_buddies[f].Value[fr].Key, Buddies[f].Value[fr].Value)); } yield return(StartCoroutine(Master.LaunchSingleTest(_buddies[f].Value[fr], AutomationMaster.Methods.Count - 1, AutomationMaster.IgnoreAllBuddyTests ? TestStatus.Ignore : TestStatus.Fail, errorMessage))); } } } HandledBuddyTests = new List <string>(); ResetBuddySystemValues(); yield return(null); }