diff options
| author | Keith Amidon | 2019-05-05 20:21:43 -0700 |
|---|---|---|
| committer | Damien Cassou | 2019-06-24 09:15:40 +0200 |
| commit | 0a580c187da9840298921a507bfe3dae3d1a00a7 (patch) | |
| tree | ba3eea941f1b603e7b97c102a058c347e5dfadae /test | |
| parent | 57e763a0a057621daac2761084556df38f7f2373 (diff) | |
| download | emacs-0a580c187da9840298921a507bfe3dae3d1a00a7.tar.gz emacs-0a580c187da9840298921a507bfe3dae3d1a00a7.zip | |
Minimize entry parsing in auth-source-pass
Prior to this commit, while searching for the most applicable entry
password-store entries were decrypted and parsed to ensure they were
valid. The entries were parsed in the order they were found on the
filesystem and all applicable entries would be decrypted and parsed,
which varied based on the contents of the password-store and the entry
to be found.
This is fine when the GPG key is cached and each entry can be
decrypted without user interaction. However, for security some people
have their GPG on a hardware token like a Yubikey setup so that they
have to touch a sensor on the toke for every cryptographic operation,
in which case it becomes inconvenient as each attempt to find an entry
requires a variable number of touches of the hardware token.
The implementation already assumes that names which contain more of
the information in the search key should be preferred so there is an
ordering of preference of applicable entries. If the decrypt and
parsing is removed from the initial identification of applicable
entries in the store then in most cases a single decrypt and parse of
the most preferred entry will suffice, improving the experience for
hardware token users that require interaction with the token.
This commit implements that strategy. It is in spirit a refactor of
the existing code.
* lisp/auth-source-pass.el (auth-source-pass--matching-entries): New
function, generate an ordered list of regular expression matchers for
all possible names that could be in the password-store for the entry
to be found and then makes a pass over the password-store entry names
accumulating the matching entries in a list after the regexp that
matched. This implementation ensures the password-store entry list
still only has to be scanned once.
(auth-source-pass--find-match-unambiguous): Use it to obtain candidate
entries and then parse them one by one until an entry containing the
desired information is located. When complete, return the parsed data
of the entry instead of the entry name so that the information can be
used directly to construct the auth-source response.
(auth-source-pass--build-result): Update accordingly.
(auth-source-pass--find-match): Update docstring accordingly.
(auth-source-pass--select-one-entry)
(auth-source-pass--entry-valid-p)
(auth-source-pass--find-all-by-entry-name)
(auth-source-pass--find-one-by-entry-name): Remove.
(auth-source-pass--select-from-entries)
(auth-source-pass--accumulate-matches)
(auth-source-pass--entry-reducer)
(auth-source-pass--generate-entry-suffixes)
(auth-source-pass--domains)
(auth-source-pass--name-port-user-suffixes): New functions.
* test/lisp/auth-source-pass-tests.el: One test case was added to the
test suite to verify that only the minimal number of entries are
parsed in common cases. The
auth-source-pass-only-return-entries-that-can-be-open test case had to
be re-implemented because the function it was used eliminated as the
functionality is provided elsewhere. All the other fairly substantial
changes to the test suite are the result of mechanical changes that
were required to adapt to auth-source-pass--find-match returning the
data from a parsed password-store entry instead of the entry name.
Diffstat (limited to 'test')
| -rw-r--r-- | test/lisp/auth-source-pass-tests.el | 264 |
1 files changed, 160 insertions, 104 deletions
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el index 1539d9611f6..2c28f799453 100644 --- a/test/lisp/auth-source-pass-tests.el +++ b/test/lisp/auth-source-pass-tests.el | |||
| @@ -63,14 +63,19 @@ | |||
| 63 | This function is intended to be set to `auth-source-debug`." | 63 | This function is intended to be set to `auth-source-debug`." |
| 64 | (add-to-list 'auth-source-pass--debug-log (apply #'format msg) t)) | 64 | (add-to-list 'auth-source-pass--debug-log (apply #'format msg) t)) |
| 65 | 65 | ||
| 66 | (defvar auth-source-pass--parse-log nil) | ||
| 67 | |||
| 66 | (defmacro auth-source-pass--with-store (store &rest body) | 68 | (defmacro auth-source-pass--with-store (store &rest body) |
| 67 | "Use STORE as password-store while executing BODY." | 69 | "Use STORE as password-store while executing BODY." |
| 68 | (declare (indent 1)) | 70 | (declare (indent 1)) |
| 69 | `(cl-letf (((symbol-function 'auth-source-pass-parse-entry) (lambda (entry) (cdr (cl-find entry ,store :key #'car :test #'string=))) ) | 71 | `(cl-letf (((symbol-function 'auth-source-pass-parse-entry) |
| 70 | ((symbol-function 'auth-source-pass-entries) (lambda () (mapcar #'car ,store))) | 72 | (lambda (entry) |
| 71 | ((symbol-function 'auth-source-pass--entry-valid-p) (lambda (_entry) t))) | 73 | (add-to-list 'auth-source-pass--parse-log entry) |
| 74 | (cdr (cl-find entry ,store :key #'car :test #'string=)))) | ||
| 75 | ((symbol-function 'auth-source-pass-entries) (lambda () (mapcar #'car ,store)))) | ||
| 72 | (let ((auth-source-debug #'auth-source-pass--debug) | 76 | (let ((auth-source-debug #'auth-source-pass--debug) |
| 73 | (auth-source-pass--debug-log nil)) | 77 | (auth-source-pass--debug-log nil) |
| 78 | (auth-source-pass--parse-log nil)) | ||
| 74 | ,@body))) | 79 | ,@body))) |
| 75 | 80 | ||
| 76 | (ert-deftest auth-source-pass-any-host () | 81 | (ert-deftest auth-source-pass-any-host () |
| @@ -88,125 +93,184 @@ This function is intended to be set to `auth-source-debug`." | |||
| 88 | ("bar")) | 93 | ("bar")) |
| 89 | (should-not (auth-source-pass-search :host "baz")))) | 94 | (should-not (auth-source-pass-search :host "baz")))) |
| 90 | 95 | ||
| 96 | (ert-deftest auth-source-pass-find-match-minimal-parsing () | ||
| 97 | (let ((store-contents | ||
| 98 | '(("baz" ("secret" . "baz password")) | ||
| 99 | ("baz:123" ("secret" . "baz:123 password")) | ||
| 100 | ("baz/foo" ("secret" . "baz/foo password")) | ||
| 101 | ("foo@baz" ("secret" . "foo@baz password")) | ||
| 102 | ("baz:123/foo" ("secret" . "baz:123/foo password")) | ||
| 103 | ("foo@baz:123" ("secret" . "foo@baz:123 password")) | ||
| 104 | ("bar.baz" ("secret" . "bar.baz password")) | ||
| 105 | ("bar.baz:123" ("secret" . "bar.baz:123 password")) | ||
| 106 | ("bar.baz/foo" ("secret" . "bar.baz/foo password")) | ||
| 107 | ("foo@bar.baz" ("secret" . "foo@bar.baz password")) | ||
| 108 | ("bar.baz:123/foo" ("secret" . "bar.baz:123/foo password")) | ||
| 109 | ("foo@bar.baz:123" ("secret" . "foo@bar.baz:123 password"))))) | ||
| 110 | (auth-source-pass--with-store store-contents | ||
| 111 | (auth-source-pass--find-match "bar.baz" "foo" "123") | ||
| 112 | (should (equal auth-source-pass--parse-log '("foo@bar.baz:123")))) | ||
| 113 | (auth-source-pass--with-store store-contents | ||
| 114 | (auth-source-pass--find-match "bar.baz" "foo" nil) | ||
| 115 | (should (equal auth-source-pass--parse-log '("foo@bar.baz")))) | ||
| 116 | (auth-source-pass--with-store store-contents | ||
| 117 | (auth-source-pass--find-match "bar.baz" nil "123") | ||
| 118 | (should (equal auth-source-pass--parse-log '("bar.baz:123")))) | ||
| 119 | (auth-source-pass--with-store store-contents | ||
| 120 | (auth-source-pass--find-match "bar.baz" nil nil) | ||
| 121 | (should (equal auth-source-pass--parse-log '("bar.baz")))) | ||
| 122 | (auth-source-pass--with-store store-contents | ||
| 123 | (auth-source-pass--find-match "baz" nil nil) | ||
| 124 | (should (equal auth-source-pass--parse-log '("baz")))))) | ||
| 91 | 125 | ||
| 92 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name () | 126 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name () |
| 93 | (auth-source-pass--with-store '(("foo")) | 127 | (auth-source-pass--with-store |
| 94 | (should (equal (auth-source-pass--find-match "foo" nil nil) | 128 | '(("foo" ("secret" . "foo password"))) |
| 95 | "foo")))) | 129 | (let ((result (auth-source-pass--find-match "foo" nil nil))) |
| 130 | (should (equal (auth-source-pass--get-attr "secret" result) | ||
| 131 | "foo password"))))) | ||
| 96 | 132 | ||
| 97 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-part () | 133 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-part () |
| 98 | (auth-source-pass--with-store '(("foo")) | 134 | (auth-source-pass--with-store |
| 99 | (should (equal (auth-source-pass--find-match "https://foo" nil nil) | 135 | '(("foo" ("secret" . "foo password"))) |
| 100 | "foo")))) | 136 | (let ((result (auth-source-pass--find-match "https://foo" nil nil))) |
| 137 | (should (equal (auth-source-pass--get-attr "secret" result) | ||
| 138 | "foo password"))))) | ||
| 101 | 139 | ||
| 102 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-ignoring-user () | 140 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-ignoring-user () |
| 103 | (auth-source-pass--with-store '(("foo")) | 141 | (auth-source-pass--with-store |
| 104 | (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil nil) | 142 | '(("foo" ("secret" . "foo password"))) |
| 105 | "foo")))) | 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"))))) | ||
| 106 | 146 | ||
| 107 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-with-user () | 147 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-with-user () |
| 108 | (auth-source-pass--with-store '(("SomeUser@foo")) | 148 | (auth-source-pass--with-store |
| 109 | (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil nil) | 149 | '(("SomeUser@foo" ("secret" . "SomeUser@foo password"))) |
| 110 | "SomeUser@foo")))) | 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"))))) | ||
| 111 | 153 | ||
| 112 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full () | 154 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full () |
| 113 | (auth-source-pass--with-store '(("SomeUser@foo") ("foo")) | 155 | (auth-source-pass--with-store |
| 114 | (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil nil) | 156 | '(("SomeUser@foo" ("secret" . "SomeUser@foo password")) |
| 115 | "SomeUser@foo")))) | 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"))))) | ||
| 116 | 161 | ||
| 117 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full-reversed () | 162 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-prefer-full-reversed () |
| 118 | (auth-source-pass--with-store '(("foo") ("SomeUser@foo")) | 163 | (auth-source-pass--with-store |
| 119 | (should (equal (auth-source-pass--find-match "https://SomeUser@foo" nil nil) | 164 | '(("foo" ("secret" . "foo password")) |
| 120 | "SomeUser@foo")))) | 165 | ("SomeUser@foo" ("secret" . "SomeUser@foo password"))) |
| 121 | 166 | (let ((result (auth-source-pass--find-match "https://SomeUser@foo" nil nil))) | |
| 122 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain () | 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 () | ||
| 123 | (auth-source-pass--with-store '(("bar.com")) | 171 | (auth-source-pass--with-store '(("bar.com")) |
| 124 | (should (equal (auth-source-pass--find-match "foo.bar.com" nil nil) | 172 | (should (equal (auth-source-pass--matching-entries "foo.bar.com" nil nil) |
| 125 | "bar.com")))) | 173 | '(nil ("bar.com") nil))))) |
| 126 | 174 | ||
| 127 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain-with-user () | 175 | (ert-deftest auth-source-pass-matching-entries-name-without-subdomain-with-user () |
| 128 | (auth-source-pass--with-store '(("someone@bar.com")) | 176 | (auth-source-pass--with-store '(("someone@bar.com")) |
| 129 | (should (equal (auth-source-pass--find-match "foo.bar.com" "someone" nil) | 177 | (should (equal (auth-source-pass--matching-entries "foo.bar.com" "someone" nil) |
| 130 | "someone@bar.com")))) | 178 | '(nil nil nil ("someone@bar.com") nil nil nil nil nil))))) |
| 131 | 179 | ||
| 132 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain-with-bad-user () | 180 | (ert-deftest auth-source-pass-matching-entries-name-without-subdomain-with-bad-user () |
| 133 | (auth-source-pass--with-store '(("someoneelse@bar.com")) | 181 | (auth-source-pass--with-store '(("someoneelse@bar.com")) |
| 134 | (should (equal (auth-source-pass--find-match "foo.bar.com" "someone" nil) | 182 | (should (equal (auth-source-pass--matching-entries "foo.bar.com" "someone" nil) |
| 135 | nil)))) | 183 | '(nil nil nil nil nil nil nil nil nil))))) |
| 136 | 184 | ||
| 137 | (ert-deftest auth-source-pass-find-match-matching-at-entry-name-without-subdomain-prefer-full () | 185 | (ert-deftest auth-source-pass-matching-entries-name-without-subdomain-prefer-full () |
| 138 | (auth-source-pass--with-store '(("bar.com") ("foo.bar.com")) | 186 | (auth-source-pass--with-store '(("bar.com") ("foo.bar.com")) |
| 139 | (should (equal (auth-source-pass--find-match "foo.bar.com" nil nil) | 187 | (should (equal (auth-source-pass--matching-entries "foo.bar.com" nil nil) |
| 140 | "foo.bar.com")))) | 188 | '(("foo.bar.com") ("bar.com") nil))))) |
| 141 | 189 | ||
| 142 | (ert-deftest auth-source-pass-dont-match-at-folder-name () | 190 | (ert-deftest auth-source-pass-dont-match-at-folder-name () |
| 143 | (auth-source-pass--with-store '(("foo.bar.com/foo")) | 191 | (auth-source-pass--with-store '(("foo.bar.com/foo")) |
| 144 | (should (equal (auth-source-pass--find-match "foo.bar.com" nil nil) | 192 | (should (equal (auth-source-pass--matching-entries "foo.bar.com" nil nil) |
| 145 | nil)))) | 193 | '(nil nil nil))))) |
| 146 | 194 | ||
| 147 | (ert-deftest auth-source-pass-find-match-matching-host-port-and-subdir-user () | 195 | (ert-deftest auth-source-pass-matching-entries-host-port-and-subdir-user () |
| 148 | (auth-source-pass--with-store '(("bar.com:443/someone")) | 196 | (auth-source-pass--with-store '(("bar.com:443/someone")) |
| 149 | (should (equal (auth-source-pass--find-match "bar.com" "someone" "443") | 197 | (should (equal (auth-source-pass--matching-entries "bar.com" "someone" "443") |
| 150 | "bar.com:443/someone")))) | 198 | '(nil ("bar.com:443/someone") nil nil nil nil |
| 199 | nil nil nil nil nil nil))))) | ||
| 151 | 200 | ||
| 152 | (ert-deftest auth-source-pass-find-match-matching-host-port-and-subdir-user-with-custom-separator () | 201 | (ert-deftest auth-source-pass-matching-entries-host-port-and-subdir-user-with-custom-separator () |
| 153 | (let ((auth-source-pass-port-separator "#")) | 202 | (let ((auth-source-pass-port-separator "#")) |
| 154 | (auth-source-pass--with-store '(("bar.com#443/someone")) | 203 | (auth-source-pass--with-store '(("bar.com#443/someone")) |
| 155 | (should (equal (auth-source-pass--find-match "bar.com" "someone" "443") | 204 | (should (equal (auth-source-pass--matching-entries "bar.com" "someone" "443") |
| 156 | "bar.com#443/someone"))))) | 205 | '(nil ("bar.com#443/someone") nil nil nil nil |
| 157 | 206 | nil nil nil nil nil nil)))))) | |
| 158 | (ert-deftest auth-source-pass-find-match-matching-extracting-user-from-host () | 207 | |
| 159 | (auth-source-pass--with-store '(("foo.com/bar")) | 208 | (ert-deftest auth-source-pass-matching-entries-extracting-user-from-host () |
| 160 | (should (equal (auth-source-pass--find-match "https://bar@foo.com" nil nil) | 209 | (auth-source-pass--with-store |
| 161 | "foo.com/bar")))) | 210 | '(("foo.com/bar" ("secret" . "foo.com/bar password"))) |
| 162 | 211 | (let ((result (auth-source-pass--find-match "https://bar@foo.com" nil nil))) | |
| 163 | (ert-deftest auth-source-pass-search-with-user-first () | 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 () | ||
| 164 | (auth-source-pass--with-store '(("foo") ("user@foo")) | 216 | (auth-source-pass--with-store '(("foo") ("user@foo")) |
| 165 | (should (equal (auth-source-pass--find-match "foo" "user" nil) | 217 | (should (equal (auth-source-pass--matching-entries "foo" "user" nil) |
| 166 | "user@foo")) | 218 | '(("user@foo") nil ("foo")))) |
| 167 | (auth-source-pass--should-have-message-containing "Found 1 match"))) | 219 | (auth-source-pass--should-have-message-containing "found: (\"user@foo\" \"foo\""))) |
| 168 | 220 | ||
| 169 | (ert-deftest auth-source-pass-give-priority-to-desired-user () | 221 | (ert-deftest auth-source-pass-give-priority-to-desired-user () |
| 170 | (auth-source-pass--with-store '(("foo") ("subdir/foo" ("user" . "someone"))) | 222 | (auth-source-pass--with-store |
| 171 | (should (equal (auth-source-pass--find-match "foo" "someone" nil) | 223 | '(("foo" ("secret" . "foo password")) |
| 172 | "subdir/foo")) | 224 | ("subdir/foo" ("secret" . "subdir/foo password") ("user" . "someone"))) |
| 173 | (auth-source-pass--should-have-message-containing "Found 2 matches") | 225 | (let ((result (auth-source-pass--find-match "foo" "someone" nil))) |
| 174 | (auth-source-pass--should-have-message-containing "matching user field"))) | 226 | (should (equal (auth-source-pass--get-attr "secret" result) |
| 227 | "subdir/foo password")) | ||
| 228 | (should (equal (auth-source-pass--get-attr "user" result) | ||
| 229 | "someone"))) | ||
| 230 | (auth-source-pass--should-have-message-containing "found: (\"foo\" \"subdir/foo\""))) | ||
| 175 | 231 | ||
| 176 | (ert-deftest auth-source-pass-give-priority-to-desired-user-reversed () | 232 | (ert-deftest auth-source-pass-give-priority-to-desired-user-reversed () |
| 177 | (auth-source-pass--with-store '(("foo" ("user" . "someone")) ("subdir/foo")) | 233 | (auth-source-pass--with-store |
| 178 | (should (equal (auth-source-pass--find-match "foo" "someone" nil) | 234 | '(("foo" ("secret" . "foo password") ("user" . "someone")) |
| 179 | "foo")) | 235 | ("subdir/foo" ("secret" . "subdir/foo password"))) |
| 180 | (auth-source-pass--should-have-message-containing "Found 2 matches") | 236 | (let ((result (auth-source-pass--find-match "foo" "someone" nil))) |
| 181 | (auth-source-pass--should-have-message-containing "matching user field"))) | 237 | (should (equal (auth-source-pass--get-attr "secret" result) |
| 238 | "foo password"))) | ||
| 239 | (auth-source-pass--should-have-message-containing "found: (\"foo\" \"subdir/foo\""))) | ||
| 182 | 240 | ||
| 183 | (ert-deftest auth-source-pass-return-first-when-several-matches () | 241 | (ert-deftest auth-source-pass-return-first-when-several-matches () |
| 184 | (auth-source-pass--with-store '(("foo") ("subdir/foo")) | 242 | (auth-source-pass--with-store |
| 185 | (should (equal (auth-source-pass--find-match "foo" nil nil) | 243 | '(("foo" ("secret" . "foo password")) |
| 186 | "foo")) | 244 | ("subdir/foo" ("secret" . "subdir/foo password"))) |
| 187 | (auth-source-pass--should-have-message-containing "Found 2 matches") | 245 | (let ((result (auth-source-pass--find-match "foo" nil nil))) |
| 188 | (auth-source-pass--should-have-message-containing "the first one"))) | 246 | (should (equal (auth-source-pass--get-attr "secret" result) |
| 189 | 247 | "foo password"))) | |
| 190 | (ert-deftest auth-source-pass-make-divansantana-happy () | 248 | (auth-source-pass--should-have-message-containing "found: (\"foo\" \"subdir/foo\""))) |
| 249 | |||
| 250 | (ert-deftest auth-source-pass-matching-entries-make-divansantana-happy () | ||
| 191 | (auth-source-pass--with-store '(("host.com")) | 251 | (auth-source-pass--with-store '(("host.com")) |
| 192 | (should (equal (auth-source-pass--find-match "smtp.host.com" "myusername@host.co.za" nil) | 252 | (should (equal (auth-source-pass--matching-entries "smtp.host.com" "myusername@host.co.za" nil) |
| 193 | "host.com")))) | 253 | '(nil nil nil nil nil ("host.com") nil nil nil))))) |
| 194 | 254 | ||
| 195 | (ert-deftest auth-source-pass-find-host-without-port () | 255 | (ert-deftest auth-source-pass-find-host-without-port () |
| 196 | (auth-source-pass--with-store '(("host.com")) | 256 | (auth-source-pass--with-store |
| 197 | (should (equal (auth-source-pass--find-match "host.com:8888" "someuser" nil) | 257 | '(("host.com" ("secret" . "host.com password"))) |
| 198 | "host.com")))) | 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"))))) | ||
| 199 | 261 | ||
| 200 | (ert-deftest auth-source-pass-find-host-with-port () | 262 | (ert-deftest auth-source-pass-matching-entries-host-with-port () |
| 201 | (auth-source-pass--with-store '(("host.com:443")) | 263 | (auth-source-pass--with-store '(("host.com:443")) |
| 202 | (should (equal (auth-source-pass--find-match "host.com" "someuser" "443") | 264 | (should (equal (auth-source-pass--matching-entries "host.com" "someuser" "443") |
| 203 | "host.com:443")))) | 265 | '(nil nil nil nil ("host.com:443") nil |
| 266 | nil nil nil nil nil nil))))) | ||
| 204 | 267 | ||
| 205 | (ert-deftest auth-source-pass-find-host-with-custom-port-separator () | 268 | (ert-deftest auth-source-pass-matching-entries-with-custom-port-separator () |
| 206 | (let ((auth-source-pass-port-separator "#")) | 269 | (let ((auth-source-pass-port-separator "#")) |
| 207 | (auth-source-pass--with-store '(("host.com#443")) | 270 | (auth-source-pass--with-store '(("host.com#443")) |
| 208 | (should (equal (auth-source-pass--find-match "host.com" "someuser" "443") | 271 | (should (equal (auth-source-pass--matching-entries "host.com" "someuser" "443") |
| 209 | "host.com#443"))))) | 272 | '(nil nil nil nil ("host.com#443") nil |
| 273 | nil nil nil nil nil nil)))))) | ||
| 210 | 274 | ||
| 211 | (defmacro auth-source-pass--with-store-find-foo (store &rest body) | 275 | (defmacro auth-source-pass--with-store-find-foo (store &rest body) |
| 212 | "Use STORE while executing BODY. \"foo\" is the matched entry." | 276 | "Use STORE while executing BODY. \"foo\" is the matched entry." |
| @@ -218,7 +282,8 @@ This function is intended to be set to `auth-source-debug`." | |||
| 218 | ,@body))) | 282 | ,@body))) |
| 219 | 283 | ||
| 220 | (ert-deftest auth-source-pass-build-result-return-parameters () | 284 | (ert-deftest auth-source-pass-build-result-return-parameters () |
| 221 | (auth-source-pass--with-store-find-foo '(("foo")) | 285 | (auth-source-pass--with-store-find-foo |
| 286 | '(("foo" ("secret" . "foo password"))) | ||
| 222 | (let ((result (auth-source-pass--build-result "foo" 512 "user"))) | 287 | (let ((result (auth-source-pass--build-result "foo" 512 "user"))) |
| 223 | (should (equal (plist-get result :port) 512)) | 288 | (should (equal (plist-get result :port) 512)) |
| 224 | (should (equal (plist-get result :user) "user"))))) | 289 | (should (equal (plist-get result :user) "user"))))) |
| @@ -238,7 +303,9 @@ This function is intended to be set to `auth-source-debug`." | |||
| 238 | (ert-deftest auth-source-pass-build-result-passes-full-host-to-find-match () | 303 | (ert-deftest auth-source-pass-build-result-passes-full-host-to-find-match () |
| 239 | (let (passed-host) | 304 | (let (passed-host) |
| 240 | (cl-letf (((symbol-function 'auth-source-pass--find-match) | 305 | (cl-letf (((symbol-function 'auth-source-pass--find-match) |
| 241 | (lambda (host _user _port) (setq passed-host host)))) | 306 | (lambda (host _user _port) |
| 307 | (setq passed-host host) | ||
| 308 | nil))) | ||
| 242 | (auth-source-pass--build-result "https://user@host.com:123" nil nil) | 309 | (auth-source-pass--build-result "https://user@host.com:123" nil nil) |
| 243 | (should (equal passed-host "https://user@host.com:123")) | 310 | (should (equal passed-host "https://user@host.com:123")) |
| 244 | (auth-source-pass--build-result "https://user@host.com" nil nil) | 311 | (auth-source-pass--build-result "https://user@host.com" nil nil) |
| @@ -249,27 +316,16 @@ This function is intended to be set to `auth-source-debug`." | |||
| 249 | (should (equal passed-host "user@host.com:443"))))) | 316 | (should (equal passed-host "user@host.com:443"))))) |
| 250 | 317 | ||
| 251 | (ert-deftest auth-source-pass-only-return-entries-that-can-be-open () | 318 | (ert-deftest auth-source-pass-only-return-entries-that-can-be-open () |
| 252 | (cl-letf (((symbol-function 'auth-source-pass-entries) | 319 | (auth-source-pass--with-store |
| 253 | (lambda () '("foo.site.com" "bar.site.com" "mail/baz.site.com/scott"))) | 320 | '(("foo.site.com" ("secret" . "foo.site.com password")) |
| 254 | ((symbol-function 'auth-source-pass--entry-valid-p) | 321 | ("bar.site.com") ; An entry name with no data is invalid |
| 255 | ;; only foo.site.com and "mail/baz.site.com/scott" are valid | 322 | ("mail/baz.site.com/scott" ("secret" . "mail/baz.site.com/scott password"))) |
| 256 | (lambda (entry) (member entry '("foo.site.com" "mail/baz.site.com/scott"))))) | 323 | (should (equal (auth-source-pass--find-match "foo.site.com" "someuser" nil) |
| 257 | (should (equal (auth-source-pass--find-all-by-entry-name "foo.site.com" "someuser") | 324 | '(("secret" . "foo.site.com password")))) |
| 258 | '("foo.site.com"))) | 325 | (should (equal (auth-source-pass--find-match "bar.site.com" "someuser" nil) |
| 259 | (should (equal (auth-source-pass--find-all-by-entry-name "bar.site.com" "someuser") | 326 | nil)) |
| 260 | '())) | 327 | (should (equal (auth-source-pass--find-match "baz.site.com" "scott" nil) |
| 261 | (should (equal (auth-source-pass--find-all-by-entry-name "baz.site.com" "scott") | 328 | '(("secret" . "mail/baz.site.com/scott password")))))) |
| 262 | '("mail/baz.site.com/scott"))))) | ||
| 263 | |||
| 264 | (ert-deftest auth-source-pass-entry-is-not-valid-when-unreadable () | ||
| 265 | (cl-letf (((symbol-function 'auth-source-pass--read-entry) | ||
| 266 | (lambda (entry) | ||
| 267 | ;; only foo is a valid entry | ||
| 268 | (if (string-equal entry "foo") | ||
| 269 | "password" | ||
| 270 | nil)))) | ||
| 271 | (should (auth-source-pass--entry-valid-p "foo")) | ||
| 272 | (should-not (auth-source-pass--entry-valid-p "bar")))) | ||
| 273 | 329 | ||
| 274 | (ert-deftest auth-source-pass-can-start-from-auth-source-search () | 330 | (ert-deftest auth-source-pass-can-start-from-auth-source-search () |
| 275 | (auth-source-pass--with-store '(("gitlab.com" ("user" . "someone"))) | 331 | (auth-source-pass--with-store '(("gitlab.com" ("user" . "someone"))) |