merge r67228-r67235, r67237, r67251 and r67256-67259 to trunk (they are
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / HashAlgorithmTest.cs
index 3c9eaa4a3d78ec7401775bf0b1bc376aea576bf8..3f1278e5e328f42f9c1d4c9bf7659520399e5539 100644 (file)
@@ -2,9 +2,29 @@
 // HashAlgorithmTest.cs - NUnit Test Cases for HashAlgorithm
 //
 // Author:
-//     Sebastien Pouliot (spouliot@motus.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004, 2006 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
 using NUnit.Framework;
@@ -13,21 +33,21 @@ using System.IO;
 using System.Security.Cryptography;
 using System.Text;
 
-namespace MonoTests.System.Security.Cryptography
-{
+namespace MonoTests.System.Security.Cryptography {
 
 // HashAlgorithm is a abstract class - so most of it's functionality wont
 // be tested here (but will be in its descendants).
-public class HashAlgorithmTest : TestCase {
+
+[TestFixture]
+public class HashAlgorithmTest : Assertion {
        protected HashAlgorithm hash;
 
-       protected override void SetUp () 
+       [SetUp]
+       protected virtual void SetUp () 
        {
                hash = HashAlgorithm.Create ();
        }
 
-       protected override void TearDown () {}
-
        public void AssertEquals (string msg, byte[] array1, byte[] array2) 
        {
                AllTests.AssertEquals (msg, array1, array2);
@@ -43,7 +63,8 @@ public class HashAlgorithmTest : TestCase {
        private const string defaultSHA512 = "System.Security.Cryptography.SHA512Managed";
        private const string defaultHash = defaultSHA1;
 
-       public virtual void TestCreate () 
+       [Test]
+       public virtual void Create () 
        {
                // try the default hash algorithm (created in SetUp)
                AssertEquals( "HashAlgorithm.Create()", defaultHash, hash.ToString());
@@ -87,53 +108,377 @@ public class HashAlgorithmTest : TestCase {
                // try to build invalid implementation
                hash = HashAlgorithm.Create ("InvalidHash");
                AssertNull ("HashAlgorithm.Create('InvalidHash')", hash);
+       }
 
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public virtual void CreateNull () 
+       {
                // try to build null implementation
-               try {
-                       hash = HashAlgorithm.Create (null);
-                       Fail ("HashAlgorithm.Create(null) should throw ArgumentNullException");
-               }
-               catch (ArgumentNullException) {
-                       // do nothing, this is what we expect
-               }
-               catch (Exception e) {
-                       Fail ("HashAlgorithm.Create(null) should throw ArgumentNullException not " + e.ToString() );
-               }
+               hash = HashAlgorithm.Create (null);
        }
 
-       public void TestClear () 
+       [Test]
+       [ExpectedException (typeof (ObjectDisposedException))]
+       public void Clear () 
        {
                byte[] inputABC = Encoding.Default.GetBytes ("abc");
                hash.ComputeHash (inputABC);
                hash.Clear ();
                // cannot use a disposed object
-               try {
-                       hash.ComputeHash (inputABC);
-                       Fail ("ComputeHash after clear should throw ObjectDisposedException but didn't");
+               hash.ComputeHash (inputABC);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ObjectDisposedException))]
+       public void Clear2 () 
+       {
+               byte[] inputABC = Encoding.Default.GetBytes ("abc");
+               MemoryStream ms = new MemoryStream (inputABC);
+               hash.ComputeHash (ms);
+               hash.Clear ();
+               // cannot use a disposed object
+               hash.ComputeHash (ms);
+       }
+
+       [Test]
+       [ExpectedException (typeof (NullReferenceException))]
+       public void NullStream () 
+       {
+               Stream s = null;
+               byte[] result = hash.ComputeHash (s);
+       }
+
+       [Test]
+       public void Disposable () 
+       {
+               using (HashAlgorithm hash = HashAlgorithm.Create ()) {
+                       byte[] data = hash.ComputeHash (new byte [0]);
                }
-               catch (ObjectDisposedException) {
-                       // do nothing, this is what we expect
+       }
+
+       [Test]
+       [ExpectedException (typeof (ObjectDisposedException))]
+       public void InitializeDisposed () 
+       {
+               hash.ComputeHash (new byte [0]);
+               hash.Clear (); // disposed
+               hash.Initialize ();
+               hash.ComputeHash (new byte [0]);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void ComputeHash_ArrayNull ()
+       {
+               byte[] array = null;
+               hash.ComputeHash (array);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void ComputeHash_ArrayNullIntInt ()
+       {
+               byte[] array = null;
+               hash.ComputeHash (array, 0, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void ComputeHash_OffsetNegative ()
+       {
+               byte[] array = new byte [0];
+               hash.ComputeHash (array, -1, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void ComputeHash_OffsetOverflow ()
+       {
+               byte[] array = new byte [1];
+               hash.ComputeHash (array, Int32.MaxValue, 1);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void ComputeHash_CountNegative ()
+       {
+               byte[] array = new byte [0];
+               hash.ComputeHash (array, 0, -1);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void ComputeHash_CountOverflow ()
+       {
+               byte[] array = new byte [1];
+               hash.ComputeHash (array, 1, Int32.MaxValue);
+       }
+
+       [Test]
+// not checked in Fx 1.1
+//     [ExpectedException (typeof (ObjectDisposedException))]
+       public void TransformBlock_Disposed () 
+       {
+               hash.ComputeHash (new byte [0]);
+               hash.Initialize ();
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, 0, input.Length, output, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void TransformBlock_InputBuffer_Null ()
+       {
+               byte[] output = new byte [8];
+               hash.TransformBlock (null, 0, output.Length, output, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void TransformBlock_InputOffset_Negative ()
+       {
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, -1, input.Length, output, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void TransformBlock_InputOffset_Overflow ()
+       {
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, Int32.MaxValue, input.Length, output, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void TransformBlock_InputCount_Negative ()
+       {
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, 0, -1, output, 0);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void TransformBlock_InputCount_Overflow ()
+       {
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, 0, Int32.MaxValue, output, 0);
+       }
+
+       [Test]
+#if ONLY_1_1
+       [Category ("NotDotNet")] // System.ExecutionEngineException on MS runtime (1.1)
+#endif
+       public void TransformBlock_OutputBuffer_Null ()
+       {
+               byte[] input = new byte [8];
+               hash.TransformBlock (input, 0, input.Length, null, 0);
+       }
+
+       [Test]
+#if NET_2_0
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+#else
+       [ExpectedException (typeof (IndexOutOfRangeException))]
+#endif
+       public void TransformBlock_OutputOffset_Negative ()
+       {
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, 0, input.Length, output, -1);
+       }
+
+       [Test]
+#if NET_2_0
+       [ExpectedException (typeof (ArgumentException))]
+#else
+       [ExpectedException (typeof (IndexOutOfRangeException))]
+#endif
+       public void TransformBlock_OutputOffset_Overflow ()
+       {
+               byte[] input = new byte [8];
+               byte[] output = new byte [8];
+               hash.TransformBlock (input, 0, input.Length, output, Int32.MaxValue);
+       }
+
+       [Test]
+// not checked in Fx 1.1
+//     [ExpectedException (typeof (ObjectDisposedException))]
+       public void TransformFinalBlock_Disposed () 
+       {
+               hash.ComputeHash (new byte [0]);
+               hash.Initialize ();
+               byte[] input = new byte [8];
+               hash.TransformFinalBlock (input, 0, input.Length);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentNullException))]
+       public void TransformFinalBlock_InputBuffer_Null ()
+       {
+               hash.TransformFinalBlock (null, 0, 8);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentOutOfRangeException))]
+       public void TransformFinalBlock_InputOffset_Negative ()
+       {
+               byte[] input = new byte [8];
+               hash.TransformFinalBlock (input, -1, input.Length);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void TransformFinalBlock_InputOffset_Overflow ()
+       {
+               byte[] input = new byte [8];
+               hash.TransformFinalBlock (input, Int32.MaxValue, input.Length);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void TransformFinalBlock_InputCount_Negative ()
+       {
+               byte[] input = new byte [8];
+               hash.TransformFinalBlock (input, 0, -1);
+       }
+
+       [Test]
+       [ExpectedException (typeof (ArgumentException))]
+       public void TransformFinalBlock_InputCount_Overflow ()
+       {
+               byte[] input = new byte [8];
+               hash.TransformFinalBlock (input, 0, Int32.MaxValue);
+       }
+
+       [Test]
+       [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-)
+       public void TransformFinalBlock_Twice ()
+       {
+               bool managed = (hash.GetType ().ToString ().IndexOf ("Managed") > 0);
+               bool exception = false;
+               byte[] input = new byte [8];
+               hash.TransformFinalBlock (input, 0, input.Length);
+               try {
+                       hash.TransformFinalBlock (input, 0, input.Length);
                }
-               catch (Exception e) {
-                       Fail ("ComputeHash after clear should throw ObjectDisposedException not " + e.ToString ());
+               catch (CryptographicException) {
+                       exception = true;
+                       if (managed)
+                               Fail ("*Managed don't throw CryptographicException");
                }
+               if (!managed && !exception)
+                       Fail ("Expected CryptographicException from non *Managed classes");
        }
 
-       public void TestNullStream () 
+       [Test]
+       [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-)
+       public void TransformFinalBlock_TransformBlock ()
        {
-               Stream s = null;
+               bool managed = (hash.GetType ().ToString ().IndexOf ("Managed") > 0);
+               bool exception = false;
+               byte[] input = new byte[8];
+               hash.TransformFinalBlock (input, 0, input.Length);
                try {
-                       byte[] result = hash.ComputeHash (s);
-                       Fail ("Expected NullReferenceException but got none");
-               }
-               catch (NullReferenceException) {
-                       // do nothing, this is what we expect
+                       hash.TransformBlock (input, 0, input.Length, input, 0);
                }
-               catch (Exception e) {
-                       Fail ("Expected NullReferenceException but got " + e.ToString ());
+               catch (CryptographicException) {
+                       exception = true;
+                       if (managed)
+                               Fail ("*Managed don't throw CryptographicException");
                }
+               if (!managed && !exception)
+                       Fail ("Expected CryptographicException from non *Managed classes");
+       }
+
+       [Test]
+       public void TransformFinalBlock_Twice_Initialize ()
+       {
+               byte[] input = new byte[8];
+               hash.TransformFinalBlock (input, 0, input.Length);
+               hash.Initialize ();
+               hash.TransformFinalBlock (input, 0, input.Length);
+       }
+
+       [Test]
+       public void TransformFinalBlock_ReturnedBuffer ()
+       {
+               byte[] input = new byte[8];
+               byte[] output = hash.TransformFinalBlock (input, 0, input.Length);
+               AssertEquals ("buffer", input, output);
+               output[0] = 1;
+               AssertEquals ("0", 0, input[0]); // output is a copy (not a reference)
+       }
+
+       private byte[] HashBuffer (bool intersect)
+       {
+               byte[] buffer = new byte [256];
+               for (int i = 0; i < buffer.Length; i++)
+                       buffer [i] = (byte) i;
+
+               hash.Initialize ();
+               // ok
+               hash.TransformBlock (buffer, 0, 64, buffer, 0);
+               // bad - we rewrite the beginning of the buffer
+               hash.TransformBlock (buffer, 64, 128, buffer, intersect ? 0 : 64);
+               // ok
+               hash.TransformFinalBlock (buffer, 192, 64);
+               return hash.Hash;
+       }
+
+       [Test]
+       public void InputOutputIntersection ()
+       {
+               AssertEquals ("Intersect", HashBuffer (false), HashBuffer (true));
        }
 
+       [Test]
+       [ExpectedException (typeof (NullReferenceException))]
+       [Category ("NotWorking")] // initialization problem ? fx2.0 only ?
+       public void Hash_AfterInitialize_FirstTime ()
+       {
+               hash.Initialize ();
+               // getting the property throws
+               AssertNull (hash.Hash);
+       }
+
+       [Test]
+       [ExpectedException (typeof (CryptographicUnexpectedOperationException))]
+       public void Hash_AfterInitialize_SecondTime ()
+       {
+               byte[] input = new byte[8];
+               hash.Initialize ();
+               hash.TransformBlock (input, 0, input.Length, input, 0);
+               hash.Initialize ();
+               // getting the property throws
+               AssertNull (hash.Hash);
+       }
+
+       [Test]
+       [ExpectedException (typeof (CryptographicUnexpectedOperationException))]
+       public void Hash_AfterTransformBlock ()
+       {
+               byte[] input = new byte[8];
+               hash.Initialize ();
+               hash.TransformBlock (input, 0, input.Length, input, 0);
+               // getting the property throws
+               AssertNull (hash.Hash);
+       }
+
+       [Test]
+       public void Hash_AfterTransformFinalBlock ()
+       {
+               byte[] input = new byte[8];
+               hash.Initialize ();
+               hash.TransformFinalBlock (input, 0, input.Length);
+               AssertNotNull (hash.Hash);
+       }
 }
 
 }