PageRenderTime 641ms CodeModel.GetById 181ms app.highlight 283ms RepoModel.GetById 170ms app.codeStats 0ms

/Lib/test/mapping_tests.py

http://unladen-swallow.googlecode.com/
Python | 676 lines | 524 code | 104 blank | 48 comment | 55 complexity | 5cee0dafa29ae2e28fed912ac2537396 MD5 | raw file
  1# tests common to dict and UserDict
  2import unittest
  3import UserDict
  4
  5
  6class BasicTestMappingProtocol(unittest.TestCase):
  7    # This base class can be used to check that an object conforms to the
  8    # mapping protocol
  9
 10    # Functions that can be useful to override to adapt to dictionary
 11    # semantics
 12    type2test = None # which class is being tested (overwrite in subclasses)
 13
 14    def _reference(self):
 15        """Return a dictionary of values which are invariant by storage
 16        in the object under test."""
 17        return {1:2, "key1":"value1", "key2":(1,2,3)}
 18    def _empty_mapping(self):
 19        """Return an empty mapping object"""
 20        return self.type2test()
 21    def _full_mapping(self, data):
 22        """Return a mapping object with the value contained in data
 23        dictionary"""
 24        x = self._empty_mapping()
 25        for key, value in data.items():
 26            x[key] = value
 27        return x
 28
 29    def __init__(self, *args, **kw):
 30        unittest.TestCase.__init__(self, *args, **kw)
 31        self.reference = self._reference().copy()
 32
 33        # A (key, value) pair not in the mapping
 34        key, value = self.reference.popitem()
 35        self.other = {key:value}
 36
 37        # A (key, value) pair in the mapping
 38        key, value = self.reference.popitem()
 39        self.inmapping = {key:value}
 40        self.reference[key] = value
 41
 42    def test_read(self):
 43        # Test for read only operations on mapping
 44        p = self._empty_mapping()
 45        p1 = dict(p) #workaround for singleton objects
 46        d = self._full_mapping(self.reference)
 47        if d is p:
 48            p = p1
 49        #Indexing
 50        for key, value in self.reference.items():
 51            self.assertEqual(d[key], value)
 52        knownkey = self.other.keys()[0]
 53        self.failUnlessRaises(KeyError, lambda:d[knownkey])
 54        #len
 55        self.assertEqual(len(p), 0)
 56        self.assertEqual(len(d), len(self.reference))
 57        #has_key
 58        for k in self.reference:
 59            self.assert_(d.has_key(k))
 60            self.assert_(k in d)
 61        for k in self.other:
 62            self.failIf(d.has_key(k))
 63            self.failIf(k in d)
 64        #cmp
 65        self.assertEqual(cmp(p,p), 0)
 66        self.assertEqual(cmp(d,d), 0)
 67        self.assertEqual(cmp(p,d), -1)
 68        self.assertEqual(cmp(d,p), 1)
 69        #__non__zero__
 70        if p: self.fail("Empty mapping must compare to False")
 71        if not d: self.fail("Full mapping must compare to True")
 72        # keys(), items(), iterkeys() ...
 73        def check_iterandlist(iter, lst, ref):
 74            self.assert_(hasattr(iter, 'next'))
 75            self.assert_(hasattr(iter, '__iter__'))
 76            x = list(iter)
 77            self.assert_(set(x)==set(lst)==set(ref))
 78        check_iterandlist(d.iterkeys(), d.keys(), self.reference.keys())
 79        check_iterandlist(iter(d), d.keys(), self.reference.keys())
 80        check_iterandlist(d.itervalues(), d.values(), self.reference.values())
 81        check_iterandlist(d.iteritems(), d.items(), self.reference.items())
 82        #get
 83        key, value = d.iteritems().next()
 84        knownkey, knownvalue = self.other.iteritems().next()
 85        self.assertEqual(d.get(key, knownvalue), value)
 86        self.assertEqual(d.get(knownkey, knownvalue), knownvalue)
 87        self.failIf(knownkey in d)
 88
 89    def test_write(self):
 90        # Test for write operations on mapping
 91        p = self._empty_mapping()
 92        #Indexing
 93        for key, value in self.reference.items():
 94            p[key] = value
 95            self.assertEqual(p[key], value)
 96        for key in self.reference.keys():
 97            del p[key]
 98            self.failUnlessRaises(KeyError, lambda:p[key])
 99        p = self._empty_mapping()
