aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael R. Mauger2019-02-20 22:13:51 -0500
committerMichael R. Mauger2019-02-20 22:13:51 -0500
commitc124d5323c05a4010db9b2d330575d029936ade1 (patch)
tree9973520a2c520ed0f378690d0996c2b0b3a53e54
parent4d91e6469828d2b934c959de5932ad5a048ddfd5 (diff)
downloademacs-c124d5323c05a4010db9b2d330575d029936ade1.tar.gz
emacs-c124d5323c05a4010db9b2d330575d029936ade1.zip
Correct implementation of `sql-set-product-feature' (Bug#30494).
* lisp.progmodes/sql.el (sql-add-product): Correct argument spec. (sql-set-product-feature): Handle all cases as intended. (sql-get-product-feature): Fetch varaiable value by `eval'. * test/lisp/progmodes/sql-tests.el (sql-test-feature-value-[a-d]): New test variables. (sql-test-product-feature-harness): New test macro. (sql-test-add-product, sql-test-add-existing-product) (sql-test-set-feature, sql-test-set-indirect-feature) (sql-test-set-existing-feature) (sql-test-set-existing-indirect-feature) (sql-test-set-missing-product, sql-test-get-feature) (sql-test-get-indirect-feature, sql-test-get-missing-product) (sql-test-get-missing-feature) (sql-test-get-missing-indirect-feature): New ERT tests
-rw-r--r--lisp/progmodes/sql.el49
-rw-r--r--test/lisp/progmodes/sql-tests.el228
2 files changed, 206 insertions, 71 deletions
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 9bae3d86640..2a42e7f4515 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -2725,7 +2725,7 @@ highlighting rules in SQL mode.")
2725 nil 'require-match 2725 nil 'require-match
2726 init 'sql-product-history init)))) 2726 init 'sql-product-history init))))
2727 2727
2728(defun sql-add-product (product display &rest plist) 2728(defun sql-add-product (product display &optional plist)
2729 "Add support for a database product in `sql-mode'. 2729 "Add support for a database product in `sql-mode'.
2730 2730
2731Add PRODUCT to `sql-product-alist' which enables `sql-mode' to 2731Add PRODUCT to `sql-product-alist' which enables `sql-mode' to
@@ -2782,19 +2782,38 @@ list. See `sql-add-product' to add new products. The FEATURE
2782argument must be a plist keyword accepted by 2782argument must be a plist keyword accepted by
2783`sql-product-alist'." 2783`sql-product-alist'."
2784 2784
2785 (let* ((p (assoc product sql-product-alist)) 2785 (let* ((p (assoc product sql-product-alist)) ;; (PRODUCT :f v ...)
2786 (v (plist-get (cdr p) feature))) 2786 (v (plist-member (cdr p) feature))) ;; (:FEATURE value ...) or null
2787 (if (and p v) 2787
2788 (if (and 2788 (if p
2789 (member feature sql-indirect-features) 2789 (if (member feature sql-indirect-features) ; is indirect
2790 (symbolp v)) 2790 (if v
2791 (set v newvalue) 2791 (if (car (cdr v))
2792 (setcdr p (plist-put (cdr p) feature newvalue))) 2792 (if (symbolp (car (cdr v)))
2793 (progn 2793 ;; Indirect reference
2794 (when (null p) 2794 (set (car (cdr v)) newvalue)
2795 (error "`%s' is not a known product; use `sql-add-product' to add it first." product)) 2795 ;; indirect is not a symbol
2796 (when (null v) 2796 (error "The value of `%s' for `%s' is not a symbol" feature product))
2797 (error "`%s' is not a known feature for `%s'; use `sql-add-product' to add it first." feature product)))))) 2797 ;; keyword present, set the indirect variable name
2798 (if (symbolp newvalue)
2799 (if (cdr v)
2800 (setf (car (cdr v)) newvalue)
2801 (setf (cdr v) (list newvalue)))
2802 (error "The indirect variable of `%s' for `%s' must be a symbol" feature product)))
2803 ;; not present; insert list
2804 (setq v (list feature newvalue))
2805 (setf (cdr (cdr v)) (cdr p))
2806 (setf (cdr p) v))
2807 ;; Not an indirect feature
2808 (if v
2809 (if (cdr v)
2810 (setf (car (cdr v)) newvalue)
2811 (setf (cdr v) (list newvalue)))
2812 ;; no value; insert into the list
2813 (setq v (list feature newvalue))
2814 (setf (cdr (cdr v)) (cdr p))
2815 (setf (cdr p) v)))
2816 (error "`%s' is not a known product; use `sql-add-product' to add it first" product))))
2798 2817
2799(defun sql-get-product-feature (product feature &optional fallback not-indirect) 2818(defun sql-get-product-feature (product feature &optional fallback not-indirect)
2800 "Lookup FEATURE associated with a SQL PRODUCT. 2819 "Lookup FEATURE associated with a SQL PRODUCT.
@@ -2822,7 +2841,7 @@ See `sql-product-alist' for a list of products and supported features."
2822 (member feature sql-indirect-features) 2841 (member feature sql-indirect-features)
2823 (not not-indirect) 2842 (not not-indirect)
2824 (symbolp v)) 2843 (symbolp v))
2825 (symbol-value v) 2844 (eval v)
2826 v)) 2845 v))
2827 (error "`%s' is not a known product; use `sql-add-product' to add it first." product) 2846 (error "`%s' is not a known product; use `sql-add-product' to add it first." product)
2828 nil))) 2847 nil)))
diff --git a/test/lisp/progmodes/sql-tests.el b/test/lisp/progmodes/sql-tests.el
index a68f9319c2f..7a11f762eb0 100644
--- a/test/lisp/progmodes/sql-tests.el
+++ b/test/lisp/progmodes/sql-tests.el
@@ -53,6 +53,8 @@
53 (error "some error")))) 53 (error "some error"))))
54 (should-not (sql-postgres-list-databases)))) 54 (should-not (sql-postgres-list-databases))))
55 55
56;;; Check Connection Password Handling/Wallet
57
56(defvar sql-test-login-params nil) 58(defvar sql-test-login-params nil)
57(defmacro with-sql-test-connect-harness (id login-params connection expected) 59(defmacro with-sql-test-connect-harness (id login-params connection expected)
58 "Set-up and tear-down SQL connect related test. 60 "Set-up and tear-down SQL connect related test.
@@ -62,40 +64,40 @@ LOGIN-PARAMS. Provide the CONNECTION parameters and the EXPECTED
62string of values passed to the comint function for validation." 64string of values passed to the comint function for validation."
63 (declare (indent 2)) 65 (declare (indent 2))
64 `(cl-letf 66 `(cl-letf
65 ((sql-test-login-params ' ,login-params) 67 ((sql-test-login-params ' ,login-params)
66 ((symbol-function 'sql-comint-test) 68 ((symbol-function 'sql-comint-test)
67 (lambda (product options &optional buf-name) 69 (lambda (product options &optional buf-name)
68 (with-current-buffer (get-buffer-create buf-name) 70 (with-current-buffer (get-buffer-create buf-name)
69 (insert (pp-to-string (list product options sql-user sql-password sql-server sql-database)))))) 71 (insert (pp-to-string (list product options sql-user sql-password sql-server sql-database))))))
70 ((symbol-function 'sql-run-test) 72 ((symbol-function 'sql-run-test)
71 (lambda (&optional buffer) 73 (lambda (&optional buffer)
72 (interactive "P") 74 (interactive "P")
73 (sql-product-interactive 'sqltest buffer))) 75 (sql-product-interactive 'sqltest buffer)))
74 (sql-user nil) 76 (sql-user nil)
75 (sql-server nil) 77 (sql-server nil)
76 (sql-database nil) 78 (sql-database nil)
77 (sql-product-alist 79 (sql-product-alist
78 '((ansi) 80 '((ansi)
79 (sqltest 81 (sqltest
80 :name "SqlTest" 82 :name "SqlTest"
81 :sqli-login sql-test-login-params 83 :sqli-login sql-test-login-params
82 :sqli-comint-func sql-comint-test))) 84 :sqli-comint-func sql-comint-test)))
83 (sql-connection-alist 85 (sql-connection-alist
84 '((,(format "test-%s" id) 86 '((,(format "test-%s" id)
85 ,@connection))) 87 ,@connection)))
86 (sql-password-wallet 88 (sql-password-wallet
87 (list 89 (list
88 (make-temp-file 90 (make-temp-file
89 "sql-test-netrc" nil nil 91 "sql-test-netrc" nil nil
90 (mapconcat #'identity 92 (mapconcat #'identity
91 '("machine aMachine user aUserName password \"netrc-A aPassword\"" 93 '("machine aMachine user aUserName password \"netrc-A aPassword\""
92 "machine aServer user aUserName password \"netrc-B aPassword\"" 94 "machine aServer user aUserName password \"netrc-B aPassword\""
93 "machine aMachine server aServer user aUserName password \"netrc-C aPassword\"" 95 "machine aMachine server aServer user aUserName password \"netrc-C aPassword\""
94 "machine aMachine database aDatabase user aUserName password \"netrc-D aPassword\"" 96 "machine aMachine database aDatabase user aUserName password \"netrc-D aPassword\""
95 "machine aDatabase user aUserName password \"netrc-E aPassword\"" 97 "machine aDatabase user aUserName password \"netrc-E aPassword\""
96 "machine aMachine server aServer database aDatabase user aUserName password \"netrc-F aPassword\"" 98 "machine aMachine server aServer database aDatabase user aUserName password \"netrc-F aPassword\""
97 "machine \"aServer/aDatabase\" user aUserName password \"netrc-G aPassword\"" 99 "machine \"aServer/aDatabase\" user aUserName password \"netrc-G aPassword\""
98 ) "\n"))))) 100 ) "\n")))))
99 101
100 (let* ((connection ,(format "test-%s" id)) 102 (let* ((connection ,(format "test-%s" id))
101 (buffername (format "*SQL: ERT TEST <%s>*" connection))) 103 (buffername (format "*SQL: ERT TEST <%s>*" connection)))
@@ -106,53 +108,167 @@ string of values passed to the comint function for validation."
106 (should (string-equal (with-current-buffer buffername (buffer-string)) ,expected)) 108 (should (string-equal (with-current-buffer buffername (buffer-string)) ,expected))
107 (when (get-buffer buffername) 109 (when (get-buffer buffername)
108 (kill-buffer buffername)) 110 (kill-buffer buffername))
109 (delete-file (car sql-password-wallet))))) 111 (delete-file (car sql-password-wallet)))))
110 112
111(ert-deftest sql-test-connect () 113(ert-deftest sql-test-connect ()
112 "Test of basic `sql-connect'." 114 "Test of basic `sql-connect'."
113 (with-sql-test-connect-harness 1 (user password server database) 115 (with-sql-test-connect-harness 1 (user password server database)
114 ((sql-product 'sqltest) 116 ((sql-product 'sqltest)
115 (sql-user "aUserName") 117 (sql-user "aUserName")
116 (sql-password "test-1 aPassword") 118 (sql-password "test-1 aPassword")
117 (sql-server "aServer") 119 (sql-server "aServer")
118 (sql-database "aDatabase")) 120 (sql-database "aDatabase"))
119 "(sqltest nil \"aUserName\" \"test-1 aPassword\" \"aServer\" \"aDatabase\")\n")) 121 "(sqltest nil \"aUserName\" \"test-1 aPassword\" \"aServer\" \"aDatabase\")\n"))
120 122
121(ert-deftest sql-test-connect-password-func () 123(ert-deftest sql-test-connect-password-func ()
122 "Test of password function." 124 "Test of password function."
123 (with-sql-test-connect-harness 2 (user password server database) 125 (with-sql-test-connect-harness 2 (user password server database)
124 ((sql-product 'sqltest) 126 ((sql-product 'sqltest)
125 (sql-user "aUserName") 127 (sql-user "aUserName")
126 (sql-password (lambda () (concat [?t ?e ?s ?t ?- ?2 ?\s 128 (sql-password (lambda () (concat [?t ?e ?s ?t ?- ?2 ?\s
127 ?a ?P ?a ?s ?s ?w ?o ?r ?d]))) 129 ?a ?P ?a ?s ?s ?w ?o ?r ?d])))
128 (sql-server "aServer") 130 (sql-server "aServer")
129 (sql-database "aDatabase")) 131 (sql-database "aDatabase"))
130 "(sqltest nil \"aUserName\" \"test-2 aPassword\" \"aServer\" \"aDatabase\")\n")) 132 "(sqltest nil \"aUserName\" \"test-2 aPassword\" \"aServer\" \"aDatabase\")\n"))
131 133
132(ert-deftest sql-test-connect-wallet-server-database () 134(ert-deftest sql-test-connect-wallet-server-database ()
133 "Test of password function." 135 "Test of password function."
134 (with-sql-test-connect-harness 3 (user password server database) 136 (with-sql-test-connect-harness 3 (user password server database)
135 ((sql-product 'sqltest) 137 ((sql-product 'sqltest)
136 (sql-user "aUserName") 138 (sql-user "aUserName")
137 (sql-server "aServer") 139 (sql-server "aServer")
138 (sql-database "aDatabase")) 140 (sql-database "aDatabase"))
139 "(sqltest nil \"aUserName\" \"netrc-G aPassword\" \"aServer\" \"aDatabase\")\n")) 141 "(sqltest nil \"aUserName\" \"netrc-G aPassword\" \"aServer\" \"aDatabase\")\n"))
140 142
141(ert-deftest sql-test-connect-wallet-database () 143(ert-deftest sql-test-connect-wallet-database ()
142 "Test of password function." 144 "Test of password function."
143 (with-sql-test-connect-harness 4 (user password database) 145 (with-sql-test-connect-harness 4 (user password database)
144 ((sql-product 'sqltest) 146 ((sql-product 'sqltest)
145 (sql-user "aUserName") 147 (sql-user "aUserName")
146 (sql-database "aDatabase")) 148 (sql-database "aDatabase"))
147 "(sqltest nil \"aUserName\" \"netrc-E aPassword\" nil \"aDatabase\")\n")) 149 "(sqltest nil \"aUserName\" \"netrc-E aPassword\" nil \"aDatabase\")\n"))
148 150
149(ert-deftest sql-test-connect-wallet-server () 151(ert-deftest sql-test-connect-wallet-server ()
150 "Test of password function." 152 "Test of password function."
151 (with-sql-test-connect-harness 5 (user password server) 153 (with-sql-test-connect-harness 5 (user password server)
152 ((sql-product 'sqltest) 154 ((sql-product 'sqltest)
153 (sql-user "aUserName") 155 (sql-user "aUserName")
154 (sql-server "aServer")) 156 (sql-server "aServer"))
155 "(sqltest nil \"aUserName\" \"netrc-B aPassword\" \"aServer\" nil)\n")) 157 "(sqltest nil \"aUserName\" \"netrc-B aPassword\" \"aServer\" nil)\n"))
156 158
159;;; Set/Get Product Features
160
161(defvar sql-test-feature-value-a nil "Indirect value A.")
162(defvar sql-test-feature-value-b nil "Indirect value B.")
163(defvar sql-test-feature-value-c nil "Indirect value C.")
164(defvar sql-test-feature-value-d nil "Indirect value D.")
165(defmacro sql-test-product-feature-harness (&rest action)
166 "Set-up and tear-down of testing product/feature API.
167
168Perform ACTION and validate results"
169 (declare (indent 2))
170 `(cl-letf
171 ((sql-product-alist
172 (list (list 'a :X 1 :Y 2 :Z 'sql-test-feature-value-a)
173 (list 'b :X 3 :Z 'sql-test-feature-value-b)
174 (list 'c :Y 6 :Z 'sql-test-feature-value-c)
175 (list 'd :X 7 :Y 8 )))
176 (sql-indirect-features '(:Z :W))
177 (sql-test-feature-value-a "original A")
178 (sql-test-feature-value-b "original B")
179 (sql-test-feature-value-c "original C")
180 (sql-test-feature-value-d "original D"))
181 ,@action))
182
183(ert-deftest sql-test-add-product ()
184 "Add a product"
185
186 (sql-test-product-feature-harness
187 (sql-add-product 'xyz "XyzDb")
188
189 (should (equal (pp-to-string (assoc 'xyz sql-product-alist))
190 "(xyz :name \"XyzDb\")\n"))))
191
192(ert-deftest sql-test-add-existing-product ()
193 "Add a product that already exists."
194
195 (sql-test-product-feature-harness
196 (should-error (sql-add-feature 'a "Aaa"))
197 (should (equal (pp-to-string (assoc 'a sql-product-alist))
198 "(a :X 1 :Y 2 :Z sql-test-feature-value-a)\n"))))
199
200(ert-deftest sql-test-set-feature ()
201 "Add a feature"
202
203 (sql-test-product-feature-harness
204 (sql-set-product-feature 'b :Y 4)
205 (should (equal (pp-to-string (assoc 'b sql-product-alist))
206 "(b :Y 4 :X 3 :Z sql-test-feature-value-b)\n"))))
207
208(ert-deftest sql-test-set-indirect-feature ()
209 "Set a new indirect feature"
210
211 (sql-test-product-feature-harness
212 (sql-set-product-feature 'd :Z 'sql-test-feature-value-d)
213 (should (equal (pp-to-string (assoc 'd sql-product-alist))
214 "(d :Z sql-test-feature-value-d :X 7 :Y 8)\n"))))
215
216(ert-deftest sql-test-set-existing-feature ()
217 "Set an existing feature."
218
219 (sql-test-product-feature-harness
220 (sql-set-product-feature 'b :X 33)
221 (should (equal (pp-to-string (assoc 'b sql-product-alist))
222 "(b :X 33 :Z sql-test-feature-value-b)\n"))))
223
224(ert-deftest sql-test-set-existing-indirect-feature ()
225 "Set an existing indirect feature."
226
227 (sql-test-product-feature-harness
228 (should (equal sql-test-feature-value-b "original B"))
229 (sql-set-product-feature 'b :Z "Hurray!")
230 (should (equal (pp-to-string (assoc 'b sql-product-alist))
231 "(b :X 3 :Z sql-test-feature-value-b)\n")) ;; unchanged
232 (should (equal sql-test-feature-value-b "Hurray!"))))
233
234(ert-deftest sql-test-set-missing-product ()
235 "Add a feature to a missing product."
236
237 (sql-test-product-feature-harness
238 (should-error (sql-set-product-feature 'x :Y 4))
239 (should-not (assoc 'x sql-product-alist))))
240
241(ert-deftest sql-test-get-feature ()
242 "Get a feature value."
243
244 (sql-test-product-feature-harness
245 (should (equal (sql-get-product-feature 'c :Y) 6))))
246
247(ert-deftest sql-test-get-indirect-feature ()
248 "Get a feature indirect value."
249
250 (sql-test-product-feature-harness
251 (should (equal (sql-get-product-feature 'c :Z nil t) 'sql-test-feature-value-c))
252 (should (equal sql-test-feature-value-c "original C"))
253 (should (equal (sql-get-product-feature 'c :Z) "original C"))))
254
255(ert-deftest sql-test-get-missing-product ()
256 "Get a feature value from a missing product."
257
258 (sql-test-product-feature-harness
259 (should-error (sql-get-product-feature 'x :Y))))
260
261(ert-deftest sql-test-get-missing-feature ()
262 "Get a missing feature value."
263
264 (sql-test-product-feature-harness
265 (should-not (sql-get-product-feature 'c :X))))
266
267(ert-deftest sql-test-get-missing-indirect-feature ()
268 "Get a missing indirect feature value."
269
270 (sql-test-product-feature-harness
271 (should-not (sql-get-product-feature 'd :Z))))
272
157(provide 'sql-tests) 273(provide 'sql-tests)
158;;; sql-tests.el ends here 274;;; sql-tests.el ends here