PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.ComponentModel.Composition/Tests/ComponentModelUnitTest/System/ComponentModel/Composition/Hosting/CompositionTransactionTests.cs

https://bitbucket.org/danipen/mono
C# | 516 lines | 391 code | 109 blank | 16 comment | 17 complexity | 0a6560300130f71419f5bcad7dc90b9d MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. using System;
  2. using System.Text;
  3. using System.Reflection;
  4. using System.Collections.Generic;
  5. using Microsoft.VisualStudio.TestTools.UnitTesting;
  6. using System.ComponentModel.Composition.Hosting;
  7. using System.UnitTesting;
  8. namespace System.ComponentModel.Composition.Hosting
  9. {
  10. [TestClass]
  11. public class AtomicCompositionTests
  12. {
  13. [TestMethod]
  14. public void Constructor1()
  15. {
  16. var ct = new AtomicComposition();
  17. }
  18. [TestMethod]
  19. public void Constructor2()
  20. {
  21. // Null should be allowed
  22. var ct = new AtomicComposition(null);
  23. // Another AtomicComposition should be allowed
  24. var ct2 = new AtomicComposition(ct);
  25. }
  26. [TestMethod]
  27. public void Constructor2_MultipleTimes()
  28. {
  29. var outer = new AtomicComposition();
  30. var ct1 = new AtomicComposition(outer);
  31. ExceptionAssert.Throws<InvalidOperationException>(() => new AtomicComposition(outer));
  32. }
  33. [TestMethod]
  34. public void Dispose_AllMethodsShouldThrow()
  35. {
  36. var ct = new AtomicComposition();
  37. ct.Dispose();
  38. ExceptionAssert.ThrowsDisposed(ct, () => ct.AddCompleteAction(() => ct = null));
  39. ExceptionAssert.ThrowsDisposed(ct, () => ct.Complete());
  40. ExceptionAssert.ThrowsDisposed(ct, () => ct.SetValue(ct, 10));
  41. object value;
  42. ExceptionAssert.ThrowsDisposed(ct, () => ct.TryGetValue(ct, out value));
  43. }
  44. [TestMethod]
  45. public void AfterComplete_AllMethodsShouldThrow()
  46. {
  47. var ct = new AtomicComposition();
  48. ct.Complete();
  49. ExceptionAssert.Throws<InvalidOperationException>(() => ct.AddCompleteAction(() => ct = null));
  50. ExceptionAssert.Throws<InvalidOperationException>(() => ct.Complete());
  51. ExceptionAssert.Throws<InvalidOperationException>(() => ct.SetValue(ct, 10));
  52. object value;
  53. ExceptionAssert.Throws<InvalidOperationException>(() => ct.TryGetValue(ct, out value));
  54. }
  55. [TestMethod]
  56. public void SetValue_ToNull_ShouldBeAllowed()
  57. {
  58. var ct = new AtomicComposition();
  59. ct.SetValue(ct, null);
  60. object value = new object();
  61. Assert.IsTrue(ct.TryGetValue(ct, out value));
  62. Assert.IsNull(value);
  63. }
  64. [TestMethod]
  65. public void SetValue_ValueType_ShouldBeAllowed()
  66. {
  67. var ct = new AtomicComposition();
  68. ct.SetValue(ct, 45);
  69. int value;
  70. Assert.IsTrue(ct.TryGetValue(ct, out value));
  71. Assert.AreEqual(45, value);
  72. }
  73. [TestMethod]
  74. public void SetValue_Reference_ShouldBeAllowed()
  75. {
  76. var ct = new AtomicComposition();
  77. var sb = new StringBuilder();
  78. ct.SetValue(ct, sb);
  79. StringBuilder value;
  80. Assert.IsTrue(ct.TryGetValue(ct, out value));
  81. Assert.AreEqual(sb, value);
  82. }
  83. [TestMethod]
  84. public void SetValue_CauseResize_ShouldWorkFine()
  85. {
  86. var ct = new AtomicComposition();
  87. var keys = new List<object>();
  88. var values = new List<object>();
  89. for (int i = 0; i < 20; i++)
  90. {
  91. var key = new object();
  92. keys.Add(key);
  93. values.Add(i);
  94. ct.SetValue(key, i);
  95. }
  96. for (int i = 0; i < keys.Count; i++)
  97. {
  98. object value;
  99. Assert.IsTrue(ct.TryGetValue(keys[i], out value));
  100. Assert.AreEqual(i, value);
  101. }
  102. }
  103. [TestMethod]
  104. public void SetValue_ChangeOuterValuesWhileHaveInner_ShouldThrow()
  105. {
  106. var ct = new AtomicComposition();
  107. var ct2 = new AtomicComposition(ct);
  108. var key = new object();
  109. ExceptionAssert.Throws<InvalidOperationException>(() => ct.SetValue(key, 1));
  110. object value;
  111. Assert.IsFalse(ct2.TryGetValue(key, out value));
  112. Assert.IsFalse(ct.TryGetValue(key, out value));
  113. // remove the inner atomicComposition so the outer one becomes unlocked.
  114. ct2.Dispose();
  115. ct.SetValue(key, 2);
  116. Assert.IsTrue(ct.TryGetValue(key, out value));
  117. Assert.AreEqual(2, value);
  118. }
  119. [TestMethod]
  120. public void Complete_ShouldExecuteActions()
  121. {
  122. bool executedAction = false;
  123. var ct = new AtomicComposition();
  124. ct.AddCompleteAction(() => executedAction = true);
  125. ct.Complete();
  126. Assert.IsTrue(executedAction);
  127. }
  128. [TestMethod]
  129. public void Complete_ShouldCopyActionsToInner()
  130. {
  131. bool executedAction = false;
  132. var innerAtomicComposition = new AtomicComposition();
  133. using (var ct = new AtomicComposition(innerAtomicComposition))
  134. {
  135. ct.AddCompleteAction(() => executedAction = true);
  136. ct.Complete();
  137. Assert.IsFalse(executedAction, "Action should not have been exectued yet");
  138. }
  139. innerAtomicComposition.Complete();
  140. Assert.IsTrue(executedAction);
  141. }
  142. [TestMethod]
  143. public void Complete_ShouldCopyValuesToInner()
  144. {
  145. var innerAtomicComposition = new AtomicComposition();
  146. object value;
  147. using (var ct = new AtomicComposition(innerAtomicComposition))
  148. {
  149. ct.SetValue(this, 21);
  150. Assert.IsFalse(innerAtomicComposition.TryGetValue(this, out value));
  151. ct.Complete();
  152. Assert.IsTrue(innerAtomicComposition.TryGetValue(this, out value));
  153. Assert.AreEqual(21, value);
  154. }
  155. // reverify after dispose
  156. Assert.IsTrue(innerAtomicComposition.TryGetValue(this, out value));
  157. Assert.AreEqual(21, value);
  158. }
  159. [TestMethod]
  160. public void NoComplete_ShouldNotCopyActionsToInner()
  161. {
  162. bool executedAction = false;
  163. var innerAtomicComposition = new AtomicComposition();
  164. using (var ct = new AtomicComposition(innerAtomicComposition))
  165. {
  166. ct.AddCompleteAction(() => executedAction = true);
  167. Assert.IsFalse(executedAction, "Action should not have been exectued yet");
  168. // Do not complete
  169. }
  170. innerAtomicComposition.Complete();
  171. Assert.IsFalse(executedAction);
  172. }
  173. [TestMethod]
  174. public void NoComplete_ShouldNotCopyValuesToInner()
  175. {
  176. var innerAtomicComposition = new AtomicComposition();
  177. object value;
  178. using (var ct = new AtomicComposition(innerAtomicComposition))
  179. {
  180. ct.SetValue(this, 21);
  181. Assert.IsFalse(innerAtomicComposition.TryGetValue(this, out value));
  182. // Do not call complete
  183. }
  184. // reverify after dispose
  185. Assert.IsFalse(innerAtomicComposition.TryGetValue(this, out value));
  186. }
  187. [TestMethod]
  188. public void AtomicComposition_CompleteActions()
  189. {
  190. var setMe = false;
  191. var setMeToo = false;
  192. var dontSetMe = false;
  193. using (var contextA = new AtomicComposition())
  194. {
  195. contextA.AddCompleteAction(() => setMe = true);
  196. using (var contextB = new AtomicComposition(contextA))
  197. {
  198. contextB.AddCompleteAction(() => setMeToo = true);
  199. contextB.Complete();
  200. }
  201. using (var contextC = new AtomicComposition(contextA))
  202. {
  203. contextC.AddCompleteAction(() => dontSetMe = true);
  204. // Don't complete
  205. }
  206. Assert.IsFalse(setMe);
  207. Assert.IsFalse(setMeToo);
  208. Assert.IsFalse(dontSetMe);
  209. contextA.Complete();
  210. Assert.IsTrue(setMe);
  211. Assert.IsTrue(setMeToo);
  212. Assert.IsFalse(dontSetMe);
  213. }
  214. }
  215. private void TestNoValue(AtomicComposition context, object key)
  216. {
  217. string value;
  218. Assert.IsFalse(context.TryGetValue(key, out value));
  219. }
  220. private void TestValue(AtomicComposition context, object key, string expectedValue)
  221. {
  222. string value;
  223. Assert.IsTrue(context.TryGetValue(key, out value));
  224. Assert.AreEqual(expectedValue, value);
  225. }
  226. [TestMethod]
  227. public void AtomicComposition_CompleteValues()
  228. {
  229. object key1 = new Object();
  230. object key2 = new Object();
  231. using (var contextA = new AtomicComposition())
  232. {
  233. TestNoValue(contextA, key1);
  234. TestNoValue(contextA, key2);
  235. contextA.SetValue(key1, "Hello");
  236. TestValue(contextA, key1, "Hello");
  237. TestNoValue(contextA, key2);
  238. // Try overwriting
  239. using (var contextB = new AtomicComposition(contextA))
  240. {
  241. TestValue(contextB, key1, "Hello");
  242. TestNoValue(contextB, key2);
  243. contextB.SetValue(key1, "Greetings");
  244. TestValue(contextB, key1, "Greetings");
  245. TestNoValue(contextB, key2);
  246. contextB.Complete();
  247. }
  248. TestValue(contextA, key1, "Greetings");
  249. TestNoValue(contextA, key2);
  250. // Try overwrite with revert
  251. using (var contextC = new AtomicComposition(contextA))
  252. {
  253. TestValue(contextC, key1, "Greetings");
  254. TestNoValue(contextC, key2);
  255. contextC.SetValue(key1, "Goodbye");
  256. contextC.SetValue(key2, "Goodbye, Again");
  257. TestValue(contextC, key1, "Goodbye");
  258. TestValue(contextC, key2, "Goodbye, Again");
  259. // Don't complete
  260. }
  261. TestValue(contextA, key1, "Greetings");
  262. TestNoValue(contextA, key2);
  263. contextA.Complete();
  264. }
  265. }
  266. private void TestQuery(AtomicComposition context, object key, int parameter, bool expectation)
  267. {
  268. Func<int, bool> query;
  269. if (context.TryGetValue(key, out query))
  270. Assert.AreEqual(expectation, query(parameter));
  271. }
  272. private void SetQuery(AtomicComposition context, object key, Func<int, Func<int, bool>, bool> query)
  273. {
  274. Func<int, bool> parentQuery;
  275. context.TryGetValue(key, out parentQuery);
  276. Func<int, bool> queryFunction = parameter => { return query(parameter, parentQuery); };
  277. context.SetValue(key, queryFunction);
  278. }
  279. [TestMethod]
  280. public void AtomicComposition_NestedQueries()
  281. {
  282. // This is a rather convoluted test that exercises the way AtomicComposition used to work to
  283. // ensure consistency of the newer design
  284. var key = new Object();
  285. using (var contextA = new AtomicComposition())
  286. {
  287. SetQuery(contextA, key, (int parameter, Func<int, bool> parentQuery) =>
  288. {
  289. if (parameter == 22)
  290. return true;
  291. if (parentQuery != null)
  292. return parentQuery(parameter);
  293. return false;
  294. });
  295. TestQuery(contextA, key, 22, true);
  296. using (var contextB = new AtomicComposition(contextA))
  297. {
  298. TestQuery(contextB, key, 22, true);
  299. SetQuery(contextB, key, (int parameter, Func<int, bool> parentQuery) =>
  300. {
  301. if (parentQuery != null)
  302. return !parentQuery(parameter);
  303. Assert.Fail(); // Should never have no parent
  304. return false;
  305. });
  306. TestQuery(contextB, key, 21, true);
  307. TestQuery(contextB, key, 22, false);
  308. using (var contextC = new AtomicComposition(contextB))
  309. {
  310. SetQuery(contextC, key, (int parameter, Func<int, bool> parentQuery) =>
  311. {
  312. if (parameter == 23)
  313. return true;
  314. if (parentQuery != null)
  315. return !parentQuery(parameter);
  316. Assert.Fail(); // Should never have no parent
  317. return false;
  318. });
  319. TestQuery(contextC, key, 21, false);
  320. TestQuery(contextC, key, 22, true);
  321. TestQuery(contextC, key, 23, true);
  322. contextC.Complete();
  323. }
  324. using (var contextD = new AtomicComposition(contextB))
  325. {
  326. SetQuery(contextD, key, (int parameter, Func<int, bool> parentQuery) =>
  327. {
  328. if (parentQuery != null)
  329. return parentQuery(parameter + 1);
  330. Assert.Fail(); // Should never have no parent
  331. return false;
  332. });
  333. TestQuery(contextD, key, 21, true);
  334. TestQuery(contextD, key, 22, true);
  335. TestQuery(contextD, key, 23, false);
  336. // No complete
  337. }
  338. contextB.Complete();
  339. }
  340. TestQuery(contextA, key, 21, false);
  341. TestQuery(contextA, key, 22, true);
  342. TestQuery(contextA, key, 23, true);
  343. contextA.Complete();
  344. }
  345. }
  346. [TestMethod]
  347. public void AddRevertAction_ShouldExecuteWhenDisposedAndNotCompleteted()
  348. {
  349. var ct = new AtomicComposition();
  350. bool executed = false;
  351. ct.AddRevertAction(() => executed = true);
  352. ct.Dispose();
  353. Assert.IsTrue(executed);
  354. }
  355. [TestMethod]
  356. public void AddRevertAction_ShouldNotExecuteWhenCompleteted()
  357. {
  358. var ct = new AtomicComposition();
  359. bool executed = false;
  360. ct.AddRevertAction(() => executed = true);
  361. ct.Complete();
  362. Assert.IsFalse(executed);
  363. ct.Dispose();
  364. Assert.IsFalse(executed);
  365. }
  366. [TestMethod]
  367. public void AddRevertAction_ShouldExecuteInReverseOrder()
  368. {
  369. var ct = new AtomicComposition();
  370. Stack<int> stack = new Stack<int>();
  371. stack.Push(1);
  372. stack.Push(2);
  373. stack.Push(3);
  374. ct.AddRevertAction(() => Assert.AreEqual(1, stack.Pop()));
  375. ct.AddRevertAction(() => Assert.AreEqual(2, stack.Pop()));
  376. ct.AddRevertAction(() => Assert.AreEqual(3, stack.Pop()));
  377. ct.Dispose();
  378. Assert.IsTrue(stack.Count == 0);
  379. }
  380. [TestMethod]
  381. public void AddRevertAction_ShouldBeCopiedWhenCompleteed()
  382. {
  383. Stack<int> stack = new Stack<int>();
  384. stack.Push(1);
  385. stack.Push(2);
  386. stack.Push(11);
  387. stack.Push(12);
  388. stack.Push(3);
  389. using (var ct = new AtomicComposition())
  390. {
  391. ct.AddRevertAction(() => Assert.AreEqual(1, stack.Pop()));
  392. ct.AddRevertAction(() => Assert.AreEqual(2, stack.Pop()));
  393. using (var ct2 = new AtomicComposition(ct))
  394. {
  395. ct2.AddRevertAction(() => Assert.AreEqual(11, stack.Pop()));
  396. ct2.AddRevertAction(() => Assert.AreEqual(12, stack.Pop()));
  397. // completeting should move those revert actions to ct
  398. ct2.Complete();
  399. Assert.AreEqual(5, stack.Count);
  400. }
  401. ct.AddRevertAction(() => Assert.AreEqual(3, stack.Pop()));
  402. // Do not complete let ct dispose and revert
  403. }
  404. Assert.IsTrue(stack.Count == 0);
  405. }
  406. }
  407. }