|
13 | 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | 14 | # See the License for the specific language governing permissions and |
15 | 15 | # limitations under the License. |
| 16 | +from unittest.mock import Mock |
16 | 17 |
|
17 | 18 | from math import inf, nan |
18 | 19 |
|
19 | 20 | from canonicaljson import ( |
20 | 21 | encode_canonical_json, |
21 | 22 | encode_pretty_printed_json, |
22 | | - frozendict_type, |
23 | 23 | iterencode_canonical_json, |
24 | 24 | iterencode_pretty_printed_json, |
25 | 25 | set_json_library, |
| 26 | + register_preserialisation_callback, |
26 | 27 | ) |
27 | 28 |
|
28 | 29 | import unittest |
@@ -107,22 +108,6 @@ def test_encode_pretty_printed(self) -> None: |
107 | 108 | b'{\n "la merde amus\xc3\xa9e": "\xF0\x9F\x92\xA9"\n}', |
108 | 109 | ) |
109 | 110 |
|
110 | | - @unittest.skipIf( |
111 | | - frozendict_type is None, |
112 | | - "If `frozendict` is not available, skip test", |
113 | | - ) |
114 | | - def test_frozen_dict(self) -> None: |
115 | | - # For mypy's benefit: |
116 | | - assert frozendict_type is not None |
117 | | - self.assertEqual( |
118 | | - encode_canonical_json(frozendict_type({"a": 1})), |
119 | | - b'{"a":1}', |
120 | | - ) |
121 | | - self.assertEqual( |
122 | | - encode_pretty_printed_json(frozendict_type({"a": 1})), |
123 | | - b'{\n "a": 1\n}', |
124 | | - ) |
125 | | - |
126 | 111 | def test_unknown_type(self) -> None: |
127 | 112 | class Unknown(object): |
128 | 113 | pass |
@@ -167,3 +152,46 @@ def test_set_json(self) -> None: |
167 | 152 | from canonicaljson import json # type: ignore[attr-defined] |
168 | 153 |
|
169 | 154 | set_json_library(json) |
| 155 | + |
| 156 | + def test_encode_unknown_class_raises(self) -> None: |
| 157 | + class C: |
| 158 | + pass |
| 159 | + |
| 160 | + with self.assertRaises(Exception): |
| 161 | + encode_canonical_json(C()) |
| 162 | + |
| 163 | + def test_preserialisation_callback(self) -> None: |
| 164 | + class C: |
| 165 | + pass |
| 166 | + |
| 167 | + # Naughty: this alters the global state of the module. However this |
| 168 | + # `C` class is limited to this test only, so this shouldn't affect |
| 169 | + # other types and other tests. |
| 170 | + register_preserialisation_callback(C, lambda c: "I am a C instance") |
| 171 | + |
| 172 | + result = encode_canonical_json(C()) |
| 173 | + self.assertEqual(result, b'"I am a C instance"') |
| 174 | + |
| 175 | + def test_cannot_register_preserialisation_callback_for_object(self) -> None: |
| 176 | + with self.assertRaises(Exception): |
| 177 | + register_preserialisation_callback( |
| 178 | + object, lambda c: "shouldn't be able to do this" |
| 179 | + ) |
| 180 | + |
| 181 | + def test_most_recent_preserialisation_callback_called(self) -> None: |
| 182 | + class C: |
| 183 | + pass |
| 184 | + |
| 185 | + callback1 = Mock(return_value="callback 1 was called") |
| 186 | + callback2 = Mock(return_value="callback 2 was called") |
| 187 | + |
| 188 | + # Naughty: this alters the global state of the module. However this |
| 189 | + # `C` class is limited to this test only, so this shouldn't affect |
| 190 | + # other types and other tests. |
| 191 | + register_preserialisation_callback(C, callback1) |
| 192 | + register_preserialisation_callback(C, callback2) |
| 193 | + |
| 194 | + encode_canonical_json(C()) |
| 195 | + |
| 196 | + callback1.assert_not_called() |
| 197 | + callback2.assert_called_once() |
0 commit comments