/*
* Copyright 2002-2004 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.
*/
using System;
using System.IO;
using System.Reflection;
using System.Threading;
using Common.Logging;
using NUnit.Framework;
using Spring.Objects;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Xml;
namespace Spring.Aop.Target{
/// <author>Rod Johnson</author>
/// <author>Federico Spinazzi</author>
[TestFixture]
public class ThreadLocalTargetSourceTests
{
/// <summary>Initial count value set in Object factory XML </summary>
private const int INITIAL_COUNT = 10;
private XmlObjectFactory ObjectFactory;
private ILog log;
[SetUp]
public void SetUp ()
{
this.ObjectFactory = new XmlObjectFactory (
new ReadOnlyXmlTestResource ("threadLocalTests.xml", GetType ()));
//TODO-LOGGING XmlConfigurator.Configure (new FileInfo ("Spring.Aop.Tests.dll.config"));
log = LogManager.GetLogger (MethodBase.GetCurrentMethod ().DeclaringType);
}
/// <summary> We must simulate container shutdown, which should clear threads.</summary>
[TearDown]
public void TearDown ()
{
this.ObjectFactory.Dispose ();
}
/// <summary> Check we can use two different ThreadLocalTargetSources
/// managing objects of different types without them interfering
/// with one another.
/// </summary>
[Test]
public virtual void UseDifferentManagedInstancesInSameThread ()
{
ISideEffectObject apartment = (ISideEffectObject) ObjectFactory.GetObject ("apartment");
Assert.AreEqual (INITIAL_COUNT, apartment.Count);
apartment.doWork ();
Assert.AreEqual (INITIAL_COUNT + 1, apartment.Count);
ITestObject test = (ITestObject) ObjectFactory.GetObject ("threadLocal2");
Assert.AreEqual ("Rod", test.Name);
Assert.AreEqual ("Kerry", test.Spouse.Name);
}
[Test]
public virtual void ReuseInSameThread ()
{
ISideEffectObject apartment = (ISideEffectObject) ObjectFactory.GetObject ("apartment");
Assert.AreEqual (INITIAL_COUNT, apartment.Count);
apartment.doWork ();
Assert.AreEqual (INITIAL_COUNT + 1, apartment.Count);
apartment = (ISideEffectObject) ObjectFactory.GetObject ("apartment");
Assert.AreEqual (INITIAL_COUNT + 1, apartment.Count);
}
/// <summary> Relies on introduction
///
/// </summary>
[Test]
public virtual void CanGetStatsViaMixinIfThereIsAnInterceptorTakingCareOfThem ()
{
IThreadLocalTargetSourceStats stats = (IThreadLocalTargetSourceStats) ObjectFactory.GetObject ("apartment");
Assert.AreEqual (0, stats.Invocations);
ISideEffectObject apartment = (ISideEffectObject) ObjectFactory.GetObject ("apartment");
apartment.doWork ();
Assert.AreEqual (1, stats.Invocations);
Assert.AreEqual (0, stats.Hits);
apartment.doWork ();
Assert.AreEqual (2, stats.Invocations);
Assert.AreEqual (1, stats.Hits);
// Only one thread so only one object can have been bound
Assert.AreEqual (1, stats.Objects);
}
public class Runner
{
private ILog log = LogManager.GetLogger (MethodBase.GetCurrentMethod ().DeclaringType);
private ThreadLocalTargetSourceTests factory;
public ISideEffectObject mine;
public Runner (ThreadLocalTargetSourceTests enclosingInstance)
{
this.factory = enclosingInstance;
}
public virtual void Run ()
{
log.Debug ("getting object");
this.mine = (ISideEffectObject) factory.ObjectFactory.GetObject ("apartment");
log.Debug (String.Format ("got object; hash code: {0}", this.mine.GetHashCode ()));
Assert.AreEqual (ThreadLocalTargetSourceTests.INITIAL_COUNT, mine.Count);
mine.doWork ();
Assert.AreEqual (ThreadLocalTargetSourceTests.INITIAL_COUNT + 1, mine.Count);
}
}
[Test]
public virtual void NewThreadHasOwnInstance ()
{
ISideEffectObject apartment = (ISideEffectObject) ObjectFactory.GetObject ("apartment");
log.Debug (String.Format ("got object; hash code: {0}", apartment.GetHashCode ()));
Assert.AreEqual (INITIAL_COUNT, apartment.Count);
apartment.doWork ();
apartment.doWork ();
apartment.doWork ();
Assert.AreEqual (INITIAL_COUNT + 3, apartment.Count);
Runner r = new Runner (this);
Thread t = new Thread (new ThreadStart (r.Run));
t.Start ();
t.Join ();
Assert.IsNotNull (r);
// Check it didn't affect the other thread's copy
Assert.AreEqual (INITIAL_COUNT + 3, apartment.Count);
// When we use other thread's copy in this thread
// it should behave like ours
Assert.AreEqual (INITIAL_COUNT + 3, r.mine.Count);
// Bound to two threads
Assert.AreEqual (2, ((IThreadLocalTargetSourceStats) apartment).Objects);
}
}
}
|