1# -*- coding: utf-8 -*- 2 3import sys 4import os 5import redis 6import json 7from RLTest import Env 8from includes import * 9 10from RLTest import Defaults 11 12Defaults.decode_responses = True 13 14# ---------------------------------------------------------------------------------------------- 15 16# Path to JSON test case files 17HERE = os.path.abspath(os.path.dirname(__file__)) 18ROOT = os.path.abspath(os.path.join(HERE, "../..")) 19TESTS_ROOT = os.path.abspath(os.path.join(HERE, "..")) 20JSON_PATH = os.path.join(TESTS_ROOT, 'files') 21 22# ---------------------------------------------------------------------------------------------- 23 24# TODO: these are currently not supported so ignore them 25json_ignore = [ 26 'pass-json-parser-0002.json', # UTF-8 to Unicode 27 'pass-json-parser-0005.json', # big numbers 28 'pass-json-parser-0006.json', # UTF-8 to Unicode 29 'pass-json-parser-0007.json', # UTF-8 to Unicode 30 'pass-json-parser-0012.json', # UTF-8 to Unicode 31 'pass-jsonsl-1.json', # big numbers 32 'pass-jsonsl-yelp.json', # float precision 33] 34 35# Some basic documents to use in the tests 36docs = { 37 'simple': { 38 'foo': 'bar', 39 }, 40 'basic': { 41 'string': 'string value', 42 'none': None, 43 'bool': True, 44 'int': 42, 45 'num': 4.2, 46 'arr': [42, None, -1.2, False, ['sub', 'array'], {'subdict': True}], 47 'dict': { 48 'a': 1, 49 'b': '2', 50 'c': None, 51 } 52 }, 53 'scalars': { 54 'unicode': 'string value', 55 'NoneType': None, 56 'bool': True, 57 'int': 42, 58 'float': -1.2, 59 }, 60 'values': { 61 'str': 'string value', 62 'NoneType': None, 63 'bool': True, 64 'int': 42, 65 'float': -1.2, 66 'dict': {}, 67 'list': [] 68 }, 69 'types': { 70 'null': None, 71 'boolean': False, 72 'integer': 42, 73 'number': 1.2, 74 'string': 'str', 75 'object': {}, 76 'array': [], 77 }, 78} 79 80#---------------------------------------------------------------------------------------------- 81 82# def getCacheInfo(env): 83# r = env 84# res = r.cmd('JSON._CACHEINFO') 85# ret = {} 86# for x in range(0, len(res), 2): 87# ret[res[x]] = res[x+1] 88# return ret 89 90 91def assertOk(r, x, msg=None): 92 r.assertOk(x, message=msg) 93 94def assertExists(r, key, msg=None): 95 r.assertTrue(r.exists(key), message=msg) 96 97def assertNotExists(r, key, msg=None): 98 r.assertFalse(r.exists(key), message=msg) 99 100#---------------------------------------------------------------------------------------------- 101 102def testSetRootWithInvalidJSONValuesShouldFail(env): 103 """Test that setting the root of a ReJSON key with invalid JSON values fails""" 104 r = env 105 invalid = ['{', '}', '[', ']', '{]', '[}', '\\', '\\\\', '', 106 ' ', '\\"', '\'', '\[', '\x00', '\x0a', '\x0c', 107 # '\xff' TODO pending https://github.com/RedisLabsModules/redismodule-rs/pull/15 108 ] 109 for i in invalid: 110 r.expect('JSON.SET', 'test', '.', i).raiseError() 111 assertNotExists(r, 'test%s' % i) 112 113def testSetInvalidPathShouldFail(env): 114 """Test that invalid paths fail""" 115 r = env 116 117 invalid = ['', ' ', '\x00', '\x0a', '\x0c', 118 # '\xff' TODO pending https://github.com/RedisLabsModules/redismodule-rs/pull/15 119 '."', '.\x00', '.\x0a\x0c', '.-foo', '.43', 120 '.foo\n.bar'] 121 for i in invalid: 122 r.expect('JSON.SET', 'test', i, 'null').raiseError() 123 assertNotExists(r, 'test%s' % i) 124 125def testSetRootWithJSONValuesShouldSucceed(env): 126 """Test that the root of a JSON key can be set with any valid JSON""" 127 r = env 128 for v in ['string', 1, -2, 3.14, None, True, False, [], {}]: 129 r.cmd('DEL', 'test') 130 j = json.dumps(v) 131 r.assertOk(r.execute_command('JSON.SET', 'test', '.', j)) 132 r.assertExists('test') 133 s = json.loads(r.execute_command('JSON.GET', 'test')) 134 r.assertEqual(v, s) 135 136def testSetReplaceRootShouldSucceed(env): 137 """Test replacing the root of an existing key with a valid object succeeds""" 138 r = env 139 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(docs['basic']))) 140 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(docs['simple']))) 141 raw = r.execute_command('JSON.GET', 'test', '.') 142 r.assertEqual(json.loads(raw), docs['simple']) 143 for k, v in iter(docs['values'].items()): 144 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(v))) 145 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 146 r.assertEqual(str(type(data)), '<class \'{}\'>'.format(k)) 147 r.assertEqual(data, v) 148 149def testSetGetWholeBasicDocumentShouldBeEqual(env): 150 """Test basic JSON.GET/JSON.SET""" 151 r = env 152 data = json.dumps(docs['basic']) 153 r.assertOk(r.execute_command('JSON.SET', 'test', '.', data)) 154 r.assertExists('test') 155 r.assertEqual(json.dumps(json.loads(r.execute_command('JSON.GET', 'test'))), data) 156 157def testSetBehaviorModifyingSubcommands(env): 158 """Test JSON.SET's NX and XX subcommands""" 159 r = env 160 161 # test against the root 162 r.assertIsNone(r.execute_command('JSON.SET', 'test', '.', '{}', 'XX')) 163 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{}', 'NX')) 164 r.assertIsNone(r.execute_command('JSON.SET', 'test', '.', '{}', 'NX')) 165 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{}', 'XX')) 166 167 # test an object key 168 r.assertIsNone(r.execute_command('JSON.SET', 'test', '.foo', '[]', 'XX')) 169 r.assertOk(r.execute_command('JSON.SET', 'test', '.foo', '[]', 'NX')) 170 r.assertIsNone(r.execute_command('JSON.SET', 'test', '.foo', '[]', 'NX')) 171 r.assertOk(r.execute_command('JSON.SET', 'test', '.foo', '[1]', 'XX')) 172 173 # verify failure for arrays 174 r.expect('JSON.SET', 'test', '.foo[1]', 'null', 'NX').raiseError() 175 # r.expect('JSON.SET', 'test', '.foo[1]', 'null', 'XX').raiseError() 176 177 # Wrong arguments 178 r.expect('JSON.SET', 'test', '.foo', '[]', '').raiseError() 179 r.expect('JSON.SET', 'test', '.foo', '[]', 'NN').raiseError() 180 r.expect('JSON.SET', 'test', '.foo', '[]', 'FORMAT', 'TT').raiseError() 181 r.expect('JSON.SET', 'test', '.foo', '[]', 'XX', 'FORMAT', '').raiseError() 182 r.expect('JSON.SET', 'test', '.foo', '[]', 'XX', 'XN').raiseError() 183 r.expect('JSON.SET', 'test', '.foo', '[]', 'XX', '').raiseError() 184 185def testSetWithBracketNotation(env): 186 r = env 187 188 r.assertOk(r.execute_command('JSON.SET', 'x', '.', '{}')) 189 r.assertOk(r.execute_command('JSON.SET', 'x', '.["f1"]', '{}')) # Simple bracket notation 190 r.assertOk(r.execute_command('JSON.SET', 'x', '.["f1"].f2', '[0,0,0]')) # Mixed with dot notation 191 r.assertOk(r.execute_command('JSON.SET', 'x', '.["f1"].f2[1]', '{}')) # Replace in array 192 r.assertOk(r.execute_command('JSON.SET', 'x', '.["f1"].f2[1]["f.]$.f"]', '{}')) # Dots and invalid chars in the brackets 193 r.assertOk(r.execute_command('JSON.SET', 'x', '.["f1"]["f2"][1]["f.]$.f"]', '1')) # Replace existing value 194 r.assertIsNone(r.execute_command('JSON.SET', 'x', '.["f3"].f2', '1')) # Fail trying to set f2 when f3 doesn't exist 195 r.assertEqual(json.loads(r.execute_command('JSON.GET', 'x')), {'f1': {'f2': [0, {'f.]$.f': 1}, 0]}}) # Make sure it worked 196 197def testGetWithBracketNotation(env): 198 r = env 199 200 r.assertOk(r.execute_command('JSON.SET', 'x', '.', '[1,2,3]')) 201 r.assertEqual(json.loads(r.execute_command('JSON.GET', 'x', '.[1]')), 2) # dot notation - single value 202 r.assertEqual(json.loads(r.execute_command('JSON.GET', 'x', '[1]')), 2) # implicit dot notation - single value 203 r.assertEqual(json.loads(r.execute_command('JSON.GET', 'x', '$.[1]')), [2]) # dollar notation - array 204 r.assertEqual(json.loads(r.execute_command('JSON.GET', 'x', '$[1]')), [2]) # dollar notation - array 205 206def testSetWithPathErrors(env): 207 r = env 208 209 r.expect('JSON.SET', 'x', '.', '{}').ok() 210 211 # Add to non static path 212 r.expect('JSON.SET', 'x', '$..f', 1).raiseError() 213 # r.assertEqual(str(e.exception), 'Err: wrong static path') 214 215 # Treat object as array 216 r.expect('JSON.SET', 'x', '$[0]', 1).raiseError() 217 # r.assertEqual(str(e.exception), 'Err: path not an object') 218 219def testGetNonExistantPathsFromBasicDocumentShouldFail(env): 220 """Test failure of getting non-existing values""" 221 222 r = env 223 224 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(docs['scalars']))) 225 226 # Paths that do not exist 227 paths = ['.foo', 'boo', '.key1[0]', '.key2.bar', '.key5[99]', '.key5["moo"]'] 228 for p in paths: 229 r.expect('JSON.GET', 'test', p).raiseError() 230 # TODO uncomment 231 # # Test failure in multi-path get 232 # r.expect('JSON.GET', 'test', '.bool', paths[0]).raiseError() 233 234def testGetPartsOfValuesDocumentOneByOne(env): 235 """Test type and value returned by JSON.GET""" 236 r = env 237 r.expect('JSON.SET', 'test', '.', json.dumps(docs['values'])).ok() 238 for k, v in iter(docs['values'].items()): 239 data = json.loads(r.execute_command('JSON.GET', 'test', '.{}'.format(k))) 240 r.assertEqual(str(type(data)), '<class \'{}\'>'.format(k), message=k) 241 r.assertEqual(data, v, message=k) 242 243def testGetPartsOfValuesDocumentMultiple(env): 244 """Test correctness of an object returned by JSON.GET""" 245 r = env 246 r.expect('JSON.SET', 'test', '.', json.dumps(docs['values'])).ok() 247 data = json.loads(r.execute_command('JSON.GET', 'test', *docs['values'].keys())) 248 r.assertEqual(data, docs['values']) 249 250def testGetFormatting(env): 251 r = env 252 253 objects_to_test = [ 254 {'obj': {'f': 'v'}}, 255 {'arr': [0, 1]} 256 ] 257 formatted_objects = [ 258 '{{{newline}{indent}"obj":{space}{{{newline}{indent}{indent}"f":{space}"v"{newline}{indent}}}{newline}}}', 259 '{{{newline}{indent}"arr":{space}[{newline}{indent}{indent}0,{newline}{indent}{indent}1{newline}{indent}]{newline}}}' 260 ] 261 262 for o in objects_to_test: 263 r.assertOk(r.execute_command('JSON.SET', list(o.keys()).pop(), '$', json.dumps(o))) 264 265 for space in ['', ' ', '\t', ' ']: 266 for indent in ['', ' ', '\t', ' ']: 267 for newline in ['', '\n', '\r\n']: 268 for o, f in zip(objects_to_test, formatted_objects): 269 res = r.execute_command('JSON.GET', list(o.keys()).pop(), 'INDENT', indent, 'NEWLINE', newline, 'SPACE', space) 270 r.assertEqual(res, f.format(newline=newline, space=space, indent=indent)) 271 272def testBackwardRDB(env): 273 env.skipOnCluster() 274 dbFileName = env.cmd('config', 'get', 'dbfilename')[1] 275 dbDir = env.cmd('config', 'get', 'dir')[1] 276 rdbFilePath = os.path.join(dbDir, dbFileName) 277 env.stop() 278 try: 279 os.unlink(rdbFilePath) 280 except OSError: 281 pass 282 filePath = os.path.join(JSON_PATH, 'backward.rdb') 283 os.symlink(filePath, rdbFilePath) 284 env.start() 285 286 r = env 287 data = json.loads(r.execute_command('JSON.GET', 'complex')) 288 r.assertEqual(data, {"a":{"b":[{"c":{"d":[1,'2'],"e":None}},True],"a":'a'},"b":1,"c":True,"d":None}) 289 290def testSetBSON(env): 291 r = env 292 bson = open(os.path.join(JSON_PATH , 'bson_bytes_1.bson'), 'rb').read() 293 r.assertOk(r.execute_command('JSON.SET', 'test', '.', bson, 'FORMAT', 'BSON')) 294 r.expect('JSON.GET', 'test', *docs['values'].keys()).raiseError() 295 296def testMgetCommand(env): 297 """Test REJSON.MGET command""" 298 r = env 299 300 # Set up a few keys 301 for d in range(0, 5): 302 key = 'doc:{}'.format(d) 303 r.cmd('DEL', key) 304 r.expect('JSON.SET', key, '.', json.dumps(docs['basic'])).ok() 305 306 # Test an MGET that succeeds on all keys 307 raw = r.execute_command('JSON.MGET', *['doc:{}'.format(d) for d in range(0, 5)] + ['.']) 308 r.assertEqual(len(raw), 5) 309 for d in range(0, 5): 310 key = 'doc:{}'.format(d) 311 r.assertEqual(json.loads(raw[d]), docs['basic'], d) 312 313 # Test an MGET that fails for one key 314 r.cmd('DEL', 'test') 315 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"bool":false}')) 316 raw = r.execute_command('JSON.MGET', 'test', 'doc:0', 'foo', '.bool') 317 r.assertEqual(len(raw), 3) 318 r.assertFalse(json.loads(raw[0])) 319 r.assertTrue(json.loads(raw[1])) 320 r.assertEqual(raw[2], None) 321 322 # Test that MGET on missing path 323 raw = r.execute_command('JSON.MGET', 'doc:0', 'doc:1', '42isnotapath') 324 r.assertEqual(len(raw), 2) 325 r.assertEqual(raw[0], None) 326 r.assertEqual(raw[1], None) 327 328 # Test that MGET fails on path errors 329 r.cmd('DEL', 'test') 330 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"bull":4.2}')) 331 raw = r.execute_command('JSON.MGET', 'doc:0', 'test', 'doc:1', '.bool') 332 r.assertEqual(len(raw), 3) 333 r.assertTrue(json.loads(raw[0])) 334 r.assertEqual(raw[1], None) 335 r.assertTrue(json.loads(raw[2])) 336 337def testToggleCommand(env): 338 """Test REJSON.TOGGLE command""" 339 r = env 340 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo":true}')) 341 r.assertEqual(r.execute_command('JSON.TOGGLE','test','.foo'), 'false') 342 r.assertEqual(r.execute_command('JSON.TOGGLE','test','.foo'), 'true') 343 344 # Test Toggeling Empty Path 345 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo":"bar"}')) 346 r.expect('JSON.TOGGLE', 'test', '.bar').raiseError() 347 348 # Test Toggeling Non Boolean 349 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo":"bar"}')) 350 r.expect('JSON.TOGGLE','test','.foo').raiseError() 351 352def testDelCommand(env): 353 """Test REJSON.DEL command""" 354 r = env 355 # Test deleting an empty object 356 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{}')) 357 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.'), 1) 358 assertNotExists(r, 'test') 359 360 # Test deleting an empty object 361 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo": "bar", "baz": "qux"}')) 362 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.baz'), 1) 363 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.'), 1) 364 r.assertIsNone(r.execute_command('JSON.TYPE', 'test', '.baz')) 365 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.foo'), 1) 366 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.'), 0) 367 r.assertIsNone(r.execute_command('JSON.TYPE', 'test', '.foo')) 368 r.assertEqual(r.execute_command('JSON.TYPE', 'test', '.'), 'object') 369 370 # Test deleting some keys from an object 371 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{}')) 372 r.assertOk(r.execute_command('JSON.SET', 'test', '.foo', '"bar"')) 373 r.assertOk(r.execute_command('JSON.SET', 'test', '.baz', '"qux"')) 374 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.baz'), 1) 375 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.'), 1) 376 r.assertIsNone(r.execute_command('JSON.TYPE', 'test', '.baz')) 377 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.foo'), 1) 378 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.'), 0) 379 r.assertIsNone(r.execute_command('JSON.TYPE', 'test', '.foo')) 380 r.assertEqual(r.execute_command('JSON.TYPE', 'test', '.'), 'object') 381 382 # Test with an array 383 r.assertOk(r.execute_command('JSON.SET', 'test', '.foo', '"bar"')) 384 r.assertOk(r.execute_command('JSON.SET', 'test', '.baz', '"qux"')) 385 r.assertOk(r.execute_command('JSON.SET', 'test', '.arr', '[1.2,1,2]')) 386 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.arr[1]'), 1) 387 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.'), 3) 388 r.assertEqual(r.execute_command('JSON.ARRLEN', 'test', '.arr'), 2) 389 r.assertEqual(r.execute_command('JSON.TYPE', 'test', '.arr'), 'array') 390 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.arr'), 1) 391 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.'), 2) 392 r.assertEqual(r.execute_command('JSON.DEL', 'test', '.'), 1) 393 r.assertIsNone(r.execute_command('JSON.GET', 'test')) 394 395def testObjectCRUD(env): 396 r = env 397 398 # Create an object 399 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{ }')) 400 r.assertEqual('object', r.execute_command('JSON.TYPE', 'test', '.')) 401 r.assertEqual(0, r.execute_command('JSON.OBJLEN', 'test', '.')) 402 raw = r.execute_command('JSON.GET', 'test') 403 data = json.loads(raw) 404 r.assertEqual(data, {}) 405 406 # Test failure to access a non-existing element 407 r.expect('JSON.GET', 'test', '.foo').raiseError() 408 409 # Test setting a key in the oject 410 r.assertOk(r.execute_command('JSON.SET', 'test', '.foo', '"bar"')) 411 r.assertEqual(1, r.execute_command('JSON.OBJLEN', 'test', '.')) 412 raw = r.execute_command('JSON.GET', 'test', '.') 413 data = json.loads(raw) 414 r.assertEqual(data, {u'foo': u'bar'}) 415 416 # Test replacing a key's value in the object 417 r.assertOk(r.execute_command('JSON.SET', 'test', '.foo', '"baz"')) 418 raw = r.execute_command('JSON.GET', 'test', '.') 419 data = json.loads(raw) 420 r.assertEqual(data, {u'foo': u'baz'}) 421 422 # Test adding another key to the object 423 r.assertOk(r.execute_command('JSON.SET', 'test', '.boo', '"far"')) 424 r.assertEqual(2, r.execute_command('JSON.OBJLEN', 'test', '.')) 425 raw = r.execute_command('JSON.GET', 'test', '.') 426 data = json.loads(raw) 427 r.assertEqual(data, {u'foo': u'baz', u'boo': u'far'}) 428 429 # Test deleting a key from the object 430 r.assertEqual(1, r.execute_command('JSON.DEL', 'test', '.foo')) 431 raw = r.execute_command('JSON.GET', 'test', '.') 432 data = json.loads(raw) 433 r.assertEqual(data, {u'boo': u'far'}) 434 435 # Test replacing the object 436 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo": "bar"}')) 437 raw = r.execute_command('JSON.GET', 'test', '.') 438 data = json.loads(raw) 439 r.assertEqual(data, {u'foo': u'bar'}) 440 441 # Test deleting the object 442 r.assertEqual(1, r.execute_command('JSON.DEL', 'test', '.')) 443 r.assertIsNone(r.execute_command('JSON.GET', 'test', '.')) 444 445 # Test deleting with default (root) path 446 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo": "bar"}')) 447 r.assertEqual(1, r.execute_command('JSON.DEL', 'test')) 448 r.assertIsNone(r.execute_command('JSON.GET', 'test', '.')) 449 450def testClear(env): 451 """Test JSON.CLEAR command""" 452 453 r = env 454 multi_content = r'{"n":42,"s":"42","arr":[{"n":44},"s",{"n":{"a":1,"b":2}},{"n2":{"x":3.02,"n":["to","be","cleared",4],"y":4.91}}]}' 455 r.expect('JSON.SET', 'test', '.', multi_content).ok() 456 457 # Test get multi results (using .. recursive descent) 458 r.expect('JSON.GET', 'test', '$..n').equal(r'[42,44,{"a":1,"b":2},["to","be","cleared",4]]') 459 460 # Make sure specific obj content exists before clear 461 obj_content = r'[{"a":1,"b":2}]' 462 obj_content_legacy = r'{"a":1,"b":2}' 463 r.expect('JSON.GET', 'test', '$.arr[2].n').equal(obj_content) 464 r.expect('JSON.GET', 'test', '.arr[2].n').equal(obj_content_legacy) 465 # Make sure specific arr content exists before clear 466 arr_content = r'[["to","be","cleared",4]]' 467 arr_content_legacy = r'["to","be","cleared",4]' 468 r.expect('JSON.GET', 'test', '$.arr[3].n2.n').equal(arr_content) 469 r.expect('JSON.GET', 'test', '.arr[3].n2.n').equal(arr_content_legacy) 470 471 # Clear obj and arr with specific paths 472 r.expect('JSON.CLEAR', 'test', '$.arr[2].n').equal(1) 473 r.expect('JSON.CLEAR', 'test', '$.arr[3].n2.n').equal(1) 474 475 # Fail clear on inappropriate path (not obj or arr) 476 r.expect('JSON.CLEAR', 'test', '$.arr[1]').equal(0) 477 478 # Make sure specific obj content was cleared 479 r.expect('JSON.GET', 'test', '$.arr[2].n').equal('[{}]') 480 r.expect('JSON.GET', 'test', '.arr[2].n').equal('{}') 481 # Make sure specific arr content was cleared 482 r.expect('JSON.GET', 'test', '$.arr[3].n2.n').equal('[[]]') 483 r.expect('JSON.GET', 'test', '.arr[3].n2.n').equal('[]') 484 485 # Make sure only appropriate content (obj and arr) was cleared 486 r.expect('JSON.GET', 'test', '$..n').equal('[42,44,{},[]]') 487 488 # Clear dynamic path 489 r.expect('JSON.SET', 'test', '.', r'{"n":42,"s":"42","arr":[{"n":44},"s",{"n":{"a":1,"b":2}},{"n2":{"x":3.02,"n":["to","be","cleared",4],"y":4.91}}]}') \ 490 .ok() 491 r.expect('JSON.CLEAR', 'test', '$.arr.*').equal(3) 492 r.expect('JSON.GET', 'test', '$').equal('[{"n":42,"s":"42","arr":[{},"s",{},{}]}]') 493 494 # Clear root 495 r.expect('JSON.SET', 'test', '.', r'{"n":42,"s":"42","arr":[{"n":44},"s",{"n":{"a":1,"b":2}},{"n2":{"x":3.02,"n":["to","be","cleared",4],"y":4.91}}]}') \ 496 .ok() 497 # TODO: switch order of the following paths and expect .equals(2) when supporting multi-paths in JSON.CLEAR 498 r.expect('JSON.CLEAR', 'test', '$', '$.arr[2].n').equal(1) 499 r.expect('JSON.GET', 'test', '$').equal('[{}]') 500 501 r.expect('JSON.SET', 'test', '$', obj_content_legacy).ok() 502 r.expect('JSON.CLEAR', 'test').equal(1) 503 r.expect('JSON.GET', 'test', '$').equal('[{}]') 504 505 # Clear none existing path 506 r.expect('JSON.SET', 'test', '.', r'{"a":[1,2], "b":{"c":"d"}}').ok() 507 r.expect('JSON.CLEAR', 'test', '$.c').equal(0) 508 r.expect('JSON.GET', 'test', '$').equal('[{"a":[1,2],"b":{"c":"d"}}]') 509 510 r.expect('JSON.CLEAR', 'test', '$.b..a').equal(0) 511 r.expect('JSON.GET', 'test', '$').equal('[{"a":[1,2],"b":{"c":"d"}}]') 512 513 # Key doesn't exist 514 r.expect('JSON.CLEAR', 'not_test_key', '$').raiseError() 515 516def testArrayCRUD(env): 517 """Test JSON Array CRUDness""" 518 519 r = env 520 521 # Test creation of an empty array 522 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '[]')) 523 r.assertEqual('array', r.execute_command('JSON.TYPE', 'test', '.')) 524 r.assertEqual(0, r.execute_command('JSON.ARRLEN', 'test', '.')) 525 526 # Test failure of setting an element at different positons in an empty array 527 r.expect('JSON.SET', 'test', '[0]', 0).raiseError() 528 r.expect('JSON.SET', 'test', '[19]', 0).raiseError() 529 r.expect('JSON.SET', 'test', '[-1]', 0).raiseError() 530 531 # Test appending and inserting elements to the array 532 r.assertEqual(1, r.execute_command('JSON.ARRAPPEND', 'test', '.', 1)) 533 r.assertEqual(1, r.execute_command('JSON.ARRLEN', 'test', '.')) 534 r.assertEqual(2, r.execute_command('JSON.ARRINSERT', 'test', '.', 0, -1)) 535 r.assertEqual(2, r.execute_command('JSON.ARRLEN', 'test', '.')) 536 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 537 r.assertListEqual([-1, 1, ], data) 538 r.assertEqual(3, r.execute_command('JSON.ARRINSERT', 'test', '.', -1, 0)) 539 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 540 r.assertListEqual([-1, 0, 1, ], data) 541 r.assertEqual(5, r.execute_command('JSON.ARRINSERT', 'test', '.', -3, -3, -2)) 542 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 543 r.assertListEqual([-3, -2, -1, 0, 1, ], data) 544 r.assertEqual(7, r.execute_command('JSON.ARRAPPEND', 'test', '.', 2, 3)) 545 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 546 r.assertListEqual([-3, -2, -1, 0, 1, 2, 3], data) 547 548 # Test replacing elements in the array 549 r.assertOk(r.execute_command('JSON.SET', 'test', '[0]', '"-inf"')) 550 r.assertOk(r.execute_command('JSON.SET', 'test', '[-1]', '"+inf"')) 551 r.assertOk(r.execute_command('JSON.SET', 'test', '[3]', 'null')) 552 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 553 r.assertListEqual([u'-inf', -2, -1, None, 1, 2, u'+inf'], data) 554 555 # Test deleting from the array 556 r.assertEqual(1, r.execute_command('JSON.DEL', 'test', '[1]')) 557 r.assertEqual(1, r.execute_command('JSON.DEL', 'test', '[-2]')) 558 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 559 r.assertListEqual([u'-inf', -1, None, 1, u'+inf'], data) 560 561 # TODO: Should not be needed once DEL works 562 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '["-inf", -1, null, 1, "+inf"]')) 563 564 # Test trimming the array 565 r.assertEqual(4, r.execute_command('JSON.ARRTRIM', 'test', '.', 1, -1)) 566 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 567 r.assertListEqual([-1, None, 1, u'+inf'], data) 568 r.assertEqual(3, r.execute_command('JSON.ARRTRIM', 'test', '.', 0, -2)) 569 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 570 r.assertListEqual([-1, None, 1], data) 571 r.assertEqual(1, r.execute_command('JSON.ARRTRIM', 'test', '.', 1, 1)) 572 data = json.loads(r.execute_command('JSON.GET', 'test', '.')) 573 r.assertListEqual([None], data) 574 575 # Test replacing the array 576 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '[true]')) 577 r.assertEqual('array', r.execute_command('JSON.TYPE', 'test', '.')) 578 r.assertEqual(1, r.execute_command('JSON.ARRLEN', 'test', '.')) 579 r.assertEqual('true', r.execute_command('JSON.GET', 'test', '[0]')) 580 581def testArrIndexCommand(env): 582 """Test JSON.ARRINDEX command""" 583 r = env 584 585 r.assertOk(r.execute_command('JSON.SET', 'test', 586 '.', '{ "arr": [0, 1, 2, 3, 2, 1, 0] }')) 587 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0), 0) 588 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 3), 3) 589 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 4), -1) 590 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 1), 6) 591 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, -1), 6) 592 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 6), 6) 593 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 4, -0), 6) 594 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 5, -1), -1) 595 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 5, 0), 6) 596 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 2, -2, 6), -1) 597 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', '"foo"'), -1) 598 599 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', 4, '[4]'), 8) 600 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 3), 3) 601 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 2, 3), 5) 602 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', '[4]'), 4) 603 604 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 1), 1) 605 606 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '$.arr', 1), [1]) 607 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '$.arr', 2, 1, 4), [2]) 608 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '$.arr', 6), [-1]) 609 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '$.arr', 3, 0, 2), [-1]) 610 611 612def testArrInsertCommand(env): 613 """Test JSON.ARRINSERT command""" 614 r = env 615 616 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{ "arr": [] }')) 617 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', 0, '1'), 1) 618 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', -1, '2'), 2) 619 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', -2, '3'), 3) 620 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', 3, '4'), 4) 621 r.assertEqual(r.execute_command('JSON.GET', 'test', '.arr'), "[3,2,1,4]") 622 623 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', 1, '5'), 5) 624 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', -2, '6'), 6) 625 r.assertEqual(r.execute_command('JSON.GET', 'test', '.arr'), "[3,5,2,6,1,4]") 626 627 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', -3, '7', '{"A":"Z"}', '9'), 9) 628 r.assertEqual(r.execute_command('JSON.GET', 'test', '.arr'), '[3,5,2,7,{"A":"Z"},9,6,1,4]') 629 630 r.expect('JSON.ARRINSERT', 'test', '.arr', -10, '10').raiseError() 631 r.expect('JSON.ARRINSERT', 'test', '.arr', 10, '10').raiseError() 632 633def testArrIndexMixCommand(env): 634 """Test JSON.ARRINDEX command with mixed values""" 635 r = env 636 637 r.assertOk(r.execute_command('JSON.SET', 'test', 638 '.', '{ "arr": [0, 1, 2, 3, 2, 1, 0, {"val": 4}, {"val": 9}, [3,4,8], ["a", "b", 8]] }')) 639 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0), 0) 640 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 3), 3) 641 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 4), -1) 642 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 1), 6) 643 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, -5), 6) 644 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 6), 6) 645 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 4, -0), 6) 646 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 0, 5, -1), 6) 647 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 2, -2, 6), -1) 648 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', '"foo"'), -1) 649 650 r.assertEqual(r.execute_command('JSON.ARRINSERT', 'test', '.arr', 4, '[4]'), 12) 651 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 3), 3) 652 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', 2, 3), 5) 653 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', '[4]'), 4) 654 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', '{\"val\":4}'), 8) 655 r.assertEqual(r.execute_command('JSON.ARRINDEX', 'test', '.arr', '["a", "b", 8]'), 11) 656 657def testArrTrimCommand(env): 658 """Test JSON.ARRTRIM command""" 659 660 r = env 661 r.assertOk(r.execute_command('JSON.SET', 'test', 662 '.', '{ "arr": [0, 1, 2, 3, 2, 1, 0] }')) 663 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', 1, -2), 5) 664 r.assertListEqual(json.loads(r.execute_command( 665 'JSON.GET', 'test', '.arr')), [1, 2, 3, 2, 1]) 666 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', 0, 99), 5) 667 r.assertListEqual(json.loads(r.execute_command( 668 'JSON.GET', 'test', '.arr')), [1, 2, 3, 2, 1]) 669 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', 0, 2), 3) 670 r.assertListEqual(json.loads(r.execute_command( 671 'JSON.GET', 'test', '.arr')), [1, 2, 3]) 672 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', 99, 2), 0) 673 r.assertListEqual(json.loads(r.execute_command('JSON.GET', 'test', '.arr')), []) 674 675 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', -1, 0), 0) 676 677 r.assertOk(r.execute_command('JSON.SET', 'test', 678 '.', '{ "arr": [0, 1, 2, 3, 2, 1, 0] }')) 679 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', -1, 0), 0) 680 681 r.assertOk(r.execute_command('JSON.SET', 'test', 682 '.', '{ "arr": [0, 1, 2, 3, 2, 1, 0] }')) 683 r.assertEqual(r.execute_command('JSON.ARRTRIM', 'test', '.arr', -4, 1), 0) 684 685 686def testArrPopCommand(env): 687 """Test JSON.ARRPOP command""" 688 689 r = env 690 691 r.assertOk(r.execute_command('JSON.SET', 'test', 692 '.', '[1,2,3,4,5,6,7,8,9]')) 693 r.assertEqual('9', r.execute_command('JSON.ARRPOP', 'test')) 694 r.assertEqual('8', r.execute_command('JSON.ARRPOP', 'test', '.')) 695 r.assertEqual('7', r.execute_command('JSON.ARRPOP', 'test', '.', -1)) 696 r.assertEqual('5', r.execute_command('JSON.ARRPOP', 'test', '.', -2)) 697 r.assertEqual('1', r.execute_command('JSON.ARRPOP', 'test', '.', 0)) 698 r.assertEqual('4', r.execute_command('JSON.ARRPOP', 'test', '.', 2)) 699 r.assertEqual('6', r.execute_command('JSON.ARRPOP', 'test', '.', 99)) 700 r.assertEqual('2', r.execute_command('JSON.ARRPOP', 'test', '.', -99)) 701 r.assertEqual('3', r.execute_command('JSON.ARRPOP', 'test')) 702 r.assertIsNone(r.execute_command('JSON.ARRPOP', 'test')) 703 r.assertIsNone(r.execute_command('JSON.ARRPOP', 'test', '.')) 704 r.assertIsNone(r.execute_command('JSON.ARRPOP', 'test', '.', 2)) 705 706def testArrPopErrors(env): 707 r = env 708 709 r.assertOk(r.execute_command('JSON.SET', 'test','.', '1')) 710 r.expect('JSON.ARRPOP', 'test').error().contains("not an array") 711 712def testArrWrongChars(env): 713 r = env 714 715 r.assertOk(r.execute_command('JSON.SET', 'test','.', '{"arr":[1,2]}')) 716 r.expect('JSON.ARRINSERT', 'test', '.arr', 0, b'\x80abc').error().contains("Couldn't parse as UTF-8 string") 717 r.expect('JSON.ARRAPPEND', 'test', '.arr', b'\x80abc').error().contains("Couldn't parse as UTF-8 string") 718 719def testArrTrimErrors(env): 720 r = env 721 722 r.assertOk(r.execute_command('JSON.SET', 'test','.', '1')) 723 r.expect('JSON.ARRTRIM', 'test', '.', '0', '1').error().contains("not an array") 724 725def testTypeCommand(env): 726 """Test JSON.TYPE command""" 727 r = env 728 for k, v in iter(docs['types'].items()): 729 r.cmd('DEL', 'test') 730 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(v))) 731 reply = r.execute_command('JSON.TYPE', 'test', '.') 732 r.assertEqual(reply, k) 733 734def testLenCommands(env): 735 """Test the JSON.ARRLEN, JSON.OBJLEN and JSON.STRLEN commands""" 736 r = env 737 738 # test that nothing is returned for empty keys 739 r.assertEqual(r.execute_command('JSON.ARRLEN', 'foo', '.bar'), None) 740 741 # test elements with valid lengths 742 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(docs['basic']))) 743 r.assertEqual(r.execute_command('JSON.STRLEN', 'test', '.string'), 12) 744 r.assertEqual(r.execute_command('JSON.OBJLEN', 'test', '.dict'), 3) 745 r.assertEqual(r.execute_command('JSON.ARRLEN', 'test', '.arr'), 6) 746 747 # test elements with undefined lengths 748 r.expect('JSON.ARRLEN', 'test', '.bool').raiseError().contains("not an array") 749 r.expect('JSON.STRLEN', 'test', '.none').raiseError().contains("expected string but found null") 750 r.expect('JSON.OBJLEN', 'test', '.int').raiseError().contains("expected object but found integer") 751 r.expect('JSON.STRLEN', 'test', '.num').raiseError().contains("expected string but found number") 752 753 # test a non existing key 754 r.expect('JSON.ARRLEN', 'test', '.foo').raiseError().contains("does not exist") 755 756 # test an out of bounds index 757 r.expect('JSON.ARRLEN', 'test', '.arr[999]').raiseError().contains("does not exist") 758 759 # test an infinite index 760 r.expect('JSON.ARRLEN', 'test', '.arr[-inf]').raiseError().contains("path error") 761 r.expect('JSON.ARRLEN', 'test', '.arr[4294967295]').raiseError().contains("does not exist") 762 763def testObjKeysCommand(env): 764 """Test JSON.OBJKEYS command""" 765 r = env 766 767 r.expect('JSON.SET', 'test', '.', json.dumps(docs['types'])).ok() 768 data = r.execute_command('JSON.OBJKEYS', 'test', '.') 769 r.assertEqual(len(data), len(docs['types'])) 770 for k in data: 771 r.assertTrue(k in docs['types'], message=k) 772 773 # test a wrong type 774 r.expect('JSON.OBJKEYS', 'test', '.null').raiseError() 775 776def testNumIncrCommand(env): 777 """Test JSON.NUMINCRBY command""" 778 r = env 779 780 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{ "foo": 0, "bar": "baz" }')) 781 r.assertEqual('1', r.execute_command('JSON.NUMINCRBY', 'test', '.foo', 1)) 782 r.assertEqual('1', r.execute_command('JSON.GET', 'test', '.foo')) 783 r.assertEqual('3', r.execute_command('JSON.NUMINCRBY', 'test', '.foo', 2)) 784 r.assertEqual('3.5', r.execute_command('JSON.NUMINCRBY', 'test', '.foo', .5)) 785 786 # test a wrong type 787 r.expect('JSON.NUMINCRBY', 'test', '.bar', 1).raiseError() 788 789 # test a missing path 790 r.expect('JSON.NUMINCRBY', 'test', '.fuzz', 1).raiseError() 791 792 # test issue #9 793 r.assertOk(r.execute_command('JSON.SET', 'num', '.', '0')) 794 r.assertEqual('1', r.execute_command('JSON.NUMINCRBY', 'num', '.', 1)) 795 r.assertEqual('2.5', r.execute_command('JSON.NUMINCRBY', 'num', '.', 1.5)) 796 797 # test issue 55 798 r.assertOk(r.execute_command('JSON.SET', 'foo', '.', '{"foo":0,"bar":42}')) 799 # Get the document once 800 r.execute_command('JSON.GET', 'foo', '.') 801 r.assertEqual('1', r.execute_command('JSON.NUMINCRBY', 'foo', 'foo', 1)) 802 r.assertEqual('84', r.execute_command('JSON.NUMMULTBY', 'foo', 'bar', 2)) 803 res = json.loads(r.execute_command('JSON.GET', 'foo', '.')) 804 r.assertEqual(1, res['foo']) 805 r.assertEqual(84, res['bar']) 806 807 808def testStrCommands(env): 809 """Test JSON.STRAPPEND and JSON.STRLEN commands""" 810 r = env 811 812 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '"foo"')) 813 r.assertEqual('string', r.execute_command('JSON.TYPE', 'test', '.')) 814 r.assertEqual(3, r.execute_command('JSON.STRLEN', 'test', '.')) 815 r.assertEqual(6, r.execute_command('JSON.STRAPPEND', 'test', '.', '"bar"')) 816 r.assertEqual('"foobar"', r.execute_command('JSON.GET', 'test', '.')) 817 818def testRespCommand(env): 819 """Test JSON.RESP command""" 820 r = env 821 822 r.assertOk(r.execute_command('JSON.SET', 'test', '.', 'null')) 823# r.assertIsNone(r.execute_command('JSON.RESP', 'test')) 824# r.assertOk(r.execute_command('JSON.SET', 'test', '.', 'true')) 825# r.assertEquals('true', r.execute_command('JSON.RESP', 'test')) 826# r.assertOk(r.execute_command('JSON.SET', 'test', '.', 42)) 827# r.assertEquals(42, r.execute_command('JSON.RESP', 'test')) 828# r.assertOk(r.execute_command('JSON.SET', 'test', '.', 2.5)) 829# r.assertEquals('2.5', r.execute_command('JSON.RESP', 'test')) 830# r.assertOk(r.execute_command('JSON.SET', 'test', '.', '"foo"')) 831# r.assertEquals('foo', r.execute_command('JSON.RESP', 'test')) 832# r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{"foo":"bar"}')) 833# resp = r.execute_command('JSON.RESP', 'test') 834# r.assertEqual(2, len(resp)) 835# r.assertEqual('{', resp[0]) 836# r.assertEqual(2, len(resp[1])) 837# r.assertEqual('foo', resp[1][0]) 838# r.assertEqual('bar', resp[1][1]) 839# r.assertOk(r.execute_command('JSON.SET', 'test', '.', '[1,2]')) 840# resp = r.execute_command('JSON.RESP', 'test') 841# r.assertEqual(3, len(resp)) 842# r.assertEqual('[', resp[0]) 843# r.assertEqual(1, resp[1]) 844# r.assertEqual(2, resp[2]) 845 846# def testAllJSONCaseFiles(env): 847# """Test using all JSON test case files""" 848# r.maxDiff = None 849# with r.redis() as r: 850# r.client_setname(r._testMethodName) 851# r.flushdb() 852 853# for jsonfile in os.listdir(JSON_PATH): 854# if jsonfile.endswith('.json'): 855# path = '{}/{}'.format(JSON_PATH, jsonfile) 856# with open(path) as f: 857# value = f.read() 858# if jsonfile.startswith('pass-'): 859# r.assertOk(r.execute_command('JSON.SET', jsonfile, '.', value), path) 860# elif jsonfile.startswith('fail-'): 861# r.expect('JSON.SET', jsonfile, '.', value).raiseError() 862# assertNotExists(r, jsonfile, path) 863 864def testSetGetComparePassJSONCaseFiles(env): 865 """Test setting, getting, saving and loading passable JSON test case files""" 866 r = env 867 868 for jsonfile in os.listdir(JSON_PATH): 869 r.maxDiff = None 870 if jsonfile.startswith('pass-') and jsonfile.endswith('.json') and jsonfile not in json_ignore: 871 path = '{}/{}'.format(JSON_PATH, jsonfile) 872 r.flush() 873 with open(path) as f: 874 value = f.read() 875 r.expect('JSON.SET', jsonfile, '.', value).ok() 876 d1 = json.loads(value) 877 for _ in r.retry_with_rdb_reload(): 878 r.assertExists(jsonfile) 879 raw = r.execute_command('JSON.GET', jsonfile) 880 d2 = json.loads(raw) 881 r.assertEqual(d1, d2, message=path) 882 883def testIssue_13(env): 884 """https://github.com/RedisJSON/RedisJSON/issues/13""" 885 r = env 886 887 r.assertOk(r.execute_command('JSON.SET', 'test', '.', json.dumps(docs['simple']))) 888 # This shouldn't crash Redis 889 r.execute_command('JSON.GET', 'test', 'foo', 'foo') 890 891def testIssue_74(env): 892 """https://github.com/RedisJSON/RedisJSON2/issues/74""" 893 r = env 894 895 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '{}')) 896 # This shouldn't crash Redis 897 r.expect('JSON.SET', 'test', '$a', '12').raiseError() 898 899def testDoubleParse(env): 900 r = env 901 r.cmd('JSON.SET', 'dblNum', '.', '[1512060373.222988]') 902 res = r.cmd('JSON.GET', 'dblNum', '[0]') 903 r.assertEqual(1512060373.222988, float(res)) 904 r.assertEqual('1512060373.222988', res) 905 906def testIssue_80(env): 907 """https://github.com/RedisJSON/RedisJSON2/issues/80""" 908 r = env 909 r.assertOk(r.execute_command('JSON.SET', 'test', '.', '[{"code":"1"}, {"code":"2"}]')) 910 r.execute_command('JSON.GET', 'test', '.[?(@.code=="2")]') 911 912 # This shouldn't crash Redis 913 r.execute_command('JSON.GET', 'test', '$.[?(@.code=="2")]') 914 915 916def testMultiPathResults(env): 917 env.expect("JSON.SET", "k", '$', '[1,2,3]').ok() 918 env.expect("JSON.GET", "k", '$[*]').equal('[1,2,3]') 919 env.expect("JSON.SET", "k", '$', '{"a":[1,2,3],"b":["c","d","e"],"c":"k"}').ok() 920 env.expect("JSON.GET", "k", '$.*[0,2]').equal('[1,3,"c","e"]') 921 922 # make sure legacy json path returns single result 923 env.expect("JSON.GET", "k", '.*[0,2]').equal('1') 924 925# class CacheTestCase(BaseReJSONTest): 926# @property 927# def module_args(env): 928# return ['CACHE', 'ON'] 929# 930# def testLruCache(self): 931# def cacheItems(): 932# return getCacheInfo(r)['items'] 933# def cacheBytes(): 934# return getCacheInfo(r)['bytes'] 935# 936# r.cmd('JSON.SET', 'myDoc', '.', json.dumps({ 937# 'foo': 'fooValue', 938# 'bar': 'barValue', 939# 'baz': 'bazValue', 940# 'key\\': 'escapedKey' 941# })) 942# 943# res = r.cmd('JSON.GET', 'myDoc', 'foo') 944# r.assertEqual(1, cacheItems()) 945# r.assertEqual('"fooValue"', res) 946# r.assertEqual('"fooValue"', r.cmd('JSON.GET', 'myDoc', 'foo')) 947# r.assertEqual('"fooValue"', r.cmd('JSON.GET', 'myDoc', '.foo')) 948# # Get it again - item count should be the same 949# r.cmd('JSON.GET', 'myDoc', 'foo') 950# r.assertEqual(1, cacheItems()) 951# 952# res = r.cmd('JSON.GET', 'myDoc', '.') 953# # print repr(json.loads(res)) 954# r.assertEqual({u'bar': u'barValue', u'foo': u'fooValue', u'baz': u'bazValue', u'key\\': u'escapedKey'}, 955# json.loads(res)) 956# 957# # Try to issue multiple gets 958# r.cmd('JSON.GET', 'myDoc', '.foo') 959# r.cmd('JSON.GET', 'myDoc', 'foo') 960# r.cmd('JSON.GET', 'myDoc', '.bar') 961# r.cmd('JSON.GET', 'myDoc', 'bar') 962# 963# res = r.cmd('JSON.GET', 'myDoc', '.foo', 'foo', '.bar', 'bar', '["key\\"]') 964# # print repr(json.loads(res)) 965# r.assertEqual({u'.foo': u'fooValue', u'foo': u'fooValue', u'bar': u'barValue', u'.bar': u'barValue', u'["key\\"]': u'escapedKey'}, json.loads(res)) 966# 967# r.cmd('JSON.DEL', 'myDoc', '.') 968# r.assertEqual(0, cacheItems()) 969# r.assertEqual(0, cacheBytes()) 970# 971# # Try with an array document 972# r.cmd('JSON.SET', 'arr', '.', '[{}, 1,2,3,4]') 973# r.assertEqual('{}', r.cmd('JSON.GET', 'arr', '[0]')) 974# r.assertEqual(1, cacheItems()) 975# r.assertEqual('{}', r.cmd('JSON.GET', 'arr', '[0]')) 976# r.assertEqual(1, cacheItems()) 977# r.assertEqual('{}', r.cmd('JSON.GET', 'arr', '[0]')) 978# 979# r.assertEqual('[{},1,2,3,4]', r.cmd('JSON.GET', 'arr', '.')) 980# r.assertEqual(2, cacheItems()) 981# 982# r.cmd('JSON.SET', 'arr', '[0].key', 'null') 983# r.assertEqual(0, cacheItems()) 984# 985# r.assertEqual('null', r.cmd('JSON.GET', 'arr', '[0].key')) 986# # NULL is still not cached! 987# r.assertEqual(0, cacheItems()) 988# 989# # Try with a document that contains top level object with an array child 990# r.cmd('JSON.DEL', 'arr', '.') 991# r.cmd('JSON.SET', 'mixed', '.', '{"arr":[{},\"Hello\",2,3,null]}') 992# r.assertEqual("\"Hello\"", r.cmd('JSON.GET', 'mixed', '.arr[1]')) 993# r.assertEqual(1, cacheItems()) 994# 995# r.cmd('JSON.ARRAPPEND', 'mixed', 'arr', '42') 996# r.assertEqual(0, cacheItems()) 997# r.assertEqual("\"Hello\"", r.cmd('JSON.GET', 'mixed', 'arr[1]')) 998# 999# # Test cache eviction 1000# r.cmd('json._cacheinit', 4096, 20, 0) 1001# keys = ['json_{}'.format(x) for x in range(10)] 1002# paths = ['path_{}'.format(x) for x in xrange(100)] 1003# doc = json.dumps({ p: "some string" for p in paths}) 1004# 1005# # 100k different path/key combinations 1006# for k in keys: 1007# r.cmd('JSON.SET', k, '.', doc) 1008# 1009# # Now get 'em back all 1010# for k in keys: 1011# for p in paths: 1012# r.cmd('JSON.GET', k, p) 1013# r.assertEqual(20, cacheItems()) 1014# 1015# r.cmd('json._cacheinit') 1016 1017# class NoCacheTestCase(BaseReJSONTest): 1018# def testNoCache(self): 1019# def cacheItems(): 1020# return getCacheInfo(r)['items'] 1021# def cacheBytes(): 1022# return getCacheInfo(r)['bytes'] 1023# 1024# r.cmd('JSON.SET', 'myDoc', '.', json.dumps({ 1025# 'foo': 'fooValue', 1026# 'bar': 'barValue', 1027# 'baz': 'bazValue', 1028# 'key\\': 'escapedKey' 1029# })) 1030# 1031# res = r.cmd('JSON.GET', 'myDoc', 'foo') 1032# r.assertEqual(0, cacheItems()) 1033