#region CPL License /* Nuclex Framework Copyright (C) 2002-2008 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.IO; #if UNITTEST using NUnit.Framework; namespace Nuclex.Support.Collections { /// Unit Test for the ring buffer class [TestFixture] public class RingMemoryStreamTest { /// Prepares some test data for the units test methods [TestFixtureSetUp] public void Setup() { this.testBytes = new byte[20]; for(int i = 0; i < 20; ++i) this.testBytes[i] = (byte)i; } /// /// Ensures that the ring buffer blocks write attempts that would exceed its capacity /// [Test, ExpectedException(typeof(OverflowException))] public void TestWriteTooLargeChunk() { new RingMemoryStream(10).Write(this.testBytes, 0, 11); } /// /// Ensures that the ring buffer still accepts write attempts that would fill the /// entire buffer in one go. /// [Test] public void TestWriteBarelyFittingChunk() { new RingMemoryStream(10).Write(this.testBytes, 0, 10); } /// /// Ensures that the ring buffer correctly manages write attempts that have to /// be split at the end of the ring buffer /// [Test] public void TestWriteSplitBlock() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 8); testRing.Read(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 7); byte[] actual = new byte[10]; testRing.Read(actual, 0, 10); Assert.AreEqual(new byte[] { 5, 6, 7, 0, 1, 2, 3, 4, 5, 6 }, actual); } /// /// Ensures that the ring buffer correctly manages write attempts that write into /// the gap after the ring buffer's data has become split /// [Test] public void TestWriteSplitAndLinearBlock() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 8); testRing.Read(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 2); byte[] actual = new byte[10]; testRing.Read(actual, 0, 10); Assert.AreEqual(new byte[] { 5, 6, 7, 0, 1, 2, 3, 4, 0, 1 }, actual); } /// /// Ensures that the ring buffer still detects write that would exceed its capacity /// if they write into the gap after the ring buffer's data has become split /// [Test, ExpectedException(typeof(OverflowException))] public void TestWriteSplitAndLinearTooLargeBlock() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 8); testRing.Read(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 3); } /// Tests whether the ring buffer correctly handles fragmentation [Test] public void TestSplitBlockWrappedRead() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 10); testRing.Read(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 5); byte[] actual = new byte[10]; testRing.Read(actual, 0, 10); Assert.AreEqual(new byte[] { 5, 6, 7, 8, 9, 0, 1, 2, 3, 4 }, actual); } /// Tests whether the ring buffer correctly handles fragmentation [Test] public void TestSplitBlockLinearRead() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 10); testRing.Read(this.testBytes, 0, 5); testRing.Write(this.testBytes, 0, 5); byte[] actual = new byte[5]; testRing.Read(actual, 0, 5); Assert.AreEqual(new byte[] { 5, 6, 7, 8, 9 }, actual); } /// /// Tests whether the ring buffer correctly returns partial data if more /// data is requested than is contained in it. /// [Test] public void TestEndOfStream() { byte[] tempBytes = new byte[10]; RingMemoryStream testRing = new RingMemoryStream(10); Assert.AreEqual(0, testRing.Read(tempBytes, 0, 5)); testRing.Write(this.testBytes, 0, 5); Assert.AreEqual(5, testRing.Read(tempBytes, 0, 10)); testRing.Write(this.testBytes, 0, 6); testRing.Read(tempBytes, 0, 5); testRing.Write(this.testBytes, 0, 9); Assert.AreEqual(10, testRing.Read(tempBytes, 0, 20)); } /// /// Validates that the ring buffer can extend its capacity without loosing data /// [Test] public void TestCapacityIncrease() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 10); testRing.Capacity = 20; byte[] actual = new byte[10]; testRing.Read(actual, 0, 10); Assert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, actual); } /// /// Validates that the ring buffer can reduce its capacity without loosing data /// [Test] public void TestCapacityDecrease() { RingMemoryStream testRing = new RingMemoryStream(20); testRing.Write(this.testBytes, 0, 10); testRing.Capacity = 10; byte[] actual = new byte[10]; testRing.Read(actual, 0, 10); Assert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, actual); } /// /// Checks that an exception is thrown when the ring buffer's capacity is /// reduced so much it would have to give up some of its contained data /// [Test, ExpectedException(typeof(ArgumentOutOfRangeException))] public void TestCapacityDecreaseException() { RingMemoryStream testRing = new RingMemoryStream(20); testRing.Write(this.testBytes, 0, 20); testRing.Capacity = 10; } /// Tests whether the Capacity property returns the current capacity [Test] public void TestCapacity() { RingMemoryStream testRing = new RingMemoryStream(123); Assert.AreEqual(123, testRing.Capacity); } /// Ensures that the CanRead property returns true [Test] public void TestCanRead() { Assert.IsTrue(new RingMemoryStream(10).CanRead); } /// Ensures that the CanSeek property returns false [Test] public void TestCanSeek() { Assert.IsFalse(new RingMemoryStream(10).CanSeek); } /// Ensures that the CanWrite property returns true [Test] public void TestCanWrite() { Assert.IsTrue(new RingMemoryStream(10).CanWrite); } /// /// Tests whether the auto reset feature works (resets the buffer pointer to the /// left end of the buffer when it gets empty; mainly a performance feature). /// [Test] public void TestAutoReset() { byte[] tempBytes = new byte[10]; RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(this.testBytes, 0, 8); testRing.Read(tempBytes, 0, 2); testRing.Read(tempBytes, 0, 2); testRing.Read(tempBytes, 0, 1); testRing.Read(tempBytes, 0, 1); Assert.AreEqual(2, testRing.Length); } /// /// Verifies that an exception is thrown when the Position property of the ring /// memory stream is used to retrieve the current file pointer position /// [Test, ExpectedException(typeof(NotSupportedException))] public void TestThrowOnRetrievePosition() { long position = new RingMemoryStream(10).Position; } /// /// Verifies that an exception is thrown when the Position property of the ring /// memory stream is used to modify the current file pointer position /// [Test, ExpectedException(typeof(NotSupportedException))] public void TestThrowOnAssignPosition() { new RingMemoryStream(10).Position = 0; } /// /// Verifies that an exception is thrown when the Seek() method of the ring memory /// stream is attempted to be used /// [Test, ExpectedException(typeof(NotSupportedException))] public void TestThrowOnSeek() { new RingMemoryStream(10).Seek(0, SeekOrigin.Begin); } /// /// Verifies that an exception is thrown when the SetLength() method of the ring /// memory stream is attempted to be used /// [Test, ExpectedException(typeof(NotSupportedException))] public void TestThrowOnSetLength() { new RingMemoryStream(10).SetLength(10); } /// /// Tests the Flush() method of the ring memory stream, which is either a dummy /// implementation or has no side effects /// [Test] public void TestFlush() { new RingMemoryStream(10).Flush(); } /// /// Tests whether the length property is updated in accordance to the data written /// into the ring memory stream /// [Test] public void TestLengthOnLinearBlock() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(new byte[10], 0, 10); Assert.AreEqual(10, testRing.Length); } /// /// Tests whether the length property is updated in accordance to the data written /// into the ring memory stream when the data is split within the stream /// [Test] public void TestLengthOnSplitBlock() { RingMemoryStream testRing = new RingMemoryStream(10); testRing.Write(new byte[10], 0, 10); testRing.Read(new byte[5], 0, 5); testRing.Write(new byte[5], 0, 5); Assert.AreEqual(10, testRing.Length); } /// Test data for the ring buffer unit tests private byte[] testBytes; } } // namespace Nuclex.Support.Collections #endif // UNITTEST