5 // Jb Evain <jbevain@novell.com>
7 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Collections.Generic;
34 using NUnit.Framework;
36 namespace MonoTests.System.Collections.Generic {
39 public class HashSetTest {
42 public void TestAdd ()
44 var set = new HashSet<int> ();
46 Assert.IsTrue (set.Add (1));
47 Assert.IsTrue (set.Add (2));
48 Assert.IsTrue (set.Add (3));
49 Assert.IsTrue (set.Add (4));
50 Assert.IsFalse (set.Add (4));
51 Assert.IsFalse (set.Add (3));
52 Assert.IsFalse (set.Add (2));
53 Assert.IsFalse (set.Add (1));
54 Assert.IsTrue (set.Add (0));
55 Assert.IsFalse (set.Add (0));
59 public void TestRemove ()
61 var set = new HashSet<int> ();
63 Assert.IsTrue (set.Add (1));
64 Assert.IsTrue (set.Add (2));
65 Assert.IsTrue (set.Add (3));
66 Assert.IsTrue (set.Add (4));
68 Assert.IsTrue (set.Remove (2));
69 Assert.IsTrue (set.Remove (3));
71 AssertContainsOnly (new int [] {1, 4}, set);
75 public void TestMassiveAdd ()
77 var set = new HashSet<int> ();
79 var massive = Enumerable.Range (0, 10000).ToArray ();
80 foreach (var item in massive)
81 Assert.IsTrue (set.Add (item));
83 AssertContainsOnly (massive, set);
87 public void TestMassiveRemove ()
89 var massive = Enumerable.Range (0, 10000).ToArray ();
90 var set = new HashSet<int> (massive);
92 foreach (var item in massive)
93 Assert.IsTrue (set.Remove (item));
99 [Category("TargetJvmNotWorking")]
100 public void TestCopyTo ()
102 var data = new [] {1, 2, 3, 4, 5};
103 var set = new HashSet<int> (data);
105 var array = new int [set.Count];
106 set.CopyTo (array, 0);
108 AssertContainsOnly (data, array);
112 public void TestClear ()
114 var data = new [] {1, 2, 3, 4, 5, 6};
115 var set = new HashSet<int> (data);
117 Assert.AreEqual (data.Length, set.Count);
123 public void TestContains ()
125 var data = new [] {1, 2, 3, 4, 5, 6};
126 var set = new HashSet<int> (data);
128 foreach (var item in data)
129 Assert.IsTrue (set.Contains (item));
132 [Test, ExpectedException (typeof (InvalidOperationException))]
133 public void TestModifySetWhileForeach ()
135 var set = new HashSet<int> (new [] {1, 2, 3, 4});
136 foreach (var item in set)
141 public void TestRemoveWhere ()
143 var data = new [] {1, 2, 3, 4, 5, 6, 7, 8, 9};
144 var result = new [] {2, 4, 6, 8};
146 var set = new HashSet<int> (data);
147 int removed = set.RemoveWhere (i => (i % 2) != 0);
149 Assert.AreEqual (data.Length - result.Length, removed);
150 AssertContainsOnly (result, set);
154 public void TestOverlaps ()
156 var set = new HashSet<int> (new [] {1, 2, 3, 4, 5});
158 Assert.IsTrue (set.Overlaps (new [] {0, 2}));
162 public void TestIntersectWith ()
164 var data = new [] {1, 2, 3, 4};
165 var other = new [] {2, 4, 5, 6};
166 var result = new [] {2, 4};
168 var set = new HashSet<int> (data);
170 set.IntersectWith (other);
172 AssertContainsOnly (result, set);
176 public void TestIntersectWithComparer ()
178 var data = new[] {"a", "b", "C", "d", "E"};
179 var other = new[] {"a", "B", "e"};
180 var result = new[] {"a", "b", "E"};
182 var set = new HashSet<string> (data, StringComparer.OrdinalIgnoreCase);
184 set.IntersectWith (other);
186 AssertContainsOnly (result, set);
190 public void TestExceptWith ()
192 var data = new [] {1, 2, 3, 4, 5, 6};
193 var other = new [] {2, 4, 6};
194 var result = new [] {1, 3, 5};
195 var set = new HashSet<int> (data);
197 set.ExceptWith (other);
199 AssertContainsOnly (result, set);
203 public void TestUnionWith ()
205 var data = new [] {1, 2, 3, 4, 5, 6};
206 var other = new [] {4, 5, 6, 7, 8, 9};
207 var result = new [] {1, 2, 3, 4, 5, 6, 7, 8, 9};
209 var set = new HashSet<int> (data);
210 set.UnionWith (other);
212 AssertContainsOnly (result, set);
216 public void TestSymmetricExceptWith ()
218 var data = new [] {1, 2, 3, 4, 5};
219 var other = new [] {4, 5, 6, 7, 8, 9, 9};
220 var result = new [] {1, 2, 3, 6, 7, 8, 9};
222 var set = new HashSet<int> (data);
223 set.SymmetricExceptWith (other);
225 AssertContainsOnly (result, set);
229 public void TestEmptyHashSubsetOf ()
231 var set = new HashSet<int> ();
233 Assert.IsTrue (set.IsSubsetOf (new int [0]));
234 Assert.IsTrue (set.IsSubsetOf (new [] {1, 2}));
238 public void TestSubsetOf ()
240 var data = new [] {1, 2, 3};
241 var other = new [] {1, 2, 3, 4, 5};
242 var other2 = new [] {1, 2, 3};
243 var other3 = new [] {0, 1, 2};
245 var set = new HashSet<int> (data);
247 Assert.IsTrue (set.IsSubsetOf (other));
248 Assert.IsTrue (set.IsSubsetOf (other2));
249 Assert.IsFalse (set.IsSubsetOf (other3));
253 public void TestSubsetOfComparer ()
255 var data = new[] { "abc", "DF", "gHIl" };
257 var other1 = new[] { "pqR", "ABC", "ghil", "dF", "lmn" };
259 var set = new HashSet<string> (data, StringComparer.OrdinalIgnoreCase);
261 Assert.IsTrue (set.IsSubsetOf (other1));
265 public void TestProperSubsetOf ()
267 var data = new [] {1, 2, 3};
268 var other = new [] {1, 2, 3, 4, 5};
269 var other2 = new [] {1, 2, 3};
270 var other3 = new [] {0, 1, 2};
272 var set = new HashSet<int> (data);
274 Assert.IsTrue (set.IsProperSubsetOf (other));
275 Assert.IsFalse (set.IsProperSubsetOf (other2));
276 Assert.IsFalse (set.IsProperSubsetOf (other3));
280 public void TestProperSubsetOfComparer ()
282 var data = new[] { "abc", "DF", "gHIl" };
284 var other1 = new[] { "pqR", "ABC", "ghil", "dF", "lmn" };
286 var set = new HashSet<string> (data, StringComparer.OrdinalIgnoreCase);
288 Assert.IsTrue (set.IsProperSubsetOf (other1));
292 public void TestSupersetOf ()
294 var data = new [] {1, 2, 3, 4, 5};
295 var other = new [] {2, 3, 4};
296 var other2 = new [] {1, 2, 3, 4, 5};
297 var other3 = new [] {4, 5, 6};
299 var set = new HashSet<int> (data);
301 Assert.IsTrue (set.IsSupersetOf (other));
302 Assert.IsTrue (set.IsSupersetOf (other2));
303 Assert.IsFalse (set.IsSupersetOf (other3));
307 public void TestSupersetOfComparer ()
309 var data = new[] {"a", "B", "c", "D"};
311 var other1 = new[] {"A", "a", "C", "c"};
312 var other2 = new[] {"A", "a", "B", "D", "C", "c"};
314 var set = new HashSet<string> (data, StringComparer.OrdinalIgnoreCase);
316 Assert.IsTrue (set.IsSupersetOf (other1));
317 Assert.IsTrue (set.IsSupersetOf (other2));
321 public void TestProperSupersetOf ()
323 var data = new [] {1, 2, 3, 4, 5};
324 var other = new [] {2, 3, 4};
325 var other2 = new [] {1, 2, 3, 4, 5};
326 var other3 = new [] {4, 5, 6};
328 var set = new HashSet<int> (data);
330 Assert.IsTrue (set.IsProperSupersetOf (other));
331 Assert.IsFalse (set.IsProperSupersetOf (other2));
332 Assert.IsFalse (set.IsProperSupersetOf (other3));
336 public void TestProperSupersetOfComparer ()
338 var data = new[] { "a", "B", "c", "D" };
340 var other1 = new[] { "A", "a", "d", "D" };
341 var other2 = new[] { "A", "a", "B", "D", "C", "c" };
343 var set = new HashSet<string> (data, StringComparer.OrdinalIgnoreCase);
345 Assert.IsTrue (set.IsProperSupersetOf (other1));
346 Assert.IsFalse (set.IsProperSupersetOf (other2));
350 public void TestSetEquals ()
352 var data = new [] {1, 2, 3, 4};
354 var other = new [] {1, 2, 3, 4};
355 var other2 = new [] {1, 2, 2, 4};
356 var other3 = new [] {1, 2};
357 var other4 = new [] {1, 2, 3, 4, 5};
358 var other5 = new [] {1, 1, 1, 1};
360 var set = new HashSet<int> (data);
362 Assert.IsTrue (set.SetEquals (other));
363 Assert.IsFalse (set.SetEquals (other2));
364 Assert.IsFalse (set.SetEquals (other3));
365 Assert.IsFalse (set.SetEquals (other4));
366 Assert.IsFalse (set.SetEquals (other5));
370 public void TestSetEqualsComparer ()
372 var data = new[] { "abc", "DF", "gHIl" };
374 var other1 = new[] { "ABC", "DF", "GHIL" };
375 var other2 = new[] { "ABC", "aBc", "DF", "GHIL", "ghil" };
377 var set = new HashSet<string>(data, StringComparer.OrdinalIgnoreCase);
379 Assert.IsTrue (set.SetEquals (other1));
380 Assert.IsTrue (set.SetEquals (other2));
384 public void TestCopyToFull ()
386 var data = new [] {1, 2, 3, 4};
388 var set = new HashSet<int> (data);
390 var res = new int [set.Count];
393 AssertContainsOnly (res, data);
397 public void TestCopyToEmpty ()
399 var set = new HashSet<int> ();
401 var res = new int [0];
406 public void TestCopyToPrecise ()
408 var set = new HashSet<int> ();
411 var dest = new int [12];
413 set.CopyTo (dest, 6, 1);
415 Assert.AreEqual (42, dest [6]);
419 public void TestICollection ()
421 var set = new HashSet<int> () as ICollection<int>;
425 Assert.AreEqual (1, set.Count);
429 public void TestHashSetEqualityComparer ()
431 var data = new string[] { "foo", "bar", "foobar" };
432 var set1 = new HashSet<string> (data, StringComparer.Ordinal);
433 var set2 = new HashSet<string> (data, StringComparer.OrdinalIgnoreCase);
435 var comparer = HashSet<string>.CreateSetComparer ();
436 Assert.IsTrue (comparer.Equals (set1, set1));
437 Assert.IsTrue (comparer.Equals (set1, set2));
438 Assert.AreEqual (comparer.GetHashCode (set1), comparer.GetHashCode (set2));
440 var set3 = new HashSet<string> (new [] { "foobar", "foo", "bar" });
441 Assert.IsTrue (comparer.Equals (set1, set3));
442 Assert.AreEqual (comparer.GetHashCode (set1), comparer.GetHashCode (set3));
444 var set4 = new HashSet<string> (new [] { "oh", "hai", "folks" });
445 Assert.IsFalse (comparer.Equals (set2, set4));
446 Assert.AreNotEqual (comparer.GetHashCode (set2), comparer.GetHashCode (set4));
448 Assert.IsTrue (comparer.Equals (null, null));
449 Assert.AreEqual (0, comparer.GetHashCode (null));
450 Assert.IsFalse (comparer.Equals (set1, null));
453 static void AssertContainsOnly<T> (IEnumerable<T> result, IEnumerable<T> data)
455 Assert.AreEqual (result.Count (), data.Count ());
457 var store = new List<T> (result);
458 foreach (var element in data) {
459 Assert.IsTrue (store.Contains (element));
460 store.Remove (element);
463 AssertIsEmpty (store);
466 static void AssertIsEmpty<T> (IEnumerable<T> source)
468 Assert.AreEqual (0, source.Count ());
484 // based on #491858, #517415
485 public void Enumerator_Current ()
487 #pragma warning disable 0168
488 var e1 = new HashSet<int>.Enumerator ();
489 Assert.IsFalse (Throws (delegate { var x = e1.Current; }));
491 var d = new HashSet<int> ();
492 var e2 = d.GetEnumerator ();
493 Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
495 Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
497 Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
499 var e3 = ((IEnumerable<int>) d).GetEnumerator ();
500 Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
502 Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
504 Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
506 var e4 = ((IEnumerable) d).GetEnumerator ();
507 Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
509 Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
510 ((IDisposable) e4).Dispose ();
511 Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
512 #pragma warning restore 0168
516 public void TestNullsWithComparerThrowingException ()
518 // NOTE: We should get the same errors when using StringComparer.Ordinal on Mono 2.6.1, but the look-alike gives us more control over this test case
519 var set = new HashSet<string> (new StringComparerOrdinalLookAlike ());
520 Assert.IsTrue (set.Add (string.Empty), "#1a");
521 Assert.IsFalse (set.Contains (null), "#2a");
522 Assert.IsTrue (set.Add (null), "#2b");
523 Assert.IsTrue (set.Contains (null), "#2c");
524 Assert.AreEqual (2, set.Count, "#3");
525 Assert.IsTrue (set.Add ("a"), "#4");
526 AssertContainsOnly (new string [] { string.Empty, null, "a" }, set);
527 Assert.IsFalse (set.Add (null), "#5");
528 Assert.IsTrue (set.Add ("b"), "#6");
529 Assert.IsFalse (set.Add ("b"), "#7");
530 Assert.IsFalse (set.Add (string.Empty), "#8");
531 Assert.IsFalse (set.Add ("a"), "#9");
532 Assert.IsFalse (set.Add (null), "#10");
533 Assert.IsTrue (set.Add ("c"), "#11");
534 Assert.IsFalse (set.Add ("c"), "#12");
535 Assert.AreEqual (5, set.Count, "#13");
536 Assert.IsTrue (set.Remove (null), "#14");
537 Assert.IsTrue (set.Remove ("b"), "#15");
538 Assert.IsFalse (set.Remove (null), "#16");
539 Assert.AreEqual (3, set.Count, "#17");
540 AssertContainsOnly (new string [] { string.Empty, "a", "c" }, set);
543 private class StringComparerOrdinalLookAlike : IEqualityComparer<string>
545 public bool Equals(string x, string y)
547 return string.CompareOrdinal(x, y) == 0;
550 public int GetHashCode(string str)
553 return str.GetHashCode();
554 throw new ArgumentNullException (); // Important aspect for test (same as what StringComparer.Ordinal does, and different from GenericEqualityComparer<string>)
559 public void TrimWithoutChange ()
561 var lookup = new HashSet<string> ();
563 for (int i = 0; i < 10000; i++) {
564 lookup.Add (i.ToString ());
567 lookup.Remove (3.ToString ());
569 for (int i = 0; i < 1000; i++) {
570 lookup.TrimExcess ();