cus-test.el 18.2 KB
Newer Older
1
;;; cus-test.el --- tests for custom types and load problems
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1998, 2000, 2002-2020 Free Software Foundation, Inc.
4

5
;; Author: Markus Rost <rost@math.uni-bielefeld.de>
6 7 8 9 10
;; Created: 13 Sep 1998
;; Keywords: maint

;; This file is part of GNU Emacs.

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 14
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
15 16 17 18 19 20 21

;; GNU Emacs 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
22
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
23 24 25

;;; Commentary:

26 27 28
;; This file provides simple tests to detect custom options with
;; incorrect customization types and load problems for custom and
;; autoload dependencies.
29
;;
30 31
;; The basic tests can be run in batch mode.  Invoke them with
;;
Glenn Morris's avatar
Glenn Morris committed
32
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-opts [all]
33 34 35
;;
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-deps
;;
Glenn Morris's avatar
Glenn Morris committed
36
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-libs [all]
37
;;
38 39
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-noloads
;;
40 41 42
;; in the emacs source directory.
;;
;; For interactive use: Load this file.  Then
43 44 45 46 47 48 49 50 51 52 53 54 55 56
;;
;;    M-x cus-test-apropos REGEXP RET
;;
;; checks the options matching REGEXP.	In particular
;;
;;    M-x cus-test-apropos RET
;;
;; checks all options.  The detected options are stored in the
;; variable `cus-test-errors'.
;;
;; Only those options are checked which have been already loaded.
;; Therefore `cus-test-apropos' is more efficient after loading many
;; libraries.
;;
57 58 59
;;    M-x cus-test-load-custom-loads
;;
;; loads all (!) custom dependencies and
60
;;
61 62 63
;;    M-x cus-test-load-libs
;;
;; loads all (!) libraries with autoloads.
64 65
;;
;; Options with a custom-get property, usually defined by a :get
66 67 68 69 70 71 72 73 74 75 76 77
;; declaration, are stored in the variable
;;
;; `cus-test-vars-with-custom-get'
;;
;; Options with a state of 'changed ("changed outside the customize
;; buffer") are stored in the variable
;;
;; `cus-test-vars-with-changed-state'
;;
;; These lists are prepared just in case one wants to investigate
;; those options further.
;;
78
;; The command `cus-test-opts' tests many (all?) custom options.
79
;;
80 81
;; The command `cus-test-deps' is like `cus-test-load-custom-loads'
;; but reports about load errors.
Markus Rost's avatar
Markus Rost committed
82
;;
83 84
;; The command `cus-test-libs' runs for all libraries with autoloads
;; separate emacs processes of the form "emacs -batch -l LIB".
Markus Rost's avatar
Markus Rost committed
85
;;
86 87 88
;; The command `cus-test-noloads' returns a list of variables which
;; are somewhere declared as custom options, but not loaded by
;; `custom-load-symbol'.
89

90

Markus Rost's avatar
Markus Rost committed
91
;;; Code:
92

93
;;; Workarounds.  For a smooth run and to avoid some side effects.
94

95
(defvar cus-test-after-load-libs-hook nil
96 97 98 99
  "Used to switch off undesired side effects of loading libraries.")

(defvar cus-test-skip-list nil
  "List of variables to disregard by `cus-test-apropos'.")
100

Glenn Morris's avatar
Glenn Morris committed
101 102 103 104 105 106 107 108
(defvar cus-test-libs-noloads
  ;; Loading dunnet in batch mode leads to a Dead end.
  ;; blessmail writes a file.
  ;; characters cannot be loaded twice ("Category `a' is already defined").
  '("play/dunnet.el" "emulation/edt-mapper.el"
    "loadup.el" "mail/blessmail.el" "international/characters.el"
    "cedet/ede/loaddefs.el" "cedet/semantic/loaddefs.el"
    "net/tramp-loaddefs.el")
Glenn Morris's avatar
Glenn Morris committed
109 110
  "List of files not to load by `cus-test-load-libs'.
Names should be as they appear in loaddefs.el.")
111 112 113

