/mcs/class/System.ComponentModel.Composition/Tests/ComponentModelUnitTest/System/ComponentModel/Composition/Hosting/CompositionTransactionTests.cs
C# | 516 lines | 391 code | 109 blank | 16 comment | 17 complexity | 0a6560300130f71419f5bcad7dc90b9d MD5 | raw file
- using System;
- using System.Text;
- using System.Reflection;
- using System.Collections.Generic;
-
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- using System.ComponentModel.Composition.Hosting;
- using System.UnitTesting;
-
- namespace System.ComponentModel.Composition.Hosting
- {
- [TestClass]
- public class AtomicCompositionTests
- {
- [TestMethod]
- public void Constructor1()
- {
- var ct = new AtomicComposition();
- }
-
- [TestMethod]
- public void Constructor2()
- {
- // Null should be allowed
- var ct = new AtomicComposition(null);
-
- // Another AtomicComposition should be allowed
- var ct2 = new AtomicComposition(ct);
- }
-
- [TestMethod]
- public void Constructor2_MultipleTimes()
- {
- var outer = new AtomicComposition();
-
- var ct1 = new AtomicComposition(outer);
-
- ExceptionAssert.Throws<InvalidOperationException>(() => new AtomicComposition(outer));
- }
-
- [TestMethod]
- public void Dispose_AllMethodsShouldThrow()
- {
- var ct = new AtomicComposition();
-
- ct.Dispose();
-
- ExceptionAssert.ThrowsDisposed(ct, () => ct.AddCompleteAction(() => ct = null));
- ExceptionAssert.ThrowsDisposed(ct, () => ct.Complete());
- ExceptionAssert.ThrowsDisposed(ct, () => ct.SetValue(ct, 10));
- object value;
- ExceptionAssert.ThrowsDisposed(ct, () => ct.TryGetValue(ct, out value));
- }
-
- [TestMethod]
- public void AfterComplete_AllMethodsShouldThrow()
- {
- var ct = new AtomicComposition();
-
- ct.Complete();
-
- ExceptionAssert.Throws<InvalidOperationException>(() => ct.AddCompleteAction(() => ct = null));
- ExceptionAssert.Throws<InvalidOperationException>(() => ct.Complete());
- ExceptionAssert.Throws<InvalidOperationException>(() => ct.SetValue(ct, 10));
- object value;
- ExceptionAssert.Throws<InvalidOperationException>(() => ct.TryGetValue(ct, out value));
- }
-
- [TestMethod]
- public void SetValue_ToNull_ShouldBeAllowed()
- {
- var ct = new AtomicComposition();
-
- ct.SetValue(ct, null);
-
- object value = new object();
-
- Assert.IsTrue(ct.TryGetValue(ct, out value));
- Assert.IsNull(value);
- }
-
- [TestMethod]
- public void SetValue_ValueType_ShouldBeAllowed()
- {
- var ct = new AtomicComposition();
-
- ct.SetValue(ct, 45);
-
- int value;
-
- Assert.IsTrue(ct.TryGetValue(ct, out value));
- Assert.AreEqual(45, value);
- }
-
- [TestMethod]
- public void SetValue_Reference_ShouldBeAllowed()
- {
- var ct = new AtomicComposition();
-
- var sb = new StringBuilder();
- ct.SetValue(ct, sb);
-
- StringBuilder value;
-
- Assert.IsTrue(ct.TryGetValue(ct, out value));
- Assert.AreEqual(sb, value);
- }
-
- [TestMethod]
- public void SetValue_CauseResize_ShouldWorkFine()
- {
- var ct = new AtomicComposition();
-
- var keys = new List<object>();
- var values = new List<object>();
-
-
- for (int i = 0; i < 20; i++)
- {
- var key = new object();
- keys.Add(key);
- values.Add(i);
- ct.SetValue(key, i);
- }
-
- for (int i = 0; i < keys.Count; i++)
- {
- object value;
- Assert.IsTrue(ct.TryGetValue(keys[i], out value));
- Assert.AreEqual(i, value);
- }
- }
-
- [TestMethod]
- public void SetValue_ChangeOuterValuesWhileHaveInner_ShouldThrow()
- {
- var ct = new AtomicComposition();
-
- var ct2 = new AtomicComposition(ct);
-
- var key = new object();
- ExceptionAssert.Throws<InvalidOperationException>(() => ct.SetValue(key, 1));
-
- object value;
- Assert.IsFalse(ct2.TryGetValue(key, out value));
- Assert.IsFalse(ct.TryGetValue(key, out value));
-
- // remove the inner atomicComposition so the outer one becomes unlocked.
- ct2.Dispose();
-
- ct.SetValue(key, 2);
- Assert.IsTrue(ct.TryGetValue(key, out value));
- Assert.AreEqual(2, value);
- }
-
- [TestMethod]
- public void Complete_ShouldExecuteActions()
- {
- bool executedAction = false;
-
- var ct = new AtomicComposition();
-
- ct.AddCompleteAction(() => executedAction = true);
-
- ct.Complete();
-
- Assert.IsTrue(executedAction);
- }
-
- [TestMethod]
- public void Complete_ShouldCopyActionsToInner()
- {
- bool executedAction = false;
-
- var innerAtomicComposition = new AtomicComposition();
-
- using (var ct = new AtomicComposition(innerAtomicComposition))
- {
- ct.AddCompleteAction(() => executedAction = true);
-
- ct.Complete();
- Assert.IsFalse(executedAction, "Action should not have been exectued yet");
- }
-
- innerAtomicComposition.Complete();
- Assert.IsTrue(executedAction);
- }
-
- [TestMethod]
- public void Complete_ShouldCopyValuesToInner()
- {
- var innerAtomicComposition = new AtomicComposition();
-
- object value;
- using (var ct = new AtomicComposition(innerAtomicComposition))
- {
- ct.SetValue(this, 21);
-
- Assert.IsFalse(innerAtomicComposition.TryGetValue(this, out value));
-
- ct.Complete();
-
- Assert.IsTrue(innerAtomicComposition.TryGetValue(this, out value));
- Assert.AreEqual(21, value);
- }
-
- // reverify after dispose
- Assert.IsTrue(innerAtomicComposition.TryGetValue(this, out value));
- Assert.AreEqual(21, value);
- }
-
- [TestMethod]
- public void NoComplete_ShouldNotCopyActionsToInner()
- {
- bool executedAction = false;
-
- var innerAtomicComposition = new AtomicComposition();
-
- using (var ct = new AtomicComposition(innerAtomicComposition))
- {
- ct.AddCompleteAction(() => executedAction = true);
-
- Assert.IsFalse(executedAction, "Action should not have been exectued yet");
-
- // Do not complete
- }
-
- innerAtomicComposition.Complete();
- Assert.IsFalse(executedAction);
- }
-
- [TestMethod]
- public void NoComplete_ShouldNotCopyValuesToInner()
- {
- var innerAtomicComposition = new AtomicComposition();
-
- object value;
- using (var ct = new AtomicComposition(innerAtomicComposition))
- {
- ct.SetValue(this, 21);
-
- Assert.IsFalse(innerAtomicComposition.TryGetValue(this, out value));
-
- // Do not call complete
- }
-
- // reverify after dispose
- Assert.IsFalse(innerAtomicComposition.TryGetValue(this, out value));
- }
-
-
- [TestMethod]
- public void AtomicComposition_CompleteActions()
- {
- var setMe = false;
- var setMeToo = false;
- var dontSetMe = false;
- using (var contextA = new AtomicComposition())
- {
- contextA.AddCompleteAction(() => setMe = true);
- using (var contextB = new AtomicComposition(contextA))
- {
- contextB.AddCompleteAction(() => setMeToo = true);
- contextB.Complete();
- }
-
- using (var contextC = new AtomicComposition(contextA))
- {
- contextC.AddCompleteAction(() => dontSetMe = true);
- // Don't complete
- }
- Assert.IsFalse(setMe);
- Assert.IsFalse(setMeToo);
- Assert.IsFalse(dontSetMe);
-
- contextA.Complete();
-
- Assert.IsTrue(setMe);
- Assert.IsTrue(setMeToo);
- Assert.IsFalse(dontSetMe);
- }
- }
-
- private void TestNoValue(AtomicComposition context, object key)
- {
- string value;
- Assert.IsFalse(context.TryGetValue(key, out value));
- }
-
- private void TestValue(AtomicComposition context, object key, string expectedValue)
- {
- string value;
- Assert.IsTrue(context.TryGetValue(key, out value));
- Assert.AreEqual(expectedValue, value);
- }
-
- [TestMethod]
- public void AtomicComposition_CompleteValues()
- {
- object key1 = new Object();
- object key2 = new Object();
-
- using (var contextA = new AtomicComposition())
- {
- TestNoValue(contextA, key1);
- TestNoValue(contextA, key2);
- contextA.SetValue(key1, "Hello");
- TestValue(contextA, key1, "Hello");
- TestNoValue(contextA, key2);
-
- // Try overwriting
- using (var contextB = new AtomicComposition(contextA))
- {
- TestValue(contextB, key1, "Hello");
- TestNoValue(contextB, key2);
- contextB.SetValue(key1, "Greetings");
- TestValue(contextB, key1, "Greetings");
- TestNoValue(contextB, key2);
-
- contextB.Complete();
- }
- TestValue(contextA, key1, "Greetings");
- TestNoValue(contextA, key2);
-
- // Try overwrite with revert
- using (var contextC = new AtomicComposition(contextA))
- {
- TestValue(contextC, key1, "Greetings");
- TestNoValue(contextC, key2);
- contextC.SetValue(key1, "Goodbye");
- contextC.SetValue(key2, "Goodbye, Again");
- TestValue(contextC, key1, "Goodbye");
- TestValue(contextC, key2, "Goodbye, Again");
-
- // Don't complete
- }
- TestValue(contextA, key1, "Greetings");
- TestNoValue(contextA, key2);
-
- contextA.Complete();
- }
- }
-
- private void TestQuery(AtomicComposition context, object key, int parameter, bool expectation)
- {
- Func<int, bool> query;
- if (context.TryGetValue(key, out query))
- Assert.AreEqual(expectation, query(parameter));
- }
-
- private void SetQuery(AtomicComposition context, object key, Func<int, Func<int, bool>, bool> query)
- {
- Func<int, bool> parentQuery;
- context.TryGetValue(key, out parentQuery);
- Func<int, bool> queryFunction = parameter => { return query(parameter, parentQuery); };
- context.SetValue(key, queryFunction);
- }
-
- [TestMethod]
- public void AtomicComposition_NestedQueries()
- {
- // This is a rather convoluted test that exercises the way AtomicComposition used to work to
- // ensure consistency of the newer design
- var key = new Object();
-
- using (var contextA = new AtomicComposition())
- {
- SetQuery(contextA, key, (int parameter, Func<int, bool> parentQuery) =>
- {
- if (parameter == 22)
- return true;
- if (parentQuery != null)
- return parentQuery(parameter);
- return false;
- });
- TestQuery(contextA, key, 22, true);
-
- using (var contextB = new AtomicComposition(contextA))
- {
- TestQuery(contextB, key, 22, true);
- SetQuery(contextB, key, (int parameter, Func<int, bool> parentQuery) =>
- {
- if (parentQuery != null)
- return !parentQuery(parameter);
- Assert.Fail(); // Should never have no parent
- return false;
- });
- TestQuery(contextB, key, 21, true);
- TestQuery(contextB, key, 22, false);
-
- using (var contextC = new AtomicComposition(contextB))
- {
- SetQuery(contextC, key, (int parameter, Func<int, bool> parentQuery) =>
- {
- if (parameter == 23)
- return true;
- if (parentQuery != null)
- return !parentQuery(parameter);
- Assert.Fail(); // Should never have no parent
- return false;
- });
- TestQuery(contextC, key, 21, false);
- TestQuery(contextC, key, 22, true);
- TestQuery(contextC, key, 23, true);
- contextC.Complete();
- }
-
- using (var contextD = new AtomicComposition(contextB))
- {
- SetQuery(contextD, key, (int parameter, Func<int, bool> parentQuery) =>
- {
- if (parentQuery != null)
- return parentQuery(parameter + 1);
- Assert.Fail(); // Should never have no parent
- return false;
- });
- TestQuery(contextD, key, 21, true);
- TestQuery(contextD, key, 22, true);
- TestQuery(contextD, key, 23, false);
- // No complete
- }
-
- contextB.Complete();
- }
- TestQuery(contextA, key, 21, false);
- TestQuery(contextA, key, 22, true);
- TestQuery(contextA, key, 23, true);
- contextA.Complete();
- }
- }
-
- [TestMethod]
- public void AddRevertAction_ShouldExecuteWhenDisposedAndNotCompleteted()
- {
- var ct = new AtomicComposition();
- bool executed = false;
-
- ct.AddRevertAction(() => executed = true);
-
- ct.Dispose();
-
- Assert.IsTrue(executed);
- }
-
- [TestMethod]
- public void AddRevertAction_ShouldNotExecuteWhenCompleteted()
- {
- var ct = new AtomicComposition();
- bool executed = false;
-
- ct.AddRevertAction(() => executed = true);
-
- ct.Complete();
-
- Assert.IsFalse(executed);
-
- ct.Dispose();
-
- Assert.IsFalse(executed);
- }
-
- [TestMethod]
- public void AddRevertAction_ShouldExecuteInReverseOrder()
- {
- var ct = new AtomicComposition();
- Stack<int> stack = new Stack<int>();
- stack.Push(1);
- stack.Push(2);
- stack.Push(3);
-
- ct.AddRevertAction(() => Assert.AreEqual(1, stack.Pop()));
- ct.AddRevertAction(() => Assert.AreEqual(2, stack.Pop()));
- ct.AddRevertAction(() => Assert.AreEqual(3, stack.Pop()));
-
- ct.Dispose();
-
- Assert.IsTrue(stack.Count == 0);
- }
-
- [TestMethod]
- public void AddRevertAction_ShouldBeCopiedWhenCompleteed()
- {
- Stack<int> stack = new Stack<int>();
- stack.Push(1);
- stack.Push(2);
- stack.Push(11);
- stack.Push(12);
- stack.Push(3);
-
- using (var ct = new AtomicComposition())
- {
- ct.AddRevertAction(() => Assert.AreEqual(1, stack.Pop()));
- ct.AddRevertAction(() => Assert.AreEqual(2, stack.Pop()));
-
- using (var ct2 = new AtomicComposition(ct))
- {
- ct2.AddRevertAction(() => Assert.AreEqual(11, stack.Pop()));
- ct2.AddRevertAction(() => Assert.AreEqual(12, stack.Pop()));
-
- // completeting should move those revert actions to ct
- ct2.Complete();
-
- Assert.AreEqual(5, stack.Count);
- }
-
- ct.AddRevertAction(() => Assert.AreEqual(3, stack.Pop()));
-
- // Do not complete let ct dispose and revert
- }
-
- Assert.IsTrue(stack.Count == 0);
- }
-
-
- }
- }