add PlayerLoopTiming.Last***
parent
75f0bd26e7
commit
6e80295ec7
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace RuntimeUnitTestToolkit
|
|||
public class UnitTestRunner : MonoBehaviour
|
||||
{
|
||||
// object is IEnumerator or Func<IEnumerator>
|
||||
Dictionary<string, List<KeyValuePair<string, object>>> tests = new Dictionary<string, List<KeyValuePair<string, object>>>();
|
||||
Dictionary<string, List<TestKeyValuePair>> tests = new Dictionary<string, List<TestKeyValuePair>>();
|
||||
|
||||
List<Pair> additionalActionsOnFirst = new List<Pair>();
|
||||
|
||||
|
@ -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<TestAttribute>(true);
|
||||
TestAttribute t1 = null;
|
||||
try
|
||||
{
|
||||
t1 = method.GetCustomAttribute<TestAttribute>(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<UnityTestAttribute>(true);
|
||||
|
||||
UnityTestAttribute t2 = null;
|
||||
try
|
||||
{
|
||||
t2 = method.GetCustomAttribute<UnityTestAttribute>(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<Action> setups, List<Action> teardowns)
|
||||
{
|
||||
List<KeyValuePair<string, object>> list;
|
||||
List<TestKeyValuePair> list;
|
||||
if (!tests.TryGetValue(group, out list))
|
||||
{
|
||||
list = new List<KeyValuePair<string, object>>();
|
||||
list = new List<TestKeyValuePair>();
|
||||
tests[group] = list;
|
||||
}
|
||||
|
||||
list.Add(new KeyValuePair<string, object>(title, test));
|
||||
list.Add(new TestKeyValuePair(title, test, setups, teardowns));
|
||||
}
|
||||
|
||||
public void AddAsyncTest(string group, string title, Func<IEnumerator> asyncTestCoroutine)
|
||||
public void AddAsyncTest(string group, string title, Func<IEnumerator> asyncTestCoroutine, List<Action> setups, List<Action> teardowns)
|
||||
{
|
||||
List<KeyValuePair<string, object>> list;
|
||||
List<TestKeyValuePair> list;
|
||||
if (!tests.TryGetValue(group, out list))
|
||||
{
|
||||
list = new List<KeyValuePair<string, object>>();
|
||||
list = new List<TestKeyValuePair>();
|
||||
tests[group] = list;
|
||||
}
|
||||
|
||||
list.Add(new KeyValuePair<string, object>(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<Action> setups = new List<Action>();
|
||||
List<Action> teardowns = new List<Action>();
|
||||
foreach (var item in methods)
|
||||
{
|
||||
try
|
||||
{
|
||||
var setup = item.GetCustomAttribute<NUnit.Framework.SetUpAttribute>(true);
|
||||
if (setup != null)
|
||||
{
|
||||
setups.Add((Action)Delegate.CreateDelegate(typeof(Action), test, item));
|
||||
}
|
||||
var teardown = item.GetCustomAttribute<NUnit.Framework.TearDownAttribute>(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<IEnumerator>)Delegate.CreateDelegate(typeof(Func<IEnumerator>), 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<IEnumerator> 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<object[]> GetTestData(MethodInfo methodInfo)
|
||||
{
|
||||
List<object[]> testCases = new List<object[]>();
|
||||
|
||||
var inlineData = methodInfo.GetCustomAttributes<NUnit.Framework.TestCaseAttribute>(true);
|
||||
foreach (var item in inlineData)
|
||||
{
|
||||
testCases.Add(item.Arguments);
|
||||
}
|
||||
|
||||
var sourceData = methodInfo.GetCustomAttributes<NUnit.Framework.TestCaseSourceAttribute>(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<object>();
|
||||
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<Type>();
|
||||
List<Type> genericParameters = new List<Type>();
|
||||
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<string, List<KeyValuePair<string, object>>> actionList)
|
||||
IEnumerator RunTestInCoroutine(KeyValuePair<string, List<TestKeyValuePair>> actionList)
|
||||
{
|
||||
Button self = null;
|
||||
foreach (var btn in list.GetComponentsInChildren<Button>())
|
||||
|
@ -259,19 +443,27 @@ namespace RuntimeUnitTestToolkit
|
|||
|
||||
var allGreen = true;
|
||||
|
||||
logText.text += "<color=yellow>" + actionList.Key + "</color>\n";
|
||||
AppendToGraphicText("<color=yellow>" + actionList.Key + "</color>\n");
|
||||
WriteToConsole("Begin Test Class: " + actionList.Key);
|
||||
yield return null;
|
||||
|
||||
var totalExecutionTime = new List<double>();
|
||||
foreach (var item2 in actionList.Value)
|
||||
{
|
||||
// setup
|
||||
try
|
||||
{
|
||||
foreach (var setup in item2.Setups)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
// before start, cleanup
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
logText.text += "<color=teal>" + item2.Key + "</color>\n";
|
||||
AppendToGraphicText("<color=teal>" + item2.Key + "</color>\n");
|
||||
yield return null;
|
||||
|
||||
var v = item2.Value;
|
||||
|
@ -309,27 +501,31 @@ namespace RuntimeUnitTestToolkit
|
|||
}));
|
||||
}
|
||||
}
|
||||
|
||||
methodStopwatch.Stop();
|
||||
totalExecutionTime.Add(methodStopwatch.Elapsed.TotalMilliseconds);
|
||||
if (exception == null)
|
||||
{
|
||||
logText.text += "OK, " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms\n";
|
||||
AppendToGraphicText("OK, " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms\n");
|
||||
WriteToConsoleResult(item2.Key + ", " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// found match line...
|
||||
var line = string.Join("\n", exception.StackTrace.Split('\n').Where(x => x.Contains(actionList.Key) || x.Contains(item2.Key)).ToArray());
|
||||
logText.text += "<color=red>" + exception.Message + "\n" + line + "</color>\n";
|
||||
WriteToConsoleResult(item2.Key + ", " + exception.Message, false);
|
||||
WriteToConsole(line);
|
||||
AppendToGraphicText("<color=red>" + exception.ToString() + "</color>\n");
|
||||
WriteToConsoleResult(item2.Key + ", " + exception.ToString(), false);
|
||||
allGreen = false;
|
||||
allTestGreen = false;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var teardown in item2.Teardowns)
|
||||
{
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logText.text += "[" + actionList.Key + "]" + totalExecutionTime.Sum().ToString("0.00") + "ms\n\n";
|
||||
AppendToGraphicText("[" + actionList.Key + "]" + totalExecutionTime.Sum().ToString("0.00") + "ms\n\n");
|
||||
foreach (var btn in list.GetComponentsInChildren<Button>()) btn.interactable = true;
|
||||
if (self != null)
|
||||
{
|
||||
|
@ -418,6 +614,27 @@ namespace RuntimeUnitTestToolkit
|
|||
}
|
||||
}
|
||||
|
||||
void AppendToGraphicText(string msg)
|
||||
{
|
||||
if (!Application.isBatchMode)
|
||||
{
|
||||
if (logClear)
|
||||
{
|
||||
logText.text = "";
|
||||
logClear = false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
logText.text += msg;
|
||||
}
|
||||
catch
|
||||
{
|
||||
logClear = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteToConsoleResult(string msg, bool green)
|
||||
{
|
||||
if (Application.isBatchMode)
|
||||
|
@ -447,4 +664,21 @@ namespace RuntimeUnitTestToolkit
|
|||
public UnityAction Action;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestKeyValuePair
|
||||
{
|
||||
public string Key;
|
||||
/// <summary>IEnumerator or Func[IEnumerator]</summary>
|
||||
public object Value;
|
||||
public List<Action> Setups;
|
||||
public List<Action> Teardowns;
|
||||
|
||||
public TestKeyValuePair(string key, object value, List<Action> setups, List<Action> teardowns)
|
||||
{
|
||||
this.Key = key;
|
||||
this.Value = value;
|
||||
this.Setups = setups;
|
||||
this.Teardowns = teardowns;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "jp.cysharp.runtimeunittesttoolkit",
|
||||
"name": "com.cysharp.runtimeunittesttoolkit",
|
||||
"displayName": "RuntimeUnitTestToolkit",
|
||||
"version": "2.0.0",
|
||||
"version": "2.3.0",
|
||||
"unity": "2018.3",
|
||||
"description": "CLI/GUI Frontend of Unity Test Runner to test on any platform.",
|
||||
"keywords": ["test"],
|
||||
|
|
|
@ -22,6 +22,17 @@ public class SandboxMain : MonoBehaviour
|
|||
|
||||
void Start()
|
||||
{
|
||||
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetCurrentPlayerLoop();
|
||||
ShowPlayerLoop.DumpPlayerLoop("Current", playerLoop);
|
||||
|
||||
//for (int i = 0; i < 14; i++)
|
||||
//{
|
||||
// TimingDump((PlayerLoopTiming)i).Forget();
|
||||
//}
|
||||
|
||||
//StartCoroutine(CoroutineDump("yield WaitForEndOfFrame", new WaitForEndOfFrame()));
|
||||
//StartCoroutine(CoroutineDump("yield WaitForFixedUpdate", new WaitForFixedUpdate()));
|
||||
//StartCoroutine(CoroutineDump("yield null", null));
|
||||
|
||||
// -----
|
||||
|
||||
|
@ -45,6 +56,40 @@ public class SandboxMain : MonoBehaviour
|
|||
});
|
||||
}
|
||||
|
||||
async UniTask TimingDump(PlayerLoopTiming timing)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await UniTask.Yield(timing);
|
||||
Debug.Log("PlayerLoopTiming." + timing);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator CoroutineDump(string msg, YieldInstruction waitObj)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
yield return waitObj;
|
||||
Debug.Log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
//private void Update()
|
||||
//{
|
||||
// Debug.Log("Update");
|
||||
//}
|
||||
|
||||
//private void LateUpdate()
|
||||
//{
|
||||
// Debug.Log("LateUpdate");
|
||||
//}
|
||||
|
||||
//private void FixedUpdate()
|
||||
//{
|
||||
// Debug.Log("FixedUpdate");
|
||||
//}
|
||||
|
||||
|
||||
private void Application_logMessageReceived(string condition, string stackTrace, LogType type)
|
||||
{
|
||||
text.text += "\n" + condition;
|
||||
|
@ -79,9 +124,33 @@ public class SandboxMain : MonoBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
PlayerLoopTiming.Initialization
|
||||
PlayerLoopTiming.LastInitialization
|
||||
PlayerLoopTiming.EarlyUpdate
|
||||
PlayerLoopTiming.LastEarlyUpdate
|
||||
PlayerLoopTiming.PreUpdate
|
||||
PlayerLoopTiming.LastPreUpdate
|
||||
PlayerLoopTiming.Update
|
||||
Update
|
||||
yield null
|
||||
yield WaitForSeconds
|
||||
yield WWW
|
||||
yield StartCoroutine
|
||||
PlayerLoopTiming.LastUpdate
|
||||
PlayerLoopTiming.PreLateUpdate
|
||||
LateUpdate
|
||||
PlayerLoopTiming.LastPreLateUpdate
|
||||
PlayerLoopTiming.PostLateUpdate
|
||||
PlayerLoopTiming.LastPostLateUpdate
|
||||
yield WaitForEndOfFrame
|
||||
|
||||
|
||||
|
||||
// --- Physics Loop
|
||||
PlayerLoopTiming.FixedUpdate
|
||||
FixedUpdate
|
||||
yield WaitForFixedUpdate
|
||||
PlayerLoopTiming.LastFixedUpdate
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
@ -114,13 +183,17 @@ public class SandboxMain : MonoBehaviour
|
|||
|
||||
public class ShowPlayerLoop
|
||||
{
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
static void Init()
|
||||
{
|
||||
var playerLoop = UnityEngine.LowLevel.PlayerLoop.GetDefaultPlayerLoop();
|
||||
DumpPlayerLoop("Default", playerLoop);
|
||||
}
|
||||
|
||||
public static void DumpPlayerLoop(string which, UnityEngine.LowLevel.PlayerLoopSystem playerLoop)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Default Playerloop List");
|
||||
sb.AppendLine($"{which} PlayerLoop List");
|
||||
foreach (var header in playerLoop.subSystemList)
|
||||
{
|
||||
sb.AppendFormat("------{0}------", header.type.Name);
|
||||
|
@ -129,6 +202,11 @@ public class ShowPlayerLoop
|
|||
{
|
||||
sb.AppendFormat("{0}.{1}", header.type.Name, subSystem.type.Name);
|
||||
sb.AppendLine();
|
||||
|
||||
if (subSystem.subSystemList != null)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("More Subsystem:" + subSystem.subSystemList.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,16 @@ namespace UniRx.Async
|
|||
public struct UniTaskLoopRunnerPreLateUpdate { };
|
||||
public struct UniTaskLoopRunnerPostLateUpdate { };
|
||||
|
||||
// Last
|
||||
|
||||
public struct UniTaskLoopRunnerLastInitialization { };
|
||||
public struct UniTaskLoopRunnerLastEarlyUpdate { };
|
||||
public struct UniTaskLoopRunnerLastFixedUpdate { };
|
||||
public struct UniTaskLoopRunnerLastPreUpdate { };
|
||||
public struct UniTaskLoopRunnerLastUpdate { };
|
||||
public struct UniTaskLoopRunnerLastPreLateUpdate { };
|
||||
public struct UniTaskLoopRunnerLastPostLateUpdate { };
|
||||
|
||||
// Yield
|
||||
|
||||
public struct UniTaskLoopRunnerYieldInitialization { };
|
||||
|
@ -38,17 +48,40 @@ namespace UniRx.Async
|
|||
public struct UniTaskLoopRunnerYieldUpdate { };
|
||||
public struct UniTaskLoopRunnerYieldPreLateUpdate { };
|
||||
public struct UniTaskLoopRunnerYieldPostLateUpdate { };
|
||||
|
||||
// Yield Last
|
||||
|
||||
public struct UniTaskLoopRunnerLastYieldInitialization { };
|
||||
public struct UniTaskLoopRunnerLastYieldEarlyUpdate { };
|
||||
public struct UniTaskLoopRunnerLastYieldFixedUpdate { };
|
||||
public struct UniTaskLoopRunnerLastYieldPreUpdate { };
|
||||
public struct UniTaskLoopRunnerLastYieldUpdate { };
|
||||
public struct UniTaskLoopRunnerLastYieldPreLateUpdate { };
|
||||
public struct UniTaskLoopRunnerLastYieldPostLateUpdate { };
|
||||
}
|
||||
|
||||
public enum PlayerLoopTiming
|
||||
{
|
||||
Initialization = 0,
|
||||
EarlyUpdate = 1,
|
||||
FixedUpdate = 2,
|
||||
PreUpdate = 3,
|
||||
Update = 4,
|
||||
PreLateUpdate = 5,
|
||||
PostLateUpdate = 6
|
||||
LastInitialization = 1,
|
||||
|
||||
EarlyUpdate = 2,
|
||||
LastEarlyUpdate = 3,
|
||||
|
||||
FixedUpdate = 4,
|
||||
LastFixedUpdate = 5,
|
||||
|
||||
PreUpdate = 6,
|
||||
LastPreUpdate = 7,
|
||||
|
||||
Update = 8,
|
||||
LastUpdate = 9,
|
||||
|
||||
PreLateUpdate = 10,
|
||||
LastPreLateUpdate = 11,
|
||||
|
||||
PostLateUpdate = 12,
|
||||
LastPostLateUpdate = 13
|
||||
}
|
||||
|
||||
public interface IPlayerLoopItem
|
||||
|
@ -66,19 +99,36 @@ namespace UniRx.Async
|
|||
static ContinuationQueue[] yielders;
|
||||
static PlayerLoopRunner[] runners;
|
||||
|
||||
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType,
|
||||
ContinuationQueue cq, Type loopRunnerType, PlayerLoopRunner runner)
|
||||
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem,
|
||||
Type loopRunnerYieldType, ContinuationQueue cq, Type lastLoopRunnerYieldType, ContinuationQueue lastCq,
|
||||
Type loopRunnerType, PlayerLoopRunner runner, Type lastLoopRunnerType, PlayerLoopRunner lastRunner)
|
||||
{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.playModeStateChanged += (state) =>
|
||||
{
|
||||
if (state == PlayModeStateChange.EnteredEditMode ||
|
||||
state == PlayModeStateChange.EnteredPlayMode) return;
|
||||
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (runner != null)
|
||||
{
|
||||
runner.Clear();
|
||||
}
|
||||
if (lastRunner != null)
|
||||
{
|
||||
lastRunner.Clear();
|
||||
}
|
||||
|
||||
if (cq != null)
|
||||
{
|
||||
cq.Clear();
|
||||
}
|
||||
if (lastCq != null)
|
||||
{
|
||||
lastCq.Clear();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -88,18 +138,37 @@ namespace UniRx.Async
|
|||
updateDelegate = cq.Run
|
||||
};
|
||||
|
||||
var lastYieldLoop = new PlayerLoopSystem
|
||||
{
|
||||
type = lastLoopRunnerYieldType,
|
||||
updateDelegate = lastCq.Run
|
||||
};
|
||||
|
||||
var runnerLoop = new PlayerLoopSystem
|
||||
{
|
||||
type = loopRunnerType,
|
||||
updateDelegate = runner.Run
|
||||
};
|
||||
|
||||
var source = loopSystem.subSystemList // Remove items from previous initializations.
|
||||
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType).ToArray();
|
||||
var dest = new PlayerLoopSystem[source.Length + 2];
|
||||
var lastRunnerLoop = new PlayerLoopSystem
|
||||
{
|
||||
type = lastLoopRunnerType,
|
||||
updateDelegate = lastRunner.Run
|
||||
};
|
||||
|
||||
// Remove items from previous initializations.
|
||||
var source = loopSystem.subSystemList
|
||||
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType && ls.type != lastLoopRunnerYieldType && ls.type != lastLoopRunnerType)
|
||||
.ToArray();
|
||||
|
||||
var dest = new PlayerLoopSystem[source.Length + 4];
|
||||
|
||||
Array.Copy(source, 0, dest, 2, source.Length);
|
||||
dest[0] = yieldLoop;
|
||||
dest[1] = runnerLoop;
|
||||
dest[dest.Length - 2] = lastYieldLoop;
|
||||
dest[dest.Length - 1] = lastRunnerLoop;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -142,7 +211,6 @@ namespace UniRx.Async
|
|||
EditorApplication.update += ForceEditorPlayerLoopUpdate;
|
||||
}
|
||||
|
||||
|
||||
private static void ForceEditorPlayerLoopUpdate()
|
||||
{
|
||||
if (EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isCompiling ||
|
||||
|
@ -160,18 +228,46 @@ namespace UniRx.Async
|
|||
|
||||
public static void Initialize(ref PlayerLoopSystem playerLoop)
|
||||
{
|
||||
yielders = new ContinuationQueue[7];
|
||||
runners = new PlayerLoopRunner[7];
|
||||
yielders = new ContinuationQueue[14];
|
||||
runners = new PlayerLoopRunner[14];
|
||||
|
||||
var copyList = playerLoop.subSystemList.ToArray();
|
||||
|
||||
copyList[0].subSystemList = InsertRunner(copyList[0], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[0] = new PlayerLoopRunner());
|
||||
copyList[1].subSystemList = InsertRunner(copyList[1], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[1] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), runners[1] = new PlayerLoopRunner());
|
||||
copyList[2].subSystemList = InsertRunner(copyList[2], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), yielders[2] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), runners[2] = new PlayerLoopRunner());
|
||||
copyList[3].subSystemList = InsertRunner(copyList[3], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), yielders[3] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), runners[3] = new PlayerLoopRunner());
|
||||
copyList[4].subSystemList = InsertRunner(copyList[4], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), yielders[4] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), runners[4] = new PlayerLoopRunner());
|
||||
copyList[5].subSystemList = InsertRunner(copyList[5], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), yielders[5] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), runners[5] = new PlayerLoopRunner());
|
||||
copyList[6].subSystemList = InsertRunner(copyList[6], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), yielders[6] = new ContinuationQueue(), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[6] = new PlayerLoopRunner());
|
||||
// Initialization
|
||||
copyList[0].subSystemList = InsertRunner(copyList[0], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), yielders[1] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[1] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), runners[1] = new PlayerLoopRunner());
|
||||
// EarlyUpdate
|
||||
copyList[1].subSystemList = InsertRunner(copyList[1], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[2] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), yielders[3] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), runners[2] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), runners[3] = new PlayerLoopRunner());
|
||||
// FixedUpdate
|
||||
copyList[2].subSystemList = InsertRunner(copyList[2], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), yielders[4] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), yielders[5] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), runners[4] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), runners[5] = new PlayerLoopRunner());
|
||||
// PreUpdate
|
||||
copyList[3].subSystemList = InsertRunner(copyList[3], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), yielders[6] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), yielders[7] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), runners[6] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), runners[7] = new PlayerLoopRunner());
|
||||
// Update
|
||||
copyList[4].subSystemList = InsertRunner(copyList[4], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), yielders[8] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), yielders[9] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), runners[8] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), runners[9] = new PlayerLoopRunner());
|
||||
// PreLateUpdate
|
||||
copyList[5].subSystemList = InsertRunner(copyList[5], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), yielders[10] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), yielders[11] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), runners[10] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), runners[11] = new PlayerLoopRunner());
|
||||
// PostLateUpdate
|
||||
copyList[6].subSystemList = InsertRunner(copyList[6], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), yielders[12] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), yielders[13] = new ContinuationQueue(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[12] = new PlayerLoopRunner(),
|
||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), runners[13] = new PlayerLoopRunner());
|
||||
|
||||
playerLoop.subSystemList = copyList;
|
||||
PlayerLoop.SetPlayerLoop(playerLoop);
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c30655636c35c3d4da44064af3d2d9a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3ca26d0cd9373354c8cd147490f32c8e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8cc7fd65dd1433e419be4764aeb51391
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b1053c85b3f0794488b10e6de53e9c02
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in New Issue