暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

EditmodeTest.cs 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. using System;
  2. using System.Collections;
  3. using NUnit.Framework;
  4. using UnityEngine;
  5. using Unity.Jobs.LowLevel.Unsafe;
  6. using UnityEngine.TestTools;
  7. using Unity.Burst;
  8. using Unity.Collections;
  9. using Unity.Jobs;
  10. using System.Threading;
  11. using System.Diagnostics;
  12. using UnityEditor;
  13. using Debug = UnityEngine.Debug;
  14. using System.Text.RegularExpressions;
  15. using Unity.Profiling;
  16. [TestFixture]
  17. public class EditModeTest
  18. {
  19. private const int MaxIterations = 500;
  20. #if UNITY_2019_3_OR_NEWER
  21. [UnityTest]
  22. public IEnumerator CheckBurstJobEnabledDisabled()
  23. {
  24. BurstCompiler.Options.EnableBurstCompileSynchronously = true;
  25. try
  26. {
  27. foreach(var item in CheckBurstJobDisabled()) yield return item;
  28. foreach(var item in CheckBurstJobEnabled()) yield return item;
  29. }
  30. finally
  31. {
  32. BurstCompiler.Options.EnableBurstCompilation = true;
  33. }
  34. }
  35. #endif
  36. private IEnumerable CheckBurstJobEnabled()
  37. {
  38. BurstCompiler.Options.EnableBurstCompilation = true;
  39. yield return null;
  40. using (var jobTester = new BurstJobTester2())
  41. {
  42. var result = jobTester.Calculate();
  43. Assert.AreNotEqual(0.0f, result);
  44. }
  45. }
  46. private IEnumerable CheckBurstJobDisabled()
  47. {
  48. BurstCompiler.Options.EnableBurstCompilation = false;
  49. yield return null;
  50. using (var jobTester = new BurstJobTester2())
  51. {
  52. var result = jobTester.Calculate();
  53. Assert.AreEqual(0.0f, result);
  54. }
  55. }
  56. #if UNITY_2019_3_OR_NEWER
  57. [UnityTest]
  58. public IEnumerator CheckJobWithNativeArray()
  59. {
  60. BurstCompiler.Options.EnableBurstCompileSynchronously = true;
  61. BurstCompiler.Options.EnableBurstCompilation = true;
  62. yield return null;
  63. var job = new BurstJobTester2.MyJobCreatingAndDisposingNativeArray()
  64. {
  65. Length = 128,
  66. Result = new NativeArray<int>(16, Allocator.TempJob)
  67. };
  68. var handle = job.Schedule();
  69. handle.Complete();
  70. try
  71. {
  72. Assert.AreEqual(job.Length, job.Result[0]);
  73. }
  74. finally
  75. {
  76. job.Result.Dispose();
  77. }
  78. }
  79. #endif
  80. #if UNITY_BURST_BUG_FUNCTION_POINTER_FIXED
  81. [UnityTest]
  82. public IEnumerator CheckBurstFunctionPointerException()
  83. {
  84. BurstCompiler.Options.EnableBurstCompileSynchronously = true;
  85. BurstCompiler.Options.EnableBurstCompilation = true;
  86. yield return null;
  87. using (var jobTester = new BurstJobTester())
  88. {
  89. var exception = Assert.Throws<InvalidOperationException>(() => jobTester.CheckFunctionPointer());
  90. StringAssert.Contains("Exception was thrown from a function compiled with Burst", exception.Message);
  91. }
  92. }
  93. #endif
  94. [BurstCompile(CompileSynchronously = true)]
  95. private struct HashTestJob : IJob
  96. {
  97. public NativeArray<int> Hashes;
  98. public void Execute()
  99. {
  100. Hashes[0] = BurstRuntime.GetHashCode32<int>();
  101. Hashes[1] = TypeHashWrapper.GetIntHash();
  102. Hashes[2] = BurstRuntime.GetHashCode32<TypeHashWrapper.SomeStruct<int>>();
  103. Hashes[3] = TypeHashWrapper.GetGenericHash<int>();
  104. }
  105. }
  106. [Test]
  107. public static void TestTypeHash()
  108. {
  109. HashTestJob job = new HashTestJob
  110. {
  111. Hashes = new NativeArray<int>(4, Allocator.TempJob)
  112. };
  113. job.Schedule().Complete();
  114. var hash0 = job.Hashes[0];
  115. var hash1 = job.Hashes[1];
  116. var hash2 = job.Hashes[2];
  117. var hash3 = job.Hashes[3];
  118. job.Hashes.Dispose();
  119. Assert.AreEqual(hash0, hash1, "BurstRuntime.GetHashCode32<int>() has returned two different hashes");
  120. Assert.AreEqual(hash2, hash3, "BurstRuntime.GetHashCode32<SomeStruct<int>>() has returned two different hashes");
  121. }
  122. #if UNITY_2019_3_OR_NEWER
  123. [UnityTest]
  124. public IEnumerator CheckSafetyChecksWithDomainReload()
  125. {
  126. {
  127. var job = new SafetyCheckJobWithDomainReload();
  128. {
  129. // Run with safety-checks true
  130. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  131. job.Result = new NativeArray<int>(1, Allocator.TempJob);
  132. try
  133. {
  134. var handle = job.Schedule();
  135. handle.Complete();
  136. Assert.AreEqual(2, job.Result[0]);
  137. }
  138. finally
  139. {
  140. job.Result.Dispose();
  141. }
  142. }
  143. {
  144. // Run with safety-checks false
  145. BurstCompiler.Options.EnableBurstSafetyChecks = false;
  146. job.Result = new NativeArray<int>(1, Allocator.TempJob);
  147. bool hasException = false;
  148. try
  149. {
  150. var handle = job.Schedule();
  151. handle.Complete();
  152. Assert.AreEqual(1, job.Result[0]);
  153. }
  154. catch
  155. {
  156. hasException = true;
  157. throw;
  158. }
  159. finally
  160. {
  161. job.Result.Dispose();
  162. if (hasException)
  163. {
  164. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  165. }
  166. }
  167. }
  168. }
  169. // Ask for domain reload
  170. EditorUtility.RequestScriptReload();
  171. // Wait for the domain reload to be completed
  172. yield return new WaitForDomainReload();
  173. {
  174. // The safety checks should have been disabled by the previous code
  175. Assert.False(BurstCompiler.Options.EnableBurstSafetyChecks);
  176. // Restore safety checks
  177. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  178. }
  179. }
  180. #endif
  181. [BurstCompile(CompileSynchronously = true)]
  182. private struct DebugLogJob : IJob
  183. {
  184. public int Value;
  185. public void Execute()
  186. {
  187. UnityEngine.Debug.Log($"This is a string logged from a job with burst with the following {Value}");
  188. }
  189. }
  190. [Test]
  191. public static void TestDebugLog()
  192. {
  193. var job = new DebugLogJob
  194. {
  195. Value = 256
  196. };
  197. job.Schedule().Complete();
  198. }
  199. [BurstCompile(CompileSynchronously = true)]
  200. private struct SafetyCheckJobWithDomainReload : IJob
  201. {
  202. public NativeArray<int> Result;
  203. public void Execute()
  204. {
  205. Result[0] = 1;
  206. SetResultWithSafetyChecksOnly();
  207. }
  208. [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
  209. private void SetResultWithSafetyChecksOnly()
  210. {
  211. Result[0] = 2;
  212. }
  213. }
  214. [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
  215. private static void SafelySetSomeBool(ref bool b)
  216. {
  217. b = true;
  218. }
  219. [BurstCompile(DisableSafetyChecks = false)]
  220. private struct EnabledSafetyChecksJob : IJob
  221. {
  222. [WriteOnly] public NativeArray<int> WasHit;
  223. public void Execute()
  224. {
  225. var b = false;
  226. SafelySetSomeBool(ref b);
  227. WasHit[0] = b ? 1 : 0;
  228. }
  229. }
  230. [BurstCompile(DisableSafetyChecks = true)]
  231. private struct DisabledSafetyChecksJob : IJob
  232. {
  233. [WriteOnly] public NativeArray<int> WasHit;
  234. public void Execute()
  235. {
  236. var b = false;
  237. SafelySetSomeBool(ref b);
  238. WasHit[0] = b ? 1 : 0;
  239. }
  240. }
  241. #if UNITY_2019_3_OR_NEWER
  242. [UnityTest]
  243. public IEnumerator CheckSafetyChecksOffGloballyAndOnInJob()
  244. {
  245. BurstCompiler.Options.EnableBurstSafetyChecks = false;
  246. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  247. yield return null;
  248. var job = new EnabledSafetyChecksJob()
  249. {
  250. WasHit = new NativeArray<int>(1, Allocator.TempJob)
  251. };
  252. job.Schedule().Complete();
  253. try
  254. {
  255. // Safety checks are off globally which overwrites the job having safety checks on.
  256. Assert.AreEqual(0, job.WasHit[0]);
  257. }
  258. finally
  259. {
  260. job.WasHit.Dispose();
  261. }
  262. }
  263. [UnityTest]
  264. public IEnumerator CheckSafetyChecksOffGloballyAndOffInJob()
  265. {
  266. BurstCompiler.Options.EnableBurstSafetyChecks = false;
  267. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  268. yield return null;
  269. var job = new DisabledSafetyChecksJob()
  270. {
  271. WasHit = new NativeArray<int>(1, Allocator.TempJob)
  272. };
  273. job.Schedule().Complete();
  274. try
  275. {
  276. // Safety checks are off globally and off in job.
  277. Assert.AreEqual(0, job.WasHit[0]);
  278. }
  279. finally
  280. {
  281. job.WasHit.Dispose();
  282. }
  283. }
  284. [UnityTest]
  285. public IEnumerator CheckSafetyChecksOnGloballyAndOnInJob()
  286. {
  287. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  288. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  289. yield return null;
  290. var job = new EnabledSafetyChecksJob()
  291. {
  292. WasHit = new NativeArray<int>(1, Allocator.TempJob)
  293. };
  294. job.Schedule().Complete();
  295. try
  296. {
  297. // Safety checks are on globally and on in job.
  298. Assert.AreEqual(1, job.WasHit[0]);
  299. }
  300. finally
  301. {
  302. job.WasHit.Dispose();
  303. }
  304. }
  305. [UnityTest]
  306. public IEnumerator CheckSafetyChecksOnGloballyAndOffInJob()
  307. {
  308. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  309. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  310. yield return null;
  311. var job = new DisabledSafetyChecksJob()
  312. {
  313. WasHit = new NativeArray<int>(1, Allocator.TempJob)
  314. };
  315. job.Schedule().Complete();
  316. try
  317. {
  318. // Safety checks are on globally but off in job.
  319. Assert.AreEqual(0, job.WasHit[0]);
  320. }
  321. finally
  322. {
  323. job.WasHit.Dispose();
  324. }
  325. }
  326. [UnityTest]
  327. public IEnumerator CheckForceSafetyChecksWorks()
  328. {
  329. BurstCompiler.Options.ForceEnableBurstSafetyChecks = true;
  330. yield return null;
  331. var job = new DisabledSafetyChecksJob()
  332. {
  333. WasHit = new NativeArray<int>(1, Allocator.TempJob)
  334. };
  335. job.Schedule().Complete();
  336. try
  337. {
  338. // Even though the job has set disabled safety checks, the menu item 'Force On'
  339. // has been set which overrides any other requested behaviour.
  340. Assert.AreEqual(1, job.WasHit[0]);
  341. }
  342. finally
  343. {
  344. job.WasHit.Dispose();
  345. }
  346. }
  347. [UnityTest]
  348. public IEnumerator CheckSharedStaticWithDomainReload()
  349. {
  350. // Check that on a first access, SharedStatic is always empty
  351. AssertTestSharedStaticEmpty();
  352. // Fill with some data
  353. TestSharedStatic.SharedValue.Data = new TestSharedStatic(1, 2, 3, 4);
  354. Assert.AreEqual(1, TestSharedStatic.SharedValue.Data.Value1);
  355. Assert.AreEqual(2, TestSharedStatic.SharedValue.Data.Value2);
  356. Assert.AreEqual(3, TestSharedStatic.SharedValue.Data.Value3);
  357. Assert.AreEqual(4, TestSharedStatic.SharedValue.Data.Value4);
  358. // Ask for domain reload
  359. EditorUtility.RequestScriptReload();
  360. // Wait for the domain reload to be completed
  361. yield return new WaitForDomainReload();
  362. // Make sure that after a domain reload everything is initialized back to zero
  363. AssertTestSharedStaticEmpty();
  364. }
  365. private static void AssertTestSharedStaticEmpty()
  366. {
  367. Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value1);
  368. Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value2);
  369. Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value3);
  370. Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value4);
  371. }
  372. private struct TestSharedStatic
  373. {
  374. public static readonly SharedStatic<TestSharedStatic> SharedValue = SharedStatic<TestSharedStatic>.GetOrCreate<TestSharedStatic>();
  375. public TestSharedStatic(int value1, long value2, long value3, long value4)
  376. {
  377. Value1 = value1;
  378. Value2 = value2;
  379. Value3 = value3;
  380. Value4 = value4;
  381. }
  382. public int Value1;
  383. public long Value2;
  384. public long Value3;
  385. public long Value4;
  386. }
  387. static EditModeTest()
  388. {
  389. // UnityEngine.Debug.Log("Domain Reload");
  390. }
  391. [BurstCompile]
  392. private static class FunctionPointers
  393. {
  394. public delegate int SafetyChecksDelegate();
  395. [BurstCompile(DisableSafetyChecks = false)]
  396. public static int WithSafetyChecksEnabled()
  397. {
  398. var b = false;
  399. SafelySetSomeBool(ref b);
  400. return b ? 1 : 0;
  401. }
  402. [BurstCompile(DisableSafetyChecks = true)]
  403. public static int WithSafetyChecksDisabled()
  404. {
  405. var b = false;
  406. SafelySetSomeBool(ref b);
  407. return b ? 1 : 0;
  408. }
  409. }
  410. [UnityTest]
  411. public IEnumerator CheckSafetyChecksOffGloballyAndOffInFunctionPointer()
  412. {
  413. BurstCompiler.Options.EnableBurstSafetyChecks = false;
  414. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  415. yield return null;
  416. var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksDisabled);
  417. // Safety Checks are off globally and off in the job.
  418. Assert.AreEqual(0, funcPtr.Invoke());
  419. }
  420. [UnityTest]
  421. public IEnumerator CheckSafetyChecksOffGloballyAndOnInFunctionPointer()
  422. {
  423. BurstCompiler.Options.EnableBurstSafetyChecks = false;
  424. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  425. yield return null;
  426. var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksEnabled);
  427. // Safety Checks are off globally and on in job, but the global setting takes precedence.
  428. Assert.AreEqual(0, funcPtr.Invoke());
  429. }
  430. [UnityTest]
  431. public IEnumerator CheckSafetyChecksOnGloballyAndOffInFunctionPointer()
  432. {
  433. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  434. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  435. yield return null;
  436. var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksDisabled);
  437. // Safety Checks are on globally and off in the job, so the job takes predence.
  438. Assert.AreEqual(0, funcPtr.Invoke());
  439. }
  440. [UnityTest]
  441. public IEnumerator CheckSafetyChecksOnGloballyAndOnInFunctionPointer()
  442. {
  443. BurstCompiler.Options.EnableBurstSafetyChecks = true;
  444. BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
  445. yield return null;
  446. var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksEnabled);
  447. // Safety Checks are on globally and on in the job.
  448. Assert.AreEqual(1, funcPtr.Invoke());
  449. }
  450. [UnityTest]
  451. public IEnumerator CheckFunctionPointerForceSafetyChecksWorks()
  452. {
  453. BurstCompiler.Options.ForceEnableBurstSafetyChecks = true;
  454. yield return null;
  455. var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksDisabled);
  456. // Even though the job has set disabled safety checks, the menu item 'Force On'
  457. // has been set which overrides any other requested behaviour.
  458. Assert.AreEqual(1, funcPtr.Invoke());
  459. }
  460. #endif
  461. #if UNITY_2020_1_OR_NEWER
  462. [BurstCompile(CompileSynchronously = true)]
  463. private struct DebugDrawLineJob : IJob
  464. {
  465. public void Execute()
  466. {
  467. Debug.DrawLine(new Vector3(0, 0, 0), new Vector3(5, 0, 0), Color.green);
  468. }
  469. }
  470. [Test]
  471. public void TestDebugDrawLine()
  472. {
  473. var job = new DebugDrawLineJob();
  474. job.Schedule().Complete();
  475. }
  476. #endif
  477. #if UNITY_2020_2_OR_NEWER
  478. [BurstCompile]
  479. private static class ProfilerMarkerWrapper
  480. {
  481. private static readonly ProfilerMarker StaticMarker = new ProfilerMarker("TestStaticBurst");
  482. [BurstCompile(CompileSynchronously = true)]
  483. public static int CreateAndUseProfilerMarker(int start)
  484. {
  485. using (StaticMarker.Auto())
  486. {
  487. var p = new ProfilerMarker("TestBurst");
  488. p.Begin();
  489. var result = 0;
  490. for (var i = start; i < start + 100000; i++)
  491. {
  492. result += i;
  493. }
  494. p.End();
  495. return result;
  496. }
  497. }
  498. }
  499. private delegate int IntReturnIntDelegate(int param);
  500. [Test]
  501. public void TestCreateProfilerMarker()
  502. {
  503. var fp = BurstCompiler.CompileFunctionPointer<IntReturnIntDelegate>(ProfilerMarkerWrapper.CreateAndUseProfilerMarker);
  504. fp.Invoke(5);
  505. }
  506. #endif
  507. }