Browse Source

Add System.IO.Compression from Chris Lahey ([email protected])

svn path=/trunk/mcs/; revision=34610
Miguel de Icaza 21 years ago
parent
commit
ff0d74eeb5

+ 5 - 0
mcs/class/System/System.IO.Compression/ChangeLog

@@ -0,0 +1,5 @@
+2004-10-02  Christopher Lahey ([email protected])
+
+	* DeflateStream.cs GzipStream.cs: Implemented the DeflateStream
+	and GzipStream using zlib.
+

+ 20 - 0
mcs/class/System/System.IO.Compression/CompressionMode.cs

@@ -0,0 +1,20 @@
+/* -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+// 
+// CompressionMOode.cs
+//
+// Authors:
+//	Christopher James Lahey <[email protected]>
+//
+// (c) 2004 Novell, Inc. (http://www.novell.com)
+//
+
+#if NET_2_0
+
+namespace System.IO.Compression {
+	enum CompressionMode {
+		Decompress=0,	// Decompress the given stream.
+		Compress=1	// Compress the given stream.
+	};
+}
+
+#endif

+ 403 - 0
mcs/class/System/System.IO.Compression/DeflateStream.cs

@@ -0,0 +1,403 @@
+/* -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+// 
+// DeflateStream.cs
+//
+// Authors:
+//	Christopher James Lahey <[email protected]>
+//
+// (c) 2004 Novell, Inc. <http://www.novell.com>
+//
+
+#if NET_2_0
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting.Messaging;
+
+namespace System.IO.Compression {
+	class DeflateStream : Stream
+	{
+		private Stream compressedStream;
+		private CompressionMode mode;
+		private bool leaveOpen;
+		private bool open;
+		private IntPtr z_stream;
+
+		private const int BUFFER_SIZE = 4096;
+		private IntPtr sized_buffer;
+		static int bytes_read = 0;
+		private bool finished = false;
+		private enum ZReturnConsts {
+			Z_OK = 0,
+			Z_STREAM_END = 1,
+			Z_NEED_DICT = 2,
+			Z_STREAM_ERROR = -2,
+			Z_DATA_ERROR = -3,
+			Z_MEM_ERROR = -4,
+			Z_BUF_ERROR = -5,
+		}
+		private enum ZFlushConsts {
+			Z_NO_FLUSH     = 0,
+			Z_PARTIAL_FLUSH = 1, /* will be removed, use Z_SYNC_FLUSH instead */
+			Z_SYNC_FLUSH    = 2,
+			Z_FULL_FLUSH    = 3,
+			Z_FINISH        = 4,
+			Z_BLOCK         = 5,
+		};
+
+
+		[DllImport("MonoPosixHelper")]
+		static extern IntPtr create_z_stream(CompressionMode compress, bool gzip);
+		[DllImport("MonoPosixHelper")]
+		static extern void free_z_stream(IntPtr z_stream);
+		[DllImport("MonoPosixHelper")]
+		static extern void z_stream_set_next_in(IntPtr z_stream, IntPtr next_in);
+		[DllImport("MonoPosixHelper")]
+		static extern void z_stream_set_avail_in(IntPtr z_stream, int avail_in);
+		[DllImport("MonoPosixHelper")]
+		static extern int z_stream_get_avail_in(IntPtr z_stream);
+		[DllImport("MonoPosixHelper")]
+		static extern void z_stream_set_next_out(IntPtr z_stream, IntPtr next_out);
+		[DllImport("MonoPosixHelper")]
+		static extern void z_stream_set_avail_out(IntPtr z_stream, int avail_out);
+		[DllImport("MonoPosixHelper")]
+		static extern ZReturnConsts z_stream_inflate(IntPtr z_stream, ref int avail_out);
+		[DllImport("MonoPosixHelper")]
+		static extern ZReturnConsts z_stream_deflate(IntPtr z_stream, ZFlushConsts flush, IntPtr next_out, ref int avail_out);
+
+		delegate int  ReadMethod (byte[] array, int offset, int count);
+		delegate void WriteMethod(byte[] array, int offset, int count);
+
+		internal DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen, bool gzip) {
+			this.compressedStream = compressedStream;
+			this.mode = mode;
+			this.leaveOpen = leaveOpen;
+			this.sized_buffer = Marshal.AllocHGlobal (BUFFER_SIZE);
+			this.z_stream = create_z_stream (mode, gzip);
+			if (z_stream == IntPtr.Zero) {
+				throw new OutOfMemoryException ();
+			}
+			this.open = true;
+			if (mode == CompressionMode.Compress) {
+				Flush();
+			}
+		}
+
+		public DeflateStream (Stream compressedStream, CompressionMode mode) :
+			this (compressedStream, mode, false, false) { }
+
+		public DeflateStream (Stream compressedStream, CompressionMode mode, bool leaveOpen) :
+			this (compressedStream, mode, leaveOpen, false) { }
+
+		~DeflateStream () {
+			Marshal.FreeHGlobal (sized_buffer);
+		}
+
+		public override void Close () {
+			FlushInternal (true);
+
+			if (mode == CompressionMode.Decompress && compressedStream.CanSeek) {
+				int avail_in = z_stream_get_avail_in (z_stream);
+				if (avail_in != 0) {
+					compressedStream.Seek (- avail_in, SeekOrigin.Current);
+					z_stream_set_avail_in (z_stream, 0);
+				}
+			}
+
+			free_z_stream (z_stream);
+			z_stream = IntPtr.Zero;
+
+			if (!leaveOpen) {
+				compressedStream.Close();
+			}
+
+			open = false;
+		}
+
+		private int ReadInternal(byte[] array, int offset, int count) {
+
+			int buffer_size;
+			if (finished)
+				return 0;
+
+			if (compressedStream.CanSeek)
+				buffer_size = BUFFER_SIZE;
+			else
+				buffer_size = 1;
+
+			IntPtr buffer = Marshal.AllocHGlobal(count);
+			try {
+				int avail_out;
+
+				avail_out = count;
+				z_stream_set_next_out (z_stream, buffer);
+
+				while (avail_out != 0 && !finished) {
+					if (z_stream_get_avail_in (z_stream) == 0) {
+						byte[] read_buf = new byte[buffer_size];
+						int length_read = compressedStream.Read (read_buf, 0, buffer_size);
+						bytes_read += length_read;
+						if (length_read == 0) {
+							break;
+						}
+						Marshal.Copy (read_buf, 0, sized_buffer, length_read);
+						z_stream_set_next_in (z_stream, sized_buffer);
+						z_stream_set_avail_in (z_stream, length_read);
+					}
+					ZReturnConsts ret_val = z_stream_inflate(z_stream, ref avail_out);
+					switch (ret_val) {
+					case ZReturnConsts.Z_OK:
+						break;
+					case ZReturnConsts.Z_STREAM_END:
+						finished = true;
+						break;
+					case ZReturnConsts.Z_NEED_DICT:
+						throw new InvalidDataException ("ZLib stream requires a dictionary.");
+					case ZReturnConsts.Z_DATA_ERROR:
+						throw new InvalidDataException ("Invalid ZLib data.");
+					case ZReturnConsts.Z_STREAM_ERROR:
+						throw new InvalidOperationException ("Internal DeflateStream error.");
+					case ZReturnConsts.Z_MEM_ERROR:
+						throw new OutOfMemoryException ();
+					case ZReturnConsts.Z_BUF_ERROR:
+						throw new InvalidOperationException ("Internal DeflateStream error: Buf error.");
+					}
+				}
+				if (count != avail_out)
+					Marshal.Copy (buffer, array, offset, count - avail_out);
+				return count - avail_out; 
+			} finally {
+				Marshal.FreeHGlobal(buffer);
+			}
+		}
+
+		public override int Read (byte[] dest, int dest_offset, int count)
+		{
+			if (dest == null)
+				throw new ArgumentNullException ("Destination array is null.");
+			if (!CanRead)
+				throw new NotSupportedException ("Stream does not support reading.");
+			int len = dest.Length;
+			if (dest_offset < 0 || count < 0)
+				throw new ArgumentException ("Dest or count is negative.");
+			if (dest_offset > len)
+				throw new ArgumentException ("destination offset is beyond array size");
+			if ((dest_offset + count) > len)
+				throw new ArgumentException ("Reading would overrun buffer");
+
+			return ReadInternal (dest, dest_offset, count);
+		}
+
+
+		private ZReturnConsts do_deflate (ZFlushConsts flush, out int avail_out) {
+			avail_out = BUFFER_SIZE;
+			ZReturnConsts ret_val = z_stream_deflate (z_stream, flush, sized_buffer, ref avail_out);
+			switch (ret_val) {
+			case ZReturnConsts.Z_STREAM_ERROR:
+				throw new InvalidOperationException ("Internal error.");
+			case ZReturnConsts.Z_MEM_ERROR:
+				throw new InvalidOperationException ("Memory error.");
+			}
+			return ret_val;
+		}
+
+		private void WriteInternal(byte[] array, int offset, int count) {
+			IntPtr buffer = Marshal.AllocHGlobal(count);
+			try {
+				int avail_in;
+
+				avail_in = count;
+
+				Marshal.Copy (array, offset, buffer, count);
+				z_stream_set_next_in (z_stream, buffer);
+				z_stream_set_avail_in (z_stream, avail_in);
+				while (avail_in != 0) {
+					int avail_out;
+				
+					do_deflate (ZFlushConsts.Z_NO_FLUSH, out avail_out);
+
+					if (avail_out != BUFFER_SIZE) {
+						byte[] output = new byte[BUFFER_SIZE - avail_out];
+						Marshal.Copy (sized_buffer, output, 0, BUFFER_SIZE - avail_out);
+						compressedStream.Write(output, 0, BUFFER_SIZE - avail_out);
+					}
+
+					avail_in = z_stream_get_avail_in (z_stream);
+				}
+			} finally {
+				Marshal.FreeHGlobal(buffer);
+			}
+		}
+
+		public override void Write (byte[] src, int src_offset, int count)
+		{
+			if (src == null)
+				throw new ArgumentNullException ("src");
+
+			if (src_offset < 0)
+				throw new ArgumentOutOfRangeException ("src_offset");
+
+			if (count < 0)
+				throw new ArgumentOutOfRangeException ("count");
+
+			if (!CanWrite)
+				throw new NotSupportedException ("Stream does not support writing");
+
+			WriteInternal (src, src_offset, count);
+		}
+
+		private void FlushInternal (bool finish) {
+			int avail_out;
+			ZReturnConsts ret_val;
+
+			if (!(open && mode == CompressionMode.Compress && compressedStream.CanWrite))
+				return;
+
+			z_stream_set_next_in (z_stream, IntPtr.Zero);
+			z_stream_set_avail_in (z_stream, 0);
+
+			while (true) {
+				ret_val = do_deflate (finish ? ZFlushConsts.Z_FINISH : ZFlushConsts.Z_SYNC_FLUSH, out avail_out);
+
+				if (BUFFER_SIZE != avail_out) {
+					byte[] output = new byte[BUFFER_SIZE - avail_out];
+					Marshal.Copy (sized_buffer, output, 0, BUFFER_SIZE - avail_out);
+					compressedStream.Write(output, 0, BUFFER_SIZE - avail_out);
+				} else {
+					if (!finish)
+						break;
+				}
+				if (ret_val == ZReturnConsts.Z_STREAM_END)
+					break;
+			}
+
+			compressedStream.Flush();
+		}
+
+		public override void Flush () {
+			FlushInternal (false);
+		}
+
+		public override long Seek (long offset, SeekOrigin origin) {
+			throw new System.NotSupportedException();
+		}
+
+		public override void SetLength (long value) {
+			throw new System.NotSupportedException();
+		}
+
+		public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
+							AsyncCallback cback, object state)
+		{
+			if (!CanRead)
+				throw new NotSupportedException ("This stream does not support reading");
+
+			if (buffer == null)
+				throw new ArgumentNullException ("buffer");
+
+			if (count < 0)
+				throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
+
+			if (offset < 0)
+				throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
+
+			if (count + offset > buffer.Length)
+				throw new ArgumentException ("Buffer too small. count/offset wrong.");
+
+			ReadMethod r = new ReadMethod (ReadInternal);
+			return r.BeginInvoke (buffer, offset, count, cback, state);
+		}
+
+		public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
+							AsyncCallback cback, object state)
+		{
+			if (!CanWrite)
+				throw new NotSupportedException ("This stream does not support writing");
+
+			if (buffer == null)
+				throw new ArgumentNullException ("buffer");
+
+			if (count < 0)
+				throw new ArgumentOutOfRangeException ("count", "Must be >= 0");
+
+			if (offset < 0)
+				throw new ArgumentOutOfRangeException ("offset", "Must be >= 0");
+
+			if (count + offset > buffer.Length)
+				throw new ArgumentException ("Buffer too small. count/offset wrong.");
+
+			WriteMethod w = new WriteMethod (WriteInternal);
+			return w.BeginInvoke (buffer, offset, count, cback, state);			
+		}
+
+		public override int EndRead(IAsyncResult async_result) {
+			if (async_result == null)
+				throw new ArgumentNullException ("async_result");
+
+			AsyncResult ares = async_result as AsyncResult;
+			if (ares == null)
+				throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+			ReadMethod r = ares.AsyncDelegate as ReadMethod;
+			if (r == null)
+				throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+			return r.EndInvoke (async_result);
+		}
+
+		public override void EndWrite (IAsyncResult async_result)
+		{
+			if (async_result == null)
+				throw new ArgumentNullException ("async_result");
+
+			AsyncResult ares = async_result as AsyncResult;
+			if (ares == null)
+				throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+			WriteMethod w = ares.AsyncDelegate as WriteMethod;
+			if (w == null)
+				throw new ArgumentException ("Invalid IAsyncResult", "async_result");
+
+			w.EndInvoke (async_result);
+			return;
+		}
+
+		public Stream BaseStream {
+			get {
+				return compressedStream;
+			}
+		}
+		public override bool CanRead {
+			get {
+				return open && mode == CompressionMode.Decompress && compressedStream.CanRead;
+			}
+		}
+		public override bool CanSeek {
+			get {
+				return false;
+			}
+		}
+		public override bool CanWrite {
+			get {
+				return open && mode == CompressionMode.Compress && compressedStream.CanWrite;
+			}
+		}
+		public override long Length {
+			get {
+				throw new System.NotSupportedException();
+			}
+			set {
+				throw new System.NotSupportedException();
+			}
+		}
+		public override long Position {
+			get {
+				throw new System.NotSupportedException();
+			}
+			set {
+				throw new System.NotSupportedException();
+			}
+		}
+	}
+}
+#endif

