From c62a66a85271a39ca4a698f1ccb0557a9b467767 Mon Sep 17 00:00:00 2001 From: sbohlen Date: Fri, 27 Aug 2010 19:09:47 +0000 Subject: [PATCH] SPRNET-1330 -wrapped modifications to nestingCount in Interlock.Increment and Interlock.Decrement calls -wrapped calls to decrement nestingCount with protection against it decrementing to < 0 --- .../Factory/Support/AbstractObjectFactory.cs | 40 +- .../Factory/AbstractObjectFactoryTests.cs | 703 ++++++++++-------- 2 files changed, 403 insertions(+), 340 deletions(-) diff --git a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs index 9623ba27..6888486a 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Support/AbstractObjectFactory.cs @@ -33,6 +33,7 @@ using Spring.Core.TypeConversion; using Spring.Objects.Factory.Config; using Spring.Threading; using Spring.Util; +using System.Threading; #endregion @@ -1748,7 +1749,7 @@ namespace Spring.Objects.Factory.Support { string objectName = TransformedObjectName(name); - if (ContainsSingleton(objectName) ||ContainsObjectDefinition(objectName)) + if (ContainsSingleton(objectName) || ContainsObjectDefinition(objectName)) { return (!ObjectFactoryUtils.IsFactoryDereference(name) || IsFactoryObject(name)); } @@ -1930,14 +1931,20 @@ namespace Spring.Objects.Factory.Support /// protected object GetObjectInternal(string name, Type requiredType, object[] arguments, bool suppressConfigure) { + object monitor = new object(); const int INDENT = 3; bool hasErrors = false; try { string objectName = TransformedObjectName(name); - - nestingCount++; - +#if NET_1_1 + lock (monitor) + { + nestingCount++; + } +#else + Interlocked.Increment(ref nestingCount); +#endif #region Instrumentation if (log.IsDebugEnabled) { @@ -2035,7 +2042,15 @@ namespace Spring.Objects.Factory.Support } catch { - nestingCount--; + + lock (monitor) + { + if (nestingCount > 0) + { + nestingCount--; + } + } + hasErrors = true; #region Instrumentation if (log.IsErrorEnabled) @@ -2049,7 +2064,13 @@ namespace Spring.Objects.Factory.Support { if (!hasErrors) { - nestingCount--; + lock (monitor) + { + if (nestingCount > 0) + { + nestingCount--; + } + } #region Instrumentation if (log.IsDebugEnabled) { @@ -2060,7 +2081,6 @@ namespace Spring.Objects.Factory.Support } } - [ThreadStatic] private int nestingCount; /// @@ -2074,9 +2094,9 @@ namespace Spring.Objects.Factory.Support /// if is null or not assignable to . /// private object EnsureObjectIsOfRequiredType(string name, object instance, Type requiredType) - { + { // check that any required type matches the type of the actual object instance... - if (requiredType != null && instance!= null && !requiredType.IsAssignableFrom(instance.GetType())) + if (requiredType != null && instance != null && !requiredType.IsAssignableFrom(instance.GetType())) { throw new ObjectNotOfRequiredTypeException(name, requiredType, instance); } @@ -2169,7 +2189,7 @@ namespace Spring.Objects.Factory.Support #endregion this.prototypesInCreation.Dispose(); - + lock (singletonCache) { // copy the keys into a new set, 'cos we are going to modifying the diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs index ae2a824d..2193f1ed 100644 --- a/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs +++ b/test/Spring/Spring.Core.Tests/Objects/Factory/AbstractObjectFactoryTests.cs @@ -25,31 +25,33 @@ using NUnit.Framework; using Spring.Expressions; using Spring.Objects.Factory.Config; using Spring.Objects.Factory.Support; +using Spring.Threading; +using System.Threading; #endregion namespace Spring.Objects.Factory { - /// - /// Subclasses must override SetUp () to initialize the object factory - /// and any other variables they need. - /// - /// Rod Johnson - /// Rick Evans (.NET) - public abstract class AbstractObjectFactoryTests - { - #region Properties + /// + /// Subclasses must override SetUp () to initialize the object factory + /// and any other variables they need. + /// + /// Rod Johnson + /// Rick Evans (.NET) + public abstract class AbstractObjectFactoryTests + { + #region Properties - protected internal abstract AbstractObjectFactory CreateObjectFactory(bool caseSensitive); + protected internal abstract AbstractObjectFactory CreateObjectFactory(bool caseSensitive); - private AbstractObjectFactory cachedFactory; + private AbstractObjectFactory cachedFactory; - protected AbstractObjectFactory ObjectFactory - { - get { return cachedFactory; } + protected AbstractObjectFactory ObjectFactory + { + get { return cachedFactory; } set { cachedFactory = value; } - } - + } + #endregion #region Case Insensitive Tests @@ -70,7 +72,7 @@ namespace Spring.Objects.Factory } catch (ObjectDefinitionStoreException ex) { - Assert.IsTrue( -1 - /// Roderick objects inherits from rod, overriding name only. - /// - [Test] - public void Inheritance() - { - Assert.IsTrue(ObjectFactory.ContainsObject("rod")); - Assert.IsTrue(ObjectFactory.ContainsObject("roderick")); - TestObject rod = (TestObject) ObjectFactory["rod"]; - TestObject roderick = (TestObject) ObjectFactory["roderick"]; - Assert.IsTrue(rod != roderick, "not == "); - Assert.IsTrue(rod.Name.Equals("Rod"), "rod.name is Rod"); - Assert.IsTrue(rod.Age == 31, "rod.age is 31"); - Assert.IsTrue(roderick.Name.Equals("Roderick"), "roderick.name is Roderick"); - Assert.IsTrue(roderick.Age == rod.Age, "roderick.age was inherited"); - } + /// + /// Roderick objects inherits from rod, overriding name only. + /// + [Test] + public void Inheritance() + { + Assert.IsTrue(ObjectFactory.ContainsObject("rod")); + Assert.IsTrue(ObjectFactory.ContainsObject("roderick")); + TestObject rod = (TestObject)ObjectFactory["rod"]; + TestObject roderick = (TestObject)ObjectFactory["roderick"]; + Assert.IsTrue(rod != roderick, "not == "); + Assert.IsTrue(rod.Name.Equals("Rod"), "rod.name is Rod"); + Assert.IsTrue(rod.Age == 31, "rod.age is 31"); + Assert.IsTrue(roderick.Name.Equals("Roderick"), "roderick.name is Roderick"); + Assert.IsTrue(roderick.Age == rod.Age, "roderick.age was inherited"); + } - [Test] - [ExpectedException(typeof (ArgumentNullException))] - public virtual void GetObjectWithNullName() - { - ObjectFactory.GetObject(null); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public virtual void GetObjectWithNullName() + { + ObjectFactory.GetObject(null); + } - /// - /// Test that InitializingObject objects receive the AfterPropertiesSet () callback. - /// - [Test] - public void InitializingObjectCallback() - { - MustBeInitialized mbi = - (MustBeInitialized) ObjectFactory["mustBeInitialized"]; - // The dummy business method will throw an exception if the - // AfterPropertiesSet () callback wasn't invoked - mbi.BusinessMethod(); - } + /// + /// Test that InitializingObject objects receive the AfterPropertiesSet () callback. + /// + [Test] + public void InitializingObjectCallback() + { + MustBeInitialized mbi = + (MustBeInitialized)ObjectFactory["mustBeInitialized"]; + // The dummy business method will throw an exception if the + // AfterPropertiesSet () callback wasn't invoked + mbi.BusinessMethod(); + } - /// - /// Test that InitializingObject/ObjectFactoryAware/DisposableObject objects - /// receive the AfterPropertiesSet () callback before ObjectFactoryAware - /// callbacks. - /// - [Test] - public void LifecycleCallbacks() - { - LifecycleObject lb = (LifecycleObject) ObjectFactory.GetObject("lifecycle"); - Assert.AreEqual("lifecycle", lb.ObjectName); - // The dummy business method will throw an exception if the - // necessary callbacks weren't invoked in the right order - lb.BusinessMethod(); - Assert.IsFalse(lb.Destroyed, "Was destroyed"); - } + /// + /// Test that InitializingObject/ObjectFactoryAware/DisposableObject objects + /// receive the AfterPropertiesSet () callback before ObjectFactoryAware + /// callbacks. + /// + [Test] + public void LifecycleCallbacks() + { + LifecycleObject lb = (LifecycleObject)ObjectFactory.GetObject("lifecycle"); + Assert.AreEqual("lifecycle", lb.ObjectName); + // The dummy business method will throw an exception if the + // necessary callbacks weren't invoked in the right order + lb.BusinessMethod(); + Assert.IsFalse(lb.Destroyed, "Was destroyed"); + } [Test(Description = "SPRNET-1208")] public void AddObjectFactoryOnObjectFactoryAwareObjectPostProcessors() @@ -139,156 +141,156 @@ namespace Spring.Objects.Factory AbstractObjectFactory aof = ObjectFactory; LifecycleObject.PostProcessor lb = new LifecycleObject.PostProcessor(); aof.AddObjectPostProcessor(lb); - Assert.AreSame( aof, lb.ObjectFactory ); + Assert.AreSame(aof, lb.ObjectFactory); } - [Test] - public void FindsValidInstance() - { - object o = ObjectFactory.GetObject("rod"); - Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); - TestObject rod = (TestObject) o; - Assert.IsTrue(rod.Name.Equals("Rod"), "rod.name is Rod"); - Assert.IsTrue(rod.Age == 31, "rod.age is 31"); - } + [Test] + public void FindsValidInstance() + { + object o = ObjectFactory.GetObject("rod"); + Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); + TestObject rod = (TestObject)o; + Assert.IsTrue(rod.Name.Equals("Rod"), "rod.name is Rod"); + Assert.IsTrue(rod.Age == 31, "rod.age is 31"); + } - [Test] - public void GetInstanceByMatchingClass() - { - object o = ObjectFactory.GetObject("rod", typeof (TestObject)); - Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); - } + [Test] + public void GetInstanceByMatchingClass() + { + object o = ObjectFactory.GetObject("rod", typeof(TestObject)); + Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); + } - [Test] - public void GetInstanceByNonmatchingClass() - { - try - { - ObjectFactory.GetObject("rod", typeof (IObjectFactory)); - Assert.Fail("Rod object is not of type IObjectFactory; GetObjectInstance(rod, typeof (IObjectFactory)) should throw ObjectNotOfRequiredTypeException"); - } - catch (ObjectNotOfRequiredTypeException ex) - { - Assert.IsTrue(ex.ObjectName.Equals("rod"), "Exception has correct object name"); - Assert.IsTrue(ex.RequiredType.Equals(typeof (IObjectFactory)), "Exception requiredType must be ObjectFactory.class"); - Assert.IsTrue(typeof (TestObject).IsAssignableFrom(ex.ActualType), "Exception actualType as TestObject.class"); - Assert.IsTrue(ex.ActualInstance == ObjectFactory.GetObject("rod"), "Actual instance is correct"); - } - } + [Test] + public void GetInstanceByNonmatchingClass() + { + try + { + ObjectFactory.GetObject("rod", typeof(IObjectFactory)); + Assert.Fail("Rod object is not of type IObjectFactory; GetObjectInstance(rod, typeof (IObjectFactory)) should throw ObjectNotOfRequiredTypeException"); + } + catch (ObjectNotOfRequiredTypeException ex) + { + Assert.IsTrue(ex.ObjectName.Equals("rod"), "Exception has correct object name"); + Assert.IsTrue(ex.RequiredType.Equals(typeof(IObjectFactory)), "Exception requiredType must be ObjectFactory.class"); + Assert.IsTrue(typeof(TestObject).IsAssignableFrom(ex.ActualType), "Exception actualType as TestObject.class"); + Assert.IsTrue(ex.ActualInstance == ObjectFactory.GetObject("rod"), "Actual instance is correct"); + } + } - [Test] - public virtual void GetSharedInstanceByMatchingClass() - { - object o = ObjectFactory.GetObject("rod", typeof (TestObject)); - Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); - } + [Test] + public virtual void GetSharedInstanceByMatchingClass() + { + object o = ObjectFactory.GetObject("rod", typeof(TestObject)); + Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); + } - [Test] - public virtual void GetSharedInstanceByMatchingClassNoCatch() - { - object o = ObjectFactory.GetObject("rod", typeof (TestObject)); - Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); - } + [Test] + public virtual void GetSharedInstanceByMatchingClassNoCatch() + { + object o = ObjectFactory.GetObject("rod", typeof(TestObject)); + Assert.IsTrue(o is TestObject, "Rod object is a TestObject"); + } - [Test] - public void GetSharedInstanceByNonmatchingClass() - { - try - { - ObjectFactory.GetObject("rod", typeof (IObjectFactory)); - Assert.Fail("Rod object is not of type ObjectFactory; getObjectInstance(rod, ObjectFactory.class) should throw ObjectNotOfRequiredTypeException"); - } - catch (ObjectNotOfRequiredTypeException ex) - { - // So far, so good - Assert.IsTrue(ex.ObjectName.Equals("rod"), "Exception has correct object name"); - Assert.IsTrue(ex.RequiredType.Equals(typeof (IObjectFactory)), "Exception requiredType must be IObjectFactory class"); - Assert.IsTrue(typeof (TestObject).IsAssignableFrom(ex.ActualType), "Exception actualType as TestObject class"); - } - catch (Exception ex) - { - Assert.Fail("Shouldn't throw exception on getting valid instance with matching class : " + ex.Message); - } - } + [Test] + public void GetSharedInstanceByNonmatchingClass() + { + try + { + ObjectFactory.GetObject("rod", typeof(IObjectFactory)); + Assert.Fail("Rod object is not of type ObjectFactory; getObjectInstance(rod, ObjectFactory.class) should throw ObjectNotOfRequiredTypeException"); + } + catch (ObjectNotOfRequiredTypeException ex) + { + // So far, so good + Assert.IsTrue(ex.ObjectName.Equals("rod"), "Exception has correct object name"); + Assert.IsTrue(ex.RequiredType.Equals(typeof(IObjectFactory)), "Exception requiredType must be IObjectFactory class"); + Assert.IsTrue(typeof(TestObject).IsAssignableFrom(ex.ActualType), "Exception actualType as TestObject class"); + } + catch (Exception ex) + { + Assert.Fail("Shouldn't throw exception on getting valid instance with matching class : " + ex.Message); + } + } - [Test] - public virtual void SharedInstancesAreEqual() - { - try - { - object o = ObjectFactory.GetObject("rod"); - Assert.IsTrue(o is TestObject, "Rod object1 is a TestObject"); - object o1 = ObjectFactory.GetObject("rod"); - Assert.IsTrue(o1 is TestObject, "Rod object2 is a TestObject"); - Assert.IsTrue(o == o1, "Object equals applies"); - } - catch - { - Assert.Fail("Shouldn't throw exception on getting valid instance"); - } - } + [Test] + public virtual void SharedInstancesAreEqual() + { + try + { + object o = ObjectFactory.GetObject("rod"); + Assert.IsTrue(o is TestObject, "Rod object1 is a TestObject"); + object o1 = ObjectFactory.GetObject("rod"); + Assert.IsTrue(o1 is TestObject, "Rod object2 is a TestObject"); + Assert.IsTrue(o == o1, "Object equals applies"); + } + catch + { + Assert.Fail("Shouldn't throw exception on getting valid instance"); + } + } - [Test] - [ExpectedException(typeof (NoSuchObjectDefinitionException))] - public void NotThere() - { - Assert.IsFalse(ObjectFactory.ContainsObject("Mr Squiggle")); - ObjectFactory.GetObject("Mr Squiggle"); - } + [Test] + [ExpectedException(typeof(NoSuchObjectDefinitionException))] + public void NotThere() + { + Assert.IsFalse(ObjectFactory.ContainsObject("Mr Squiggle")); + ObjectFactory.GetObject("Mr Squiggle"); + } - [Test] - public void ValidEmpty() - { - try - { - object o = ObjectFactory.GetObject("validEmpty"); - Assert.IsTrue(o is TestObject, "validEmpty object is a TestObject"); - TestObject ve = (TestObject) o; - Assert.IsTrue(ve.Name == null && ve.Age == 0 && ve.Spouse == null, "Valid empty has defaults"); - } - catch - { - Assert.Fail("Shouldn't throw exception on valid empty"); - } - } + [Test] + public void ValidEmpty() + { + try + { + object o = ObjectFactory.GetObject("validEmpty"); + Assert.IsTrue(o is TestObject, "validEmpty object is a TestObject"); + TestObject ve = (TestObject)o; + Assert.IsTrue(ve.Name == null && ve.Age == 0 && ve.Spouse == null, "Valid empty has defaults"); + } + catch + { + Assert.Fail("Shouldn't throw exception on valid empty"); + } + } - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void RegisterNullCustomTypeConverter() - { + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void RegisterNullCustomTypeConverter() + { ObjectFactory.RegisterCustomConverter(null, null); - } + } - [Test] - public virtual void TypeMismatch() - { - try - { - ObjectFactory.GetObject("typeMismatch"); - Assert.Fail("Shouldn't succeed with type mismatch"); - } - catch (ObjectCreationException wex) - { - Assert.IsTrue(wex.InnerException is PropertyAccessExceptionsException); - PropertyAccessExceptionsException ex = (PropertyAccessExceptionsException) wex.InnerException; - // Furthers - Assert.IsTrue(ex.ExceptionCount == 1, "Has one error"); - Assert.IsTrue(ex.GetPropertyAccessException("age") != null, "Error is for field age"); + [Test] + public virtual void TypeMismatch() + { + try + { + ObjectFactory.GetObject("typeMismatch"); + Assert.Fail("Shouldn't succeed with type mismatch"); + } + catch (ObjectCreationException wex) + { + Assert.IsTrue(wex.InnerException is PropertyAccessExceptionsException); + PropertyAccessExceptionsException ex = (PropertyAccessExceptionsException)wex.InnerException; + // Furthers + Assert.IsTrue(ex.ExceptionCount == 1, "Has one error"); + Assert.IsTrue(ex.GetPropertyAccessException("age") != null, "Error is for field age"); - TestObject tb = (TestObject) ex.ObjectWrapper.WrappedInstance; - Assert.IsTrue(tb.Age == 0, "Age still has default"); - Assert.IsTrue(ex.GetPropertyAccessException("age").PropertyChangeArgs.NewValue.Equals("34x"), "We have rejected age in exception"); - Assert.IsTrue(tb.Name.Equals("typeMismatch"), "valid name stuck"); - Assert.IsTrue(tb.Spouse.Name.Equals("Rod"), "valid spouse stuck"); - } - } + TestObject tb = (TestObject)ex.ObjectWrapper.WrappedInstance; + Assert.IsTrue(tb.Age == 0, "Age still has default"); + Assert.IsTrue(ex.GetPropertyAccessException("age").PropertyChangeArgs.NewValue.Equals("34x"), "We have rejected age in exception"); + Assert.IsTrue(tb.Name.Equals("typeMismatch"), "valid name stuck"); + Assert.IsTrue(tb.Spouse.Name.Equals("Rod"), "valid spouse stuck"); + } + } - [Test] - public virtual void GrandParentDefinitionFoundInObjectFactory() - { - TestObject dad = (TestObject) ObjectFactory.GetObject("father"); - Assert.IsTrue(dad.Name.Equals("Albert"), "Dad has correct name"); - } + [Test] + public virtual void GrandParentDefinitionFoundInObjectFactory() + { + TestObject dad = (TestObject)ObjectFactory.GetObject("father"); + Assert.IsTrue(dad.Name.Equals("Albert"), "Dad has correct name"); + } [Test] public virtual void GrandParentDefinitionFoundInObjectFactoryWithType() @@ -300,7 +302,7 @@ namespace Spring.Objects.Factory [Test] public virtual void GrandParentDefinitionFoundInObjectFactoryWithArguments() { - TestObject dad = (TestObject)ObjectFactory.GetObject("namedfather", new object[] { "Hugo", 65 } ); + TestObject dad = (TestObject)ObjectFactory.GetObject("namedfather", new object[] { "Hugo", 65 }); Assert.AreEqual("Hugo", dad.Name, "Dad has not correct name"); Assert.AreEqual(65, dad.Age, "Dad has not correct age"); } @@ -313,7 +315,7 @@ namespace Spring.Objects.Factory Assert.AreEqual(66, dad.Age, "Dad has not correct age"); } - [Test(Description="Extra check that the type is really passed on to the parent factory")] + [Test(Description = "Extra check that the type is really passed on to the parent factory")] public virtual void GrandParentDefinitionFoundInObjectFactoryWithTypeAndArgumentsWithWrongType() { try @@ -322,102 +324,102 @@ namespace Spring.Objects.Factory Assert.Fail("should throw ObjectNotOfRequiredTypeException"); } catch (ObjectNotOfRequiredTypeException) - { + { } } - [Test] - public virtual void FactorySingleton() - { - Assert.IsTrue(ObjectFactory.IsSingleton("&singletonFactory")); - Assert.IsTrue(ObjectFactory.IsSingleton("singletonFactory")); - TestObject tb = (TestObject) ObjectFactory.GetObject("singletonFactory"); - Assert.IsTrue(tb.Name.Equals(DummyFactory.SINGLETON_NAME), "Singleton from factory has correct name, not " + tb.Name); - DummyFactory factory = (DummyFactory) ObjectFactory.GetObject("&singletonFactory"); - TestObject tb2 = (TestObject) ObjectFactory.GetObject("singletonFactory"); - Assert.IsTrue(tb == tb2, "Singleton references =="); - Assert.IsTrue(factory.ObjectFactory != null, "FactoryObject is ObjectFactoryAware"); - } + [Test] + public virtual void FactorySingleton() + { + Assert.IsTrue(ObjectFactory.IsSingleton("&singletonFactory")); + Assert.IsTrue(ObjectFactory.IsSingleton("singletonFactory")); + TestObject tb = (TestObject)ObjectFactory.GetObject("singletonFactory"); + Assert.IsTrue(tb.Name.Equals(DummyFactory.SINGLETON_NAME), "Singleton from factory has correct name, not " + tb.Name); + DummyFactory factory = (DummyFactory)ObjectFactory.GetObject("&singletonFactory"); + TestObject tb2 = (TestObject)ObjectFactory.GetObject("singletonFactory"); + Assert.IsTrue(tb == tb2, "Singleton references =="); + Assert.IsTrue(factory.ObjectFactory != null, "FactoryObject is ObjectFactoryAware"); + } - [Test] - public virtual void FactoryPrototype() - { - Assert.IsTrue(ObjectFactory.IsSingleton("&prototypeFactory")); - Assert.IsFalse(ObjectFactory.IsSingleton("prototypeFactory")); - TestObject tb = (TestObject) ObjectFactory.GetObject("prototypeFactory"); - Assert.IsTrue(!tb.Name.Equals(DummyFactory.SINGLETON_NAME)); - TestObject tb2 = (TestObject) ObjectFactory.GetObject("prototypeFactory"); - Assert.IsTrue(tb != tb2, "Prototype references !="); - } + [Test] + public virtual void FactoryPrototype() + { + Assert.IsTrue(ObjectFactory.IsSingleton("&prototypeFactory")); + Assert.IsFalse(ObjectFactory.IsSingleton("prototypeFactory")); + TestObject tb = (TestObject)ObjectFactory.GetObject("prototypeFactory"); + Assert.IsTrue(!tb.Name.Equals(DummyFactory.SINGLETON_NAME)); + TestObject tb2 = (TestObject)ObjectFactory.GetObject("prototypeFactory"); + Assert.IsTrue(tb != tb2, "Prototype references !="); + } - /// - /// Check that we can get the factory object itself. - /// This is only possible if we're dealing with a factory - /// - [Test] - public virtual void GetFactoryItself() - { - DummyFactory factory = (DummyFactory) ObjectFactory.GetObject("&singletonFactory"); - Assert.IsTrue(factory != null); - } + /// + /// Check that we can get the factory object itself. + /// This is only possible if we're dealing with a factory + /// + [Test] + public virtual void GetFactoryItself() + { + DummyFactory factory = (DummyFactory)ObjectFactory.GetObject("&singletonFactory"); + Assert.IsTrue(factory != null); + } - /// Check that AfterPropertiesSet gets called on factory. - [Test] - public virtual void FactoryIsInitialized() - { - TestObject tb = (TestObject) ObjectFactory.GetObject("singletonFactory"); - DummyFactory factory = (DummyFactory) ObjectFactory.GetObject("&singletonFactory"); - Assert.IsTrue(factory.WasInitialized, "Factory was not initialized even though it implemented IInitializingObject"); - } + /// Check that AfterPropertiesSet gets called on factory. + [Test] + public virtual void FactoryIsInitialized() + { + TestObject tb = (TestObject)ObjectFactory.GetObject("singletonFactory"); + DummyFactory factory = (DummyFactory)ObjectFactory.GetObject("&singletonFactory"); + Assert.IsTrue(factory.WasInitialized, "Factory was not initialized even though it implemented IInitializingObject"); + } - /// - /// It should be illegal to dereference a normal object as a factory. - /// - [Test] - [ExpectedException(typeof (ObjectIsNotAFactoryException))] - public virtual void RejectsFactoryGetOnNormalObject() - { - ObjectFactory.GetObject("&rod"); - } + /// + /// It should be illegal to dereference a normal object as a factory. + /// + [Test] + [ExpectedException(typeof(ObjectIsNotAFactoryException))] + public virtual void RejectsFactoryGetOnNormalObject() + { + ObjectFactory.GetObject("&rod"); + } - [Test] - [ExpectedException(typeof (ObjectDefinitionStoreException))] - public virtual void Aliasing() - { - string alias = "rods alias"; - try - { - ObjectFactory.GetObject(alias); - Assert.Fail("Shouldn't permit factory get on normal object"); - } - catch (NoSuchObjectDefinitionException ex) - { - Assert.IsTrue(alias.Equals(ex.ObjectName)); - } + [Test] + [ExpectedException(typeof(ObjectDefinitionStoreException))] + public virtual void Aliasing() + { + string alias = "rods alias"; + try + { + ObjectFactory.GetObject(alias); + Assert.Fail("Shouldn't permit factory get on normal object"); + } + catch (NoSuchObjectDefinitionException ex) + { + Assert.IsTrue(alias.Equals(ex.ObjectName)); + } - // Create alias - ObjectFactory.RegisterAlias("rod", alias); - object rod = ObjectFactory.GetObject("rod"); - object aliasRod = ObjectFactory.GetObject(alias); - Assert.IsTrue(rod == aliasRod); - ObjectFactory.RegisterAlias("father", alias); - } + // Create alias + ObjectFactory.RegisterAlias("rod", alias); + object rod = ObjectFactory.GetObject("rod"); + object aliasRod = ObjectFactory.GetObject(alias); + Assert.IsTrue(rod == aliasRod); + ObjectFactory.RegisterAlias("father", alias); + } - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void RegisterSingletonWithEmptyName() - { - ((AbstractObjectFactory) ObjectFactory) - .RegisterSingleton(Environment.NewLine, DBNull.Value); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void RegisterSingletonWithEmptyName() + { + ((AbstractObjectFactory)ObjectFactory) + .RegisterSingleton(Environment.NewLine, DBNull.Value); + } - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void RegisterSingletonWithNullName() - { - ((AbstractObjectFactory) ObjectFactory) - .RegisterSingleton(null, DBNull.Value); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void RegisterSingletonWithNullName() + { + ((AbstractObjectFactory)ObjectFactory) + .RegisterSingleton(null, DBNull.Value); + } #if NET_2_0 [Test] @@ -428,60 +430,60 @@ namespace Spring.Objects.Factory of.RegisterSingleton("A", new object()); of.RegisterSingleton("C", new object()); of.RegisterSingleton("B", new object()); - Assert.AreEqual(new string[] { "A", "C", "B"}, of.GetSingletonNames()); + Assert.AreEqual(new string[] { "A", "C", "B" }, of.GetSingletonNames()); of = CreateObjectFactory(false); of.RegisterSingleton("A", new object()); of.RegisterSingleton("C", new object()); of.RegisterSingleton("B", new object()); - Assert.AreEqual(new string[] { "A", "C", "B"}, of.GetSingletonNames(typeof(object))); + Assert.AreEqual(new string[] { "A", "C", "B" }, of.GetSingletonNames(typeof(object))); } #endif - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void ContainsSingletonWithEmptyName() - { - ((AbstractObjectFactory) ObjectFactory) - .ContainsSingleton(Environment.NewLine); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void ContainsSingletonWithEmptyName() + { + ((AbstractObjectFactory)ObjectFactory) + .ContainsSingleton(Environment.NewLine); + } - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void ContainsSingletonWithNullName() - { - ((AbstractObjectFactory) ObjectFactory) - .ContainsSingleton(null); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void ContainsSingletonWithNullName() + { + ((AbstractObjectFactory)ObjectFactory) + .ContainsSingleton(null); + } - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void AliasWithEmptyName() - { - ((AbstractObjectFactory) ObjectFactory).RegisterAlias(Environment.NewLine, "the whipping boy"); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void AliasWithEmptyName() + { + ((AbstractObjectFactory)ObjectFactory).RegisterAlias(Environment.NewLine, "the whipping boy"); + } - [Test] - [ExpectedException(typeof(ArgumentNullException))] - public void AliasWithEmptyAlias() - { - ((AbstractObjectFactory) ObjectFactory).RegisterAlias("rick", Environment.NewLine); - } + [Test] + [ExpectedException(typeof(ArgumentNullException))] + public void AliasWithEmptyAlias() + { + ((AbstractObjectFactory)ObjectFactory).RegisterAlias("rick", Environment.NewLine); + } -// [Test] -// [ExpectedException(typeof(ObjectDefinitionStoreException))] -// public void ChokesIfNotGivenSupportedIObjectDefinitionImplementation() -// { -// ObjectFactory.GetObject("unsupportedDefinition"); -// } + // [Test] + // [ExpectedException(typeof(ObjectDefinitionStoreException))] + // public void ChokesIfNotGivenSupportedIObjectDefinitionImplementation() + // { + // ObjectFactory.GetObject("unsupportedDefinition"); + // } /// /// This test resembles a scenario that may happen e.g. using ProxyFactoryObject proxying sibling objects with cyclic dependencies /// - [Test] - public void CanResolveCyclicSingletonFactoryObjectProductDependencies() - { - AbstractObjectFactory of = this.CreateObjectFactory(true); + [Test] + public void CanResolveCyclicSingletonFactoryObjectProductDependencies() + { + AbstractObjectFactory of = this.CreateObjectFactory(true); GenericObjectDefinition od = new GenericObjectDefinition(); od.ObjectTypeName = typeof(TestObject).FullName; @@ -498,11 +500,11 @@ namespace Spring.Objects.Factory of.RegisterSingleton("product1", new ObjectReferenceFactoryObject("product1Target", of)); of.RegisterSingleton("product2", new ObjectReferenceFactoryObject("product2Target", of)); - TestObject to = (TestObject) of.GetObject("product1"); + TestObject to = (TestObject)of.GetObject("product1"); Assert.NotNull(to); Assert.NotNull(to.Spouse); - Assert.NotNull( ((TestObject)to.Spouse).Sibling); - } + Assert.NotNull(((TestObject)to.Spouse).Sibling); + } [Test] public void ThrowsOnCyclicDependenciesOnNonSingletons() @@ -531,5 +533,46 @@ namespace Spring.Objects.Factory Assert.AreEqual("product1", ex.ObjectName); } } - } + + private void GetTheTestObject() + { + if (DateTime.Now.Millisecond % 2 == 0) + { + ObjectFactory.GetObject("theObject"); + } + else + { + ObjectFactory.GetObject("theSpouse"); + } + } + + [Test] + public void GetObjectIsThreadSafe() + { + ObjectFactory = CreateObjectFactory(true); + + GenericObjectDefinition theSpouse = new GenericObjectDefinition(); + theSpouse.ObjectTypeName = typeof(TestObject).FullName; + theSpouse.IsSingleton = false; + ObjectFactory.RegisterObjectDefinition("theSpouse", theSpouse); + + + GenericObjectDefinition theObject = new GenericObjectDefinition(); + theObject.ObjectTypeName = typeof(TestObject).FullName; + theObject.IsSingleton = false; + theObject.PropertyValues.Add("Spouse", theSpouse); + ObjectFactory.RegisterObjectDefinition("theObject", theObject); + + AsyncTestTask t1 = new AsyncTestMethod(20000, new ThreadStart(GetTheTestObject)).Start(); + AsyncTestTask t2 = new AsyncTestMethod(20000, new ThreadStart(GetTheTestObject)).Start(); + AsyncTestTask t3 = new AsyncTestMethod(20000, new ThreadStart(GetTheTestObject)).Start(); + AsyncTestTask t4 = new AsyncTestMethod(20000, new ThreadStart(GetTheTestObject)).Start(); + + t1.AssertNoException(); + t2.AssertNoException(); + t3.AssertNoException(); + t4.AssertNoException(); + } + + } } \ No newline at end of file