src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/mods/os/os_test.elvts (about) 1 //each:eval use os 2 //each:in-temp-dir 3 4 //////////// 5 # os:mkdir # 6 //////////// 7 8 ~> os:mkdir d 9 os:is-dir d 10 ▶ $true 11 12 ## error when directory already exists ## 13 ~> os:mkdir d 14 try { os:mkdir d } catch e { os:-is-exist $e } 15 ▶ $true 16 17 ## &perm ## 18 //only-on !windows 19 //umask 0 20 // TODO: Re-enable this after os:mkdir respects &perm on Windows. 21 ~> os:mkdir &perm=0o555 d555 22 printf "%O\n" (os:stat d555)[perm] 23 0o555 24 25 ## &perm on Unix ## 26 //only-on unix 27 //umask 0 28 // Windows only supports 0o555 and 0o777; test other values on Unix only. 29 ~> os:mkdir &perm=0o400 d400 30 printf "%O\n" (os:stat d400)[perm] 31 0o400 32 33 //////////////// 34 # os:mkdir-all # 35 //////////////// 36 37 ~> os:mkdir-all a/b 38 os:is-dir a 39 os:is-dir a/b 40 ▶ $true 41 ▶ $true 42 43 ## no error if the directory already exists ## 44 ~> os:mkdir-all a/b 45 ~> os:mkdir-all a/b 46 47 ## &perm ## 48 //only-on !windows 49 //umask 0 50 ~> os:mkdir-all &perm=0o700 a/b 51 printf "%O\n" (os:stat a)[perm] 52 printf "%O\n" (os:stat a/b)[perm] 53 0o700 54 0o700 55 56 ////////////// 57 # os:symlink # 58 ////////////// 59 60 //only-if-can-create-symlink 61 62 ~> echo foo > regular 63 ~> os:symlink regular symlink 64 ~> slurp < symlink 65 ▶ "foo\n" 66 ~> os:eval-symlinks symlink 67 ▶ regular 68 69 ///////////// 70 # os:remove # 71 ///////////// 72 73 ~> echo > f; os:exists f 74 os:remove f; os:exists f 75 ▶ $true 76 ▶ $false 77 ~> os:mkdir d; os:exists d 78 os:remove d; os:exists d 79 ▶ $true 80 ▶ $false 81 82 ## can't remove non-empty directory (Unix) ## 83 //only-on unix 84 ~> os:mkdir d; echo > d/file 85 os:remove d 86 Exception: remove d: directory not empty 87 [tty]:2:1-11: os:remove d 88 89 ## can't remove non-empty directory (Windows) ## 90 //only-on windows 91 // Windows has a different error message. 92 ~> os:mkdir d; echo > d/file 93 os:remove d 94 Exception: remove d: The directory is not empty. 95 [tty]:2:1-11: os:remove d 96 97 ## can't remove non-existent file ## 98 ~> try { os:remove d } catch e { os:-is-not-exist $e } 99 ▶ $true 100 101 ## doesn't take empty string ## 102 ~> os:remove "" 103 Exception: bad value: path must be non-empty string, but is empty string 104 [tty]:1:1-12: os:remove "" 105 106 ///////////////// 107 # os:remove-all # 108 ///////////////// 109 110 ## relative path ## 111 ~> os:mkdir d; echo > d/file 112 os:remove-all d; os:exists d 113 ▶ $false 114 115 ## absolute path ## 116 ~> os:mkdir d; echo > d/file 117 os:remove-all $pwd/d; os:exists d 118 ▶ $false 119 120 ## removing non-existent file is not an error ## 121 ~> os:remove-all d 122 123 ## doesn't take empty string ## 124 ~> os:remove-all "" 125 Exception: bad value: path must be non-empty string, but is empty string 126 [tty]:1:1-16: os:remove-all "" 127 128 ///////////// 129 # os:rename # 130 ///////////// 131 132 ~> echo > old 133 os:exists old 134 os:exists new 135 ▶ $true 136 ▶ $false 137 ~> os:rename old new 138 os:exists old 139 os:exists new 140 ▶ $false 141 ▶ $true 142 143 //////////// 144 # os:chmod # 145 //////////// 146 147 ~> os:mkdir d 148 ~> os:chmod 0o555 d 149 printf "%O\n" (os:stat d)[perm] 150 0o555 151 ~> os:chmod 0o777 d 152 printf "%O\n" (os:stat d)[perm] 153 0o777 154 155 ## Unix ## 156 //only-on unix 157 // Windows only supports 0o555 (for read-only files) and 0o777 (for non-readonly 158 // files) in the perm bits, and no special modes. Test more perm bits and 159 // special modes on Unix only. 160 ~> os:mkdir d 161 ~> os:chmod &special-modes=[setuid setgid sticky] 0o400 d 162 put (printf "%O" (os:stat d)[perm]) 163 put (os:stat d)[special-modes] 164 ▶ 0o400 165 ▶ [setuid setgid sticky] 166 167 ## invalid arguments ## 168 ~> os:chmod -1 d 169 Exception: out of range: permission bits must be from 0 to 0o777, but is -1 170 [tty]:1:1-13: os:chmod -1 d 171 // TODO: This error should be more informative and point out that it is the 172 // special modes that should be iterable 173 ~> os:chmod &special-modes=(num 0) 0 d 174 Exception: cannot iterate number 175 [tty]:1:1-35: os:chmod &special-modes=(num 0) 0 d 176 ~> os:chmod &special-modes=[bad] 0 d 177 Exception: bad value: special mode must be setuid, setgid or sticky, but is bad 178 [tty]:1:1-33: os:chmod &special-modes=[bad] 0 d 179 180 /////////// 181 # os:stat # 182 /////////// 183 184 // Test basic fields common to all platforms. The perm and special-modes fields 185 // and already tested alongside os:chmod, so we don't repeat those. 186 ~> os:mkdir dir 187 ~> print 123456 > file 188 ~> put (os:stat file)[name type size] 189 ▶ file 190 ▶ regular 191 ▶ (num 6) 192 // size exists for directories on all platforms, but the value is 193 // platform-depedent. 194 ~> put (os:stat dir)[name type] 195 ▶ dir 196 ▶ dir 197 198 ## can't stat non-existent file (Unix) ## 199 //only-on unix 200 ~> os:stat non-existent 201 Exception: lstat non-existent: no such file or directory 202 [tty]:1:1-20: os:stat non-existent 203 204 ## can't stat non-existent file (Windows) ## 205 //only-on windows 206 // Windows has a different error message. 207 ~> os:stat non-existent 208 Exception: CreateFile non-existent: The system cannot find the file specified. 209 [tty]:1:1-20: os:stat non-existent 210 211 ## symlink ## 212 //only-if-can-create-symlink 213 ~> echo > regular 214 os:symlink regular symlink 215 ~> put (os:stat symlink)[type] 216 ▶ symlink 217 ~> put (os:stat &follow-symlink symlink)[type] 218 ▶ regular 219 220 ## fifo ## 221 //mkfifo-or-skip fifo 222 ~> put (os:stat fifo)[type] 223 ▶ named-pipe 224 225 ## sock on Unix ## 226 //mksock-or-skip sock 227 //only-on unix 228 ~> put (os:stat sock)[type] 229 ▶ socket 230 231 ## sock on Windows ## 232 //mksock-or-skip sock 233 //only-on windows 234 // Windows does support Unix sockets now, but the type is not reflected in what 235 // we get from os.Stat. 236 ~> put (os:stat sock)[type] 237 ▶ irregular 238 239 ## device ## 240 //only-on unix 241 ~> put (os:stat /dev/null)[type] 242 ▶ char-device 243 244 ## sys on Unix ## 245 //only-on unix 246 ~> echo > file 247 var sys = (os:stat file)[sys] 248 put $sys[nlink] 249 and (each {|f| has-key $sys $f} [dev ino uid gid rdev blksize blocks]) 250 ▶ (num 1) 251 ▶ $true 252 253 ## sys on Windows ## 254 //only-on windows 255 //create-windows-special-files-or-skip 256 ~> has-value (os:stat directory)[sys][file-attributes] directory 257 ▶ $true 258 ~> has-value (os:stat readonly)[sys][file-attributes] readonly 259 ▶ $true 260 ~> has-value (os:stat hidden)[sys][file-attributes] hidden 261 ▶ $true 262 263 ////////////////////////////////////////// 264 # os:exists, os:is-dir and os:is-regular # 265 ////////////////////////////////////////// 266 267 ~> os:mkdir d 268 ~> echo > d/f 269 ~> os:exists $pwd 270 ▶ $true 271 ~> os:is-dir $pwd 272 ▶ $true 273 ~> os:is-regular $pwd 274 ▶ $false 275 ~> os:exists d 276 ▶ $true 277 ~> os:is-dir d 278 ▶ $true 279 ~> os:is-regular d 280 ▶ $false 281 ~> os:exists d/f 282 ▶ $true 283 ~> os:is-dir d/f 284 ▶ $false 285 ~> os:is-regular d/f 286 ▶ $true 287 ~> os:exists bad 288 ▶ $false 289 ~> os:is-dir bad 290 ▶ $false 291 ~> os:is-regular bad 292 ▶ $false 293 294 ///////////////////////// 295 # symbolic link-related # 296 ///////////////////////// 297 298 //only-if-can-create-symlink 299 // Set up symlinks to test. Each file is named as "s-" plus path relative to the 300 // test directory root, with / changed to -. 301 ~> os:mkdir d 302 echo > d/f 303 os:symlink f d/s-f # target is in same directory 304 os:symlink d s-d # target is directory 305 os:symlink d/f s-d-f # target is in subdirectory 306 os:symlink bad s-bad # target doesn't exist 307 // These tests can run on Windows, where the output of os:eval-symlinks will use 308 // \ as the path separator, so we can't rely on the exact output. 309 ~> use path 310 // Not symlink 311 ~> eq (os:eval-symlinks d/f) (path:join d f) 312 ▶ $true 313 // Leaf is symlink 314 ~> eq (os:eval-symlinks d/s-f) (path:join d f) 315 ▶ $true 316 // Non-leaf is symlink 317 ~> eq (os:eval-symlinks s-d/f) (path:join d f) 318 ▶ $true 319 ~> os:exists s-d 320 ▶ $true 321 ~> os:exists s-d &follow-symlink 322 ▶ $true 323 ~> os:exists s-d-f 324 ▶ $true 325 ~> os:exists s-d-f &follow-symlink 326 ▶ $true 327 ~> os:exists s-bad 328 ▶ $true 329 ~> os:exists s-bad &follow-symlink 330 ▶ $false 331 ~> os:exists bad 332 ▶ $false 333 ~> os:exists bad &follow-symlink 334 ▶ $false 335 ~> os:is-dir s-d 336 ▶ $false 337 ~> os:is-dir s-d &follow-symlink 338 ▶ $true 339 ~> os:is-dir s-d-f 340 ▶ $false 341 ~> os:is-dir s-d-f &follow-symlink 342 ▶ $false 343 ~> os:is-dir s-bad 344 ▶ $false 345 ~> os:is-dir s-bad &follow-symlink 346 ▶ $false 347 ~> os:is-dir bad 348 ▶ $false 349 ~> os:is-dir bad &follow-symlink 350 ▶ $false 351 ~> os:is-regular s-d 352 ▶ $false 353 ~> os:is-regular s-d &follow-symlink 354 ▶ $false 355 ~> os:is-regular s-d-f 356 ▶ $false 357 ~> os:is-regular s-d-f &follow-symlink 358 ▶ $true 359 ~> os:is-regular s-bad 360 ▶ $false 361 ~> os:is-regular s-bad &follow-symlink 362 ▶ $false 363 ~> os:is-regular bad 364 ▶ $false 365 ~> os:is-regular bad &follow-symlink 366 ▶ $false 367 368 ## os:eval-symlinks given non-existent file (Unix) ## 369 //only-on unix 370 ~> os:symlink bad s-bad 371 ~> os:eval-symlinks s-bad 372 Exception: lstat bad: no such file or directory 373 [tty]:1:1-22: os:eval-symlinks s-bad 374 375 ## os:eval-symlinks given non-existent file (Windows) ## 376 // Windows has a different error message. 377 //only-on windows 378 ~> os:symlink bad s-bad 379 ~> os:eval-symlinks s-bad 380 Exception: CreateFile bad: The system cannot find the file specified. 381 [tty]:1:1-22: os:eval-symlinks s-bad 382 383 /////////////// 384 # os:temp-dir # 385 /////////////// 386 387 //each:eval use re 388 389 // default name template is elvish-* 390 ~> var x = (os:temp-dir) 391 os:remove $x 392 re:match '[/\\]elvish-.*$' $x 393 ▶ $true 394 // explicit name template 395 ~> var x = (os:temp-dir 'x-*.y') 396 os:remove $x 397 re:match '[/\\]x-.*\.y$' $x 398 ▶ $true 399 400 ## create in pwd ## 401 //in-temp-dir 402 ~> var x = (os:temp-dir &dir=.) 403 os:remove $x 404 re:match '^(\.[/\\])?elvish-.*$' $x 405 ▶ $true 406 ~> var x = (os:temp-dir &dir=. 'x-*.y') 407 os:remove $x 408 re:match '^(\.[/\\])?x-.*\.y$' $x 409 ▶ $true 410 411 ## arity check ## 412 ~> os:temp-dir a b 413 Exception: arity mismatch: arguments must be 0 to 1 values, but is 2 values 414 [tty]:1:1-15: os:temp-dir a b 415 416 //////////////// 417 # os:temp-file # 418 //////////////// 419 420 //each:eval use re 421 //each:eval use file 422 423 ~> var f = (os:temp-file) 424 re:match '[/\\]elvish-.*$' $f[name] 425 file:close $f 426 os:remove $f[name] 427 ▶ $true 428 ~> var f = (os:temp-file 'x-*.y') 429 re:match '[/\\]x-.*\.y$' $f[name] 430 file:close $f 431 os:remove $f[name] 432 ▶ $true 433 434 ## create in pwd ## 435 //in-temp-dir 436 ~> var f = (os:temp-file &dir=.) 437 re:match '^(\.[/\\])?elvish-.*$' $f[name] 438 file:close $f 439 os:remove $f[name] 440 ▶ $true 441 ~> var f = (os:temp-file &dir=. 'x-*.y') 442 re:match '^(\.[/\\])?x-.*\.y$' $f[name] 443 file:close $f 444 os:remove $f[name] 445 ▶ $true 446 447 ## arity check ## 448 ~> os:temp-file a b 449 Exception: arity mismatch: arguments must be 0 to 1 values, but is 2 values 450 [tty]:1:1-16: os:temp-file a b