blob: b33deb5505165e6ed6fadfb6b2b97091b6f69bed (
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
106
107
108
109
110
|
;;; test-dwim-shell-config-password-file.el --- Tests for password-file lifetime -*- lexical-binding: t; -*-
;;; Commentary:
;; Covers the password-file helpers in dwim-shell-config: the on-completion
;; cleanup callback factory and the run-with-password-file wrapper. The point
;; of these helpers is that the password temp file is deleted only after the
;; spawned async process exits (success or failure), not when it is launched.
;; The async `dwim-shell-command-on-marked-files' call is stubbed so no external
;; process runs.
;;; Code:
(when noninteractive
(package-initialize))
(require 'ert)
(require 'cl-lib)
(require 'dwim-shell-config)
;; ---------------------------------------------------------------------------
;;; cj/dwim-shell--password-cleanup-callback
;; ---------------------------------------------------------------------------
(ert-deftest test-dwim-password-cleanup-deletes-on-success ()
"Normal: callback deletes the temp file when the process exits cleanly."
(let ((temp (make-temp-file "dwim-pass-test-"))
(pbuf (generate-new-buffer " *test-proc*")))
(unwind-protect
(cl-letf (((symbol-function 'processp) (lambda (_) t))
((symbol-function 'process-exit-status) (lambda (_) 0)))
(funcall (cj/dwim-shell--password-cleanup-callback temp) pbuf 'fake-proc)
(should-not (file-exists-p temp)))
(when (file-exists-p temp) (delete-file temp))
(when (buffer-live-p pbuf) (kill-buffer pbuf)))))
(ert-deftest test-dwim-password-cleanup-deletes-on-error ()
"Error: callback still deletes the temp file when the process exits non-zero."
(let ((temp (make-temp-file "dwim-pass-test-"))
(pbuf (generate-new-buffer " *test-proc*")))
(unwind-protect
(cl-letf (((symbol-function 'processp) (lambda (_) t))
((symbol-function 'process-exit-status) (lambda (_) 1))
((symbol-function 'display-buffer) (lambda (&rest _) nil)))
(funcall (cj/dwim-shell--password-cleanup-callback temp) pbuf 'fake-proc)
(should-not (file-exists-p temp)))
(when (file-exists-p temp) (delete-file temp))
(when (buffer-live-p pbuf) (kill-buffer pbuf)))))
(ert-deftest test-dwim-password-cleanup-missing-file-no-error ()
"Boundary: callback does not error when the temp file is already gone."
(let ((temp (make-temp-file "dwim-pass-test-"))
(pbuf (generate-new-buffer " *test-proc*")))
(delete-file temp)
(unwind-protect
(cl-letf (((symbol-function 'processp) (lambda (_) t))
((symbol-function 'process-exit-status) (lambda (_) 0)))
(funcall (cj/dwim-shell--password-cleanup-callback temp) pbuf 'fake-proc)
(should-not (file-exists-p temp)))
(when (buffer-live-p pbuf) (kill-buffer pbuf)))))
;; ---------------------------------------------------------------------------
;;; cj/dwim-shell--run-with-password-file
;; ---------------------------------------------------------------------------
(ert-deftest test-dwim-run-with-password-file-writes-and-defers-cleanup ()
"Normal: writes a mode-600 temp file, passes :on-completion, keeps the file
alive after a successful launch (the callback owns deletion)."
(let (captured-script captured-keys)
(cl-letf (((symbol-function 'dwim-shell-command-on-marked-files)
(lambda (_buffer-name script &rest keys)
(setq captured-script script
captured-keys keys))))
(cj/dwim-shell--run-with-password-file
"secret-pw" "Test op"
(lambda (temp-file) (format "tool --password-file='%s' '<<f>>'" temp-file))
:utils "tool")
;; the script embeds a real temp path, and that file still exists
(should (string-match "--password-file='\\([^']*\\)'" captured-script))
(let ((temp (match-string 1 captured-script)))
(unwind-protect
(progn
(should (file-exists-p temp))
(should (string= "secret-pw"
(with-temp-buffer (insert-file-contents temp)
(buffer-string))))
(should (eq #o600 (file-modes temp)))
(should (functionp (plist-get captured-keys :on-completion)))
(should (equal "tool" (plist-get captured-keys :utils))))
(when (file-exists-p temp) (delete-file temp)))))))
(ert-deftest test-dwim-run-with-password-file-cleans-up-on-launch-failure ()
"Error: if the async launch throws before the process starts, the temp file
is cleaned up synchronously (no orphaned password file)."
(let (leaked-temp)
(cl-letf (((symbol-function 'dwim-shell-command-on-marked-files)
(lambda (_buffer-name script &rest _keys)
;; capture the temp path the script was built with, then throw
(when (string-match "FILE='\\(.*\\)'" script)
(setq leaked-temp (match-string 1 script)))
(error "simulated launch failure"))))
(should-error
(cj/dwim-shell--run-with-password-file
"secret-pw" "Test op"
(lambda (temp-file) (format "tool FILE='%s'" temp-file))
:utils "tool"))
(should leaked-temp)
(should-not (file-exists-p leaked-temp)))))
(provide 'test-dwim-shell-config-password-file)
;;; test-dwim-shell-config-password-file.el ends here
|