Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

NativeHashSetTests.cs 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. using System;
  2. using NUnit.Framework;
  3. using Unity.Burst;
  4. using Unity.Collections;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. using Unity.Collections.NotBurstCompatible;
  7. using Unity.Jobs;
  8. using Unity.Collections.Tests;
  9. internal class NativeHashSetTests: CollectionsTestFixture
  10. {
  11. static void ExpectedCount<T>(ref NativeHashSet<T> container, int expected)
  12. where T : unmanaged, IEquatable<T>
  13. {
  14. Assert.AreEqual(expected == 0, container.IsEmpty);
  15. Assert.AreEqual(expected, container.Count);
  16. }
  17. [Test]
  18. public void NativeHashSet_IsEmpty()
  19. {
  20. var container = new NativeHashSet<int>(0, Allocator.Persistent);
  21. Assert.IsTrue(container.IsEmpty);
  22. Assert.IsTrue(container.Add(0));
  23. Assert.IsFalse(container.IsEmpty);
  24. Assert.AreNotEqual(0, container.Capacity);
  25. ExpectedCount(ref container, 1);
  26. container.Remove(0);
  27. Assert.IsTrue(container.IsEmpty);
  28. Assert.IsTrue(container.Add(0));
  29. container.Clear();
  30. Assert.IsTrue(container.IsEmpty);
  31. container.Dispose();
  32. }
  33. [Test]
  34. public void NativeHashSet_Capacity()
  35. {
  36. var container = new NativeHashSet<int>(0, Allocator.Persistent);
  37. Assert.IsTrue(container.IsEmpty);
  38. container.Capacity = 10;
  39. Assert.AreNotEqual(0, container.Capacity);
  40. container.Dispose();
  41. }
  42. [Test]
  43. public void NativeHashSet_CapacityAtLeastCount()
  44. {
  45. var container = new NativeHashSet<int>(0, Allocator.Persistent);
  46. for (int i = 0; i < 300; i++)
  47. container.Add(i);
  48. container.Capacity = 3;
  49. Assert.IsTrue(container.Capacity >= container.Count);
  50. container.Dispose();
  51. }
  52. [Test]
  53. public void NativeHashSet_RemoveOnEmptyMap_DoesNotThrow()
  54. {
  55. var container = new NativeHashSet<int>(0, Allocator.Temp);
  56. Assert.DoesNotThrow(() => container.Remove(0));
  57. Assert.DoesNotThrow(() => container.Remove(-425196));
  58. container.Dispose();
  59. }
  60. [Test]
  61. public void NativeHashSet_Collisions()
  62. {
  63. var container = new NativeHashSet<int>(16, Allocator.Temp);
  64. Assert.IsFalse(container.Contains(0), "Contains on empty hash map did not fail");
  65. ExpectedCount(ref container, 0);
  66. // Make sure inserting values work
  67. for (int i = 0; i < 8; ++i)
  68. {
  69. Assert.IsTrue(container.Add(i), "Failed to add value");
  70. }
  71. ExpectedCount(ref container, 8);
  72. // The bucket size is capacity * 2, adding that number should result in hash collisions
  73. for (int i = 0; i < 8; ++i)
  74. {
  75. Assert.IsTrue(container.Add(i + 32), "Failed to add value with potential hash collision");
  76. }
  77. // Make sure reading the inserted values work
  78. for (int i = 0; i < 8; ++i)
  79. {
  80. Assert.IsTrue(container.Contains(i), "Failed get value from hash set");
  81. }
  82. for (int i = 0; i < 8; ++i)
  83. {
  84. Assert.IsTrue(container.Contains(i + 32), "Failed get value from hash set");
  85. }
  86. container.Dispose();
  87. }
  88. [Test]
  89. public void NativeHashSet_SameElement()
  90. {
  91. using (var container = new NativeHashSet<int>(0, Allocator.Persistent))
  92. {
  93. Assert.IsTrue(container.Add(0));
  94. Assert.IsFalse(container.Add(0));
  95. }
  96. }
  97. [Test]
  98. public void NativeHashSet_CanBeReadFromJob()
  99. {
  100. using (var hashSet = new NativeHashSet<int>(1, CommonRwdAllocator.Handle))
  101. using (var result = new NativeReference<int>(CommonRwdAllocator.Handle))
  102. {
  103. hashSet.Add(42);
  104. new ReadHashSetJob
  105. {
  106. Input = hashSet.AsReadOnly(),
  107. Output = result,
  108. }.Run();
  109. Assert.AreEqual(42, result.Value);
  110. }
  111. }
  112. struct TempHashSet : IJob
  113. {
  114. public void Execute()
  115. {
  116. using (var stringList = new NativeList<FixedString32Bytes>(10, Allocator.Persistent) { "Hello", ",", "World", "!" })
  117. {
  118. var container = new NativeHashSet<FixedString128Bytes>(50, Allocator.Temp);
  119. var seen = new NativeArray<int>(stringList.Length, Allocator.Temp);
  120. foreach (var str in stringList)
  121. {
  122. container.Add(str);
  123. }
  124. foreach (var value in container)
  125. {
  126. int index = stringList.IndexOf(value);
  127. Assert.AreEqual(stringList[index], value.ToString());
  128. seen[index] = seen[index] + 1;
  129. }
  130. for (int i = 0; i < stringList.Length; i++)
  131. {
  132. Assert.AreEqual(1, seen[i], $"Incorrect value count {stringList[i]}");
  133. }
  134. }
  135. }
  136. }
  137. [Test]
  138. public void NativeHashSet_TempHashSetInJob()
  139. {
  140. new TempHashSet { }.Schedule().Complete();
  141. }
  142. struct ReadHashSetJob : IJob
  143. {
  144. [ReadOnly]
  145. public NativeHashSet<int>.ReadOnly Input;
  146. public NativeReference<int> Output;
  147. public void Execute()
  148. {
  149. Output.Value = Input.ToNativeArray(Allocator.Temp)[0];
  150. foreach (var value in Input)
  151. {
  152. Assert.AreEqual(42, value);
  153. }
  154. }
  155. }
  156. [Test]
  157. public void NativeHashSet_ForEach_FixedStringInHashMap()
  158. {
  159. using (var stringList = new NativeList<FixedString32Bytes>(10, Allocator.Persistent) { "Hello", ",", "World", "!" })
  160. {
  161. var container = new NativeHashSet<FixedString128Bytes>(50, Allocator.Temp);
  162. var seen = new NativeArray<int>(stringList.Length, Allocator.Temp);
  163. foreach (var str in stringList)
  164. {
  165. container.Add(str);
  166. }
  167. foreach (var value in container)
  168. {
  169. int index = stringList.IndexOf(value);
  170. Assert.AreEqual(stringList[index], value.ToString());
  171. seen[index] = seen[index] + 1;
  172. }
  173. for (int i = 0; i < stringList.Length; i++)
  174. {
  175. Assert.AreEqual(1, seen[i], $"Incorrect value count {stringList[i]}");
  176. }
  177. }
  178. }
  179. [Test]
  180. public void NativeHashSet_ForEach([Values(10, 1000)]int n)
  181. {
  182. var seen = new NativeArray<int>(n, Allocator.Temp);
  183. using (var container = new NativeHashSet<int>(32, CommonRwdAllocator.Handle))
  184. {
  185. for (int i = 0; i < n; i++)
  186. {
  187. Assert.True(container.Add(i));
  188. }
  189. var count = 0;
  190. foreach (var item in container)
  191. {
  192. Assert.True(container.Contains(item));
  193. seen[item] = seen[item] + 1;
  194. ++count;
  195. }
  196. Assert.AreEqual(container.Count, count);
  197. for (int i = 0; i < n; i++)
  198. {
  199. Assert.AreEqual(1, seen[i], $"Incorrect item count {i}");
  200. }
  201. }
  202. }
  203. struct NativeHashSet_ForEach_Job : IJob
  204. {
  205. [ReadOnly]
  206. public NativeHashSet<int>.ReadOnly Input;
  207. [ReadOnly]
  208. public int Num;
  209. public void Execute()
  210. {
  211. var seen = new NativeArray<int>(Num, Allocator.Temp);
  212. var count = 0;
  213. foreach (var item in Input)
  214. {
  215. Assert.True(Input.Contains(item));
  216. seen[item] = seen[item] + 1;
  217. ++count;
  218. }
  219. Assert.AreEqual(Input.Count, count);
  220. for (int i = 0; i < Num; i++)
  221. {
  222. Assert.AreEqual(1, seen[i], $"Incorrect item count {i}");
  223. }
  224. seen.Dispose();
  225. }
  226. }
  227. [Test]
  228. public void NativeHashSet_ForEach_From_Job([Values(10, 1000)] int n)
  229. {
  230. using (var container = new NativeHashSet<int>(32, CommonRwdAllocator.Handle))
  231. {
  232. for (int i = 0; i < n; i++)
  233. {
  234. container.Add(i);
  235. }
  236. new NativeHashSet_ForEach_Job
  237. {
  238. Input = container.AsReadOnly(),
  239. Num = n,
  240. }.Run();
  241. }
  242. }
  243. struct NativeHashSet_Write_Job : IJob
  244. {
  245. public NativeHashSet<int> Input;
  246. public void Execute()
  247. {
  248. Input.Clear();
  249. }
  250. }
  251. [Test]
  252. public void NativeHashSet_Write_From_Job()
  253. {
  254. using (var container = new NativeHashSet<int>(32, CommonRwdAllocator.Handle))
  255. {
  256. container.Add(0);
  257. Assert.IsFalse(container.IsEmpty);
  258. new NativeHashSet_Write_Job
  259. {
  260. Input = container,
  261. }.Run();
  262. Assert.IsTrue(container.IsEmpty);
  263. }
  264. }
  265. [Test]
  266. [TestRequiresCollectionChecks]
  267. public void NativeHashSet_ForEach_Throws_When_Modified()
  268. {
  269. using (var container = new NativeHashSet<int>(32, CommonRwdAllocator.Handle))
  270. {
  271. container.Add(0);
  272. container.Add(1);
  273. container.Add(2);
  274. container.Add(3);
  275. container.Add(4);
  276. container.Add(5);
  277. container.Add(6);
  278. container.Add(7);
  279. container.Add(8);
  280. container.Add(9);
  281. Assert.Throws<ObjectDisposedException>(() =>
  282. {
  283. foreach (var item in container)
  284. {
  285. container.Add(10);
  286. }
  287. });
  288. Assert.Throws<ObjectDisposedException>(() =>
  289. {
  290. foreach (var item in container)
  291. {
  292. container.Remove(1);
  293. }
  294. });
  295. }
  296. }
  297. struct ForEachIterator : IJob
  298. {
  299. [ReadOnly]
  300. public NativeHashSet<int>.Enumerator Iter;
  301. public void Execute()
  302. {
  303. while (Iter.MoveNext())
  304. {
  305. }
  306. }
  307. }
  308. [Test]
  309. [TestRequiresCollectionChecks]
  310. public void NativeHashSet_ForEach_Throws_Job_Iterator()
  311. {
  312. using (var container = new NativeHashSet<int>(32, CommonRwdAllocator.Handle))
  313. {
  314. var jobHandle = new ForEachIterator
  315. {
  316. Iter = container.GetEnumerator()
  317. }.Schedule();
  318. Assert.Throws<InvalidOperationException>(() => { container.Add(1); });
  319. jobHandle.Complete();
  320. }
  321. }
  322. [Test]
  323. public void NativeHashSet_EIU_ExceptWith_Empty()
  324. {
  325. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { };
  326. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { };
  327. setA.ExceptWith(setB);
  328. ExpectedCount(ref setA, 0);
  329. setA.Dispose();
  330. setB.Dispose();
  331. }
  332. [Test]
  333. public void NativeHashSet_EIU_ExceptWith_AxB()
  334. {
  335. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 0, 1, 2, 3, 4, 5 };
  336. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 3, 4, 5, 6, 7, 8 };
  337. setA.ExceptWith(setB);
  338. ExpectedCount(ref setA, 3);
  339. Assert.True(setA.Contains(0));
  340. Assert.True(setA.Contains(1));
  341. Assert.True(setA.Contains(2));
  342. setA.Dispose();
  343. setB.Dispose();
  344. }
  345. [Test]
  346. public void NativeHashSet_EIU_ExceptWith_BxA()
  347. {
  348. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 0, 1, 2, 3, 4, 5 };
  349. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 3, 4, 5, 6, 7, 8 };
  350. setB.ExceptWith(setA);
  351. ExpectedCount(ref setB, 3);
  352. Assert.True(setB.Contains(6));
  353. Assert.True(setB.Contains(7));
  354. Assert.True(setB.Contains(8));
  355. setA.Dispose();
  356. setB.Dispose();
  357. }
  358. [Test]
  359. public void NativeHashSet_EIU_IntersectWith_Empty()
  360. {
  361. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { };
  362. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { };
  363. setA.IntersectWith(setB);
  364. ExpectedCount(ref setA, 0);
  365. setA.Dispose();
  366. setB.Dispose();
  367. }
  368. [Test]
  369. public void NativeHashSet_EIU_IntersectWith()
  370. {
  371. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 0, 1, 2, 3, 4, 5 };
  372. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 3, 4, 5, 6, 7, 8 };
  373. setA.IntersectWith(setB);
  374. ExpectedCount(ref setA, 3);
  375. Assert.True(setA.Contains(3));
  376. Assert.True(setA.Contains(4));
  377. Assert.True(setA.Contains(5));
  378. setA.Dispose();
  379. setB.Dispose();
  380. }
  381. [Test]
  382. public void NativeHashSet_EIU_UnionWith_Empty()
  383. {
  384. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { };
  385. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { };
  386. setA.UnionWith(setB);
  387. ExpectedCount(ref setA, 0);
  388. setA.Dispose();
  389. setB.Dispose();
  390. }
  391. [Test]
  392. public void NativeHashSet_EIU_UnionWith()
  393. {
  394. var setA = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 0, 1, 2, 3, 4, 5 };
  395. var setB = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 3, 4, 5, 6, 7, 8 };
  396. setA.UnionWith(setB);
  397. ExpectedCount(ref setA, 9);
  398. Assert.True(setA.Contains(0));
  399. Assert.True(setA.Contains(1));
  400. Assert.True(setA.Contains(2));
  401. Assert.True(setA.Contains(3));
  402. Assert.True(setA.Contains(4));
  403. Assert.True(setA.Contains(5));
  404. Assert.True(setA.Contains(6));
  405. Assert.True(setA.Contains(7));
  406. Assert.True(setA.Contains(8));
  407. setA.Dispose();
  408. setB.Dispose();
  409. }
  410. [Test]
  411. public void NativeHashSet_ToArray()
  412. {
  413. using (var set = new NativeHashSet<int>(8, CommonRwdAllocator.Handle) { 0, 1, 2, 3, 4, 5 })
  414. {
  415. var array = set.ToArray();
  416. Array.Sort(array);
  417. for (int i = 0, num = set.Count; i < num; i++)
  418. {
  419. Assert.AreEqual(array[i], i);
  420. }
  421. }
  422. }
  423. [Test]
  424. public void NativeHashSet_CustomAllocatorTest()
  425. {
  426. AllocatorManager.Initialize();
  427. var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
  428. ref var allocator = ref allocatorHelper.Allocator;
  429. allocator.Initialize();
  430. using (var container = new NativeHashSet<int>(1, allocator.Handle))
  431. {
  432. }
  433. FastAssert.IsTrue(allocator.WasUsed);
  434. allocator.Dispose();
  435. allocatorHelper.Dispose();
  436. AllocatorManager.Shutdown();
  437. }
  438. [BurstCompile]
  439. struct BurstedCustomAllocatorJob : IJob
  440. {
  441. [NativeDisableUnsafePtrRestriction]
  442. public unsafe CustomAllocatorTests.CountingAllocator* Allocator;
  443. public void Execute()
  444. {
  445. unsafe
  446. {
  447. using (var container = new NativeHashSet<int>(1, Allocator->Handle))
  448. {
  449. }
  450. }
  451. }
  452. }
  453. [Test]
  454. public unsafe void NativeHashSet_BurstedCustomAllocatorTest()
  455. {
  456. AllocatorManager.Initialize();
  457. var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
  458. ref var allocator = ref allocatorHelper.Allocator;
  459. allocator.Initialize();
  460. var allocatorPtr = (CustomAllocatorTests.CountingAllocator*)UnsafeUtility.AddressOf<CustomAllocatorTests.CountingAllocator>(ref allocator);
  461. unsafe
  462. {
  463. var handle = new BurstedCustomAllocatorJob {Allocator = allocatorPtr }.Schedule();
  464. handle.Complete();
  465. }
  466. FastAssert.IsTrue(allocator.WasUsed);
  467. allocator.Dispose();
  468. allocatorHelper.Dispose();
  469. AllocatorManager.Shutdown();
  470. }
  471. }