summaryrefslogtreecommitdiff
path: root/test/lisp/net
diff options
context:
space:
mode:
Diffstat (limited to 'test/lisp/net')
-rw-r--r--test/lisp/net/gnutls-tests.el30
-rw-r--r--test/lisp/net/secrets-tests.el275
-rw-r--r--test/lisp/net/tramp-archive-resources/foo.iso/foo1
-rw-r--r--test/lisp/net/tramp-archive-resources/foo.tar.gzbin0 -> 274 bytes
-rw-r--r--test/lisp/net/tramp-archive-tests.el948
-rw-r--r--test/lisp/net/tramp-tests.el892
6 files changed, 1884 insertions, 262 deletions
diff --git a/test/lisp/net/gnutls-tests.el b/test/lisp/net/gnutls-tests.el
index c5bfe439d17..326e2416495 100644
--- a/test/lisp/net/gnutls-tests.el
+++ b/test/lisp/net/gnutls-tests.el
@@ -26,7 +26,7 @@
;;; Code:
(require 'ert)
-(require 'cl)
+(require 'cl-lib)
(require 'gnutls)
(require 'hex-util)
@@ -46,22 +46,22 @@
(defvar gnutls-tests-tested-macs
(when (gnutls-available-p)
- (remove-duplicates
- (append (mapcar 'cdr gnutls-tests-internal-macs-upcased)
- (mapcar 'car (gnutls-macs))))))
+ (cl-remove-duplicates
+ (append (mapcar #'cdr gnutls-tests-internal-macs-upcased)
+ (mapcar #'car (gnutls-macs))))))
(defvar gnutls-tests-tested-digests
(when (gnutls-available-p)
- (remove-duplicates
- (append (mapcar 'cdr gnutls-tests-internal-macs-upcased)
- (mapcar 'car (gnutls-digests))))))
+ (cl-remove-duplicates
+ (append (mapcar #'cdr gnutls-tests-internal-macs-upcased)
+ (mapcar #'car (gnutls-digests))))))
(defvar gnutls-tests-tested-ciphers
(when (gnutls-available-p)
- (remove-duplicates
- ; these cause FPEs or SEGVs
- (remove-if (lambda (e) (memq e '(ARCFOUR-128)))
- (mapcar 'car (gnutls-ciphers))))))
+ (cl-remove-duplicates
+ ;; these cause FPEs or SEGVs
+ (cl-remove-if (lambda (e) (memq e '(ARCFOUR-128)))
+ (mapcar #'car (gnutls-ciphers))))))
(defvar gnutls-tests-mondo-strings
(list
@@ -154,7 +154,7 @@
("0cc175b9c0f1b6a831c399e269772661" "a" MD5)
("a9993e364706816aba3e25717850c26c9cd0d89d" "abc" SHA1)
("a9993e364706816aba3e25717850c26c9cd0d89d" "abc" "SHA1"))) ; check string ID for digest
- (destructuring-bind (hash input mac) test
+ (pcase-let ((`(,hash ,input ,mac) test))
(let ((plist (cdr (assq mac macs)))
result resultb)
(gnutls-tests-message "%s %S" mac plist)
@@ -178,7 +178,7 @@
("81568ba71fa2c5f33cc84bf362466988f98eba3735479100b4e8908acad87ac4" "more and more data goes into a file to exceed the buffer size" "very long key goes here to exceed the key size" SHA256)
("4bc830005783a73b8112f4bd5f4aa5f92e05b51e9b55c0cd6f9a7bee48371def" "more and more data goes into a file to exceed the buffer size" "" "SHA256") ; check string ID for HMAC
("4bc830005783a73b8112f4bd5f4aa5f92e05b51e9b55c0cd6f9a7bee48371def" "more and more data goes into a file to exceed the buffer size" "" SHA256)))
- (destructuring-bind (hash input key mac) test
+ (pcase-let ((`(,hash ,input ,key ,mac) test))
(let ((plist (cdr (assq mac macs)))
result)
(gnutls-tests-message "%s %S" mac plist)
@@ -214,7 +214,7 @@
(let ((keys '("mykey" "mykey2"))
(inputs gnutls-tests-mondo-strings)
(ivs '("" "-abc123-" "init" "ini2"))
- (ciphers (remove-if
+ (ciphers (cl-remove-if
(lambda (c) (plist-get (cdr (assq c (gnutls-ciphers)))
:cipher-aead-capable))
gnutls-tests-tested-ciphers)))
@@ -252,7 +252,7 @@
"auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data auth and auth of data "
"AUTH data and more data to go over the block limit!"
"AUTH data and more data to go over the block limit"))
- (ciphers (remove-if
+ (ciphers (cl-remove-if
(lambda (c) (or (null (plist-get (cdr (assq c (gnutls-ciphers)))
:cipher-aead-capable))))
gnutls-tests-tested-ciphers))
diff --git a/test/lisp/net/secrets-tests.el b/test/lisp/net/secrets-tests.el
new file mode 100644
index 00000000000..de3ce731bec
--- /dev/null
+++ b/test/lisp/net/secrets-tests.el
@@ -0,0 +1,275 @@
+;;; secrets-tests.el --- Tests of Secret Service API
+
+;; Copyright (C) 2018 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program 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
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+
+;;; Code:
+
+(require 'ert)
+(require 'secrets)
+(require 'notifications)
+
+;; We do not want chatty messages.
+(setq secrets-debug nil)
+
+(ert-deftest secrets-test00-availability ()
+ "Test availability of Secret Service API."
+ :expected-result (if secrets-enabled :passed :failed)
+ (should secrets-enabled)
+ (should (dbus-ping :session secrets-service))
+
+ ;; Exit.
+ (secrets--test-close-all-sessions))
+
+(defun secrets--test-get-all-sessions ()
+ "Return all object paths for existing secrets sessions."
+ (let ((session-path (concat secrets-path "/session")))
+ (delete
+ session-path
+ (dbus-introspect-get-all-nodes :session secrets-service session-path))))
+
+(defun secrets--test-close-all-sessions ()
+ "Close all secrets sessions which are bound to this Emacs."
+ (secrets-close-session)
+ ;; We loop over all other sessions. If a session does not belong to
+ ;; us, a `dbus-error' is fired, which we ignore.
+ (dolist (path (secrets--test-get-all-sessions))
+ (dbus-ignore-errors
+ (dbus-call-method
+ :session secrets-service path secrets-interface-session "Close"))))
+
+(defun secrets--test-delete-all-session-items ()
+ "Delete all items of collection \"session\" bound to this Emacs."
+ (dolist (item (secrets-list-items "session"))
+ (secrets-delete-item "session" item)))
+
+(ert-deftest secrets-test01-sessions ()
+ "Test opening / closing a secrets session."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (progn
+ ;; Simple opening / closing of a session.
+ (should (secrets-open-session))
+ (should-not (secrets-empty-path secrets-session-path))
+ (should (secrets-close-session))
+ (should (secrets-empty-path secrets-session-path))
+
+ ;; Reopening a new session.
+ (should (string-equal (secrets-open-session) (secrets-open-session)))
+ (should (string-equal secrets-session-path (secrets-open-session)))
+ (should-not
+ (string-equal (secrets-open-session) (secrets-open-session 'reopen)))
+ (should-not
+ (string-equal secrets-session-path (secrets-open-session 'reopen))))
+
+ ;; Exit.
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(ert-deftest secrets-test02-collections ()
+ "Test creation / deletion a secrets collections."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (progn
+ (should (secrets-open-session))
+
+ ;; There must be at least the collections "Login" and "session".
+ (should (or (member "Login" (secrets-list-collections))
+ (member "login" (secrets-list-collections))))
+ (should (member "session" (secrets-list-collections)))
+
+ ;; Create a random collection. This asks for a password
+ ;; outside our control, so we make it in the interactive case
+ ;; only.
+ (unless noninteractive
+ (let ((collection (md5 (concat (prin1-to-string process-environment)
+ (current-time-string))))
+ (alias (secrets-get-alias "default")))
+ (notifications-notify
+ :title (symbol-name (ert-test-name (ert-running-test)))
+ :body "Please enter the password \"secret\" twice")
+ ;; The optional argument ALIAS does not seem to work.
+ (should (secrets-create-collection collection))
+ (should (member collection (secrets-list-collections)))
+
+ ;; We reset the alias. The temporary collection "session"
+ ;; is not accepted.
+ (secrets-set-alias collection "default")
+ (should (string-equal (secrets-get-alias "default") collection))
+
+ ;; Delete alias.
+ (secrets-delete-alias "default")
+ (should-not (secrets-get-alias "default"))
+
+ ;; Lock / unlock the collection.
+ (secrets-lock-collection collection)
+ (should
+ (secrets-get-collection-property
+ (secrets-collection-path collection) "Locked"))
+ (notifications-notify
+ :title (symbol-name (ert-test-name (ert-running-test)))
+ :body "Please enter the password \"secret\"")
+ (secrets-unlock-collection collection)
+ (should-not
+ (secrets-get-collection-property
+ (secrets-collection-path collection) "Locked"))
+
+ ;; Delete the collection. The alias disappears as well.
+ (secrets-set-alias collection "default")
+ (secrets-delete-collection collection)
+ (should-not (secrets-get-alias "default"))
+
+ ;; Reset alias.
+ (when alias
+ (secrets-set-alias alias "default")
+ (should (string-equal (secrets-get-alias "default") alias))))))
+
+ ;; Exit.
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(ert-deftest secrets-test03-items ()
+ "Test creation / deletion a secret item."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (let (item-path)
+ (should (secrets-open-session))
+
+ ;; Cleanup. There could be items in the "session" collection.
+ (secrets--test-delete-all-session-items)
+
+ ;; There shall be no items in the "session" collection.
+ (should-not (secrets-list-items "session"))
+ ;; There shall be items in the "Login" collection.
+ (should (or (secrets-list-items "Login")
+ (secrets-list-items "login")))
+
+ ;; Create a new item.
+ (should (setq item-path (secrets-create-item "session" "foo" "secret")))
+ (dolist (item `("foo" ,item-path))
+ (should (string-equal (secrets-get-secret "session" item) "secret")))
+
+ ;; Create another item with same label.
+ (should (secrets-create-item "session" "foo" "geheim"))
+ (should (equal (secrets-list-items "session") '("foo" "foo")))
+
+ ;; Create an item with attributes.
+ (should
+ (setq item-path
+ (secrets-create-item
+ "session" "bar" "secret"
+ :method "sudo" :user "joe" :host "remote-host")))
+ (dolist (item `("bar" ,item-path))
+ (should
+ (string-equal (secrets-get-attribute "session" item :method) "sudo"))
+ ;; The attributes are collected in reverse order.
+ ;; :xdg:schema is added silently.
+ (should
+ (equal
+ (secrets-get-attributes "session" item)
+ '((:xdg:schema . "org.freedesktop.Secret.Generic")
+ (:host . "remote-host") (:user . "joe") (:method . "sudo")))))
+
+ ;; Create an item with another schema.
+ (should
+ (setq item-path
+ (secrets-create-item
+ "session" "baz" "secret" :xdg:schema "org.gnu.Emacs.foo")))
+ (dolist (item `("baz" ,item-path))
+ (should
+ (equal
+ (secrets-get-attributes "session" item)
+ '((:xdg:schema . "org.gnu.Emacs.foo")))))
+
+ ;; Delete them.
+ (dolist (item (secrets-list-items "session"))
+ (secrets-delete-item "session" item))
+ (should-not (secrets-list-items "session")))
+
+ ;; Exit.
+ (secrets--test-delete-all-session-items)
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(ert-deftest secrets-test04-search ()
+ "Test searching of secret items."
+ (skip-unless secrets-enabled)
+ (skip-unless (secrets-empty-path secrets-session-path))
+
+ (unwind-protect
+ (progn
+ (should (secrets-open-session))
+
+ ;; Cleanup. There could be items in the "session" collection.
+ (secrets--test-delete-all-session-items)
+
+ ;; There shall be no items in the "session" collection.
+ (should-not (secrets-list-items "session"))
+
+ ;; Create some items.
+ (should
+ (secrets-create-item
+ "session" "foo" "secret"
+ :method "sudo" :user "joe" :host "remote-host"))
+ (should
+ (secrets-create-item
+ "session" "bar" "secret"
+ :method "sudo" :user "smith" :host "remote-host"))
+ (should
+ (secrets-create-item
+ "session" "baz" "secret"
+ :method "ssh" :user "joe" :host "other-host"))
+
+ ;; Search the items. `secrets-search-items' uses
+ ;; `secrets-search-item-paths' internally, it is sufficient to
+ ;; test only one of them.
+ (should-not (secrets-search-item-paths "session" :user "john"))
+ (should-not (secrets-search-items "session" :user "john"))
+ (should-not
+ (secrets-search-items "session" :xdg:schema "org.gnu.Emacs.foo"))
+ (should
+ (equal
+ (sort (secrets-search-items "session" :user "joe") 'string-lessp)
+ '("baz" "foo")))
+ (should
+ (equal
+ (secrets-search-items "session":method "sudo" :user "joe") '("foo")))
+ (should
+ (equal
+ (sort (secrets-search-items "session") 'string-lessp)
+ '("bar" "baz" "foo"))))
+
+ ;; Exit.
+ (secrets--test-delete-all-session-items)
+ (should (secrets-close-session))
+ (secrets--test-close-all-sessions)))
+
+(defun secrets-test-all (&optional interactive)
+ "Run all tests for \\[secrets]."
+ (interactive "p")
+ (funcall
+ (if interactive 'ert-run-tests-interactively 'ert-run-tests-batch)
+ "^secrets"))
+
+(provide 'secrets-tests)
+;;; secrets-tests.el ends here
diff --git a/test/lisp/net/tramp-archive-resources/foo.iso/foo b/test/lisp/net/tramp-archive-resources/foo.iso/foo
new file mode 100644
index 00000000000..257cc5642cb
--- /dev/null
+++ b/test/lisp/net/tramp-archive-resources/foo.iso/foo
@@ -0,0 +1 @@
+foo
diff --git a/test/lisp/net/tramp-archive-resources/foo.tar.gz b/test/lisp/net/tramp-archive-resources/foo.tar.gz
new file mode 100644
index 00000000000..0d2e9878dd7
--- /dev/null
+++ b/test/lisp/net/tramp-archive-resources/foo.tar.gz
Binary files differ
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el
new file mode 100644
index 00000000000..e7597864c6e
--- /dev/null
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -0,0 +1,948 @@
+;;; tramp-archive-tests.el --- Tests of file archive access -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017-2018 Free Software Foundation, Inc.
+
+;; Author: Michael Albinus <michael.albinus@gmx.de>
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program 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
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
+
+;;; Code:
+
+;; The `tramp-archive-testnn-*' tests correspond to the respective
+;; tests in tramp-tests.el.
+
+(require 'ert)
+(require 'tramp-archive)
+
+(defconst tramp-archive-test-resource-directory
+ (let ((default-directory
+ (if load-in-progress
+ (file-name-directory load-file-name)
+ default-directory)))
+ (cond
+ ((file-accessible-directory-p (expand-file-name "resources"))
+ (expand-file-name "resources"))
+ ((file-accessible-directory-p (expand-file-name "tramp-archive-resources"))
+ (expand-file-name "tramp-archive-resources"))))
+ "The resources directory test files are located in.")
+
+(defconst tramp-archive-test-file-archive
+ (file-truename
+ (expand-file-name "foo.tar.gz" tramp-archive-test-resource-directory))
+ "The test file archive.")
+
+(defconst tramp-archive-test-archive
+ (file-name-as-directory tramp-archive-test-file-archive)
+ "The test archive.")
+
+(defconst tramp-archive-test-directory
+ (file-truename
+ (expand-file-name "foo.iso" tramp-archive-test-resource-directory))
+ "A directory file name, which looks like an archive.")
+
+(setq password-cache-expiry nil
+ tramp-verbose 0
+ tramp-cache-read-persistent-data t ;; For auth-sources.
+ tramp-copy-size-limit nil
+ tramp-message-show-message nil
+ tramp-persistency-file-name nil)
+
+(defun tramp-archive--test-make-temp-name ()
+ "Return a temporary file name for test.
+The temporary file is not created."
+ (expand-file-name
+ (make-temp-name "tramp-archive-test") temporary-file-directory))
+
+(defun tramp-archive--test-delete (tmpfile)
+ "Delete temporary file or directory TMPFILE.
+This needs special support, because archive file names, which are
+the origin of the temporary TMPFILE, have no write permissions."
+ (unless (file-writable-p (file-name-directory tmpfile))
+ (set-file-modes
+ (file-name-directory tmpfile)
+ (logior (file-modes (file-name-directory tmpfile)) #o0700)))
+ (set-file-modes tmpfile #o0700)
+ (if (file-regular-p tmpfile)
+ (delete-file tmpfile)
+ (mapc
+ 'tramp-archive--test-delete
+ (directory-files tmpfile 'full directory-files-no-dot-files-regexp))
+ (delete-directory tmpfile)))
+
+(defun tramp-archive--test-emacs26-p ()
+ "Check for Emacs version >= 26.1.
+Some semantics has been changed for there, w/o new functions or
+variables, so we check the Emacs version directly."
+ (>= emacs-major-version 26))
+
+(defun tramp-archive--test-emacs27-p ()
+ "Check for Emacs version >= 27.1.
+Some semantics has been changed for there, w/o new functions or
+variables, so we check the Emacs version directly."
+ (>= emacs-major-version 27))
+
+(ert-deftest tramp-archive-test00-availability ()
+ "Test availability of archive file name functions."
+ :expected-result (if tramp-archive-enabled :passed :failed)
+ (should
+ (and
+ tramp-archive-enabled
+ (file-exists-p tramp-archive-test-file-archive)
+ (tramp-archive-file-name-p tramp-archive-test-archive))))
+
+(ert-deftest tramp-archive-test01-file-name-syntax ()
+ "Check archive file name syntax."
+ (should-not (tramp-archive-file-name-p tramp-archive-test-file-archive))
+ (should (tramp-archive-file-name-p tramp-archive-test-archive))
+ (should
+ (string-equal
+ (tramp-archive-file-name-archive tramp-archive-test-archive)
+ tramp-archive-test-file-archive))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname tramp-archive-test-archive) "/"))
+ (should (tramp-archive-file-name-p (concat tramp-archive-test-archive "foo")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "foo"))
+ "/foo"))
+ (should
+ (tramp-archive-file-name-p (concat tramp-archive-test-archive "foo/bar")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "foo/bar"))
+ "/foo/bar"))
+ ;; A file archive inside a file archive.
+ (should
+ (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-archive
+ (concat tramp-archive-test-archive "baz.tar"))
+ tramp-archive-test-file-archive))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "baz.tar"))
+ "/baz.tar"))
+ (should
+ (tramp-archive-file-name-p (concat tramp-archive-test-archive "baz.tar/")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-archive
+ (concat tramp-archive-test-archive "baz.tar/"))
+ (concat tramp-archive-test-archive "baz.tar")))
+ (should
+ (string-equal
+ (tramp-archive-file-name-localname
+ (concat tramp-archive-test-archive "baz.tar/"))
+ "/")))
+
+(ert-deftest tramp-archive-test02-file-name-dissect ()
+ "Check archive file name components."
+ (skip-unless tramp-archive-enabled)
+
+ (with-parsed-tramp-archive-file-name tramp-archive-test-archive nil
+ (should (string-equal method tramp-archive-method))
+ (should-not user)
+ (should-not domain)
+ (should
+ (string-equal
+ host
+ (file-remote-p
+ (tramp-archive-gvfs-file-name tramp-archive-test-archive) 'host)))
+ (should
+ (string-equal
+ host
+ (url-hexify-string (concat "file://" tramp-archive-test-file-archive))))
+ (should-not port)
+ (should (string-equal localname "/"))
+ (should (string-equal archive tramp-archive-test-file-archive)))
+
+ ;; Localname.
+ (with-parsed-tramp-archive-file-name
+ (concat tramp-archive-test-archive "foo") nil
+ (should (string-equal method tramp-archive-method))
+ (should-not user)
+ (should-not domain)
+ (should
+ (string-equal
+ host
+ (file-remote-p
+ (tramp-archive-gvfs-file-name tramp-archive-test-archive) 'host)))
+ (should
+ (string-equal
+ host
+ (url-hexify-string (concat "file://" tramp-archive-test-file-archive))))
+ (should-not port)
+ (should (string-equal localname "/foo"))
+ (should (string-equal archive tramp-archive-test-file-archive)))
+
+ ;; File archive in file archive.
+ (let* ((tramp-archive-test-file-archive
+ (concat tramp-archive-test-archive "baz.tar"))
+ (tramp-archive-test-archive
+ (file-name-as-directory tramp-archive-test-file-archive))
+ (tramp-methods (cons `(,tramp-archive-method) tramp-methods))
+ (tramp-gvfs-methods tramp-archive-all-gvfs-methods))
+ (unwind-protect
+ (with-parsed-tramp-archive-file-name
+ (expand-file-name "bar" tramp-archive-test-archive) nil
+ (should (string-equal method tramp-archive-method))
+ (should-not user)
+ (should-not domain)
+ (should
+ (string-equal
+ host
+ (file-remote-p
+ (tramp-archive-gvfs-file-name tramp-archive-test-archive) 'host)))
+ ;; We reimplement the logic of tramp-archive.el here. Don't
+ ;; know, whether it is worth the test.
+ (should
+ (string-equal
+ host
+ (url-hexify-string
+ (concat
+ (tramp-gvfs-url-file-name
+ (tramp-make-tramp-file-name
+ tramp-archive-method
+ ;; User and Domain.
+ nil nil
+ ;; Host.
+ (url-hexify-string
+ (concat
+ "file://"
+ ;; `directory-file-name' does not leave file archive
+ ;; boundaries. So we must cut the trailing slash
+ ;; ourselves.
+ (substring
+ (file-name-directory tramp-archive-test-file-archive) 0 -1)))
+ nil "/"))
+ (file-name-nondirectory tramp-archive-test-file-archive)))))
+ (should-not port)
+ (should (string-equal localname "/bar"))
+ (should (string-equal archive tramp-archive-test-file-archive)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test05-expand-file-name ()
+ "Check `expand-file-name'."
+ (should
+ (string-equal
+ (expand-file-name "/foo.tar/path/./file") "/foo.tar/path/file"))
+ (should
+ (string-equal (expand-file-name "/foo.tar/path/../file") "/foo.tar/file"))
+ ;; `expand-file-name' does not care "~/" in archive file names.
+ (should
+ (string-equal (expand-file-name "/foo.tar/~/file") "/foo.tar/~/file"))
+ ;; `expand-file-name' does not care file archive boundaries.
+ (should (string-equal (expand-file-name "/foo.tar/./file") "/foo.tar/file"))
+ (should (string-equal (expand-file-name "/foo.tar/../file") "/file")))
+
+;; This test is inspired by Bug#30293.
+(ert-deftest tramp-archive-test05-expand-file-name-non-archive-directory ()
+ "Check existing directories with archive file name syntax.
+They shall still be supported"
+ (should (file-directory-p tramp-archive-test-directory))
+ ;; `tramp-archive-file-name-p' tests only for file name syntax. It
+ ;; doesn't test, whether it is really a file archive.
+ (should
+ (tramp-archive-file-name-p
+ (file-name-as-directory tramp-archive-test-directory)))
+ (should
+ (file-directory-p (file-name-as-directory tramp-archive-test-directory)))
+ (should
+ (file-exists-p (expand-file-name "foo" tramp-archive-test-directory))))
+
+(ert-deftest tramp-archive-test06-directory-file-name ()
+ "Check `directory-file-name'.
+This checks also `file-name-as-directory', `file-name-directory',
+`file-name-nondirectory' and `unhandled-file-name-directory'."
+ (skip-unless tramp-archive-enabled)
+
+ (should
+ (string-equal
+ (directory-file-name "/foo.tar/path/to/file") "/foo.tar/path/to/file"))
+ (should
+ (string-equal
+ (directory-file-name "/foo.tar/path/to/file/") "/foo.tar/path/to/file"))
+ ;; `directory-file-name' does not leave file archive boundaries.
+ (should (string-equal (directory-file-name "/foo.tar/") "/foo.tar/"))
+
+ (should
+ (string-equal
+ (file-name-as-directory "/foo.tar/path/to/file") "/foo.tar/path/to/file/"))
+ (should
+ (string-equal
+ (file-name-as-directory "/foo.tar/path/to/file/") "/foo.tar/path/to/file/"))
+ (should (string-equal (file-name-as-directory "/foo.tar/") "/foo.tar/"))
+ (should (string-equal (file-name-as-directory "/foo.tar") "/foo.tar/"))
+
+ (should
+ (string-equal
+ (file-name-directory "/foo.tar/path/to/file") "/foo.tar/path/to/"))
+ (should
+ (string-equal
+ (file-name-directory "/foo.tar/path/to/file/") "/foo.tar/path/to/file/"))
+ (should (string-equal (file-name-directory "/foo.tar/") "/foo.tar/"))
+
+ (should
+ (string-equal (file-name-nondirectory "/foo.tar/path/to/file") "file"))
+ (should
+ (string-equal (file-name-nondirectory "/foo.tar/path/to/file/") ""))
+ (should (string-equal (file-name-nondirectory "/foo.tar/") ""))
+
+ (should-not
+ (unhandled-file-name-directory "/foo.tar/path/to/file")))
+
+(ert-deftest tramp-archive-test07-file-exists-p ()
+ "Check `file-exist-p', `write-region' and `delete-file'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (unwind-protect
+ (let ((default-directory tramp-archive-test-archive))
+ (should (file-exists-p tramp-archive-test-file-archive))
+ (should (file-exists-p tramp-archive-test-archive))
+ (should (file-exists-p "foo.txt"))
+ (should (file-exists-p "foo.lnk"))
+ (should (file-exists-p "bar"))
+ (should (file-exists-p "bar/bar"))
+ (should-error
+ (write-region "foo" nil "baz")
+ :type 'file-error)
+ (should-error
+ (delete-file "baz")
+ :type 'file-error))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash)))
+
+(ert-deftest tramp-archive-test08-file-local-copy ()
+ "Check `file-local-copy'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let (tmp-name)
+ (unwind-protect
+ (progn
+ (should
+ (setq tmp-name
+ (file-local-copy
+ (expand-file-name "bar/bar" tramp-archive-test-archive))))
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "bar\n")))
+ ;; Error case.
+ (tramp-archive--test-delete tmp-name)
+ (should-error
+ (setq tmp-name
+ (file-local-copy
+ (expand-file-name "what" tramp-archive-test-archive)))
+ :type tramp-file-missing))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name))
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test09-insert-file-contents ()
+ "Check `insert-file-contents'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name (expand-file-name "bar/bar" tramp-archive-test-archive)))
+ (unwind-protect
+ (with-temp-buffer
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "bar\n"))
+ (insert-file-contents tmp-name)
+ (should (string-equal (buffer-string) "bar\nbar\n"))
+ ;; Insert partly.
+ (insert-file-contents tmp-name nil 1 3)
+ (should (string-equal (buffer-string) "arbar\nbar\n"))
+ ;; Replace.
+ (insert-file-contents tmp-name nil nil nil 'replace)
+ (should (string-equal (buffer-string) "bar\n"))
+ ;; Error case.
+ (should-error
+ (insert-file-contents
+ (expand-file-name "what" tramp-archive-test-archive))
+ :type tramp-file-missing))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test11-copy-file ()
+ "Check `copy-file'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ ;; Copy simple file.
+ (let ((tmp-name1 (expand-file-name "bar/bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name)))
+ (unwind-protect
+ (progn
+ (copy-file tmp-name1 tmp-name2)
+ (should (file-exists-p tmp-name2))
+ (with-temp-buffer
+ (insert-file-contents tmp-name2)
+ (should (string-equal (buffer-string) "bar\n")))
+ (should-error
+ (copy-file tmp-name1 tmp-name2)
+ :type 'file-already-exists)
+ (copy-file tmp-name1 tmp-name2 'ok)
+ ;; The file archive is not writable.
+ (should-error
+ (copy-file tmp-name2 tmp-name1 'ok)
+ :type 'file-error))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash)))
+
+ ;; Copy directory to existing directory.
+ (let ((tmp-name1 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name)))
+ (unwind-protect
+ (progn
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ ;; Directory `tmp-name2' exists already, so we must use
+ ;; `file-name-as-directory'.
+ (copy-file tmp-name1 (file-name-as-directory tmp-name2))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory tmp-name1) "/bar") tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash)))
+
+ ;; Copy directory/file to non-existing directory.
+ (let ((tmp-name1 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name)))
+ (unwind-protect
+ (progn
+ (make-directory tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (copy-file
+ tmp-name1
+ (expand-file-name (file-name-nondirectory tmp-name1) tmp-name2))
+ (should
+ (file-exists-p
+ (expand-file-name
+ (concat (file-name-nondirectory tmp-name1) "/bar") tmp-name2))))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test15-copy-directory ()
+ "Check `copy-directory'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let* ((tmp-name1 (expand-file-name "bar" tramp-archive-test-archive))
+ (tmp-name2 (tramp-archive--test-make-temp-name))
+ (tmp-name3 (expand-file-name
+ (file-name-nondirectory tmp-name1) tmp-name2))
+ (tmp-name4 (expand-file-name "bar" tmp-name2))
+ (tmp-name5 (expand-file-name "bar" tmp-name3)))
+
+ ;; Copy complete directory.
+ (unwind-protect
+ (progn
+ ;; Copy empty directory.
+ (copy-directory tmp-name1 tmp-name2)
+ (should (file-directory-p tmp-name2))
+ (should (file-exists-p tmp-name4))
+ ;; Target directory does exist already.
+ ;; This has been changed in Emacs 26.1.
+ (when (tramp-archive--test-emacs26-p)
+ (should-error
+ (copy-directory tmp-name1 tmp-name2)
+ :type 'file-error))
+ (tramp-archive--test-delete tmp-name4)
+ (copy-directory tmp-name1 (file-name-as-directory tmp-name2))
+ (should (file-directory-p tmp-name3))
+ (should (file-exists-p tmp-name5)))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash))
+
+ ;; Copy directory contents.
+ (unwind-protect
+ (progn
+ ;; Copy empty directory.
+ (copy-directory tmp-name1 tmp-name2 nil 'parents 'contents)
+ (should (file-directory-p tmp-name2))
+ (should (file-exists-p tmp-name4))
+ ;; Target directory does exist already.
+ (tramp-archive--test-delete tmp-name4)
+ (copy-directory
+ tmp-name1 (file-name-as-directory tmp-name2)
+ nil 'parents 'contents)
+ (should (file-directory-p tmp-name2))
+ (should (file-exists-p tmp-name4))
+ (should-not (file-directory-p tmp-name3))
+ (should-not (file-exists-p tmp-name5)))
+
+ ;; Cleanup.
+ (ignore-errors (tramp-archive--test-delete tmp-name2))
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test16-directory-files ()
+ "Check `directory-files'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name tramp-archive-test-archive)
+ (files '("." ".." "bar" "baz.tar" "foo.hrd" "foo.lnk" "foo.txt")))
+ (unwind-protect
+ (progn
+ (should (file-directory-p tmp-name))
+ (should (equal (directory-files tmp-name) files))
+ (should (equal (directory-files tmp-name 'full)
+ (mapcar (lambda (x) (concat tmp-name x)) files)))
+ (should (equal (directory-files
+ tmp-name nil directory-files-no-dot-files-regexp)
+ (delete "." (delete ".." files))))
+ (should (equal (directory-files
+ tmp-name 'full directory-files-no-dot-files-regexp)
+ (mapcar (lambda (x) (concat tmp-name x))
+ (delete "." (delete ".." files))))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test17-insert-directory ()
+ "Check `insert-directory'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let (;; We test for the summary line. Keyword "total" could be localized.
+ (process-environment
+ (append '("LANG=C" "LANGUAGE=C" "LC_ALL=C") process-environment)))
+ (unwind-protect
+ (progn
+ ;; Due to Bug#29423, this works only since for Emacs 26.1.
+ (when nil ;; TODO (tramp-archive--test-emacs26-p)
+ (with-temp-buffer
+ (insert-directory tramp-archive-test-archive nil)
+ (goto-char (point-min))
+ (should
+ (looking-at-p (regexp-quote tramp-archive-test-archive)))))
+ (with-temp-buffer
+ (insert-directory tramp-archive-test-archive "-al")
+ (goto-char (point-min))
+ (should
+ (looking-at-p
+ (format "^.+ %s$" (regexp-quote tramp-archive-test-archive)))))
+ (with-temp-buffer
+ (insert-directory
+ (file-name-as-directory tramp-archive-test-archive)
+ "-al" nil 'full-directory-p)
+ (goto-char (point-min))
+ (should
+ (looking-at-p
+ (concat
+ ;; There might be a summary line.
+ "\\(total.+[[:digit:]]+\n\\)?"
+ ;; We don't know in which order the files appear.
+ (format
+ "\\(.+ %s\\( ->.+\\)?\n\\)\\{%d\\}"
+ (regexp-opt (directory-files tramp-archive-test-archive))
+ (length (directory-files tramp-archive-test-archive))))))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test18-file-attributes ()
+ "Check `file-attributes'.
+This tests also `file-readable-p' and `file-regular-p'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name1 (expand-file-name "foo.txt" tramp-archive-test-archive))
+ (tmp-name2 (expand-file-name "foo.lnk" tramp-archive-test-archive))
+ (tmp-name3 (expand-file-name "bar" tramp-archive-test-archive))
+ attr)
+ (unwind-protect
+ (progn
+ (should (file-exists-p tmp-name1))
+ (should (file-readable-p tmp-name1))
+ (should (file-regular-p tmp-name1))
+
+ ;; We do not test inodes and device numbers.
+ (setq attr (file-attributes tmp-name1))
+ (should (consp attr))
+ (should (null (car attr)))
+ (should (numberp (nth 1 attr))) ;; Link.
+ (should (numberp (nth 2 attr))) ;; Uid.
+ (should (numberp (nth 3 attr))) ;; Gid.
+ ;; Last access time.
+ (should (stringp (current-time-string (nth 4 attr))))
+ ;; Last modification time.
+ (should (stringp (current-time-string (nth 5 attr))))
+ ;; Last status change time.
+ (should (stringp (current-time-string (nth 6 attr))))
+ (should (numberp (nth 7 attr))) ;; Size.
+ (should (stringp (nth 8 attr))) ;; Modes.
+
+ (setq attr (file-attributes tmp-name1 'string))
+ (should (stringp (nth 2 attr))) ;; Uid.
+ (should (stringp (nth 3 attr))) ;; Gid.
+
+ ;; Symlink.
+ (should (file-exists-p tmp-name2))
+ (should (file-symlink-p tmp-name2))
+ (setq attr (file-attributes tmp-name2))
+ (should (string-equal (car attr) (file-name-nondirectory tmp-name1)))
+
+ ;; Directory.
+ (should (file-exists-p tmp-name3))
+ (should (file-readable-p tmp-name3))
+ (should-not (file-regular-p tmp-name3))
+ (setq attr (file-attributes tmp-name3))
+ (should (eq (car attr) t)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test19-directory-files-and-attributes ()
+ "Check `directory-files-and-attributes'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name (expand-file-name "bar" tramp-archive-test-archive))
+ attr)
+ (unwind-protect
+ (progn
+ (should (file-directory-p tmp-name))
+ (setq attr (directory-files-and-attributes tmp-name))
+ (should (consp attr))
+ (dolist (elt attr)
+ (should
+ (equal (file-attributes (expand-file-name (car elt) tmp-name))
+ (cdr elt))))
+ (setq attr (directory-files-and-attributes tmp-name 'full))
+ (dolist (elt attr)
+ (should (equal (file-attributes (car elt)) (cdr elt))))
+ (setq attr (directory-files-and-attributes tmp-name nil "^b"))
+ (should (equal (mapcar 'car attr) '("bar"))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test20-file-modes ()
+ "Check `file-modes'.
+This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name1 (expand-file-name "foo.txt" tramp-archive-test-archive))
+ (tmp-name2 (expand-file-name "bar" tramp-archive-test-archive)))
+ (unwind-protect
+ (progn
+ (should (file-exists-p tmp-name1))
+ ;; `set-file-modes' is not implemented.
+ (should-error
+ (set-file-modes tmp-name1 #o777)
+ :type 'file-error)
+ (should (= (file-modes tmp-name1) #o400))
+ (should-not (file-executable-p tmp-name1))
+ (should-not (file-writable-p tmp-name1))
+
+ (should (file-exists-p tmp-name2))
+ ;; `set-file-modes' is not implemented.
+ (should-error
+ (set-file-modes tmp-name2 #o777)
+ :type 'file-error)
+ (should (= (file-modes tmp-name2) #o500))
+ (should (file-executable-p tmp-name2))
+ (should-not (file-writable-p tmp-name2)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test21-file-links ()
+ "Check `file-symlink-p' and `file-truename'"
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ ;; We must use `file-truename' for the file archive, because it
+ ;; could be located on a symlinked directory. This would let the
+ ;; test fail.
+ (let* ((tramp-archive-test-archive (file-truename tramp-archive-test-archive))
+ (tmp-name1 (expand-file-name "foo.txt" tramp-archive-test-archive))
+ (tmp-name2 (expand-file-name "foo.lnk" tramp-archive-test-archive)))
+
+ (unwind-protect
+ (progn
+ (should (file-exists-p tmp-name1))
+ (should (string-equal tmp-name1 (file-truename tmp-name1)))
+ ;; `make-symbolic-link' is not implemented.
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name2)
+ :type 'file-error)
+ (should (file-symlink-p tmp-name2))
+ (should
+ (string-equal
+ ;; This is "/foo.txt".
+ (with-parsed-tramp-archive-file-name tmp-name1 nil localname)
+ ;; `file-symlink-p' returns "foo.txt". Wer must expand, therefore.
+ (with-parsed-tramp-archive-file-name
+ (expand-file-name
+ (file-symlink-p tmp-name2) tramp-archive-test-archive)
+ nil
+ localname)))
+ (should-not (string-equal tmp-name2 (file-truename tmp-name2)))
+ (should
+ (string-equal (file-truename tmp-name1) (file-truename tmp-name2)))
+ (should (file-equal-p tmp-name1 tmp-name2)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+(ert-deftest tramp-archive-test26-file-name-completion ()
+ "Check `file-name-completion' and `file-name-all-completions'."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+
+ (let ((tmp-name tramp-archive-test-archive))
+ (unwind-protect
+ (progn
+ ;; Local files.
+ (should (equal (file-name-completion "fo" tmp-name) "foo."))
+ (should (equal (file-name-completion "foo.txt" tmp-name) t))
+ (should (equal (file-name-completion "b" tmp-name) "ba"))
+ (should-not (file-name-completion "a" tmp-name))
+ (should
+ (equal
+ (file-name-completion "b" tmp-name 'file-directory-p) "bar/"))
+ (should
+ (equal
+ (sort (file-name-all-completions "fo" tmp-name) 'string-lessp)
+ '("foo.hrd" "foo.lnk" "foo.txt")))
+ (should
+ (equal
+ (sort (file-name-all-completions "b" tmp-name) 'string-lessp)
+ '("bar/" "baz.tar")))
+ (should-not (file-name-all-completions "a" tmp-name))
+ ;; `completion-regexp-list' restricts the completion to
+ ;; files which match all expressions in this list.
+ (let ((completion-regexp-list
+ `(,directory-files-no-dot-files-regexp "b")))
+ (should
+ (equal (file-name-completion "" tmp-name) "ba"))
+ (should
+ (equal
+ (sort (file-name-all-completions "" tmp-name) 'string-lessp)
+ '("bar/" "baz.tar")))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))))
+
+;; The functions were introduced in Emacs 26.1.
+(ert-deftest tramp-archive-test38-make-nearby-temp-file ()
+ "Check `make-nearby-temp-file' and `temporary-file-directory'."
+ (skip-unless tramp-archive-enabled)
+ ;; Since Emacs 26.1.
+ (skip-unless
+ (and (fboundp 'make-nearby-temp-file) (fboundp 'temporary-file-directory)))
+
+ ;; `make-nearby-temp-file' and `temporary-file-directory' exists
+ ;; since Emacs 26.1. We don't want to see compiler warnings for
+ ;; older Emacsen.
+ (let ((default-directory tramp-archive-test-archive)
+ tmp-file)
+ ;; The file archive shall know a temporary file directory. It is
+ ;; not in the archive itself.
+ (should
+ (stringp (with-no-warnings (with-no-warnings (temporary-file-directory)))))
+ (should-not
+ (tramp-archive-file-name-p (with-no-warnings (temporary-file-directory))))
+
+ ;; A temporary file or directory shall not be located in the
+ ;; archive itself.
+ (setq tmp-file
+ (with-no-warnings (make-nearby-temp-file "tramp-archive-test")))
+ (should (file-exists-p tmp-file))
+ (should (file-regular-p tmp-file))
+ (should-not (tramp-archive-file-name-p tmp-file))
+ (delete-file tmp-file)
+ (should-not (file-exists-p tmp-file))
+
+ (setq tmp-file
+ (with-no-warnings (make-nearby-temp-file "tramp-archive-test" 'dir)))
+ (should (file-exists-p tmp-file))
+ (should (file-directory-p tmp-file))
+ (should-not (tramp-archive-file-name-p tmp-file))
+ (delete-directory tmp-file)
+ (should-not (file-exists-p tmp-file))))
+
+(ert-deftest tramp-archive-test41-file-system-info ()
+ "Check that `file-system-info' returns proper values."
+ (skip-unless tramp-archive-enabled)
+ ;; Since Emacs 27.1.
+ (skip-unless (fboundp 'file-system-info))
+
+ ;; `file-system-info' exists since Emacs 27. We don't want to see
+ ;; compiler warnings for older Emacsen.
+ (let ((fsi (with-no-warnings (file-system-info tramp-archive-test-archive))))
+ (skip-unless fsi)
+ (should (and (consp fsi)
+ (= (length fsi) 3)
+ (numberp (nth 0 fsi))
+ ;; FREE and AVAIL are always 0.
+ (zerop (nth 1 fsi))
+ (zerop (nth 2 fsi))))))
+
+(ert-deftest tramp-archive-test44-auto-load ()
+ "Check that `tramp-archive' autoloads properly."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+ ;; Autoloading tramp-archive works since Emacs 27.1.
+ (skip-unless (tramp-archive--test-emacs27-p))
+
+ ;; tramp-archive is neither loaded at Emacs startup, nor when
+ ;; loading a file like "/mock::foo" (which loads Tramp).
+ (let ((default-directory (expand-file-name temporary-file-directory))
+ (code
+ "(progn \
+ (message \"tramp-archive loaded: %%s %%s\" \
+ (featurep 'tramp) (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s %%s\" \
+ (featurep 'tramp) (featurep 'tramp-archive)))"))
+ (dolist (file `("/mock::foo" ,(concat tramp-archive-test-archive "foo")))
+ (should
+ (string-match
+ (format
+ "tramp-archive loaded: nil nil[[:ascii:]]+tramp-archive loaded: t %s"
+ (tramp-archive-file-name-p file))
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat 'shell-quote-argument load-path " -L ")
+ (shell-quote-argument (format code file)))))))))
+
+(ert-deftest tramp-archive-test44-delay-load ()
+ "Check that `tramp-archive' is loaded lazily, only when needed."
+ :tags '(:expensive-test)
+ (skip-unless tramp-archive-enabled)
+ ;; Autoloading tramp-archive works since Emacs 27.1.
+ (skip-unless (tramp-archive--test-emacs27-p))
+
+ ;; tramp-archive is neither loaded at Emacs startup, nor when
+ ;; loading a file like "/foo.tar". It is loaded only when
+ ;; `tramp-archive-enabled' is t.
+ (let ((default-directory (expand-file-name temporary-file-directory))
+ (code
+ "(progn \
+ (setq tramp-archive-enabled %s) \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)) \
+ (file-attributes %S \"/\") \
+ (message \"tramp-archive loaded: %%s\" \
+ (featurep 'tramp-archive)))"))
+ ;; tramp-archive doesn't load when `tramp-archive-enabled' is nil.
+ (dolist (tae '(t nil))
+ (should
+ (string-match
+ (format
+ "tramp-archive loaded: nil[[:ascii:]]+tramp-archive loaded: nil[[:ascii:]]+tramp-archive loaded: %s"
+ tae)
+ (shell-command-to-string
+ (format
+ "%s -batch -Q -L %s --eval %s"
+ (shell-quote-argument
+ (expand-file-name invocation-name invocation-directory))
+ (mapconcat 'shell-quote-argument load-path " -L ")
+ (shell-quote-argument
+ (format
+ code tae tramp-archive-test-file-archive
+ (concat tramp-archive-test-archive "foo"))))))))))
+
+(ert-deftest tramp-archive-test99-libarchive-tests ()
+ "Run tests of libarchive test files."
+ :tags '(:expensive-test :unstable)
+ (skip-unless tramp-archive-enabled)
+ ;; We do not want to run unless chosen explicitly. This test makes
+ ;; sense only in my local environment. Michael Albinus.
+ (skip-unless
+ (equal
+ (ert--stats-selector ert--current-run-stats)
+ (ert-test-name (ert-running-test))))
+
+ (url-handler-mode)
+ (unwind-protect
+ (dolist (dir
+ '("~/Downloads" "/sftp::~/Downloads" "/ssh::~/Downloads"
+ "http://ftp.debian.org/debian/pool/main/c/coreutils"))
+ (dolist
+ (file
+ '("coreutils_8.26-3_amd64.deb"
+ "coreutils_8.26-3ubuntu3_amd64.deb"))
+ (setq file (expand-file-name file dir))
+ (when (file-exists-p file)
+ (setq file (expand-file-name "control.tar.gz/control" file))
+ (message "%s" file)
+ (should (file-attributes (file-name-as-directory file))))))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash))
+
+ (unwind-protect
+ (dolist (dir '("" "/sftp::" "/ssh::"))
+ (dolist
+ (file
+ (apply
+ 'append
+ (mapcar
+ (lambda (x) (directory-files (concat dir x) 'full "uu\\'" 'sort))
+ '("~/src/libarchive-3.2.2/libarchive/test"
+ "~/src/libarchive-3.2.2/cpio/test"
+ "~/src/libarchive-3.2.2/tar/test"))))
+ (setq file (file-name-as-directory file))
+ (cond
+ ((not (tramp-archive-file-name-p file))
+ (message "skipped: %s" file))
+ ((file-attributes file)
+ (message "%s" file))
+ (t (message "failed: %s" file)))
+ (tramp-archive-cleanup-hash)))
+
+ ;; Cleanup.
+ (tramp-archive-cleanup-hash)))
+
+(defun tramp-archive-test-all (&optional interactive)
+ "Run all tests for \\[tramp-archive]."
+ (interactive "p")
+ (funcall
+ (if interactive 'ert-run-tests-interactively 'ert-run-tests-batch)
+ "^tramp-archive"))
+
+(provide 'tramp-archive-tests)
+;;; tramp-archive-tests.el ends here
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 8f810818af1..523c7afada8 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -33,7 +33,7 @@
;; remote host, set this environment variable to "/dev/null" or
;; whatever is appropriate on your system.
-;; For slow remote connections, `tramp-test41-asynchronous-requests'
+;; For slow remote connections, `tramp-test42-asynchronous-requests'
;; might be too heavy. Setting $REMOTE_PARALLEL_PROCESSES to a proper
;; value less than 10 could help.
@@ -52,14 +52,23 @@
(declare-function tramp-find-executable "tramp-sh")
(declare-function tramp-get-remote-path "tramp-sh")
-(declare-function tramp-get-remote-stat "tramp-sh")
(declare-function tramp-get-remote-perl "tramp-sh")
+(declare-function tramp-get-remote-stat "tramp-sh")
+(declare-function tramp-method-out-of-band-p "tramp-sh")
+(declare-function tramp-smb-get-localname "tramp-smb")
(defvar auto-save-file-name-transforms)
(defvar tramp-copy-size-limit)
(defvar tramp-persistency-file-name)
(defvar tramp-remote-process-environment)
-;; Suppress nasty messages.
-(fset 'shell-command-sentinel 'ignore)
+
+;; Beautify batch mode.
+(when noninteractive
+ ;; Suppress nasty messages.
+ (fset 'shell-command-sentinel 'ignore)
+ ;; We do not want to be interrupted.
+ (eval-after-load 'tramp-gvfs
+ '(fset 'tramp-gvfs-handler-askquestion
+ (lambda (_message _choices) '(t nil 0)))))
;; There is no default value on w32 systems, which could work out of the box.
(defconst tramp-test-temporary-file-directory
@@ -84,7 +93,8 @@
(format "/mock::%s" temporary-file-directory)))
"Temporary directory for Tramp tests.")
-(setq password-cache-expiry nil
+(setq auth-source-save-behavior nil
+ password-cache-expiry nil
tramp-verbose 0
tramp-cache-read-persistent-data t ;; For auth-sources.
tramp-copy-size-limit nil
@@ -95,11 +105,6 @@
(when (getenv "EMACS_HYDRA_CI")
(add-to-list 'tramp-remote-path 'tramp-own-remote-path))
-(defvar tramp--test-expensive-test
- (null
- (string-equal (getenv "SELECTOR") "(quote (not (tag :expensive-test)))"))
- "Whether expensive tests are run.")
-
(defvar tramp--test-enabled-checked nil
"Cached result of `tramp--test-enabled'.
If the function did run, the value is a cons cell, the `cdr'
@@ -127,6 +132,13 @@ being the result.")
;; Return result.
(cdr tramp--test-enabled-checked))
+(defsubst tramp--test-expensive-test ()
+ "Whether expensive tests are run."
+ (ert-select-tests
+ (ert--stats-selector ert--current-run-stats)
+ (list (make-ert-test :name (ert-test-name (ert-running-test))
+ :body nil :tags '(:expensive-test)))))
+
(defun tramp--test-make-temp-name (&optional local quoted)
"Return a temporary file name for test.
If LOCAL is non-nil, a local file name is returned.
@@ -179,6 +191,16 @@ handled properly. BODY shall not contain a timeout."
(tramp-backtrace
(tramp-dissect-file-name tramp-test-temporary-file-directory))))
+(defmacro tramp--test-print-duration (message &rest body)
+ "Run BODY and print a message with duration, prompted by MESSAGE."
+ (declare (indent 1) (debug (stringp body)))
+ `(let ((start (current-time)))
+ (unwind-protect
+ (progn ,@body)
+ (tramp--test-message
+ "%s %f sec"
+ ,message (float-time (time-subtract (current-time) start))))))
+
(ert-deftest tramp-test00-availability ()
"Test availability of Tramp functions."
:expected-result (if (tramp--test-enabled) :passed :failed)
@@ -229,6 +251,9 @@ handled properly. BODY shall not contain a timeout."
;; No strings.
(should-not (tramp-tramp-file-p nil))
(should-not (tramp-tramp-file-p 'symbol))
+ ;; No newline or linefeed.
+ (should-not (tramp-tramp-file-p "/method::file\nname"))
+ (should-not (tramp-tramp-file-p "/method::file\rname"))
;; Ange-ftp syntax.
(should-not (tramp-tramp-file-p "/host:"))
(should-not (tramp-tramp-file-p "/user@host:"))
@@ -242,6 +267,12 @@ handled properly. BODY shall not contain a timeout."
(should-not (tramp-tramp-file-p "/::"))
(should-not (tramp-tramp-file-p "/:@:"))
(should-not (tramp-tramp-file-p "/:[]:"))
+ ;; When `tramp-mode' is nil, Tramp is not activated.
+ (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:"))
+ (should-not (tramp-tramp-file-p "/method:user@host:")))
;; Methods shall be at least two characters on MS Windows, except
;; the default method.
(let ((system-type 'windows-nt))
@@ -365,7 +396,10 @@ handled properly. BODY shall not contain a timeout."
"Check remote file name components."
(let ((tramp-default-method "default-method")
(tramp-default-user "default-user")
- (tramp-default-host "default-host"))
+ (tramp-default-host "default-host")
+ tramp-default-method-alist
+ tramp-default-user-alist
+ tramp-default-host-alist)
;; Expand `tramp-default-user' and `tramp-default-host'.
(should (string-equal
(file-remote-p "/method::")
@@ -715,7 +749,55 @@ handled properly. BODY shall not contain a timeout."
"|method3:user3@host3:/path/to/file")
'hop)
(format "%s:%s@%s|%s:%s@%s|"
- "method1" "user1" "host1" "method2" "user2" "host2")))))
+ "method1" "user1" "host1" "method2" "user2" "host2")))
+
+ ;; Expand `tramp-default-method-alist'.
+ (add-to-list 'tramp-default-method-alist '("host1" "user1" "method1"))
+ (add-to-list 'tramp-default-method-alist '("host2" "user2" "method2"))
+ (add-to-list 'tramp-default-method-alist '("host3" "user3" "method3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/-:user1@host1"
+ "|-:user2@host2"
+ "|-:user3@host3:/path/to/file"))
+ (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
+ "-" "user1" "host1"
+ "-" "user2" "host2"
+ "method3" "user3" "host3")))
+
+ ;; Expand `tramp-default-user-alist'.
+ (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
+ (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
+ (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:host1"
+ "|method2:host2"
+ "|method3:host3:/path/to/file"))
+ (format "/%s:%s|%s:%s|%s:%s@%s:"
+ "method1" "host1"
+ "method2" "host2"
+ "method3" "user3" "host3")))
+
+ ;; Expand `tramp-default-host-alist'.
+ (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
+ (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
+ (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/method1:user1@"
+ "|method2:user2@"
+ "|method3:user3@:/path/to/file"))
+ (format "/%s:%s@|%s:%s@|%s:%s@%s:"
+ "method1" "user1"
+ "method2" "user2"
+ "method3" "user3" "host3")))))
(ert-deftest tramp-test02-file-name-dissect-simplified ()
"Check simplified file name components."
@@ -723,6 +805,8 @@ handled properly. BODY shall not contain a timeout."
(let ((tramp-default-method "default-method")
(tramp-default-user "default-user")
(tramp-default-host "default-host")
+ tramp-default-user-alist
+ tramp-default-host-alist
(syntax tramp-syntax))
(unwind-protect
(progn
@@ -970,7 +1054,39 @@ handled properly. BODY shall not contain a timeout."
"|user3@host3:/path/to/file")
'hop)
(format "%s@%s|%s@%s|"
- "user1" "host1" "user2" "host2"))))
+ "user1" "host1" "user2" "host2")))
+
+ ;; Expand `tramp-default-user-alist'.
+ (add-to-list 'tramp-default-user-alist '(nil "host1" "user1"))
+ (add-to-list 'tramp-default-user-alist '(nil "host2" "user2"))
+ (add-to-list 'tramp-default-user-alist '(nil "host3" "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/host1"
+ "|host2"
+ "|host3:/path/to/file"))
+ (format "/%s|%s|%s@%s:"
+ "host1"
+ "host2"
+ "user3" "host3")))
+
+ ;; Expand `tramp-default-host-alist'.
+ (add-to-list 'tramp-default-host-alist '(nil "user1" "host1"))
+ (add-to-list 'tramp-default-host-alist '(nil "user2" "host2"))
+ (add-to-list 'tramp-default-host-alist '(nil "user3" "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/user1@"
+ "|user2@"
+ "|user3@:/path/to/file"))
+ (format "/%s@|%s@|%s@%s:"
+ "user1"
+ "user2"
+ "user3" "host3"))))
;; Exit.
(tramp-change-syntax syntax))))
@@ -981,6 +1097,9 @@ handled properly. BODY shall not contain a timeout."
(let ((tramp-default-method "default-method")
(tramp-default-user "default-user")
(tramp-default-host "default-host")
+ tramp-default-method-alist
+ tramp-default-user-alist
+ tramp-default-host-alist
(syntax tramp-syntax))
(unwind-protect
(progn
@@ -1538,7 +1657,55 @@ handled properly. BODY shall not contain a timeout."
"|method3/user3@host3]/path/to/file")
'hop)
(format "%s/%s@%s|%s/%s@%s|"
- "method1" "user1" "host1" "method2" "user2" "host2"))))
+ "method1" "user1" "host1" "method2" "user2" "host2")))
+
+ ;; Expand `tramp-default-method-alist'.
+ (add-to-list 'tramp-default-method-alist '("host1" "user1" "method1"))
+ (add-to-list 'tramp-default-method-alist '("host2" "user2" "method2"))
+ (add-to-list 'tramp-default-method-alist '("host3" "user3" "method3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[/user1@host1"
+ "|/user2@host2"
+ "|/user3@host3]/path/to/file"))
+ (format "/[/%s@%s|/%s@%s|%s/%s@%s]"
+ "user1" "host1"
+ "user2" "host2"
+ "method3" "user3" "host3")))
+
+ ;; Expand `tramp-default-user-alist'.
+ (add-to-list 'tramp-default-user-alist '("method1" "host1" "user1"))
+ (add-to-list 'tramp-default-user-alist '("method2" "host2" "user2"))
+ (add-to-list 'tramp-default-user-alist '("method3" "host3" "user3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[method1/host1"
+ "|method2/host2"
+ "|method3/host3]/path/to/file"))
+ (format "/[%s/%s|%s/%s|%s/%s@%s]"
+ "method1" "host1"
+ "method2" "host2"
+ "method3" "user3" "host3")))
+
+ ;; Expand `tramp-default-host-alist'.
+ (add-to-list 'tramp-default-host-alist '("method1" "user1" "host1"))
+ (add-to-list 'tramp-default-host-alist '("method2" "user2" "host2"))
+ (add-to-list 'tramp-default-host-alist '("method3" "user3" "host3"))
+ (should
+ (string-equal
+ (file-remote-p
+ (concat
+ "/[method1/user1@"
+ "|method2/user2@"
+ "|method3/user3@]/path/to/file"))
+ (format "/[%s/%s@|%s/%s@|%s/%s@%s]"
+ "method1" "user1"
+ "method2" "user2"
+ "method3" "user3" "host3"))))
;; Exit.
(tramp-change-syntax syntax))))
@@ -1567,41 +1734,103 @@ handled properly. BODY shall not contain a timeout."
;; Default values in tramp-smb.el.
(should (string-equal (file-remote-p "/smb::" 'user) nil)))
+;; The following test is inspired by Bug#30946.
+(ert-deftest tramp-test03-file-name-host-rules ()
+ "Check host name rules for host-less methods."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (tramp--test-sh-p))
+ ;; `user-error' has appeared in Emacs 24.3.
+ (skip-unless (fboundp 'user-error))
+
+ ;; Host names must match rules in case the command template of a
+ ;; method doesn't use them.
+ (dolist (m '("su" "sg" "sudo" "doas" "ksu"))
+ (let ((vec (tramp-dissect-file-name tramp-test-temporary-file-directory))
+ tramp-connection-properties tramp-default-proxies-alist)
+ (ignore-errors (tramp-cleanup-connection vec nil 'keep-password))
+ ;; Single hop. The host name must match `tramp-local-host-regexp'.
+ (should-error
+ (find-file (format "/%s:foo:" m))
+ :type 'user-error)
+ ;; Multi hop. The host name must match the previous hop.
+ (should-error
+ (find-file
+ (format
+ "%s|%s:foo:"
+ (substring (file-remote-p tramp-test-temporary-file-directory) 0 -1)
+ m))
+ :type
+ (if (tramp-method-out-of-band-p vec 0) 'file-error 'user-error)))))
+
+(ert-deftest tramp-test03-file-name-method-rules ()
+ "Check file name rules for some methods."
+ (skip-unless (tramp--test-enabled))
+
+ ;; Samba does not support file names with periods followed by
+ ;; spaces, and trailing periods or spaces.
+ (when (tramp-smb-file-name-p tramp-test-temporary-file-directory)
+ (dolist (file '("foo." "foo. bar" "foo "))
+ (should-error
+ (tramp-smb-get-localname
+ (tramp-dissect-file-name
+ (expand-file-name file tramp-test-temporary-file-directory)))
+ :type 'file-error))))
+
(ert-deftest tramp-test04-substitute-in-file-name ()
"Check `substitute-in-file-name'."
- (should (string-equal (substitute-in-file-name "/method:host://foo") "/foo"))
+ (should (string-equal (substitute-in-file-name "/method:host:///foo") "/foo"))
(should
(string-equal
- (substitute-in-file-name "/method:host:/path//foo") "/method:host:/foo"))
+ (substitute-in-file-name "/method:host://foo") "/method:host:/foo"))
(should
(string-equal (substitute-in-file-name "/method:host:/path///foo") "/foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/path//foo") "/method:host:/foo"))
;; Quoting local part.
(should
(string-equal
- (substitute-in-file-name "/method:host:/://foo") "/method:host:/://foo"))
+ (substitute-in-file-name "/method:host:/:///foo") "/method:host:/:///foo"))
(should
(string-equal
- (substitute-in-file-name "/method:host:/:/path//foo")
- "/method:host:/:/path//foo"))
+ (substitute-in-file-name "/method:host:/://foo") "/method:host:/://foo"))
(should
(string-equal
(substitute-in-file-name "/method:host:/:/path///foo")
"/method:host:/:/path///foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/path//foo")
+ "/method:host:/:/path//foo"))
(should
+ (string-equal (substitute-in-file-name "/method:host://~foo") "/~foo"))
+ (should
(string-equal
- (substitute-in-file-name "/method:host:/path/~/foo") "/method:host:~/foo"))
+ (substitute-in-file-name "/method:host:/~foo") "/method:host:/~foo"))
+ (should
+ (string-equal (substitute-in-file-name "/method:host:/path//~foo") "/~foo"))
+ ;; (substitute-in-file-name "/path/~foo") expands only for a local
+ ;; user "foo" to "/~foo"". Otherwise, it doesn't expand.
(should
- (string-equal (substitute-in-file-name "/method:host:/path//~/foo") "~/foo"))
+ (string-equal
+ (substitute-in-file-name
+ "/method:host:/path/~foo") "/method:host:/path/~foo"))
;; Quoting local part.
(should
(string-equal
- (substitute-in-file-name "/method:host:/:/path/~/foo")
- "/method:host:/:/path/~/foo"))
+ (substitute-in-file-name "/method:host:/://~foo") "/method:host:/://~foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name "/method:host:/:/~foo") "/method:host:/:/~foo"))
+ (should
+ (string-equal
+ (substitute-in-file-name
+ "/method:host:/:/path//~foo") "/method:host:/:/path//~foo"))
(should
(string-equal
- (substitute-in-file-name "/method:host:/:/path//~/foo")
- "/method:host:/:/path//~/foo"))
+ (substitute-in-file-name
+ "/method:host:/:/path/~foo") "/method:host:/:/path/~foo"))
(let (process-environment)
(should
@@ -1661,6 +1890,7 @@ handled properly. BODY shall not contain a timeout."
;; Mark as failed until bug has been fixed.
:expected-result :failed
(skip-unless (tramp--test-enabled))
+
;; These are the methods the test doesn't fail.
(when (or (tramp--test-adb-p) (tramp--test-gvfs-p)
(tramp-smb-file-name-p tramp-test-temporary-file-directory))
@@ -1709,6 +1939,14 @@ This checks also `file-name-as-directory', `file-name-directory',
(file-name-directory "/method:host:/path/to/file/")
"/method:host:/path/to/file/"))
(should
+ (string-equal (file-name-directory "/method:host:file") "/method:host:"))
+ (should
+ (string-equal
+ (file-name-directory "/method:host:path/") "/method:host:path/"))
+ (should
+ (string-equal
+ (file-name-directory "/method:host:path/to") "/method:host:path/"))
+ (should
(string-equal (file-name-nondirectory "/method:host:/path/to/file") "file"))
(should
(string-equal (file-name-nondirectory "/method:host:/path/to/file/") ""))
@@ -1743,7 +1981,7 @@ This checks also `file-name-as-directory', `file-name-directory',
"Check `file-exist-p', `write-region' and `delete-file'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(should-not (file-exists-p tmp-name))
(write-region "foo" nil tmp-name)
@@ -1755,7 +1993,7 @@ This checks also `file-name-as-directory', `file-name-directory',
"Check `file-local-copy'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
tmp-name2)
(unwind-protect
@@ -1787,7 +2025,7 @@ This checks also `file-name-as-directory', `file-name-directory',
"Check `insert-file-contents'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(with-temp-buffer
@@ -1815,7 +2053,7 @@ This checks also `file-name-as-directory', `file-name-directory',
"Check `write-region'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
@@ -1905,7 +2143,7 @@ This checks also `file-name-as-directory', `file-name-directory',
(skip-unless (tramp--test-enabled))
;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
- (dolist (quoted (if (and tramp--test-expensive-test (tramp--test-emacs27-p))
+ (dolist (quoted (if (and (tramp--test-expensive-test) (tramp--test-emacs27-p))
'(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
@@ -1930,9 +2168,10 @@ This checks also `file-name-as-directory', `file-name-directory',
(with-temp-buffer
(insert-file-contents target)
(should (string-equal (buffer-string) "foo")))
- (should-error
- (copy-file source target)
- :type 'file-already-exists)
+ (when (tramp--test-expensive-test)
+ (should-error
+ (copy-file source target)
+ :type 'file-already-exists))
(copy-file source target 'ok))
;; Cleanup.
@@ -1941,13 +2180,15 @@ This checks also `file-name-as-directory', `file-name-directory',
;; Copy file to directory.
(unwind-protect
- (progn
+ ;; FIXME: This fails on my QNAP server, see
+ ;; /share/Web/owncloud/data/owncloud.log
+ (unless (tramp--test-nextcloud-p)
(write-region "foo" nil source)
(should (file-exists-p source))
(make-directory target)
(should (file-directory-p target))
;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
+ (when (and (tramp--test-expensive-test) (tramp--test-emacs26-p))
(should-error
(copy-file source target)
:type 'file-already-exists))
@@ -1962,7 +2203,11 @@ This checks also `file-name-as-directory', `file-name-directory',
;; Copy directory to existing directory.
(unwind-protect
- (progn
+ ;; FIXME: This fails on my QNAP server, see
+ ;; /share/Web/owncloud/data/owncloud.log
+ (unless (and (tramp--test-nextcloud-p)
+ (or (not (file-remote-p source))
+ (not (file-remote-p target))))
(make-directory source)
(should (file-directory-p source))
(write-region "foo" nil (expand-file-name "foo" source))
@@ -1983,7 +2228,10 @@ This checks also `file-name-as-directory', `file-name-directory',
;; Copy directory/file to non-existing directory.
(unwind-protect
- (progn
+ ;; FIXME: This fails on my QNAP server, see
+ ;; /share/Web/owncloud/data/owncloud.log
+ (unless
+ (and (tramp--test-nextcloud-p) (not (file-remote-p source)))
(make-directory source)
(should (file-directory-p source))
(write-region "foo" nil (expand-file-name "foo" source))
@@ -2007,7 +2255,7 @@ This checks also `file-name-as-directory', `file-name-directory',
(skip-unless (tramp--test-enabled))
;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
- (dolist (quoted (if (and tramp--test-expensive-test (tramp--test-emacs27-p))
+ (dolist (quoted (if (and (tramp--test-expensive-test) (tramp--test-emacs27-p))
'(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
@@ -2035,9 +2283,10 @@ This checks also `file-name-as-directory', `file-name-directory',
(should (string-equal (buffer-string) "foo")))
(write-region "foo" nil source)
(should (file-exists-p source))
- (should-error
- (rename-file source target)
- :type 'file-already-exists)
+ (when (tramp--test-expensive-test)
+ (should-error
+ (rename-file source target)
+ :type 'file-already-exists))
(rename-file source target 'ok)
(should-not (file-exists-p source)))
@@ -2053,7 +2302,7 @@ This checks also `file-name-as-directory', `file-name-directory',
(make-directory target)
(should (file-directory-p target))
;; This has been changed in Emacs 26.1.
- (when (tramp--test-emacs26-p)
+ (when (and (tramp--test-expensive-test) (tramp--test-emacs26-p))
(should-error
(rename-file source target)
:type 'file-already-exists))
@@ -2069,7 +2318,9 @@ This checks also `file-name-as-directory', `file-name-directory',
;; Rename directory to existing directory.
(unwind-protect
- (progn
+ ;; FIXME: This fails on my QNAP server, see
+ ;; /share/Web/owncloud/data/owncloud.log
+ (unless (tramp--test-nextcloud-p)
(make-directory source)
(should (file-directory-p source))
(write-region "foo" nil (expand-file-name "foo" source))
@@ -2091,7 +2342,9 @@ This checks also `file-name-as-directory', `file-name-directory',
;; Rename directory/file to non-existing directory.
(unwind-protect
- (progn
+ ;; FIXME: This fails on my QNAP server, see
+ ;; /share/Web/owncloud/data/owncloud.log
+ (unless (tramp--test-nextcloud-p)
(make-directory source)
(should (file-directory-p source))
(write-region "foo" nil (expand-file-name "foo" source))
@@ -2116,7 +2369,7 @@ This checks also `file-name-as-directory', `file-name-directory',
This tests also `file-directory-p' and `file-accessible-directory-p'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo/bar" tmp-name1)))
(unwind-protect
@@ -2139,7 +2392,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `delete-directory'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
;; Delete empty directory.
(make-directory tmp-name)
@@ -2159,7 +2412,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `copy-directory'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (expand-file-name
@@ -2225,7 +2478,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `directory-files'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "bla" tmp-name1))
(tmp-name3 (expand-file-name "foo" tmp-name1)))
@@ -2258,7 +2511,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `file-expand-wildcards'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo" tmp-name1))
(tmp-name3 (expand-file-name "bar" tmp-name1))
@@ -2322,7 +2575,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
"Check `insert-directory'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name1
(expand-file-name (tramp--test-make-temp-name nil quoted)))
(tmp-name2 (expand-file-name "foo" tmp-name1))
@@ -2383,7 +2636,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
;; Since Emacs 26.1.
(skip-unless (fboundp 'insert-directory-wildcard-in-dir-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name1
(expand-file-name (tramp--test-make-temp-name nil quoted)))
(tmp-name2
@@ -2500,7 +2753,7 @@ This tests also `file-readable-p', `file-regular-p' and
`file-ownership-preserved-p'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
@@ -2607,7 +2860,7 @@ This tests also `file-readable-p', `file-regular-p' and
"Check `directory-files-and-attributes'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
;; `directory-files-and-attributes' contains also values for
;; "../". Ensure that this doesn't change during tests, for
;; example due to handling temporary files.
@@ -2629,16 +2882,17 @@ This tests also `file-readable-p', `file-regular-p' and
;; able to return the date correctly. They say "don't know".
(dolist (elt attr)
(unless
- (equal
+ (tramp-compat-time-equal-p
(nth
5 (file-attributes (expand-file-name (car elt) tmp-name2)))
- '(0 0))
+ tramp-time-dont-know)
(should
(equal (file-attributes (expand-file-name (car elt) tmp-name2))
(cdr elt)))))
(setq attr (directory-files-and-attributes tmp-name2 'full))
(dolist (elt attr)
- (unless (equal (nth 5 (file-attributes (car elt))) '(0 0))
+ (unless (tramp-compat-time-equal-p
+ (nth 5 (file-attributes (car elt))) tramp-time-dont-know)
(should
(equal (file-attributes (car elt)) (cdr elt)))))
(setq attr (directory-files-and-attributes tmp-name2 nil "^b"))
@@ -2653,7 +2907,7 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
@@ -2673,15 +2927,27 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
;; Cleanup.
(ignore-errors (delete-file tmp-name))))))
+;; Method "smb" could run into "NT_STATUS_REVISION_MISMATCH" error.
+(defmacro tramp--test-ignore-add-name-to-file-error (&rest body)
+ "Run BODY, ignoring \"error with add-name-to-file\" file error."
+ (declare (indent defun) (debug t))
+ `(condition-case err
+ (progn ,@body)
+ ((error quit debug)
+ (unless (and (eq (car err) 'file-error)
+ (string-match "^error with add-name-to-file"
+ (error-message-string err)))
+ (signal (car err) (cdr err))))))
+
(ert-deftest tramp-test21-file-links ()
"Check `file-symlink-p'.
This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (tramp--test-enabled))
- ;; The semantics has changed heavily in Emacs 26.1. We cannot test
+ ;; The semantics have changed heavily in Emacs 26.1. We cannot test
;; older Emacsen, therefore.
(skip-unless (tramp--test-emacs26-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
;; would let the test fail.
@@ -2705,14 +2971,16 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(if quoted 'tramp-compat-file-name-unquote 'identity)
(file-remote-p tmp-name1 'localname))
(file-symlink-p tmp-name2)))
- (should-error
- (make-symbolic-link tmp-name1 tmp-name2)
- :type 'file-already-exists)
- ;; A number means interactive case.
- (cl-letf (((symbol-function 'yes-or-no-p) 'ignore))
+ (when (tramp--test-expensive-test)
(should-error
- (make-symbolic-link tmp-name1 tmp-name2 0)
+ (make-symbolic-link tmp-name1 tmp-name2)
:type 'file-already-exists))
+ (when (tramp--test-expensive-test)
+ ;; A number means interactive case.
+ (cl-letf (((symbol-function 'yes-or-no-p) 'ignore))
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name2 0)
+ :type 'file-already-exists)))
(cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
(make-symbolic-link tmp-name1 tmp-name2 0)
(should
@@ -2747,9 +3015,10 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(string-equal tmp-name1 (file-symlink-p tmp-name3))))
;; Check directory as newname.
(make-directory tmp-name4)
- (should-error
- (make-symbolic-link tmp-name1 tmp-name4)
- :type 'file-already-exists)
+ (when (tramp--test-expensive-test)
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name4)
+ :type 'file-already-exists))
(make-symbolic-link tmp-name1 (file-name-as-directory tmp-name4))
(should
(string-equal
@@ -2771,38 +3040,40 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Check `add-name-to-file'.
(unwind-protect
- (unless (tramp-smb-file-name-p tramp-test-temporary-file-directory)
- (write-region "foo" nil tmp-name1)
- (should (file-exists-p tmp-name1))
- (add-name-to-file tmp-name1 tmp-name2)
- (should (file-regular-p tmp-name2))
- (should-error
+ (when (tramp--test-expensive-test)
+ (tramp--test-ignore-add-name-to-file-error
+ (write-region "foo" nil tmp-name1)
+ (should (file-exists-p tmp-name1))
(add-name-to-file tmp-name1 tmp-name2)
- :type 'file-already-exists)
- ;; A number means interactive case.
- (cl-letf (((symbol-function 'yes-or-no-p) 'ignore))
- (should-error
- (add-name-to-file tmp-name1 tmp-name2 0)
- :type 'file-already-exists))
- (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
+ (should (file-regular-p tmp-name2))
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name2)
+ :type 'file-already-exists)
+ ;; A number means interactive case.
+ (cl-letf (((symbol-function 'yes-or-no-p) 'ignore))
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name2 0)
+ :type 'file-already-exists))
+ (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
(add-name-to-file tmp-name1 tmp-name2 0)
(should (file-regular-p tmp-name2)))
- (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
- (should-not (file-symlink-p tmp-name2))
- (should (file-regular-p tmp-name2))
- ;; `tmp-name3' is a local file name.
- (should-error
- (add-name-to-file tmp-name1 tmp-name3)
- :type 'file-error)
- ;; Check directory as newname.
- (make-directory tmp-name4)
- (should-error
- (add-name-to-file tmp-name1 tmp-name4)
- :type 'file-already-exists)
- (add-name-to-file tmp-name1 (file-name-as-directory tmp-name4))
- (should
- (file-regular-p
- (expand-file-name (file-name-nondirectory tmp-name1) tmp-name4))))
+ (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
+ (should-not (file-symlink-p tmp-name2))
+ (should (file-regular-p tmp-name2))
+ ;; `tmp-name3' is a local file name.
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name3)
+ :type 'file-error)
+ ;; Check directory as newname.
+ (make-directory tmp-name4)
+ (should-error
+ (add-name-to-file tmp-name1 tmp-name4)
+ :type 'file-already-exists)
+ (add-name-to-file tmp-name1 (file-name-as-directory tmp-name4))
+ (should
+ (file-regular-p
+ (expand-file-name
+ (file-name-nondirectory tmp-name1) tmp-name4)))))
;; Cleanup.
(ignore-errors
@@ -2882,12 +3153,14 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(string-equal
(file-truename tmp-name2)
(file-truename tmp-name3)))
- (should-error
- (with-temp-buffer (insert-file-contents tmp-name2))
- :type tramp-file-missing)
- (should-error
- (with-temp-buffer (insert-file-contents tmp-name3))
- :type tramp-file-missing)
+ (when (tramp--test-expensive-test)
+ (should-error
+ (with-temp-buffer (insert-file-contents tmp-name2))
+ :type tramp-file-missing))
+ (when (tramp--test-expensive-test)
+ (should-error
+ (with-temp-buffer (insert-file-contents tmp-name3))
+ :type tramp-file-missing))
;; `directory-files' does not show symlinks to
;; non-existing targets in the "smb" case. So we remove
;; the symlinks manually.
@@ -2900,32 +3173,41 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Detect cyclic symbolic links.
(unwind-protect
- (tramp--test-ignore-make-symbolic-link-error
- (make-symbolic-link tmp-name2 tmp-name1)
- (should (file-symlink-p tmp-name1))
- (make-symbolic-link tmp-name1 tmp-name2)
- (should (file-symlink-p tmp-name2))
- (should-error (file-truename tmp-name1) :type 'file-error))
+ (when (tramp--test-expensive-test)
+ (tramp--test-ignore-make-symbolic-link-error
+ (make-symbolic-link tmp-name2 tmp-name1)
+ (should (file-symlink-p tmp-name1))
+ (if (tramp-smb-file-name-p tramp-test-temporary-file-directory)
+ ;; The symlink command of `smbclient' detects the
+ ;; cycle already.
+ (should-error
+ (make-symbolic-link tmp-name1 tmp-name2)
+ :type 'file-error)
+ (make-symbolic-link tmp-name1 tmp-name2)
+ (should (file-symlink-p tmp-name2))
+ (should-error (file-truename tmp-name1) :type 'file-error))))
;; Cleanup.
(ignore-errors
(delete-file tmp-name1)
(delete-file tmp-name2)))
- ;; `file-truename' shall preserve trailing link of directories.
- (unless (file-symlink-p tramp-test-temporary-file-directory)
- (let* ((dir1 (directory-file-name tramp-test-temporary-file-directory))
- (dir2 (file-name-as-directory dir1)))
- (should (string-equal (file-truename dir1) (expand-file-name dir1)))
- (should
- (string-equal (file-truename dir2) (expand-file-name dir2))))))))
+ ;; `file-truename' shall preserve trailing slash of directories.
+ (let* ((dir1
+ (directory-file-name
+ (funcall
+ (if quoted 'tramp-compat-file-name-quote 'identity)
+ tramp-test-temporary-file-directory)))
+ (dir2 (file-name-as-directory dir1)))
+ (should (string-equal (file-truename dir1) (expand-file-name dir1)))
+ (should (string-equal (file-truename dir2) (expand-file-name dir2)))))))
(ert-deftest tramp-test22-file-times ()
"Check `set-file-times' and `file-newer-than-file-p'."
(skip-unless (tramp--test-enabled))
(skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (tramp--test-make-temp-name nil quoted)))
@@ -2934,15 +3216,15 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(write-region "foo" nil tmp-name1)
(should (file-exists-p tmp-name1))
(should (consp (nth 5 (file-attributes tmp-name1))))
- ;; '(0 0) means don't know, and will be replaced by
- ;; `current-time'. Therefore, we use '(0 1). We skip the
- ;; test, if the remote handler is not able to set the
- ;; correct time.
- (skip-unless (set-file-times tmp-name1 '(0 1)))
+ ;; Skip the test, if the remote handler is not able to set
+ ;; the correct time.
+ (skip-unless (set-file-times tmp-name1 (seconds-to-time 1)))
;; Dumb remote shells without perl(1) or stat(1) are not
;; able to return the date correctly. They say "don't know".
- (unless (equal (nth 5 (file-attributes tmp-name1)) '(0 0))
- (should (equal (nth 5 (file-attributes tmp-name1)) '(0 1)))
+ (unless (tramp-compat-time-equal-p
+ (nth 5 (file-attributes tmp-name1)) tramp-time-dont-know)
+ (should
+ (equal (nth 5 (file-attributes tmp-name1)) (seconds-to-time 1)))
(write-region "bla" nil tmp-name2)
(should (file-exists-p tmp-name2))
(should (file-newer-than-file-p tmp-name2 tmp-name1))
@@ -2959,7 +3241,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
"Check `set-visited-file-modtime' and `verify-visited-file-modtime'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
@@ -2968,9 +3250,17 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(with-temp-buffer
(insert-file-contents tmp-name)
(should (verify-visited-file-modtime))
- (set-visited-file-modtime '(0 1))
+ (set-visited-file-modtime (seconds-to-time 1))
(should (verify-visited-file-modtime))
- (should (equal (visited-file-modtime) '(0 1 0 0)))))
+ (should (= 1 (float-time (visited-file-modtime))))
+
+ ;; Checks with deleted file.
+ (delete-file tmp-name)
+ (dired-uncache tmp-name)
+ (should (verify-visited-file-modtime))
+ (set-visited-file-modtime (seconds-to-time 1))
+ (should (verify-visited-file-modtime))
+ (should (= 1 (float-time (visited-file-modtime))))))
;; Cleanup.
(ignore-errors (delete-file tmp-name))))))
@@ -2982,7 +3272,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (file-acl tramp-test-temporary-file-directory))
;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
- (dolist (quoted (if (and tramp--test-expensive-test (tramp--test-emacs27-p))
+ (dolist (quoted (if (and (tramp--test-expensive-test) (tramp--test-emacs27-p))
'(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
@@ -3060,7 +3350,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
'(nil nil nil nil))))
;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
- (dolist (quoted (if (and tramp--test-expensive-test (tramp--test-emacs27-p))
+ (dolist (quoted (if (and (tramp--test-expensive-test) (tramp--test-emacs27-p))
'(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
@@ -3208,7 +3498,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(unwind-protect
(dolist
(syntax
- (if tramp--test-expensive-test
+ (if (tramp--test-expensive-test)
(tramp-syntax-values) `(,orig-syntax)))
(tramp-change-syntax syntax)
(let ;; This is needed for the `simplified' syntax.
@@ -3259,7 +3549,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(tramp-change-syntax orig-syntax))))
(dolist (n-e '(nil t))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((non-essential n-e)
(tmp-name (tramp--test-make-temp-name nil quoted)))
@@ -3321,7 +3611,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
"Check `load'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted)))
(unwind-protect
(progn
@@ -3346,7 +3636,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (tramp--test-enabled))
(skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((tmp-name (tramp--test-make-temp-name nil quoted))
(fnnd (file-name-nondirectory tmp-name))
(default-directory tramp-test-temporary-file-directory)
@@ -3392,7 +3682,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((default-directory tramp-test-temporary-file-directory)
(tmp-name (tramp--test-make-temp-name nil quoted))
kill-buffer-query-functions proc)
@@ -3484,7 +3774,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name (tramp--test-make-temp-name nil quoted))
(default-directory tramp-test-temporary-file-directory)
;; Suppress nasty messages.
@@ -3740,13 +4030,55 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(put 'explicit-shell-file-name 'permanent-local nil)
(kill-buffer "*shell*"))))
-(ert-deftest tramp-test34-vc-registered ()
+;; `exec-path' was introduced in Emacs 27.1. `executable-find' has
+;; changed the number of parameters, so we use `apply' for older
+;; Emacsen.
+(ert-deftest tramp-test34-exec-path ()
+ "Check `exec-path' and `executable-find'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
+ ;; Since Emacs 27.1.
+ (skip-unless (fboundp 'exec-path))
+
+ (let ((tmp-name (tramp--test-make-temp-name))
+ (default-directory tramp-test-temporary-file-directory))
+ (unwind-protect
+ (progn
+ (should (consp (with-no-warnings (exec-path))))
+ ;; Last element is the `exec-directory'.
+ (should
+ (string-equal
+ (car (last (with-no-warnings (exec-path))))
+ (file-remote-p default-directory 'localname)))
+ ;; The shell "sh" shall always exist.
+ (should (apply 'executable-find '("sh" remote)))
+ ;; Since the last element in `exec-path' is the current
+ ;; directory, an executable file in that directory will be
+ ;; found.
+ (write-region "foo" nil tmp-name)
+ (should (file-exists-p tmp-name))
+ (set-file-modes tmp-name #o777)
+ (should (file-executable-p tmp-name))
+ (should
+ (string-equal
+ (apply
+ 'executable-find `(,(file-name-nondirectory tmp-name) remote))
+ (file-remote-p tmp-name 'localname)))
+ (should-not
+ (apply
+ 'executable-find
+ `(,(concat (file-name-nondirectory tmp-name) "foo") remote))))
+
+ ;; Cleanup.
+ (ignore-errors (delete-file tmp-name)))))
+
+(ert-deftest tramp-test35-vc-registered ()
"Check `vc-registered'."
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let* ((default-directory tramp-test-temporary-file-directory)
(tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo" tmp-name1))
@@ -3810,11 +4142,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
-(ert-deftest tramp-test35-make-auto-save-file-name ()
+(ert-deftest tramp-test36-make-auto-save-file-name ()
"Check `make-auto-save-file-name'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted)))
@@ -3901,11 +4233,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(ignore-errors (delete-file tmp-name1))
(ignore-errors (delete-directory tmp-name2 'recursive))))))
-(ert-deftest tramp-test36-find-backup-file-name ()
+(ert-deftest tramp-test37-find-backup-file-name ()
"Check `find-backup-file-name'."
(skip-unless (tramp--test-enabled))
- (dolist (quoted (if tramp--test-expensive-test '(nil t) '(nil)))
+ (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted))
;; These settings are not used by Tramp, so we ignore them.
@@ -4012,7 +4344,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(ignore-errors (delete-directory tmp-name2 'recursive))))))
;; The functions were introduced in Emacs 26.1.
-(ert-deftest tramp-test37-make-nearby-temp-file ()
+(ert-deftest tramp-test38-make-nearby-temp-file ()
"Check `make-nearby-temp-file' and `temporary-file-directory'."
(skip-unless (tramp--test-enabled))
;; Since Emacs 26.1.
@@ -4104,6 +4436,11 @@ This does not support external Emacs calls."
(string-equal
"mock" (file-remote-p tramp-test-temporary-file-directory 'method)))
+(defun tramp--test-nextcloud-p ()
+ "Check, whether the nextcloud method is used."
+ (string-equal
+ "nextcloud" (file-remote-p tramp-test-temporary-file-directory 'method)))
+
(defun tramp--test-rsync-p ()
"Check, whether the rsync method is used.
This does not support special file names."
@@ -4142,7 +4479,7 @@ This requires restrictions of file name syntax."
(defun tramp--test-check-files (&rest files)
"Run a simple but comprehensive test over every file in FILES."
;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579.
- (dolist (quoted (if (and tramp--test-expensive-test (tramp--test-emacs27-p))
+ (dolist (quoted (if (and (tramp--test-expensive-test) (tramp--test-emacs27-p))
'(nil t) '(nil)))
;; We must use `file-truename' for the temporary directory,
;; because it could be located on a symlinked directory. This
@@ -4275,9 +4612,10 @@ This requires restrictions of file name syntax."
(should-not (file-exists-p file1))))
;; Check, that environment variables are set correctly.
- (when (and tramp--test-expensive-test (tramp--test-sh-p))
+ (when (and (tramp--test-expensive-test) (tramp--test-sh-p))
(dolist (elt files)
(let ((envvar (concat "VAR_" (upcase (md5 elt))))
+ (elt (encode-coding-string elt coding-system-for-read))
(default-directory tramp-test-temporary-file-directory)
(process-environment process-environment))
(setenv envvar elt)
@@ -4299,50 +4637,55 @@ This requires restrictions of file name syntax."
(ignore-errors (delete-directory tmp-name2 'recursive))))))
(defun tramp--test-special-characters ()
- "Perform the test in `tramp-test38-special-characters*'."
+ "Perform the test in `tramp-test39-special-characters*'."
;; Newlines, slashes and backslashes in file names are not
;; supported. So we don't test. And we don't test the tab
;; character on Windows or Cygwin, because the backslash is
;; interpreted as a path separator, preventing "\t" from being
;; expanded to <TAB>.
- (tramp--test-check-files
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "foo bar baz"
- (if (or (tramp--test-adb-p)
- (tramp--test-docker-p)
- (eq system-type 'cygwin))
- " foo bar baz "
- " foo\tbar baz\t"))
- "$foo$bar$$baz$"
- "-foo-bar-baz-"
- "%foo%bar%baz%"
- "&foo&bar&baz&"
- (unless (or (tramp--test-ftp-p)
- (tramp--test-gvfs-p)
- (tramp--test-windows-nt-or-smb-p))
- "?foo?bar?baz?")
- (unless (or (tramp--test-ftp-p)
- (tramp--test-gvfs-p)
- (tramp--test-windows-nt-or-smb-p))
- "*foo*bar*baz*")
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "'foo'bar'baz'"
- "'foo\"bar'baz\"")
- "#foo~bar#baz~"
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "!foo!bar!baz!"
- "!foo|bar!baz|")
- (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- ";foo;bar;baz;"
- ":foo;bar:baz;")
- (unless (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
- "<foo>bar<baz>")
- "(foo)bar(baz)"
- (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
- "{foo}bar{baz}"))
+ (let ((files
+ (list
+ (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "foo bar baz"
+ (if (or (tramp--test-adb-p)
+ (tramp--test-docker-p)
+ (eq system-type 'cygwin))
+ " foo bar baz "
+ " foo\tbar baz\t"))
+ "$foo$bar$$baz$"
+ "-foo-bar-baz-"
+ "%foo%bar%baz%"
+ "&foo&bar&baz&"
+ (unless (or (tramp--test-ftp-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-windows-nt-or-smb-p))
+ "?foo?bar?baz?")
+ (unless (or (tramp--test-ftp-p)
+ (tramp--test-gvfs-p)
+ (tramp--test-windows-nt-or-smb-p))
+ "*foo*bar*baz*")
+ (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "'foo'bar'baz'"
+ "'foo\"bar'baz\"")
+ "#foo~bar#baz~"
+ (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "!foo!bar!baz!"
+ "!foo|bar!baz|")
+ (if (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ ";foo;bar;baz;"
+ ":foo;bar:baz;")
+ (unless (or (tramp--test-gvfs-p) (tramp--test-windows-nt-or-smb-p))
+ "<foo>bar<baz>")
+ "(foo)bar(baz)"
+ (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
+ "{foo}bar{baz}")))
+ ;; Simplify test in order to speed up.
+ (apply 'tramp--test-check-files
+ (if (tramp--test-expensive-test)
+ files (list (mapconcat 'identity files ""))))))
;; These tests are inspired by Bug#17238.
-(ert-deftest tramp-test38-special-characters ()
+(ert-deftest tramp-test39-special-characters ()
"Check special characters in file names."
(skip-unless (tramp--test-enabled))
(skip-unless (not (tramp--test-rsync-p)))
@@ -4350,7 +4693,7 @@ This requires restrictions of file name syntax."
(tramp--test-special-characters))
-(ert-deftest tramp-test38-special-characters-with-stat ()
+(ert-deftest tramp-test39-special-characters-with-stat ()
"Check special characters in file names.
Use the `stat' command."
:tags '(:expensive-test)
@@ -4368,7 +4711,7 @@ Use the `stat' command."
tramp-connection-properties)))
(tramp--test-special-characters)))
-(ert-deftest tramp-test38-special-characters-with-perl ()
+(ert-deftest tramp-test39-special-characters-with-perl ()
"Check special characters in file names.
Use the `perl' command."
:tags '(:expensive-test)
@@ -4389,7 +4732,7 @@ Use the `perl' command."
tramp-connection-properties)))
(tramp--test-special-characters)))
-(ert-deftest tramp-test38-special-characters-with-ls ()
+(ert-deftest tramp-test39-special-characters-with-ls ()
"Check special characters in file names.
Use the `ls' command."
:tags '(:expensive-test)
@@ -4412,7 +4755,7 @@ Use the `ls' command."
(tramp--test-special-characters)))
(defun tramp--test-utf8 ()
- "Perform the test in `tramp-test39-utf8*'."
+ "Perform the test in `tramp-test40-utf8*'."
(let* ((utf8 (if (and (eq system-type 'darwin)
(memq 'utf-8-hfs (coding-system-list)))
'utf-8-hfs 'utf-8))
@@ -4420,14 +4763,34 @@ Use the `ls' command."
(coding-system-for-write utf8)
(file-name-coding-system
(coding-system-change-eol-conversion utf8 'unix)))
- (tramp--test-check-files
- (unless (tramp--test-hpux-p) "Γυρίστε το Γαλαξία με Ώτο Στοπ")
- (unless (tramp--test-hpux-p)
- "أصبح بوسعك الآن تنزيل نسخة كاملة من موسوعة ويكيبيديا العربية لتصفحها بلا اتصال بالإنترنت")
- "银河系漫游指南系列"
- "Автостопом по гала́ктике")))
-
-(ert-deftest tramp-test39-utf8 ()
+ (apply
+ 'tramp--test-check-files
+ (append
+ (list
+ (unless (tramp--test-hpux-p) "Γυρίστε το Γαλαξία με Ώτο Στοπ")
+ (unless (tramp--test-hpux-p)
+ "أصبح بوسعك الآن تنزيل نسخة كاملة من موسوعة ويكيبيديا العربية لتصفحها بلا اتصال بالإنترنت")
+ "银河系漫游指南系列"
+ "Автостопом по гала́ктике"
+ ;; Use codepoints without a name. See Bug#31272.
+ "™›šbung")
+
+ (when (tramp--test-expensive-test)
+ (delete-dups
+ (mapcar
+ ;; Use all available language specific snippets. Filter out
+ ;; strings which use unencodable characters.
+ (lambda (x)
+ (and
+ (stringp (setq x (eval (get-language-info (car x) 'sample-text))))
+ (not (unencodable-char-position
+ 0 (length x) file-name-coding-system nil x))
+ ;; ?\n and ?/ shouldn't be part of any file name. ?\t,
+ ;; ?. and ?? do not work for "smb" method.
+ (replace-regexp-in-string "[\t\n/.?]" "" x)))
+ language-info-alist)))))))
+
+(ert-deftest tramp-test40-utf8 ()
"Check UTF8 encoding in file names and file contents."
(skip-unless (tramp--test-enabled))
(skip-unless (not (tramp--test-docker-p)))
@@ -4437,7 +4800,7 @@ Use the `ls' command."
(tramp--test-utf8))
-(ert-deftest tramp-test39-utf8-with-stat ()
+(ert-deftest tramp-test40-utf8-with-stat ()
"Check UTF8 encoding in file names and file contents.
Use the `stat' command."
:tags '(:expensive-test)
@@ -4457,7 +4820,7 @@ Use the `stat' command."
tramp-connection-properties)))
(tramp--test-utf8)))
-(ert-deftest tramp-test39-utf8-with-perl ()
+(ert-deftest tramp-test40-utf8-with-perl ()
"Check UTF8 encoding in file names and file contents.
Use the `perl' command."
:tags '(:expensive-test)
@@ -4480,7 +4843,7 @@ Use the `perl' command."
tramp-connection-properties)))
(tramp--test-utf8)))
-(ert-deftest tramp-test39-utf8-with-ls ()
+(ert-deftest tramp-test40-utf8-with-ls ()
"Check UTF8 encoding in file names and file contents.
Use the `ls' command."
:tags '(:expensive-test)
@@ -4503,7 +4866,7 @@ Use the `ls' command."
tramp-connection-properties)))
(tramp--test-utf8)))
-(ert-deftest tramp-test40-file-system-info ()
+(ert-deftest tramp-test41-file-system-info ()
"Check that `file-system-info' returns proper values."
(skip-unless (tramp--test-enabled))
;; Since Emacs 27.1.
@@ -4525,18 +4888,21 @@ Use the `ls' command."
(ert-fail (format "`%s' timed out" (ert-test-name (ert-running-test)))))
;; This test is inspired by Bug#16928.
-(ert-deftest tramp-test41-asynchronous-requests ()
+(ert-deftest tramp-test42-asynchronous-requests ()
"Check parallel asynchronous requests.
Such requests could arrive from timers, process filters and
process sentinels. They shall not disturb each other."
- :tags '(:expensive-test)
+ :tags '(:expensive-test :unstable)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
;; This test could be blocked on hydra. So we set a timeout of 300
;; seconds, and we send a SIGUSR1 signal after 300 seconds.
+ ;; This clearly doesn't work though, because the test not
+ ;; infrequently hangs for hours until killed by the infrastructure.
(with-timeout (300 (tramp--test-timeout-handler))
(define-key special-event-map [sigusr1] 'tramp--test-timeout-handler)
+ (tramp--test-instrument-test-case (if (getenv "EMACS_HYDRA_CI") 10 0)
(let* (;; For the watchdog.
(default-directory (expand-file-name temporary-file-directory))
(watchdog
@@ -4555,10 +4921,11 @@ process sentinels. They shall not disturb each other."
;; Number of asynchronous processes for test. Tests on
;; some machines handle less parallel processes.
(number-proc
- (or
- (ignore-errors
- (string-to-number (getenv "REMOTE_PARALLEL_PROCESSES")))
- 10))
+ (cond
+ ((ignore-errors
+ (string-to-number (getenv "REMOTE_PARALLEL_PROCESSES"))))
+ ((getenv "EMACS_HYDRA_CI") 5)
+ (t 10)))
;; On hydra, timings are bad.
(timer-repeat
(cond
@@ -4588,11 +4955,16 @@ process sentinels. They shall not disturb each other."
(default-directory tmp-name)
(file
(buffer-name (nth (random (length buffers)) buffers))))
+ (tramp--test-message
+ "Start timer %s %s" file (current-time-string))
(funcall timer-operation file)
;; Adjust timer if it takes too much time.
(when (> (- (float-time) time) timer-repeat)
(setq timer-repeat (* 1.5 timer-repeat))
- (setf (timer--repeat-delay timer) timer-repeat)))))))
+ (setf (timer--repeat-delay timer) timer-repeat)
+ (tramp--test-message "Increase timer %s" timer-repeat))
+ (tramp--test-message
+ "Stop timer %s %s" file (current-time-string)))))))
;; Create temporary buffers. The number of buffers
;; corresponds to the number of processes; it could be
@@ -4619,6 +4991,8 @@ process sentinels. They shall not disturb each other."
(set-process-filter
proc
(lambda (proc string)
+ (tramp--test-message
+ "Process filter %s %s %s" proc string (current-time-string))
(with-current-buffer (process-buffer proc)
(insert string))
(unless (zerop (length string))
@@ -4628,6 +5002,8 @@ process sentinels. They shall not disturb each other."
(set-process-sentinel
proc
(lambda (proc _state)
+ (tramp--test-message
+ "Process sentinel %s %s" proc (current-time-string))
(dired-uncache (process-get proc 'foo))
(should-not (file-attributes (process-get proc 'foo)))))))
@@ -4641,6 +5017,8 @@ process sentinels. They shall not disturb each other."
(proc (get-buffer-process buf))
(file (process-get proc 'foo))
(count (process-get proc 'bar)))
+ (tramp--test-message
+ "Start action %d %s %s" count buf (current-time-string))
;; Regular operation prior process action.
(dired-uncache file)
(if (= count 0)
@@ -4651,11 +5029,15 @@ process sentinels. They shall not disturb each other."
(accept-process-output proc 0.1 nil 0)
;; Give the watchdog a chance.
(read-event nil nil 0.01)
+ (tramp--test-message
+ "Continue action %d %s %s" count buf (current-time-string))
;; Regular operation post process action.
(dired-uncache file)
(if (= count 2)
(should-not (file-attributes file))
(should (file-attributes file)))
+ (tramp--test-message
+ "Stop action %d %s %s" count buf (current-time-string))
(process-put proc 'bar (1+ count))
(unless (process-live-p proc)
(setq buffers (delq buf buffers))))))
@@ -4663,6 +5045,7 @@ process sentinels. They shall not disturb each other."
;; Checks. All process output shall exists in the
;; respective buffers. All created files shall be
;; deleted.
+ (tramp--test-message "Check %s" (current-time-string))
(dolist (buf buffers)
(with-current-buffer buf
(should (string-equal (format "%s\n" buf) (buffer-string)))))
@@ -4677,11 +5060,13 @@ process sentinels. They shall not disturb each other."
(ignore-errors (delete-process (get-buffer-process buf)))
(ignore-errors (kill-buffer buf)))
(ignore-errors (cancel-timer timer))
- (ignore-errors (delete-directory tmp-name 'recursive))))))
+ (ignore-errors (delete-directory tmp-name 'recursive)))))))
;; This test is inspired by Bug#29163.
-(ert-deftest tramp-test42-auto-load ()
+(ert-deftest tramp-test43-auto-load ()
"Check that Tramp autoloads properly."
+ (skip-unless (tramp--test-enabled))
+
(let ((default-directory (expand-file-name temporary-file-directory))
(code
(format
@@ -4698,7 +5083,7 @@ process sentinels. They shall not disturb each other."
(mapconcat 'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
-(ert-deftest tramp-test42-delay-load ()
+(ert-deftest tramp-test43-delay-load ()
"Check that Tramp is loaded lazily, only when needed."
;; The autoloaded Tramp objects are different since Emacs 26.1. We
;; cannot test older Emacsen, therefore.
@@ -4731,7 +5116,7 @@ process sentinels. They shall not disturb each other."
(mapconcat 'shell-quote-argument load-path " -L ")
(shell-quote-argument (format code tm)))))))))
-(ert-deftest tramp-test42-recursive-load ()
+(ert-deftest tramp-test43-recursive-load ()
"Check that Tramp does not fail due to recursive load."
(skip-unless (tramp--test-enabled))
@@ -4755,7 +5140,7 @@ process sentinels. They shall not disturb each other."
(mapconcat 'shell-quote-argument load-path " -L ")
(shell-quote-argument code))))))))
-(ert-deftest tramp-test42-remote-load-path ()
+(ert-deftest tramp-test43-remote-load-path ()
"Check that Tramp autoloads its packages with remote `load-path'."
;; The autoloaded Tramp objects are different since Emacs 26.1. We
;; cannot test older Emacsen, therefore.
@@ -4783,7 +5168,7 @@ process sentinels. They shall not disturb each other."
(mapconcat 'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
-(ert-deftest tramp-test43-unload ()
+(ert-deftest tramp-test44-unload ()
"Check that Tramp and its subpackages unload completely.
Since it unloads Tramp, it shall be the last test to run."
:tags '(:expensive-test)
@@ -4792,42 +5177,52 @@ Since it unloads Tramp, it shall be the last test to run."
;; cannot test older Emacsen, therefore.
(skip-unless (tramp--test-emacs26-p))
- (when (featurep 'tramp)
- (unload-feature 'tramp 'force)
- ;; No Tramp feature must be left.
- (should-not (featurep 'tramp))
- (should-not (all-completions "tramp" (delq 'tramp-tests features)))
- ;; `file-name-handler-alist' must be clean.
- (should-not (all-completions "tramp" (mapcar 'cdr file-name-handler-alist)))
- ;; There shouldn't be left a bound symbol, except buffer-local
- ;; variables, and autoload functions. We do not regard our test
- ;; symbols, and the Tramp unload hooks.
- (mapatoms
- (lambda (x)
- (and (or (and (boundp x) (null (local-variable-if-set-p x)))
- (and (functionp x) (null (autoloadp (symbol-function x)))))
- (string-match "^tramp" (symbol-name x))
- (not (string-match "^tramp--?test" (symbol-name x)))
- (not (string-match "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.
- (should-not (cl--find-class 'tramp-file-name))
- (mapatoms
- (lambda (x)
- (and (functionp x)
- (string-match "tramp-file-name" (symbol-name x))
- (ert-fail (format "Structure function `%s' still exists" x)))))
- ;; There shouldn't be left a hook function containing a Tramp
- ;; function. We do not regard the Tramp unload hooks.
- (mapatoms
- (lambda (x)
- (and (boundp x)
- (string-match "-\\(hook\\|function\\)s?$" (symbol-name x))
- (not (string-match "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)))))))
+ ;; We have autoloaded objects from tramp.el and tramp-archive.el.
+ ;; In order to remove them, we first need to load both packages.
+ (require 'tramp)
+ (require 'tramp-archive)
+ (should (featurep 'tramp))
+ (should (featurep 'tramp-archive))
+ ;; This unloads also tramp-archive.el and tramp-theme.el if needed.
+ (unload-feature 'tramp 'force)
+ ;; No Tramp feature must be left.
+ (should-not (featurep 'tramp))
+ (should-not (featurep 'tramp-archive))
+ (should-not (featurep 'tramp-theme))
+ (should-not
+ (all-completions
+ "tramp" (delq 'tramp-tests (delq 'tramp-archive-tests features))))
+ ;; `file-name-handler-alist' must be clean.
+ (should-not (all-completions "tramp" (mapcar 'cdr file-name-handler-alist)))
+ ;; There shouldn't be left a bound symbol, except buffer-local
+ ;; variables, and autoload functions. We do not regard our test
+ ;; symbols, and the Tramp unload hooks.
+ (mapatoms
+ (lambda (x)
+ (and (or (and (boundp x) (null (local-variable-if-set-p x)))
+ (and (functionp x) (null (autoloadp (symbol-function x)))))
+ (string-match "^tramp" (symbol-name x))
+ (not (string-match "^tramp\\(-archive\\)?--?test" (symbol-name x)))
+ (not (string-match "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.
+ (should-not (cl--find-class 'tramp-file-name))
+ (mapatoms
+ (lambda (x)
+ (and (functionp x)
+ (string-match "tramp-file-name" (symbol-name x))
+ (ert-fail (format "Structure function `%s' still exists" x)))))
+ ;; There shouldn't be left a hook function containing a Tramp
+ ;; function. We do not regard the Tramp unload hooks.
+ (mapatoms
+ (lambda (x)
+ (and (boundp x)
+ (string-match "-\\(hook\\|function\\)s?$" (symbol-name x))
+ (not (string-match "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))))))
(defun tramp-test-all (&optional interactive)
"Run all tests for \\[tramp]."
@@ -4844,11 +5239,14 @@ Since it unloads Tramp, it shall be the last test to run."
;; * file-name-case-insensitive-p
;; * Work on skipped tests. Make a comment, when it is impossible.
+;; * Revisit expensive tests, once problems in `tramp-error' are solved.
;; * Fix `tramp-test05-expand-file-name-relative' in `expand-file-name'.
;; * Fix `tramp-test06-directory-file-name' for `ftp'.
+;; * Investigate, why `tramp-test11-copy-file' and `tramp-test12-rename-file'
+;; do not work properly for `nextcloud'.
;; * Fix `tramp-test29-start-file-process' on MS Windows (`process-send-eof'?).
;; * Fix `tramp-test30-interrupt-process', timeout doesn't work reliably.
-;; * Fix Bug#16928 in `tramp-test41-asynchronous-requests'.
+;; * Fix Bug#16928 in `tramp-test42-asynchronous-requests'.
(provide 'tramp-tests)
;;; tramp-tests.el ends here