#lang racket/base ;; To include a test, add an appropriate entry in `tests' below. ;; Notes: ;; - Each test is run in its own namespace, but there is very little ;; additional sandboxing. (There is a timeout of 15 minutes.) ;; - Specifically, the I/O ports are not diverted -- so please keep ;; output to a minimum, preferably nothing if there are no errors. ;; - Tests are only running in racket (*not* gracket), but note that ;; they will run with both the default 3m and the CGC executable, and ;; with the JIT enabled and disabled. ;; - They will also run on all build platforms, some can be slow (eg, ;; the Solaris build, or if we get an ARM build). Many of the build ;; machines are used by people, be polite! ;; - The tests are usually run from some temporary directory, you can ;; create files in it, but DO NOT use any other paths: don't write ;; into the PLT tree, don't write into the home directory (or rely ;; on things in it), assume a fresh planet cache. ;; - To signal failures, either raise an error, or `exit' with a ;; positive code. Obviously, make sure that failures print some ;; indicative text for you. ;; Tests to run: ;; - Each should be a `test' call, with the path to the test file to ;; require (relative to this script). (define (all-tests) (test "racket/quiet.rktl" #:load? #t #:handler? #f ;; this *must* be in (lib ...) form, since that's the way that racket ;; uses the -I value to initialize the namespace, and there are tests ;; that expect to get (lib "racket/init") as a result. #:additional-modules '((lib "racket/init"))) ;; (test "planet/lang.rkt") (test "typed-racket/nightly-run.rkt" #:timeout 25) (test "match/plt-match-tests.rkt") ;; (test "stepper/automatic-tests.rkt" #:additional-modules (scheme/base)) (test "lazy/main.rkt") (test "scribble/main.rkt") (test "net/main.rkt") (test "file/main.rkt") (test "profile/main.rkt") (test "errortrace/alert.rkt") ) (require racket/runtime-path) (define-runtime-path here ".") (define exit-code 0) (define (test path #:load? [load? #f] #:handler? [handler? #t] #:timeout [timeout 15] ; in minutes #:additional-modules [additional-modules '()]) (define gloabl-state (current-preserved-thread-cell-values)) (define stderr (current-error-port)) (define (echo fmt . args) (flush-output (current-output-port)) (flush-output (current-error-port)) (fprintf stderr ">>> ~a: ~a\n" path (apply format fmt args))) (newline stderr) (echo "running...") (let/ec break (define (abort n fmt . xs) (when (positive? n) (apply echo fmt xs) (set! exit-code (max exit-code n)) (echo "BOOM!") ; used to find errors in nightly builds (break))) (define timeout-thread (thread (let ([th (current-thread)]) (lambda () (sleep (* 60 timeout)) (echo "Timeout!") (break-thread th) (sleep 60) (echo "BOOM! A minute has passed, killing the test thread!") (kill-thread th) (sleep 60) (echo "Another minute passed, aborting!") (abort 1 "Goodbye."))))) (parameterize* ([exit-handler (lambda (n) (abort n "exit with error code ~a" n))] [current-namespace (make-base-empty-namespace)]) (for-each namespace-require additional-modules) (let ([thunk (lambda () ((if load? load namespace-require) (build-path here path)))]) (if handler? (with-handlers ([void (lambda (exn) (abort 1 "error: ~a" (exn-message exn)))]) (thunk)) (thunk))) (kill-thread timeout-thread) (echo "no failures."))) (current-preserved-thread-cell-values gloabl-state)) (all-tests) (exit exit-code)