public void TestConstructorWithAlreadyEndedTransaction()
        {
            WeightedTransaction <Transaction> testTransaction = new WeightedTransaction <Transaction>(
                Transaction.EndedDummy
                );

            IObservationSubscriber subscriber = this.mockery.NewMock <IObservationSubscriber>();

            Expect.AtLeast(0).On(subscriber).Method("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.
            Expect.Never.On(subscriber).Method("Ended");

            using (
                ObservedWeightedTransaction <Transaction> test =
                    new ObservedWeightedTransaction <Transaction>(
                        testTransaction,
                        new ObservedWeightedTransaction <Transaction> .ReportDelegate(
                            subscriber.ProgressUpdated
                            ),
                        new ObservedWeightedTransaction <Transaction> .ReportDelegate(
                            subscriber.Ended
                            )
                        )
                ) {
                this.mockery.VerifyAllExpectationsHaveBeenMet();
            }
        }
        public void TestConstructorWithEndingTransaction()
        {
            WeightedTransaction <Transaction> testTransaction = new WeightedTransaction <Transaction>(
                new FunkyTransaction()
                );

            IObservationSubscriber subscriber = this.mockery.NewMock <IObservationSubscriber>();

            Expect.AtLeast(0).On(subscriber).Method("ProgressUpdated");
            Expect.Once.On(subscriber).Method("Ended");

            using (
                ObservedWeightedTransaction <Transaction> test =
                    new ObservedWeightedTransaction <Transaction>(
                        testTransaction,
                        new ObservedWeightedTransaction <Transaction> .ReportDelegate(
                            subscriber.ProgressUpdated
                            ),
                        new ObservedWeightedTransaction <Transaction> .ReportDelegate(
                            subscriber.Ended
                            )
                        )
                ) {
                this.mockery.VerifyAllExpectationsHaveBeenMet();
            }
        }
        public void TestConstructorWithEndingTransaction()
        {
            WeightedTransaction <Transaction> testTransaction = new WeightedTransaction <Transaction>(
                new FunkyTransaction()
                );

            Mock <IObservationSubscriber> subscriber = this.mockery.CreateMock <IObservationSubscriber>();

            subscriber.Expects.AtLeast(0).Method(m => m.ProgressUpdated());
            subscriber.Expects.One.Method(m => m.Ended());

            using (
                ObservedWeightedTransaction <Transaction> test =
                    new ObservedWeightedTransaction <Transaction>(
                        testTransaction,
                        new ObservedWeightedTransaction <Transaction> .ReportDelegate(
                            subscriber.MockObject.ProgressUpdated
                            ),
                        new ObservedWeightedTransaction <Transaction> .ReportDelegate(
                            subscriber.MockObject.Ended
                            )
                        )
                ) {
                this.mockery.VerifyAllExpectationsHaveBeenMet();
            }
        }
        /// <summary>Stops tracking the specified background transaction</summary>
        /// <param name="transaction">Background transaction to stop tracking of</param>
        public void Untrack(Transaction transaction)
        {
            lock (this.trackedTransactions) {
                // Locate the object to be untracked in our collection
                int index;
                for (index = 0; index < this.trackedTransactions.Count; ++index)
                {
                    bool same = ReferenceEquals(
                        transaction,
                        this.trackedTransactions[index].WeightedTransaction.Transaction
                        );
                    if (same)
                    {
                        break;
                    }
                }
                if (index == this.trackedTransactions.Count)
                {
                    throw new ArgumentException("Specified transaction is not being tracked");
                }

                // Remove and dispose the transaction the user wants to untrack
                {
                    ObservedWeightedTransaction <Transaction> wrappedTransaction =
                        this.trackedTransactions[index];

                    this.trackedTransactions.RemoveAt(index);
                    wrappedTransaction.Dispose();
                }

                // If the list is empty, then we're back in the idle state
                if (this.trackedTransactions.Count == 0)
                {
                    this.totalWeight = 0.0f;

                    // If we entered the idle state with this call, report the state change!
                    setIdle(true);
                }
                else
                {
                    // Rebuild the total weight from scratch. Subtracting the removed transaction's
                    // weight would work, too, but we might accumulate rounding errors making the sum
                    // drift slowly away from the actual value.
                    float newTotalWeight = 0.0f;
                    for (index = 0; index < this.trackedTransactions.Count; ++index)
                    {
                        newTotalWeight += this.trackedTransactions[index].WeightedTransaction.Weight;
                    }

                    this.totalWeight = newTotalWeight;

                    recalculateProgress();
                }
            } // lock
        }
Beispiel #5
0
        public void TestWrapperCollection()
        {
            WeightedTransaction <Transaction> transaction = new WeightedTransaction <Transaction>(
                Transaction.EndedDummy
                );

            ObservedWeightedTransaction <Transaction> observed =
                new ObservedWeightedTransaction <Transaction>(
                    transaction,
                    endedCallback,
                    progressUpdatedCallback
                    );

            WeightedTransactionWrapperCollection <Transaction> wrapper =
                new WeightedTransactionWrapperCollection <Transaction>(
                    new ObservedWeightedTransaction <Transaction>[] { observed }
                    );

            Assert.AreSame(transaction, wrapper[0]);
        }
 /// <summary>
 ///   Checks whether the provided transaction matches the comparison
 ///   transaction of the instance
 /// </summary>
 /// <param name="other">Transaction to match to the comparison transaction</param>
 public bool Matches(ObservedWeightedTransaction <Transaction> other)
 {
     return(ReferenceEquals(other.WeightedTransaction.Transaction, this.toMatch));
 }
        /// <summary>Begins tracking the specified background transaction</summary>
        /// <param name="transaction">Background transaction to be tracked</param>
        /// <param name="weight">Weight to assign to this background transaction</param>
        public void Track(Transaction transaction, float weight)
        {
            // Add the new transaction into the tracking list. This has to be done
            // inside a lock to prevent issues with the progressUpdate callback, which could
            // access the totalWeight field before it has been updated to reflect the
            // new transaction added to the collection.
            lock (this.trackedTransactions) {
                bool wasEmpty = (this.trackedTransactions.Count == 0);

                if (transaction.Ended)
                {
                    // If the ended transaction would become the only transaction in the list,
                    // there's no sense in doing anything at all because it would have to be
                    // thrown right out again. Only add the transaction when there are other
                    // running transactions to properly sum total progress for consistency.
                    if (!wasEmpty)
                    {
                        // Construct a new observation wrapper. This is done inside the lock
                        // because as soon as we are subscribed to the events, we can potentially
                        // receive them. The lock eliminates the risk of processing a progress update
                        // before the transaction has been added to the tracked transactions list.
                        this.trackedTransactions.Add(
                            new ObservedWeightedTransaction <Transaction>(
                                new WeightedTransaction <Transaction>(transaction, weight),
                                this.asyncProgressUpdatedDelegate,
                                this.asyncEndedDelegate
                                )
                            );
                    }
                }
                else // Not ended -- Transaction is still running

                // Construct a new transation observer and add the transaction to our
                // list of tracked transactions.
                {
                    ObservedWeightedTransaction <Transaction> observedTransaction =
                        new ObservedWeightedTransaction <Transaction>(
                            new WeightedTransaction <Transaction>(transaction, weight),
                            this.asyncProgressUpdatedDelegate,
                            this.asyncEndedDelegate
                            );

                    this.trackedTransactions.Add(observedTransaction);

                    // If this is the first transaction to be added to the list, tell our
                    // owner that we're idle no longer!
                    if (wasEmpty)
                    {
                        setIdle(false);
                    }
                } // if transaction ended

                // This can be done after we registered the wrapper to our delegates because
                // any incoming progress updates will be stopped from the danger of a
                // division-by-zero from the potentially still zeroed totalWeight by the lock.
                this.totalWeight += weight;

                // All done, the total progress is different now, so force a recalculation and
                // send out the AsyncProgressUpdated event.
                recalculateProgress();
            } // lock
        }
Beispiel #8
0
 /// <summary>Transforms an item into the exposed type</summary>
 /// <param name="item">Item to be transformed</param>
 /// <returns>The transformed item</returns>
 /// <remarks>
 ///   This method is used to transform an item in the wrapped collection into
 ///   the exposed item type whenever the user accesses an item. Expect it to
 ///   be called frequently, because the TransformingReadOnlyCollection does
 ///   not cache otherwise store the transformed items.
 /// </remarks>
 protected override WeightedTransaction <TransactionType> Transform(
     ObservedWeightedTransaction <TransactionType> item
     )
 {
     return(item.WeightedTransaction);
 }