llm-tools-edit-test.el (5721B)
1 ;; -*- lexical-binding: t; -*- 2 (require 'ert) 3 (require 'llm-tools-edit) 4 5 (defmacro llm-tools-edit-test--with-file (content &rest body) 6 "Run BODY with FILE containing CONTENT, then delete FILE." 7 (declare (indent 1)) 8 `(let ((file (make-temp-file "llm-tools-edit-test-" nil nil ,content))) 9 (unwind-protect (progn ,@body) 10 (delete-file file)))) 11 12 (defun llm-tools-edit-test--contents (file) 13 "Return FILE contents without decoding line endings." 14 (with-temp-buffer 15 (insert-file-contents-literally file) 16 (buffer-string))) 17 18 (ert-deftest llm-tools--edit-file-read-test () 19 (llm-tools-edit-test--with-file "alpha\nbeta\n" 20 (should (equal (llm-tools--edit-file-read file) "alpha\nbeta")) 21 (should (equal (llm-tools--edit-file-read file nil nil t) 22 '("alpha" "beta"))))) 23 24 (ert-deftest llm-tools--edit-file-read-range-test () 25 (llm-tools-edit-test--with-file "one\ntwo\nthree\nfour\n" 26 (should (equal (llm-tools--edit-file-read file 2 3) "two\nthree")) 27 (should (equal (llm-tools--edit-file-read file 2 3 t) '("two" "three"))))) 28 29 (ert-deftest llm-tools--edit-file-lines-test () 30 (llm-tools-edit-test--with-file "alpha\nbeta\ngamma\n" 31 (should (equal (llm-tools--edit-file-lines file) '("alpha" "beta" "gamma"))) 32 (should (equal (llm-tools--edit-file-lines file 1 2) '("alpha" "beta"))) 33 (should (equal (llm-tools--edit-file-lines file 2 3) '("beta" "gamma"))) 34 (should (equal (llm-tools--edit-file-lines file 2 2) '("beta"))))) 35 36 (ert-deftest llm-tools--edit-file-lines-empty-file-test () 37 (llm-tools-edit-test--with-file "" 38 (should (equal (llm-tools--edit-file-lines file) '(""))))) 39 40 (ert-deftest llm-tools--edit-apply-replacement-test () 41 (should (equal (llm-tools--edit-apply "hello world\n" "world" "there") 42 "hello there\n")) 43 (should (equal (llm-tools--edit-apply "A\nB\nC\n" "A\nB" "X\nY\nZ") 44 "X\nY\nZ\nC\n"))) 45 46 (ert-deftest llm-tools--edit-apply-insertion-test () 47 (should (equal (llm-tools--edit-apply "A\nB\n" "A\n" "A\nNEW\n") 48 "A\nNEW\nB\n")) 49 (should (equal (llm-tools--edit-apply "A\nB\n" "B\n" "NEW\nB\n") 50 "A\nNEW\nB\n")) 51 (should (equal (llm-tools--edit-apply "A\nB\n" "B\n" "B\nLAST\n") 52 "A\nB\nLAST\n"))) 53 54 (ert-deftest llm-tools--edit-apply-deletion-test () 55 (should (equal (llm-tools--edit-apply "A\nB\nC\n" "B\n" "") "A\nC\n")) 56 (should (equal (llm-tools--edit-apply "A\nB\nC\n" "B" "") "A\n\nC\n"))) 57 58 (ert-deftest llm-tools--edit-apply-replace-all-test () 59 (should-error (llm-tools--edit-apply "cat cat" "cat" "dog")) 60 (should (equal (llm-tools--edit-apply "cat cat" "cat" "dog" t) "dog dog"))) 61 62 (ert-deftest llm-tools--edit-apply-non-overlapping-test () 63 (should (equal (llm-tools--edit-apply "aaa" "aa" "x") "xa")) 64 (should (equal (llm-tools--edit-apply "aaaa" "aa" "x" t) "xx"))) 65 66 (ert-deftest llm-tools--edit-apply-invalid-input-test () 67 (should-error (llm-tools--edit-apply "hello" "" "x")) 68 (should-error (llm-tools--edit-apply "hello" "hello" "hello")) 69 (should-error (llm-tools--edit-apply "hello" "absent" "x")) 70 (should-error (llm-tools--edit-apply "" "absent" "x" t))) 71 72 (ert-deftest llm-tools--edit-apply-exact-match-test () 73 (let ((case-fold-search t)) 74 (should-error (llm-tools--edit-apply "Hello" "hello" "x"))) 75 (should-error (llm-tools--edit-apply "A\n hello\n" "A\n hello\n" "x")) 76 (should-error (llm-tools--edit-apply "hello \n" "hello\n" "x")) 77 (should-error (llm-tools--edit-apply "‘hello’" "'hello'" "x"))) 78 79 (ert-deftest llm-tools--edit-apply-literal-text-test () 80 (should (equal (llm-tools--edit-apply "a.*[b]" ".*[" "\\1\\&$") 81 "a\\1\\&$b]")) 82 (should (equal (llm-tools--edit-apply "HELLO" "HELLO" "lower") "lower")) 83 (should (equal (llm-tools--edit-apply "你好 café" "café" "世界") "你好 世界"))) 84 85 (ert-deftest llm-tools--edit-apply-line-endings-test () 86 (should (equal (llm-tools--edit-apply "A\r\nB\r\n" "A\r\n" "X\r\n") 87 "X\nB\n")) 88 (should (equal (llm-tools--edit-apply "A\rB" "B" "C") "A\rC"))) 89 90 (ert-deftest llm-tools--edit-success-test () 91 (dolist (content '("hello\n" "hello" "hello\r\n")) 92 (llm-tools-edit-test--with-file content 93 (should (equal (llm-tools--edit file "hello" "world") 94 (format "The file %s has been updated successfully." file))) 95 (should (equal (llm-tools-edit-test--contents file) 96 (string-replace "hello" "world" content)))))) 97 98 (ert-deftest llm-tools--edit-replace-all-test () 99 (llm-tools-edit-test--with-file "hello hello\n" 100 (should (equal (llm-tools--edit file "hello" "world" t) 101 (format "The file %s has been updated. All occurrences were successfully replaced." 102 file))) 103 (should (equal (llm-tools-edit-test--contents file) "world world\n")))) 104 105 (ert-deftest llm-tools--edit-failure-preserves-file-test () 106 (llm-tools-edit-test--with-file "hello hello\n" 107 (dolist (args '(("absent" "x") ("hello" "x") ("" "x") ("hello" "hello"))) 108 (should (string-prefix-p "Error:" (apply #'llm-tools--edit file args))) 109 (should (equal (llm-tools-edit-test--contents file) "hello hello\n"))))) 110 111 (ert-deftest llm-tools--edit-invalid-target-test () 112 (let ((directory (make-temp-file "llm-tools-edit-test-" t))) 113 (unwind-protect 114 (let ((missing (expand-file-name "missing" directory))) 115 (should (string-prefix-p "Error:" (llm-tools--edit " " "a" "b"))) 116 (should (string-prefix-p "Error:" (llm-tools--edit directory "a" "b"))) 117 (should (string-prefix-p "Error:" (llm-tools--edit missing "" "new"))) 118 (should-not (file-exists-p missing))) 119 (delete-directory directory))))