;;; coroutine-tests.el --- coroutine tests -*- lexical-binding: t; -*- ;; Copyright (C) 2016 Free Software Foundation, Inc. ;; Author: Philipp Stephani ;; 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 3 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 this program. If not, see . ;;; Commentary: ;; Unit tests for src/coroutine.c. ;;; Code: (defun coroutine-tests--prime-task (channel) (let ((prime (receive-from-channel channel))) (message "%d" prime) (let ((new-channel (make-channel))) (start-coroutine (lambda () (coroutine-tests--prime-task new-channel))) (while t (let ((i (receive-from-channel channel))) (unless (zerop (mod i prime)) (send-to-channel new-channel i))))))) (ert-deftest coroutines-tests--prime () (let ((channel (make-channel))) (start-coroutine (lambda () (coroutine-tests--prime-task channel))) (cl-loop for i from 2 to 100 do (send-to-channel channel i)))) (ert-deftest coroutines-test--go-tour-1 () (cl-flet ((say (s) (dotimes (_ 5) (sleep-for 0.1) (message "%s" s)))) (start-coroutine (lambda () (say "world"))) (say "hello"))) (ert-deftest coroutines-test--go-tour-2 () (cl-flet ((sum (s c) (let ((sum 0)) (dolist (v s) (cl-incf sum v)) (send-to-channel c sum)))) (let ((s '(7 2 8 -9 4 0)) (c (make-channel))) (start-coroutine (lambda () (sum (butlast s (/ (length s) 2)) c))) (start-coroutine (lambda () (sum (nthcdr (/ (length s) 2) s) c))) (let ((x (receive-from-channel c)) (y (receive-from-channel c))) (message "%d" (+ x y)) (should (equal (+ x y) (apply #'+ s))))))) (ert-deftest coroutines-test--go-tour-3 () (let ((ch (make-channel 2))) (send-to-channel ch 1) (send-to-channel ch 2) (should (equal (receive-from-channel ch) 1)) (should (equal (receive-from-channel ch) 2)))) (ert-deftest coroutines-test--go-tour-4 () (cl-flet ((fibonacci (n c close) (let ((x 0) (y 1)) (dotimes (_ n) (send-to-channel c x) (cl-psetq x y y (+ x y)))) (send-to-channel close nil))) (let ((c (make-channel 10)) (close (make-channel 1))) (start-coroutine (lambda () (fibonacci 10 c close))) (cl-block nil (while t (select ((receive c i) (message "%d" i)) ((receive close) (cl-return)))))))) (ert-deftest coroutines-test--go-tour-5 () (cl-flet ((fibonacci (c quit) (cl-block nil (let ((x 0) (y 1)) (while t (select ((send c x) (cl-psetq x y y (+ x y))) ((receive quit) (message "quit") (cl-return)))))))) (let ((c (make-channel)) (quit (make-channel))) (start-coroutine (lambda () (dotimes (_ 10) (message "%S" (receive-from-channel c))) (send-to-channel quit nil))) (fibonacci c quit)))) (defun coroutines-test--time-tick (d) (cl-check-type d (and number cl-plus)) (let ((c (make-channel 1))) (run-at-time nil d (lambda () (try-send-to-channel c (current-time)))) c)) (defun coroutines-test--time-after (d) (cl-check-type d (and number cl-plus)) (let ((c (make-channel 1))) (run-at-time d nil (lambda () (try-send-to-channel c (current-time)))) c)) (ert-deftest coroutines-test--go-tour-6 () (cl-block nil (let ((tick (coroutines-test--time-tick 0.1)) (boom (coroutines-test--time-after 0.5))) (while t (select ((receive tick) (message "tick.")) ((receive boom) (message "BOOM!") (cl-return)) (default (message " .") (sleep-for 0.05))))))) (defvar coroutines-test--var nil) (ert-deftest coroutines-test--specbind () (let ((coroutines-test--var 'main) (channel (make-channel))) (start-coroutine (lambda () (let ((coroutines-test--var 'child)) (setq coroutines-test--var 'child-setq) (receive-from-channel channel) (should (equal coroutines-test--var 'child-setq))))) (should (equal coroutines-test--var 'main)) (setq coroutines-test--var 'main-setq) (send-to-channel channel nil) (should (equal coroutines-test--var 'main-setq)))) ;; (ert-deftest coroutines-test--deadlock () ;; (let ((ch-1 (make-channel)) ;; (ch-2 (make-channel))) ;; (start-coroutine ;; (lambda () ;; (receive-from-channel ch-1) ;; (send-to-channel ch-2 nil))) ;; (receive-from-channel ch-2) ;; (send-to-channel ch-1 nil))) (ert-deftest coroutines-test--signal () (start-coroutine (lambda () (signal 'beginning-of-buffer '(foo)))) (let ((err (should-error (sleep-for 0.1)))) (should (equal err '(beginning-of-buffer foo))))) (ert-deftest channelp () (should-not (channelp nil)) (should-not (channelp 5)) (should (channelp (make-channel)))) ;;; coroutine-tests.el ends here