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-2019 Free Software Foundation, Inc.
4 5 6 7 8 9 10 11

;; Author: Markus Rost <markus.rost@mathematik.uni-regensburg.de>
;; Maintainer: Markus Rost <rost@math.ohio-state.edu>
;; Created: 13 Sep 1998
;; Keywords: maint

;; This file is part of GNU Emacs.

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

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

;;; Commentary:

27 28 29
;; This file provides simple tests to detect custom options with
;; incorrect customization types and load problems for custom and
;; autoload dependencies.
30
;;
31 32
;; The basic tests can be run in batch mode.  Invoke them with
;;
Glenn Morris's avatar
Glenn Morris committed
33
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-opts [all]
34 35 36
;;
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-deps
;;
Glenn Morris's avatar
Glenn Morris committed
37
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-libs [all]
38
;;
39 40
;;   src/emacs -batch -l admin/cus-test.el -f cus-test-noloads
;;
41 42 43
;; in the emacs source directory.
;;
;; For interactive use: Load this file.  Then
44 45 46 47 48 49 50 51 52 53 54 55 56 57
;;
;;    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.
;;
58 59 60
;;    M-x cus-test-load-custom-loads
;;
;; loads all (!) custom dependencies and
61
;;
62 63 64
;;    M-x cus-test-load-libs
;;
;; loads all (!) libraries with autoloads.
65 66
;;
;; Options with a custom-get property, usually defined by a :get
67 68 69 70 71 72 73 74 75 76 77 78
;; 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.
;;
79
;; The command `cus-test-opts' tests many (all?) custom options.
80
;;
81 82
;; The command `cus-test-deps' is like `cus-test-load-custom-loads'
;; but reports about load errors.
Markus Rost's avatar
Markus Rost committed
83
;;
84 85
;; 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
86
;;
87 88 89
;; The command `cus-test-noloads' returns a list of variables which
;; are somewhere declared as custom options, but not loaded by
;; `custom-load-symbol'.
90

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

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

96
(defvar cus-test-after-load-libs-hook nil
97 98 99 100
  "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'.")
101

