#lang scheme/gui (require framework) (provide go) (define numButtonsToPush 200) (define the-seed (+ 1 (modulo (current-seconds) (- (expt 2 31) 1)))) (random-seed the-seed) ;;find-all-actions: area -> (listof (-> void)) (define (find-all-actions area) (cond [(is-a? area area-container<%>) (apply append (map find-all-actions (send area get-children)))] [(and (is-a? area button%) (send area is-enabled?) (send area is-shown?)) (list (case-lambda [(x) (format "button ~s" (send area get-label))] [() (test:button-push area)]))] [(and (is-a? area check-box%) (send area is-enabled?)) (let ([func (λ (which-way) (case-lambda [(x) (format "checkbox ~s" (send area get-label))] [() (test:set-check-box! area which-way)]))]) (list (func #t) (func #f)))] [(and (is-a? area radio-box%) (send area is-enabled?)) (for/list ([i (in-range 0 (send area get-number))]) (case-lambda [(x) (format "radiobox, item ~s" (send area get-item-label i))] [() (test:set-radio-box! area i)]))] [else '()])) ;;find-random-button: area -> random element of the buttons in area ;;return #f if there is no buttons in area (define (find-random-action area) (define buttons (find-all-actions area)) (cond ;;Area with no buttons [(null? buttons) #f] [else (list-ref buttons (random (length buttons)))])) ;; Trace the path to the area back to a base-frame (define (trace-area area base-frame) (cond [(eq? area base-frame) (list base-frame)] [else (append (trace-area (send area get-parent) base-frame) (list area))] )) ;;toy print-label function (define (print-label area) (cond [(is-a? area tab-panel%) ;(send area get-item-label (send area get-selection))] (send area get-item-label 0)] [(is-a? area vertical-panel%) "Vert-Panel"] [(is-a? area horizontal-panel%) "Hort-Panel"] [(is-a? area vertical-pane%) "Vert-Pane"] [(is-a? area horizontal-pane%) "Hort-Pane"] [else (send area get-label)])) (define (g open-dialog) (let ((base-window (get-top-level-focus-window))) (open-dialog) (wait-for-different-frame base-window) (let loop ([n numButtonsToPush] [actions '()]) (cond [(zero? n) (printf "\n") (exit 0)] [else (printf "~a " n) (when (= 1 (modulo n 10)) (printf "\n")) (flush-output) (let ((window (get-top-level-focus-window))) (cond ;; Back to base-window is not interesting, Reopen [(eq? base-window window) (open-dialog) (wait-for-different-frame base-window) (loop (- n 1) actions)] ;; get-top-level-focus-window returns #f may imply window not in current eventspace ;; but it also might just mean we didn't look into subeventspaces(?) ;; or that we need to wait for something to happen in the GUI(?) [(eq? window #f) (sleep .1) (loop (- n 1) actions)] [else ;; print out the button before the button is pushed ;; Using the toy print-label function ;; because some of the parents may not be sent with get-label e.g. vertical-pane% ;(print (map print-label (trace-area button window))) (let ([action (find-random-action window)]) (cond [action (with-handlers ((exn:fail? (λ (x) (fprintf (current-error-port) "\nExecution fail: transcript of ~a clicking follows with seed ~s\n" (send window get-label) the-seed) (apply show-log (cons action actions)) (raise x)))) ;; pause to make sure all events are flushed from the queue (let ([s (make-semaphore 0)]) (queue-callback (λ () (semaphore-post s)) #f) (semaphore-wait s)) ;; do the new thing. (action)) (loop (- n 1) (cons action actions))] [else (fprintf (current-error-port) "\nExists/Meets window with no button: Bug? seed ~s\n" the-seed) (apply show-log actions) (error 'randomly-click.rkt "giving up")]))]))])))) (define (show-log . actions) (for ((action (in-list actions))) (fprintf (current-error-port) " ~a\n" (action 'ignored)))) ;; the splash screen is in a separate eventspace so wont' show up. (define (wait-for-first-frame) (let loop () (let ([tlw (get-top-level-focus-window)]) (cond [(not tlw) (sleep 1/20) (loop)] [else tlw])))) (define (wait-for-different-frame win) (let loop ([n 1000]) (cond [(zero? n) (error 'wait-for-different-frame "never got that new window, only this one: ~s" win)] [else (let ([tlw (get-top-level-focus-window)]) (when (eq? win tlw) (sleep 1/10) (loop (- n 1))))]))) (define orig-display-handler (error-display-handler)) (define (go which-dialog) (dynamic-require 'drscheme #f) ;; reset the uncaught exception handler to be sure we kill everything (drscheme sets it) (uncaught-exception-handler (λ (x) (if (exn? x) (orig-display-handler (exn-message x) x) (fprintf (current-error-port) "uncaught exception ~s\n" x)) (exit 1))) (void (thread (λ () (define drs (wait-for-first-frame)) (case which-dialog [(language-dialog) (g (λ () (test:menu-select "Language" "Choose Language...")))] [(preferences-dialog) (g (λ () (preferences:show-dialog)))])))))