#lang racket
(require rackunit
(only-in net/base64 base64-encode-stream)
(only-in (planet lizorkin/sxml:2:0/sxml) sxpath))
(provide (all-defined-out))
(define RPC-TIMEOUT 10)
(define-syntax (with-timeout stx)
(syntax-case stx ()
[(_ timeout-msg time body)
#`(let ()
(define complete? #f)
(define test-thread
(thread (lambda () (set! complete? body))))
(define timeout-thread
(thread (lambda ()
(sleep time)
(when (thread-running? test-thread)
(printf "Test timed out.~n")
(printf "Test skipped: ~a~n" timeout-msg)
(kill-thread test-thread)))))
(define test-done (thread-dead-evt test-thread))
(define kill-done (thread-dead-evt timeout-thread))
(sync test-done kill-done)
(when (thread-running? timeout-thread)
(kill-thread timeout-thread))
complete?
)]))
(define-syntax (check-fail stx)
(syntax-case stx ()
[(_ check)
#`(check-exn
exn:test:check?
(lambda ()
check))]))
(define-check (check-hash-table-equal? hash1 hash2)
(check-hash-table-contains hash1 hash2)
(check-hash-table-contains hash2 hash1))
(define (set-equal? ls1 ls2)
(define (check-set s1 s2)
(andmap (lambda (o)
(member o s2)) s1))
(and (check-set ls1 ls2)
(check-set ls2 ls1)))
(define-check (check-serialised-hash-table-equal? sxml1 sxml2)
(define (extract-names sxml) ((sxpath '(// name)) sxml))
(define (extract-values sxml) ((sxpath '(// value)) sxml))
(let ([names1 (extract-names sxml1)]
[names2 (extract-names sxml2)]
[values1 (extract-values sxml1)]
[values2 (extract-values sxml2)])
(when (not (equal? (length names1) (length names2)))
(with-check-info
(('message "Hash tables have different numbers of elements."))
(fail-check)))
(unless (set-equal? names1 names2)
(with-check-info
(('message
(format "First hash has different keys than second hash:~n\tH1: ~s~n\tH2 ~s~n"
names1 names2)))
(fail-check)))
(unless (set-equal? values1 values2)
(with-check-info
(('message
(format "First hash has different values than second hash:~n\tH1: ~s~n\tH2 ~s~n"
values1 values2)))
(fail-check)))
(let ([h1 (make-hash)]
[h2 (make-hash)])
(define (load-hash h lon lov)
(for-each (lambda (n v)
(hash-set! h (string->symbol (cadr n)) v))
lon lov))
(load-hash h1 names1 values1)
(load-hash h2 names2 values2)
(unless (check-hash-table-equal? h1 h2)
(with-check-info
(('message "Serialised hash tables are not equal."))
(fail-check))))
))
(define-check (check-hash-table-contains hash1 hash2)
(hash-for-each
hash2
(lambda (key v2)
(let ((v1
(hash-ref
hash1 key
(lambda ()
(with-check-info
(('message
(format "No value found with key ~e" key)))
(fail-check))))))
(if (and (hash? v1) (hash? v2))
(check-hash-table-equal? v1 v2)
(check-equal? v1 v2))))))
(define (base64-encode byte)
(let ((output (open-output-string)))
(base64-encode-stream
(open-input-bytes byte)
output
#"")
(get-output-string output)))