public void TransactionalStack1()
        {
            var stack = new TransactionalStack<int>();
            stack.Push(1);
            stack.Push(2);
            stack.Push(3);
            Assert.IsFalse(stack.IsEmpty);
            var t = stack.BeginTransaction();
            Assert.AreEqual(3, t.Top);
            Assert.AreEqual(3, t.Pop());
            Assert.AreEqual(2, t.Pop());
            Assert.AreEqual(1, t.Pop());
            Assert.AreEqual(3, stack.Top);
            Assert.IsTrue(t.IsEmpty);
            Assert.IsFalse(stack.IsEmpty);
            t.Commit();
            Assert.IsTrue(stack.IsEmpty);
            Helpers.AssertionHelpers.AssertThrows<Exception>(() => stack.Pop());
            Helpers.AssertionHelpers.AssertThrows<Exception>(() => t.Pop());

            stack = new TransactionalStack<int>();
            t = stack.BeginTransaction();
            t.Push(1);
            t.Push(2);
            t.Push(3);
            Assert.IsTrue(stack.IsEmpty);
            Assert.IsFalse(t.IsEmpty);
            Assert.AreEqual(3, t.Top);
            Assert.AreEqual(3, t.Pop());
            t.Commit();
            Assert.AreEqual(2, stack.Top);

            stack = new TransactionalStack<int>();
            t = stack.BeginTransaction();
            t.Push(1);
            t.Push(2);
            t.Push(3);
            t.Commit();
            var verifier = stack.BeginTransaction();
            Assert.AreEqual(3, verifier.Pop());
            Assert.AreEqual(2, verifier.Pop());
            Assert.AreEqual(1, verifier.Pop());
            var modifier = stack.BeginTransaction();
            modifier.Pop();
            modifier.Pop();
            modifier.Pop();
            modifier.Push(5);
            modifier.Push(6);
            modifier.Push(7);
            modifier.Commit();
            Assert.AreEqual(7, stack.Pop());
            Assert.AreEqual(6, stack.Pop());
            Assert.AreEqual(5, stack.Pop());
        }
        public void TransactionalStack5()
        {
            var stack = new TransactionalStack<int>();

            stack.Push(1);
            stack.Push(2);
            stack.Push(3);

            var t1 = stack.BeginTransaction();

            t1.Pop();
            t1.Pop();
            t1.Push(10);
            t1.Push(15);

            var list = t1.AsEnumerable().ToList();

            Assert.AreEqual(15, list[0]);
            Assert.AreEqual(10, list[1]);
            Assert.AreEqual(1, list[2]);

            t1.Commit();

            var list2 = stack.AsEnumerable().ToList();

            Assert.AreEqual(15, list2[0]);
            Assert.AreEqual(10, list2[1]);
            Assert.AreEqual(1, list2[2]);
        }
        public void TransactionalStack3()
        {
            var stack = new TransactionalStack<int>();

            stack.Push(1);
            stack.Push(2);
            stack.Push(3);

            var t1 = stack.BeginTransaction();
            var t2 = stack.BeginTransaction();

            t1.Push(4);
            t2.Push(5);

            t1.Commit();
            AssertionHelpers.AssertThrows<Psimulex.Core.Exceptions.InvalidTransactionException>(() => t2.Commit());

            Assert.AreEqual(4, stack.Pop());
            Assert.AreEqual(3, stack.Pop());
            Assert.AreEqual(2, stack.Pop());
            Assert.AreEqual(1, stack.Pop());

            var transactions = new List<StackTransaction<int>>();
            for (int i = 0; i < 100; ++i)
            {
                transactions.Add(stack.BeginTransaction());
            }

            transactions[22].Push(9);
            transactions[22].Commit();

            transactions.TrueForAll(t => t.Status == TransactionStates.Invalid || t.Status == TransactionStates.Committed);
            transactions.ForEach(t => AssertionHelpers.AssertThrows<Psimulex.Core.Exceptions.InvalidTransactionException>(() => t.Commit()));
        }
        public void TransactionalStack4()
        {
            var stack = new TransactionalStack<int>();

            stack.Push(1);
            stack.Push(2);
            stack.Push(3);

            var t1 = stack.BeginTransaction();

            t1.Pop();
            t1.Pop();
            t1.Push(10);
            t1.Push(15);

            Assert.AreEqual(15, t1.Top);
            Assert.AreEqual(3, stack.Top);

            t1.Commit();

            Assert.AreEqual(15, stack.Pop());
            Assert.AreEqual(10, stack.Pop());
            Assert.AreEqual(1, stack.Pop());
        }
        public void TransactionalStack2()
        {
            var stack = new TransactionalStack<int>();
            for (int i = 0; i < 1000; ++i)
            {
                stack.Push(i);
            }

            for (int i = 0; i < 100; ++i)
            {
                var t = stack.BeginTransaction();
                t.Pop();
                t.Push(-1);
                t.Commit();
                Assert.AreEqual(-1, stack.Top);
                t = stack.BeginTransaction();
                t.Pop();
                t.Commit();
                Assert.AreEqual(998 - i, stack.Top);
                t = stack.BeginTransaction();
                t.Clear();
                Assert.IsTrue(t.IsEmpty);
                Assert.IsFalse(stack.IsEmpty);
                t.Rollback();
                Assert.IsFalse(t.IsEmpty);
                Assert.IsFalse(stack.IsEmpty);
                Assert.AreEqual(998 - i, t.Top);
                Assert.AreEqual(998 - i, stack.Top);
            }

            var ts = stack.BeginTransaction();
            ts.Clear();
            ts.Commit();
            Assert.IsTrue(ts.IsEmpty);
            Assert.IsTrue(stack.IsEmpty);
        }