#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2010 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.IO;
using System.Threading;
#if UNITTEST
using NUnit.Framework;
using NMock;
namespace Nuclex.Support.Tracking {
/// Unit Test for the observation wrapper of weighted transactions
[TestFixture]
public class ObservedWeightedTransactionTest {
#region interface IObservationSubscriber
///
/// Interface used to test the observation wrapper of weighted transactions
///
public interface IObservationSubscriber {
/// Will be invoked when an observed transaction's progress changes
void ProgressUpdated();
/// Will be invoked when an observed transaction completes
void Ended();
}
#endregion // interface IObservationSubscriber
#region class FunkyTransaction
///
/// Transaction that goes into the 'ended' state as soon as someone registers for
/// state change notifications
///
private class FunkyTransaction : Transaction {
/// Manages registrations to the AsyncEnded event
public override event EventHandler AsyncEnded {
add {
base.AsyncEnded += value;
// To deterministically provoke an 'Ended' event just after registration we
// will switch the transaction into the 'ended' state right here
int oldValue = Interlocked.Exchange(ref this.alreadyEnded, 1);
if(oldValue != 1) {
OnAsyncEnded();
}
}
remove {
base.AsyncEnded -= value;
}
}
/// Whether the transaction has already been ended
private int alreadyEnded;
}
#endregion // class FunkyTransaction
/// Initialization routine executed before each test is run
[SetUp]
public void Setup() {
this.mockery = new MockFactory();
}
/// Verifies that the constructor of the observation wrapper works
[Test]
public void TestConstructorWithAlreadyEndedTransaction() {
WeightedTransaction testTransaction = new WeightedTransaction(
Transaction.EndedDummy
);
Mock subscriber = this.mockery.CreateMock();
subscriber.Expects.AtLeast(0).Method(m => m.ProgressUpdated());
// This should no be called because otherwise, the 'Ended' event would be raised
// to the transaction group before all transactions have been added into
// the internal list, leading to an early ending or even multiple endings.
subscriber.Expects.No.Method(m => m.Ended());
using(
ObservedWeightedTransaction test =
new ObservedWeightedTransaction(
testTransaction,
new ObservedWeightedTransaction.ReportDelegate(
subscriber.MockObject.ProgressUpdated
),
new ObservedWeightedTransaction.ReportDelegate(
subscriber.MockObject.Ended
)
)
) {
this.mockery.VerifyAllExpectationsHaveBeenMet();
}
}
///
/// Verifies that the constructor of the observation wrapper can handle a transaction
/// entering the 'ended' state right on subscription
///
[Test]
public void TestConstructorWithEndingTransaction() {
WeightedTransaction testTransaction = new WeightedTransaction(
new FunkyTransaction()
);
Mock subscriber = this.mockery.CreateMock();
subscriber.Expects.AtLeast(0).Method(m => m.ProgressUpdated());
subscriber.Expects.One.Method(m => m.Ended());
using(
ObservedWeightedTransaction test =
new ObservedWeightedTransaction(
testTransaction,
new ObservedWeightedTransaction.ReportDelegate(
subscriber.MockObject.ProgressUpdated
),
new ObservedWeightedTransaction.ReportDelegate(
subscriber.MockObject.Ended
)
)
) {
this.mockery.VerifyAllExpectationsHaveBeenMet();
}
}
/// Mock object factory
private MockFactory mockery;
}
} // namespace Nuclex.Support.Tracking
#endif // UNITTEST