aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDamien Cassou2019-05-14 05:50:59 +0200
committerDamien Cassou2019-06-24 09:15:41 +0200
commit7022e3fde6bc577cc281bd8770fe5a41f7492b4f (patch)
tree7c423e6931eb57a3a5d0bf7ec7c3153cbfbbf0a3 /test
parent736f78bb1af0593d9b02f0a45a64b1422a6fcc12 (diff)
downloademacs-7022e3fde6bc577cc281bd8770fe5a41f7492b4f.tar.gz
emacs-7022e3fde6bc577cc281bd8770fe5a41f7492b4f.zip
Refactoring of auth-source-pass
* lisp/auth-source-pass.el (auth-source-pass--find-match): Refactor by moving some code to auth-source-pass--disambiguate. (auth-source-pass--disambiguate) (auth-source-pass--entries-matching-suffix): New function. (auth-source-pass--find-match-unambiguous) (auth-source-pass--select-from-entries) (auth-source-pass--entry-reducer): Refactor to simplify and improve logging. (auth-source-pass--matching-entries) (auth-source-pass--accumulate-matches): Remove. * test/lisp/auth-source-pass-tests.el: Complete rewrite to facilitate maintenance. (auth-source-pass--have-message-containing): Remove. (auth-source-pass--have-message-matching) (auth-source-pass--explain--have-message-matching) (auth-source-pass--explain-match-entry-p) (auth-source-pass--includes-sorted-entries) (auth-source-pass--explain-includes-sorted-entries) (auth-source-pass--explain-match-any-entry-p) (auth-source-pass--matching-entries) (auth-source-pass-match-entry-p) (auth-source-pass-match-any-entry-p): New function.
Diffstat (limited to 'test')
-rw-r--r--test/lisp/auth-source-pass-tests.el482
1 files changed, 304 insertions, 178 deletions
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index 2c28f799453..6f0d308cebf 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -52,11 +52,21 @@
52(defvar auth-source-pass--debug-log nil 52(defvar auth-source-pass--debug-log nil
53 "Contains a list of all messages passed to `auth-source-do-debug`.") 53 "Contains a list of all messages passed to `auth-source-do-debug`.")
54 54
55(defun auth-source-pass--should-have-message-containing (regexp) 55(defun auth-source-pass--have-message-matching (regexp)
56 "Assert that at least one `auth-source-do-debug` matched REGEXP." 56 "Return non-nil iff at least one `auth-source-do-debug` match REGEXP."
57 (should (seq-find (lambda (message) 57 (seq-find (lambda (message)
58 (string-match regexp message)) 58 (string-match regexp message))
59 auth-source-pass--debug-log))) 59 auth-source-pass--debug-log))
60
61(defun auth-source-pass--explain--have-message-matching (regexp)
62 "Explainer function for `auth-source-pass--have-message-matching'.
63REGEXP is the same as in `auth-source-pass--have-message-matching'."
64 `(regexp
65 ,regexp
66 messages
67 ,(mapconcat #'identity auth-source-pass--debug-log "\n- ")))
68
69(put #'auth-source-pass--have-message-matching 'ert-explainer #'auth-source-pass--explain--have-message-matching)
60 70
61(defun auth-source-pass--debug (&rest msg) 71(defun auth-source-pass--debug (&rest msg)
62 "Format MSG and add that to `auth-source-pass--debug-log`. 72 "Format MSG and add that to `auth-source-pass--debug-log`.
@@ -78,6 +88,82 @@ This function is intended to be set to `auth-source-debug`."
78 (auth-source-pass--parse-log nil)) 88 (auth-source-pass--parse-log nil))
79 ,@body))) 89 ,@body)))
80 90
91(defun auth-source-pass--explain-match-entry-p (entry hostname &optional user port)
92 "Explainer function for `auth-source-pass-match-entry-p'.
93
94ENTRY, HOSTNAME, USER and PORT are the same as in `auth-source-pass-match-entry-p'."
95 `(entry
96 ,entry
97 store
98 ,(auth-source-pass-entries)
99 matching-entries
100 ,(auth-source-pass--matching-entries hostname user port)))
101
102(put 'auth-source-pass-match-entry-p 'ert-explainer #'auth-source-pass--explain-match-entry-p)
103
104(defun auth-source-pass--includes-sorted-entries (entries hostname &optional user port)
105 "Return non-nil iff ENTRIES matching the parameters are found in store.
106ENTRIES should be sorted from most specific to least specific.
107
108HOSTNAME, USER and PORT are passed unchanged to
109`auth-source-pass--matching-entries'."
110 (if (seq-empty-p entries)
111 t
112 (and
113 (auth-source-pass-match-entry-p (car entries) hostname user port)
114 (auth-source-pass--includes-sorted-entries (cdr entries) hostname user port))))
115
116(defun auth-source-pass--explain-includes-sorted-entries (entries hostname &optional user port)
117 "Explainer function for `auth-source-pass--includes-sorted-entries'.
118
119ENTRIES, HOSTNAME, USER and PORT are the same as in `auth-source-pass--includes-sorted-entries'."
120 `(store
121 ,(auth-source-pass-entries)
122 matching-entries
123 ,(auth-source-pass--matching-entries hostname user port)
124 entries
125 ,entries))
126
127(put 'auth-source-pass--includes-sorted-entries 'ert-explainer #'auth-source-pass--explain-includes-sorted-entries)
128
129(defun auth-source-pass--explain-match-any-entry-p (hostname &optional user port)
130 "Explainer function for `auth-source-pass-match-any-entry-p'.
131
132HOSTNAME, USER and PORT are the same as in `auth-source-pass-match-any-entry-p'."
133 `(store
134 ,(auth-source-pass-entries)
135 matching-entries
136 ,(auth-source-pass--matching-entries hostname user port)))
137
138(put 'auth-source-pass-match-any-entry-p 'ert-explainer #'auth-source-pass--explain-match-any-entry-p)
139
140(defun auth-source-pass--matching-entries (hostname &optional user port)
141 "Return password-store entries matching HOSTNAME, USER, PORT.
142
143The result is a list of lists of password-store entries. Each
144sublist contains the password-store entries whose names match a
145suffix in `auth-source-pass--generate-entry-suffixes'. The
146result is ordered the same way as the suffixes."
147 (let ((entries (auth-source-pass-entries)))
148 (mapcar (lambda (suffix) (auth-source-pass--entries-matching-suffix suffix entries))
149 (auth-source-pass--generate-entry-suffixes hostname user port))))
150
151(defun auth-source-pass-match-entry-p (entry hostname &optional user port)
152 "Return non-nil iff an ENTRY matching the parameters is found in store.
153
154HOSTNAME, USER and PORT are passed unchanged to
155`auth-source-pass--matching-entries'."
156 (cl-find-if
157 (lambda (entries) (cl-find entry entries :test #'string=))
158 (auth-source-pass--matching-entries hostname user port)))
159
160(defun auth-source-pass-match-any-entry-p (hostname &optional user port)
161 "Return non-nil iff there is at least one entry matching the parameters.
162
163HOSTNAME, USER and PORT are passed unchanged to
164`auth-source-pass--matching-entries'."
165 (cl-find-if #'identity (auth-source-pass--matching-entries hostname user port)))
166
81(ert-deftest auth-source-pass-any-host () 167(ert-deftest auth-source-pass-any-host ()
82 (auth-source-pass--with-store '(("foo" ("port" . "foo-port") ("host" . "foo-user")) 168 (auth-source-pass--with-store '(("foo" ("port" . "foo-port") ("host" . "foo-user"))
83 ("bar")) 169 ("bar"))
@@ -93,6 +179,101 @@ This function is intended to be set to `auth-source-debug`."
93 ("bar")) 179 ("bar"))
94 (should-not (auth-source-pass-search :host "baz")))) 180 (should-not (auth-source-pass-search :host "baz"))))
95 181
182(ert-deftest auth-source-pass--disambiguate-extract-host-from-hostname ()
183 ;; no user or port
184 (should (equal (cl-first (auth-source-pass--disambiguate "foo")) "foo"))
185 ;; only user
186 (should (equal (cl-first (auth-source-pass--disambiguate "user@foo")) "foo"))
187 ;; only port
188 (should (equal (cl-first (auth-source-pass--disambiguate "https://foo")) "foo"))
189 (should (equal (cl-first (auth-source-pass--disambiguate "foo:80")) "foo"))
190 ;; both user and port
191 (should (equal (cl-first (auth-source-pass--disambiguate "https://user@foo")) "foo"))
192 (should (equal (cl-first (auth-source-pass--disambiguate "user@foo:80")) "foo"))
193 ;; all of the above with a trailing path
194 (should (equal (cl-first (auth-source-pass--disambiguate "foo/path")) "foo"))
195 (should (equal (cl-first (auth-source-pass--disambiguate "user@foo/path")) "foo"))
196 (should (equal (cl-first (auth-source-pass--disambiguate "https://foo/path")) "foo"))
197 (should (equal (cl-first (auth-source-pass--disambiguate "foo:80/path")) "foo"))
198 (should (equal (cl-first (auth-source-pass--disambiguate "https://user@foo/path")) "foo"))
199 (should (equal (cl-first (auth-source-pass--disambiguate "user@foo:80/path")) "foo")))
200
201(ert-deftest auth-source-pass--disambiguate-extract-user-from-hostname ()
202 ;; no user or port
203 (should (equal (cl-second (auth-source-pass--disambiguate "foo")) nil))
204 ;; only user
205 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo")) "user"))
206 ;; only port
207 (should (equal (cl-second (auth-source-pass--disambiguate "https://foo")) nil))
208 (should (equal (cl-second (auth-source-pass--disambiguate "foo:80")) nil))
209 ;; both user and port
210 (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo")) "user"))
211 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80")) "user"))
212 ;; all of the above with a trailing path
213 (should (equal (cl-second (auth-source-pass--disambiguate "foo/path")) nil))
214 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo/path")) "user"))
215 (should (equal (cl-second (auth-source-pass--disambiguate "https://foo/path")) nil))
216 (should (equal (cl-second (auth-source-pass--disambiguate "foo:80/path")) nil))
217 (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo/path")) "user"))
218 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80/path")) "user")))
219
220(ert-deftest auth-source-pass--disambiguate-prefer-user-parameter ()
221 ;; no user or port
222 (should (equal (cl-second (auth-source-pass--disambiguate "foo" "user2")) "user2"))
223 ;; only user
224 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo" "user2")) "user2"))
225 ;; only port
226 (should (equal (cl-second (auth-source-pass--disambiguate "https://foo" "user2")) "user2"))
227 (should (equal (cl-second (auth-source-pass--disambiguate "foo:80" "user2")) "user2"))
228 ;; both user and port
229 (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo" "user2")) "user2"))
230 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80" "user2")) "user2"))
231 ;; all of the above with a trailing path
232 (should (equal (cl-second (auth-source-pass--disambiguate "foo/path" "user2")) "user2"))
233 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo/path" "user2")) "user2"))
234 (should (equal (cl-second (auth-source-pass--disambiguate "https://foo/path" "user2")) "user2"))
235 (should (equal (cl-second (auth-source-pass--disambiguate "foo:80/path" "user2")) "user2"))
236 (should (equal (cl-second (auth-source-pass--disambiguate "https://user@foo/path" "user2")) "user2"))
237 (should (equal (cl-second (auth-source-pass--disambiguate "user@foo:80/path" "user2")) "user2")))
238
239(ert-deftest auth-source-pass--disambiguate-extract-port-from-hostname ()
240 ;; no user or port
241 (should (equal (cl-third (auth-source-pass--disambiguate "foo")) "443"))
242 ;; only user
243 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo")) "443"))
244 ;; only port
245 (should (equal (cl-third (auth-source-pass--disambiguate "https://foo")) "443"))
246 (should (equal (cl-third (auth-source-pass--disambiguate "foo:80")) "80"))
247 ;; both user and port
248 (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo")) "443"))
249 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80")) "80"))
250 ;; all of the above with a trailing path
251 (should (equal (cl-third (auth-source-pass--disambiguate "foo/path")) "443"))
252 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo/path")) "443"))
253 (should (equal (cl-third (auth-source-pass--disambiguate "https://foo/path")) "443"))
254 (should (equal (cl-third (auth-source-pass--disambiguate "foo:80/path")) "80"))
255 (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo/path")) "443"))
256 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80/path")) "80")))
257
258(ert-deftest auth-source-pass--disambiguate-prefer-port-parameter ()
259 ;; no user or port
260 (should (equal (cl-third (auth-source-pass--disambiguate "foo" "user2" "8080")) "8080"))
261 ;; only user
262 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo" "user2" "8080")) "8080"))
263 ;; only port
264 (should (equal (cl-third (auth-source-pass--disambiguate "https://foo" "user2" "8080")) "8080"))
265 (should (equal (cl-third (auth-source-pass--disambiguate "foo:80" "user2" "8080")) "8080"))
266 ;; both user and port
267 (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo" "user2" "8080")) "8080"))
268 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80" "user2" "8080")) "8080"))
269 ;; all of the above with a trailing path
270 (should (equal (cl-third (auth-source-pass--disambiguate "foo/path" "user2" "8080")) "8080"))
271 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo/path" "user2" "8080")) "8080"))
272 (should (equal (cl-third (auth-source-pass--disambiguate "https://foo/path" "user2" "8080")) "8080"))
273 (should (equal (cl-third (auth-source-pass--disambiguate "foo:80/path" "user2" "8080")) "8080"))
274 (should (equal (cl-third (auth-source-pass--disambiguate "https://user@foo/path" "user2" "8080")) "8080"))
275 (should (equal (cl-third (auth-source-pass--disambiguate "user@foo:80/path" "user2" "8080")) "8080")))
276
96(ert-deftest auth-source-pass-find-match-minimal-parsing () 277(ert-deftest auth-source-pass-find-match-minimal-parsing ()
97 (let ((store-contents 278 (let ((store-contents
98 '(("baz" ("secret" . "baz password")) 279 '(("baz" ("secret" . "baz password"))
@@ -121,156 +302,110 @@ This function is intended to be set to `auth-source-debug`."
121 (should (equal auth-source-pass--parse-log '("bar.baz")))) 302 (should (equal auth-source-pass--parse-log '("bar.baz"))))
122 (auth-source-pass--with-store store-contents 303 (auth-source-pass--with-store store-contents
123 (auth-source-pass--find-match "baz" nil nil) 304 (auth-source-pass--find-match "baz" nil nil)
124 (should (equal auth-source-pass--parse-log '("baz")))))) 305 (should (equal auth-source-pass--parse-log '("baz"))))
125 306 (auth-source-pass--with-store
126(ert-deftest auth-source-pass-find-match-matching-at-entry-name () 307 '(("dir1/bar.com" ("key" . "val"))
127 (auth-source-pass--with-store 308 ("dir2/bar.com" ("key" . "val"))
128 '(("foo" ("secret" . "foo password"))) 309 ("dir3/bar.com" ("key" . "val")))
129 (let ((result (auth-source-pass--find-match "foo" nil nil))) 310 (auth-source-pass--find-match "bar.com" nil nil)
130 (should (equal (auth-source-pass--get-attr "secret" result) 311 (should (= (length auth-source-pass--parse-log) 1)))))
131 "foo password"))))) 312
132 313(ert-deftest auth-source-pass--find-match-return-parsed-data ()
133(ert-deftest auth-source-pass-find-match-matching-at-entry-name-part () 314 (auth-source-pass--with-store '(("bar.com" ("key" . "val")))
134 (auth-source-pass--with-store 315 (should (consp (auth-source-pass--find-match "bar.com" nil nil))))
135 '(("foo" ("secret" . "foo password"))) 316 (auth-source-pass--with-store '(("dir1/bar.com" ("key1" . "val1")) ("dir2/bar.com" ("key2" . "val2")))
136 (let ((result (auth-source-pass--find-match "https://foo" nil nil))) 317 (should (consp (auth-source-pass--find-match "bar.com" nil nil)))))
137 (should (equal (auth-source-pass--get-attr "secret" result) 318
138 "foo password"))))) 319(ert-deftest auth-source-pass--matching-entries ()
139
140(ert-deftest auth-source-pass-find-match-matching-at-entry-name-ignoring-user ()
141 (auth-source-pass--with-store
142 '(("foo" ("secret" . "foo password")))
143 (let ((result (auth-source-pass--find-match "https://SomeUser@foo" nil nil)))
144 (should (equal (auth-source-pass--get-attr "secret" result)
145 "foo password")))))
146
147(ert-deftest auth-source-pass-find-match-matching-at-entry-name-with-user ()
148 (auth-source-pass--with-store
149 '(("SomeUser@foo" ("secret" . "SomeUser@foo password")))
150 (let ((result (auth-source-pass--find-match "https://SomeUser@foo" nil nil)))
151 (should (equal (auth-source-pass--get-attr "secret" result)
152 "SomeUser@foo password")))))
153
154(ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full ()
155 (auth-source-pass--with-store
156 '(("SomeUser@foo" ("secret" . "SomeUser@foo password"))
157 ("foo" ("secret" . "foo password")))
158 (let ((result (auth-source-pass--find-match "https://SomeUser@foo" nil nil)))
159 (should (equal (auth-source-pass--get-attr "secret" result)
160 "SomeUser@foo password")))))
161
162(ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full-reversed ()
163 (auth-source-pass--with-store
164 '(("foo" ("secret" . "foo password"))
165 ("SomeUser@foo" ("secret" . "SomeUser@foo password")))
166 (let ((result (auth-source-pass--find-match "https://SomeUser@foo" nil nil)))
167 (should (equal (auth-source-pass--get-attr "secret" result)
168 "SomeUser@foo password")))))
169
170(ert-deftest auth-source-pass-matching-entries-name-without-subdomain ()
171 (auth-source-pass--with-store '(("bar.com")) 320 (auth-source-pass--with-store '(("bar.com"))
172 (should (equal (auth-source-pass--matching-entries "foo.bar.com" nil nil) 321 (should (auth-source-pass-match-entry-p "bar.com" "bar.com"))
173 '(nil ("bar.com") nil))))) 322 ;; match even if sub-domain is asked for
174 323 (should (auth-source-pass-match-entry-p "bar.com" "foo.bar.com"))
175(ert-deftest auth-source-pass-matching-entries-name-without-subdomain-with-user () 324 ;; match even if a user is asked for
176 (auth-source-pass--with-store '(("someone@bar.com")) 325 (should (auth-source-pass-match-entry-p "bar.com" "bar.com" "user"))
177 (should (equal (auth-source-pass--matching-entries "foo.bar.com" "someone" nil) 326 ;; match even if user as an @ sign
178 '(nil nil nil ("someone@bar.com") nil nil nil nil nil))))) 327 (should (auth-source-pass-match-entry-p "bar.com" "bar.com" "user@someplace"))
179 328 ;; match even if a port is asked for
180(ert-deftest auth-source-pass-matching-entries-name-without-subdomain-with-bad-user () 329 (should (auth-source-pass-match-entry-p "bar.com" "bar.com" nil "8080"))
181 (auth-source-pass--with-store '(("someoneelse@bar.com")) 330 ;; match even if a user and a port are asked for
182 (should (equal (auth-source-pass--matching-entries "foo.bar.com" "someone" nil) 331 (should (auth-source-pass-match-entry-p "bar.com" "bar.com" "user" "8080"))
183 '(nil nil nil nil nil nil nil nil nil))))) 332 ;; don't match if a '.' is replaced with another character
184 333 (auth-source-pass--with-store '(("barXcom"))
185(ert-deftest auth-source-pass-matching-entries-name-without-subdomain-prefer-full () 334 (should-not (auth-source-pass-match-any-entry-p "bar.com" nil nil)))))
186 (auth-source-pass--with-store '(("bar.com") ("foo.bar.com")) 335
187 (should (equal (auth-source-pass--matching-entries "foo.bar.com" nil nil) 336(ert-deftest auth-source-pass--matching-entries-find-entries-with-a-username ()
188 '(("foo.bar.com") ("bar.com") nil))))) 337 (auth-source-pass--with-store '(("user@foo"))
189 338 (should (auth-source-pass-match-entry-p "user@foo" "foo" "user")))
190(ert-deftest auth-source-pass-dont-match-at-folder-name () 339 ;; match even if sub-domain is asked for
191 (auth-source-pass--with-store '(("foo.bar.com/foo")) 340 (auth-source-pass--with-store '(("user@bar.com"))
192 (should (equal (auth-source-pass--matching-entries "foo.bar.com" nil nil) 341 (should (auth-source-pass-match-entry-p "user@bar.com" "foo.bar.com" "user")))
193 '(nil nil nil))))) 342 ;; don't match if no user is asked for
194 343 (auth-source-pass--with-store '(("user@foo"))
195(ert-deftest auth-source-pass-matching-entries-host-port-and-subdir-user () 344 (should-not (auth-source-pass-match-any-entry-p "foo")))
196 (auth-source-pass--with-store '(("bar.com:443/someone")) 345 ;; don't match if user is different
197 (should (equal (auth-source-pass--matching-entries "bar.com" "someone" "443") 346 (auth-source-pass--with-store '(("user1@foo"))
198 '(nil ("bar.com:443/someone") nil nil nil nil 347 (should-not (auth-source-pass-match-any-entry-p "foo" "user2")))
199 nil nil nil nil nil nil))))) 348 ;; don't match if sub-domain is asked for but user is different
200 349 (auth-source-pass--with-store '(("user1@bar.com"))
201(ert-deftest auth-source-pass-matching-entries-host-port-and-subdir-user-with-custom-separator () 350 (should-not (auth-source-pass-match-any-entry-p "foo.bar.com" "user2"))))
351
352(ert-deftest auth-source-pass--matching-entries-find-entries-with-a-port ()
353 (auth-source-pass--with-store '(("bar.com:8080"))
354 (should (auth-source-pass-match-entry-p "bar.com:8080" "bar.com" nil "8080"))))
355
356(ert-deftest auth-source-pass--matching-entries-find-entries-with-slash ()
357 ;; match if entry filename matches user
358 (auth-source-pass--with-store '(("foo.com/user"))
359 (should (auth-source-pass-match-entry-p "foo.com/user" "foo.com" "user")))
360 ;; match with port if entry filename matches user
361 (auth-source-pass--with-store '(("foo.com:8080/user"))
362 (should (auth-source-pass-match-entry-p "foo.com:8080/user" "foo.com" "user" "8080")))
363 ;; don't match if entry filename doesn't match user
364 (auth-source-pass--with-store '(("foo.com/baz"))
365 (should-not (auth-source-pass-match-any-entry-p "foo.com" "user"))))
366
367(ert-deftest auth-source-pass-matching-entries-with-custom-separator ()
202 (let ((auth-source-pass-port-separator "#")) 368 (let ((auth-source-pass-port-separator "#"))
203 (auth-source-pass--with-store '(("bar.com#443/someone")) 369 (auth-source-pass--with-store '(("bar.com#443/someone"))
204 (should (equal (auth-source-pass--matching-entries "bar.com" "someone" "443") 370 (should (auth-source-pass-match-entry-p "bar.com#443/someone" "bar.com" "someone" "443")))))
205 '(nil ("bar.com#443/someone") nil nil nil nil 371
206 nil nil nil nil nil nil)))))) 372(ert-deftest auth-source-pass--matching-entries-sort-results ()
207 373 (auth-source-pass--with-store '(("user@foo") ("foo"))
208(ert-deftest auth-source-pass-matching-entries-extracting-user-from-host () 374 (should (auth-source-pass--includes-sorted-entries '("user@foo" "foo") "foo" "user")))
209 (auth-source-pass--with-store 375 ;; same, but store is reversed
210 '(("foo.com/bar" ("secret" . "foo.com/bar password")))
211 (let ((result (auth-source-pass--find-match "https://bar@foo.com" nil nil)))
212 (should (equal (auth-source-pass--get-attr "secret" result)
213 "foo.com/bar password")))))
214
215(ert-deftest auth-source-pass-matching-entries-with-user-first ()
216 (auth-source-pass--with-store '(("foo") ("user@foo")) 376 (auth-source-pass--with-store '(("foo") ("user@foo"))
217 (should (equal (auth-source-pass--matching-entries "foo" "user" nil) 377 (should (auth-source-pass--includes-sorted-entries '("user@foo" "foo") "foo" "user")))
218 '(("user@foo") nil ("foo")))) 378 ;; with sub-domain
219 (auth-source-pass--should-have-message-containing "found: (\"user@foo\" \"foo\""))) 379 (auth-source-pass--with-store '(("bar.com") ("foo.bar.com"))
220 380 (should (auth-source-pass--includes-sorted-entries '("foo.bar.com" "bar.com") "foo.bar.com")))
221(ert-deftest auth-source-pass-give-priority-to-desired-user () 381 ;; matching user in the entry data takes priority
222 (auth-source-pass--with-store 382 (auth-source-pass--with-store '(("dir1/bar.com") ("dir2/bar.com" ("user" . "user")))
223 '(("foo" ("secret" . "foo password")) 383 (should (auth-source-pass--includes-sorted-entries
224 ("subdir/foo" ("secret" . "subdir/foo password") ("user" . "someone"))) 384 '("dir2/bar.com" "dir1/bar.com")
225 (let ((result (auth-source-pass--find-match "foo" "someone" nil))) 385 "bar.com" "user")))
226 (should (equal (auth-source-pass--get-attr "secret" result) 386 ;; same, but store is reversed
227 "subdir/foo password")) 387 (auth-source-pass--with-store '(("dir2/bar.com" ("user" . "user")) ("dir1/bar.com"))
228 (should (equal (auth-source-pass--get-attr "user" result) 388 (should (auth-source-pass--includes-sorted-entries
229 "someone"))) 389 '("dir2/bar.com" "dir1/bar.com")
230 (auth-source-pass--should-have-message-containing "found: (\"foo\" \"subdir/foo\""))) 390 "bar.com" "user"))))
231 391
232(ert-deftest auth-source-pass-give-priority-to-desired-user-reversed () 392(ert-deftest auth-source-pass-all-supported-organizations ()
233 (auth-source-pass--with-store 393 ;; test every possible entry to store this data: user=rms host=gnu.org port=22
234 '(("foo" ("secret" . "foo password") ("user" . "someone")) 394 (dolist (entry '(;; only host name
235 ("subdir/foo" ("secret" . "subdir/foo password"))) 395 "gnu.org"
236 (let ((result (auth-source-pass--find-match "foo" "someone" nil))) 396 ;; hostname + user
237 (should (equal (auth-source-pass--get-attr "secret" result) 397 "gnu.org/rms" "rms@gnu.org"
238 "foo password"))) 398 ;; hostname + port
239 (auth-source-pass--should-have-message-containing "found: (\"foo\" \"subdir/foo\""))) 399 "gnu.org:22"
240 400 ;; hostname + user + port
241(ert-deftest auth-source-pass-return-first-when-several-matches () 401 "gnu.org:22/rms" "rms@gnu.org:22"
242 (auth-source-pass--with-store 402 ;; all of the above in a random folder
243 '(("foo" ("secret" . "foo password")) 403 "a/b/gnu.org"
244 ("subdir/foo" ("secret" . "subdir/foo password"))) 404 "a/b/gnu.org/rms" "a/b/rms@gnu.org"
245 (let ((result (auth-source-pass--find-match "foo" nil nil))) 405 "a/b/gnu.org:22"
246 (should (equal (auth-source-pass--get-attr "secret" result) 406 "a/b/gnu.org:22/rms" "a/b/rms@gnu.org:22"))
247 "foo password"))) 407 (auth-source-pass--with-store `((,entry))
248 (auth-source-pass--should-have-message-containing "found: (\"foo\" \"subdir/foo\""))) 408 (should (auth-source-pass-match-entry-p entry "gnu.org" "rms" "22")))))
249
250(ert-deftest auth-source-pass-matching-entries-make-divansantana-happy ()
251 (auth-source-pass--with-store '(("host.com"))
252 (should (equal (auth-source-pass--matching-entries "smtp.host.com" "myusername@host.co.za" nil)
253 '(nil nil nil nil nil ("host.com") nil nil nil)))))
254
255(ert-deftest auth-source-pass-find-host-without-port ()
256 (auth-source-pass--with-store
257 '(("host.com" ("secret" . "host.com password")))
258 (let ((result (auth-source-pass--find-match "host.com:8888" "someuser" nil)))
259 (should (equal (auth-source-pass--get-attr "secret" result)
260 "host.com password")))))
261
262(ert-deftest auth-source-pass-matching-entries-host-with-port ()
263 (auth-source-pass--with-store '(("host.com:443"))
264 (should (equal (auth-source-pass--matching-entries "host.com" "someuser" "443")
265 '(nil nil nil nil ("host.com:443") nil
266 nil nil nil nil nil nil)))))
267
268(ert-deftest auth-source-pass-matching-entries-with-custom-port-separator ()
269 (let ((auth-source-pass-port-separator "#"))
270 (auth-source-pass--with-store '(("host.com#443"))
271 (should (equal (auth-source-pass--matching-entries "host.com" "someuser" "443")
272 '(nil nil nil nil ("host.com#443") nil
273 nil nil nil nil nil nil))))))
274 409
275(defmacro auth-source-pass--with-store-find-foo (store &rest body) 410(defmacro auth-source-pass--with-store-find-foo (store &rest body)
276 "Use STORE while executing BODY. \"foo\" is the matched entry." 411 "Use STORE while executing BODY. \"foo\" is the matched entry."
@@ -300,33 +435,6 @@ This function is intended to be set to `auth-source-debug`."
300 (should (equal (plist-get result :port) 512)) 435 (should (equal (plist-get result :port) 512))
301 (should (equal (plist-get result :user) "anuser"))))) 436 (should (equal (plist-get result :user) "anuser")))))
302 437
303(ert-deftest auth-source-pass-build-result-passes-full-host-to-find-match ()
304 (let (passed-host)
305 (cl-letf (((symbol-function 'auth-source-pass--find-match)
306 (lambda (host _user _port)
307 (setq passed-host host)
308 nil)))
309 (auth-source-pass--build-result "https://user@host.com:123" nil nil)
310 (should (equal passed-host "https://user@host.com:123"))
311 (auth-source-pass--build-result "https://user@host.com" nil nil)
312 (should (equal passed-host "https://user@host.com"))
313 (auth-source-pass--build-result "user@host.com" nil nil)
314 (should (equal passed-host "user@host.com"))
315 (auth-source-pass--build-result "user@host.com:443" nil nil)
316 (should (equal passed-host "user@host.com:443")))))
317
318(ert-deftest auth-source-pass-only-return-entries-that-can-be-open ()
319 (auth-source-pass--with-store
320 '(("foo.site.com" ("secret" . "foo.site.com password"))
321 ("bar.site.com") ; An entry name with no data is invalid
322 ("mail/baz.site.com/scott" ("secret" . "mail/baz.site.com/scott password")))
323 (should (equal (auth-source-pass--find-match "foo.site.com" "someuser" nil)
324 '(("secret" . "foo.site.com password"))))
325 (should (equal (auth-source-pass--find-match "bar.site.com" "someuser" nil)
326 nil))
327 (should (equal (auth-source-pass--find-match "baz.site.com" "scott" nil)
328 '(("secret" . "mail/baz.site.com/scott password"))))))
329
330(ert-deftest auth-source-pass-can-start-from-auth-source-search () 438(ert-deftest auth-source-pass-can-start-from-auth-source-search ()
331 (auth-source-pass--with-store '(("gitlab.com" ("user" . "someone"))) 439 (auth-source-pass--with-store '(("gitlab.com" ("user" . "someone")))
332 (auth-source-pass-enable) 440 (auth-source-pass-enable)
@@ -334,6 +442,24 @@ This function is intended to be set to `auth-source-debug`."
334 (should (equal (plist-get result :user) "someone")) 442 (should (equal (plist-get result :user) "someone"))
335 (should (equal (plist-get result :host) "gitlab.com"))))) 443 (should (equal (plist-get result :host) "gitlab.com")))))
336 444
445(ert-deftest auth-source-pass-prints-meaningful-debug-log ()
446 (auth-source-pass--with-store '()
447 (auth-source-pass--find-match "gitlab.com" nil nil)
448 (should (auth-source-pass--have-message-matching
449 "entries matching hostname=\"gitlab.com\""))
450 (should (auth-source-pass--have-message-matching
451 "corresponding suffixes to search for: .*\"gitlab.com\""))
452 (should (auth-source-pass--have-message-matching
453 "found no entries matching \"gitlab.com\"")))
454 (auth-source-pass--with-store '(("gitlab.com"))
455 (auth-source-pass--find-match "gitlab.com" nil nil)
456 (should (auth-source-pass--have-message-matching
457 "found 1 entry matching \"gitlab.com\": \"gitlab.com\"")))
458 (auth-source-pass--with-store '(("a/gitlab.com") ("b/gitlab.com"))
459 (auth-source-pass--find-match "gitlab.com" nil nil)
460 (should (auth-source-pass--have-message-matching
461 "found 2 entries matching \"gitlab.com\": (\"a/gitlab.com\" \"b/gitlab.com\")"))))
462
337(provide 'auth-source-pass-tests) 463(provide 'auth-source-pass-tests)
338 464
339;;; auth-source-pass-tests.el ends here 465;;; auth-source-pass-tests.el ends here