A game about forced loneliness, made by TACStudios
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEditor.TestRunner.TestLaunchers; 5using UnityEditor.TestTools.TestRunner.Api; 6using UnityEngine; 7 8namespace UnityEditor.TestTools.TestRunner.CommandLineTest 9{ 10 internal class Executer : IExecuter 11 { 12 internal IRunData runData = RunData.instance; 13 14 private ITestRunnerApi m_TestRunnerApi; 15 private ISettingsBuilder m_SettingsBuilder; 16 private Action<string, object[]> m_LogErrorFormat; 17 private Action<Exception> m_LogException; 18 private Action<string> m_LogMessage; 19 private Action<int> m_ExitEditorApplication; 20 private Func<bool> m_ScriptCompilationFailedCheck; 21 private Func<bool> m_IsRunActive; 22 23 public Executer(ITestRunnerApi testRunnerApi, ISettingsBuilder settingsBuilder, Action<string, object[]> logErrorFormat, Action<Exception> logException, Action<string> logMessage, Action<int> exitEditorApplication, Func<bool> scriptCompilationFailedCheck, Func<bool> isRunActive) 24 { 25 m_TestRunnerApi = testRunnerApi; 26 m_SettingsBuilder = settingsBuilder; 27 m_LogErrorFormat = logErrorFormat; 28 m_LogException = logException; 29 m_LogMessage = logMessage; 30 m_ExitEditorApplication = exitEditorApplication; 31 m_ScriptCompilationFailedCheck = scriptCompilationFailedCheck; 32 m_IsRunActive = isRunActive; 33 } 34 35 public string InitializeAndExecuteRun(string[] commandLineArgs) 36 { 37 Api.ExecutionSettings executionSettings; 38 try 39 { 40 executionSettings = m_SettingsBuilder.BuildApiExecutionSettings(commandLineArgs); 41 if (executionSettings.targetPlatform.HasValue) 42 RemotePlayerLogController.instance.SetBuildTarget(executionSettings.targetPlatform.Value); 43 } 44 catch (SetupException exception) 45 { 46 HandleSetupException(exception); 47 return string.Empty; 48 } 49 50 try 51 { 52 // It is important that the message starts with "Running tests for ", otherwise TestCleanConsole will fail. 53 m_LogMessage($"Running tests for {executionSettings}"); 54 return m_TestRunnerApi.Execute(executionSettings); 55 } 56 catch (Exception exception) 57 { 58 m_LogException(exception); 59 ExitApplication(ReturnCodes.RunError, "Exception when starting test run."); 60 return string.Empty; 61 } 62 } 63 64 public void ExitIfRunIsCompleted() 65 { 66 if (m_IsRunActive()) 67 { 68 return; 69 } 70 71 var runState = runData.RunState; 72 var returnCode = s_StateReturnCodes[runState]; 73 var reason = s_StateMessages[runState] ?? runData.RunErrorMessage; 74 ExitApplication(returnCode, reason); 75 } 76 77 private void ExitApplication(ReturnCodes returnCode, string reason) 78 { 79 var returnCodeInt = (int)returnCode; 80 81 m_LogMessage($"Test run completed. Exiting with code {returnCodeInt} ({returnCode}). {reason}"); 82 83 m_ExitEditorApplication(returnCodeInt); 84 } 85 86 public ExecutionSettings BuildExecutionSettings(string[] commandLineArgs) 87 { 88 return m_SettingsBuilder.BuildExecutionSettings(commandLineArgs); 89 } 90 91 internal enum ReturnCodes 92 { 93 Ok = 0, 94 Failed = 2, 95 RunError = 3, 96 PlatformNotFoundReturnCode = 4 97 } 98 99 public void SetUpCallbacks(ExecutionSettings executionSettings) 100 { 101 RemotePlayerLogController.instance.SetLogsDirectory(executionSettings.DeviceLogsDirectory); 102 103 var resultSavingCallback = ScriptableObject.CreateInstance<ResultsSavingCallbacks>(); 104 resultSavingCallback.m_ResultFilePath = executionSettings.TestResultsFile; 105 106 var logSavingCallback = ScriptableObject.CreateInstance<LogSavingCallbacks>(); 107 108 TestRunnerApi.RegisterTestCallback(resultSavingCallback); 109 TestRunnerApi.RegisterTestCallback(logSavingCallback); 110 TestRunnerApi.RegisterTestCallback(new RunStateCallbacks()); 111 } 112 113 public void ExitOnCompileErrors() 114 { 115 if (m_ScriptCompilationFailedCheck()) 116 { 117 var handling = s_ExceptionHandlingMapping.First(h => h.m_ExceptionType == SetupException.ExceptionType.ScriptCompilationFailed); 118 m_LogErrorFormat(handling.m_Message, new object[0]); 119 ExitApplication(handling.m_ReturnCode, handling.m_Message); 120 } 121 } 122 123 private void HandleSetupException(SetupException exception) 124 { 125 ExceptionHandling handling = s_ExceptionHandlingMapping.FirstOrDefault(h => h.m_ExceptionType == exception.Type) ?? new ExceptionHandling(exception.Type, "Unknown command line test run error. " + exception.Type, ReturnCodes.RunError); 126 m_LogErrorFormat(handling.m_Message, exception.Details); 127 ExitApplication(handling.m_ReturnCode, handling.m_Message); 128 } 129 130 private class ExceptionHandling 131 { 132 internal SetupException.ExceptionType m_ExceptionType; 133 internal string m_Message; 134 internal ReturnCodes m_ReturnCode; 135 public ExceptionHandling(SetupException.ExceptionType exceptionType, string message, ReturnCodes returnCode) 136 { 137 m_ExceptionType = exceptionType; 138 m_Message = message; 139 m_ReturnCode = returnCode; 140 } 141 } 142 143 private static ExceptionHandling[] s_ExceptionHandlingMapping = { 144 new ExceptionHandling(SetupException.ExceptionType.ScriptCompilationFailed, "Scripts had compilation errors.", ReturnCodes.RunError), 145 new ExceptionHandling(SetupException.ExceptionType.PlatformNotFound, "Test platform not found ({0}).", ReturnCodes.PlatformNotFoundReturnCode), 146 new ExceptionHandling(SetupException.ExceptionType.TestSettingsFileNotFound, "Test settings file not found at {0}.", ReturnCodes.RunError), 147 new ExceptionHandling(SetupException.ExceptionType.OrderedTestListFileNotFound, "Ordered test list file not found at {0}.", ReturnCodes.RunError) 148 }; 149 150 private static IDictionary<TestRunState, string> s_StateMessages = new Dictionary<TestRunState, string>() 151 { 152 {TestRunState.NoCallbacksReceived, "No callbacks received."}, 153 {TestRunState.OneOrMoreTestsExecutedWithNoFailures, "Run completed."}, 154 {TestRunState.OneOrMoreTestsExecutedWithOneOrMoreFailed, "One or more tests failed."}, 155 {TestRunState.CompletedJobWithoutAnyTestsExecuted, "No tests were executed."}, 156 {TestRunState.RunError, null} 157 }; 158 159 private static IDictionary<TestRunState, ReturnCodes> s_StateReturnCodes = new Dictionary<TestRunState, ReturnCodes>() 160 { 161 {TestRunState.NoCallbacksReceived, ReturnCodes.RunError}, 162 {TestRunState.OneOrMoreTestsExecutedWithNoFailures, ReturnCodes.Ok}, 163 {TestRunState.OneOrMoreTestsExecutedWithOneOrMoreFailed, ReturnCodes.Failed}, 164 {TestRunState.CompletedJobWithoutAnyTestsExecuted, ReturnCodes.Ok}, 165 {TestRunState.RunError, ReturnCodes.RunError} 166 }; 167 } 168}