diff --git a/src/Spring/Spring.Core/Objects/Factory/Config/DictionaryVariableSource.cs b/src/Spring/Spring.Core/Objects/Factory/Config/DictionaryVariableSource.cs index d45dfd3b..b8054f02 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Config/DictionaryVariableSource.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Config/DictionaryVariableSource.cs @@ -36,7 +36,7 @@ namespace Spring.Objects.Factory.Config /// Creates a new, empty variable source /// public DictionaryVariableSource() - :this(null, true) + : this(null, true) { } @@ -44,7 +44,7 @@ namespace Spring.Objects.Factory.Config /// Creates a new, empty and case-insensitive variable source /// public DictionaryVariableSource(bool ignoreCase) - :this(null, ignoreCase) + : this(null, ignoreCase) { } @@ -61,17 +61,32 @@ namespace Spring.Objects.Factory.Config /// /// the argument list containing pairs, or null public DictionaryVariableSource(params string[] args) - :this(true) + : this(true) { if (args != null) { - for (int i = 0; i < args.Length; i += 2) + if (args.Length % 2 != 0) { - Add(args[i], args[i + 1]); + throw new ArgumentOutOfRangeException("Unbalanced Key-Value pairs of strings detected. Verify that args contains pairs of key strings and value strings."); } + + for (int i = 0; i < args.Length; i += 2) + { + Add(args[i], args[i + 1]); + } + } } + /// + /// Initializes a new instance of the DictionaryVariableSource class. + /// + public DictionaryVariableSource(IDictionary dictionary) + : this(dictionary, true) + { + } + + /// /// Creates a new variable source, reading values from another dictionary /// and converting them to strings if necessary diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/DictionaryVariableSourceTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/DictionaryVariableSourceTests.cs new file mode 100644 index 00000000..51ee22d1 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/DictionaryVariableSourceTests.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections; +using System.Text; +using NUnit.Framework; + +namespace Spring.Objects.Factory.Config +{ + [TestFixture] + public class DictionaryVariableSourceTests + { + [Test] + public void Initialize_WithCaseSensitiveFlag_AddsCaseSensitiveKeys() + { + DictionaryVariableSource dvs = new DictionaryVariableSource(false); + dvs.Add("key1", "lowercasevalue"); + dvs.Add("KEY1", "uppercasevalue"); + + Assert.AreEqual("lowercasevalue", dvs.ResolveVariable("key1")); + Assert.AreEqual("uppercasevalue", dvs.ResolveVariable("KEY1")); + } + + [Test] + public void Iniitialize_WithStringArray_FillsKeyValuesInPairs() + { + DictionaryVariableSource dvs = new DictionaryVariableSource(new string[] { "key1", "value1", "key2", "value2" }); + + Assert.AreEqual("value1", dvs.ResolveVariable("key1")); + Assert.AreEqual("value2", dvs.ResolveVariable("key2")); + } + + [Test] + public void Iniitialize_WithStringArray_ThrowsException_WhenOddNumberOfStringsProvided() + { + Assert.Throws(() => new DictionaryVariableSource(new string[] { "key1", "value1", "key2", "value2", "orphanedKey1" })); + } + + + [Test] + public void Initialize_WithDictionaryConstructor_AddsCaseInsensitiveKeys() + { + IDictionary dict = new Hashtable() { { "key1", "value1" }, { "KEY2", "value2" } }; + + DictionaryVariableSource dvs = new DictionaryVariableSource(dict); + + Assert.AreEqual("value1", dvs.ResolveVariable("KEY1")); + Assert.AreEqual("value2", dvs.ResolveVariable("key2")); + } + + [Test] + public void Initialize_WithDictionaryConstructor_AddsKeys() + { + IDictionary dict = new Hashtable() { { "key1", "value1" }, { "key2", "value2" } }; + + DictionaryVariableSource dvs = new DictionaryVariableSource(dict); + + Assert.AreEqual("value1", dvs.ResolveVariable("key1")); + Assert.AreEqual("value2", dvs.ResolveVariable("key2")); + } + + [Test] + public void Initialize_WithDictionaryConstructorAndCaseSensitiveFlag_AddsCaseSensitiveKeys() + { + IDictionary dict = new Hashtable() { { "key1", "lowecasevalue" }, { "KEY1", "uppercasevalue" } }; + + DictionaryVariableSource dvs = new DictionaryVariableSource(dict, false); + + Assert.AreEqual("lowecasevalue", dvs.ResolveVariable("key1")); + Assert.AreEqual("uppercasevalue", dvs.ResolveVariable("KEY1")); + } + + [Test] + public void Initialize_WithEmptyConstructor_AddsCaseInsensitiveKeys() + { + DictionaryVariableSource dvs = new DictionaryVariableSource(); + dvs.Add("key1", "value1"); + dvs.Add("KEY2", "value2"); + + Assert.AreEqual("value1", dvs.ResolveVariable("KEY1")); + Assert.AreEqual("value2", dvs.ResolveVariable("key2")); + } + + [Test] + public void Test() + { + Hashtable hashtable = new Hashtable(); + hashtable.Add("KEY1", "value1"); + + Assert.False(hashtable.ContainsKey("key1")); + } + + [Test] + public void CanResolveVariable_RespectsCaseSensitivity() + { + DictionaryVariableSource caseSensitive = new DictionaryVariableSource(false); + caseSensitive.Add("KEY1", "value1"); + + Assert.False(caseSensitive.CanResolveVariable("key1")); + } + + [Test] + public void CanResolveVariable_RespectsCaseInsensitivity() + { + DictionaryVariableSource caseInsensitive = new DictionaryVariableSource(); + caseInsensitive.Add("key1", "value1"); + + Assert.True(caseInsensitive.CanResolveVariable("KEY1")); + } + + + [Test] + public void Requesting_KeyNotFound_ThrowsException() + { + DictionaryVariableSource dvs = new DictionaryVariableSource(); + dvs.Add("key-found", "value-found"); + + Assert.Throws(() => dvs.ResolveVariable("key-not-found")); + } + + } +} diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs index e453cfd5..5e15b3a0 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Config/VariablePlaceholderConfigurerTests.cs @@ -38,13 +38,8 @@ namespace Spring.Objects.Factory.Config { StaticApplicationContext ac = new StaticApplicationContext(); VariablePlaceholderConfigurer vphc = new VariablePlaceholderConfigurer(); - try - { - vphc.PostProcessObjectFactory(ac.ObjectFactory); - Assert.Fail(); - } - catch (ArgumentException) - {} + + Assert.Throws(() => vphc.PostProcessObjectFactory(ac.ObjectFactory)); } [Test] @@ -52,15 +47,9 @@ namespace Spring.Objects.Factory.Config { StaticApplicationContext ac = new StaticApplicationContext(); VariablePlaceholderConfigurer vphc = new VariablePlaceholderConfigurer(); - vphc.VariableSources = new ArrayList( new object[] { new object() } ); + vphc.VariableSources = new ArrayList(new object[] { new object() }); - try - { - vphc.PostProcessObjectFactory(ac.ObjectFactory); - Assert.Fail(); - } - catch (ArgumentException) - {} + Assert.Throws(() => vphc.PostProcessObjectFactory(ac.ObjectFactory)); } [Test] @@ -85,7 +74,7 @@ namespace Spring.Objects.Factory.Config pvs = new MutablePropertyValues(); pvs.Add("VariableSources", variableSources); - + ac.RegisterSingleton("configurer", typeof(VariablePlaceholderConfigurer), pvs); ac.Refresh(); @@ -106,7 +95,7 @@ namespace Spring.Objects.Factory.Config ac.RegisterSingleton("tb1", typeof(TestObject), pvs); IList variableSources = new ArrayList(); - variableSources.Add( new DictionaryVariableSource( new string[] { "maxResults", "35", "name", "Erich" } ) ); + variableSources.Add(new DictionaryVariableSource(new string[] { "maxResults", "35", "name", "Erich" })); pvs = new MutablePropertyValues(); @@ -119,9 +108,9 @@ namespace Spring.Objects.Factory.Config TestObject tb1 = (TestObject)ac.GetObject("tb1"); Assert.AreEqual(35, tb1.Age); - Assert.AreEqual("Erich", tb1.Name); - } - + Assert.AreEqual("Erich", tb1.Name); + } + [Test] public void MultiResolution() { @@ -132,11 +121,11 @@ namespace Spring.Objects.Factory.Config IList variableSources = new ArrayList(); variableSources.Add(new DictionaryVariableSource(new string[] { "firstname", "FirstName" })); - variableSources.Add(new DictionaryVariableSource(new string[] { "lastname", "LastName"})); + variableSources.Add(new DictionaryVariableSource(new string[] { "lastname", "LastName" })); VariablePlaceholderConfigurer vphc = new VariablePlaceholderConfigurer(variableSources); vphc.PostProcessObjectFactory(of); - RootObjectDefinition rod = (RootObjectDefinition) of.GetObjectDefinition("tb1"); + RootObjectDefinition rod = (RootObjectDefinition)of.GetObjectDefinition("tb1"); Assert.AreEqual("Hello FirstName LastName!", rod.PropertyValues.GetPropertyValue("Greeting").Value); } @@ -150,11 +139,11 @@ namespace Spring.Objects.Factory.Config IList variableSources = new ArrayList(); variableSources.Add(new DictionaryVariableSource(new string[] { "name", "${nickname}" })); - variableSources.Add(new DictionaryVariableSource(new string[] { "nickname", "nickname-value"})); + variableSources.Add(new DictionaryVariableSource(new string[] { "nickname", "nickname-value" })); VariablePlaceholderConfigurer vphc = new VariablePlaceholderConfigurer(variableSources); vphc.PostProcessObjectFactory(of); - RootObjectDefinition rod = (RootObjectDefinition) of.GetObjectDefinition("tb1"); + RootObjectDefinition rod = (RootObjectDefinition)of.GetObjectDefinition("tb1"); Assert.AreEqual("nickname-value", rod.PropertyValues.GetPropertyValue("NameProperty").Value); } @@ -170,7 +159,7 @@ namespace Spring.Objects.Factory.Config IList variableSources = new ArrayList(); variableSources.Add(new DictionaryVariableSource(new string[] { "name", "name-value" })); - variableSources.Add(new DictionaryVariableSource(new string[] { "nickname", "nickname-value"})); + variableSources.Add(new DictionaryVariableSource(new string[] { "nickname", "nickname-value" })); VariablePlaceholderConfigurer vphc = new VariablePlaceholderConfigurer(variableSources); ac.AddObjectFactoryPostProcessor(vphc); ac.Refresh(); @@ -192,11 +181,11 @@ namespace Spring.Objects.Factory.Config IList variableSources = new ArrayList(); variableSources.Add(new DictionaryVariableSource(new string[] { "name", "name-value", "nickname", null })); - variableSources.Add(new DictionaryVariableSource(new string[] { "nickname", "nickname-value"})); + variableSources.Add(new DictionaryVariableSource(new string[] { "nickname", "nickname-value" })); VariablePlaceholderConfigurer vphc = new VariablePlaceholderConfigurer(variableSources); vphc.PostProcessObjectFactory(of); - RootObjectDefinition rod = (RootObjectDefinition) of.GetObjectDefinition("tb1"); + RootObjectDefinition rod = (RootObjectDefinition)of.GetObjectDefinition("tb1"); Assert.AreEqual("name-value", rod.PropertyValues.GetPropertyValue("NameProperty").Value); Assert.AreEqual(null, rod.PropertyValues.GetPropertyValue("NickNameProperty").Value); } @@ -245,7 +234,7 @@ namespace Spring.Objects.Factory.Config } catch (ObjectDefinitionStoreException ex) { - Assert.IsTrue( ex.Message.IndexOf("nickname") > -1 ); + Assert.IsTrue(ex.Message.IndexOf("nickname") > -1); } } @@ -261,12 +250,12 @@ namespace Spring.Objects.Factory.Config VariablePlaceholderConfigurer vpc = new VariablePlaceholderConfigurer(); vpc.IgnoreUnresolvablePlaceholders = true; - vpc.VariableSource = new DictionaryVariableSource(new string[] {"name", "Erich"}); + vpc.VariableSource = new DictionaryVariableSource(new string[] { "name", "Erich" }); ac.AddObjectFactoryPostProcessor(vpc); ac.Refresh(); - TestObject tb1 = (TestObject) ac.GetObject("tb1"); + TestObject tb1 = (TestObject)ac.GetObject("tb1"); Assert.AreEqual("Erich", tb1.Name); Assert.AreEqual("${nickname}", tb1.Nickname); } diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj index 0969d3c2..78ac3611 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj @@ -324,6 +324,7 @@ + diff --git a/test/Spring/Spring.Messaging.Tests/Messaging/Core/MessageQueueUtils.cs b/test/Spring/Spring.Messaging.Tests/Messaging/Core/MessageQueueUtils.cs index dd8d187c..2fdca74b 100644 --- a/test/Spring/Spring.Messaging.Tests/Messaging/Core/MessageQueueUtils.cs +++ b/test/Spring/Spring.Messaging.Tests/Messaging/Core/MessageQueueUtils.cs @@ -35,17 +35,27 @@ namespace Spring.Messaging.Core MessageQueue.EnableConnectionCache = false; if (MessageQueue.Exists(path)) { - MessageQueue queue; // TODO (EE): delete/create doesn't work for some reason // MessageQueue.Delete(path); // queue = MessageQueue.Create(path, transactional); - queue = new MessageQueue(path); - queue.Purge(); - queue.Dispose(); + using (MessageQueue queue = new MessageQueue(path)) + { + queue.Purge(); + } } else { - MessageQueue.Create(path, transactional).Dispose(); + /* + * MSDN docs indicate that calls to the static .Create() method should include + * an explicit call to .Dispose() b/c unmanaged resources are involved + * Here this req'ment is handled implicitly with the using() statement + * even though the empty using() block seems odd at first glance b/c it + * encloses a static method call + */ + using (MessageQueue.Create(path, transactional)) + { + + } } MessageQueue.ClearConnectionCache(); MessageQueue.EnableConnectionCache = defaultCacheEnabled; // set to default diff --git a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/DistributedTxMessageListenerContainerTests.cs b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/DistributedTxMessageListenerContainerTests.cs index 7e2e9821..ba93916c 100644 --- a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/DistributedTxMessageListenerContainerTests.cs +++ b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/DistributedTxMessageListenerContainerTests.cs @@ -25,6 +25,7 @@ using System.Threading; using NUnit.Framework; using Spring.Messaging.Core; using Spring.Testing.NUnit; +using System; #endregion @@ -48,6 +49,11 @@ namespace Spring.Messaging.Listener { MessageQueueUtils.RecreateMessageQueue(@".\Private$\testtxqueue", true); MessageQueueUtils.RecreateMessageQueue(@".\Private$\testtxretryqueue", true); + + + if (listener != null) + listener.MessageCount = 0; //reset the property between tests b/c the object lifecycle is singleton! + base.SetUp(); } @@ -74,7 +80,7 @@ namespace Spring.Messaging.Listener q.ConvertAndSend("Goodbye World 1"); - Assert.AreEqual(0, listener.MessageCount); + Assert.AreEqual(0, listener.MessageCount, "PRECONDITION FAILURE: Unable to send the message!"); distributedTxMessageListenerContainer.Start(); Thread.Sleep(waitInMillis); @@ -94,23 +100,28 @@ namespace Spring.Messaging.Listener [Test] public void SendAndAsyncReceive() { + const int MESSAGE_COUNT = 5; + //must match the retry count in the object registration for test to pass! + const int EXCEPTION_QUEUE_RETRY_COUNT = 2; MessageQueueTemplate q = applicationContext["queueTemplate"] as MessageQueueTemplate; Assert.IsNotNull(q); - q.ConvertAndSend("Hello World 1"); - q.ConvertAndSend("Hello World 2"); - q.ConvertAndSend("Hello World 3"); - q.ConvertAndSend("Hello World 4"); - q.ConvertAndSend("Hello World 5"); + for (int i = 0; i < MESSAGE_COUNT; i++) + { + q.ConvertAndSend(String.Format("Hello World {0}", (i + 1))); + } Assert.AreEqual(0, listener.MessageCount); distributedTxMessageListenerContainer.Start(); - Thread.Sleep(waitInMillis); - Assert.AreEqual(15, listener.MessageCount); + //this test needs to wait somewhat longer than the others in order to consistently pass so + //artificially inflate the waiting period before attempting subsequent asserts: + Thread.Sleep((int)(waitInMillis * 1.5)); + + Assert.AreEqual(MESSAGE_COUNT + (MESSAGE_COUNT * EXCEPTION_QUEUE_RETRY_COUNT), listener.MessageCount); distributedTxMessageListenerContainer.Stop(); distributedTxMessageListenerContainer.Shutdown(); diff --git a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/NonTransactionalMessageListenerContainerTests.xml b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/NonTransactionalMessageListenerContainerTests.xml index ad8eb5ec..1601f5b5 100644 --- a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/NonTransactionalMessageListenerContainerTests.xml +++ b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/NonTransactionalMessageListenerContainerTests.xml @@ -34,7 +34,7 @@ - + diff --git a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.cs b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.cs index 1d0e9ba2..f2fd2cd3 100644 --- a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.cs +++ b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.cs @@ -62,12 +62,14 @@ namespace Spring.Messaging.Listener set { listener = value; } } - [Test, ExpectedException(typeof(ArgumentException), ExpectedMessage = "Property 'MessageQueueObjectName' is required")] + [Test] public void EnsureMessageQueuePropertyIsSet() { TransactionalMessageListenerContainer container = new TransactionalMessageListenerContainer(); - container.AfterPropertiesSet(); - container.Start(); + + ArgumentException ex = Assert.Throws(() => container.AfterPropertiesSet()); + Assert.AreEqual("Property 'MessageQueueObjectName' is required", ex.Message); + } [Test] @@ -75,12 +77,14 @@ namespace Spring.Messaging.Listener { TransactionalMessageListenerContainer container = applicationContext["transactionalMessageListenerContainer"] as TransactionalMessageListenerContainer; Assert.IsNotNull(container); - Assert.AreEqual(true, container.UseContainerManagedMessageQueueTransaction); + Assert.AreEqual(true, container.UseContainerManagedMessageQueueTransaction); } [Test] public void SendAndAsyncReceiveWithExceptionHandling() { + listener.MessageCount = 0; + MessageQueueTemplate q = applicationContext["queueTemplate"] as MessageQueueTemplate; Assert.IsNotNull(q); @@ -110,28 +114,28 @@ namespace Spring.Messaging.Listener [Test] public void SendAndAsyncReceive() { + listener.MessageCount = 0; - MessageQueueTemplate q = applicationContext["queueTemplate"] as MessageQueueTemplate; Assert.IsNotNull(q); - + q.ConvertAndSend("Hello World 1"); q.ConvertAndSend("Hello World 2"); q.ConvertAndSend("Hello World 3"); q.ConvertAndSend("Hello World 4"); q.ConvertAndSend("Hello World 5"); - + Assert.AreEqual(0, listener.MessageCount); transactionalMessageListenerContainer.Start(); - Thread.Sleep(waitInMillis); + Thread.Sleep(waitInMillis * 2); Assert.AreEqual(5, listener.MessageCount); transactionalMessageListenerContainer.Stop(); transactionalMessageListenerContainer.Shutdown(); Thread.Sleep(2500); - + } diff --git a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.xml b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.xml index 581bf7b4..bbbd0c4d 100644 --- a/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.xml +++ b/test/Spring/Spring.Messaging.Tests/Messaging/Listener/TransactionalMessageListenerContainerTests.xml @@ -5,7 +5,8 @@ + connectionString="Data Source=.\SQLExpress;Initial Catalog=springqa;Persist Security Info=True;User ID=springqa;Password=springqa"/> +