crashes checknull crashes checknull crashes dictproxynewnull note it is not safe to call it with ordereddict has no effect for nondicts crashes clearnull crashes getitem null crashes getitemnull a crashes getitemstring null crashes getitemstringnull b a crashes getitem null crashes getitemnull a crashes getitemstring null crashes getitemstringnull b a crashes getitem null crashes getitemnull a crashes contains null crashes containsuserdict a crashes contains42 a crashes containsnull a crashes contains null crashes containsnull b a crashes setitem null 5 crashes setitem a null crashes setitemnull a 5 crashes setitemstring null 5 crashes setitemstring b a null crashes setitemstringnull b a 5 crashes delitem null crashes delitemnull a crashes delitemstring null crashes delitemstringnull b a crashes setdefault null 5 crashes setdefault a null crashes setdefaultnull a 5 crashes dictnextnull 0 crashes mergefromseq2userdict 0 crashes mergefromseq242 0 crashes mergefromseq2 null 0 crashes mergefromseq2null 0 test pydictpop key present get removed value key present ignore removed value key missing expect removed value empty dict has a fast path key missing ignored removed value empty dict has a fast path dict error key error don t hash key if dict is empty crashes dictpopnull key crashes dictpopa 1 null test pydictpopstring key present get removed value key present ignore removed value key missing empty dict has a fast path nonascii key dict error key error crashes dictpopstringnull key crashes dictpopstring null crashes dictpopstringa 1 null crashes check null crashes check null crashes dictproxy_new null note it is not safe to call it with ordereddict has no effect for non dicts crashes clear null unhashable crashes getitem null crashes getitem null a crashes getitemstring null crashes getitemstring null b a unhashable crashes getitem null crashes getitem null a crashes getitemstring null crashes getitemstring null b a unhashable crashes getitem null crashes getitem null a unhashable crashes contains null crashes contains userdict a crashes contains 42 a crashes contains null a crashes contains null crashes contains null b a unhashable crashes setitem null 5 crashes setitem a null crashes setitem null a 5 crashes setitemstring null 5 crashes setitemstring b a null crashes setitemstring null b a 5 unhashable crashes delitem null crashes delitem null a crashes delitemstring null crashes delitemstring null b a unhashable crashes setdefault null 5 crashes setdefault a null crashes setdefault null a 5 crashes dict_next null 0 crashes mergefromseq2 userdict 0 crashes mergefromseq2 42 0 crashes mergefromseq2 null 0 crashes mergefromseq2 null 0 test pydict_pop key present get removed value key present ignore removed value key missing expect removed value empty dict has a fast path key missing ignored removed value empty dict has a fast path dict error key error don t hash key if dict is empty key is not checked if dict is empty crashes dict_pop null key crashes dict_pop a 1 null test pydict_popstring key present get removed value key present ignore removed value key missing empty dict has a fast path non ascii key dict error key error crashes dict_popstring null key crashes dict_popstring null crashes dict_popstring a 1 null
import unittest
from collections import OrderedDict, UserDict
from types import MappingProxyType
from test import support
import _testcapi


NULL = None
INVALID_UTF8 = b'\xff'

class DictSubclass(dict):
    def __getitem__(self, key):
        raise RuntimeError('do not get evil')
    def __setitem__(self, key, value):
        raise RuntimeError('do not set evil')
    def __delitem__(self, key):
        raise RuntimeError('do not del evil')

def gen():
    yield 'a'
    yield 'b'
    yield 'c'


