*** empty log message ***
[bpt/emacs.git] / admin / cus-test.el
CommitLineData
6be19e60 1;;; cus-test.el --- tests for custom types and load problems
82e74860
MR
2
3;; Copyright (C) 1998, 2000, 2002 Free Software Foundation, Inc.
4
5;; Author: Markus Rost <markus.rost@mathematik.uni-regensburg.de>
6;; Maintainer: Markus Rost <rost@math.ohio-state.edu>
7;; Created: 13 Sep 1998
8;; Keywords: maint
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
27;;; Commentary:
28
6be19e60
MR
29;; This file provides simple tests to detect custom options with
30;; incorrect customization types and load problems for custom and
31;; autoload dependencies.
82e74860 32;;
6be19e60
MR
33;; The basic tests can be run in batch mode. Invoke them with
34;;
35;; src/emacs -batch -l admin/cus-test.el -f cus-test-opts
36;;
37;; src/emacs -batch -l admin/cus-test.el -f cus-test-deps
38;;
39;; src/emacs -batch -l admin/cus-test.el -f cus-test-libs
40;;
41;; in the emacs source directory.
42;;
43;; For interactive use: Load this file. Then
82e74860
MR
44;;
45;; M-x cus-test-apropos REGEXP RET
46;;
47;; checks the options matching REGEXP. In particular
48;;
49;; M-x cus-test-apropos RET
50;;
51;; checks all options. The detected options are stored in the
52;; variable `cus-test-errors'.
53;;
54;; Only those options are checked which have been already loaded.
55;; Therefore `cus-test-apropos' is more efficient after loading many
56;; libraries.
57;;
6be19e60
MR
58;; M-x cus-test-load-custom-loads
59;;
60;; loads all (!) custom dependencies and
82e74860 61;;
6be19e60
MR
62;; M-x cus-test-load-libs
63;;
64;; loads all (!) libraries with autoloads.
82e74860 65;;
82e74860 66;; Options with a custom-get property, usually defined by a :get
bd08d86a
MR
67;; declaration, are stored in the variable
68;;
69;; `cus-test-vars-with-custom-get'
70;;
71;; Options with a state of 'changed ("changed outside the customize
72;; buffer") are stored in the variable
73;;
74;; `cus-test-vars-with-changed-state'
75;;
76;; These lists are prepared just in case one wants to investigate
77;; those options further.
78;;
6be19e60 79;; The command `cus-test-opts' tests many (all?) custom options.
bd08d86a 80;;
6be19e60
MR
81;; The command `cus-test-deps' is like `cus-test-load-custom-loads'
82;; but reports about load errors.
592cd48b 83;;
6be19e60
MR
84;; The command `cus-test-libs' runs for all libraries with autoloads
85;; separate emacs processes of the form "emacs -batch -l LIB".
592cd48b 86;;
6be19e60 87;; Some results from October 2002:
592cd48b 88;;
6be19e60
MR
89;; 4523 options tested
90;; The following variables might have problems:
91;; ps-mule-font-info-database-default
bf7a63e1
MR
92;; grep-tree-command
93;; grep-find-command
592cd48b 94;;
6be19e60
MR
95;; 288 features required
96;; 10 files loaded
97;; The following load problems appeared:
bf7a63e1 98;; (killing x-win (file-error Cannot open load file x-win))
6be19e60 99;; Symbol faces has loaddefs as custom dependency
95dc5eeb
MR
100;; (reftex-index-support reftex-vars (void-function reftex-set-dirty))
101;; (eshell-script em-script (void-variable eshell-directory-name))
102;; (pcomplete em-cmpl (void-function eshell-under-windows-p))
103;; (eshell-ext esh-ext (void-function eshell-under-windows-p))
6be19e60 104;; ...
592cd48b 105;;
6be19e60 106;; 422 libraries had no load errors
592cd48b 107;; The following load problems appeared:
6be19e60 108;; (eudc-export error 255)
95dc5eeb
MR
109;; (ada-xref error 255)
110;; (ada-stmt error 255)
82e74860 111
e170d16c 112\f
592cd48b 113;;; Code:
82e74860 114
6be19e60 115;;; Workarounds. For a smooth run and to avoid some side effects.
82e74860 116
bd08d86a 117(defvar cus-test-after-load-libs-hook nil
6be19e60
MR
118 "Used to switch off undesired side effects of loading libraries.")
119
120(defvar cus-test-skip-list nil
121 "List of variables to disregard by `cus-test-apropos'.")
bd08d86a 122
6be19e60
MR
123(defvar cus-test-noloads nil
124 "List of libraries not to load by `cus-test-load-libs'.")
125
126;; The file eudc-export.el loads libraries "bbdb" and "bbdb-com" which
127;; are not part of GNU Emacs: (locate-library "bbdb") => nil
128;; We avoid the resulting errors from loading eudc-export.el:
129(provide 'bbdb)
130(provide 'bbdb-com)
82e74860 131
6be19e60
MR
132;; This avoids a hang of `cus-test-apropos' in 21.2.
133;; (add-to-list 'cus-test-skip-list 'sh-alias-alist)
82e74860 134
6be19e60
MR
135;; Don't create a file `filesets-menu-cache-file'.
136(setq filesets-menu-cache-file "")
137;; Disable filesets hooks.
82e74860 138(add-hook
bd08d86a 139 'cus-test-after-load-libs-hook
82e74860
MR
140 (lambda nil
141 (remove-hook 'menu-bar-update-hook 'filesets-build-menu-maybe)
142 (remove-hook 'kill-emacs-hook 'filesets-exit)
143 (remove-hook 'kill-buffer-hook 'filesets-remove-from-ubl)
144 (remove-hook 'first-change-hook 'filesets-reset-filename-on-change)
145 ))
592cd48b
MR
146
147;; Loading dunnet in batch mode leads to a Dead end.
6be19e60
MR
148(let (noninteractive) (load "dunnet"))
149(add-to-list 'cus-test-noloads "dunnet")
592cd48b 150
6be19e60
MR
151;; Never Viperize.
152(setq viper-mode nil)
82e74860 153
592cd48b 154;; Don't create a file `save-place-file'.
82e74860
MR
155(eval-after-load "saveplace"
156 '(remove-hook 'kill-emacs-hook 'save-place-kill-emacs-hook))
157
592cd48b 158;; Don't create a file `abbrev-file-name'.
82e74860
MR
159(setq save-abbrevs nil)
160
161;; Avoid compile logs from adviced functions.
162(eval-after-load "bytecomp"
163 '(setq ad-default-compilation-action 'never))
164
6be19e60
MR
165\f
166;;; Main code:
167
82e74860
MR
168;; We want to log all messages.
169(setq message-log-max t)
170
592cd48b
MR
171(require 'cus-edit)
172(require 'cus-load)
173
82e74860
MR
174(defvar cus-test-errors nil
175 "List of problematic variables found by `cus-test-apropos'.")
176
6be19e60
MR
177(defvar cus-test-tested-variables nil
178 "List of options tested by last call of `cus-test-apropos'.")
179
592cd48b
MR
180(defvar cus-test-deps-errors nil
181 "List of require/load problems found by `cus-test-deps'.")
182
6be19e60
MR
183(defvar cus-test-deps-required nil
184 "List of dependencies required by `cus-test-deps'.
185Only unloaded features will be require'd.")
186
bd9aba20 187(defvar cus-test-deps-loaded nil
6be19e60 188 "List of dependencies loaded by `cus-test-deps'.")
592cd48b
MR
189
190(defvar cus-test-libs-errors nil
6be19e60 191 "List of load problems found by `cus-test-load-libs' or `cus-test-libs'.")
592cd48b
MR
192
193(defvar cus-test-libs-loaded nil
6be19e60 194 "List of files loaded by `cus-test-load-libs' or `cus-test-libs'.")
592cd48b 195
6be19e60
MR
196;; I haven't understood this :get stuff. The symbols with a
197;; custom-get property are stored here.
bd08d86a 198(defvar cus-test-vars-with-custom-get nil
82e74860
MR
199 "Set by `cus-test-apropos' to a list of options with :get property.")
200
bd08d86a
MR
201(defvar cus-test-vars-with-changed-state nil
202 "Set by `cus-test-apropos' to a list of options with state 'changed.")
203
82e74860
MR
204(defun cus-test-apropos (regexp)
205 "Check the options matching REGEXP.
206The detected problematic options are stored in `cus-test-errors'."
207 (interactive "sVariable regexp: ")
208 (setq cus-test-errors nil)
209 (setq cus-test-tested-variables nil)
6be19e60 210 (mapc
82e74860
MR
211 (lambda (symbol)
212 (push symbol cus-test-tested-variables)
6be19e60
MR
213 ;; Be verbose in case we hang.
214 (message "Cus Test running...%s %s"
215 (length cus-test-tested-variables) symbol)
82e74860
MR
216 (condition-case alpha
217 (let* ((type (custom-variable-type symbol))
218 (conv (widget-convert type))
82e74860
MR
219 (get (or (get symbol 'custom-get) 'default-value))
220 values
221 mismatch)
222 (when (default-boundp symbol)
592cd48b
MR
223 (push (funcall get symbol) values)
224 (push (eval (car (get symbol 'standard-value))) values))
82e74860 225 (if (boundp symbol)
592cd48b 226 (push (symbol-value symbol) values))
82e74860 227 ;; That does not work.
592cd48b 228 ;; (push (widget-get conv :value) values)
82e74860
MR
229
230 ;; Check the values
6be19e60
MR
231 (mapc (lambda (value)
232 (unless (widget-apply conv :match value)
233 (setq mismatch 'mismatch)))
234 values)
82e74860 235
592cd48b
MR
236 ;; Store symbols with a custom-get property.
237 (when (get symbol 'custom-get)
2a7e0e41 238 (add-to-list 'cus-test-vars-with-custom-get symbol))
592cd48b 239
82e74860 240 ;; Changed outside the customize buffer?
bd08d86a
MR
241 ;; This routine is not very much tested.
242 (let ((c-value
243 (or (get symbol 'customized-value)
244 (get symbol 'saved-value)
245 (get symbol 'standard-value))))
246 (and (consp c-value)
247 (boundp symbol)
248 (not (equal (eval (car c-value)) (symbol-value symbol)))
2a7e0e41 249 (add-to-list 'cus-test-vars-with-changed-state symbol)))
82e74860
MR
250
251 (if mismatch
592cd48b 252 (push symbol cus-test-errors)))
82e74860
MR
253
254 (error
592cd48b
MR
255 (push symbol cus-test-errors)
256 (message "Error for %s: %s" symbol alpha))))
82e74860 257 (cus-test-get-options regexp))
6be19e60 258 (message "%s options tested"
82e74860 259 (length cus-test-tested-variables))
592cd48b 260 (cus-test-errors-display))
82e74860
MR
261
262(defun cus-test-get-options (regexp)
263 "Return a list of custom options matching REGEXP."
264 (let (found)
265 (mapatoms
266 (lambda (symbol)
267 (and
268 (or
269 ;; (user-variable-p symbol)
270 (get symbol 'standard-value)
271 ;; (get symbol 'saved-value)
272 (get symbol 'custom-type))
273 (string-match regexp (symbol-name symbol))
6be19e60 274 (not (member symbol cus-test-skip-list))
82e74860
MR
275 (push symbol found))))
276 found))
277
278(defun cus-test-errors-display ()
279 "Report about the errors found by cus-test."
280 (with-output-to-temp-buffer "*cus-test-errors*"
281 (set-buffer standard-output)
282 (insert (format "Cus Test tested %s variables.\
283 See `cus-test-tested-variables'.\n\n"
284 (length cus-test-tested-variables)))
6be19e60
MR
285 (if (not cus-test-errors)
286 (insert "No errors found by cus-test.")
287 (insert "The following variables seem to have problems:\n\n")
288 (dolist (E cus-test-errors)
289 (insert (symbol-name E) "\n")))))
290
291(defun cus-test-load-custom-loads ()
82e74860
MR
292 "Call `custom-load-symbol' on all atoms."
293 (interactive)
294 (mapatoms 'custom-load-symbol)
bd08d86a 295 (run-hooks 'cus-test-after-load-libs-hook))
82e74860 296
6be19e60
MR
297(defun cus-test-load-libs ()
298 "Load the libraries with autoloads.
299Don't load libraries in `cus-test-noloads'."
300 (interactive)
301 (setq cus-test-libs-errors nil)
302 (setq cus-test-libs-loaded nil)
303 (mapc
304 (lambda (file)
305 (condition-case alpha
306 (unless (member file cus-test-noloads)
307 (load file)
308 (push file cus-test-libs-loaded))
309 (error
310 (push (cons file alpha) cus-test-libs-errors)
311 (message "Error for %s: %s" file alpha))))
312 (cus-test-get-autoload-deps))
313 (message "%s libraries loaded successfully"
314 (length cus-test-libs-loaded))
315 (if (not cus-test-libs-errors)
316 (message "No load problems encountered")
317 (message "The following load problems appeared:")
318 (cus-test-message cus-test-libs-errors))
319 (run-hooks 'cus-test-after-load-libs-hook))
320
321(defun cus-test-get-autoload-deps ()
322 "Return the list of libraries with autoloads."
323 (with-temp-buffer
324 (insert-file-contents (locate-library "loaddefs"))
325 ;; This is from `customize-option'.
326 (let (deps file)
327 (while
328 (search-forward "\n;;; Generated autoloads from " nil t)
329 (goto-char (match-end 0))
330 (setq file (buffer-substring (point)
331 (progn (end-of-line) (point))))
332 (setq file (file-name-nondirectory file))
333 (string-match "\\.el\\'" file)
334 (setq file (substring file 0 (match-beginning 0)))
335 (setq deps (nconc deps (list file))))
336 deps)))
337
338(defun cus-test-message (list)
339 "Print the members of LIST line by line."
340 (dolist (m list) (message "%s" m)))
341
342\f
592cd48b
MR
343;;; The routines for batch mode:
344
6be19e60 345(defun cus-test-opts ()
592cd48b
MR
346 "Test custom options.
347This function is suitable for batch mode. E.g., invoke
348
349 src/emacs -batch -l admin/cus-test.el -f cus-test-opts
350
351in the emacs source directory."
352 (interactive)
bf7a63e1
MR
353 (message "Running %s" 'cus-test-load-libs)
354 (cus-test-load-libs)
592cd48b
MR
355 (message "Running %s" 'cus-test-load-custom-loads)
356 (cus-test-load-custom-loads)
357 (message "Running %s" 'cus-test-apropos)
358 (cus-test-apropos "")
6be19e60
MR
359 (if (not cus-test-errors)
360 (message "No problems found")
361 (message "The following options might have problems:")
362 (cus-test-message cus-test-errors)))
592cd48b 363
6be19e60 364(defun cus-test-deps ()
592cd48b
MR
365 "Run a verbose version of `custom-load-symbol' on all atoms.
366This function is suitable for batch mode. E.g., invoke
367
368 src/emacs -batch -l admin/cus-test.el -f cus-test-deps
369
370in the emacs source directory."
371 (interactive)
372 (setq cus-test-deps-errors nil)
6be19e60 373 (setq cus-test-deps-required nil)
bd9aba20 374 (setq cus-test-deps-loaded nil)
592cd48b
MR
375 (mapatoms
376 ;; This code is mainly from `custom-load-symbol'.
377 (lambda (symbol)
378 (unless custom-load-recursion
379 (let ((custom-load-recursion t))
380 (dolist (load (get symbol 'custom-loads))
381 (cond
382 ((symbolp load)
383 ;; (condition-case nil (require load) (error nil))
384 (condition-case alpha
6be19e60 385 (unless (featurep load)
bd9aba20 386 (require load)
6be19e60 387 (push (list symbol load) cus-test-deps-required))
592cd48b
MR
388 (error
389 (push (list symbol load alpha) cus-test-deps-errors)
6be19e60
MR
390 (message "Require problem: %s %s %s" symbol load alpha))))
391 ((equal load "loaddefs")
392 (push
393 (message "Symbol %s has loaddefs as custom dependency" symbol)
394 cus-test-deps-errors))
592cd48b
MR
395 ;; This is subsumed by the test below, but it's much
396 ;; faster.
397 ((assoc load load-history))
398 ;; This was just
399 ;; (assoc (locate-library load) load-history)
400 ;; but has been optimized not to load locate-library
401 ;; if not necessary.
402 ((let ((regexp (concat "\\(\\`\\|/\\)" (regexp-quote load)
403 "\\(\\'\\|\\.\\)"))
404 (found nil))
405 (dolist (loaded load-history)
406 (and (stringp (car loaded))
407 (string-match regexp (car loaded))
408 (setq found t)))
409 found))
410 ;; Without this, we would load cus-edit recursively.
411 ;; We are still loading it when we call this,
412 ;; and it is not in load-history yet.
413 ((equal load "cus-edit"))
bf7a63e1
MR
414 ;; This would ignore load problems with files in
415 ;; lisp/term/
416 ;; ((locate-library (concat term-file-prefix load)))
592cd48b
MR
417 (t
418 ;; (condition-case nil (load load) (error nil))
419 (condition-case alpha
bd9aba20
MR
420 (progn
421 (load load)
422 (push (list symbol load) cus-test-deps-loaded))
592cd48b
MR
423 (error
424 (push (list symbol load alpha) cus-test-deps-errors)
6be19e60 425 (message "Load Problem: %s %s %s" symbol load alpha))))
592cd48b 426 ))))))
6be19e60
MR
427 (message "%s features required"
428 (length cus-test-deps-required))
429 (message "%s files loaded"
bd9aba20 430 (length cus-test-deps-loaded))
6be19e60
MR
431 (if (not cus-test-deps-errors)
432 (message "No load problems encountered")
433 (message "The following load problems appeared:")
434 (cus-test-message cus-test-deps-errors))
592cd48b
MR
435 (run-hooks 'cus-test-after-load-libs-hook))
436
437(defun cus-test-libs ()
6be19e60 438 "Load the libraries with autoloads in separate processes.
592cd48b
MR
439This function is useful to detect load problems of libraries.
440It is suitable for batch mode. E.g., invoke
441
442 src/emacs -batch -l admin/cus-test.el -f cus-test-libs
443
444in the emacs source directory."
82e74860 445 (interactive)
6be19e60
MR
446 (with-temp-buffer
447 (setq cus-test-libs-errors nil)
448 (setq cus-test-libs-loaded nil)
449 (cd source-directory)
450 (if (not (file-executable-p "src/emacs"))
451 (error "No Emacs executable in %ssrc" default-directory))
452 (mapc
453 (lambda (file)
454 (condition-case alpha
455 (let (fn cmd status)
456 (setq fn (locate-library file))
457 (if (not fn)
458 (error "Library %s not found" file))
459 (setq cmd (concat "src/emacs -batch -l " fn))
460 (setq status (call-process shell-file-name nil nil nil
461 shell-command-switch cmd))
e170d16c 462 (if (equal status 0)
6be19e60
MR
463 (message "%s" file)
464 (error "%s" status))
465 (push file cus-test-libs-loaded))
466 (error
467 (push (cons file alpha) cus-test-libs-errors)
468 (message "Error for %s: %s" file alpha))))
469 (cus-test-get-autoload-deps))
470 (message "Default Directory: %s" default-directory)
471 (message "%s libraries had no load errors"
472 (length cus-test-libs-loaded))
473 (if (not cus-test-libs-errors)
474 (message "No load problems encountered")
475 (message "The following load problems appeared:")
476 (cus-test-message cus-test-libs-errors))
477 (run-hooks 'cus-test-after-load-libs-hook)))
82e74860 478
82e74860
MR
479(provide 'cus-test)
480
481;;; cus-test.el ends here