syndicate-2017/racket/syndicate/test.rkt

75 lines
2.6 KiB
Racket

#lang racket
(provide test-module-begin
(rename-out [illegal-trace trace]))
(module reader syntax/module-reader
syndicate/test-lang)
(require racket/async-channel)
(require racket/engine)
(require (prefix-in big: "actor-lang.rkt"))
(require "monitor.rkt")
(require "upside-down.rkt")
(require (prefix-in little: (only-in "little-actors/core.rkt" run-with)))
(require (for-syntax syntax/parse))
(require rackunit)
(define-syntax (illegal-trace stx)
(raise-syntax-error #f "trace: only allowed at top level of a test module" stx))
(begin-for-syntax
(define (trace->actor+channel trace-stx)
#`(let ([chan (make-async-channel)])
(cons (trace-actor #,trace-stx
(lambda () (async-channel-put chan #t)))
chan))))
(define-syntax (test-module-begin stx)
(define-syntax-class not-trace
#:datum-literals (trace)
(pattern (~and _:expr (~not _:trace))))
(syntax-parse stx
;; only allow one trace!
[(_ (~or (~once t:trace)
exps:expr)
...)
#'(#%module-begin
;; do I need to worry about catching exceptions here?
(define big-result (run-with-trace big:run-ground t (list (spawn-upside-down exps) ...)))
(define little-result (run-with-trace little:run-with t '(exps ...)))
(check-equal? big-result little-result)
;; it would be nice to specify false-y traces, too
(check-true big-result)
(check-true little-result))]))
(define DEFAULT-FUEL 2000)
(define-syntax-rule (run-with-trace run-ground trc act-exps)
(let ([chan (make-async-channel)])
(test-harness run-ground
chan
(trace-actor trc (lambda () (async-channel-put chan #t)))
act-exps
DEFAULT-FUEL)))
(define (test-harness run-ground chan trace-act acts [timeout never-evt])
(define syndicate-thread
(thread (lambda ()
(engine-run timeout
(engine (lambda (x) (run-ground trace-act acts)))))))
(define result
(sync (handle-evt chan
(lambda (val) #t))
(handle-evt syndicate-thread
(lambda (val)
;; it's possible one of the final events in the
;; dataspace resulted in an accepting trace and the
;; thread ended at the same time, so the scheduler
;; picked this event. Double check the channel for this
;; case.
(async-channel-try-get chan)))))
(kill-thread syndicate-thread)
result)