;;; Tests for the function in section 3.3 of the scsh-manual "File system" ;;; Author: David Frese ; file-type: don't know how to test block-special, char-special ; socket should be tested in section "Networking"!! ; file-device: ?? ; file-inode: only tested for overflow ; ; sync-file: Test is not very stable, I guess?? ; ; glob: hard work ?? ; temp-file-iterate: could it be ignored?? create-temp-file uses it anyway?? ; temp-file-channel: ?? (define create-temp-dir (let ((temp-dir "/tmp/scsh-test/")) (lambda () (if (file-not-exists? temp-dir) (create-directory temp-dir)) temp-dir))) (define (file-perms fname/fd/port) (bitwise-and (file-mode fname/fd/port) #o777)) (define (mask fixnum) (bitwise-and fixnum (bitwise-not (umask)))) (define (create-file fname) (close-output-port (open-output-file fname))) (define (open/create-file fname flags) (if (file-not-exists? fname) (create-file fname)) (open-file fname flags)) (define (symbol-append symbol string) (string->symbol (string-append (symbol->string symbol) string))) ;; --- Create-Directory --- (add-test! 'create-directory-1 'file-system (lambda (name) (with-cwd (create-temp-dir) (create-directory name) (let ((result (file-directory? name))) (delete-filesys-object name) result))) "dir") (add-test! 'create-directory-2 'file-system (lambda (name perms) (with-cwd (create-temp-dir) (create-directory name perms) (let ((result (and (file-directory? name) (= (file-perms name) (mask perms))))) (delete-filesys-object name) result))) "dir" #o700) ;; --- Create FIFO --- (add-test! 'create-fifo-1 'file-system (lambda (name) (with-cwd (create-temp-dir) (create-fifo name) (let ((result (eq? (file-type name) 'fifo))) (delete-filesys-object name) result))) "fifo") (add-test! 'create-fifo-2 'file-system (lambda (name perms) (with-cwd (create-temp-dir) (create-fifo name perms) (let ((result (and (eq? (file-type name) 'fifo) (= (file-perms name) (mask perms))))) (delete-filesys-object name) result))) "fifo" #o700) ;; --- Create-hard-link --- (add-test! 'create-hard-link 'file-system (lambda (fname linkname) (with-cwd (create-temp-dir) (close-output-port (open-output-file fname)) (create-hard-link fname linkname) (let ((result (file-exists? linkname))) (delete-filesys-object fname) (delete-filesys-object linkname) result))) "file" "hard-link") ;; --- Create-symlink --- (add-test! 'create-symlink 'file-system (lambda (fname linkname) (with-cwd (create-temp-dir) (create-file fname) (create-symlink fname linkname) (let ((result (and (file-exists? linkname) (eq? (file-type linkname #f) 'symlink) (eq? (file-type linkname #t) 'regular)))) (delete-filesys-object fname) (delete-filesys-object linkname) result))) "file" "symlink") ;; --- Delete-Directory --- (add-test! 'delete-directory 'file-system (lambda (name) (with-cwd (create-temp-dir) (create-directory name) (delete-directory name) (file-not-exists? name))) "dir") ;; --- Delete-File --- (add-test! 'delete-file 'file-system (lambda (name) (with-cwd (create-temp-dir) (create-file name) (delete-file name) (file-not-exists? name))) "file") (add-test! 'delete-filesys-object 'file-system (lambda (name) (with-cwd (create-temp-dir) (create-file name) (delete-filesys-object name) (and (file-not-exists? name) ;; even now, it shouldn't signal an error (delete-filesys-object name)))) "file") ;; --- Read-Symlink --- (add-test! 'read-symlink 'file-system (lambda (fname linkname) (with-cwd (create-temp-dir) (create-file fname) (create-symlink fname linkname) (let ((result (equal? fname (read-symlink linkname)))) (delete-filesys-object fname) (delete-filesys-object linkname) result))) "file" "symlink") ;; --- Rename-File --- (add-test! 'rename-file 'file-system (lambda (name1 name2) (with-cwd (create-temp-dir) (create-file name1) (rename-file name1 name2) (let ((result (and (file-exists? name2) (file-not-exists? name1)))) (delete-filesys-object name2) result))) "file-1" "file-2") ;; --- Little Abstraction for funcs with fname/fd/port --- ;; uses add-test-multiple! (define (add-test/fname/fd/port! name before-func func result-func . input-lists) (let ((name-1 (string->symbol (string-append (symbol->string name) "/fname"))) (name-2 (string->symbol (string-append (symbol->string name) "/fd"))) (name-3 (string->symbol (string-append (symbol->string name) "/port")))) ;; Test as a filename (apply add-test-multiple! name-1 'file-system (lambda (fname . params) (with-cwd (create-temp-dir) (let ((port (open/create-file fname open/write))) (if before-func (before-func port)) (let ((result (apply func (cons fname params)))) (close port) (delete-filesys-object fname) (if result-func (apply result-func result params) result))))) input-lists) ;; Test as a fdes (apply add-test-multiple! name-2 'file-system (lambda (fname . params) (with-cwd (create-temp-dir) (let ((port (open/create-file fname open/write))) (if before-func (before-func port)) (let ((result (apply func (cons (port->fdes port) params)))) (close port) (delete-filesys-object fname) (if result-func (apply result-func result params) result))))) input-lists) ;; Test as a port (apply add-test-multiple! name-3 'file-system (lambda (fname . params) (with-cwd (create-temp-dir) (let ((port (open/create-file fname open/write))) (if before-func (before-func port)) (let ((result (apply func (cons port params)))) (close port) (delete-filesys-object fname) (if result-func (apply result-func result params) result))))) input-lists) )) ;; --- Set-file-mode --- (add-test/fname/fd/port! 'set-file-mode #f (lambda (fname/fd/port mode) (set-file-mode fname/fd/port mode) (file-perms fname/fd/port)) = '("file") '(#o754)) ;; --- Set-file-owner --- (add-test/fname/fd/port! 'set-file-owner #f (lambda (fname/fd/port uid) (set-file-owner fname/fd/port uid) (file-owner fname/fd/port)) equal? '("file") (list (user-uid))) ;; --- Set-file-group --- (add-test/fname/fd/port! 'set-file-group #f (lambda (fname/fd/port gid) (set-file-group fname/fd/port gid) (file-group fname/fd/port)) equal? '("file") (list (user-gid))) ;; --- set-file-times --- (add-test! 'set-file-times-1 'file-system (lambda (fname time-1) (with-cwd (create-temp-dir) (create-file fname) (set-file-times fname time-1 0) (let ((result (file-last-access fname))) (delete-filesys-object fname) (= result time-1)))) "file" 10000) (add-test! 'set-file-times-2 'file-system (lambda (fname time-2) (with-cwd (create-temp-dir) (create-file fname) (set-file-times fname 0 time-2) (let ((result (file-last-mod fname))) (delete-filesys-object fname) (= result time-2)))) "file" 10000) ;; --- sync-file --- (add-test! 'sync-file 'file-system (lambda (fname) (with-cwd (create-temp-dir) (create-file fname) (let ((port (open-file fname open/write))) (write-string "1" port) (let ((res-1 (file-size fname))) (sync-file port) (let ((res-2 (file-size fname))) (close port) (delete-filesys-object fname) (and (= res-1 0) (> res-2 0))))))) "file") ;; --- truncate-file --- (add-test/fname/fd/port! 'truncate-file (lambda (port) (write (make-string 100 #\*) port)) (lambda (fname/fd/port len) (truncate-file fname/fd/port len) (file-size fname/fd/port)) = '("file") '(10)) ;; --- file-info stuff --- ;; --- file-type --- (add-test! 'file-type-dir 'file-system (lambda (fname) (with-cwd (create-temp-dir) (create-directory fname) (let ((result (file-type fname))) (delete-filesys-object fname) (equal? result 'directory)))) "dir") (add-test! 'file-type-fifo 'file-system (lambda (fname) (with-cwd (create-temp-dir) (create-fifo fname) (let ((result (file-type fname))) (delete-filesys-object fname) (equal? result 'fifo)))) "fifo") (add-test! 'file-type-regular 'file-system (lambda (fname) (with-cwd (create-temp-dir) (create-file fname) (let ((result (file-type fname))) (delete-filesys-object fname) (equal? result 'regular)))) "file") ;(add-test! 'file-type-socket 'file-system ; (lambda (fname) ; (let* ((pathname (string-append (create-temp-dir) ; fname)) ; (socket (create-socket protocol-family/unix ; socket-type/raw)) ; (addr (unix-address->socket-address ; pathname))) ; (bind-socket socket addr) ; ;; now fname should be a socket ; (let ((result (file-info pathname))) ; (delete-filesys-object pathname) ; (equal? result 'socket)))) ; "socket") (add-test! 'file-type-symlink 'file-system (lambda (fname linkname) (create-file fname) (create-symlink fname linkname) (let ((result (file-type linkname #f)) (result-2 (file-type linkname #t))) (delete-filesys-object linkname) (delete-filesys-object fname) (and (equal? result 'symlink) (equal? result-2 'regular)))) "file" "symlink") ;; --- file-inode --- ;; only check for overrun (problem on AFS according to Martin) (add-test/fname/fd/port! 'file-inode #f (lambda (fname/fd/port) (> 0 (file-inode fname/fd/port))) '("file")) ;; --- file-mode --- (add-test/fname/fd/port! 'file-mode #f (lambda (fname/fd/port mode) (set-file-mode fname/fd/port mode) (bitwise-and (file-mode fname/fd/port) #o777)) = '("file") (list #o754)) ;; --- file-nlinks --- (add-test/fname/fd/port! 'file-nlinks #f (lambda (fname/fd/port fname1 fname2) (create-hard-link fname1 fname2) (let ((result (file-nlinks fname/fd/port))) (delete-filesys-object fname2) (= result 2))) #f '("file-1") '("file-1") '("file-2")) ;; --- file-owner --- (add-test/fname/fd/port! 'file-owner #f (lambda (fname/fd/port uid) (set-file-owner fname/fd/port uid) (file-owner fname/fd/port)) equal? '("file") (list (user-uid))) ;; --- file-group --- (add-test/fname/fd/port! 'file-group #f (lambda (fname/fd/port gid) (set-file-group fname/fd/port gid) (file-group fname/fd/port)) equal? '("file") (list (user-gid))) ;; --- file-size --- (add-test/fname/fd/port! 'file-size (lambda (port) (write-string "0123456789" port) (sync-file port)) file-size (lambda (res) (= res 10)) '("file")) ;; --- file-last-access --- (add-test/fname/fd/port! 'file-last-access #f (lambda (fname/fd/port fname atime) (set-file-times fname atime 0) (file-last-access fname/fd/port)) (lambda (restime fname mtime) (= restime mtime)) '("file") '("file") '(10000)) ;; --- file-last-mod --- (add-test/fname/fd/port! 'file-last-mod #f (lambda (fname/fd/port fname mtime) (set-file-times fname 0 mtime) (file-last-mod fname/fd/port)) (lambda (restime fname mtime) (= restime mtime)) '("file") '("file") '(10000)) ;; -- file-last-status-change --- (add-test/fname/fd/port! 'file-last-status-change #f (lambda (fname/fd/port) (let ((before (file-last-status-change fname/fd/port))) ;; do anything (set-file-mode fname/fd/port #o777) (let ((after (file-last-status-change fname/fd/port))) (> after before) ;; how much?? ))) '("file")) ;; --- file-not-read/write/exec-able --- (define (add-file-not-?-able func name perms) ;; normal function (add-test! (symbol-append name "-normal") 'file-system (lambda (fname) (with-cwd (create-temp-dir) (create-file fname) (set-file-mode fname perms) (let ((result (not (func fname)))) (delete-filesys-object fname) result))) "file") ;; search-denied (add-test! (symbol-append name "-search-denied") 'file-system (lambda (fname dirname) (with-cwd (create-temp-dir) (create-directory dirname) (create-file (string-append dirname fname)) (set-file-mode dirname 0) ;; or 666 ?? (let ((result (func (string-append dirname fname)))) (set-file-mode dirname #o777) (delete-filesys-object (string-append dirname fname)) (delete-filesys-object dirname) (equal? result 'search-denied)))) "file" "dir/") ;; permission denied (add-test! (symbol-append name "-permission") 'file-system (lambda (fname) (with-cwd (create-temp-dir) (create-file fname) (set-file-mode fname (bitwise-xor perms #o777)) (let ((result (func fname))) (delete-filesys-object fname) (equal? result 'permission)))) "file") ;; not-directory (add-test! (symbol-append name "-no-directory") 'file-system (lambda (fname fname2) (with-cwd (create-temp-dir) (create-file fname2) (let ((result (func (string-append fname2 "/" fname)))) (delete-filesys-object fname2) (equal? result 'no-directory)))) "file" "file2") ;; nonexistent (add-test! (symbol-append name "-nonexistent") 'file-system (lambda (fname) (with-cwd (create-temp-dir) (delete-filesys-object fname) (let ((result (func fname))) (or (equal? result 'nonexistent) (and (not result) (eq? func file-not-writable?)))))) "file")) (add-file-not-?-able file-not-readable? 'file-not-readable? #o444) (add-file-not-?-able file-not-writable? 'file-not-writable? #o222) (add-file-not-?-able file-not-executable? 'file-not-executable? #o111) ;; --- file-(not)-exists? -- (add-test! 'file-not-exists-1? 'file-system (lambda (fname) (with-cwd (create-temp-dir) (delete-filesys-object fname) (let ((res-1 (file-not-exists? fname))) (create-file fname) (let ((res-2 (file-exists? fname))) (delete-filesys-object fname) (and res-1 res-2))))) "file") (add-test! 'file-not-exists-2? 'file-system (lambda (fname dirname) (with-cwd (create-temp-dir) (create-directory dirname) (create-file (string-append dirname fname)) (set-file-mode dirname 0) (let ((result (file-not-exists? (string-append dirname fname)))) (set-file-mode dirname #o777) (delete-filesys-object (string-append dirname fname)) (delete-filesys-object dirname) (equal? result 'search-denied)))) "file" "dir/") ;; --- directory-files --- (add-test-multiple! 'directory-files 'file-system (lambda (fname dotfiles?) (with-cwd (create-temp-dir) (create-file fname) (or (and (string-ref fname 0) (not dotfiles?)) (member fname (directory-files (cwd) dotfiles?))))) '("file" ".file") '(#t #f)) ;; --- create-temp-file --- (add-test! 'create-temp-file 'file-system (lambda () (let ((temp-dir (create-temp-dir))) (let ((file-1 (create-temp-file temp-dir)) (file-2 (create-temp-file temp-dir))) (let ((result (and (not (equal? file-1 file-2)) (file-exists? file-1) (file-exists? file-2)))) (delete-filesys-object file-1) (delete-filesys-object file-2) result)))))