Subject: bug#53632: Function definition history

From: Stefan Monnier <[email-masked]>
Date: Fri, 04 Feb 2022 11:30:26 -0500

> Now, this behavior has changed. With the same recipe, we get
>
> --8<---------------cut here---------------start------------->8---
> =>
> tramp-unload-file-name-handlers
> tramp-unload-tramp
> tramp-register-archive-file-name-handler
> tramp-archive-autoload-file-name-handler
> tramp-register-autoload-file-name-handlers
> tramp-autoload-file-name-handler
> --8<---------------cut here---------------end--------------->8---

Indeed, the behavior is changed, but AFAICT it's "better" in that it
gives us a state closer to the one we had before `tramp.el` was loaded:
the above functions are predefined in `loaddefs.el`
via `;;;###autoload` cookies, so it's normal that they're defined when
`tramp` is not loaded.

So I think the problem is in the test rather than in the unload code.
The patch below fixes the test for me.

BTW, I notice that the test uses `functionp` so it doesn't pay attention
to whether macros are properly unloaded (I noticed because I thought it
was odd that the above list didn't include
`tramp-archive-autoload-file-name-regexp` which is similarly predefined
in `loaddefs.el`).

        Stefan

diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index b41824a6cf3..1f9eea4c5f7 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -202,8 +202,8 @@ tramp--test-instrument-test-case
 	  (trace-buffer (tramp-trace-buffer-name tramp-test-vec))
 	  (debug-ignored-errors
 	   (append
-	    '("^make-symbolic-link not supported$"
-	      "^error with add-name-to-file")
+	    '("\\`make-symbolic-link not supported\\'"
+	      "\\`error with add-name-to-file")
 	    debug-ignored-errors))
 	  inhibit-message)
      (unwind-protect
@@ -326,7 +326,7 @@ tramp-test01-file-name-syntax
 	  (let (tramp-mode)
 	    (should-not (tramp-tramp-file-p "/method:user@host:")))
 	  ;; `tramp-ignored-file-name-regexp' suppresses Tramp.
-	  (let ((tramp-ignored-file-name-regexp "^/method:user@host:"))
+	  (let ((tramp-ignored-file-name-regexp "\\`/method:user@host:"))
 	    (should-not (tramp-tramp-file-p "/method:user@host:")))
 	  ;; Methods shall be at least two characters on MS Windows,
 	  ;; except the default method.
@@ -3664,7 +3664,7 @@ tramp--test-ignore-add-name-to-file-error
   `(condition-case err
        (progn ,@body)
      (file-error
-      (unless (string-match-p "^error with add-name-to-file"
+      (unless (string-match-p "\\`error with add-name-to-file"
 			      (error-message-string err))
 	(signal (car err) (cdr err))))))
 
@@ -6070,7 +6070,7 @@ tramp-test39-detect-external-change
 		      (when create-lockfiles
 			(should (string-match-p
 				 (format
-				  "^%s changed on disk; really edit the buffer\\?"
+				  "\\`%s changed on disk; really edit the buffer\\?"
 				  (if (tramp--test-crypt-p)
 				      ".+" (file-name-nondirectory tmp-name)))
 				 captured-messages))
@@ -6183,7 +6183,7 @@ tramp--test-ftp-p
 This does not support globbing characters in file names (yet)."
   ;; Globbing characters are ??, ?* and ?\[.
   (string-match-p
-   "ftp$" (file-remote-p tramp-test-temporary-file-directory 'method)))
+   "ftp\\'" (file-remote-p tramp-test-temporary-file-directory 'method)))
 
 (defun tramp--test-fuse-p ()
   "Check, whether an FUSE file system isused."
@@ -6215,7 +6215,7 @@ tramp--test-ksh-p
   ;; We must refill the cache.  `file-truename' does it.
   (file-truename tramp-test-temporary-file-directory)
   (string-match-p
-   "ksh$" (tramp-get-connection-property tramp-test-vec "remote-shell" "")))
+   "ksh\\'" (tramp-get-connection-property tramp-test-vec "remote-shell" "")))
 
 (defun tramp--test-macos-p ()
   "Check, whether the remote host runs macOS."
@@ -6263,7 +6263,7 @@ tramp--test-share-p
   "Check, whether the method needs a share."
   (and (tramp--test-gvfs-p)
        (string-match-p
-	"^\\(afp\\|davs?\\|smb\\)$"
+	"\\`\\(afp\\|davs?\\|smb\\)\\'"
 	(file-remote-p tramp-test-temporary-file-directory 'method))))
 
 (defun tramp--test-sshfs-p ()
@@ -7206,11 +7206,20 @@ tramp-test47-unload
    (lambda (x)
      (and (or (and (boundp x) (null (local-variable-if-set-p x)))
 	      (and (functionp x) (null (autoloadp (symbol-function x)))))
-	  (string-match-p "^tramp" (symbol-name x))
+	  (string-match-p "\\`tramp" (symbol-name x))
 	  ;; `tramp-completion-mode' is autoloaded in Emacs < 28.1.
 	  (not (eq 'tramp-completion-mode x))
-	  (not (string-match-p "^tramp\\(-archive\\)?--?test" (symbol-name x)))
-	  (not (string-match-p "unload-hook$" (symbol-name x)))
+	  ;; Some functions aren't autoloads but they are similarly
+	  ;; predefined before `Tramp' is loaded (bug#53632):
+	  (not (memq x '(tramp-unload-file-name-handlers
+	                 tramp-unload-tramp
+	                 tramp-register-archive-file-name-handler
+	                 tramp-archive-autoload-file-name-handler
+	                 tramp-register-autoload-file-name-handlers
+	                 tramp-autoload-file-name-handler)))
+	  (not (string-match-p "\\`tramp\\(-archive\\)?--?test"
+	                       (symbol-name x)))
+	  (not (string-match-p "unload-hook\\'" (symbol-name x)))
 	  (ert-fail (format "`%s' still bound" x)))))
   ;; The defstruct `tramp-file-name' and all its internal functions
   ;; shall be purged.
@@ -7225,8 +7234,8 @@ tramp-test47-unload
   (mapatoms
    (lambda (x)
      (and (boundp x)
-	  (string-match-p "-\\(hook\\|function\\)s?$" (symbol-name x))
-	  (not (string-match-p "unload-hook$" (symbol-name x)))
+	  (string-match-p "-\\(hook\\|function\\)s?\\'" (symbol-name x))
+	  (not (string-match-p "unload-hook\\'" (symbol-name x)))
 	  (consp (symbol-value x))
 	  (ignore-errors (all-completions "tramp" (symbol-value x)))
 	  (ert-fail (format "Hook `%s' still contains Tramp function" x))))))
@@ -7237,7 +7246,7 @@ tramp-test-all
   (interactive "p")
   (funcall
    (if interactive #'ert-run-tests-interactively #'ert-run-tests-batch)
-   "^tramp"))
+   "\\`tramp"))
 
 ;; TODO: