import decimal import json import math import sys import unittest import pytest from io import StringIO from pathlib import Path from srsly import ujson json_unicode = json.dumps class UltraJSONTests(unittest.TestCase): def test_encodeDecimal(self): sut = decimal.Decimal("1337.1337") encoded = ujson.encode(sut) decoded = ujson.decode(encoded) self.assertEqual(decoded, 1337.1337) def test_encodeStringConversion(self): input = "A string \\ / \b \f \n \r \t &" not_html_encoded = '"A string \\\\ \\/ \\b \\f \\n \\r \\t <\\/script> &"' html_encoded = ( '"A string \\\\ \\/ \\b \\f \\n \\r \\t \\u003c\\/script\\u003e \\u0026"' ) not_slashes_escaped = '"A string \\\\ / \\b \\f \\n \\r \\t &"' def helper(expected_output, **encode_kwargs): output = ujson.encode(input, **encode_kwargs) self.assertEqual(output, expected_output) if encode_kwargs.get("escape_forward_slashes", True): self.assertEqual(input, json.loads(output)) self.assertEqual(input, ujson.decode(output)) # Default behavior assumes encode_html_chars=False. helper(not_html_encoded, ensure_ascii=True) helper(not_html_encoded, ensure_ascii=False) # Make sure explicit encode_html_chars=False works. helper(not_html_encoded, ensure_ascii=True, encode_html_chars=False) helper(not_html_encoded, ensure_ascii=False, encode_html_chars=False) # Make sure explicit encode_html_chars=True does the encoding. helper(html_encoded, ensure_ascii=True, encode_html_chars=True) helper(html_encoded, ensure_ascii=False, encode_html_chars=True) # Do escape forward slashes if disabled. helper(not_slashes_escaped, escape_forward_slashes=False) def testWriteEscapedString(self): self.assertEqual( "\"\\u003cimg src='\\u0026amp;'\\/\\u003e\"", ujson.dumps("", encode_html_chars=True), ) def test_doubleLongIssue(self): sut = {"a": -4342969734183514} encoded = json.dumps(sut) decoded = json.loads(encoded) self.assertEqual(sut, decoded) encoded = ujson.encode(sut) decoded = ujson.decode(encoded) self.assertEqual(sut, decoded) def test_doubleLongDecimalIssue(self): sut = {"a": -12345678901234.56789012} encoded = json.dumps(sut) decoded = json.loads(encoded) self.assertEqual(sut, decoded) encoded = ujson.encode(sut) decoded = ujson.decode(encoded) self.assertEqual(sut, decoded) def test_encodeDecodeLongDecimal(self): sut = {"a": -528656961.4399388} encoded = ujson.dumps(sut) ujson.decode(encoded) def test_decimalDecodeTest(self): sut = {"a": 4.56} encoded = ujson.encode(sut) decoded = ujson.decode(encoded) self.assertAlmostEqual(sut[u"a"], decoded[u"a"]) def test_encodeDictWithUnicodeKeys(self): input = { "key1": "value1", "key1": "value1", "key1": "value1", "key1": "value1", "key1": "value1", "key1": "value1", } ujson.encode(input) input = { "بن": "value1", "بن": "value1", "بن": "value1", "بن": "value1", "بن": "value1", "بن": "value1", "بن": "value1", } ujson.encode(input) def test_encodeDoubleConversion(self): input = math.pi output = ujson.encode(input) self.assertEqual(round(input, 5), round(json.loads(output), 5)) self.assertEqual(round(input, 5), round(ujson.decode(output), 5)) def test_encodeWithDecimal(self): input = 1.0 output = ujson.encode(input) self.assertEqual(output, "1.0") def test_encodeDoubleNegConversion(self): input = -math.pi output = ujson.encode(input) self.assertEqual(round(input, 5), round(json.loads(output), 5)) self.assertEqual(round(input, 5), round(ujson.decode(output), 5)) def test_encodeArrayOfNestedArrays(self): input = [[[[]]]] * 20 output = ujson.encode(input) self.assertEqual(input, json.loads(output)) # self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeArrayOfDoubles(self): input = [31337.31337, 31337.31337, 31337.31337, 31337.31337] * 10 output = ujson.encode(input) self.assertEqual(input, json.loads(output)) # self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeStringConversion2(self): input = "A string \\ / \b \f \n \r \t" output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, '"A string \\\\ \\/ \\b \\f \\n \\r \\t"') self.assertEqual(input, ujson.decode(output)) def test_decodeUnicodeConversion(self): pass def test_encodeUnicodeConversion1(self): input = "Räksmörgås اسامة بن محمد بن عوض بن لادن" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEqual(enc, json_unicode(input)) self.assertEqual(dec, json.loads(enc)) def test_encodeControlEscaping(self): input = "\x19" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEqual(input, dec) self.assertEqual(enc, json_unicode(input)) def test_encodeUnicodeConversion2(self): input = "\xe6\x97\xa5\xd1\x88" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEqual(enc, json_unicode(input)) self.assertEqual(dec, json.loads(enc)) def test_encodeUnicodeSurrogatePair(self): input = "\xf0\x90\x8d\x86" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEqual(enc, json_unicode(input)) self.assertEqual(dec, json.loads(enc)) def test_encodeUnicode4BytesUTF8(self): input = "\xf0\x91\x80\xb0TRAILINGNORMAL" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEqual(enc, json_unicode(input)) self.assertEqual(dec, json.loads(enc)) def test_encodeUnicode4BytesUTF8Highest(self): input = "\xf3\xbf\xbf\xbfTRAILINGNORMAL" enc = ujson.encode(input) dec = ujson.decode(enc) self.assertEqual(enc, json_unicode(input)) self.assertEqual(dec, json.loads(enc)) # Characters outside of Basic Multilingual Plane(larger than # 16 bits) are represented as \UXXXXXXXX in python but should be encoded # as \uXXXX\uXXXX in json. def testEncodeUnicodeBMP(self): s = "\U0001f42e\U0001f42e\U0001F42D\U0001F42D" # 🐮🐮🐭🐭 encoded = ujson.dumps(s) encoded_json = json.dumps(s) if len(s) == 4: self.assertEqual(len(encoded), len(s) * 12 + 2) else: self.assertEqual(len(encoded), len(s) * 6 + 2) self.assertEqual(encoded, encoded_json) decoded = ujson.loads(encoded) self.assertEqual(s, decoded) # ujson outputs an UTF-8 encoded str object encoded = ujson.dumps(s, ensure_ascii=False) # json outputs an unicode object encoded_json = json.dumps(s, ensure_ascii=False) self.assertEqual(len(encoded), len(s) + 2) # original length + quotes self.assertEqual(encoded, encoded_json) decoded = ujson.loads(encoded) self.assertEqual(s, decoded) def testEncodeSymbols(self): s = "\u273f\u2661\u273f" # ✿♡✿ encoded = ujson.dumps(s) encoded_json = json.dumps(s) self.assertEqual(len(encoded), len(s) * 6 + 2) # 6 characters + quotes self.assertEqual(encoded, encoded_json) decoded = ujson.loads(encoded) self.assertEqual(s, decoded) # ujson outputs an UTF-8 encoded str object encoded = ujson.dumps(s, ensure_ascii=False) # json outputs an unicode object encoded_json = json.dumps(s, ensure_ascii=False) self.assertEqual(len(encoded), len(s) + 2) # original length + quotes self.assertEqual(encoded, encoded_json) decoded = ujson.loads(encoded) self.assertEqual(s, decoded) def test_encodeArrayInArray(self): input = [[[[]]]] output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeIntConversion(self): input = 31337 output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeIntNegConversion(self): input = -31337 output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeLongNegConversion(self): input = -9223372036854775808 output = ujson.encode(input) json.loads(output) ujson.decode(output) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeListConversion(self): input = [1, 2, 3, 4] output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(input, ujson.decode(output)) def test_encodeDictConversion(self): input = {"k1": 1, "k2": 2, "k3": 3, "k4": 4} output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(input, ujson.decode(output)) self.assertEqual(input, ujson.decode(output)) def test_encodeNoneConversion(self): input = None output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeTrueConversion(self): input = True output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeFalseConversion(self): input = False output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeToUTF8(self): input = b"\xe6\x97\xa5\xd1\x88" input = input.decode("utf-8") enc = ujson.encode(input, ensure_ascii=False) dec = ujson.decode(enc) self.assertEqual(enc, json.dumps(input, ensure_ascii=False)) self.assertEqual(dec, json.loads(enc)) def test_decodeFromUnicode(self): input = '{"obj": 31337}' dec1 = ujson.decode(input) dec2 = ujson.decode(str(input)) self.assertEqual(dec1, dec2) def test_encodeRecursionMax(self): # 8 is the max recursion depth class O2: member = 0 def toDict(self): return {"member": self.member} class O1: member = 0 def toDict(self): return {"member": self.member} input = O1() input.member = O2() input.member.member = input self.assertRaises(OverflowError, ujson.encode, input) def test_encodeDoubleNan(self): input = float("nan") self.assertRaises(OverflowError, ujson.encode, input) def test_encodeDoubleInf(self): input = float("inf") self.assertRaises(OverflowError, ujson.encode, input) def test_encodeDoubleNegInf(self): input = -float("inf") self.assertRaises(OverflowError, ujson.encode, input) def test_encodeOrderedDict(self): from collections import OrderedDict input = OrderedDict([(1, 1), (0, 0), (8, 8), (2, 2)]) self.assertEqual('{"1":1,"0":0,"8":8,"2":2}', ujson.encode(input)) def test_decodeJibberish(self): input = "fdsa sda v9sa fdsa" self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenArrayStart(self): input = "[" self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenObjectStart(self): input = "{" self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenArrayEnd(self): input = "]" self.assertRaises(ValueError, ujson.decode, input) def test_decodeArrayDepthTooBig(self): input = "[" * (1024 * 1024) self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenObjectEnd(self): input = "}" self.assertRaises(ValueError, ujson.decode, input) def test_decodeObjectTrailingCommaFail(self): input = '{"one":1,}' self.assertRaises(ValueError, ujson.decode, input) def test_decodeObjectDepthTooBig(self): input = "{" * (1024 * 1024) self.assertRaises(ValueError, ujson.decode, input) def test_decodeStringUnterminated(self): input = '"TESTING' self.assertRaises(ValueError, ujson.decode, input) def test_decodeStringUntermEscapeSequence(self): input = '"TESTING\\"' self.assertRaises(ValueError, ujson.decode, input) def test_decodeStringBadEscape(self): input = '"TESTING\\"' self.assertRaises(ValueError, ujson.decode, input) def test_decodeTrueBroken(self): input = "tru" self.assertRaises(ValueError, ujson.decode, input) def test_decodeFalseBroken(self): input = "fa" self.assertRaises(ValueError, ujson.decode, input) def test_decodeNullBroken(self): input = "n" self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenDictKeyTypeLeakTest(self): input = '{{1337:""}}' for x in range(1000): self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenDictLeakTest(self): input = '{{"key":"}' for x in range(1000): self.assertRaises(ValueError, ujson.decode, input) def test_decodeBrokenListLeakTest(self): input = "[[[true" for x in range(1000): self.assertRaises(ValueError, ujson.decode, input) def test_decodeDictWithNoKey(self): input = "{{{{31337}}}}" self.assertRaises(ValueError, ujson.decode, input) def test_decodeDictWithNoColonOrValue(self): input = '{{{{"key"}}}}' self.assertRaises(ValueError, ujson.decode, input) def test_decodeDictWithNoValue(self): input = '{{{{"key":}}}}' self.assertRaises(ValueError, ujson.decode, input) def test_decodeNumericIntPos(self): input = "31337" self.assertEqual(31337, ujson.decode(input)) def test_decodeNumericIntNeg(self): input = "-31337" self.assertEqual(-31337, ujson.decode(input)) def test_encodeUnicode4BytesUTF8Fail(self): input = b"\xfd\xbf\xbf\xbf\xbf\xbf" self.assertRaises(OverflowError, ujson.encode, input) def test_encodeNullCharacter(self): input = "31337 \x00 1337" output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) input = "\x00" output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) self.assertEqual('" \\u0000\\r\\n "', ujson.dumps(" \u0000\r\n ")) def test_decodeNullCharacter(self): input = '"31337 \\u0000 31337"' self.assertEqual(ujson.decode(input), json.loads(input)) def test_encodeListLongConversion(self): input = [ 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, 9223372036854775807, ] output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(input, ujson.decode(output)) def test_encodeListLongUnsignedConversion(self): input = [18446744073709551615, 18446744073709551615, 18446744073709551615] output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(input, ujson.decode(output)) def test_encodeLongConversion(self): input = 9223372036854775807 output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_encodeLongUnsignedConversion(self): input = 18446744073709551615 output = ujson.encode(input) self.assertEqual(input, json.loads(output)) self.assertEqual(output, json.dumps(input)) self.assertEqual(input, ujson.decode(output)) def test_numericIntExp(self): input = "1337E40" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_numericIntFrcExp(self): input = "1.337E40" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_decodeNumericIntExpEPLUS(self): input = "1337E+9" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_decodeNumericIntExpePLUS(self): input = "1.337e+40" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_decodeNumericIntExpE(self): input = "1337E40" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_decodeNumericIntExpe(self): input = "1337e40" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_decodeNumericIntExpEMinus(self): input = "1.337E-4" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_decodeNumericIntExpeMinus(self): input = "1.337e-4" output = ujson.decode(input) self.assertEqual(output, json.loads(input)) def test_dumpToFile(self): f = StringIO() ujson.dump([1, 2, 3], f) self.assertEqual("[1,2,3]", f.getvalue()) def test_dumpToFileLikeObject(self): class filelike: def __init__(self): self.bytes = "" def write(self, bytes): self.bytes += bytes f = filelike() ujson.dump([1, 2, 3], f) self.assertEqual("[1,2,3]", f.bytes) def test_dumpFileArgsError(self): self.assertRaises(TypeError, ujson.dump, [], "") def test_loadFile(self): f = StringIO("[1,2,3,4]") self.assertEqual([1, 2, 3, 4], ujson.load(f)) def test_loadFileLikeObject(self): class filelike: def read(self): try: self.end except AttributeError: self.end = True return "[1,2,3,4]" f = filelike() self.assertEqual([1, 2, 3, 4], ujson.load(f)) def test_loadFileArgsError(self): self.assertRaises(TypeError, ujson.load, "[]") def test_encodeNumericOverflow(self): self.assertRaises(OverflowError, ujson.encode, 12839128391289382193812939) def test_decodeNumberWith32bitSignBit(self): # Test that numbers that fit within 32 bits but would have the # sign bit set (2**31 <= x < 2**32) are decoded properly. docs = ( '{"id": 3590016419}', '{"id": %s}' % 2 ** 31, '{"id": %s}' % 2 ** 32, '{"id": %s}' % ((2 ** 32) - 1), ) results = (3590016419, 2 ** 31, 2 ** 32, 2 ** 32 - 1) for doc, result in zip(docs, results): self.assertEqual(ujson.decode(doc)["id"], result) def test_encodeBigEscape(self): for x in range(10): base = "\u00e5".encode("utf-8") input = base * 1024 * 1024 * 2 ujson.encode(input) def test_decodeBigEscape(self): for x in range(10): base = "\u00e5".encode("utf-8") quote = '"'.encode() input = quote + (base * 1024 * 1024 * 2) + quote ujson.decode(input) def test_toDict(self): d = {"key": 31337} class DictTest: def toDict(self): return d def __json__(self): return '"json defined"' # Fallback and shouldn't be called. o = DictTest() output = ujson.encode(o) dec = ujson.decode(output) self.assertEqual(dec, d) def test_object_with_json(self): # If __json__ returns a string, then that string # will be used as a raw JSON snippet in the object. output_text = "this is the correct output" class JSONTest: def __json__(self): return '"' + output_text + '"' d = {u"key": JSONTest()} output = ujson.encode(d) dec = ujson.decode(output) self.assertEqual(dec, {u"key": output_text}) def test_object_with_json_unicode(self): # If __json__ returns a string, then that string # will be used as a raw JSON snippet in the object. output_text = u"this is the correct output" class JSONTest: def __json__(self): return u'"' + output_text + u'"' d = {u"key": JSONTest()} output = ujson.encode(d) dec = ujson.decode(output) self.assertEqual(dec, {u"key": output_text}) def test_object_with_complex_json(self): # If __json__ returns a string, then that string # will be used as a raw JSON snippet in the object. obj = {u"foo": [u"bar", u"baz"]} class JSONTest: def __json__(self): return ujson.encode(obj) d = {u"key": JSONTest()} output = ujson.encode(d) dec = ujson.decode(output) self.assertEqual(dec, {u"key": obj}) def test_object_with_json_type_error(self): # __json__ must return a string, otherwise it should raise an error. for return_value in (None, 1234, 12.34, True, {}): class JSONTest: def __json__(self): return return_value d = {u"key": JSONTest()} self.assertRaises(TypeError, ujson.encode, d) def test_object_with_json_attribute_error(self): # If __json__ raises an error, make sure python actually raises it. class JSONTest: def __json__(self): raise AttributeError d = {u"key": JSONTest()} self.assertRaises(AttributeError, ujson.encode, d) def test_decodeArrayTrailingCommaFail(self): input = "[31337,]" self.assertRaises(ValueError, ujson.decode, input) def test_decodeArrayLeadingCommaFail(self): input = "[,31337]" self.assertRaises(ValueError, ujson.decode, input) def test_decodeArrayOnlyCommaFail(self): input = "[,]" self.assertRaises(ValueError, ujson.decode, input) def test_decodeArrayUnmatchedBracketFail(self): input = "[]]" self.assertRaises(ValueError, ujson.decode, input) def test_decodeArrayEmpty(self): input = "[]" obj = ujson.decode(input) self.assertEqual([], obj) def test_decodeArrayOneItem(self): input = "[31337]" ujson.decode(input) def test_decodeLongUnsignedValue(self): input = "18446744073709551615" ujson.decode(input) def test_decodeBigValue(self): input = "9223372036854775807" ujson.decode(input) def test_decodeSmallValue(self): input = "-9223372036854775808" ujson.decode(input) def test_decodeTooBigValue(self): input = "18446744073709551616" self.assertRaises(ValueError, ujson.decode, input) def test_decodeTooSmallValue(self): input = "-90223372036854775809" self.assertRaises(ValueError, ujson.decode, input) def test_decodeVeryTooBigValue(self): input = "18446744073709551616" self.assertRaises(ValueError, ujson.decode, input) def test_decodeVeryTooSmallValue(self): input = "-90223372036854775809" self.assertRaises(ValueError, ujson.decode, input) def test_decodeWithTrailingWhitespaces(self): input = "{}\n\t " ujson.decode(input) def test_decodeWithTrailingNonWhitespaces(self): input = "{}\n\t a" self.assertRaises(ValueError, ujson.decode, input) def test_decodeArrayWithBigInt(self): input = "[18446744073709551616]" self.assertRaises(ValueError, ujson.decode, input) def test_decodeFloatingPointAdditionalTests(self): self.assertAlmostEqual(-1.1234567893, ujson.loads("-1.1234567893")) self.assertAlmostEqual(-1.234567893, ujson.loads("-1.234567893")) self.assertAlmostEqual(-1.34567893, ujson.loads("-1.34567893")) self.assertAlmostEqual(-1.4567893, ujson.loads("-1.4567893")) self.assertAlmostEqual(-1.567893, ujson.loads("-1.567893")) self.assertAlmostEqual(-1.67893, ujson.loads("-1.67893")) self.assertAlmostEqual(-1.7894, ujson.loads("-1.7894")) self.assertAlmostEqual(-1.893, ujson.loads("-1.893")) self.assertAlmostEqual(-1.3, ujson.loads("-1.3")) self.assertAlmostEqual(1.1234567893, ujson.loads("1.1234567893")) self.assertAlmostEqual(1.234567893, ujson.loads("1.234567893")) self.assertAlmostEqual(1.34567893, ujson.loads("1.34567893")) self.assertAlmostEqual(1.4567893, ujson.loads("1.4567893")) self.assertAlmostEqual(1.567893, ujson.loads("1.567893")) self.assertAlmostEqual(1.67893, ujson.loads("1.67893")) self.assertAlmostEqual(1.7894, ujson.loads("1.7894")) self.assertAlmostEqual(1.893, ujson.loads("1.893")) self.assertAlmostEqual(1.3, ujson.loads("1.3")) def test_ReadBadObjectSyntax(self): input = '{"age", 44}' self.assertRaises(ValueError, ujson.decode, input) def test_ReadTrue(self): self.assertEqual(True, ujson.loads("true")) def test_ReadFalse(self): self.assertEqual(False, ujson.loads("false")) def test_ReadNull(self): self.assertEqual(None, ujson.loads("null")) def test_WriteTrue(self): self.assertEqual("true", ujson.dumps(True)) def test_WriteFalse(self): self.assertEqual("false", ujson.dumps(False)) def test_WriteNull(self): self.assertEqual("null", ujson.dumps(None)) def test_ReadArrayOfSymbols(self): self.assertEqual([True, False, None], ujson.loads(" [ true, false,null] ")) def test_WriteArrayOfSymbolsFromList(self): self.assertEqual("[true,false,null]", ujson.dumps([True, False, None])) def test_WriteArrayOfSymbolsFromTuple(self): self.assertEqual("[true,false,null]", ujson.dumps((True, False, None))) def test_encodingInvalidUnicodeCharacter(self): s = "\udc7f" self.assertRaises(UnicodeEncodeError, ujson.dumps, s) def test_sortKeys(self): data = {"a": 1, "c": 1, "b": 1, "e": 1, "f": 1, "d": 1} sortedKeys = ujson.dumps(data, sort_keys=True) self.assertEqual(sortedKeys, '{"a":1,"b":1,"c":1,"d":1,"e":1,"f":1}') @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount") def test_does_not_leak_dictionary_values(self): import gc gc.collect() value = ["abc"] data = {"1": value} ref_count = sys.getrefcount(value) ujson.dumps(data) self.assertEqual(ref_count, sys.getrefcount(value)) @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount") def test_does_not_leak_dictionary_keys(self): import gc gc.collect() key1 = "1" key2 = "1" value1 = ["abc"] value2 = [1, 2, 3] data = {key1: value1, key2: value2} ref_count1 = sys.getrefcount(key1) ref_count2 = sys.getrefcount(key2) ujson.dumps(data) self.assertEqual(ref_count1, sys.getrefcount(key1)) self.assertEqual(ref_count2, sys.getrefcount(key2)) @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount") def test_does_not_leak_dictionary_string_key(self): import gc gc.collect() key1 = "1" value1 = 1 data = {key1: value1} ref_count1 = sys.getrefcount(key1) ujson.dumps(data) self.assertEqual(ref_count1, sys.getrefcount(key1)) @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount") def test_does_not_leak_dictionary_tuple_key(self): import gc gc.collect() key1 = ("a",) value1 = 1 data = {key1: value1} ref_count1 = sys.getrefcount(key1) ujson.dumps(data) self.assertEqual(ref_count1, sys.getrefcount(key1)) @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount") def test_does_not_leak_dictionary_bytes_key(self): import gc gc.collect() key1 = b"1" value1 = 1 data = {key1: value1} ref_count1 = sys.getrefcount(key1) ujson.dumps(data) self.assertEqual(ref_count1, sys.getrefcount(key1)) @unittest.skipIf(not hasattr(sys, 'getrefcount') == True, reason="test requires sys.refcount") def test_does_not_leak_dictionary_None_key(self): import gc gc.collect() key1 = None value1 = 1 data = {key1: value1} ref_count1 = sys.getrefcount(key1) ujson.dumps(data) self.assertEqual(ref_count1, sys.getrefcount(key1)) """ def test_decodeNumericIntFrcOverflow(self): input = "X.Y" raise NotImplementedError("Implement this test!") def test_decodeStringUnicodeEscape(self): input = "\u3131" raise NotImplementedError("Implement this test!") def test_decodeStringUnicodeBrokenEscape(self): input = "\u3131" raise NotImplementedError("Implement this test!") def test_decodeStringUnicodeInvalidEscape(self): input = "\u3131" raise NotImplementedError("Implement this test!") def test_decodeStringUTF8(self): input = "someutfcharacters" raise NotImplementedError("Implement this test!") """ if __name__ == "__main__": unittest.main() """ # Use this to look for memory leaks if __name__ == '__main__': from guppy import hpy hp = hpy() hp.setrelheap() while True: try: unittest.main() except SystemExit: pass heap = hp.heapu() print(heap) """ @pytest.mark.parametrize("indent", list(range(65537, 65542))) def test_dump_huge_indent(indent): ujson.encode({"a": True}, indent=indent) @pytest.mark.parametrize("first_length", list(range(2, 7))) @pytest.mark.parametrize("second_length", list(range(10919, 10924))) def test_dump_long_string(first_length, second_length): ujson.dumps(["a" * first_length, "\x00" * second_length]) def test_dump_indented_nested_list(): a = _a = [] for i in range(20): _a.append(list(range(i))) _a = _a[-1] ujson.dumps(a, indent=i) @pytest.mark.parametrize("indent", [0, 1, 2, 4, 5, 8, 49]) def test_issue_334(indent): path = Path(__file__).with_name("334-reproducer.json") a = ujson.loads(path.read_bytes()) ujson.dumps(a, indent=indent) @pytest.mark.parametrize( "test_input, expected", [ # Normal cases (r'"\uD83D\uDCA9"', "\U0001F4A9"), (r'"a\uD83D\uDCA9b"', "a\U0001F4A9b"), # Unpaired surrogates (r'"\uD800"', "\uD800"), (r'"a\uD800b"', "a\uD800b"), (r'"\uDEAD"', "\uDEAD"), (r'"a\uDEADb"', "a\uDEADb"), (r'"\uD83D\uD83D\uDCA9"', "\uD83D\U0001F4A9"), (r'"\uDCA9\uD83D\uDCA9"', "\uDCA9\U0001F4A9"), (r'"\uD83D\uDCA9\uD83D"', "\U0001F4A9\uD83D"), (r'"\uD83D\uDCA9\uDCA9"', "\U0001F4A9\uDCA9"), (r'"\uD83D \uDCA9"', "\uD83D \uDCA9"), # No decoding of actual surrogate characters (rather than escaped ones) ('"\uD800"', "\uD800"), ('"\uDEAD"', "\uDEAD"), ('"\uD800a\uDEAD"', "\uD800a\uDEAD"), ('"\uD83D\uDCA9"', "\uD83D\uDCA9"), ], ) def test_decode_surrogate_characters(test_input, expected): assert ujson.loads(test_input) == expected assert ujson.loads(test_input.encode("utf-8", "surrogatepass")) == expected # Ensure that this matches stdlib's behaviour assert json.loads(test_input) == expected