;; This avoids a hang of `cus-test-apropos' in 21.2.
;; (add-to-list 'cus-test-skip-list 'sh-alias-alist)
114

Glenn Morris's avatar
Glenn Morris committed
115 116 117
(or noninteractive
    ;; Never Viperize.
    (setq viper-mode nil))
118

Markus Rost's avatar
Markus Rost committed
119
;; Don't create a file `save-place-file'.
120 121 122
(eval-after-load "saveplace"
  '(remove-hook 'kill-emacs-hook 'save-place-kill-emacs-hook))

Markus Rost's avatar
Markus Rost committed
123
;; Don't create a file `abbrev-file-name'.
124 125 126 127 128 129
(setq save-abbrevs nil)

;; Avoid compile logs from adviced functions.
(eval-after-load "bytecomp"
  '(setq ad-default-compilation-action 'never))

130 131 132

;;; Main code:

133 134 135
;; We want to log all messages.
(setq message-log-max t)

Markus Rost's avatar
Markus Rost committed
136 137 138
(require 'cus-edit)
(require 'cus-load)

139 140 141
(defvar cus-test-errors nil
  "List of problematic variables found by `cus-test-apropos'.")

142 143 144
(defvar cus-test-tested-variables nil
  "List of options tested by last call of `cus-test-apropos'.")

145 146 147 148 149 150 151 152
;; I haven't understood this :get stuff.  The symbols with a
;; custom-get property are stored here.
(defvar cus-test-vars-with-custom-get nil
  "Set by `cus-test-apropos' to a list of options with :get property.")

(defvar cus-test-vars-with-changed-state nil
  "Set by `cus-test-apropos' to a list of options with state 'changed.")

Markus Rost's avatar
Markus Rost committed
153 154 155
(defvar cus-test-deps-errors nil
  "List of require/load problems found by `cus-test-deps'.")

156 157 158 159
(defvar cus-test-deps-required nil
  "List of dependencies required by `cus-test-deps'.
Only unloaded features will be require'd.")

Markus Rost's avatar
Markus Rost committed
160
(defvar cus-test-deps-loaded nil
161
  "List of dependencies loaded by `cus-test-deps'.")
Markus Rost's avatar
Markus Rost committed
162 163

(defvar cus-test-libs-errors nil
164
  "List of load problems found by `cus-test-load-libs' or `cus-test-libs'.")
Markus Rost's avatar
Markus Rost committed
165 166

(defvar cus-test-libs-loaded nil
167
  "List of files loaded by `cus-test-load-libs' or `cus-test-libs'.")
Markus Rost's avatar
Markus Rost committed
168

169 170 171
(defvar cus-test-vars-not-cus-loaded nil
  "A list of options not loaded by `custom-load-symbol'.
Set by `cus-test-noloads'.")
172

173 174
;; (defvar cus-test-vars-cus-loaded nil
;;   "A list of options loaded by `custom-load-symbol'.")
175

176 177 178 179 180 181
(defun cus-test-apropos (regexp)
  "Check the options matching REGEXP.
The detected problematic options are stored in `cus-test-errors'."
  (interactive "sVariable regexp: ")
  (setq cus-test-errors nil)
  (setq cus-test-tested-variables nil)
182
  (mapc
183 184
   (lambda (symbol)
     (push symbol cus-test-tested-variables)
185 186 187
     ;; Be verbose in case we hang.
     (message "Cus Test running...%s %s"
	      (length cus-test-tested-variables) symbol)
188
     (condition-case alpha
189 190 191
	 ;; FIXME This defaults to 'sexp if no type was specified.
	 ;; Always report such instances as a type mismatch.
	 ;; Currently abusing cusver-scan to do that.
192 193 194 195 196 197
	 (let* ((type (custom-variable-type symbol))
		(conv (widget-convert type))
		(get (or (get symbol 'custom-get) 'default-value))
		values
		mismatch)
	   (when (default-boundp symbol)
Markus Rost's avatar
Markus Rost committed
198 199
	     (push (funcall get symbol) values)
	     (push (eval (car (get symbol 'standard-value))) values))
200
	   (if (boundp symbol)
Markus Rost's avatar
Markus Rost committed
201
	       (push (symbol-value symbol) values))
202
	   ;; That does not work.
Markus Rost's avatar
Markus Rost committed
203
	   ;; (push (widget-get conv :value) values)
204 205

	   ;; Check the values
206
	   (mapc (lambda (value)
Glenn Morris's avatar
Glenn Morris committed
207 208
		   ;; TODO for booleans, check for values that can be
		   ;; evaluated and are not t or nil.  Usually a bug.
209 210 211
		   (unless (widget-apply conv :match value)
		     (setq mismatch 'mismatch)))
		 values)
212

Markus Rost's avatar
Markus Rost committed
213 214
	   ;; Store symbols with a custom-get property.
	   (when (get symbol 'custom-get)
Markus Rost's avatar
Markus Rost committed
215
	     (add-to-list 'cus-test-vars-with-custom-get symbol))
Markus Rost's avatar
Markus Rost committed
216

217
	   ;; Changed outside the customize buffer?
218 219 220 221 222 223 224 225
	   ;; This routine is not very much tested.
	   (let ((c-value
		  (or (get symbol 'customized-value)
		      (get symbol 'saved-value)
		      (get symbol 'standard-value))))
	     (and (consp c-value)
		  (boundp symbol)
		  (not (equal (eval (car c-value)) (symbol-value symbol)))
Markus Rost's avatar
Markus Rost committed
226
		  (add-to-list 'cus-test-vars-with-changed-state symbol)))
227 228

	   (if mismatch
Markus Rost's avatar
Markus Rost committed
229
	       (push symbol cus-test-errors)))
230 231

       (error
Markus Rost's avatar
Markus Rost committed
232 233
	(push symbol cus-test-errors)
	(message "Error for %s: %s" symbol alpha))))
234
   (cus-test-get-options regexp))
235
  (message "%s options tested"
236
	   (length cus-test-tested-variables))
Markus Rost's avatar
Markus Rost committed
237
  (cus-test-errors-display))
238

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
(defun cus-test-cus-load-groups (&optional cus-load)
  "Return a list of current custom groups.
If CUS-LOAD is non-nil, include groups from cus-load.el."
  (append (mapcar 'cdr custom-current-group-alist)
	  (if cus-load
	      (with-temp-buffer
		(insert-file-contents (locate-library "cus-load.el"))
		(search-forward "(put '")
		(beginning-of-line)
		(let (res)
		  (while (and (looking-at "^(put '\\(\\S-+\\)")
			      (zerop (forward-line 1)))
		    (push (intern (match-string 1)) res))
		  res)))))

(defun cus-test-get-options (regexp &optional group)
  "Return a list of custom options matching REGEXP.
If GROUP is non-nil, return groups rather than options.
If GROUP is `cus-load', include groups listed in cus-loads as well as
currently defined groups."
  (let ((groups (if group (cus-test-cus-load-groups (eq group 'cus-load))))
	found)
261 262 263
    (mapatoms
     (lambda (symbol)
       (and
264 265 266 267 268 269 270
	(if group
	    (memq symbol groups)
	  (or
	   ;; (user-variable-p symbol)
	   (get symbol 'standard-value)
	   ;; (get symbol 'saved-value)
	   (get symbol 'custom-type)))
271
	(string-match regexp (symbol-name symbol))
272
	(not (member symbol cus-test-skip-list))
273 274 275 276 277 278 279 280 281 282
	(push symbol found))))
    found))

(defun cus-test-errors-display ()
  "Report about the errors found by cus-test."
  (with-output-to-temp-buffer "*cus-test-errors*"
    (set-buffer standard-output)
    (insert (format "Cus Test tested %s variables.\
  See `cus-test-tested-variables'.\n\n"
		    (length cus-test-tested-variables)))
283 284 285
    (if (not cus-test-errors)
	(insert "No errors found by cus-test.")
      (insert "The following variables seem to have problems:\n\n")
286 287
      (dolist (e cus-test-errors)
	(insert (symbol-name e) "\n")))))
288 289

(defun cus-test-load-custom-loads ()
290 291
  "Call `custom-load-symbol' on all atoms."
  (interactive)
Glenn Morris's avatar
Glenn Morris committed
292
  (if noninteractive (let (noninteractive) (require 'dunnet)))
293
  (mapatoms 'custom-load-symbol)
294
  (run-hooks 'cus-test-after-load-libs-hook))
295

Glenn Morris's avatar
Glenn Morris committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309
(defmacro cus-test-load-1 (&rest body)
  `(progn
     (setq cus-test-libs-errors nil
	   cus-test-libs-loaded nil)
     ,@body
     (message "%s libraries loaded successfully"
	      (length cus-test-libs-loaded))
     (if (not cus-test-libs-errors)
	 (message "No load problems encountered")
       (message "The following load problems appeared:")
       (cus-test-message cus-test-libs-errors))
     (run-hooks 'cus-test-after-load-libs-hook)))

;; This is just cus-test-libs, but loading in the current Emacs process.
Glenn Morris's avatar
Glenn Morris committed
310
(defun cus-test-load-libs (&optional more)
311
  "Load the libraries with autoloads.
Glenn Morris's avatar
Glenn Morris committed
312 313 314
Don't load libraries in `cus-test-libs-noloads'.
If optional argument MORE is \"defcustom\", load all files with defcustoms.
If it is \"all\", load all Lisp files."
315
  (interactive)
Glenn Morris's avatar
Glenn Morris committed
316 317 318 319 320 321 322 323 324 325 326
  (cus-test-load-1
   (let ((lispdir (file-name-directory (locate-library "loaddefs"))))
     (mapc
      (lambda (file)
	(condition-case alpha
	    (unless (member file cus-test-libs-noloads)
	      (load (file-name-sans-extension (expand-file-name file lispdir)))
	      (push file cus-test-libs-loaded))
	  (error
	   (push (cons file alpha) cus-test-libs-errors)
	   (message "Error for %s: %s" file alpha))))
Glenn Morris's avatar
Glenn Morris committed
327 328 329
      (if more
	  (cus-test-get-lisp-files (equal more "all"))
	(cus-test-get-autoload-deps))))))
330 331

(defun cus-test-get-autoload-deps ()
Glenn Morris's avatar
Glenn Morris committed
332
  "Return the list of files with autoloads."
333 334
  (with-temp-buffer
    (insert-file-contents (locate-library "loaddefs"))
Glenn Morris's avatar
Glenn Morris committed
335 336 337 338
    (let (files)
      (while (search-forward "\n;;; Generated autoloads from " nil t)
	(push (buffer-substring (match-end 0) (line-end-position)) files))
      files)))
339

340 341
(defun cus-test-get-lisp-files (&optional all)
  "Return list of all Lisp files with defcustoms.
Glenn Morris's avatar
Glenn Morris committed
342
Optional argument ALL non-nil means list all (non-obsolete) Lisp files."
343 344 345 346 347 348 349
  (let ((default-directory (expand-file-name "lisp/" source-directory))
	(msg "Finding files..."))
    (message "%s" msg)
    (prog1
	;; Hack to remove leading "./".
	(mapcar (lambda (e) (substring e 2))
		(apply 'process-lines find-program
Glenn Morris's avatar
Glenn Morris committed
350
		       "-name" "obsolete" "-prune" "-o"
Glenn Morris's avatar
Glenn Morris committed
351
		       "-name" "[^.]*.el" ; ignore .dir-locals.el
Glenn Morris's avatar
Glenn Morris committed
352 353
		       (if all
			   '("-print")
354 355 356 357
			 (list "-exec" grep-program
			       "-l" "^[ \t]*(defcustom" "{}" "+"))))
      (message "%sdone" msg))))

358 359 360 361 362
(defun cus-test-message (list)
  "Print the members of LIST line by line."
  (dolist (m list) (message "%s" m)))


Markus Rost's avatar
Markus Rost committed
363 364
;;; The routines for batch mode:

Glenn Morris's avatar
Glenn Morris committed
365
(defun cus-test-opts (&optional all)
Markus Rost's avatar
Markus Rost committed
366 367 368 369 370
  "Test custom options.
This function is suitable for batch mode.  E.g., invoke

  src/emacs -batch -l admin/cus-test.el -f cus-test-opts

Glenn Morris's avatar
Glenn Morris committed
371 372 373
in the Emacs source directory.
Normally only tests options belonging to files in loaddefs.el.
If optional argument ALL is non-nil, test all files with defcustoms."
Markus Rost's avatar
Markus Rost committed
374
  (interactive)
Glenn Morris's avatar
Glenn Morris committed
375 376 377
  (and noninteractive
       command-line-args-left
       (setq all (pop command-line-args-left)))
378
  (message "Running %s" 'cus-test-load-libs)
Glenn Morris's avatar
Glenn Morris committed
379
  (cus-test-load-libs (if all "defcustom"))
Markus Rost's avatar
Markus Rost committed
380 381 382 383
  (message "Running %s" 'cus-test-load-custom-loads)
  (cus-test-load-custom-loads)
  (message "Running %s" 'cus-test-apropos)
  (cus-test-apropos "")
384 385 386 387
  (if (not cus-test-errors)
      (message "No problems found")
    (message "The following options might have problems:")
    (cus-test-message cus-test-errors)))
Markus Rost's avatar
Markus Rost committed
388

389
(defun cus-test-deps ()
Markus Rost's avatar
Markus Rost committed
390 391 392 393 394
  "Run a verbose version of `custom-load-symbol' on all atoms.
This function is suitable for batch mode.  E.g., invoke

  src/emacs -batch -l admin/cus-test.el -f cus-test-deps

395
in the Emacs source directory."
Markus Rost's avatar
Markus Rost committed
396 397
  (interactive)
  (setq cus-test-deps-errors nil)
398
  (setq cus-test-deps-required nil)
Markus Rost's avatar
Markus Rost committed
399
  (setq cus-test-deps-loaded nil)
Markus Rost's avatar
Markus Rost committed
400 401 402
  (mapatoms
   ;; This code is mainly from `custom-load-symbol'.
   (lambda (symbol)
403 404 405 406 407 408
     (let ((custom-load-recursion t))
       (dolist (load (get symbol 'custom-loads))
	 (cond
	  ((symbolp load)
	   ;; (condition-case nil (require load) (error nil))
	   (condition-case alpha
Glenn Morris's avatar
Glenn Morris committed
409 410
	       (unless (or (featurep load)
			   (and noninteractive (eq load 'dunnet)))
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
		 (require load)
		 (push (list symbol load) cus-test-deps-required))
	     (error
	      (push (list symbol load alpha) cus-test-deps-errors)
	      (message "Require problem: %s %s %s" symbol load alpha))))
	  ((equal load "loaddefs")
	   (push
	    (message "Symbol %s has loaddefs as custom dependency" symbol)
	    cus-test-deps-errors))
	  ;; This is subsumed by the test below, but it's much
	  ;; faster.
	  ((assoc load load-history))
	  ;; This was just
	  ;; (assoc (locate-library load) load-history)
	  ;; but has been optimized not to load locate-library
	  ;; if not necessary.
	  ((let ((regexp (concat "\\(\\`\\|/\\)" (regexp-quote load)
				 "\\(\\'\\|\\.\\)"))
		 (found nil))
	     (dolist (loaded load-history)
	       (and (stringp (car loaded))
		    (string-match regexp (car loaded))
		    (setq found t)))
	     found))
	  ;; Without this, we would load cus-edit recursively.
	  ;; We are still loading it when we call this,
	  ;; and it is not in load-history yet.
	  ((equal load "cus-edit"))
	  ;; This would ignore load problems with files in
	  ;; lisp/term/
	  ;; ((locate-library (concat term-file-prefix load)))
	  (t
	   ;; (condition-case nil (load load) (error nil))
	   (condition-case alpha
	       (progn
		 (load load)
		 (push (list symbol load) cus-test-deps-loaded))
	     (error
	      (push (list symbol load alpha) cus-test-deps-errors)
	      (message "Load Problem: %s %s %s" symbol load alpha))))
	  )))))
452 453 454
  (message "%s features required"
	   (length cus-test-deps-required))
  (message "%s files loaded"
Markus Rost's avatar
Markus Rost committed
455
	   (length cus-test-deps-loaded))
456 457 458 459
  (if (not cus-test-deps-errors)
      (message "No load problems encountered")
    (message "The following load problems appeared:")
    (cus-test-message cus-test-deps-errors))
Markus Rost's avatar
Markus Rost committed
460 461
  (run-hooks 'cus-test-after-load-libs-hook))

462
(defun cus-test-libs (&optional more)
463
  "Load the libraries with autoloads in separate processes.
Markus Rost's avatar
Markus Rost committed
464 465 466
This function is useful to detect load problems of libraries.
It is suitable for batch mode.  E.g., invoke

Glenn Morris's avatar
Glenn Morris committed
467
  ./src/emacs -batch -l admin/cus-test.el -f cus-test-libs
Markus Rost's avatar
Markus Rost committed
468

469 470 471 472
in the Emacs source directory.

If optional argument MORE is \"defcustom\", load all files with defcustoms.
If it is \"all\", load all Lisp files."
473
  (interactive)
474 475 476
  (and noninteractive
       command-line-args-left
       (setq more (pop command-line-args-left)))
Glenn Morris's avatar
Glenn Morris committed
477
  (cus-test-load-1
Glenn Morris's avatar
Glenn Morris committed
478 479 480
   (let* ((default-directory source-directory)
	  (emacs (expand-file-name "src/emacs"))
	  skipped)
Glenn Morris's avatar
Glenn Morris committed
481
     (or (file-executable-p emacs)
Glenn Morris's avatar
Glenn Morris committed
482
	 (error "No such executable `%s'" emacs))
Glenn Morris's avatar
Glenn Morris committed
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
     (mapc
      (lambda (file)
	(if (member file cus-test-libs-noloads)
	    (push file skipped)
	  (condition-case alpha
	      (let* ((fn (expand-file-name file "lisp/"))
		     (elc (concat fn "c"))
		     status)
		(if (file-readable-p elc) ; load compiled if present (faster)
		    (setq fn elc)
		  (or (file-readable-p fn)
		      (error "Library %s not found" file)))
		(if (equal 0 (setq status (call-process emacs nil nil nil
							"-batch" "-l" fn)))
		    (message "%s" file)
		  (error "%s" status))
		(push file cus-test-libs-loaded))
	    (error
	     (push (cons file alpha) cus-test-libs-errors)
	     (message "Error for %s: %s" file alpha)))))
503 504 505
      (if more
	  (cus-test-get-lisp-files (equal more "all"))
	(cus-test-get-autoload-deps)))
Glenn Morris's avatar
Glenn Morris committed
506 507 508 509
     (message "Default directory: %s" default-directory)
     (when skipped
       (message "The following libraries were skipped:")
       (cus-test-message skipped)))))
510

511 512 513 514 515 516 517 518 519
(defun cus-test-noloads ()
  "Find custom options not loaded by `custom-load-symbol'.
Calling this function after `cus-test-load-libs' is not meaningful.
It is suitable for batch mode.  E.g., invoke

  src/emacs -batch -l admin/cus-test.el -f cus-test-noloads

in the Emacs source directory."
  (interactive)
520 521
  (let ((groups-loaded (cus-test-get-options "" 'cus-load))
	cus-loaded groups-not-loaded)
522 523 524

    (message "Running %s" 'cus-test-load-custom-loads)
    (cus-test-load-custom-loads)
525
    (setq cus-loaded (cus-test-get-options ""))
526 527

    (message "Running %s" 'cus-test-load-libs)
Glenn Morris's avatar
Glenn Morris committed
528
    (cus-test-load-libs "all")
529 530
    (setq cus-test-vars-not-cus-loaded (cus-test-get-options "")
	  groups-not-loaded (cus-test-get-options "" t))
531 532 533 534 535 536 537 538 539

    (dolist (o cus-loaded)
      (setq cus-test-vars-not-cus-loaded
	    (delete o cus-test-vars-not-cus-loaded)))

    (if (not cus-test-vars-not-cus-loaded)
	(message "No options not loaded by custom-load-symbol found")
      (message "The following options were not loaded by custom-load-symbol:")
      (cus-test-message
540 541 542 543 544 545 546 547 548
       (sort cus-test-vars-not-cus-loaded 'string<)))

    (dolist (o groups-loaded)
      (setq groups-not-loaded (delete o groups-not-loaded)))

    (if (not groups-not-loaded)
	(message "No groups not in cus-load.el found")
      (message "The following groups are not in cus-load.el:")
      (cus-test-message (sort groups-not-loaded 'string<)))))
549

550 551 552
(provide 'cus-test)

;;; cus-test.el ends here