]> granicus.if.org Git - python/commitdiff
Issue #25616: Tests for OrderedDict are extracted from test_collections
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 25 Nov 2015 15:18:57 +0000 (17:18 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 25 Nov 2015 15:18:57 +0000 (17:18 +0200)
into separate file test_ordered_dict.

1  2 
Lib/test/test_ordered_dict.py
Misc/NEWS

index 0000000000000000000000000000000000000000,4b092279692c212731a76bed89edc2086c97229f..e64c7e50806ffdbc855472c28a1f3231ffbb5a99
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,683 +1,691 @@@
+ import contextlib
+ import copy
+ import pickle
+ from random import randrange, shuffle
+ import sys
+ import unittest
+ from collections.abc import MutableMapping
+ from test import mapping_tests, support
+ py_coll = support.import_fresh_module('collections', blocked=['_collections'])
+ c_coll = support.import_fresh_module('collections', fresh=['_collections'])
+ @contextlib.contextmanager
+ def replaced_module(name, replacement):
+     original_module = sys.modules[name]
+     sys.modules[name] = replacement
+     try:
+         yield
+     finally:
+         sys.modules[name] = original_module
+ class OrderedDictTests:
+     def test_init(self):
+         OrderedDict = self.OrderedDict
+         with self.assertRaises(TypeError):
+             OrderedDict([('a', 1), ('b', 2)], None)                                 # too many args
+         pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+         self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs)           # dict input
+         self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs)         # kwds input
+         self.assertEqual(list(OrderedDict(pairs).items()), pairs)                   # pairs input
+         self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
+                                           c=3, e=5).items()), pairs)                # mixed input
+         # make sure no positional args conflict with possible kwdargs
+         self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
+         self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
+         self.assertRaises(TypeError, OrderedDict, 42)
+         self.assertRaises(TypeError, OrderedDict, (), ())
+         self.assertRaises(TypeError, OrderedDict.__init__)
+         # Make sure that direct calls to __init__ do not clear previous contents
+         d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
+         d.__init__([('e', 5), ('f', 6)], g=7, d=4)
+         self.assertEqual(list(d.items()),
+             [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
+     def test_update(self):
+         OrderedDict = self.OrderedDict
+         with self.assertRaises(TypeError):
+             OrderedDict().update([('a', 1), ('b', 2)], None)                        # too many args
+         pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+         od = OrderedDict()
+         od.update(dict(pairs))
+         self.assertEqual(sorted(od.items()), pairs)                                 # dict input
+         od = OrderedDict()
+         od.update(**dict(pairs))
+         self.assertEqual(sorted(od.items()), pairs)                                 # kwds input
+         od = OrderedDict()
+         od.update(pairs)
+         self.assertEqual(list(od.items()), pairs)                                   # pairs input
+         od = OrderedDict()
+         od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
+         self.assertEqual(list(od.items()), pairs)                                   # mixed input
+         # Issue 9137: Named argument called 'other' or 'self'
+         # shouldn't be treated specially.
+         od = OrderedDict()
+         od.update(self=23)
+         self.assertEqual(list(od.items()), [('self', 23)])
+         od = OrderedDict()
+         od.update(other={})
+         self.assertEqual(list(od.items()), [('other', {})])
+         od = OrderedDict()
+         od.update(red=5, blue=6, other=7, self=8)
+         self.assertEqual(sorted(list(od.items())),
+                          [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
+         # Make sure that direct calls to update do not clear previous contents
+         # add that updates items are not moved to the end
+         d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
+         d.update([('e', 5), ('f', 6)], g=7, d=4)
+         self.assertEqual(list(d.items()),
+             [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
+         self.assertRaises(TypeError, OrderedDict().update, 42)
+         self.assertRaises(TypeError, OrderedDict().update, (), ())
+         self.assertRaises(TypeError, OrderedDict.update)
+         self.assertRaises(TypeError, OrderedDict().update, 42)
+         self.assertRaises(TypeError, OrderedDict().update, (), ())
+         self.assertRaises(TypeError, OrderedDict.update)
+     def test_fromkeys(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict.fromkeys('abc')
+         self.assertEqual(list(od.items()), [(c, None) for c in 'abc'])
+         od = OrderedDict.fromkeys('abc', value=None)
+         self.assertEqual(list(od.items()), [(c, None) for c in 'abc'])
+         od = OrderedDict.fromkeys('abc', value=0)
+         self.assertEqual(list(od.items()), [(c, 0) for c in 'abc'])
+     def test_abc(self):
+         OrderedDict = self.OrderedDict
+         self.assertIsInstance(OrderedDict(), MutableMapping)
+         self.assertTrue(issubclass(OrderedDict, MutableMapping))
+     def test_clear(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         shuffle(pairs)
+         od = OrderedDict(pairs)
+         self.assertEqual(len(od), len(pairs))
+         od.clear()
+         self.assertEqual(len(od), 0)
+     def test_delitem(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         od = OrderedDict(pairs)
+         del od['a']
+         self.assertNotIn('a', od)
+         with self.assertRaises(KeyError):
+             del od['a']
+         self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
+     def test_setitem(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
+         od['c'] = 10           # existing element
+         od['f'] = 20           # new element
+         self.assertEqual(list(od.items()),
+                          [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
+     def test_iterators(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         shuffle(pairs)
+         od = OrderedDict(pairs)
+         self.assertEqual(list(od), [t[0] for t in pairs])
+         self.assertEqual(list(od.keys()), [t[0] for t in pairs])
+         self.assertEqual(list(od.values()), [t[1] for t in pairs])
+         self.assertEqual(list(od.items()), pairs)
+         self.assertEqual(list(reversed(od)),
+                          [t[0] for t in reversed(pairs)])
+         self.assertEqual(list(reversed(od.keys())),
+                          [t[0] for t in reversed(pairs)])
+         self.assertEqual(list(reversed(od.values())),
+                          [t[1] for t in reversed(pairs)])
+         self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
+     def test_detect_deletion_during_iteration(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict.fromkeys('abc')
+         it = iter(od)
+         key = next(it)
+         del od[key]
+         with self.assertRaises(Exception):
+             # Note, the exact exception raised is not guaranteed
+             # The only guarantee that the next() will not succeed
+             next(it)
+     def test_sorted_iterators(self):
+         OrderedDict = self.OrderedDict
+         with self.assertRaises(TypeError):
+             OrderedDict([('a', 1), ('b', 2)], None)
+         pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+         od = OrderedDict(pairs)
+         self.assertEqual(sorted(od), [t[0] for t in pairs])
+         self.assertEqual(sorted(od.keys()), [t[0] for t in pairs])
+         self.assertEqual(sorted(od.values()), [t[1] for t in pairs])
+         self.assertEqual(sorted(od.items()), pairs)
+         self.assertEqual(sorted(reversed(od)),
+                          sorted([t[0] for t in reversed(pairs)]))
+     def test_iterators_empty(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         empty = []
+         self.assertEqual(list(od), empty)
+         self.assertEqual(list(od.keys()), empty)
+         self.assertEqual(list(od.values()), empty)
+         self.assertEqual(list(od.items()), empty)
+         self.assertEqual(list(reversed(od)), empty)
+         self.assertEqual(list(reversed(od.keys())), empty)
+         self.assertEqual(list(reversed(od.values())), empty)
+         self.assertEqual(list(reversed(od.items())), empty)
+     def test_popitem(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         shuffle(pairs)
+         od = OrderedDict(pairs)
+         while pairs:
+             self.assertEqual(od.popitem(), pairs.pop())
+         with self.assertRaises(KeyError):
+             od.popitem()
+         self.assertEqual(len(od), 0)
+     def test_popitem_last(self):
+         OrderedDict = self.OrderedDict
+         pairs = [(i, i) for i in range(30)]
+         obj = OrderedDict(pairs)
+         for i in range(8):
+             obj.popitem(True)
+         obj.popitem(True)
+         obj.popitem(last=True)
+         self.assertEqual(len(obj), 20)
+     def test_pop(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         shuffle(pairs)
+         od = OrderedDict(pairs)
+         shuffle(pairs)
+         while pairs:
+             k, v = pairs.pop()
+             self.assertEqual(od.pop(k), v)
+         with self.assertRaises(KeyError):
+             od.pop('xyz')
+         self.assertEqual(len(od), 0)
+         self.assertEqual(od.pop(k, 12345), 12345)
+         # make sure pop still works when __missing__ is defined
+         class Missing(OrderedDict):
+             def __missing__(self, key):
+                 return 0
+         m = Missing(a=1)
+         self.assertEqual(m.pop('b', 5), 5)
+         self.assertEqual(m.pop('a', 6), 1)
+         self.assertEqual(m.pop('a', 6), 6)
+         self.assertEqual(m.pop('a', default=6), 6)
+         with self.assertRaises(KeyError):
+             m.pop('a')
+     def test_equality(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         shuffle(pairs)
+         od1 = OrderedDict(pairs)
+         od2 = OrderedDict(pairs)
+         self.assertEqual(od1, od2)          # same order implies equality
+         pairs = pairs[2:] + pairs[:2]
+         od2 = OrderedDict(pairs)
+         self.assertNotEqual(od1, od2)       # different order implies inequality
+         # comparison to regular dict is not order sensitive
+         self.assertEqual(od1, dict(od2))
+         self.assertEqual(dict(od2), od1)
+         # different length implied inequality
+         self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
+     def test_copying(self):
+         OrderedDict = self.OrderedDict
+         # Check that ordered dicts are copyable, deepcopyable, picklable,
+         # and have a repr/eval round-trip
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         od = OrderedDict(pairs)
+         def check(dup):
+             msg = "\ncopy: %s\nod: %s" % (dup, od)
+             self.assertIsNot(dup, od, msg)
+             self.assertEqual(dup, od)
+             self.assertEqual(list(dup.items()), list(od.items()))
+             self.assertEqual(len(dup), len(od))
+             self.assertEqual(type(dup), type(od))
+         check(od.copy())
+         check(copy.copy(od))
+         check(copy.deepcopy(od))
+         # pickle directly pulls the module, so we have to fake it
+         with replaced_module('collections', self.module):
+             for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+                 with self.subTest(proto=proto):
+                     check(pickle.loads(pickle.dumps(od, proto)))
+         check(eval(repr(od)))
+         update_test = OrderedDict()
+         update_test.update(od)
+         check(update_test)
+         check(OrderedDict(od))
+     def test_yaml_linkage(self):
+         OrderedDict = self.OrderedDict
+         # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
+         # In yaml, lists are native but tuples are not.
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         od = OrderedDict(pairs)
+         # yaml.dump(od) -->
+         # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n  - [b, 2]\n'
+         self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
+     def test_reduce_not_too_fat(self):
+         OrderedDict = self.OrderedDict
+         # do not save instance dictionary if not needed
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         od = OrderedDict(pairs)
+         self.assertIsNone(od.__reduce__()[2])
+         od.x = 10
+         self.assertIsNotNone(od.__reduce__()[2])
+     def test_pickle_recursive(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         od[1] = od
+         # pickle directly pulls the module, so we have to fake it
+         with replaced_module('collections', self.module):
+             for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
+                 dup = pickle.loads(pickle.dumps(od, proto))
+                 self.assertIsNot(dup, od)
+                 self.assertEqual(list(dup.keys()), [1])
+                 self.assertIs(dup[1], dup)
+     def test_repr(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
+         self.assertEqual(repr(od),
+             "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
+         self.assertEqual(eval(repr(od)), od)
+         self.assertEqual(repr(OrderedDict()), "OrderedDict()")
+     def test_repr_recursive(self):
+         OrderedDict = self.OrderedDict
+         # See issue #9826
+         od = OrderedDict.fromkeys('abc')
+         od['x'] = od
+         self.assertEqual(repr(od),
+             "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
+     def test_setdefault(self):
+         OrderedDict = self.OrderedDict
+         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+         shuffle(pairs)
+         od = OrderedDict(pairs)
+         pair_order = list(od.items())
+         self.assertEqual(od.setdefault('a', 10), 3)
+         # make sure order didn't change
+         self.assertEqual(list(od.items()), pair_order)
+         self.assertEqual(od.setdefault('x', 10), 10)
+         # make sure 'x' is added to the end
+         self.assertEqual(list(od.items())[-1], ('x', 10))
+         self.assertEqual(od.setdefault('g', default=9), 9)
+         # make sure setdefault still works when __missing__ is defined
+         class Missing(OrderedDict):
+             def __missing__(self, key):
+                 return 0
+         self.assertEqual(Missing().setdefault(5, 9), 9)
+     def test_reinsert(self):
+         OrderedDict = self.OrderedDict
+         # Given insert a, insert b, delete a, re-insert a,
+         # verify that a is now later than b.
+         od = OrderedDict()
+         od['a'] = 1
+         od['b'] = 2
+         del od['a']
+         self.assertEqual(list(od.items()), [('b', 2)])
+         od['a'] = 1
+         self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
+     def test_move_to_end(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict.fromkeys('abcde')
+         self.assertEqual(list(od), list('abcde'))
+         od.move_to_end('c')
+         self.assertEqual(list(od), list('abdec'))
+         od.move_to_end('c', 0)
+         self.assertEqual(list(od), list('cabde'))
+         od.move_to_end('c', 0)
+         self.assertEqual(list(od), list('cabde'))
+         od.move_to_end('e')
+         self.assertEqual(list(od), list('cabde'))
+         od.move_to_end('b', last=False)
+         self.assertEqual(list(od), list('bcade'))
+         with self.assertRaises(KeyError):
+             od.move_to_end('x')
+         with self.assertRaises(KeyError):
+             od.move_to_end('x', 0)
+     def test_move_to_end_issue25406(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict.fromkeys('abc')
+         od.move_to_end('c', last=False)
+         self.assertEqual(list(od), list('cab'))
+         od.move_to_end('a', last=False)
+         self.assertEqual(list(od), list('acb'))
+         od = OrderedDict.fromkeys('abc')
+         od.move_to_end('a')
+         self.assertEqual(list(od), list('bca'))
+         od.move_to_end('c')
+         self.assertEqual(list(od), list('bac'))
+     def test_sizeof(self):
+         OrderedDict = self.OrderedDict
+         # Wimpy test: Just verify the reported size is larger than a regular dict
+         d = dict(a=1)
+         od = OrderedDict(**d)
+         self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
++    def test_views(self):
++        OrderedDict = self.OrderedDict
++        # See http://bugs.python.org/issue24286
++        s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split()
++        od = OrderedDict.fromkeys(s)
++        self.assertEqual(od.keys(), dict(od).keys())
++        self.assertEqual(od.items(), dict(od).items())
++
+     def test_override_update(self):
+         OrderedDict = self.OrderedDict
+         # Verify that subclasses can override update() without breaking __init__()
+         class MyOD(OrderedDict):
+             def update(self, *args, **kwds):
+                 raise Exception()
+         items = [('a', 1), ('c', 3), ('b', 2)]
+         self.assertEqual(list(MyOD(items).items()), items)
+     def test_highly_nested(self):
+         # Issue 25395: crashes during garbage collection
+         OrderedDict = self.OrderedDict
+         obj = None
+         for _ in range(1000):
+             obj = OrderedDict([(None, obj)])
+         del obj
+         support.gc_collect()
+     def test_highly_nested_subclass(self):
+         # Issue 25395: crashes during garbage collection
+         OrderedDict = self.OrderedDict
+         deleted = []
+         class MyOD(OrderedDict):
+             def __del__(self):
+                 deleted.append(self.i)
+         obj = None
+         for i in range(100):
+             obj = MyOD([(None, obj)])
+             obj.i = i
+         del obj
+         support.gc_collect()
+         self.assertEqual(deleted, list(reversed(range(100))))
+     def test_delitem_hash_collision(self):
+         OrderedDict = self.OrderedDict
+         class Key:
+             def __init__(self, hash):
+                 self._hash = hash
+                 self.value = str(id(self))
+             def __hash__(self):
+                 return self._hash
+             def __eq__(self, other):
+                 try:
+                     return self.value == other.value
+                 except AttributeError:
+                     return False
+             def __repr__(self):
+                 return self.value
+         def blocking_hash(hash):
+             # See the collision-handling in lookdict (in Objects/dictobject.c).
+             MINSIZE = 8
+             i = (hash & MINSIZE-1)
+             return (i << 2) + i + hash + 1
+         COLLIDING = 1
+         key = Key(COLLIDING)
+         colliding = Key(COLLIDING)
+         blocking = Key(blocking_hash(COLLIDING))
+         od = OrderedDict()
+         od[key] = ...
+         od[blocking] = ...
+         od[colliding] = ...
+         od['after'] = ...
+         del od[blocking]
+         del od[colliding]
+         self.assertEqual(list(od.items()), [(key, ...), ('after', ...)])
+     def test_issue24347(self):
+         OrderedDict = self.OrderedDict
+         class Key:
+             def __hash__(self):
+                 return randrange(100000)
+         od = OrderedDict()
+         for i in range(100):
+             key = Key()
+             od[key] = i
+         # These should not crash.
+         with self.assertRaises(KeyError):
+             list(od.values())
+         with self.assertRaises(KeyError):
+             list(od.items())
+         with self.assertRaises(KeyError):
+             repr(od)
+         with self.assertRaises(KeyError):
+             od.copy()
+     def test_issue24348(self):
+         OrderedDict = self.OrderedDict
+         class Key:
+             def __hash__(self):
+                 return 1
+         od = OrderedDict()
+         od[Key()] = 0
+         # This should not crash.
+         od.popitem()
+     def test_issue24667(self):
+         """
+         dict resizes after a certain number of insertion operations,
+         whether or not there were deletions that freed up slots in the
+         hash table.  During fast node lookup, OrderedDict must correctly
+         respond to all resizes, even if the current "size" is the same
+         as the old one.  We verify that here by forcing a dict resize
+         on a sparse odict and then perform an operation that should
+         trigger an odict resize (e.g. popitem).  One key aspect here is
+         that we will keep the size of the odict the same at each popitem
+         call.  This verifies that we handled the dict resize properly.
+         """
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         for c0 in '0123456789ABCDEF':
+             for c1 in '0123456789ABCDEF':
+                 if len(od) == 4:
+                     # This should not raise a KeyError.
+                     od.popitem(last=False)
+                 key = c0 + c1
+                 od[key] = key
+     # Direct use of dict methods
+     def test_dict_setitem(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         dict.__setitem__(od, 'spam', 1)
+         self.assertNotIn('NULL', repr(od))
+     def test_dict_delitem(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         od['spam'] = 1
+         od['ham'] = 2
+         dict.__delitem__(od, 'spam')
+         with self.assertRaises(KeyError):
+             repr(od)
+     def test_dict_clear(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         od['spam'] = 1
+         od['ham'] = 2
+         dict.clear(od)
+         self.assertNotIn('NULL', repr(od))
+     def test_dict_pop(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         od['spam'] = 1
+         od['ham'] = 2
+         dict.pop(od, 'spam')
+         with self.assertRaises(KeyError):
+             repr(od)
+     def test_dict_popitem(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         od['spam'] = 1
+         od['ham'] = 2
+         dict.popitem(od)
+         with self.assertRaises(KeyError):
+             repr(od)
+     def test_dict_setdefault(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         dict.setdefault(od, 'spam', 1)
+         self.assertNotIn('NULL', repr(od))
+     def test_dict_update(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict()
+         dict.update(od, [('spam', 1)])
+         self.assertNotIn('NULL', repr(od))
+ class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
+     module = py_coll
+     OrderedDict = py_coll.OrderedDict
+ @unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+ class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
+     module = c_coll
+     OrderedDict = c_coll.OrderedDict
+     def test_key_change_during_iteration(self):
+         OrderedDict = self.OrderedDict
+         od = OrderedDict.fromkeys('abcde')
+         self.assertEqual(list(od), list('abcde'))
+         with self.assertRaises(RuntimeError):
+             for i, k in enumerate(od):
+                 od.move_to_end(k)
+                 self.assertLess(i, 5)
+         with self.assertRaises(RuntimeError):
+             for k in od:
+                 od['f'] = None
+         with self.assertRaises(RuntimeError):
+             for k in od:
+                 del od['c']
+         self.assertEqual(list(od), list('bdeaf'))
+ class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests):
+     module = py_coll
+     class OrderedDict(py_coll.OrderedDict):
+         pass
+ class CPythonOrderedDictSubclassTests(CPythonOrderedDictTests):
+     module = c_coll
+     class OrderedDict(c_coll.OrderedDict):
+         pass
+ class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
+     @classmethod
+     def setUpClass(cls):
+         cls.type2test = py_coll.OrderedDict
+     def test_popitem(self):
+         d = self._empty_mapping()
+         self.assertRaises(KeyError, d.popitem)
+ @unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+ class CPythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
+     @classmethod
+     def setUpClass(cls):
+         cls.type2test = c_coll.OrderedDict
+     def test_popitem(self):
+         d = self._empty_mapping()
+         self.assertRaises(KeyError, d.popitem)
+ class PurePythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
+     @classmethod
+     def setUpClass(cls):
+         class MyOrderedDict(py_coll.OrderedDict):
+             pass
+         cls.type2test = MyOrderedDict
+     def test_popitem(self):
+         d = self._empty_mapping()
+         self.assertRaises(KeyError, d.popitem)
+ @unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+ class CPythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
+     @classmethod
+     def setUpClass(cls):
+         class MyOrderedDict(c_coll.OrderedDict):
+             pass
+         cls.type2test = MyOrderedDict
+     def test_popitem(self):
+         d = self._empty_mapping()
+         self.assertRaises(KeyError, d.popitem)
+ if __name__ == "__main__":
+     unittest.main()
diff --cc Misc/NEWS
index 3f22a20c41b8d2881be5cbd21f70dba395bc8fff,ba4b54ccd069adcb0f08bf31759a3d9e0e1bda14..9961e3d271290224caa44210d341feade8d5133f
+++ b/Misc/NEWS
@@@ -413,221 -452,6 +413,224 @@@ IDL
  Documentation
  -------------
  
 +- Issue #24952: Clarify the default size argument of stack_size() in
 +  the "threading" and "_thread" modules. Patch from Mattip.
 +
 +Tests
 +-----
 +
++- Issue #25616: Tests for OrderedDict are extracted from test_collections
++  into separate file test_ordered_dict.
++
 +- Issue #25449: Added tests for OrderedDict subclasses.
 +
 +- Issue #25188: Add -P/--pgo to test.regrtest to suppress error output when
 +  running the test suite for the purposes of a PGO build. Initial patch by
 +  Alecsandru Patrascu.
 +
 +- Issue #22806: Add ``python -m test --list-tests`` command to list tests.
 +
 +- Issue #18174: ``python -m test --huntrleaks ...`` now also checks for leak of
 +  file descriptors. Patch written by Richard Oudkerk.
 +
 +- Issue #25260: Fix ``python -m test --coverage`` on Windows. Remove the
 +  list of ignored directories.
 +
 +- ``PCbuild\rt.bat`` now accepts an unlimited number of arguments to pass along
 +  to regrtest.py.  Previously there was a limit of 9.
 +
 +Build
 +-----
 +
 +- Issue #24986: It is now possible to build Python on Windows without errors
 +  when external libraries are not available.
 +
 +Windows
 +-------
 +
 +- Issue #25022: Removed very outdated PC/example_nt/ directory.
 +
 +Tools/Demos
 +-----------
 +
 +- Issue #25440: Fix output of python-config --extension-suffix.
 +
 +- Issue #25154: The pyvenv script has been deprecated in favour of
 +  `python3 -m venv`.
 +
 +
 +What's New in Python 3.5.1 release candidate 1?
 +===============================================
 +
 +Release date: TBA
 +
 +Core and Builtins
 +-----------------
 +
 +- Issue #24802: Avoid buffer overreads when int(), float(), compile(), exec()
 +  and eval() are passed bytes-like objects.  These objects are not
 +  necessarily terminated by a null byte, but the functions assumed they were.
 +
 +- Issue #24402: Fix input() to prompt to the redirected stdout when
 +  sys.stdout.fileno() fails.
 +
 +- Issue #25182: The stdprinter (used as sys.stderr before the io module is
 +  imported at startup) now uses the backslashreplace error handler.
 +
 +- Issue #25131: Make the line number and column offset of set/dict literals and
 +  comprehensions correspond to the opening brace.
 +
 +- Issue #25150: Hide the private _Py_atomic_xxx symbols from the public
 +  Python.h header to fix a compilation error with OpenMP. PyThreadState_GET()
 +  becomes an alias to PyThreadState_Get() to avoid ABI incompatibilies.
 +
 +Library
 +-------
 +
 +- Issue #25626: Change three zlib functions to accept sizes that fit in
 +  Py_ssize_t, but internally cap those sizes to UINT_MAX.  This resolves a
 +  regression in 3.5 where GzipFile.read() failed to read chunks larger than 2
 +  or 4 GiB.  The change affects the zlib.Decompress.decompress() max_length
 +  parameter, the zlib.decompress() bufsize parameter, and the
 +  zlib.Decompress.flush() length parameter.
 +
 +- Issue #25583: Avoid incorrect errors raised by os.makedirs(exist_ok=True)
 +  when the OS gives priority to errors such as EACCES over EEXIST.
 +
 +- Issue #25590: In the Readline completer, only call getattr() once per
 +  attribute.
 +
 +- Issue #25498: Fix a crash when garbage-collecting ctypes objects created
 +  by wrapping a memoryview.  This was a regression made in 3.5a1.  Based
 +  on patch by Eryksun.
 +
 +- Issue #25232: Fix CGIRequestHandler to split the query from the URL at the
 +  first question mark (?) rather than the last. Patch from Xiang Zhang.
 +
 +- Issue #24657: Prevent CGIRequestHandler from collapsing slashes in the
 +  query part of the URL as if it were a path. Patch from Xiang Zhang.
 +
 +- Issue #24483: C implementation of functools.lru_cache() now calculates key's
 +  hash only once.
 +
 +- Issue #22958: Constructor and update method of weakref.WeakValueDictionary
 +  now accept the self and the dict keyword arguments.
 +
 +- Issue #22609: Constructor of collections.UserDict now accepts the self keyword
 +  argument.
 +
 +- Issue #25111: Fixed comparison of traceback.FrameSummary.
 +
 +- Issue #25262. Added support for BINBYTES8 opcode in Python implementation of
 +  unpickler.  Highest 32 bits of 64-bit size for BINUNICODE8 and BINBYTES8
 +  opcodes no longer silently ignored on 32-bit platforms in C implementation.
 +
 +- Issue #25034: Fix string.Formatter problem with auto-numbering and
 +  nested format_specs. Patch by Anthon van der Neut.
 +
 +- Issue #25233: Rewrite the guts of asyncio.Queue and
 +  asyncio.Semaphore to be more understandable and correct.
 +
 +- Issue #23600: Default implementation of tzinfo.fromutc() was returning
 +  wrong results in some cases.
 +
 +- Issue #23329: Allow the ssl module to be built with older versions of
 +  LibreSSL.
 +
 +- Prevent overflow in _Unpickler_Read.
 +
 +- Issue #25047: The XML encoding declaration written by Element Tree now
 +  respects the letter case given by the user. This restores the ability to
 +  write encoding names in uppercase like "UTF-8", which worked in Python 2.
 +
 +- Issue #25135: Make deque_clear() safer by emptying the deque before clearing.
 +  This helps avoid possible reentrancy issues.
 +
 +- Issue #19143: platform module now reads Windows version from kernel32.dll to
 +  avoid compatibility shims.
 +
 +- Issue #25092: Fix datetime.strftime() failure when errno was already set to
 +  EINVAL.
 +
 +- Issue #23517: Fix rounding in fromtimestamp() and utcfromtimestamp() methods
 +  of datetime.datetime: microseconds are now rounded to nearest with ties
 +  going to nearest even integer (ROUND_HALF_EVEN), instead of being rounding
 +  towards minus infinity (ROUND_FLOOR). It's important that these methods use
 +  the same rounding mode than datetime.timedelta to keep the property:
 +  (datetime(1970,1,1) + timedelta(seconds=t)) == datetime.utcfromtimestamp(t).
 +  It also the rounding mode used by round(float) for example.
 +
 +- Issue #25155: Fix datetime.datetime.now() and datetime.datetime.utcnow() on
 +  Windows to support date after year 2038. It was a regression introduced in
 +  Python 3.5.0.
 +
 +- Issue #25108: Omitted internal frames in traceback functions print_stack(),
 +  format_stack(), and extract_stack() called without arguments.
 +
 +- Issue #25118: Fix a regression of Python 3.5.0 in os.waitpid() on Windows.
 +
 +- Issue #24684: socket.socket.getaddrinfo() now calls
 +  PyUnicode_AsEncodedString() instead of calling the encode() method of the
 +  host, to handle correctly custom string with an encode() method which doesn't
 +  return a byte string. The encoder of the IDNA codec is now called directly
 +  instead of calling the encode() method of the string.
 +
 +- Issue #25060: Correctly compute stack usage of the BUILD_MAP opcode.
 +
 +- Issue #24857: Comparing call_args to a long sequence now correctly returns a
 +  boolean result instead of raising an exception.  Patch by A Kaptur.
 +
 +- Issue #23144: Make sure that HTMLParser.feed() returns all the data, even
 +  when convert_charrefs is True.
 +
 +- Issue #24982: shutil.make_archive() with the "zip" format now adds entries
 +  for directories (including empty directories) in ZIP file.
 +
 +- Issue #25019: Fixed a crash caused by setting non-string key of expat parser.
 +  Based on patch by John Leitch.
 +
 +- Issue #16180: Exit pdb if file has syntax error, instead of trapping user
 +  in an infinite loop.  Patch by Xavier de Gaye.
 +
 +- Issue #24891: Fix a race condition at Python startup if the file descriptor
 +  of stdin (0), stdout (1) or stderr (2) is closed while Python is creating
 +  sys.stdin, sys.stdout and sys.stderr objects. These attributes are now set
 +  to None if the creation of the object failed, instead of raising an OSError
 +  exception. Initial patch written by Marco Paolini.
 +
 +- Issue #24992: Fix error handling and a race condition (related to garbage
 +  collection) in collections.OrderedDict constructor.
 +
 +- Issue #24881: Fixed setting binary mode in Python implementation of FileIO
 +  on Windows and Cygwin.  Patch from Akira Li.
 +
 +- Issue #21112: Fix regression in unittest.expectedFailure on subclasses.
 +  Patch from Berker Peksag.
 +
 +- Issue #24764: cgi.FieldStorage.read_multi() now ignores the Content-Length
 +  header in part headers. Patch written by Peter Landry and reviewed by Pierre
 +  Quentel.
 +
 +- Issue #24913: Fix overrun error in deque.index().
 +  Found by John Leitch and Bryce Darling.
 +
 +- Issue #24774: Fix docstring in http.server.test. Patch from Chiu-Hsiang Hsu.
 +
 +- Issue #21159: Improve message in configparser.InterpolationMissingOptionError.
 +  Patch from Ćukasz Langa.
 +
 +- Issue #20362: Honour TestCase.longMessage correctly in assertRegex.
 +  Patch from Ilia Kurenkov.
 +
 +- Issue #23572: Fixed functools.singledispatch on classes with falsy
 +  metaclasses.  Patch by Ethan Furman.
 +
 +- Issue #12006: Add ISO 8601 year, week, and day directives (%G, %V, %u) to
 +  strptime.
 +
 +Documentation
 +-------------
 +
  - Issue #12067: Rewrite Comparisons section in the Expressions chapter of the
    language reference. Some of the details of comparing mixed types were
    incorrect or ambiguous. NotImplemented is only relevant at a lower level