blob: b81e1b48c62fe2adae441f2dd5e7cd67069d52f8 (
plain)
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
|
;;; testutil-reconcile-open-repos.el --- Test helpers for reconcile-open-repos -*- lexical-binding: t; -*-
;;; Commentary:
;; Provides helper macros and functions for testing reconcile-open-repos.
;; Creates temporary directory trees with fake .git dirs and mocks git commands.
;;; Code:
(require 'cl-lib)
(defmacro reconcile-test-with-temp-dirs (dir-spec &rest body)
"Create a temp directory tree per DIR-SPEC, bind `test-root', then run BODY.
DIR-SPEC is a list of relative paths. Paths ending in / create directories;
others create files. A path containing `.git/' creates the .git dir automatically.
Example:
(reconcile-test-with-temp-dirs
(\"repo-a/.git/\" \"repo-b/subdir/\" \"not-a-repo/readme.txt\")
...use test-root...)"
(declare (indent 1))
`(let ((test-root (make-temp-file "reconcile-test-" t)))
(unwind-protect
(progn
(dolist (path ',dir-spec)
(let ((full (expand-file-name path test-root)))
(if (string-suffix-p "/" path)
(make-directory full t)
(progn
(make-directory (file-name-directory full) t)
(write-region "" nil full)))))
,@body)
(delete-directory test-root t))))
(defmacro reconcile-test-with-shell-mocks (shell-cmd-fn shell-cmd-to-str-fn &rest body)
"Run BODY with `shell-command' and `shell-command-to-string' overridden.
SHELL-CMD-FN receives (command) and returns an exit code integer.
SHELL-CMD-TO-STR-FN receives (command) and returns a string."
(declare (indent 2))
`(cl-letf (((symbol-function 'shell-command)
(lambda (cmd &rest _) (funcall ,shell-cmd-fn cmd)))
((symbol-function 'shell-command-to-string)
(lambda (cmd) (funcall ,shell-cmd-to-str-fn cmd))))
,@body))
(defvar reconcile-test-git-calls nil
"List of git argv lists observed during reconcile tests.")
(defmacro reconcile-test-with-git-mock (handler &rest body)
"Run BODY with `process-file' mocked for git.
HANDLER receives the argv list and returns either an exit code integer or a
plist with :exit and :output."
(declare (indent 1))
`(let ((reconcile-test-git-calls nil))
(cl-letf (((symbol-function 'process-file)
(lambda (program _infile destination _display &rest args)
(unless (string= program "git")
(error "Unexpected program: %s" program))
(push args reconcile-test-git-calls)
(let* ((result (funcall ,handler args))
(plist-result (and (consp result) (keywordp (car result))))
(exit (if plist-result (plist-get result :exit) result))
(output (if plist-result (plist-get result :output) "")))
(when (and destination output)
(let ((stdout-dest (if (consp destination)
(car destination)
destination)))
(cond
((bufferp stdout-dest)
(with-current-buffer stdout-dest (insert output)))
((eq stdout-dest t)
(insert output)))))
exit))))
,@body)))
(defvar reconcile-test-magit-calls nil
"List of directories passed to magit-status during tests.")
(defmacro reconcile-test-with-magit-mock (&rest body)
"Run BODY with `magit-status' mocked to record calls."
(declare (indent 0))
`(let ((reconcile-test-magit-calls nil))
(cl-letf (((symbol-function 'magit-status)
(lambda (dir &rest _) (push dir reconcile-test-magit-calls))))
,@body)))
(provide 'testutil-reconcile-open-repos)
;;; testutil-reconcile-open-repos.el ends here
|