pytorch

Форк
0
/
test_weak.py 
917 строк · 29.2 Кб
1
# Owner(s): ["module: meta tensors"]
2

3
import copy
4
import gc
5
import random
6
import threading
7

8
import unittest
9

10
import torch
11
from torch.testing._internal.common_utils import (
12
    find_library_location,
13
    IS_FBCODE,
14
    IS_MACOS,
15
    IS_SANDCASTLE,
16
    IS_WINDOWS,
17
    run_tests,
18
    TestCase,
19
)
20
from torch.utils.weak import _WeakHashRef, WeakIdKeyDictionary
21

22

23
def C():
24
    return torch.randn(1)
25

26

27
# These tests are ported from cpython/Lib/test/test_weakref.py,
28
# but adapted to use tensor rather than object
29
class WeakTest(TestCase):
30
    COUNT = 10
31

32
    def test_make_weak_keyed_dict_from_dict(self):
33
        o = torch.randn(2)
34
        dict = WeakIdKeyDictionary({o: 364})
35
        self.assertEqual(dict[o], 364)
36

37
    def test_make_weak_keyed_dict_from_weak_keyed_dict(self):
38
        o = torch.randn(3)
39
        dict = WeakIdKeyDictionary({o: 364})
40
        dict2 = WeakIdKeyDictionary(dict)
41
        self.assertEqual(dict[o], 364)
42

43
    def check_popitem(self, klass, key1, value1, key2, value2):
44
        weakdict = klass()
45
        weakdict[key1] = value1
46
        weakdict[key2] = value2
47
        self.assertEqual(len(weakdict), 2)
48
        k, v = weakdict.popitem()
49
        self.assertEqual(len(weakdict), 1)
50
        if k is key1:
51
            self.assertIs(v, value1)
52
        else:
53
            self.assertIs(v, value2)
54
        k, v = weakdict.popitem()
55
        self.assertEqual(len(weakdict), 0)
56
        if k is key1:
57
            self.assertIs(v, value1)
58
        else:
59
            self.assertIs(v, value2)
60

61
    def test_weak_keyed_dict_popitem(self):
62
        self.check_popitem(WeakIdKeyDictionary, C(), "value 1", C(), "value 2")
63

64
    def check_setdefault(self, klass, key, value1, value2):
65
        self.assertIsNot(
66
            value1,
67
            value2,
68
            "invalid test -- value parameters must be distinct objects",
69
        )
70
        weakdict = klass()
71
        o = weakdict.setdefault(key, value1)
72
        self.assertIs(o, value1)
73
        self.assertIn(key, weakdict)
74
        self.assertIs(weakdict.get(key), value1)
75
        self.assertIs(weakdict[key], value1)
76

77
        o = weakdict.setdefault(key, value2)
78
        self.assertIs(o, value1)
79
        self.assertIn(key, weakdict)
80
        self.assertIs(weakdict.get(key), value1)
81
        self.assertIs(weakdict[key], value1)
82

83
    def test_weak_keyed_dict_setdefault(self):
84
        self.check_setdefault(WeakIdKeyDictionary, C(), "value 1", "value 2")
85

86
    def check_update(self, klass, dict):
87
        #
88
        #  This exercises d.update(), len(d), d.keys(), k in d,
89
        #  d.get(), d[].
90
        #
91
        weakdict = klass()
92
        weakdict.update(dict)
93
        self.assertEqual(len(weakdict), len(dict))
94
        for k in weakdict.keys():
95
            self.assertIn(k, dict, "mysterious new key appeared in weak dict")
96
            v = dict.get(k)
97
            self.assertIs(v, weakdict[k])
98
            self.assertIs(v, weakdict.get(k))
99
        for k in dict.keys():
100
            self.assertIn(k, weakdict, "original key disappeared in weak dict")
101
            v = dict[k]
102
            self.assertIs(v, weakdict[k])
103
            self.assertIs(v, weakdict.get(k))
104

105
    def test_weak_keyed_dict_update(self):
106
        self.check_update(WeakIdKeyDictionary, {C(): 1, C(): 2, C(): 3})
107

108
    def test_weak_keyed_delitem(self):
109
        d = WeakIdKeyDictionary()
110
        o1 = torch.randn(1)
