(use-modules (gnubba xmpp)) (suite "iq/message/presence stanzas" (tests (test "iq should return a simple iq stanza" e (assert-equal '(*TOP* (iq (@ (to "romeo@capulet.it") (type "get") (id "1234")) "payload")) (e 'iq1))) (test "message should return a simple message stanza" e (assert-equal '(*TOP* (message (@ (to "romeo@capulet.it")) (body "hello, romeo!"))) (e 'message1))) (test "presence should return a simple presence stanza" e (assert-equal '(*TOP* (presence (@ (id "1234")))) (e 'presence1))) (test "presence takes optional body argument" e (assert-equal '(*TOP* (presence (@ (id "1234")) "body")) (e 'presence2))) (test "iq? should return #t on an iq stanza" e (assert-true (iq? (e 'iq1)))) (test "iq? should return #f on any other stanza" e (assert-false (iq? (e 'message1)))) (test "message? should return #t on a message stanza" e (assert-true (message? (e 'message1)))) (test "message? should return #f on any other stanza" e (assert-false (message? (e 'iq1)))) (test "presence? should return #t on a presence stanza" e (assert-true (presence? (e 'presence1)))) (test "presence? should return #f on any other stanza" e (assert-false (presence? (e 'iq1))))) (options) (setups (setup 'iq1 (iq "payload" #:to "romeo@capulet.it" #:id "1234")) (setup 'message1 (message "romeo@capulet.it" "hello, romeo!")) (setup 'presence1 (presence #:id "1234")) (setup 'presence2 (presence "body" #:id "1234")) (setup 'presence3 (presence "body" #:id "1234" #:from "romeo@capulet.it")))) (suite "register-temp-stanza-handler-for-id" (tests (test "handler is not executed if stanza with non-matching id is received" e (assert-false (error? (begin (register-temp-stanza-handler-for-id "1234a" (lambda _ (throw 'error))) ((@@ (gnubba xmpp) handle-stanza) (e 'stanza)))))) (test "handler remains if stanza with non-matching id is received" e (assert-equal 1 (begin (register-temp-stanza-handler-for-id "1234b" (lambda _ (throw 'error))) ((@@ (gnubba xmpp) handle-stanza) (e 'stanza)) (hash-count (const #t) (@@ (gnubba xmpp) *stanza-id-handlers*))))) (test "handler is removed after execution" e (assert-equal 0 (begin (register-temp-stanza-handler-for-id "999" (lambda _ 'handler)) ((@@ (gnubba xmpp) handle-stanza) (e 'stanza)) (hash-count (const #t) (@@ (gnubba xmpp) *stanza-id-handlers*)))))) (options) (setups (setup 'stanza (iq "payload" #:to "romeo@capulet.it" #:id "999"))) (teardowns ;; always reset the internal state after each test (teardown e (set! (@@ (gnubba xmpp) *stanza-id-handlers*) (make-hash-table))))) (suite "register-stanza-handler" (tests (test "initially, *stanza-handlers* should be empty" e (assert-equal '() ((e 'handlers)))) (test "after registering a handler *stanza-handlers* contains one handler" e (assert-equal 1 (begin (register-stanza-handler (lambda _ 'handler1)) (length ((e 'handlers)))))) (test "after registering two handlers *stanza-handlers* contains two handlers" e (assert-equal 2 (begin (register-stanza-handler (lambda _ 'handler1)) (register-stanza-handler (lambda _ 'handler2)) (length ((e 'handlers)))))) (test "handlers may have guards" e (assert-equal 3 (begin (register-stanza-handler message? (lambda _ 'handler1)) (register-stanza-handler iq? (lambda _ 'handler2)) (register-stanza-handler #t (lambda _ 'handler2)) (length ((e 'handlers))))))) (options) (setups (setup 'handlers (lambda () (@@ (gnubba xmpp) *stanza-handlers*)))) (teardowns ;; always reset the internal state after each test (teardown e (set! (@@ (gnubba xmpp) *stanza-handlers*) '())))) (suite "try-stanza-handlers" (tests (test "a handler registered without a guard or #t is executed for any stanza" e (assert-equal '(handler2 handler1) (begin (register-stanza-handler (lambda _ 'handler1)) (register-stanza-handler #t (lambda _ 'handler2)) ((@@ (gnubba xmpp) try-stanza-handlers) (e 'message1))))) (test "handlers with guards are only executed for stanzas that match (a)" e (assert-equal '(#f handler1) (begin (register-stanza-handler message? (lambda _ 'handler1)) (register-stanza-handler iq? (lambda _ 'handler2)) ((@@ (gnubba xmpp) try-stanza-handlers) (e 'message1))))) (test "handlers with guards are only executed for stanzas that match (b)" e (assert-equal '(handler2 #f) (begin (register-stanza-handler message? (lambda _ 'handler1)) (register-stanza-handler iq? (lambda _ 'handler2)) ((@@ (gnubba xmpp) try-stanza-handlers) (e 'iq1))))) (test "no handlers are executed if none of the guards match the stanza" e (assert-equal '(#f #f) (begin (register-stanza-handler message? (lambda _ 'handler1)) (register-stanza-handler iq? (lambda _ 'handler2)) ((@@ (gnubba xmpp) try-stanza-handlers) (e 'presence1))))) (test "when a handler throws 'halt no other handlers are executed" e (assert-equal '(handler2 handler3) (let ((*executed* '())) (register-stanza-handler (lambda _ (set! *executed* (cons 'handler1 *executed*)))) (register-stanza-handler (lambda _ (set! *executed* (cons 'handler2 *executed*)) (throw 'halt 'handler2))) (register-stanza-handler (lambda _ (set! *executed* (cons 'handler3 *executed*)))) (catch 'halt (lambda _ ((@@ (gnubba xmpp) try-stanza-handlers) (e 'message1))) (lambda _ #t)) *executed*)))) (options) (setups (setup 'iq1 (iq "payload" #:to "romeo@capulet.it" #:id "1234")) (setup 'message1 (message "romeo@capulet.it" "hello, romeo!")) (setup 'presence1 (presence #:id "1234"))) (teardowns ;; always reset the internal state after each test (teardown e (set! (@@ (gnubba xmpp) *stanza-handlers*) '())))) ;; TODO (suite "next-stanza-id!" (tests)) (suite "handle-stanza" (tests (test "calls id handler first, then generic handler" e (assert-equal '(generic-handler id-handler) (let ((results '())) (register-stanza-handler (lambda _ (set! results (cons 'generic-handler results)))) (register-temp-stanza-handler-for-id (stanza-id (e 'stanza)) (lambda _ (set! results (cons 'id-handler results)))) ((@@ (gnubba xmpp) handle-stanza) (e 'stanza)) results))) (test "catches 'halt" e (assert-false (error? (begin (register-stanza-handler (lambda _ (throw 'never-executed))) (register-temp-stanza-handler-for-id (stanza-id (e 'stanza)) (lambda _ (throw 'halt))) ((@@ (gnubba xmpp) handle-stanza) (e 'stanza))))))) (options) (setups (setup 'stanza (iq "payload" #:to "romeo@capulet.it" #:id "1234"))) (teardowns ;; always reset the internal state after each test (teardown e (set! (@@ (gnubba xmpp) *stanza-handlers*) '())))) (suite "run-handler-loop" (tests (test "does not die when a handler throws an exception" e (assert-false (error? (begin (register-stanza-handler (lambda _ (throw 'some-error "no reason"))) (call-with-input-string "" run-handler-loop))))) (test "processes all stanzas in the queue" e (assert-equal 2 (let ((count 0)) (register-stanza-handler (lambda _ (begin (set! count (1+ count)) (throw 'some-error "no reason")))) (call-with-input-string "" run-handler-loop) count)))))