github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/testdata/lua-5.3.3-tests/closure.lua (about) 1 -- $Id: closure.lua,v 1.58 2014/12/26 17:20:53 roberto Exp $ 2 3 print "testing closures" 4 5 local A,B = 0,{g=10} 6 function f(x) 7 local a = {} 8 for i=1,1000 do 9 local y = 0 10 do 11 a[i] = function () B.g = B.g+1; y = y+x; return y+A end 12 end 13 end 14 local dummy = function () return a[A] end 15 collectgarbage() 16 A = 1; assert(dummy() == a[1]); A = 0; 17 assert(a[1]() == x) 18 assert(a[3]() == x) 19 collectgarbage() 20 assert(B.g == 12) 21 return a 22 end 23 24 local a = f(10) 25 -- TODO or spec: weak tables are not supported 26 -- force a GC in this level 27 -- local x = {[1] = {}} -- to detect a GC 28 -- setmetatable(x, {__mode = 'kv'}) 29 -- while x[1] do -- repeat until GC 30 -- local a = A..A..A..A -- create garbage 31 -- A = A+1 32 -- end 33 -- assert(a[1]() == 20+A) 34 -- assert(a[1]() == 30+A) 35 -- assert(a[2]() == 10+A) 36 -- collectgarbage() 37 -- assert(a[2]() == 20+A) 38 -- assert(a[2]() == 30+A) 39 -- assert(a[3]() == 20+A) 40 -- assert(a[8]() == 10+A) 41 -- assert(getmetatable(x).__mode == 'kv') 42 -- assert(B.g == 19) 43 44 45 -- testing equality 46 a = {} 47 for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end 48 assert(a[3] == a[4] and a[4] == a[5]) 49 50 for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end 51 assert(a[3] ~= a[4] and a[4] ~= a[5]) 52 53 local function f() 54 return function (x) return math.sin(_ENV[x]) end 55 end 56 assert(f() == f()) 57 58 59 -- testing closures with 'for' control variable 60 a = {} 61 for i=1,10 do 62 a[i] = {set = function(x) i=x end, get = function () return i end} 63 if i == 3 then break end 64 end 65 assert(a[4] == nil) 66 a[1].set(10) 67 assert(a[2].get() == 2) 68 a[2].set('a') 69 assert(a[3].get() == 3) 70 assert(a[2].get() == 'a') 71 72 a = {} 73 local t = {"a", "b"} 74 for i = 1, #t do 75 local k = t[i] 76 a[i] = {set = function(x, y) i=x; k=y end, 77 get = function () return i, k end} 78 if i == 2 then break end 79 end 80 a[1].set(10, 20) 81 local r,s = a[2].get() 82 assert(r == 2 and s == 'b') 83 r,s = a[1].get() 84 assert(r == 10 and s == 20) 85 a[2].set('a', 'b') 86 r,s = a[2].get() 87 assert(r == "a" and s == "b") 88 89 90 -- testing closures with 'for' control variable x break 91 for i=1,3 do 92 f = function () return i end 93 break 94 end 95 assert(f() == 1) 96 97 for k = 1, #t do 98 local v = t[k] 99 f = function () return k, v end 100 break 101 end 102 assert(({f()})[1] == 1) 103 assert(({f()})[2] == "a") 104 105 106 -- testing closure x break x return x errors 107 108 local b 109 function f(x) 110 local first = 1 111 while 1 do 112 if x == 3 and not first then return end 113 local a = 'xuxu' 114 b = function (op, y) 115 if op == 'set' then 116 a = x+y 117 else 118 return a 119 end 120 end 121 if x == 1 then do break end 122 elseif x == 2 then return 123 else if x ~= 3 then error() end 124 end 125 first = nil 126 end 127 end 128 129 for i=1,3 do 130 f(i) 131 assert(b('get') == 'xuxu') 132 b('set', 10); assert(b('get') == 10+i) 133 b = nil 134 end 135 136 pcall(f, 4); 137 assert(b('get') == 'xuxu') 138 b('set', 10); assert(b('get') == 14) 139 140 141 local w 142 -- testing multi-level closure 143 function f(x) 144 return function (y) 145 return function (z) return w+x+y+z end 146 end 147 end 148 149 y = f(10) 150 w = 1.345 151 assert(y(20)(30) == 60+w) 152 153 -- testing closures x repeat-until 154 155 local a = {} 156 local i = 1 157 repeat 158 local x = i 159 a[i] = function () i = x+1; return x end 160 until i > 10 or a[i]() ~= x 161 assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4) 162 163 164 -- testing closures created in 'then' and 'else' parts of 'if's 165 a = {} 166 for i = 1, 10 do 167 if i % 3 == 0 then 168 local y = 0 169 a[i] = function (x) local t = y; y = x; return t end 170 elseif i % 3 == 1 then 171 goto L1 172 error'not here' 173 ::L1:: 174 local y = 1 175 a[i] = function (x) local t = y; y = x; return t end 176 elseif i % 3 == 2 then 177 local t 178 goto l4 179 ::l4a:: a[i] = t; goto l4b 180 error("should never be here!") 181 ::l4:: 182 local y = 2 183 t = function (x) local t = y; y = x; return t end 184 goto l4a 185 error("should never be here!") 186 ::l4b:: 187 end 188 end 189 190 for i = 1, 10 do 191 assert(a[i](i * 10) == i % 3 and a[i]() == i * 10) 192 end 193 194 print'+' 195 196 197 -- test for correctly closing upvalues in tail calls of vararg functions 198 local function t () 199 local function c(a,b) assert(a=="test" and b=="OK") end 200 local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end 201 local x = 1 202 return v(function() return x end) 203 end 204 t() 205 206 207 -- test for debug manipulation of upvalues 208 local debug = require'debug' 209 210 do 211 local a , b, c = 3, 5, 7 212 foo1 = function () return a+b end; 213 foo2 = function () return b+a end; 214 do 215 local a = 10 216 foo3 = function () return a+b end; 217 end 218 end 219 220 assert(debug.upvalueid(foo1, 1)) 221 assert(debug.upvalueid(foo1, 2)) 222 assert(not pcall(debug.upvalueid, foo1, 3)) 223 assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) 224 assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) 225 assert(debug.upvalueid(foo3, 1)) 226 assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1)) 227 assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2)) 228 229 -- TODO or spec: no plan to support upvalues for GoFunction 230 -- assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil) 231 232 assert(foo1() == 3 + 5 and foo2() == 5 + 3) 233 debug.upvaluejoin(foo1, 2, foo2, 2) 234 assert(foo1() == 3 + 3 and foo2() == 5 + 3) 235 assert(foo3() == 10 + 5) 236 debug.upvaluejoin(foo3, 2, foo2, 1) 237 assert(foo3() == 10 + 5) 238 debug.upvaluejoin(foo3, 2, foo2, 2) 239 assert(foo3() == 10 + 3) 240 241 assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1)) 242 assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3)) 243 assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1)) 244 assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1)) 245 assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1)) 246 assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1)) 247 248 print'OK'