| 107 | |
| 108 | |
| 109 | def create_test(case_spec): |
| 110 | bson_type = case_spec["bson_type"] |
| 111 | # Test key is absent when testing top-level documents. |
| 112 | test_key = case_spec.get("test_key") |
| 113 | deprecated = case_spec.get("deprecated") |
| 114 | |
| 115 | def run_test(self): |
| 116 | for valid_case in case_spec.get("valid", []): |
| 117 | description = valid_case["description"] |
| 118 | if description in _TESTS_TO_SKIP: |
| 119 | continue |
| 120 | |
| 121 | # Special case for testing encoding UUID as binary subtype 0x04. |
| 122 | if description.startswith("subtype 0x04"): |
| 123 | encode_extjson = to_extjson_uuid_04 |
| 124 | encode_bson = to_bson_uuid_04 |
| 125 | else: |
| 126 | encode_extjson = to_extjson |
| 127 | encode_bson = to_bson |
| 128 | |
| 129 | cB = binascii.unhexlify(valid_case["canonical_bson"].encode("utf8")) |
| 130 | cEJ = valid_case["canonical_extjson"] |
| 131 | rEJ = valid_case.get("relaxed_extjson") |
| 132 | dEJ = valid_case.get("degenerate_extjson") |
| 133 | if description in _IMPLCIT_LOSSY_TESTS: |
| 134 | valid_case.setdefault("lossy", True) |
| 135 | lossy = valid_case.get("lossy") |
| 136 | |
| 137 | # BSON double, use lowercase 'e+' to match Python's encoding |
| 138 | if bson_type == "0x01": |
| 139 | cEJ = cEJ.replace("E+", "e+") |
| 140 | |
| 141 | decoded_bson = decode_bson(cB) |
| 142 | |
| 143 | if not lossy: |
| 144 | # Make sure we can parse the legacy (default) JSON format. |
| 145 | legacy_json = json_util.dumps( |
| 146 | decoded_bson, json_options=json_util.LEGACY_JSON_OPTIONS |
| 147 | ) |
| 148 | self.assertEqual(decode_extjson(legacy_json), decoded_bson, description) |
| 149 | |
| 150 | if deprecated: |
| 151 | if "converted_bson" in valid_case: |
| 152 | converted_bson = binascii.unhexlify(valid_case["converted_bson"].encode("utf8")) |
| 153 | self.assertEqual(encode_bson(decoded_bson), converted_bson) |
| 154 | self.assertJsonEqual( |
| 155 | encode_extjson(decode_bson(converted_bson)), valid_case["converted_extjson"] |
| 156 | ) |
| 157 | # Make sure we can decode the type. |
| 158 | self.assertEqual(decoded_bson, decode_extjson(cEJ)) |
| 159 | if test_key is not None: |
| 160 | self.assertIsInstance(decoded_bson[test_key], _DEPRECATED_BSON_TYPES[bson_type]) |
| 161 | continue |
| 162 | |
| 163 | self.assertJsonEqual(encode_extjson(decoded_bson), cEJ) |
| 164 | |
| 165 | # Test round-tripping canonical extended json. |
| 166 | decoded_json = decode_extjson(cEJ) |