mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-17 10:06:13 +00:00
26bed8ba10
Run 'TZ=UTC0 admin/update-copyright $(git ls-files)'.
921 lines
34 KiB
EmacsLisp
921 lines
34 KiB
EmacsLisp
;;; shadowfile-tests.el --- Tests of shadowfile
|
|
|
|
;; Copyright (C) 2018-2019 Free Software Foundation, Inc.
|
|
|
|
;; Author: Michael Albinus <michael.albinus@gmx.de>
|
|
|
|
;; This program is free software: you can redistribute it and/or
|
|
;; modify it under the terms of the GNU General Public License as
|
|
;; published by the Free Software Foundation, either version 3 of the
|
|
;; License, or (at your option) any later version.
|
|
;;
|
|
;; This program is distributed in the hope that it will be useful, but
|
|
;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
;; General Public License for more details.
|
|
;;
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with this program. If not, see `https://www.gnu.org/licenses/'.
|
|
|
|
;;; Commentary:
|
|
|
|
;; 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 `shadowfile-test-all'.
|
|
|
|
;;; Code:
|
|
|
|
(require 'ert)
|
|
(require 'shadowfile)
|
|
(require 'tramp)
|
|
|
|
;; There is no default value on w32 systems, which could work out of the box.
|
|
(defconst shadow-test-remote-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)))
|
|
(add-to-list
|
|
'tramp-default-host-alist
|
|
`("\\`mock\\'" nil ,(system-name)))
|
|
;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in
|
|
;; batch mode only, therefore. It cannot be
|
|
;; `temporary-directory', because the tests with "~" would fail.
|
|
(unless (and (null noninteractive) (file-directory-p "~/"))
|
|
(setenv "HOME" invocation-directory))
|
|
(format "/mock::%s" temporary-file-directory)))
|
|
"Temporary directory for Tramp tests.")
|
|
|
|
(setq password-cache-expiry nil
|
|
tramp-verbose 0
|
|
tramp-message-show-message nil)
|
|
|
|
;; This should happen on hydra only.
|
|
(when (getenv "EMACS_HYDRA_CI")
|
|
(add-to-list 'tramp-remote-path 'tramp-own-remote-path))
|
|
|
|
(defconst shadow-test-info-file
|
|
(expand-file-name "shadows_test" temporary-file-directory)
|
|
"File to keep shadow information in during tests.")
|
|
|
|
(defconst shadow-test-todo-file
|
|
(expand-file-name "shadow_todo_test" temporary-file-directory)
|
|
"File to store the list of uncopied shadows in during tests.")
|
|
|
|
(ert-deftest shadow-test00-clusters ()
|
|
"Check cluster definitions.
|
|
Per definition, all files are identical on the different hosts of
|
|
a cluster (or site). This is not tested here; it must be
|
|
guaranteed by the originator of a cluster definition."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((text-quoting-style 'grave) ;; We inspect the *Messages* buffer!
|
|
(inhibit-message t)
|
|
(shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters
|
|
cluster primary regexp mocked-input)
|
|
(unwind-protect
|
|
;; We must mock `read-from-minibuffer' and `read-string', in
|
|
;; order to avoid interactive arguments.
|
|
(cl-letf* (((symbol-function 'read-from-minibuffer)
|
|
(lambda (&rest args) (pop mocked-input)))
|
|
((symbol-function 'read-string)
|
|
(lambda (&rest args) (pop mocked-input))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define a cluster.
|
|
(setq cluster "cluster"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary)
|
|
mocked-input `(,cluster ,primary ,regexp))
|
|
(call-interactively 'shadow-define-cluster)
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-name (shadow-get-cluster cluster)) cluster))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-primary (shadow-get-cluster cluster)) primary))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
|
|
(should-not (shadow-get-cluster "non-existent-cluster-name"))
|
|
|
|
;; Test `shadow-set-cluster' and `make-shadow-cluster'.
|
|
(shadow-set-cluster cluster primary regexp)
|
|
(should
|
|
(equal (shadow-get-cluster cluster)
|
|
(make-shadow-cluster
|
|
:name cluster :primary primary :regexp regexp)))
|
|
|
|
;; The primary must be either `shadow-system-name', or a remote file.
|
|
(setq ;; The second "cluster" is wrong.
|
|
mocked-input `(,cluster ,cluster ,primary ,regexp))
|
|
(with-current-buffer (messages-buffer)
|
|
(narrow-to-region (point-max) (point-max)))
|
|
(call-interactively 'shadow-define-cluster)
|
|
(should
|
|
(string-match
|
|
(regexp-quote "Not a valid primary!")
|
|
(with-current-buffer (messages-buffer) (buffer-string))))
|
|
;; The first cluster definition is still valid.
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-name (shadow-get-cluster cluster)) cluster))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-primary (shadow-get-cluster cluster)) primary))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
|
|
|
|
;; The regexp must match the primary name.
|
|
(setq ;; The second "cluster" is wrong.
|
|
mocked-input `(,cluster ,primary ,cluster ,regexp))
|
|
(with-current-buffer (messages-buffer)
|
|
(narrow-to-region (point-max) (point-max)))
|
|
(call-interactively 'shadow-define-cluster)
|
|
(should
|
|
(string-match
|
|
(regexp-quote "Regexp doesn't include the primary host!")
|
|
(with-current-buffer (messages-buffer) (buffer-string))))
|
|
;; The first cluster definition is still valid.
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-name (shadow-get-cluster cluster)) cluster))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-primary (shadow-get-cluster cluster)) primary))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
|
|
|
|
;; Redefine the cluster.
|
|
(setq primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary)
|
|
mocked-input `(,cluster ,primary ,regexp))
|
|
(call-interactively 'shadow-define-cluster)
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-name (shadow-get-cluster cluster)) cluster))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-primary (shadow-get-cluster cluster)) primary))
|
|
(should
|
|
(string-equal
|
|
(shadow-cluster-regexp (shadow-get-cluster cluster)) regexp))
|
|
|
|
;; Test `shadow-set-cluster' and `make-shadow-cluster'.
|
|
(shadow-set-cluster cluster primary regexp)
|
|
(should
|
|
(equal (shadow-get-cluster cluster)
|
|
(make-shadow-cluster
|
|
:name cluster :primary primary :regexp regexp))))
|
|
|
|
;; Cleanup.
|
|
(with-current-buffer (messages-buffer) (widen))
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test01-sites ()
|
|
"Check site definitions.
|
|
Per definition, all files are identical on the different hosts of
|
|
a cluster (or site). This is not tested here; it must be
|
|
guaranteed by the originator of a cluster definition."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters
|
|
cluster1 cluster2 primary1 primary2 regexp1 regexp2 mocked-input)
|
|
(unwind-protect
|
|
;; We must mock `read-from-minibuffer' and `read-string', in
|
|
;; order to avoid interactive arguments.
|
|
(cl-letf* (((symbol-function 'read-from-minibuffer)
|
|
(lambda (&rest args) (pop mocked-input)))
|
|
((symbol-function 'read-string)
|
|
(lambda (&rest args) (pop mocked-input))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define a cluster.
|
|
(setq cluster1 "cluster1"
|
|
primary1 shadow-system-name
|
|
regexp1 (shadow-regexp-superquote primary1))
|
|
(shadow-set-cluster cluster1 primary1 regexp1)
|
|
|
|
;; A site is either a cluster identification, or a primary host.
|
|
(should (string-equal cluster1 (shadow-site-name cluster1)))
|
|
(should (string-equal primary1 (shadow-name-site primary1)))
|
|
(should
|
|
(string-equal (format "/%s:" cluster1) (shadow-name-site cluster1)))
|
|
(should (string-equal (system-name) (shadow-site-name primary1)))
|
|
(should
|
|
(string-equal
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
(shadow-name-site
|
|
(file-remote-p shadow-test-remote-temporary-file-directory))))
|
|
(should
|
|
(string-equal
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
(shadow-site-name
|
|
(file-remote-p shadow-test-remote-temporary-file-directory))))
|
|
|
|
(should (equal (shadow-site-cluster cluster1)
|
|
(shadow-get-cluster cluster1)))
|
|
(should (equal (shadow-site-cluster (shadow-name-site cluster1))
|
|
(shadow-get-cluster cluster1)))
|
|
(should (equal (shadow-site-cluster primary1)
|
|
(shadow-get-cluster cluster1)))
|
|
(should (equal (shadow-site-cluster (shadow-site-name primary1))
|
|
(shadow-get-cluster cluster1)))
|
|
(should (string-equal (shadow-site-primary cluster1) primary1))
|
|
(should (string-equal (shadow-site-primary primary1) primary1))
|
|
|
|
;; `shadow-read-site' accepts "cluster", "/cluster:",
|
|
;; "system", "/system:". It shall reject bad site names.
|
|
(setq mocked-input
|
|
`(,cluster1 ,(shadow-name-site cluster1)
|
|
,primary1 ,(shadow-site-name primary1)
|
|
,shadow-system-name "" "bad" "/bad:"))
|
|
(should (string-equal (shadow-read-site) cluster1))
|
|
(should (string-equal (shadow-read-site) (shadow-name-site cluster1)))
|
|
(should (string-equal (shadow-read-site) primary1))
|
|
(should (string-equal (shadow-read-site) (shadow-site-name primary1)))
|
|
(should (string-equal (shadow-read-site) shadow-system-name))
|
|
(should-not (shadow-read-site)) ; ""
|
|
(should-not (shadow-read-site)) ; "bad"
|
|
(should-not (shadow-read-site)) ; "/bad:"
|
|
(should-error (shadow-read-site)) ; no input at all
|
|
|
|
;; Define a second cluster.
|
|
(setq cluster2 "cluster2"
|
|
primary2
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp2 (format "^\\(%s\\|%s\\)$" shadow-system-name primary2))
|
|
(shadow-set-cluster cluster2 primary2 regexp2)
|
|
|
|
;; `shadow-site-match' shall know all different kind of site names.
|
|
(should (shadow-site-match cluster1 cluster1))
|
|
(should (shadow-site-match primary1 primary1))
|
|
(should (shadow-site-match cluster1 primary1))
|
|
(should (shadow-site-match primary1 cluster1))
|
|
(should (shadow-site-match cluster2 cluster2))
|
|
(should (shadow-site-match primary2 primary2))
|
|
(should (shadow-site-match cluster2 primary2))
|
|
(should (shadow-site-match primary2 cluster2))
|
|
|
|
;; The regexp of `cluster2' matches the primary of
|
|
;; `cluster1'. Not vice versa.
|
|
(should (shadow-site-match cluster2 cluster1))
|
|
(should-not (shadow-site-match cluster1 cluster2))
|
|
|
|
;; If we use the primaries of a cluster, it doesn't match.
|
|
(should-not
|
|
(shadow-site-match (shadow-site-primary cluster2) cluster1))
|
|
(should-not
|
|
(shadow-site-match (shadow-site-primary cluster1) cluster2)))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test02-files ()
|
|
"Check file manipulation functions."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters
|
|
cluster primary regexp file hup)
|
|
(unwind-protect
|
|
(progn
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define a cluster.
|
|
(setq cluster "cluster"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary)
|
|
file (make-temp-name
|
|
(expand-file-name
|
|
"shadowfile-tests" temporary-file-directory)))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
;; The constant structure to compare with.
|
|
(setq hup (make-tramp-file-name :host (system-name) :localname file))
|
|
|
|
;; The structure a local file is transformed in.
|
|
(should (equal (shadow-parse-name file) hup))
|
|
(should (equal (shadow-parse-name (concat "/" cluster ":" file)) hup))
|
|
(should (equal (shadow-parse-name (concat primary file)) hup))
|
|
|
|
;; A local file name is kept.
|
|
(should
|
|
(string-equal (shadow-local-file file) file))
|
|
;; A file on this cluster is also local.
|
|
(should
|
|
(string-equal
|
|
(shadow-local-file (concat "/" cluster ":" file)) file))
|
|
;; A file on the primary host is also local.
|
|
(should
|
|
(string-equal (shadow-local-file (concat primary file)) file))
|
|
|
|
;; Redefine the cluster.
|
|
(setq primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
;; The structure of the local file is still the same.
|
|
(should (equal (shadow-parse-name file) hup))
|
|
;; The cluster name must be used.
|
|
(setf (tramp-file-name-host hup) cluster)
|
|
(should (equal (shadow-parse-name (concat "/" cluster ":" file)) hup))
|
|
;; The structure of a remote file is different.
|
|
(should
|
|
(equal (shadow-parse-name (concat primary file))
|
|
(tramp-dissect-file-name (concat primary file))))
|
|
|
|
;; A local file is still local.
|
|
(should (shadow-local-file file))
|
|
;; A file on this cluster is not local.
|
|
(should-not (shadow-local-file (concat "/" cluster ":" file)))
|
|
;; A file on the primary host is not local.
|
|
(should-not (shadow-local-file (concat primary file)))
|
|
;; There's no error on wrong FILE.
|
|
(should-not (shadow-local-file nil)))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test03-expand-cluster-in-file-name ()
|
|
"Check canonical file name of a cluster or site."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters
|
|
cluster primary regexp file1 file2)
|
|
(unwind-protect
|
|
(progn
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define a cluster.
|
|
(setq cluster "cluster"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
(setq file1
|
|
(make-temp-name
|
|
(expand-file-name "shadowfile-tests" temporary-file-directory))
|
|
file2
|
|
(make-temp-name
|
|
(expand-file-name
|
|
"shadowfile-tests"
|
|
shadow-test-remote-temporary-file-directory)))
|
|
|
|
;; A local file name is kept.
|
|
(should
|
|
(string-equal (shadow-expand-cluster-in-file-name file1) file1))
|
|
;; A remote file is kept.
|
|
(should
|
|
(string-equal (shadow-expand-cluster-in-file-name file2) file2))
|
|
;; A cluster name is expanded to the primary name.
|
|
(should
|
|
(string-equal
|
|
(shadow-expand-cluster-in-file-name (format "/%s:%s" cluster file1))
|
|
(shadow-expand-cluster-in-file-name (concat primary file1))))
|
|
;; A primary name is expanded if it is a local file name.
|
|
(should
|
|
(string-equal
|
|
(shadow-expand-cluster-in-file-name (concat primary file1)) file1))
|
|
|
|
;; Redefine the cluster.
|
|
(setq primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
;; A cluster name is expanded to the primary name.
|
|
(should
|
|
(string-equal
|
|
(shadow-expand-cluster-in-file-name (format "/%s:%s" cluster file1))
|
|
(shadow-expand-cluster-in-file-name (concat primary file1))))
|
|
;; A primary name is not expanded if it isn't is a local file name.
|
|
(should
|
|
(string-equal
|
|
(shadow-expand-cluster-in-file-name (concat primary file1))
|
|
(concat primary file1))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test04-contract-file-name ()
|
|
"Check canonical file name of a cluster or site."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters
|
|
cluster primary regexp file)
|
|
(unwind-protect
|
|
(progn
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define a cluster.
|
|
(setq cluster "cluster"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary)
|
|
file (make-temp-name
|
|
(expand-file-name
|
|
"shadowfile-tests" temporary-file-directory)))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
;; The cluster name is prepended for local files.
|
|
(should
|
|
(string-equal
|
|
(shadow-contract-file-name file) (concat "/cluster:" file)))
|
|
;; A cluster file name is preserved.
|
|
(should
|
|
(string-equal
|
|
(shadow-contract-file-name (concat "/cluster:" file))
|
|
(concat "/cluster:" file)))
|
|
;; `shadow-system-name' is mapped to the cluster.
|
|
(should
|
|
(string-equal
|
|
(shadow-contract-file-name (concat shadow-system-name file))
|
|
(concat "/cluster:" file)))
|
|
|
|
;; Redefine the cluster.
|
|
(setq primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
;; A remote file name is mapped to the cluster.
|
|
(should
|
|
(string-equal
|
|
(shadow-contract-file-name
|
|
(concat
|
|
(file-remote-p shadow-test-remote-temporary-file-directory) file))
|
|
(concat "/cluster:" file))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test05-file-match ()
|
|
"Check `shadow-same-site' and `shadow-file-match'."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters
|
|
cluster primary regexp file)
|
|
(unwind-protect
|
|
(progn
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define a cluster.
|
|
(setq cluster "cluster"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary)
|
|
file (make-temp-name
|
|
(expand-file-name
|
|
"shadowfile-tests" temporary-file-directory)))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
(should (shadow-same-site (shadow-parse-name "/cluster:") file))
|
|
(should
|
|
(shadow-same-site (shadow-parse-name shadow-system-name) file))
|
|
(should (shadow-same-site (shadow-parse-name file) file))
|
|
|
|
(should
|
|
(shadow-file-match
|
|
(shadow-parse-name (concat "/cluster:" file)) file))
|
|
(should
|
|
(shadow-file-match
|
|
(shadow-parse-name (concat shadow-system-name file)) file))
|
|
(should (shadow-file-match (shadow-parse-name file) file))
|
|
|
|
;; Redefine the cluster.
|
|
(setq primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster primary regexp)
|
|
|
|
(should
|
|
(shadow-file-match
|
|
(shadow-parse-name
|
|
(concat
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
file))
|
|
file)))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test06-literal-groups ()
|
|
"Check literal group definitions."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters shadow-literal-groups
|
|
cluster1 cluster2 primary regexp file1 file2 mocked-input)
|
|
(unwind-protect
|
|
;; We must mock `read-from-minibuffer' and `read-string', in
|
|
;; order to avoid interactive arguments.
|
|
(cl-letf* (((symbol-function 'read-from-minibuffer)
|
|
(lambda (&rest args) (pop mocked-input)))
|
|
((symbol-function 'read-string)
|
|
(lambda (&rest args) (pop mocked-input))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define clusters.
|
|
(setq cluster1 "cluster1"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster1 primary regexp)
|
|
|
|
(setq cluster2 "cluster2"
|
|
primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary))
|
|
(shadow-set-cluster cluster2 primary regexp)
|
|
|
|
;; Define a literal group.
|
|
(setq file1
|
|
(make-temp-name
|
|
(expand-file-name "shadowfile-tests" temporary-file-directory))
|
|
file2
|
|
(make-temp-name
|
|
(expand-file-name
|
|
"shadowfile-tests"
|
|
shadow-test-remote-temporary-file-directory))
|
|
mocked-input `(,cluster1 ,file1 ,cluster2 ,file2 ,(kbd "RET")))
|
|
(with-temp-buffer
|
|
(set-visited-file-name file1)
|
|
(call-interactively 'shadow-define-literal-group))
|
|
|
|
;; `shadow-literal-groups' is a list of lists.
|
|
(should (consp shadow-literal-groups))
|
|
(should (consp (car shadow-literal-groups)))
|
|
(should-not (cdr shadow-literal-groups))
|
|
|
|
(should (member (format "/%s:%s" cluster1 (file-local-name file1))
|
|
(car shadow-literal-groups)))
|
|
(should (member (format "/%s:%s" cluster2 (file-local-name file2))
|
|
(car shadow-literal-groups))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test07-regexp-groups ()
|
|
"Check regexp group definitions."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
shadow-clusters shadow-regexp-groups
|
|
cluster1 cluster2 primary regexp file mocked-input)
|
|
(unwind-protect
|
|
;; We must mock `read-from-minibuffer' and `read-string', in
|
|
;; order to avoid interactive arguments.
|
|
(cl-letf* (((symbol-function 'read-from-minibuffer)
|
|
(lambda (&rest args) (pop mocked-input)))
|
|
((symbol-function 'read-string)
|
|
(lambda (&rest args) (pop mocked-input))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define clusters.
|
|
(setq cluster1 "cluster1"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster1 primary regexp)
|
|
|
|
(setq cluster2 "cluster2"
|
|
primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary))
|
|
(shadow-set-cluster cluster2 primary regexp)
|
|
|
|
;; Define a regexp group.
|
|
(setq file
|
|
(make-temp-name
|
|
(expand-file-name "shadowfile-tests" temporary-file-directory))
|
|
mocked-input `(,(shadow-regexp-superquote file)
|
|
,cluster1 ,cluster2 ,(kbd "RET")))
|
|
(with-temp-buffer
|
|
(set-visited-file-name nil)
|
|
(call-interactively 'shadow-define-regexp-group))
|
|
|
|
;; `shadow-regexp-groups' is a list of lists.
|
|
(should (consp shadow-regexp-groups))
|
|
(should (consp (car shadow-regexp-groups)))
|
|
(should-not (cdr shadow-regexp-groups))
|
|
|
|
(should
|
|
(member
|
|
(concat
|
|
(shadow-site-primary cluster1) (shadow-regexp-superquote file))
|
|
(car shadow-regexp-groups)))
|
|
(should
|
|
(member
|
|
(concat
|
|
(shadow-site-primary cluster2) (shadow-regexp-superquote file))
|
|
(car shadow-regexp-groups))))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file)))))
|
|
|
|
(ert-deftest shadow-test08-shadow-todo ()
|
|
"Check that needed shadows are added to todo."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
(skip-unless (file-writable-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((backup-inhibited t)
|
|
(shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
(shadow-inhibit-message t)
|
|
shadow-clusters shadow-literal-groups shadow-regexp-groups
|
|
shadow-files-to-copy
|
|
cluster1 cluster2 primary regexp file)
|
|
(unwind-protect
|
|
(progn
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
|
|
;; Define clusters.
|
|
(setq cluster1 "cluster1"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster1 primary regexp)
|
|
|
|
(setq cluster2 "cluster2"
|
|
primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster2 primary regexp)
|
|
|
|
;; Define a literal group.
|
|
(setq file
|
|
(make-temp-name
|
|
(expand-file-name "shadowfile-tests" temporary-file-directory))
|
|
shadow-literal-groups
|
|
`((,(concat "/cluster1:" file) ,(concat "/cluster2:" file))))
|
|
|
|
;; Save file from "cluster1" definition.
|
|
(with-temp-buffer
|
|
(set-visited-file-name file)
|
|
(insert "foo")
|
|
(save-buffer))
|
|
(should
|
|
(member
|
|
(cons file (shadow-contract-file-name (concat "/cluster2:" file)))
|
|
shadow-files-to-copy))
|
|
|
|
;; Save file from "cluster2" definition.
|
|
(with-temp-buffer
|
|
(set-visited-file-name (concat (shadow-site-primary cluster2) file))
|
|
(insert "foo")
|
|
(save-buffer))
|
|
(should
|
|
(member
|
|
(cons
|
|
(concat (shadow-site-primary cluster2) file)
|
|
(shadow-contract-file-name (concat "/cluster1:" file)))
|
|
shadow-files-to-copy))
|
|
|
|
;; Define a regexp group.
|
|
(setq shadow-files-to-copy nil
|
|
shadow-regexp-groups
|
|
`((,(concat (shadow-site-primary cluster1)
|
|
(shadow-regexp-superquote file))
|
|
,(concat (shadow-site-primary cluster2)
|
|
(shadow-regexp-superquote file)))))
|
|
|
|
;; Save file from "cluster1" definition.
|
|
(with-temp-buffer
|
|
(set-visited-file-name file)
|
|
(insert "foo")
|
|
(save-buffer))
|
|
(should
|
|
(member
|
|
(cons file (shadow-contract-file-name (concat "/cluster2:" file)))
|
|
shadow-files-to-copy))
|
|
|
|
;; Save file from "cluster2" definition.
|
|
(with-temp-buffer
|
|
(set-visited-file-name (concat (shadow-site-primary cluster2) file))
|
|
(insert "foo")
|
|
(save-buffer))
|
|
(should
|
|
(member
|
|
(cons
|
|
(concat (shadow-site-primary cluster2) file)
|
|
(shadow-contract-file-name (concat "/cluster1:" file)))
|
|
shadow-files-to-copy)))
|
|
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
(ignore-errors
|
|
(when (file-exists-p file)
|
|
(delete-file file)))
|
|
(ignore-errors
|
|
(when (file-exists-p (concat (shadow-site-primary cluster2) file))
|
|
(delete-file (concat (shadow-site-primary cluster2) file)))))))
|
|
|
|
(ert-deftest shadow-test09-shadow-copy-files ()
|
|
"Check that needed shadow files are copied."
|
|
(skip-unless (not (memq system-type '(windows-nt ms-dos))))
|
|
(skip-unless (file-remote-p shadow-test-remote-temporary-file-directory))
|
|
(skip-unless (file-writable-p shadow-test-remote-temporary-file-directory))
|
|
|
|
(let ((backup-inhibited t)
|
|
(shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file)
|
|
(shadow-inhibit-message t)
|
|
(shadow-noquery t)
|
|
shadow-clusters shadow-files-to-copy
|
|
cluster1 cluster2 primary regexp file mocked-input)
|
|
(unwind-protect
|
|
(progn
|
|
;; Cleanup.
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
(when (buffer-live-p shadow-todo-buffer)
|
|
(with-current-buffer shadow-todo-buffer (erase-buffer)))
|
|
|
|
;; Define clusters.
|
|
(setq cluster1 "cluster1"
|
|
primary shadow-system-name
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster1 primary regexp)
|
|
|
|
(setq cluster2 "cluster2"
|
|
primary
|
|
(file-remote-p shadow-test-remote-temporary-file-directory)
|
|
regexp (shadow-regexp-superquote primary))
|
|
(shadow-set-cluster cluster2 primary regexp)
|
|
|
|
;; Define files to copy.
|
|
(setq file
|
|
(make-temp-name
|
|
(expand-file-name "shadowfile-tests" temporary-file-directory))
|
|
shadow-literal-groups
|
|
`((,(concat "/cluster1:" file) ,(concat "/cluster2:" file)))
|
|
shadow-regexp-groups
|
|
`((,(concat (shadow-site-primary cluster1)
|
|
(shadow-regexp-superquote file))
|
|
,(concat (shadow-site-primary cluster2)
|
|
(shadow-regexp-superquote file))))
|
|
mocked-input `(,(concat (shadow-site-primary cluster2) file)
|
|
,file))
|
|
|
|
;; Save files.
|
|
(with-temp-buffer
|
|
(set-visited-file-name file)
|
|
(insert "foo")
|
|
(save-buffer))
|
|
(with-temp-buffer
|
|
(set-visited-file-name (concat (shadow-site-primary cluster2) file))
|
|
(insert "foo")
|
|
(save-buffer))
|
|
|
|
;; We must mock `write-region', in order to check proper
|
|
;; action.
|
|
(add-function
|
|
:before (symbol-function 'write-region)
|
|
(lambda (&rest args)
|
|
(when (and (buffer-file-name) mocked-input)
|
|
(should (equal (buffer-file-name) (pop mocked-input)))))
|
|
'((name . "write-region-mock")))
|
|
|
|
;; Copy the files.
|
|
(shadow-copy-files 'noquery)
|
|
(should-not shadow-files-to-copy)
|
|
(with-current-buffer shadow-todo-buffer
|
|
(goto-char (point-min))
|
|
(should
|
|
(looking-at (regexp-quote "(setq shadow-files-to-copy nil)")))))
|
|
|
|
;; Cleanup.
|
|
(remove-function (symbol-function 'write-region) "write-region-mock")
|
|
(when (file-exists-p shadow-info-file)
|
|
(delete-file shadow-info-file))
|
|
(when (file-exists-p shadow-todo-file)
|
|
(delete-file shadow-todo-file))
|
|
(ignore-errors
|
|
(when (file-exists-p file)
|
|
(delete-file file)))
|
|
(ignore-errors
|
|
(when (file-exists-p (concat (shadow-site-primary cluster2) file))
|
|
(delete-file (concat (shadow-site-primary cluster2) file)))))))
|
|
|
|
(defun shadowfile-test-all (&optional interactive)
|
|
"Run all tests for \\[shadowfile]."
|
|
(interactive "p")
|
|
(if interactive
|
|
(ert-run-tests-interactively "^shadowfile-")
|
|
(ert-run-tests-batch "^shadowfile-")))
|
|
|
|
(let ((shadow-info-file shadow-test-info-file)
|
|
(shadow-todo-file shadow-test-todo-file))
|
|
(shadow-initialize))
|
|
|
|
(provide 'shadowfile-tests)
|
|
;;; shadowfile-tests.el ends here
|