;;; gnus-mock.el --- Mock Gnus installation for testing -*- lexical-binding: t; -*- ;; Copyright (C) 2018 Free Software Foundation ;; Author: Eric Abrahamsen ;; 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: ;; This module provides a reproducible mock Gnus installation, ;; including dummy data, that can be used for Gnus development and ;; testing. Start the mock Gnus session with either `gnus-mock' or ;; `gnus-mock-unplugged'. Nothing in the mock sessions will make a ;; network connection, and mail sending is stubbed out using ;; `gnus-mock-sendmail-program'. ;; The mock session starts with a predefined nnmaildir server, as well ;; as some dummy mail data. Other predefined servers may be added in ;; the future. At startup, all dummy data is copied into a temporary ;; directory. At shutdown, the temporary directory is deleted. ;; A special config file is used for the mock session; users may add ;; to this config, or shadow its options, by setting ;; `gnus-mock-settings-file' to the name of an additional config file. ;;; Code: (require 'gnus) (require 'message) (defgroup gnus-mock nil "Options for the mock Gnus installation." :group 'gnus :version "27.1") (defcustom gnus-mock-settings-file nil "Path to an additional config file for mock Gnus. The contents of this file will be appended to gnus-mock's own config file before Gnus startup, in effect shadowing config values in the default file." :group 'gnus-mock :type 'file) (defcustom gnus-mock-data-dir (expand-file-name "test/data/gnus/mock" source-directory) "Source directory for Gnus mock data." :group 'gnus-mock :type 'string) (defcustom gnus-mock-cleanup-p t "When non-nil, delete temporary files after shutdown. Each Gnus mock session will create a new temporary directory, so multiple sessions will not conflict if this option is nil." :group 'gnus-mock :type 'boolean) (defcustom gnus-mock-sendmail-program (nnheader-concat gnus-mock-data-dir "fakesendmail.py") "Program used as the value of `sendmail-program'." :group 'gnus-mock :type 'string) ;; Regular Gnus can also check this, in case of a "dirty" mock ;; session. (defvar gnus-mock-p nil "Non-nil during a mocked Gnus session.") (defun gnus-mock-setup () "Set up mock data and config." (let ((mock-tmp-dir (make-temp-file "emacs-gnus-mock-" t))) (setq gnus-home-directory mock-tmp-dir gnus-directory (nnheader-concat gnus-home-directory "News") gnus-agent-directory (nnheader-concat gnus-directory "agent/") nndraft-directory (nnheader-concat gnus-directory "drafts/") gnus-init-file (nnheader-concat gnus-home-directory ".gnus") gnus-startup-file (nnheader-concat gnus-home-directory ".newsrc") message-directory gnus-home-directory sendmail-program gnus-mock-sendmail-program ;; If Emacs was started with -Q, as it should have been, ;; `init-file-user' will be nil which will prevent reading of ;; `gnus-init-file'. init-file-user "gnus-mock") ;; Put our data and config in place. (copy-directory gnus-mock-data-dir (file-name-as-directory gnus-home-directory) nil nil t) ;; Possibly insert additional config. (when gnus-mock-settings-file (with-temp-buffer (insert-file-contents gnus-mock-settings-file) (append-to-file (point-min) (point-max) gnus-init-file))))) ;;;###autoload (defun gnus-mock-unplugged () "Start an unplugged mock Gnus session." (interactive) (gnus-mock t)) ;;;###autoload (defun gnus-mock (&optional unplugged) "Start a mock Gnus session." (interactive) (when (gnus-alive-p) (error "First save and quit your running Gnus session")) (gnus-mock-setup) (when unplugged (setq gnus-plugged nil)) (setq gnus-mock-p t) (gnus) (add-hook 'gnus-after-exiting-gnus-hook #'gnus-mock-restore)) (defun gnus-mock-restore () "Restore after quitting a mock Gnus session." (when gnus-mock-p (when gnus-mock-cleanup-p (delete-directory gnus-home-directory t)) (setq gnus-mock-p nil) (remove-hook 'gnus-after-exiting-gnus-hook #'gnus-mock-restore))) (provide 'gnus-mock) ;;; gnus-mock.el ends here