Click here to Skip to main content
15,885,537 members
Articles / Programming Languages / C#

Optimizing Serialization in .NET - part 2

Rate me:
Please Sign up or sign in to vote.
4.95/5 (34 votes)
27 Nov 2006Public Domain33 min read 327.5K   3.7K   156  
Provides code and techniques to enable developers to optimize serialization of DataSets/DataTables.
#if DEBUG
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using NUnit.Framework;

namespace SimmoTech.Utils.Serialization
{
	[TestFixture]
	public class FastSerializerTests
	{
		SerializationWriter Writer;
		private int writerPosition;
		private long writerLength;
		private long objectWriterLength;
		
		[SetUp]
		public void CreateWriter()
		{
			Writer = new SerializationWriter();
			reader = null;
			writerPosition = 0;
			writerLength = -1;
			objectWriterLength = -1;
		}
		
		[Browsable(false)]
		public SerializationReader Reader
		{
			get
			{
				if (reader == null)
				{
					writerPosition = (int) Writer.BaseStream.Position;
					reader = getReaderFromWriter(Writer);
				}
				return reader;
			}
		} SerializationReader reader;
		
		private void CheckValueAsObject(int expectedSizeAsObject, object value) {
			SerializationWriter objectWriter = new SerializationWriter();
			objectWriter.WriteObject(value);
			Assert.AreEqual(expectedSizeAsObject, objectWriter.BaseStream.Position - 4, "Incorrect length on Write As Object");

			SerializationReader objectReader = getReaderFromWriter(objectWriter);
			object newValue = objectReader.ReadObject();
			Assert.AreEqual(expectedSizeAsObject, objectReader.BaseStream.Position - 4, "Incorrect length on Read As Object");
			Assert.AreEqual(value, newValue, "Object Value Read does not match Object Value Write");
		}
		
		private void CheckValue(int expectedSize, int expectedSizeAsObject, object value, object newValue) {
			if (expectedSize != -1)
			{
				Assert.AreEqual(expectedSize, writerPosition - 4, "Incorrect length on Write Direct");
				Assert.AreEqual(expectedSize, Reader.BaseStream.Position - 4, "Incorrect length on Read Direct");
			}
			
			Assert.AreEqual(value, newValue, "Direct Value Read does not match Direct Value Write");
			
			if (expectedSizeAsObject != -1) CheckValueAsObject(expectedSizeAsObject, value);
		}
		
		
		private void CheckObjectTypeAsObject(int expectedSizeAsObject, object value) {
			SerializationWriter objectWriter = new SerializationWriter();
			objectWriter.WriteObject(value);
			Assert.AreEqual(expectedSizeAsObject, objectWriter.BaseStream.Position - 4, "Incorrect length on Write As Object");

			SerializationReader objectReader = getReaderFromWriter(objectWriter);
			object newValue = objectReader.ReadObject();
			Assert.AreEqual(expectedSizeAsObject, objectReader.BaseStream.Position - 4, "Incorrect length on Read As Object");
			Assert.AreEqual(value.GetType(), newValue.GetType(), "Object Value Read Type does not match Object Value Write Type");
		}
		
		private void CheckObjectType(int expectedSize, int expectedSizeAsObject, object value, object newValue) {
			if (expectedSize != -1)
			{
				Assert.AreEqual(expectedSize, writerPosition - 4, "Incorrect length on Write Direct");
				Assert.AreEqual(expectedSize, Reader.BaseStream.Position - 4, "Incorrect length on Read Direct");
			}
			
			Assert.AreEqual(value.GetType(), newValue.GetType(), "Direct Value Read Type does not match Direct Value Write Type");
			
			if (expectedSizeAsObject != -1) CheckObjectTypeAsObject(expectedSizeAsObject, value);
		}
		
		private SerializationReader getReaderFromWriter(SerializationWriter writer)
		{
			byte[] data = writer.ToArray();
			if (writerLength == -1)
				writerLength = data.Length;
			else
			{
				objectWriterLength = data.Length;
			}
			return new SerializationReader(data);
		}
		
		[Test]
		public void CheckTrueBoolean()
		{
			bool value = true;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadBoolean());
		}
		
