-
Notifications
You must be signed in to change notification settings - Fork 423
/
Copy pathDebugUtils.cs
73 lines (59 loc) · 3.41 KB
/
DebugUtils.cs
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
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using NUnit.Framework.Internal;
using osu.Framework.Extensions.ObjectExtensions;
namespace osu.Framework.Development
{
public static class DebugUtils
{
public static bool IsNUnitRunning => is_nunit_running.Value;
private static readonly Lazy<bool> is_nunit_running = new Lazy<bool>(() =>
{
var entry = Assembly.GetEntryAssembly();
// when running under nunit + netcore, entry assembly becomes nunit itself (testhost, Version=15.0.0.0), which isn't what we want.
// when running under nunit + Rider > 2020.2 EAP6, entry assembly becomes ReSharperTestRunner[32|64], which isn't what we want.
bool entryIsKnownTestAssembly = entry != null && (entry.Location.Contains("testhost") || entry.Location.Contains("ReSharperTestRunner"));
// null assembly can indicate nunit, but it can also indicate native code (e.g. android).
// to distinguish nunit runs from android launches, check the class name of the current test.
// if no actual test is running, nunit will make up an ad-hoc test context, which we can match on
// to eliminate such false positives.
bool nullEntryWithActualTestContext = entry == null && TestContext.CurrentContext.Test.ClassName != typeof(TestExecutionContext.AdhocContext).FullName;
return entryIsKnownTestAssembly || nullEntryWithActualTestContext;
}
);
private static readonly Lazy<Assembly> nunit_test_assembly = new Lazy<Assembly>(() =>
{
Debug.Assert(IsNUnitRunning);
string testName = TestContext.CurrentContext.Test.ClassName.AsNonNull();
return AppDomain.CurrentDomain.GetAssemblies().First(asm => asm.GetType(testName) != null);
}
);
public static bool IsDebugBuild => is_debug_build.Value;
private static readonly Lazy<bool> is_debug_build = new Lazy<bool>(() =>
isDebugAssembly(typeof(DebugUtils).Assembly) || isDebugAssembly(GetEntryAssembly())
);
/// <summary>
/// Whether the framework is currently logging performance issues.
/// This should be used only when a configuration is not available via DI or otherwise (ie. in a static context).
/// </summary>
public static bool LogPerformanceIssues { get; internal set; }
// https://stackoverflow.com/a/2186634
private static bool isDebugAssembly(Assembly? assembly) => assembly?.GetCustomAttributes(false).OfType<DebuggableAttribute>().Any(da => da.IsJITTrackingEnabled) ?? false;
/// <summary>
/// Gets the entry assembly, or calling assembly otherwise.
/// When running under NUnit, the assembly of the current test will be returned instead.
/// </summary>
/// <returns>The entry assembly (usually obtained via <see cref="Assembly.GetEntryAssembly()"/>.</returns>
public static Assembly GetEntryAssembly()
{
if (IsNUnitRunning)
return nunit_test_assembly.Value;
return Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();
}
}
}