111
        o2 = torch.randn(2)
112
        d[o1] = "something"
113
        d[o2] = "something"
114
        self.assertEqual(len(d), 2)
115
        del d[o1]
116
        self.assertEqual(len(d), 1)
117
        self.assertEqual(list(d.keys()), [o2])
118

119
    def test_weak_keyed_union_operators(self):
120
        try:
121
            {} | {}
122
        except TypeError:
123
            self.skipTest("dict union not supported in this Python")
124

125
        o1 = C()
126
        o2 = C()
127
        o3 = C()
128
        wkd1 = WeakIdKeyDictionary({o1: 1, o2: 2})
129
        wkd2 = WeakIdKeyDictionary({o3: 3, o1: 4})
130
        wkd3 = wkd1.copy()
131
        d1 = {o2: "5", o3: "6"}
132
        pairs = [(o2, 7), (o3, 8)]
133

134
        tmp1 = wkd1 | wkd2  # Between two WeakKeyDictionaries
135
        self.assertEqual(dict(tmp1), dict(wkd1) | dict(wkd2))
136
        self.assertIs(type(tmp1), WeakIdKeyDictionary)
137
        wkd1 |= wkd2
138
        self.assertEqual(wkd1, tmp1)
139

140
        tmp2 = wkd2 | d1  # Between WeakKeyDictionary and mapping
141
        self.assertEqual(dict(tmp2), dict(wkd2) | d1)
142
        self.assertIs(type(tmp2), WeakIdKeyDictionary)
143
        wkd2 |= d1
144
        self.assertEqual(wkd2, tmp2)
145

146
        tmp3 = wkd3.copy()  # Between WeakKeyDictionary and iterable key, value
147
        tmp3 |= pairs
148
        self.assertEqual(dict(tmp3), dict(wkd3) | dict(pairs))
149
        self.assertIs(type(tmp3), WeakIdKeyDictionary)
150

151
        tmp4 = d1 | wkd3  # Testing .__ror__
152
        self.assertEqual(dict(tmp4), d1 | dict(wkd3))
153
        self.assertIs(type(tmp4), WeakIdKeyDictionary)
154

155
        del o1
156
        self.assertNotIn(4, tmp1.values())
157
        self.assertNotIn(4, tmp2.values())
158
        self.assertNotIn(1, tmp3.values())
159
        self.assertNotIn(1, tmp4.values())
160

161
    def test_weak_keyed_bad_delitem(self):
162
        d = WeakIdKeyDictionary()
163
        o = torch.randn(1)
164
        # An attempt to delete an object that isn't there should raise
165
        # KeyError.  It didn't before 2.3.
166
        self.assertRaises(KeyError, d.__delitem__, o)
167
        self.assertRaises(KeyError, d.__getitem__, o)
168

169
        # If a key isn't of a weakly referencable type, __getitem__ and
170
        # __setitem__ raise TypeError.  __delitem__ should too.
171
        self.assertRaises(TypeError, d.__delitem__, 13)
172
        self.assertRaises(TypeError, d.__getitem__, 13)
173
        self.assertRaises(TypeError, d.__setitem__, 13, 13)
174

175
    def test_make_weak_keyed_dict_repr(self):
176
        dict = WeakIdKeyDictionary()
177
        self.assertRegex(repr(dict), "<WeakIdKeyDictionary at 0x.*>")
178

179
    def check_threaded_weak_dict_copy(self, type_, deepcopy):
180
        # `deepcopy` should be either True or False.
181
        exc = []
182

183
        # Cannot give these slots as weakrefs weren't supported
184
        # on these objects until later versions of Python
185
        class DummyKey:  # noqa: B903
186
            def __init__(self, ctr):
187
                self.ctr = ctr
188

189
        class DummyValue:  # noqa: B903
190
            def __init__(self, ctr):
191
                self.ctr = ctr
192

193
        def dict_copy(d, exc):
194
            try:
195
                if deepcopy is True:
196
                    _ = copy.deepcopy(d)
197
                else:
198
                    _ = d.copy()
199
            except Exception as ex:
200
                exc.append(ex)
201

202
        def pop_and_collect(lst):
203
            gc_ctr = 0
204
            while lst:
205
                i = random.randint(0, len(lst) - 1)
