aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorJim Porter2022-03-19 12:41:13 -0700
committerEli Zaretskii2022-04-17 10:28:23 +0300
commit6358cbc21a816ac95c2e6e22e087ccd3736874bc (patch)
tree991f8731ca91f51f1c87380132b03b793c42c8ba /test
parentbbb92dde01ec3fc46b24247fb2d181a21dbcc40a (diff)
downloademacs-6358cbc21a816ac95c2e6e22e087ccd3736874bc.tar.gz
emacs-6358cbc21a816ac95c2e6e22e087ccd3736874bc.zip
Add unit tests and documentation for Eshell predicates/modifiers
* lisp/eshell/esh-cmd.el (eshell-eval-argument): New function. * lisp/eshell/esh-util.el (eshell-file-attributes): Pass original value of FILE to 'file-attributes'. * lisp/eshell/em-pred.el (eshell-predicate-alist): Change socket char to '=', since 's' conflicts with setuid. (eshell-modifier-alist): Fix 'E' (eval) modifier by using 'eshell-eval-argument'. Also improve performance of 'O' (reversed sort) modifier. (eshell-modifier-help-string): Fix documentation of global substitution modifier. (eshell-pred-substitute): Fix infinite loop in some global substitutions. (eshell-join-members): Fix joining with implicit " " delimiter. (Bug#54470) * test/lisp/eshell/em-pred-tests.el: New file. * doc/misc/eshell.texi (Argument Predication): New section.
Diffstat (limited to 'test')
-rw-r--r--test/lisp/eshell/em-pred-tests.el521
1 files changed, 521 insertions, 0 deletions
diff --git a/test/lisp/eshell/em-pred-tests.el b/test/lisp/eshell/em-pred-tests.el
new file mode 100644
index 00000000000..74dad9f8b87
--- /dev/null
+++ b/test/lisp/eshell/em-pred-tests.el
@@ -0,0 +1,521 @@
1;;; em-pred-tests.el --- em-pred test suite -*- lexical-binding:t -*-
2
3;; Copyright (C) 2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
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.
11
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.
16
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/>.
19
20;;; Commentary:
21
22;; Tests for Eshell's argument predicates/modifiers.
23
24;;; Code:
25
26(require 'ert)
27(require 'esh-mode)
28(require 'eshell)
29
30(require 'eshell-tests-helpers
31 (expand-file-name "eshell-tests-helpers"
32 (file-name-directory (or load-file-name
33 default-directory))))
34
35(defvar eshell-test-value nil)
36
37(defun eshell-eval-predicate (initial-value predicate)
38 "Evaluate PREDICATE on INITIAL-VALUE, returning the result.
39PREDICATE is an Eshell argument predicate/modifier."
40 (let ((eshell-test-value initial-value))
41 (with-temp-eshell
42 (eshell-insert-command
43 (format "setq eshell-test-value $eshell-test-value(%s)" predicate)))
44 eshell-test-value))
45
46(defun eshell-parse-file-name-attributes (file)
47 "Parse a fake FILE name to determine its attributes.
48Fake file names are file names beginning with \"/fake/\". This
49allows defining file names for fake files with various properties
50to query via predicates. Attributes are written as a
51comma-separate list of ATTR=VALUE pairs as the file's base name,
52like:
53
54 /fake/type=-,modes=0755.el
55
56The following attributes are recognized:
57
58 * \"type\": A single character describing the file type;
59 accepts the same values as the first character of the file
60 modes in `ls -l'.
61 * \"modes\": The file's permission modes, in octal.
62 * \"links\": The number of links to this file.
63 * \"uid\": The UID of the file's owner.
64 * \"gid\": The UID of the file's group.
65 * \"atime\": The time the file was last accessed, in seconds
66 since the UNIX epoch.
67 * \"mtime\": As \"atime\", but for modification time.
68 * \"ctime\": As \"atime\", but for inode change time.
69 * \"size\": The file's size in bytes."
70 (mapcar (lambda (i)
71 (pcase (split-string i "=")
72 (`("modes" ,modes)
73 (cons 'modes (string-to-number modes 8)))
74 (`(,(and (or "links" "uid" "gid" "size") key) ,value)
75 (cons (intern key) (string-to-number value)))
76 (`(,(and (or "atime" "mtime" "ctime") key) ,value)
77 (cons (intern key) (time-convert (string-to-number value))))
78 (`(,key ,value)
79 (cons (intern key) value))
80 (_ (error "invalid format %S" i))))
81 (split-string (file-name-base file) ",")))
82
83(defmacro eshell-partial-let-func (overrides &rest body)
84 "Temporarily bind to FUNCTION-NAMEs and evaluate BODY.
85This is roughly analogous to advising functions, but only does so
86while BODY is executing, and only calls NEW-FUNCTION if its first
87argument is a string beginning with \"/fake/\".
88
89This allows selectively overriding functions to test file
90properties with fake files without altering the functions'
91behavior for real files.
92
93\(fn ((FUNCTION-NAME NEW-FUNCTION) ...) BODY...)"
94 (declare (indent 1))
95 `(cl-letf
96 ,(mapcar
97 (lambda (override)
98 (let ((orig-function (symbol-function (car override))))
99 `((symbol-function #',(car override))
100 (lambda (file &rest rest)
101 (apply
102 (if (and (stringp file) (string-prefix-p "/fake/" file))
103 ,(cadr override)
104 ,orig-function)
105 file rest)))))
106 overrides)
107 ,@body))
108
109(defmacro eshell-with-file-attributes-from-name (&rest body)
110 "Temporarily override file attribute functions and evaluate BODY."
111 (declare (indent 0))
112 `(eshell-partial-let-func
113 ((file-attributes
114 (lambda (file &optional _id-format)
115 (let ((attrs (eshell-parse-file-name-attributes file)))
116 (list (equal (alist-get 'type attrs) "d")
117 (or (alist-get 'links attrs) 1)
118 (or (alist-get 'uid attrs) 0)
119 (or (alist-get 'gid attrs) 0)
120 (or (alist-get 'atime attrs) nil)
121 (or (alist-get 'mtime attrs) nil)
122 (or (alist-get 'ctime attrs) nil)
123 (or (alist-get 'size attrs) 0)
124 (format "%s---------" (or (alist-get 'type attrs) "-"))
125 nil 0 0))))
126 (file-modes
127 (lambda (file _nofollow)
128 (let ((attrs (eshell-parse-file-name-attributes file)))
129 (or (alist-get 'modes attrs) 0))))
130 (file-exists-p #'always)
131 (file-regular-p
132 (lambda (file)
133 (let ((attrs (eshell-parse-file-name-attributes file)))
134 (member (or (alist-get 'type attrs) "-") '("-" "l")))))
135 (file-symlink-p
136 (lambda (file)
137 (let ((attrs (eshell-parse-file-name-attributes file)))
138 (equal (alist-get 'type attrs) "l"))))
139 (file-executable-p
140 (lambda (file)
141 (let ((attrs (eshell-parse-file-name-attributes file)))
142 ;; For simplicity, just return whether the file is
143 ;; world-executable.
144 (= (logand (or (alist-get 'modes attrs) 0) 1) 1)))))
145 ,@body))
146
147;;; Tests:
148
149
150;; Argument predicates
151
152(ert-deftest em-pred-test/predicate-file-types ()
153 "Test file type predicates."
154 (eshell-with-file-attributes-from-name
155 (let ((files (mapcar (lambda (i) (format "/fake/type=%s" i))
156 '("b" "c" "d/" "p" "s" "l" "-"))))
157 (should (equal (eshell-eval-predicate files "%")
158 '("/fake/type=b" "/fake/type=c")))
159 (should (equal (eshell-eval-predicate files "%b") '("/fake/type=b")))
160 (should (equal (eshell-eval-predicate files "%c") '("/fake/type=c")))
161 (should (equal (eshell-eval-predicate files "/") '("/fake/type=d/")))
162 (should (equal (eshell-eval-predicate files ".") '("/fake/type=-")))
163 (should (equal (eshell-eval-predicate files "p") '("/fake/type=p")))
164 (should (equal (eshell-eval-predicate files "=") '("/fake/type=s")))
165 (should (equal (eshell-eval-predicate files "@") '("/fake/type=l"))))))
166
167(ert-deftest em-pred-test/predicate-executable ()
168 "Test that \"*\" matches only regular, non-symlink executable files."
169 (eshell-with-file-attributes-from-name
170 (let ((files '("/fake/modes=0777" "/fake/modes=0666"
171 "/fake/type=d,modes=0777" "/fake/type=l,modes=0777")))
172 (should (equal (eshell-eval-predicate files "*")
173 '("/fake/modes=0777"))))))
174
175(defmacro em-pred-test--file-modes-deftest (name mode-template predicates
176 &optional docstring)
177 "Define NAME as a file-mode test.
178MODE-TEMPLATE is a format string to convert an integer from 0 to
1797 to an octal file mode. PREDICATES is a list of strings for the
180read, write, and execute predicates to query the file's modes."
181 (declare (indent 4) (doc-string 4))
182 `(ert-deftest ,name ()
183 ,docstring
184 (eshell-with-file-attributes-from-name
185 (let ((file-template (concat "/fake/modes=" ,mode-template)))
186 (cl-flet ((make-files (perms)
187 (mapcar (lambda (i) (format file-template i))
188 perms)))
189 (pcase-let ((files (make-files (number-sequence 0 7)))
190 (`(,read ,write ,exec) ,predicates))
191 (should (equal (eshell-eval-predicate files read)
192 (make-files '(4 5 6 7))))
193 (should (equal (eshell-eval-predicate files (concat "^" read))
194 (make-files '(0 1 2 3))))
195 (should (equal (eshell-eval-predicate files write)
196 (make-files '(2 3 6 7))))
197 (should (equal (eshell-eval-predicate files (concat "^" write))
198 (make-files '(0 1 4 5))))
199 (should (equal (eshell-eval-predicate files exec)
200 (make-files '(1 3 5 7))))
201 (should (equal (eshell-eval-predicate files (concat "^" exec))
202 (make-files '(0 2 4 6))))))))))
203
204(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-owner
205 "0%o00" '("r" "w" "x")
206 "Test predicates for file permissions for the owner.")
207
208(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-group
209 "00%o0" '("A" "I" "E")
210 "Test predicates for file permissions for the group.")
211
212(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-world
213 "000%o" '("R" "W" "X")
214 "Test predicates for file permissions for the world.")
215
216(em-pred-test--file-modes-deftest em-pred-test/predicate-file-modes-flags
217 "%o000" '("s" "S" "t")
218 "Test predicates for \"s\" (setuid), \"S\" (setgid), and \"t\" (sticky).")
219
220(ert-deftest em-pred-test/predicate-effective-uid ()
221 "Test that \"U\" matches files owned by the effective UID."
222 (eshell-with-file-attributes-from-name
223 (cl-letf (((symbol-function 'user-uid) (lambda () 1)))
224 (let ((files '("/fake/uid=1" "/fake/uid=2")))
225 (should (equal (eshell-eval-predicate files "U")
226 '("/fake/uid=1")))))))
227
228(ert-deftest em-pred-test/predicate-links ()
229 "Test that \"l\" filters by number of links."
230 (eshell-with-file-attributes-from-name
231 (let ((files '("/fake/links=1" "/fake/links=2" "/fake/links=3")))
232 (should (equal (eshell-eval-predicate files "l1")
233 '("/fake/links=1")))
234 (should (equal (eshell-eval-predicate files "l+1")
235 '("/fake/links=2" "/fake/links=3")))
236 (should (equal (eshell-eval-predicate files "l-3")
237 '("/fake/links=1" "/fake/links=2"))))))
238
239(ert-deftest em-pred-test/predicate-uid ()
240 "Test that \"u\" filters by UID/user name."
241 (eshell-with-file-attributes-from-name
242 (let ((files '("/fake/uid=1" "/fake/uid=2"))
243 (user-names '("root" "one" "two")))
244 (should (equal (eshell-eval-predicate files "u1")
245 '("/fake/uid=1")))
246 (cl-letf (((symbol-function 'eshell-user-id)
247 (lambda (name) (seq-position user-names name))))
248 (should (equal (eshell-eval-predicate files "u'one'")
249 '("/fake/uid=1")))
250 (should (equal (eshell-eval-predicate files "u{one}")
251 '("/fake/uid=1")))))))
252
253(ert-deftest em-pred-test/predicate-gid ()
254 "Test that \"g\" filters by GID/group name."
255 (eshell-with-file-attributes-from-name
256 (let ((files '("/fake/gid=1" "/fake/gid=2"))
257 (group-names '("root" "one" "two")))
258 (should (equal (eshell-eval-predicate files "g1")
259 '("/fake/gid=1")))
260 (cl-letf (((symbol-function 'eshell-group-id)
261 (lambda (name) (seq-position group-names name))))
262 (should (equal (eshell-eval-predicate files "g'one'")
263 '("/fake/gid=1")))
264 (should (equal (eshell-eval-predicate files "g{one}")
265 '("/fake/gid=1")))))))
266
267(defmacro em-pred-test--time-deftest (name file-attribute predicate
268 &optional docstring)
269 "Define NAME as a file-time test.
270FILE-ATTRIBUTE is the file's attribute to set (e.g. \"atime\").
271PREDICATE is the predicate used to query that attribute."
272 (declare (indent 4) (doc-string 4))
273 `(ert-deftest ,name ()
274 ,docstring
275 (eshell-with-file-attributes-from-name
276 (cl-flet ((make-file (time)
277 (format "/fake/%s=%d" ,file-attribute time)))
278 (let* ((now (time-convert nil 'integer))
279 (yesterday (- now 86400))
280 (files (mapcar #'make-file (list now yesterday))))
281 ;; Test comparison against a number of days.
282 (should (equal (eshell-eval-predicate
283 files (concat ,predicate "-1"))
284 (mapcar #'make-file (list now))))
285 (should (equal (eshell-eval-predicate
286 files (concat ,predicate "+1"))
287 (mapcar #'make-file (list yesterday))))
288 (should (equal (eshell-eval-predicate
289 files (concat ,predicate "+2"))
290 nil))
291 ;; Test comparison against a number of hours.
292 (should (equal (eshell-eval-predicate
293 files (concat ,predicate "h-1"))
294 (mapcar #'make-file (list now))))
295 (should (equal (eshell-eval-predicate
296 files (concat ,predicate "h+1"))
297 (mapcar #'make-file (list yesterday))))
298 (should (equal (eshell-eval-predicate
299 files (concat ,predicate "+48"))
300 nil))
301 ;; Test comparison against another file.
302 (should (equal (eshell-eval-predicate
303 files (format "%s-'%s'" ,predicate (make-file now)))
304 nil))
305 (should (equal (eshell-eval-predicate
306 files (format "%s+'%s'" ,predicate (make-file now)))
307 (mapcar #'make-file (list yesterday)))))))))
308
309(em-pred-test--time-deftest em-pred-test/predicate-access-time
310 "atime" "a"
311 "Test that \"a\" filters by access time.")
312
313(em-pred-test--time-deftest em-pred-test/predicate-modification-time
314 "mtime" "m"
315 "Test that \"m\" filters by change time.")
316
317(em-pred-test--time-deftest em-pred-test/predicate-change-time
318 "ctime" "c"
319 "Test that \"c\" filters by change time.")
320
321(ert-deftest em-pred-test/predicate-size ()
322 "Test that \"L\" filters by file size."
323 (eshell-with-file-attributes-from-name
324 (let ((files '("/fake/size=0"
325 ;; 1 and 2 KiB.
326 "/fake/size=1024" "/fake/size=2048"
327 ;; 1 and 2 MiB.
328 "/fake/size=1048576" "/fake/size=2097152")))
329 ;; Size in bytes.
330 (should (equal (eshell-eval-predicate files "L2048")
331 '("/fake/size=2048")))
332 (should (equal (eshell-eval-predicate files "L+2048")
333 '("/fake/size=1048576" "/fake/size=2097152")))
334 (should (equal (eshell-eval-predicate files "L-2048")
335 '("/fake/size=0" "/fake/size=1024")))
336 ;; Size in blocks.
337 (should (equal (eshell-eval-predicate files "Lp4")
338 '("/fake/size=2048")))
339 (should (equal (eshell-eval-predicate files "Lp+4")
340 '("/fake/size=1048576" "/fake/size=2097152")))
341 (should (equal (eshell-eval-predicate files "Lp-4")
342 '("/fake/size=0" "/fake/size=1024")))
343 ;; Size in KiB.
344 (should (equal (eshell-eval-predicate files "Lk2")
345 '("/fake/size=2048")))
346 (should (equal (eshell-eval-predicate files "Lk+2")
347 '("/fake/size=1048576" "/fake/size=2097152")))
348 (should (equal (eshell-eval-predicate files "Lk-2")
349 '("/fake/size=0" "/fake/size=1024")))
350 ;; Size in MiB.
351 (should (equal (eshell-eval-predicate files "LM1")
352 '("/fake/size=1048576")))
353 (should (equal (eshell-eval-predicate files "LM+1")
354 '("/fake/size=2097152")))
355 (should (equal (eshell-eval-predicate files "LM-1")
356 '("/fake/size=0" "/fake/size=1024" "/fake/size=2048"))))))
357
358
359;; Argument modifiers
360
361(ert-deftest em-pred-test/modifier-eval ()
362 "Test that \":E\" re-evaluates the value."
363 (should (equal (eshell-eval-predicate "${echo hi}" ":E") "hi"))
364 (should (equal (eshell-eval-predicate
365 '("${echo hi}" "$(upcase \"bye\")") ":E")
366 '("hi" "BYE"))))
367
368(ert-deftest em-pred-test/modifier-downcase ()
369 "Test that \":L\" downcases values."
370 (should (equal (eshell-eval-predicate "FOO" ":L") "foo"))
371 (should (equal (eshell-eval-predicate '("FOO" "BAR") ":L")
372 '("foo" "bar"))))
373
374(ert-deftest em-pred-test/modifier-upcase ()
375 "Test that \":U\" upcases values."
376 (should (equal (eshell-eval-predicate "foo" ":U") "FOO"))
377 (should (equal (eshell-eval-predicate '("foo" "bar") ":U")
378 '("FOO" "BAR"))))
379
380(ert-deftest em-pred-test/modifier-capitalize ()
381 "Test that \":C\" capitalizes values."
382 (should (equal (eshell-eval-predicate "foo bar" ":C") "Foo Bar"))
383 (should (equal (eshell-eval-predicate '("foo bar" "baz") ":C")
384 '("Foo Bar" "Baz"))))
385
386(ert-deftest em-pred-test/modifier-dirname ()
387 "Test that \":h\" returns the dirname."
388 (should (equal (eshell-eval-predicate "/path/to/file.el" ":h") "/path/to/"))
389 (should (equal (eshell-eval-predicate
390 '("/path/to/file.el" "/other/path/") ":h")
391 '("/path/to/" "/other/path/"))))
392
393(ert-deftest em-pred-test/modifier-basename ()
394 "Test that \":t\" returns the basename."
395 (should (equal (eshell-eval-predicate "/path/to/file.el" ":t") "file.el"))
396 (should (equal (eshell-eval-predicate
397 '("/path/to/file.el" "/other/path/") ":t")
398 '("file.el" ""))))
399
400(ert-deftest em-pred-test/modifier-extension ()
401 "Test that \":e\" returns the extension."
402 (should (equal (eshell-eval-predicate "/path/to/file.el" ":e") "el"))
403 (should (equal (eshell-eval-predicate
404 '("/path/to/file.el" "/other/path/") ":e")
405 '("el" nil))))
406
407(ert-deftest em-pred-test/modifier-sans-extension ()
408 "Test that \":r\" returns the file name san extension."
409 (should (equal (eshell-eval-predicate "/path/to/file.el" ":r")
410 "/path/to/file"))
411 (should (equal (eshell-eval-predicate
412 '("/path/to/file.el" "/other/path/") ":r")
413 '("/path/to/file" "/other/path/"))))
414
415(ert-deftest em-pred-test/modifier-quote ()
416 "Test that \":q\" quotes arguments."
417 (should (equal-including-properties
418 (eshell-eval-predicate '("foo" "bar") ":q")
419 (list (eshell-escape-arg "foo") (eshell-escape-arg "bar")))))
420
421(ert-deftest em-pred-test/modifier-substitute ()
422 "Test that \":s/PAT/REP/\" replaces PAT with REP once."
423 (should (equal (eshell-eval-predicate "bar" ":s/a/*/") "b*r"))
424 (should (equal (eshell-eval-predicate "bar" ":s|a|*|") "b*r"))
425 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":s/[ao]/*/")
426 '("f*o" "b*r" "b*z")))
427 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":s|[ao]|*|")
428 '("f*o" "b*r" "b*z"))))
429
430(ert-deftest em-pred-test/modifier-global-substitute ()
431 "Test that \":s/PAT/REP/\" replaces PAT with REP for all occurrences."
432 (should (equal (eshell-eval-predicate "foo" ":gs/a/*/") "foo"))
433 (should (equal (eshell-eval-predicate "foo" ":gs|a|*|") "foo"))
434 (should (equal (eshell-eval-predicate "bar" ":gs/a/*/") "b*r"))
435 (should (equal (eshell-eval-predicate "bar" ":gs|a|*|") "b*r"))
436 (should (equal (eshell-eval-predicate "foo" ":gs/o/O/") "fOO"))
437 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":gs/[aeiou]/*/")
438 '("f**" "b*r" "b*z")))
439 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":gs|[aeiou]|*|")
440 '("f**" "b*r" "b*z"))))
441
442(ert-deftest em-pred-test/modifier-include ()
443 "Test that \":i/PAT/\" filters elements to include only ones matching PAT."
444 (should (equal (eshell-eval-predicate "foo" ":i/a/") nil))
445 (should (equal (eshell-eval-predicate "foo" ":i|a|") nil))
446 (should (equal (eshell-eval-predicate "bar" ":i/a/") "bar"))
447 (should (equal (eshell-eval-predicate "bar" ":i|a|") "bar"))
448 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":i/a/")
449 '("bar" "baz")))
450 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":i|a|")
451 '("bar" "baz"))))
452
453(ert-deftest em-pred-test/modifier-exclude ()
454 "Test that \":x/PAT/\" filters elements to exclude any matching PAT."
455 (should (equal (eshell-eval-predicate "foo" ":x/a/") "foo"))
456 (should (equal (eshell-eval-predicate "foo" ":x|a|") "foo"))
457 (should (equal (eshell-eval-predicate "bar" ":x/a/") nil))
458 (should (equal (eshell-eval-predicate "bar" ":x|a|") nil))
459 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":x/a/")
460 '("foo")))
461 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":x|a|")
462 '("foo"))))
463
464(ert-deftest em-pred-test/modifier-split ()
465 "Test that \":S\" and \":S/PAT/\" split elements by spaces (or PAT)."
466 (should (equal (eshell-eval-predicate "foo bar baz" ":S")
467 '("foo" "bar" "baz")))
468 (should (equal (eshell-eval-predicate '("foo bar" "baz") ":S")
469 '(("foo" "bar") ("baz"))))
470 (should (equal (eshell-eval-predicate "foo-bar-baz" ":S/-/")
471 '("foo" "bar" "baz")))
472 (should (equal (eshell-eval-predicate '("foo-bar" "baz") ":S/-/")
473 '(("foo" "bar") ("baz")))))
474
475(ert-deftest em-pred-test/modifier-join ()
476 "Test that \":j\" and \":j/DELIM/\" join elements by spaces (or DELIM)."
477 (should (equal (eshell-eval-predicate "foo" ":j") "foo"))
478 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j")
479 "foo bar baz"))
480 (should (equal (eshell-eval-predicate "foo" ":j/-/") "foo"))
481 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j/-/")
482 "foo-bar-baz")))
483
484(ert-deftest em-pred-test/modifier-sort ()
485 "Test that \":o\" sorts elements in lexicographic order."
486 (should (equal (eshell-eval-predicate "foo" ":o") "foo"))
487 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":o")
488 '("bar" "baz" "foo"))))
489
490(ert-deftest em-pred-test/modifier-sort-reverse ()
491 "Test that \":o\" sorts elements in reverse lexicographic order."
492 (should (equal (eshell-eval-predicate "foo" ":O") "foo"))
493 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":O")
494 '("foo" "baz" "bar"))))
495
496(ert-deftest em-pred-test/modifier-unique ()
497 "Test that \":u\" filters out duplicate elements."
498 (should (equal (eshell-eval-predicate "foo" ":u") "foo"))
499 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":u")
500 '("foo" "bar" "baz")))
501 (should (equal (eshell-eval-predicate '("foo" "bar" "baz" "foo") ":u")
502 '("foo" "bar" "baz"))))
503
504(ert-deftest em-pred-test/modifier-reverse ()
505 "Test that \":r\" reverses the order of elements."
506 (should (equal (eshell-eval-predicate "foo" ":R") "foo"))
507 (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":R")
508 '("baz" "bar" "foo"))))
509
510
511;; Combinations
512
513(ert-deftest em-pred-test/combine-predicate-and-modifier ()
514 "Test combination of predicates and modifiers."
515 (eshell-with-file-attributes-from-name
516 (let ((files '("/fake/type=-.el" "/fake/type=-.txt" "/fake/type=s.el"
517 "/fake/subdir/type=-.el")))
518 (should (equal (eshell-eval-predicate files ".:e:u")
519 '("el" "txt"))))))
520
521;; em-pred-tests.el ends here