diff options
Diffstat (limited to 'test/lisp/progmodes/uniquify-files-test.el')
-rw-r--r-- | test/lisp/progmodes/uniquify-files-test.el | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/test/lisp/progmodes/uniquify-files-test.el b/test/lisp/progmodes/uniquify-files-test.el new file mode 100644 index 00000000000..ad19e6ad188 --- /dev/null +++ b/test/lisp/progmodes/uniquify-files-test.el @@ -0,0 +1,481 @@ +;;; uniquify-files-test.el - Test functions in uniquify-files.el -*- lexical-binding:t no-byte-compile:t -*- +;; +;; Copyright (C) 2017, 2019 Free Software Foundation, Inc. +;; +;; Author: Stephen Leake <stephen_leake@stephe-leake.org> +;; Maintainer: Stephen Leake <stephen_leake@stephe-leake.org> +;; +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: +;;; +;; This is not a complete test of the completion style; the way the +;; completion functions interact with completing-read is not fully +;; tested. The following table gives useful test cases for a manual +;; interactive test (copy it to an org-mode buffer). + +;; See `test-uniquify-file-all-completions-face' below for an +;; explanation of `no-byte-compile'. + +(require 'ert) +(require 'uniquify-files) + +(defconst uft-root + (concat + (file-name-directory (or load-file-name (buffer-file-name))) + ;; We deliberately leave out the trailing '/' here, because users + ;; often do; the code must cope. + "uniquify-files-resources")) + +(defconst uft-alice1 (concat uft-root "/Alice/alice-1")) +(defconst uft-alice2 (concat uft-root "/Alice/alice-2")) +(defconst uft-Alice-alice3 (concat uft-root "/Alice/alice-3")) +(defconst uft-Bob-alice3 (concat uft-root "/Bob/alice-3")) +(defconst uft-bob1 (concat uft-root "/Bob/bob-1")) +(defconst uft-bob2 (concat uft-root "/Bob/bob-2")) + +(defconst uft-path + (list uft-root + (concat uft-root "/Alice") + uft-alice1 + uft-alice2 + uft-Alice-alice3 + (concat uft-root "/Bob") + uft-Bob-alice3 + uft-bob1 + uft-bob2)) + +(defun uft-table () + (apply-partially 'uniq-file-completion-table (uniq-file-uniquify (path-files uft-path)))) + +(ert-deftest test-uniq-file-test-completion () + (let ((table (uft-table)) + (completion-current-style 'uniquify-file)) + (should (equal (test-completion "foo-fi" table) + nil)) + + (should (equal (test-completion "f-fi<dir" table) + nil)) + + (should (equal (test-completion "foo-file1.text<>" table) + t)) + + (should (equal (test-completion "foo-file1.text" table) + nil)) + + (should (equal (test-completion "foo-file1.text<Alice/alice-1/>" table) + t)) + + (should (equal (test-completion "foo-file3.tex" table) ;; partial file name + nil)) + + (should (equal (test-completion "foo-file3.texts2" table) + t)) + + (should (equal (test-completion "bar-file2.text<Alice/alice-" table) + nil)) + )) + +(ert-deftest test-uniq-file-all-completions-noface () + (let ((table (uft-table)) + (completion-current-style 'uniquify-file) + (completion-ignore-case nil)) + (should (equal + (sort (uniq-file-all-completions "" table nil nil) #'string-lessp) + (list + "bar-file1.text<alice-1/>" + "bar-file1.text<alice-2/>" + "bar-file2.text<alice-1/>" + "bar-file2.text<alice-2/>" + "foo-file1.text<>" + "foo-file1.text<Alice/alice-1/>" + "foo-file1.text<Alice/alice-2/>" + "foo-file1.text<Bob/bob-1/>" + "foo-file1.text<Bob/bob-2/>" + "foo-file2.text<Alice/alice-1/>" + "foo-file2.text<Bob/bob-1/>" + "foo-file3.text" + "foo-file3.texts" + "foo-file3.texts2" + "foo-file4.text<Alice/alice-3/>" + "foo-file4.text<Bob/alice-3/>" + "foo-file5.text" + "wisitoken-generate-packrat-test.text" + "wisitoken-syntax_trees-test.text" + "wisitoken-text_io_trace.text" + ))) + + (should (equal + (sort (uniq-file-all-completions "*-fi" table nil nil) #'string-lessp) + (list + "bar-file1.text<alice-1/>" + "bar-file1.text<alice-2/>" + "bar-file2.text<alice-1/>" + "bar-file2.text<alice-2/>" + "foo-file1.text<>" + "foo-file1.text<Alice/alice-1/>" + "foo-file1.text<Alice/alice-2/>" + "foo-file1.text<Bob/bob-1/>" + "foo-file1.text<Bob/bob-2/>" + "foo-file2.text<Alice/alice-1/>" + "foo-file2.text<Bob/bob-1/>" + "foo-file3.text" + "foo-file3.texts" + "foo-file3.texts2" + "foo-file4.text<Alice/alice-3/>" + "foo-file4.text<Bob/alice-3/>" + "foo-file5.text" + ))) + + (should (equal + (sort (uniq-file-all-completions "a" table nil nil) #'string-lessp) + ;; Should _not_ match directory names + nil)) + + (should (equal + (sort (uniq-file-all-completions "b" table nil nil) #'string-lessp) + (list + "bar-file1.text<alice-1/>" + "bar-file1.text<alice-2/>" + "bar-file2.text<alice-1/>" + "bar-file2.text<alice-2/>" + ))) + + (should (equal + (sort (uniq-file-all-completions "foo" table nil nil) #'string-lessp) + (list + "foo-file1.text<>" + "foo-file1.text<Alice/alice-1/>" + "foo-file1.text<Alice/alice-2/>" + "foo-file1.text<Bob/bob-1/>" + "foo-file1.text<Bob/bob-2/>" + "foo-file2.text<Alice/alice-1/>" + "foo-file2.text<Bob/bob-1/>" + "foo-file3.text" + "foo-file3.texts" + "foo-file3.texts2" + "foo-file4.text<Alice/alice-3/>" + "foo-file4.text<Bob/alice-3/>" + "foo-file5.text" + ))) + + (should (equal + (sort (uniq-file-all-completions "f-file2" table nil nil) #'string-lessp) + (list + "foo-file2.text<Alice/alice-1/>" + "foo-file2.text<Bob/bob-1/>" + ))) + + (should (equal + (sort (uniq-file-all-completions "b-fi<" table nil nil) #'string-lessp) + (list + "bar-file1.text<alice-1/>" + "bar-file1.text<alice-2/>" + "bar-file2.text<alice-1/>" + "bar-file2.text<alice-2/>" + ))) + + (should (equal + (sort (uniq-file-all-completions "f-file<" table nil nil) #'string-lessp) + (list + "foo-file1.text<>" + "foo-file1.text<Alice/alice-1/>" + "foo-file1.text<Alice/alice-2/>" + "foo-file1.text<Bob/bob-1/>" + "foo-file1.text<Bob/bob-2/>" + "foo-file2.text<Alice/alice-1/>" + "foo-file2.text<Bob/bob-1/>" + "foo-file3.text" + "foo-file3.texts" + "foo-file3.texts2" + "foo-file4.text<Alice/alice-3/>" + "foo-file4.text<Bob/alice-3/>" + "foo-file5.text" + ))) + + (should (equal + (sort (uniq-file-all-completions "b-fi<a-" table nil nil) #'string-lessp) + (list + "bar-file1.text<alice-1/>" + "bar-file1.text<alice-2/>" + "bar-file2.text<alice-1/>" + "bar-file2.text<alice-2/>" + ))) + + (should (equal + (sort (uniq-file-all-completions "b-fi<a-1" table nil nil) #'string-lessp) + (list "bar-file1.text<alice-1/>" + "bar-file2.text<alice-1/>"))) + + (should (equal (uniq-file-all-completions "f-file1.text<a-1" table nil nil) + (list "foo-file1.text<Alice/alice-1/>"))) + + (should (equal (sort (uniq-file-all-completions "f-file1.text<al" table nil nil) #'string-lessp) + (list + "foo-file1.text<Alice/alice-1/>" + "foo-file1.text<Alice/alice-2/>"))) + + (should (equal (sort (uniq-file-all-completions "f-file4.text<a-3" table nil nil) #'string-lessp) + (list + "foo-file4.text<Alice/alice-3/>" + "foo-file4.text<Bob/alice-3/>"))) + + (should (equal (sort (uniq-file-all-completions "foo-file4.text<Bob" table nil nil) #'string-lessp) + (list + "foo-file4.text<Bob/alice-3/>"))) + + (should (equal (uniq-file-all-completions "f-file5" table nil nil) + (list "foo-file5.text"))) + + (should (equal (uniq-file-all-completions "foo-file1.text<Alice/alice-1/>" table nil nil) + (list "foo-file1.text<Alice/alice-1/>"))) + + (should (equal + (sort (uniq-file-all-completions "b-fi<a>" table nil nil) #'string-lessp) + (list + "bar-file1.text<alice-1/>" + "bar-file1.text<alice-2/>" + "bar-file2.text<alice-1/>" + "bar-file2.text<alice-2/>" + ))) + + (should (equal + (sort (uniq-file-all-completions "foo-file1.text<>" table nil nil) #'string-lessp) + ;; This is complete but not unique, because the directory part matches multiple directories. + (list + "foo-file1.text<>" + "foo-file1.text<Alice/alice-1/>" + "foo-file1.text<Alice/alice-2/>" + "foo-file1.text<Bob/bob-1/>" + "foo-file1.text<Bob/bob-2/>" + ))) + )) + +(defun test-uniq-file-hilit (pos-list string) + "Set 'face text property to 'completions-first-difference at +all positions in POS-LIST in STRING; return new string." + (while pos-list + (let ((pos (pop pos-list))) + (put-text-property pos (1+ pos) 'face 'completions-first-difference string))) + string) + +(ert-deftest test-uniq-file-all-completions-face () + ;; `all-completions' tested above without considering face text + ;; properties; here we test just those properties. Test cases are + ;; the same as above. + ;; + ;; WORKAROUND: byte-compiling this test makes it fail; it appears to be + ;; sharing strings that should not be shared because they have + ;; different text properties. + (let ((table (uft-table)) + (completion-ignore-case nil)) + + (should (equal-including-properties + (sort (uniq-file-all-completions "b" table nil nil) #'string-lessp) + (list + (test-uniq-file-hilit '(8) "bar-file1.text<alice-1/>") + (test-uniq-file-hilit '(8) "bar-file1.text<alice-2/>") + (test-uniq-file-hilit '(8) "bar-file2.text<alice-1/>") + (test-uniq-file-hilit '(8) "bar-file2.text<alice-2/>") + ))) + + (should (equal-including-properties + (sort (uniq-file-all-completions "foo" table nil nil) #'string-lessp) + (list + (test-uniq-file-hilit '(8) "foo-file1.text<>") + (test-uniq-file-hilit '(8) "foo-file1.text<Alice/alice-1/>") + (test-uniq-file-hilit '(8) "foo-file1.text<Alice/alice-2/>") + (test-uniq-file-hilit '(8) "foo-file1.text<Bob/bob-1/>") + (test-uniq-file-hilit '(8) "foo-file1.text<Bob/bob-2/>") + (test-uniq-file-hilit '(8) "foo-file2.text<Alice/alice-1/>") + (test-uniq-file-hilit '(8) "foo-file2.text<Bob/bob-1/>") + (test-uniq-file-hilit '(8) "foo-file3.text") + (test-uniq-file-hilit '(8) "foo-file3.texts") + (test-uniq-file-hilit '(8) "foo-file3.texts2") + (test-uniq-file-hilit '(8) "foo-file4.text<Alice/alice-3/>") + (test-uniq-file-hilit '(8) "foo-file4.text<Bob/alice-3/>") + (test-uniq-file-hilit '(8) "foo-file5.text") + ))) + + (should (equal-including-properties + (sort (uniq-file-all-completions "f-file2" table nil nil) #'string-lessp) + (list + (test-uniq-file-hilit '(15) "foo-file2.text<Alice/alice-1/>") + (test-uniq-file-hilit '(15) "foo-file2.text<Bob/bob-1/>") + ))) + + (should (equal-including-properties + (sort (uniq-file-all-completions "foo-file3.text" table nil nil) #'string-lessp) + (list + (test-uniq-file-hilit '() "foo-file3.text") + (test-uniq-file-hilit '(14) "foo-file3.texts") + (test-uniq-file-hilit '(14) "foo-file3.texts2") + ))) + + ;; Two places for possible completion, with different intervening text + (should (equal-including-properties + (sort (uniq-file-all-completions "wisi-te" table nil 5) #'string-lessp) + (list ;; 0 10 20 30 + (test-uniq-file-hilit '(10 18) "wisitoken-generate-packrat-test.text") + (test-uniq-file-hilit '(10 25) "wisitoken-syntax_trees-test.text") + (test-uniq-file-hilit '(10 12) "wisitoken-text_io_trace.text") + ))) + )) + +(ert-deftest test-uniq-file-try-completion () + (let ((table (uft-table)) + (completion-current-style 'uniquify-file) + (completion-ignore-case nil) + string) + + (setq string "fo") + (should (equal (uniq-file-try-completion string table nil (length string)) + '("foo-file" . 8))) + + (setq string "b") + (should (equal (uniq-file-try-completion string table nil (length string)) + '("bar-file" . 8))) + + (setq string "fo<al") + (should (equal (uniq-file-try-completion string table nil 2) + '("foo-file.text<alice-" . 8))) + (should (equal (uniq-file-try-completion string table nil 5) + '("foo-file<alice-" . 15))) + + (let ((completion-ignore-case t)) + (setq string "fo<al") + (should (equal (uniq-file-try-completion string table nil 2) + '("foo-file.text<alice" . 8))) + (should (equal (uniq-file-try-completion string table nil 5) + '("foo-file<alice" . 14))) + ) + + (setq string "foo-file3") ;; not unique, not valid + (should (equal (uniq-file-try-completion string table nil (length string)) + '("foo-file3.text" . 14))) + + (setq string "f-file1.text<a-1") + ;; Not unique, because "a" accidentally matches "packages" in + ;; uft-root-dir, and "-" covers "/". Also not valid. + (should (equal (uniq-file-try-completion string table nil (length string)) + '("foo-file1.text<Alice/alice-1/>" . 30))) + + (setq string "foo-file1.text") ;; valid but not unique + (should (equal (uniq-file-try-completion string table nil (length string)) + (cons "foo-file1.text<" 15))) + + (setq string "foo-file1<") ;; not valid + (should (equal (uniq-file-try-completion string table nil (length string)) + (cons "foo-file1.text<" 15))) + + (setq string "foo-file1.text<>") ;; valid but not unique + (should (equal (uniq-file-try-completion string table nil (length string)) + (cons "foo-file1.text<>" 15))) + + (setq string "foo-file1.text<Alice/alice-1/>") ;; valid and unique + (should (equal (uniq-file-try-completion string table nil (length string)) + t)) + + (setq string "foo-file3.texts") ;; not unique, valid + (should (equal (uniq-file-try-completion string table nil (length string)) + '("foo-file3.texts" . 15))) + + (setq string "foo-file3.texts2") ;; unique and valid + (should (equal (uniq-file-try-completion string table nil (length string)) + t)) + + (setq string "fil2") ;; misspelled + (should (equal (uniq-file-try-completion string table nil (length string)) + nil)) + + (setq string "b-file2") + (should (equal (uniq-file-try-completion string table nil (length string)) + '("bar-file2.text<alice-" . 21))) + + ;; prev + <tab>; input is prev output + (setq string "bar-file2.text<alice-") + (should (equal (uniq-file-try-completion string table nil (length string)) + '("bar-file2.text<alice-" . 21))) + + ;; prev + <tab>; input is prev output + (setq string "bar-file2.text<alice-") + (should (equal (uniq-file-try-completion string table nil (length string)) + '("bar-file2.text<alice-" . 21))) + + ;; completion-try-completion called from icomplete-completions with + ;; result of all-completions instead of table function. + (setq string "f-file<") + (let ((comps (uniq-file-all-completions string table nil nil))) + (should (equal (uniq-file-try-completion string comps nil (length string)) + (cons "foo-file" 8)))) + )) + +(ert-deftest test-uniq-file-uniquify () + (should (equal (uniq-file-uniquify + '("/Alice/alice1/file1.text" + "/Alice/alice1/file2.text" + "/Alice/alice2/file1.text" + "/Alice/alice2/file3.text" + "/Bob/bob1/file1.text")) + (list + '("file3.text" . "/Alice/alice2/file3.text") + '("file2.text" . "/Alice/alice1/file2.text") + '("file1.text<Bob/bob1/>" . "/Bob/bob1/file1.text") + '("file1.text<Alice/alice2/>" . "/Alice/alice2/file1.text") + '("file1.text<Alice/alice1/>" . "/Alice/alice1/file1.text") + ))) + + (should (equal (uniq-file-uniquify + (list + (concat uft-alice1 "/foo-file1.text") + (concat uft-alice2 "/foo-file1.text") + (concat uft-bob1 "/foo-file1.text") + (concat uft-bob2 "/foo-file1.text") + (concat uft-root "/foo-file1.text") + )) + (list + (cons "foo-file1.text<>" (concat uft-root "/foo-file1.text")) + (cons "foo-file1.text<Bob/bob-2/>" (concat uft-bob2 "/foo-file1.text")) + (cons "foo-file1.text<Bob/bob-1/>" (concat uft-bob1 "/foo-file1.text")) + (cons "foo-file1.text<Alice/alice-2/>" (concat uft-alice2 "/foo-file1.text")) + (cons "foo-file1.text<Alice/alice-1/>" (concat uft-alice1 "/foo-file1.text")) + ))) + + (should (equal (uniq-file-uniquify + (list + (concat uft-alice1 "/bar-file1.c") + (concat uft-alice1 "/bar-file2.c") + (concat uft-alice2 "/bar-file1.c") + (concat uft-alice2 "/bar-file2.c") + (concat uft-bob1 "/foo-file1.c") + (concat uft-bob1 "/foo-file2.c") + (concat uft-bob2 "/foo-file1.c") + (concat uft-bob2 "/foo-file5.c") + )) + (list + (cons "foo-file5.c" (concat uft-bob2 "/foo-file5.c")) + (cons "foo-file2.c" (concat uft-bob1 "/foo-file2.c")) + (cons "foo-file1.c<bob-2/>" (concat uft-bob2 "/foo-file1.c")) + (cons "foo-file1.c<bob-1/>" (concat uft-bob1 "/foo-file1.c")) + (cons "bar-file2.c<alice-2/>" (concat uft-alice2 "/bar-file2.c")) + (cons "bar-file2.c<alice-1/>" (concat uft-alice1 "/bar-file2.c")) + (cons "bar-file1.c<alice-2/>" (concat uft-alice2 "/bar-file1.c")) + (cons "bar-file1.c<alice-1/>" (concat uft-alice1 "/bar-file1.c")) + ))) + ) + +(provide 'uniquify-files-test) +;;; uniquify-files-test.el ends here |