Glenn Morris's avatar
Glenn Morris committed
102 103 104 105 106 107 108 109
(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
110 111
  "List of files not to load by `cus-test-load-libs'.
Names should be as they appear in loaddefs.el.")
112 113 114

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

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

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

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

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

131 132 133

;;; Main code:

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

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

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

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

146 147 148 149 150 151 152 153
;; 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
154 155 156
(defvar cus-test-deps-errors nil
  "List of require/load problems found by `cus-test-deps'.")

157 158 159 160
(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
161
(defvar cus-test-deps-loaded nil
162
  "List of dependencies loaded by `cus-test-deps'.")
Markus Rost's avatar
Markus Rost committed
163 164

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

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

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

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

177 178 179 180 181 182
(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)
183
  (mapc
184 185
   (lambda (symbol)
     (push symbol cus-test-tested-variables)
186 187 188
     ;; Be verbose in case we hang.
     (message "Cus Test running...%s %s"
	      (length cus-test-tested-variables) symbol)
189
     (condition-case alpha
190 191 192
	 ;; 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.
193 194 195 196 197 198
	 (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
199 200
	     (push (funcall get symbol) values)
	     (push (eval (car (get symbol 'standard-value))) values))
201
	   (if (boundp symbol)
Markus Rost's avatar
Markus Rost committed
202
	       (push (symbol-value symbol) values))
203
	   ;; That does not work.
Markus Rost's avatar
Markus Rost committed
204
	   ;; (push (widget-get conv :value) values)
205 206

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

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

218
	   ;; Changed outside the customize buffer?
219 220 221 222 223 224 225 226
	   ;; 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
227
		  (add-to-list 'cus-test-vars-with-changed-state symbol)))
228 229

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

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

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
(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)
262 263 264
    (mapatoms
     (lambda (symbol)
       (and
265 266 267 268 269 270 271
	(if group
	    (memq symbol groups)
	  (or
	   ;; (user-variable-p symbol)
	   (get symbol 'standard-value)
	   ;; (get symbol 'saved-value)
	   (get symbol 'custom-type)))
272
	(string-match regexp (symbol-name symbol))
273
	(not (member symbol cus-test-skip-list))
274 275 276 277 278 279 280 281 282 283
	(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)))
284 285 286
    (if (not cus-test-errors)
	(insert "No errors found by cus-test.")
      (insert "The following variables seem to have problems:\n\n")
287 288
      (dolist (e cus-test-errors)
	(insert (symbol-name e) "\n")))))
289 290

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

Glenn Morris's avatar
Glenn Morris committed
297 298 299 300 301 302 303 304 305 306 307 308 309 310
(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
311
(defun cus-test-load-libs (&optional more)
312
  "Load the libraries with autoloads.
Glenn Morris's avatar
Glenn Morris committed
313 314 315
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."
316
  (interactive)
Glenn Morris's avatar
Glenn Morris committed
317 318 319 320 321 322 323 324 325 326 327
  (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
328 329 330
      (if more
	  (cus-test-get-lisp-files (equal more "all"))
	(cus-test-get-autoload-deps))))))
331 332

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

341 342
(defun cus-test-get-lisp-files (&optional all)
  "Return list of all Lisp files with defcustoms.
Glenn Morris's avatar
Glenn Morris committed
343
Optional argument ALL non-nil means list all (non-obsolete) Lisp files."
344 345 346 347 348 349 350
  (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
351
		       "-name" "obsolete" "-prune" "-o"
Glenn Morris's avatar
Glenn Morris committed
352
		       "-name" "[^.]*.el" ; ignore .dir-locals.el
Glenn Morris's avatar
Glenn Morris committed
353 354
		       (if all
			   '("-print")
355 356 357 358
			 (list "-exec" grep-program
			       "-l" "^[ \t]*(defcustom" "{}" "+"))))
      (message "%sdone" msg))))

359 360 361 362 363
(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
364 365
;;; The routines for batch mode:

Glenn Morris's avatar
Glenn Morris committed
366
(defun cus-test-opts (&optional all)
Markus Rost's avatar
Markus Rost committed
367 368 369 370 371
  "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
372 373 374
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
375
  (interactive)
Glenn Morris's avatar
Glenn Morris committed
376 377 378
  (and noninteractive
       command-line-args-left
       (setq all (pop command-line-args-left)))
379
  (message "Running %s" 'cus-test-load-libs)
Glenn Morris's avatar
Glenn Morris committed
380
  (cus-test-load-libs (if all "defcustom"))
Markus Rost's avatar
Markus Rost committed
381 382 383 384
  (message "Running %s" 'cus-test-load-custom-loads)
  (cus-test-load-custom-loads)
  (message "Running %s" 'cus-test-apropos)
  (cus-test-apropos "")
385 386 387 388
  (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
389

390
(defun cus-test-deps ()
Markus Rost's avatar
Markus Rost committed
391 392 393 394 395
  "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

396
in the Emacs source directory."
Markus Rost's avatar
Markus Rost committed
397 398
  (interactive)
  (setq cus-test-deps-errors nil)
399
  (setq cus-test-deps-required nil)
Markus Rost's avatar
Markus Rost committed
400
  (setq cus-test-deps-loaded nil)
Markus Rost's avatar
Markus Rost committed
401 402 403
  (mapatoms
   ;; This code is mainly from `custom-load-symbol'.
   (lambda (symbol)
404 405 406 407 408 409
     (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
410 411
	       (unless (or (featurep load)
			   (and noninteractive (eq load 'dunnet)))
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 452
		 (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))))
	  )))))
453 454 455
  (message "%s features required"
	   (length cus-test-deps-required))
  (message "%s files loaded"
Markus Rost's avatar
Markus Rost committed
456
	   (length cus-test-deps-loaded))
457 458 459 460
  (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
461 462
  (run-hooks 'cus-test-after-load-libs-hook))

463
(defun cus-test-libs (&optional more)
464
  "Load the libraries with autoloads in separate processes.
Markus Rost's avatar
Markus Rost committed
465 466 467
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
468
  ./src/emacs -batch -l admin/cus-test.el -f cus-test-libs
Markus Rost's avatar
Markus Rost committed
469

470 471 472 473
in the Emacs source directory.

If optional argument MORE is \"defcustom\", load all files with defcustoms.
If it is \"all\", load all Lisp files."
474
  (interactive)
475 476 477
  (and noninteractive
       command-line-args-left
       (setq more (pop command-line-args-left)))
Glenn Morris's avatar
Glenn Morris committed
478
  (cus-test-load-1
Glenn Morris's avatar
Glenn Morris committed
479 480 481
   (let* ((default-directory source-directory)
	  (emacs (expand-file-name "src/emacs"))
	  skipped)
Glenn Morris's avatar
Glenn Morris committed
482
     (or (file-executable-p emacs)
Glenn Morris's avatar
Glenn Morris committed
483
	 (error "No such executable `%s'" emacs))
Glenn Morris's avatar
Glenn Morris committed
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
     (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)))))
504 505 506
      (if more
	  (cus-test-get-lisp-files (equal more "all"))
	(cus-test-get-autoload-deps)))
Glenn Morris's avatar
Glenn Morris committed
507 508 509 510
     (message "Default directory: %s" default-directory)
     (when skipped
       (message "The following libraries were skipped:")
       (cus-test-message skipped)))))
511

512 513 514 515 516 517 518 519 520
(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)
521 522
  (let ((groups-loaded (cus-test-get-options "" 'cus-load))
	cus-loaded groups-not-loaded)
523 524 525

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

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

    (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
541 542 543 544 545 546 547 548 549
       (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<)))))
550

551 552 553
(provide 'cus-test)

;;; cus-test.el ends here