		[Test]
		public void ReadWriteFalseBoolean()
		{
			bool value = false;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadBoolean());
		}

		[Test]
		public void CheckByte()
		{
			Byte value = 33;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadByte());
		}
		[Test]
		public void CheckByteAsZero()
		{
			Byte value = 0;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadByte());
		}
		
		[Test]
		public void CheckByteAsOne()
		{
			Byte value = 1;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadByte());
		}
		
		[Test]
		public void CheckByteAsMaxValue()
		{
			Byte value = Byte.MaxValue;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadByte());
		}
		
		[Test]
		public void CheckSByte()
		{
			SByte value = 33;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadSByte());
		}
		
		[Test]
		public void CheckSByteNegative()
		{
			SByte value = -33;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadSByte());
		}
		
		[Test]
		public void CheckSByteAsZero()
		{
			SByte value = 0;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadSByte());
		}
		
		[Test]
		public void CheckSByteAsMinValue()
		{
			SByte value = SByte.MinValue;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadSByte());
		}
		
		[Test]
		public void CheckSByteAsMaxValue()
		{
			SByte value = SByte.MaxValue;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadSByte());
		}
		
		[Test]
		public void CheckSByteAsOne()
		{
			SByte value = 1;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadSByte());
		}

		[Test]
		public void CheckChar()
		{
			Char value = (Char) 33;
			Writer.Write(value);
			CheckValue(1, 2, value, Reader.ReadChar());
		}
		[Test]
		public void CheckCharAsZero()
		{
			Char value = (char) 0;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadChar());
		}
		
		[Test]
		public void CheckCharAsOne()
		{
			Char value = (Char) 1;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadChar());
		}

		[Test]
		public void CheckDecimal()
		{
			Decimal value = 33;
			Writer.Write(value);
			CheckValue(16, 3, value, Reader.ReadDecimal());
		}
		
		[Test]
		public void CheckDecimalLarge()
		{
			Decimal value = Decimal.MaxValue - 1;
			Writer.Write(value);
			CheckValue(16, 14, value, Reader.ReadDecimal());
		}
		
		[Test]
		public void CheckDecimalNegative()
		{
			Decimal value = 33;
			Writer.Write(value);
			CheckValue(16, 3, value, Reader.ReadDecimal());
		}
		
		[Test]
		public void CheckDecimalLargeNegative()
		{
			Decimal value = Decimal.MinValue + 1;
			Writer.Write(value);
			CheckValue(16, 14, value, Reader.ReadDecimal());
		}
		
		[Test]
		public void CheckDecimalAsZero()
		{
			Decimal value = 0;
			Writer.Write(value);
			CheckValue(16, 1, value, Reader.ReadDecimal());
		}
		
		[Test]
		public void CheckDecimalAsOne()
		{
			Decimal value = 1;
			Writer.Write(value);
			CheckValue(16, 1, value, Reader.ReadDecimal());
		}
		
		[Test]
		public void CheckDecimalAsMinValue()
		{
			Decimal value = Decimal.MinValue;
			Writer.Write(value);
			CheckValue(16, 14, value, Reader.ReadDecimal());
		}

		[Test]
		public void CheckDecimalAsMaxValue()
		{
			Decimal value = Decimal.MaxValue;
			Writer.Write(value);
			CheckValue(16, 14, value, Reader.ReadDecimal());
		}

		[Test]
		public void CheckOptimizedDecimal()
		{
			Decimal value = 33;
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedDecimal());
		}
		
		[Test]
		public void CheckOptimizedDecimalLarge()
		{
			Decimal value = Decimal.MaxValue - 1;
			Writer.WriteOptimized(value);
			CheckValue(13, 14, value, Reader.ReadOptimizedDecimal());
		}
		
		[Test]
		public void CheckOptimizedDecimalNegative()
		{
			Decimal value = -33;
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedDecimal());
		}
		
		[Test]
		public void CheckOptimizedDecimalLargeNegative()
		{
			Decimal value = Decimal.MinValue + 1;
			Writer.WriteOptimized(value);
			CheckValue(13, 14, value, Reader.ReadOptimizedDecimal());
		}
		
		[Test]
		public void CheckOptimizedDecimalAsZero()
		{
			Decimal value = 0;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedDecimal());
		}
		
		[Test]
		public void CheckOptimizedDecimalAsOne()
		{
			Decimal value = 1;
			Writer.WriteOptimized(value);
			CheckValue(2, 1, value, Reader.ReadOptimizedDecimal());
		}
		
		public void CheckOptimizedDecimalAsMinValue()
		{
			Decimal value = Decimal.MinValue;
			Writer.WriteOptimized(value);
			CheckValue(16, 13, value, Reader.ReadOptimizedDecimal());
		}

		public void CheckOptimizedDecimalAsMaxValue()
		{
			Decimal value = Decimal.MaxValue;
			Writer.WriteOptimized(value);
			CheckValue(16, 13, value, Reader.ReadOptimizedDecimal());
		}

		[Test]
		public void CheckDouble()
		{
			Double value = 33;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleLarge()
		{
			Double value = Double.MaxValue - 1;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleNegative()
		{
			Double value = -33;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleLargeNegative()
		{
			Double value = Double.MinValue + 1;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleAsZero()
		{
			Double value = 0;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleAsOne()
		{
			Double value = 1;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleAsMinValue()
		{
			Double value = Double.MinValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckDoubleAsMaxValue()
		{
			Double value = Double.MaxValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDouble());
		}
		
		[Test]
		public void CheckSingle()
		{
			Single value = 33;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleLarge()
		{
			Single value = Single.MaxValue - 1;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleNegative()
		{
			Single value = -33;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleLargeNegative()
		{
			Single value = Single.MinValue + 1;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleAsZero()
		{
			Single value = 0;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleAsOne()
		{
			Single value = 1;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleAsMinValue()
		{
			Single value = Single.MinValue;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckSingleAsMaxValue()
		{
			Single value = Single.MaxValue;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadSingle());
		}
		
		[Test]
		public void CheckInt16()
		{
			Int16 value = 33;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16Large()
		{
			Int16 value = Int16.MaxValue - 1;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16Negative()
		{
			Int16 value = -33;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16LargeNegative()
		{
			Int16 value = Int16.MinValue + 1;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16AsZero()
		{
			Int16 value = 0;
			Writer.Write(value);
			CheckValue(2, 1, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16AsMinusOne()
		{
			Int16 value = -1;
			Writer.Write(value);
			CheckValue(2, 1, value, Reader.ReadInt16());
		}

		[Test]
		public void CheckInt16AsOne()
		{
			Int16 value = 1;
			Writer.Write(value);
			CheckValue(2, 1, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16AsMinValue()
		{
			Int16 value = Int16.MinValue;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt16AsMaxValue()
		{
			Int16 value = Int16.MaxValue;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadInt16());
		}
		
		[Test]
		public void CheckInt32()
		{
			Int32 value = 33;
			Writer.Write(value);
			CheckValue(4, 2, value, Reader.ReadInt32());
		}
		
		[Test]
		public void CheckInt32Large()
		{
			Int32 value = Int32.MaxValue - 1;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadInt32());
		}
		
		[Test]
		public void CheckInt32Negative()
		{
			Int32 value = -33;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadInt32());
		}
		
		[Test]
		public void CheckInt32LargeNegative()
		{
			Int32 value = Int32.MinValue + 1;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadInt32());
		}
		
		[Test]
		public void CheckInt32AsZero()
		{
			Int32 value = 0;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadInt32());
		}
		
		[Test]
		public void CheckInt32AsMinusOne()
		{
			Int32 value = -1;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadInt32());
		}

		[Test]
		public void CheckInt32AsOne()
		{
			Int32 value = 1;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadInt32());
		}

		[Test]
		public void CheckInt32AsMinValue()
		{
			Int32 value = Int32.MinValue;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadInt32());
		}

		[Test]
		public void CheckInt32AsMaxValue()
		{
			Int32 value = Int32.MaxValue;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadInt32());
		}

		[Test]
		public void CheckOptimizedInt32()
		{
			Int32 value = 33;
			Writer.WriteOptimized(value);
			CheckValue(1, 2, value, Reader.ReadOptimizedInt32());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedInt32Large()
		{
			Int32 value = Int32.MaxValue - 1;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedInt32Negative()
		{
			Int32 value = -33;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedInt32LargeNegative()
		{
			Int32 value = Int32.MinValue + 1;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckOptimizedInt32AsZero()
		{
			Int32 value = 0;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedInt32());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedInt32AsMinusOne()
		{
			Int32 value = -1;
			Writer.WriteOptimized(value);
		}

		[Test]
		public void CheckOptimizedInt32AsOne()
		{
			Int32 value = 1;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedInt32());
		}

		[Test]
		public void CheckInt64()
		{
			Int64 value = 33;
			Writer.Write(value);
			CheckValue(8, 2, value, Reader.ReadInt64());
		}

		[Test]
		public void CheckInt64Large()
		{
			Int64 value = Int64.MaxValue - 1;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadInt64());
		}

		[Test]
		public void CheckInt64Negative()
		{
			Int64 value = -33;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadInt64());
		}

		[Test]
		public void CheckInt64LargeNegative()
		{
			Int64 value = Int64.MinValue + 1;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadInt64());
		}

		[Test]
		public void CheckInt64AsZero()
		{
			Int64 value = 0;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadInt64());
		}
		
		[Test]
		public void CheckInt64AsMinusOne()
		{
			Int64 value = -1;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadInt64());
		}
		
		[Test]
		public void CheckInt64AsOne()
		{
			Int64 value = 1;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadInt64());
		}

		[Test]
		public void CheckInt64AsMinValue()
		{
			Int64 value = Int64.MinValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadInt64());
		}
		
		[Test]
		public void CheckInt64AsMaxValue()
		{
			Int64 value = Int64.MaxValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadInt64());
		}
		
		[Test]
		public void CheckInt64Optimized()
		{
			Int64 value = 33;
			Writer.WriteOptimized(value);
			CheckValue(1, 2, value, Reader.ReadOptimizedInt64());
		}
		
		[Test]
		public void CheckInt64OptimizedAsZero()
		{
			Int64 value = 0;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedInt64());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt64OptimizedAsMinusOne()
		{
			Int64 value = -1;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckInt64OptimizedAsOne()
		{
			Int64 value = 1;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedInt64());
		}
		
		[Test]
		public void CheckUInt16()
		{
			UInt16 value = 33;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadUInt16());
		}
		
		[Test]
		public void CheckUInt16Large()
		{
			UInt16 value = UInt16.MaxValue - 1;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadUInt16());
		}
		
		[Test]
		public void CheckUInt16AsZero()
		{
			UInt16 value = 0;
			Writer.Write(value);
			CheckValue(2, 1, value, Reader.ReadUInt16());
		}
		
		[Test]
		public void CheckUInt16AsOne()
		{
			UInt16 value = 1;
			Writer.Write(value);
			CheckValue(2, 1, value, Reader.ReadUInt16());
		}

		[Test]
		public void CheckUInt16AsMaxValue()
		{
			UInt16 value = UInt16.MaxValue;
			Writer.Write(value);
			CheckValue(2, 3, value, Reader.ReadUInt16());
		}

		[Test]
		public void CheckUInt32()
		{
			UInt32 value = 33;
			Writer.Write(value);
			CheckValue(4, 2, value, Reader.ReadUInt32());
		}
		
		[Test]
		public void CheckUInt32Large()
		{
			UInt32 value = UInt32.MaxValue - 1;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadUInt32());
		}
		
		[Test]
		public void CheckUInt32AsZero()
		{
			UInt32 value = 0;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadUInt32());
		}
		
		[Test]
		public void CheckUInt32AsOne()
		{
			UInt32 value = 1;
			Writer.Write(value);
			CheckValue(4, 1, value, Reader.ReadUInt32());
		}

		[Test]
		public void CheckUInt32AsMaxValue()
		{
			UInt32 value = UInt32.MaxValue;
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadUInt32());
		}

		[Test]
		public void CheckOptimizedUInt32()
		{
			UInt32 value = 33;
			Writer.WriteOptimized(value);
			CheckValue(1, 2, value, Reader.ReadOptimizedUInt32());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedUInt32Large()
		{
			UInt32 value = UInt32.MaxValue - 1;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckOptimizedUInt32AsZero()
		{
			UInt32 value = 0;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedUInt32());
		}
		
		[Test]
		public void CheckOptimizedUInt32AsOne()
		{
			UInt32 value = 1;
			Writer.WriteOptimized(value);
			CheckValue(1, 1, value, Reader.ReadOptimizedUInt32());
		}
		
		[Test]
		public void CheckUInt64()
		{
			UInt64 value = 33;
			Writer.Write(value);
			CheckValue(8, 2, value, Reader.ReadUInt64());
		}
		
		[Test]
		public void CheckUInt64Large()
		{
			UInt64 value = UInt64.MaxValue - 1;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadUInt64());
		}

		[Test]
		public void CheckUInt64AsZero()
		{
			UInt64 value = 0;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadUInt64());
		}
		
		[Test]
		public void CheckUInt64AsOne()
		{
			UInt64 value = 1;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadUInt64());
		}
		
		[Test]
		public void CheckUInt64AsMaxValue()
		{
			UInt64 value = UInt64.MaxValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadUInt64());
		}
		
		[Test]
		public void CheckString() {
			string value = "Fast";
			Writer.Write(value);
			CheckValue(2, 2, value, Reader.ReadString());
		}
		
		[Test]
		public void CheckStringAsNull() {
			string value = null;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadString());
		}
		
		[Test]
		public void CheckStringAsEmpty() {
			string value = "";
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadString());
		}
		
		[Test]
		public void CheckStringAsSingleChar() {
			string value = "X";
			Writer.Write(value);
			CheckValue(2, 2, value, Reader.ReadString());
		}
		
		[Test]
		public void CheckStringAsY() {
			string value = "Y";
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadString());
		}
		
		[Test]
		public void CheckStringAsN() {
			string value = "N";
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadString());
		}
		
		[Test]
		public void CheckStringDirect() {
			string value = "Fast";
			Writer.WriteStringDirect(value);
			CheckValue(5, 2, value, Reader.ReadStringDirect());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckStringDirectAsNull() {
			string value = null;
			Writer.WriteStringDirect(value);
		}
		
		[Test]
		public void CheckStringDirectAsEmpty() {
			string value = "";
			Writer.WriteStringDirect(value);
			CheckValue(1, 1, value, Reader.ReadStringDirect());
		}
		
		[Test]
		public void CheckStringDirectAsSingleChar() {
			string value = "X";
			Writer.WriteStringDirect(value);
			CheckValue(2, 2, value, Reader.ReadStringDirect());
		}
		
		[Test]
		public void CheckDateTime() {
			DateTime value = DateTime.Now;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadDateTime());
		}
		
		[Test]
		public void CheckDateTimeAsMinValue() {
			DateTime value = DateTime.MinValue;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadDateTime());
		}
		
		[Test]
		public void CheckDateTimeAsMaxValue() {
			DateTime value = DateTime.MaxValue;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadDateTime());
		}
		
		[Test]
		public void CheckTimeSpan() {
			TimeSpan value = TimeSpan.FromDays(1);
			Writer.Write(value);
			CheckValue(8, 4, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckTimeSpanNegative() {
			TimeSpan value = TimeSpan.FromDays(-6.44);
			Writer.Write(value);
			CheckValue(8, 5, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckTimeSpanMinValue() {
			TimeSpan value = TimeSpan.MinValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckTimeSpanMaxValue() {
			TimeSpan value = TimeSpan.MaxValue;
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckTimeSpanMaxValueNoOddTicks() {
			TimeSpan value = new TimeSpan(TimeSpan.MaxValue.Ticks  - (TimeSpan.MaxValue.Ticks % TimeSpan.TicksPerMillisecond));
			Writer.Write(value);
			CheckValue(8, 9, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckTimeSpanMaxDaysValue() {
			TimeSpan value = new TimeSpan((int) TimeSpan.MaxValue.TotalDays, 0, 0);
			Writer.Write(value);
			CheckValue(8, 6, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckTimeSpanAsZero() {
			TimeSpan value = TimeSpan.Zero;
			Writer.Write(value);
			CheckValue(8, 1, value, Reader.ReadTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpan() {
			TimeSpan value = TimeSpan.FromDays(1);
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanNegative() {
			TimeSpan value = TimeSpan.FromDays(-6.44);
			Writer.WriteOptimized(value);
			CheckValue(4, 5, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedTimeSpanMinValue() {
			TimeSpan value = TimeSpan.MinValue;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedTimeSpanMaxValue() {
			TimeSpan value = TimeSpan.MaxValue;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckOptimizedTimeSpanMaxValueNoOddTicks() {
			TimeSpan value = new TimeSpan(TimeSpan.MaxValue.Ticks - (TimeSpan.MaxValue.Ticks % TimeSpan.TicksPerMillisecond));
			Writer.WriteOptimized(value);
			CheckValue(8, 9, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanMaxDaysValue() {
			TimeSpan value = new TimeSpan((int) TimeSpan.MaxValue.TotalDays, 0, 0);
			Writer.WriteOptimized(value);
			CheckValue(5, 6, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanMinValueNoOddTicks() {
			TimeSpan value = new TimeSpan(TimeSpan.MinValue.Ticks - (TimeSpan.MinValue.Ticks % TimeSpan.TicksPerMillisecond));
			Writer.WriteOptimized(value);
			CheckValue(8, 9, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanMinDaysValue() {
			TimeSpan value = new TimeSpan((int) TimeSpan.MinValue.TotalDays, 0, 0);
			Writer.WriteOptimized(value);
			CheckValue(5, 6, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanAsZero() {
			TimeSpan value = TimeSpan.Zero;
			Writer.WriteOptimized(value);
			CheckValue(2, 1, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanSecondsOnly() {
			TimeSpan value = TimeSpan.FromSeconds(30);
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanMinutesOnly() {
			TimeSpan value = TimeSpan.FromMinutes(59);
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedTimeSpan());
		}

		[Test]
		public void CheckOptimizedTimeSpanHoursOnly() {
			TimeSpan value = TimeSpan.FromHours(23);
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanMillisecondsOnly() {
			TimeSpan value = TimeSpan.FromMilliseconds(999);
			Writer.WriteOptimized(value);
			CheckValue(4, 5, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedTimeSpanTicksOnly() {
			TimeSpan value = TimeSpan.FromTicks(59);
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckOptimizedTimeSpanTimeOnly() {
			TimeSpan value = new TimeSpan(21, 10, 0);
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanTimeAndSeconds() {
			TimeSpan value = new TimeSpan(0, 21, 10, 1);
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanTimeAndMilliseconds() {
			TimeSpan value = new TimeSpan(0, 21, 10, 1);
			value = value.Add(TimeSpan.FromMilliseconds(4));
			Writer.WriteOptimized(value);
			CheckValue(4, 5, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeDayAndSpanSecondsOnly() {
			TimeSpan value = TimeSpan.FromSeconds(30);
			value = value.Add(TimeSpan.FromDays(14));
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeDayAndSpanMinutesOnly() {
			TimeSpan value = TimeSpan.FromMinutes(59);
			value = value.Add(TimeSpan.FromDays(14));
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedTimeSpan());
		}

		[Test]
		public void CheckOptimizedTimeDayAndSpanHoursOnly() {
			TimeSpan value = TimeSpan.FromHours(23);
			value = value.Add(TimeSpan.FromDays(14));
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanDayAndMillisecondsOnly() {
			TimeSpan value = TimeSpan.FromMilliseconds(999);
			value = value.Add(TimeSpan.FromDays(14));
			Writer.WriteOptimized(value);
			CheckValue(5, 6, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanDayAndTimeOnly() {
			TimeSpan value = new TimeSpan(21, 10, 0);
			value = value.Add(TimeSpan.FromDays(14));
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanDayAndTimeAndSeconds() {
			TimeSpan value = new TimeSpan(0, 21, 10, 1);
			value = value.Add(TimeSpan.FromDays(140000));
			Writer.WriteOptimized(value);
			CheckValue(6, 7, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckOptimizedTimeSpanTimeDayAndMilliseconds() {
			TimeSpan value = new TimeSpan(0, 21, 10, 1);
			value = value.Add(TimeSpan.FromMilliseconds(4));
			value = value.Add(TimeSpan.FromDays(140000));
			Writer.WriteOptimized(value);
			CheckValue(7, 8, value, Reader.ReadOptimizedTimeSpan());
		}
		
		[Test]
		public void CheckGuid() {
			Guid value = Guid.NewGuid();
			Writer.Write(value);
			CheckValue(16, 17, value, Reader.ReadGuid());
		}
		
		[Test]
		public void CheckGuidAsEmpty() {
			Guid value = Guid.Empty;
			Writer.Write(value);
			CheckValue(16, 1, value, Reader.ReadGuid());
		}
		
		[Test]
		public void CheckCharArray() {
			Char[] value = new char[] {'a', 'b', 'c'};
			Writer.Write(value);
			CheckValue(5, 6, value, Reader.ReadCharArray());
		}
		
		[Test]
		public void CheckLargeCharArray() {
			Char[] value = new char[300];
			Writer.Write(value);
			CheckValue(303, 304, value, Reader.ReadCharArray());
		}
		
		[Test]
		public void CheckCharArrayAsNull() {
			Char[] value = null;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadCharArray());
		}
		
		#region ObjectArray
		[Test]
		public void CheckObjectArray() {
			// 1+2 1+5 1+8 1 1+16   + 1 for length
			object[] value = new object[] {(int) 132, "Fast", (double) 10.64, DateTime.MinValue, Guid.NewGuid()};
			Writer.Write(value);
			CheckValue(34, 34, value, Reader.ReadObjectArray());
		}

		[Test]
		public void CheckObjectArrayAsNull() {
			object[] value = null;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadObjectArray());
		}

		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedObjectArrayAsNull() {
			object[] value = null;
			Writer.WriteOptimized(value);
		}

		[Test]
		public void CheckObjectArrayAsEmpty() {
			object[] value = new object[0];
			Writer.Write(value);
			CheckValue(2, 2, value, Reader.ReadObjectArray());
		}

		[Test]
		public void CheckObjectArrayWithAllEmbeddedNulls() {
			object[] value = new object[20];
			Writer.Write(value);
			CheckValue(4, 4, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithAllEmbeddedDBNulls() {
			object[] value = new object[20]; for(int i = 0; i < value.Length; i++) value[i] = DBNull.Value;
			Writer.Write(value);
			CheckValue(4, 4, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithEmbeddedNullsAtEnd() {
			object[] value = new object[20]; 
			for(int i = 0; i < 10; i++) value[i] = i;
			Writer.Write(value);
			CheckValue(22, 22, value, Reader.ReadObjectArray());
		}

		[Test]
		public void CheckObjectArrayWithEmbeddedDBNullsAtEnd() {
			object[] value = new object[20]; for(int i = 0; i < value.Length; i++) value[i] = DBNull.Value;
			for(int i = 0; i < 10; i++) value[i] = i;
			Writer.Write(value);
			CheckValue(22, 22, value, Reader.ReadObjectArray());
		}

		[Test]
		public void CheckObjectArrayWithEmbeddedNullsAtStart() {
			object[] value = new object[20];
			for(int i = 10; i < 20; i++) value[i] = i - 10;
			Writer.Write(value);
			CheckValue(22, 22, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithEmbeddedDBNullsAtStart() {
			object[] value = new object[20]; for(int i = 0; i < value.Length; i++) value[i] = DBNull.Value;
			for(int i = 10; i < 20; i++) value[i] = i - 10;
			Writer.Write(value);
			CheckValue(22, 22, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithEmbeddedNullsInMiddle() {
			object[] value = new object[20];
			for(int i = 0; i < 5; i++) value[i] = i;
			for(int i = 15; i < 20; i++) value[i] = i;
			Writer.Write(value);
			CheckValue(22, 22, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithEmbeddedDBNullsInMiddle() {
			object[] value = new object[20]; for(int i = 0; i < value.Length; i++) value[i] = DBNull.Value;
			for(int i = 0; i < 5; i++) value[i] = i;
			for(int i = 15; i < 20; i++) value[i] = i;
			Writer.Write(value);
			CheckValue(22, 22, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithAllEmbeddedNullsExceptOneAtStart() {
			object[] value = new object[20];
			value[0] = 1;
			Writer.Write(value);
			CheckValue(5, 5, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithAllEmbeddedDBNullsExceptOneAtStart() {
			object[] value = new object[20]; for(int i = 0; i < value.Length; i++) value[i] = DBNull.Value;
			value[0] = 1;
			Writer.Write(value);
			CheckValue(5, 5, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithAllEmbeddedNullsExceptOneAtEnd() {
			object[] value = new object[20];
			value[19] = 1;
			Writer.Write(value);
			CheckValue(5, 5, value, Reader.ReadObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayWithAllEmbeddedDBNullsExceptOneAtEnd() {
			object[] value = new object[20]; for(int i = 0; i < value.Length; i++) value[i] = DBNull.Value;
			value[19] = 1;
			Writer.Write(value);
			CheckValue(5, 5, value, Reader.ReadObjectArray());
		}
		#endregion ObjectArray
		
		#region ObjectNotNullArray
		[Test]
		public void CheckOptimizedObjectArray() {
			// 1+2 1+5 1+8 1 1+16   + 1 for length
			object[] value = new object[] {(int) 132, "Fast", (double) 10.64, DateTime.MinValue, Guid.NewGuid()};
			Writer.WriteOptimized(value);
			CheckValue(33, 34, value, Reader.ReadOptimizedObjectArray());
		}

		[Test]
		public void CheckObjectArrayNotNullAsEmpty() {
			object[] value = new object[0];
			Writer.WriteOptimized(value);
			CheckValue(1, 2, value, Reader.ReadOptimizedObjectArray());
		}

		[Test]
		public void CheckObjectArrayNotNullWithAllEmbeddedNulls() {
			object[] value = new object[20];
			Writer.WriteOptimized(value);
			CheckValue(3, 4, value, Reader.ReadOptimizedObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayNotNullWithEmbeddedNullsAtEnd() {
			object[] value = new object[20];
			for(int i = 0; i < 10; i++) value[i] = i;
			Writer.WriteOptimized(value);
			CheckValue(21, 22, value, Reader.ReadOptimizedObjectArray());
		}

		[Test]
		public void CheckObjectArrayNotNullWithEmbeddedNullsAtStart() {
			object[] value = new object[20];
			for(int i = 10; i < 20; i++) value[i] = i - 10;
			Writer.WriteOptimized(value);
			CheckValue(21, 22, value, Reader.ReadOptimizedObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayNotNullWithEmbeddedNullsInMiddle() {
			object[] value = new object[20];
			for(int i = 0; i < 5; i++) value[i] = i;
			for(int i = 15; i < 20; i++) value[i] = i;
			Writer.WriteOptimized(value);
			CheckValue(21, 22, value, Reader.ReadOptimizedObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayNotNullWithAllEmbeddedNullsExceptOneAtStart() {
			object[] value = new object[20];
			value[0] = 1;
			Writer.WriteOptimized(value);
			CheckValue(4, 5, value, Reader.ReadOptimizedObjectArray());
		}
		
		[Test]
		public void CheckObjectArrayNotNullWithAllEmbeddedNullsExceptOneAtEnd() {
			object[] value = new object[20];
			value[19] = 1;
			Writer.WriteOptimized(value);
			CheckValue(4, 5, value, Reader.ReadOptimizedObjectArray());
		}
		#endregion ObjectArrayNotNull

		[Test]
		public void CheckByteArray() {
			Byte[] value = new Byte[] {10, 11, 12, 13, 14, 15};
			Writer.Write(value);
			CheckValue(8, 8, value, Reader.ReadByteArray());
		}

		[Test]
		public void CheckByteArrayAsNull() {
			Byte[] value = null;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadByteArray());
		}

		[Test]
		public void CheckByteArrayAsEmpty() {
			Byte[] value = new Byte[0];
			Writer.Write(value);
			CheckValue(2, 2, value, Reader.ReadByteArray());
		}

		[Test]
		public void CheckBitVector32()
		{
			BitVector32 value = new BitVector32();
			Writer.Write(value);
			CheckValue(4, 5, value, Reader.ReadBitVector32());
		}
		
		[Test]
		public void CheckBitVector32Optimized()
		{
			BitVector32 value = new BitVector32();
			Writer.WriteOptimized(value);
			CheckValue(1, 5, value, Reader.ReadOptimizedBitVector32());
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckBitVector32OptimizedWithTopBitSet()
		{
			BitVector32 value = new BitVector32(-1);
			Writer.WriteOptimized(value);
		}

		[Test]
		public void CheckArrayList()
		{
			ArrayList	value = new ArrayList();
			value.Add(123456);
			value.Add("ABC");
			Writer.Write(value);
			CheckObjectType(8, 8, value, Reader.ReadArrayList());
		}
		
		[Test]
		public void CheckArrayListNull()
		{
			ArrayList	value = null;
			Writer.Write(value);
			CheckValue(1, 1, value, Reader.ReadArrayList());
		}
		
		[Test]
		public void CheckArrayListEmpty()
		{
			ArrayList	value = new ArrayList();
			Writer.Write(value);
			CheckObjectType(2, 2, value, Reader.ReadArrayList());
		}
		
		[Test]
		public void CheckArrayListOptimized()
		{
			ArrayList	value = new ArrayList();
			value.Add(123456);
			value.Add("ABC");
			Writer.WriteOptimized(value);
			CheckObjectType(7, 8, value, Reader.ReadOptimizedArrayList());
		}

		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedArrayListNull()
		{
			ArrayList	value = null;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckOptimizedArrayListEmpty()
		{
			ArrayList	value = new ArrayList();
			Writer.WriteOptimized(value);
			CheckObjectType(1, 2, value, Reader.ReadOptimizedArrayList());
		}
		
		
		[Test]
		public void CheckObjectArrayPairAsAllNulls()
		{
			object[] values1 = new object[10];
			object[] values2 = new object[10];
			Writer.WriteOptimized(values1, values2);
			object[] newValues1, newValues2;
			Reader.ReadOptimizedObjectArrayPair(out newValues1, out newValues2);
			CheckValue(5, -1, values1, values1);
			CheckValue(-1, -1, values2, values2);
		}
		
		[Test]
		public void CheckObjectArrayPairAsAllDBNulls()
		{
			object[] values1 = new object[10];
			object[] values2 = new object[10];
			for(int i = 0; i < values1.Length; i++) values1[i] = values2[i] = DBNull.Value;
			Writer.WriteOptimized(values1, values2);
			object[] newValues1, newValues2;
			Reader.ReadOptimizedObjectArrayPair(out newValues1, out newValues2);
			CheckValue(5, -1, values1, values1);
			CheckValue(-1, -1, values2, values2);
		}
		
		[Test]
		public void CheckObjectArrayPairAsDifferentNullTypes()
		{
			object[] values1 = new object[10];
			object[] values2 = new object[10];
			for(int i = 0; i < values1.Length; i++) values1[i] = DBNull.Value;
			Writer.WriteOptimized(values1, values2);
			object[] newValues1, newValues2;
			Reader.ReadOptimizedObjectArrayPair(out newValues1, out newValues2);
			CheckValue(5, -1, values1, values1);
			CheckValue(-1, -1, values2, values2);
		}
		
		[Test]
		public void CheckObjectArrayPairAsSameValues()
		{
			object[] values1 = new object[10];
			object[] values2 = new object[10];
			for(int i = 0; i < values1.Length; i++) values1[i] = values2[i] = i + 20;
			Writer.WriteOptimized(values1, values2);
			object[] newValues1, newValues2;
			Reader.ReadOptimizedObjectArrayPair(out newValues1, out newValues2);
			CheckValue(31, -1, values1, values1);
			CheckValue(-1, -1, values2, values2);
		}
		
		[Test]
		public void CheckObjectArrayPairAsDifferentValues()
		{
			object[] values1 = new object[10];
			object[] values2 = new object[10];
			for(int i = 0; i < values1.Length; i++) { values1[i] = i + 20; values2[i] = i + 21;}
			Writer.WriteOptimized(values1, values2);
			object[] newValues1, newValues2;
			Reader.ReadOptimizedObjectArrayPair(out newValues1, out newValues2);
			CheckValue(41, -1, values1, values1);
			CheckValue(-1, -1, values2, values2);
		}
		
		[Test]
		public void CheckTypeAsNull()
		{
			Type value = null;
			Writer.Write(value, true);
			CheckValue(1, 1, value, Reader.ReadType());
		}
		
		[Test]
		public void CheckSystemTypeFullyQualified()
		{
			Type value = typeof(string);
			Writer.Write(value, true);
			CheckValue(3, 3, value, Reader.ReadType());
			Assert.AreEqual(104, writerLength);
			Assert.AreEqual(24, objectWriterLength);
		}
		
		[Test]
		public void CheckSystemTypeNotFullyQualified()
		{
			Type value = typeof(string);
			Writer.Write(value, false);
			CheckValue(3, 3, value, Reader.ReadType());
			Assert.AreEqual(24, writerLength);
			Assert.AreEqual(24, objectWriterLength);
		}
		
		[Test]
		public void CheckNonSystemTypeFullyQualified()
		{
			Type value = typeof(DataTable);
			Writer.Write(value, true);
			CheckValue(3, 3, value, Reader.ReadType());
			Assert.AreEqual(115, writerLength);
			Assert.AreEqual(115, objectWriterLength);
		}
		
		[Test, ExpectedException(typeof(TypeLoadException))]
		public void CheckNonSystemTypeNotFullyQualified()
		{
			Type value = typeof(DataTable);
			Writer.Write(value, false);
			CheckValue(3, 3, value, Reader.ReadType(true));
		}
		
		[Test]
		public void CheckSystemOptimizedType()
		{
			Type value = typeof(string);
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedType());
			Assert.AreEqual(23, writerLength);
			Assert.AreEqual(24, objectWriterLength);
		}
		
		[Test]
		public void CheckNonSystemOptimizedType()
		{
			Type value = typeof(DataTable);
			Writer.WriteOptimized(value);
			CheckValue(2, 3, value, Reader.ReadOptimizedType());
			Assert.AreEqual(114, writerLength);
			Assert.AreEqual(115, objectWriterLength);
		}
		
		[Test]
		public void CheckFactoryClass()
		{
			object value = new SampleFactoryClass();
			Writer.WriteTokenizedObject(value);
			object value1 = Reader.ReadTokenizedObject();
			Assert.IsFalse(value == value1);
			Assert.AreEqual(44 + value.GetType().AssemblyQualifiedName.Length, Reader.BaseStream.Length);
			
		}
		
		[Test]
		public void CheckFactoryClassMultipleTokens()
		{
			object value = new SampleFactoryClass();
			Writer.WriteTokenizedObject(value);
			Writer.WriteTokenizedObject(value);
			object value1 = Reader.ReadTokenizedObject();
			object value2 = Reader.ReadTokenizedObject();
			Assert.IsFalse(value == value1);
			Assert.AreSame(value1, value2);
			Assert.AreEqual(45 + value.GetType().AssemblyQualifiedName.Length, Reader.BaseStream.Length);
			
		}
	
		[Test]
		public void CheckFactoryClassAsType()
		{
			object value = new SampleFactoryClass();
			Writer.WriteTokenizedObject(value, true);
			object value1 = Reader.ReadTokenizedObject();
			Assert.IsFalse(value == value1);

			// This test gets around a .Net serialization feature where the size is off by *sometimes*
			int typeSize = (int) (Reader.BaseStream.Length - value.GetType().AssemblyQualifiedName.Length);
			Assert.IsTrue(typeSize == 9 || typeSize == 10);
			
		}
		
		[Test]
		public void CheckFactoryClassAsTypeMultipleTokens()
		{
			object value = new SampleFactoryClass();
			Writer.WriteTokenizedObject(value, true);
			Writer.WriteTokenizedObject(value, true);
			object value1 = Reader.ReadTokenizedObject();
			object value2 = Reader.ReadTokenizedObject();
			Assert.IsFalse(value == value1);
			Assert.AreSame(value1, value2);
			
			// This test gets around a .Net serialization feature where the size is off by *sometimes*
			int typeSize = (int) (Reader.BaseStream.Length - value.GetType().AssemblyQualifiedName.Length);
			Assert.IsTrue(typeSize == 10 || typeSize == 11);
			
		}

		[Test]
		public void CheckInt64OptimizedRange() {
			long value;
			
			value = 0; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 1; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 127; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			
			value = 128; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			value = 16383; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			
			value = 16384; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			value = 2097151; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			
			value = 2097152; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			value = 268435455; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			
			value = 268435456; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(5, Writer.BaseStream.Position);
			value = 34359738367; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(5, Writer.BaseStream.Position);
			
			value = 34359738368; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(6, Writer.BaseStream.Position);
			value = 4398046511103; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(6, Writer.BaseStream.Position);
			
			value = 4398046511104; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(7, Writer.BaseStream.Position);
			value = 562949953421311; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(7, Writer.BaseStream.Position);
			
			value = 562949953421312; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(8, Writer.BaseStream.Position);
			value = 72057594037927935; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(8, Writer.BaseStream.Position);
			
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt64OptimizedTooLowMin()
		{
			long value = long.MinValue;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt64OptimizedTooLow()
		{
			long value = -1;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt64OptimizedTooHigh()
		{
			long value = 72057594037927936;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt64OptimizedTooHighMax()
		{
			long value = long.MaxValue;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckUInt64OptimizedRange() {
			ulong value;
			
			value = ulong.MinValue; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 0; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 1; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 127; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			
			value = 128; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			value = 16383; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			
			value = 16384; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			value = 2097151; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			
			value = 2097152; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			value = 268435455; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			
			value = 268435456; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(5, Writer.BaseStream.Position);
			value = 34359738367; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(5, Writer.BaseStream.Position);
			
			value = 34359738368; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(6, Writer.BaseStream.Position);
			value = 4398046511103; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(6, Writer.BaseStream.Position);
			
			value = 4398046511104; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(7, Writer.BaseStream.Position);
			value = 562949953421311; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(7, Writer.BaseStream.Position);
			
			value = 562949953421312; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(8, Writer.BaseStream.Position);
			value = 72057594037927935; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(8, Writer.BaseStream.Position);
			
		}
	
		[Test, ExpectedException(typeof(OptimizationException))]
	  public void CheckUInt64OptimizedTooHigh()
		{
			ulong value = 72057594037927936;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
	  public void CheckUInt64OptimizedTooHighMax()
		{
			ulong value = ulong.MaxValue;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckInt32OptimizedRange() {
			int value;
			
			value = 0; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 1; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 127; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			
			value = 128; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			value = 16383; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			
			value = 16384; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			value = 2097151; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			
			value = 2097152; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			value = 268435455; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt32OptimizedTooLowMin()
		{
			int value = int.MinValue;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt32OptimizedTooLow()
		{
			int value = -1;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt32OptimizedTooHigh()
		{
			int value = 268435456;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckInt32OptimizedTooHighMax()
		{
			int value = int.MaxValue;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckUInt32OptimizedRange() {
			uint value;
			
			value = uint.MinValue; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 0; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 1; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			value = 127; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(1, Writer.BaseStream.Position);
			
			value = 128; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			value = 16383; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(2, Writer.BaseStream.Position);
			
			value = 16384; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			value = 2097151; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(3, Writer.BaseStream.Position);
			
			value = 2097152; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
			value = 268435455; Writer.BaseStream.Position = 0; Writer.WriteOptimized(value); Assert.AreEqual(4, Writer.BaseStream.Position);
		}

		[Test, ExpectedException(typeof(OptimizationException))]
	  public void CheckUInt32OptimizedTooHigh()
		{
			uint value = 268435456;
			Writer.WriteOptimized(value);
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
	  public void CheckUInt32OptimizedTooHighMax()
		{
			uint value = uint.MaxValue;
			Writer.WriteOptimized(value);
		}
		
		[Test]
		public void CheckOptimizedDateWithDateOnly()
		{
			DateTime value = new DateTime(2006, 9, 17);
			Writer.WriteOptimized(value);
			if (Writer.OptimizeForSize)
				CheckValue(3, 4, value, Reader.ReadOptimizedDateTime());
			else
			{
				CheckValue(3, 9, value, Reader.ReadOptimizedDateTime());
			}
		}
		
		[Test]
		public void CheckOptimizedDateWithDateHoursAndMinutes()
		{
			DateTime value = new DateTime(2006, 9, 17, 12, 20, 0);
			Writer.WriteOptimized(value);
			if (Writer.OptimizeForSize)
				CheckValue(5, 6, value, Reader.ReadOptimizedDateTime());
			else
			{
				CheckValue(5, 9, value, Reader.ReadOptimizedDateTime());
			}
		}
		
		[Test]
		public void CheckOptimizedDateWithDateHoursAndMinutesAndSeconds()
		{
			DateTime value = new DateTime(2006, 9, 17, 12, 20, 22);
			Writer.WriteOptimized(value);
			if (Writer.OptimizeForSize)
				CheckValue(6, 7, value, Reader.ReadOptimizedDateTime());
			else
			{
				CheckValue(6, 9, value, Reader.ReadOptimizedDateTime());
			}
		}
		
		[Test, ExpectedException(typeof(OptimizationException))]
		public void CheckOptimizedDateWithOddTicks()
		{
			DateTime value = new DateTime(2006, 9, 17, 12, 20, 22);
			value = value.AddTicks(1);
			Writer.WriteOptimized(value);
		}
		
		private void fixedStringSize(int count, int length)
		{
			Writer = new SerializationWriter();

			string format = "{0," + length + "}";
			for(int i = 0; i < count; i++)
			{
				Writer.Write(string.Format(format, i));
			}
			Assert.AreEqual(1 + (count + 127) / 128 + (count * (length + 1)) + 1, Writer.writeTokenTables(), string.Format("Failed for count={0}, length={1}", count, length));
			//Assert.AreEqual(1 + (count == 0 ? 0 : (count + 127) / 128) + (count * (length + 1)) + 1, Writer.writeTokenTables(), string.Format("Failed for count={0}, length={1}", count, length));
		}
		
		[Test]
		public void TestTokenizedStringsStartNewListBeforeTokenSizeIncreases()
		{
			fixedStringSize(0, 9);
			fixedStringSize(1, 9);
			fixedStringSize(2, 9);
			fixedStringSize(127, 9);
			fixedStringSize(128, 9);
			fixedStringSize(129, 9);
			fixedStringSize(255, 9);
			fixedStringSize(256, 9);
			fixedStringSize(257, 9);
			fixedStringSize(16383, 9);
			fixedStringSize(16384, 9);
			fixedStringSize(16385, 9);
		}
		
	}
	
	[Serializable]
	public class SampleFactoryClass {}

}
#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Software Developer (Senior) Hunton Information Systems Ltd.
United Kingdom United Kingdom
Simon Hewitt is a freelance IT consultant and is MD of Hunton Information Systems Ltd.

He is currently looking for contract work in London.

He is happily married to Karen (originally from Florida, US), has a lovely daughter Bailey, and they live in Kings Langley, Hertfordshire, UK.

Comments and Discussions