mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-13 22:41:57 +00:00
298 lines
12 KiB
YAML
298 lines
12 KiB
YAML
desc: Tests RQL control flow structures
|
|
table_variable_name: tbl, tbl2
|
|
tests:
|
|
|
|
## FunCall
|
|
|
|
- py: r.expr(1).do(lambda v: v * 2)
|
|
js: r.expr(1).do(function(v) { return v.mul(2); })
|
|
rb: r.expr(1).do{|v| v * 2 }
|
|
ot: 2
|
|
|
|
- py: r.expr([0, 1, 2]).do(lambda v: v.append(3))
|
|
js: r([0, 1, 2]).do(function(v) { return v.append(3); })
|
|
rb: r([0, 1, 2]).do{ |v| v.append(3) }
|
|
ot: [0, 1, 2, 3]
|
|
|
|
- py: r.do(1, 2, lambda x, y: x + y)
|
|
js: r.do(1, 2, function(x, y) { return x.add(y); })
|
|
rb: r.do(1, 2) {|x, y| x + y}
|
|
ot: 3
|
|
|
|
- py: r.do(lambda: 1)
|
|
js: r.do(function() { return 1; })
|
|
rb: r.do{1}
|
|
ot: 1
|
|
|
|
# do error cases
|
|
- py: r.do(1, 2, lambda x: x)
|
|
js: r.do(1, 2, function(x) { return x; })
|
|
rb: r.do(1, 2) {|x| x}
|
|
ot: err("ReqlQueryLogicError", 'Expected function with 2 arguments but found function with 1 argument.', [1])
|
|
|
|
- py: r.do(1, 2, 3, lambda x, y: x + y)
|
|
js: r.do(1, 2, 3, function(x, y) { return x.add(y); })
|
|
rb: r.do(1, 2, 3) {|x, y| x + y}
|
|
ot: err("ReqlQueryLogicError", 'Expected function with 3 arguments but found function with 2 arguments.', [1])
|
|
|
|
- cd: r.do(1)
|
|
ot: 1
|
|
|
|
- js: r.do(1, function(x) {})
|
|
ot: err("ReqlDriverCompileError", 'Anonymous function returned `undefined`. Did you forget a `return`?', [1])
|
|
|
|
- js: r.do(1, function(x) { return undefined; })
|
|
ot: err("ReqlDriverCompileError", 'Anonymous function returned `undefined`. Did you forget a `return`?', [1])
|
|
|
|
- cd: r.do()
|
|
ot:
|
|
cd: err("ReqlCompileError", 'Expected 1 or more arguments but found 0.', [1])
|
|
|
|
# FunCall errors
|
|
|
|
- py: r.expr('abc').do(lambda v: v.append(3))
|
|
js: r('abc').do(function(v) { return v.append(3); })
|
|
rb: r('abc').do{ |v| v.append(3) }
|
|
ot: err("ReqlQueryLogicError", "Expected type ARRAY but found STRING.", [1, 0])
|
|
|
|
- py: r.expr('abc').do(lambda v: v + 3)
|
|
js: r('abc').do(function(v) { return v.add(3); })
|
|
rb: r('abc').do{ |v| v + 3 }
|
|
ot: err("ReqlQueryLogicError", "Expected type STRING but found NUMBER.", [1, 1])
|
|
|
|
- py: r.expr('abc').do(lambda v: v + 'def') + 3
|
|
js: r('abc').do(function(v) { return v.add('def'); }).add(3)
|
|
rb: r('abc').do{ |v| v + 'def' } + 3
|
|
ot: err("ReqlQueryLogicError", "Expected type STRING but found NUMBER.", [1])
|
|
|
|
- py: r.expr(0).do(lambda a,b: a + b)
|
|
js: r(0).do(function(a,b) { return a.add(b); })
|
|
rb: r(0).do{ |a, b| a + b }
|
|
ot: err("ReqlQueryLogicError", 'Expected function with 1 argument but found function with 2 arguments.', [1])
|
|
|
|
- py: r.do(1, 2, lambda a: a)
|
|
js: r.do(1,2, function(a) { return a; })
|
|
rb: r.do(1, 2) { |a| a }
|
|
ot: err("ReqlQueryLogicError", 'Expected function with 2 arguments but found function with 1 argument.', [1])
|
|
|
|
- cd: r.expr(5).do(r.row)
|
|
rb: r(5).do{ |row| row }
|
|
ot: 5
|
|
|
|
## Branch
|
|
|
|
- cd: r.branch(True, 1, 2)
|
|
ot: 1
|
|
- cd: r.branch(False, 1, 2)
|
|
ot: 2
|
|
- cd: r.branch(1, 'c', False)
|
|
ot: ("c")
|
|
- cd: r.branch(null, {}, [])
|
|
ot: ([])
|
|
|
|
- cd: r.branch(r.db('test'), 1, 2)
|
|
ot: err("ReqlQueryLogicError", "Expected type DATUM but found DATABASE:", [])
|
|
- cd: r.branch(tbl, 1, 2)
|
|
ot: err("ReqlQueryLogicError", "Expected type DATUM but found TABLE:", [])
|
|
- cd: r.branch(r.error("a"), 1, 2)
|
|
ot: err("ReqlUserError", "a", [])
|
|
|
|
- cd: r.branch([], 1, 2)
|
|
ot: 1
|
|
- cd: r.branch({}, 1, 2)
|
|
ot: 1
|
|
- cd: r.branch("a", 1, 2)
|
|
ot: 1
|
|
- cd: r.branch(1.2, 1, 2)
|
|
ot: 1
|
|
|
|
- cd: r.branch(True, 1, True, 2, 3)
|
|
ot: 1
|
|
- cd: r.branch(True, 1, False, 2, 3)
|
|
ot: 1
|
|
- cd: r.branch(False, 1, True, 2, 3)
|
|
ot: 2
|
|
- cd: r.branch(False, 1, False, 2, 3)
|
|
ot: 3
|
|
|
|
- cd: r.branch(True, 1, True, 2)
|
|
ot: err("ReqlQueryLogicError", "Cannot call `branch` term with an even number of arguments.")
|
|
|
|
# r.error()
|
|
- cd: r.error('Hello World')
|
|
ot: err("ReqlUserError", "Hello World", [0])
|
|
|
|
- cd: r.error(5)
|
|
# we might want to allow this eventually
|
|
ot: err("ReqlQueryLogicError", "Expected type STRING but found NUMBER.", [0])
|
|
|
|
# r.filter
|
|
- cd: r.expr([1, 2, 3]).filter()
|
|
ot:
|
|
cd: err("ReqlCompileError", "Expected 2 arguments but found 1.", [0])
|
|
js: err("ReqlCompileError", "Expected 1 argument (not including options) but found 0.", [0])
|
|
- cd: r.expr([1, 2, 3]).filter(1, 2)
|
|
ot:
|
|
cd: err("ReqlCompileError", "Expected 2 arguments but found 3.", [0])
|
|
js: err("ReqlCompileError", "Expected 1 argument (not including options) but found 2.", [0])
|
|
|
|
# r.js()
|
|
- cd: r.js('1 + 1')
|
|
ot: 2
|
|
|
|
- cd: r.js('1 + 1; 2 + 2')
|
|
ot: 4
|
|
|
|
- cd: r.do(1, 2, r.js('(function(a, b) { return a + b; })'))
|
|
ot: 3
|
|
|
|
- cd: r.expr(1).do(r.js('(function(x) { return x + 1; })'))
|
|
ot: 2
|
|
|
|
- cd: r.expr('foo').do(r.js('(function(x) { return x + "bar"; })'))
|
|
ot: 'foobar'
|
|
|
|
# js timeout optarg shouldn't be triggered
|
|
- cd: r.js('1 + 2', {timeout:1.2})
|
|
py: r.js('1 + 2', timeout=1.2)
|
|
ot: 3
|
|
|
|
# js error cases
|
|
- cd: r.js('(function() { return 1; })')
|
|
ot: err("ReqlQueryLogicError", "Query result must be of type DATUM, GROUPED_DATA, or STREAM (got FUNCTION).", [0])
|
|
|
|
- cd: r.js('function() { return 1; }')
|
|
ot: err("ReqlQueryLogicError", "SyntaxError: Unexpected token (", [0])
|
|
|
|
# Play with the number of arguments in the JS function
|
|
- cd: r.do(1, 2, r.js('(function(a) { return a; })'))
|
|
ot: 1
|
|
|
|
- cd: r.do(1, 2, r.js('(function(a, b, c) { return a; })'))
|
|
ot: 1
|
|
|
|
- cd: r.do(1, 2, r.js('(function(a, b, c) { return c; })'))
|
|
ot: err("ReqlQueryLogicError", "Cannot convert javascript `undefined` to ql::datum_t.", [0])
|
|
|
|
- cd: r.expr([1, 2, 3]).filter(r.js('(function(a) { return a >= 2; })'))
|
|
ot: ([2, 3])
|
|
|
|
- cd: r.expr([1, 2, 3]).map(r.js('(function(a) { return a + 1; })'))
|
|
ot: ([2, 3, 4])
|
|
|
|
- cd: r.expr([1, 2, 3]).map(r.js('1'))
|
|
ot: err("ReqlQueryLogicError", "Expected type FUNCTION but found DATUM:", [0])
|
|
|
|
- cd: r.expr([1, 2, 3]).filter(r.js('(function(a) {})'))
|
|
ot: err("ReqlQueryLogicError", "Cannot convert javascript `undefined` to ql::datum_t.", [0])
|
|
|
|
# What happens if we pass static values to things that expect functions
|
|
- cd: r.expr([1, 2, 3]).map(1)
|
|
ot: err("ReqlQueryLogicError", "Expected type FUNCTION but found DATUM:", [0])
|
|
|
|
- cd: r.expr([1, 2, 3]).filter('foo')
|
|
ot: ([1, 2, 3])
|
|
- cd: r.expr([1, 2, 4]).filter([])
|
|
ot: ([1, 2, 4])
|
|
- cd: r.expr([1, 2, 3]).filter(null)
|
|
ot: ([])
|
|
|
|
- cd: r.expr([1, 2, 4]).filter(False)
|
|
rb: r([1, 2, 4]).filter(false)
|
|
ot: ([])
|
|
|
|
# forEach
|
|
- cd: tbl.count()
|
|
ot: 0
|
|
|
|
# Insert three elements
|
|
- js: r([1, 2, 3]).forEach(function (row) { return tbl.insert({ id:row }) })
|
|
py: r.expr([1, 2, 3]).for_each(lambda row:tbl.insert({ 'id':row }))
|
|
rb: r([1, 2, 3]).for_each{ |row| tbl.insert({ :id => row }) }
|
|
ot: ({'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':3})
|
|
|
|
- cd: tbl.count()
|
|
ot: 3
|
|
|
|
# Update each row to add additional attribute
|
|
- js: r([1, 2, 3]).forEach(function (row) { return tbl.update({ foo:row }) })
|
|
py: r.expr([1,2,3]).for_each(lambda row:tbl.update({'foo':row}))
|
|
rb: r.expr([1,2,3]).for_each{ |row| tbl.update({ :foo => row }) }
|
|
ot: ({'deleted':0.0,'replaced':9,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':0.0})
|
|
|
|
# Insert three more elements (and error on three)
|
|
- js: r([1, 2, 3]).forEach(function (row) { return [tbl.insert({ id:row }), tbl.insert({ id:row.mul(10) })] })
|
|
py: r.expr([1,2,3]).for_each(lambda row:[tbl.insert({ 'id':row }), tbl.insert({ 'id':row*10 })])
|
|
rb: r.expr([1,2,3]).for_each{ |row| [tbl.insert({ :id => row}), tbl.insert({ :id => row*10})] }
|
|
ot: {'first_error':"Duplicate primary key `id`:\n{\n\t\"foo\":\t3,\n\t\"id\":\t1\n}\n{\n\t\"id\":\t1\n}",'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':3,'skipped':0.0,'inserted':3}
|
|
|
|
- cd: tbl.count()
|
|
ot: 6
|
|
|
|
- cd: tableCount = tbl2.count()
|
|
- cd: r.expr([1, 2, 3]).for_each( tbl2.insert({}) )
|
|
ot: ({'deleted':0.0,'replaced':0.0,'generated_keys':arrlen(3,uuid()),'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':3})
|
|
# inserts only a single document per #3700
|
|
- cd: tbl2.count()
|
|
ot: tableCount + 1
|
|
|
|
# We have six elements, update them 6*2*3=36 times
|
|
- js: r([1, 2, 3]).forEach(function (row) { return [tbl.update({ foo:row }), tbl.update({ bar:row })] })
|
|
py: r.expr([1,2,3]).for_each(lambda row:[tbl.update({'foo':row}), tbl.update({'bar':row})])
|
|
rb: r.expr([1,2,3]).for_each{ |row| [tbl.update({:foo => row}), tbl.update({:bar => row})]}
|
|
ot: ({'deleted':0.0,'replaced':36,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':0.0})
|
|
|
|
# forEach negative cases
|
|
- cd: r.expr([1, 2, 3]).for_each( tbl2.insert({ 'id':r.row }) )
|
|
rb: r([1, 2, 3]).for_each{ |row| tbl2.insert({ 'id':row }) }
|
|
ot: ({'deleted':0.0,'replaced':0.0,'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':3})
|
|
|
|
- cd: r.expr([1, 2, 3]).for_each(1)
|
|
ot: err("ReqlQueryLogicError", "FOR_EACH expects one or more basic write queries. Expected type ARRAY but found NUMBER.", [0])
|
|
|
|
- py: r.expr([1, 2, 3]).for_each(lambda x:x)
|
|
js: r([1, 2, 3]).forEach(function (x) { return x; })
|
|
rb: r([1, 2, 3]).for_each{ |x| x }
|
|
ot: err("ReqlQueryLogicError", "FOR_EACH expects one or more basic write queries. Expected type ARRAY but found NUMBER.", [1, 1])
|
|
|
|
- cd: r.expr([1, 2, 3]).for_each(r.row)
|
|
rb: r([1, 2, 3]).for_each{ |row| row }
|
|
ot: err("ReqlQueryLogicError", "FOR_EACH expects one or more basic write queries. Expected type ARRAY but found NUMBER.", [1, 1])
|
|
|
|
- js: r([1, 2, 3]).forEach(function (row) { return tbl; })
|
|
py: r.expr([1, 2, 3]).for_each(lambda row:tbl)
|
|
rb: r([1, 2, 3]).for_each{ |row| tbl }
|
|
ot: err("ReqlQueryLogicError", "FOR_EACH expects one or more basic write queries.", [1, 1])
|
|
|
|
# This is only relevant in JS -- what happens when we return undefined
|
|
- js: r([1, 2, 3]).forEach(function (row) {})
|
|
ot: err("ReqlDriverCompileError", 'Anonymous function returned `undefined`. Did you forget a `return`?', [1])
|
|
|
|
# Make sure write queries can't be nested into stream ops
|
|
- cd: r.expr(1).do(tbl.insert({'foo':r.row}))
|
|
rb: r(1).do{ |row| tbl.insert({ :foo => row }) }
|
|
ot: ({'deleted':0.0,'replaced':0.0,'generated_keys':arrlen(1,uuid()),'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':1})
|
|
|
|
- py: r.expr([1, 2])[0].do(tbl.insert({'foo':r.row}))
|
|
js: r.expr([1, 2]).nth(0).do(tbl.insert({'foo':r.row}))
|
|
rb: r([1, 2])[0].do{ |row| tbl.insert({ :foo => row }) }
|
|
ot: ({'deleted':0.0,'replaced':0.0,'generated_keys':arrlen(1,uuid()),'unchanged':0.0,'errors':0.0,'skipped':0.0,'inserted':1})
|
|
|
|
- cd: r.expr([1, 2]).map(tbl.insert({'foo':r.row}))
|
|
rb: r([1, 2]).map{ |row| tbl.insert({ :foo => row }) }
|
|
ot: err('ReqlCompileError', 'Cannot nest writes or meta ops in stream operations. Use FOR_EACH instead.', [0])
|
|
|
|
- cd: r.expr([1, 2]).map(r.db('test').table_create('table_create_failure'))
|
|
ot: err('ReqlCompileError', 'Cannot nest writes or meta ops in stream operations. Use FOR_EACH instead.', [0])
|
|
|
|
- cd: r.expr([1, 2]).map(tbl.insert({'foo':r.row}).get_field('inserted'))
|
|
rb: r.expr([1, 2]).map{|x| tbl.insert({'foo':x}).get_field('inserted')}
|
|
ot: err('ReqlCompileError', 'Cannot nest writes or meta ops in stream operations. Use FOR_EACH instead.', [0])
|
|
|
|
- cd: r.expr([1, 2]).map(tbl.insert({'foo':r.row}).get_field('inserted').add(5))
|
|
rb: r.expr([1, 2]).map{|x| tbl.insert({'foo':x}).get_field('inserted').add(5)}
|
|
ot: err('ReqlCompileError', 'Cannot nest writes or meta ops in stream operations. Use FOR_EACH instead.', [0])
|
|
|
|
- cd: r.expr(1).do(r.db('test').table_create('table_create_success'))
|
|
ot: partial({'tables_created':1})
|