mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-15 09:19:49 +00:00
171 lines
6.1 KiB
Python
171 lines
6.1 KiB
Python
"""
|
|
Tests for allmydata.util.dictutil.
|
|
|
|
Ported to Python 3.
|
|
"""
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
from future.utils import PY2, PY3
|
|
if PY2:
|
|
# dict omitted to match dictutil.py.
|
|
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, list, object, range, str, max, min # noqa: F401
|
|
|
|
from unittest import skipIf
|
|
|
|
from twisted.trial import unittest
|
|
|
|
from allmydata.util import dictutil
|
|
|
|
|
|
class DictUtil(unittest.TestCase):
|
|
def test_dict_of_sets(self):
|
|
ds = dictutil.DictOfSets()
|
|
ds.add(1, "a")
|
|
ds.add(2, "b")
|
|
ds.add(2, "b")
|
|
ds.add(2, "c")
|
|
self.failUnlessEqual(ds[1], set(["a"]))
|
|
self.failUnlessEqual(ds[2], set(["b", "c"]))
|
|
ds.discard(3, "d") # should not raise an exception
|
|
ds.discard(2, "b")
|
|
self.failUnlessEqual(ds[2], set(["c"]))
|
|
ds.discard(2, "c")
|
|
self.failIf(2 in ds)
|
|
|
|
ds.add(3, "f")
|
|
ds2 = dictutil.DictOfSets()
|
|
ds2.add(3, "f")
|
|
ds2.add(3, "g")
|
|
ds2.add(4, "h")
|
|
ds.update(ds2)
|
|
self.failUnlessEqual(ds[1], set(["a"]))
|
|
self.failUnlessEqual(ds[3], set(["f", "g"]))
|
|
self.failUnlessEqual(ds[4], set(["h"]))
|
|
|
|
def test_auxdict(self):
|
|
d = dictutil.AuxValueDict()
|
|
# we put the serialized form in the auxdata
|
|
d.set_with_aux("key", ("filecap", "metadata"), "serialized")
|
|
|
|
self.failUnlessEqual(list(d.keys()), ["key"])
|
|
self.failUnlessEqual(d["key"], ("filecap", "metadata"))
|
|
self.failUnlessEqual(d.get_aux("key"), "serialized")
|
|
def _get_missing(key):
|
|
return d[key]
|
|
self.failUnlessRaises(KeyError, _get_missing, "nonkey")
|
|
self.failUnlessEqual(d.get("nonkey"), None)
|
|
self.failUnlessEqual(d.get("nonkey", "nonvalue"), "nonvalue")
|
|
self.failUnlessEqual(d.get_aux("nonkey"), None)
|
|
self.failUnlessEqual(d.get_aux("nonkey", "nonvalue"), "nonvalue")
|
|
|
|
d["key"] = ("filecap2", "metadata2")
|
|
self.failUnlessEqual(d["key"], ("filecap2", "metadata2"))
|
|
self.failUnlessEqual(d.get_aux("key"), None)
|
|
|
|
d.set_with_aux("key2", "value2", "aux2")
|
|
self.failUnlessEqual(sorted(d.keys()), ["key", "key2"])
|
|
del d["key2"]
|
|
self.failUnlessEqual(list(d.keys()), ["key"])
|
|
self.failIf("key2" in d)
|
|
self.failUnlessRaises(KeyError, _get_missing, "key2")
|
|
self.failUnlessEqual(d.get("key2"), None)
|
|
self.failUnlessEqual(d.get_aux("key2"), None)
|
|
d["key2"] = "newvalue2"
|
|
self.failUnlessEqual(d.get("key2"), "newvalue2")
|
|
self.failUnlessEqual(d.get_aux("key2"), None)
|
|
|
|
d = dictutil.AuxValueDict({1:2,3:4})
|
|
self.failUnlessEqual(sorted(d.keys()), [1,3])
|
|
self.failUnlessEqual(d[1], 2)
|
|
self.failUnlessEqual(d.get_aux(1), None)
|
|
|
|
d = dictutil.AuxValueDict([ (1,2), (3,4) ])
|
|
self.failUnlessEqual(sorted(d.keys()), [1,3])
|
|
self.failUnlessEqual(d[1], 2)
|
|
self.failUnlessEqual(d.get_aux(1), None)
|
|
|
|
d = dictutil.AuxValueDict(one=1, two=2)
|
|
self.failUnlessEqual(sorted(d.keys()), ["one","two"])
|
|
self.failUnlessEqual(d["one"], 1)
|
|
self.failUnlessEqual(d.get_aux("one"), None)
|
|
|
|
|
|
class TypedKeyDict(unittest.TestCase):
|
|
"""Tests for dictionaries that limit keys."""
|
|
|
|
@skipIf(PY2, "Python 2 doesn't have issues mixing bytes and unicode.")
|
|
def setUp(self):
|
|
pass
|
|
|
|
def test_bytes(self):
|
|
"""BytesKeyDict is limited to just byte keys."""
|
|
self.assertRaises(TypeError, dictutil.BytesKeyDict, {u"hello": 123})
|
|
d = dictutil.BytesKeyDict({b"123": 200})
|
|
with self.assertRaises(TypeError):
|
|
d[u"hello"] = "blah"
|
|
with self.assertRaises(TypeError):
|
|
d[u"hello"]
|
|
with self.assertRaises(TypeError):
|
|
del d[u"hello"]
|
|
with self.assertRaises(TypeError):
|
|
d.setdefault(u"hello", "123")
|
|
with self.assertRaises(TypeError):
|
|
d.get(u"xcd")
|
|
|
|
# Byte keys are fine:
|
|
self.assertEqual(d, {b"123": 200})
|
|
d[b"456"] = 400
|
|
self.assertEqual(d[b"456"], 400)
|
|
del d[b"456"]
|
|
self.assertEqual(d.get(b"456", 50), 50)
|
|
self.assertEqual(d.setdefault(b"456", 300), 300)
|
|
self.assertEqual(d[b"456"], 300)
|
|
|
|
def test_unicode(self):
|
|
"""UnicodeKeyDict is limited to just unicode keys."""
|
|
self.assertRaises(TypeError, dictutil.UnicodeKeyDict, {b"hello": 123})
|
|
d = dictutil.UnicodeKeyDict({u"123": 200})
|
|
with self.assertRaises(TypeError):
|
|
d[b"hello"] = "blah"
|
|
with self.assertRaises(TypeError):
|
|
d[b"hello"]
|
|
with self.assertRaises(TypeError):
|
|
del d[b"hello"]
|
|
with self.assertRaises(TypeError):
|
|
d.setdefault(b"hello", "123")
|
|
with self.assertRaises(TypeError):
|
|
d.get(b"xcd")
|
|
|
|
# Byte keys are fine:
|
|
self.assertEqual(d, {u"123": 200})
|
|
d[u"456"] = 400
|
|
self.assertEqual(d[u"456"], 400)
|
|
del d[u"456"]
|
|
self.assertEqual(d.get(u"456", 50), 50)
|
|
self.assertEqual(d.setdefault(u"456", 300), 300)
|
|
self.assertEqual(d[u"456"], 300)
|
|
|
|
|
|
class TypedKeyDictPython2(unittest.TestCase):
|
|
"""Tests for dictionaries that limit keys on Python 2."""
|
|
|
|
@skipIf(PY3, "Testing Python 2 behavior.")
|
|
def test_python2(self):
|
|
"""
|
|
On Python2, BytesKeyDict and UnicodeKeyDict are unnecessary, because
|
|
dicts can mix both without problem so you don't get confusing behavior
|
|
if you get the type wrong.
|
|
|
|
Eventually in a Python 3-only world mixing bytes and unicode will be
|
|
bad, thus the existence of these classes, but as we port there will be
|
|
situations where it's mixed on Python 2, which again is fine.
|
|
"""
|
|
self.assertIs(dictutil.UnicodeKeyDict, dict)
|
|
self.assertIs(dictutil.BytesKeyDict, dict)
|
|
# Demonstration of how bytes and unicode can be mixed:
|
|
d = {u"abc": 1}
|
|
self.assertEqual(d[b"abc"], 1)
|