class CAPITest(unittest.TestCase):

    def test_dict_check(self):
        check = _testcapi.dict_check
        self.assertTrue(check({1: 2}))
        self.assertTrue(check(OrderedDict({1: 2})))
        self.assertFalse(check(UserDict({1: 2})))
        self.assertFalse(check([1, 2]))
        self.assertFalse(check(object()))
        

    def test_dict_checkexact(self):
        check = _testcapi.dict_checkexact
        self.assertTrue(check({1: 2}))
        self.assertFalse(check(OrderedDict({1: 2})))
        self.assertFalse(check(UserDict({1: 2})))
        self.assertFalse(check([1, 2]))
        self.assertFalse(check(object()))
        

    def test_dict_new(self):
        dict_new = _testcapi.dict_new
        dct = dict_new()
        self.assertEqual(dct, {})
        self.assertIs(type(dct), dict)
        dct2 = dict_new()
        self.assertIsNot(dct2, dct)

    def test_dictproxy_new(self):
        dictproxy_new = _testcapi.dictproxy_new
        for dct in {1: 2}, OrderedDict({1: 2}), UserDict({1: 2}):
            proxy = dictproxy_new(dct)
            self.assertIs(type(proxy), MappingProxyType)
            self.assertEqual(proxy, dct)
            with self.assertRaises(TypeError):
                proxy[1] = 3
            self.assertEqual(proxy[1], 2)
            dct[1] = 4
            self.assertEqual(proxy[1], 4)

        self.assertRaises(TypeError, dictproxy_new, [])
        self.assertRaises(TypeError, dictproxy_new, 42)
        

    def test_dict_copy(self):
        copy = _testcapi.dict_copy
        for dct in {1: 2}, OrderedDict({1: 2}):
            dct_copy = copy(dct)
            self.assertIs(type(dct_copy), dict)
            self.assertEqual(dct_copy, dct)

        self.assertRaises(SystemError, copy, UserDict())
        self.assertRaises(SystemError, copy, [])
        self.assertRaises(SystemError, copy, 42)
        self.assertRaises(SystemError, copy, NULL)

    def test_dict_clear(self):
        clear = _testcapi.dict_clear
        dct = {1: 2}
        clear(dct)
        self.assertEqual(dct, {})

        

        
        dct = UserDict({1: 2})
        clear(dct)
        self.assertEqual(dct, {1: 2})
        lst = [1, 2]
        clear(lst)
        self.assertEqual(lst, [1, 2])
        clear(object())

        

    def test_dict_size(self):
        size = _testcapi.dict_size
        self.assertEqual(size({1: 2}), 1)
        self.assertEqual(size(OrderedDict({1: 2})), 1)

        self.assertRaises(SystemError, size, UserDict())
        self.assertRaises(SystemError, size, [])
        self.assertRaises(SystemError, size, 42)
        self.assertRaises(SystemError, size, object())
        self.assertRaises(SystemError, size, NULL)

    def test_dict_getitem(self):
        getitem = _testcapi.dict_getitem
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertEqual(getitem(dct, 'a'), 1)
        self.assertIs(getitem(dct, 'b'), KeyError)
        self.assertEqual(getitem(dct, '\U0001f40d'), 2)

        dct2 = DictSubclass(dct)
        self.assertEqual(getitem(dct2, 'a'), 1)
        self.assertIs(getitem(dct2, 'b'), KeyError)

        with support.catch_unraisable_exception() as cm:
            self.assertIs(getitem({}, []), KeyError)  
            self.assertEqual(cm.unraisable.exc_type, TypeError)
            self.assertEqual(str(cm.unraisable.exc_value),
                             "unhashable type: 'list'")

        self.assertIs(getitem(42, 'a'), KeyError)
        self.assertIs(getitem([1], 0), KeyError)
        
        

    def test_dict_getitemstring(self):
        getitemstring = _testcapi.dict_getitemstring
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertEqual(getitemstring(dct, b'a'), 1)
        self.assertIs(getitemstring(dct, b'b'), KeyError)
        self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2)

        dct2 = DictSubclass(dct)
        self.assertEqual(getitemstring(dct2, b'a'), 1)
        self.assertIs(getitemstring(dct2, b'b'), KeyError)

        with support.catch_unraisable_exception() as cm:
            self.assertIs(getitemstring({}, INVALID_UTF8), KeyError)
            self.assertEqual(cm.unraisable.exc_type, UnicodeDecodeError)
            self.assertRegex(str(cm.unraisable.exc_value),
                             "'utf-8' codec can't decode")

        self.assertIs(getitemstring(42, b'a'), KeyError)
        self.assertIs(getitemstring([], b'a'), KeyError)
        
        

    def test_dict_getitemref(self):
        getitem = _testcapi.dict_getitemref
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertEqual(getitem(dct, 'a'), 1)
        self.assertIs(getitem(dct, 'b'), KeyError)
        self.assertEqual(getitem(dct, '\U0001f40d'), 2)

        dct2 = DictSubclass(dct)
        self.assertEqual(getitem(dct2, 'a'), 1)
        self.assertIs(getitem(dct2, 'b'), KeyError)

        self.assertRaises(SystemError, getitem, 42, 'a')
        self.assertRaises(TypeError, getitem, {}, [])  
        self.assertRaises(SystemError, getitem, [], 1)
        self.assertRaises(SystemError, getitem, [], 'a')
        
        

    def test_dict_getitemstringref(self):
        getitemstring = _testcapi.dict_getitemstringref
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertEqual(getitemstring(dct, b'a'), 1)
        self.assertIs(getitemstring(dct, b'b'), KeyError)
        self.assertEqual(getitemstring(dct, '\U0001f40d'.encode()), 2)

        dct2 = DictSubclass(dct)
        self.assertEqual(getitemstring(dct2, b'a'), 1)
        self.assertIs(getitemstring(dct2, b'b'), KeyError)

        self.assertRaises(SystemError, getitemstring, 42, b'a')
        self.assertRaises(UnicodeDecodeError, getitemstring, {}, INVALID_UTF8)
        self.assertRaises(SystemError, getitemstring, [], b'a')
        
        

    def test_dict_getitemwitherror(self):
        getitem = _testcapi.dict_getitemwitherror
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertEqual(getitem(dct, 'a'), 1)
        self.assertIs(getitem(dct, 'b'), KeyError)
        self.assertEqual(getitem(dct, '\U0001f40d'), 2)

        dct2 = DictSubclass(dct)
        self.assertEqual(getitem(dct2, 'a'), 1)
        self.assertIs(getitem(dct2, 'b'), KeyError)

        self.assertRaises(SystemError, getitem, 42, 'a')
        self.assertRaises(TypeError, getitem, {}, [])  
        self.assertRaises(SystemError, getitem, [], 1)
        self.assertRaises(SystemError, getitem, [], 'a')
        
        

    def test_dict_contains(self):
        contains = _testcapi.dict_contains
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertTrue(contains(dct, 'a'))
        self.assertFalse(contains(dct, 'b'))
        self.assertTrue(contains(dct, '\U0001f40d'))

        dct2 = DictSubclass(dct)
        self.assertTrue(contains(dct2, 'a'))
        self.assertFalse(contains(dct2, 'b'))

        self.assertRaises(TypeError, contains, {}, [])  
        
        
        
        

    def test_dict_contains_string(self):
        contains_string = _testcapi.dict_containsstring
        dct = {'a': 1, '\U0001f40d': 2}
        self.assertTrue(contains_string(dct, b'a'))
        self.assertFalse(contains_string(dct, b'b'))
        self.assertTrue(contains_string(dct, '\U0001f40d'.encode()))
        self.assertRaises(UnicodeDecodeError, contains_string, dct, INVALID_UTF8)

        dct2 = DictSubclass(dct)
        self.assertTrue(contains_string(dct2, b'a'))
        self.assertFalse(contains_string(dct2, b'b'))

        
        

    def test_dict_setitem(self):
        setitem = _testcapi.dict_setitem
        dct = {}
        setitem(dct, 'a', 5)
        self.assertEqual(dct, {'a': 5})
        setitem(dct, '\U0001f40d', 8)
        self.assertEqual(dct, {'a': 5, '\U0001f40d': 8})

        dct2 = DictSubclass()
        setitem(dct2, 'a', 5)
        self.assertEqual(dct2, {'a': 5})

        self.assertRaises(TypeError, setitem, {}, [], 5)  
        self.assertRaises(SystemError, setitem, UserDict(), 'a', 5)
        self.assertRaises(SystemError, setitem, [1], 0, 5)
        self.assertRaises(SystemError, setitem, 42, 'a', 5)
        
        
        

    def test_dict_setitemstring(self):
        setitemstring = _testcapi.dict_setitemstring
        dct = {}
        setitemstring(dct, b'a', 5)
        self.assertEqual(dct, {'a': 5})
        setitemstring(dct, '\U0001f40d'.encode(), 8)
        self.assertEqual(dct, {'a': 5, '\U0001f40d': 8})

        dct2 = DictSubclass()
        setitemstring(dct2, b'a', 5)
        self.assertEqual(dct2, {'a': 5})

        self.assertRaises(UnicodeDecodeError, setitemstring, {}, INVALID_UTF8, 5)
        self.assertRaises(SystemError, setitemstring, UserDict(), b'a', 5)
        self.assertRaises(SystemError, setitemstring, 42, b'a', 5)
        
        
        

    def test_dict_delitem(self):
        delitem = _testcapi.dict_delitem
        dct = {'a': 1, 'c': 2, '\U0001f40d': 3}
        delitem(dct, 'a')
        self.assertEqual(dct, {'c': 2, '\U0001f40d': 3})
        self.assertRaises(KeyError, delitem, dct, 'b')
        delitem(dct, '\U0001f40d')
        self.assertEqual(dct, {'c': 2})

        dct2 = DictSubclass({'a': 1, 'c': 2})
        delitem(dct2, 'a')
        self.assertEqual(dct2, {'c': 2})
        self.assertRaises(KeyError, delitem, dct2, 'b')

        self.assertRaises(TypeError, delitem, {}, [])  
        self.assertRaises(SystemError, delitem, UserDict({'a': 1}), 'a')
        self.assertRaises(SystemError, delitem, [1], 0)
        self.assertRaises(SystemError, delitem, 42, 'a')
        
        

    def test_dict_delitemstring(self):
        delitemstring = _testcapi.dict_delitemstring
        dct = {'a': 1, 'c': 2, '\U0001f40d': 3}
        delitemstring(dct, b'a')
        self.assertEqual(dct, {'c': 2, '\U0001f40d': 3})
        self.assertRaises(KeyError, delitemstring, dct, b'b')
        delitemstring(dct, '\U0001f40d'.encode())
        self.assertEqual(dct, {'c': 2})

        dct2 = DictSubclass({'a': 1, 'c': 2})
        delitemstring(dct2, b'a')
        self.assertEqual(dct2, {'c': 2})
        self.assertRaises(KeyError, delitemstring, dct2, b'b')

        self.assertRaises(UnicodeDecodeError, delitemstring, {}, INVALID_UTF8)
        self.assertRaises(SystemError, delitemstring, UserDict({'a': 1}), b'a')
        self.assertRaises(SystemError, delitemstring, 42, b'a')
        
        

    def test_dict_setdefault(self):
        setdefault = _testcapi.dict_setdefault
        dct = {}
        self.assertEqual(setdefault(dct, 'a', 5), 5)
        self.assertEqual(dct, {'a': 5})
        self.assertEqual(setdefault(dct, 'a', 8), 5)
        self.assertEqual(dct, {'a': 5})

        dct2 = DictSubclass()
        self.assertEqual(setdefault(dct2, 'a', 5), 5)
        self.assertEqual(dct2, {'a': 5})
        self.assertEqual(setdefault(dct2, 'a', 8), 5)
        self.assertEqual(dct2, {'a': 5})

        self.assertRaises(TypeError, setdefault, {}, [], 5)  
        self.assertRaises(SystemError, setdefault, UserDict(), 'a', 5)
        self.assertRaises(SystemError, setdefault, [1], 0, 5)
        self.assertRaises(SystemError, setdefault, 42, 'a', 5)
        
        
        

    def test_mapping_keys_valuesitems(self):
        class BadMapping(dict):
            def keys(self):
                return None
            def values(self):
                return None
            def items(self):
                return None
        dict_obj = {'foo': 1, 'bar': 2, 'spam': 3}
        for mapping in [dict_obj, DictSubclass(dict_obj), BadMapping(dict_obj)]:
            self.assertListEqual(_testcapi.dict_keys(mapping),
                                 list(dict_obj.keys()))
            self.assertListEqual(_testcapi.dict_values(mapping),
                                 list(dict_obj.values()))
            self.assertListEqual(_testcapi.dict_items(mapping),
                                 list(dict_obj.items()))

    def test_dict_keys_valuesitems_bad_arg(self):
        for mapping in UserDict(), [], object():
            self.assertRaises(SystemError, _testcapi.dict_keys, mapping)
            self.assertRaises(SystemError, _testcapi.dict_values, mapping)
            self.assertRaises(SystemError, _testcapi.dict_items, mapping)

    def test_dict_next(self):
        dict_next = _testcapi.dict_next
        self.assertIsNone(dict_next({}, 0))
        dct = {'a': 1, 'b': 2, 'c': 3}
        pos = 0
        pairs = []
        while True:
            res = dict_next(dct, pos)
            if res is None:
                break
            rc, pos, key, value = res
            self.assertEqual(rc, 1)
            pairs.append((key, value))
        self.assertEqual(pairs, list(dct.items()))

        

    def test_dict_update(self):
        update = _testcapi.dict_update
        for cls1 in dict, DictSubclass:
            for cls2 in dict, DictSubclass, UserDict:
                dct = cls1({'a': 1, 'b': 2})
                update(dct, cls2({'b': 3, 'c': 4}))
                self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})

        self.assertRaises(AttributeError, update, {}, [])
        self.assertRaises(AttributeError, update, {}, 42)
        self.assertRaises(SystemError, update, UserDict(), {})
        self.assertRaises(SystemError, update, 42, {})
        self.assertRaises(SystemError, update, {}, NULL)
        self.assertRaises(SystemError, update, NULL, {})

    def test_dict_merge(self):
        merge = _testcapi.dict_merge
        for cls1 in dict, DictSubclass:
            for cls2 in dict, DictSubclass, UserDict:
                dct = cls1({'a': 1, 'b': 2})
                merge(dct, cls2({'b': 3, 'c': 4}), 0)
                self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4})
                dct = cls1({'a': 1, 'b': 2})
                merge(dct, cls2({'b': 3, 'c': 4}), 1)
                self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})

        self.assertRaises(AttributeError, merge, {}, [], 0)
        self.assertRaises(AttributeError, merge, {}, 42, 0)
        self.assertRaises(SystemError, merge, UserDict(), {}, 0)
        self.assertRaises(SystemError, merge, 42, {}, 0)
        self.assertRaises(SystemError, merge, {}, NULL, 0)
        self.assertRaises(SystemError, merge, NULL, {}, 0)

    def test_dict_mergefromseq2(self):
        mergefromseq2 = _testcapi.dict_mergefromseq2
        for cls1 in dict, DictSubclass:
            for cls2 in list, iter:
                dct = cls1({'a': 1, 'b': 2})
                mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 0)
                self.assertEqual(dct, {'a': 1, 'b': 2, 'c': 4})
                dct = cls1({'a': 1, 'b': 2})
                mergefromseq2(dct, cls2([('b', 3), ('c', 4)]), 1)
                self.assertEqual(dct, {'a': 1, 'b': 3, 'c': 4})

        self.assertRaises(ValueError, mergefromseq2, {}, [(1,)], 0)
        self.assertRaises(ValueError, mergefromseq2, {}, [(1, 2, 3)], 0)
        self.assertRaises(TypeError, mergefromseq2, {}, [1], 0)
        self.assertRaises(TypeError, mergefromseq2, {}, 42, 0)
        
        
        
        

    def test_dict_pop(self):
        
        dict_pop = _testcapi.dict_pop
        dict_pop_null = _testcapi.dict_pop_null

        
        mydict = {"key": "value", "key2": "value2"}
        self.assertEqual(dict_pop(mydict, "key"), (1, "value"))
        self.assertEqual(mydict, {"key2": "value2"})
        self.assertEqual(dict_pop(mydict, "key2"), (1, "value2"))
        self.assertEqual(mydict, {})

        
        mydict = {"key": "value", "key2": "value2"}
        self.assertEqual(dict_pop_null(mydict, "key"), 1)
        self.assertEqual(mydict, {"key2": "value2"})
        self.assertEqual(dict_pop_null(mydict, "key2"), 1)
        self.assertEqual(mydict, {})

        
        self.assertEqual(dict_pop({}, "key"), (0, NULL))
        self.assertEqual(dict_pop({"a": 1}, "key"), (0, NULL))

        
        self.assertEqual(dict_pop_null({}, "key"), 0)
        self.assertEqual(dict_pop_null({"a": 1}, "key"), 0)

        
        not_dict = UserDict({1: 2})
        self.assertRaises(SystemError, dict_pop, not_dict, "key")
        self.assertRaises(SystemError, dict_pop_null, not_dict, "key")

        
        not_hashable_key = ["list"]
        self.assertEqual(dict_pop({}, not_hashable_key), (0, NULL))
        with self.assertRaises(TypeError):
            dict_pop({'key': 1}, not_hashable_key)
        dict_pop({}, NULL)  

        
        

    def test_dict_popstring(self):
        
        dict_popstring = _testcapi.dict_popstring
        dict_popstring_null = _testcapi.dict_popstring_null

        
        mydict = {"key": "value", "key2": "value2"}
        self.assertEqual(dict_popstring(mydict, "key"), (1, "value"))
        self.assertEqual(mydict, {"key2": "value2"})
        self.assertEqual(dict_popstring(mydict, "key2"), (1, "value2"))
        self.assertEqual(mydict, {})

        
        mydict = {"key": "value", "key2": "value2"}
        self.assertEqual(dict_popstring_null(mydict, "key"), 1)
        self.assertEqual(mydict, {"key2": "value2"})
        self.assertEqual(dict_popstring_null(mydict, "key2"), 1)
        self.assertEqual(mydict, {})

        
        self.assertEqual(dict_popstring({}, "key"), (0, NULL))
        self.assertEqual(dict_popstring_null({}, "key"), 0)
        self.assertEqual(dict_popstring({"a": 1}, "key"), (0, NULL))
        self.assertEqual(dict_popstring_null({"a": 1}, "key"), 0)

        
        non_ascii = '\U0001f40d'
        dct = {'\U0001f40d': 123}
        self.assertEqual(dict_popstring(dct, '\U0001f40d'.encode()), (1, 123))
        dct = {'\U0001f40d': 123}
        self.assertEqual(dict_popstring_null(dct, '\U0001f40d'.encode()), 1)

        
        not_dict = UserDict({1: 2})
        self.assertRaises(SystemError, dict_popstring, not_dict, "key")
        self.assertRaises(SystemError, dict_popstring_null, not_dict, "key")

        
        self.assertRaises(UnicodeDecodeError, dict_popstring, {1: 2}, INVALID_UTF8)
        self.assertRaises(UnicodeDecodeError, dict_popstring_null, {1: 2}, INVALID_UTF8)

        
        
        


if __name__ == "__main__":
    unittest.main()