initial project folder

This commit is contained in:
ToAallonranta
2020-01-29 10:05:38 +02:00
parent e6d2f9b9ca
commit 837543ed9a
3804 changed files with 100819 additions and 0 deletions

View File

@ -0,0 +1,16 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("UnityEngine.TestRunner")]
[assembly: InternalsVisibleTo("UnityEditor.TestRunner")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
[assembly: InternalsVisibleTo("Unity.PerformanceTesting")]
[assembly: InternalsVisibleTo("Unity.PerformanceTesting.Editor")]
[assembly: InternalsVisibleTo("Assembly-CSharp-testable")]
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor-testable")]
[assembly: InternalsVisibleTo("UnityEngine.TestRunner.Tests")]
[assembly: InternalsVisibleTo("UnityEditor.TestRunner.Tests")]
[assembly: InternalsVisibleTo("Unity.PackageManagerUI.Editor")]
[assembly: AssemblyVersion("1.0.0")]

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc22cc13b69c1094c85e176c008b9ef8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1ad55f5ad04d1d045a1f287409c650dd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,83 @@
using System;
using NUnit.Framework;
using NUnit.Framework.Constraints;
using UnityEngine.Profiling;
namespace UnityEngine.TestTools.Constraints
{
public class AllocatingGCMemoryConstraint : Constraint
{
private class AllocatingGCMemoryResult : ConstraintResult
{
private readonly int diff;
public AllocatingGCMemoryResult(IConstraint constraint, object actualValue, int diff) : base(constraint, actualValue, diff > 0)
{
this.diff = diff;
}
public override void WriteMessageTo(MessageWriter writer)
{
if (diff == 0)
writer.WriteMessageLine("The provided delegate did not make any GC allocations.");
else
writer.WriteMessageLine("The provided delegate made {0} GC allocation(s).", diff);
}
}
private ConstraintResult ApplyTo(Action action, object original)
{
var recorder = Recorder.Get("GC.Alloc");
// The recorder was created enabled, which means it captured the creation of the Recorder object itself, etc.
// Disabling it flushes its data, so that we can retrieve the sample block count and have it correctly account
// for these initial allocations.
recorder.enabled = false;
#if !UNITY_WEBGL
recorder.FilterToCurrentThread();
#endif
recorder.enabled = true;
try
{
action();
}
finally
{
recorder.enabled = false;
#if !UNITY_WEBGL
recorder.CollectFromAllThreads();
#endif
}
return new AllocatingGCMemoryResult(this, original, recorder.sampleBlockCount);
}
public override ConstraintResult ApplyTo(object obj)
{
if (obj == null)
throw new ArgumentNullException();
TestDelegate d = obj as TestDelegate;
if (d == null)
throw new ArgumentException(string.Format("The actual value must be a TestDelegate but was {0}",
obj.GetType()));
return ApplyTo(() => d.Invoke(), obj);
}
public override ConstraintResult ApplyTo<TActual>(ActualValueDelegate<TActual> del)
{
if (del == null)
throw new ArgumentNullException();
return ApplyTo(() => del.Invoke(), del);
}
public override string Description
{
get { return "allocates GC memory"; }
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d09858396dd7adb4bbdb22ea0c8c3a37
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
using NUnit.Framework.Constraints;
namespace UnityEngine.TestTools.Constraints
{
public static class ConstraintExtensions
{
public static AllocatingGCMemoryConstraint AllocatingGCMemory(this ConstraintExpression chain)
{
var constraint = new AllocatingGCMemoryConstraint();
chain.Append(constraint);
return constraint;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68a48d1900320ed458e118415857faf6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using NUnit.Framework;
using NUnit.Framework.Interfaces;
namespace UnityEngine.TestTools.TestRunner
{
internal class InvalidSignatureException : ResultStateException
{
public InvalidSignatureException(string message)
: base(message)
{
}
public override ResultState ResultState
{
get { return ResultState.NotRunnable; }
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9650d910fcaefb34cb45f121c1993892
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
namespace UnityEngine.TestTools.Constraints
{
public class Is : NUnit.Framework.Is
{
public static AllocatingGCMemoryConstraint AllocatingGCMemory()
{
return new AllocatingGCMemoryConstraint();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d5833966abeadb429de247e4316eef4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
using System.Text.RegularExpressions;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestTools
{
public static class LogAssert
{
public static void Expect(LogType type, string message)
{
LogScope.Current.ExpectedLogs.Enqueue(new LogMatch() { LogType = type, Message = message });
}
public static void Expect(LogType type, Regex message)
{
LogScope.Current.ExpectedLogs.Enqueue(new LogMatch() { LogType = type, MessageRegex = message });
}
public static void NoUnexpectedReceived()
{
LogScope.Current.ProcessExpectedLogs();
var isAllLogsHandled = LogScope.Current.IsAllLogsHandled();
if (isAllLogsHandled)
{
return;
}
var unhandledLog = LogScope.Current.GetUnhandledLog();
throw new UnhandledLogMessageException(unhandledLog);
}
public static bool ignoreFailingMessages
{
get
{
return LogScope.Current.IgnoreFailingMessages;
}
set
{
LogScope.Current.IgnoreFailingMessages = value;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c97b794b51780d349a16826a4c7898d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b1d8465ba1376b148bdab58965101f47
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
namespace UnityEngine.TestTools.Logging
{
internal interface ILogScope : IDisposable
{
List<LogEvent> LogEvents { get; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3504aa04cda851b44a65973f9aead6f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
namespace UnityEngine.TestTools.Logging
{
internal class LogEvent
{
public string Message { get; set; }
public string StackTrace { get; set; }
public LogType LogType { get; set; }
public bool IsHandled { get; set; }
public override string ToString()
{
return string.Format("[{0}] {1}", LogType, Message);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c56471f08a0f6846afc792f0b4205b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,103 @@
using System;
using System.Text.RegularExpressions;
namespace UnityEngine.TestTools.Logging
{
[Serializable]
internal class LogMatch
{
[SerializeField]
private bool m_UseRegex;
[SerializeField]
private string m_Message;
[SerializeField]
private string m_MessageRegex;
[SerializeField]
private string m_LogType;
public string Message
{
get { return m_Message; }
set
{
m_Message = value;
m_UseRegex = false;
}
}
public Regex MessageRegex
{
get
{
if (!m_UseRegex)
{
return null;
}
return new Regex(m_MessageRegex);
}
set
{
if (value != null)
{
m_MessageRegex = value.ToString();
m_UseRegex = true;
}
else
{
m_MessageRegex = null;
m_UseRegex = false;
}
}
}
public LogType? LogType
{
get
{
if (!string.IsNullOrEmpty(m_LogType))
{
return Enum.Parse(typeof(LogType), m_LogType) as LogType ? ;
}
return null;
}
set
{
if (value != null)
{
m_LogType = value.Value.ToString();
}
else
{
m_LogType = null;
}
}
}
public bool Matches(LogEvent log)
{
if (LogType != null && LogType != log.LogType)
{
return false;
}
if (m_UseRegex)
{
return MessageRegex.IsMatch(log.Message);
}
else
{
return Message.Equals(log.Message);
}
}
public override string ToString()
{
if (m_UseRegex)
return string.Format("[{0}] Regex: {1}", LogType, MessageRegex);
else
return string.Format("[{0}] {1}", LogType, Message);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9945ffed4692c6044b6d3acf81efd694
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace UnityEngine.TestTools.Logging
{
internal class LogScope : IDisposable
{
private bool m_Disposed;
private readonly object _lock = new object();
public Queue<LogMatch> ExpectedLogs { get; set; }
public List<LogEvent> AllLogs { get; }
public List<LogEvent> FailingLogs { get; }
public bool IgnoreFailingMessages { get; set; }
public bool IsNUnitException { get; private set; }
public bool IsNUnitSuccessException { get; private set; }
public bool IsNUnitInconclusiveException { get; private set; }
public bool IsNUnitIgnoreException { get; private set; }
public string NUnitExceptionMessage { get; private set; }
private bool m_NeedToProcessLogs;
private static List<LogScope> s_ActiveScopes = new List<LogScope>();
internal static LogScope Current
{
get
{
if (s_ActiveScopes.Count == 0)
throw new InvalidOperationException("No log scope is available");
return s_ActiveScopes[0];
}
}
internal static bool HasCurrentLogScope()
{
return s_ActiveScopes.Count > 0;
}
public LogScope()
{
AllLogs = new List<LogEvent>();
FailingLogs = new List<LogEvent>();
ExpectedLogs = new Queue<LogMatch>();
IgnoreFailingMessages = false;
Activate();
}
private void Activate()
{
s_ActiveScopes.Insert(0, this);
RegisterScope(this);
Application.logMessageReceivedThreaded -= AddLog;
Application.logMessageReceivedThreaded += AddLog;
}
private void Deactivate()
{
Application.logMessageReceivedThreaded -= AddLog;
s_ActiveScopes.Remove(this);
UnregisterScope(this);
}
private static void RegisterScope(LogScope logScope)
{
Application.logMessageReceivedThreaded += logScope.AddLog;
}
private static void UnregisterScope(LogScope logScope)
{
Application.logMessageReceivedThreaded -= logScope.AddLog;
}
public void AddLog(string message, string stacktrace, LogType type)
{
lock (_lock)
{
m_NeedToProcessLogs = true;
var log = new LogEvent
{
LogType = type,
Message = message,
StackTrace = stacktrace,
};
AllLogs.Add(log);
if (IsNUnitResultStateException(stacktrace, type))
{
if (message.StartsWith("SuccessException"))
{
IsNUnitException = true;
IsNUnitSuccessException = true;
if (message.StartsWith("SuccessException: "))
{
NUnitExceptionMessage = message.Substring("SuccessException: ".Length);
return;
}
}
else if (message.StartsWith("InconclusiveException"))
{
IsNUnitException = true;
IsNUnitInconclusiveException = true;
if (message.StartsWith("InconclusiveException: "))
{
NUnitExceptionMessage = message.Substring("InconclusiveException: ".Length);
return;
}
}
else if (message.StartsWith("IgnoreException"))
{
IsNUnitException = true;
IsNUnitIgnoreException = true;
if (message.StartsWith("IgnoreException: "))
{
NUnitExceptionMessage = message.Substring("IgnoreException: ".Length);
return;
}
}
}
if (IsFailingLog(type) && !IgnoreFailingMessages)
{
FailingLogs.Add(log);
}
}
}
public bool IsAllLogsHandled()
{
lock (_lock)
{
return AllLogs.All(x => x.IsHandled);
}
}
public LogEvent GetUnhandledLog()
{
lock (_lock)
{
return AllLogs.First(x => !x.IsHandled);
}
}
private static bool IsNUnitResultStateException(string stacktrace, LogType logType)
{
if (logType != LogType.Exception)
return false;
return string.IsNullOrEmpty(stacktrace) || stacktrace.StartsWith("NUnit.Framework.Assert.");
}
private static bool IsFailingLog(LogType type)
{
switch (type)
{
case LogType.Assert:
case LogType.Error:
case LogType.Exception:
return true;
default:
return false;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (m_Disposed)
{
return;
}
m_Disposed = true;
if (disposing)
{
Deactivate();
}
}
internal bool AnyFailingLogs()
{
ProcessExpectedLogs();
return FailingLogs.Any();
}
internal void ProcessExpectedLogs()
{
lock (_lock)
{
if (!m_NeedToProcessLogs || !ExpectedLogs.Any())
return;
LogMatch expectedLog = null;
foreach (var logEvent in AllLogs)
{
if (!ExpectedLogs.Any())
break;
if (expectedLog == null && ExpectedLogs.Any())
expectedLog = ExpectedLogs.Peek();
if (expectedLog != null && expectedLog.Matches(logEvent))
{
ExpectedLogs.Dequeue();
logEvent.IsHandled = true;
if (FailingLogs.Any(expectedLog.Matches))
{
var failingLog = FailingLogs.First(expectedLog.Matches);
FailingLogs.Remove(failingLog);
}
expectedLog = null;
}
}
m_NeedToProcessLogs = false;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4bbc17b35884fdf468e4b52ae4222882
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,29 @@
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using UnityEngine.TestTools.Logging;
namespace UnityEngine.TestTools.TestRunner
{
internal class UnexpectedLogMessageException : ResultStateException
{
public LogMatch LogEvent;
public UnexpectedLogMessageException(LogMatch log)
: base(BuildMessage(log))
{
LogEvent = log;
}
private static string BuildMessage(LogMatch log)
{
return string.Format("Expected log did not appear: {0}", log);
}
public override ResultState ResultState
{
get { return ResultState.Failure; }
}
public override string StackTrace { get { return null; } }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5b2eeca598284bd4abb4a15c30df1576
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.Utils;
namespace UnityEngine.TestTools.TestRunner
{
internal class UnhandledLogMessageException : ResultStateException
{
public LogEvent LogEvent;
private readonly string m_CustomStackTrace;
public UnhandledLogMessageException(LogEvent log)
: base(BuildMessage(log))
{
LogEvent = log;
m_CustomStackTrace = StackTraceFilter.Filter(log.StackTrace);
}
private static string BuildMessage(LogEvent log)
{
return string.Format("Unhandled log message: '{0}'. Use UnityEngine.TestTools.LogAssert.Expect", log);
}
public override ResultState ResultState
{
get { return ResultState.Failure; }
}
public override string StackTrace
{
get { return m_CustomStackTrace; }
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8ed4063f2beecd41a234a582202f3c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,28 @@
using NUnit.Framework;
using NUnit.Framework.Interfaces;
namespace UnityEngine.TestTools.TestRunner
{
internal class UnityTestTimeoutException : ResultStateException
{
public UnityTestTimeoutException(int timeout)
: base(BuildMessage(timeout))
{
}
private static string BuildMessage(int timeout)
{
return string.Format("UnityTest exceeded Timeout value of {0}ms", timeout);
}
public override ResultState ResultState
{
get { return ResultState.Failure; }
}
public override string StackTrace
{
get { return ""; }
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ffb335140c799c4408411d81789fb05c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3e8d6af343b383544ba5743d119f4062
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,79 @@
using System;
using System.Linq;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestTools.NUnitExtensions
{
/// <summary>
/// This class delegates actions from the NUnit thread that should be executed on the main thread.
/// NUnit thread calls Delegate which blocks the execution on the thread until the action is executed.
/// The main thread will poll for awaiting actions (HasAction) and invoke them (Execute).
/// Once the action is executed, the main thread releases the lock and executino on the NUnit thread is continued.
/// </summary>
internal class ActionDelegator : BaseDelegator
{
private Func<object> m_Action;
public object Delegate(Action action)
{
return Delegate(() => { action(); return null; });
}
public object Delegate(Func<object> action)
{
if (m_Aborted)
{
return null;
}
AssertState();
m_Context = UnityTestExecutionContext.CurrentContext;
m_Signal.Reset();
m_Action = action;
WaitForSignal();
return HandleResult();
}
private void AssertState()
{
if (m_Action != null)
{
throw new Exception("Action not executed yet");
}
}
public bool HasAction()
{
return m_Action != null;
}
public void Execute(LogScope logScope)
{
try
{
SetCurrentTestContext();
m_Result = m_Action();
if (logScope.AnyFailingLogs())
{
var failingLog = logScope.FailingLogs.First();
throw new UnhandledLogMessageException(failingLog);
}
if (logScope.ExpectedLogs.Any())
throw new UnexpectedLogMessageException(LogScope.Current.ExpectedLogs.Peek());
}
catch (Exception e)
{
m_Exception = e;
}
finally
{
m_Action = null;
m_Signal.Set();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4f939b9e23a0946439b812551e07ac81
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0cb14878543cf3d4f8472b15f7ecf0e3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,52 @@
using System;
using System.Collections;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
namespace UnityEngine.TestTools
{
internal class TestEnumerator
{
private readonly ITestExecutionContext m_Context;
private static IEnumerator m_TestEnumerator;
public static IEnumerator Enumerator { get { return m_TestEnumerator; } }
public TestEnumerator(ITestExecutionContext context, IEnumerator testEnumerator)
{
m_Context = context;
m_TestEnumerator = testEnumerator;
}
public IEnumerator Execute()
{
m_Context.CurrentResult.SetResult(ResultState.Success);
while (true)
{
object current = null;
try
{
if (!m_TestEnumerator.MoveNext())
{
yield break;
}
if (!m_Context.CurrentResult.ResultState.Equals(ResultState.Success))
{
yield break;
}
current = m_TestEnumerator.Current;
}
catch (Exception exception)
{
m_Context.CurrentResult.RecordException(exception);
yield break;
}
yield return current;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 750aad009559b814dbc27001341fc1c3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal.Builders;
namespace UnityEngine.TestTools
{
internal class UnityCombinatorialStrategy : CombinatorialStrategy, ICombiningStrategy
{
public new IEnumerable<ITestCaseData> GetTestCases(IEnumerable[] sources)
{
var testCases = base.GetTestCases(sources);
foreach (var testCase in testCases)
{
testCase.GetType().GetProperty("ExpectedResult").SetValue(testCase, new object(), null);
}
return testCases;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7af6ac3e6b51b8d4aab04adc85b8de2f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
namespace UnityEngine.TestTools
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
public class UnityPlatformAttribute : NUnitAttribute, IApplyToTest
{
public RuntimePlatform[] include { get; set; }
public RuntimePlatform[] exclude { get; set; }
private string m_skippedReason;
public UnityPlatformAttribute()
{
include = new List<RuntimePlatform>().ToArray();
exclude = new List<RuntimePlatform>().ToArray();
}
public UnityPlatformAttribute(params RuntimePlatform[] include)
: this()
{
this.include = include;
}
public void ApplyToTest(Test test)
{
if (test.RunState == RunState.NotRunnable || test.RunState == RunState.Ignored || IsPlatformSupported(Application.platform))
{
return;
}
test.RunState = RunState.Skipped;
test.Properties.Add("_SKIPREASON", m_skippedReason);
}
internal bool IsPlatformSupported(RuntimePlatform testTargetPlatform)
{
if (include.Any() && !include.Any(x => x == testTargetPlatform))
{
m_skippedReason = string.Format("Only supported on {0}", string.Join(", ", include.Select(x => x.ToString()).ToArray()));
return false;
}
if (exclude.Any(x => x == testTargetPlatform))
{
m_skippedReason = string.Format("Not supported on {0}", string.Join(", ", include.Select(x => x.ToString()).ToArray()));
return false;
}
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5440c1153b397e14c9c7b1d6eb83b9f9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
using System;
using NUnit.Framework;
namespace UnityEngine.TestTools
{
[AttributeUsage(AttributeTargets.Method)]
public class UnitySetUpAttribute : NUnitAttribute
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc6401f13df54ba44bfd7cdc93c7d64d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
using System;
using NUnit.Framework;
namespace UnityEngine.TestTools
{
[AttributeUsage(AttributeTargets.Method)]
public class UnityTearDownAttribute : NUnitAttribute
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 600f4b74746dbf944901257f81a8af6d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
using System;
using NUnit.Framework;
using NUnit.Framework.Internal.Commands;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Builders;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
[AttributeUsage(AttributeTargets.Method)]
public class UnityTestAttribute : CombiningStrategyAttribute, IWrapSetUpTearDown, ISimpleTestBuilder, IImplyFixture
{
public UnityTestAttribute() : base(new UnityCombinatorialStrategy(), new ParameterDataSourceProvider()) {}
private readonly NUnitTestCaseBuilder _builder = new NUnitTestCaseBuilder();
TestMethod ISimpleTestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
TestCaseParameters parms = new TestCaseParameters
{
ExpectedResult = new object(),
HasExpectedResult = true
};
var t = _builder.BuildTestMethod(method, suite, parms);
if (t.parms != null)
t.parms.HasExpectedResult = false;
return t;
}
public TestCommand Wrap(TestCommand command)
{
return new OuterUnityTestActionCommand(
new EnumerableSetUpTearDownCommand(
new SetUpTearDownCommand(
new TestActionCommand(
new UnityLogCheckDelegatingCommand(
new EnumerableTestMethodCommand((TestMethod)command.Test))))));
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fedb0f9e5006b1943abae52f52f08a1a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,58 @@
using System;
using System.Threading;
using NUnit.Framework.Internal;
namespace UnityEngine.TestTools.NUnitExtensions
{
internal abstract class BaseDelegator
{
protected ManualResetEvent m_Signal = new ManualResetEvent(false);
protected object m_Result;
protected Exception m_Exception;
protected ITestExecutionContext m_Context;
protected bool m_Aborted;
protected object HandleResult()
{
SetCurrentTestContext();
if (m_Exception != null)
{
var temp = m_Exception;
m_Exception = null;
throw temp;
}
var tempResult = m_Result;
m_Result = null;
return tempResult;
}
protected void WaitForSignal()
{
while (!m_Signal.WaitOne(100))
{
if (m_Aborted)
{
m_Aborted = false;
Reflect.MethodCallWrapper = null;
throw new Exception();
}
}
}
public void Abort()
{
m_Aborted = true;
}
protected void SetCurrentTestContext()
{
var prop = typeof(TestExecutionContext).GetProperty("CurrentContext");
if (prop != null)
{
prop.SetValue(null, m_Context, null);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 37cea569bfefafe49a1513c4d7f0e9eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6b72875690e0f7343911e06af3145bd5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,196 @@
using System;
using System.Collections;
using System.Linq;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestRunner.NUnitExtensions;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestTools
{
internal abstract class BeforeAfterTestCommandBase<T> : DelegatingTestCommand, IEnumerableTestMethodCommand
{
private string m_BeforeErrorPrefix;
private string m_AfterErrorPrefix;
private bool m_SkipYieldAfterActions;
protected BeforeAfterTestCommandBase(TestCommand innerCommand, string beforeErrorPrefix, string afterErrorPrefix, bool skipYieldAfterActions = false)
: base(innerCommand)
{
m_BeforeErrorPrefix = beforeErrorPrefix;
m_AfterErrorPrefix = afterErrorPrefix;
m_SkipYieldAfterActions = skipYieldAfterActions;
}
protected T[] BeforeActions = new T[0];
protected T[] AfterActions = new T[0];
protected abstract IEnumerator InvokeBefore(T action, Test test, UnityTestExecutionContext context);
protected abstract IEnumerator InvokeAfter(T action, Test test, UnityTestExecutionContext context);
protected abstract BeforeAfterTestCommandState GetState(UnityTestExecutionContext context);
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
{
var unityContext = (UnityTestExecutionContext)context;
var state = GetState(unityContext);
if (state == null)
{
// We do not expect a state to exist in playmode
state = ScriptableObject.CreateInstance<BeforeAfterTestCommandState>();
}
state.ApplyTestResult(context.CurrentResult);
while (state.NextBeforeStepIndex < BeforeActions.Length)
{
var action = BeforeActions[state.NextBeforeStepIndex];
var enumerator = InvokeBefore(action, Test, unityContext);
ActivePcHelper.SetEnumeratorPC(enumerator, state.NextBeforeStepPc);
using (var logScope = new LogScope())
{
while (true)
{
try
{
if (!enumerator.MoveNext())
{
break;
}
}
catch (Exception ex)
{
state.TestHasRun = true;
context.CurrentResult.RecordPrefixedException(m_BeforeErrorPrefix, ex);
state.StoreTestResult(context.CurrentResult);
break;
}
state.NextBeforeStepPc = ActivePcHelper.GetEnumeratorPC(enumerator);
state.StoreTestResult(context.CurrentResult);
if (m_SkipYieldAfterActions)
{
break;
}
else
{
yield return enumerator.Current;
}
}
if (logScope.AnyFailingLogs())
{
state.TestHasRun = true;
context.CurrentResult.RecordPrefixedError(m_BeforeErrorPrefix, new UnhandledLogMessageException(logScope.FailingLogs.First()).Message);
state.StoreTestResult(context.CurrentResult);
}
}
state.NextBeforeStepIndex++;
state.NextBeforeStepPc = 0;
}
if (!state.TestHasRun)
{
if (innerCommand is IEnumerableTestMethodCommand)
{
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
foreach (var iterator in executeEnumerable)
{
state.StoreTestResult(context.CurrentResult);
yield return iterator;
}
}
else
{
context.CurrentResult = innerCommand.Execute(context);
state.StoreTestResult(context.CurrentResult);
}
state.TestHasRun = true;
}
while (state.NextAfterStepIndex < AfterActions.Length)
{
state.TestAfterStarted = true;
var action = AfterActions[state.NextAfterStepIndex];
var enumerator = InvokeAfter(action, Test, unityContext);
ActivePcHelper.SetEnumeratorPC(enumerator, state.NextAfterStepPc);
using (var logScope = new LogScope())
{
while (true)
{
try
{
if (!enumerator.MoveNext())
{
break;
}
}
catch (Exception ex)
{
context.CurrentResult.RecordPrefixedException(m_AfterErrorPrefix, ex);
state.StoreTestResult(context.CurrentResult);
break;
}
state.NextAfterStepPc = ActivePcHelper.GetEnumeratorPC(enumerator);
state.StoreTestResult(context.CurrentResult);
if (m_SkipYieldAfterActions)
{
break;
}
else
{
yield return enumerator.Current;
}
}
if (logScope.AnyFailingLogs())
{
state.TestHasRun = true;
context.CurrentResult.RecordPrefixedError(m_AfterErrorPrefix, new UnhandledLogMessageException(logScope.FailingLogs.First()).Message);
state.StoreTestResult(context.CurrentResult);
}
}
state.NextAfterStepIndex++;
state.NextAfterStepPc = 0;
}
state.Reset();
}
public override TestResult Execute(ITestExecutionContext context)
{
throw new NotImplementedException("Use ExecuteEnumerable");
}
private static TestCommandPcHelper pcHelper;
internal static TestCommandPcHelper ActivePcHelper
{
get
{
if (pcHelper == null)
{
pcHelper = new TestCommandPcHelper();
}
return pcHelper;
}
set
{
pcHelper = value;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cbbca1d8a0434be4bbc7f165523763ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,49 @@
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
namespace UnityEngine.TestTools
{
internal class BeforeAfterTestCommandState : ScriptableObject
{
public int NextBeforeStepIndex;
public int NextBeforeStepPc;
public int NextAfterStepIndex;
public int NextAfterStepPc;
public bool TestHasRun;
public TestStatus CurrentTestResultStatus;
public string CurrentTestResultLabel;
public FailureSite CurrentTestResultSite;
public string CurrentTestMessage;
public string CurrentTestStrackTrace;
public bool TestAfterStarted;
public void Reset()
{
NextBeforeStepIndex = 0;
NextBeforeStepPc = 0;
NextAfterStepIndex = 0;
NextAfterStepPc = 0;
TestHasRun = false;
CurrentTestResultStatus = TestStatus.Inconclusive;
CurrentTestResultLabel = null;
CurrentTestResultSite = default(FailureSite);
CurrentTestMessage = null;
CurrentTestStrackTrace = null;
TestAfterStarted = false;
}
public void StoreTestResult(TestResult result)
{
CurrentTestResultStatus = result.ResultState.Status;
CurrentTestResultLabel = result.ResultState.Label;
CurrentTestResultSite = result.ResultState.Site;
CurrentTestMessage = result.Message;
CurrentTestStrackTrace = result.StackTrace;
}
public void ApplyTestResult(TestResult result)
{
result.SetResult(new ResultState(CurrentTestResultStatus, CurrentTestResultLabel, CurrentTestResultSite), CurrentTestMessage, CurrentTestStrackTrace);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f65567c9026afb4db5de3355accc636
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
internal class EnumerableApplyChangesToContextCommand : ApplyChangesToContextCommand, IEnumerableTestMethodCommand
{
public EnumerableApplyChangesToContextCommand(TestCommand innerCommand, IEnumerable<IApplyToContext> changes)
: base(innerCommand, changes) { }
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
{
ApplyChanges(context);
if (innerCommand is IEnumerableTestMethodCommand)
{
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
foreach (var iterator in executeEnumerable)
{
yield return iterator;
}
}
else
{
context.CurrentResult = innerCommand.Execute(context);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b4429eff9fcffb48b006e8edcc90338
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,44 @@
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
internal class EnumerableSetUpTearDownCommand : BeforeAfterTestCommandBase<MethodInfo>
{
public EnumerableSetUpTearDownCommand(TestCommand innerCommand)
: base(innerCommand, "SetUp", "TearDown")
{
if (Test.TypeInfo.Type != null)
{
BeforeActions = GetMethodsWithAttributeFromFixture(Test.TypeInfo.Type, typeof(UnitySetUpAttribute));
AfterActions = GetMethodsWithAttributeFromFixture(Test.TypeInfo.Type, typeof(UnityTearDownAttribute)).Reverse().ToArray();
}
}
private static MethodInfo[] GetMethodsWithAttributeFromFixture(Type fixtureType, Type setUpType)
{
MethodInfo[] methodsWithAttribute = Reflect.GetMethodsWithAttribute(fixtureType, setUpType, true);
return methodsWithAttribute.Where(x => x.ReturnType == typeof(IEnumerator)).ToArray();
}
protected override IEnumerator InvokeBefore(MethodInfo action, Test test, UnityTestExecutionContext context)
{
return (IEnumerator)Reflect.InvokeMethod(action, context.TestObject);
}
protected override IEnumerator InvokeAfter(MethodInfo action, Test test, UnityTestExecutionContext context)
{
return (IEnumerator)Reflect.InvokeMethod(action, context.TestObject);
}
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
{
return context.SetUpTearDownState;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd85a35169d313840a0874aea1a28629
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,86 @@
using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using NUnit.Framework.Internal.Execution;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestTools
{
internal class EnumerableTestMethodCommand : TestCommand, IEnumerableTestMethodCommand
{
private readonly TestMethod testMethod;
public EnumerableTestMethodCommand(TestMethod testMethod)
: base(testMethod)
{
this.testMethod = testMethod;
}
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
{
yield return null;
var currentExecutingTestEnumerator = new TestEnumeratorWrapper(testMethod).GetEnumerator(context);
if (currentExecutingTestEnumerator != null)
{
var testEnumeraterYieldInstruction = new TestEnumerator(context, currentExecutingTestEnumerator);
yield return testEnumeraterYieldInstruction;
var enumerator = testEnumeraterYieldInstruction.Execute();
var executingEnumerator = ExecuteEnumerableAndRecordExceptions(enumerator, context);
while (executingEnumerator.MoveNext())
{
yield return executingEnumerator.Current;
}
}
else
{
if (context.CurrentResult.ResultState != ResultState.Ignored)
{
context.CurrentResult.SetResult(ResultState.Success);
}
}
}
private static IEnumerator ExecuteEnumerableAndRecordExceptions(IEnumerator enumerator, ITestExecutionContext context)
{
while (true)
{
try
{
if (!enumerator.MoveNext())
{
break;
}
}
catch (Exception ex)
{
context.CurrentResult.RecordException(ex);
break;
}
if (enumerator.Current is IEnumerator)
{
var current = (IEnumerator)enumerator.Current;
yield return ExecuteEnumerableAndRecordExceptions(current, context);
}
else
{
yield return enumerator.Current;
}
}
}
public override TestResult Execute(ITestExecutionContext context)
{
throw new NotImplementedException("Use ExecuteEnumerable");
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 19a6f000f81e24c4a826c1abd43e77c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
using System;
using System.Collections;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
internal class ImmediateEnumerableCommand : DelegatingTestCommand
{
public ImmediateEnumerableCommand(TestCommand innerCommand)
: base(innerCommand) { }
public override TestResult Execute(ITestExecutionContext context)
{
if (innerCommand is IEnumerableTestMethodCommand)
{
var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
foreach (var iterator in executeEnumerable)
{
if (iterator != null)
{
throw new Exception("Only null can be yielded at this point.");
}
}
return context.CurrentResult;
}
return innerCommand.Execute(context);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8349e42a2b30c7a4abd8678c203428ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
internal class OuterUnityTestActionCommand : BeforeAfterTestCommandBase<IOuterUnityTestAction>
{
public OuterUnityTestActionCommand(TestCommand innerCommand)
: base(innerCommand, "BeforeTest", "AfterTest")
{
if (Test.TypeInfo.Type != null)
{
BeforeActions = GetUnityTestActionsFromMethod(Test.Method.MethodInfo);
AfterActions = BeforeActions;
}
}
private static IOuterUnityTestAction[] GetUnityTestActionsFromMethod(MethodInfo method)
{
var attributes = method.GetCustomAttributes(false);
List<IOuterUnityTestAction> actions = new List<IOuterUnityTestAction>();
foreach (var attribute in attributes)
{
if (attribute is IOuterUnityTestAction)
actions.Add(attribute as IOuterUnityTestAction);
}
return actions.ToArray();
}
protected override IEnumerator InvokeBefore(IOuterUnityTestAction action, Test test, UnityTestExecutionContext context)
{
return action.BeforeTest(test);
}
protected override IEnumerator InvokeAfter(IOuterUnityTestAction action, Test test, UnityTestExecutionContext context)
{
return action.AfterTest(test);
}
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
{
return context.OuterUnityTestActionState;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0d4fc309a0784294c8ab658b53b12320
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using NUnit.Framework.Internal.Execution;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
internal class SetUpTearDownCommand : BeforeAfterTestCommandBase<MethodInfo>
{
public SetUpTearDownCommand(TestCommand innerCommand)
: base(innerCommand, "SetUp", "TearDown", true)
{
if (Test.TypeInfo.Type != null)
{
BeforeActions = GetMethodsWithAttributeFromFixture(Test.TypeInfo.Type, typeof(SetUpAttribute));
AfterActions = GetMethodsWithAttributeFromFixture(Test.TypeInfo.Type, typeof(TearDownAttribute)).Reverse().ToArray();
}
}
private static MethodInfo[] GetMethodsWithAttributeFromFixture(Type fixtureType, Type setUpType)
{
MethodInfo[] methodsWithAttribute = Reflect.GetMethodsWithAttribute(fixtureType, setUpType, true);
return methodsWithAttribute.Where(x => x.ReturnType == typeof(void)).ToArray();
}
protected override IEnumerator InvokeBefore(MethodInfo action, Test test, UnityTestExecutionContext context)
{
Reflect.InvokeMethod(action, context.TestObject);
yield return null;
}
protected override IEnumerator InvokeAfter(MethodInfo action, Test test, UnityTestExecutionContext context)
{
Reflect.InvokeMethod(action, context.TestObject);
yield return null;
}
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
{
return null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e0db3f3921670cd4ca2e925737c3fba4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NUnit.Framework;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
namespace UnityEngine.TestTools
{
internal class TestActionCommand : BeforeAfterTestCommandBase<ITestAction>
{
public TestActionCommand(TestCommand innerCommand)
: base(innerCommand, "BeforeTest", "AfterTest", true)
{
if (Test.TypeInfo.Type != null)
{
BeforeActions = GetTestActionsFromMethod(Test.Method.MethodInfo);
AfterActions = BeforeActions;
}
}
private static ITestAction[] GetTestActionsFromMethod(MethodInfo method)
{
var attributes = method.GetCustomAttributes(false);
List<ITestAction> actions = new List<ITestAction>();
foreach (var attribute in attributes)
{
if (attribute is ITestAction)
actions.Add(attribute as ITestAction);
}
return actions.ToArray();
}
protected override IEnumerator InvokeBefore(ITestAction action, Test test, UnityTestExecutionContext context)
{
action.BeforeTest(test);
yield return null;
}
protected override IEnumerator InvokeAfter(ITestAction action, Test test, UnityTestExecutionContext context)
{
action.AfterTest(test);
yield return null;
}
protected override BeforeAfterTestCommandState GetState(UnityTestExecutionContext context)
{
return null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2de8ba3b840049641897e0da7ce1d5cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using System;
using System.Collections;
namespace UnityEngine.TestTools
{
internal class TestCommandPcHelper
{
public virtual void SetEnumeratorPC(IEnumerator enumerator, int pc)
{
// Noop implementation used in playmode.
}
public virtual int GetEnumeratorPC(IEnumerator enumerator)
{
return 0;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33e6b78c96bb0694e96383e3c56b7b54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,141 @@
using System;
using System.Linq;
using NUnit.Framework.Internal;
using UnityEngine.TestRunner.NUnitExtensions.Runner;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestTools.NUnitExtensions
{
/// <summary>
/// Specialization of BaseDelegator that makes sure objects are created on the MainThread.
/// It also deals with ScriptableObjects so that tests can survive assembly reload.
/// </summary>
internal class ConstructDelegator
{
private Type m_RequestedType;
private object[] m_Arguments;
private ScriptableObject m_CurrentRunningTest;
private readonly IStateSerializer m_StateSerializer;
protected Exception m_Exception;
protected object m_Result;
protected ITestExecutionContext m_Context;
public ConstructDelegator(IStateSerializer stateSerializer)
{
m_StateSerializer = stateSerializer;
}
protected object HandleResult()
{
SetCurrentTestContext();
if (m_Exception != null)
{
var temp = m_Exception;
m_Exception = null;
throw temp;
}
var tempResult = m_Result;
m_Result = null;
return tempResult;
}
protected void SetCurrentTestContext()
{
var prop = typeof(UnityTestExecutionContext).GetProperty("CurrentContext");
if (prop != null)
{
prop.SetValue(null, m_Context, null);
}
}
public object Delegate(Type type, object[] arguments)
{
AssertState();
m_Context = UnityTestExecutionContext.CurrentContext;
m_RequestedType = type;
m_Arguments = arguments;
using (var logScope = new LogScope())
{
Execute(logScope);
}
return HandleResult();
}
private void AssertState()
{
if (m_RequestedType != null)
{
throw new Exception("Constructor not executed yet");
}
}
public bool HasAction()
{
return m_RequestedType != null;
}
public void Execute(LogScope logScope)
{
try
{
if (typeof(ScriptableObject).IsAssignableFrom(m_RequestedType))
{
if (m_CurrentRunningTest != null && m_RequestedType != m_CurrentRunningTest.GetType())
{
DestroyCurrentTestObjectIfExists();
}
if (m_CurrentRunningTest == null)
{
if (m_StateSerializer.CanRestoreFromScriptableObject(m_RequestedType))
{
m_CurrentRunningTest = m_StateSerializer.RestoreScriptableObjectInstance();
}
else
{
m_CurrentRunningTest = ScriptableObject.CreateInstance(m_RequestedType);
}
}
m_Result = m_CurrentRunningTest;
}
else
{
DestroyCurrentTestObjectIfExists();
m_Result = Activator.CreateInstance(m_RequestedType, m_Arguments);
if (m_StateSerializer.CanRestoreFromJson(m_RequestedType))
{
m_StateSerializer.RestoreClassFromJson(ref m_Result);
}
}
if (logScope.AnyFailingLogs())
{
var failingLog = logScope.FailingLogs.First();
throw new UnhandledLogMessageException(failingLog);
}
if (logScope.ExpectedLogs.Any())
throw new UnexpectedLogMessageException(LogScope.Current.ExpectedLogs.Peek());
}
catch (Exception e)
{
m_Exception = e;
}
finally
{
m_RequestedType = null;
m_Arguments = null;
}
}
public void DestroyCurrentTestObjectIfExists()
{
if (m_CurrentRunningTest == null)
return;
Object.DestroyImmediate(m_CurrentRunningTest);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b42e1db66fe9c634798674cb9e1df2ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c3de99f9efc582a48995bc8e8c2df418
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,25 @@
using System;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal.Filters;
namespace UnityEngine.TestRunner.NUnitExtensions.Filters
{
internal class AssemblyNameFilter : ValueMatchFilter
{
public AssemblyNameFilter(string assemblyName) : base(assemblyName) {}
public override bool Match(ITest test)
{
string assemblyName = string.Empty;
//Assembly fullname is in the format "Assembly-name, meta data ...", so extract the name by looking for the comma
if (test.TypeInfo != null && test.TypeInfo.Assembly != null && test.TypeInfo.FullName != null)
assemblyName = test.TypeInfo.Assembly.FullName.Substring(0, test.TypeInfo.Assembly.FullName.IndexOf(',')).TrimEnd(',');
return ExpectedValue.Equals(assemblyName, StringComparison.OrdinalIgnoreCase);
}
protected override string ElementName
{
get { return "id"; }
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91319408591cec1478efd3c62f9f418a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,36 @@
using System.Collections;
using System.Linq;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Filters;
namespace UnityEngine.TestRunner.NUnitExtensions.Filters
{
internal class CategoryFilterExtended : CategoryFilter
{
public static string k_DefaultCategory = "Uncategorized";
public CategoryFilterExtended(string name) : base(name)
{
}
public override bool Match(ITest test)
{
IList testCategories = test.Properties[PropertyNames.Category].Cast<string>().ToList();
if (test is TestMethod)
{
// Do not count tests with no attribute as Uncategorized if test fixture class has at least one attribute
// The test inherits the attribute from the test fixture
IList fixtureCategories = test.Parent.Properties[PropertyNames.Category].Cast<string>().ToList();
if (fixtureCategories.Count > 0)
return false;
}
if (testCategories.Count == 0 && ExpectedValue == k_DefaultCategory && test is TestMethod)
return true;
return base.Match(test);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ebeedaa04bb53e24ba2e7fb6745e3fd3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
using System;
namespace UnityEngine.TestTools.NUnitExtensions
{
internal interface IStateSerializer
{
ScriptableObject RestoreScriptableObjectInstance();
void RestoreClassFromJson(ref object instance);
bool CanRestoreFromJson(Type requestedType);
bool CanRestoreFromScriptableObject(Type requestedType);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5f875a14565308a40a5262d2504da705
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 37888acc09d9ee848bf9559f06645c45
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,342 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using NUnit.Framework.Internal.Execution;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class CompositeWorkItem : UnityWorkItem
{
private readonly TestSuite _suite;
private readonly TestSuiteResult _suiteResult;
private readonly ITestFilter _childFilter;
private TestCommand _setupCommand;
private TestCommand _teardownCommand;
public List<UnityWorkItem> Children { get; private set; }
private int _countOrder;
private CountdownEvent _childTestCountdown;
public CompositeWorkItem(TestSuite suite, ITestFilter childFilter, WorkItemFactory factory)
: base(suite, factory)
{
_suite = suite;
_suiteResult = Result as TestSuiteResult;
_childFilter = childFilter;
_countOrder = 0;
}
protected override IEnumerable PerformWork()
{
InitializeSetUpAndTearDownCommands();
if (UnityTestExecutionContext.CurrentContext != null && m_DontRunRestoringResult && EditModeTestCallbacks.RestoringTestContext != null)
{
EditModeTestCallbacks.RestoringTestContext();
}
if (!CheckForCancellation())
if (Test.RunState == RunState.Explicit && !_childFilter.IsExplicitMatch(Test))
SkipFixture(ResultState.Explicit, GetSkipReason(), null);
else
switch (Test.RunState)
{
default:
case RunState.Runnable:
case RunState.Explicit:
Result.SetResult(ResultState.Success);
CreateChildWorkItems();
if (Children.Count > 0)
{
if (!m_DontRunRestoringResult)
{
//This is needed to give the editor a chance to go out of playmode if needed before creating objects.
//If we do not, the objects could be automatically destroyed when exiting playmode and could result in errors later on
yield return null;
PerformOneTimeSetUp();
}
if (!CheckForCancellation())
{
switch (Result.ResultState.Status)
{
case TestStatus.Passed:
foreach (var child in RunChildren())
{
if (CheckForCancellation())
{
yield break;
}
yield return child;
}
break;
case TestStatus.Skipped:
case TestStatus.Inconclusive:
case TestStatus.Failed:
SkipChildren(_suite, Result.ResultState.WithSite(FailureSite.Parent), "OneTimeSetUp: " + Result.Message);
break;
}
}
if (Context.ExecutionStatus != TestExecutionStatus.AbortRequested && !m_DontRunRestoringResult)
{
PerformOneTimeTearDown();
}
}
break;
case RunState.Skipped:
SkipFixture(ResultState.Skipped, GetSkipReason(), null);
break;
case RunState.Ignored:
SkipFixture(ResultState.Ignored, GetSkipReason(), null);
break;
case RunState.NotRunnable:
SkipFixture(ResultState.NotRunnable, GetSkipReason(), GetProviderStackTrace());
break;
}
if (!ResultedInDomainReload)
{
WorkItemComplete();
}
}
private bool CheckForCancellation()
{
if (Context.ExecutionStatus != TestExecutionStatus.Running)
{
Result.SetResult(ResultState.Cancelled, "Test cancelled by user");
return true;
}
return false;
}
private void InitializeSetUpAndTearDownCommands()
{
List<SetUpTearDownItem> setUpTearDownItems = _suite.TypeInfo != null
? CommandBuilder.BuildSetUpTearDownList(_suite.TypeInfo.Type, typeof(OneTimeSetUpAttribute), typeof(OneTimeTearDownAttribute))
: new List<SetUpTearDownItem>();
var actionItems = new List<TestActionItem>();
foreach (ITestAction action in Actions)
{
bool applyToSuite = (action.Targets & ActionTargets.Suite) == ActionTargets.Suite
|| action.Targets == ActionTargets.Default && !(Test is ParameterizedMethodSuite);
bool applyToTest = (action.Targets & ActionTargets.Test) == ActionTargets.Test
&& !(Test is ParameterizedMethodSuite);
if (applyToSuite)
actionItems.Add(new TestActionItem(action));
if (applyToTest)
Context.UpstreamActions.Add(action);
}
_setupCommand = CommandBuilder.MakeOneTimeSetUpCommand(_suite, setUpTearDownItems, actionItems);
_teardownCommand = CommandBuilder.MakeOneTimeTearDownCommand(_suite, setUpTearDownItems, actionItems);
}
private void PerformOneTimeSetUp()
{
var logScope = new LogScope();
try
{
_setupCommand.Execute(Context);
}
catch (Exception ex)
{
if (ex is NUnitException || ex is TargetInvocationException)
ex = ex.InnerException;
Result.RecordException(ex, FailureSite.SetUp);
}
if (logScope.AnyFailingLogs())
{
Result.RecordException(new UnhandledLogMessageException(logScope.FailingLogs.First()));
}
logScope.Dispose();
}
private IEnumerable RunChildren()
{
int childCount = Children.Count;
if (childCount == 0)
throw new InvalidOperationException("RunChildren called but item has no children");
_childTestCountdown = new CountdownEvent(childCount);
foreach (UnityWorkItem child in Children)
{
if (CheckForCancellation())
{
yield break;
}
var unityTestExecutionContext = new UnityTestExecutionContext(Context);
child.InitializeContext(unityTestExecutionContext);
var enumerable = child.Execute().GetEnumerator();
while (true)
{
if (!enumerable.MoveNext())
{
break;
}
ResultedInDomainReload |= child.ResultedInDomainReload;
yield return enumerable.Current;
}
_suiteResult.AddResult(child.Result);
childCount--;
}
if (childCount > 0)
{
while (childCount-- > 0)
CountDownChildTest();
}
}
private void CreateChildWorkItems()
{
Children = new List<UnityWorkItem>();
var testSuite = _suite;
foreach (ITest test in testSuite.Tests)
{
if (_childFilter.Pass(test))
{
var child = m_Factory.Create(test, _childFilter);
if (test.Properties.ContainsKey(PropertyNames.Order))
{
Children.Insert(0, child);
_countOrder++;
}
else
{
Children.Add(child);
}
}
}
if (_countOrder != 0) SortChildren();
}
private class UnityWorkItemOrderComparer : IComparer<UnityWorkItem>
{
public int Compare(UnityWorkItem x, UnityWorkItem y)
{
var xKey = int.MaxValue;
var yKey = int.MaxValue;
if (x.Test.Properties.ContainsKey(PropertyNames.Order))
xKey = (int)x.Test.Properties[PropertyNames.Order][0];
if (y.Test.Properties.ContainsKey(PropertyNames.Order))
yKey = (int)y.Test.Properties[PropertyNames.Order][0];
return xKey.CompareTo(yKey);
}
}
private void SortChildren()
{
Children.Sort(0, _countOrder, new UnityWorkItemOrderComparer());
}
private void SkipFixture(ResultState resultState, string message, string stackTrace)
{
Result.SetResult(resultState.WithSite(FailureSite.SetUp), message, StackFilter.Filter(stackTrace));
SkipChildren(_suite, resultState.WithSite(FailureSite.Parent), "OneTimeSetUp: " + message);
}
private void SkipChildren(TestSuite suite, ResultState resultState, string message)
{
foreach (Test child in suite.Tests)
{
if (_childFilter.Pass(child))
{
Context.Listener.TestStarted(child);
TestResult childResult = child.MakeTestResult();
childResult.SetResult(resultState, message);
_suiteResult.AddResult(childResult);
if (child.IsSuite)
SkipChildren((TestSuite)child, resultState, message);
Context.Listener.TestFinished(childResult);
}
}
}
private void PerformOneTimeTearDown()
{
_teardownCommand.Execute(Context);
}
private string GetSkipReason()
{
return (string)Test.Properties.Get(PropertyNames.SkipReason);
}
private string GetProviderStackTrace()
{
return (string)Test.Properties.Get(PropertyNames.ProviderStackTrace);
}
private void CountDownChildTest()
{
_childTestCountdown.Signal();
if (_childTestCountdown.CurrentCount == 0)
{
if (Context.ExecutionStatus != TestExecutionStatus.AbortRequested)
PerformOneTimeTearDown();
foreach (var childResult in _suiteResult.Children)
if (childResult.ResultState == ResultState.Cancelled)
{
this.Result.SetResult(ResultState.Cancelled, "Cancelled by user");
break;
}
WorkItemComplete();
}
}
public override void Cancel(bool force)
{
if (Children == null)
return;
foreach (var child in Children)
{
var ctx = child.Context;
if (ctx != null)
ctx.ExecutionStatus = force ? TestExecutionStatus.AbortRequested : TestExecutionStatus.StopRequested;
if (child.State == WorkItemState.Running)
child.Cancel(force);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 110d5035a36a6a34580fb65bb40cd78f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,77 @@
using System;
using System.Collections;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using NUnit.Framework.Internal.Execution;
using UnityEngine.TestTools.Utils;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class CoroutineTestWorkItem : UnityWorkItem
{
private static MonoBehaviour m_MonoBehaviourCoroutineRunner;
private TestCommand m_Command;
public static MonoBehaviour monoBehaviourCoroutineRunner
{
get
{
if (m_MonoBehaviourCoroutineRunner == null)
{
throw new NullReferenceException("MonoBehaviour coroutine runner not set");
}
return m_MonoBehaviourCoroutineRunner;
}
set { m_MonoBehaviourCoroutineRunner = value; }
}
public CoroutineTestWorkItem(TestMethod test, ITestFilter filter)
: base(test, null)
{
m_Command = test.RunState == RunState.Runnable || test.RunState == RunState.Explicit && filter.IsExplicitMatch(test)
? CommandBuilder.MakeTestCommand(test)
: CommandBuilder.MakeSkipCommand(test);
}
protected override IEnumerable PerformWork()
{
if (m_Command is SkipCommand)
{
m_Command.Execute(Context);
Result = Context.CurrentResult;
WorkItemComplete();
yield break;
}
if (m_Command is ApplyChangesToContextCommand)
{
var applyChangesToContextCommand = (ApplyChangesToContextCommand)m_Command;
applyChangesToContextCommand.ApplyChanges(Context);
m_Command = applyChangesToContextCommand.GetInnerCommand();
}
var enumerableTestMethodCommand = (IEnumerableTestMethodCommand)m_Command;
try
{
var executeEnumerable = enumerableTestMethodCommand.ExecuteEnumerable(Context).GetEnumerator();
var coroutineRunner = new CoroutineRunner(monoBehaviourCoroutineRunner, Context);
yield return coroutineRunner.HandleEnumerableTest(executeEnumerable);
if (coroutineRunner.HasFailedWithTimeout())
{
Context.CurrentResult.SetResult(ResultState.Failure, string.Format("Test exceeded Timeout value of {0}ms", Context.TestCaseTimeout));
}
while (executeEnumerable.MoveNext()) {}
Result = Context.CurrentResult;
}
finally
{
WorkItemComplete();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b557515fff172984e8c4400b43f1c631
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,137 @@
using System;
using System.Collections;
using System.Linq;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using NUnit.Framework.Internal.Execution;
using UnityEngine.TestTools;
using SetUpTearDownCommand = NUnit.Framework.Internal.Commands.SetUpTearDownCommand;
using TestActionCommand = NUnit.Framework.Internal.Commands.TestActionCommand;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class EditModeTestCallbacks
{
public static Action RestoringTestContext { get; set; }
}
internal class DefaultTestWorkItem : UnityWorkItem
{
private TestCommand _command;
public DefaultTestWorkItem(TestMethod test, ITestFilter filter)
: base(test, null)
{
_command = test.RunState == RunState.Runnable || test.RunState == RunState.Explicit && filter.IsExplicitMatch(test)
? BuildTestCommand(test)
: new SkipCommand(test);
}
private static TestCommand BuildTestCommand(TestMethod test)
{
var command = (TestCommand)new TestMethodCommand(test);
command = new UnityLogCheckDelegatingCommand(command);
foreach (var wrapper in test.Method.GetCustomAttributes<IWrapTestMethod>(true))
{
command = wrapper.Wrap(command);
if (command == null)
{
var message = string.Format("IWrapTestMethod implementation '{0}' returned null as command.", wrapper.GetType().FullName);
return new FailCommand(test, ResultState.Failure, message);
}
}
command = new TestTools.TestActionCommand(command);
command = new TestTools.SetUpTearDownCommand(command);
command = new ImmediateEnumerableCommand(command);
foreach (var wrapper in test.Method.GetCustomAttributes<IWrapSetUpTearDown>(true))
{
command = wrapper.Wrap(command);
if (command == null)
{
var message = string.Format("IWrapSetUpTearDown implementation '{0}' returned null as command.", wrapper.GetType().FullName);
return new FailCommand(test, ResultState.Failure, message);
}
}
command = new EnumerableSetUpTearDownCommand(command);
command = new OuterUnityTestActionCommand(command);
IApplyToContext[] changes = test.Method.GetCustomAttributes<IApplyToContext>(true);
if (changes.Length > 0)
{
command = new EnumerableApplyChangesToContextCommand(command, changes);
}
return command;
}
protected override IEnumerable PerformWork()
{
if (m_DontRunRestoringResult && EditModeTestCallbacks.RestoringTestContext != null)
{
EditModeTestCallbacks.RestoringTestContext();
Result = Context.CurrentResult;
yield break;
}
try
{
if (_command is SkipCommand || _command is FailCommand)
{
Result = _command.Execute(Context);
yield break;
}
if (!(_command is IEnumerableTestMethodCommand))
{
Debug.LogError("Cannot perform work on " + _command.GetType().Name);
yield break;
}
foreach (var workItemStep in ((IEnumerableTestMethodCommand)_command).ExecuteEnumerable(Context))
{
ResultedInDomainReload = false;
if (workItemStep is IEditModeTestYieldInstruction)
{
var editModeTestYieldInstruction = (IEditModeTestYieldInstruction)workItemStep;
yield return editModeTestYieldInstruction;
var enumerator = editModeTestYieldInstruction.Perform();
while (true)
{
bool moveNext;
try
{
moveNext = enumerator.MoveNext();
}
catch (Exception e)
{
Context.CurrentResult.RecordException(e);
break;
}
if (!moveNext)
{
break;
}
yield return null;
}
}
else
{
yield return workItemStep;
}
}
Result = Context.CurrentResult;
}
finally
{
WorkItemComplete();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7cfda246e604b945b12b7afedb094ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class FailCommand : TestCommand
{
private ResultState m_ResultState;
private string m_Message;
public FailCommand(Test test, ResultState resultState, string message)
: base(test)
{
m_ResultState = resultState;
m_Message = message;
}
public override TestResult Execute(ITestExecutionContext context)
{
context.CurrentResult.SetResult(m_ResultState, m_Message);
return context.CurrentResult;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68e5dc8bfd5d72647a93b7f2e1da831a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
using System.Collections;
using NUnit.Framework.Internal;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal interface IEnumerableTestMethodCommand
{
IEnumerable ExecuteEnumerable(ITestExecutionContext context);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dbd43d8a3b8122d4e89b055f53382b11
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,13 @@
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class PlaymodeWorkItemFactory : WorkItemFactory
{
protected override UnityWorkItem Create(TestMethod method, ITestFilter filter, ITest loadedTest)
{
return new CoroutineTestWorkItem(method, filter);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ef6801a8b664544aa9f2ab1bc1f8b60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,4 @@
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class RestoreTestContextAfterDomainReload {}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 26721f9940339264fb14bdbfe1290e21
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,106 @@
using System;
using System.Collections;
using System.Linq;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class UnityLogCheckDelegatingCommand : DelegatingTestCommand, IEnumerableTestMethodCommand
{
public UnityLogCheckDelegatingCommand(TestCommand innerCommand)
: base(innerCommand) {}
public override TestResult Execute(ITestExecutionContext context)
{
var logCollector = new LogScope();
try
{
innerCommand.Execute(context);
if (logCollector.AnyFailingLogs())
{
var failingLog = logCollector.FailingLogs.First();
throw new UnhandledLogMessageException(failingLog);
}
if (logCollector.ExpectedLogs.Any())
{
throw new UnexpectedLogMessageException(logCollector.ExpectedLogs.Peek());
}
}
catch (Exception exception)
{
context.CurrentResult.RecordException(exception);
}
logCollector.Dispose();
return context.CurrentResult;
}
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
{
var logCollector = new LogScope();
if (!(innerCommand is IEnumerableTestMethodCommand))
{
Execute(context);
yield break;
}
var enumerableTestMethodCommand = (IEnumerableTestMethodCommand)innerCommand;
IEnumerable executeEnumerable;
try
{
executeEnumerable = enumerableTestMethodCommand.ExecuteEnumerable(context);
}
catch (Exception e)
{
context.CurrentResult.RecordException(e);
yield break;
}
foreach (var step in executeEnumerable)
{
try
{
if (logCollector.AnyFailingLogs())
{
var failingLog = logCollector.FailingLogs.First();
throw new UnhandledLogMessageException(failingLog);
}
}
catch (Exception e)
{
context.CurrentResult.RecordException(e);
break;
}
yield return step;
}
try
{
if (logCollector.AnyFailingLogs())
{
var failingLog = logCollector.FailingLogs.First();
throw new UnhandledLogMessageException(failingLog);
}
logCollector.ProcessExpectedLogs();
if (logCollector.ExpectedLogs.Any())
{
throw new UnexpectedLogMessageException(LogScope.Current.ExpectedLogs.Peek());
}
}
catch (Exception exception)
{
context.CurrentResult.RecordException(exception);
}
logCollector.Dispose();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 48230e4e90fb4d14a9d56bddea898413
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,96 @@
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NUnit;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using UnityEngine.TestTools.NUnitExtensions;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal interface IUnityTestAssemblyRunner
{
ITest LoadedTest { get; }
ITestResult Result { get; }
bool IsTestLoaded { get; }
bool IsTestRunning { get; }
bool IsTestComplete { get; }
UnityWorkItem TopLevelWorkItem { get; set; }
UnityTestExecutionContext GetCurrentContext();
ITest Load(Assembly[] assemblies, IDictionary<string, object> settings);
IEnumerable Run(ITestListener listener, ITestFilter filter);
void StopRun();
}
internal class UnityTestAssemblyRunner : IUnityTestAssemblyRunner
{
private readonly UnityTestAssemblyBuilder unityBuilder;
private readonly WorkItemFactory m_Factory;
protected UnityTestExecutionContext Context { get; set; }
public UnityTestExecutionContext GetCurrentContext()
{
return UnityTestExecutionContext.CurrentContext;
}
protected IDictionary<string, object> Settings { get; set; }
public ITest LoadedTest { get; protected set; }
public ITestResult Result
{
get { return TopLevelWorkItem == null ? null : TopLevelWorkItem.Result; }
}
public bool IsTestLoaded
{
get { return LoadedTest != null; }
}
public bool IsTestRunning
{
get { return TopLevelWorkItem != null && TopLevelWorkItem.State == NUnit.Framework.Internal.Execution.WorkItemState.Running; }
}
public bool IsTestComplete
{
get { return TopLevelWorkItem != null && TopLevelWorkItem.State == NUnit.Framework.Internal.Execution.WorkItemState.Complete; }
}
public UnityTestAssemblyRunner(UnityTestAssemblyBuilder builder, WorkItemFactory factory)
{
unityBuilder = builder;
m_Factory = factory;
Context = new UnityTestExecutionContext();
}
public ITest Load(Assembly[] assemblies, IDictionary<string, object> settings)
{
Settings = settings;
if (settings.ContainsKey(FrameworkPackageSettings.RandomSeed))
Randomizer.InitialSeed = (int)settings[FrameworkPackageSettings.RandomSeed];
return LoadedTest = unityBuilder.Build(assemblies, settings);
}
public IEnumerable Run(ITestListener listener, ITestFilter filter)
{
TopLevelWorkItem = m_Factory.Create(LoadedTest, filter);
TopLevelWorkItem.InitializeContext(Context);
UnityTestExecutionContext.CurrentContext = Context;
Context.Listener = listener;
return TopLevelWorkItem.Execute();
}
public UnityWorkItem TopLevelWorkItem { get; set; }
public void StopRun()
{
if (IsTestRunning)
{
TopLevelWorkItem.Cancel(false);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 874e40a588dbb1e48bc128d686337d4e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using NUnit.Framework;
using NUnit.Framework.Constraints;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Execution;
using UnityEngine.TestTools;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class UnityTestExecutionContext : ITestExecutionContext
{
private readonly UnityTestExecutionContext _priorContext;
private TestResult _currentResult;
private int _assertCount;
public static UnityTestExecutionContext CurrentContext { get; set; }
public UnityTestExecutionContext Context { get; private set; }
public Test CurrentTest { get; set; }
public DateTime StartTime { get; set; }
public long StartTicks { get; set; }
public TestResult CurrentResult
{
get { return _currentResult; }
set
{
_currentResult = value;
if (value != null)
OutWriter = value.OutWriter;
}
}
public object TestObject { get; set; }
public string WorkDirectory { get; set; }
private TestExecutionStatus _executionStatus;
public TestExecutionStatus ExecutionStatus
{
get
{
// ExecutionStatus may have been set to StopRequested or AbortRequested
// in a prior context. If so, reflect the same setting in this context.
if (_executionStatus == TestExecutionStatus.Running && _priorContext != null)
_executionStatus = _priorContext.ExecutionStatus;
return _executionStatus;
}
set
{
_executionStatus = value;
// Push the same setting up to all prior contexts
if (_priorContext != null)
_priorContext.ExecutionStatus = value;
}
}
public List<ITestAction> UpstreamActions { get; private set; }
public int TestCaseTimeout { get; set; }
public CultureInfo CurrentCulture { get; set; }
public CultureInfo CurrentUICulture { get; set; }
public ITestListener Listener { get; set; }
public UnityTestExecutionContext()
{
UpstreamActions = new List<ITestAction>();
CurrentContext = this;
}
public UnityTestExecutionContext(UnityTestExecutionContext other)
{
_priorContext = other;
CurrentTest = other.CurrentTest;
CurrentResult = other.CurrentResult;
TestObject = other.TestObject;
WorkDirectory = other.WorkDirectory;
Listener = other.Listener;
TestCaseTimeout = other.TestCaseTimeout;
UpstreamActions = new List<ITestAction>(other.UpstreamActions);
SetUpTearDownState = other.SetUpTearDownState;
OuterUnityTestActionState = other.OuterUnityTestActionState;
TestContext.CurrentTestExecutionContext = this;
CurrentCulture = other.CurrentCulture;
CurrentUICulture = other.CurrentUICulture;
CurrentContext = this;
}
public TextWriter OutWriter { get; private set; }
public bool StopOnError { get; set; }
public IWorkItemDispatcher Dispatcher { get; set; }
public ParallelScope ParallelScope { get; set; }
public string WorkerId { get; private set; }
public Randomizer RandomGenerator { get; private set; }
public ValueFormatter CurrentValueFormatter { get; private set; }
public bool IsSingleThreaded { get; set; }
public BeforeAfterTestCommandState SetUpTearDownState { get; set; }
public BeforeAfterTestCommandState OuterUnityTestActionState { get; set; }
internal int AssertCount
{
get
{
return _assertCount;
}
}
public void IncrementAssertCount()
{
_assertCount += 1;
}
public void AddFormatter(ValueFormatterFactory formatterFactory)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 59ff995fabb3bac45afa0f96f333e5dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,112 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Execution;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal abstract class UnityWorkItem
{
protected readonly WorkItemFactory m_Factory;
protected bool m_ExecuteTestStartEvent;
protected bool m_DontRunRestoringResult;
public event EventHandler Completed;
public bool ResultedInDomainReload { get; internal set; }
public UnityTestExecutionContext Context { get; private set; }
public Test Test { get; private set; }
public TestResult Result { get; protected set; }
public WorkItemState State { get; private set; }
public List<ITestAction> Actions { get; private set; }
protected UnityWorkItem(Test test, WorkItemFactory factory)
{
m_Factory = factory;
Test = test;
Actions = new List<ITestAction>();
Result = test.MakeTestResult();
State = WorkItemState.Ready;
m_ExecuteTestStartEvent = ShouldExecuteStartEvent();
m_DontRunRestoringResult = ShouldRestore(test);
}
protected static bool ShouldRestore(ITest loadedTest)
{
return UnityWorkItemDataHolder.alreadyExecutedTests != null && UnityWorkItemDataHolder.alreadyExecutedTests.Contains(loadedTest.FullName);
}
protected bool ShouldExecuteStartEvent()
{
return UnityWorkItemDataHolder.alreadyStartedTests != null && UnityWorkItemDataHolder.alreadyStartedTests.All(x => x != Test.FullName) && !ShouldRestore(Test);
}
protected abstract IEnumerable PerformWork();
public void InitializeContext(UnityTestExecutionContext context)
{
Context = context;
if (Test is TestAssembly)
Actions.AddRange(ActionsHelper.GetActionsFromTestAssembly((TestAssembly)Test));
else if (Test is ParameterizedMethodSuite)
Actions.AddRange(ActionsHelper.GetActionsFromTestMethodInfo(Test.Method));
else if (Test.TypeInfo != null)
Actions.AddRange(ActionsHelper.GetActionsFromTypesAttributes(Test.TypeInfo.Type));
}
public virtual IEnumerable Execute()
{
Context.CurrentTest = this.Test;
Context.CurrentResult = this.Result;
if (m_ExecuteTestStartEvent)
{
Context.Listener.TestStarted(Test);
}
Context.StartTime = DateTime.UtcNow;
Context.StartTicks = Stopwatch.GetTimestamp();
State = WorkItemState.Running;
return PerformWork();
}
protected void WorkItemComplete()
{
State = WorkItemState.Complete;
Result.StartTime = Context.StartTime;
Result.EndTime = DateTime.UtcNow;
long tickCount = Stopwatch.GetTimestamp() - Context.StartTicks;
double seconds = (double)tickCount / Stopwatch.Frequency;
Result.Duration = seconds;
//Result.AssertCount += Context.AssertCount;
Context.Listener.TestFinished(Result);
if (Completed != null)
Completed(this, EventArgs.Empty);
Context.TestObject = null;
Test.Fixture = null;
}
public virtual void Cancel(bool force)
{
Context.Listener.TestFinished(Result);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 79ced2556f0af814a840b86232613ff1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
internal class UnityWorkItemDataHolder
{
public static List<string> alreadyStartedTests = new List<string>();
public static List<string> alreadyExecutedTests;
}
}

Some files were not shown because too many files have changed in this diff Show More