ConditionalWeakTableTests.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // -----------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // -----------------------------------------------------------------------
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Runtime.CompilerServices;
  8. using System.Text;
  9. using System.UnitTesting;
  10. using Microsoft.VisualStudio.TestTools.UnitTesting;
  11. namespace Microsoft.Internal.Collections
  12. {
  13. [TestClass]
  14. public class ConditionalWeakTableTests
  15. {
  16. [TestMethod]
  17. public void Add_KeyShouldBeCollected()
  18. {
  19. var obj = new object();
  20. var cwt = new ConditionalWeakTable<object, object>();
  21. cwt.Add(obj, new object());
  22. var wr = new WeakReference(obj);
  23. obj = null;
  24. GC.Collect();
  25. GC.WaitForPendingFinalizers();
  26. Assert.IsNull(wr.Target, "Key should be collected now!");
  27. GC.KeepAlive(cwt);
  28. }
  29. [TestMethod]
  30. public void Add_KeyHeld_ValueShouldNotBeCollected()
  31. {
  32. var obj = new object();
  33. var str = new StringBuilder();
  34. var cwt = new ConditionalWeakTable<object, StringBuilder>();
  35. var wrKey = new WeakReference(obj);
  36. var wrValue = new WeakReference(str);
  37. cwt.Add(obj, str);
  38. str = null;
  39. GC.Collect();
  40. GC.WaitForPendingFinalizers();
  41. // Should still have both references
  42. Assert.IsNotNull(wrKey.Target, "Key should NOT be collected yet!");
  43. Assert.IsNotNull(wrValue.Target, "Value should NOT be collected yet!");
  44. GC.KeepAlive(obj);
  45. GC.KeepAlive(cwt);
  46. }
  47. #if CLR40
  48. [TestMethod]
  49. public void Add_KeyCollected_ValueShouldBeCollected()
  50. {
  51. var obj = new object();
  52. var str = new StringBuilder();
  53. var cwt = new ConditionalWeakTable<object, StringBuilder>();
  54. cwt.Add(obj, str);
  55. var wrKey = new WeakReference(obj);
  56. var wrValue = new WeakReference(str);
  57. str = null;
  58. obj = null;
  59. GC.Collect();
  60. GC.WaitForPendingFinalizers();
  61. Assert.IsNull(wrKey.Target, "Key should be collected now!");
  62. Assert.IsNull(wrValue.Target, "Value should be collected now!");
  63. GC.KeepAlive(cwt);
  64. }
  65. #endif
  66. [TestMethod]
  67. public void Remove_ValidKey_ShouldReturnTrue()
  68. {
  69. var obj = new object();
  70. var obj2 = new object();
  71. var cwt = new ConditionalWeakTable<object, object>();
  72. cwt.Add(obj, obj2);
  73. Assert.IsTrue(cwt.Remove(obj));
  74. }
  75. [TestMethod]
  76. public void Remove_InvalidKey_ShouldReturnTrue()
  77. {
  78. var obj = new object();
  79. var obj2 = new object();
  80. var cwt = new ConditionalWeakTable<object, object>();
  81. cwt.Add(obj, obj2);
  82. Assert.IsFalse(cwt.Remove(obj2));
  83. }
  84. [TestMethod]
  85. public void TryGetValue_ValidKey_ShouldReturnTrueAndValue()
  86. {
  87. var obj = new object();
  88. var obj2 = new object();
  89. var cwt = new ConditionalWeakTable<object, object>();
  90. cwt.Add(obj, obj2);
  91. object obj3;
  92. Assert.IsTrue(cwt.TryGetValue(obj, out obj3), "Should find a value with the key!");
  93. Assert.AreEqual(obj2, obj3);
  94. }
  95. [TestMethod]
  96. public void TryGetValue_InvalidKey_ShouldReturnFalseAndNull()
  97. {
  98. var obj = new object();
  99. var obj2 = new object();
  100. var cwt = new ConditionalWeakTable<object, object>();
  101. cwt.Add(obj, obj2);
  102. object obj3;
  103. Assert.IsFalse(cwt.TryGetValue(obj2, out obj3), "Should NOT find a value with the key!");
  104. Assert.IsNull(obj3);
  105. }
  106. #if !CLR40
  107. [TestMethod]
  108. public void Add_KeyValueSame_KeyShouldNotBeCollected()
  109. {
  110. // Dev10:556089 - This test demonstrations a bug in our implementation
  111. // of ConditionalWeakTable which needs CLR 4 support to fix so once
  112. // we switch to the CLR 4 version of ConditionalWeakTable this should go away.
  113. var obj = new object();
  114. var cwt = new ConditionalWeakTable<object, object>();
  115. cwt.Add(obj, obj);
  116. var wrKey = new WeakReference(obj);
  117. obj = null;
  118. GC.Collect();
  119. GC.WaitForPendingFinalizers();
  120. Assert.IsNotNull(wrKey.Target, "Key should NOT be collected yet!");
  121. // Apply pressure to ensure they still don't go away.
  122. ApplyMemoryPressureOnConditionalWeakTable(cwt);
  123. Assert.IsNotNull(wrKey.Target, "Key should NOT be collected yet!");
  124. GC.KeepAlive(cwt);
  125. }
  126. public class ObjectHolder
  127. {
  128. public object Obj { get; set; }
  129. public ObjectHolder() { }
  130. public ObjectHolder(object obj)
  131. {
  132. Obj = obj;
  133. }
  134. }
  135. [TestMethod]
  136. public void Add_ValueReferencesKey_KeyAndValueShouldNotBeCollected()
  137. {
  138. // Dev10:556089 - This test demonstrations a bug in our implementation
  139. // of ConditionalWeakTable which needs CLR 4 support to fix so once
  140. // we switch to the CLR 4 version of ConditionalWeakTable this should go away.
  141. var obj = new object();
  142. var holder = new ObjectHolder(obj);
  143. var cwt = new ConditionalWeakTable<object, ObjectHolder>();
  144. cwt.Add(obj, holder);
  145. var wrKey = new WeakReference(obj);
  146. var wrValue = new WeakReference(holder);
  147. holder = null;
  148. obj = null;
  149. GC.Collect();
  150. GC.WaitForPendingFinalizers();
  151. Assert.IsNotNull(wrKey.Target, "Key should NOT be collected yet!");
  152. Assert.IsNotNull(wrValue.Target, "Value should NOT be collected now!");
  153. // Apply pressure to ensure they still don't go away.
  154. ApplyMemoryPressureOnConditionalWeakTable(cwt);
  155. Assert.IsNotNull(wrKey.Target, "Key should NOT be collected yet!");
  156. Assert.IsNotNull(wrValue.Target, "Value should NOT be collected now!");
  157. GC.KeepAlive(cwt);
  158. }
  159. private void ApplyMemoryPressureOnConditionalWeakTable<T,V>(ConditionalWeakTable<T,V> table)
  160. where T : class, new()
  161. where V : class, new()
  162. {
  163. // Adding 100 items should do it.
  164. for (int i = 0; i < 100; i++)
  165. {
  166. table.Add(new T(), new V());
  167. }
  168. GC.Collect();
  169. GC.WaitForPendingFinalizers();
  170. }
  171. #endif //!CLR40
  172. }
  173. }