File size: 5,025 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using UnityEngine.TestTools;
using UnityEngine.TestTools.Logging;
using UnityEngine.TestTools.TestRunner;
namespace UnityEngine.TestRunner.NUnitExtensions.Runner
{
class UnityLogCheckDelegatingCommand : DelegatingTestCommand, IEnumerableTestMethodCommand
{
static Dictionary<object, bool?> s_AttributeCache = new Dictionary<object, bool?>();
public UnityLogCheckDelegatingCommand(TestCommand innerCommand)
: base(innerCommand) {}
public override TestResult Execute(ITestExecutionContext context)
{
using (var logScope = new LogScope())
{
if (ExecuteAndCheckLog(logScope, context.CurrentResult, () => innerCommand.Execute(context)))
PostTestValidation(logScope, innerCommand, context.CurrentResult);
}
return context.CurrentResult;
}
public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
{
if (!(innerCommand is IEnumerableTestMethodCommand enumerableTestMethodCommand))
{
Execute(context);
yield break;
}
using (var logScope = new LogScope())
{
IEnumerable executeEnumerable = null;
if (!ExecuteAndCheckLog(logScope, context.CurrentResult,
() => executeEnumerable = enumerableTestMethodCommand.ExecuteEnumerable(context)))
yield break;
foreach (var step in executeEnumerable)
{
// do not check expected logs here - we want to permit expecting and receiving messages to run
// across frames. (but we do always want to catch a fail immediately.)
if (!CheckFailingLogs(logScope, context.CurrentResult))
yield break;
yield return step;
}
if (!CheckLogs(context.CurrentResult, logScope))
yield break;
PostTestValidation(logScope, innerCommand, context.CurrentResult);
}
}
static bool CaptureException(TestResult result, Action action)
{
try
{
action();
return true;
}
catch (Exception e)
{
result.RecordException(e);
return false;
}
}
static bool ExecuteAndCheckLog(LogScope logScope, TestResult result, Action action)
=> CaptureException(result, action) && CheckLogs(result, logScope);
static void PostTestValidation(LogScope logScope, TestCommand command, TestResult result)
{
if (MustExpect(command.Test.Method.MethodInfo))
CaptureException(result, logScope.NoUnexpectedReceived);
}
static bool CheckLogs(TestResult result, LogScope logScope)
{
try
{
logScope.EvaluateLogScope(true);
}
catch (Exception e)
{
result.RecordException(e);
return false;
}
return true;
}
static bool CheckFailingLogs(LogScope logScope, TestResult result)
{
try
{
logScope.EvaluateLogScope(false);
}
catch (Exception e)
{
result.RecordException(e);
return false;
}
return true;
}
static bool MustExpect(MemberInfo method)
{
// method
var methodAttr = method.GetCustomAttributes<TestMustExpectAllLogsAttribute>(true).FirstOrDefault();
if (methodAttr != null)
return methodAttr.MustExpect;
// fixture
var fixture = method.DeclaringType;
if (!s_AttributeCache.TryGetValue(fixture, out var mustExpect))
{
var fixtureAttr = fixture.GetCustomAttributes<TestMustExpectAllLogsAttribute>(true).FirstOrDefault();
mustExpect = s_AttributeCache[fixture] = fixtureAttr?.MustExpect;
}
if (mustExpect != null)
return mustExpect.Value;
// assembly
var assembly = fixture.Assembly;
if (!s_AttributeCache.TryGetValue(assembly, out mustExpect))
{
var assemblyAttr = assembly.GetCustomAttributes<TestMustExpectAllLogsAttribute>().FirstOrDefault();
mustExpect = s_AttributeCache[assembly] = assemblyAttr?.MustExpect;
}
return mustExpect == true;
}
}
}
|