blob: b9e826411cf10c070bb8f423cdc66462e9d5ebbb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
;;; test-duet-classify-path.el --- Tests for duet--classify-path -*- lexical-binding: t; -*-
;; Copyright (C) 2026 Craig Jennings
;; Author: Craig Jennings <c@cjennings.net>
;; 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:
;; Normal/Boundary/Error coverage for `duet--classify-path', the pure path
;; classifier that turns a path string into a `:locality'/`:method'/`:user'/
;; `:host'/`:port'/`:localname'/`:hop' plist. TRAMP owns the dissection; these
;; tests verify the locality decision, the extracted fields, and graceful
;; handling of paths TRAMP does not recognize as remote.
;;; Code:
(require 'test-bootstrap (expand-file-name "test-bootstrap.el"))
;;; Normal cases
(ert-deftest test-duet-classify-path-local-absolute ()
"An absolute local path classifies as local with no remote fields."
(let ((p (duet--classify-path "/home/cjennings/file")))
(should (eq 'local (plist-get p :locality)))
(should (null (plist-get p :method)))
(should (null (plist-get p :user)))
(should (null (plist-get p :host)))
(should (null (plist-get p :port)))
(should (null (plist-get p :hop)))
(should (equal "/home/cjennings/file" (plist-get p :localname)))))
(ert-deftest test-duet-classify-path-ssh-host-only ()
"A remote ssh path with no user fills method/host/localname, user nil."
(let ((p (duet--classify-path "/ssh:host:/path")))
(should (eq 'remote (plist-get p :locality)))
(should (equal "ssh" (plist-get p :method)))
(should (null (plist-get p :user)))
(should (equal "host" (plist-get p :host)))
(should (null (plist-get p :port)))
(should (equal "/path" (plist-get p :localname)))))
(ert-deftest test-duet-classify-path-ssh-user-host ()
"A user@host ssh path extracts the user."
(let ((p (duet--classify-path "/ssh:user@host:/path")))
(should (eq 'remote (plist-get p :locality)))
(should (equal "user" (plist-get p :user)))
(should (equal "host" (plist-get p :host)))
(should (equal "/path" (plist-get p :localname)))))
;;; Boundary cases
(ert-deftest test-duet-classify-path-tilde-expands ()
"A leading ~ in a local path expands to the home directory."
(let ((p (duet--classify-path "~/media")))
(should (eq 'local (plist-get p :locality)))
(should (equal (expand-file-name "~/media") (plist-get p :localname)))))
(ert-deftest test-duet-classify-path-host-with-port ()
"A host#port path splits the port out into the :port field."
(let ((p (duet--classify-path "/ssh:user@host#2222:/path")))
(should (eq 'remote (plist-get p :locality)))
(should (equal "host" (plist-get p :host)))
(should (equal "2222" (plist-get p :port)))
(should (equal "/path" (plist-get p :localname)))))
(ert-deftest test-duet-classify-path-sshx-and-scp-methods ()
"Methods other than ssh are preserved verbatim."
(should (equal "sshx" (plist-get (duet--classify-path "/sshx:u@h:/p") :method)))
(should (equal "scp" (plist-get (duet--classify-path "/scp:u@h:/p") :method))))
(ert-deftest test-duet-classify-path-multi-hop ()
"A multi-hop path reports the final host and preserves the leading hops."
(let ((p (duet--classify-path "/ssh:host1|ssh:host2:/path")))
(should (eq 'remote (plist-get p :locality)))
(should (equal "host2" (plist-get p :host)))
(should (equal "/path" (plist-get p :localname)))
(should (stringp (plist-get p :hop)))
(should (string-match-p "host1" (plist-get p :hop)))))
;;; Error / edge cases
(ert-deftest test-duet-classify-path-malformed-is-local-not-error ()
"A TRAMP-looking string TRAMP does not accept as remote is treated as local.
Validation of raw TRAMP entry belongs to the connection reader, not the
classifier; classification stays total and never throws."
(dolist (bad '("/ssh:" "/ssh:host"))
(let ((p (duet--classify-path bad)))
(should (eq 'local (plist-get p :locality)))
(should (null (plist-get p :method))))))
(provide 'test-duet-classify-path)
;;; test-duet-classify-path.el ends here
|