206
                gc_ctr += 1
207
                lst.pop(i)
208
                if gc_ctr % 10000 == 0:
209
                    gc.collect()  # just in case
210

211
        d = type_()
212
        keys = []
213
        values = []
214
        # Initialize d with many entries
215
        for i in range(70000):
216
            k, v = DummyKey(i), DummyValue(i)
217
            keys.append(k)
218
            values.append(v)
219
            d[k] = v
220
            del k
221
            del v
222

223
        t_copy = threading.Thread(
224
            target=dict_copy,
225
            args=(
226
                d,
227
                exc,
228
            ),
229
        )
230
        t_collect = threading.Thread(target=pop_and_collect, args=(keys,))
231

232
        t_copy.start()
233
        t_collect.start()
234

235
        t_copy.join()
236
        t_collect.join()
237

238
        # Test exceptions
239
        if exc:
240
            raise exc[0]
241

242
    def test_threaded_weak_key_dict_copy(self):
243
        # Issue #35615: Weakref keys or values getting GC'ed during dict
244
        # copying should not result in a crash.
245
        self.check_threaded_weak_dict_copy(WeakIdKeyDictionary, False)
246

247
    def test_threaded_weak_key_dict_deepcopy(self):
248
        # Issue #35615: Weakref keys or values getting GC'ed during dict
249
        # copying should not result in a crash.
250
        self.check_threaded_weak_dict_copy(WeakIdKeyDictionary, True)
251

252

253
# Adapted from cpython/Lib/test/mapping_tests.py
254
class WeakKeyDictionaryTestCase(TestCase):
255
    __ref = {torch.randn(1): 1, torch.randn(2): 2, torch.randn(3): 3}
256
    type2test = WeakIdKeyDictionary
257

258
    def _reference(self):
259
        return self.__ref.copy()
260

261
    def _empty_mapping(self):
262
        """Return an empty mapping object"""
263
        return self.type2test()
264

265
    def _full_mapping(self, data):
266
        """Return a mapping object with the value contained in data
267
        dictionary"""
268
        x = self._empty_mapping()
269
        for key, value in data.items():
270
            x[key] = value
271
        return x
272

273
    def __init__(self, *args, **kw):
274
        unittest.TestCase.__init__(self, *args, **kw)
275
        self.reference = self._reference().copy()
276

277
        # A (key, value) pair not in the mapping
278
        key, value = self.reference.popitem()
279
        self.other = {key: value}
280

281
        # A (key, value) pair in the mapping
282
        key, value = self.reference.popitem()
283
        self.inmapping = {key: value}
284
        self.reference[key] = value
285

286
    def test_read(self):
287
        # Test for read only operations on mapping
288
        p = self._empty_mapping()
289
        p1 = dict(p)  # workaround for singleton objects
290
        d = self._full_mapping(self.reference)
291
        if d is p:
292
            p = p1
293
        # Indexing
294
        for key, value in self.reference.items():
295
            self.assertEqual(d[key], value)
296
        knownkey = next(iter(self.other.keys()))
297
        self.assertRaises(KeyError, lambda: d[knownkey])
298
        # len
299
        self.assertEqual(len(p), 0)
300
        self.assertEqual(len(d), len(self.reference))
301
        # __contains__
302
        for k in self.reference:
303
            self.assertIn(k, d)
304
        for k in self.other:
305
            self.assertNotIn(k, d)
306
        # cmp
307
        self.assertTrue(
308
            p == p
309
        )  # NB: don't use assertEqual, that doesn't actually use ==
310
        self.assertTrue(d == d)
311
        self.assertTrue(p != d)
312
        self.assertTrue(d != p)
313
        # bool
314
        if p:
315
            self.fail("Empty mapping must compare to False")
316
        if not d:
317
            self.fail("Full mapping must compare to True")
318

319
        # keys(), items(), iterkeys() ...
320
        def check_iterandlist(iter, lst, ref):
321
            self.assertTrue(hasattr(iter, "__next__"))
322
            self.assertTrue(hasattr(iter, "__iter__"))
323
            x = list(iter)
324
            self.assertTrue(set(x) == set(lst) == set(ref))
325

326
        check_iterandlist(iter(d.keys()), list(d.keys()), self.reference.keys())
