Açıklama Yok
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.

LongTextAreaTests.cs 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. using System;
  2. using System.Reflection;
  3. using NUnit.Framework;
  4. using UnityEngine;
  5. using UnityEditor;
  6. using Unity.Burst.Editor;
  7. using System.Text;
  8. using Unity.Burst;
  9. using System.Text.RegularExpressions;
  10. using System.Collections.Generic;
  11. using System.IO;
  12. using System.Linq;
  13. using UnityEngine.TestTools.Utils;
  14. using System.Runtime.CompilerServices;
  15. [TestFixture]
  16. public class LongTextAreaTests
  17. {
  18. private LongTextArea _textArea;
  19. [OneTimeSetUp]
  20. public void SetUp()
  21. {
  22. _textArea = new LongTextArea();
  23. }
  24. [Test]
  25. [TestCase("", " push rbp\n .seh_pushreg rbp\n", 7, true)]
  26. [TestCase("<color=#CCCCCC>", " push rbp\n .seh_pushreg rbp\n", 25, true)]
  27. [TestCase("<color=#d7ba7d>", " push rbp\n .seh_pushreg rbp\n", 21 + 15 + 8 + 15, true)]
  28. [TestCase("", "\n# hulahop hejsa\n", 5, false)]
  29. public void GetStartingColorTagTest(string tag, string text, int textIdx, bool syntaxHighlight)
  30. {
  31. var disAssembler = new BurstDisassembler();
  32. _textArea.SetText("", text, true, disAssembler, disAssembler.Initialize(text, BurstDisassembler.AsmKind.Intel, true, syntaxHighlight));
  33. if (!_textArea.CopyColorTags) _textArea.ChangeCopyMode();
  34. Assert.That(_textArea.GetStartingColorTag(0, textIdx), Is.EqualTo(tag));
  35. }
  36. [Test]
  37. [TestCase("", " push rbp\n .seh_pushreg rbp\n", 7, true)]
  38. [TestCase("</color>", " push rbp\n .seh_pushreg rbp\n", 25, true)]
  39. [TestCase("</color>", " push rbp\n .seh_pushreg rbp\n", 21 + 15 + 8 + 15, true)]
  40. [TestCase("", " push rbp\n .seh_pushreg rbp\n", 14 + 15 + 8, true)]
  41. [TestCase("", "\n# hulahop hejsa\n", 5, false)]
  42. public void GetEndingColorTagTest(string tag, string text, int textIdx, bool syntaxHighlight)
  43. {
  44. var disAssembler = new BurstDisassembler();
  45. _textArea.SetText("", text, true, disAssembler, disAssembler.Initialize(text, BurstDisassembler.AsmKind.Intel, true, syntaxHighlight));
  46. if (!_textArea.CopyColorTags) _textArea.ChangeCopyMode();
  47. Assert.That(_textArea.GetEndingColorTag(0, textIdx), Is.EqualTo(tag));
  48. }
  49. [Test]
  50. [TestCase("<color=#FFFF00>hulahop</color> <color=#DCDCAA>hejsa</color>\n", 0, 16, 16)]
  51. [TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n", 1, 40, 9)]
  52. [TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n hej", 2, 67, 3)]
  53. [TestCase("<color=#FFFF00>hulahop</color> <color=#DCDCAA>hejsa</color>", 0, 15, 15)]
  54. [TestCase("\n <color=#4EC9B0>je</color> <color=#d4d4d4>.LBB11_4</color>", 1, 34, 33)]
  55. // Test cases for when on enhanced text and not coloured.
  56. [TestCase("hulahop hejsa\n", 0, 16, 16)]
  57. [TestCase("hulahop\n hejsa\n", 1, 17, 9)]
  58. [TestCase("hulahop\n hejsa\n hej", 2, 21, 3)]
  59. [TestCase("hulahop hejsa", 0, 15, 15)]
  60. public void GetEndIndexOfColoredLineTest(string text, int line, int resTotal, int resRel)
  61. {
  62. Assert.That(_textArea.GetEndIndexOfColoredLine(text, line), Is.EqualTo((resTotal, resRel)));
  63. }
  64. [Test]
  65. [TestCase("hulahop hejsa\n", 0, 16, 16)]
  66. [TestCase("hulahop\n hejsa\n", 1, 17, 9)]
  67. [TestCase("hulahop\n hejsa\n hej", 2, 21, 3)]
  68. [TestCase("hulahop hejsa", 0, 15, 15)]
  69. [TestCase("\nhulahop hejsa", 1, 16, 15)]
  70. public void GetEndIndexOfPlainLineTest(string text, int line, int resTotal, int resRel)
  71. {
  72. Assert.That(_textArea.GetEndIndexOfPlainLine(text, line), Is.EqualTo((resTotal, resRel)));
  73. }
  74. [Test]
  75. [TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n hej", 2, 2, 0)]
  76. [TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n hej", 1, 5, 15)]
  77. [TestCase("<color=#FFFF00>hulahop</color> <color=#DCDCAA>hejsa</color>:", 0, 17, 46)]
  78. public void BumpSelectionXByColortagTest(string text, int lineNum, int charsIn, int colourTagFiller)
  79. {
  80. var (idxTotal, idxRel) = _textArea.GetEndIndexOfColoredLine(text, lineNum);
  81. Assert.That(_textArea.BumpSelectionXByColorTag(text, idxTotal - idxRel, charsIn), Is.EqualTo(charsIn + colourTagFiller));
  82. }
  83. [Test]
  84. [TestCase(" push rbp\n .seh_pushreg rbp\n", false)]
  85. [TestCase(" push rbp\n .seh_pushreg rbp\n", true)]
  86. public void SelectAllTest(string text, bool useDisassembler)
  87. {
  88. if (useDisassembler)
  89. {
  90. var disAssembler = new BurstDisassembler();
  91. _textArea.SetText("", text, true, disAssembler, disAssembler.Initialize(text, BurstDisassembler.AsmKind.Intel));
  92. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
  93. }
  94. else
  95. {
  96. _textArea.SetText("", text, true, null, false);
  97. }
  98. _textArea.selectPos = new Vector2(2, 2);
  99. // There is no inserted comments or similar in my test example, so finalAreaSize, should be equivalent for the two.
  100. _textArea.finalAreaSize = new Vector2(7.5f * text.Length, 15.2f);
  101. _textArea.SelectAll();
  102. Assert.That(_textArea.selectPos, Is.EqualTo(Vector2.zero));
  103. Assert.That(_textArea.selectDragPos, Is.EqualTo(new Vector2(7.5f * text.Length, 15.2f)));
  104. if (!useDisassembler)
  105. {
  106. Assert.That(_textArea.textSelectionIdx, Is.EqualTo((0, text.Length)));
  107. }
  108. }
  109. private BurstDisassembler GetDisassemblerandText(string compileTargetName, int debugLvl, out string textToRender)
  110. {
  111. // Get target job assembly:
  112. var assemblies = BurstReflection.EditorAssembliesThatCanPossiblyContainJobs;
  113. var result = BurstReflection.FindExecuteMethods(assemblies, BurstReflectionAssemblyOptions.None);
  114. var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName);
  115. Assert.IsTrue(compileTarget != default, $"Could not find compile target: {compileTarget}");
  116. BurstDisassembler disassembler = new BurstDisassembler();
  117. var options = new StringBuilder();
  118. compileTarget.Options.TryGetOptions(compileTarget.JobType, out string defaultOptions);
  119. options.AppendLine(defaultOptions);
  120. // Disables the 2 current warnings generated from code (since they clutter up the inspector display)
  121. // BC1370 - throw inside code not guarded with ConditionalSafetyCheck attribute
  122. // BC1322 - loop intrinsic on loop that has been optimised away
  123. options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDisableWarnings, "BC1370;BC1322")}");
  124. options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionTarget, BurstTargetCpu.X64_SSE4)}");
  125. options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDebug, $"{debugLvl}")}");
  126. var baseOptions = options.ToString();
  127. var append = BurstInspectorGUI.GetDisasmOptions()[(int)DisassemblyKind.Asm];
  128. // Setup disAssembler with the job:
  129. compileTarget.RawDisassembly = BurstInspectorGUI.GetDisassembly(compileTarget.Method, baseOptions + append);
  130. textToRender = compileTarget.RawDisassembly.TrimStart('\n');
  131. return disassembler;
  132. }
  133. [Test]
  134. [TestCase(true, true, 2)]
  135. [TestCase(true, true, 1)]
  136. [TestCase(true, false, 2)]
  137. [TestCase(true, false, 1)]
  138. [TestCase(false, true, 2)]
  139. [TestCase(false, true, 1)]
  140. [TestCase(false, false, 2)]
  141. [TestCase(false, false, 1)]
  142. public void CopyAllTest(bool useDisassembler, bool coloured, int debugLvl)
  143. {
  144. // Get target job assembly:
  145. var disassembler = new BurstDisassembler();
  146. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  147. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  148. if (useDisassembler)
  149. {
  150. _textArea.SetText("", textToRender, true, disassembler, disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, true, coloured));
  151. _textArea.ExpandAllBlocks();
  152. var builder = new StringBuilder();
  153. for (int i = 0; i < disassembler.Blocks.Count; i++)
  154. {
  155. builder.Append(disassembler.GetOrRenderBlockToText(i));
  156. }
  157. textToRender = builder.ToString();
  158. }
  159. else
  160. {
  161. _textArea.SetText("", textToRender, true, null, false);
  162. }
  163. _textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
  164. _textArea.SelectAll();
  165. _textArea.DoSelectionCopy();
  166. Assert.AreEqual(textToRender, EditorGUIUtility.systemCopyBuffer);
  167. }
  168. [Test]
  169. public void CopyAllTextWithoutColorTagsTest()
  170. {
  171. // Setup:
  172. var disassembler = new BurstDisassembler();
  173. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  174. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  175. _textArea.SetText("", textToRender, true, disassembler,
  176. disassembler.Initialize(
  177. textToRender,
  178. BurstDisassembler.AsmKind.Intel));
  179. _textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
  180. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
  181. // Actual test to reproduce error:
  182. _textArea.ChangeCopyMode();
  183. _textArea.SelectAll();
  184. Assert.DoesNotThrow(_textArea.DoSelectionCopy);
  185. }
  186. [Test]
  187. public void CopyTextAfterSelectionMovedTest()
  188. {
  189. // Setup:
  190. const bool sbm = true;
  191. var wa = Rect.zero;
  192. var disassembler = new BurstDisassembler();
  193. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  194. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  195. _textArea.SetText("", textToRender, true, disassembler,
  196. disassembler.Initialize(
  197. textToRender,
  198. BurstDisassembler.AsmKind.Intel));
  199. _textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
  200. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, sbm);
  201. // Actual test to reproduce error:
  202. _textArea.ChangeCopyMode();
  203. _textArea.MoveSelectionDown(wa, sbm);
  204. _textArea.MoveSelectionDown(wa, sbm);
  205. _textArea.MoveSelectionLeft(wa, sbm);
  206. Assert.DoesNotThrow(_textArea.DoSelectionCopy);
  207. _textArea.MoveSelectionRight(wa, sbm);
  208. Assert.DoesNotThrow(_textArea.DoSelectionCopy);
  209. }
  210. [Test]
  211. public void CopyTextIdenticalWithAndWithoutColorTags()
  212. {
  213. // We don't wanna go messing with the users system buffer. At least if user didn't break anything.
  214. var savedSystemBuffer = EditorGUIUtility.systemCopyBuffer;
  215. // Get target job assembly:
  216. var disassembler = new BurstDisassembler();
  217. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  218. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  219. _textArea.SetText("", textToRender, true, disassembler,
  220. disassembler.Initialize(
  221. textToRender,
  222. BurstDisassembler.AsmKind.Intel));
  223. _textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
  224. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
  225. for (var i=0; i<disassembler.Blocks[0].Length+50; i++) _textArea.MoveSelectionDown(Rect.zero, true);
  226. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
  227. _textArea.UpdateEnhancedSelectTextIdx(_textArea.horizontalPad);
  228. _textArea.DoSelectionCopy();
  229. var copiedText1 = EditorGUIUtility.systemCopyBuffer;
  230. _textArea.ChangeCopyMode();
  231. _textArea.DoSelectionCopy();
  232. var copiedText2 = EditorGUIUtility.systemCopyBuffer;
  233. var regx = new Regex(@"(<color=#[0-9A-Za-z]*>)|(</color>)");
  234. if (!_textArea.CopyColorTags)
  235. {
  236. (copiedText1, copiedText2) = (copiedText2, copiedText1);
  237. }
  238. copiedText2 = regx.Replace(copiedText2, "");
  239. EditorGUIUtility.systemCopyBuffer = savedSystemBuffer;
  240. Assert.AreEqual(copiedText1, copiedText2,
  241. "Copy with color tags did not match copy without " +
  242. "(Color tags is removed from the copy to make it comparable with the color-tag-less copy).");
  243. }
  244. // Disabled due to https://jira.unity3d.com/browse/BUR-2207
  245. [Test]
  246. [TestCase(true)]
  247. [TestCase(false)]
  248. public void KeepingSelectionWhenMovingTest(bool useDisassembler)
  249. {
  250. const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
  251. BurstDisassembler disassembler = new BurstDisassembler();
  252. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  253. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  254. Rect workingArea = new Rect();
  255. if (useDisassembler)
  256. {
  257. _textArea.SetText(jobName, textToRender, true, disassembler, disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel));
  258. _textArea.LayoutEnhanced(GUIStyle.none, workingArea, true);
  259. }
  260. else
  261. {
  262. _textArea.SetText(jobName, textToRender, false, null, false);
  263. }
  264. _textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
  265. Assert.IsFalse(_textArea.HasSelection);
  266. Vector2 start = _textArea.selectDragPos;
  267. if (useDisassembler) start.x = _textArea.horizontalPad + _textArea.fontWidth / 2;
  268. // Horizontal movement:
  269. _textArea.MoveSelectionRight(workingArea, true);
  270. Assert.IsTrue(_textArea.HasSelection);
  271. Assert.AreEqual(start + new Vector2(_textArea.fontWidth, 0), _textArea.selectDragPos);
  272. _textArea.MoveSelectionLeft(workingArea, true);
  273. Assert.IsTrue(_textArea.HasSelection);
  274. Assert.AreEqual(start, _textArea.selectDragPos);
  275. // Vertical movement:
  276. _textArea.MoveSelectionDown(workingArea, true);
  277. Assert.IsTrue(_textArea.HasSelection);
  278. Assert.AreEqual(start + new Vector2(0, _textArea.fontHeight), _textArea.selectDragPos);
  279. _textArea.MoveSelectionUp(workingArea, true);
  280. Assert.IsTrue(_textArea.HasSelection);
  281. Assert.AreEqual(start, _textArea.selectDragPos);
  282. }
  283. [Test]
  284. public void GetFragNrFromBlockIdxTest()
  285. {
  286. var disassembler = new BurstDisassembler();
  287. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  288. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  289. _textArea.SetText("", textToRender, true, disassembler,
  290. disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, false, false));
  291. var garbageVariable = 0f;
  292. var numBlocks = disassembler.Blocks.Count;
  293. // Want to get the last fragment possible
  294. var expectedFragNr = 0;
  295. for (var i = 0; i < _textArea.blocksFragmentsPlain.Length-1; i++)
  296. {
  297. expectedFragNr += _textArea.GetPlainFragments(i).Count;
  298. }
  299. Assert.AreEqual(expectedFragNr, _textArea.GetFragNrFromBlockIdx(numBlocks-1, 0, 0, ref garbageVariable));
  300. Assert.AreEqual(3, _textArea.GetFragNrFromBlockIdx(3, 1, 1, ref garbageVariable));
  301. }
  302. [Test]
  303. public void GetFragNrFromEnhancedTextIdxTest()
  304. {
  305. const string jobName = "BurstJobTester2.MyJob - (IJob)";
  306. var disassembler = new BurstDisassembler();
  307. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  308. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  309. _textArea.SetText(jobName, textToRender, true, disassembler,
  310. disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, false, false));
  311. _textArea.Layout(GUIStyle.none, 0);
  312. var garbageVariable = 0f;
  313. const int blockIdx = 2;
  314. var fragments = _textArea.RecomputeFragmentsFromBlock(blockIdx);
  315. var text = _textArea.GetText;
  316. var expectedFrag = blockIdx + fragments.Count - 1;
  317. var info = disassembler.BlockIdxs[blockIdx];
  318. var extraFragLen = fragments.Count > 1
  319. ? fragments[0].text.Length + 1 // job only contains 2 fragments at max
  320. : 0;
  321. var idx = info.startIdx + extraFragLen + 1;
  322. var expectedPosY = garbageVariable;
  323. for (int i = 0; i < blockIdx; i++)
  324. {
  325. foreach (var frag in _textArea.RecomputeFragmentsFromBlock(i))
  326. {
  327. expectedPosY += frag.lineCount * _textArea.fontHeight;
  328. }
  329. }
  330. var expected =
  331. ( expectedFrag
  332. , info.startIdx + extraFragLen
  333. , expectedPosY);
  334. var actual = _textArea.GetFragNrFromEnhancedTextIdx(idx, 0, 0, 0, garbageVariable);
  335. Assert.AreEqual(expected, actual);
  336. }
  337. [Test]
  338. [TestCase(true)]
  339. [TestCase(false)]
  340. public void SearchTextEnhancedTest(bool colored)
  341. {
  342. var disassembler = new BurstDisassembler();
  343. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  344. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  345. _textArea.SetText("", textToRender, true, disassembler, disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, true, colored));
  346. var workingArea = new Rect(0, 0, 10, 10);
  347. _textArea.SearchText(new SearchCriteria(".Ltmp.:", true, false, true), new Regex(@"\.Ltmp.:"), ref workingArea);
  348. Assert.AreEqual(10, _textArea.NrSearchHits);
  349. // Check that they are filled out probably
  350. int nr = 0;
  351. foreach (var fragHits in _textArea.searchHits.Values)
  352. {
  353. foreach (var hit in fragHits)
  354. {
  355. Assert.AreEqual((0, 7, nr++), hit);
  356. }
  357. }
  358. }
  359. [Test]
  360. public void SelectOnOneLineTest()
  361. {
  362. const string testCase = "\n<color=#d4d4d4>.Ltmp12</color>: ...";
  363. var disassembler = new BurstDisassembler();
  364. _textArea.SetText("", testCase, false, disassembler, disassembler.Initialize(testCase, BurstDisassembler.AsmKind.Intel));
  365. // Set fontWidth and fontHeight
  366. _textArea.Layout(GUIStyle.none, 20f);
  367. // Set selection markers.
  368. // Error happened when selection started at the lowest point of a line.
  369. _textArea.selectPos = new Vector2(0, _textArea.fontHeight);
  370. // Select further down to make sure it wont be switched with selectPos.
  371. _textArea.selectDragPos = new Vector2(10 * _textArea.fontWidth, _textArea.fontHeight*2);
  372. // Hopefully it wont throw anything
  373. Assert.DoesNotThrow(() =>
  374. _textArea.PrepareInfoForSelection(0, 0, _textArea.fontHeight,
  375. new LongTextArea.Fragment() { text = testCase.TrimStart('\n'), lineCount = 1 },
  376. _textArea.GetEndIndexOfColoredLine));
  377. }
  378. [Test]
  379. public void GetLineHighlightTest()
  380. {
  381. const float hPad = 20f;
  382. const int linePressed = 4 + 13;
  383. // Get target job assembly:
  384. var disassembler = new BurstDisassembler();
  385. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  386. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  387. // Set up dependencies for GetLineHighlight(.)
  388. _textArea.SetText("", textToRender, true, disassembler,
  389. disassembler.Initialize(
  390. textToRender,
  391. BurstDisassembler.AsmKind.Intel)
  392. );
  393. _textArea.Layout(GUIStyle.none, hPad);
  394. _textArea.LayoutEnhanced(GUIStyle.none,
  395. new Rect(0,0, _textArea.fontWidth*50,_textArea.fontHeight*50),
  396. false
  397. );
  398. // Setup simple cache.
  399. var cache = new LongTextArea.LineRegRectsCache();
  400. var rect = _textArea.GetLineHighlight(ref cache, hPad, linePressed);
  401. Assert.IsFalse(cache.IsRegistersCached(linePressed));
  402. Assert.IsTrue(cache.IsLineHighlightCached(linePressed, false));
  403. var expectedX = hPad;
  404. var b = 0;
  405. for (; b < disassembler.Blocks.Count; b++)
  406. {
  407. if (disassembler.Blocks[b].LineIndex > linePressed)
  408. {
  409. b--;
  410. break;
  411. }
  412. }
  413. var expectedY = (_textArea.blockLine[b] + (linePressed - disassembler.Blocks[b].LineIndex)) * _textArea.fontHeight + _textArea.fontHeight;
  414. var lineStr = _textArea.GetLineString(disassembler.Lines[linePressed]);
  415. var lineLen = lineStr.Length * _textArea.fontWidth;
  416. var expected = new Rect(expectedX,
  417. expectedY,
  418. lineLen,
  419. 2f
  420. );
  421. var result = Mathf.Approximately(expectedX, rect.x)
  422. && Mathf.Approximately(expectedY, rect.y)
  423. && Mathf.Approximately(lineLen, rect.width)
  424. && Mathf.Approximately(2f, rect.height);
  425. Assert.IsTrue(result, $"line highlight for \"{lineStr}\" was wrong.\nExpected: {expected}\nBut was: {rect}");
  426. }
  427. [Test]
  428. public void GetRegRectsTest()
  429. {
  430. #region Initialize-test-states
  431. const float hPad = 20f;
  432. const int linePressed = 8 + 13;
  433. // Get target job assembly:
  434. var disassembler = new BurstDisassembler();
  435. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  436. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  437. // Set up dependencies for GetLineHighlight(.)
  438. _textArea.SetText("", textToRender, true, disassembler,
  439. disassembler.Initialize(
  440. textToRender,
  441. BurstDisassembler.AsmKind.Intel)
  442. );
  443. // Setting up variables to determine view size:
  444. _textArea.Layout(GUIStyle.none, hPad);
  445. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, false);
  446. #endregion
  447. // Find the block index to put within view:
  448. var blockIdx = disassembler.Blocks.Count/2;
  449. for (; blockIdx > 0; blockIdx--)
  450. {
  451. // Take the first block where we know the lastLine will be in the next block.
  452. if (!_textArea._folded[blockIdx + 1] && disassembler.Blocks[blockIdx].Length >= 5) break;
  453. }
  454. // Initialize states with regards to view:
  455. _textArea.Layout(GUIStyle.none, hPad);
  456. _textArea.LayoutEnhanced(GUIStyle.none,
  457. new Rect(0,0, _textArea.fontWidth*100,_textArea.fontHeight*(_textArea.blockLine[blockIdx]+1)),
  458. false
  459. );
  460. #region Function-to-test-call
  461. var cache = new LongTextArea.LineRegRectsCache();
  462. var registersUsed = new List<string> { "rbp", "rsp" };
  463. var rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
  464. #endregion
  465. #region Expected-variables
  466. var lastLine = disassembler.Blocks[_textArea._renderBlockEnd+1].LineIndex + 4;
  467. var expectedRbp =
  468. (from pair in disassembler._registersUsedAtLine._linesRegisters.TakeWhile(x => x.Key < lastLine)
  469. where pair.Value.Contains("rbp") && disassembler.Lines[pair.Key].Kind != BurstDisassembler.AsmLineKind.Directive
  470. select pair);
  471. var expectedRsp =
  472. (from pair in disassembler._registersUsedAtLine._linesRegisters.TakeWhile(x => x.Key < lastLine)
  473. where pair.Value.Contains("rsp") && disassembler.Lines[pair.Key].Kind != BurstDisassembler.AsmLineKind.Directive
  474. select pair);
  475. // Check that they are correctly placed!
  476. // Only check the last here, as under development the "hardest" behaviour was from within the lowest blocks.
  477. var lastRectLineIdx = expectedRbp.Last().Key;
  478. var lastRectLine = disassembler.Lines[lastRectLineIdx];
  479. var lastRectLineStr = _textArea.GetLineString(lastRectLine);
  480. var expectedX = lastRectLineStr.Substring(0, lastRectLineStr.IndexOf("rbp")).Length * _textArea.fontWidth + hPad + 2f;
  481. #endregion
  482. Assert.IsTrue(cache.IsRegistersCached(linePressed), "Register Rect cache not probarly setup.");
  483. Assert.IsFalse(cache.IsLineHighlightCached(linePressed, false), "Line highlight cache faultily set to cached.");
  484. Assert.AreEqual(2, rects.Length, "Register Rect cache does not have correct number of registered registers.");
  485. Assert.AreEqual(expectedRbp.Count(), rects[0].Count, "Did not find all \"rbp\" registers.");
  486. Assert.AreEqual(expectedRsp.Count(), rects[1].Count, "Did not find all \"rsp\" registers.");
  487. Assert.That(rects[0][rects[0].Count - 1].x, Is.EqualTo(expectedX).Using(FloatEqualityComparer.Instance),
  488. "Wrong x position for last found \"rbp\" rect.");
  489. // Note: Does not check Y position, as this is highly dependent on architecture, making it annoyingly hard
  490. // to reason about.
  491. }
  492. [Test]
  493. public void RegsRectCacheTest()
  494. {
  495. const float hPad = 20f;
  496. const int linePressed = 8 + 13;
  497. // Get target job assembly:
  498. var disassembler = new BurstDisassembler();
  499. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  500. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  501. // Set up dependencies for GetLineHighlight(.)
  502. _textArea.SetText("", textToRender, true, disassembler,
  503. disassembler.Initialize(
  504. textToRender,
  505. BurstDisassembler.AsmKind.Intel)
  506. );
  507. _textArea.Layout(GUIStyle.none, hPad);
  508. var yStart = 0f;
  509. var yHeight = _textArea.fontHeight*44;
  510. _textArea.LayoutEnhanced(GUIStyle.none,
  511. new Rect(0,yStart, _textArea.fontWidth*100,yHeight),
  512. false
  513. );
  514. var cache = new LongTextArea.LineRegRectsCache();
  515. var registersUsed = new List<string> { "rbp", "rsp" };
  516. var rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
  517. Assert.IsTrue(cache.IsRegistersCached(linePressed));
  518. var cachedItems =
  519. (from elm in rects
  520. select elm.Count).Sum();
  521. yStart = yHeight;
  522. _textArea.Layout(GUIStyle.none, hPad);
  523. _textArea.LayoutEnhanced(GUIStyle.none,
  524. new Rect(0,yStart, _textArea.fontWidth*100,yHeight),
  525. false
  526. );
  527. rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
  528. Assert.IsTrue(cache.IsRegistersCached(linePressed));
  529. var cachedItems2 =
  530. (from elm in rects
  531. select elm.Count).Sum();
  532. Assert.IsTrue(cachedItems2 >= cachedItems);
  533. }
  534. [Test]
  535. [TestCase("\n xor r9d, r9d\n", "r9d")]
  536. [TestCase("\n push edx rdx\n", "rdx")]
  537. public void SameRegisterUsedTwiceTest(string line, string reg)
  538. {
  539. const float hPad = 20f;
  540. const int linePressed = 0;
  541. // Get target job assembly:
  542. var disassembler = new BurstDisassembler();
  543. // Set up dependencies for GetLineHighlight(.)
  544. _textArea.SetText("", line, true, disassembler,
  545. disassembler.Initialize(
  546. line,
  547. BurstDisassembler.AsmKind.Intel)
  548. );
  549. _textArea.Layout(GUIStyle.none, hPad);
  550. var yStart = 0f;
  551. var yHeight = _textArea.fontHeight;
  552. _textArea.LayoutEnhanced(GUIStyle.none,
  553. new Rect(0,yStart, _textArea.fontWidth*100,yHeight),
  554. false
  555. );
  556. var cache = new LongTextArea.LineRegRectsCache();
  557. var registersUsed = new List<string> { reg };
  558. var rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
  559. Assert.IsTrue(cache.IsRegistersCached(linePressed));
  560. Assert.IsTrue(rects.Length == 1);
  561. Assert.IsTrue(rects[0].Count == 2, "Did not find exactly both registers.");
  562. }
  563. /// <summary>
  564. /// This test should check whether line press information is cleared when it is necessary.
  565. /// It does not check whether it is unnecessarily cleared.
  566. /// </summary>
  567. [Test]
  568. public void ClearLinePressTest()
  569. {
  570. void SetupCache(float pad, int lineNr, ref LongTextArea.LineRegRectsCache cache, List<string> regsUsed)
  571. {
  572. _textArea._pressedLine = lineNr;
  573. _ = _textArea.GetRegisterRects(pad, ref cache, lineNr, regsUsed);
  574. _ = _textArea.GetLineHighlight(ref cache, pad, lineNr);
  575. }
  576. // Test setup:
  577. var registersUsed = new List<string> { "rbp", "rsp" };
  578. const float hPad = 20f;
  579. const int linePressed = 4 + 13;
  580. var disassembler = new BurstDisassembler();
  581. var thisPath = Path.GetDirectoryName(GetThisFilePath());
  582. Assert.NotNull(thisPath, "Could not retrieve path for current directory.");
  583. var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
  584. // Set up dependencies for GetLineHighlight(.)
  585. _textArea.SetText("", textToRender, true, disassembler,
  586. disassembler.Initialize(
  587. textToRender,
  588. BurstDisassembler.AsmKind.Intel)
  589. );
  590. // Setting up variables to determine view size:
  591. _textArea.Layout(GUIStyle.none, hPad);
  592. _textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, false);
  593. var blockIdx = _textArea.GetLinesBlockIdx(linePressed);
  594. _textArea.Layout(GUIStyle.none, hPad);
  595. _textArea.LayoutEnhanced(GUIStyle.none,
  596. new Rect(0,0, _textArea.fontWidth*100,_textArea.fontHeight*(_textArea.blockLine[blockIdx]+1)),
  597. false);
  598. void TestCache(bool isLineRect, bool isRect, bool isLine, string msg)
  599. {
  600. Assert.AreEqual(isLineRect,
  601. _textArea._lineRegCache.IsLineHighlightCached(linePressed, _textArea._folded[blockIdx]),
  602. msg + " Line highlight failed.");
  603. Assert.AreEqual(isRect,
  604. _textArea._lineRegCache.IsRegistersCached(linePressed),
  605. msg + " Register cache failed.");
  606. msg += " Line press failed.";
  607. if (!isLine)
  608. {
  609. Assert.AreEqual(-1, _textArea._pressedLine, msg);
  610. }
  611. else
  612. {
  613. Assert.AreNotEqual(-1, _textArea._pressedLine, msg);
  614. }
  615. SetupCache(hPad, linePressed, ref _textArea._lineRegCache, registersUsed);
  616. }
  617. SetupCache(hPad, linePressed, ref _textArea._lineRegCache, registersUsed);
  618. TestCache(true, true, true, "Initial setup failed.");
  619. // Following changes should result in clearing everything, as assembly text might have changed:
  620. // * Expand all.
  621. _textArea.ExpandAllBlocks();
  622. TestCache(false, false, false, "Expanding blocks failed.");
  623. // * Focus code.
  624. _textArea.FocusCodeBlocks();
  625. TestCache(false, false, false, "Focusing code blocks failed.");
  626. // * disassembly kind, Target change, Safety check changes, Assembly kind changes e.g. by amount of debug info.
  627. _textArea.SetText("", textToRender, true, disassembler,
  628. disassembler.Initialize(
  629. textToRender,
  630. BurstDisassembler.AsmKind.Intel)
  631. );
  632. TestCache(false, false, false, "Setting up new text failed.");
  633. // Following changes should only result in Rec change clear, as line number still resembles same line:
  634. // * Font size.
  635. _textArea.Invalidate();
  636. TestCache(false, false, true, "Changing font size failed.");
  637. // * Show branch flow.
  638. _textArea.LayoutEnhanced(GUIStyle.none,
  639. new Rect(0,0, _textArea.fontWidth*100,_textArea.fontHeight*(_textArea.blockLine[blockIdx]+1)),
  640. true);
  641. TestCache(false, false, true, "Changing font size failed.");
  642. // * Smell test (This will however clear everything as ´SetText()´ required).
  643. // Hence tested in the cases for fill clear.
  644. }
  645. private static string GetThisFilePath([CallerFilePath] string path = null) => path;
  646. private readonly string _burstJobPath = "burstTestTarget.txt";
  647. }