Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / mcs / class / corlib / Test / System.Collections.Generic / DictionaryTest.cs
index 4d9d141b41c1dff35347ace3d8a021662460f98c..1a89b8eedb2130b48f03a5d39e4d2a04da29e962 100644 (file)
@@ -1,5 +1,5 @@
 //
-// MonoTests.System.Collections.Generic.Test.DictionaryTest
+// MonoTests.System.Collections.Generic.DictionaryTest
 //
 // Authors:
 //     Sureshkumar T (tsureshkumar@novell.com)
@@ -37,6 +37,8 @@ using System.Collections.Generic;
 using System.IO;
 using System.Runtime.Serialization.Formatters.Binary;
 using System.Text;
+using System.Threading;
+
 using NUnit.Framework;
 
 namespace MonoTests.System.Collections.Generic {
@@ -208,6 +210,29 @@ namespace MonoTests.System.Collections.Generic {
                        Assert.AreEqual (20, _dictionary2 [m2].Value, "#4");
                        
                }
+
+               [Test]
+               [Category ("NotWorking")]
+               public void Remove_ZeroOut ()
+               {
+                       object key = new object ();
+                       object value = new object ();
+
+                       WeakReference wrKey = new WeakReference (key);
+                       WeakReference wrValue = new WeakReference (value);
+
+                       Dictionary <object, object> dictionary = new Dictionary <object, object> ();
+                       dictionary.Add (key, value);
+                       dictionary.Remove (key);
+
+                       key = null;
+                       value = null;
+                       GC.Collect ();
+                       Thread.Sleep (200);
+
+                       Assert.IsNull (wrKey.Target, "#1");
+                       Assert.IsNull (wrValue.Target, "#2");
+               }
        
                [Test, ExpectedException(typeof(ArgumentNullException))]
                public void IndexerSetNullTest()
@@ -227,6 +252,42 @@ namespace MonoTests.System.Collections.Generic {
                        Assert.IsFalse (_dictionary.ContainsKey ("key2"));
                }
        
+               [Test] // bug 432441
+               public void Clear_Iterators ()
+               {
+                       Dictionary<object, object> d = new Dictionary <object, object> ();
+
+                       d [new object ()] = new object ();
+                       d.Clear ();
+                       int hash = 0;
+                       foreach (object o in d) {
+                               hash += o.GetHashCode ();
+                       }
+               }
+
+               [Test]
+               [Category ("NotWorking")]
+               public void Clear_ZeroOut ()
+               {
+                       object key = new object ();
+                       object value = new object ();
+
+                       WeakReference wrKey = new WeakReference (key);
+                       WeakReference wrValue = new WeakReference (value);
+
+                       Dictionary <object, object> dictionary = new Dictionary <object, object> ();
+                       dictionary.Add (key, value);
+                       dictionary.Clear ();
+
+                       key = null;
+                       value = null;
+                       GC.Collect ();
+                       Thread.Sleep (200);
+
+                       Assert.IsNull (wrKey.Target, "#1");
+                       Assert.IsNull (wrValue.Target, "#2");
+               }
+
                [Test]
                public void ContainsKeyTest ()
                {
@@ -239,6 +300,12 @@ namespace MonoTests.System.Collections.Generic {
                        contains = _dictionary.ContainsKey ("key5");
                        Assert.IsFalse (contains, "ContainsKey for non existant does not return correct value!");
                }
+
+               [Test, ExpectedException (typeof (ArgumentNullException))]
+               public void ContainsKeyTest2 ()
+               {
+                       _dictionary.ContainsKey (null);
+               }
        
                [Test]
                public void ContainsValueTest ()
@@ -302,7 +369,6 @@ namespace MonoTests.System.Collections.Generic {
                                return myt.Name.Equals (this.Name) &&
                                                myt.RollNo.Equals (this.RollNo);
                        }
-       
                }
        
                [Test]
@@ -341,10 +407,8 @@ namespace MonoTests.System.Collections.Generic {
                        IEnumerator itr = ((IEnumerable)_dictionary).GetEnumerator ();
                        while (itr.MoveNext ()) {
                                object o = itr.Current;
-                               Assert.AreEqual (typeof (DictionaryEntry), o.GetType (), "Current should return a type of DictionaryEntry");
-                               DictionaryEntry entry = (DictionaryEntry)itr.Current;
-                               if (entry.Key.ToString () == "key4")
-                                       entry.Value = "value33";
+                               Assert.AreEqual (typeof (KeyValuePair<string,object>), o.GetType (), "Current should return a type of KeyValuePair");
+                               KeyValuePair<string,object> entry = (KeyValuePair<string,object>) itr.Current;
                        }
                        Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
                }
@@ -360,11 +424,10 @@ namespace MonoTests.System.Collections.Generic {
                        IEnumerator <KeyValuePair <string, object>> itr = ((IEnumerable <KeyValuePair <string, object>>)_dictionary).GetEnumerator ();
                        while (itr.MoveNext ()) {
                                object o = itr.Current;
-                               Assert.AreEqual (typeof (KeyValuePair <string, object>), o.GetType (), "Current should return a type of DictionaryEntry");
+                               Assert.AreEqual (typeof (KeyValuePair <string, object>), o.GetType (), "Current should return a type of KeyValuePair<object,string>");
                                KeyValuePair <string, object> entry = (KeyValuePair <string, object>)itr.Current;
                        }
                        Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
-       
                }
        
                [Test]
@@ -378,12 +441,9 @@ namespace MonoTests.System.Collections.Generic {
                        while (itr.MoveNext ()) {
                                object o = itr.Current;
                                Assert.AreEqual (typeof (DictionaryEntry), o.GetType (), "Current should return a type of DictionaryEntry");
-                               DictionaryEntry entry = (DictionaryEntry)itr.Current;
-                               if (entry.Key.ToString () == "key4")
-                                       entry.Value = "value33";
+                               DictionaryEntry entry = (DictionaryEntry) itr.Current;
                        }
                        Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
-       
                }
        
                [Test]
@@ -396,23 +456,17 @@ namespace MonoTests.System.Collections.Generic {
        
                        int i = 0;
                        foreach (KeyValuePair <string, object> entry in _dictionary)
-                       {
                                i++;
-                       }
                        Assert.AreEqual(4, i, "fail1: foreach entry failed!");
        
                        i = 0;
-                       foreach (DictionaryEntry entry in ((IEnumerable)_dictionary))
-                       {
+                       foreach (KeyValuePair <string, object> entry in ((IEnumerable)_dictionary))
                                i++;
-                       }
                        Assert.AreEqual(4, i, "fail2: foreach entry failed!");
        
                        i = 0;
                        foreach (DictionaryEntry entry in ((IDictionary)_dictionary))
-                       {
                                i++;
-                       }
                        Assert.AreEqual (4, i, "fail3: foreach entry failed!");
                }
        
@@ -455,37 +509,37 @@ namespace MonoTests.System.Collections.Generic {
                [Test]
                public void KeyValueEnumeratorTest ()
                {
-                       IDictionary<int, int> d = new Dictionary<int, int>();
+                       IDictionary<int, int> d = new Dictionary<int, int>();
 
                        // Values are chosen such that two keys map to the same bucket.
                        // Default dictionary table size == 10
-                       d [9] = 1;
-                       d [10] = 2;
-                       d [19] = 3;
+                       d [9] = 1;
+                       d [10] = 2;
+                       d [19] = 3;
 
                        Assert.AreEqual (d.Count, d.Keys.Count, "d and d.Keys don't appear to match");
                        Assert.AreEqual (d.Values.Count, d.Keys.Count, "d.Keys and d.Values don't appear to match");
 
-                       int count = 0;
-                       foreach (int i in d.Values)
-                               ++count;
+                       int count = 0;
+                       foreach (int i in d.Values)
+                               ++count;
                        Assert.AreEqual (count, d.Values.Count, "d.Values doesn't have the correct number of elements");
        
-                       count = 0;
+                       count = 0;
                        foreach (int i in d.Keys)
                                ++count;
                        Assert.AreEqual (count, d.Keys.Count, "d.Keys doesn't have the correct number of elements");
 
                        int nkeys = count;
                        count = 0;
-                       foreach (int i in d.Keys) {
+                       foreach (int i in d.Keys) {
                                int foo = d [i];
                                if (count++ >= nkeys)
                                        Assert.Fail ("Reading a value appears to trash enumerator state");
                        }
                }
 
-               [Test]          // bug 75073
+               [Test] // bug 75073
                public void SliceCollectionsEnumeratorTest ()
                {
                        Dictionary<string, int> values = new Dictionary<string, int> ();
@@ -500,13 +554,14 @@ namespace MonoTests.System.Collections.Generic {
                [Test]
                public void PlainEnumeratorReturnTest ()
                {
-                       // Test that we return a DictionaryEntry for non-generic dictionary iteration
+                       // Test that we return a KeyValuePair even for non-generic dictionary iteration
                        _dictionary["foo"] = "bar";
                        IEnumerator<KeyValuePair<string, object>> enumerator = _dictionary.GetEnumerator();
-                       Assert.IsTrue(enumerator.MoveNext());
-                       Assert.IsTrue(((IEnumerator)enumerator).Current is DictionaryEntry);
-                       Assert.IsTrue(((IDictionaryEnumerator)enumerator).Current is DictionaryEntry);
-                       Assert.IsFalse(((object) enumerator.Current) is DictionaryEntry);
+                       Assert.IsTrue(enumerator.MoveNext(), "#1");
+                       Assert.AreEqual (typeof (KeyValuePair<string,object>), ((IEnumerator)enumerator).Current.GetType (), "#2");
+                       Assert.AreEqual (typeof (DictionaryEntry), ((IDictionaryEnumerator)enumerator).Entry.GetType (), "#3");
+                       Assert.AreEqual (typeof (KeyValuePair<string,object>), ((IDictionaryEnumerator)enumerator).Current.GetType (), "#4");
+                       Assert.AreEqual (typeof (KeyValuePair<string,object>), ((object) enumerator.Current).GetType (), "#5");
                }
 
                [Test, ExpectedException (typeof (InvalidOperationException))]
@@ -612,8 +667,567 @@ namespace MonoTests.System.Collections.Generic {
                        object ob = x.Values;
                        foreach (KeyValuePair<int,int> a in x){
                        }
+               }
+
+               [Test]
+               public void Empty_KeysValues_CopyTo ()
+               {
+                       Dictionary<int, int> d = new Dictionary<int, int> ();
+                       int[] array = new int[1];
+                       d.Keys.CopyTo (array, array.Length);
+                       d.Values.CopyTo (array, array.Length);
+               }
+
+               [Test]
+               public void Empty_CopyTo ()
+               {
+                       Dictionary<int, int> d = new Dictionary<int, int> ();
+                       ICollection c = (ICollection) d;
+                       DictionaryEntry [] array = new DictionaryEntry [1];
+                       c.CopyTo (array, array.Length);
+
+                       ICollection<KeyValuePair<int,int>> c2 = d;
+                       KeyValuePair<int,int> [] array2 = new KeyValuePair<int,int> [1];
+                       c2.CopyTo (array2, array2.Length);
+               }
+
+               [Test]
+               public void IDictionary_Contains ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add (1, 2);
+                       Assert.IsTrue (d.Contains (1));
+                       Assert.IsFalse (d.Contains (2));
+                       Assert.IsFalse (d.Contains ("x"));
+               }
+
+               [Test, ExpectedException (typeof (ArgumentNullException))]
+               public void IDictionary_Contains2 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Contains (null);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentNullException))]
+               public void IDictionary_Add1 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add (null, 1);
+               }
 
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void IDictionary_Add2 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add ("bar", 1);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void IDictionary_Add3 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add (1, "bar");
+               }
+
+               [Test]
+               public void IDictionary_Add_Null ()
+               {
+                       IDictionary d = new Dictionary<int, string> ();
+                       d.Add (1, null);
+                       d [2] = null;
+
+                       Assert.IsNull (d [1]);
+                       Assert.IsNull (d [2]);
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void IDictionary_Add_Null_2 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add (1, null);
+               }
+
+               [Test]
+               public void IDictionary_Remove1 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add (1, 2);
+                       d.Remove (1);
+                       d.Remove (5);
+                       d.Remove ("foo");
+               }
+
+               [Test, ExpectedException (typeof (ArgumentNullException))]
+               public void IDictionary_Remove2 ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Remove (null);
+               }
+               
+               [Test]
+               public void IDictionary_IndexerGetNonExistingTest ()
+               {
+                       IDictionary d = new Dictionary<int, int> ();
+                       d.Add(1, 2);
+                       Assert.IsNull(d[2]);
+                       Assert.IsNull(d["foo"]);
+               }
+
+               [Test] // bug #332534
+               public void Dictionary_MoveNext ()
+               {
+                       Dictionary<int,int> a = new Dictionary<int,int>();
+                       a.Add(3,1);
+                       a.Add(4,1);
+
+                       IEnumerator en = a.GetEnumerator();
+                       for (int i = 1; i < 10; i++)
+                               en.MoveNext();
+               }
+
+               [Test]
+               public void CopyToArray ()
+               {
+                       Dictionary<string, string> test = new Dictionary<string, string> ();
+                       test.Add ("monkey", "singe");
+                       test.Add ("singe", "mono");
+                       test.Add ("mono", "monkey");
+                       Assert.AreEqual (3, test.Keys.Count, "Dictionary.Count");
                        
+                       ArrayList list = new ArrayList (test.Keys);
+                       Assert.AreEqual (3, list.Count, "ArrayList.Count");
+                       Assert.IsTrue (list.Contains ("monkey"), "monkey");
+                       Assert.IsTrue (list.Contains ("singe"), "singe");
+                       Assert.IsTrue (list.Contains ("mono"), "mono");
+               }
+
+               [Test]
+               public void KeyObjectMustNotGetChangedIfKeyAlreadyExists ()
+               {
+                       Dictionary<String, int> d = new Dictionary<string, int> ();
+                       string s1 = "Test";
+                       string s2 = "Tes" + "T".ToLowerInvariant();
+                       d[s1] = 1;
+                       d[s2] = 2;
+                       string comp = String.Empty;
+                       foreach (String s in d.Keys)
+                               comp = s;
+                       Assert.IsTrue (Object.ReferenceEquals (s1, comp));
+               }
+
+               [Test]
+               public void ResetKeysEnumerator ()
+               {
+                       Dictionary<string, string> test = new Dictionary<string, string> ();
+                       test.Add ("monkey", "singe");
+                       test.Add ("singe", "mono");
+                       test.Add ("mono", "monkey");
+
+                       IEnumerator enumerator = test.Keys.GetEnumerator ();
+
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+
+                       enumerator.Reset ();
+
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsFalse (enumerator.MoveNext ());
+               }
+
+               [Test]
+               public void ResetValuesEnumerator ()
+               {
+                       Dictionary<string, string> test = new Dictionary<string, string> ();
+                       test.Add ("monkey", "singe");
+                       test.Add ("singe", "mono");
+                       test.Add ("mono", "monkey");
+
+                       IEnumerator enumerator = test.Values.GetEnumerator ();
+
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+
+                       enumerator.Reset ();
+
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsFalse (enumerator.MoveNext ());
+               }
+
+               [Test]
+               public void ResetShimEnumerator ()
+               {
+                       IDictionary test = new Dictionary<string, string> ();
+                       test.Add ("monkey", "singe");
+                       test.Add ("singe", "mono");
+                       test.Add ("mono", "monkey");
+
+                       IEnumerator enumerator = test.GetEnumerator ();
+
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+
+                       enumerator.Reset ();
+
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsTrue (enumerator.MoveNext ());
+                       Assert.IsFalse (enumerator.MoveNext ());
+               }
+
+               [Test]
+               public void ICollectionOfKeyValuePairContains ()
+               {
+                       var dictionary = new Dictionary<string, int> ();
+                       dictionary.Add ("foo", 42);
+                       dictionary.Add ("bar", 12);
+
+                       var collection = dictionary as ICollection<KeyValuePair<string, int>>;
+
+                       Assert.AreEqual (2, collection.Count);
+
+                       Assert.IsFalse (collection.Contains (new KeyValuePair<string, int> ("baz", 13)));
+                       Assert.IsFalse (collection.Contains (new KeyValuePair<string, int> ("foo", 13)));
+                       Assert.IsTrue (collection.Contains (new KeyValuePair<string, int> ("foo", 42)));
+               }
+
+               [Test]
+               public void ICollectionOfKeyValuePairRemove ()
+               {
+                       var dictionary = new Dictionary<string, int> ();
+                       dictionary.Add ("foo", 42);
+                       dictionary.Add ("bar", 12);
+
+                       var collection = dictionary as ICollection<KeyValuePair<string, int>>;
+
+                       Assert.AreEqual (2, collection.Count);
+
+                       Assert.IsFalse (collection.Remove (new KeyValuePair<string, int> ("baz", 13)));
+                       Assert.IsFalse (collection.Remove (new KeyValuePair<string, int> ("foo", 13)));
+                       Assert.IsTrue (collection.Remove (new KeyValuePair<string, int> ("foo", 42)));
+
+                       Assert.AreEqual (12, dictionary ["bar"]);
+                       Assert.IsFalse (dictionary.ContainsKey ("foo"));
+               }
+
+               [Test]
+               public void ICollectionCopyToKeyValuePairArray ()
+               {
+                       var dictionary = new Dictionary<string, int> ();
+                       dictionary.Add ("foo", 42);
+
+                       var collection = dictionary as ICollection;
+
+                       Assert.AreEqual (1, collection.Count);
+
+                       var pairs = new KeyValuePair<string, int> [1];
+
+                       collection.CopyTo (pairs, 0);
+
+                       Assert.AreEqual ("foo", pairs [0].Key);
+                       Assert.AreEqual (42, pairs [0].Value);
+               }
+
+               [Test]
+               public void ICollectionCopyToDictionaryEntryArray ()
+               {
+                       var dictionary = new Dictionary<string, int> ();
+                       dictionary.Add ("foo", 42);
+
+                       var collection = dictionary as ICollection;
+
+                       Assert.AreEqual (1, collection.Count);
+
+                       var entries = new DictionaryEntry [1];
+
+                       collection.CopyTo (entries, 0);
+
+                       Assert.AreEqual ("foo", (string) entries [0].Key);
+                       Assert.AreEqual (42, (int) entries [0].Value);
+               }
+
+               [Test]
+               public void ICollectionCopyToObjectArray ()
+               {
+                       var dictionary = new Dictionary<string, int> ();
+                       dictionary.Add ("foo", 42);
+
+                       var collection = dictionary as ICollection;
+
+                       Assert.AreEqual (1, collection.Count);
+
+                       var array = new object [1];
+
+                       collection.CopyTo (array, 0);
+
+                       var pair = (KeyValuePair<string, int>) array [0];
+
+                       Assert.AreEqual ("foo", pair.Key);
+                       Assert.AreEqual (42, pair.Value);
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void ICollectionCopyToInvalidArray ()
+               {
+                       var dictionary = new Dictionary<string, int> ();
+                       dictionary.Add ("foo", 42);
+
+                       var collection = dictionary as ICollection;
+
+                       Assert.AreEqual (1, collection.Count);
+
+                       var array = new int [1];
+
+                       collection.CopyTo (array, 0);
+               }
+
+               [Test]
+               public void ValuesCopyToObjectArray ()
+               {
+                       var dictionary = new Dictionary<string, string> { { "foo", "bar" } };
+
+                       var values = dictionary.Values as ICollection;
+
+                       var array = new object [values.Count];
+
+                       values.CopyTo (array, 0);
+
+                       Assert.AreEqual ("bar", array [0]);
+               }
+
+               delegate void D ();
+               bool Throws (D d)
+               {
+                       try {
+                               d ();
+                               return false;
+                       } catch {
+                               return true;
+                       }
+               }
+
+               [Test]
+               // based on #491858, #517415
+               public void Enumerator_Current ()
+               {
+                       var e1 = new Dictionary<int,int>.Enumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e1.Current; }));
+
+                       var d = new Dictionary<int,int> ();
+                       var e2 = d.GetEnumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+                       e2.MoveNext ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+                       e2.Dispose ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+
+                       var e3 = ((IEnumerable<KeyValuePair<int,int>>) d).GetEnumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+                       e3.MoveNext ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+                       e3.Dispose ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+
+                       var e4 = ((IEnumerable) d).GetEnumerator ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+                       e4.MoveNext ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+                       ((IDisposable) e4).Dispose ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+               }
+
+               [Test]
+               // based on #491858, #517415
+               public void KeyEnumerator_Current ()
+               {
+                       var e1 = new Dictionary<int,int>.KeyCollection.Enumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e1.Current; }));
+
+                       var d = new Dictionary<int,int> ().Keys;
+                       var e2 = d.GetEnumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+                       e2.MoveNext ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+                       e2.Dispose ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+
+                       var e3 = ((IEnumerable<int>) d).GetEnumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+                       e3.MoveNext ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+                       e3.Dispose ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+
+                       var e4 = ((IEnumerable) d).GetEnumerator ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+                       e4.MoveNext ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+                       ((IDisposable) e4).Dispose ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+               }
+
+               [Test]
+               // based on #491858, #517415
+               public void ValueEnumerator_Current ()
+               {
+                       var e1 = new Dictionary<int,int>.ValueCollection.Enumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e1.Current; }));
+
+                       var d = new Dictionary<int,int> ().Values;
+                       var e2 = d.GetEnumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+                       e2.MoveNext ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+                       e2.Dispose ();
+                       Assert.IsFalse (Throws (delegate { var x = e2.Current; }));
+
+                       var e3 = ((IEnumerable<int>) d).GetEnumerator ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+                       e3.MoveNext ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+                       e3.Dispose ();
+                       Assert.IsFalse (Throws (delegate { var x = e3.Current; }));
+
+                       var e4 = ((IEnumerable) d).GetEnumerator ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+                       e4.MoveNext ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+                       ((IDisposable) e4).Dispose ();
+                       Assert.IsTrue (Throws (delegate { var x = e4.Current; }));
+               }
+
+               [Test]
+               public void ICollectionCopyTo ()
+               {
+                       var d = new Dictionary<int, string> ();
+
+                       ICollection c = d;
+                       c.CopyTo (new object [0], 0);
+                       c.CopyTo (new string [0], 0);
+                       c.CopyTo (new MyClass [0], 0);
+
+                       c = d.Keys;
+                       c.CopyTo (new object [0], 0);
+                       c.CopyTo (new ValueType [0], 0);
+
+                       c = d.Values;
+                       c.CopyTo (new object [0], 0);
+                       c.CopyTo (new MyClass [0], 0);
+
+                       d [3] = null;
+
+                       c = d.Keys;
+                       c.CopyTo (new object [1], 0);
+                       c.CopyTo (new ValueType [1], 0);
+
+                       c = d.Values;
+                       c.CopyTo (new object [1], 0);
+                       c.CopyTo (new MyClass [1], 0);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ICollectionCopyTo_ex1 ()
+               {
+                       var d = new Dictionary<int, string> ();
+                       ICollection c = d.Keys;
+                       c.CopyTo (new string [1], 0);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ICollectionCopyTo_ex2 ()
+               {
+                       var d = new Dictionary<int, string> ();
+                       ICollection c = d.Values;
+                       c.CopyTo (new int [1], 0);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ICollectionCopyTo_ex3 ()
+               {
+                       var d = new Dictionary<int, string> ();
+                       d [3] = "5";
+
+                       ICollection c = d.Keys;
+                       c.CopyTo (new MyClass [1], 0);
+               }
+
+               [Test, ExpectedException (typeof (ArgumentException))]
+               public void ICollectionCopyTo_ex4 ()
+               {
+                       var d = new Dictionary<int, string> ();
+                       d [3] = "5";
+
+                       ICollection c = d.Values;
+                       c.CopyTo (new MyClass [1], 0);
+               }
+
+               [Test] // bug 474009
+               public void DeserializeEmptyDictionary ()
+               {
+                       // contains a Dictionary<string, int> with Count = 0
+                       // serialized with MS.NET 3.5
+                       string data =
+@"AAEAAAD/////AQAAAAAAAAAEAQAAAOEBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuRGljdGlv
+bmFyeWAyW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJl
+PW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uSW50MzIs
+IG1zY29ybGliLCBWZXJzaW9uPTIuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9r
+ZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAwAAAAdWZXJzaW9uCENvbXBhcmVyCEhhc2hTaXplAAMACJIB
+U3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuR2VuZXJpY0VxdWFsaXR5Q29tcGFyZXJgMVtbU3lz
+dGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQ
+dWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAAAAAAkCAAAAAAAAAAQCAAAAkgFTeXN0
+ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5HZW5lcmljRXF1YWxpdHlDb21wYXJlcmAxW1tTeXN0ZW0u
+U3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1Ymxp
+Y0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQAAAAAL";
+
+                       var stream = new MemoryStream (Convert.FromBase64String (data));
+                       var fmt = new BinaryFormatter ();
+                       var dict = (Dictionary <string, int>) fmt.Deserialize (stream);
+                       Assert.AreEqual (0, dict.Count);
+               }
+
+               [Test]
+               public void DeserializeNonEmptyDictionary ()
+               {
+                       // contains a Dictionary<string, int> with Count = 2
+                       // and dict [i.ToString()] == i for each i.
+                       // serialized with MS.NET 3.5
+                       string data =
+@"AAEAAAD/////AQAAAAAAAAAEAQAAAOEBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuRGljdGlv
+bmFyeWAyW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJl
+PW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uSW50MzIs
+IG1zY29ybGliLCBWZXJzaW9uPTIuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9r
+ZW49Yjc3YTVjNTYxOTM0ZTA4OV1dBAAAAAdWZXJzaW9uCENvbXBhcmVyCEhhc2hTaXplDUtleVZh
+bHVlUGFpcnMAAwADCJIBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuR2VuZXJpY0VxdWFsaXR5
+Q29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249Mi4wLjAuMCwgQ3Vs
+dHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0I5QFTeXN0ZW0u
+Q29sbGVjdGlvbnMuR2VuZXJpYy5LZXlWYWx1ZVBhaXJgMltbU3lzdGVtLlN0cmluZywgbXNjb3Js
+aWIsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdh
+NWM1NjE5MzRlMDg5XSxbU3lzdGVtLkludDMyLCBtc2NvcmxpYiwgVmVyc2lvbj0yLjAuMC4wLCBD
+dWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXVtdAgAAAAkC
+AAAAAwAAAAkDAAAABAIAAACSAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkdlbmVyaWNFcXVh
+bGl0eUNvbXBhcmVyYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTIuMC4wLjAs
+IEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dAAAAAAcD
+AAAAAAEAAAACAAAAA+MBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuS2V5VmFsdWVQYWlyYDJb
+W1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTIuMC4wLjAsIEN1bHR1cmU9bmV1dHJh
+bCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5JbnQzMiwgbXNjb3Js
+aWIsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdh
+NWM1NjE5MzRlMDg5XV0E/P///+MBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuS2V5VmFsdWVQ
+YWlyYDJbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTIuMC4wLjAsIEN1bHR1cmU9
+bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5JbnQzMiwg
+bXNjb3JsaWIsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tl
+bj1iNzdhNWM1NjE5MzRlMDg5XV0CAAAAA2tleQV2YWx1ZQEACAYFAAAAATAAAAAAAfr////8////
+BgcAAAABMQEAAAAL";
+                       var stream = new MemoryStream (Convert.FromBase64String (data));
+                       var fmt = new BinaryFormatter ();
+                       var dict = (Dictionary <string, int>) fmt.Deserialize (stream);
+                       Assert.AreEqual (2, dict.Count);
+                       for (int i = 0; i < dict.Count; i++)
+                               Assert.AreEqual (i, dict[i.ToString ()]);
                }
        }
 }