Fix decoding of directories when "~" includes non-ASCII chars
[emacs.git] / test / src / json-tests.el
blob09067bad8c884ef1e5f5004458157ed26cd297f7
1 ;;; json-tests.el --- unit tests for json.c -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2017-2018 Free Software Foundation, Inc.
5 ;; This file is part of GNU Emacs.
7 ;; GNU Emacs is free software: you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; GNU Emacs is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20 ;;; Commentary:
22 ;; Unit tests for src/json.c.
24 ;;; Code:
26 (require 'cl-lib)
27 (require 'map)
29 (declare-function json-serialize "json.c" (object))
30 (declare-function json-insert "json.c" (object))
31 (declare-function json-parse-string "json.c" (string &rest args))
32 (declare-function json-parse-buffer "json.c" (&rest args))
34 (define-error 'json-tests--error "JSON test error")
36 (ert-deftest json-serialize/roundtrip ()
37 (skip-unless (fboundp 'json-serialize))
38 ;; The noncharacter U+FFFF should be passed through,
39 ;; cf. https://www.unicode.org/faq/private_use.html#noncharacters.
40 (let ((lisp [:null :false t 0 123 -456 3.75 "abc\uFFFFαβγ𝔸𝐁𝖢\"\\"])
41 (json "[null,false,true,0,123,-456,3.75,\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"]"))
42 (should (equal (json-serialize lisp) json))
43 (with-temp-buffer
44 (json-insert lisp)
45 (should (equal (buffer-string) json))
46 (should (eobp)))
47 (should (equal (json-parse-string json) lisp))
48 (with-temp-buffer
49 (insert json)
50 (goto-char 1)
51 (should (equal (json-parse-buffer) lisp))
52 (should (eobp)))))
54 (ert-deftest json-serialize/object ()
55 (skip-unless (fboundp 'json-serialize))
56 (let ((table (make-hash-table :test #'equal)))
57 (puthash "abc" [1 2 t] table)
58 (puthash "def" :null table)
59 (should (equal (json-serialize table)
60 "{\"abc\":[1,2,true],\"def\":null}")))
61 (should (equal (json-serialize '((abc . [1 2 t]) (def . :null)))
62 "{\"abc\":[1,2,true],\"def\":null}"))
63 (should (equal (json-serialize nil) "{}"))
64 (should (equal (json-serialize '((abc))) "{\"abc\":{}}"))
65 (should (equal (json-serialize '((a . 1) (b . 2) (a . 3)))
66 "{\"a\":1,\"b\":2}"))
67 (should-error (json-serialize '(abc)) :type 'wrong-type-argument)
68 (should-error (json-serialize '((a 1))) :type 'wrong-type-argument)
69 (should-error (json-serialize '((1 . 2))) :type 'wrong-type-argument)
70 (should-error (json-serialize '((a . 1) . b)) :type 'wrong-type-argument)
71 (should-error (json-serialize '#1=((a . 1) . #1#)) :type 'circular-list)
72 (should-error (json-serialize '(#1=(a #1#)))))
74 (ert-deftest json-serialize/object-with-duplicate-keys ()
75 (skip-unless (fboundp 'json-serialize))
76 (let ((table (make-hash-table :test #'eq)))
77 (puthash (copy-sequence "abc") [1 2 t] table)
78 (puthash (copy-sequence "abc") :null table)
79 (should (equal (hash-table-count table) 2))
80 (should-error (json-serialize table) :type 'wrong-type-argument)))
82 (ert-deftest json-parse-string/object ()
83 (skip-unless (fboundp 'json-parse-string))
84 (let ((input
85 "{ \"abc\" : [1, 2, true], \"def\" : null, \"abc\" : [9, false] }\n"))
86 (let ((actual (json-parse-string input)))
87 (should (hash-table-p actual))
88 (should (equal (hash-table-count actual) 2))
89 (should (equal (cl-sort (map-pairs actual) #'string< :key #'car)
90 '(("abc" . [9 :false]) ("def" . :null)))))
91 (should (equal (json-parse-string input :object-type 'alist)
92 '((abc . [9 :false]) (def . :null))))))
94 (ert-deftest json-parse-string/string ()
95 (skip-unless (fboundp 'json-parse-string))
96 (should-error (json-parse-string "[\"formfeed\f\"]") :type 'json-parse-error)
97 (should (equal (json-parse-string "[\"foo \\\"bar\\\"\"]") ["foo \"bar\""]))
98 (should (equal (json-parse-string "[\"abcαβγ\"]") ["abcαβγ"]))
99 (should (equal (json-parse-string "[\"\\nasd\\u0444\\u044b\\u0432fgh\\t\"]")
100 ["\nasdфывfgh\t"]))
101 (should (equal (json-parse-string "[\"\\uD834\\uDD1E\"]") ["\U0001D11E"]))
102 (should-error (json-parse-string "foo") :type 'json-parse-error)
103 ;; FIXME: Is this the right behavior?
104 (should (equal (json-parse-string "[\"\u00C4\xC3\x84\"]") ["\u00C4\u00C4"])))
106 (ert-deftest json-serialize/string ()
107 (skip-unless (fboundp 'json-serialize))
108 (should (equal (json-serialize ["foo"]) "[\"foo\"]"))
109 (should (equal (json-serialize ["a\n\fb"]) "[\"a\\n\\fb\"]"))
110 (should (equal (json-serialize ["\nasdфыв\u001f\u007ffgh\t"])
111 "[\"\\nasdфыв\\u001F\u007ffgh\\t\"]"))
112 (should (equal (json-serialize ["a\0b"]) "[\"a\\u0000b\"]"))
113 ;; FIXME: Is this the right behavior?
114 (should (equal (json-serialize ["\u00C4\xC3\x84"]) "[\"\u00C4\u00C4\"]")))
116 (ert-deftest json-serialize/invalid-unicode ()
117 (skip-unless (fboundp 'json-serialize))
118 (should-error (json-serialize ["a\uDBBBb"]) :type 'wrong-type-argument)
119 (should-error (json-serialize ["u\x110000v"]) :type 'wrong-type-argument)
120 (should-error (json-serialize ["u\x3FFFFFv"]) :type 'wrong-type-argument)
121 (should-error (json-serialize ["u\xCCv"]) :type 'wrong-type-argument)
122 (should-error (json-serialize ["u\u00C4\xCCv"]) :type 'wrong-type-argument))
124 (ert-deftest json-parse-string/null ()
125 (skip-unless (fboundp 'json-parse-string))
126 (should-error (json-parse-string "\x00") :type 'wrong-type-argument)
127 ;; FIXME: Reconsider whether this is the right behavior.
128 (should-error (json-parse-string "[a\\u0000b]") :type 'json-parse-error))
130 (ert-deftest json-parse-string/invalid-unicode ()
131 "Some examples from
132 https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt.
133 Test with both unibyte and multibyte strings."
134 (skip-unless (fboundp 'json-parse-string))
135 ;; Invalid UTF-8 code unit sequences.
136 (should-error (json-parse-string "[\"\x80\"]") :type 'json-parse-error)
137 (should-error (json-parse-string "[\"\u00C4\x80\"]") :type 'json-parse-error)
138 (should-error (json-parse-string "[\"\xBF\"]") :type 'json-parse-error)
139 (should-error (json-parse-string "[\"\u00C4\xBF\"]") :type 'json-parse-error)
140 (should-error (json-parse-string "[\"\xFE\"]") :type 'json-parse-error)
141 (should-error (json-parse-string "[\"\u00C4\xFE\"]") :type 'json-parse-error)
142 (should-error (json-parse-string "[\"\xC0\xAF\"]") :type 'json-parse-error)
143 (should-error (json-parse-string "[\"\u00C4\xC0\xAF\"]")
144 :type 'json-parse-error)
145 (should-error (json-parse-string "[\"\u00C4\xC0\x80\"]")
146 :type 'json-parse-error)
147 ;; Surrogates.
148 (should-error (json-parse-string "[\"\uDB7F\"]")
149 :type 'json-parse-error)
150 (should-error (json-parse-string "[\"\xED\xAD\xBF\"]")
151 :type 'json-parse-error)
152 (should-error (json-parse-string "[\"\u00C4\xED\xAD\xBF\"]")
153 :type 'json-parse-error)
154 (should-error (json-parse-string "[\"\uDB7F\uDFFF\"]")
155 :type 'json-parse-error)
156 (should-error (json-parse-string "[\"\xED\xAD\xBF\xED\xBF\xBF\"]")
157 :type 'json-parse-error)
158 (should-error (json-parse-string "[\"\u00C4\xED\xAD\xBF\xED\xBF\xBF\"]")
159 :type 'json-parse-error))
161 (ert-deftest json-parse-string/incomplete ()
162 (skip-unless (fboundp 'json-parse-string))
163 (should-error (json-parse-string "[123") :type 'json-end-of-file))
165 (ert-deftest json-parse-string/trailing ()
166 (skip-unless (fboundp 'json-parse-string))
167 (should-error (json-parse-string "[123] [456]") :type 'json-trailing-content))
169 (ert-deftest json-parse-buffer/incomplete ()
170 (skip-unless (fboundp 'json-parse-buffer))
171 (with-temp-buffer
172 (insert "[123")
173 (goto-char 1)
174 (should-error (json-parse-buffer) :type 'json-end-of-file)
175 (should (bobp))))
177 (ert-deftest json-parse-buffer/trailing ()
178 (skip-unless (fboundp 'json-parse-buffer))
179 (with-temp-buffer
180 (insert "[123] [456]")
181 (goto-char 1)
182 (should (equal (json-parse-buffer) [123]))
183 (should-not (bobp))
184 (should (looking-at-p (rx " [456]" eos)))))
186 (ert-deftest json-insert/signal ()
187 (skip-unless (fboundp 'json-insert))
188 (with-temp-buffer
189 (let ((calls 0))
190 (add-hook 'after-change-functions
191 (lambda (_begin _end _length)
192 (cl-incf calls)
193 (signal 'json-tests--error
194 '("Error in `after-change-functions'")))
195 :local)
196 (should-error
197 (json-insert '((a . "b") (c . 123) (d . [1 2 t :false])))
198 :type 'json-tests--error)
199 (should (equal calls 1)))))
201 (ert-deftest json-insert/throw ()
202 (skip-unless (fboundp 'json-insert))
203 (with-temp-buffer
204 (let ((calls 0))
205 (add-hook 'after-change-functions
206 (lambda (_begin _end _length)
207 (cl-incf calls)
208 (throw 'test-tag 'throw-value))
209 :local)
210 (should-error
211 (catch 'test-tag
212 (json-insert '((a . "b") (c . 123) (d . [1 2 t :false]))))
213 :type 'no-catch)
214 (should (equal calls 1)))))
216 (provide 'json-tests)
217 ;;; json-tests.el ends here