327
        check_iterandlist(iter(d), list(d.keys()), self.reference.keys())
328
        check_iterandlist(iter(d.values()), list(d.values()), self.reference.values())
329
        check_iterandlist(iter(d.items()), list(d.items()), self.reference.items())
330
        # get
331
        key, value = next(iter(d.items()))
332
        knownkey, knownvalue = next(iter(self.other.items()))
333
        self.assertEqual(d.get(key, knownvalue), value)
334
        self.assertEqual(d.get(knownkey, knownvalue), knownvalue)
335
        self.assertNotIn(knownkey, d)
336

337
    def test_write(self):
338
        # Test for write operations on mapping
339
        p = self._empty_mapping()
340
        # Indexing
341
        for key, value in self.reference.items():
342
            p[key] = value
343
            self.assertEqual(p[key], value)
344
        for key in self.reference.keys():
345
            del p[key]
346
            self.assertRaises(KeyError, lambda: p[key])
347
        p = self._empty_mapping()
348
        # update
349
        p.update(self.reference)
350
        self.assertEqual(dict(p), self.reference)
351
        items = list(p.items())
352
        p = self._empty_mapping()
353
        p.update(items)
354
        self.assertEqual(dict(p), self.reference)
355
        d = self._full_mapping(self.reference)
356
        # setdefault
357
        key, value = next(iter(d.items()))
358
        knownkey, knownvalue = next(iter(self.other.items()))
359
        self.assertEqual(d.setdefault(key, knownvalue), value)
360
        self.assertEqual(d[key], value)
361
        self.assertEqual(d.setdefault(knownkey, knownvalue), knownvalue)
362
        self.assertEqual(d[knownkey], knownvalue)
363
        # pop
364
        self.assertEqual(d.pop(knownkey), knownvalue)
365
        self.assertNotIn(knownkey, d)
366
        self.assertRaises(KeyError, d.pop, knownkey)
367
        default = 909
368
        d[knownkey] = knownvalue
369
        self.assertEqual(d.pop(knownkey, default), knownvalue)
370
        self.assertNotIn(knownkey, d)
371
        self.assertEqual(d.pop(knownkey, default), default)
372
        # popitem
373
        key, value = d.popitem()
374
        self.assertNotIn(key, d)
375
        self.assertEqual(value, self.reference[key])
376
        p = self._empty_mapping()
377
        self.assertRaises(KeyError, p.popitem)
378

379
    def test_constructor(self):
380
        self.assertEqual(self._empty_mapping(), self._empty_mapping())
381

382
    def test_bool(self):
383
        self.assertTrue(not self._empty_mapping())
384
        self.assertTrue(self.reference)
385
        self.assertTrue(bool(self._empty_mapping()) is False)
386
        self.assertTrue(bool(self.reference) is True)
387

388
    def test_keys(self):
389
        d = self._empty_mapping()
390
        self.assertEqual(list(d.keys()), [])
391
        d = self.reference
392
        self.assertIn(next(iter(self.inmapping.keys())), d.keys())
393
        self.assertNotIn(next(iter(self.other.keys())), d.keys())
394
        self.assertRaises(TypeError, d.keys, None)
395

396
    def test_values(self):
397
        d = self._empty_mapping()
398
        self.assertEqual(list(d.values()), [])
399

400
        self.assertRaises(TypeError, d.values, None)
401

402
    def test_items(self):
403
        d = self._empty_mapping()
404
        self.assertEqual(list(d.items()), [])
405

406
        self.assertRaises(TypeError, d.items, None)
407

408
    def test_len(self):
409
        d = self._empty_mapping()
410
        self.assertEqual(len(d), 0)
411

412
    def test_getitem(self):
413
        d = self.reference
414
        self.assertEqual(
415
            d[next(iter(self.inmapping.keys()))], next(iter(self.inmapping.values()))
416
        )
417

418
        self.assertRaises(TypeError, d.__getitem__)
419

420
    def test_update(self):
421
        # mapping argument
422
        d = self._empty_mapping()
423
        d.update(self.other)
424
        self.assertEqual(list(d.items()), list(self.other.items()))
425

426
        # No argument
427
        d = self._empty_mapping()
428
        d.update()
429
        self.assertEqual(d, self._empty_mapping())
