1# LYAML binding for Lua 5.1, 5.2, 5.3 & 5.4 2# Copyright (C) 2013-2022 Gary V. Vaughan 3 4before: 5 this_module = 'lyaml.functional' 6 global_table = '_G' 7 8 exported_apis = {'NULL', 'anyof', 'id', 'iscallable', 'isnull'} 9 10 M = require(this_module) 11 12 nop = function() end 13 14 fail = function() return nil end 15 pass = function() return false end 16 throw = function() error 'oh noes!' end 17 18 parmlist = pack( 19 nil, 20 false, 21 42, 22 'str', 23 io.stderr, 24 {}, 25 nop, 26 setmetatable({}, {__call=nop}) 27 ) 28 29 30specify functional: 31- context when required: 32 - context by name: 33 - it does not touch the global table: 34 expect(show_apis{added_to=global_table, by=this_module}).to_equal{} 35 - it exports the decumented apis: 36 t = {} 37 for k in pairs(M) do t[#t + 1] = k end 38 expect(t).to_contain.a_permutation_of(exported_apis) 39 40 41- describe anyof: 42 - before: 43 f = M.anyof 44 45 - it returns a callable: 46 expect(f{nop}).to_be_callable() 47 expect(f{nop, nop}).to_be_callable() 48 - it returns a lazy function that calls arguments if necessary: 49 expect(f{pass, throw}()).not_to_raise 'any error' 50 expect(f{pass, throw}()).not_to_be(nil) 51 - it silently skips non-callable arguments: 52 expect(f(list({nil, false, true}))()).to_be(nil) 53 expect(f{1, 2, pass, 'pass'}()).not_to_be(nil) 54 - it returns non-nil if any callable returns non-nil: 55 expect(f{pass, pass, fail}()).not_to_be(nil) 56 expect(f{pass, fail}()).not_to_be(nil) 57 expect(f{fail, pass}()).not_to_be(nil) 58 - it returns nil if all callables are nil: 59 expect(f{fail}()).to_be(nil) 60 expect(f{fail, fail}()).to_be(nil) 61 expect(f{fail, fail, fail}()).to_be(nil) 62 - it propagates data to all callables: 63 expect(f{fail, function(...) return select('#', ...) end}(nil)).to_be(1) 64 expect(f{function(...) return select('#', ...) end, fail}(nil, false)).to_be(2) 65 expect(f{function(...) return select('#', ...) end, pass}(nil, false)).to_be(2) 66 - it returns the first non-nil callables result: 67 expect(f{fail, function(...) return ... end}(42)).to_be(42) 68 expect(f{function(...) return ... end, fail}(42)).to_be(42) 69 expect(f{pass, fail}(42)).to_be(false) 70 expect(f{fail, pass}(42)).to_be(false) 71 - it propagates only the first return value: 72 expect(f{fail, function(...) return ... end}(1, 2, 5)).to_be(1) 73 expect(f{function(...) return ... end, fail}(1, 2, 5)).to_be(1) 74 expect(f{function(...) return ... end, pass}(1, 2, 5)).to_be(1) 75 76 77- describe id: 78 - before: 79 f = M.id 80 81 - it returns its own argument: 82 expect(f(false)).to_be(false) 83 expect(f(42)).to_be(42) 84 - it handles nil argumen: 85 expect(f(nil)).to_be(nil) 86 - it handles missing argument: 87 expect(f()).to_be() 88 - it returns multiple arguments: 89 expect(f(nil, 1, fn, false, nil)).to_be(nil, 1, fn, false, nil) 90 91 92- describe iscallable: 93 - before: 94 f = M.iscallable 95 96 - it returns callable for a callable: 97 expect(f(f)).to_be(f) 98 expect(f(setmetatable({}, {__call=f}))).to_be(f) 99 - it returns nil for a non-callable: 100 expect(f()).to_be(nil) 101 expect(f(nil)).to_be(nil) 102 expect(f(false)).to_be(nil) 103 expect(f(true)).to_be(nil) 104 expect(f'str').to_be(nil) 105 expect(f(42)).to_be(nil) 106 expect(f(setmetatable({}, {__index={}}))).to_be(nil) 107 expect(f(setmetatable({}, {__call=42}))).to_be(nil) 108 109 110- describe isnull: 111 - before: 112 NULL = M.NULL 113 f = M.isnull 114 115 - it returns 'true' for a NULL argument: 116 expect(f(NULL)).to_be(true) 117 - it returns 'false' for any argument other than NULL: 118 for i=1,parmlist.n do 119 expect(f(parmlist[i])).to_be(false) 120 end 121 122