]> git.eshelyaron.com Git - emacs.git/commitdiff
Merge from origin/emacs-25
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 5 Aug 2016 21:09:08 +0000 (14:09 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 5 Aug 2016 21:09:08 +0000 (14:09 -0700)
9ba51ed Document buffer-swap-text+save-excursion interaction
452aa94 Fix eieio vs cl-generic incompatibilities found in Rudel (bug...
248d5dd Include cl-generic in package--builtin-versions (bug#22817)
8f5a8b6 Improve timing in `tramp-test29-environment-variables'
05ba7a0 Add test for handling environment variables in Tramp
e393d4f * lisp/emacs-lisp/package.el (describe-package-1) (package-st...
5e38887 ; * lisp/net/tramp.el: Fix 2010-10-04 comment typo.  (Bug#23913)
90f2169 ; Spelling fixes
069fc05 Improve documentation of search functions
0a0144a Delete environment variables in Tramp when needed
f624671 Add "New in Emacs 25" section to the FAQ
658daf9 Fix 'vertical-motion' in non-interactive sessions
686b520 Fix memory leak in imagemagick-types
4069b71 Update ELisp manual to match 'string-collate-equalp' doc string
1b2d6a6 Clarify docstring of find-feature-regexp
aac62a6 Add details to cl-lib defining macros' docstrings
d6aa4da Clarify doc string of 'save-buffer'
03bcf11 Un-confuse doc string of 'string-collate-equalp'
c53135b Clarify documentation of 'mouse-on-link-p'

# Conflicts:
# lisp/emacs-lisp/eieio-core.el

20 files changed:
1  2 
doc/lispref/searching.texi
doc/lispref/strings.texi
etc/PROBLEMS
lisp/emacs-lisp/cl-generic.el
lisp/emacs-lisp/cl-macs.el
lisp/emacs-lisp/eieio-compat.el
lisp/emacs-lisp/eieio-core.el
lisp/emacs-lisp/find-func.el
lisp/emacs-lisp/package.el
lisp/files.el
lisp/isearch.el
lisp/mouse.el
lisp/net/tramp-sh.el
lisp/net/tramp.el
src/buffer.c
src/fns.c
src/image.c
src/indent.c
src/search.c
test/lisp/net/tramp-tests.el

Simple merge
Simple merge
diff --cc etc/PROBLEMS
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc lisp/files.el
Simple merge
diff --cc lisp/isearch.el
Simple merge
diff --cc lisp/mouse.el
Simple merge
index f79394ac9b7763b2654a14e0028bdc65c9c2a6a2,85712cc9d8ab2703e016547b0bb29f0cd7b328c0..80e8375b944fae46ccad6e24f8137a9717e1d29d
@@@ -5522,12 -5704,17 +5535,19 @@@ Return ATTR.
               (tramp-get-remote-gid-with-python vec id-format))))))
        ;; Ensure there is a valid result.
        (cond
 -       ((and (equal id-format 'integer) (not (integerp res))) -1)
 -       ((and (equal id-format 'string) (not (stringp res))) "UNKNOWN")
 +       ((and (equal id-format 'integer) (not (integerp res)))
 +      tramp-unknown-id-integer)
 +       ((and (equal id-format 'string) (not (stringp res)))
 +      tramp-unknown-id-string)
         (t res)))))
  
+ (defun tramp-get-env-with-u-option (vec)
+   (with-tramp-connection-property vec "env-u-option"
+     (tramp-message vec 5 "Checking, whether `env -u' works")
+     ;; Option "-u" is a GNU extension.
+     (tramp-send-command-and-check
+      vec "env FOO=foo env -u FOO 2>/dev/null | grep -qv FOO" t)))
  ;; Some predefined connection properties.
  (defun tramp-get-inline-compress (vec prop size)
    "Return the compress command related to PROP.
Simple merge
diff --cc src/buffer.c
Simple merge
diff --cc src/fns.c
Simple merge
diff --cc src/image.c
Simple merge
diff --cc src/indent.c
Simple merge
diff --cc src/search.c
Simple merge
index a1ae78ab5c3ff4f807021a85314a5c93f61b49c9,0000000000000000000000000000000000000000..e05786fa07068144faed4cb24ff9fbc7d8bb8a6c
mode 100644,000000..100644
--- /dev/null
@@@ -1,2409 -1,0 +1,2501 @@@
- (ert-deftest tramp-test29-vc-registered ()
 +;;; tramp-tests.el --- Tests of remote file access
 +
 +;; Copyright (C) 2013-2016 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 `http://www.gnu.org/licenses/'.
 +
 +;;; Commentary:
 +
 +;; The tests require a recent ert.el from Emacs 24.4.
 +
 +;; Some of the tests require access to a remote host files.  Since
 +;; this could be problematic, a mock-up connection method "mock" is
 +;; used.  Emulating a remote connection, it simply calls "sh -i".
 +;; Tramp's file name handlers still run, so this test is sufficient
 +;; except for connection establishing.
 +
 +;; If you want to test a real Tramp connection, set
 +;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to
 +;; overwrite the default value.  If you want to skip tests accessing a
 +;; remote host, set this environment variable to "/dev/null" or
 +;; whatever is appropriate on your system.
 +
 +;; A whole test run can be performed calling the command `tramp-test-all'.
 +
 +;;; Code:
 +
 +(require 'ert)
 +(require 'tramp)
 +(require 'vc)
 +(require 'vc-bzr)
 +(require 'vc-git)
 +(require 'vc-hg)
 +
 +(autoload 'dired-uncache "dired")
 +(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")
 +(defvar tramp-copy-size-limit)
 +(defvar tramp-persistency-file-name)
 +(defvar tramp-remote-process-environment)
 +
 +;; There is no default value on w32 systems, which could work out of the box.
 +(defconst tramp-test-temporary-file-directory
 +  (cond
 +   ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY"))
 +   ((eq system-type 'windows-nt) null-device)
 +   (t (add-to-list
 +       'tramp-methods
 +       '("mock"
 +       (tramp-login-program        "sh")
 +       (tramp-login-args           (("-i")))
 +       (tramp-remote-shell         "/bin/sh")
 +       (tramp-remote-shell-args    ("-c"))
 +       (tramp-connection-timeout   10)))
 +      (format "/mock::%s" temporary-file-directory)))
 +  "Temporary directory for Tramp tests.")
 +
 +(setq password-cache-expiry nil
 +      tramp-verbose 0
 +      tramp-copy-size-limit nil
 +      tramp-message-show-message nil
 +      tramp-persistency-file-name nil)
 +
 +;; This shall happen on hydra only.
 +(when (getenv "NIX_STORE")
 +  (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
 +
 +(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'
 +being the result.")
 +
 +(defun tramp--test-enabled ()
 +  "Whether remote file access is enabled."
 +  (unless (consp tramp--test-enabled-checked)
 +    (setq
 +     tramp--test-enabled-checked
 +     (cons
 +      t (ignore-errors
 +        (and
 +         (file-remote-p tramp-test-temporary-file-directory)
 +         (file-directory-p tramp-test-temporary-file-directory)
 +         (file-writable-p tramp-test-temporary-file-directory))))))
 +
 +  (when (cdr tramp--test-enabled-checked)
 +    ;; Cleanup connection.
 +    (ignore-errors
 +      (tramp-cleanup-connection
 +       (tramp-dissect-file-name tramp-test-temporary-file-directory)
 +       nil 'keep-password)))
 +
 +  ;; Return result.
 +  (cdr tramp--test-enabled-checked))
 +
 +(defun tramp--test-make-temp-name (&optional local)
 +  "Create a temporary file name for test."
 +  (expand-file-name
 +   (make-temp-name "tramp-test")
 +   (if local temporary-file-directory tramp-test-temporary-file-directory)))
 +
 +(defmacro tramp--instrument-test-case (verbose &rest body)
 +  "Run BODY with `tramp-verbose' equal VERBOSE.
 +Print the the content of the Tramp debug buffer, if BODY does not
 +eval properly in `should' or `should-not'.  `should-error' is not
 +handled properly.  BODY shall not contain a timeout."
 +  (declare (indent 1) (debug (natnump body)))
 +  `(let ((tramp-verbose ,verbose)
 +       (tramp-debug-on-error t)
 +       (debug-ignored-errors
 +        (cons "^make-symbolic-link not supported$" debug-ignored-errors)))
 +     (unwind-protect
 +       (progn ,@body)
 +       (when (> tramp-verbose 3)
 +       (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
 +         (with-current-buffer (tramp-get-connection-buffer v)
 +           (message "%s" (buffer-string)))
 +         (with-current-buffer (tramp-get-debug-buffer v)
 +           (message "%s" (buffer-string))))))))
 +
 +(ert-deftest tramp-test00-availability ()
 +  "Test availability of Tramp functions."
 +  :expected-result (if (tramp--test-enabled) :passed :failed)
 +  (message "Remote directory: `%s'" tramp-test-temporary-file-directory)
 +  (should (ignore-errors
 +          (and
 +           (file-remote-p tramp-test-temporary-file-directory)
 +           (file-directory-p tramp-test-temporary-file-directory)
 +           (file-writable-p tramp-test-temporary-file-directory)))))
 +
 +(ert-deftest tramp-test01-file-name-syntax ()
 +  "Check remote file name syntax."
 +  ;; Simple cases.
 +  (should (tramp-tramp-file-p "/method::"))
 +  (should (tramp-tramp-file-p "/host:"))
 +  (should (tramp-tramp-file-p "/user@:"))
 +  (should (tramp-tramp-file-p "/user@host:"))
 +  (should (tramp-tramp-file-p "/method:host:"))
 +  (should (tramp-tramp-file-p "/method:user@:"))
 +  (should (tramp-tramp-file-p "/method:user@host:"))
 +  (should (tramp-tramp-file-p "/method:user@email@host:"))
 +
 +  ;; Using a port.
 +  (should (tramp-tramp-file-p "/host#1234:"))
 +  (should (tramp-tramp-file-p "/user@host#1234:"))
 +  (should (tramp-tramp-file-p "/method:host#1234:"))
 +  (should (tramp-tramp-file-p "/method:user@host#1234:"))
 +
 +  ;; Using an IPv4 address.
 +  (should (tramp-tramp-file-p "/1.2.3.4:"))
 +  (should (tramp-tramp-file-p "/user@1.2.3.4:"))
 +  (should (tramp-tramp-file-p "/method:1.2.3.4:"))
 +  (should (tramp-tramp-file-p "/method:user@1.2.3.4:"))
 +
 +  ;; Using an IPv6 address.
 +  (should (tramp-tramp-file-p "/[]:"))
 +  (should (tramp-tramp-file-p "/[::1]:"))
 +  (should (tramp-tramp-file-p "/user@[::1]:"))
 +  (should (tramp-tramp-file-p "/method:[::1]:"))
 +  (should (tramp-tramp-file-p "/method:user@[::1]:"))
 +
 +  ;; Local file name part.
 +  (should (tramp-tramp-file-p "/host:/:"))
 +  (should (tramp-tramp-file-p "/method:::"))
 +  (should (tramp-tramp-file-p "/method::/path/to/file"))
 +  (should (tramp-tramp-file-p "/method::file"))
 +
 +  ;; Multihop.
 +  (should (tramp-tramp-file-p "/method1:|method2::"))
 +  (should (tramp-tramp-file-p "/method1:host1|host2:"))
 +  (should (tramp-tramp-file-p "/method1:host1|method2:host2:"))
 +  (should (tramp-tramp-file-p "/method1:user1@host1|method2:user2@host2:"))
 +  (should (tramp-tramp-file-p
 +         "/method1:user1@host1|method2:user2@host2|method3:user3@host3:"))
 +
 +  ;; No strings.
 +  (should-not (tramp-tramp-file-p nil))
 +  (should-not (tramp-tramp-file-p 'symbol))
 +  ;; "/:" suppresses file name handlers.
 +  (should-not (tramp-tramp-file-p "/::"))
 +  (should-not (tramp-tramp-file-p "/:@:"))
 +  (should-not (tramp-tramp-file-p "/:[]:"))
 +  ;; Multihops require a method.
 +  (should-not (tramp-tramp-file-p "/host1|host2:"))
 +  ;; Methods or hostnames shall be at least two characters on MS Windows.
 +  (when (memq system-type '(cygwin windows-nt))
 +      (should-not (tramp-tramp-file-p "/c:/path/to/file"))
 +      (should-not (tramp-tramp-file-p "/c::/path/to/file"))))
 +
 +(ert-deftest tramp-test02-file-name-dissect ()
 +  "Check remote file name components."
 +  (let ((tramp-default-method "default-method")
 +      (tramp-default-user "default-user")
 +      (tramp-default-host "default-host"))
 +    ;; Expand `tramp-default-user' and `tramp-default-host'.
 +    (should (string-equal
 +           (file-remote-p "/method::")
 +           (format "/%s:%s@%s:" "method" "default-user" "default-host")))
 +    (should (string-equal (file-remote-p "/method::" 'method) "method"))
 +    (should (string-equal (file-remote-p "/method::" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/method::" 'host) "default-host"))
 +    (should (string-equal (file-remote-p "/method::" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method::" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method' and `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/host:")
 +           (format "/%s:%s@%s:" "default-method" "default-user" "host")))
 +    (should (string-equal (file-remote-p "/host:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/host:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/host:" 'host) "host"))
 +    (should (string-equal (file-remote-p "/host:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/host:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method' and `tramp-default-host'.
 +    (should (string-equal
 +           (file-remote-p "/user@:")
 +           (format "/%s:%s@%s:" "default-method""user" "default-host")))
 +    (should (string-equal (file-remote-p "/user@:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/user@:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/user@:" 'host) "default-host"))
 +    (should (string-equal (file-remote-p "/user@:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/user@:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method'.
 +    (should (string-equal
 +           (file-remote-p "/user@host:")
 +           (format "/%s:%s@%s:" "default-method" "user" "host")))
 +    (should (string-equal
 +           (file-remote-p "/user@host:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/user@host:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/user@host:" 'host) "host"))
 +    (should (string-equal (file-remote-p "/user@host:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/user@host:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/method:host:")
 +           (format "/%s:%s@%s:" "method" "default-user" "host")))
 +    (should (string-equal (file-remote-p "/method:host:" 'method) "method"))
 +    (should (string-equal (file-remote-p "/method:host:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/method:host:" 'host) "host"))
 +    (should (string-equal (file-remote-p "/method:host:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:host:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-host'.
 +    (should (string-equal
 +           (file-remote-p "/method:user@:")
 +           (format "/%s:%s@%s:" "method" "user" "default-host")))
 +    (should (string-equal (file-remote-p "/method:user@:" 'method) "method"))
 +    (should (string-equal (file-remote-p "/method:user@:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/method:user@:" 'host)
 +                        "default-host"))
 +    (should (string-equal (file-remote-p "/method:user@:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:user@:" 'hop) nil))
 +
 +    ;; No expansion.
 +    (should (string-equal
 +           (file-remote-p "/method:user@host:")
 +           (format "/%s:%s@%s:" "method" "user" "host")))
 +    (should (string-equal
 +           (file-remote-p "/method:user@host:" 'method) "method"))
 +    (should (string-equal (file-remote-p "/method:user@host:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/method:user@host:" 'host) "host"))
 +    (should (string-equal (file-remote-p "/method:user@host:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:user@host:" 'hop) nil))
 +
 +    ;; No expansion.
 +    (should (string-equal
 +           (file-remote-p "/method:user@email@host:")
 +           (format "/%s:%s@%s:" "method" "user@email" "host")))
 +    (should (string-equal
 +           (file-remote-p "/method:user@email@host:" 'method) "method"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@email@host:" 'user) "user@email"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@email@host:" 'host) "host"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@email@host:" 'localname) ""))
 +    (should (string-equal
 +           (file-remote-p "/method:user@email@host:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method' and `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/host#1234:")
 +           (format "/%s:%s@%s:" "default-method" "default-user" "host#1234")))
 +    (should (string-equal
 +           (file-remote-p "/host#1234:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/host#1234:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/host#1234:" 'host) "host#1234"))
 +    (should (string-equal (file-remote-p "/host#1234:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/host#1234:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method'.
 +    (should (string-equal
 +           (file-remote-p "/user@host#1234:")
 +           (format "/%s:%s@%s:" "default-method" "user" "host#1234")))
 +    (should (string-equal
 +           (file-remote-p "/user@host#1234:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/user@host#1234:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/user@host#1234:" 'host) "host#1234"))
 +    (should (string-equal (file-remote-p "/user@host#1234:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/user@host#1234:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/method:host#1234:")
 +           (format "/%s:%s@%s:" "method" "default-user" "host#1234")))
 +    (should (string-equal
 +           (file-remote-p "/method:host#1234:" 'method) "method"))
 +    (should (string-equal
 +           (file-remote-p "/method:host#1234:" 'user) "default-user"))
 +    (should (string-equal
 +           (file-remote-p "/method:host#1234:" 'host) "host#1234"))
 +    (should (string-equal (file-remote-p "/method:host#1234:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:host#1234:" 'hop) nil))
 +
 +    ;; No expansion.
 +    (should (string-equal
 +           (file-remote-p "/method:user@host#1234:")
 +           (format "/%s:%s@%s:" "method" "user" "host#1234")))
 +    (should (string-equal
 +           (file-remote-p "/method:user@host#1234:" 'method) "method"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@host#1234:" 'user) "user"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@host#1234:" 'host) "host#1234"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@host#1234:" 'localname) ""))
 +    (should (string-equal
 +           (file-remote-p "/method:user@host#1234:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method' and `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/1.2.3.4:")
 +           (format "/%s:%s@%s:" "default-method" "default-user" "1.2.3.4")))
 +    (should (string-equal (file-remote-p "/1.2.3.4:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/1.2.3.4:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/1.2.3.4:" 'host) "1.2.3.4"))
 +    (should (string-equal (file-remote-p "/1.2.3.4:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/1.2.3.4:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method'.
 +    (should (string-equal
 +           (file-remote-p "/user@1.2.3.4:")
 +           (format "/%s:%s@%s:" "default-method" "user" "1.2.3.4")))
 +    (should (string-equal
 +           (file-remote-p "/user@1.2.3.4:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/user@1.2.3.4:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/user@1.2.3.4:" 'host) "1.2.3.4"))
 +    (should (string-equal (file-remote-p "/user@1.2.3.4:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/user@1.2.3.4:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/method:1.2.3.4:")
 +           (format "/%s:%s@%s:" "method" "default-user" "1.2.3.4")))
 +    (should (string-equal (file-remote-p "/method:1.2.3.4:" 'method) "method"))
 +    (should (string-equal
 +           (file-remote-p "/method:1.2.3.4:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/method:1.2.3.4:" 'host) "1.2.3.4"))
 +    (should (string-equal (file-remote-p "/method:1.2.3.4:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:1.2.3.4:" 'hop) nil))
 +
 +    ;; No expansion.
 +    (should (string-equal
 +           (file-remote-p "/method:user@1.2.3.4:")
 +           (format "/%s:%s@%s:" "method" "user" "1.2.3.4")))
 +    (should (string-equal
 +           (file-remote-p "/method:user@1.2.3.4:" 'method) "method"))
 +    (should (string-equal (file-remote-p "/method:user@1.2.3.4:" 'user) "user"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@1.2.3.4:" 'host) "1.2.3.4"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@1.2.3.4:" 'localname) ""))
 +    (should (string-equal
 +           (file-remote-p "/method:user@1.2.3.4:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method', `tramp-default-user' and
 +    ;; `tramp-default-host'.
 +    (should (string-equal
 +           (file-remote-p "/[]:")
 +           (format
 +            "/%s:%s@%s:" "default-method" "default-user" "default-host")))
 +    (should (string-equal (file-remote-p "/[]:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/[]:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/[]:" 'host) "default-host"))
 +    (should (string-equal (file-remote-p "/[]:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/[]:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method' and `tramp-default-user'.
 +    (let ((tramp-default-host "::1"))
 +      (should (string-equal
 +             (file-remote-p "/[]:")
 +             (format "/%s:%s@%s:" "default-method" "default-user" "[::1]")))
 +      (should (string-equal (file-remote-p "/[]:" 'method) "default-method"))
 +      (should (string-equal (file-remote-p "/[]:" 'user) "default-user"))
 +      (should (string-equal (file-remote-p "/[]:" 'host) "::1"))
 +      (should (string-equal (file-remote-p "/[]:" 'localname) ""))
 +      (should (string-equal (file-remote-p "/[]:" 'hop) nil)))
 +
 +    ;; Expand `tramp-default-method' and `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/[::1]:")
 +           (format "/%s:%s@%s:" "default-method" "default-user" "[::1]")))
 +    (should (string-equal (file-remote-p "/[::1]:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/[::1]:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/[::1]:" 'host) "::1"))
 +    (should (string-equal (file-remote-p "/[::1]:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/[::1]:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-method'.
 +    (should (string-equal
 +           (file-remote-p "/user@[::1]:")
 +           (format "/%s:%s@%s:" "default-method" "user" "[::1]")))
 +    (should (string-equal
 +           (file-remote-p "/user@[::1]:" 'method) "default-method"))
 +    (should (string-equal (file-remote-p "/user@[::1]:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/user@[::1]:" 'host) "::1"))
 +    (should (string-equal (file-remote-p "/user@[::1]:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/user@[::1]:" 'hop) nil))
 +
 +    ;; Expand `tramp-default-user'.
 +    (should (string-equal
 +           (file-remote-p "/method:[::1]:")
 +           (format "/%s:%s@%s:" "method" "default-user" "[::1]")))
 +    (should (string-equal (file-remote-p "/method:[::1]:" 'method) "method"))
 +    (should (string-equal
 +           (file-remote-p "/method:[::1]:" 'user) "default-user"))
 +    (should (string-equal (file-remote-p "/method:[::1]:" 'host) "::1"))
 +    (should (string-equal (file-remote-p "/method:[::1]:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:[::1]:" 'hop) nil))
 +
 +    ;; No expansion.
 +    (should (string-equal
 +           (file-remote-p "/method:user@[::1]:")
 +           (format "/%s:%s@%s:" "method" "user" "[::1]")))
 +    (should (string-equal
 +           (file-remote-p "/method:user@[::1]:" 'method) "method"))
 +    (should (string-equal (file-remote-p "/method:user@[::1]:" 'user) "user"))
 +    (should (string-equal (file-remote-p "/method:user@[::1]:" 'host) "::1"))
 +    (should (string-equal
 +           (file-remote-p "/method:user@[::1]:" 'localname) ""))
 +    (should (string-equal (file-remote-p "/method:user@[::1]:" 'hop) nil))
 +
 +    ;; Local file name part.
 +    (should (string-equal (file-remote-p "/host:/:" 'localname) "/:"))
 +    (should (string-equal (file-remote-p "/method:::" 'localname) ":"))
 +    (should (string-equal (file-remote-p "/method:: " 'localname) " "))
 +    (should (string-equal (file-remote-p "/method::file" 'localname) "file"))
 +    (should (string-equal
 +           (file-remote-p "/method::/path/to/file" 'localname)
 +           "/path/to/file"))
 +
 +    ;; Multihop.
 +    (should
 +     (string-equal
 +      (file-remote-p "/method1:user1@host1|method2:user2@host2:/path/to/file")
 +      (format "/%s:%s@%s|%s:%s@%s:"
 +            "method1" "user1" "host1" "method2" "user2" "host2")))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2:/path/to/file" 'method)
 +      "method2"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2:/path/to/file" 'user)
 +      "user2"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2:/path/to/file" 'host)
 +      "host2"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2:/path/to/file" 'localname)
 +      "/path/to/file"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2:/path/to/file" 'hop)
 +      (format "%s:%s@%s|"
 +            "method1" "user1" "host1")))
 +
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2|method3:user3@host3:/path/to/file")
 +      (format "/%s:%s@%s|%s:%s@%s|%s:%s@%s:"
 +            "method1" "user1" "host1"
 +            "method2" "user2" "host2"
 +            "method3" "user3" "host3")))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2|method3:user3@host3:/path/to/file"
 +       'method)
 +      "method3"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2|method3:user3@host3:/path/to/file"
 +       'user)
 +      "user3"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2|method3:user3@host3:/path/to/file"
 +       'host)
 +      "host3"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2|method3:user3@host3:/path/to/file"
 +       'localname)
 +      "/path/to/file"))
 +    (should
 +     (string-equal
 +      (file-remote-p
 +       "/method1:user1@host1|method2:user2@host2|method3:user3@host3:/path/to/file"
 +       'hop)
 +      (format "%s:%s@%s|%s:%s@%s|"
 +            "method1" "user1" "host1" "method2" "user2" "host2")))))
 +
 +(ert-deftest tramp-test03-file-name-defaults ()
 +  "Check default values for some methods."
 +  ;; Default values in tramp-adb.el.
 +  (should (string-equal (file-remote-p "/adb::" 'host) ""))
 +  ;; Default values in tramp-ftp.el.
 +  (should (string-equal (file-remote-p "/ftp.host:" 'method) "ftp"))
 +  (dolist (u '("ftp" "anonymous"))
 +    (should (string-equal (file-remote-p (format "/%s@:" u) 'method) "ftp")))
 +  ;; Default values in tramp-gvfs.el.
 +  (when (and (load "tramp-gvfs" 'noerror 'nomessage)
 +           (symbol-value 'tramp-gvfs-enabled))
 +    (should (string-equal (file-remote-p "/synce::" 'user) nil)))
 +  ;; Default values in tramp-gw.el.
 +  (dolist (m '("tunnel" "socks"))
 +    (should
 +     (string-equal (file-remote-p (format "/%s::" m) 'user) (user-login-name))))
 +  ;; Default values in tramp-sh.el.
 +  (dolist (h `("127.0.0.1" "[::1]" "localhost" "localhost6" ,(system-name)))
 +    (should (string-equal (file-remote-p (format "/root@%s:" h) 'method) "su")))
 +  (dolist (m '("su" "sudo" "ksu"))
 +    (should (string-equal (file-remote-p (format "/%s::" m) 'user) "root")))
 +  (dolist (m '("rcp" "remcp" "rsh" "telnet" "krlogin" "fcp"))
 +    (should
 +     (string-equal (file-remote-p (format "/%s::" m) 'user) (user-login-name))))
 +  ;; Default values in tramp-smb.el.
 +  (should (string-equal (file-remote-p "/user%domain@host:" 'method) "smb"))
 +  (should (string-equal (file-remote-p "/smb::" 'user) nil)))
 +
 +(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:/path//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"))
 +  (should
 +   (string-equal (substitute-in-file-name "/method:host:/path//~/foo") "~/foo"))
 +  (let (process-environment)
 +    (should
 +     (string-equal
 +      (substitute-in-file-name "/method:host:/path/$FOO")
 +      "/method:host:/path/$FOO"))
 +    (setenv "FOO" "bla")
 +    (should
 +     (string-equal
 +      (substitute-in-file-name "/method:host:/path/$FOO")
 +      "/method:host:/path/bla"))
 +    (should
 +     (string-equal
 +      (substitute-in-file-name "/method:host:/path/$$FOO")
 +      "/method:host:/path/$FOO"))))
 +
 +(ert-deftest tramp-test05-expand-file-name ()
 +  "Check `expand-file-name'."
 +  (should
 +   (string-equal
 +    (expand-file-name "/method:host:/path/./file") "/method:host:/path/file"))
 +  (should
 +   (string-equal
 +    (expand-file-name "/method:host:/path/../file") "/method:host:/file")))
 +
 +(ert-deftest tramp-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'."
 +  (should
 +   (string-equal
 +    (directory-file-name "/method:host:/path/to/file")
 +    "/method:host:/path/to/file"))
 +  (should
 +   (string-equal
 +    (directory-file-name "/method:host:/path/to/file/")
 +    "/method:host:/path/to/file"))
 +  (should
 +   (string-equal
 +    (file-name-as-directory "/method:host:/path/to/file")
 +    "/method:host:/path/to/file/"))
 +  (should
 +   (string-equal
 +    (file-name-as-directory "/method:host:/path/to/file/")
 +    "/method:host:/path/to/file/"))
 +  (should
 +   (string-equal
 +    (file-name-directory "/method:host:/path/to/file")
 +    "/method:host:/path/to/"))
 +  (should
 +   (string-equal
 +    (file-name-directory "/method:host:/path/to/file/")
 +    "/method:host:/path/to/file/"))
 +  (should
 +   (string-equal (file-name-nondirectory "/method:host:/path/to/file") "file"))
 +  (should
 +   (string-equal (file-name-nondirectory "/method:host:/path/to/file/") ""))
 +  (should-not
 +   (unhandled-file-name-directory "/method:host:/path/to/file"))
 +
 +  ;; Bug#10085.
 +  (dolist (n-e '(nil t))
 +    ;; We must clear `tramp-default-method'.  On hydra, it is "ftp",
 +    ;; which ruins the tests.
 +    (let ((non-essential n-e)
 +          tramp-default-method)
 +      (dolist (file
 +             `(,(file-remote-p tramp-test-temporary-file-directory 'method)
 +               ,(file-remote-p tramp-test-temporary-file-directory 'host)))
 +      (unless (zerop (length file))
 +        (setq file (format "/%s:" file))
 +        (should (string-equal (directory-file-name file) file))
 +        (should
 +         (string-equal
 +          (file-name-as-directory file)
 +          (if (tramp-completion-mode-p) file (concat file "./"))))
 +        (should (string-equal (file-name-directory file) file))
 +        (should (string-equal (file-name-nondirectory file) "")))))))
 +
 +(ert-deftest tramp-test07-file-exists-p ()
 +  "Check `file-exist-p', `write-region' and `delete-file'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    (should-not (file-exists-p tmp-name))
 +    (write-region "foo" nil tmp-name)
 +    (should (file-exists-p tmp-name))
 +    (delete-file tmp-name)
 +    (should-not (file-exists-p tmp-name))))
 +
 +(ert-deftest tramp-test08-file-local-copy ()
 +  "Check `file-local-copy'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name1 (tramp--test-make-temp-name))
 +      tmp-name2)
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (should (setq tmp-name2 (file-local-copy tmp-name1)))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name2)
 +          (should (string-equal (buffer-string) "foo")))
 +        ;; Check also that a file transfer with compression works.
 +        (let ((default-directory tramp-test-temporary-file-directory)
 +              (tramp-copy-size-limit 4)
 +              (tramp-inline-compress-start-size 2))
 +          (delete-file tmp-name2)
 +          (should (setq tmp-name2 (file-local-copy tmp-name1)))))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-file tmp-name1)
 +      (delete-file tmp-name2)))))
 +
 +(ert-deftest tramp-test09-insert-file-contents ()
 +  "Check `insert-file-contents'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name)
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name)
 +          (should (string-equal (buffer-string) "foo"))
 +          (insert-file-contents tmp-name)
 +          (should (string-equal (buffer-string) "foofoo"))
 +          ;; Insert partly.
 +          (insert-file-contents tmp-name nil 1 3)
 +          (should (string-equal (buffer-string) "oofoofoo"))
 +          ;; Replace.
 +          (insert-file-contents tmp-name nil nil nil 'replace)
 +          (should (string-equal (buffer-string) "foo"))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))))
 +
 +(ert-deftest tramp-test10-write-region ()
 +  "Check `write-region'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    (unwind-protect
 +      (progn
 +        (with-temp-buffer
 +          (insert "foo")
 +          (write-region nil nil tmp-name))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name)
 +          (should (string-equal (buffer-string) "foo")))
 +        ;; Append.
 +        (with-temp-buffer
 +          (insert "bla")
 +          (write-region nil nil tmp-name 'append))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name)
 +          (should (string-equal (buffer-string) "foobla")))
 +        ;; Write string.
 +        (write-region "foo" nil tmp-name)
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name)
 +          (should (string-equal (buffer-string) "foo")))
 +        ;; Write partly.
 +        (with-temp-buffer
 +          (insert "123456789")
 +          (write-region 3 5 tmp-name))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name)
 +          (should (string-equal (buffer-string) "34"))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))))
 +
 +(ert-deftest tramp-test11-copy-file ()
 +  "Check `copy-file'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name1 (tramp--test-make-temp-name))
 +      (tmp-name2 (tramp--test-make-temp-name))
 +      (tmp-name3 (tramp--test-make-temp-name))
 +      (tmp-name4 (tramp--test-make-temp-name 'local))
 +      (tmp-name5 (tramp--test-make-temp-name 'local)))
 +
 +    ;; Copy on remote side.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (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) "foo")))
 +        (should-error (copy-file tmp-name1 tmp-name2))
 +        (copy-file tmp-name1 tmp-name2 'ok)
 +        (make-directory tmp-name3)
 +        (copy-file tmp-name1 tmp-name3)
 +        (should
 +         (file-exists-p
 +          (expand-file-name (file-name-nondirectory tmp-name1) tmp-name3))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name2))
 +      (ignore-errors (delete-directory tmp-name3 'recursive)))
 +
 +    ;; Copy from remote side to local side.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (copy-file tmp-name1 tmp-name4)
 +        (should (file-exists-p tmp-name4))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name4)
 +          (should (string-equal (buffer-string) "foo")))
 +        (should-error (copy-file tmp-name1 tmp-name4))
 +        (copy-file tmp-name1 tmp-name4 'ok)
 +        (make-directory tmp-name5)
 +        (copy-file tmp-name1 tmp-name5)
 +        (should
 +         (file-exists-p
 +          (expand-file-name (file-name-nondirectory tmp-name1) tmp-name5))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name4))
 +      (ignore-errors (delete-directory tmp-name5 'recursive)))
 +
 +    ;; Copy from local side to remote side.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name4 nil 'nomessage)
 +        (copy-file tmp-name4 tmp-name1)
 +        (should (file-exists-p tmp-name1))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name1)
 +          (should (string-equal (buffer-string) "foo")))
 +        (should-error (copy-file tmp-name4 tmp-name1))
 +        (copy-file tmp-name4 tmp-name1 'ok)
 +        (make-directory tmp-name3)
 +        (copy-file tmp-name4 tmp-name3)
 +        (should
 +         (file-exists-p
 +          (expand-file-name (file-name-nondirectory tmp-name4) tmp-name3))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name4))
 +      (ignore-errors (delete-directory tmp-name3 'recursive)))))
 +
 +(ert-deftest tramp-test12-rename-file ()
 +  "Check `rename-file'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name1 (tramp--test-make-temp-name))
 +      (tmp-name2 (tramp--test-make-temp-name))
 +      (tmp-name3 (tramp--test-make-temp-name))
 +      (tmp-name4 (tramp--test-make-temp-name 'local))
 +      (tmp-name5 (tramp--test-make-temp-name 'local)))
 +
 +    ;; Rename on remote side.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (rename-file tmp-name1 tmp-name2)
 +        (should-not (file-exists-p tmp-name1))
 +        (should (file-exists-p tmp-name2))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name2)
 +          (should (string-equal (buffer-string) "foo")))
 +        (write-region "foo" nil tmp-name1)
 +        (should-error (rename-file tmp-name1 tmp-name2))
 +        (rename-file tmp-name1 tmp-name2 'ok)
 +        (should-not (file-exists-p tmp-name1))
 +        (write-region "foo" nil tmp-name1)
 +        (make-directory tmp-name3)
 +        (rename-file tmp-name1 tmp-name3)
 +        (should-not (file-exists-p tmp-name1))
 +        (should
 +         (file-exists-p
 +          (expand-file-name (file-name-nondirectory tmp-name1) tmp-name3))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name2))
 +      (ignore-errors (delete-directory tmp-name3 'recursive)))
 +
 +    ;; Rename from remote side to local side.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (rename-file tmp-name1 tmp-name4)
 +        (should-not (file-exists-p tmp-name1))
 +        (should (file-exists-p tmp-name4))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name4)
 +          (should (string-equal (buffer-string) "foo")))
 +        (write-region "foo" nil tmp-name1)
 +        (should-error (rename-file tmp-name1 tmp-name4))
 +        (rename-file tmp-name1 tmp-name4 'ok)
 +        (should-not (file-exists-p tmp-name1))
 +        (write-region "foo" nil tmp-name1)
 +        (make-directory tmp-name5)
 +        (rename-file tmp-name1 tmp-name5)
 +        (should-not (file-exists-p tmp-name1))
 +        (should
 +         (file-exists-p
 +          (expand-file-name (file-name-nondirectory tmp-name1) tmp-name5))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name4))
 +      (ignore-errors (delete-directory tmp-name5 'recursive)))
 +
 +    ;; Rename from local side to remote side.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name4 nil 'nomessage)
 +        (rename-file tmp-name4 tmp-name1)
 +        (should-not (file-exists-p tmp-name4))
 +        (should (file-exists-p tmp-name1))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name1)
 +          (should (string-equal (buffer-string) "foo")))
 +        (write-region "foo" nil tmp-name4 nil 'nomessage)
 +        (should-error (rename-file tmp-name4 tmp-name1))
 +        (rename-file tmp-name4 tmp-name1 'ok)
 +        (should-not (file-exists-p tmp-name4))
 +        (write-region "foo" nil tmp-name4 nil 'nomessage)
 +        (make-directory tmp-name3)
 +        (rename-file tmp-name4 tmp-name3)
 +        (should-not (file-exists-p tmp-name4))
 +        (should
 +         (file-exists-p
 +          (expand-file-name (file-name-nondirectory tmp-name4) tmp-name3))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name4))
 +      (ignore-errors (delete-directory tmp-name3 'recursive)))))
 +
 +(ert-deftest tramp-test13-make-directory ()
 +  "Check `make-directory'.
 +This tests also `file-directory-p' and `file-accessible-directory-p'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let* ((tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (expand-file-name "foo/bar" tmp-name1)))
 +    (unwind-protect
 +      (progn
 +        (make-directory tmp-name1)
 +        (should (file-directory-p tmp-name1))
 +        (should (file-accessible-directory-p tmp-name1))
 +        (should-error (make-directory tmp-name2))
 +        (make-directory tmp-name2 'parents)
 +        (should (file-directory-p tmp-name2))
 +        (should (file-accessible-directory-p tmp-name2)))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1 'recursive)))))
 +
 +(ert-deftest tramp-test14-delete-directory ()
 +  "Check `delete-directory'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    ;; Delete empty directory.
 +    (make-directory tmp-name)
 +    (should (file-directory-p tmp-name))
 +    (delete-directory tmp-name)
 +    (should-not (file-directory-p tmp-name))
 +    ;; Delete non-empty directory.
 +    (make-directory tmp-name)
 +    (should (file-directory-p tmp-name))
 +    (write-region "foo" nil (expand-file-name "bla" tmp-name))
 +    (should (file-exists-p (expand-file-name "bla" tmp-name)))
 +    (should-error (delete-directory tmp-name))
 +    (delete-directory tmp-name 'recursive)
 +    (should-not (file-directory-p tmp-name))))
 +
 +(ert-deftest tramp-test15-copy-directory ()
 +  "Check `copy-directory'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let* ((tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (tramp--test-make-temp-name))
 +       (tmp-name3 (expand-file-name
 +                   (file-name-nondirectory tmp-name1) tmp-name2))
 +       (tmp-name4 (expand-file-name "foo" tmp-name1))
 +       (tmp-name5 (expand-file-name "foo" tmp-name2))
 +       (tmp-name6 (expand-file-name "foo" tmp-name3)))
 +
 +    ;; Copy complete directory.
 +    (unwind-protect
 +      (progn
 +        ;; Copy empty directory.
 +        (make-directory tmp-name1)
 +        (write-region "foo" nil tmp-name4)
 +        (should (file-directory-p tmp-name1))
 +        (should (file-exists-p tmp-name4))
 +        (copy-directory tmp-name1 tmp-name2)
 +        (should (file-directory-p tmp-name2))
 +        (should (file-exists-p tmp-name5))
 +        ;; Target directory does exist already.
 +        (copy-directory tmp-name1 tmp-name2)
 +        (should (file-directory-p tmp-name3))
 +        (should (file-exists-p tmp-name6)))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-directory tmp-name1 'recursive)
 +      (delete-directory tmp-name2 'recursive)))
 +
 +    ;; Copy directory contents.
 +    (unwind-protect
 +      (progn
 +        ;; Copy empty directory.
 +        (make-directory tmp-name1)
 +        (write-region "foo" nil tmp-name4)
 +        (should (file-directory-p tmp-name1))
 +        (should (file-exists-p tmp-name4))
 +        (copy-directory tmp-name1 tmp-name2 nil 'parents 'contents)
 +        (should (file-directory-p tmp-name2))
 +        (should (file-exists-p tmp-name5))
 +        ;; Target directory does exist already.
 +        (delete-file tmp-name5)
 +        (should-not (file-exists-p tmp-name5))
 +        (copy-directory tmp-name1 tmp-name2 nil 'parents 'contents)
 +        (should (file-directory-p tmp-name2))
 +        (should (file-exists-p tmp-name5))
 +        (should-not (file-directory-p tmp-name3))
 +        (should-not (file-exists-p tmp-name6)))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-directory tmp-name1 'recursive)
 +      (delete-directory tmp-name2 'recursive)))))
 +
 +(ert-deftest tramp-test16-directory-files ()
 +  "Check `directory-files'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let* ((tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (expand-file-name "bla" tmp-name1))
 +       (tmp-name3 (expand-file-name "foo" tmp-name1)))
 +    (unwind-protect
 +      (progn
 +        (make-directory tmp-name1)
 +        (write-region "foo" nil tmp-name2)
 +        (write-region "bla" nil tmp-name3)
 +        (should (file-directory-p tmp-name1))
 +        (should (file-exists-p tmp-name2))
 +        (should (file-exists-p tmp-name3))
 +        (should (equal (directory-files tmp-name1) '("." ".." "bla" "foo")))
 +        (should (equal (directory-files tmp-name1 'full)
 +                       `(,(concat tmp-name1 "/.")
 +                         ,(concat tmp-name1 "/..")
 +                         ,tmp-name2 ,tmp-name3)))
 +        (should (equal (directory-files
 +                        tmp-name1 nil directory-files-no-dot-files-regexp)
 +                       '("bla" "foo")))
 +        (should (equal (directory-files
 +                        tmp-name1 'full directory-files-no-dot-files-regexp)
 +                       `(,tmp-name2 ,tmp-name3))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1 'recursive)))))
 +
 +(ert-deftest tramp-test17-insert-directory ()
 +  "Check `insert-directory'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let* ((tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (expand-file-name "foo" tmp-name1))
 +       ;; 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
 +        (make-directory tmp-name1)
 +        (write-region "foo" nil tmp-name2)
 +        (should (file-directory-p tmp-name1))
 +        (should (file-exists-p tmp-name2))
 +        (with-temp-buffer
 +          (insert-directory tmp-name1 nil)
 +          (goto-char (point-min))
 +          (should (looking-at-p (regexp-quote tmp-name1))))
 +        (with-temp-buffer
 +          (insert-directory tmp-name1 "-al")
 +          (goto-char (point-min))
 +          (should (looking-at-p (format "^.+ %s$" (regexp-quote tmp-name1)))))
 +        (with-temp-buffer
 +          (insert-directory (file-name-as-directory tmp-name1) "-al")
 +          (goto-char (point-min))
 +          (should
 +           (looking-at-p (format "^.+ %s/$" (regexp-quote tmp-name1)))))
 +        (with-temp-buffer
 +          (insert-directory
 +           (file-name-as-directory tmp-name1) "-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 ".", ".." and "foo" appear.
 +             "\\(.+ \\(\\.?\\.\\|foo\\)\n\\)\\{3\\}")))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1 'recursive)))))
 +
 +(ert-deftest tramp-test18-file-attributes ()
 +  "Check `file-attributes'.
 +This tests also `file-readable-p' and `file-regular-p'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  ;; We must use `file-truename' for the temporary directory, because
 +  ;; it could be located on a symlinked directory.  This would let the
 +  ;; test fail.
 +  (let* ((tramp-test-temporary-file-directory
 +        (file-truename tramp-test-temporary-file-directory))
 +       (tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (tramp--test-make-temp-name))
 +       ;; File name with "//".
 +       (tmp-name3
 +        (format
 +         "%s%s"
 +         (file-remote-p tmp-name1)
 +         (replace-regexp-in-string
 +          "/" "//" (file-remote-p tmp-name1 'localname))))
 +       attr)
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (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.
 +
 +        (condition-case err
 +            (progn
 +              (make-symbolic-link tmp-name1 tmp-name2)
 +              (should (file-exists-p tmp-name2))
 +              (should (file-symlink-p tmp-name2))
 +              (setq attr (file-attributes tmp-name2))
 +              (should (string-equal
 +                       (car attr)
 +                       (file-remote-p (file-truename tmp-name1) 'localname)))
 +              (delete-file tmp-name2))
 +          (file-error
 +           (should (string-equal (error-message-string err)
 +                                 "make-symbolic-link not supported"))))
 +
 +        ;; Check, that "//" in symlinks are handled properly.
 +        (with-temp-buffer
 +          (let ((default-directory tramp-test-temporary-file-directory))
 +            (shell-command
 +             (format
 +              "ln -s %s %s"
 +              (tramp-file-name-localname (tramp-dissect-file-name tmp-name3))
 +              (tramp-file-name-localname (tramp-dissect-file-name tmp-name2)))
 +             t)))
 +        (when (file-symlink-p tmp-name2)
 +          (setq attr (file-attributes tmp-name2))
 +          (should
 +           (string-equal
 +            (car attr)
 +            (tramp-file-name-localname (tramp-dissect-file-name tmp-name3))))
 +          (delete-file tmp-name2))
 +
 +        (delete-file tmp-name1)
 +        (make-directory tmp-name1)
 +        (should (file-exists-p tmp-name1))
 +        (should (file-readable-p tmp-name1))
 +        (should-not (file-regular-p tmp-name1))
 +        (setq attr (file-attributes tmp-name1))
 +        (should (eq (car attr) t)))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1))
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-file tmp-name2)))))
 +
 +(ert-deftest tramp-test19-directory-files-and-attributes ()
 +  "Check `directory-files-and-attributes'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  ;; `directory-files-and-attributes' contains also values for "../".
 +  ;; Ensure that this doesn't change during tests, for
 +  ;; example due to handling temporary files.
 +  (let* ((tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (expand-file-name "bla" tmp-name1))
 +       attr)
 +    (unwind-protect
 +      (progn
 +        (make-directory tmp-name1)
 +        (should (file-directory-p tmp-name1))
 +        (make-directory tmp-name2)
 +        (should (file-directory-p tmp-name2))
 +        (write-region "foo" nil (expand-file-name "foo" tmp-name2))
 +        (write-region "bar" nil (expand-file-name "bar" tmp-name2))
 +        (write-region "boz" nil (expand-file-name "boz" tmp-name2))
 +        (setq attr (directory-files-and-attributes tmp-name2))
 +        (should (consp attr))
 +        ;; Dumb remote shells without perl(1) or stat(1) are not
 +        ;; able to return the date correctly.  They say "don't know".
 +        (dolist (elt attr)
 +          (unless
 +              (equal
 +               (nth 5
 +                    (file-attributes (expand-file-name (car elt) tmp-name2)))
 +               '(0 0))
 +            (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))
 +            (should
 +             (equal (file-attributes (car elt)) (cdr elt)))))
 +        (setq attr (directory-files-and-attributes tmp-name2 nil "^b"))
 +        (should (equal (mapcar 'car attr) '("bar" "boz"))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1 'recursive)))))
 +
 +(ert-deftest tramp-test20-file-modes ()
 +  "Check `file-modes'.
 +This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (not
 +    (memq
 +     (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +     '(tramp-adb-file-name-handler
 +       tramp-gvfs-file-name-handler
 +       tramp-smb-file-name-handler))))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name)
 +        (should (file-exists-p tmp-name))
 +        (set-file-modes tmp-name #o777)
 +        (should (= (file-modes tmp-name) #o777))
 +        (should (file-executable-p tmp-name))
 +        (should (file-writable-p tmp-name))
 +        (set-file-modes tmp-name #o444)
 +        (should (= (file-modes tmp-name) #o444))
 +        (should-not (file-executable-p tmp-name))
 +        ;; A file is always writable for user "root".
 +        (unless (zerop (nth 2 (file-attributes tmp-name)))
 +          (should-not (file-writable-p tmp-name))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))))
 +
 +(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))
 +
 +  ;; We must use `file-truename' for the temporary directory, because
 +  ;; it could be located on a symlinked directory.  This would let the
 +  ;; test fail.
 +  (let* ((tramp-test-temporary-file-directory
 +        (file-truename tramp-test-temporary-file-directory))
 +       (tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (tramp--test-make-temp-name))
 +       (tmp-name3 (tramp--test-make-temp-name 'local)))
 +
 +    ;; Check `make-symbolic-link'.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (should (file-exists-p tmp-name1))
 +        ;; Method "smb" supports `make-symbolic-link' only if the
 +        ;; remote host has CIFS capabilities.  tramp-adb.el and
 +        ;; tramp-gvfs.el do not support symbolic links at all.
 +        (condition-case err
 +            (make-symbolic-link tmp-name1 tmp-name2)
 +          (file-error
 +           (skip-unless
 +            (not (string-equal (error-message-string err)
 +                               "make-symbolic-link not supported")))))
 +        (should (file-symlink-p tmp-name2))
 +        (should-error (make-symbolic-link tmp-name1 tmp-name2))
 +        (make-symbolic-link tmp-name1 tmp-name2 'ok-if-already-exists)
 +        (should (file-symlink-p tmp-name2))
 +        ;; `tmp-name3' is a local file name.
 +        (should-error (make-symbolic-link tmp-name1 tmp-name3)))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-file tmp-name1)
 +      (delete-file tmp-name2)))
 +
 +    ;; Check `add-name-to-file'.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (should (file-exists-p tmp-name1))
 +        (add-name-to-file tmp-name1 tmp-name2)
 +        (should-not (file-symlink-p tmp-name2))
 +        (should-error (add-name-to-file tmp-name1 tmp-name2))
 +        (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
 +        (should-not (file-symlink-p tmp-name2))
 +        ;; `tmp-name3' is a local file name.
 +        (should-error (add-name-to-file tmp-name1 tmp-name3)))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-file tmp-name1)
 +      (delete-file tmp-name2)))
 +
 +    ;; Check `file-truename'.
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name1)
 +        (should (file-exists-p tmp-name1))
 +        (make-symbolic-link tmp-name1 tmp-name2)
 +        (should (file-symlink-p tmp-name2))
 +        (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)))
 +      (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)))))))
 +
 +(ert-deftest tramp-test22-file-times ()
 +  "Check `set-file-times' and `file-newer-than-file-p'."
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (not
 +    (memq
 +     (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +     '(tramp-gvfs-file-name-handler tramp-smb-file-name-handler))))
 +
 +  (let ((tmp-name1 (tramp--test-make-temp-name))
 +      (tmp-name2 (tramp--test-make-temp-name))
 +      (tmp-name3 (tramp--test-make-temp-name)))
 +    (unwind-protect
 +      (progn
 +        (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)))
 +        ;; 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)))
 +          (write-region "bla" nil tmp-name2)
 +          (should (file-exists-p tmp-name2))
 +          (should (file-newer-than-file-p tmp-name2 tmp-name1))
 +          ;; `tmp-name3' does not exist.
 +          (should (file-newer-than-file-p tmp-name2 tmp-name3))
 +          (should-not (file-newer-than-file-p tmp-name3 tmp-name1))))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-file tmp-name1)
 +      (delete-file tmp-name2)))))
 +
 +(ert-deftest tramp-test23-visited-file-modtime ()
 +  "Check `set-visited-file-modtime' and `verify-visited-file-modtime'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    (unwind-protect
 +      (progn
 +        (write-region "foo" nil tmp-name)
 +        (should (file-exists-p tmp-name))
 +        (with-temp-buffer
 +          (insert-file-contents tmp-name)
 +          (should (verify-visited-file-modtime))
 +          (set-visited-file-modtime '(0 1))
 +          (should (verify-visited-file-modtime))
 +          (should (equal (visited-file-modtime) '(0 1 0 0)))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))))
 +
 +(ert-deftest tramp-test24-file-name-completion ()
 +  "Check `file-name-completion' and `file-name-all-completions'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (dolist (n-e '(nil t))
 +    (let ((non-essential n-e)
 +        (tmp-name (tramp--test-make-temp-name))
 +        (method (file-remote-p tramp-test-temporary-file-directory 'method))
 +        (host (file-remote-p tramp-test-temporary-file-directory 'host)))
 +
 +      (unwind-protect
 +        (progn
 +          ;; Method and host name in completion mode.  This kind of
 +          ;; completion does not work on MS Windows.
 +          (when (and (tramp-completion-mode-p)
 +                     (not (memq system-type '(cygwin windows-nt))))
 +            (unless (zerop (length method))
 +              (should
 +               (member
 +                (format "%s:" method)
 +                (file-name-all-completions (substring method 0 1) "/"))))
 +            (unless (zerop (length host))
 +              (let ((tramp-default-method (or method tramp-default-method)))
 +                (should
 +                 (member
 +                  (format "%s:" host)
 +                  (file-name-all-completions (substring host 0 1) "/")))))
 +            (unless (or (zerop (length method)) (zerop (length host)))
 +              (should
 +               (member
 +                (format "%s:" host)
 +                (file-name-all-completions
 +                 (substring host 0 1) (format "/%s:" method))))))
 +
 +          ;; Local files.
 +          (make-directory tmp-name)
 +          (should (file-directory-p tmp-name))
 +          (write-region "foo" nil (expand-file-name "foo" tmp-name))
 +          (should (file-exists-p (expand-file-name "foo" tmp-name)))
 +          (write-region "bar" nil (expand-file-name "bold" tmp-name))
 +          (should (file-exists-p (expand-file-name "bold" tmp-name)))
 +          (make-directory (expand-file-name "boz" tmp-name))
 +          (should (file-directory-p (expand-file-name "boz" tmp-name)))
 +          (should (equal (file-name-completion "fo" tmp-name) "foo"))
 +          (should (equal (file-name-completion "foo" tmp-name) t))
 +          (should (equal (file-name-completion "b" tmp-name) "bo"))
 +          (should-not (file-name-completion "a" tmp-name))
 +          (should
 +           (equal
 +            (file-name-completion "b" tmp-name 'file-directory-p) "boz/"))
 +          (should (equal (file-name-all-completions "fo" tmp-name) '("foo")))
 +          (should
 +           (equal
 +            (sort (file-name-all-completions "b" tmp-name) 'string-lessp)
 +            '("bold" "boz/")))
 +          (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) "bo"))
 +            (should
 +             (equal
 +              (sort (file-name-all-completions "" tmp-name) 'string-lessp)
 +              '("bold" "boz/"))))
 +          ;; `file-name-completion' ignores file names that end in
 +          ;; any string in `completion-ignored-extensions'.
 +          (let ((completion-ignored-extensions '(".ext")))
 +            (write-region "foo" nil (expand-file-name "foo.ext" tmp-name))
 +            (should (file-exists-p (expand-file-name "foo.ext" tmp-name)))
 +            (should (equal (file-name-completion "fo" tmp-name) "foo"))
 +            (should (equal (file-name-completion "foo" tmp-name) t))
 +            (should (equal (file-name-completion "foo." tmp-name) "foo.ext"))
 +            (should (equal (file-name-completion "foo.ext" tmp-name) t))
 +            ;; `file-name-all-completions' is not affected.
 +            (should
 +             (equal
 +              (sort (file-name-all-completions "" tmp-name) 'string-lessp)
 +              '("../" "./" "bold" "boz/" "foo" "foo.ext")))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name 'recursive))))))
 +
 +(ert-deftest tramp-test25-load ()
 +  "Check `load'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name)))
 +    (unwind-protect
 +      (progn
 +        (load tmp-name 'noerror 'nomessage)
 +        (should-not (featurep 'tramp-test-load))
 +        (write-region "(provide 'tramp-test-load)" nil tmp-name)
 +        ;; `load' in lread.c does not pass `must-suffix'.  Why?
 +        ;(should-error (load tmp-name nil 'nomessage 'nosuffix 'must-suffix))
 +        (load tmp-name nil 'nomessage 'nosuffix)
 +        (should (featurep 'tramp-test-load)))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (and (featurep 'tramp-test-load) (unload-feature 'tramp-test-load))
 +      (delete-file tmp-name)))))
 +
 +(ert-deftest tramp-test26-process-file ()
 +  "Check `process-file'."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (not
 +    (memq
 +     (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +     '(tramp-gvfs-file-name-handler tramp-smb-file-name-handler))))
 +
 +  (let* ((tmp-name (tramp--test-make-temp-name))
 +       (fnnd (file-name-nondirectory tmp-name))
 +       (default-directory tramp-test-temporary-file-directory)
 +       kill-buffer-query-functions)
 +    (unwind-protect
 +      (progn
 +        ;; We cannot use "/bin/true" and "/bin/false"; those paths
 +        ;; do not exist on hydra.
 +        (should (zerop (process-file "true")))
 +        (should-not (zerop (process-file "false")))
 +        (should-not (zerop (process-file "binary-does-not-exist")))
 +        (with-temp-buffer
 +          (write-region "foo" nil tmp-name)
 +          (should (file-exists-p tmp-name))
 +          (should (zerop (process-file "ls" nil t nil fnnd)))
 +          ;; `ls' could produce colorized output.
 +          (goto-char (point-min))
 +          (while
 +              (re-search-forward tramp-display-escape-sequence-regexp nil t)
 +            (replace-match "" nil nil))
 +          (should (string-equal (format "%s\n" fnnd) (buffer-string)))
 +          (should-not (get-buffer-window (current-buffer) t))
 +
 +          ;; Second run. The output must be appended.
 +          (goto-char (point-max))
 +          (should (zerop (process-file "ls" nil t t fnnd)))
 +          ;; `ls' could produce colorized output.
 +          (goto-char (point-min))
 +          (while
 +              (re-search-forward tramp-display-escape-sequence-regexp nil t)
 +            (replace-match "" nil nil))
 +          (should
 +           (string-equal (format "%s\n%s\n" fnnd fnnd) (buffer-string)))
 +          ;; A non-nil DISPLAY must not raise the buffer.
 +          (should-not (get-buffer-window (current-buffer) t))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))))
 +
 +(ert-deftest tramp-test27-start-file-process ()
 +  "Check `start-file-process'."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (not
 +    (memq
 +     (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +     '(tramp-adb-file-name-handler
 +       tramp-gvfs-file-name-handler
 +       tramp-smb-file-name-handler))))
 +
 +  (let ((default-directory tramp-test-temporary-file-directory)
 +      (tmp-name (tramp--test-make-temp-name))
 +      kill-buffer-query-functions proc)
 +    (unwind-protect
 +      (with-temp-buffer
 +        (setq proc (start-file-process "test1" (current-buffer) "cat"))
 +        (should (processp proc))
 +        (should (equal (process-status proc) 'run))
 +        (process-send-string proc "foo")
 +        (process-send-eof proc)
 +        ;; Read output.
 +        (with-timeout (10 (ert-fail "`start-file-process' timed out"))
 +          (while (< (- (point-max) (point-min)) (length "foo"))
 +            (accept-process-output proc 1)))
 +        (should (string-equal (buffer-string) "foo")))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-process proc)))
 +
 +    (unwind-protect
 +      (with-temp-buffer
 +        (write-region "foo" nil tmp-name)
 +        (should (file-exists-p tmp-name))
 +        (setq proc
 +              (start-file-process
 +               "test2" (current-buffer)
 +               "cat" (file-name-nondirectory tmp-name)))
 +        (should (processp proc))
 +        ;; Read output.
 +        (with-timeout (10 (ert-fail "`start-file-process' timed out"))
 +          (while (< (- (point-max) (point-min)) (length "foo"))
 +            (accept-process-output proc 1)))
 +        (should (string-equal (buffer-string) "foo")))
 +
 +      ;; Cleanup.
 +      (ignore-errors
 +      (delete-process proc)
 +      (delete-file tmp-name)))
 +
 +    (unwind-protect
 +      (with-temp-buffer
 +        (setq proc (start-file-process "test3" (current-buffer) "cat"))
 +        (should (processp proc))
 +        (should (equal (process-status proc) 'run))
 +        (set-process-filter
 +         proc
 +         (lambda (p s) (with-current-buffer (process-buffer p) (insert s))))
 +        (process-send-string proc "foo")
 +        (process-send-eof proc)
 +        ;; Read output.
 +        (with-timeout (10 (ert-fail "`start-file-process' timed out"))
 +          (while (< (- (point-max) (point-min)) (length "foo"))
 +            (accept-process-output proc 1)))
 +        (should (string-equal (buffer-string) "foo")))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-process proc)))))
 +
 +(ert-deftest tramp-test28-shell-command ()
 +  "Check `shell-command'."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (not
 +    (memq
 +     (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +     '(tramp-adb-file-name-handler
 +       tramp-gvfs-file-name-handler
 +       tramp-smb-file-name-handler))))
 +
 +  (let ((tmp-name (tramp--test-make-temp-name))
 +      (default-directory tramp-test-temporary-file-directory)
 +      kill-buffer-query-functions)
 +    (unwind-protect
 +      (with-temp-buffer
 +        (write-region "foo" nil tmp-name)
 +        (should (file-exists-p tmp-name))
 +        (shell-command
 +         (format "ls %s" (file-name-nondirectory tmp-name)) (current-buffer))
 +        ;; `ls' could produce colorized output.
 +        (goto-char (point-min))
 +        (while (re-search-forward tramp-display-escape-sequence-regexp nil t)
 +          (replace-match "" nil nil))
 +        (should
 +         (string-equal
 +          (format "%s\n" (file-name-nondirectory tmp-name)) (buffer-string))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))
 +
 +    (unwind-protect
 +        (with-temp-buffer
 +          (write-region "foo" nil tmp-name)
 +        (should (file-exists-p tmp-name))
 +          (async-shell-command
 +         (format "ls %s" (file-name-nondirectory tmp-name)) (current-buffer))
 +        (set-process-sentinel (get-buffer-process (current-buffer)) nil)
 +        ;; Read output.
 +        (with-timeout (10 (ert-fail "`async-shell-command' timed out"))
 +          (while (< (- (point-max) (point-min))
 +                    (1+ (length (file-name-nondirectory tmp-name))))
 +            (accept-process-output (get-buffer-process (current-buffer)) 1)))
 +        ;; `ls' could produce colorized output.
 +        (goto-char (point-min))
 +        (while (re-search-forward tramp-display-escape-sequence-regexp nil t)
 +          (replace-match "" nil nil))
 +        ;; There might be a nasty "Process *Async Shell* finished" message.
 +        (goto-char (point-min))
 +        (forward-line)
 +        (narrow-to-region (point-min) (point))
 +        (should
 +         (string-equal
 +          (format "%s\n" (file-name-nondirectory tmp-name)) (buffer-string))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))
 +
 +    (unwind-protect
 +      (with-temp-buffer
 +          (write-region "foo" nil tmp-name)
 +        (should (file-exists-p tmp-name))
 +        (async-shell-command "read line; ls $line" (current-buffer))
 +        (set-process-sentinel (get-buffer-process (current-buffer)) nil)
 +        (process-send-string
 +         (get-buffer-process (current-buffer))
 +         (format "%s\n" (file-name-nondirectory tmp-name)))
 +        ;; Read output.
 +        (with-timeout (10 (ert-fail "`async-shell-command' timed out"))
 +          (while (< (- (point-max) (point-min))
 +                    (1+ (length (file-name-nondirectory tmp-name))))
 +            (accept-process-output (get-buffer-process (current-buffer)) 1)))
 +        ;; `ls' could produce colorized output.
 +        (goto-char (point-min))
 +        (while (re-search-forward tramp-display-escape-sequence-regexp nil t)
 +          (replace-match "" nil nil))
 +        ;; There might be a nasty "Process *Async Shell* finished" message.
 +        (goto-char (point-min))
 +        (forward-line)
 +        (narrow-to-region (point-min) (point))
 +        (should
 +         (string-equal
 +          (format "%s\n" (file-name-nondirectory tmp-name)) (buffer-string))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name)))))
 +
- (ert-deftest tramp-test30-make-auto-save-file-name ()
++(defun tramp-test--shell-command-to-string-asynchronously (command)
++  "Like `shell-command-to-string', but for asynchronous processes."
++  (with-temp-buffer
++    (async-shell-command command (current-buffer))
++    ;; Suppress nasty messages.
++    (set-process-sentinel (get-buffer-process (current-buffer)) nil)
++    (while (get-buffer-process (current-buffer))
++      (accept-process-output (get-buffer-process (current-buffer)) 0.1))
++    (accept-process-output)
++    (buffer-substring-no-properties (point-min) (point-max))))
++
++;; This test is inspired by Bug#23952.
++(ert-deftest tramp-test29-environment-variables ()
++  "Check that remote processes set / unset environment variables properly."
++  :tags '(:expensive-test)
++  (skip-unless (tramp--test-enabled))
++  (skip-unless
++   (eq
++    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
++    'tramp-sh-file-name-handler))
++
++  (dolist (this-shell-command-to-string
++         '(;; Synchronously.
++           shell-command-to-string
++           ;; Asynchronously.
++           tramp-test--shell-command-to-string-asynchronously))
++
++    (let ((default-directory tramp-test-temporary-file-directory)
++        (shell-file-name "/bin/sh")
++        (envvar (concat "VAR_" (upcase (md5 (current-time-string)))))
++        kill-buffer-query-functions)
++
++      (unwind-protect
++        ;; Set a value.
++        (let ((process-environment
++               (cons (concat envvar "=foo") process-environment)))
++          ;; Default value.
++          (should
++           (string-match
++            "foo"
++            (funcall
++             this-shell-command-to-string
++             (format "echo -n ${%s:?bla}" envvar))))))
++
++      (unwind-protect
++        ;; Set the empty value.
++        (let ((process-environment
++               (cons (concat envvar "=") process-environment)))
++          ;; Value is null.
++          (should
++           (string-match
++            "bla"
++            (funcall
++             this-shell-command-to-string
++             (format "echo -n ${%s:?bla}" envvar))))
++          ;; Variable is set.
++          (should
++           (string-match
++            (regexp-quote envvar)
++            (funcall this-shell-command-to-string "set")))))
++
++      ;; We force a reconnect, in order to have a clean environment.
++      (tramp-cleanup-connection
++       (tramp-dissect-file-name tramp-test-temporary-file-directory)
++       'keep-debug 'keep-password)
++      (unwind-protect
++        ;; Unset the variable.
++        (let ((tramp-remote-process-environment
++               (cons (concat envvar "=foo")
++                     tramp-remote-process-environment)))
++          ;; Set the initial value, we want to unset below.
++          (should
++           (string-match
++            "foo"
++            (funcall
++             this-shell-command-to-string
++             (format "echo -n ${%s:?bla}" envvar))))
++          (let ((process-environment
++                 (cons envvar process-environment)))
++            ;; Variable is unset.
++            (should
++             (string-match
++              "bla"
++              (funcall
++               this-shell-command-to-string
++               (format "echo -n ${%s:?bla}" envvar))))
++            ;; Variable is unset.
++            (should-not
++             (string-match
++              (regexp-quote envvar)
++              (funcall this-shell-command-to-string "set")))))))))
++
++(ert-deftest tramp-test30-vc-registered ()
 +  "Check `vc-registered'."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +
 +  (let* ((default-directory tramp-test-temporary-file-directory)
 +       (tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (expand-file-name "foo" tmp-name1))
 +       (tramp-remote-process-environment tramp-remote-process-environment)
 +       (vc-handled-backends
 +        (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
 +          (cond
 +           ((tramp-find-executable v vc-git-program (tramp-get-remote-path v))
 +            '(Git))
 +           ((tramp-find-executable v vc-hg-program (tramp-get-remote-path v))
 +            '(Hg))
 +           ((tramp-find-executable v vc-bzr-program (tramp-get-remote-path v))
 +            (setq tramp-remote-process-environment
 +                  (cons (format "BZR_HOME=%s"
 +                                (file-remote-p tmp-name1 'localname))
 +                        tramp-remote-process-environment))
 +            ;; We must force a reconnect, in order to activate $BZR_HOME.
 +            (tramp-cleanup-connection
 +             (tramp-dissect-file-name tramp-test-temporary-file-directory)
 +             nil 'keep-password)
 +            '(Bzr))
 +           (t nil)))))
 +    (skip-unless vc-handled-backends)
 +    (message "%s" vc-handled-backends)
 +
 +    (unwind-protect
 +      (progn
 +        (make-directory tmp-name1)
 +        (write-region "foo" nil tmp-name2)
 +        (should (file-directory-p tmp-name1))
 +        (should (file-exists-p tmp-name2))
 +        (should-not (vc-registered tmp-name1))
 +        (should-not (vc-registered tmp-name2))
 +
 +        (let ((default-directory tmp-name1))
 +          ;; Create empty repository, and register the file.
 +          ;; Sometimes, creation of repository fails (bzr!); we skip
 +          ;; the test then.
 +          (condition-case nil
 +              (vc-create-repo (car vc-handled-backends))
 +            (error (skip-unless nil)))
 +          ;; The structure of VC-FILESET is not documented.  Let's
 +          ;; hope it won't change.
 +          (condition-case nil
 +              (vc-register
 +               (list (car vc-handled-backends)
 +                     (list (file-name-nondirectory tmp-name2))))
 +            ;; `vc-register' has changed its arguments in Emacs 25.1.
 +            (error
 +             (vc-register
 +              nil (list (car vc-handled-backends)
 +                        (list (file-name-nondirectory tmp-name2))))))
 +          ;; vc-git uses an own process sentinel, Tramp's sentinel
 +          ;; for flushing the cache isn't used.
 +          (dired-uncache (concat (file-remote-p default-directory) "/"))
 +          (should (vc-registered (file-name-nondirectory tmp-name2)))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1 'recursive)))))
 +
-   "Perform the test in `tramp-test31-special-characters*'."
++(ert-deftest tramp-test31-make-auto-save-file-name ()
 +  "Check `make-auto-save-file-name'."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (let ((tmp-name1 (tramp--test-make-temp-name))
 +      (tmp-name2 (tramp--test-make-temp-name)))
 +
 +    (unwind-protect
 +      (progn
 +        ;; Use default `auto-save-file-name-transforms' mechanism.
 +        (let (tramp-auto-save-directory)
 +          (with-temp-buffer
 +            (setq buffer-file-name tmp-name1)
 +            (should
 +             (string-equal
 +              (make-auto-save-file-name)
 +              ;; This is taken from original `make-auto-save-file-name'.
 +              (expand-file-name
 +               (format
 +                "#%s#"
 +                (subst-char-in-string
 +                 ?/ ?! (replace-regexp-in-string "!" "!!" tmp-name1)))
 +               temporary-file-directory)))))
 +
 +        ;; No mapping.
 +        (let (tramp-auto-save-directory auto-save-file-name-transforms)
 +          (with-temp-buffer
 +            (setq buffer-file-name tmp-name1)
 +            (should
 +             (string-equal
 +              (make-auto-save-file-name)
 +              (expand-file-name
 +               (format "#%s#" (file-name-nondirectory tmp-name1))
 +               tramp-test-temporary-file-directory)))))
 +
 +        ;; Use default `tramp-auto-save-directory' mechanism.
 +        (let ((tramp-auto-save-directory tmp-name2))
 +          (with-temp-buffer
 +            (setq buffer-file-name tmp-name1)
 +            (should
 +             (string-equal
 +              (make-auto-save-file-name)
 +              ;; This is taken from Tramp.
 +              (expand-file-name
 +               (format
 +                "#%s#"
 +                (tramp-subst-strs-in-string
 +                 '(("_" . "|")
 +                   ("/" . "_a")
 +                   (":" . "_b")
 +                   ("|" . "__")
 +                   ("[" . "_l")
 +                   ("]" . "_r"))
 +                 tmp-name1))
 +               tmp-name2)))
 +            (should (file-directory-p tmp-name2))))
 +
 +        ;; Relative file names shall work, too.
 +        (let ((tramp-auto-save-directory "."))
 +          (with-temp-buffer
 +            (setq buffer-file-name tmp-name1
 +                  default-directory tmp-name2)
 +            (should
 +             (string-equal
 +              (make-auto-save-file-name)
 +              ;; This is taken from Tramp.
 +              (expand-file-name
 +               (format
 +                "#%s#"
 +                (tramp-subst-strs-in-string
 +                 '(("_" . "|")
 +                   ("/" . "_a")
 +                   (":" . "_b")
 +                   ("|" . "__")
 +                   ("[" . "_l")
 +                   ("]" . "_r"))
 +                 tmp-name1))
 +               tmp-name2)))
 +            (should (file-directory-p tmp-name2)))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-file tmp-name1))
 +      (ignore-errors (delete-directory tmp-name2 'recursive)))))
 +
 +(defun tramp--test-adb-p ()
 +  "Check, whether the remote host runs Android.
 +This requires restrictions of file name syntax."
 +  (tramp-adb-file-name-p tramp-test-temporary-file-directory))
 +
 +(defun tramp--test-ftp-p ()
 +  "Check, whether an FTP-like method is used.
 +This does not support globbing characters in file names (yet)."
 +  ;; Globbing characters are ??, ?* and ?\[.
 +  (and (eq (tramp-find-foreign-file-name-handler
 +          tramp-test-temporary-file-directory)
 +         'tramp-sh-file-name-handler)
 +       (string-match
 +      "ftp$" (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."
 +  (string-equal
 +   "rsync" (file-remote-p tramp-test-temporary-file-directory 'method)))
 +
 +(defun tramp--test-gvfs-p ()
 +  "Check, whether the remote host runs a GVFS based method.
 +This requires restrictions of file name syntax."
 +  (tramp-gvfs-file-name-p tramp-test-temporary-file-directory))
 +
 +(defun tramp--test-smb-or-windows-nt-p ()
 +  "Check, whether the locale or remote host runs MS Windows.
 +This requires restrictions of file name syntax."
 +  (or (eq system-type 'windows-nt)
 +      (tramp-smb-file-name-p tramp-test-temporary-file-directory)))
 +
 +(defun tramp--test-hpux-p ()
 +  "Check, whether the remote host runs HP-UX.
 +Several special characters do not work properly there."
 +  ;; We must refill the cache.  `file-truename' does it.
 +  (with-parsed-tramp-file-name
 +      (file-truename tramp-test-temporary-file-directory) nil
 +    (string-match "^HP-UX" (tramp-get-connection-property v "uname" ""))))
 +
 +(defun tramp--test-check-files (&rest files)
 +  "Run a simple but comprehensive test over every file in FILES."
 +  ;; We must use `file-truename' for the temporary directory, because
 +  ;; it could be located on a symlinked directory.  This would let the
 +  ;; test fail.
 +  (let* ((tramp-test-temporary-file-directory
 +        (file-truename tramp-test-temporary-file-directory))
 +       (tmp-name1 (tramp--test-make-temp-name))
 +       (tmp-name2 (tramp--test-make-temp-name 'local))
 +       (files (delq nil files)))
 +    (unwind-protect
 +      (progn
 +        (make-directory tmp-name1)
 +        (make-directory tmp-name2)
 +        (dolist (elt files)
 +          (let* ((file1 (expand-file-name elt tmp-name1))
 +                 (file2 (expand-file-name elt tmp-name2))
 +                 (file3 (expand-file-name (concat elt "foo") tmp-name1)))
 +            (write-region elt nil file1)
 +            (should (file-exists-p file1))
 +
 +            ;; Check file contents.
 +            (with-temp-buffer
 +              (insert-file-contents file1)
 +              (should (string-equal (buffer-string) elt)))
 +
 +            ;; Copy file both directions.
 +            (copy-file file1 tmp-name2)
 +            (should (file-exists-p file2))
 +            (delete-file file1)
 +            (should-not (file-exists-p file1))
 +            (copy-file file2 tmp-name1)
 +            (should (file-exists-p file1))
 +
 +            ;; Method "smb" supports `make-symbolic-link' only if the
 +            ;; remote host has CIFS capabilities.  tramp-adb.el and
 +            ;; tramp-gvfs.el do not support symbolic links at all.
 +            (condition-case err
 +                (progn
 +                  (make-symbolic-link file1 file3)
 +                  (should (file-symlink-p file3))
 +                  (should
 +                   (string-equal
 +                    (expand-file-name file1) (file-truename file3)))
 +                  (should
 +                   (string-equal
 +                    (car (file-attributes file3))
 +                    (file-remote-p (file-truename file1) 'localname)))
 +                  ;; Check file contents.
 +                  (with-temp-buffer
 +                    (insert-file-contents file3)
 +                    (should (string-equal (buffer-string) elt)))
 +                  (delete-file file3))
 +              (file-error
 +               (should (string-equal (error-message-string err)
 +                                     "make-symbolic-link not supported"))))))
 +
 +        ;; Check file names.
 +        (should (equal (directory-files
 +                        tmp-name1 nil directory-files-no-dot-files-regexp)
 +                       (sort (copy-sequence files) 'string-lessp)))
 +        (should (equal (directory-files
 +                        tmp-name2 nil directory-files-no-dot-files-regexp)
 +                       (sort (copy-sequence files) 'string-lessp)))
 +
 +        ;; `substitute-in-file-name' could return different values.
 +        ;; For `adb', there could be strange file permissions
 +        ;; preventing overwriting a file.  We don't care in this
 +        ;; testcase.
 +        (dolist (elt files)
 +          (let ((file1
 +                 (substitute-in-file-name (expand-file-name elt tmp-name1)))
 +                (file2
 +                 (substitute-in-file-name (expand-file-name elt tmp-name2))))
 +            (ignore-errors (write-region elt nil file1))
 +            (should (file-exists-p file1))
 +            (ignore-errors (write-region elt nil file2 nil 'nomessage))
 +            (should (file-exists-p file2))))
 +
 +        (should (equal (directory-files
 +                        tmp-name1 nil directory-files-no-dot-files-regexp)
 +                       (directory-files
 +                        tmp-name2 nil directory-files-no-dot-files-regexp)))
 +
 +        ;; Check directory creation.  We use a subdirectory "foo"
 +        ;; in order to avoid conflicts with previous file name tests.
 +        (dolist (elt files)
 +          (let* ((elt1 (concat elt "foo"))
 +                 (file1 (expand-file-name (concat "foo/" elt) tmp-name1))
 +                 (file2 (expand-file-name elt file1))
 +                 (file3 (expand-file-name elt1 file1)))
 +            (make-directory file1 'parents)
 +            (should (file-directory-p file1))
 +            (write-region elt nil file2)
 +            (should (file-exists-p file2))
 +            (should
 +             (equal
 +              (directory-files file1 nil directory-files-no-dot-files-regexp)
 +              `(,elt)))
 +            (should
 +             (equal
 +              (caar (directory-files-and-attributes
 +                     file1 nil directory-files-no-dot-files-regexp))
 +              elt))
 +
 +            ;; Check symlink in `directory-files-and-attributes'.
 +            (condition-case err
 +                (progn
 +                  (make-symbolic-link file2 file3)
 +                  (should (file-symlink-p file3))
 +                  (should
 +                   (string-equal
 +                    (caar (directory-files-and-attributes
 +                           file1 nil (regexp-quote elt1)))
 +                    elt1))
 +                  (should
 +                   (string-equal
 +                    (cadr (car (directory-files-and-attributes
 +                                file1 nil (regexp-quote elt1))))
 +                    (file-remote-p (file-truename file2) 'localname)))
 +                  (delete-file file3)
 +                  (should-not (file-exists-p file3)))
 +              (file-error
 +               (should (string-equal (error-message-string err)
 +                                     "make-symbolic-link not supported"))))
 +
 +            (delete-file file2)
 +            (should-not (file-exists-p file2))
 +            (delete-directory file1)
 +            (should-not (file-exists-p file1)))))
 +
 +      ;; Cleanup.
 +      (ignore-errors (delete-directory tmp-name1 'recursive))
 +      (ignore-errors (delete-directory tmp-name2 'recursive)))))
 +
 +(defun tramp--test-special-characters ()
- (ert-deftest tramp-test31-special-characters ()
++  "Perform the test in `tramp-test32-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-smb-or-windows-nt-p))
 +       "foo bar baz"
 +     (if (or (tramp--test-adb-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-smb-or-windows-nt-p))
 +     "?foo?bar?baz?")
 +   (unless (or (tramp--test-ftp-p)
 +             (tramp--test-gvfs-p)
 +             (tramp--test-smb-or-windows-nt-p))
 +     "*foo*bar*baz*")
 +   (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
 +       "'foo'bar'baz'"
 +     "'foo\"bar'baz\"")
 +   "#foo~bar#baz~"
 +   (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
 +       "!foo!bar!baz!"
 +     "!foo|bar!baz|")
 +   (if (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
 +       ";foo;bar;baz;"
 +     ":foo;bar:baz;")
 +   (unless (or (tramp--test-gvfs-p) (tramp--test-smb-or-windows-nt-p))
 +     "<foo>bar<baz>")
 +   "(foo)bar(baz)"
 +   (unless (or (tramp--test-ftp-p) (tramp--test-gvfs-p)) "[foo]bar[baz]")
 +   "{foo}bar{baz}"))
 +
 +;; These tests are inspired by Bug#17238.
- (ert-deftest tramp-test31-special-characters-with-stat ()
++(ert-deftest tramp-test32-special-characters ()
 +  "Check special characters in file names."
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +
 +  (tramp--test-special-characters))
 +
- (ert-deftest tramp-test31-special-characters-with-perl ()
++(ert-deftest tramp-test32-special-characters-with-stat ()
 +  "Check special characters in file names.
 +Use the `stat' command."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +  (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
 +    (skip-unless (tramp-get-remote-stat v)))
 +
 +  (let ((tramp-connection-properties
 +       (append
 +        `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "perl" nil))
 +        tramp-connection-properties)))
 +    (tramp--test-special-characters)))
 +
- (ert-deftest tramp-test31-special-characters-with-ls ()
++(ert-deftest tramp-test32-special-characters-with-perl ()
 +  "Check special characters in file names.
 +Use the `perl' command."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +  (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
 +    (skip-unless (tramp-get-remote-perl v)))
 +
 +  (let ((tramp-connection-properties
 +       (append
 +        `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "stat" nil)
 +          ;; See `tramp-sh-handle-file-truename'.
 +          (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "readlink" nil))
 +        tramp-connection-properties)))
 +    (tramp--test-special-characters)))
 +
-   "Perform the test in `tramp-test32-utf8*'."
++(ert-deftest tramp-test32-special-characters-with-ls ()
 +  "Check special characters in file names.
 +Use the `ls' command."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +
 +  (let ((tramp-connection-properties
 +       (append
 +        `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "perl" nil)
 +          (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "stat" nil)
 +          ;; See `tramp-sh-handle-file-truename'.
 +          (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "readlink" nil))
 +        tramp-connection-properties)))
 +    (tramp--test-special-characters)))
 +
 +(defun tramp--test-utf8 ()
- (ert-deftest tramp-test32-utf8 ()
++  "Perform the test in `tramp-test33-utf8*'."
 +  (let* ((utf8 (if (and (eq system-type 'darwin)
 +                      (memq 'utf-8-hfs (coding-system-list)))
 +                 'utf-8-hfs 'utf-8))
 +       (coding-system-for-read utf8)
 +       (coding-system-for-write utf8)
 +       (file-name-coding-system utf8))
 +    (tramp--test-check-files
 +     (unless (tramp--test-hpux-p) "Γυρίστε το Γαλαξία με Ώτο Στοπ")
 +     (unless (tramp--test-hpux-p)
 +       "أصبح بوسعك الآن تنزيل نسخة كاملة من موسوعة ويكيبيديا العربية لتصفحها بلا اتصال بالإنترنت")
 +     "银河系漫游指南系列"
 +     "Автостопом по гала́ктике")))
 +
- (ert-deftest tramp-test32-utf8-with-stat ()
++(ert-deftest tramp-test33-utf8 ()
 +  "Check UTF8 encoding in file names and file contents."
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +
 +  (tramp--test-utf8))
 +
- (ert-deftest tramp-test32-utf8-with-perl ()
++(ert-deftest tramp-test33-utf8-with-stat ()
 +  "Check UTF8 encoding in file names and file contents.
 +Use the `stat' command."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +  (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
 +    (skip-unless (tramp-get-remote-stat v)))
 +
 +  (let ((tramp-connection-properties
 +       (append
 +        `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "perl" nil))
 +        tramp-connection-properties)))
 +    (tramp--test-utf8)))
 +
- (ert-deftest tramp-test32-utf8-with-ls ()
++(ert-deftest tramp-test33-utf8-with-perl ()
 +  "Check UTF8 encoding in file names and file contents.
 +Use the `perl' command."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +  (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil
 +    (skip-unless (tramp-get-remote-perl v)))
 +
 +  (let ((tramp-connection-properties
 +       (append
 +        `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "stat" nil)
 +          ;; See `tramp-sh-handle-file-truename'.
 +          (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "readlink" nil))
 +        tramp-connection-properties)))
 +    (tramp--test-utf8)))
 +
- (ert-deftest tramp-test33-asynchronous-requests ()
++(ert-deftest tramp-test33-utf8-with-ls ()
 +  "Check UTF8 encoding in file names and file contents.
 +Use the `ls' command."
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless (not (tramp--test-rsync-p)))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +
 +  (let ((tramp-connection-properties
 +       (append
 +        `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "perl" nil)
 +          (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "stat" nil)
 +          ;; See `tramp-sh-handle-file-truename'.
 +          (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory))
 +           "readlink" nil))
 +        tramp-connection-properties)))
 +    (tramp--test-utf8)))
 +
 +;; This test is inspired by Bug#16928.
- (ert-deftest tramp-test34-recursive-load ()
++(ert-deftest tramp-test34-asynchronous-requests ()
 +  "Check parallel asynchronous requests.
 +Such requests could arrive from timers, process filters and
 +process sentinels.  They shall not disturb each other."
 +  ;; Mark as failed until bug has been fixed.
 +  :expected-result :failed
 +  :tags '(:expensive-test)
 +  (skip-unless (tramp--test-enabled))
 +  (skip-unless
 +   (eq
 +    (tramp-find-foreign-file-name-handler tramp-test-temporary-file-directory)
 +    'tramp-sh-file-name-handler))
 +
 +  ;; Keep instrumentation verbosity 0 until Tramp bug is fixed.  This
 +  ;; has the side effect, that this test fails instead to abort.  Good
 +  ;; for hydra.
 +  (tramp--instrument-test-case 0
 +  (let* ((tmp-name (tramp--test-make-temp-name))
 +       (default-directory tmp-name)
 +       (remote-file-name-inhibit-cache t)
 +       timer buffers kill-buffer-query-functions)
 +
 +    (unwind-protect
 +      (progn
 +        (make-directory tmp-name)
 +
 +        ;; Setup a timer in order to raise an ordinary command again
 +        ;; and again.  `vc-registered' is well suited, because there
 +        ;; are many checks.
 +        (setq
 +         timer
 +         (run-at-time
 +          0 1
 +          (lambda ()
 +            (when buffers
 +              (vc-registered
 +               (buffer-name (nth (random (length buffers)) buffers)))))))
 +
 +        ;; Create temporary buffers.  The number of buffers
 +        ;; corresponds to the number of processes; it could be
 +        ;; increased in order to make pressure on Tramp.
 +        (dotimes (i 5)
 +          (add-to-list 'buffers (generate-new-buffer "*temp*")))
 +
 +        ;; Open asynchronous processes.  Set process sentinel.
 +        (dolist (buf buffers)
 +          (async-shell-command "read line; touch $line; echo $line" buf)
 +          (set-process-sentinel
 +           (get-buffer-process buf)
 +           (lambda (proc _state)
 +             (delete-file (buffer-name (process-buffer proc))))))
 +
 +        ;; Send a string.  Use a random order of the buffers.  Mix
 +        ;; with regular operation.
 +        (let ((buffers (copy-sequence buffers))
 +              buf)
 +          (while buffers
 +            (setq buf (nth (random (length buffers)) buffers))
 +            (process-send-string
 +             (get-buffer-process buf) (format "'%s'\n" buf))
 +            (file-attributes (buffer-name buf))
 +            (setq buffers (delq buf buffers))))
 +
 +        ;; Wait until the whole output has been read.
 +        (with-timeout ((* 10 (length buffers))
 +                       (ert-fail "`async-shell-command' timed out"))
 +          (let ((buffers (copy-sequence buffers))
 +                buf)
 +            (while buffers
 +              (setq buf (nth (random (length buffers)) buffers))
 +              (if (ignore-errors
 +                    (memq (process-status (get-buffer-process buf))
 +                          '(run open)))
 +                  (accept-process-output (get-buffer-process buf) 0.1)
 +                (setq buffers (delq buf buffers))))))
 +
 +        ;; Check.
 +        (dolist (buf buffers)
 +          (with-current-buffer buf
 +            (should
 +             (string-equal (format "'%s'\n" buf) (buffer-string)))))
 +        (should-not
 +         (directory-files tmp-name nil directory-files-no-dot-files-regexp)))
 +
 +      ;; Cleanup.
 +      (ignore-errors (cancel-timer timer))
 +      (ignore-errors (delete-directory tmp-name 'recursive))
 +      (dolist (buf buffers)
 +      (ignore-errors (kill-buffer buf)))))))
 +
- (ert-deftest tramp-test35-unload ()
++(ert-deftest tramp-test35-recursive-load ()
 +  "Check that Tramp does not fail due to recursive load."
 +  (skip-unless (tramp--test-enabled))
 +
 +  (dolist (code
 +         (list
 +          (format
 +           "(expand-file-name %S)"
 +           tramp-test-temporary-file-directory)
 +          (format
 +           "(let ((default-directory %S)) (expand-file-name %S))"
 +           tramp-test-temporary-file-directory
 +           temporary-file-directory)))
 +    (should-not
 +     (string-match
 +      "Recursive load"
 +      (shell-command-to-string
 +       (format
 +      "%s -batch -Q -L %s --eval %s"
 +      (expand-file-name invocation-name invocation-directory)
 +      (mapconcat 'shell-quote-argument load-path " -L ")
 +      (shell-quote-argument code)))))))
 +
- ;; * Fix Bug#16928.  Set expected error of `tramp-test33-asynchronous-requests'.
- ;; * Fix `tramp-test35-unload' (Not all symbols are unbound).  Set
++(ert-deftest tramp-test36-unload ()
 +  "Check that Tramp and its subpackages unload completely.
 +Since it unloads Tramp, it shall be the last test to run."
 +  ;; Mark as failed until all symbols are unbound.
 +  :expected-result (if (featurep 'tramp) :failed :passed)
 +  :tags '(:expensive-test)
 +  (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.  We do not regard our
 +    ;; test symbols, and the Tramp unload hooks.
 +    (mapatoms
 +     (lambda (x)
 +       (and (or (boundp x) (functionp 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)))))
 +    ;; 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 "-hooks?$" (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)))))))
 +
 +;; TODO:
 +
 +;; * dired-compress-file
 +;; * dired-uncache
 +;; * file-acl
 +;; * file-ownership-preserved-p
 +;; * file-selinux-context
 +;; * find-backup-file-name
 +;; * set-file-acl
 +;; * set-file-selinux-context
 +
 +;; * Work on skipped tests.  Make a comment, when it is impossible.
 +;; * Fix `tramp-test06-directory-file-name' for `ftp'.
 +;; * Fix `tramp-test15-copy-directory' for `rsync'.
 +;; * Fix `tramp-test27-start-file-process' on MS Windows (`process-send-eof'?).
++;; * Fix Bug#16928.  Set expected error of `tramp-test34-asynchronous-requests'.
++;; * Fix `tramp-test36-unload' (Not all symbols are unbound).  Set
 +;;   expected error.
 +
 +(defun tramp-test-all (&optional interactive)
 +  "Run all tests for \\[tramp]."
 +  (interactive "p")
 +  (funcall
 +   (if interactive 'ert-run-tests-interactively 'ert-run-tests-batch) "^tramp"))
 +
 +(provide 'tramp-tests)
 +;;; tramp-tests.el ends here