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