2
0

OrderedDictionaryTest.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Microsoft.VisualStudio.TestTools.UnitTesting;
  5. namespace Renci.SshNet.Tests.Classes
  6. {
  7. [TestClass]
  8. public class OrderedDictionaryTest
  9. {
  10. private static void AssertEqual<TKey, TValue>(List<KeyValuePair<TKey, TValue>> expected, OrderedDictionary<TKey, TValue> o)
  11. {
  12. Assert.AreEqual(expected.Count, o.Count);
  13. CollectionAssert.AreEqual(expected, ToList(o)); // Test the enumerator
  14. for (int i = 0; i < expected.Count; i++)
  15. {
  16. Assert.AreEqual(expected[i], o.GetAt(i));
  17. Assert.AreEqual(expected[i].Value, o[expected[i].Key]);
  18. Assert.IsTrue(o.TryGetValue(expected[i].Key, out TValue value));
  19. Assert.AreEqual(expected[i].Value, value);
  20. Assert.IsTrue(o.TryGetValue(expected[i].Key, out value, out int index));
  21. Assert.AreEqual(expected[i].Value, value);
  22. Assert.AreEqual(i, index);
  23. Assert.IsTrue(((ICollection<KeyValuePair<TKey, TValue>>)o).Contains(expected[i]));
  24. Assert.IsTrue(o.ContainsKey(expected[i].Key));
  25. Assert.IsTrue(o.ContainsValue(expected[i].Value));
  26. Assert.IsTrue(o.Keys.Contains(expected[i].Key));
  27. Assert.IsTrue(o.Values.Contains(expected[i].Value));
  28. Assert.AreEqual(i, o.IndexOf(expected[i].Key));
  29. Assert.IsFalse(o.TryAdd(expected[i].Key, default));
  30. Assert.IsFalse(o.TryAdd(expected[i].Key, default, out index));
  31. Assert.AreEqual(i, index);
  32. }
  33. Assert.AreEqual(expected.Count, o.Keys.Count);
  34. CollectionAssert.AreEqual(expected.Select(kvp => kvp.Key).ToList(), ToList(o.Keys));
  35. CollectionAssert.AreEqual(ToList(o.Keys), ToList(((IReadOnlyDictionary<TKey, TValue>)o).Keys));
  36. Assert.AreEqual(expected.Count, o.Values.Count);
  37. CollectionAssert.AreEqual(expected.Select(kvp => kvp.Value).ToList(), ToList(o.Values));
  38. CollectionAssert.AreEqual(ToList(o.Values), ToList(((IReadOnlyDictionary<TKey, TValue>)o).Values));
  39. // Test CopyTo
  40. var kvpArray = new KeyValuePair<TKey, TValue>[1 + expected.Count + 1];
  41. ((ICollection<KeyValuePair<TKey, TValue>>)o).CopyTo(kvpArray, 1);
  42. CollectionAssert.AreEqual(
  43. (List<KeyValuePair<TKey, TValue>>)[default, .. expected, default],
  44. kvpArray);
  45. var keysArray = new TKey[1 + expected.Count + 1];
  46. o.Keys.CopyTo(keysArray, 1);
  47. CollectionAssert.AreEqual(
  48. (List<TKey>)[default, .. expected.Select(kvp => kvp.Key), default],
  49. keysArray);
  50. var valuesArray = new TValue[1 + expected.Count + 1];
  51. o.Values.CopyTo(valuesArray, 1);
  52. CollectionAssert.AreEqual(
  53. (List<TValue>)[default, .. expected.Select(kvp => kvp.Value), default],
  54. valuesArray);
  55. // Creates a List<T> via enumeration, avoiding the ICollection<T>.CopyTo
  56. // optimisation in the List<T> constructor.
  57. static List<T> ToList<T>(IEnumerable<T> values)
  58. {
  59. List<T> list = new();
  60. foreach (T t in values)
  61. {
  62. list.Add(t);
  63. }
  64. return list;
  65. }
  66. }
  67. [TestMethod]
  68. public void NullKey_ThrowsArgumentNull()
  69. {
  70. OrderedDictionary<string, int> o = new() { { "a", 4 } };
  71. Assert.ThrowsException<ArgumentNullException>(() => o[null]);
  72. Assert.ThrowsException<ArgumentNullException>(() => o.Add(null, 1));
  73. Assert.ThrowsException<ArgumentNullException>(() => ((ICollection<KeyValuePair<string, int>>)o).Add(new KeyValuePair<string, int>(null, 1)));
  74. Assert.ThrowsException<ArgumentNullException>(() => ((ICollection<KeyValuePair<string, int>>)o).Contains(new KeyValuePair<string, int>(null, 1)));
  75. Assert.ThrowsException<ArgumentNullException>(() => o.ContainsKey(null));
  76. Assert.ThrowsException<ArgumentNullException>(() => o.IndexOf(null));
  77. Assert.ThrowsException<ArgumentNullException>(() => o.Insert(0, null, 1));
  78. Assert.ThrowsException<ArgumentNullException>(() => o.Remove(null, out _));
  79. Assert.ThrowsException<ArgumentNullException>(() => o.Remove(null));
  80. Assert.ThrowsException<ArgumentNullException>(() => ((ICollection<KeyValuePair<string, int>>)o).Remove(new KeyValuePair<string, int>(null, 1)));
  81. Assert.ThrowsException<ArgumentNullException>(() => o.SetAt(0, null, 1));
  82. Assert.ThrowsException<ArgumentNullException>(() => o.SetPosition(null, 0));
  83. Assert.ThrowsException<ArgumentNullException>(() => o.TryAdd(null, 1));
  84. Assert.ThrowsException<ArgumentNullException>(() => o.TryAdd(null, 1, out _));
  85. Assert.ThrowsException<ArgumentNullException>(() => o.TryGetValue(null, out _));
  86. Assert.ThrowsException<ArgumentNullException>(() => o.TryGetValue(null, out _, out _));
  87. }
  88. [TestMethod]
  89. public void Indexer_Match_GetterReturnsValue()
  90. {
  91. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 } };
  92. Assert.AreEqual(8, o["b"]);
  93. }
  94. [TestMethod]
  95. public void Indexer_Match_SetterChangesValue()
  96. {
  97. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 } };
  98. o["a"] = 5;
  99. AssertEqual([new("a", 5), new("b", 8)], o);
  100. }
  101. [TestMethod]
  102. public void Indexer_NoMatch_GetterThrowsKeyNotFound()
  103. {
  104. OrderedDictionary<string, int> o = new() { { "a", 4 } };
  105. Assert.ThrowsException<KeyNotFoundException>(() => o["b"]);
  106. }
  107. [TestMethod]
  108. public void Indexer_NoMatch_SetterAddsItem()
  109. {
  110. OrderedDictionary<string, int> o = new() { { "a", 4 } };
  111. o["b"] = 8;
  112. AssertEqual([new("a", 4), new("b", 8)], o);
  113. }
  114. [TestMethod]
  115. public void Add_Match()
  116. {
  117. OrderedDictionary<string, int> o = new() { { "a", 4 } };
  118. Assert.ThrowsException<ArgumentException>(() => o.Add("a", 8));
  119. Assert.ThrowsException<ArgumentException>(() => ((ICollection<KeyValuePair<string, int>>)o).Add(new KeyValuePair<string, int>("a", 8)));
  120. }
  121. [TestMethod]
  122. public void Clear()
  123. {
  124. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 } };
  125. AssertEqual([new("a", 4), new("b", 8)], o);
  126. o.Clear();
  127. AssertEqual([], o);
  128. }
  129. [TestMethod]
  130. public void CopyTo()
  131. {
  132. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 } };
  133. Assert.ThrowsException<ArgumentNullException>(() => ((ICollection<KeyValuePair<string, int>>)o).CopyTo(null, 0));
  134. Assert.ThrowsException<ArgumentOutOfRangeException>(() => ((ICollection<KeyValuePair<string, int>>)o).CopyTo(new KeyValuePair<string, int>[3], -1));
  135. Assert.ThrowsException<ArgumentException>(() => ((ICollection<KeyValuePair<string, int>>)o).CopyTo(new KeyValuePair<string, int>[3], 3));
  136. Assert.ThrowsException<ArgumentException>(() => ((ICollection<KeyValuePair<string, int>>)o).CopyTo(new KeyValuePair<string, int>[3], 2));
  137. Assert.ThrowsException<ArgumentNullException>(() => o.Keys.CopyTo(null, 0));
  138. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.Keys.CopyTo(new string[3], -1));
  139. Assert.ThrowsException<ArgumentException>(() => o.Keys.CopyTo(new string[3], 3));
  140. Assert.ThrowsException<ArgumentException>(() => o.Keys.CopyTo(new string[3], 2));
  141. Assert.ThrowsException<ArgumentNullException>(() => o.Values.CopyTo(null, 0));
  142. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.Values.CopyTo(new int[3], -1));
  143. Assert.ThrowsException<ArgumentException>(() => o.Values.CopyTo(new int[3], 3));
  144. Assert.ThrowsException<ArgumentException>(() => o.Values.CopyTo(new int[3], 2));
  145. }
  146. [TestMethod]
  147. public void ContainsKvp_ChecksKeyAndValue()
  148. {
  149. OrderedDictionary<string, int> o = new() { { "a", 4 } };
  150. Assert.IsFalse(((ICollection<KeyValuePair<string, int>>)o).Contains(new KeyValuePair<string, int>("a", 8)));
  151. Assert.IsTrue(((ICollection<KeyValuePair<string, int>>)o).Contains(new KeyValuePair<string, int>("a", 4)));
  152. }
  153. [TestMethod]
  154. public void NullValues_Permitted()
  155. {
  156. OrderedDictionary<string, string> o = new() { { "a", "1" } };
  157. Assert.IsFalse(o.ContainsValue(null));
  158. o.Add("b", null);
  159. AssertEqual([new("a", "1"), new("b", null)], o);
  160. }
  161. [TestMethod]
  162. public void GetAt_OutOfRange()
  163. {
  164. OrderedDictionary<string, string> o = new() { { "a", "1" } };
  165. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.GetAt(-2));
  166. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.GetAt(-1));
  167. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.GetAt(1));
  168. }
  169. [TestMethod]
  170. public void RemoveKvp_ChecksKeyAndValue()
  171. {
  172. OrderedDictionary<string, int> o = new() { { "a", 4 } };
  173. Assert.IsFalse(((ICollection<KeyValuePair<string, int>>)o).Remove(new KeyValuePair<string, int>("a", 8)));
  174. AssertEqual([new("a", 4)], o);
  175. Assert.IsTrue(((ICollection<KeyValuePair<string, int>>)o).Remove(new KeyValuePair<string, int>("a", 4)));
  176. AssertEqual([], o);
  177. }
  178. [TestMethod]
  179. public void SetAt()
  180. {
  181. OrderedDictionary<string, double> o = new();
  182. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(-2, 1.1));
  183. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(-1, 1.1));
  184. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(0, 1.1));
  185. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(1, 1.1));
  186. o.Add("a", 4);
  187. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(-2, 1.1));
  188. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(-1, 1.1));
  189. o.SetAt(0, 1.1);
  190. AssertEqual([new("a", 1.1)], o);
  191. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(1, 5.5));
  192. }
  193. [TestMethod]
  194. public void SetAt3Params_OutOfRange()
  195. {
  196. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 } };
  197. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(-1, "d", 16));
  198. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetAt(3, "d", 16));
  199. }
  200. [TestMethod]
  201. public void SetAt3Params_ExistingKeyCorrectIndex_PermitsChangingValue()
  202. {
  203. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 } };
  204. o.SetAt(2, "c", 16);
  205. AssertEqual([new("a", 4), new("b", 8), new("c", 16)], o);
  206. }
  207. [TestMethod]
  208. public void SetAt3Params_ExistingKeyDifferentIndex_Throws()
  209. {
  210. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 } };
  211. Assert.ThrowsException<ArgumentException>(() => o.SetAt(1, "c", 16));
  212. }
  213. [TestMethod]
  214. public void SetAt3Params_PermitsChangingToNewKey()
  215. {
  216. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 } };
  217. o.SetAt(1, "d", 16);
  218. AssertEqual([new("a", 4), new("d", 16), new("c", 12)], o);
  219. }
  220. [TestMethod]
  221. public void Get_NonExistent()
  222. {
  223. OrderedDictionary<string, float> o = new() { { "a", 4 } };
  224. Assert.ThrowsException<KeyNotFoundException>(() => o["doesn't exist"]);
  225. Assert.IsFalse(((ICollection<KeyValuePair<string, float>>)o).Contains(new KeyValuePair<string, float>("doesn't exist", 1)));
  226. Assert.IsFalse(o.ContainsKey("doesn't exist"));
  227. Assert.IsFalse(o.ContainsValue(999));
  228. Assert.AreEqual(-1, o.IndexOf("doesn't exist"));
  229. Assert.IsFalse(o.Remove("doesn't exist", out float value));
  230. Assert.AreEqual(default, value);
  231. Assert.IsFalse(o.Remove("doesn't exist"));
  232. Assert.IsFalse(((ICollection<KeyValuePair<string, float>>)o).Remove(new KeyValuePair<string, float>("doesn't exist", 1)));
  233. Assert.IsFalse(o.TryGetValue("doesn't exist", out value));
  234. Assert.AreEqual(default, value);
  235. Assert.IsFalse(o.TryGetValue("doesn't exist", out value, out int index));
  236. Assert.AreEqual(default, value);
  237. Assert.AreEqual(-1, index);
  238. AssertEqual([new("a", 4)], o);
  239. }
  240. [TestMethod]
  241. public void Insert()
  242. {
  243. OrderedDictionary<string, float> o = new() { { "a", 4 }, { "b", 8 } };
  244. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.Insert(-1, "c", 12));
  245. o.Insert(0, "c", 12); // Start
  246. AssertEqual([new("c", 12), new("a", 4), new("b", 8)], o);
  247. o.Insert(2, "d", 12); // Middle
  248. AssertEqual([new("c", 12), new("a", 4), new("d", 12), new("b", 8)], o);
  249. o.Insert(o.Count, "e", 16); // End
  250. AssertEqual([new("c", 12), new("a", 4), new("d", 12), new("b", 8), new("e", 16)], o);
  251. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.Insert(o.Count + 1, "f", 16));
  252. // Existing key
  253. Assert.ThrowsException<ArgumentException>(() => o.Insert(0, "a", 12));
  254. }
  255. [TestMethod]
  256. public void Remove_Success()
  257. {
  258. OrderedDictionary<string, float> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 } };
  259. Assert.IsTrue(o.Remove("b"));
  260. AssertEqual([new("a", 4), new("c", 12)], o);
  261. Assert.IsTrue(o.Remove("a", out float value));
  262. Assert.AreEqual(4, value);
  263. AssertEqual([new("c", 12)], o);
  264. // ICollection.Remove must match Key and Value
  265. Assert.IsFalse(((ICollection<KeyValuePair<string, float>>)o).Remove(new KeyValuePair<string, float>("c", -1)));
  266. AssertEqual([new("c", 12)], o);
  267. Assert.IsTrue(((ICollection<KeyValuePair<string, float>>)o).Remove(new KeyValuePair<string, float>("c", 12)));
  268. AssertEqual([], o);
  269. }
  270. [TestMethod]
  271. public void RemoveAt()
  272. {
  273. OrderedDictionary<string, float> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 }, { "d", 16 } };
  274. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.RemoveAt(-2));
  275. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.RemoveAt(-1));
  276. o.RemoveAt(0); // Start
  277. AssertEqual([new("b", 8), new("c", 12), new("d", 16)], o);
  278. o.RemoveAt(1); // Middle
  279. AssertEqual([new("b", 8), new("d", 16)], o);
  280. o.RemoveAt(1); // End
  281. AssertEqual([new("b", 8)], o);
  282. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.RemoveAt(1));
  283. }
  284. [TestMethod]
  285. public void SetPosition_ByIndex()
  286. {
  287. OrderedDictionary<string, float> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 }, { "d", 16 } };
  288. ArgumentOutOfRangeException ex;
  289. ex = Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetPosition(-1, 0));
  290. Assert.AreEqual("index", ex.ParamName);
  291. ex = Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetPosition(0, -1));
  292. Assert.AreEqual("newIndex", ex.ParamName);
  293. ex = Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetPosition(0, 4));
  294. Assert.AreEqual("newIndex", ex.ParamName);
  295. ex = Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetPosition(4, 0));
  296. Assert.AreEqual("index", ex.ParamName);
  297. o.SetPosition(1, 0);
  298. AssertEqual([new("b", 8), new("a", 4), new("c", 12), new("d", 16)], o);
  299. o.SetPosition(0, 1);
  300. AssertEqual([new("a", 4), new("b", 8), new("c", 12), new("d", 16)], o);
  301. o.SetPosition(1, 2);
  302. AssertEqual([new("a", 4), new("c", 12), new("b", 8), new("d", 16)], o);
  303. o.SetPosition(2, 1);
  304. AssertEqual([new("a", 4), new("b", 8), new("c", 12), new("d", 16)], o);
  305. o.SetPosition(0, 3);
  306. AssertEqual([new("b", 8), new("c", 12), new("d", 16), new("a", 4)], o);
  307. o.SetPosition(3, 1);
  308. AssertEqual([new("b", 8), new("a", 4), new("c", 12), new("d", 16)], o);
  309. o.SetPosition(1, 1); // No-op
  310. AssertEqual([new("b", 8), new("a", 4), new("c", 12), new("d", 16)], o);
  311. }
  312. [TestMethod]
  313. public void SetPosition_ByKey()
  314. {
  315. OrderedDictionary<string, float> o = new() { { "a", 4 }, { "b", 8 }, { "c", 12 }, { "d", 16 } };
  316. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetPosition("a", -1));
  317. Assert.ThrowsException<ArgumentOutOfRangeException>(() => o.SetPosition("a", 4));
  318. Assert.ThrowsException<KeyNotFoundException>(() => o.SetPosition("e", 0));
  319. o.SetPosition("b", 0);
  320. AssertEqual([new("b", 8), new("a", 4), new("c", 12), new("d", 16)], o);
  321. o.SetPosition("b", 1);
  322. AssertEqual([new("a", 4), new("b", 8), new("c", 12), new("d", 16)], o);
  323. o.SetPosition("a", 3);
  324. AssertEqual([new("b", 8), new("c", 12), new("d", 16), new("a", 4)], o);
  325. o.SetPosition("d", 2); // No-op
  326. AssertEqual([new("b", 8), new("c", 12), new("d", 16), new("a", 4)], o);
  327. }
  328. [TestMethod]
  329. public void TryAdd_Success()
  330. {
  331. OrderedDictionary<string, float> o = new() { { "a", 4 }, { "b", 8 } };
  332. Assert.IsTrue(o.TryAdd("c", 12));
  333. AssertEqual([new("a", 4), new("b", 8), new("c", 12)], o);
  334. Assert.IsTrue(o.TryAdd("d", 16, out int index));
  335. Assert.AreEqual(3, index);
  336. AssertEqual([new("a", 4), new("b", 8), new("c", 12), new("d", 16)], o);
  337. }
  338. [TestMethod]
  339. public void KeysAndValuesAreReadOnly()
  340. {
  341. OrderedDictionary<string, int> o = new() { { "a", 4 }, { "b", 8 } };
  342. Assert.IsTrue(o.Keys.IsReadOnly);
  343. Assert.ThrowsException<NotSupportedException>(() => o.Keys.Add("c"));
  344. Assert.ThrowsException<NotSupportedException>(o.Keys.Clear);
  345. Assert.ThrowsException<NotSupportedException>(() => o.Keys.Remove("a"));
  346. Assert.IsTrue(o.Values.IsReadOnly);
  347. Assert.ThrowsException<NotSupportedException>(() => o.Values.Add(12));
  348. Assert.ThrowsException<NotSupportedException>(o.Values.Clear);
  349. Assert.ThrowsException<NotSupportedException>(() => o.Values.Remove(4));
  350. }
  351. }
  352. }