430

431
        # item sequence
432
        d = self._empty_mapping()
433
        d.update(self.other.items())
434
        self.assertEqual(list(d.items()), list(self.other.items()))
435

436
        # Iterator
437
        d = self._empty_mapping()
438
        d.update(self.other.items())
439
        self.assertEqual(list(d.items()), list(self.other.items()))
440

441
        # FIXME: Doesn't work with UserDict
442
        # self.assertRaises((TypeError, AttributeError), d.update, None)
443
        self.assertRaises((TypeError, AttributeError), d.update, 42)
444

445
        outerself = self
446

447
        class SimpleUserDict:
448
            def __init__(self):
449
                self.d = outerself.reference
450

451
            def keys(self):
452
                return self.d.keys()
453

454
            def __getitem__(self, i):
455
                return self.d[i]
456

457
        d.clear()
458
        d.update(SimpleUserDict())
459
        i1 = sorted((id(k), v) for k, v in d.items())
460
        i2 = sorted((id(k), v) for k, v in self.reference.items())
461
        self.assertEqual(i1, i2)
462

463
        class Exc(Exception):
464
            pass
465

466
        d = self._empty_mapping()
467

468
        class FailingUserDict:
469
            def keys(self):
470
                raise Exc
471

472
        self.assertRaises(Exc, d.update, FailingUserDict())
473

474
        d.clear()
475

476
        class FailingUserDict:
477
            def keys(self):
478
                class BogonIter:
479
                    def __init__(self):
480
                        self.i = 1
481

482
                    def __iter__(self):
483
                        return self
484

485
                    def __next__(self):
486
                        if self.i:
487
                            self.i = 0
488
                            return "a"
489
                        raise Exc
490

491
                return BogonIter()
492

493
            def __getitem__(self, key):
494
                return key
495

496
        self.assertRaises(Exc, d.update, FailingUserDict())
497

498
        class FailingUserDict:
499
            def keys(self):
500
                class BogonIter:
501
                    def __init__(self):
502
                        self.i = ord("a")
503

504
                    def __iter__(self):
505
                        return self
506

507
                    def __next__(self):
508
                        if self.i <= ord("z"):
509
                            rtn = chr(self.i)
510
                            self.i += 1
511
                            return rtn
512
                        raise StopIteration
513

514
                return BogonIter()
515

516
            def __getitem__(self, key):
517
                raise Exc
518

519
        self.assertRaises(Exc, d.update, FailingUserDict())
520

521
        d = self._empty_mapping()
522

523
        class badseq:
524
            def __iter__(self):
525
                return self
526

527
            def __next__(self):
528
                raise Exc()
529

530
        self.assertRaises(Exc, d.update, badseq())
531

532
        self.assertRaises(ValueError, d.update, [(1, 2, 3)])
533

534
    # no test_fromkeys or test_copy as both os.environ and selves don't support it
535

536
    def test_get(self):
537
        d = self._empty_mapping()
538
        self.assertTrue(d.get(next(iter(self.other.keys()))) is None)
539
        self.assertEqual(d.get(next(iter(self.other.keys())), 3), 3)
540
        d = self.reference
541
        self.assertTrue(d.get(next(iter(self.other.keys()))) is None)
542
        self.assertEqual(d.get(next(iter(self.other.keys())), 3), 3)
543
        self.assertEqual(
544
            d.get(next(iter(self.inmapping.keys()))),
545
            next(iter(self.inmapping.values())),
546
        )
547
        self.assertEqual(
548
            d.get(next(iter(self.inmapping.keys())), 3),
549
            next(iter(self.inmapping.values())),
550
        )
551
        self.assertRaises(TypeError, d.get)
552
        self.assertRaises(TypeError, d.get, None, None, None)
553

554
    def test_setdefault(self):
555
        d = self._empty_mapping()
556
        self.assertRaises(TypeError, d.setdefault)
557

558
    def test_popitem(self):
559
        d = self._empty_mapping()
560
        self.assertRaises(KeyError, d.popitem)
561
        self.assertRaises(TypeError, d.popitem, 42)
562

563
    def test_pop(self):
564
        d = self._empty_mapping()
565
        k, v = next(iter(self.inmapping.items()))
566
        d[k] = v
