From 6e80295ec7437c667f3da6641305d3dc0f01c1a0 Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 5 May 2020 05:22:49 +0900 Subject: [PATCH] add PlayerLoopTiming.Last*** --- .../Editor/UnitTestBuilder.MenuItems.cs | 32 +- .../Editor/UnitTestBuilder.cs | 41 +- .../RuntimeUnitTestToolkit/UnitTestRunner.cs | 374 ++++++++++++++---- Assets/RuntimeUnitTestToolkit/package.json | 4 +- Assets/Scenes/SandboxMain.cs | 86 +++- Assets/UniRx.Async/PlayerLoopHelper.cs | 144 +++++-- .../MonoBehaviourMessagesTriggers.cs.meta | 11 + .../MonoBehaviourMessagesTriggers.tt.meta | 7 + .../UniRx.Async/UnityAsyncExtensions.cs.meta | 11 + .../UniRx.Async/UnityAsyncExtensions.tt.meta | 7 + 10 files changed, 598 insertions(+), 119 deletions(-) create mode 100644 Assets/UniRx.Async/Triggers/MonoBehaviourMessagesTriggers.cs.meta create mode 100644 Assets/UniRx.Async/Triggers/MonoBehaviourMessagesTriggers.tt.meta create mode 100644 Assets/UniRx.Async/UnityAsyncExtensions.cs.meta create mode 100644 Assets/UniRx.Async/UnityAsyncExtensions.tt.meta diff --git a/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.MenuItems.cs b/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.MenuItems.cs index cef082e..94508b5 100644 --- a/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.MenuItems.cs +++ b/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.MenuItems.cs @@ -169,21 +169,25 @@ Switch, SaveSettings(settings); } - //[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = true, priority = 3)] - //static bool ValidateBuildTargetStandaloneLinux() - //{ - // Menu.SetChecked("Test/Settings/BuildTarget/StandaloneLinux", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneLinux); - // return true; - //} +#if !UNITY_2019_2_OR_NEWER - //[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = false, priority = 3)] - //static void BuildTargetStandaloneLinux() - //{ - // var settings = LoadOrGetDefaultSettings(); - // settings.UseCurrentBuildTarget = false; - // settings.BuildTarget = BuildTarget.StandaloneLinux; - // SaveSettings(settings); - //} + [MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = true, priority = 3)] + static bool ValidateBuildTargetStandaloneLinux() + { + Menu.SetChecked("Test/Settings/BuildTarget/StandaloneLinux", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneLinux); + return true; + } + + [MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = false, priority = 3)] + static void BuildTargetStandaloneLinux() + { + var settings = LoadOrGetDefaultSettings(); + settings.UseCurrentBuildTarget = false; + settings.BuildTarget = BuildTarget.StandaloneLinux; + SaveSettings(settings); + } + +#endif [MenuItem("Test/Settings/BuildTarget/StandaloneLinux64", validate = true, priority = 4)] static bool ValidateBuildTargetStandaloneLinux64() diff --git a/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.cs b/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.cs index 8ca1068..ca45d0b 100644 --- a/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.cs +++ b/Assets/RuntimeUnitTestToolkit/Editor/UnitTestBuilder.cs @@ -1,4 +1,4 @@ -#if UNITY_EDITOR +#if UNITY_EDITOR using RuntimeUnitTestToolkit; using RuntimeUnitTestToolkit.Editor; @@ -118,7 +118,7 @@ public static partial class UnitTestBuilder if (buildPath == null) { - buildPath = $"bin/UnitTest/{settings.BuildTarget}_{settings.ScriptBackend}/test" + (IsWindows(settings.BuildTarget) ? ".exe" : ""); + buildPath = $"bin/UnitTest/{settings.BuildTarget}_{settings.ScriptBackend}/test" + GetExtensionForBuildTarget(settings.BuildTarget); } var originalScene = SceneManager.GetActiveScene().path; @@ -136,6 +136,15 @@ public static partial class UnitTestBuilder } } + + [MenuItem("Test/LoadUnitTestScene")] + public static void LoadUnitTestScene() + { + var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); + BuildUnitTestRunnerScene(); + EditorSceneManager.MarkSceneDirty(scene); + } + static RuntimeUnitTestSettings LoadOrGetDefaultSettings() { var key = SettingsKeyBase + Application.productName; @@ -448,20 +457,42 @@ public static partial class UnitTestBuilder } } + static string GetExtensionForBuildTarget(BuildTarget buildTarget) + { + switch (buildTarget) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + case BuildTarget.WSAPlayer: + return ".exe"; + case BuildTarget.StandaloneOSX: + return ".app"; + case BuildTarget.Android: + return ".apk"; + default: + return ""; + } + } + static BuildTargetGroup ToBuildTargetGroup(BuildTarget buildTarget) { #pragma warning disable CS0618 switch (buildTarget) { +#if UNITY_2017_3_OR_NEWER case BuildTarget.StandaloneOSX: - case (BuildTarget)3: +#else case BuildTarget.StandaloneOSXIntel: case BuildTarget.StandaloneOSXIntel64: + case BuildTarget.StandaloneOSXUniversal: +#endif // UNITY_2017_3_OR_NEWER case BuildTarget.StandaloneWindows: case BuildTarget.StandaloneWindows64: - case BuildTarget.StandaloneLinux: case BuildTarget.StandaloneLinux64: +#if !UNITY_2019_2_OR_NEWER + case BuildTarget.StandaloneLinux: case BuildTarget.StandaloneLinuxUniversal: +#endif // !UNITY_2019_2_OR_NEWER return BuildTargetGroup.Standalone; case (BuildTarget)6: case (BuildTarget)7: @@ -512,4 +543,4 @@ public static partial class UnitTestBuilder } } -#endif \ No newline at end of file +#endif diff --git a/Assets/RuntimeUnitTestToolkit/UnitTestRunner.cs b/Assets/RuntimeUnitTestToolkit/UnitTestRunner.cs index ff7041c..8637876 100644 --- a/Assets/RuntimeUnitTestToolkit/UnitTestRunner.cs +++ b/Assets/RuntimeUnitTestToolkit/UnitTestRunner.cs @@ -14,7 +14,7 @@ namespace RuntimeUnitTestToolkit public class UnitTestRunner : MonoBehaviour { // object is IEnumerator or Func - Dictionary>> tests = new Dictionary>>(); + Dictionary> tests = new Dictionary>(); List additionalActionsOnFirst = new List(); @@ -30,6 +30,7 @@ namespace RuntimeUnitTestToolkit readonly Color normalColor = new Color(1f, 1f, 1f, 1f); // white bool allTestGreen = true; + bool logClear = false; void Start() { @@ -37,7 +38,15 @@ namespace RuntimeUnitTestToolkit { UnityEngine.Application.logMessageReceived += (a, b, c) => { - logText.text += "[" + c + "]" + a + "\n"; + if (a.Contains("Mesh can not have more than 65000 vertices")) + { + logClear = true; + } + else + { + AppendToGraphicText("[" + c + "]" + a + "\n"); + WriteToConsole("[" + c + "]" + a); + } }; // register all test types @@ -133,13 +142,34 @@ namespace RuntimeUnitTestToolkit { foreach (var method in item.GetMethods()) { - var t1 = method.GetCustomAttribute(true); + TestAttribute t1 = null; + try + { + t1 = method.GetCustomAttribute(true); + } + catch (Exception ex) + { + Debug.Log("TestAttribute Load Fail, Assembly:" + assembly.FullName); + Debug.LogException(ex); + goto NEXT_ASSEMBLY; + } if (t1 != null) { yield return item; break; } - var t2 = method.GetCustomAttribute(true); + + UnityTestAttribute t2 = null; + try + { + t2 = method.GetCustomAttribute(true); + } + catch (Exception ex) + { + Debug.Log("UnityTestAttribute Load Fail, Assembly:" + assembly.FullName); + Debug.LogException(ex); + goto NEXT_ASSEMBLY; + } if (t2 != null) { yield return item; @@ -147,31 +177,34 @@ namespace RuntimeUnitTestToolkit } } } + +NEXT_ASSEMBLY: + continue; } } - public void AddTest(string group, string title, Action test) + public void AddTest(string group, string title, Action test, List setups, List teardowns) { - List> list; + List list; if (!tests.TryGetValue(group, out list)) { - list = new List>(); + list = new List(); tests[group] = list; } - list.Add(new KeyValuePair(title, test)); + list.Add(new TestKeyValuePair(title, test, setups, teardowns)); } - public void AddAsyncTest(string group, string title, Func asyncTestCoroutine) + public void AddAsyncTest(string group, string title, Func asyncTestCoroutine, List setups, List teardowns) { - List> list; + List list; if (!tests.TryGetValue(group, out list)) { - list = new List>(); + list = new List(); tests[group] = list; } - list.Add(new KeyValuePair(title, asyncTestCoroutine)); + list.Add(new TestKeyValuePair(title, asyncTestCoroutine, setups, teardowns)); } public void AddCutomAction(string name, UnityAction action) @@ -193,6 +226,29 @@ namespace RuntimeUnitTestToolkit var test = Activator.CreateInstance(testType); var methods = testType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + List setups = new List(); + List teardowns = new List(); + foreach (var item in methods) + { + try + { + var setup = item.GetCustomAttribute(true); + if (setup != null) + { + setups.Add((Action)Delegate.CreateDelegate(typeof(Action), test, item)); + } + var teardown = item.GetCustomAttribute(true); + if (teardown != null) + { + teardowns.Add((Action)Delegate.CreateDelegate(typeof(Action), test, item)); + } + } + catch (Exception e) + { + UnityEngine.Debug.LogError(testType.Name + "." + item.Name + " failed to register setup/teardown method, exception: " + e.ToString()); + } + } + foreach (var item in methods) { try @@ -203,11 +259,34 @@ namespace RuntimeUnitTestToolkit if (item.GetParameters().Length == 0 && item.ReturnType == typeof(IEnumerator)) { var factory = (Func)Delegate.CreateDelegate(typeof(Func), test, item); - AddAsyncTest(factory.Target.GetType().Name, factory.Method.Name, factory); + AddAsyncTest(factory.Target.GetType().Name, factory.Method.Name, factory, setups, teardowns); } else { - UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter or return type is invalid)."); + var testData = GetTestData(item); + if (testData.Count != 0) + { + foreach (var item2 in testData) + { + Func factory; + if (item.IsGenericMethod) + { + var method2 = InferGenericType(item, item2); + factory = () => (IEnumerator)method2.Invoke(test, item2); + } + else + { + factory = () => (IEnumerator)item.Invoke(test, item2); + } + var name = item.Name + "(" + string.Join(", ", item2.Select(x => x?.ToString() ?? "null")) + ")"; + name = name.Replace(Char.MinValue, ' ').Replace(Char.MaxValue, ' ').Replace("<", "[").Replace(">", "]"); + AddAsyncTest(test.GetType().Name, name, factory, setups, teardowns); + } + } + else + { + UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter without TestCase or return type is invalid)."); + } } } @@ -217,11 +296,34 @@ namespace RuntimeUnitTestToolkit if (item.GetParameters().Length == 0 && item.ReturnType == typeof(void)) { var invoke = (Action)Delegate.CreateDelegate(typeof(Action), test, item); - AddTest(invoke.Target.GetType().Name, invoke.Method.Name, invoke); + AddTest(invoke.Target.GetType().Name, invoke.Method.Name, invoke, setups, teardowns); } else { - UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter or return type is invalid)."); + var testData = GetTestData(item); + if (testData.Count != 0) + { + foreach (var item2 in testData) + { + Action invoke = null; + if (item.IsGenericMethod) + { + var method2 = InferGenericType(item, item2); + invoke = () => method2.Invoke(test, item2); + } + else + { + invoke = () => item.Invoke(test, item2); + } + var name = item.Name + "(" + string.Join(", ", item2.Select(x => x?.ToString() ?? "null")) + ")"; + name = name.Replace(Char.MinValue, ' ').Replace(Char.MaxValue, ' ').Replace("<", "[").Replace(">", "]"); + AddTest(test.GetType().Name, name, invoke, setups, teardowns); + } + } + else + { + UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter without TestCase or return type is invalid)."); + } } } } @@ -237,6 +339,88 @@ namespace RuntimeUnitTestToolkit } } + List GetTestData(MethodInfo methodInfo) + { + List testCases = new List(); + + var inlineData = methodInfo.GetCustomAttributes(true); + foreach (var item in inlineData) + { + testCases.Add(item.Arguments); + } + + var sourceData = methodInfo.GetCustomAttributes(true); + foreach (var item in sourceData) + { + var enumerator = GetTestCaseSource(methodInfo, item.SourceType, item.SourceName, item.MethodParams); + foreach (var item2 in enumerator) + { + var item3 = item2 as IEnumerable; // object[][] + if (item3 != null) + { + var l = new List(); + foreach (var item4 in item3) + { + l.Add(item4); + } + testCases.Add(l.ToArray()); + } + } + } + + return testCases; + } + + IEnumerable GetTestCaseSource(MethodInfo method, Type sourceType, string sourceName, object[] methodParams) + { + Type type = sourceType ?? method.DeclaringType; + + MemberInfo[] member = type.GetMember(sourceName, BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); + if (member.Length == 1) + { + MemberInfo memberInfo = member[0]; + FieldInfo fieldInfo = memberInfo as FieldInfo; + if ((object)fieldInfo != null) + { + return (!fieldInfo.IsStatic) ? ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.") : ((methodParams == null) ? ((IEnumerable)fieldInfo.GetValue(null)) : ReturnErrorAsParameter("You have specified a data source field but also given a set of parameters. Fields cannot take parameters, please revise the 3rd parameter passed to the TestCaseSourceAttribute and either remove it or specify a method.")); + } + PropertyInfo propertyInfo = memberInfo as PropertyInfo; + if ((object)propertyInfo != null) + { + return (!propertyInfo.GetGetMethod(nonPublic: true).IsStatic) ? ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.") : ((methodParams == null) ? ((IEnumerable)propertyInfo.GetValue(null, null)) : ReturnErrorAsParameter("You have specified a data source property but also given a set of parameters. Properties cannot take parameters, please revise the 3rd parameter passed to the TestCaseSource attribute and either remove it or specify a method.")); + } + MethodInfo methodInfo = memberInfo as MethodInfo; + if ((object)methodInfo != null) + { + return (!methodInfo.IsStatic) ? ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.") : ((methodParams == null || methodInfo.GetParameters().Length == methodParams.Length) ? ((IEnumerable)methodInfo.Invoke(null, methodParams)) : ReturnErrorAsParameter("You have given the wrong number of arguments to the method in the TestCaseSourceAttribute, please check the number of parameters passed in the object is correct in the 3rd parameter for the TestCaseSourceAttribute and this matches the number of parameters in the target method and try again.")); + } + } + return null; + } + + MethodInfo InferGenericType(MethodInfo methodInfo, object[] parameters) + { + var set = new HashSet(); + List genericParameters = new List(); + foreach (var item in methodInfo.GetParameters() + .Select((x, i) => new { x.ParameterType, i }) + .Where(x => x.ParameterType.IsGenericParameter) + .OrderBy(x => x.ParameterType.GenericParameterPosition)) + { + if (set.Add(item.ParameterType)) // DistinctBy + { + genericParameters.Add(parameters[item.i].GetType()); + } + } + + return methodInfo.MakeGenericMethod(genericParameters.ToArray()); + } + + IEnumerable ReturnErrorAsParameter(string name) + { + throw new Exception(name); + } + System.Collections.IEnumerator ScrollLogToEndNextFrame() { yield return null; @@ -244,7 +428,7 @@ namespace RuntimeUnitTestToolkit logScrollBar.value = 0; } - IEnumerator RunTestInCoroutine(KeyValuePair>> actionList) + IEnumerator RunTestInCoroutine(KeyValuePair> actionList) { Button self = null; foreach (var btn in list.GetComponentsInChildren