A game about forced loneliness, made by TACStudios
1using System;
2using NUnit.Framework;
3using Unity.Collections.NotBurstCompatible;
4using Unity.Collections.LowLevel.Unsafe;
5using Unity.Jobs;
6using UnityEngine.TestTools;
7using UnityEngine;
8
9namespace Unity.Collections.Tests
10{
11 internal class DataStreamTests
12 {
13 internal class ReadAndWrite
14 {
15 [TestCase(ushort.MaxValue)]
16 [TestCase(ushort.MinValue)]
17 public void UShort(ushort expected)
18 {
19 bool Write(ref DataStreamWriter writer) => writer.WriteUShort(expected);
20 CheckReadWrite(sizeof(ushort), reader => reader.ReadUShort(), Write, expected);
21 }
22
23 [TestCase((uint) 0b101010)]
24 [TestCase((uint) 0b111111)]
25 public void RawBits(uint expected)
26 {
27 bool Write(ref DataStreamWriter writer) => writer.WriteRawBits(expected, 6);
28 CheckReadWrite(6, reader => reader.ReadRawBits(6), Write, expected);
29 }
30
31 [Test]
32 public void RawBits_OutOfCapacity()
33 {
34 const uint expected = 0b101011001;
35 var writer = new DataStreamWriter(1, Allocator.Temp);
36 Assert.False(writer.WriteRawBits(expected, 9));
37 Assert.True(writer.HasFailedWrites);
38 }
39
40 [TestCase(uint.MaxValue)]
41 [TestCase(uint.MinValue)]
42 public void UInt(uint expected)
43 {
44 bool Write(ref DataStreamWriter writer) => writer.WriteUInt(expected);
45 CheckReadWrite(sizeof(uint), reader => reader.ReadUInt(), Write, expected);
46 }
47
48 [TestCase(float.MaxValue)]
49 [TestCase(float.MinValue)]
50 public void Float(float expected)
51 {
52 bool Write(ref DataStreamWriter writer) => writer.WriteFloat(expected);
53 CheckReadWrite(sizeof(float), reader => reader.ReadFloat(), Write, expected);
54 }
55
56 [TestCase(short.MaxValue)]
57 [TestCase(short.MinValue)]
58 public void Short(short expected)
59 {
60 bool Write(ref DataStreamWriter writer) => writer.WriteShort(expected);
61 CheckReadWrite(sizeof(short), reader => reader.ReadShort(), Write, expected);
62 }
63
64 [Test]
65 public void FixedString32()
66 {
67 var expected = new FixedString32Bytes("This is a string");
68 bool Write(ref DataStreamWriter writer) => writer.WriteFixedString32(expected);
69 CheckReadWrite(expected.Length + FixedStringHeader, reader => reader.ReadFixedString32(), Write, expected);
70 }
71
72 [Test]
73 public void FixedString64()
74 {
75 var expected = new FixedString64Bytes("This is a string");
76 bool Write(ref DataStreamWriter writer) => writer.WriteFixedString64(expected);
77 CheckReadWrite(expected.Length + FixedStringHeader, reader => reader.ReadFixedString64(), Write, expected);
78 }
79
80 [Test]
81 public void FixedString128()
82 {
83 var expected = new FixedString128Bytes("This is a string");
84 bool Write(ref DataStreamWriter writer) => writer.WriteFixedString128(expected);
85 CheckReadWrite(expected.Length + FixedStringHeader, reader => reader.ReadFixedString128(), Write, expected);
86 }
87
88 [Test]
89 public void FixedString512()
90 {
91 var expected = new FixedString512Bytes("This is a string");
92 bool Write(ref DataStreamWriter writer) => writer.WriteFixedString512(expected);
93 CheckReadWrite(expected.Length + FixedStringHeader, reader => reader.ReadFixedString512(), Write, expected);
94 }
95
96 [Test]
97 public void FixedString4096()
98 {
99 var expected = new FixedString4096Bytes("This is a string");
100 bool Write(ref DataStreamWriter writer) => writer.WriteFixedString4096(expected);
101 CheckReadWrite(expected.Length + FixedStringHeader, reader => reader.ReadFixedString4096(), Write,
102 expected);
103 }
104
105 [Test]
106 public void LongLooped()
107 {
108 const long baseVal = -99;
109 const long expected = -1979;
110 bool Write(ref DataStreamWriter writer, long value) => writer.WriteLong(value);
111 long Read(ref DataStreamReader reader) => reader.ReadLong();
112 CheckReadWriteLooped(sizeof(long), baseVal, expected, Write, Read, (l, u) => l + u);
113 }
114 }
115
116 internal class ReadAndWriteNetworkOrder
117 {
118 [TestCase(int.MaxValue)]
119 [TestCase(int.MinValue)]
120 public void Int(int expected)
121 {
122 bool Write(ref DataStreamWriter writer) => writer.WriteIntNetworkByteOrder(expected);
123 CheckReadWrite(sizeof(int), reader => reader.ReadIntNetworkByteOrder(), Write, expected);
124 }
125
126 [TestCase(uint.MaxValue)]
127 [TestCase(uint.MinValue)]
128 public void UInt(uint expected)
129 {
130 bool Write(ref DataStreamWriter writer) => writer.WriteUIntNetworkByteOrder(expected);
131 CheckReadWrite(sizeof(uint), reader => reader.ReadUIntNetworkByteOrder(), Write, expected);
132 }
133
134 [TestCase(short.MaxValue)]
135 [TestCase(short.MinValue)]
136 public void Short(short expected)
137 {
138 bool Write(ref DataStreamWriter writer) => writer.WriteShortNetworkByteOrder(expected);
139 CheckReadWrite(sizeof(short), reader => reader.ReadShortNetworkByteOrder(), Write, expected);
140 }
141
142 [TestCase(ushort.MaxValue)]
143 [TestCase(ushort.MinValue)]
144 public void UShort(ushort expected)
145 {
146 bool Write(ref DataStreamWriter writer) => writer.WriteUShortNetworkByteOrder(expected);
147 CheckReadWrite(sizeof(ushort), reader => reader.ReadUShortNetworkByteOrder(), Write, expected);
148 }
149
150 [Test]
151 public void ReadIncorrect()
152 {
153 var dataStream = new DataStreamWriter(4, Allocator.Temp);
154 dataStream.WriteIntNetworkByteOrder(1979);
155 dataStream.Flush();
156 var reader = new DataStreamReader(dataStream.AsNativeArray());
157 Assert.AreNotEqual(1979, reader.ReadInt());
158 }
159 }
160
161 internal class ReadWritePacked
162 {
163 [Test]
164 public void UInt()
165 {
166 const uint expected = 1979;
167 const uint baseVal = 2000;
168 bool Write(ref DataStreamWriter writer) => writer.WriteUInt(expected);
169 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model, uint value) => writer.WritePackedUInt(value, model);
170 uint Read(ref DataStreamReader reader) => reader.ReadUInt();
171 uint ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedUInt(model);
172 CheckReadWritePackedLooped(sizeof(uint), baseVal, expected, Write, WritePacked, Read, ReadPacked, (l, u) => l + u);
173 }
174
175 [Test]
176 public void IntExistingData()
177 {
178 unsafe
179 {
180 var n = 300 * 4;
181 var data = stackalloc byte[n];
182 var compressionModel = StreamCompressionModel.Default;
183 var dataStream = new DataStreamWriter(data, n);
184 const int base_val = -10;
185 const int count = 20;
186 for (int i = 0; i < count; ++i)
187 dataStream.WritePackedInt(base_val + i, compressionModel);
188
189 dataStream.WriteInt((int)1979);
190 dataStream.Flush();
191
192 var na = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<byte>(data, n, Allocator.Invalid);
193#if ENABLE_UNITY_COLLECTIONS_CHECKS
194 NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref na, AtomicSafetyHandle.GetTempMemoryHandle());
195#endif
196 var reader = new DataStreamReader(na);
197 for (int i = 0; i < count; ++i)
198 {
199 var val = reader.ReadPackedInt(compressionModel);
200 Assert.AreEqual(base_val + i, val);
201 }
202
203 Assert.AreEqual(1979, reader.ReadInt());
204 }
205 }
206
207 [Test]
208 public void Int()
209 {
210 const int expected = -1979;
211 const int baseVal = -10;
212 bool Write(ref DataStreamWriter writer) => writer.WriteInt(expected);
213 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model, int value) => writer.WritePackedInt(value, model);
214 int Read(ref DataStreamReader reader) => reader.ReadInt();
215 int ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedInt(model);
216 CheckReadWritePackedLooped(sizeof(int), baseVal, expected, Write, WritePacked, Read, ReadPacked, (i, u) => (int)(i + u));
217 }
218
219 [Test]
220 public void Long()
221 {
222 const long expected = -1979;
223 const long baseVal = -99;
224 bool Write(ref DataStreamWriter writer) => writer.WriteLong(expected);
225 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model, long value) => writer.WritePackedLong(value, model);
226 long Read(ref DataStreamReader reader) => reader.ReadLong();
227 long ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedLong(model);
228
229 CheckReadWritePackedLooped(sizeof(long), baseVal, expected, Write, WritePacked, Read, ReadPacked, (l, u) => l + u);
230 }
231
232 [Test]
233 public void ULong()
234 {
235 const ulong expected = 1979;
236 const ulong baseVal = 2000;
237 bool Write(ref DataStreamWriter writer) => writer.WriteULong(expected);
238 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model, ulong value) => writer.WritePackedULong(value, model);
239 ulong Read(ref DataStreamReader reader) => reader.ReadULong();
240 ulong ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedULong(model);
241 CheckReadWritePackedLooped(sizeof(ulong), baseVal, expected, Write, WritePacked, Read, ReadPacked, (l, u) => l + u);
242 }
243
244 [Test]
245 public void Float()
246 {
247 const float expected = 1979.1f;
248 const float baseVal = 2000.1f;
249 bool Write(ref DataStreamWriter writer) => writer.WriteFloat(expected);
250 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model, float value) => writer.WritePackedFloat(value, model);
251 float Read(ref DataStreamReader reader) => reader.ReadFloat();
252 float ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFloat(model);
253 CheckReadWritePackedLooped(sizeof(float), baseVal, expected, Write, WritePacked, Read, ReadPacked, (l, u) => l + u);
254 }
255
256 [Test]
257 public void Double()
258 {
259 const double expected = 1979.1989;
260 const double baseVal = 2000.2000;
261 bool Write(ref DataStreamWriter writer) => writer.WriteDouble(expected);
262 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model, double value) => writer.WritePackedDouble(value, model);
263 double Read(ref DataStreamReader reader) => reader.ReadDouble();
264 double ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedDouble(model);
265 CheckReadWritePackedLooped(sizeof(double), baseVal, expected, Write, WritePacked, Read, ReadPacked, (l, u) => l + u);
266 }
267
268 [Test]
269 public void WriteOutSideOfCapacity_Fails()
270 {
271 var model = StreamCompressionModel.Default;
272 var writer = new DataStreamWriter(sizeof(uint) / 2, Allocator.Temp);
273 Assert.False(writer.HasFailedWrites);
274 Assert.False(writer.WritePackedUInt(uint.MaxValue, model), "Writing a uint where there is no room should fail.");
275 Assert.That(writer.HasFailedWrites);
276 }
277
278 [Test]
279 [TestRequiresDotsDebugOrCollectionChecks]
280 public void ReadOutSideOfCapacity_Fails()
281 {
282 var model = StreamCompressionModel.Default;
283 var reader = new DataStreamReader(new NativeArray<byte>(0, Allocator.Temp));
284 LogAssert.Expect(LogType.Error, "Trying to read 2 bits from a stream where only 0 are available");
285 Assert.That(reader.ReadPackedUInt(model), Is.EqualTo(0));
286 Assert.That(reader.HasFailedReads);
287 }
288 }
289
290 internal class ReadWritePackedDelta
291 {
292 [Test]
293 public void Int()
294 {
295 const int expected = int.MaxValue;
296 const int baseline = int.MinValue;
297 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedIntDelta(expected, baseline, model);
298 int ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedIntDelta(baseline, model);
299 CheckReadWritePacked(sizeof(int), ReadPacked, WritePacked, expected);
300 }
301
302 [Test]
303 public void Long()
304 {
305 const long expected = long.MaxValue;
306 const long baseline = long.MinValue;
307 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedLongDelta(expected, baseline, model);
308 long ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedLongDelta(baseline, model);
309 CheckReadWritePacked(sizeof(long), ReadPacked, WritePacked, expected);
310 }
311
312 [Test]
313 public void ULong()
314 {
315 const ulong expected = ulong.MaxValue;
316 const ulong baseline = ulong.MinValue;
317 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedULongDelta(expected, baseline, model);
318 ulong ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedULongDelta(baseline, model);
319 CheckReadWritePacked(sizeof(ulong), ReadPacked, WritePacked, expected);
320 }
321
322 [Test]
323 public void FixedString32()
324 {
325 var expected = new FixedString32Bytes("This is a string");
326 var baseline = new FixedString32Bytes("This is another string");
327 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedFixedString32Delta(expected, baseline, model);
328 FixedString32Bytes ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFixedString32Delta(baseline, model);
329 CheckReadWritePacked(expected.Length + FixedStringHeader, ReadPacked, WritePacked, expected);
330 }
331
332 [Test]
333 public void FixedString32_LargerBaseline()
334 {
335 var expected = new FixedString32Bytes("This is another string");
336 var baseline = new FixedString32Bytes("This is a string");
337 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedFixedString32Delta(expected, baseline, model);
338 FixedString32Bytes ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFixedString32Delta(baseline, model);
339 CheckReadWritePacked(expected.Length + FixedStringHeader, ReadPacked, WritePacked, expected);
340 }
341
342 [Test]
343 public void FixedString64()
344 {
345 var expected = new FixedString64Bytes("This is a string");
346 var baseline = new FixedString64Bytes("This is another string");
347 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedFixedString64Delta(expected, baseline, model);
348 FixedString64Bytes ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFixedString64Delta(baseline, model);
349 CheckReadWritePacked(expected.Length + FixedStringHeader, ReadPacked, WritePacked, expected);
350 }
351
352 [Test]
353 public void FixedString128()
354 {
355 var expected = new FixedString128Bytes("This is a string");
356 var baseline = new FixedString128Bytes("This is another string");
357 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedFixedString128Delta(expected, baseline, model);
358 FixedString128Bytes ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFixedString128Delta(baseline, model);
359 CheckReadWritePacked(expected.Length + FixedStringHeader, ReadPacked, WritePacked, expected);
360 }
361
362 [Test]
363 public void FixedString512()
364 {
365 var expected = new FixedString512Bytes("This is a string");
366 var baseline = new FixedString512Bytes("This is another string");
367 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedFixedString512Delta(expected, baseline, model);
368 FixedString512Bytes ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFixedString512Delta(baseline, model);
369 CheckReadWritePacked(expected.Length + FixedStringHeader, ReadPacked, WritePacked, expected);
370 }
371
372 [Test]
373 public void FixedString4096()
374 {
375 var expected = new FixedString4096Bytes("This is a string");
376 var baseline = new FixedString4096Bytes("This is another string");
377 bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model) => writer.WritePackedFixedString4096Delta(expected, baseline, model);
378 FixedString4096Bytes ReadPacked(ref DataStreamReader reader, StreamCompressionModel model) => reader.ReadPackedFixedString4096Delta(baseline, model);
379 CheckReadWritePacked(expected.Length + FixedStringHeader, ReadPacked, WritePacked, expected);
380 }
381
382 [Test]
383 public void Float_OutOfBoundsFails()
384 {
385 const float expected = float.MaxValue;
386 const float baseline = float.MinValue;
387 var model = StreamCompressionModel.Default;
388 var writer = new DataStreamWriter(sizeof(float) / 2, Allocator.Temp);
389 Assert.False(writer.HasFailedWrites);
390 Assert.False(writer.WritePackedFloatDelta(expected, baseline, model));
391 Assert.That(writer.HasFailedWrites);
392 }
393
394 [Test]
395 public void Float_UnchangedData()
396 {
397 const float expected = float.MaxValue;
398 const float baseline = float.MaxValue;
399 var model = StreamCompressionModel.Default;
400 var writer = new DataStreamWriter(1, Allocator.Temp);
401 Assert.True(writer.WritePackedFloatDelta(expected, baseline, model));
402 var reader = new DataStreamReader(writer.AsNativeArray());
403 Assert.AreEqual(baseline, reader.ReadPackedFloatDelta(baseline, model));
404 Assert.That(reader.GetBitsRead(), Is.EqualTo(1));
405 }
406
407 [Test]
408 public void Float_ChangedData()
409 {
410 const float expected = float.MaxValue;
411 const float baseline = float.MinValue;
412 var model = StreamCompressionModel.Default;
413 var writer = new DataStreamWriter(sizeof(float) + 1, Allocator.Temp);
414 Assert.True(writer.WritePackedFloatDelta(expected, baseline, model));
415 var reader = new DataStreamReader(writer.AsNativeArray());
416 Assert.AreEqual(1, reader.ReadRawBits(1));
417 var uf = new UIntFloat
418 {
419 intValue = reader.ReadRawBits(32)
420 };
421 Assert.AreEqual(expected, uf.floatValue);
422 }
423
424 [Test]
425 [TestRequiresDotsDebugOrCollectionChecks]
426 public void UInt_OutOfCapacity()
427 {
428 var model = StreamCompressionModel.Default;
429 var writer = new DataStreamWriter(0, Allocator.Temp);
430 var reader = new DataStreamReader(writer.AsNativeArray());
431 LogAssert.Expect(LogType.Error, "Trying to read 2 bits from a stream where only 0 are available");
432 Assert.That(reader.ReadPackedUInt(model), Is.EqualTo(0));
433 Assert.That(reader.HasFailedReads);
434 }
435
436
437 // We test with a variable amount of writes to ensure we overflow the internal ulong bitBuffer.
438 [Test]
439 public void Flush_Works([Values(1, 7, 24, 65)]int numWrites)
440 {
441 const int baseline = 100;
442 var model = StreamCompressionModel.Default;
443 var writer = new DataStreamWriter(512, Allocator.Temp);
444
445 // Writer:
446 for(int i = 0; i < numWrites; i++)
447 writer.WritePackedUIntDelta((uint) (100 + i), baseline, model);
448
449 // Flush, and write another sentinel value in.
450 writer.Flush();
451 writer.WritePackedUIntDelta(45, baseline, model);
452 writer.Flush();
453 Assert.IsFalse(writer.HasFailedWrites, "Sanity: writer.HasFailedWrites");
454
455 // Reader:
456 var reader = new DataStreamReader(writer.AsNativeArray());
457 for(int i = 0; i < numWrites; i++)
458 {
459 var read = reader.ReadPackedUIntDelta(baseline, model);
460 Assert.AreEqual((uint)(100 + i), read, "100 + i");
461 }
462
463 // When we flush the reader, we expect to now be aligned.
464 reader.Flush();
465 var read45 = reader.ReadPackedUIntDelta(baseline, model);
466 Assert.AreEqual(45, read45, "45");
467 reader.Flush();
468 Assert.IsFalse(reader.HasFailedReads, "reader.HasFailedReads");
469 Assert.AreEqual(writer.LengthInBits, reader.GetBitsRead(), "writer.LengthInBits vs reader.GetBitsRead()");
470 LogAssert.NoUnexpectedReceived();
471 }
472
473 [Test]
474 public void NotMirroringFlushCall_Fails()
475 {
476 const int baseline = 100;
477 var model = StreamCompressionModel.Default;
478 var writer = new DataStreamWriter(512, Allocator.Temp);
479
480 // Writer:
481 writer.WritePackedUIntDelta(100, baseline, model);
482 Assert.AreNotEqual(0, writer.LengthInBits % 8, "Sanity: Not byte aligned!");
483 writer.Flush();
484 writer.WritePackedUIntDelta(45, baseline, model);
485 writer.Flush();
486 Assert.IsFalse(writer.HasFailedWrites, "Sanity: writer.HasFailedWrites");
487
488 // Reader:
489 var reader = new DataStreamReader(writer.AsNativeArray());
490 var read = reader.ReadPackedUIntDelta(baseline, model);
491 Assert.AreEqual(100u, read, "100u");
492
493 // SKIPPED: reader.Flush();
494 // THUS: Read pointer alignment should be wrong.
495 LogAssert.ignoreFailingMessages = true; // Defensive: Technically we're reading too FEW bits,
496 // so we shouldn't get error logs here.
497 Assert.AreNotEqual(45, reader.ReadPackedIntDelta(baseline, model), "!45");
498 Assert.AreNotEqual(writer.LengthInBits, reader.GetBitsRead(), "writer.LengthInBits vs reader.GetBitsRead()");
499 }
500
501 [Test]
502 public void CanMixPackedAndNonPacked()
503 {
504 const int baseline = 200;
505 var model = StreamCompressionModel.Default;
506 var writer = new DataStreamWriter(12, Allocator.Temp);
507
508 writer.WritePackedIntDelta(201, baseline, model);
509 Assert.AreNotEqual(0, writer.LengthInBits % 8, "Sanity: This test is invalid if we accidentally byte-align.");
510 writer.WriteInt(202);
511 writer.WritePackedInt(203, model);
512 writer.WriteInt(204);
513
514 Assert.IsFalse(writer.HasFailedWrites, "Sanity: writer.HasFailedWrites");
515
516 var reader = new DataStreamReader(writer.AsNativeArray());
517 Assert.AreEqual(201, reader.ReadPackedIntDelta(baseline, model));
518 Assert.AreEqual(202, reader.ReadInt());
519 Assert.AreEqual(203, reader.ReadPackedInt(model));
520 Assert.AreEqual(204, reader.ReadInt());
521 Assert.IsFalse(reader.HasFailedReads, "reader.HasFailedReads");
522 }
523 }
524
525 [Test]
526 public void IsCreated_ReturnsTrueAfterConstructor()
527 {
528 var dataStream = new DataStreamWriter(4, Allocator.Temp);
529 Assert.True(dataStream.IsCreated, "Buffer must be created after calling constructor.");
530 }
531
532 [Test]
533 public void LengthInBits_MatchesWrittenCount()
534 {
535 var dataStream = new DataStreamWriter(4, Allocator.Temp);
536 dataStream.WriteByte(0);
537 Assert.That(dataStream.LengthInBits, Is.EqualTo(1 * 8));
538 dataStream.WriteByte(1);
539 dataStream.WriteByte(1);
540 Assert.That(dataStream.LengthInBits, Is.EqualTo(3 * 8));
541 }
542
543 [Test]
544 public void CreateStreamWithPartOfSourceByteArray()
545 {
546 byte[] byteArray =
547 {
548 (byte)'s', (byte)'o', (byte)'m', (byte)'e',
549 (byte)' ', (byte)'d', (byte)'a', (byte)'t', (byte)'a'
550 };
551
552 DataStreamWriter dataStream;
553 dataStream = new DataStreamWriter(4, Allocator.Temp);
554 dataStream.WriteBytes(new NativeArray<byte>(byteArray, Allocator.Temp).GetSubArray(0, 4));
555 Assert.AreEqual(dataStream.Length, 4);
556 var reader = new DataStreamReader(dataStream.AsNativeArray());
557 for (int i = 0; i < dataStream.Length; ++i)
558 {
559 Assert.AreEqual(byteArray[i], reader.ReadByte());
560 }
561
562#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG
563 LogAssert.Expect(LogType.Error, "Trying to read 1 bytes from a stream where only 0 are available");
564 Assert.AreEqual(0, reader.ReadByte());
565#endif
566 }
567
568 [Test]
569 public void CreateStreamWithSourceByteArray()
570 {
571 byte[] byteArray = new byte[100];
572 byteArray[0] = (byte)'a';
573 byteArray[1] = (byte)'b';
574 byteArray[2] = (byte)'c';
575
576 DataStreamWriter dataStream1, dataStream2;
577 dataStream1 = new DataStreamWriter(byteArray.Length, Allocator.Temp);
578 dataStream2 = new DataStreamWriter(byteArray.Length, Allocator.Temp);
579 dataStream1.WriteBytes(new NativeArray<byte>(byteArray, Allocator.Temp));
580 dataStream2.WriteBytes(byteArray);
581
582 var arr1 = dataStream1.AsNativeArray();
583 var arr2 = dataStream2.AsNativeArray();
584 var reader1 = new DataStreamReader(arr1);
585 var reader2 = new DataStreamReader(arr2);
586 for (var i = 0; i < byteArray.Length; ++i)
587 {
588 Assert.AreEqual(byteArray[i], reader1.ReadByte());
589 Assert.AreEqual(byteArray[i], reader2.ReadByte());
590 }
591 }
592
593 [Test]
594 public void ReadIntoExistingNativeByteArray()
595 {
596 var byteArray = new NativeArray<byte>(100, Allocator.Temp);
597
598 DataStreamWriter dataStream;
599 dataStream = new DataStreamWriter(3, Allocator.Temp);
600 {
601 dataStream.WriteByte((byte)'a');
602 dataStream.WriteByte((byte)'b');
603 dataStream.WriteByte((byte)'c');
604 var reader = new DataStreamReader(dataStream.AsNativeArray());
605 reader.ReadBytes(byteArray.GetSubArray(0, dataStream.Length));
606 reader = new DataStreamReader(dataStream.AsNativeArray());
607 for (int i = 0; i < reader.Length; ++i)
608 {
609 Assert.AreEqual(byteArray[i], reader.ReadByte());
610 }
611 }
612 }
613
614 [Test]
615 public void ReadIntoExistingByteArray()
616 {
617 var byteArray = new byte[3];
618
619 DataStreamWriter dataStream;
620 dataStream = new DataStreamWriter(3, Allocator.Temp);
621 {
622 dataStream.WriteByte((byte)'a');
623 dataStream.WriteByte((byte)'b');
624 dataStream.WriteByte((byte)'c');
625 var reader = new DataStreamReader(dataStream.AsNativeArray());
626 reader.ReadBytes(byteArray);
627 reader = new DataStreamReader(dataStream.AsNativeArray());
628 for (int i = 0; i < reader.Length; ++i)
629 {
630 Assert.AreEqual(byteArray[i], reader.ReadByte());
631 }
632 }
633 }
634
635 [Test]
636 public void ReadingDataFromStreamWithSliceOffset()
637 {
638 var dataStream = new DataStreamWriter(100, Allocator.Temp);
639 dataStream.WriteByte((byte)'a');
640 dataStream.WriteByte((byte)'b');
641 dataStream.WriteByte((byte)'c');
642 dataStream.WriteByte((byte)'d');
643 dataStream.WriteByte((byte)'e');
644 dataStream.WriteByte((byte)'f');
645 var reader = new DataStreamReader(dataStream.AsNativeArray().GetSubArray(3, 3));
646 Assert.AreEqual('d', reader.ReadByte());
647 Assert.AreEqual('e', reader.ReadByte());
648 Assert.AreEqual('f', reader.ReadByte());
649 }
650
651 [Test]
652 public void GetStreamReaderUnsafePtr()
653 {
654 var a = new NativeArray<byte>(1, Allocator.Temp);
655 a[0] = (byte)42;
656 var reader = new DataStreamReader(a);
657
658 unsafe
659 {
660 var ptr = (byte*)reader.GetUnsafeReadOnlyPtr();
661 Assert.AreEqual((byte)42, *ptr);
662 }
663 }
664
665 [Test]
666 public void WriteOutOfBounds()
667 {
668 var dataStream = new DataStreamWriter(9, Allocator.Temp);
669 Assert.IsTrue(dataStream.WriteInt(42));
670 Assert.AreEqual(4, dataStream.Length);
671 Assert.IsTrue(dataStream.WriteInt(42));
672 Assert.AreEqual(8, dataStream.Length);
673 Assert.IsFalse(dataStream.HasFailedWrites);
674 Assert.IsFalse(dataStream.WriteInt(42));
675 Assert.AreEqual(8, dataStream.Length);
676 Assert.IsTrue(dataStream.HasFailedWrites);
677
678 Assert.IsFalse(dataStream.WriteShort(42));
679 Assert.AreEqual(8, dataStream.Length);
680 Assert.IsTrue(dataStream.HasFailedWrites);
681
682 Assert.IsTrue(dataStream.WriteByte(42));
683 Assert.AreEqual(9, dataStream.Length);
684 Assert.IsTrue(dataStream.HasFailedWrites);
685
686 Assert.IsFalse(dataStream.WriteByte(42));
687 Assert.AreEqual(9, dataStream.Length);
688 Assert.IsTrue(dataStream.HasFailedWrites);
689 }
690
691 [Test]
692 public void ReadWritePackedUIntWithDeferred()
693 {
694 var compressionModel = StreamCompressionModel.Default;
695 var dataStream = new DataStreamWriter(300 * 4, Allocator.Temp);
696 uint base_val = 2000;
697 uint count = 277;
698 var def = dataStream;
699 dataStream.WriteInt((int)0);
700 for (uint i = 0; i < count; ++i)
701 dataStream.WritePackedUInt(base_val + i, compressionModel);
702
703 dataStream.Flush();
704 def.WriteInt(1979);
705 def = dataStream;
706 dataStream.WriteInt((int)0);
707 def.WriteInt(1979);
708 dataStream.Flush();
709 var reader = new DataStreamReader(dataStream.AsNativeArray());
710 Assert.AreEqual(1979, reader.ReadInt());
711 for (uint i = 0; i < count; ++i)
712 {
713 var val = reader.ReadPackedUInt(compressionModel);
714 Assert.AreEqual(base_val + i, val);
715 }
716
717 Assert.AreEqual(1979, reader.ReadInt());
718 }
719
720 [Test]
721 public void PassDataStreamReaderToJob()
722 {
723 using (var returnValue = new NativeArray<int>(1, Allocator.TempJob))
724 {
725 var writer = new DataStreamWriter(sizeof(int), Allocator.Temp);
726 writer.WriteInt(42);
727
728 var reader = new DataStreamReader(writer.AsNativeArray());
729
730 new ReaderTestJob
731 {
732 Reader = reader,
733 ReturnValue = returnValue
734 }.Run();
735
736 Assert.AreEqual(42, returnValue[0]);
737 }
738 }
739
740 private struct ReaderTestJob : IJob
741 {
742 public DataStreamReader Reader;
743 public NativeArray<int> ReturnValue;
744
745 public void Execute()
746 {
747 ReturnValue[0] = Reader.ReadInt();
748 }
749 }
750
751 delegate T Read<out T>(ref DataStreamReader reader);
752 delegate T ReadPacked<out T>(ref DataStreamReader reader, StreamCompressionModel model);
753 delegate bool Write(ref DataStreamWriter writer);
754 delegate T Sum<T>(T x, uint y);
755 delegate bool WriteWithValue<in T>(ref DataStreamWriter writer, T value);
756 delegate bool WritePacked(ref DataStreamWriter writer, StreamCompressionModel model);
757 delegate bool WritePackedWithValue<in T>(ref DataStreamWriter writer, StreamCompressionModel model, T value);
758
759 const int FixedStringHeader = 2;
760
761 static void CheckReadWritePackedLooped<T>(int size, T baseVal, T expected,
762 Write write, WritePackedWithValue<T> writePackedWithValue,
763 Read<T> read, ReadPacked<T> readPacked, Sum<T> sum)
764 {
765 var compressionModel = StreamCompressionModel.Default;
766 var dataStream = new DataStreamWriter(300 * size, Allocator.Temp);
767 const int count = 277;
768 for (uint i = 0; i < count; ++i)
769 {
770 T res = sum(baseVal, i);
771 writePackedWithValue(ref dataStream, compressionModel, res);
772 }
773
774 write(ref dataStream);
775 dataStream.Flush();
776 var reader = new DataStreamReader(dataStream.AsNativeArray());
777 for (uint i = 0; i < count; ++i)
778 {
779 var val = readPacked(ref reader, compressionModel);
780 Assert.AreEqual(sum(baseVal, i), val);
781 }
782
783 Assert.AreEqual(expected, read(ref reader));
784 }
785
786 static void CheckReadWritePacked<T>(int size, ReadPacked<T> read, WritePacked write, T value)
787 {
788 var model = StreamCompressionModel.Default;
789 var writer = new DataStreamWriter(size, Allocator.Temp);
790 write(ref writer, model);
791 writer.Flush();
792 var reader = new DataStreamReader(writer.AsNativeArray());
793 Assert.That(read(ref reader, model), Is.EqualTo(value));
794 }
795
796 static void CheckReadWrite<T>(int size, Func<DataStreamReader, T> read, Write write, T value)
797 {
798 var writer = new DataStreamWriter(size, Allocator.Temp);
799 write(ref writer);
800 writer.Flush();
801 Assert.That(read(new DataStreamReader(writer.AsNativeArray())), Is.EqualTo(value));
802 }
803
804 static void CheckReadWriteLooped<T>(int size, T baseVal, T expected, WriteWithValue<T> write, Read<T> read, Sum<T> sum)
805 {
806 var writer = new DataStreamWriter(300 * size, Allocator.Temp);
807 const int count = 277;
808 for (uint i = 0; i < count; ++i)
809 {
810 write(ref writer, sum(baseVal, i));
811 }
812
813 write(ref writer, expected);
814 writer.Flush();
815 var reader = new DataStreamReader(writer.AsNativeArray());
816 for (uint i = 0; i < count; ++i)
817 {
818 var val = read(ref reader);
819 Assert.AreEqual(sum(baseVal, i), val);
820 }
821
822 Assert.AreEqual(expected, read(ref reader));
823 }
824
825 [Test]
826 public void MiNiCheck()
827 {
828 var model = StreamCompressionModel.Default;
829 Assert.That(model.ToString(), Is.EqualTo("Unity.Collections.StreamCompressionModel"));
830 }
831 }
832}