]> git.notmuchmail.org Git - notmuch/blobdiff - test/test-lib.el
test: Test buttonization of id: links
[notmuch] / test / test-lib.el
index a78393684c4e4b308f3e822e6eae1c593ebfb89a..dece811e6136064b84afec343161c1e25f5c9dec 100644 (file)
@@ -20,8 +20,7 @@
 ;;
 ;; Authors: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
 
-;; avoid crazy 10-column default of --batch
-(set-frame-width (window-frame (get-buffer-window)) 80)
+(require 'cl)  ;; This code is generally used uncompiled.
 
 ;; `read-file-name' by default uses `completing-read' function to read
 ;; user input.  It does not respect `standard-input' variable which we
 ;; `read' call.
 (setq read-file-name-function (lambda (&rest _) (read)))
 
+;; Work around a bug in emacs 23.1 and emacs 23.2 which prevents
+;; noninteractive (kill-emacs) from emacsclient.
+(if (and (= emacs-major-version 23) (< emacs-minor-version 3))
+  (defadvice kill-emacs (before disable-yes-or-no-p activate)
+    "Disable yes-or-no-p before executing kill-emacs"
+    (defun yes-or-no-p (prompt) t)))
+
+;; Emacs bug #2930:
+;;     23.0.92; `accept-process-output' and `sleep-for' do not run sentinels
+;; seems to be present in Emacs 23.1.
+;; Running `list-processes' after `accept-process-output' seems to work
+;; around this problem.
+(if (and (= emacs-major-version 23) (= emacs-minor-version 1))
+  (defadvice accept-process-output (after run-list-processes activate)
+    "run list-processes after executing accept-process-output"
+    (list-processes)))
+
 (defun notmuch-test-wait ()
   "Wait for process completion."
   (while (get-buffer-process (current-buffer))
-    (sleep-for 0.1)))
+    (accept-process-output nil 0.1)))
 
 (defun test-output (&optional filename)
   "Save current buffer to file FILENAME.  Default FILENAME is OUTPUT."
@@ -45,16 +61,19 @@ FILENAME is OUTPUT."
     (with-temp-file (or filename "OUTPUT") (insert text))))
 
 (defun visible-buffer-string ()
-  "Same as `buffer-string', but excludes invisible text."
+  "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', but excludes invisible text."
+  "Same as `buffer-substring-no-properties', but excludes
+invisible text."
   (let (str)
     (while (< start end)
       (let ((next-pos (next-char-property-change start end)))
        (when (not (invisible-p start))
-         (setq str (concat str (buffer-substring start next-pos))))
+         (setq str (concat str (buffer-substring-no-properties
+                                start next-pos))))
        (setq start next-pos)))
     str))
 
@@ -64,3 +83,75 @@ running, quit if it terminated."
   (if (not (process-attributes pid))
       (kill-emacs)
     (run-at-time "1 min" nil 'orphan-watchdog pid)))
+
+(defun hook-counter (hook)
+  "Count how many times a hook is called.  Increments
+`hook'-counter variable value if it is bound, otherwise does
+nothing."
+  (let ((counter (intern (concat (symbol-name hook) "-counter"))))
+    (if (boundp counter)
+       (set counter (1+ (symbol-value counter))))))
+
+(defun add-hook-counter (hook)
+  "Add hook to count how many times `hook' is called."
+  (add-hook hook (apply-partially 'hook-counter hook)))
+
+(add-hook-counter 'notmuch-hello-mode-hook)
+(add-hook-counter 'notmuch-hello-refresh-hook)
+
+(defadvice notmuch-search-process-filter (around pessimal activate disable)
+  "Feed notmuch-search-process-filter one character at a time."
+  (let ((string (ad-get-arg 1)))
+    (loop for char across string
+         do (progn
+              (ad-set-arg 1 (char-to-string char))
+              ad-do-it))))
+
+(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 discrepencies."
+  (if (equal output expected)
+      t
+    (cond
+     ((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 (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)))))