aboutsummaryrefslogtreecommitdiff
path: root/testes/files.lua
diff options
context:
space:
mode:
Diffstat (limited to 'testes/files.lua')
-rw-r--r--testes/files.lua832
1 files changed, 832 insertions, 0 deletions
diff --git a/testes/files.lua b/testes/files.lua
new file mode 100644
index 00000000..b2c7c202
--- /dev/null
+++ b/testes/files.lua
@@ -0,0 +1,832 @@
1-- $Id: files.lua,v 1.101 2018/03/12 13:51:02 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4local debug = require "debug"
5
6local maxint = math.maxinteger
7
8assert(type(os.getenv"PATH") == "string")
9
10assert(io.input(io.stdin) == io.stdin)
11assert(not pcall(io.input, "non-existent-file"))
12assert(io.output(io.stdout) == io.stdout)
13
14
15local function testerr (msg, f, ...)
16 local stat, err = pcall(f, ...)
17 return (not stat and string.find(err, msg, 1, true))
18end
19
20
21local function checkerr (msg, f, ...)
22 assert(testerr(msg, f, ...))
23end
24
25
26-- cannot close standard files
27assert(not io.close(io.stdin) and
28 not io.stdout:close() and
29 not io.stderr:close())
30
31-- cannot call close method without an argument (new in 5.3.5)
32checkerr("got no value", io.stdin.close)
33
34
35assert(type(io.input()) == "userdata" and io.type(io.output()) == "file")
36assert(type(io.stdin) == "userdata" and io.type(io.stderr) == "file")
37assert(not io.type(8))
38local a = {}; setmetatable(a, {})
39assert(not io.type(a))
40
41assert(getmetatable(io.input()).__name == "FILE*")
42
43local a,b,c = io.open('xuxu_nao_existe')
44assert(not a and type(b) == "string" and type(c) == "number")
45
46a,b,c = io.open('/a/b/c/d', 'w')
47assert(not a and type(b) == "string" and type(c) == "number")
48
49local file = os.tmpname()
50local f, msg = io.open(file, "w")
51if not f then
52 (Message or print)("'os.tmpname' file cannot be open; skipping file tests")
53
54else --{ most tests here need tmpname
55f:close()
56
57print('testing i/o')
58
59local otherfile = os.tmpname()
60
61checkerr("invalid mode", io.open, file, "rw")
62checkerr("invalid mode", io.open, file, "rb+")
63checkerr("invalid mode", io.open, file, "r+bk")
64checkerr("invalid mode", io.open, file, "")
65checkerr("invalid mode", io.open, file, "+")
66checkerr("invalid mode", io.open, file, "b")
67assert(io.open(file, "r+b")):close()
68assert(io.open(file, "r+")):close()
69assert(io.open(file, "rb")):close()
70
71assert(os.setlocale('C', 'all'))
72
73io.input(io.stdin); io.output(io.stdout);
74
75os.remove(file)
76assert(not loadfile(file))
77checkerr("", dofile, file)
78assert(not io.open(file))
79io.output(file)
80assert(io.output() ~= io.stdout)
81
82if not _port then -- invalid seek
83 local status, msg, code = io.stdin:seek("set", 1000)
84 assert(not status and type(msg) == "string" and type(code) == "number")
85end
86
87assert(io.output():seek() == 0)
88assert(io.write("alo alo"):seek() == string.len("alo alo"))
89assert(io.output():seek("cur", -3) == string.len("alo alo")-3)
90assert(io.write("joao"))
91assert(io.output():seek("end") == string.len("alo joao"))
92
93assert(io.output():seek("set") == 0)
94
95assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n"))
96assert(io.write('çfourth_line'))
97io.output(io.stdout)
98collectgarbage() -- file should be closed by GC
99assert(io.input() == io.stdin and rawequal(io.output(), io.stdout))
100print('+')
101
102-- test GC for files
103collectgarbage()
104for i=1,120 do
105 for i=1,5 do
106 io.input(file)
107 assert(io.open(file, 'r'))
108 io.lines(file)
109 end
110 collectgarbage()
111end
112
113io.input():close()
114io.close()
115
116assert(os.rename(file, otherfile))
117assert(not os.rename(file, otherfile))
118
119io.output(io.open(otherfile, "ab"))
120assert(io.write("\n\n\t\t ", 3450, "\n"));
121io.close()
122
123-- test writing/reading numbers
124f = assert(io.open(file, "w"))
125f:write(maxint, '\n')
126f:write(string.format("0X%x\n", maxint))
127f:write("0xABCp-3", '\n')
128f:write(0, '\n')
129f:write(-maxint, '\n')
130f:write(string.format("0x%X\n", -maxint))
131f:write("-0xABCp-3", '\n')
132assert(f:close())
133f = assert(io.open(file, "r"))
134assert(f:read("n") == maxint)
135assert(f:read("n") == maxint)
136assert(f:read("n") == 0xABCp-3)
137assert(f:read("n") == 0)
138assert(f:read("*n") == -maxint) -- test old format (with '*')
139assert(f:read("n") == -maxint)
140assert(f:read("*n") == -0xABCp-3) -- test old format (with '*')
141assert(f:close())
142assert(os.remove(file))
143
144
145-- testing multiple arguments to io.read
146do
147 local f = assert(io.open(file, "w"))
148 f:write[[
149a line
150another line
1511234
1523.45
153one
154two
155three
156]]
157 local l1, l2, l3, l4, n1, n2, c, dummy
158 assert(f:close())
159 f = assert(io.open(file, "r"))
160 l1, l2, n1, n2, dummy = f:read("l", "L", "n", "n")
161 assert(l1 == "a line" and l2 == "another line\n" and
162 n1 == 1234 and n2 == 3.45 and dummy == nil)
163 assert(f:close())
164 f = assert(io.open(file, "r"))
165 l1, l2, n1, n2, c, l3, l4, dummy = f:read(7, "l", "n", "n", 1, "l", "l")
166 assert(l1 == "a line\n" and l2 == "another line" and c == '\n' and
167 n1 == 1234 and n2 == 3.45 and l3 == "one" and l4 == "two"
168 and dummy == nil)
169 assert(f:close())
170 f = assert(io.open(file, "r"))
171 -- second item failing
172 l1, n1, n2, dummy = f:read("l", "n", "n", "l")
173 assert(l1 == "a line" and n1 == nil)
174 assert(f:close())
175 assert(os.remove(file))
176end
177
178
179
180-- test yielding during 'dofile'
181f = assert(io.open(file, "w"))
182f:write[[
183local x, z = coroutine.yield(10)
184local y = coroutine.yield(20)
185return x + y * z
186]]
187assert(f:close())
188f = coroutine.wrap(dofile)
189assert(f(file) == 10)
190print(f(100, 101) == 20)
191assert(f(200) == 100 + 200 * 101)
192assert(os.remove(file))
193
194
195f = assert(io.open(file, "w"))
196-- test number termination
197f:write[[
198-12.3- -0xffff+ .3|5.E-3X +234e+13E 0xDEADBEEFDEADBEEFx
1990x1.13Ap+3e
200]]
201-- very long number
202f:write("1234"); for i = 1, 1000 do f:write("0") end; f:write("\n")
203-- invalid sequences (must read and discard valid prefixes)
204f:write[[
205.e+ 0.e; --; 0xX;
206]]
207assert(f:close())
208f = assert(io.open(file, "r"))
209assert(f:read("n") == -12.3); assert(f:read(1) == "-")
210assert(f:read("n") == -0xffff); assert(f:read(2) == "+ ")
211assert(f:read("n") == 0.3); assert(f:read(1) == "|")
212assert(f:read("n") == 5e-3); assert(f:read(1) == "X")
213assert(f:read("n") == 234e13); assert(f:read(1) == "E")
214assert(f:read("n") == 0Xdeadbeefdeadbeef); assert(f:read(2) == "x\n")
215assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e")
216
217do -- attempt to read too long number
218 assert(f:read("n") == nil) -- fails
219 local s = f:read("L") -- read rest of line
220 assert(string.find(s, "^00*\n$")) -- lots of 0's left
221end
222
223assert(not f:read("n")); assert(f:read(2) == "e+")
224assert(not f:read("n")); assert(f:read(1) == ";")
225assert(not f:read("n")); assert(f:read(2) == "-;")
226assert(not f:read("n")); assert(f:read(1) == "X")
227assert(not f:read("n")); assert(f:read(1) == ";")
228assert(not f:read("n")); assert(not f:read(0)) -- end of file
229assert(f:close())
230assert(os.remove(file))
231
232
233-- test line generators
234assert(not pcall(io.lines, "non-existent-file"))
235assert(os.rename(otherfile, file))
236io.output(otherfile)
237local n = 0
238local f = io.lines(file)
239while f() do n = n + 1 end;
240assert(n == 6) -- number of lines in the file
241checkerr("file is already closed", f)
242checkerr("file is already closed", f)
243-- copy from file to otherfile
244n = 0
245for l in io.lines(file) do io.write(l, "\n"); n = n + 1 end
246io.close()
247assert(n == 6)
248-- copy from otherfile back to file
249local f = assert(io.open(otherfile))
250assert(io.type(f) == "file")
251io.output(file)
252assert(not io.output():read())
253n = 0
254for l in f:lines() do io.write(l, "\n"); n = n + 1 end
255assert(tostring(f):sub(1, 5) == "file ")
256assert(f:close()); io.close()
257assert(n == 6)
258checkerr("closed file", io.close, f)
259assert(tostring(f) == "file (closed)")
260assert(io.type(f) == "closed file")
261io.input(file)
262f = io.open(otherfile):lines()
263n = 0
264for l in io.lines() do assert(l == f()); n = n + 1 end
265f = nil; collectgarbage()
266assert(n == 6)
267assert(os.remove(otherfile))
268
269do -- bug in 5.3.1
270 io.output(otherfile)
271 io.write(string.rep("a", 300), "\n")
272 io.close()
273 local t ={}; for i = 1, 250 do t[i] = 1 end
274 t = {io.lines(otherfile, table.unpack(t))()}
275 -- everything ok here
276 assert(#t == 250 and t[1] == 'a' and t[#t] == 'a')
277 t[#t + 1] = 1 -- one too many
278 checkerr("too many arguments", io.lines, otherfile, table.unpack(t))
279 collectgarbage() -- ensure 'otherfile' is closed
280 assert(os.remove(otherfile))
281end
282
283io.input(file)
284do -- test error returns
285 local a,b,c = io.input():write("xuxu")
286 assert(not a and type(b) == "string" and type(c) == "number")
287end
288checkerr("invalid format", io.read, "x")
289assert(io.read(0) == "") -- not eof
290assert(io.read(5, 'l') == '"álo"')
291assert(io.read(0) == "")
292assert(io.read() == "second line")
293local x = io.input():seek()
294assert(io.read() == "third line ")
295assert(io.input():seek("set", x))
296assert(io.read('L') == "third line \n")
297assert(io.read(1) == "ç")
298assert(io.read(string.len"fourth_line") == "fourth_line")
299assert(io.input():seek("cur", -string.len"fourth_line"))
300assert(io.read() == "fourth_line")
301assert(io.read() == "") -- empty line
302assert(io.read('n') == 3450)
303assert(io.read(1) == '\n')
304assert(io.read(0) == nil) -- end of file
305assert(io.read(1) == nil) -- end of file
306assert(io.read(30000) == nil) -- end of file
307assert(({io.read(1)})[2] == undef)
308assert(io.read() == nil) -- end of file
309assert(({io.read()})[2] == undef)
310assert(io.read('n') == nil) -- end of file
311assert(({io.read('n')})[2] == undef)
312assert(io.read('a') == '') -- end of file (OK for 'a')
313assert(io.read('a') == '') -- end of file (OK for 'a')
314collectgarbage()
315print('+')
316io.close(io.input())
317checkerr(" input file is closed", io.read)
318
319assert(os.remove(file))
320
321local t = '0123456789'
322for i=1,10 do t = t..t; end
323assert(string.len(t) == 10*2^10)
324
325io.output(file)
326io.write("alo"):write("\n")
327io.close()
328checkerr(" output file is closed", io.write)
329local f = io.open(file, "a+b")
330io.output(f)
331collectgarbage()
332
333assert(io.write(' ' .. t .. ' '))
334assert(io.write(';', 'end of file\n'))
335f:flush(); io.flush()
336f:close()
337print('+')
338
339io.input(file)
340assert(io.read() == "alo")
341assert(io.read(1) == ' ')
342assert(io.read(string.len(t)) == t)
343assert(io.read(1) == ' ')
344assert(io.read(0))
345assert(io.read('a') == ';end of file\n')
346assert(io.read(0) == nil)
347assert(io.close(io.input()))
348
349
350-- test errors in read/write
351do
352 local function ismsg (m)
353 -- error message is not a code number
354 return (type(m) == "string" and tonumber(m) == nil)
355 end
356
357 -- read
358 local f = io.open(file, "w")
359 local r, m, c = f:read()
360 assert(not r and ismsg(m) and type(c) == "number")
361 assert(f:close())
362 -- write
363 f = io.open(file, "r")
364 r, m, c = f:write("whatever")
365 assert(not r and ismsg(m) and type(c) == "number")
366 assert(f:close())
367 -- lines
368 f = io.open(file, "w")
369 r, m = pcall(f:lines())
370 assert(r == false and ismsg(m))
371 assert(f:close())
372end
373
374assert(os.remove(file))
375
376-- test for L format
377io.output(file); io.write"\n\nline\nother":close()
378io.input(file)
379assert(io.read"L" == "\n")
380assert(io.read"L" == "\n")
381assert(io.read"L" == "line\n")
382assert(io.read"L" == "other")
383assert(io.read"L" == nil)
384io.input():close()
385
386local f = assert(io.open(file))
387local s = ""
388for l in f:lines("L") do s = s .. l end
389assert(s == "\n\nline\nother")
390f:close()
391
392io.input(file)
393s = ""
394for l in io.lines(nil, "L") do s = s .. l end
395assert(s == "\n\nline\nother")
396io.input():close()
397
398s = ""
399for l in io.lines(file, "L") do s = s .. l end
400assert(s == "\n\nline\nother")
401
402s = ""
403for l in io.lines(file, "l") do s = s .. l end
404assert(s == "lineother")
405
406io.output(file); io.write"a = 10 + 34\na = 2*a\na = -a\n":close()
407local t = {}
408assert(load(io.lines(file, "L"), nil, nil, t))()
409assert(t.a == -((10 + 34) * 2))
410
411
412-- test for multipe arguments in 'lines'
413io.output(file); io.write"0123456789\n":close()
414for a,b in io.lines(file, 1, 1) do
415 if a == "\n" then assert(b == nil)
416 else assert(tonumber(a) == tonumber(b) - 1)
417 end
418end
419
420for a,b,c in io.lines(file, 1, 2, "a") do
421 assert(a == "0" and b == "12" and c == "3456789\n")
422end
423
424for a,b,c in io.lines(file, "a", 0, 1) do
425 if a == "" then break end
426 assert(a == "0123456789\n" and b == nil and c == nil)
427end
428collectgarbage() -- to close file in previous iteration
429
430io.output(file); io.write"00\n10\n20\n30\n40\n":close()
431for a, b in io.lines(file, "n", "n") do
432 if a == 40 then assert(b == nil)
433 else assert(a == b - 10)
434 end
435end
436
437
438-- test load x lines
439io.output(file);
440io.write[[
441local y
442= X
443X =
444X *
4452 +
446X;
447X =
448X
449- y;
450]]:close()
451_G.X = 1
452assert(not load(io.lines(file)))
453collectgarbage() -- to close file in previous iteration
454load(io.lines(file, "L"))()
455assert(_G.X == 2)
456load(io.lines(file, 1))()
457assert(_G.X == 4)
458load(io.lines(file, 3))()
459assert(_G.X == 8)
460
461print('+')
462
463local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
464io.output(file)
465assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1)))
466io.close()
467assert(loadfile(file))()
468assert(x1 == x2)
469print('+')
470assert(os.remove(file))
471assert(not os.remove(file))
472assert(not os.remove(otherfile))
473
474-- testing loadfile
475local function testloadfile (s, expres)
476 io.output(file)
477 if s then io.write(s) end
478 io.close()
479 local res = assert(loadfile(file))()
480 assert(os.remove(file))
481 assert(res == expres)
482end
483
484-- loading empty file
485testloadfile(nil, nil)
486
487-- loading file with initial comment without end of line
488testloadfile("# a non-ending comment", nil)
489
490
491-- checking Unicode BOM in files
492testloadfile("\xEF\xBB\xBF# some comment\nreturn 234", 234)
493testloadfile("\xEF\xBB\xBFreturn 239", 239)
494testloadfile("\xEF\xBB\xBF", nil) -- empty file with a BOM
495
496
497-- checking line numbers in files with initial comments
498testloadfile("# a comment\nreturn require'debug'.getinfo(1).currentline", 2)
499
500
501-- loading binary file
502io.output(io.open(file, "wb"))
503assert(io.write(string.dump(function () return 10, '\0alo\255', 'hi' end)))
504io.close()
505a, b, c = assert(loadfile(file))()
506assert(a == 10 and b == "\0alo\255" and c == "hi")
507assert(os.remove(file))
508
509-- bug in 5.2.1
510do
511 io.output(io.open(file, "wb"))
512 -- save function with no upvalues
513 assert(io.write(string.dump(function () return 1 end)))
514 io.close()
515 f = assert(loadfile(file, "b", {}))
516 assert(type(f) == "function" and f() == 1)
517 assert(os.remove(file))
518end
519
520-- loading binary file with initial comment
521io.output(io.open(file, "wb"))
522assert(io.write("#this is a comment for a binary file\0\n",
523 string.dump(function () return 20, '\0\0\0' end)))
524io.close()
525a, b, c = assert(loadfile(file))()
526assert(a == 20 and b == "\0\0\0" and c == nil)
527assert(os.remove(file))
528
529
530-- 'loadfile' with 'env'
531do
532 local f = io.open(file, 'w')
533 f:write[[
534 if (...) then a = 15; return b, c, d
535 else return _ENV
536 end
537 ]]
538 f:close()
539 local t = {b = 12, c = "xuxu", d = print}
540 local f = assert(loadfile(file, 't', t))
541 local b, c, d = f(1)
542 assert(t.a == 15 and b == 12 and c == t.c and d == print)
543 assert(f() == t)
544 f = assert(loadfile(file, 't', nil))
545 assert(f() == nil)
546 f = assert(loadfile(file))
547 assert(f() == _G)
548 assert(os.remove(file))
549end
550
551
552-- 'loadfile' x modes
553do
554 io.open(file, 'w'):write("return 10"):close()
555 local s, m = loadfile(file, 'b')
556 assert(not s and string.find(m, "a text chunk"))
557 io.open(file, 'w'):write("\27 return 10"):close()
558 local s, m = loadfile(file, 't')
559 assert(not s and string.find(m, "a binary chunk"))
560 assert(os.remove(file))
561end
562
563
564io.output(file)
565assert(io.write("qualquer coisa\n"))
566assert(io.write("mais qualquer coisa"))
567io.close()
568assert(io.output(assert(io.open(otherfile, 'wb')))
569 :write("outra coisa\0\1\3\0\0\0\0\255\0")
570 :close())
571
572local filehandle = assert(io.open(file, 'r+'))
573local otherfilehandle = assert(io.open(otherfile, 'rb'))
574assert(filehandle ~= otherfilehandle)
575assert(type(filehandle) == "userdata")
576assert(filehandle:read('l') == "qualquer coisa")
577io.input(otherfilehandle)
578assert(io.read(string.len"outra coisa") == "outra coisa")
579assert(filehandle:read('l') == "mais qualquer coisa")
580filehandle:close();
581assert(type(filehandle) == "userdata")
582io.input(otherfilehandle)
583assert(io.read(4) == "\0\1\3\0")
584assert(io.read(3) == "\0\0\0")
585assert(io.read(0) == "") -- 255 is not eof
586assert(io.read(1) == "\255")
587assert(io.read('a') == "\0")
588assert(not io.read(0))
589assert(otherfilehandle == io.input())
590otherfilehandle:close()
591assert(os.remove(file))
592assert(os.remove(otherfile))
593collectgarbage()
594
595io.output(file)
596 :write[[
597 123.4 -56e-2 not a number
598second line
599third line
600
601and the rest of the file
602]]
603 :close()
604io.input(file)
605local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10)
606assert(io.close(io.input()))
607assert(_ == ' ' and __ == nil)
608assert(type(a) == 'number' and a==123.4 and b==-56e-2)
609assert(d=='second line' and e=='third line')
610assert(h==[[
611
612and the rest of the file
613]])
614assert(os.remove(file))
615collectgarbage()
616
617-- testing buffers
618do
619 local f = assert(io.open(file, "w"))
620 local fr = assert(io.open(file, "r"))
621 assert(f:setvbuf("full", 2000))
622 f:write("x")
623 assert(fr:read("all") == "") -- full buffer; output not written yet
624 f:close()
625 fr:seek("set")
626 assert(fr:read("all") == "x") -- `close' flushes it
627 f = assert(io.open(file), "w")
628 assert(f:setvbuf("no"))
629 f:write("x")
630 fr:seek("set")
631 assert(fr:read("all") == "x") -- no buffer; output is ready
632 f:close()
633 f = assert(io.open(file, "a"))
634 assert(f:setvbuf("line"))
635 f:write("x")
636 fr:seek("set", 1)
637 assert(fr:read("all") == "") -- line buffer; no output without `\n'
638 f:write("a\n"):seek("set", 1)
639 assert(fr:read("all") == "xa\n") -- now we have a whole line
640 f:close(); fr:close()
641 assert(os.remove(file))
642end
643
644
645if not _soft then
646 print("testing large files (> BUFSIZ)")
647 io.output(file)
648 for i=1,5001 do io.write('0123456789123') end
649 io.write('\n12346'):close()
650 io.input(file)
651 local x = io.read('a')
652 io.input():seek('set', 0)
653 local y = io.read(30001)..io.read(1005)..io.read(0)..
654 io.read(1)..io.read(100003)
655 assert(x == y and string.len(x) == 5001*13 + 6)
656 io.input():seek('set', 0)
657 y = io.read() -- huge line
658 assert(x == y..'\n'..io.read())
659 assert(io.read() == nil)
660 io.close(io.input())
661 assert(os.remove(file))
662 x = nil; y = nil
663end
664
665if not _port then
666 local progname
667 do -- get name of running executable
668 local arg = arg or ARG
669 local i = 0
670 while arg[i] do i = i - 1 end
671 progname = '"' .. arg[i + 1] .. '"'
672 end
673 print("testing popen/pclose and execute")
674 local tests = {
675 -- command, what, code
676 {"ls > /dev/null", "ok"},
677 {"not-to-be-found-command", "exit"},
678 {"exit 3", "exit", 3},
679 {"exit 129", "exit", 129},
680 {"kill -s HUP $$", "signal", 1},
681 {"kill -s KILL $$", "signal", 9},
682 {"sh -c 'kill -s HUP $$'", "exit"},
683 {progname .. ' -e " "', "ok"},
684 {progname .. ' -e "os.exit(0, true)"', "ok"},
685 {progname .. ' -e "os.exit(20, true)"', "exit", 20},
686 }
687 print("\n(some error messages are expected now)")
688 for _, v in ipairs(tests) do
689 local x, y, z = io.popen(v[1]):close()
690 local x1, y1, z1 = os.execute(v[1])
691 assert(x == x1 and y == y1 and z == z1)
692 if v[2] == "ok" then
693 assert(x and y == 'exit' and z == 0)
694 else
695 assert(not x and y == v[2]) -- correct status and 'what'
696 -- correct code if known (but always different from 0)
697 assert((v[3] == nil and z > 0) or v[3] == z)
698 end
699 end
700end
701
702
703-- testing tmpfile
704f = io.tmpfile()
705assert(io.type(f) == "file")
706f:write("alo")
707f:seek("set")
708assert(f:read"a" == "alo")
709
710end --}
711
712print'+'
713
714print("testing date/time")
715
716assert(os.date("") == "")
717assert(os.date("!") == "")
718assert(os.date("\0\0") == "\0\0")
719assert(os.date("!\0\0") == "\0\0")
720local x = string.rep("a", 10000)
721assert(os.date(x) == x)
722local t = os.time()
723D = os.date("*t", t)
724assert(os.date(string.rep("%d", 1000), t) ==
725 string.rep(os.date("%d", t), 1000))
726assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
727
728local t = os.time()
729D = os.date("*t", t)
730load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
731 D.hour==%H and D.min==%M and D.sec==%S and
732 D.wday==%w+1 and D.yday==%j and type(D.isdst) == 'boolean')]], t))()
733
734checkerr("invalid conversion specifier", os.date, "%")
735checkerr("invalid conversion specifier", os.date, "%9")
736checkerr("invalid conversion specifier", os.date, "%")
737checkerr("invalid conversion specifier", os.date, "%O")
738checkerr("invalid conversion specifier", os.date, "%E")
739checkerr("invalid conversion specifier", os.date, "%Ea")
740
741checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour='x'})
742checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour=1.5})
743
744checkerr("missing", os.time, {hour = 12}) -- missing date
745
746if not _port then
747 -- test Posix-specific modifiers
748 assert(type(os.date("%Ex")) == 'string')
749 assert(type(os.date("%Oy")) == 'string')
750
751
752 -- test out-of-range dates (at least for Unix)
753 if maxint >= 2^62 then -- cannot do these tests in Small Lua
754 -- no arith overflows
755 checkerr("out-of-bound", os.time, {year = -maxint, month = 1, day = 1})
756 if string.packsize("i") == 4 then -- 4-byte ints
757 if testerr("out-of-bound", os.date, "%Y", 2^40) then
758 -- time_t has 4 bytes and therefore cannot represent year 4000
759 print(" 4-byte time_t")
760 checkerr("cannot be represented", os.time, {year=4000, month=1, day=1})
761 else
762 -- time_t has 8 bytes; an int year cannot represent a huge time
763 print(" 8-byte time_t")
764 checkerr("cannot be represented", os.date, "%Y", 2^60)
765 -- it should have no problems with year 4000
766 assert(tonumber(os.time{year=4000, month=1, day=1}))
767 end
768 else -- 8-byte ints
769 -- assume time_t has 8 bytes too
770 print(" 8-byte time_t")
771 assert(tonumber(os.date("%Y", 2^60)))
772 -- but still cannot represent a huge year
773 checkerr("cannot be represented", os.time, {year=2^60, month=1, day=1})
774 end
775 end
776end
777
778
779D = os.date("!*t", t)
780load(os.date([[!assert(D.year==%Y and D.month==%m and D.day==%d and
781 D.hour==%H and D.min==%M and D.sec==%S and
782 D.wday==%w+1 and D.yday==%j and type(D.isdst) == 'boolean')]], t))()
783
784do
785 local D = os.date("*t")
786 local t = os.time(D)
787 assert(type(D.isdst) == 'boolean')
788 D.isdst = nil
789 local t1 = os.time(D)
790 assert(t == t1) -- if isdst is absent uses correct default
791end
792
793t = os.time(D)
794D.year = D.year-1;
795local t1 = os.time(D)
796-- allow for leap years
797assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2)
798
799-- should not take more than 1 second to execute these two lines
800t = os.time()
801t1 = os.time(os.date("*t"))
802local diff = os.difftime(t1,t)
803assert(0 <= diff and diff <= 1)
804diff = os.difftime(t,t1)
805assert(-1 <= diff and diff <= 0)
806
807local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12}
808local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19}
809assert(os.difftime(t1,t2) == 60*2-19)
810
811-- since 5.3.3, 'os.time' normalizes table fields
812t1 = {year = 2005, month = 1, day = 1, hour = 1, min = 0, sec = -3602}
813os.time(t1)
814assert(t1.day == 31 and t1.month == 12 and t1.year == 2004 and
815 t1.hour == 23 and t1.min == 59 and t1.sec == 58 and
816 t1.yday == 366)
817
818io.output(io.stdout)
819local t = os.date('%d %m %Y %H %M %S')
820local d, m, a, h, min, s = string.match(t,
821 "(%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")
822d = tonumber(d)
823m = tonumber(m)
824a = tonumber(a)
825h = tonumber(h)
826min = tonumber(min)
827s = tonumber(s)
828io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a))
829io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s))
830io.write(string.format('%s\n', _VERSION))
831
832