unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
blob 1b5e8549113eb9342e7d1633f1538a68248dbe9f 7115 bytes (raw)
name: test/test-lib.el 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
 
;;; test-lib.el --- auxiliary stuff for Notmuch Emacs tests
;;
;; Copyright © Carl Worth
;; Copyright © David Edmondson
;;
;; This file is part of Notmuch test suit.
;;
;; Notmuch 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.
;;
;; Notmuch 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 Notmuch.  If not, see <https://www.gnu.org/licenses/>.
;;
;; Authors: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>

;;; Code:

(require 'cl-lib)

;; Ensure that the dynamic variables that are defined by this library
;; are defined by the time that we let-bind them.  This is needed
;; because starting with Emacs 27 undeclared variables in evaluated
;; interactive code (such as our tests) use lexical scope.
(require 'smtpmail)

;; `read-file-name' by default uses `completing-read' function to read
;; user input.  It does not respect `standard-input' variable which we
;; use in tests to provide user input.  So replace it with a plain
;; `read' call.
(setq read-file-name-function (lambda (&rest _) (read)))

(defun notmuch-test-wait ()
  "Wait for process completion."
  (while (get-buffer-process (current-buffer))
    (accept-process-output nil 0.1)))

(defun test-output (&optional filename)
  "Save current buffer to file FILENAME.  Default FILENAME is OUTPUT."
  (notmuch-post-command)
  (write-region (point-min) (point-max) (or filename "OUTPUT")))

(defun test-visible-output (&optional filename)
  "Save visible text in current buffer to file FILENAME.  Default
FILENAME is OUTPUT."
  (notmuch-post-command)
  (let ((text (visible-buffer-string))
	;; Tests expect output in UTF-8 encoding
	(coding-system-for-write 'utf-8))
    (with-temp-file (or filename "OUTPUT") (insert text))))

(defun visible-buffer-string ()
  "Same as `buffer-string', but excludes invisible text and
removes any text properties."
  (visible-buffer-substring (point-min) (point-max)))

(defun visible-buffer-substring (start end)
  "Same as `buffer-substring-no-properties', but excludes
invisible text."
  (let (str)
    (while (< start end)
      (let ((next-pos (next-char-property-change start end)))
	(unless (invisible-p start)
	  (setq str (concat str (buffer-substring-no-properties
				 start next-pos))))
	(setq start next-pos)))
    str))

;; process-attributes is not defined everywhere, so define an
;; alternate way to test if a process still exists.

(defun test-process-running (pid)
  (= 0
   (signal-process pid 0)))

(defun orphan-watchdog-check (pid)
  "Periodically check that the process with id PID is still
running, quit if it terminated."
  (unless (test-process-running pid)
    (kill-emacs)))

(defun orphan-watchdog (pid)
  "Initiate orphan watchdog check."
  (run-at-time 60 60 'orphan-watchdog-check pid))

(defvar notmuch-hello-mode-hook-counter -100
  "Tests that care about this counter must let-bind it to 0.")
(add-hook 'notmuch-hello-mode-hook
	  (lambda () (cl-incf notmuch-hello-mode-hook-counter)))

(defvar notmuch-hello-refresh-hook-counter -100
  "Tests that care about this counter must let-bind it to 0.")
(add-hook 'notmuch-hello-refresh-hook
	  (lambda () (cl-incf notmuch-hello-refresh-hook-counter)))

(defvar notmuch-test-tag-hook-output nil)
(defun notmuch-test-tag-hook () (push (cons query tag-changes) notmuch-test-tag-hook-output))

(defun notmuch-test-mark-links ()
  "Enclose links in the current buffer with << and >>."
  ;; Links are often created by jit-lock functions
  (jit-lock-fontify-now)
  (save-excursion
    (let ((inhibit-read-only t))
      (goto-char (point-min))
      (let ((button))
	(while (setq button (next-button (point)))
	  (goto-char (button-start button))
	  (insert "<<")
	  (goto-char (button-end button))
	  (insert ">>"))))))

(defmacro notmuch-test-run (&rest body)
  "Evaluate a BODY of test expressions and output the result."
  `(with-temp-buffer
     (let ((buffer (current-buffer))
	   (result (progn ,@body)))
       (switch-to-buffer buffer)
       (insert (if (stringp result)
		   result
		 (prin1-to-string result)))
       (test-output))))

(defun notmuch-test-report-unexpected (output expected)
  "Report that the OUTPUT does not match the EXPECTED result."
  (concat "Expect:\t" (prin1-to-string expected) "\n"
	  "Output:\t" (prin1-to-string output) "\n"))

(defun notmuch-test-expect-equal (output expected)
  "Compare OUTPUT with EXPECTED. Report any discrepancies."
  (cond
   ((equal output expected)
    t)
   ((and (listp output)
	 (listp expected))
    ;; Reporting the difference between two lists is done by
    ;; reporting differing elements of OUTPUT and EXPECTED
    ;; pairwise. This is expected to make analysis of failures
    ;; simpler.
    (apply #'concat (cl-loop for o in output
			     for e in expected
			     if (not (equal o e))
			     collect (notmuch-test-report-unexpected o e))))
   (t
    (notmuch-test-report-unexpected output expected))))

(defun notmuch-post-command ()
  (run-hooks 'post-command-hook))

(defmacro notmuch-test-progn (&rest body)
  (cons 'progn
	(mapcar
	 (lambda (x) `(prog1 ,x (notmuch-post-command)))
	 body)))

;; For testing functions in
;; notmuch-{search,tree,unsorted}-result-format
(defun notmuch-test-result-flags (format-string result)
  (let ((tags-to-letters (quote (("attachment" . "&")
				 ("signed" . "=")
				 ("unread" . "u")
				 ("inbox" . "i"))))
	(tags (plist-get result :tags)))
    (format format-string
	    (mapconcat (lambda (t2l)
			 (if (member (car t2l) tags)
			     (cdr t2l)
			   " "))
		       tags-to-letters ""))))

;; Log any signalled error (and other messages) to MESSAGES
;; Log "COMPLETE" if forms complete without error.
(defmacro test-log-error (&rest body)
  `(progn
     (with-current-buffer "*Messages*"
       (let ((inhibit-read-only t)) (erase-buffer)))
     (condition-case err
       (progn ,@body
	  (message "COMPLETE"))
       (t (message "%s" err)))
     (with-current-buffer "*Messages*" (test-output "MESSAGES"))
     (with-current-buffer (get-buffer-create "*Notmuch errors*")
       (test-output "ERRORS"))))

(defmacro test-time (&rest body)
  `(let ((results (mapcar (lambda (x) (/ x 5.0)) (benchmark-run 5 ,@body))))
     (message "\t\t%0.2f\t%0.2f\t%0.2f" (nth 0 results) (nth 1 results) (nth 2 results))
     (with-current-buffer "*Messages*" (test-output "MESSAGES"))))

;; For historical reasons, we hide deleted tags by default in the test
;; suite
(setq notmuch-tag-deleted-formats
      '((".*" nil)))

;; Also for historical reasons, we set the fcc handler to file not
;; insert.

(setq notmuch-maildir-use-notmuch-insert nil)

;; force a common html renderer, to avoid test variations between
;; environments

(setq mm-text-html-renderer 'html2text)

debug log:

solving 1b5e8549 ...
found 1b5e8549 in https://yhetil.org/notmuch/20220203143254.3344753-6-david@tethera.net/
found adabda4a in https://yhetil.org/notmuch/20220203143254.3344753-5-david@tethera.net/
found 6831b46f in https://yhetil.org/notmuch.git/
preparing index
index prepared:
100644 6831b46f668b771ed1234e7a3ed618a75adb8876	test/test-lib.el

applying [1/2] https://yhetil.org/notmuch/20220203143254.3344753-5-david@tethera.net/
diff --git a/test/test-lib.el b/test/test-lib.el
index 6831b46f..adabda4a 100644


applying [2/2] https://yhetil.org/notmuch/20220203143254.3344753-6-david@tethera.net/
diff --git a/test/test-lib.el b/test/test-lib.el
index adabda4a..1b5e8549 100644

Checking patch test/test-lib.el...
Applied patch test/test-lib.el cleanly.
Checking patch test/test-lib.el...
Applied patch test/test-lib.el cleanly.

index at:
100644 1b5e8549113eb9342e7d1633f1538a68248dbe9f	test/test-lib.el

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).