llm-tools.el

Opinionated tools for use by a (local) LLM
Log | Files | Refs | LICENSE

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))))