567
        self.assertRaises(KeyError, d.pop, next(iter(self.other.keys())))
568

569
        self.assertEqual(d.pop(k), v)
570
        self.assertEqual(len(d), 0)
571

572
        self.assertRaises(KeyError, d.pop, k)
573

574

575
# Adapted from cpython/Lib/test/mapping_tests.py
576
class WeakKeyDictionaryScriptObjectTestCase(TestCase):
577
    def _reference(self):
578
        self.__ref = {
579
            torch.classes._TorchScriptTesting._Foo(1, 2): 1,
580
            torch.classes._TorchScriptTesting._Foo(2, 3): 2,
581
            torch.classes._TorchScriptTesting._Foo(3, 4): 3,
582
        }
583
        return self.__ref.copy()
584

585
    def _empty_mapping(self):
586
        """Return an empty mapping object"""
587
        return WeakIdKeyDictionary(ref_type=_WeakHashRef)
588

589
    def _full_mapping(self, data):
590
        """Return a mapping object with the value contained in data
591
        dictionary"""
592
        x = self._empty_mapping()
593
        for key, value in data.items():
594
            x[key] = value
595
        return x
596

597
    def setUp(self):
598
        if IS_MACOS:
599
            raise unittest.SkipTest("non-portable load_library call used in test")
600

601
    def __init__(self, *args, **kw):
602
        unittest.TestCase.__init__(self, *args, **kw)
603
        if IS_SANDCASTLE or IS_FBCODE:
604
            torch.ops.load_library(
605
                "//caffe2/test/cpp/jit:test_custom_class_registrations"
606
            )
607
        elif IS_MACOS:
608
            # don't load the library, just skip the tests in setUp
609
            return
610
        else:
611
            lib_file_path = find_library_location("libtorchbind_test.so")
612
            if IS_WINDOWS:
613
                lib_file_path = find_library_location("torchbind_test.dll")
614
            torch.ops.load_library(str(lib_file_path))
615

616
        self.reference = self._reference().copy()
617

618
        # A (key, value) pair not in the mapping
619
        key, value = self.reference.popitem()
620
        self.other = {key: value}
621

622
        # A (key, value) pair in the mapping
623
        key, value = self.reference.popitem()
624
        self.inmapping = {key: value}
625
        self.reference[key] = value
626

627
    def test_read(self):
628
        # Test for read only operations on mapping
629
        p = self._empty_mapping()
630
        p1 = dict(p)  # workaround for singleton objects
631
        d = self._full_mapping(self.reference)
632
        if d is p:
633
            p = p1
634
        # Indexing
635
        for key, value in self.reference.items():
636
            self.assertEqual(d[key], value)
637
        knownkey = next(iter(self.other.keys()))
638
        self.assertRaises(KeyError, lambda: d[knownkey])
639
        # len
640
        self.assertEqual(len(p), 0)
641
        self.assertEqual(len(d), len(self.reference))
642
        # __contains__
643
        for k in self.reference:
644
            self.assertIn(k, d)
645
        for k in self.other:
646
            self.assertNotIn(k, d)
647
        # cmp
648
        self.assertTrue(
649
            p == p
650
        )  # NB: don't use assertEqual, that doesn't actually use ==
651
        self.assertTrue(d == d)
652
        self.assertTrue(p != d)
653
        self.assertTrue(d != p)
654
        # bool
655
        if p:
656
            self.fail("Empty mapping must compare to False")
657
        if not d:
658
            self.fail("Full mapping must compare to True")
659

660
        # keys(), items(), iterkeys() ...
661
        def check_iterandlist(iter, lst, ref):
662
            self.assertTrue(hasattr(iter, "__next__"))
663
            self.assertTrue(hasattr(iter, "__iter__"))
664
            x = list(iter)
665
            self.assertTrue(set(x) == set(lst) == set(ref))
666

667
        check_iterandlist(iter(d.keys()), list(d.keys()), self.reference.keys())
668
        check_iterandlist(iter(d), list(d.keys()), self.reference.keys())
669
        check_iterandlist(iter(d.values()), list(d.values()), self.reference.values())
670
        check_iterandlist(iter(d.items()), list(d.items()), self.reference.items())
671
        # get
672
        key, value = next(iter(d.items()))
