1 | """ |
---|
2 | Tests for allmydata.util.dictutil. |
---|
3 | """ |
---|
4 | from __future__ import annotations |
---|
5 | |
---|
6 | from twisted.trial import unittest |
---|
7 | |
---|
8 | from allmydata.util import dictutil |
---|
9 | |
---|
10 | |
---|
11 | class DictUtil(unittest.TestCase): |
---|
12 | def test_dict_of_sets(self): |
---|
13 | ds = dictutil.DictOfSets() |
---|
14 | ds.add(1, "a") |
---|
15 | ds.add(2, "b") |
---|
16 | ds.add(2, "b") |
---|
17 | ds.add(2, "c") |
---|
18 | self.failUnlessEqual(ds[1], set(["a"])) |
---|
19 | self.failUnlessEqual(ds[2], set(["b", "c"])) |
---|
20 | ds.discard(3, "d") # should not raise an exception |
---|
21 | ds.discard(2, "b") |
---|
22 | self.failUnlessEqual(ds[2], set(["c"])) |
---|
23 | ds.discard(2, "c") |
---|
24 | self.failIf(2 in ds) |
---|
25 | |
---|
26 | ds.add(3, "f") |
---|
27 | ds2 = dictutil.DictOfSets() |
---|
28 | ds2.add(3, "f") |
---|
29 | ds2.add(3, "g") |
---|
30 | ds2.add(4, "h") |
---|
31 | ds.update(ds2) |
---|
32 | self.failUnlessEqual(ds[1], set(["a"])) |
---|
33 | self.failUnlessEqual(ds[3], set(["f", "g"])) |
---|
34 | self.failUnlessEqual(ds[4], set(["h"])) |
---|
35 | |
---|
36 | def test_auxdict(self): |
---|
37 | d = dictutil.AuxValueDict() |
---|
38 | # we put the serialized form in the auxdata |
---|
39 | d.set_with_aux("key", ("filecap", "metadata"), "serialized") |
---|
40 | |
---|
41 | self.failUnlessEqual(list(d.keys()), ["key"]) |
---|
42 | self.failUnlessEqual(d["key"], ("filecap", "metadata")) |
---|
43 | self.failUnlessEqual(d.get_aux("key"), "serialized") |
---|
44 | def _get_missing(key): |
---|
45 | return d[key] |
---|
46 | self.failUnlessRaises(KeyError, _get_missing, "nonkey") |
---|
47 | self.failUnlessEqual(d.get("nonkey"), None) |
---|
48 | self.failUnlessEqual(d.get("nonkey", "nonvalue"), "nonvalue") |
---|
49 | self.failUnlessEqual(d.get_aux("nonkey"), None) |
---|
50 | self.failUnlessEqual(d.get_aux("nonkey", "nonvalue"), "nonvalue") |
---|
51 | |
---|
52 | d["key"] = ("filecap2", "metadata2") |
---|
53 | self.failUnlessEqual(d["key"], ("filecap2", "metadata2")) |
---|
54 | self.failUnlessEqual(d.get_aux("key"), None) |
---|
55 | |
---|
56 | d.set_with_aux("key2", "value2", "aux2") |
---|
57 | self.failUnlessEqual(sorted(d.keys()), ["key", "key2"]) |
---|
58 | del d["key2"] |
---|
59 | self.failUnlessEqual(list(d.keys()), ["key"]) |
---|
60 | self.failIf("key2" in d) |
---|
61 | self.failUnlessRaises(KeyError, _get_missing, "key2") |
---|
62 | self.failUnlessEqual(d.get("key2"), None) |
---|
63 | self.failUnlessEqual(d.get_aux("key2"), None) |
---|
64 | d["key2"] = "newvalue2" |
---|
65 | self.failUnlessEqual(d.get("key2"), "newvalue2") |
---|
66 | self.failUnlessEqual(d.get_aux("key2"), None) |
---|
67 | |
---|
68 | d = dictutil.AuxValueDict({1:2,3:4}) |
---|
69 | self.failUnlessEqual(sorted(d.keys()), [1,3]) |
---|
70 | self.failUnlessEqual(d[1], 2) |
---|
71 | self.failUnlessEqual(d.get_aux(1), None) |
---|
72 | |
---|
73 | d = dictutil.AuxValueDict([ (1,2), (3,4) ]) |
---|
74 | self.failUnlessEqual(sorted(d.keys()), [1,3]) |
---|
75 | self.failUnlessEqual(d[1], 2) |
---|
76 | self.failUnlessEqual(d.get_aux(1), None) |
---|
77 | |
---|
78 | d = dictutil.AuxValueDict(one=1, two=2) |
---|
79 | self.failUnlessEqual(sorted(d.keys()), ["one","two"]) |
---|
80 | self.failUnlessEqual(d["one"], 1) |
---|
81 | self.failUnlessEqual(d.get_aux("one"), None) |
---|
82 | |
---|
83 | |
---|
84 | class TypedKeyDict(unittest.TestCase): |
---|
85 | """Tests for dictionaries that limit keys.""" |
---|
86 | |
---|
87 | def setUp(self): |
---|
88 | pass |
---|
89 | |
---|
90 | def test_bytes(self): |
---|
91 | """BytesKeyDict is limited to just byte keys.""" |
---|
92 | self.assertRaises(TypeError, dictutil.BytesKeyDict, {u"hello": 123}) |
---|
93 | d = dictutil.BytesKeyDict({b"123": 200}) |
---|
94 | with self.assertRaises(TypeError): |
---|
95 | d[u"hello"] = "blah" |
---|
96 | with self.assertRaises(TypeError): |
---|
97 | d[u"hello"] |
---|
98 | with self.assertRaises(TypeError): |
---|
99 | del d[u"hello"] |
---|
100 | with self.assertRaises(TypeError): |
---|
101 | d.setdefault(u"hello", "123") |
---|
102 | with self.assertRaises(TypeError): |
---|
103 | d.get(u"xcd") |
---|
104 | |
---|
105 | # Byte keys are fine: |
---|
106 | self.assertEqual(d, {b"123": 200}) |
---|
107 | d[b"456"] = 400 |
---|
108 | self.assertEqual(d[b"456"], 400) |
---|
109 | del d[b"456"] |
---|
110 | self.assertEqual(d.get(b"456", 50), 50) |
---|
111 | self.assertEqual(d.setdefault(b"456", 300), 300) |
---|
112 | self.assertEqual(d[b"456"], 300) |
---|
113 | |
---|
114 | def test_unicode(self): |
---|
115 | """UnicodeKeyDict is limited to just unicode keys.""" |
---|
116 | self.assertRaises(TypeError, dictutil.UnicodeKeyDict, {b"hello": 123}) |
---|
117 | d = dictutil.UnicodeKeyDict({u"123": 200}) |
---|
118 | with self.assertRaises(TypeError): |
---|
119 | d[b"hello"] = "blah" |
---|
120 | with self.assertRaises(TypeError): |
---|
121 | d[b"hello"] |
---|
122 | with self.assertRaises(TypeError): |
---|
123 | del d[b"hello"] |
---|
124 | with self.assertRaises(TypeError): |
---|
125 | d.setdefault(b"hello", "123") |
---|
126 | with self.assertRaises(TypeError): |
---|
127 | d.get(b"xcd") |
---|
128 | |
---|
129 | # Byte keys are fine: |
---|
130 | self.assertEqual(d, {u"123": 200}) |
---|
131 | d[u"456"] = 400 |
---|
132 | self.assertEqual(d[u"456"], 400) |
---|
133 | del d[u"456"] |
---|
134 | self.assertEqual(d.get(u"456", 50), 50) |
---|
135 | self.assertEqual(d.setdefault(u"456", 300), 300) |
---|
136 | self.assertEqual(d[u"456"], 300) |
---|
137 | |
---|
138 | |
---|
139 | class FilterTests(unittest.TestCase): |
---|
140 | """ |
---|
141 | Tests for ``dictutil.filter``. |
---|
142 | """ |
---|
143 | def test_filter(self) -> None: |
---|
144 | """ |
---|
145 | ``dictutil.filter`` returns a ``dict`` that contains the key/value |
---|
146 | pairs for which the value is matched by the given predicate. |
---|
147 | """ |
---|
148 | self.assertEqual( |
---|
149 | {1: 2}, |
---|
150 | dictutil.filter(lambda v: v == 2, {1: 2, 2: 3}), |
---|
151 | ) |
---|