A game about forced loneliness, made by TACStudios
1using NUnit.Framework;
2using Unity.Burst;
3using Unity.Collections;
4using Unity.Collections.NotBurstCompatible;
5using Unity.Collections.Tests;
6using Unity.Collections.LowLevel.Unsafe;
7using Unity.Jobs;
8
9internal class UnsafeParallelMultiHashMapTests : CollectionsTestCommonBase
10{
11 [BurstCompile(CompileSynchronously = true)]
12 public struct UnsafeParallelMultiHashMapAddJob : IJobParallelFor
13 {
14 public UnsafeParallelMultiHashMap<int, int>.ParallelWriter Writer;
15
16 public void Execute(int index)
17 {
18 Writer.Add(123, index);
19 }
20 }
21
22 [Test]
23 public void UnsafeParallelMultiHashMap_AddJob()
24 {
25 var container = new UnsafeParallelMultiHashMap<int, int>(32, CommonRwdAllocator.Handle);
26
27 var job = new UnsafeParallelMultiHashMapAddJob()
28 {
29 Writer = container.AsParallelWriter(),
30 };
31
32 job.Schedule(3, 1).Complete();
33
34 Assert.True(container.ContainsKey(123));
35 Assert.AreEqual(container.CountValuesForKey(123), 3);
36
37 container.Dispose();
38 }
39
40 [Test]
41 public void UnsafeParallelHashMap_RemoveOnEmptyMap_DoesNotThrow()
42 {
43 var container = new UnsafeParallelHashMap<int, int>(0, Allocator.Temp);
44 Assert.DoesNotThrow(() => container.Remove(0));
45 Assert.DoesNotThrow(() => container.Remove(-425196));
46 container.Dispose();
47 }
48
49 [Test]
50 public void UnsafeParallelMultiHashMap_RemoveOnEmptyMap_DoesNotThrow()
51 {
52 var container = new UnsafeParallelMultiHashMap<int, int>(0, Allocator.Temp);
53
54 Assert.DoesNotThrow(() => container.Remove(0));
55 Assert.DoesNotThrow(() => container.Remove(-425196));
56 Assert.DoesNotThrow(() => container.Remove(0, 0));
57 Assert.DoesNotThrow(() => container.Remove(-425196, 0));
58
59 container.Dispose();
60 }
61
62 [Test]
63 public void UnsafeParallelMultiHashMap_ForEach_FixedStringInHashMap()
64 {
65 using (var stringList = new NativeList<FixedString32Bytes>(10, Allocator.Persistent) { "Hello", ",", "World", "!" })
66 {
67 var container = new UnsafeParallelMultiHashMap<FixedString128Bytes, float>(50, Allocator.Temp);
68 var seen = new NativeArray<int>(stringList.Length, Allocator.Temp);
69 foreach (var str in stringList)
70 {
71 container.Add(str, 0);
72 }
73
74 foreach (var pair in container)
75 {
76 int index = stringList.IndexOf(pair.Key);
77 Assert.AreEqual(stringList[index], pair.Key.ToString());
78 seen[index] = seen[index] + 1;
79 }
80
81 for (int i = 0; i < stringList.Length; i++)
82 {
83 Assert.AreEqual(1, seen[i], $"Incorrect value count {stringList[i]}");
84 }
85 }
86 }
87
88 [Test]
89 public void UnsafeParallelMultiHashMap_ForEach([Values(10, 1000)]int n)
90 {
91 var seenKeys = new NativeArray<int>(n, Allocator.Temp);
92 var seenValues = new NativeArray<int>(n * 2, Allocator.Temp);
93 using (var container = new UnsafeParallelMultiHashMap<int, int>(1, Allocator.Temp))
94 {
95 for (int i = 0; i < n; ++i)
96 {
97 container.Add(i, i);
98 container.Add(i, i + n);
99 }
100
101 var count = 0;
102 foreach (var kv in container)
103 {
104 if (kv.Value < n)
105 {
106 Assert.AreEqual(kv.Key, kv.Value);
107 }
108 else
109 {
110 Assert.AreEqual(kv.Key + n, kv.Value);
111 }
112
113 seenKeys[kv.Key] = seenKeys[kv.Key] + 1;
114 seenValues[kv.Value] = seenValues[kv.Value] + 1;
115
116 ++count;
117 }
118
119 Assert.AreEqual(container.Count(), count);
120 for (int i = 0; i < n; i++)
121 {
122 Assert.AreEqual(2, seenKeys[i], $"Incorrect key count {i}");
123 Assert.AreEqual(1, seenValues[i], $"Incorrect value count {i}");
124 Assert.AreEqual(1, seenValues[i + n], $"Incorrect value count {i + n}");
125 }
126 }
127 }
128
129 [Test]
130 public void UnsafeParallelMultiHashMap_GetKeys()
131 {
132 var container = new UnsafeParallelMultiHashMap<int, int>(1, Allocator.Temp);
133 for (int i = 0; i < 30; ++i)
134 {
135 container.Add(i, 2 * i);
136 container.Add(i, 3 * i);
137 }
138 var keys = container.GetKeyArray(Allocator.Temp);
139 var (unique, uniqueLength) = container.GetUniqueKeyArray(Allocator.Temp);
140 Assert.AreEqual(30, uniqueLength);
141
142 Assert.AreEqual(60, keys.Length);
143 keys.Sort();
144 for (int i = 0; i < 30; ++i)
145 {
146 Assert.AreEqual(i, keys[i * 2 + 0]);
147 Assert.AreEqual(i, keys[i * 2 + 1]);
148 Assert.AreEqual(i, unique[i]);
149 }
150 }
151
152 [Test]
153 public void UnsafeParallelMultiHashMap_CustomAllocatorTest()
154 {
155 AllocatorManager.Initialize();
156 var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
157 ref var allocator = ref allocatorHelper.Allocator;
158 allocator.Initialize();
159
160 using (var container = new UnsafeParallelMultiHashMap<int, int>(1, allocator.Handle))
161 {
162 }
163
164 Assert.IsTrue(allocator.WasUsed);
165 allocator.Dispose();
166 allocatorHelper.Dispose();
167 AllocatorManager.Shutdown();
168 }
169
170 [BurstCompile]
171 struct BurstedCustomAllocatorJob : IJob
172 {
173 [NativeDisableUnsafePtrRestriction]
174 public unsafe CustomAllocatorTests.CountingAllocator* Allocator;
175
176 public void Execute()
177 {
178 unsafe
179 {
180 using (var container = new UnsafeParallelMultiHashMap<int, int>(1, Allocator->Handle))
181 {
182 }
183 }
184 }
185 }
186
187 [Test]
188 public unsafe void UnsafeParallelMultiHashMap_BurstedCustomAllocatorTest()
189 {
190 AllocatorManager.Initialize();
191 var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
192 ref var allocator = ref allocatorHelper.Allocator;
193 allocator.Initialize();
194
195 var allocatorPtr = (CustomAllocatorTests.CountingAllocator*)UnsafeUtility.AddressOf<CustomAllocatorTests.CountingAllocator>(ref allocator);
196 unsafe
197 {
198 var handle = new BurstedCustomAllocatorJob {Allocator = allocatorPtr}.Schedule();
199 handle.Complete();
200 }
201
202 Assert.IsTrue(allocator.WasUsed);
203 allocator.Dispose();
204 allocatorHelper.Dispose();
205 AllocatorManager.Shutdown();
206 }
207}