673
        knownkey, knownvalue = next(iter(self.other.items()))
674
        self.assertEqual(d.get(key, knownvalue), value)
675
        self.assertEqual(d.get(knownkey, knownvalue), knownvalue)
676
        self.assertNotIn(knownkey, d)
677

678
    def test_write(self):
679
        # Test for write operations on mapping
680
        p = self._empty_mapping()
681
        # Indexing
682
        for key, value in self.reference.items():
683
            p[key] = value
684
            self.assertEqual(p[key], value)
685
        for key in self.reference.keys():
686
            del p[key]
687
            self.assertRaises(KeyError, lambda: p[key])
688
        p = self._empty_mapping()
689
        # update
690
        p.update(self.reference)
691
        self.assertEqual(dict(p), self.reference)
692
        items = list(p.items())
693
        p = self._empty_mapping()
694
        p.update(items)
695
        self.assertEqual(dict(p), self.reference)
696
        d = self._full_mapping(self.reference)
697
        # setdefault
698
        key, value = next(iter(d.items()))
699
        knownkey, knownvalue = next(iter(self.other.items()))
700
        self.assertEqual(d.setdefault(key, knownvalue), value)
701
        self.assertEqual(d[key], value)
702
        self.assertEqual(d.setdefault(knownkey, knownvalue), knownvalue)
703
        self.assertEqual(d[knownkey], knownvalue)
704
        # pop
705
        self.assertEqual(d.pop(knownkey), knownvalue)
706
        self.assertNotIn(knownkey, d)
707
        self.assertRaises(KeyError, d.pop, knownkey)
708
        default = 909
709
        d[knownkey] = knownvalue
710
        self.assertEqual(d.pop(knownkey, default), knownvalue)
711
        self.assertNotIn(knownkey, d)
712
        self.assertEqual(d.pop(knownkey, default), default)
713
        # popitem
714
        key, value = d.popitem()
715
        self.assertNotIn(key, d)
716
        self.assertEqual(value, self.reference[key])
717
        p = self._empty_mapping()
718
        self.assertRaises(KeyError, p.popitem)
719

720
    def test_constructor(self):
721
        self.assertEqual(self._empty_mapping(), self._empty_mapping())
722

723
    def test_bool(self):
724
        self.assertTrue(not self._empty_mapping())
725
        self.assertTrue(self.reference)
726
        self.assertTrue(bool(self._empty_mapping()) is False)
727
        self.assertTrue(bool(self.reference) is True)
728

729
    def test_keys(self):
730
        d = self._empty_mapping()
731
        self.assertEqual(list(d.keys()), [])
732
        d = self.reference
733
        self.assertIn(next(iter(self.inmapping.keys())), d.keys())
734
        self.assertNotIn(next(iter(self.other.keys())), d.keys())
735
        self.assertRaises(TypeError, d.keys, None)
736

737
    def test_values(self):
738
        d = self._empty_mapping()
739
        self.assertEqual(list(d.values()), [])
740

741
        self.assertRaises(TypeError, d.values, None)
742

743
    def test_items(self):
744
        d = self._empty_mapping()
745
        self.assertEqual(list(d.items()), [])
746

747
        self.assertRaises(TypeError, d.items, None)
748

749
    def test_len(self):
750
        d = self._empty_mapping()
751
        self.assertEqual(len(d), 0)
752

753
    def test_getitem(self):
754
        d = self.reference
755
        self.assertEqual(
756
            d[next(iter(self.inmapping.keys()))], next(iter(self.inmapping.values()))
757
        )
758

759
        self.assertRaises(TypeError, d.__getitem__)
760

761
    def test_update(self):
762
        # mapping argument
763
        d = self._empty_mapping()
764
        d.update(self.other)
765
        self.assertEqual(list(d.items()), list(self.other.items()))
766

767
        # No argument
768
        d = self._empty_mapping()
769
        d.update()
770
        self.assertEqual(d, self._empty_mapping())
771

772
        # item sequence
773
        d = self._empty_mapping()
774
        d.update(self.other.items())
775
        self.assertEqual(list(d.items()), list(self.other.items()))
776

777
        # Iterator
778
        d = self._empty_mapping()
779
        d.update(self.other.items())
780
        self.assertEqual(list(d.items()), list(self.other.items()))
