context: // ArrayListTest.cs - NUnit Test Cases for the System.Collections.ArrayList class
  //
  // David Brandt (bucky@keystreams.com)
  //
  // (C) Ximian, Inc.  http://www.ximian.com
  // Copyright (C) 2005 Novell (http://www.novell.com)
  // 
  
  using System;
  using System.Collections;
  
  using NUnit.Framework;
  
  namespace MonoTests.System.Collections
  {
  	[TestFixture]
  	public class ArrayListTest
  	{
  		[Test]
  		public void TestCtor ()
  		{
  			{
  				ArrayList al1 = new ArrayList ();
  				Assert.IsNotNull (al1, "no basic ArrayList");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList a = new ArrayList (null);
  				} catch (ArgumentNullException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "null icollection error not thrown");
  			}
  			{
  				// what can I say?  I like chars.  [--DB]
  				char [] coll = { 'a', 'b', 'c', 'd' };
  				ArrayList al1 = new ArrayList (coll);
  				Assert.IsNotNull (al1, "no icollection ArrayList");
  				for (int i = 0; i < coll.Length; i++) {
  					Assert.AreEqual (coll [i], al1 [i], i + " not ctor'ed properly.");
  				}
  			}
  			{
  				try {
  					Char [,] c1 = new Char [2, 2];
  					ArrayList al1 = new ArrayList (c1);
  					Assert.Fail ("Should fail with multi-dimensional array in constructor.");
  				} catch (RankException) {
  				}
  			}
  
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList a = new ArrayList (-1);
  				} catch (ArgumentOutOfRangeException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "negative capacity error not thrown");
  			}
  		}
  
  		[Test]
  		public void TestCapacity ()
  		{
  		int default_capacity = 4;
  		int unspecified_capacity = 0;
  			for (int i = 1; i < 100; i++) {
  				ArrayList al1 = new ArrayList (i);
  				Assert.AreEqual (i, al1.Capacity, "Bad capacity of " + i);
  			}
  			{
  				ArrayList al1 = new ArrayList (0);
  				// LAMESPEC: 
  				// Assert.AreEqual (//	     16, al1.Capacity, "Bad capacity when set to 0");
  				al1.Add ("?");
  				Assert.AreEqual (default_capacity, al1.Capacity, "Bad capacity when set to 0");
  			}
  			{
  				ArrayList al1 = new ArrayList ();
  				Assert.AreEqual (unspecified_capacity, al1.Capacity, "Bad default capacity");
  			}
  		}
  
  		[Test]
  		public void TestCount ()
  		{
  			{
  				ArrayList al1 = new ArrayList ();
  				Assert.AreEqual (0, al1.Count, "Bad initial count");
  				for (int i = 1; i <= 100; i++) {
  					al1.Add (i);
  					Assert.AreEqual (i, al1.Count, "Bad count " + i);
  				}
  			}
  			for (int i = 0; i < 100; i++) {
  				char [] coll = new Char [i];
  				ArrayList al1 = new ArrayList (coll);
  				Assert.AreEqual (i, al1.Count, "Bad count for " + i);
  			}
  		}
  
  		[Test]
  		public void TestIsFixed ()
  		{
  			ArrayList al1 = new ArrayList ();
  			Assert.IsTrue (!al1.IsFixedSize, "should not be fixed by default");
  			ArrayList al2 = ArrayList.FixedSize (al1);
  			Assert.IsTrue (al2.IsFixedSize, "fixed-size wrapper not working");
  		}
  
  		[Test]
  		public void TestIsReadOnly ()
  		{
  			ArrayList al1 = new ArrayList ();
  			Assert.IsTrue (!al1.IsReadOnly, "should not be ReadOnly by default");
  			ArrayList al2 = ArrayList.ReadOnly (al1);
  			Assert.IsTrue (al2.IsReadOnly, "read-only wrapper not working");
  		}
  
  		[Test]
  		public void TestIsSynchronized ()
  		{
  			ArrayList al1 = new ArrayList ();
  			Assert.IsTrue (!al1.IsSynchronized, "should not be synchronized by default");
  			ArrayList al2 = ArrayList.Synchronized (al1);
  			Assert.IsTrue (al2.IsSynchronized, "synchronized wrapper not working");
  		}
  
  		[Test]
  		public void TestItem ()
  		{
  			ArrayList al1 = new ArrayList ();
  			{
  				bool errorThrown = false;
  				try {
  					object o = al1 [-1];
  				} catch (ArgumentOutOfRangeException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "negative item error not thrown");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					object o = al1 [1];
  				} catch (ArgumentOutOfRangeException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "past-end item error not thrown");
  			}
  			for (int i = 0; i <= 100; i++) {
  				al1.Add (i);
  			}
  			for (int i = 0; i <= 100; i++) {
  				Assert.AreEqual (i, al1 [i], "item not fetched for " + i);
  			}
  		}
  
  		[Test]
  		public void TestAdapter ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 = ArrayList.Adapter (null);
  				} catch (ArgumentNullException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 1: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "null adapter error not thrown");
  			}
  			{
  				char [] list = { 'a', 'b', 'c', 'd' };
  				ArrayList al1 = ArrayList.Adapter (list);
  				Assert.IsNotNull (al1, "Couldn't get an adapter");
  				for (int i = 0; i < list.Length; i++) {
  					Assert.AreEqual (list [i], al1 [i], "adapter not adapting");
  				}
  				list [0] = 'z';
  				for (int i = 0; i < list.Length; i++) {
  					Assert.AreEqual (list [i], al1 [i], "adapter not adapting");
  				}
  			}
  			// Test Binary Search
  			{
  				bool errorThrown = false;
  				try {
  
  					String [] s1 = { "This", "is", "a", "test" };
  					ArrayList al1 = ArrayList.Adapter (s1);
  					al1.BinarySearch (42);
  				} catch (InvalidOperationException) {
  					// this is what .NET throws
  					errorThrown = true;
  				} catch (ArgumentException) {
  					// this is what the docs say it should throw
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 1: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "search-for-wrong-type error not thrown");
  			}
  
  			{
  				char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' };
  				ArrayList al1 = ArrayList.Adapter (arr);
  				Assert.IsTrue (al1.BinarySearch ('c') >= 3, "couldn't find elem #1");
  				Assert.IsTrue (al1.BinarySearch ('c') < 6, "couldn't find elem #2");
  			}
  			{
  				char [] arr = { 'a', 'b', 'b', 'd', 'd', 'd', 'e', 'e' };
  				ArrayList al1 = ArrayList.Adapter (arr);
  				Assert.AreEqual (-4, al1.BinarySearch ('c'), "couldn't find next-higher elem");
  			}
  			{
  				char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' };
  				ArrayList al1 = ArrayList.Adapter (arr);
  				Assert.AreEqual (-9, al1.BinarySearch ('e'), "couldn't find end");
  			}
  			// Sort
  			{
  				char [] starter = { 'd', 'b', 'f', 'e', 'a', 'c' };
  				ArrayList al1 = ArrayList.Adapter (starter);
  				al1.Sort ();
  				Assert.AreEqual ('a', al1 [0], "Should be sorted");
  				Assert.AreEqual ('b', al1 [1], "Should be sorted");
  				Assert.AreEqual ('c', al1 [2], "Should be sorted");
  				Assert.AreEqual ('d', al1 [3], "Should be sorted");
  				Assert.AreEqual ('e', al1 [4], "Should be sorted");
  				Assert.AreEqual ('f', al1 [5], "Should be sorted");
  			}
  
  			// TODO - test other adapter types?
  		}
  
  		[Test]
  		public void TestAdd ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 =
  						ArrayList.FixedSize (new ArrayList ());
  					al1.Add ("Hi!");
  				} catch (NotSupportedException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 1: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "add to fixed size error not thrown");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 =
  						ArrayList.ReadOnly (new ArrayList ());
  					al1.Add ("Hi!");
  				} catch (NotSupportedException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 2: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "add to read only error not thrown");
  			}
  			{
  				ArrayList al1 = new ArrayList ();
  				for (int i = 1; i <= 100; i++) {
  					al1.Add (i);
  					Assert.AreEqual (i, al1.Count, "add failed " + i);
  					Assert.AreEqual (i, al1 [i - 1], "add failed " + i);
  
  				}
  			}
  			{
  				string [] strArray = new string [] { };
  				ArrayList al1 = new ArrayList (strArray);
  				al1.Add ("Hi!");
  				al1.Add ("Hi!");
  				Assert.AreEqual (2, al1.Count, "add failed");
  			}
  		}
  
  		[Test]
  		public void TestAddRange ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 =
  						ArrayList.FixedSize (new ArrayList ());
  					String [] s1 = { "Hi!" };
  					al1.AddRange (s1);
  				} catch (NotSupportedException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 1: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "add to fixed size error not thrown");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 =
  						ArrayList.ReadOnly (new ArrayList ());
  					String [] s1 = { "Hi!" };
  					al1.AddRange (s1);
  				} catch (NotSupportedException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 2: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "add to read only error not thrown");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 = new ArrayList ();
  					al1.AddRange (null);
  				} catch (ArgumentNullException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 3: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "add to read only error not thrown");
  			}
  
  			{
  				ArrayList a1 = new ArrayList ();
  				Assert.AreEqual (0, a1.Count, "ArrayList should start empty");
  				char [] coll = { 'a', 'b', 'c' };
  				a1.AddRange (coll);
  				Assert.AreEqual (3, a1.Count, "ArrayList has wrong elements");
  				a1.AddRange (coll);
  				Assert.AreEqual (6, a1.Count, "ArrayList has wrong elements");
  			}
  
  			{
  				ArrayList list = new ArrayList ();
  
  				for (int i = 0; i < 100; i++) {
  					list.Add (1);
  				}
  
  				Assert.AreEqual (49, list.BinarySearch (1), "BinarySearch off-by-one bug");
  			}
  		}
  
  		[Test]
  		public void TestBinarySearch ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 = new ArrayList ();
  					String [] s1 = { "This", "is", "a", "test" };
  					al1.AddRange (s1);
  					al1.BinarySearch (42);
  				} catch (InvalidOperationException) {
  					// this is what .NET throws
  					errorThrown = true;
  				} catch (ArgumentException) {
  					// this is what the docs say it should throw
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 1: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "search-for-wrong-type error not thrown");
  			}
  
  			{
  				char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' };
  				ArrayList al1 = new ArrayList (arr);
  				Assert.IsTrue (al1.BinarySearch ('c') >= 3, "couldn't find elem #1");
  				Assert.IsTrue (al1.BinarySearch ('c') < 6, "couldn't find elem #2");
  			}
  			{
  				char [] arr = { 'a', 'b', 'b', 'd', 'd', 'd', 'e', 'e' };
  				ArrayList al1 = new ArrayList (arr);
  				Assert.AreEqual (-4, al1.BinarySearch ('c'), "couldn't find next-higher elem");
  			}
  			{
  				char [] arr = { 'a', 'b', 'b', 'c', 'c', 'c', 'd', 'd' };
  				ArrayList al1 = new ArrayList (arr);
  				Assert.AreEqual (-9, al1.BinarySearch ('e'), "couldn't find end");
  			}
  
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentException))]
  		public void BinarySearch_IndexOverflow ()
  		{
  			ArrayList al = new ArrayList ();
  			al.Add (this);
  			al.BinarySearch (Int32.MaxValue, 1, this, null);
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentException))]
  		public void BinarySearch_CountOverflow ()
  		{
  			ArrayList al = new ArrayList ();
  			al.Add (this);
  			al.BinarySearch (1, Int32.MaxValue, this, null);
  		}
  
  		[Test]
  		public void BinarySearch_Null ()
  		{
  			ArrayList al = new ArrayList ();
  			al.Add (this);
  			Assert.AreEqual (-1, al.BinarySearch (null), "null");
  		}
  
  		// TODO - BinarySearch with IComparer
  
  		[Test]
  		public void TestClear ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 =
  						ArrayList.FixedSize (new ArrayList ());
  					al1.Clear ();
  				} catch (NotSupportedException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "add to fixed size error not thrown");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 =
  						ArrayList.ReadOnly (new ArrayList ());
  					al1.Clear ();
  				} catch (NotSupportedException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "add to read only error not thrown");
  			}
  			{
  				ArrayList al1 = new ArrayList ();
  				al1.Add ('c');
  				Assert.AreEqual (1, al1.Count, "should have one element");
  				al1.Clear ();
  				Assert.AreEqual (0, al1.Count, "should be empty");
  			}
  			{
  				int [] i1 = { 1, 2, 3, 4 };
  				ArrayList al1 = new ArrayList (i1);
  				Assert.AreEqual (i1.Length, al1.Count, "should have elements");
  				int capacity = al1.Capacity;
  				al1.Clear ();
  				Assert.AreEqual (0, al1.Count, "should be empty again");
  				Assert.AreEqual (capacity, al1.Capacity, "capacity shouldn't have changed");
  			}
  		}
  
  		[Test]
  		public void TestClone ()
  		{
  			{
  				char [] c1 = { 'a', 'b', 'c' };
  				ArrayList al1 = new ArrayList (c1);
  				ArrayList al2 = (ArrayList) al1.Clone ();
  				Assert.AreEqual (al1 [0], al2 [0], "ArrayList match");
  				Assert.AreEqual (al1 [1], al2 [1], "ArrayList match");
  				Assert.AreEqual (al1 [2], al2 [2], "ArrayList match");
  			}
  			{
  				char [] d10 = { 'a', 'b' };
  				char [] d11 = { 'a', 'c' };
  				char [] d12 = { 'b', 'c' };
  				char [] [] d1 = { d10, d11, d12 };
  				ArrayList al1 = new ArrayList (d1);
  				ArrayList al2 = (ArrayList) al1.Clone ();
  				Assert.AreEqual (al1 [0], al2 [0], "Array match");
  				Assert.AreEqual (al1 [1], al2 [1], "Array match");
  				Assert.AreEqual (al1 [2], al2 [2], "Array match");
  
  				((char []) al1 [0]) [0] = 'z';
  				Assert.AreEqual (al1 [0], al2 [0], "shallow copy");
  			}
  		}
  
  		[Test]
  		public void TestContains ()
  		{
  			char [] c1 = { 'a', 'b', 'c' };
  			ArrayList al1 = new ArrayList (c1);
  			Assert.IsTrue (!al1.Contains (null), "never find a null");
  			Assert.IsTrue (al1.Contains ('b'), "can't find value");
  			Assert.IsTrue (!al1.Contains ('?'), "shouldn't find value");
  		}
  
  		[Test]
  		public void TestCopyTo ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					Char [] c1 = new Char [2];
  					ArrayList al1 = new ArrayList (c1);
  					al1.CopyTo (null, 2);
  				} catch (ArgumentNullException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 1: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 1");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					Char [] c1 = new Char [2];
  					ArrayList al1 = new ArrayList (c1);
  					Char [,] c2 = new Char [2, 2];
  					al1.CopyTo (c2, 2);
  				} catch (ArgumentException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 2: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 2");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					// This appears to be a bug in the ArrayList Constructor.
  					// It throws a RankException if a multidimensional Array
  					// is passed. The docs imply that an IEnumerator is used
  					// to retrieve the items from the collection, so this should
  					// work.  In anycase this test is for CopyTo, so use what
  					// works on both platforms.
  					//Char[,] c1 = new Char[2,2];
  					Char [] c1 = new Char [2];
  					ArrayList al1 = new ArrayList (c1);
  					Char [] c2 = new Char [2];
  					al1.CopyTo (c2, 2);
  				} catch (ArgumentException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 3: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 3");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					Char [] c1 = new Char [2];
  					ArrayList al1 = new ArrayList (c1);
  					Char [] c2 = new Char [2];
  					al1.CopyTo (c2, -1);
  				} catch (ArgumentOutOfRangeException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 4: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 4");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					Char [] c1 = new Char [2];
  					ArrayList al1 = new ArrayList (c1);
  					Char [] c2 = new Char [2];
  					al1.CopyTo (c2, 3);
  				} catch (ArgumentException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 5: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 5");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					Char [] c1 = new Char [2];
  					ArrayList al1 = new ArrayList (c1);
  					Char [] c2 = new Char [2];
  					al1.CopyTo (c2, 1);
  				} catch (ArgumentException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 6: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 6");
  			}
  			{
  				bool errorThrown = false;
  				try {
  					String [] c1 = { "String", "array" };
  					ArrayList al1 = new ArrayList (c1);
  					Char [] c2 = new Char [2];
  					al1.CopyTo (c2, 0);
  				} catch (InvalidCastException) {
  					errorThrown = true;
  				} catch (Exception e) {
  					Assert.Fail ("Incorrect exception thrown at 7: " + e.ToString ());
  				}
  				Assert.IsTrue (errorThrown, "error not thrown 7");
  			}
  
  			Char [] orig = { 'a', 'b', 'c', 'd' };
  			ArrayList al = new ArrayList (orig);
  			Char [] copy = new Char [10];
  			Array.Clear (copy, 0, copy.Length);
  			al.CopyTo (copy, 3);
  			Assert.AreEqual ((char) 0, copy [0], "Wrong CopyTo 0");
  			Assert.AreEqual ((char) 0, copy [1], "Wrong CopyTo 1");
  			Assert.AreEqual ((char) 0, copy [2], "Wrong CopyTo 2");
  			Assert.AreEqual (orig [0], copy [3], "Wrong CopyTo 3");
  			Assert.AreEqual (orig [1], copy [4], "Wrong CopyTo 4");
  			Assert.AreEqual (orig [2], copy [5], "Wrong CopyTo 5");
  			Assert.AreEqual (orig [3], copy [6], "Wrong CopyTo 6");
  			Assert.AreEqual ((char) 0, copy [7], "Wrong CopyTo 7");
  			Assert.AreEqual ((char) 0, copy [8], "Wrong CopyTo 8");
  			Assert.AreEqual ((char) 0, copy [9], "Wrong CopyTo 9");
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentException))]
  		public void CopyTo_IndexOverflow ()
  		{
  			ArrayList al = new ArrayList ();
  			al.Add (this);
  			al.CopyTo (Int32.MaxValue, new byte [2], 0, 0);
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentException))]
  		public void CopyTo_ArrayIndexOverflow ()
  		{
  			ArrayList al = new ArrayList ();
  			al.Add (this);
  			al.CopyTo (0, new byte [2], Int32.MaxValue, 0);
  		}
  
  		[Test]
  		[ExpectedException (typeof (ArgumentException))]
  		public void CopyTo_CountOverflow ()
  		{
  			ArrayList al = new ArrayList ();
  			al.Add (this);
  			al.CopyTo (0, new byte [2], 0, Int32.MaxValue);
  		}
  
  		[Test]
  		public void TestFixedSize ()
  		{
  			{
  				bool errorThrown = false;
  				try {
  					ArrayList al1 = ArrayList.FixedSize (null);
  				} catch (ArgumentNullException) {
  					errorThrown = true;
  				}
  				Assert.IsTrue (errorThrown, "null arg error not thrown");
  			}
  			{
  
gt: 				ArrayList al1 = new ArrayList ();