aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrzemysław Kryger2025-09-02 09:28:13 +0100
committerPhilip Kaludercic2025-12-07 22:27:13 +0100
commit3b0dcb0b1b2e88ae3e960bf74588c1a6f13ccd01 (patch)
tree9a63efc95192180ffc07728c16a93755bdd5b6ad
parentdba1c734bfdbc6432c8f6028583491b8c8f9663e (diff)
downloademacs-3b0dcb0b1b2e88ae3e960bf74588c1a6f13ccd01.tar.gz
emacs-3b0dcb0b1b2e88ae3e960bf74588c1a6f13ccd01.zip
Add tests for package-vc
* test/lisp/package-vc-tests.el (package-vc-tests-preserve-artefacts): When non nil then preserve temporary test files and buffers. (package-vc-tests-dir, package-vc-tests-packages) (package-vc-tests-repository): Silence byte compiler. (package-vc-tests-packages): Define packages to test. (package-vc-tests-add): Copy a an in file template, update SUFFIX in it and add it to index. (package-vc-tests-create-repository): Create a package git repository with a test package's source. (package-vc-tests-package-desc): Retrieve a `package-desc' for tested package. (package-vc-tests-package-spec): Retrieve a pkg-spec for tested package. (package-vc-tests-package-lisp-dir): Determine a lisp directory for a package. (package-vc-tests-package-main-file): Calculate expected location of package's main file. (package-vc-tests-load-history-marker): Create a load history marker. (package-vc-tests-load-history-pattern): Create a regexp pattern to search in `load-history'. (package-vc-tests-load-history-position): Calculate a position in `load-history'. (package-vc-tests-load-history-interesting-entries): Return `load-history' entries related to the current `package-vc-tests-dir'. (package-vc-tests-explain-load-history-position): Return ERT explanation for load history position failures. (package-vc-tests-log-buffer-name): Return name of a log buffer used to build package or its documentation. (package-vc-tests-log-buffer-exists): Return non-nil when a log buffer used to build package or its documentation exists. (package-vc-tests-explain-log-buffer): Print contents of log buffer used to build package or its documentation and return ERT explanation for the failure. (package-vc-tests-elc-files): Check that there are elc files and that there is no compiled autoloads file amongst them. (package-vc-tests-assert-delete-elc): Assert that .elc files are present for a package. (package-vc-tests-assert-package-alist): Assert that `package-alist' contains a `package-desc' for package, and that the `package-desc' has correct slot `version' and slot `dir'.:(package-vc-tests-reset-head^): Reset head of checkout of tested packages to HEAD^. (package-vc-tests-packages-head): Return current checkout revision. (package-vc-tests-make-spec): Make a new test spec for a test package. (with-package-vc-tests-environment): Setup test environment. (package-vc-tests-environment-tear-down): Tear down test environment. (with-package-vc-tests-installed): Withing a test environment, install package, evaluate test body, and then tear down the test environment. (package-vc-tests-install-from-elpa) (package-vc-tests-install-from-spec): Install a test package. (package-vc-tests-checkout-from-elpa-install-from-checkout) (package-vc-tests-checkout-with-git-install-from-checkout): Checkout and install a test package. (package-vc-tests-package-vc-async-wait): Wait for an asynchronous VC command to finish. (package-vc-tests-deftest): Define series tests for each package in `package-vc-tests-under-test'. (install-post-conditions): Tests that after installing a test package the `load-history' entries, package's main file, commit, elc files, and `package-alist' entry are correct. (require): Test that after calling `require' the `load-history' entries are correct. (upgrade, upgrade-all): Test that after calling `package-vc-upgrade'/`package-vc-upgrade-all' the `load-history' entries, package's elc files, commit, and `package-alist' entry are correct. (upgrade-after-require, upgrade-all-after-require): Test that after calling `require' followed by `package-vc-upgrade'/`package-vc-upgrade-all' the `load-history' entries, commit, package's elc files, and `package-alist' entry are correct. (rebuild): Test that after calling `package-vc-rebuild' on an old version of a package, the package's old function, old macro, elc files, and `package-alist' entry are correct. (rebuild-after-require): Test that after calling `require' followed by `package-vc-rebuild' on an old version of a package, the package's old function, old macro, elc files, and `package-alist' entry are correct. (prepare-patch): Test that after calling `package-vc-prepare-patch' the message buffer is correct. (log-incoming): Test that after calling `package-vc-log-incoming' the log buffer is correct. (pkg-spec-doc-make-shell-command): Test that :doc, :make, and :shell-command slots in a pkg spec execute. * test/lisp/package-vc-resources/test-package-SUFFIX-v0.1.el.in: * test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.1.el.in: Code template of version 0.1 of a test package. * test/lisp/package-vc-resources/test-package-SUFFIX-v0.2.el.in: * test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.2.el.in: Code template of code of version 0.2 of a test package. * test/lisp/package-vc-resources/test-package-SUFFIX-inc.texi.in: * test/lisp/package-vc-resources/test-package-SUFFIX.texi.in: Documentation template of a test package. * test/lisp/package-vc-resources/Makefile.in: Makefile template of a test package. Co-developed-by: Philip Kaludercic <philipk@posteo.net> (Bug#79188)
-rw-r--r--test/lisp/package-vc-resources/Makefile.in4
-rw-r--r--test/lisp/package-vc-resources/test-package-SUFFIX-inc.texi.in3
-rw-r--r--test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.1.el.in16
-rw-r--r--test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.2.el.in16
-rw-r--r--test/lisp/package-vc-resources/test-package-SUFFIX-v0.1.el.in28
-rw-r--r--test/lisp/package-vc-resources/test-package-SUFFIX-v0.2.el.in24
-rw-r--r--test/lisp/package-vc-resources/test-package-SUFFIX.texi.in11
-rw-r--r--test/lisp/package-vc-tests.el1022
8 files changed, 1124 insertions, 0 deletions
diff --git a/test/lisp/package-vc-resources/Makefile.in b/test/lisp/package-vc-resources/Makefile.in
new file mode 100644
index 00000000000..8618ae8f2f4
--- /dev/null
+++ b/test/lisp/package-vc-resources/Makefile.in
@@ -0,0 +1,4 @@
1.PHONY: build-test-package-SUFFIX
2
3build-test-package-SUFFIX:
4 @touch test-package-SUFFIX.make-build
diff --git a/test/lisp/package-vc-resources/test-package-SUFFIX-inc.texi.in b/test/lisp/package-vc-resources/test-package-SUFFIX-inc.texi.in
new file mode 100644
index 00000000000..9e4e38b74a4
--- /dev/null
+++ b/test/lisp/package-vc-resources/test-package-SUFFIX-inc.texi.in
@@ -0,0 +1,3 @@
1@c -*- texinfo -*-
2@chapter Second chapter for test-package-SUFFIX
3 Second test text.
diff --git a/test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.1.el.in b/test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.1.el.in
new file mode 100644
index 00000000000..c8bfce3e8ab
--- /dev/null
+++ b/test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.1.el.in
@@ -0,0 +1,16 @@
1;;; test-package-SUFFIX-lib.el --- Test package lib -*- lexical-binding: t -*-
2
3;;; Commentary:
4;;
5;; Test package SUFFIX library.
6
7;;; Code:
8
9(defmacro test-package-SUFFIX-mac (arg)
10 ;; checkdoc-params: (arg)
11 "Old test macro for `test-package-SUFFIX'."
12 `(format "Old macro %s" ,arg))
13
14(provide 'test-package-SUFFIX-lib)
15
16;;; test-package-SUFFIX-lib.el ends here
diff --git a/test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.2.el.in b/test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.2.el.in
new file mode 100644
index 00000000000..bfa4c35f014
--- /dev/null
+++ b/test/lisp/package-vc-resources/test-package-SUFFIX-lib-v0.2.el.in
@@ -0,0 +1,16 @@
1;;; test-package-SUFFIX-lib.el --- Test package lib -*- lexical-binding: t -*-
2
3;;; Commentary:
4;;
5;; Test package SUFFIX library.
6
7;;; Code:
8
9(defmacro test-package-SUFFIX-mac (arg)
10 ;; checkdoc-params: (arg)
11 "Test macro for `test-package-SUFFIX'."
12 `(format "New macro %s" ,arg))
13
14(provide 'test-package-SUFFIX-lib)
15
16;;; test-package-SUFFIX-lib.el ends here
diff --git a/test/lisp/package-vc-resources/test-package-SUFFIX-v0.1.el.in b/test/lisp/package-vc-resources/test-package-SUFFIX-v0.1.el.in
new file mode 100644
index 00000000000..ddecc88e1c5
--- /dev/null
+++ b/test/lisp/package-vc-resources/test-package-SUFFIX-v0.1.el.in
@@ -0,0 +1,28 @@
1;;; test-package-SUFFIX.el --- Test package -*- lexical-binding: t -*-
2
3;; Homepage: https://test-domain.org
4;; Maintainer: Test Maintainer <test-maintainer@test-domain.org>
5;; Package-Requires: ((emacs "30.1"))
6;; Version: 0.1
7
8;;; Commentary:
9;;
10;; Test package SUFFIX.
11
12;;; Code:
13
14(require 'test-package-SUFFIX-lib)
15
16;;;###autoload
17(defun test-package-SUFFIX-func (arg)
18 ;; checkdoc-params: (arg)
19 "Test function for `test-package-SUFFIX'."
20 (test-package-SUFFIX-mac arg))
21
22;;;###autoload
23(defun test-package-SUFFIX-old-func ()
24 "Old test function for `test-package-SUFFIX'.")
25
26(provide 'test-package-SUFFIX)
27
28;;; test-package-SUFFIX.el ends here
diff --git a/test/lisp/package-vc-resources/test-package-SUFFIX-v0.2.el.in b/test/lisp/package-vc-resources/test-package-SUFFIX-v0.2.el.in
new file mode 100644
index 00000000000..902066d787d
--- /dev/null
+++ b/test/lisp/package-vc-resources/test-package-SUFFIX-v0.2.el.in
@@ -0,0 +1,24 @@
1;;; test-package-SUFFIX.el --- Test package -*- lexical-binding: t -*-
2
3;; Homepage: https://test-domain.org
4;; Maintainer: Test Maintainer <test-maintainer@test-domain.org>
5;; Package-Requires: ((emacs "30.1"))
6;; Version: 0.2
7
8;;; Commentary:
9;;
10;; Test package SUFFIX.
11
12;;; Code:
13
14(require 'test-package-SUFFIX-lib)
15
16;;;###autoload
17(defun test-package-SUFFIX-func (arg)
18 ;; checkdoc-params: (arg)
19 "Test function for `test-package-SUFFIX'."
20 (test-package-SUFFIX-mac arg))
21
22(provide 'test-package-SUFFIX)
23
24;;; test-package-SUFFIX.el ends here
diff --git a/test/lisp/package-vc-resources/test-package-SUFFIX.texi.in b/test/lisp/package-vc-resources/test-package-SUFFIX.texi.in
new file mode 100644
index 00000000000..0fc4fc3653d
--- /dev/null
+++ b/test/lisp/package-vc-resources/test-package-SUFFIX.texi.in
@@ -0,0 +1,11 @@
1\input texinfo @c -*- texinfo -*-
2@settitle Info for test-package-SUFFIX
3@direntry
4* Test-package-SUFFIX: (test-package-SUFFIX). test-package-SUFFIX.
5@end direntry
6
7@chapter First chapter for test-package-SUFFIX
8 First test text.
9
10@include test-package-SUFFIX-inc.texi
11@bye
diff --git a/test/lisp/package-vc-tests.el b/test/lisp/package-vc-tests.el
new file mode 100644
index 00000000000..74235da7ec5
--- /dev/null
+++ b/test/lisp/package-vc-tests.el
@@ -0,0 +1,1022 @@
1;;; package-vc-tests.el --- Tests for package-vc -*- lexical-binding:t -*-
2
3;; Copyright (C) 2025 Free Software Foundation, Inc.
4
5;; Author: Przemsyław Kryger <pkryger@gmail.com>
6;; Maintainer: Philip Kaludercic <philipk@posteo.net>
7;; Keywords: package
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software: you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
23
24;;; Commentary:
25
26;; These tests focus on verifying post conditions for `package-vc'
27;; operations on packages. These tests install and load test packages
28;; with a sample test implementation, resulting in modification of
29;; numerous global variables, for example `load-history', `load-path',
30;; `features', etc. When run with `ert' it may contaminate current
31;; Emacs session. For this reason, tests execute their bodies in
32;; `with-package-vc-tests-installed' (which see), that takes care of
33;; cleaning up the environment.
34
35;;; Code:
36
37(require 'package-vc)
38(require 'package)
39(require 'vc-git)
40(require 'vc)
41(require 'cl-lib)
42(require 'info)
43(require 'ert-x)
44(require 'ert)
45
46(defvar package-vc-tests-preserve-artefacts nil
47 "When non-nil preserve temporary files and buffers produced by tests.
48Each test produces a new temporary directory for each package under
49test. This leads to creation of [length of `package-vc-tests-packages']
50times [number of tests executed] temporary directories for each tests
51run. Tests create temporary directories with `make-temp-file', which
52see.
53
54In addition some tests may produce temporary buffers, for example when
55building a documentation.
56
57When this variable is nil then delete temporary directories and kill
58temporary buffers as soon as they are no longer needed. When this
59variable is a symbol, then preserve temporary directories and buffers
60for the package that matches the symbol. When this variable is a list
61of symbols, then preserve temporary directories and buffers for each
62package that matches a symbol in the list. When this variable is t then
63preserve all temporary directories.")
64
65(defvar package-vc-tests-dir)
66(defvar package-vc-tests-packages)
67(defvar package-vc-tests-repository)
68
69(eval-and-compile
70 (defun package-vc-tests-packages ()
71 "Return a list of package definitions to test.
72When variable `package-vc-tests-packages' is bound then return its
73value. If `package-vc-tests-dir' is bound then each entry is in a form
74of (PKG CHECKOUT-DIR LISP-DIR INSTALL-FUN), where PKG is a package
75name (a symbol), CHECKOUT-DIR is an expected checkout directory,
76LISP-DIR is a directory with package's sources (relative to
77CHECKOUT-DIR), and INSTALL-FUN is a function that checkouts and install
78the package. Otherwise each entry is in a form of PKG."
79 (if (boundp 'package-vc-tests-packages)
80 package-vc-tests-packages
81 (cl-macrolet ((test-package-def
82 (pkg checkout-dir-exp lisp-dir install-fun)
83 `(if (boundp 'package-vc-tests-dir)
84 (list
85 ',pkg
86 (expand-file-name (symbol-name ',pkg)
87 ,checkout-dir-exp)
88 ,lisp-dir
89 #',install-fun)
90 ',pkg)))
91 (list
92 ;; checkout and install with `package-vc-install' (on ELPA)
93 (test-package-def
94 test-package-1 package-user-dir nil
95 package-vc-tests-install-from-elpa)
96 ;; checkout and install with `package-vc-install' (not on ELPA)
97 (test-package-def
98 test-package-2 package-user-dir nil
99 package-vc-tests-install-from-spec)
100 ;; checkout with `package-vc-checktout' and install with
101 ;; `package-vc-install-from-checkout' (on ELPA)
102 (test-package-def
103 test-package-3 package-vc-tests-dir nil
104 package-vc-tests-checkout-from-elpa-install-from-checkout)
105 ;; checkout with git and install with
106 ;; `package-vc-install-from-checkout'
107 (test-package-def
108 test-package-4 package-vc-tests-dir nil
109 package-vc-tests-checkout-with-git-install-from-checkout)
110 ;; sources in "lisp" sub directory, checkout and install with
111 ;; `package-vc-install' (not on ELPA)
112 (test-package-def
113 test-package-5 package-user-dir "lisp"
114 package-vc-tests-install-from-spec)
115 ;; sources in "lisp" sub directory, checkout with git and
116 ;; install with `package-vc-install-from-checkout'
117 (test-package-def
118 test-package-6 package-vc-tests-dir "lisp"
119 package-vc-tests-checkout-with-git-install-from-checkout)
120 ;; sources in "src" sub directory, checkout and install with
121 ;; `package-vc-install' (on ELPA)
122 (test-package-def
123 test-package-7 package-user-dir "src"
124 package-vc-tests-install-from-elpa)
125 ;; sources in "src" sub directory, checkout with
126 ;; `package-vc-checktout' and install with
127 ;; `package-vc-install-from-checkout' (on ELPA)
128 (test-package-def
129 test-package-8 package-vc-tests-dir nil
130 package-vc-tests-checkout-from-elpa-install-from-checkout)
131 ;; sources in "custom-dir" sub directory, checkout and install
132 ;; with `package-vc-install' (on ELPA)
133 (test-package-def
134 test-package-9 package-user-dir "custom-dir"
135 package-vc-tests-install-from-elpa))))))
136
137;; TODO: add test for deleting packages, with asserting
138;; `package-vc-selected-packages'
139
140;; TODO: clarify `package-vc-install-all' behaviour with regards to
141;; packages installed with `package-vc' but not stored in
142;; `package-vc-selected-packages' i.e., packages from ELPAs
143
144(defun package-vc-tests-add (suffix in-file &optional lisp-dir)
145 "Create a new file from IN-FILE template updating SUFFIX in it.
146When LISP-DIR is non-nil place the NAME file under LISP-DIR."
147 (let* ((resource-dir (ert-resource-directory))
148 (suffix (if (stringp suffix) suffix (format "%s" suffix)))
149 (file (let ((file (replace-regexp-in-string
150 (rx (or "SUFFIX"
151 (: "-v" digit (* "." (1+ digit)))
152 (: ".in" string-end)) )
153 (lambda (mat)
154 (if (string= mat "SUFFIX") suffix ""))
155 in-file)))
156 (file-name-concat lisp-dir file))))
157 (unless (zerop (call-process
158 "sed" (expand-file-name in-file resource-dir)
159 `(:file ,file) nil
160 (format "s/SUFFIX/%s/g" suffix)))
161 (error "Failed to invoke sed on %s" in-file))
162 (vc-git-command nil 0 nil "add" ".")))
163
164(defun package-vc-tests-create-repository (suffix &optional lisp-dir)
165 "Create a test package repository with SUFFIX.
166If LISP-DIR is non-nil place sources of the package in LISP-DIR."
167 (let* ((name (format "test-package-%s" suffix))
168 (repo-dir (expand-file-name (file-name-concat "repo" name)
169 package-vc-tests-dir)))
170 (make-directory (expand-file-name (or lisp-dir ".") repo-dir) t)
171 (let ((default-directory repo-dir))
172 (vc-git-command nil 0 nil "init" "-b" "master")
173 (package-vc-tests-add
174 suffix "test-package-SUFFIX-lib-v0.1.el.in" lisp-dir)
175 (package-vc-tests-add
176 suffix "test-package-SUFFIX-v0.1.el.in" lisp-dir)
177 (package-vc-tests-add
178 suffix "test-package-SUFFIX.texi.in" lisp-dir)
179 (package-vc-tests-add
180 suffix "test-package-SUFFIX-inc.texi.in" lisp-dir)
181 ;; Place Makefile in root of the repository
182 (package-vc-tests-add
183 suffix "Makefile.in" nil)
184 (vc-git-command nil 0 nil "commit" "-m" "First commit")
185 (package-vc-tests-add
186 suffix "test-package-SUFFIX-lib-v0.2.el.in" lisp-dir)
187 (package-vc-tests-add
188 suffix "test-package-SUFFIX-v0.2.el.in" lisp-dir)
189 (vc-git-command nil 0 nil "commit" "-m" "Second commit")
190 (list repo-dir (vc-git-working-revision nil)))))
191
192(defun package-vc-tests-package-desc (pkg &optional installed)
193 "Return descriptor of PKG.
194When INSTALLED is non-nil the descriptor comes from `package-alist'.
195Otherwise the descriptor comes from `package-archive-contents'. This
196is to mimic `package-vc--read-package-desc'."
197 (cadr (assq pkg (if installed package-alist package-archive-contents))))
198
199(defun package-vc-tests-package-spec (pkg)
200 "Return pkg-spec for PKG from `package-vc-selected-packages'."
201 (cdr (assoc pkg package-vc-selected-packages #'string=)))
202
203(defun package-vc-tests-package-lisp-dir (pkg)
204 "Return a Lisp directory of PKG."
205 (and-let* ((checkout-dir (car (alist-get pkg package-vc-tests-packages))))
206 (if-let* ((lisp-dir (cadr (alist-get pkg package-vc-tests-packages))))
207 (expand-file-name lisp-dir checkout-dir)
208 checkout-dir)))
209
210(defun package-vc-tests-package-main-file (pkg)
211 "Return a main file of PKG."
212 (file-name-concat (package-vc-tests-package-lisp-dir pkg)
213 (format "%s.el" pkg)))
214
215;; When `package-vc-upgrade', `package-vc-rebuild', or other a
216;; package-vc function re-compiles a package's source the package also
217;; reloaded [1] to ensure that the most recent version of compiled code
218;; is available to Emacs. Some tests add markers in `load-history'
219;; before executing such functions. And then follow up tests use these
220;; markers to assert that expected package files are in correct places
221;; in the `load-history'.
222;;
223;; [1] Only when a file has been previously loaded.
224
225(defun package-vc-tests-load-history-marker (name)
226 "Return a `load-history' marker with NAME."
227 (file-truename
228 (expand-file-name (symbol-name name) package-vc-tests-dir)))
229
230(defun package-vc-tests-load-history-pattern (pkg type)
231 "Return a regexp pattern for PKG's file of TYPE."
232 (pcase type
233 (:autoloads
234 (rx (literal (file-truename
235 (file-name-concat
236 package-user-dir
237 (symbol-name pkg)
238 (format "%s-autoloads.el" pkg))))
239 eos))
240 (:main
241 (rx (literal (file-truename
242 (package-vc-tests-package-main-file pkg)))
243 eos))
244 (:main-compiled
245 (rx (literal (file-truename
246 (package-vc-tests-package-main-file pkg)))
247 "c" eos))
248 (:marker
249 (regexp-quote (file-truename
250 (package-vc-tests-load-history-marker pkg))))))
251
252(defun package-vc-tests-load-history-interesting-entries ()
253 "Return interesting entries in `load-history'.
254An entry in `load-history' is interesting when it starts with
255`package-vc-tests-dir'."
256 (let ((interesting-entry
257 (rx bos (literal (file-truename package-vc-tests-dir)))))
258 (mapcan
259 (lambda (ent)
260 (and (consp ent)
261 (stringp (car ent))
262 (let ((file-name (file-truename (car ent))))
263 (and (string-match interesting-entry file-name)
264 (list file-name)))))
265 load-history)))
266
267(defun package-vc-tests-load-history-position (pkg type)
268 "Return a PKG's file of TYPE position in `load-history'.
269If TYPE is `:autoloads' return a position of a PKG autoloads file.
270Otherwise, if TYPE is `:main' return a position of PKG main file (not
271compiled). Otherwise, if TYPE is `:main-compiled' return a position of
272PKG compiled main file. Otherwise, if TYPE is `:marker' return a
273position of a marker PKG."
274 (let ((pkg-file (package-vc-tests-load-history-pattern pkg type)))
275 (cl-position-if
276 (lambda (file) (string-match pkg-file file))
277 (package-vc-tests-load-history-interesting-entries))))
278
279(defun package-vc-tests-explain-load-history-position (pkg type)
280 "Explain why `package-vc-tests-load-history' failed for PKG of TYPE."
281 (let ((pattern
282 (concat "..."
283 (substring
284 (package-vc-tests-load-history-pattern pkg type)
285 (length (regexp-quote
286 (file-truename package-vc-tests-dir))))))
287 (reason
288 (if-let* ((pos (package-vc-tests-load-history-position
289 pkg type)))
290 `(found in load-history at pos ,pos)
291 '(not found in load-history)))
292 (entries
293 (cl-loop
294 with len = (length (file-truename package-vc-tests-dir))
295 for hist in (package-vc-tests-load-history-interesting-entries)
296 collect (concat "..." (substring hist len)))))
297 (append (list 'pattern pattern) reason (list entries))))
298
299(put #'package-vc-tests-load-history-position
300 'ert-explainer
301 #'package-vc-tests-explain-load-history-position)
302
303(defun package-vc-tests-log-buffer-name (pkg type)
304 "Return name for action TYPE log buffer for PKG .
305See `package-vc--build-documentation' and `package-vc--make' for format
306names."
307 (format " *package-vc %s: %s*" type pkg))
308
309(defun package-vc-tests-log-buffer-exists (pkg type)
310 "Return non-nil when log buffer for action TYPE exists for PKG."
311 (when-let* ((name (package-vc-tests-log-buffer-name pkg type)))
312 (get-buffer name)))
313
314(defun package-vc-tests-explain-log-buffer (pkg type)
315 "Explain why `package-vc-tests-log-buffer-exists' failed for TYPE action for PKG."
316 (if-let* ((name (package-vc-tests-log-buffer-name pkg type))
317 (buffer (get-buffer name))
318 (sep (make-string 80 ?-)))
319 (progn
320 (message "package-vc-tests: Contents of log-buffer %s\n%s\n%s\n%s"
321 name
322 sep
323 (with-current-buffer buffer
324 (buffer-string))
325 sep)
326 `(log-buffer ,name exists))
327 `(log-buffer ,name does not exist)))
328
329(put #'package-vc-tests-log-buffer-exists
330 'ert-explainer
331 #'package-vc-tests-explain-log-buffer)
332
333(defun package-vc-tests-elc-files (pkg)
334 "Return elc files for PKG."
335 (when-let* ((dir (package-vc-tests-package-lisp-dir pkg)))
336 (directory-files dir nil (rx ".elc" string-end))))
337
338(defun package-vc-tests-assert-elc (pkg)
339 "Assert that PKG has correct .elc files in."
340 (let* ((dir (package-vc-tests-package-lisp-dir pkg))
341 (elc-files (should (package-vc-tests-elc-files pkg)))
342 (autoloads-rx (rx (literal (format "%s-autoloads.elc" pkg))
343 string-end)))
344 (should-not (cl-find-if (lambda (elc)
345 (string-match autoloads-rx elc))
346 elc-files))
347 (dolist (elc-file elc-files)
348 (delete-file (expand-file-name elc-file dir)))))
349
350(defun package-vc-tests-assert-package-alist (pkg version)
351 "Assert that PKG entry in `package-alist' have correct VERSION and dir."
352 (let ((pkg-desc (should (cadr (assq pkg package-alist)))))
353 (should (equal (file-name-as-directory
354 (expand-file-name (format "%s" pkg)
355 package-user-dir))
356 (file-name-as-directory
357 (package-desc-dir pkg-desc))))
358 (should (equal (list pkg version)
359 (list pkg (package-desc-version pkg-desc))))))
360
361(defun package-vc-tests-reset-head^ (pkg)
362 "Reset to HEAD^ checkout for PKG."
363 (let ((default-directory (cadr (assoc pkg package-vc-tests-packages))))
364 (vc-git-command nil 0 nil "reset" "--hard" "HEAD^")))
365
366(defun package-vc-tests-package-head (pkg)
367 "Return HEAD revisions of a PKG."
368 (let ((default-directory (cadr (assoc pkg package-vc-tests-packages))))
369 (vc-git-working-revision nil)))
370
371(defun package-vc-tests-make-spec (pkg)
372 "Return a pkg-spec for PKG."
373 (let ((lisp-dir
374 (cadr (alist-get pkg package-vc-tests-packages))))
375 (append
376 (list pkg
377 :url (car package-vc-tests-repository)
378 :doc (let ((doc-file (format "%s.texi" pkg)))
379 (if lisp-dir
380 (file-name-concat lisp-dir doc-file)
381 doc-file))
382 :make (format "build-%s" pkg)
383 :shell-command (format "touch %s.cmd-build" pkg))
384 (and lisp-dir
385 (not (member lisp-dir '("lisp" "src")))
386 (list :lisp-dir lisp-dir)))))
387
388(defun package-vc-with-tests-environment (pkg function)
389 "Call FUNCTION with no arguments within a test environment set up for PKG."
390 ;; Create a test package sources repository, based on skeleton files
391 ;; in directory package-vc-resources. Before executing body make sure
392 ;; that:
393 ;;
394 ;; - `package' has been initialised, and there are no
395 ;; `package-archives' defined
396 (let* ((package-archives (unless package--initialized
397 (let (package-archives)
398 (package-initialize)
399 (package-vc--archives-initialize))
400 nil))
401 ;; - create a temporary location for packages and test files
402 (package-vc-tests-dir
403 (expand-file-name
404 (make-temp-file "package-vc-tests-"
405 t
406 (format-time-string "-%Y%m%d.%H%M%S.%3N"))))
407 ;; - packages are installed into a test directory
408 (package-user-dir (expand-file-name "elpa"
409 package-vc-tests-dir))
410 ;; - define test packages, their checkout locations, lisp
411 ;; directories, and install functions
412 (package-vc-tests-packages (package-vc-tests-packages))
413 ;; - create a test package bundle
414 (package-vc-tests-repository
415 (let* ((pkg-name (symbol-name pkg))
416 (suffix (and (string-match
417 (rx ?- (group (1+ (not ?-))) eos)
418 pkg-name)
419 (match-string 1 pkg-name))))
420 (package-vc-tests-create-repository
421 suffix (cadr (alist-get pkg package-vc-tests-packages)))))
422 ;; - find all packages that are present in a test ELPA
423 (package-vc-tests-elpa-packages
424 (cl-loop
425 for (name _ _ fn) in package-vc-tests-packages
426 when (memq
427 fn
428 '(package-vc-tests-install-from-elpa
429 package-vc-tests-checkout-from-elpa-install-from-checkout))
430 collect name))
431 ;; - make test packages recognisable by `package' and
432 ;; `package-vc' internals:
433 (package-archive-contents
434 (mapcar
435 (lambda (pkg)
436 (list pkg
437 (package-desc-create
438 :name pkg
439 :version '(0 2)
440 :reqs '((emacs (30.1)))
441 :kind 'tar
442 :archive "test-elpa"
443 :extras
444 (list
445 '(:maintainer
446 ("Test Maintainer"
447 . "test-maintainer@test-domain.org"))
448 (cons :url (car package-vc-tests-repository))
449 (cons :commit (cadr package-vc-tests-repository))
450 (cons :revdesc (substring
451 (cadr package-vc-tests-repository)
452 0 12))))))
453 package-vc-tests-elpa-packages))
454 ;; Branch needs to be specified in a pkg-spec, as cloning from
455 ;; a bundle won't checkout a default branch.
456 (package-vc--archive-spec-alists
457 (list
458 (cons 'test-elpa
459 (mapcar #'package-vc-tests-make-spec
460 package-vc-tests-elpa-packages))))
461 (package-vc--archive-data-alist
462 '((test-elpa :version 1 :default-vc Git)))
463 ;; - `vc-guess-backend-url' is recognising bundles as `Git'
464 ;; repositories:
465 (vc-clone-heuristic-alist
466 `((,(rx "test-package-" (1+ digit) ".bundle" eos)
467 . Git)
468 ,@vc-clone-heuristic-alist))
469 ;; - ensure that `package-alist' and
470 ;; `package-vc-selected-packages' are empty
471 (package-alist '())
472 (package-vc-selected-packages '())
473 ;; - don't save any customization
474 (user-init-file nil)
475 (custom-file nil)
476 ;; - don't register projects
477 (package-vc-register-as-project nil)
478 ;; - allow build commands
479 (package-vc-allow-build-commands t)
480 ;; - FIXME: something sets `default-directory' to last
481 ;; checkout directory after `package-vc-checkout', which
482 ;; causes problems when this function deletes the temporary
483 ;; directory after body execution.
484 (default-directory package-vc-tests-dir))
485 (funcall function)))
486
487(defun package-vc-tests-environment-tear-down (pkg)
488 "Tear down test environment for PKG.
489Unbind package defined symbols, and remove package defined features and
490entries from `load-path',`load-history', and `Info-directory-list'.
491Delete temporary directories and buffers produced by tests, except for
492when PKG matches `package-vc-tests-preserve-artefacts'."
493 (let ((pattern (rx string-start (literal package-vc-tests-dir))))
494 (dolist (entry load-history)
495 (when-let* ((file (car-safe entry))
496 ((stringp file))
497 ((string-match pattern file)))
498 (dolist (elt (cdr entry))
499 (pcase elt
500 (`(defun . ,fun)
501 (fmakunbound fun))
502 (`(provide . ,feat)
503 (setq features (cl-remove feat features)))
504 ((and (pred symbolp)
505 (pred boundp))
506 (makunbound elt))))))
507 (setq load-path (cl-remove-if
508 (lambda (path)
509 (and (stringp path)
510 (string-match pattern path)))
511 load-path)
512 load-history (cl-remove-if
513 (lambda (entry)
514 (and-let* ((path (car-safe entry))
515 (_ (stringp path)))
516 (string-match pattern path)))
517 load-history)
518 Info-directory-list (cl-remove-if
519 (lambda (dir)
520 (and (stringp dir)
521 (string-match pattern dir)))
522 Info-directory-list)))
523 (let ((buffers
524 (delq nil
525 (mapcar (lambda (type)
526 (get-buffer
527 (package-vc-tests-log-buffer-name type
528 pkg)))
529 '(doc make)))))
530 (if (or (memq package-vc-tests-preserve-artefacts `(t ,pkg))
531 (and (listp package-vc-tests-preserve-artefacts)
532 (memq pkg package-vc-tests-preserve-artefacts)))
533 (message
534 "package-vc-tests: preserving temporary directory: %s%s"
535 package-vc-tests-dir
536 (and buffers (format " and buffers: %s" buffers)))
537 (delete-directory package-vc-tests-dir t)
538 (dolist (buffer buffers)
539 (kill-buffer buffer)))))
540
541(defun package-vc-with-installed-tests (pkg function)
542 "Call FUNCTION with PKG installed in a test environment.
543FUNCTION should have no arguments."
544 (package-vc-with-tests-environment
545 pkg (lambda ()
546 (unwind-protect
547 (progn
548 (funcall (or (caddr (alist-get pkg package-vc-tests-packages))
549 (lambda (name)
550 (ert-fail
551 (format
552 "Cannot find %s in package-vc-tests-packages"
553 name))))
554 pkg)
555 (funcall function))
556 (package-vc-tests-environment-tear-down pkg)))))
557
558(defun package-vc-tests-install-from-elpa (pkg)
559 "Install PKG with `package-vc-install'."
560 (push (list (package-vc-tests-load-history-marker 'install-begin))
561 load-history)
562 (should (eq t (package-vc-install pkg)))
563 (push (list (package-vc-tests-load-history-marker 'install-end))
564 load-history)
565 (should-not (package-vc-tests-package-spec pkg)))
566
567(defun package-vc-tests-install-from-spec (pkg)
568 "Install PKG with `package-vc-install' (not on ELPA)."
569 (push (list (package-vc-tests-load-history-marker 'install-begin))
570 load-history)
571 (should (eq t (package-vc-install (package-vc-tests-make-spec pkg))))
572 (push (list (package-vc-tests-load-history-marker 'install-end))
573 load-history)
574 (should (equal (car package-vc-tests-repository)
575 (plist-get (package-vc-tests-package-spec pkg)
576 :url))))
577
578(defun package-vc-tests-checkout-from-elpa-install-from-checkout (pkg)
579 "Install PKG with `package-vc-install-from-checkout'.
580Make checkout with `package-vc-checkout'."
581 (let ((checkout-dir (car (alist-get pkg package-vc-tests-packages))))
582 (let* ((uniquify-buffer-name-style nil)
583 (buffer (package-vc-checkout (package-vc-tests-package-desc
584 pkg)
585 checkout-dir)))
586 (should (bufferp buffer))
587 (should (string-prefix-p (symbol-name pkg) (buffer-name buffer))))
588 (push (list (package-vc-tests-load-history-marker 'install-begin))
589 load-history)
590 (should (eq t
591 (package-vc-install-from-checkout checkout-dir)))
592 (push (list (package-vc-tests-load-history-marker 'install-end))
593 load-history)
594 (let ((extras (package-desc-extras (package-vc-tests-package-desc pkg t))))
595 (should (equal checkout-dir (alist-get :vc-dir extras))))))
596
597(defun package-vc-tests-checkout-with-git-install-from-checkout (pkg)
598 "Install PKG with `package-vc-install-from-checkout'.
599Make checkout with git(1)."
600 (let ((checkout-dir (car (alist-get pkg package-vc-tests-packages))))
601 (vc-git-clone (car package-vc-tests-repository)
602 checkout-dir
603 "master")
604 (push (list (package-vc-tests-load-history-marker 'install-begin))
605 load-history)
606 (should (eq t
607 (package-vc-install-from-checkout checkout-dir
608 (symbol-name pkg))))
609 (push (list (package-vc-tests-load-history-marker 'install-end))
610 load-history)
611 (let ((extras (package-desc-extras (package-vc-tests-package-desc pkg t))))
612 (should (equal checkout-dir (alist-get :vc-dir extras))))))
613
614;; Some of VC commands used by package-vc execute VC operations
615;; asynchronously. When such an operation executes as a part of test
616;; body, the test needs to wait for the operation to finish before
617;; asserting post conditions. The maximum wait time should be at least
618;; a single order of magnitude higher than what the operation usually
619;; takes. This decreases probability of false positives (for example
620;; when execution takes place on a busy machine). On the other hand the
621;; value cannot be too large to ensure reasonable execution time in case
622;; of a legitimate failure.
623
624(defmacro package-vc-tests-package-vc-async-wait (seconds count flags &rest body)
625 "Wait up to SECONDS for COUNT async vc commands with FLAGS called by BODY.
626Return nil on timeout or the value of last form in BODY."
627 (declare (indent 3))
628 (let ((count-sym (make-symbol "count"))
629 (post-vc-command-sym (make-symbol "post-vc-command")))
630 `(let* ((,count-sym ,count)
631 (,post-vc-command-sym
632 (lambda (command _ command-flags)
633 ;; A crude filter for vc commands
634 (when (and (equal command vc-git-program)
635 (cl-every (lambda (flag)
636 (member flag command-flags))
637 ,flags))
638 (decf ,count-sym)))))
639 (add-hook 'vc-post-command-functions ,post-vc-command-sym 100)
640 (unwind-protect
641 (with-timeout (,seconds nil)
642 (prog1 (progn ,@body)
643 (while (/= ,count-sym 0)
644 (accept-process-output nil 0.01))))
645 (remove-hook 'vc-post-command-functions ,post-vc-command-sym)))))
646
647(defmacro package-vc-test-deftest (name args &rest body)
648 "For each package under test define a test with NAME.
649Use function `package-vc-tests-packages' to obtain packages under test.
650Execute BODY as a test body with a package under test installed. Bind
651car of ARGS (a symbol) to name of the package."
652 (declare (debug (&define [&name "test@" symbolp]
653 sexp
654 def-body))
655 (indent 2))
656 (when (length< args 1)
657 (error "`package-vc' tests have to take at least one argument"))
658 (unless (symbolp (car-safe args))
659 (error "`package-vc' tests first argument has to be a symbol"))
660 (let ((file (or (macroexp-file-name) buffer-file-name))
661 (tests '()) (fn (gensym)))
662 (dolist (pkg (package-vc-tests-packages))
663 (let ((name (intern (format "package-vc-tests-%s/%s" name pkg))))
664 (push
665 `(ert-set-test
666 ',name
667 (make-ert-test
668 :name ',name
669 :tags '(package-vc)
670 :file-name ,file
671 :body
672 (lambda ()
673 (package-vc-with-installed-tests
674 ',pkg (funcall ,fn ',pkg))
675 nil)))
676 tests)))
677 `(let ((,fn (lambda (,(car args))
678 (cl-macrolet ((skip-when (form) `(ert--skip-when ,form))
679 (skip-unless (form) `(ert--skip-unless ,form)))
680 (lambda () ,@body)))))
681 ,@tests)))
682
683(package-vc-test-deftest install-post-conditions (pkg)
684 (let ((install-begin
685 (should (package-vc-tests-load-history-position
686 'install-begin :marker)))
687 (install-end
688 (should (package-vc-tests-load-history-position
689 'install-end :marker)))
690 (autoloads-pos
691 (should (package-vc-tests-load-history-position
692 pkg :autoloads))))
693 (should (< install-end autoloads-pos install-begin))
694 (should-not (package-vc-tests-load-history-position
695 pkg :main))
696 (should-not (package-vc-tests-load-history-position
697 pkg :main-compiled)))
698 (should (equal (package-vc--main-file
699 (package-vc-tests-package-desc pkg t))
700 (package-vc-tests-package-main-file pkg)))
701 (should (equal (package-vc-commit
702 (package-vc-tests-package-desc pkg t))
703 (cadr package-vc-tests-repository)))
704 (package-vc-tests-assert-elc pkg)
705 (package-vc-tests-assert-package-alist pkg '(0 2)))
706
707(package-vc-test-deftest require (pkg)
708 (should (fboundp (intern (format "%s-func" pkg))))
709 (should (autoloadp
710 (symbol-function (intern (format "%s-func" pkg)))))
711 (should (require pkg))
712 (should (fboundp (intern (format "%s-func" pkg))))
713 (should-not (autoloadp
714 (symbol-function (intern (format "%s-func" pkg)))))
715 (should-not (fboundp (intern (format "%s-old-func" pkg))))
716 (should-not (package-vc-tests-load-history-position
717 pkg :main))
718 (let ((install-end
719 (should (package-vc-tests-load-history-position
720 'install-end :marker)))
721 (main-compiled-pos
722 (should (package-vc-tests-load-history-position
723 pkg :main-compiled))))
724 (should (< main-compiled-pos install-end))))
725
726(package-vc-test-deftest upgrade (pkg)
727 (let ((head (package-vc-tests-package-head pkg)))
728 (package-vc-tests-reset-head^ pkg)
729 (push (list (package-vc-tests-load-history-marker
730 'upgrade-begin))
731 load-history)
732 (should
733 (package-vc-tests-package-vc-async-wait 5 1 '("pull")
734 (package-vc-upgrade (package-vc-tests-package-desc pkg t))
735 t))
736 (push (list (package-vc-tests-load-history-marker
737 'upgrade-end))
738 load-history)
739 (should-not (package-vc-tests-load-history-position
740 pkg :main))
741 (should-not (package-vc-tests-load-history-position
742 pkg :main-compiled))
743 (let ((upgrade-begin
744 (should (package-vc-tests-load-history-position
745 'upgrade-begin :marker)))
746 (upgrade-end
747 (should (package-vc-tests-load-history-position
748 'upgrade-end :marker)))
749 (autoloads-pos
750 (should (package-vc-tests-load-history-position
751 pkg :autoloads))))
752 (should (< upgrade-end autoloads-pos upgrade-begin)))
753 (let ((func (intern (format "%s-func" pkg))))
754 (should (fboundp func))
755 (should (autoloadp
756 (symbol-function func)))
757 (should (equal "New macro test"
758 (funcall func "test"))))
759 (should-not (fboundp (intern (format "%s-old-func" pkg))))
760 (should (equal head
761 (package-vc-tests-package-head pkg))))
762 (package-vc-tests-assert-elc pkg)
763 (package-vc-tests-assert-package-alist pkg '(0 2)))
764
765(package-vc-test-deftest upgrade-after-require (pkg)
766 (should (require pkg))
767 (let ((head (package-vc-tests-package-head pkg)))
768 (package-vc-tests-reset-head^ pkg)
769 (push (list (package-vc-tests-load-history-marker
770 'upgrade-begin))
771 load-history)
772 (should
773 (package-vc-tests-package-vc-async-wait 5 1 '("pull")
774 (package-vc-upgrade (package-vc-tests-package-desc pkg t))
775 t))
776 (push (list (package-vc-tests-load-history-marker
777 'upgrade-end))
778 load-history)
779 (let ((upgrade-begin
780 (should (package-vc-tests-load-history-position
781 'upgrade-begin :marker)))
782 (upgrade-end
783 (should (package-vc-tests-load-history-position
784 'upgrade-end :marker)))
785 (autoloads-pos
786 (should (package-vc-tests-load-history-position
787 pkg :autoloads)))
788 (main-pos
789 (should (package-vc-tests-load-history-position
790 pkg :main)))
791 (main-compiled-pos
792 (should (package-vc-tests-load-history-position
793 pkg :main-compiled))))
794 (should (< upgrade-end autoloads-pos upgrade-begin))
795 (should (< upgrade-end main-pos upgrade-begin))
796 (should (< upgrade-end main-compiled-pos upgrade-begin)))
797 (let ((func (intern (format "%s-func" pkg))))
798 (should (fboundp func))
799 (should-not (autoloadp
800 (symbol-function func)))
801 (should (equal "New macro test"
802 (funcall func "test"))))
803 (should-not (fboundp (intern (format "%s-old-func" pkg))))
804 (should (equal head
805 (package-vc-tests-package-head pkg))))
806 (package-vc-tests-assert-elc pkg)
807 (package-vc-tests-assert-package-alist pkg '(0 2)))
808
809(package-vc-test-deftest upgrade-all (pkg)
810 (let ((head (package-vc-tests-package-head pkg)))
811 (package-vc-tests-reset-head^ pkg)
812 (push (list (package-vc-tests-load-history-marker
813 'upgrade-all-begin))
814 load-history)
815 (should
816 (package-vc-tests-package-vc-async-wait 5 1 '("pull")
817 (package-vc-upgrade-all)
818 t))
819 (push (list (package-vc-tests-load-history-marker
820 'upgrade-all-end))
821 load-history)
822 (should-not (package-vc-tests-load-history-position
823 pkg :main))
824 (should-not (package-vc-tests-load-history-position
825 pkg :main-compiled))
826 (let ((upgrade-begin
827 (should (package-vc-tests-load-history-position
828 'upgrade-all-begin :marker)))
829 (upgrade-end
830 (should (package-vc-tests-load-history-position
831 'upgrade-all-end :marker)))
832 (autoloads-pos
833 (should (package-vc-tests-load-history-position
834 pkg :autoloads))))
835 (should (< upgrade-end autoloads-pos upgrade-begin)))
836 (let ((func (intern (format "%s-func" pkg))))
837 (should (fboundp func))
838 (should (autoloadp
839 (symbol-function func)))
840 (should (equal "New macro test"
841 (funcall func "test"))))
842 (should-not (fboundp (intern (format "%s-old-func" pkg))))
843 (should (equal head
844 (package-vc-tests-package-head pkg))))
845 (package-vc-tests-assert-elc pkg)
846 (package-vc-tests-assert-package-alist pkg '(0 2)))
847
848(package-vc-test-deftest upgrade-all-after-require (pkg)
849 (should (require pkg))
850 (let ((head (package-vc-tests-package-head pkg)))
851 (package-vc-tests-reset-head^ pkg)
852 (push (list (package-vc-tests-load-history-marker
853 'upgrade-all-begin))
854 load-history)
855 (should
856 (package-vc-tests-package-vc-async-wait 5 1 '("pull")
857 (package-vc-upgrade-all)
858 t))
859 (push (list (package-vc-tests-load-history-marker
860 'upgrade-all-end))
861 load-history)
862 (let ((upgrade-begin
863 (should (package-vc-tests-load-history-position
864 'upgrade-all-begin :marker)))
865 (upgrade-end
866 (should (package-vc-tests-load-history-position
867 'upgrade-all-end :marker)))
868 (autoloads-pos
869 (should (package-vc-tests-load-history-position
870 pkg :autoloads)))
871 (main-pos
872 (should (package-vc-tests-load-history-position
873 pkg :main)))
874 (main-compiled-pos
875 (should (package-vc-tests-load-history-position
876 pkg :main-compiled))))
877 (should (< upgrade-end autoloads-pos upgrade-begin))
878 (should (< upgrade-end main-pos upgrade-begin))
879 (should (< upgrade-end main-compiled-pos upgrade-begin)))
880 (let ((func (intern (format "%s-func" pkg))))
881 (should (fboundp func))
882 (should-not (autoloadp
883 (symbol-function func)))
884 (should (equal "New macro test"
885 (funcall func "test"))))
886 (should-not (fboundp (intern (format "%s-old-func" pkg))))
887 (should (equal head
888 (package-vc-tests-package-head pkg))))
889 (package-vc-tests-assert-elc pkg)
890 (package-vc-tests-assert-package-alist pkg '(0 2)))
891
892(package-vc-test-deftest rebuild (pkg)
893 (package-vc-tests-reset-head^ pkg)
894 (let ((head (package-vc-tests-package-head pkg)))
895 (package-vc-rebuild
896 (package-vc-tests-package-desc pkg t))
897 (let ((old-func (intern (format "%s-old-func" pkg))))
898 (should (fboundp old-func))
899 (should (autoloadp
900 (symbol-function old-func))))
901 (let ((func (intern (format "%s-func" pkg))))
902 (should (fboundp func))
903 (should (autoloadp
904 (symbol-function func)))
905 (should (equal "Old macro test"
906 (funcall func "test"))))
907 (should (equal head
908 (package-vc-tests-package-head pkg))))
909 (package-vc-tests-assert-elc pkg)
910 (package-vc-tests-assert-package-alist pkg '(0 1)))
911
912(package-vc-test-deftest rebuild-after-require (pkg)
913 (should (require pkg))
914 (package-vc-tests-reset-head^ pkg)
915 (let ((head (package-vc-tests-package-head pkg)))
916 (package-vc-rebuild
917 (package-vc-tests-package-desc pkg t))
918 (let ((old-func (intern (format "%s-old-func" pkg))))
919 (should (fboundp old-func))
920 (should-not (autoloadp
921 (symbol-function old-func))))
922 (let ((func (intern (format "%s-func" pkg))))
923 (should (fboundp func))
924 (should-not (autoloadp
925 (symbol-function func)))
926 (should (equal "Old macro test"
927 (funcall func "test"))))
928 (should (equal head
929 (package-vc-tests-package-head pkg))))
930 (package-vc-tests-assert-elc pkg)
931 (package-vc-tests-assert-package-alist pkg '(0 1)))
932
933(package-vc-test-deftest prepare-patch (pkg)
934 ;; Ensure `vc-prepare-patch' respects subject from function argument
935 (let ((vc-prepare-patches-separately nil))
936 (package-vc-prepare-patch (package-vc-tests-package-desc pkg t)
937 "test-subject"
938 (cdr package-vc-tests-repository))
939 (let ((message-buffer
940 (should (get-buffer "*unsent mail to Test Maintainer*"))))
941 (should (bufferp message-buffer))
942 (switch-to-buffer message-buffer)
943 (goto-char (point-min))
944 (should
945 (string-match
946 (rx
947 "To: Test Maintainer <test-maintainer@test-domain.org>")
948 (buffer-substring (point) (pos-eol))))
949 (forward-line)
950 (should
951 (string-match
952 (rx "Subject: test-subject")
953 (buffer-substring (point) (pos-eol))))
954 (let ((kill-buffer-query-functions nil))
955 (with-current-buffer message-buffer
956 ;; we mark the buffer as unmodified so that `kill-buffer'
957 ;; doesn't complain (interrupting automatic testsx)
958 (set-buffer-modified-p nil))
959 (kill-buffer message-buffer)))))
960
961(package-vc-test-deftest log-incoming (pkg)
962 (package-vc-tests-reset-head^ pkg)
963 (should
964 (package-vc-tests-package-vc-async-wait
965 5 1 '("log" "--decorate")
966 (package-vc-log-incoming (package-vc-tests-package-desc pkg t))
967 t))
968 (let ((incoming-buffer (get-buffer "*vc-incoming*"))
969 (pattern (rx (literal
970 (substring
971 (cadr package-vc-tests-repository)
972 0 7))
973 (one-or-more any)
974 "Second commit"
975 line-end)))
976 (should (bufferp incoming-buffer))
977 (switch-to-buffer incoming-buffer)
978 (goto-char (point-min))
979 (should
980 (string-match
981 pattern
982 (buffer-substring (point) (pos-eol))))
983 (let (kill-buffer-query-functions)
984 (kill-buffer incoming-buffer))))
985
986(package-vc-test-deftest pkg-spec-doc-make-shell-command (pkg)
987 ;; Only `package-vc-install' runs make and shell command
988 (skip-unless (memq (caddr (alist-get pkg package-vc-tests-packages))
989 '(package-vc-tests-install-from-elpa
990 package-vc-tests-install-from-spec)))
991 (let* ((desc (package-vc-tests-package-desc pkg t))
992 (checkout-dir (package-vc--checkout-dir desc)))
993 (should (file-exists-p
994 (expand-file-name
995 (format "%s.make-build" pkg)
996 checkout-dir)))
997 (should (file-exists-p
998 (expand-file-name
999 (format "%s.cmd-build" pkg)
1000 checkout-dir))))
1001 (should-not (package-vc-tests-log-buffer-exists 'doc pkg))
1002 (should (cl-member-if
1003 (lambda (dir)
1004 (and (stringp dir)
1005 (string-prefix-p package-vc-tests-dir dir)))
1006 Info-directory-list))
1007 (let ((info-file
1008 (expand-file-name (format "%s.info" pkg)
1009 (car (alist-get
1010 pkg package-vc-tests-packages)))))
1011 (should (file-exists-p info-file))
1012 (ert-with-test-buffer
1013 (:name (format "*package-vc-tests: %s.info*" pkg))
1014 (insert-file-contents info-file)
1015 (goto-char (point-min))
1016 (should (re-search-forward
1017 (format "First chapter for %s" pkg)))
1018 (should (re-search-forward
1019 (format "Second chapter for %s" pkg))))))
1020
1021(provide 'package-vc-tests)
1022;;; package-vc-tests.el ends here