+ 117 - 0
mcs/class/System/System.IO.Compression/GzipStream.cs

@@ -0,0 +1,117 @@
+/* -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+// 
+// GzipStream.cs
+//
+// Authors:
+//	Christopher James Lahey <[email protected]>
+//
+// (c) 2004 Novell, Inc. <http://www.novell.com>
+//
+
+#if NET_2_0
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting.Messaging;
+
+namespace System.IO.Compression {
+	class GzipStream : Stream
+	{
+		private DeflateStream deflateStream;
+
+		public GzipStream (Stream compressedStream, CompressionMode mode) :
+			this (compressedStream, mode, false) {
+		}
+
+		public GzipStream (Stream compressedStream, CompressionMode mode, bool leaveOpen) {
+			this.deflateStream = new DeflateStream (compressedStream, mode, leaveOpen, true);
+		}
+
+		public override void Close () {
+			deflateStream.Close();
+		}
+
+		public override int Read (byte[] dest, int dest_offset, int count)
+		{
+			return deflateStream.Read(dest, dest_offset, count);
+		}
+
+
+		public override void Write (byte[] src, int src_offset, int count)
+		{
+			deflateStream.Write (src, src_offset, count);
+		}
+
+		public override void Flush() {
+			deflateStream.Flush();
+		}
+
+		public override long Seek (long offset, SeekOrigin origin) {
+			return deflateStream.Seek (offset, origin);
+		}
+
+		public override void SetLength (long value) {
+			deflateStream.SetLength (value);
+		}
+
+		public override IAsyncResult BeginRead (byte [] buffer, int offset, int count,
+							AsyncCallback cback, object state)
+		{
+			return deflateStream.BeginRead (buffer, offset, count, cback, state);
+		}
+
+		public override IAsyncResult BeginWrite (byte [] buffer, int offset, int count,
+							AsyncCallback cback, object state)
+		{
+			return deflateStream.BeginWrite (buffer, offset, count, cback, state);
+		}
+
+		public override int EndRead(IAsyncResult async_result) {
+			return deflateStream.EndRead (async_result);
+		}
+
+		public override void EndWrite (IAsyncResult async_result)
+		{
+			deflateStream.EndWrite (async_result);
+		}
+
+		public Stream BaseStream {
+			get {
+				return deflateStream.BaseStream;
+			}
+		}
+		public override bool CanRead {
+			get {
+				return deflateStream.CanRead;
+			}
+		}
+		public override bool CanSeek {
+			get {
+				return deflateStream.CanSeek;
+			}
+		}
+		public override bool CanWrite {
+			get {
+				return deflateStream.CanWrite;
+			}
+		}
+		public override long Length {
+			get {
+				return deflateStream.Length;
+			}
+			set {
+				deflateStream.Length = value;
+			}
+		}
+		public override long Position {
+			get {
+				return deflateStream.Position;
+			}
+			set {
+				deflateStream.Position = value;
+			}
+		}
+	}
+}
+
+#endif

+ 4 - 0
mcs/class/System/System.dll.sources

@@ -446,6 +446,9 @@ System.IO/SearchPattern.cs
 System.IO/WaitForChangedResult.cs
 System.IO/WatcherChangeTypes.cs
 System.IO/WindowsWatcher.cs
+System.IO.Compression/CompressionMode.cs
+System.IO.Compression/DeflateStream.cs
+System.IO.Compression/GzipStream.cs
 System.Net/AuthenticationManager.cs
 System.Net/Authorization.cs
 System.Net/BasicClient.cs
@@ -623,6 +626,7 @@ System.Timers/TimersDescriptionAttribute.cs
 System.Web/AspNetHostingPermission.cs
 System.Web/AspNetHostingPermissionAttribute.cs
 System.Web/AspNetHostingPermissionLevel.cs
+System/InvalidDataException.cs
 System/SRDescriptionAttribute.cs
 System/TODOAttribute.cs
 System/UriBuilder.cs

+ 49 - 0
mcs/class/System/System/InvalidDataException.cs

@@ -0,0 +1,49 @@
+//
+// System.InvalidDataException.cs
+//
+// Authors:
+//   Christopher James Lahey <[email protected]>
+//   Andreas Nahr ([email protected])
+//
+// (C) 2004 Novell, Inc.  http://www.novell.com
+//
+
+#if NET_2_0
+
+using System.Globalization;
+using System.Runtime.Serialization;
+
+namespace System
+{
+	[Serializable]
+	public class InvalidDataException : SystemException
+	{
+		const int Result = unchecked ((int)0x80131503);
+
+		// Constructors
+		public InvalidDataException ()
+			: base (Locale.GetText ("Invalid data format."))
+		{
+			HResult = Result;
+		}
+
+		public InvalidDataException (string message)
+			: base (message)
+		{
+			HResult = Result;
+		}
+
+		public InvalidDataException (string message, Exception innerException)
+			: base (message, innerException)
+		{
+			HResult = Result;
+		}
+
+		protected InvalidDataException (SerializationInfo info, StreamingContext context)
+			: base (info, context)
+		{
+		}
+	}
+}
+
+#endif

+ 2 - 0
mcs/class/System/System_test.dll.sources

@@ -28,6 +28,8 @@ System.Diagnostics/EventLogPermissionTest.cs
 System.Diagnostics/PerformanceCounterPermissionAttributeTest.cs
 System.Diagnostics/PerformanceCounterPermissionTest.cs
 System.IO/FileSystemWatcherTest.cs
+System.IO.Compression/DeflateStreamTest.cs
+System.IO.Compression/GzipStreamTest.cs
 System.Net/CookieCollectionTest.cs
 System.Net/CookieTest.cs
 System.Net/CredentialCacheTest.cs

+ 203 - 0
mcs/class/System/Test/System.IO.Compression/DeflateStreamTest.cs

@@ -0,0 +1,203 @@
+/* -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+//
+// DeflateStreamTest.cs - NUnit Test Cases for the System.IO.Compression.DeflateStream class
+//
+// Authors:
+// 	Christopher James Lahey  <[email protected]>
+//
+// (C) 2004 Novell, Inc. <http://www.novell.com>
+// 
+
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.IO.Compression;
+
+namespace MonoTests.System.IO.Compression
+{
+	[TestFixture]
+	public class DeflateStreamTest : Assertion
+	{
+		private static void CopyStream (Stream src, Stream dest)
+		{
+			byte[] array = new byte[1024];
+			int bytes_read;
+			bytes_read = src.Read (array, 0, 1024);
+			while (bytes_read != 0) {
+				dest.Write (array, 0, bytes_read);
+				bytes_read = src.Read (array, 0, 1024);
+			}
+		}
+
+		private static bool compare_buffers (byte[] first, byte[] second, int length)
+		{
+			if (first.Length < length || second.Length < length) {
+				return false;
+			}
+			for (int i = 0; i < length; i++) {
+				if (first[i] != second[i]) {
+					return false;
+				}
+			}
+			return true;
+		}
+
+		[Test]
+		public void CheckCompressDecompress () {
+			byte [] data = new byte[100000];
+			for (int i = 0; i < 100000; i++) {
+				data[i] = (byte) i;
+			}
+			MemoryStream dataStream = new MemoryStream (data);
+			MemoryStream backing = new MemoryStream ();
+			DeflateStream compressing = new DeflateStream (backing, CompressionMode.Compress, true);
+			CopyStream (dataStream, compressing);
+			dataStream.Close();
+			compressing.Close();
+			backing.Seek (0, SeekOrigin.Begin);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			MemoryStream output = new MemoryStream ();
+			CopyStream (decompressing, output);
+			Assert (compare_buffers (data, output.GetBuffer(), (int) output.Length));
+			decompressing.Close();
+			output.Close();
+		}
+
+		[Test]
+		public void CheckDecompress () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			StreamReader reader = new StreamReader (decompressing);
+			AssertEquals (reader.ReadLine (), "Hello");
+			decompressing.Close();
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentNullException))]
+		public void CheckNullRead () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			decompressing.Read (null, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (InvalidOperationException))]
+		public void CheckCompressingRead () {
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream ();
+			DeflateStream compressing = new DeflateStream (backing, CompressionMode.Compress);
+			compressing.Read (dummy, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentNullException))]
+		public void CheckRangeRead () {
+			byte [] data = {0x11, 0x78, 0x89, 0x91, 0xbe, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Read (dummy, 10, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (InvalidDataException))]
+		public void CheckInvalidDataRead () {
+			byte [] data = {0x11, 0x78, 0x89, 0x91, 0xbe, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			decompressing.Read (dummy, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ObjectDisposedException))]
+		public void CheckClosedRead () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			decompressing.Close ();
+			decompressing.Read (dummy, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ObjectDisposedException))]
+		public void CheckClosedFlush () {
+			MemoryStream backing = new MemoryStream ();
+			DeflateStream compressing = new DeflateStream (backing, CompressionMode.Compress);
+			compressing.Close ();
+			compressing.Flush ();
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckSeek () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			decompressing.Seek (20, SeekOrigin.Current);
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckSetLength () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			decompressing.SetLength (20);
+		}
+
+		[Test]
+		public void CheckGetCanSeekProp () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			AssertEquals (decompressing.CanSeek, false);
+		}
+
+		[Test]
+		public void CheckGetCanReadProp () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			AssertEquals (decompressing.CanRead, true);
+		}
+
+		[Test]
+		public void CheckGetCanWriteProp () {
+			MemoryStream backing = new MemoryStream ();
+			DeflateStream compressing = new DeflateStream (backing, CompressionMode.Decompress);
+			AssertEquals (compressing.CanWrite, true);
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckSetLengthProp () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			decompressing.Length = 20;
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckGetLengthProp () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			int length = decompressing.Length;
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckGetPositionProp () {
+			byte [] data = {0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			DeflateStream decompressing = new DeflateStream (backing, CompressionMode.Decompress);
+			int position = decompressing.Position;
+		}
+	}
+}
+

+ 203 - 0
mcs/class/System/Test/System.IO.Compression/GzipStreamTest.cs

@@ -0,0 +1,203 @@
+/* -*- Mode: csharp; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+//
+// GzipStreamTest.cs - NUnit Test Cases for the System.IO.Compression.GzipStream class
+//
+// Authors:
+// 	Christopher James Lahey  <[email protected]>
+//
+// (C) 2004 Novell, Inc. <http://www.novell.com>
+// 
+
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.IO.Compression;
+
+namespace MonoTests.System.IO.Compression
+{
+	[TestFixture]
+	public class GzipStreamTest : Assertion
+	{
+		private static void CopyStream (Stream src, Stream dest)
+		{
+			byte[] array = new byte[1024];
+			int bytes_read;
+			bytes_read = src.Read (array, 0, 1024);
+			while (bytes_read != 0) {
+				dest.Write (array, 0, bytes_read);
+				bytes_read = src.Read (array, 0, 1024);
+			}
+		}
+
+		private static bool compare_buffers (byte[] first, byte[] second, int length)
+		{
+			if (first.Length < length || second.Length < length) {
+				return false;
+			}
+			for (int i = 0; i < length; i++) {
+				if (first[i] != second[i]) {
+					return false;
+				}
+			}
+			return true;
+		}
+
+		[Test]
+		public void CheckCompressDecompress () {
+			byte [] data = new byte[100000];
+			for (int i = 0; i < 100000; i++) {
+				data[i] = (byte) i;
+			}
+			MemoryStream dataStream = new MemoryStream (data);
+			MemoryStream backing = new MemoryStream ();
+			GzipStream compressing = new GzipStream (backing, CompressionMode.Compress, true);
+			CopyStream (dataStream, compressing);
+			dataStream.Close();
+			compressing.Close();
+			backing.Seek (0, SeekOrigin.Begin);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			MemoryStream output = new MemoryStream ();
+			CopyStream (decompressing, output);
+			Assert (compare_buffers (data, output.GetBuffer(), (int) output.Length));
+			decompressing.Close();
+			output.Close();
+		}
+
+		[Test]
+		public void CheckDecompress () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			StreamReader reader = new StreamReader (decompressing);
+			AssertEquals (reader.ReadLine (), "Hello");
+			decompressing.Close();
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentNullException))]
+		public void CheckNullRead () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Read (null, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (InvalidOperationException))]
+		public void CheckCompressingRead () {
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream ();
+			GzipStream compressing = new GzipStream (backing, CompressionMode.Compress);
+			compressing.Read (dummy, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentNullException))]
+		public void CheckRangeRead () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Read (dummy, 10, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (InvalidDataException))]
+		public void CheckInvalidDataRead () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0x11, 0x78, 0x89, 0x91, 0xbe, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Read (dummy, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ObjectDisposedException))]
+		public void CheckClosedRead () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			byte [] dummy = new byte[20];
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Close ();
+			decompressing.Read (dummy, 0, 20);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ObjectDisposedException))]
+		public void CheckClosedFlush () {
+			MemoryStream backing = new MemoryStream ();
+			GzipStream compressing = new GzipStream (backing, CompressionMode.Compress);
+			compressing.Close ();
+			compressing.Flush ();
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckSeek () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Seek (20, SeekOrigin.Current);
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckSetLength () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.SetLength (20);
+		}
+
+		[Test]
+		public void CheckGetCanSeekProp () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			AssertEquals (decompressing.CanSeek, false);
+		}
+
+		[Test]
+		public void CheckGetCanReadProp () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			AssertEquals (decompressing.CanRead, true);
+		}
+
+		[Test]
+		public void CheckGetCanWriteProp () {
+			MemoryStream backing = new MemoryStream ();
+			GzipStream compressing = new GzipStream (backing, CompressionMode.Decompress);
+			AssertEquals (compressing.CanWrite, true);
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckSetLengthProp () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			decompressing.Length = 20;
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckGetLengthProp () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			int length = decompressing.Length;
+		}
+
+		[Test]
+		[ExpectedException (typeof (NotSupportedException))]
+		public void CheckGetPositionProp () {
+			byte [] data = {0x1f, 0x8b, 0x08, 0x08, 0x70, 0xbb, 0x5d, 0x41, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x00, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0xe7, 0x02, 0x00, 0x16, 0x35, 0x96, 0x31, 0x06, 0x00, 0x00, 0x00 };
+			MemoryStream backing = new MemoryStream (data);
+			GzipStream decompressing = new GzipStream (backing, CompressionMode.Decompress);
+			int position = decompressing.Position;
+		}
+	}
+}
+