100        #update
101        p.update(self.reference)
102        self.assertEqual(dict(p), self.reference)
103        items = p.items()
104        p = self._empty_mapping()
105        p.update(items)
106        self.assertEqual(dict(p), self.reference)
107        d = self._full_mapping(self.reference)
108        #setdefault
109        key, value = d.iteritems().next()
110        knownkey, knownvalue = self.other.iteritems().next()
111        self.assertEqual(d.setdefault(key, knownvalue), value)
112        self.assertEqual(d[key], value)
113        self.assertEqual(d.setdefault(knownkey, knownvalue), knownvalue)
114        self.assertEqual(d[knownkey], knownvalue)
115        #pop
116        self.assertEqual(d.pop(knownkey), knownvalue)
117        self.failIf(knownkey in d)
118        self.assertRaises(KeyError, d.pop, knownkey)
119        default = 909
120        d[knownkey] = knownvalue
121        self.assertEqual(d.pop(knownkey, default), knownvalue)
122        self.failIf(knownkey in d)
123        self.assertEqual(d.pop(knownkey, default), default)
124        #popitem
125        key, value = d.popitem()
126        self.failIf(key in d)
127        self.assertEqual(value, self.reference[key])
128        p=self._empty_mapping()
129        self.assertRaises(KeyError, p.popitem)
130
131    def test_constructor(self):
132        self.assertEqual(self._empty_mapping(), self._empty_mapping())
133
134    def test_bool(self):
135        self.assert_(not self._empty_mapping())
136        self.assert_(self.reference)
137        self.assert_(bool(self._empty_mapping()) is False)
138        self.assert_(bool(self.reference) is True)
139
140    def test_keys(self):
141        d = self._empty_mapping()
142        self.assertEqual(d.keys(), [])
143        d = self.reference
144        self.assert_(self.inmapping.keys()[0] in d.keys())
145        self.assert_(self.other.keys()[0] not in d.keys())
146        self.assertRaises(TypeError, d.keys, None)
147
148    def test_values(self):
149        d = self._empty_mapping()
150        self.assertEqual(d.values(), [])
151
152        self.assertRaises(TypeError, d.values, None)
153
154    def test_items(self):
155        d = self._empty_mapping()
156        self.assertEqual(d.items(), [])
157
158        self.assertRaises(TypeError, d.items, None)
159
160    def test_len(self):
161        d = self._empty_mapping()
162        self.assertEqual(len(d), 0)
163
164    def test_getitem(self):
165        d = self.reference
166        self.assertEqual(d[self.inmapping.keys()[0]], self.inmapping.values()[0])
167
168        self.assertRaises(TypeError, d.__getitem__)
169
170    def test_update(self):
171        # mapping argument
172        d = self._empty_mapping()
173        d.update(self.other)
174        self.assertEqual(d.items(), self.other.items())
175
176        # No argument
177        d = self._empty_mapping()
178        d.update()
179        self.assertEqual(d, self._empty_mapping())
180
181        # item sequence
182        d = self._empty_mapping()
183        d.update(self.other.items())
184        self.assertEqual(d.items(), self.other.items())
185
186        # Iterator
187        d = self._empty_mapping()
188        d.update(self.other.iteritems())
189        self.assertEqual(d.items(), self.other.items())
190
191        # FIXME: Doesn't work with UserDict
192        # self.assertRaises((TypeError, AttributeError), d.update, None)
193        self.assertRaises((TypeError, AttributeError), d.update, 42)
194
195        outerself = self
196        class SimpleUserDict:
197            def __init__(self):
198                self.d = outerself.reference
199            def keys(self):
200                return self.d.keys()
201            def __getitem__(self, i):
202                return self.d[i]
203        d.clear()
204        d.update(SimpleUserDict())
205        i1 = d.items()
206        i2 = self.reference.items()
207        i1.sort()
208        i2.sort()
209        self.assertEqual(i1, i2)
210
211        class Exc(Exception): pass
212
213        d = self._empty_mapping()
214        class FailingUserDict:
215            def keys(self):
216                raise Exc
217        self.assertRaises(Exc, d.update, FailingUserDict())
218
219        d.clear()
220
221        class FailingUserDict:
222            def keys(self):
223                class BogonIter:
224                    def __init__(self):
225                        self.i = 1
226                    def __iter__(self):
227                        return self
228                    def next(self):
229                        if self.i:
230                            self.i = 0
231                            return 'a'
232                        raise Exc
233                return BogonIter()
234            def __getitem__(self, key):
235                return key
236        self.assertRaises(Exc, d.update, FailingUserDict())
237
238        class FailingUserDict:
239            def keys(self):
240                class BogonIter:
241                    def __init__(self):
242                        self.i = ord('a')
243                    def __iter__(self):
244                        return self
245                    def next(self):
246                        if self.i <= ord('z'):
247                            rtn = chr(self.i)
248                            self.i += 1
249                            return rtn
250                        raise StopIteration
251                return BogonIter()
252            def __getitem__(self, key):
253                raise Exc
254        self.assertRaises(Exc, d.update, FailingUserDict())
255
256        d = self._empty_mapping()
257        class badseq(object):
258            def __iter__(self):
259                return self
260            def next(self):
261                raise Exc()
262
263        self.assertRaises(Exc, d.update, badseq())
264
265        self.assertRaises(ValueError, d.update, [(1, 2, 3)])
266
267    # no test_fromkeys or test_copy as both os.environ and selves don't support it
268
269    def test_get(self):
270        d = self._empty_mapping()
271        self.assert_(d.get(self.other.keys()[0]) is None)
272        self.assertEqual(d.get(self.other.keys()[0], 3), 3)
273        d = self.reference
274        self.assert_(d.get(self.other.keys()[0]) is None)
275        self.assertEqual(d.get(self.other.keys()[0], 3), 3)
276        self.assertEqual(d.get(self.inmapping.keys()[0]), self.inmapping.values()[0])
277        self.assertEqual(d.get(self.inmapping.keys()[0], 3), self.inmapping.values()[0])
278        self.assertRaises(TypeError, d.get)
279        self.assertRaises(TypeError, d.get, None, None, None)
280
281    def test_setdefault(self):
282        d = self._empty_mapping()
283        self.assertRaises(TypeError, d.setdefault)
284
285    def test_popitem(self):
286        d = self._empty_mapping()
287        self.assertRaises(KeyError, d.popitem)
288        self.assertRaises(TypeError, d.popitem, 42)
289
290    def test_pop(self):
291        d = self._empty_mapping()
292        k, v = self.inmapping.items()[0]
293        d[k] = v
294        self.assertRaises(KeyError, d.pop, self.other.keys()[0])
295
296        self.assertEqual(d.pop(k), v)
297        self.assertEqual(len(d), 0)
298
299        self.assertRaises(KeyError, d.pop, k)
300
301
302class TestMappingProtocol(BasicTestMappingProtocol):
303    def test_constructor(self):
304        BasicTestMappingProtocol.test_constructor(self)
305        self.assert_(self._empty_mapping() is not self._empty_mapping())
306        self.assertEqual(self.type2test(x=1, y=2), {"x": 1, "y": 2})
307
308    def test_bool(self):
309        BasicTestMappingProtocol.test_bool(self)
310        self.assert_(not self._empty_mapping())
311        self.assert_(self._full_mapping({"x": "y"}))
312        self.assert_(bool(self._empty_mapping()) is False)
313        self.assert_(bool(self._full_mapping({"x": "y"})) is True)
314
315    def test_keys(self):
316        BasicTestMappingProtocol.test_keys(self)
317        d = self._empty_mapping()
318        self.assertEqual(d.keys(), [])
319        d = self._full_mapping({'a': 1, 'b': 2})
320        k = d.keys()
321        self.assert_('a' in k)
322        self.assert_('b' in k)
323        self.assert_('c' not in k)
324
325    def test_values(self):
326        BasicTestMappingProtocol.test_values(self)
327        d = self._full_mapping({1:2})
328        self.assertEqual(d.values(), [2])
329
330    def test_items(self):
331        BasicTestMappingProtocol.test_items(self)
332
333        d = self._full_mapping({1:2})
334        self.assertEqual(d.items(), [(1, 2)])
335
336    def test_has_key(self):
337        d = self._empty_mapping()
338        self.assert_(not d.has_key('a'))
339        d = self._full_mapping({'a': 1, 'b': 2})
340        k = d.keys()
341        k.sort()
342        self.assertEqual(k, ['a', 'b'])
343
344        self.assertRaises(TypeError, d.has_key)
345
346    def test_contains(self):
347        d = self._empty_mapping()
348        self.assert_(not ('a' in d))
349        self.assert_('a' not in d)
350        d = self._full_mapping({'a': 1, 'b': 2})
351        self.assert_('a' in d)
352        self.assert_('b' in d)
353        self.assert_('c' not in d)
354
355        self.assertRaises(TypeError, d.__contains__)
356
357    def test_len(self):
358        BasicTestMappingProtocol.test_len(self)
359        d = self._full_mapping({'a': 1, 'b': 2})
360        self.assertEqual(len(d), 2)
361
362    def test_getitem(self):
363        BasicTestMappingProtocol.test_getitem(self)
364        d = self._full_mapping({'a': 1, 'b': 2})
365        self.assertEqual(d['a'], 1)
366        self.assertEqual(d['b'], 2)
367        d['c'] = 3
368        d['a'] = 4
369        self.assertEqual(d['c'], 3)
370        self.assertEqual(d['a'], 4)
371        del d['b']
372        self.assertEqual(d, {'a': 4, 'c': 3})
373
374        self.assertRaises(TypeError, d.__getitem__)
375
376    def test_clear(self):
377        d = self._full_mapping({1:1, 2:2, 3:3})
378        d.clear()
379        self.assertEqual(d, {})
380
381        self.assertRaises(TypeError, d.clear, None)
382
383    def test_update(self):
384        BasicTestMappingProtocol.test_update(self)
385        # mapping argument
386        d = self._empty_mapping()
387        d.update({1:100})
388        d.update({2:20})
389        d.update({1:1, 2:2, 3:3})
390        self.assertEqual(d, {1:1, 2:2, 3:3})
391
392        # no argument
393        d.update()
394        self.assertEqual(d, {1:1, 2:2, 3:3})
395
396        # keyword arguments
397        d = self._empty_mapping()
398        d.update(x=100)
399        d.update(y=20)
400        d.update(x=1, y=2, z=3)
401        self.assertEqual(d, {"x":1, "y":2, "z":3})
402
403        # item sequence
404        d = self._empty_mapping()
405        d.update([("x", 100), ("y", 20)])
406        self.assertEqual(d, {"x":100, "y":20})
407
408        # Both item sequence and keyword arguments
409        d = self._empty_mapping()
410        d.update([("x", 100), ("y", 20)], x=1, y=2)
411        self.assertEqual(d, {"x":1, "y":2})
412
413        # iterator
414        d = self._full_mapping({1:3, 2:4})
415        d.update(self._full_mapping({1:2, 3:4, 5:6}).iteritems())
416        self.assertEqual(d, {1:2, 2:4, 3:4, 5:6})
417
418        class SimpleUserDict:
419            def __init__(self):
420                self.d = {1:1, 2:2, 3:3}
421            def keys(self):
422                return self.d.keys()
423            def __getitem__(self, i):
424                return self.d[i]
425        d.clear()
426        d.update(SimpleUserDict())
427        self.assertEqual(d, {1:1, 2:2, 3:3})
428
429    def test_fromkeys(self):
430        self.assertEqual(self.type2test.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
431        d = self._empty_mapping()
432        self.assert_(not(d.fromkeys('abc') is d))
433        self.assertEqual(d.fromkeys('abc'), {'a':None, 'b':None, 'c':None})
434        self.assertEqual(d.fromkeys((4,5),0), {4:0, 5:0})
435        self.assertEqual(d.fromkeys([]), {})
436        def g():
437            yield 1
438        self.assertEqual(d.fromkeys(g()), {1:None})
439        self.assertRaises(TypeError, {}.fromkeys, 3)
440        class dictlike(self.type2test): pass
441        self.assertEqual(dictlike.fromkeys('a'), {'a':None})
442        self.assertEqual(dictlike().fromkeys('a'), {'a':None})
443        self.assert_(dictlike.fromkeys('a').__class__ is dictlike)
444        self.assert_(dictlike().fromkeys('a').__class__ is dictlike)
445        # FIXME: the following won't work with UserDict, because it's an old style class
446        # self.assert_(type(dictlike.fromkeys('a')) is dictlike)
447        class mydict(self.type2test):
448            def __new__(cls):
449                return UserDict.UserDict()
450        ud = mydict.fromkeys('ab')
451        self.assertEqual(ud, {'a':None, 'b':None})
452        # FIXME: the following won't work with UserDict, because it's an old style class
453        # self.assert_(isinstance(ud, UserDict.UserDict))
454        self.assertRaises(TypeError, dict.fromkeys)
455
456        class Exc(Exception): pass
457
458        class baddict1(self.type2test):
459            def __init__(self):
460                raise Exc()
461
462        self.assertRaises(Exc, baddict1.fromkeys, [1])
463
464        class BadSeq(object):
465            def __iter__(self):
466                return self
467            def next(self):
468                raise Exc()
469
470        self.assertRaises(Exc, self.type2test.fromkeys, BadSeq())
471
472        class baddict2(self.type2test):
473            def __setitem__(self, key, value):
474                raise Exc()
475
476        self.assertRaises(Exc, baddict2.fromkeys, [1])
477
478    def test_copy(self):
479        d = self._full_mapping({1:1, 2:2, 3:3})
480        self.assertEqual(d.copy(), {1:1, 2:2, 3:3})
481        d = self._empty_mapping()
482        self.assertEqual(d.copy(), d)
483        self.assert_(isinstance(d.copy(), d.__class__))
484        self.assertRaises(TypeError, d.copy, None)
485
486    def test_get(self):
487        BasicTestMappingProtocol.test_get(self)
488        d = self._empty_mapping()
489        self.assert_(d.get('c') is None)
490        self.assertEqual(d.get('c', 3), 3)
491        d = self._full_mapping({'a' : 1, 'b' : 2})
492        self.assert_(d.get('c') is None)
493        self.assertEqual(d.get('c', 3), 3)
494        self.assertEqual(d.get('a'), 1)
495        self.assertEqual(d.get('a', 3), 1)
496
497    def test_setdefault(self):
498        BasicTestMappingProtocol.test_setdefault(self)
499        d = self._empty_mapping()
500        self.assert_(d.setdefault('key0') is None)
501        d.setdefault('key0', [])
502        self.assert_(d.setdefault('key0') is None)
503        d.setdefault('key', []).append(3)
504        self.assertEqual(d['key'][0], 3)
505        d.setdefault('key', []).append(4)
506        self.assertEqual(len(d['key']), 2)
507
508    def test_popitem(self):
509        BasicTestMappingProtocol.test_popitem(self)
510        for copymode in -1, +1:
511            # -1: b has same structure as a
512            # +1: b is a.copy()
513            for log2size in range(12):
514                size = 2**log2size
515                a = self._empty_mapping()
516                b = self._empty_mapping()
517                for i in range(size):
518                    a[repr(i)] = i
519                    if copymode < 0:
520                        b[repr(i)] = i
521                if copymode > 0:
522                    b = a.copy()
523                for i in range(size):
524                    ka, va = ta = a.popitem()
525                    self.assertEqual(va, int(ka))
526                    kb, vb = tb = b.popitem()
527                    self.assertEqual(vb, int(kb))
528                    self.assert_(not(copymode < 0 and ta != tb))
529                self.assert_(not a)
530                self.assert_(not b)
531
532    def test_pop(self):
533        BasicTestMappingProtocol.test_pop(self)
534
535        # Tests for pop with specified key
536        d = self._empty_mapping()
537        k, v = 'abc', 'def'
538
539        # verify longs/ints get same value when key > 32 bits (for 64-bit archs)
540        # see SF bug #689659
541        x = 4503599627370496L
542        y = 4503599627370496
543        h = self._full_mapping({x: 'anything', y: 'something else'})
544        self.assertEqual(h[x], h[y])
545
546        self.assertEqual(d.pop(k, v), v)
547        d[k] = v
548        self.assertEqual(d.pop(k, 1), v)
549
550
551class TestHashMappingProtocol(TestMappingProtocol):
552
553    def test_getitem(self):
554        TestMappingProtocol.test_getitem(self)
555        class Exc(Exception): pass
556
557        class BadEq(object):
558            def __eq__(self, other):
559                raise Exc()
560            def __hash__(self):
561                return 24
562
563        d = self._empty_mapping()
564        d[BadEq()] = 42
565        self.assertRaises(KeyError, d.__getitem__, 23)
566
567        class BadHash(object):
568            fail = False
569            def __hash__(self):
570                if self.fail:
571                    raise Exc()
572                else:
573                    return 42
574
575        d = self._empty_mapping()
576        x = BadHash()
577        d[x] = 42
578        x.fail = True
579        self.assertRaises(Exc, d.__getitem__, x)
580
581    def test_fromkeys(self):
582        TestMappingProtocol.test_fromkeys(self)
583        class mydict(self.type2test):
584            def __new__(cls):
585                return UserDict.UserDict()
586        ud = mydict.fromkeys('ab')
587        self.assertEqual(ud, {'a':None, 'b':None})
588        self.assert_(isinstance(ud, UserDict.UserDict))
589
590    def test_pop(self):
591        TestMappingProtocol.test_pop(self)
592
593        class Exc(Exception): pass
594
595        class BadHash(object):
596            fail = False
597            def __hash__(self):
598                if self.fail:
599                    raise Exc()
600                else:
601                    return 42
602
603        d = self._empty_mapping()
604        x = BadHash()
605        d[x] = 42
606        x.fail = True
607        self.assertRaises(Exc, d.pop, x)
608
609    def test_mutatingiteration(self):
610        d = self._empty_mapping()
611        d[1] = 1
612        try:
613            for i in d:
614                d[i+1] = 1
615        except RuntimeError:
616            pass
617        else:
618            self.fail("changing dict size during iteration doesn't raise Error")
619
620    def test_repr(self):
621        d = self._empty_mapping()
622        self.assertEqual(repr(d), '{}')
623        d[1] = 2
624        self.assertEqual(repr(d), '{1: 2}')
625        d = self._empty_mapping()
626        d[1] = d
627        self.assertEqual(repr(d), '{1: {...}}')
628
629        class Exc(Exception): pass
630
631        class BadRepr(object):
632            def __repr__(self):
633                raise Exc()
634
635        d = self._full_mapping({1: BadRepr()})
636        self.assertRaises(Exc, repr, d)
637
638    def test_le(self):
639        self.assert_(not (self._empty_mapping() < self._empty_mapping()))
640        self.assert_(not (self._full_mapping({1: 2}) < self._full_mapping({1L: 2L})))
641
642        class Exc(Exception): pass
643
644        class BadCmp(object):
645            def __eq__(self, other):
646                raise Exc()
647            def __hash__(self):
648                return 42
649
650        d1 = self._full_mapping({BadCmp(): 1})
651        d2 = self._full_mapping({1: 1})
652        try:
653            d1 < d2
654        except Exc:
655            pass
656        else:
657            self.fail("< didn't raise Exc")
658
659    def test_setdefault(self):
660        TestMappingProtocol.test_setdefault(self)
661
662        class Exc(Exception): pass
663
664        class BadHash(object):
665            fail = False
666            def __hash__(self):
667                if self.fail:
668                    raise Exc()
669                else:
670                    return 42
671
672        d = self._empty_mapping()
673        x = BadHash()
674        d[x] = 42
675        x.fail = True
676        self.assertRaises(Exc, d.setdefault, x, [])