PR 9873 (hopefully)

svn: r12193
This commit is contained in:
Robby Findler 2008-10-31 12:40:05 +00:00
parent 7ab26eb1d7
commit bd375ef605
3 changed files with 293 additions and 278 deletions

View File

@ -273,12 +273,14 @@
(or (not (preferences:get 'framework:exit-when-no-frames)) (or (not (preferences:get 'framework:exit-when-no-frames))
(exit:exiting?) (exit:exiting?)
(not (= 1 number-of-frames)) (not (= 1 number-of-frames))
(current-eventspace-has-standard-menus?)
(exit:user-oks-exit)))) (exit:user-oks-exit))))
(define (on-close-action) (define (on-close-action)
(when (preferences:get 'framework:exit-when-no-frames) (when (preferences:get 'framework:exit-when-no-frames)
(unless (exit:exiting?) (unless (exit:exiting?)
(when (null? (send (get-the-frame-group) get-frames)) (when (and (null? (send (get-the-frame-group) get-frames))
(not (current-eventspace-has-standard-menus?)))
(exit:exit))))) (exit:exit)))))
(define (choose-a-frame parent) (define (choose-a-frame parent)

View File

@ -5,7 +5,7 @@
(let ([basics (list "Bring Frame to Front..." "Most Recent Window" (let ([basics (list "Bring Frame to Front..." "Most Recent Window"
#f)]) #f)])
(if (eq? (system-type) 'macosx) (if (eq? (system-type) 'macosx)
(list* "Minimize" "Zoom" #f basics) (list* "Minimize" "Zoom" basics)
basics))) basics)))
(send-sexp-to-mred (send-sexp-to-mred
'(define-syntax car* '(define-syntax car*
@ -14,23 +14,32 @@
(car x) (car x)
(error 'car* "got a non-pair for ~s" 'x))]))) (error 'car* "got a non-pair for ~s" 'x))])))
;; this test uses a new eventspace so that the mred function
;; current-eventspace-has-standard-menus? returns #f and thus
;; all of the platforms behave the same way.
(test (test
'exit-on 'exit-on
(lambda (x) (equal? x '("first"))) (lambda (x) (equal? x '("first")))
(lambda () (lambda ()
(send-sexp-to-mred `(define new-eventspace (make-eventspace)))
(send-sexp-to-mred (send-sexp-to-mred
'(begin (send (make-object frame:basic% "first") show #t) '(begin (parameterize ([current-eventspace new-eventspace])
(send (make-object frame:basic% "first") show #t))
(preferences:set 'framework:verify-exit #t))) (preferences:set 'framework:verify-exit #t)))
(wait-for-frame "first") (wait-for-frame "first" 'new-eventspace)
(send-sexp-to-mred (send-sexp-to-mred
`(queue-callback (lambda () (send (get-top-level-focus-window) close)))) `(queue-callback (lambda ()
(wait-for-frame "Warning") (parameterize ([current-eventspace new-eventspace])
(send (get-top-level-focus-window) close)))))
(wait-for-frame "Warning" 'new-eventspace)
(send-sexp-to-mred (send-sexp-to-mred
`(test:button-push "Cancel")) `(parameterize ([current-eventspace new-eventspace])
(wait-for-frame "first") (test:button-push "Cancel")))
(wait-for-frame "first" 'new-eventspace)
(send-sexp-to-mred (send-sexp-to-mred
`(map (lambda (x) (send x get-label)) `(parameterize ([current-eventspace new-eventspace])
(send (group:get-the-frame-group) get-frames))))) (map (lambda (x) (send x get-label))
(send (group:get-the-frame-group) get-frames))))))
;; after the first test, we should have one frame that will always ;; after the first test, we should have one frame that will always
;; be in the group. ;; be in the group.

View File

@ -1,298 +1,302 @@
#lang scheme
(module test-suite-utils mzscheme (require (only-in mzscheme fluid-let)
(require launcher launcher
mzlib/pretty scheme/system
mzlib/list "debug.ss")
mzlib/process
"debug.ss")
(provide (provide
test-name test-name
failed-tests failed-tests
;(struct eof-result ())
eof-result?
load-framework-automatically
shutdown-listener shutdown-mred mred-running?
send-sexp-to-mred queue-sexp-to-mred
test
wait-for-frame
;; sexp -> void
;; grabs the frontmost window, executes the sexp and waits for a new frontmost window
wait-for-new-frame
wait-for
reset-section-jump!
set-section-jump!
reset-section-name!
set-section-name!
set-only-these-tests!
get-only-these-tests
debug-printf
exn->str)
;(struct eof-result ()) (define section-jump void)
eof-result? (define (set-section-jump! _s) (set! section-jump _s))
(define (reset-section-jump!) (set! section-jump #f))
load-framework-automatically (define section-name "<<setup>>")
shutdown-listener shutdown-mred mred-running? (define (set-section-name! _s) (set! section-name _s))
send-sexp-to-mred queue-sexp-to-mred (define (reset-section-name!) (set! section-name "<<setup>>"))
test
wait-for-frame
;; sexp -> void (define only-these-tests #f)
;; grabs the frontmost window, executes the sexp and waits for a new frontmost window (define (get-only-these-tests) only-these-tests)
wait-for-new-frame (define (set-only-these-tests! _t) (set! only-these-tests _t))
wait-for (define test-name "<<setup>>")
(define failed-tests null)
reset-section-jump! (define-struct eof-result ())
set-section-jump!
reset-section-name!
set-section-name!
set-only-these-tests!
get-only-these-tests
debug-printf
exn->str)
(define section-jump void)
(define (set-section-jump! _s) (set! section-jump _s))
(define (reset-section-jump!) (set! section-jump #f))
(define section-name "<<setup>>") (define load-framework-automatically? #t)
(define (set-section-name! _s) (set! section-name _s))
(define (reset-section-name!) (set! section-name "<<setup>>"))
(define only-these-tests #f) (define initial-port 6012)
(define (get-only-these-tests) only-these-tests) (define port-filename
(define (set-only-these-tests! _t) (set! only-these-tests _t)) (build-path (find-system-path 'temp-dir)
"framework-tests-receive-sexps-port.ss"))
(define test-name "<<setup>>") (unless (file-exists? port-filename)
(define failed-tests null) (call-with-output-file port-filename
(lambda (port) (write initial-port port))))
(define-struct eof-result ()) (define listener
(let loop ([port (call-with-input-file port-filename read)])
(define load-framework-automatically? #t) (let ([l (with-handlers ([exn:fail? (lambda (_) #f)])
(tcp-listen port))])
(define initial-port 6012) (if l
(define port-filename
(build-path (find-system-path 'temp-dir)
"framework-tests-receive-sexps-port.ss"))
(unless (file-exists? port-filename)
(call-with-output-file port-filename
(lambda (port) (write initial-port port))))
(define listener
(let loop ([port (call-with-input-file port-filename read)])
(let ([l (with-handlers ([exn:fail? (lambda (_) #f)])
(tcp-listen port))])
(if l
(begin (debug-printf mz-tcp "listening to ~a\n" port) (begin (debug-printf mz-tcp "listening to ~a\n" port)
(call-with-output-file port-filename (call-with-output-file port-filename
(lambda (p) (write port p)) 'truncate) (lambda (p) (write port p))
#:exists 'truncate)
l) l)
(begin (debug-printf mz-tcp " tcp-listen failed for port ~a\n" port) (begin (debug-printf mz-tcp " tcp-listen failed for port ~a\n" port)
(loop (add1 port))))))) (loop (add1 port)))))))
(define in-port #f) (define in-port #f)
(define out-port #f) (define out-port #f)
(define (restart-mred) (define (restart-mred)
(shutdown-mred)
(thread
(lambda ()
(system*
(path->string
(build-path
(let-values ([(dir exe _)
(split-path (find-system-path 'exec-file))])
dir)
(if (eq? 'windows (system-type)) "MrEd.exe" "mred")))
(path->string
(build-path (collection-path "tests" "framework")
"framework-test-engine.ss")))))
(debug-printf mz-tcp "accepting listener\n")
(let-values ([(in out) (tcp-accept listener)])
(set! in-port in)
(set! out-port out))
(when load-framework-automatically?
(queue-sexp-to-mred
'(begin (eval '(require framework))
(eval '(require tests/utils/gui))))))
(define load-framework-automatically
(case-lambda
[(new-load-framework-automatically?)
(unless (eq? (not (not new-load-framework-automatically?))
load-framework-automatically?)
(set! load-framework-automatically? (not (not new-load-framework-automatically?)))
(shutdown-mred))]
[() load-framework-automatically?]))
(define shutdown-listener
(lambda ()
(shutdown-mred) (shutdown-mred)
(thread (debug-printf mz-tcp "closing listener\n")
(lambda () (tcp-close listener)))
(system*
(path->string
(build-path
(let-values ([(dir exe _)
(split-path (find-system-path 'exec-file))])
dir)
(if (eq? 'windows (system-type)) "MrEd.exe" "mred")))
(path->string
(build-path (collection-path "tests" "framework")
"framework-test-engine.ss")))))
(debug-printf mz-tcp "accepting listener\n")
(let-values ([(in out) (tcp-accept listener)])
(set! in-port in)
(set! out-port out))
(when load-framework-automatically?
(queue-sexp-to-mred
'(begin (eval '(require framework))
(eval '(require tests/utils/gui))))))
(define load-framework-automatically (define shutdown-mred
(case-lambda (lambda ()
[(new-load-framework-automatically?) (when (and in-port
(unless (eq? (not (not new-load-framework-automatically?)) out-port)
load-framework-automatically?) (with-handlers ([exn:fail? (lambda (x) (void))])
(set! load-framework-automatically? (not (not new-load-framework-automatically?))) (close-output-port out-port))
(shutdown-mred))] (with-handlers ([exn:fail? (lambda (x) (void))])
[() load-framework-automatically?])) (close-input-port in-port))
(set! in-port #f)
(set! in-port #f))))
(define shutdown-listener (define mred-running?
(lambda () (lambda ()
(shutdown-mred) (if (char-ready? in-port)
(debug-printf mz-tcp "closing listener\n") (not (eof-object? (peek-char in-port)))
(tcp-close listener))) #t)))
(define shutdown-mred (define queue-sexp-to-mred
(lambda () (lambda (sexp)
(when (and in-port (send-sexp-to-mred
out-port) `(let ([thunk (lambda () ,sexp)]
(with-handlers ([exn:fail? (lambda (x) (void))]) [sema (make-semaphore 0)])
(close-output-port out-port)) (queue-callback (lambda ()
(with-handlers ([exn:fail? (lambda (x) (void))]) (thunk)
(close-input-port in-port)) (semaphore-post sema)))
(set! in-port #f) (semaphore-wait sema)))))
(set! in-port #f))))
(define mred-running? (define re:tcp-read-error (regexp "tcp-read:"))
(lambda () (define re:tcp-write-error (regexp "tcp-write:"))
(if (char-ready? in-port) (define (tcp-error? exn)
(not (eof-object? (peek-char in-port))) (or (regexp-match re:tcp-read-error (exn-message exn))
#t))) (regexp-match re:tcp-write-error (exn-message exn))))
(define queue-sexp-to-mred (namespace-require 'scheme) ;; in order to make the eval below work right.
(lambda (sexp) (define (send-sexp-to-mred sexp)
(send-sexp-to-mred (let/ec k
`(let ([thunk (lambda () ,sexp)] (let ([show-text
[sema (make-semaphore 0)]) (lambda (sexp)
(queue-callback (lambda () (debug-when messages
(thunk) (parameterize ([pretty-print-print-line
(semaphore-post sema))) (let ([prompt " "]
(semaphore-wait sema))))) [old-liner (pretty-print-print-line)])
(lambda (ln port ol cols)
(let ([ov (old-liner ln port ol cols)])
(if ln
(begin (display prompt port)
(+ (string-length prompt) ov))
ov))))])
(pretty-print sexp)
(newline))))])
(unless (and in-port
out-port
(with-handlers ([tcp-error? (lambda (x) #f)])
(or (not (char-ready? in-port))
(not (eof-object? (peek-char in-port))))))
(restart-mred))
(debug-printf messages " ~a // ~a: sending to mred:\n"
section-name test-name)
(show-text sexp)
(with-handlers ([exn:fail?
(lambda (x)
(cond
;; this means that mred was closed
;; so we can restart it and try again.
[(tcp-error? x)
(restart-mred)
(write sexp out-port)
(newline out-port)
(flush-output out-port)]
[else (raise x)]))])
(write sexp out-port)
(newline out-port)
(flush-output out-port))
(let ([answer
(with-handlers ([exn:fail?
(lambda (x)
(if (tcp-error? x);; assume tcp-error means app closed
eof
(list 'cant-read
(string-append
(exn->str x)
"; rest of string: "
(format
"~s"
(apply
string
(let loop ()
(if (char-ready? in-port)
(let ([char (read-char in-port)])
(if (eof-object? char)
null
(cons char (loop))))
null))))))))])
(read in-port))])
(debug-printf messages " ~a // ~a: received from mred:\n" section-name test-name)
(show-text answer)
(unless (or (eof-object? answer)
(and (list? answer)
(= 2 (length answer))
(memq (car answer)
'(error last-error cant-read normal))))
(error 'send-sexp-to-mred "unpected result from mred: ~s\n" answer))
(if (eof-object? answer)
(raise (make-eof-result))
(case (car answer)
[(error)
(error 'send-sexp-to-mred "mred raised \"~a\"" (second answer))]
[(last-error)
(error 'send-sexp-to-mred "mred (last time) raised \"~a\"" (second answer))]
[(cant-read) (error 'mred/cant-parse (second answer))]
[(normal)
(eval (second answer))]))))))
(define re:tcp-read-error (regexp "tcp-read:")) (define test
(define re:tcp-write-error (regexp "tcp-write:")) (case-lambda
(define (tcp-error? exn) [(in-test-name passed? sexp/proc) (test in-test-name passed? sexp/proc 'section)]
(or (regexp-match re:tcp-read-error (exn-message exn)) [(in-test-name passed? sexp/proc jump)
(regexp-match re:tcp-write-error (exn-message exn)))) (fluid-let ([test-name in-test-name])
(when (or (not only-these-tests)
(memq test-name only-these-tests))
(let* ([result
(with-handlers ([exn:fail?
(lambda (x)
(if (exn? x)
(exn->str x)
x))])
(if (procedure? sexp/proc)
(sexp/proc)
(begin0 (send-sexp-to-mred sexp/proc)
(send-sexp-to-mred ''check-for-errors))))]
[failed (with-handlers ([exn:fail?
(lambda (x)
(string-append
"passed? test raised exn: "
(if (exn? x)
(exn->str x)
(format "~s" x))))])
(not (passed? result)))])
(when failed
(debug-printf schedule "FAILED ~a:\n ~s\n" test-name result)
(set! failed-tests (cons (cons section-name test-name) failed-tests))
(case jump
[(section) (section-jump)]
[(continue) (void)]
[else (jump)])))))]))
(namespace-require 'scheme) ;; in order to make the eval below work right. (define (exn->str exn)
(define (send-sexp-to-mred sexp) (let ([sp (open-output-string)])
(let/ec k (parameterize ([current-error-port sp])
(let ([show-text ((error-display-handler) (exn-message exn) exn))
(lambda (sexp) (get-output-string sp)))
(debug-when messages
(parameterize ([pretty-print-print-line
(let ([prompt " "]
[old-liner (pretty-print-print-line)])
(lambda (ln port ol cols)
(let ([ov (old-liner ln port ol cols)])
(if ln
(begin (display prompt port)
(+ (string-length prompt) ov))
ov))))])
(pretty-print sexp)
(newline))))])
(unless (and in-port
out-port
(with-handlers ([tcp-error? (lambda (x) #f)])
(or (not (char-ready? in-port))
(not (eof-object? (peek-char in-port))))))
(restart-mred))
(debug-printf messages " ~a // ~a: sending to mred:\n"
section-name test-name)
(show-text sexp)
(with-handlers ([exn:fail?
(lambda (x)
(cond
;; this means that mred was closed
;; so we can restart it and try again.
[(tcp-error? x)
(restart-mred)
(write sexp out-port)
(newline out-port)
(flush-output out-port)]
[else (raise x)]))])
(write sexp out-port)
(newline out-port)
(flush-output out-port))
(let ([answer
(with-handlers ([exn:fail?
(lambda (x)
(if (tcp-error? x);; assume tcp-error means app closed
eof
(list 'cant-read
(string-append
(exn->str x)
"; rest of string: "
(format
"~s"
(apply
string
(let loop ()
(if (char-ready? in-port)
(let ([char (read-char in-port)])
(if (eof-object? char)
null
(cons char (loop))))
null))))))))])
(read in-port))])
(debug-printf messages " ~a // ~a: received from mred:\n" section-name test-name)
(show-text answer)
(unless (or (eof-object? answer)
(and (list? answer)
(= 2 (length answer))
(memq (car answer)
'(error last-error cant-read normal))))
(error 'send-sexp-to-mred "unpected result from mred: ~s\n" answer))
(if (eof-object? answer)
(raise (make-eof-result))
(case (car answer)
[(error)
(error 'send-sexp-to-mred "mred raised \"~a\"" (second answer))]
[(last-error)
(error 'send-sexp-to-mred "mred (last time) raised \"~a\"" (second answer))]
[(cant-read) (error 'mred/cant-parse (second answer))]
[(normal)
(eval (second answer))]))))))
(define test (define (wait-for/wrapper wrapper sexp)
(case-lambda (let ([timeout 10]
[(in-test-name passed? sexp/proc) (test in-test-name passed? sexp/proc 'section)] [pause-time 1/2])
[(in-test-name passed? sexp/proc jump) (send-sexp-to-mred
(fluid-let ([test-name in-test-name]) (wrapper
(when (or (not only-these-tests) `(let ([test (lambda () ,sexp)])
(memq test-name only-these-tests)) (let loop ([n ,(/ timeout pause-time)])
(let* ([result (if (zero? n)
(with-handlers ([exn:fail? (error 'wait-for
(lambda (x) ,(format "after ~a seconds, ~s didn't come true" timeout sexp))
(if (exn? x) (unless (test)
(exn->str x) (sleep ,pause-time)
x))]) (loop (- n 1))))))))))
(if (procedure? sexp/proc)
(sexp/proc)
(begin0 (send-sexp-to-mred sexp/proc)
(send-sexp-to-mred ''check-for-errors))))]
[failed (with-handlers ([exn:fail?
(lambda (x)
(string-append
"passed? test raised exn: "
(if (exn? x)
(exn->str x)
(format "~s" x))))])
(not (passed? result)))])
(when failed
(debug-printf schedule "FAILED ~a:\n ~s\n" test-name result)
(set! failed-tests (cons (cons section-name test-name) failed-tests))
(case jump
[(section) (section-jump)]
[(continue) (void)]
[else (jump)])))))]))
(define (exn->str exn) (define (wait-for sexp) (wait-for/wrapper (lambda (x) x) sexp))
(let ([sp (open-output-string)])
(parameterize ([current-error-port sp])
((error-display-handler) (exn-message exn) exn))
(get-output-string sp)))
(define (wait-for/wrapper wrapper sexp)
(let ([timeout 10]
[pause-time 1/2])
(send-sexp-to-mred
(wrapper
`(let ([test (lambda () ,sexp)])
(let loop ([n ,(/ timeout pause-time)])
(if (zero? n)
(error 'wait-for
,(format "after ~a seconds, ~s didn't come true" timeout sexp))
(unless (test)
(sleep ,pause-time)
(loop (- n 1))))))))))
(define (wait-for sexp) (wait-for/wrapper (lambda (x) x) sexp)) (define (wait-for-new-frame sexp)
(wait-for/wrapper
(lambda (w)
`(let ([frame (get-top-level-focus-window)])
,sexp
,w))
`(not (eq? frame (get-top-level-focus-window)))))
(define (wait-for-new-frame sexp) (define (wait-for-frame name [eventspace #f])
(wait-for/wrapper (let ([exp `(let ([win (get-top-level-focus-window)])
(lambda (w) (and win
`(let ([frame (get-top-level-focus-window)]) (string=? (send win get-label) ,name)))])
,sexp (if eventspace
,w)) `(parameterize ([current-eventspace ,eventspace])
`(not (eq? frame (get-top-level-focus-window))))) ,exp)
(wait-for exp))))
(define (wait-for-frame name)
(wait-for `(let ([win (get-top-level-focus-window)])
(and win
(string=? (send win get-label) ,name))))))