| 1 | --[[ |
|---|
| 2 | @title lua lib test |
|---|
| 3 | @param a skip io |
|---|
| 4 | @default a 0 |
|---|
| 5 | @param b skip all os |
|---|
| 6 | @default b 0 |
|---|
| 7 | @param c skip os time |
|---|
| 8 | @default c 0 |
|---|
| 9 | @param d skip os time fmt |
|---|
| 10 | @default d 0 |
|---|
| 11 | @param e skip os filesystem |
|---|
| 12 | @default e 0 |
|---|
| 13 | ]] |
|---|
| 14 | |
|---|
| 15 | do_io=a==0 |
|---|
| 16 | do_os=b==0 |
|---|
| 17 | do_time=c==0 |
|---|
| 18 | do_fmtdump=d==0 |
|---|
| 19 | do_dir=e==0 |
|---|
| 20 | |
|---|
| 21 | nfail=0 |
|---|
| 22 | want_ok=true |
|---|
| 23 | no_rec=false |
|---|
| 24 | |
|---|
| 25 | iotfnam="A/iotest0.txt" |
|---|
| 26 | |
|---|
| 27 | -- we require minimal io functionality to run the test |
|---|
| 28 | if type(io) ~= "table" then |
|---|
| 29 | error("missing io, aborting!") |
|---|
| 30 | end |
|---|
| 31 | |
|---|
| 32 | function log(...) |
|---|
| 33 | io.write(...) |
|---|
| 34 | -- most crashes leave no log even if we flush, and it's really slow :( |
|---|
| 35 | -- io.output():flush() |
|---|
| 36 | end |
|---|
| 37 | -- record result |
|---|
| 38 | function rec(r) |
|---|
| 39 | local f |
|---|
| 40 | if no_rec then |
|---|
| 41 | return "NA" |
|---|
| 42 | end |
|---|
| 43 | if want_ok then |
|---|
| 44 | f=not r |
|---|
| 45 | else |
|---|
| 46 | f=r |
|---|
| 47 | end |
|---|
| 48 | if f then |
|---|
| 49 | nfail=nfail+1 |
|---|
| 50 | return "FAIL" |
|---|
| 51 | end |
|---|
| 52 | return "PASS" |
|---|
| 53 | end |
|---|
| 54 | function logrec(s,r,...) |
|---|
| 55 | log(s) |
|---|
| 56 | if ... then |
|---|
| 57 | log(" ",...) |
|---|
| 58 | end |
|---|
| 59 | log(" ",rec(r)) |
|---|
| 60 | log("\n") |
|---|
| 61 | end |
|---|
| 62 | function logok(...) |
|---|
| 63 | logrec("OK",true,...) |
|---|
| 64 | end |
|---|
| 65 | function logfail(...) |
|---|
| 66 | logrec("ERR",false,...) |
|---|
| 67 | end |
|---|
| 68 | function logres(r) |
|---|
| 69 | if r then |
|---|
| 70 | logok() |
|---|
| 71 | else |
|---|
| 72 | logfail() |
|---|
| 73 | end |
|---|
| 74 | return r |
|---|
| 75 | end |
|---|
| 76 | |
|---|
| 77 | function fpinfo(f,name) |
|---|
| 78 | if type(name) ~= "string" then |
|---|
| 79 | name="<unk>" |
|---|
| 80 | end |
|---|
| 81 | log("file info for ",name,": ") |
|---|
| 82 | local t=io.type(f) |
|---|
| 83 | if not t then |
|---|
| 84 | log("not a file!\n") |
|---|
| 85 | elseif t == "file" then |
|---|
| 86 | log("valid file\n") |
|---|
| 87 | log(" ptr: ",f:_getfptr()) |
|---|
| 88 | local fpv={} |
|---|
| 89 | for i=0,8 do |
|---|
| 90 | fpv[i]=peek(f:_getfptr() + i*4) |
|---|
| 91 | end |
|---|
| 92 | log(" fd: ",fpv[0]) |
|---|
| 93 | log(" len: ",fpv[1]) |
|---|
| 94 | log(" pos: ",fpv[3],"\n") |
|---|
| 95 | log(" raw vals:") |
|---|
| 96 | for i=0,8 do |
|---|
| 97 | log(" ",i*4,":",fpv[i]) |
|---|
| 98 | end |
|---|
| 99 | log("\n") |
|---|
| 100 | else |
|---|
| 101 | log("closed file!\n") |
|---|
| 102 | end |
|---|
| 103 | end |
|---|
| 104 | |
|---|
| 105 | -- wrap file obj with logging |
|---|
| 106 | tfproto={ |
|---|
| 107 | fpinfo=function(self) |
|---|
| 108 | fpinfo(self.f,self.name) |
|---|
| 109 | end, |
|---|
| 110 | open=function(self,name,mode) |
|---|
| 111 | log('io.open("',tostring(name),'","',tostring(mode),'"): ') |
|---|
| 112 | self.f,msg=io.open(name,mode) |
|---|
| 113 | if self.f then |
|---|
| 114 | self.name=name |
|---|
| 115 | logok() |
|---|
| 116 | else |
|---|
| 117 | logfail('msg=',tostring(msg)) |
|---|
| 118 | end |
|---|
| 119 | return self.f,msg |
|---|
| 120 | end, |
|---|
| 121 | rawtell=function(self) |
|---|
| 122 | return peek(self.f:_getfptr() + 12) |
|---|
| 123 | end, |
|---|
| 124 | seek=function(self,whence,offset) |
|---|
| 125 | log(self.name,':seek("',tostring(whence),'",',tostring(offset),'): ') |
|---|
| 126 | if io.type(self.f) ~= "file" then |
|---|
| 127 | log("not an open file!\n") |
|---|
| 128 | return |
|---|
| 129 | end |
|---|
| 130 | local r=self.f:seek(whence,offset) |
|---|
| 131 | if r then |
|---|
| 132 | if r == self:rawtell() then |
|---|
| 133 | logok(tostring(r)) |
|---|
| 134 | else |
|---|
| 135 | logfail("\n position mismatch r ",tostring(r)," != ", tostring(self:rawtell())) |
|---|
| 136 | end |
|---|
| 137 | else |
|---|
| 138 | logfail(tostring(r)) |
|---|
| 139 | end |
|---|
| 140 | return r |
|---|
| 141 | end, |
|---|
| 142 | write=function(self,...) |
|---|
| 143 | log(self.name,":write(...): ") |
|---|
| 144 | return logres(self.f:write(...)) |
|---|
| 145 | end, |
|---|
| 146 | read=function(self,...) |
|---|
| 147 | log(self.name,":read(",...,"): ") |
|---|
| 148 | local r={self.f:read(...)} |
|---|
| 149 | if table.maxn(r) == 0 then |
|---|
| 150 | log("<no results>") |
|---|
| 151 | else |
|---|
| 152 | for i=1,table.maxn(r) do |
|---|
| 153 | log(type(r[i])," [",tostring(r[i]),"] ") |
|---|
| 154 | end |
|---|
| 155 | end |
|---|
| 156 | log("\n") |
|---|
| 157 | rec(r[1]) -- only useful if you use a single format in tests |
|---|
| 158 | return unpack(r) |
|---|
| 159 | end, |
|---|
| 160 | flush=function(self) |
|---|
| 161 | log(self.name,":flush(): "); |
|---|
| 162 | return logres(self.f:flush()) |
|---|
| 163 | end, |
|---|
| 164 | close=function(self) |
|---|
| 165 | log(self.name,":close(): "); |
|---|
| 166 | local r=self.f:close() |
|---|
| 167 | self.f=nil |
|---|
| 168 | self.name=nil |
|---|
| 169 | return logres(r) |
|---|
| 170 | end, |
|---|
| 171 | new=function(self,name,mode) |
|---|
| 172 | local tf={} |
|---|
| 173 | for k,v in pairs(tfproto) do |
|---|
| 174 | tf[k]=v |
|---|
| 175 | end |
|---|
| 176 | if name then |
|---|
| 177 | tf:open(name,mode) |
|---|
| 178 | end |
|---|
| 179 | return tf |
|---|
| 180 | end, |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | function test_readn(tf) |
|---|
| 184 | local done |
|---|
| 185 | local ns={} |
|---|
| 186 | local want={1,2,3,1234567890} |
|---|
| 187 | local c=1 |
|---|
| 188 | log('testing file:read("*n")\n') |
|---|
| 189 | no_rec=true -- too complicated |
|---|
| 190 | while not done do |
|---|
| 191 | local t=tf:read("*n") |
|---|
| 192 | tf:seek() -- report pos |
|---|
| 193 | if t then |
|---|
| 194 | ns[c]=t |
|---|
| 195 | c=c+1 |
|---|
| 196 | else |
|---|
| 197 | t=tf:read(1) |
|---|
| 198 | tf:seek() |
|---|
| 199 | if not t then |
|---|
| 200 | done=true |
|---|
| 201 | end |
|---|
| 202 | end |
|---|
| 203 | end |
|---|
| 204 | no_rec=false |
|---|
| 205 | for i=1,c-1 do |
|---|
| 206 | if ns[i] ~= want[i] then |
|---|
| 207 | logfail(ns[i], " != ",want[i]) |
|---|
| 208 | end |
|---|
| 209 | end |
|---|
| 210 | if c ~= 5 then |
|---|
| 211 | logfail("want 5 got ",c) |
|---|
| 212 | end |
|---|
| 213 | end |
|---|
| 214 | |
|---|
| 215 | function tstart(n) |
|---|
| 216 | nfail=0 |
|---|
| 217 | want_ok=true |
|---|
| 218 | no_rec=false |
|---|
| 219 | log("***test ",n,"***\n") |
|---|
| 220 | end |
|---|
| 221 | |
|---|
| 222 | function tend(n) |
|---|
| 223 | s="***end "..n |
|---|
| 224 | if nfail > 0 then |
|---|
| 225 | s=s.." FAIL "..tostring(nfail) |
|---|
| 226 | else |
|---|
| 227 | s=s.." OK" |
|---|
| 228 | end |
|---|
| 229 | s=s.."***" |
|---|
| 230 | log(s,"\n") |
|---|
| 231 | print(s) |
|---|
| 232 | end |
|---|
| 233 | |
|---|
| 234 | function io_test() |
|---|
| 235 | tstart("io") |
|---|
| 236 | fpinfo(io.input(),"io.input") -- expect closed |
|---|
| 237 | fpinfo(io.output(),"io.output") -- expect open |
|---|
| 238 | |
|---|
| 239 | local tf=tfproto:new(iotfnam,"w+b") |
|---|
| 240 | if not tf.f then |
|---|
| 241 | log("aborting\n") |
|---|
| 242 | return |
|---|
| 243 | end |
|---|
| 244 | tf:write("the slick brown fox jumps over the lazy dog\n") |
|---|
| 245 | tf:seek("set",4) |
|---|
| 246 | local s=tf:read(5) |
|---|
| 247 | if s ~= "slick" then |
|---|
| 248 | logfail("want [slick] got [",tostring(s),"]") |
|---|
| 249 | end |
|---|
| 250 | tf:seek() -- report pos |
|---|
| 251 | tf:seek("cur",-5) |
|---|
| 252 | tf:write("qu") |
|---|
| 253 | tf:seek("end") |
|---|
| 254 | tf:write(1,"\n",2,"a"," 3"," 1234567890"," b"); |
|---|
| 255 | tf:flush() |
|---|
| 256 | tf:seek("set") |
|---|
| 257 | log("test file:lines()\n") |
|---|
| 258 | local lnum=0 |
|---|
| 259 | for line in tf.f:lines() do |
|---|
| 260 | log(lnum,": [",line,"]\n") |
|---|
| 261 | lnum=lnum + 1 |
|---|
| 262 | end |
|---|
| 263 | tf:seek("set") |
|---|
| 264 | tf:write(" \n") |
|---|
| 265 | tf:seek("set") |
|---|
| 266 | log('test file:read("*a")\n') |
|---|
| 267 | tf:read("*a") |
|---|
| 268 | tf:seek("set") |
|---|
| 269 | test_readn(tf) |
|---|
| 270 | tf:close(); |
|---|
| 271 | log('test open missing file\n') |
|---|
| 272 | want_ok=false |
|---|
| 273 | tf:open("A/bogus","r") |
|---|
| 274 | if tf.f then |
|---|
| 275 | tf:close() |
|---|
| 276 | end |
|---|
| 277 | log('test open dir\n') |
|---|
| 278 | tf:open("A/CHDK","r") |
|---|
| 279 | if tf.f then |
|---|
| 280 | tf:close() |
|---|
| 281 | end |
|---|
| 282 | want_ok=true |
|---|
| 283 | tf:open(iotfnam,"r") |
|---|
| 284 | want_ok=false |
|---|
| 285 | log('test invalid seeks\n') |
|---|
| 286 | tf:seek("set",-1) |
|---|
| 287 | tf:seek("end",100) |
|---|
| 288 | -- on a540 write succeeds, close fails |
|---|
| 289 | -- log('testinvalid write\n') |
|---|
| 290 | -- tf:write("whee!") |
|---|
| 291 | want_ok=true |
|---|
| 292 | tf:close() |
|---|
| 293 | tend("io") |
|---|
| 294 | log("\n") |
|---|
| 295 | end |
|---|
| 296 | |
|---|
| 297 | function ttime(t) |
|---|
| 298 | log('os.time(') |
|---|
| 299 | if type(t) == "table" then |
|---|
| 300 | log('{') |
|---|
| 301 | for k,v in pairs(t) do |
|---|
| 302 | log(tostring(k),'=',tostring(v),",") |
|---|
| 303 | end |
|---|
| 304 | log('}') |
|---|
| 305 | elseif type(t) ~= "nil" then |
|---|
| 306 | log(type(t),"[",tostring(t),"]") |
|---|
| 307 | end |
|---|
| 308 | log('): ') |
|---|
| 309 | local r=os.time(t) |
|---|
| 310 | if r then |
|---|
| 311 | logok(tostring(r)) |
|---|
| 312 | else |
|---|
| 313 | logfail() |
|---|
| 314 | end |
|---|
| 315 | return r |
|---|
| 316 | end |
|---|
| 317 | |
|---|
| 318 | function dump_date_fmts() |
|---|
| 319 | local tm=os.time() |
|---|
| 320 | -- fmts in vx docs |
|---|
| 321 | -- dryos (sx100) seems to support all but Z |
|---|
| 322 | -- dryos returns the partern if it isn't supported, vx returns "" |
|---|
| 323 | local fdsc={ |
|---|
| 324 | "a","A","b","B","c","d","H","I","j","m","M", |
|---|
| 325 | "p", -- vxworks docs say P but only p works |
|---|
| 326 | "S","U","w","W","x","X","y","Y","Z","%", |
|---|
| 327 | } |
|---|
| 328 | local s |
|---|
| 329 | for _,v in ipairs(fdsc) do |
|---|
| 330 | s="%"..v |
|---|
| 331 | log(s," [",os.date(s,tm),"]\n"); |
|---|
| 332 | end |
|---|
| 333 | end |
|---|
| 334 | |
|---|
| 335 | function tren(from,to) |
|---|
| 336 | log('os.rename("',tostring(from),'","',tostring(to),"): ") |
|---|
| 337 | local r,msg = os.rename(from,to) |
|---|
| 338 | if r then |
|---|
| 339 | logok() |
|---|
| 340 | else |
|---|
| 341 | logfail(tostring(msg)) |
|---|
| 342 | end |
|---|
| 343 | end |
|---|
| 344 | |
|---|
| 345 | function trem(name) |
|---|
| 346 | log('os.remove("',tostring(name),"): ") |
|---|
| 347 | local r,msg = os.remove(name) |
|---|
| 348 | if r then |
|---|
| 349 | logok() |
|---|
| 350 | else |
|---|
| 351 | logfail(tostring(msg)) |
|---|
| 352 | end |
|---|
| 353 | end |
|---|
| 354 | |
|---|
| 355 | function tmd(name) |
|---|
| 356 | log('os.mkdir("',tostring(name),'"): ') |
|---|
| 357 | local r,msg = os.mkdir(name) |
|---|
| 358 | if r then |
|---|
| 359 | logok() |
|---|
| 360 | else |
|---|
| 361 | logfail(tostring(msg)) |
|---|
| 362 | end |
|---|
| 363 | end |
|---|
| 364 | |
|---|
| 365 | function tstat(name) |
|---|
| 366 | log('os.stat("',tostring(name),'"): ') |
|---|
| 367 | local r,msg = os.stat(name) |
|---|
| 368 | if r then |
|---|
| 369 | -- local keys={ "dev", "ino", "mode", "nlink", "uid", "gid", "rdev", "size", "atime", "mtime", "ctime", "blksize", "blocks", "attrib", "reserved1", "reserved2", "reserved3", "reserved4", "reserved5", "reserved6",} |
|---|
| 370 | local keys={ "dev", "mode", "size", "atime", "mtime", "ctime", "blksize", "blocks", "attrib","is_dir","is_file",} |
|---|
| 371 | logok() |
|---|
| 372 | log("{\n") |
|---|
| 373 | for _,v in ipairs(keys) do |
|---|
| 374 | log(" ",tostring(v),"=",tostring(r[v]),"\n") |
|---|
| 375 | end |
|---|
| 376 | log("}\n") |
|---|
| 377 | else |
|---|
| 378 | logfail(tostring(msg)) |
|---|
| 379 | end |
|---|
| 380 | return r |
|---|
| 381 | end |
|---|
| 382 | |
|---|
| 383 | function tlistdir(name,showall) |
|---|
| 384 | log('os.listdir("',tostring(name),'",',tostring(showall),'): ') |
|---|
| 385 | local r,msg = os.listdir(name,showall) |
|---|
| 386 | if r then |
|---|
| 387 | logok() |
|---|
| 388 | log("{\n") |
|---|
| 389 | for k,v in ipairs(r) do |
|---|
| 390 | log(' ',k,'="',tostring(v),'"\n') |
|---|
| 391 | end |
|---|
| 392 | log("}\n") |
|---|
| 393 | else |
|---|
| 394 | logfail(tostring(msg)) |
|---|
| 395 | end |
|---|
| 396 | return r |
|---|
| 397 | end |
|---|
| 398 | |
|---|
| 399 | function tutime(name,mtime,atime) |
|---|
| 400 | log('os.utime("',tostring(name),'",',tostring(mtime),',',tostring(atime),'): ') |
|---|
| 401 | local r,msg = os.utime(name,mtime,atime) |
|---|
| 402 | if r then |
|---|
| 403 | logok() |
|---|
| 404 | else |
|---|
| 405 | logfail(tostring(msg)) |
|---|
| 406 | end |
|---|
| 407 | end |
|---|
| 408 | |
|---|
| 409 | function os_test() |
|---|
| 410 | tstart("os") |
|---|
| 411 | if type(os) ~= "table" then |
|---|
| 412 | log("missing os aborting!\n") |
|---|
| 413 | return |
|---|
| 414 | end |
|---|
| 415 | if do_time then |
|---|
| 416 | local s=os.date() |
|---|
| 417 | log("current date ",tostring(s),"\n"); |
|---|
| 418 | if not s then |
|---|
| 419 | logfail("nil value\n") |
|---|
| 420 | end |
|---|
| 421 | ttime() |
|---|
| 422 | local t={year=1980,month=1,day=1} |
|---|
| 423 | local tm=ttime(t) |
|---|
| 424 | if tm ~= 315576000 then |
|---|
| 425 | logfail("want ",315576000," got ",tostring(tm)) |
|---|
| 426 | end |
|---|
| 427 | want_ok=false |
|---|
| 428 | t={year=1066,month=1,day=1} |
|---|
| 429 | ttime(t) |
|---|
| 430 | if do_fmtdump then |
|---|
| 431 | dump_date_fmts() |
|---|
| 432 | end |
|---|
| 433 | end |
|---|
| 434 | if do_dir then |
|---|
| 435 | want_ok=true |
|---|
| 436 | local tdir0,tdat0,tdat1="A/MDTST0","/TEST0.DAT","/TEST1.DAT" |
|---|
| 437 | tmd(tdir0) |
|---|
| 438 | local tf=tfproto:new(tdir0..tdat0,"wb") |
|---|
| 439 | tf:write("data") |
|---|
| 440 | tf:close() |
|---|
| 441 | local fn=tdir0..tdat0 |
|---|
| 442 | tstat(fn) |
|---|
| 443 | tutime(fn) -- utime, current |
|---|
| 444 | tstat(fn) |
|---|
| 445 | tutime(fn,os.time({year=1984,month=1,day=1}),os.time({year=1984,month=12,day=25})) |
|---|
| 446 | tstat(fn) |
|---|
| 447 | tstat(tdir0) |
|---|
| 448 | tren(tdir0..tdat0,tdir0..tdat1) |
|---|
| 449 | tlistdir(tdir0) |
|---|
| 450 | tlistdir(tdir0,true) |
|---|
| 451 | -- NOTE invalid operations frequently leave the filesystem in a corrupt state |
|---|
| 452 | -- trename(tdir0,tdir1) |
|---|
| 453 | want_ok=false |
|---|
| 454 | trem(tdir0) --fail, not empty |
|---|
| 455 | trem("A/bogus") --fail missing |
|---|
| 456 | tlistdir("A/bogus") -- missing |
|---|
| 457 | tlistdir("A/llibtst.log") -- not a directory |
|---|
| 458 | tstat("A/bogus") -- fail missing |
|---|
| 459 | tutime("A/bogus") -- fail missing |
|---|
| 460 | tren("A/bogus","A/blah")--fail missing |
|---|
| 461 | tmd("A/CHDK")--fail, exists |
|---|
| 462 | want_ok=true |
|---|
| 463 | trem(tdir0..tdat1) |
|---|
| 464 | trem(tdir0) |
|---|
| 465 | no_rec=true |
|---|
| 466 | trem(iotfnam)--try to clean up from io |
|---|
| 467 | end |
|---|
| 468 | tend("os") |
|---|
| 469 | log("\n") |
|---|
| 470 | end |
|---|
| 471 | |
|---|
| 472 | testlog,msg=io.open("A/llibtst.log","wb") |
|---|
| 473 | if not testlog then |
|---|
| 474 | error("open test log fail:"..tostring(msg)) |
|---|
| 475 | end |
|---|
| 476 | |
|---|
| 477 | io.output(testlog) |
|---|
| 478 | bi=get_buildinfo() |
|---|
| 479 | log("test log opened\n"); |
|---|
| 480 | log("platform: ",bi.platform," ",bi.platsub,"\n") |
|---|
| 481 | log("version: ",bi.version," ",bi.build_number," built on ",bi.build_date," ",bi.build_time,"\n") |
|---|
| 482 | if do_io then |
|---|
| 483 | io_test() |
|---|
| 484 | end |
|---|
| 485 | |
|---|
| 486 | if do_os then |
|---|
| 487 | os_test() |
|---|
| 488 | end |
|---|
| 489 | log("close test log\n"); |
|---|
| 490 | io.close(testlog) |
|---|
| 491 | sleep(2000) |
|---|