;;; websocket-functional-test.el --- Simple functional testing ;; Copyright (c) 2013, 2016 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2 of the ;; License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;; These are functional tests that may fail for various environmental reasons, ;; such as blocked ports. For example Windows users have to have gnutls DLLs in ;; the Emacs bin directory for this to work. A firewall may also interfere with ;; these tests. ;; ;; These tests are written to test the basic connectivity and message-sending. ;; Corner-cases and error handling is tested in websocket-test.el. (require 'tls) ;; tests a particular bug we had on Emacs 23 (require 'websocket) (require 'cl) ;;; Code: (defmacro websocket-test-wait-with-timeout (timeout &rest body) "Run BODY until true or TIMEOUT (in seconds) is reached. Will return false if the timeout was reached. This macro is not written to be used widely." `(let ((begin (current-time)) (result nil)) (while (and (< (- (float-time (time-subtract (current-time) begin))) ,timeout) (not result)) (setq result ,@body) (sleep-for 0.5)) result)) (defun websocket-functional-client-test (wstest-server-url) "Run the main part of an ert test against WSTEST-SERVER-URL." ;; the server may have an untrusted certificate, for the test to proceed, we ;; need to disable trust checking. (let* ((tls-checktrust nil) (wstest-closed nil) (wstest-msg) (wstest-server-proc) (wstest-ws (websocket-open wstest-server-url :on-message (lambda (_websocket frame) (setq wstest-msg (websocket-frame-text frame))) :on-close (lambda (_websocket) (setq wstest-closed t))))) (should (websocket-test-wait-with-timeout 2 (websocket-openp wstest-ws))) (should (websocket-test-wait-with-timeout 2 (eq 'open (websocket-ready-state wstest-ws)))) (should (null wstest-msg)) (websocket-send-text wstest-ws "Hi!") (should (websocket-test-wait-with-timeout 5 (equal wstest-msg "Hi!"))) (websocket-close wstest-ws))) (ert-deftest websocket-client-with-local-server () ;; If testserver.py cannot start, this test will fail. In general, if you ;; don't care about avoiding outside connections, the remote server variant is ;; usually easier to run, and tests the same things.. (let ((proc (start-process "websocket-testserver" "*websocket-testserver*" "python3" "testserver.py" "--log_to_stderr" "--logging=debug"))) (when proc (sleep-for 1) (websocket-functional-client-test "ws://127.0.0.1:9999")))) (ert-deftest websocket-client-with-remote-server () ;; Emacs previous to Emacs 24 cannot handle wss. (if (>= (string-to-number (substring emacs-version 0 2)) 24) (websocket-functional-client-test "wss://echo.websocket.org") (websocket-functional-client-test "ws://echo.websocket.org"))) (ert-deftest websocket-server () (let* ((wstest-closed) (wstest-msg) (server-conn (websocket-server 9998 :host 'local :on-message (lambda (ws frame) (websocket-send-text ws (websocket-frame-text frame))) :on-close (lambda (_websocket) (setq wstest-closed t)))) (wstest-ws (websocket-open "ws://localhost:9998" :on-message (lambda (_websocket frame) (setq wstest-msg (websocket-frame-text frame)))))) (should (websocket-test-wait-with-timeout 1 (websocket-openp wstest-ws))) (websocket-send-text wstest-ws "你好") (should (websocket-test-wait-with-timeout 1 (equal wstest-msg "你好"))) (websocket-server-close server-conn) (should (websocket-test-wait-with-timeout 1 wstest-closed)))) (provide 'websocket-functional-test) ;;; websocket-functional-test.el ends here