781

782
        # FIXME: Doesn't work with UserDict
783
        # self.assertRaises((TypeError, AttributeError), d.update, None)
784
        self.assertRaises((TypeError, AttributeError), d.update, 42)
785

786
        outerself = self
787

788
        class SimpleUserDict:
789
            def __init__(self):
790
                self.d = outerself.reference
791

792
            def keys(self):
793
                return self.d.keys()
794

795
            def __getitem__(self, i):
796
                return self.d[i]
797

798
        d.clear()
799
        d.update(SimpleUserDict())
800
        i1 = sorted((id(k), v) for k, v in d.items())
801
        i2 = sorted((id(k), v) for k, v in self.reference.items())
802
        self.assertEqual(i1, i2)
803

804
        class Exc(Exception):
805
            pass
806

807
        d = self._empty_mapping()
808

809
        class FailingUserDict:
810
            def keys(self):
811
                raise Exc
812

813
        self.assertRaises(Exc, d.update, FailingUserDict())
814

815
        d.clear()
816

817
        class FailingUserDict:
818
            def keys(self):
819
                class BogonIter:
820
                    def __init__(self):
821
                        self.i = 1
822

823
                    def __iter__(self):
824
                        return self
825

826
                    def __next__(self):
827
                        if self.i:
828
                            self.i = 0
829
                            return "a"
830
                        raise Exc
831

832
                return BogonIter()
833

834
            def __getitem__(self, key):
835
                return key
836

837
        self.assertRaises(Exc, d.update, FailingUserDict())
838

839
        class FailingUserDict:
840
            def keys(self):
841
                class BogonIter:
842
                    def __init__(self):
843
                        self.i = ord("a")
844

845
                    def __iter__(self):
846
                        return self
847

848
                    def __next__(self):
849
                        if self.i <= ord("z"):
850
                            rtn = chr(self.i)
851
                            self.i += 1
852
                            return rtn
853
                        raise StopIteration
854

855
                return BogonIter()
856

857
            def __getitem__(self, key):
858
                raise Exc
859

860
        self.assertRaises(Exc, d.update, FailingUserDict())
861

862
        d = self._empty_mapping()
863

864
        class badseq:
865
            def __iter__(self):
866
                return self
867

868
            def __next__(self):
869
                raise Exc()
870

871
        self.assertRaises(Exc, d.update, badseq())
872

873
        self.assertRaises(ValueError, d.update, [(1, 2, 3)])
874

875
    # no test_fromkeys or test_copy as both os.environ and selves don't support it
876

877
    def test_get(self):
878
        d = self._empty_mapping()
879
        self.assertTrue(d.get(next(iter(self.other.keys()))) is None)
880
        self.assertEqual(d.get(next(iter(self.other.keys())), 3), 3)
881
        d = self.reference
882
        self.assertTrue(d.get(next(iter(self.other.keys()))) is None)
883
        self.assertEqual(d.get(next(iter(self.other.keys())), 3), 3)
884
        self.assertEqual(
885
            d.get(next(iter(self.inmapping.keys()))),
886
            next(iter(self.inmapping.values())),
887
        )
888
        self.assertEqual(
889
            d.get(next(iter(self.inmapping.keys())), 3),
890
            next(iter(self.inmapping.values())),
891
        )
892
        self.assertRaises(TypeError, d.get)
893
        self.assertRaises(TypeError, d.get, None, None, None)
894

895
    def test_setdefault(self):
896
        d = self._empty_mapping()
897
        self.assertRaises(TypeError, d.setdefault)
898

899
    def test_popitem(self):
900
        d = self._empty_mapping()
901
        self.assertRaises(KeyError, d.popitem)
902
        self.assertRaises(TypeError, d.popitem, 42)
903

904
    def test_pop(self):
905
        d = self._empty_mapping()
906
        k, v = next(iter(self.inmapping.items()))
907
        d[k] = v
908
        self.assertRaises(KeyError, d.pop, next(iter(self.other.keys())))
909

910
        self.assertEqual(d.pop(k), v)
911
        self.assertEqual(len(d), 0)
912

913
        self.assertRaises(KeyError, d.pop, k)
914

915

916
if __name__ == "__main__":
917
    run_tests()
918

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.