diff options
Diffstat (limited to 'testes/events.lua')
-rw-r--r-- | testes/events.lua | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/testes/events.lua b/testes/events.lua new file mode 100644 index 00000000..cf064d3d --- /dev/null +++ b/testes/events.lua | |||
@@ -0,0 +1,476 @@ | |||
1 | -- $Id: events.lua,v 1.52 2018/03/12 13:51:02 roberto Exp $ | ||
2 | -- See Copyright Notice in file all.lua | ||
3 | |||
4 | print('testing metatables') | ||
5 | |||
6 | local debug = require'debug' | ||
7 | |||
8 | X = 20; B = 30 | ||
9 | |||
10 | _ENV = setmetatable({}, {__index=_G}) | ||
11 | |||
12 | collectgarbage() | ||
13 | |||
14 | X = X+10 | ||
15 | assert(X == 30 and _G.X == 20) | ||
16 | B = false | ||
17 | assert(B == false) | ||
18 | _ENV["B"] = undef | ||
19 | assert(B == 30) | ||
20 | |||
21 | assert(getmetatable{} == nil) | ||
22 | assert(getmetatable(4) == nil) | ||
23 | assert(getmetatable(nil) == nil) | ||
24 | a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu", | ||
25 | __tostring=function(x) return x.name end}) | ||
26 | assert(getmetatable(a) == "xuxu") | ||
27 | assert(tostring(a) == "NAME") | ||
28 | -- cannot change a protected metatable | ||
29 | assert(pcall(setmetatable, a, {}) == false) | ||
30 | a.name = "gororoba" | ||
31 | assert(tostring(a) == "gororoba") | ||
32 | |||
33 | local a, t = {10,20,30; x="10", y="20"}, {} | ||
34 | assert(setmetatable(a,t) == a) | ||
35 | assert(getmetatable(a) == t) | ||
36 | assert(setmetatable(a,nil) == a) | ||
37 | assert(getmetatable(a) == nil) | ||
38 | assert(setmetatable(a,t) == a) | ||
39 | |||
40 | |||
41 | function f (t, i, e) | ||
42 | assert(not e) | ||
43 | local p = rawget(t, "parent") | ||
44 | return (p and p[i]+3), "dummy return" | ||
45 | end | ||
46 | |||
47 | t.__index = f | ||
48 | |||
49 | a.parent = {z=25, x=12, [4] = 24} | ||
50 | assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10") | ||
51 | |||
52 | collectgarbage() | ||
53 | |||
54 | a = setmetatable({}, t) | ||
55 | function f(t, i, v) rawset(t, i, v-3) end | ||
56 | setmetatable(t, t) -- causes a bug in 5.1 ! | ||
57 | t.__newindex = f | ||
58 | a[1] = 30; a.x = "101"; a[5] = 200 | ||
59 | assert(a[1] == 27 and a.x == 98 and a[5] == 197) | ||
60 | |||
61 | do -- bug in Lua 5.3.2 | ||
62 | local mt = {} | ||
63 | mt.__newindex = mt | ||
64 | local t = setmetatable({}, mt) | ||
65 | t[1] = 10 -- will segfault on some machines | ||
66 | assert(mt[1] == 10) | ||
67 | end | ||
68 | |||
69 | |||
70 | local c = {} | ||
71 | a = setmetatable({}, t) | ||
72 | t.__newindex = c | ||
73 | t.__index = c | ||
74 | a[1] = 10; a[2] = 20; a[3] = 90; | ||
75 | for i = 4, 20 do a[i] = i * 10 end | ||
76 | assert(a[1] == 10 and a[2] == 20 and a[3] == 90) | ||
77 | for i = 4, 20 do assert(a[i] == i * 10) end | ||
78 | assert(next(a) == nil) | ||
79 | |||
80 | |||
81 | do | ||
82 | local a; | ||
83 | a = setmetatable({}, {__index = setmetatable({}, | ||
84 | {__index = setmetatable({}, | ||
85 | {__index = function (_,n) return a[n-3]+4, "lixo" end})})}) | ||
86 | a[0] = 20 | ||
87 | for i=0,10 do | ||
88 | assert(a[i*3] == 20 + i*4) | ||
89 | end | ||
90 | end | ||
91 | |||
92 | |||
93 | do -- newindex | ||
94 | local foi | ||
95 | local a = {} | ||
96 | for i=1,10 do a[i] = 0; a['a'..i] = 0; end | ||
97 | setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end}) | ||
98 | foi = false; a[1]=0; assert(not foi) | ||
99 | foi = false; a['a1']=0; assert(not foi) | ||
100 | foi = false; a['a11']=0; assert(foi) | ||
101 | foi = false; a[11]=0; assert(foi) | ||
102 | foi = false; a[1]=undef; assert(not foi) | ||
103 | a[1] = undef | ||
104 | foi = false; a[1]=nil; assert(foi) | ||
105 | end | ||
106 | |||
107 | |||
108 | setmetatable(t, nil) | ||
109 | function f (t, ...) return t, {...} end | ||
110 | t.__call = f | ||
111 | |||
112 | do | ||
113 | local x,y = a(table.unpack{'a', 1}) | ||
114 | assert(x==a and y[1]=='a' and y[2]==1 and y[3]==undef) | ||
115 | x,y = a() | ||
116 | assert(x==a and y[1]==undef) | ||
117 | end | ||
118 | |||
119 | |||
120 | local b = setmetatable({}, t) | ||
121 | setmetatable(b,t) | ||
122 | |||
123 | function f(op) | ||
124 | return function (...) cap = {[0] = op, ...} ; return (...) end | ||
125 | end | ||
126 | t.__add = f("add") | ||
127 | t.__sub = f("sub") | ||
128 | t.__mul = f("mul") | ||
129 | t.__div = f("div") | ||
130 | t.__idiv = f("idiv") | ||
131 | t.__mod = f("mod") | ||
132 | t.__unm = f("unm") | ||
133 | t.__pow = f("pow") | ||
134 | t.__len = f("len") | ||
135 | t.__band = f("band") | ||
136 | t.__bor = f("bor") | ||
137 | t.__bxor = f("bxor") | ||
138 | t.__shl = f("shl") | ||
139 | t.__shr = f("shr") | ||
140 | t.__bnot = f("bnot") | ||
141 | |||
142 | -- Some tests are done inside small anonymous functions to ensure | ||
143 | -- that constants go to constant table even in debug compilation, | ||
144 | -- when the constant table is very small. | ||
145 | assert(b+5 == b) | ||
146 | assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==undef) | ||
147 | assert(b+'5' == b) | ||
148 | assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==undef) | ||
149 | assert(5+b == 5) | ||
150 | assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==undef) | ||
151 | assert('5'+b == '5') | ||
152 | assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==undef) | ||
153 | b=b-3; assert(getmetatable(b) == t) | ||
154 | assert(cap[0] == "sub" and cap[1] == b and cap[2] == 3 and cap[3]==undef) | ||
155 | assert(5-a == 5) | ||
156 | assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==undef) | ||
157 | assert('5'-a == '5') | ||
158 | assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==undef) | ||
159 | assert(a*a == a) | ||
160 | assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==undef) | ||
161 | assert(a/0 == a) | ||
162 | assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==undef) | ||
163 | assert(a%2 == a) | ||
164 | assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==undef) | ||
165 | assert(a // (1/0) == a) | ||
166 | assert(cap[0] == "idiv" and cap[1] == a and cap[2] == 1/0 and cap[3]==undef) | ||
167 | ;(function () assert(a & "hi" == a) end)() | ||
168 | assert(cap[0] == "band" and cap[1] == a and cap[2] == "hi" and cap[3]==undef) | ||
169 | ;(function () assert(10 & a == 10) end)() | ||
170 | assert(cap[0] == "band" and cap[1] == 10 and cap[2] == a and cap[3]==undef) | ||
171 | ;(function () assert(a | 10 == a) end)() | ||
172 | assert(cap[0] == "bor" and cap[1] == a and cap[2] == 10 and cap[3]==undef) | ||
173 | assert(a | "hi" == a) | ||
174 | assert(cap[0] == "bor" and cap[1] == a and cap[2] == "hi" and cap[3]==undef) | ||
175 | assert("hi" ~ a == "hi") | ||
176 | assert(cap[0] == "bxor" and cap[1] == "hi" and cap[2] == a and cap[3]==undef) | ||
177 | ;(function () assert(10 ~ a == 10) end)() | ||
178 | assert(cap[0] == "bxor" and cap[1] == 10 and cap[2] == a and cap[3]==undef) | ||
179 | assert(-a == a) | ||
180 | assert(cap[0] == "unm" and cap[1] == a) | ||
181 | assert(a^4 == a) | ||
182 | assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==undef) | ||
183 | assert(a^'4' == a) | ||
184 | assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==undef) | ||
185 | assert(4^a == 4) | ||
186 | assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==undef) | ||
187 | assert('4'^a == '4') | ||
188 | assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==undef) | ||
189 | assert(#a == a) | ||
190 | assert(cap[0] == "len" and cap[1] == a) | ||
191 | assert(~a == a) | ||
192 | assert(cap[0] == "bnot" and cap[1] == a) | ||
193 | assert(a << 3 == a) | ||
194 | assert(cap[0] == "shl" and cap[1] == a and cap[2] == 3) | ||
195 | assert(1.5 >> a == 1.5) | ||
196 | assert(cap[0] == "shr" and cap[1] == 1.5 and cap[2] == a) | ||
197 | |||
198 | |||
199 | -- test for rawlen | ||
200 | t = setmetatable({1,2,3}, {__len = function () return 10 end}) | ||
201 | assert(#t == 10 and rawlen(t) == 3) | ||
202 | assert(rawlen"abc" == 3) | ||
203 | assert(not pcall(rawlen, io.stdin)) | ||
204 | assert(not pcall(rawlen, 34)) | ||
205 | assert(not pcall(rawlen)) | ||
206 | |||
207 | -- rawlen for long strings | ||
208 | assert(rawlen(string.rep('a', 1000)) == 1000) | ||
209 | |||
210 | |||
211 | t = {} | ||
212 | t.__lt = function (a,b,c) | ||
213 | collectgarbage() | ||
214 | assert(c == nil) | ||
215 | if type(a) == 'table' then a = a.x end | ||
216 | if type(b) == 'table' then b = b.x end | ||
217 | return a<b, "dummy" | ||
218 | end | ||
219 | |||
220 | function Op(x) return setmetatable({x=x}, t) end | ||
221 | |||
222 | local function test () | ||
223 | assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1))) | ||
224 | assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1))) | ||
225 | assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a'))) | ||
226 | assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a'))) | ||
227 | assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1))) | ||
228 | assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a'))) | ||
229 | assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1))) | ||
230 | assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a'))) | ||
231 | assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1))) | ||
232 | assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1)) | ||
233 | assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) | ||
234 | assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a'))) | ||
235 | end | ||
236 | |||
237 | test() | ||
238 | |||
239 | t.__le = function (a,b,c) | ||
240 | assert(c == nil) | ||
241 | if type(a) == 'table' then a = a.x end | ||
242 | if type(b) == 'table' then b = b.x end | ||
243 | return a<=b, "dummy" | ||
244 | end | ||
245 | |||
246 | test() -- retest comparisons, now using both `lt' and `le' | ||
247 | |||
248 | |||
249 | -- test `partial order' | ||
250 | |||
251 | local function rawSet(x) | ||
252 | local y = {} | ||
253 | for _,k in pairs(x) do y[k] = 1 end | ||
254 | return y | ||
255 | end | ||
256 | |||
257 | local function Set(x) | ||
258 | return setmetatable(rawSet(x), t) | ||
259 | end | ||
260 | |||
261 | t.__lt = function (a,b) | ||
262 | for k in pairs(a) do | ||
263 | if not b[k] then return false end | ||
264 | b[k] = undef | ||
265 | end | ||
266 | return next(b) ~= nil | ||
267 | end | ||
268 | |||
269 | t.__le = nil | ||
270 | |||
271 | assert(Set{1,2,3} < Set{1,2,3,4}) | ||
272 | assert(not(Set{1,2,3,4} < Set{1,2,3,4})) | ||
273 | assert((Set{1,2,3,4} <= Set{1,2,3,4})) | ||
274 | assert((Set{1,2,3,4} >= Set{1,2,3,4})) | ||
275 | assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-) | ||
276 | |||
277 | t.__le = function (a,b) | ||
278 | for k in pairs(a) do | ||
279 | if not b[k] then return false end | ||
280 | end | ||
281 | return true | ||
282 | end | ||
283 | |||
284 | assert(not (Set{1,3} <= Set{3,5})) -- now its OK! | ||
285 | assert(not(Set{1,3} <= Set{3,5})) | ||
286 | assert(not(Set{1,3} >= Set{3,5})) | ||
287 | |||
288 | t.__eq = function (a,b) | ||
289 | for k in pairs(a) do | ||
290 | if not b[k] then return false end | ||
291 | b[k] = undef | ||
292 | end | ||
293 | return next(b) == nil | ||
294 | end | ||
295 | |||
296 | local s = Set{1,3,5} | ||
297 | assert(s == Set{3,5,1}) | ||
298 | assert(not rawequal(s, Set{3,5,1})) | ||
299 | assert(rawequal(s, s)) | ||
300 | assert(Set{1,3,5,1} == rawSet{3,5,1}) | ||
301 | assert(rawSet{1,3,5,1} == Set{3,5,1}) | ||
302 | assert(Set{1,3,5} ~= Set{3,5,1,6}) | ||
303 | |||
304 | -- '__eq' is not used for table accesses | ||
305 | t[Set{1,3,5}] = 1 | ||
306 | assert(t[Set{1,3,5}] == undef) | ||
307 | |||
308 | |||
309 | if not T then | ||
310 | (Message or print)('\n >>> testC not active: skipping tests for \z | ||
311 | userdata <<<\n') | ||
312 | else | ||
313 | local u1 = T.newuserdata(0, 1) | ||
314 | local u2 = T.newuserdata(0, 1) | ||
315 | local u3 = T.newuserdata(0, 1) | ||
316 | assert(u1 ~= u2 and u1 ~= u3) | ||
317 | debug.setuservalue(u1, 1); | ||
318 | debug.setuservalue(u2, 2); | ||
319 | debug.setuservalue(u3, 1); | ||
320 | debug.setmetatable(u1, {__eq = function (a, b) | ||
321 | return debug.getuservalue(a) == debug.getuservalue(b) | ||
322 | end}) | ||
323 | debug.setmetatable(u2, {__eq = function (a, b) | ||
324 | return true | ||
325 | end}) | ||
326 | assert(u1 == u3 and u3 == u1 and u1 ~= u2) | ||
327 | assert(u2 == u1 and u2 == u3 and u3 == u2) | ||
328 | assert(u2 ~= {}) -- different types cannot be equal | ||
329 | |||
330 | local mirror = {} | ||
331 | debug.setmetatable(u3, {__index = mirror, __newindex = mirror}) | ||
332 | for i = 1, 10 do u3[i] = i end | ||
333 | for i = 1, 10 do assert(u3[i] == i) end | ||
334 | end | ||
335 | |||
336 | |||
337 | t.__concat = function (a,b,c) | ||
338 | assert(c == nil) | ||
339 | if type(a) == 'table' then a = a.val end | ||
340 | if type(b) == 'table' then b = b.val end | ||
341 | if A then return a..b | ||
342 | else | ||
343 | return setmetatable({val=a..b}, t) | ||
344 | end | ||
345 | end | ||
346 | |||
347 | c = {val="c"}; setmetatable(c, t) | ||
348 | d = {val="d"}; setmetatable(d, t) | ||
349 | |||
350 | A = true | ||
351 | assert(c..d == 'cd') | ||
352 | assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g") | ||
353 | |||
354 | A = false | ||
355 | assert((c..d..c..d).val == 'cdcd') | ||
356 | x = c..d | ||
357 | assert(getmetatable(x) == t and x.val == 'cd') | ||
358 | x = 0 .."a".."b"..c..d.."e".."f".."g" | ||
359 | assert(x.val == "0abcdefg") | ||
360 | |||
361 | |||
362 | -- concat metamethod x numbers (bug in 5.1.1) | ||
363 | c = {} | ||
364 | local x | ||
365 | setmetatable(c, {__concat = function (a,b) | ||
366 | assert(type(a) == "number" and b == c or type(b) == "number" and a == c) | ||
367 | return c | ||
368 | end}) | ||
369 | assert(c..5 == c and 5 .. c == c) | ||
370 | assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c) | ||
371 | |||
372 | |||
373 | -- test comparison compatibilities | ||
374 | local t1, t2, c, d | ||
375 | t1 = {}; c = {}; setmetatable(c, t1) | ||
376 | d = {} | ||
377 | t1.__eq = function () return true end | ||
378 | t1.__lt = function () return true end | ||
379 | setmetatable(d, t1) | ||
380 | assert(c == d and c < d and not(d <= c)) | ||
381 | t2 = {} | ||
382 | t2.__eq = t1.__eq | ||
383 | t2.__lt = t1.__lt | ||
384 | setmetatable(d, t2) | ||
385 | assert(c == d and c < d and not(d <= c)) | ||
386 | |||
387 | |||
388 | |||
389 | -- test for several levels of calls | ||
390 | local i | ||
391 | local tt = { | ||
392 | __call = function (t, ...) | ||
393 | i = i+1 | ||
394 | if t.f then return t.f(...) | ||
395 | else return {...} | ||
396 | end | ||
397 | end | ||
398 | } | ||
399 | |||
400 | local a = setmetatable({}, tt) | ||
401 | local b = setmetatable({f=a}, tt) | ||
402 | local c = setmetatable({f=b}, tt) | ||
403 | |||
404 | i = 0 | ||
405 | x = c(3,4,5) | ||
406 | assert(i == 3 and x[1] == 3 and x[3] == 5) | ||
407 | |||
408 | |||
409 | assert(_G.X == 20) | ||
410 | |||
411 | print'+' | ||
412 | |||
413 | local _g = _G | ||
414 | _ENV = setmetatable({}, {__index=function (_,k) return _g[k] end}) | ||
415 | |||
416 | |||
417 | a = {} | ||
418 | rawset(a, "x", 1, 2, 3) | ||
419 | assert(a.x == 1 and rawget(a, "x", 3) == 1) | ||
420 | |||
421 | print '+' | ||
422 | |||
423 | -- testing metatables for basic types | ||
424 | mt = {__index = function (a,b) return a+b end, | ||
425 | __len = function (x) return math.floor(x) end} | ||
426 | debug.setmetatable(10, mt) | ||
427 | assert(getmetatable(-2) == mt) | ||
428 | assert((10)[3] == 13) | ||
429 | assert((10)["3"] == 13) | ||
430 | assert(#3.45 == 3) | ||
431 | debug.setmetatable(23, nil) | ||
432 | assert(getmetatable(-2) == nil) | ||
433 | |||
434 | debug.setmetatable(true, mt) | ||
435 | assert(getmetatable(false) == mt) | ||
436 | mt.__index = function (a,b) return a or b end | ||
437 | assert((true)[false] == true) | ||
438 | assert((false)[false] == false) | ||
439 | debug.setmetatable(false, nil) | ||
440 | assert(getmetatable(true) == nil) | ||
441 | |||
442 | debug.setmetatable(nil, mt) | ||
443 | assert(getmetatable(nil) == mt) | ||
444 | mt.__add = function (a,b) return (a or 1) + (b or 2) end | ||
445 | assert(10 + nil == 12) | ||
446 | assert(nil + 23 == 24) | ||
447 | assert(nil + nil == 3) | ||
448 | debug.setmetatable(nil, nil) | ||
449 | assert(getmetatable(nil) == nil) | ||
450 | |||
451 | debug.setmetatable(nil, {}) | ||
452 | |||
453 | |||
454 | -- loops in delegation | ||
455 | a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a | ||
456 | assert(not pcall(function (a,b) return a[b] end, a, 10)) | ||
457 | assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true)) | ||
458 | |||
459 | -- bug in 5.1 | ||
460 | T, K, V = nil | ||
461 | grandparent = {} | ||
462 | grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end | ||
463 | |||
464 | parent = {} | ||
465 | parent.__newindex = parent | ||
466 | setmetatable(parent, grandparent) | ||
467 | |||
468 | child = setmetatable({}, parent) | ||
469 | child.foo = 10 --> CRASH (on some machines) | ||
470 | assert(T == parent and K == "foo" and V == 10) | ||
471 | |||
472 | print 'OK' | ||
473 | |||
474 | return 12 | ||
475 | |||
476 | |||