// // Copyright (c) 2012-2021 Antmicro // // This file is licensed under the MIT License. // Full license text is available in the LICENSE file. using NUnit.Framework; using System.IO; using System; using System.Linq; namespace Antmicro.Migrant.Tests { [TestFixture(true)] [TestFixture(false)] public class PrimitiveReaderWriterTests { public PrimitiveReaderWriterTests(bool buffered) { this.buffered = buffered; } [Test] public void ShouldWriteAndReadInts( [Values(1, 10, 100, 10000, 1000*1000)] int numberOfInts) { var randomInts = Helpers.GetRandomIntegers(numberOfInts); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomInts.Length; i++) { writer.Write(randomInts[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomInts.Length; i++) { Assert.AreEqual(randomInts[i], reader.ReadInt32()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadLongs( [Values(1, 10, 100, 10000, 1000*1000)] int numberOfLongs) { var randomLongs = Helpers.GetRandomLongs(numberOfLongs); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomLongs.Length; i++) { writer.Write(randomLongs[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomLongs.Length; i++) { var read = reader.ReadInt64(); Assert.AreEqual(randomLongs[i], read); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadULongs( [Values(1, 10, 100, 10000, 1000*1000)] int numberOfULongs) { var randomULongs = Helpers.GetRandomLongs(numberOfULongs).Select(x=>(ulong)x).ToArray(); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomULongs.Length; i++) { writer.Write(randomULongs[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomULongs.Length; i++) { var read = reader.ReadUInt64(); Assert.AreEqual(randomULongs[i], read); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadStrings( [Values(1, 100, 10000)] int numberOfStrings, [Values(true, false)] bool withLongStrings) { const int maxLength = 100; const int longStringLength = 8000; const int longStringProbability = 10; var random = Helpers.Random; var strings = new string[numberOfStrings]; for(var i = 0; i < strings.Length; i++) { int length; if(withLongStrings && random.Next()%longStringProbability == 0) { length = longStringLength; } else { length = random.Next(maxLength); } strings[i] = Helpers.GetRandomString(length); } var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < strings.Length; i++) { writer.Write(strings[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < strings.Length; i++) { Assert.AreEqual(strings[i], reader.ReadString()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadNegativeInt() { var value = -Helpers.Random.Next(); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { writer.Write(value); } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { Assert.AreEqual(value, reader.ReadInt32()); } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadDoubles( [Values(1, 10, 100, 10000, 1000*1000)] int numberOfDoubles) { var randomDoubles = Helpers.GetRandomDoubles(numberOfDoubles); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomDoubles.Length; i++) { writer.Write(randomDoubles[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomDoubles.Length; i++) { Assert.AreEqual(randomDoubles[i], reader.ReadDouble()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadDecimal( [Values(1, 10, 100, 10000, 1000*1000)] int numberOfDecimals) { var randomDecimals = Helpers.GetRandomDecimals(numberOfDecimals); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomDecimals.Length; i++) { writer.Write(randomDecimals[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomDecimals.Length; i++) { Assert.AreEqual(randomDecimals[i], reader.ReadDecimal()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldSerializeDateTime( [Values(1, 10, 100, 10000)] int numberOfEntries) { var randomDateTimes = Helpers.GetRandomDateTimes(numberOfEntries); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomDateTimes.Length; i++) { writer.Write(randomDateTimes[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomDateTimes.Length; i++) { Assert.AreEqual(randomDateTimes[i], reader.ReadDateTime()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldSerializeTimeSpan( [Values(1, 10, 100, 10000)] int numberOfEntries) { var randomDateTimes = Helpers.GetRandomDateTimes(numberOfEntries); var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < randomDateTimes.Length; i++) { writer.Write(randomDateTimes[i]); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < randomDateTimes.Length; i++) { Assert.AreEqual(randomDateTimes[i], reader.ReadDateTime()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadByteArray( [Values(10, 1000, 100000)] int count ) { var stream = new MemoryStream(); byte[] array; using(var writer = new PrimitiveWriter(stream, buffered)) { array = new byte[count]; Helpers.Random.NextBytes(array); writer.Write(array); } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); byte[] copy; using(var reader = new PrimitiveReader(stream, buffered)) { copy = reader.ReadBytes(count); } CollectionAssert.AreEqual(array, copy); Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadGuid( [Values(10, 1000, 100000)] int count ) { var stream = new MemoryStream(); var array = new Guid[count]; using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < count; i++) { var guid = Guid.NewGuid(); array[i] = guid; writer.Write(guid); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < count; i++) { Assert.AreEqual(array[i], reader.ReadGuid()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldWriteAndReadPartsOfByteArrays() { var arrays = new byte[100][]; for(var i = 0; i < arrays.Length; i++) { arrays[i] = Enumerable.Range(0, 256).Select(x => (byte)x).ToArray(); } var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { for(var i = 0; i < arrays.Length; i++) { writer.Write(arrays[i], i, arrays[i].Length - i); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { for(var i = 0; i < arrays.Length; i++) { var writtenLength = arrays[i].Length - i; var writtenArray = reader.ReadBytes(writtenLength); var subarray = new byte[writtenLength]; Array.Copy(arrays[i], i, subarray, 0, writtenLength); CollectionAssert.AreEqual(subarray, writtenArray); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldReadAndWriteLimits() { var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { writer.Write(byte.MinValue); writer.Write(byte.MaxValue); writer.Write(sbyte.MinValue); writer.Write(sbyte.MaxValue); writer.Write(short.MinValue); writer.Write(short.MaxValue); writer.Write(ushort.MinValue); writer.Write(ushort.MaxValue); writer.Write(int.MinValue); writer.Write(int.MaxValue); writer.Write(uint.MinValue); writer.Write(uint.MaxValue); writer.Write(long.MinValue); writer.Write(long.MaxValue); writer.Write(ulong.MinValue); writer.Write(ulong.MaxValue); } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { Assert.AreEqual(byte.MinValue, reader.ReadByte()); Assert.AreEqual(byte.MaxValue, reader.ReadByte()); Assert.AreEqual(sbyte.MinValue, reader.ReadSByte()); Assert.AreEqual(sbyte.MaxValue, reader.ReadSByte()); Assert.AreEqual(short.MinValue, reader.ReadInt16()); Assert.AreEqual(short.MaxValue, reader.ReadInt16()); Assert.AreEqual(ushort.MinValue, reader.ReadUInt16()); Assert.AreEqual(ushort.MaxValue, reader.ReadUInt16()); Assert.AreEqual(int.MinValue, reader.ReadInt32()); Assert.AreEqual(int.MaxValue, reader.ReadInt32()); Assert.AreEqual(uint.MinValue, reader.ReadUInt32()); Assert.AreEqual(uint.MaxValue, reader.ReadUInt32()); Assert.AreEqual(long.MinValue, reader.ReadInt64()); Assert.AreEqual(long.MaxValue, reader.ReadInt64()); Assert.AreEqual(ulong.MinValue, reader.ReadUInt64()); Assert.AreEqual(ulong.MaxValue, reader.ReadUInt64()); } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldHandleNotAlignedWrites() { const int iterationCount = 80000; var stream = new MemoryStream(); using(var writer = new PrimitiveWriter(stream, buffered)) { writer.Write((byte)1); for(var i = 0; i < iterationCount; i++) { writer.Write(int.MaxValue); } } var position = stream.Position; stream.Seek(0, SeekOrigin.Begin); using(var reader = new PrimitiveReader(stream, buffered)) { Assert.AreEqual((byte)1, reader.ReadByte()); for(var i = 0; i < iterationCount; i++) { Assert.AreEqual(int.MaxValue, reader.ReadInt32()); } } Assert.AreEqual(position, stream.Position, StreamCorruptedMessage); } [Test] public void ShouldCopyFromStream() { var stream = new MemoryStream(); var testArray = Enumerable.Range(0, 1000).Select(x => (byte)x).ToArray(); var testStream = new MemoryStream(testArray); using(var writer = new PrimitiveWriter(stream, buffered)) { writer.CopyFrom(testStream, testArray.Length); } stream.Seek(0, SeekOrigin.Begin); var secondStream = new MemoryStream(testArray.Length); using(var reader = new PrimitiveReader(stream, buffered)) { reader.CopyTo(secondStream, testArray.Length); } CollectionAssert.AreEqual(testArray, secondStream.ToArray()); } [Test] public void ShouldThrowIfStreamPrematurelyFinishes() { var streamToRead = new MemoryStream(); var streamToWrite = new MemoryStream(); using(var reader = new PrimitiveReader(streamToRead, buffered)) { Assert.Throws(() => reader.CopyTo(streamToWrite, 100)); } } private readonly bool buffered; private const string StreamCorruptedMessage = "Stream was corrupted during read (in terms of position)."; } }