You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
16 KiB
433 lines
16 KiB
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using NUnit.Framework; |
|
using Unity.Burst.Editor; |
|
using UnityEditor; |
|
using UnityEngine; |
|
using UnityEngine.TestTools; |
|
using Unity.Collections; |
|
using Unity.Burst; |
|
using Unity.Jobs; |
|
|
|
[TestFixture] |
|
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)] |
|
public class BurstInspectorGUITests |
|
{ |
|
private readonly WaitUntil _waitForInitialized = |
|
new WaitUntil(() => EditorWindow.GetWindow<BurstInspectorGUI>()._initialized); |
|
|
|
[UnitySetUp] |
|
public IEnumerator SetUp() |
|
{ |
|
// Close down window if it's open, to start with a fresh inspector. |
|
EditorWindow.GetWindow<BurstInspectorGUI>().Close(); |
|
EditorWindow.GetWindow<BurstInspectorGUI>().Show(); |
|
|
|
// Make sure window is actually initialized before continuing. |
|
yield return _waitForInitialized; |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator TestInspectorOpenDuringDomainReloadDoesNotLogErrors() |
|
{ |
|
// Show Inspector window |
|
EditorWindow.GetWindow<BurstInspectorGUI>().Show(); |
|
|
|
Assert.IsTrue(EditorWindow.HasOpenInstances<BurstInspectorGUI>()); |
|
|
|
// Ask for domain reload |
|
EditorUtility.RequestScriptReload(); |
|
|
|
// Wait for the domain reload to be completed |
|
yield return new WaitForDomainReload(); |
|
|
|
Assert.IsTrue(EditorWindow.HasOpenInstances<BurstInspectorGUI>()); |
|
|
|
// Hide Inspector window |
|
EditorWindow.GetWindow<BurstInspectorGUI>().Close(); |
|
|
|
Assert.IsFalse(EditorWindow.HasOpenInstances<BurstInspectorGUI>()); |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator DisassemblerNotChangingUnexpectedlyTest() |
|
{ |
|
var window = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
// Selecting a specific assembly. |
|
window._treeView.TrySelectByDisplayName("BurstInspectorGUITests.MyJob - (IJob)"); |
|
|
|
// Sending event to set the displayname, to avoid it resetting _scrollPos because of target change. |
|
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) }); |
|
yield return null; |
|
|
|
// Doing actual test work: |
|
var prev = new BurstDisassemblerWithCopy(window._burstDisassembler); |
|
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) }); |
|
yield return null; |
|
Assert.IsTrue(prev.Equals(window._burstDisassembler), "Public fields changed in burstDisassembler even though they shouldn't"); |
|
|
|
prev = new BurstDisassemblerWithCopy(window._burstDisassembler); |
|
window.SendEvent(new Event() { type = EventType.MouseUp, mousePosition = Vector2.zero }); |
|
yield return null; |
|
Assert.IsTrue(prev.Equals(window._burstDisassembler), "Public fields changed in burstDisassembler even though they shouldn't"); |
|
|
|
prev = new BurstDisassemblerWithCopy(window._burstDisassembler); |
|
window._treeView.TrySelectByDisplayName("BurstReflectionTests.MyJob - (IJob)"); // Changing job, meaning SetText(.) should be called during next event. |
|
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) }); |
|
yield return null; |
|
Assert.IsFalse(prev.Equals(window._burstDisassembler), "Public fields of burstDisassembler did not change"); |
|
|
|
window.Close(); |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator InspectorStallingLoadTest() |
|
{ |
|
var win = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
// Error was triggered by selecting a display name, filtering it out, and then doing a script recompilation. |
|
win._treeView.TrySelectByDisplayName("BurstInspectorGUITests.MyJob - (IJob)"); |
|
win._searchFieldJobs.SetFocus(); |
|
yield return null; |
|
|
|
// Simulate event for sending "a" as it will filter out the chosen job. |
|
win.SendEvent(Event.KeyboardEvent("a")); |
|
yield return null; |
|
|
|
// Send RequestScriptReload to try and trigger the bug |
|
// and wait for it to return |
|
EditorUtility.RequestScriptReload(); |
|
yield return new WaitForDomainReload(); |
|
|
|
win = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
// Wait for it to actually initialize. |
|
yield return _waitForInitialized; |
|
|
|
Assert.IsTrue(win._initialized, "BurstInspector did not initialize properly after script reload"); |
|
|
|
win.Close(); |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator FontStyleDuringDomainReloadTest() |
|
{ |
|
// Enter play mod |
|
yield return new EnterPlayMode(); |
|
|
|
// Exit play mode |
|
yield return new ExitPlayMode(); |
|
|
|
// Wait for the inspector to actually reload |
|
yield return _waitForInitialized; |
|
|
|
var inspectorWindow = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
#if UNITY_2023_1_OR_NEWER |
|
Assert.AreEqual("RobotoMono-Regular", inspectorWindow._font.name); |
|
#else |
|
if (Application.platform == RuntimePlatform.WindowsEditor) |
|
{ |
|
Assert.AreEqual("Consolas", inspectorWindow._font.name); |
|
} |
|
else |
|
{ |
|
Assert.AreEqual("Courier", inspectorWindow._font.name); |
|
} |
|
#endif |
|
|
|
inspectorWindow.Close(); |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator BranchHoverTest() |
|
{ |
|
var info = SetupBranchTest(); |
|
var window = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
window.SendEvent(new Event() { type = EventType.MouseUp, mousePosition = info.mousePos }); |
|
var branch = window._textArea.hoveredBranch; |
|
yield return null; |
|
|
|
// Close window to avoid it sending more events |
|
window.Close(); |
|
|
|
Assert.AreNotEqual(branch, default(LongTextArea.Branch), "Mouse is not hovering any branch."); |
|
Assert.AreEqual(info.blockIdx.src, branch.Edge.OriginRef.BlockIndex); |
|
Assert.AreEqual(info.blockIdx.dst, branch.Edge.LineRef.BlockIndex); |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator ClickBranchTest() |
|
{ |
|
var info = SetupBranchTest(); |
|
var window = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
// Seeing if clicking the branch takes us to a spot where branch is still hovered. |
|
window.SendEvent(new Event() { type = EventType.MouseDown, mousePosition = info.mousePos }); |
|
var branch = window._textArea.hoveredBranch; |
|
yield return null; |
|
|
|
Assert.AreNotEqual(branch, default(LongTextArea.Branch), "Mouse is not hovering any branch."); |
|
Assert.AreEqual(info.blockIdx.src, branch.Edge.OriginRef.BlockIndex); |
|
Assert.AreEqual(info.blockIdx.dst, branch.Edge.LineRef.BlockIndex); |
|
|
|
// Going back again. |
|
window.SendEvent(new Event() { type = EventType.MouseDown, mousePosition = info.mousePos }); |
|
var branch2 = window._textArea.hoveredBranch; |
|
yield return null; |
|
|
|
Assert.AreNotEqual(branch2, default(LongTextArea.Branch), "Mouse is not hovering any branch."); |
|
Assert.AreEqual(info.blockIdx.src, branch2.Edge.OriginRef.BlockIndex); |
|
Assert.AreEqual(info.blockIdx.dst, branch2.Edge.LineRef.BlockIndex); |
|
|
|
// Close window to avoid it sending more events. |
|
window.Close(); |
|
} |
|
|
|
private struct InfoThingy |
|
{ |
|
public (int src, int dst) blockIdx; |
|
public Vector2 mousePos; |
|
} |
|
|
|
private InfoThingy SetupBranchTest() |
|
{ |
|
var window = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
// Selecting a specific assembly. |
|
window._treeView.TrySelectByDisplayName("BurstInspectorGUITests.MyJob - (IJob)"); |
|
// Make sure we use fontSize 12: |
|
window.fontSizeIndex = 4; |
|
window._textArea.Invalidate(); |
|
window.fixedFontStyle = null; |
|
// Force window size to actually show branch arrows. |
|
window.position = new Rect(window.position.x, window.position.y, 390, 405); |
|
|
|
// Sending event to set the displayname, to avoid it resetting _scrollPos because of target change. |
|
// Sending two events as initial guess for buttonbar width might be off, and it will be a precise calculation after second event. |
|
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) }); |
|
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) }); |
|
|
|
// Setting up for the test. |
|
// Finding an edge: |
|
int dstBlockIdx = -1; |
|
int srcBlockIdx = -1; |
|
int line = -1; |
|
for (int idx = 0; idx < window._burstDisassembler.Blocks.Count; idx++) |
|
{ |
|
var block = window._burstDisassembler.Blocks[idx]; |
|
if (block.Edges != null) |
|
{ |
|
foreach (var edge in block.Edges) |
|
{ |
|
if (edge.Kind == BurstDisassembler.AsmEdgeKind.OutBound) |
|
{ |
|
dstBlockIdx = edge.LineRef.BlockIndex; |
|
line = window._textArea.blockLine[dstBlockIdx]; |
|
if ((dstBlockIdx == idx + 1 && edge.LineRef.LineIndex == 0)) // pointing to next line |
|
{ |
|
continue; |
|
} |
|
srcBlockIdx = idx; |
|
break; |
|
} |
|
} |
|
if (srcBlockIdx != -1) |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
if (srcBlockIdx == -1) |
|
{ |
|
window.Close(); |
|
throw new System.Exception("No edges present in assembly for \"BurstInspectorGUITests.MyJob - (IJob)\""); |
|
} |
|
|
|
float dist = window._textArea.fontHeight * line; |
|
|
|
float x = (window.position.width - (window._inspectorView.width + BurstInspectorGUI._scrollbarThickness)) + window._textArea.horizontalPad - (2*window._textArea.fontWidth); |
|
|
|
// setting _ScrollPos so end of arrow is at bottom of screen, to make sure there is actually room for the scrolling. |
|
window._scrollPos = new Vector2(0, dist - window._inspectorView.height * 0.93f); |
|
|
|
// Setting mousePos to bottom of inspector view. |
|
float topOfInspectorToBranchArrow = window._buttonOverlapInspectorView + 66.5f;//66.5f is the size of space over the treeview of different jobs. |
|
|
|
var mousePos = new Vector2(x, topOfInspectorToBranchArrow + window._inspectorView.height - window._textArea.fontHeight); |
|
|
|
return new InfoThingy() { blockIdx = (srcBlockIdx, dstBlockIdx), mousePos = mousePos}; |
|
} |
|
|
|
public static IEnumerable ValueSource |
|
{ |
|
get |
|
{ |
|
yield return "BurstInspectorGUITests.MyJob - (IJob)"; |
|
yield return "BurstReflectionTests.GenericType`1.NestedGeneric`1[System.Int32,System.Single].TestMethod3()"; |
|
yield return "BurstReflectionTests.GenericType`1.NestedNonGeneric[System.Int32].TestMethod2()"; |
|
yield return "BurstReflectionTests.GenericParallelForJob`1[System.Int32] - (IJobParallelFor)"; |
|
} |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator FocusCodeTest([ValueSource(nameof(ValueSource))] string job) |
|
{ |
|
var win = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
win._treeView.TrySelectByDisplayName(job); |
|
|
|
yield return null; |
|
|
|
// Doesn't check that it's at the right spot, simply that it actually moves |
|
Assert.IsFalse(Mathf.Approximately(win._inspectorView.y, 0f), "Inspector view did not change"); |
|
win.Close(); |
|
} |
|
|
|
[UnityTest] |
|
public IEnumerator FocusCodeNotBranchesTest() |
|
{ |
|
const string case1 = "BurstInspectorGUITests.MyJob - (IJob)"; |
|
const string case2 = "BurstInspectorGUITests.MyJob2 - (IJob)"; |
|
|
|
var win = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
// Force window size to be small enough for it to position it more to the right. |
|
win.position = new Rect(win.position.x, win.position.y, 390, 405); |
|
|
|
// Test one where it should focus. |
|
win._treeView.TrySelectByDisplayName(case1); |
|
yield return null; |
|
|
|
var val1 = win._inspectorView.x; |
|
var result1 = Mathf.Approximately(val1, 0f); |
|
|
|
|
|
// Test two with no focus. |
|
win._assemblyKind = BurstInspectorGUI.AssemblyOptions.PlainWithDebugInformation; |
|
win._treeView.TrySelectByDisplayName(case2); |
|
yield return null; |
|
|
|
var val2 = win._inspectorView.x; |
|
var result2 = Mathf.Approximately(val2, 0f); |
|
|
|
// Cleanup and test assertions. |
|
win.Close(); |
|
Assert.IsFalse(result1, $"Inspector view did not change (Is {val1})."); |
|
Assert.IsTrue(result2, $"Inspector view changed unexpectedly (Is {val2})."); |
|
} |
|
|
|
public IEnumerator SelectionNotOutsideBoundsTest() |
|
{ |
|
void MoveSelection(BurstInspectorGUI gui, LongTextArea.Direction dir) |
|
{ |
|
switch (dir) |
|
{ |
|
case LongTextArea.Direction.Down: |
|
gui._textArea.SelectAll(); |
|
gui._textArea.MoveSelectionDown(gui._inspectorView, true); |
|
break; |
|
case LongTextArea.Direction.Right: |
|
gui._textArea.SelectAll(); |
|
gui._textArea.MoveSelectionRight(gui._inspectorView, true); |
|
break; |
|
case LongTextArea.Direction.Left: |
|
gui._textArea.selectDragPos = Vector2.zero; |
|
gui._textArea.MoveSelectionLeft(gui._inspectorView, true); |
|
break; |
|
case LongTextArea.Direction.Up: |
|
gui._textArea.selectDragPos = Vector2.zero; |
|
gui._textArea.MoveSelectionUp(gui._inspectorView, true); |
|
break; |
|
} |
|
} |
|
|
|
var win = EditorWindow.GetWindow<BurstInspectorGUI>(); |
|
|
|
win._treeView.TrySelectByDisplayName("BurstInspectorGUITests.MyJob - (IJob)"); |
|
yield return null; |
|
|
|
try |
|
{ |
|
foreach (var dir in Enum.GetValues(typeof(LongTextArea.Direction))) |
|
{ |
|
MoveSelection(win, (LongTextArea.Direction)dir); |
|
yield return null; |
|
|
|
// Check that no errors have happened. |
|
LogAssert.NoUnexpectedReceived(); |
|
} |
|
} |
|
finally |
|
{ |
|
win.Close(); |
|
} |
|
} |
|
|
|
[BurstCompile] |
|
private struct MyJob : IJob |
|
{ |
|
[ReadOnly] |
|
public NativeArray<float> Inpút; |
|
|
|
[WriteOnly] |
|
public NativeArray<float> Output; |
|
|
|
public void Execute() |
|
{ |
|
float result = 0.0f; |
|
for (int i = 0; i < Inpút.Length; i++) |
|
{ |
|
result += Inpút[i]; |
|
} |
|
Output[0] = result; |
|
} |
|
} |
|
|
|
[BurstCompile] |
|
private struct MyJob2 : IJob |
|
{ |
|
[ReadOnly] |
|
public NativeArray<float> Inpút; |
|
|
|
[WriteOnly] |
|
public NativeArray<float> Output; |
|
|
|
public void Execute() |
|
{ |
|
float result = 0.0f; |
|
for (int i = 0; i < Inpút.Length; i++) |
|
{ |
|
result += Inpút[i]; |
|
} |
|
Output[0] = result; |
|
} |
|
} |
|
|
|
private class BurstDisassemblerWithCopy : BurstDisassembler |
|
{ |
|
public List<AsmBlock> BlocksCopy; |
|
public bool IsColoredCopy; |
|
public List<AsmLine> LinesCopy; |
|
public List<AsmToken> TokensCopy; |
|
public BurstDisassemblerWithCopy(BurstDisassembler disassembler) : base() |
|
{ |
|
IsColoredCopy = disassembler.IsColored; |
|
|
|
BlocksCopy = new List<AsmBlock>(disassembler.Blocks); |
|
LinesCopy = new List<AsmLine>(disassembler.Lines); |
|
TokensCopy = new List<AsmToken>(disassembler.Tokens); |
|
} |
|
|
|
public bool Equals(BurstDisassembler other) |
|
{ |
|
return IsColoredCopy == other.IsColored |
|
&& BlocksCopy.SequenceEqual(other.Blocks) |
|
&& LinesCopy.SequenceEqual(other.Lines) |
|
&& TokensCopy.SequenceEqual(other.Tokens); |
|
} |
|
} |
|
}
|
|
|