text: #region License
  
  /*
   * Copyright © 2002-2011 the original author or authors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #endregion
  
  #region Imports
  
  using System;
  using NUnit.Framework;
  using Spring.Collections;
  
  #endregion
  
  namespace Spring.Objects.Factory.Config
  {
  	/// <summary>
  	/// Unit tests for the ConstructorArgumentValues class.
  	/// </summary>
  	/// <author>Rick Evans (.NET)</author>
  	[TestFixture]
  	public sealed class ConstructorArgumentValuesTests
  	{
  		[Test]
  		public void Instantiation()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			Assert.IsNotNull(values.GenericArgumentValues, "The 'GenericArgumentValues' property was not initialised.");
  			Assert.IsNotNull(values.IndexedArgumentValues, "The 'IndexedArgumentValues' property was not initialised.");
  			Assert.IsNotNull(values.NamedArgumentValues, "The 'NamedArgumentValues' property was not initialised.");
  			Assert.AreEqual(0, values.ArgumentCount, "There were some arguments in a newly initialised instance.");
  			Assert.IsTrue(values.Empty, "A newly initialised instance was not initially empty.");
  		}
  
  		[Test]
  		public void GetGenericArgumentValueIgnoresAlreadyUsedValues()
  		{
  			ISet used = new ListSet();
  
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddGenericArgumentValue(1);
  			values.AddGenericArgumentValue(2);
  			values.AddGenericArgumentValue(3);
  
  			Type intType = typeof (int);
  			ConstructorArgumentValues.ValueHolder one = values.GetGenericArgumentValue(intType, used);
  			Assert.AreEqual(1, one.Value);
  			used.Add(one);
  			ConstructorArgumentValues.ValueHolder two = values.GetGenericArgumentValue(intType, used);
  			Assert.AreEqual(2, two.Value);
  			used.Add(two);
  			ConstructorArgumentValues.ValueHolder three = values.GetGenericArgumentValue(intType, used);
  			Assert.AreEqual(3, three.Value);
  			used.Add(three);
  			ConstructorArgumentValues.ValueHolder four = values.GetGenericArgumentValue(intType, used);
  			Assert.IsNull(four);
  		}
  
  		[Test]
  		public void GetGeneric_Untyped_ArgumentValue()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			const string expectedValue = "Rick";
  			values.AddGenericArgumentValue(expectedValue);
  
  			ConstructorArgumentValues.ValueHolder name = values.GetGenericArgumentValue(null, null);
  			Assert.IsNotNull(name,
  				"Must get non-null valueholder back if no required type is specified.");
  			Assert.AreEqual(expectedValue, name.Value);
  		}
  
  		[Test]
  		public void GetGeneric_Untyped_ArgumentValueWithOnlyStronglyTypedValuesInTheCtorValueList()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			const string expectedValue = "Rick";
  			values.AddGenericArgumentValue(expectedValue, typeof(string).FullName);
  
  			ConstructorArgumentValues.ValueHolder name = values.GetGenericArgumentValue(null, null);
  			Assert.IsNull(name,
  				"Must get null valueholder back if no required type is specified but only " +
  				"strongly typed values are present in the ctor values list.");
  		}
  
  		[Test]
  		public void GetArgumentValueIgnoresAlreadyUsedValues()
  		{
  			ISet used = new ListSet();
  
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddGenericArgumentValue(1);
  			values.AddNamedArgumentValue("2", 2);
  			values.AddIndexedArgumentValue(3, 3);
  
  			Type intType = typeof (int);
  			ConstructorArgumentValues.ValueHolder one = values.GetArgumentValue(10, string.Empty, intType, used);
  			Assert.AreEqual(1, one.Value);
  			used.Add(one);
  			ConstructorArgumentValues.ValueHolder two = values.GetArgumentValue(10, "2", intType, used);
  			Assert.AreEqual(2, two.Value);
  			used.Add(two);
  			ConstructorArgumentValues.ValueHolder three = values.GetArgumentValue(3, string.Empty, intType, used);
  			Assert.AreEqual(3, three.Value);
  			used.Add(three);
  			ConstructorArgumentValues.ValueHolder four = values.GetArgumentValue(10, string.Empty, intType, used);
  			Assert.IsNull(four);
  		}
  
  		[Test]
  		public void AddNamedArgumentWithNullName()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
              Assert.Throws<ArgumentNullException>(() => values.AddNamedArgumentValue(null, 1));
  		}
  
  		[Test]
  		public void AddNamedArgumentWithEmptyStringName()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
              Assert.Throws<ArgumentNullException>(() => values.AddNamedArgumentValue(string.Empty, 1));
  		}
  
  		[Test]
  		public void AddNamedArgumentWithWhitespaceStringName()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
              Assert.Throws<ArgumentNullException>(() => values.AddNamedArgumentValue(Environment.NewLine + "  ", 1));
  		}
  
  		[Test]
  		public void AddIndexedArgumentValue()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddIndexedArgumentValue(1, DBNull.Value);
  			Assert.IsFalse(values.Empty, "Added one value, but the collection is sayin' it's empty.");
  			Assert.AreEqual(1, values.ArgumentCount, "Added one value, but the collection ain't sayin' that it's got a single element in it.");
  			Assert.AreEqual(1, values.IndexedArgumentValues.Count, "Added one indexed value, but the collection of indexed values ain't sayin' that it's got a single element in it.");
  		}
  
  		[Test]
  		public void AddGenericArgumentValue()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddGenericArgumentValue(DBNull.Value);
  			Assert.IsFalse(values.Empty, "Added one value, but the collection is sayin' it's empty.");
  			Assert.AreEqual(1, values.ArgumentCount, "Added one value, but the collection ain't sayin' that it's got a single element in it.");
  			Assert.AreEqual(1, values.GenericArgumentValues.Count, "Added one generic value, but the collection of indexed values ain't sayin' that it's got a single element in it.");
  		}
  
  		[Test]
  		public void GetIndexedArgumentValue()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			Assert.IsNull(values.GetIndexedArgumentValue(0, typeof (object)), "Mmm... managed to get a non null instance back from an empty instance.");
  			values.AddIndexedArgumentValue(16, DBNull.Value, typeof (DBNull).FullName);
  			Assert.IsNull(values.GetIndexedArgumentValue(0, typeof (object)), "Mmm... managed to get a non null instance back from an instance that should have now't at the specified index.");
  			ConstructorArgumentValues.ValueHolder value =
  				values.GetIndexedArgumentValue(16, typeof (DBNull));
  			Assert.IsNotNull(value, "Stored a value at a specified index, but got null when retrieving it.");
  			Assert.AreSame(DBNull.Value, value.Value, "The value stored at the specified index was not the exact same instance as was added.");
  			ConstructorArgumentValues.ValueHolder wrongValue =
  				values.GetIndexedArgumentValue(16, typeof (string));
  			Assert.IsNull(wrongValue, "Stored a value at a specified index, and got it (or rather something) back when retrieving it with the wrong Type specified.");
  		}
  
  		[Test]
  		public void GetGenericArgumentValue()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			Assert.IsNull(values.GetGenericArgumentValue(typeof (object)), "Mmm... managed to get a non null instance back from an empty instance.");
  			values.AddGenericArgumentValue(DBNull.Value, typeof (DBNull).FullName);
  			Assert.IsNull(values.GetGenericArgumentValue(typeof (string)), "Mmm... managed to get a non null instance back from an instance that should have now't with the specified Type.");
  			ConstructorArgumentValues.ValueHolder value =
  				values.GetGenericArgumentValue(typeof (DBNull));
  			Assert.IsNotNull(value, "Stored a value of a specified Type, but got null when retrieving it using said Type.");
  			Assert.AreSame(DBNull.Value, value.Value, "The value stored at the specified index was not the exact same instance as was added.");
  		}
  
  		[Test]
  		public void GetArgumentValue()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			Assert.IsNull(values.GetArgumentValue(0, typeof (object)), "Mmm... managed to get a non null instance back from an empty instance.");
  			values.AddGenericArgumentValue(DBNull.Value, typeof (DBNull).FullName);
  			values.AddNamedArgumentValue("foo", DBNull.Value);
  			values.AddIndexedArgumentValue(16, DBNull.Value, typeof (DBNull).FullName);
  			Assert.IsNull(values.GetArgumentValue(100, typeof (string)), "Mmm... managed to get a non null instance back from an instance that should have now't with the specified Type.");
  			ConstructorArgumentValues.ValueHolder value =
  				values.GetArgumentValue(-3, typeof (DBNull));
  			Assert.IsNotNull(value, "Stored a value of a specified Type at a specified index, but got null when retrieving it using the wrong index but the correct Type.");
  			Assert.AreSame(DBNull.Value, value.Value, "The retrieved value was not the exact same instance as was added.");
  			
  			value = values.GetArgumentValue("foo", typeof (DBNull));
  			Assert.IsNotNull(value, "Stored a value of a specified Type under a name, but got null when retrieving it using the wrong name but the correct Type.");
  			Assert.AreSame(DBNull.Value, value.Value, "The retrieved value was not the exact same instance as was added.");
  		}
  
  		[Test]
  		public void AddAllDoesntChokeOnNullArgument()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddAll(null);
  		}
  
  		[Test]
  		public void AddAllFromOther()
  		{
  			ConstructorArgumentValues other = new ConstructorArgumentValues();
  			other.AddIndexedArgumentValue(1, DBNull.Value);
  			other.AddIndexedArgumentValue(2, "Foo");
  			other.AddIndexedArgumentValue(3, 3);
  
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddAll(other);
  			Assert.AreEqual(other.ArgumentCount, values.ArgumentCount,
  				"Must have been the same since one was filled up with the values in the other.");
  		}
  
  		[Test]
  		public void AddRangeOfIndexedArgumentValues()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddIndexedArgumentValue(1, DBNull.Value);
  			values.AddIndexedArgumentValue(2, "Foo");
  			values.AddIndexedArgumentValue(3, 3);
  			new ConstructorArgumentValues(values);
  			Assert.IsFalse(values.Empty, "Added three indexed values(as a range), but the collection is sayin' it's empty.");
  			Assert.AreEqual(3, values.ArgumentCount, "Added three indexed values(as a range), but the collection ain't sayin' that it's got 3 elements in it.");
  			Assert.AreEqual(3, values.IndexedArgumentValues.Count, "Added three indexed values(as a range), but the collection of indexed values ain't sayin' that it's got 3 elements in it.");
  		}
  
  		[Test]
  		public void NamedArgumentsAreCaseInsensitive()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddNamedArgumentValue("foo", "sball");
  			Assert.AreEqual(1, values.NamedArgumentValues.Count, "Added one named argument but it doesn't seem to have been added to the named arguments collection.");
  			Assert.AreEqual(1, values.ArgumentCount, "Added one named argument but it doesn't seem to be reflected in the overall argument count.");
  			Assert.IsTrue(values.ContainsNamedArgument("FOo"), "Mmm, the ContainsNamedArgument() method eveidently IS case sensitive (which is wrong).");
  			ConstructorArgumentValues.ValueHolder arg = values.GetNamedArgumentValue("fOo");
  			Assert.IsNotNull(arg, "The named argument previously added could not be pulled from the ctor arg collection.");
  			Assert.AreEqual("sball", arg.Value, "The value of the named argument passed in is not the same as the one that was pulled out.");
  		}
  
  		[Test]
  		public void AddNamedArgument()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddNamedArgumentValue("foo", "sball");
  			Assert.AreEqual(1, values.NamedArgumentValues.Count, "Added one named argument but it doesn't seem to have been added to the named arguments collection.");
  			Assert.AreEqual(1, values.ArgumentCount, "Added one named argument but it doesn't seem to be reflected in the overall argument count.");
  			ConstructorArgumentValues.ValueHolder arg = values.GetNamedArgumentValue("foo");
  			Assert.IsNotNull(arg, "The named argument previously added could not be pulled from the ctor arg collection.");
  			Assert.AreEqual("sball", arg.Value, "The value of the named argument passed in is not the same as the one that was pulled out.");
  		}
  
  		[Test]
  		public void AddNamedArgumentFromAotherCtorArgCollection()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddNamedArgumentValue("foo", "sball");
  			ConstructorArgumentValues copy = new ConstructorArgumentValues(values);
  			Assert.AreEqual(1, copy.NamedArgumentValues.Count, "Added one named argument but it doesn't seem to have been added to the named arguments collection.");
  			Assert.AreEqual(1, copy.ArgumentCount, "Added one named argument but it doesn't seem to be reflected in the overall argument count.");
  			ConstructorArgumentValues.ValueHolder arg = copy.GetNamedArgumentValue("foo");
  			Assert.IsNotNull(arg, "The named argument previously added could not be pulled from the ctor arg collection.");
  			Assert.AreEqual("sball", arg.Value, "The value of the named argument passed in is not the same as the one that was pulled out.");
  		}
  
  		[Test]
  		public void ValueHolderToStringsNicely()
  		{
  			ConstructorArgumentValues values = new ConstructorArgumentValues();
  			values.AddGenericArgumentValue(1, typeof(int).FullName);
  			ConstructorArgumentValues.ValueHolder vh = values.GetGenericArgumentValue(typeof(int));
  			Assert.AreEqual("'1' [System.Int32]", vh.ToString());
  		}
  	}
  }