branch: externals/llm commit cff5db8ad5185ac623759f737fc2554948b62c6a Author: Andrew Hyatt <ahy...@gmail.com> Commit: Andrew Hyatt <ahy...@gmail.com>
Add unit tests and fix all brokenness detected by them --- llm-fake.el | 32 +++++++++++++++++--------------- llm-test.el | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ llm.el | 2 +- 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/llm-fake.el b/llm-fake.el index f74f868c1f..8a72ccebd1 100644 --- a/llm-fake.el +++ b/llm-fake.el @@ -51,25 +51,27 @@ message cons. If nil, the response will be a simple vector." (with-current-buffer (get-buffer-create (llm-fake-output-to-buffer provider)) (goto-char (point-max)) (insert "\nCall to llm-chat-response\n" (llm-chat-prompt-to-text prompt) "\n"))) - (or (when-let (f (llm-fake-chat-action-func provider)) - (let ((result (funcall f))) - (pcase (type-of result) - ('string (funcall response-callback result)) - ('cons (funcall error-callback (car result) (cdr result))) - (_ (error "Incorrect type found in `chat-action-func': %s" (type-of-result)))))) - (funcall response-callback "Sample response from `llm-chat-response-async'"))) + (if (llm-fake-chat-action-func provider) + (let* ((f (llm-fake-chat-action-func provider)) + (result (funcall f))) + (pcase (type-of result) + ('string (funcall response-callback result)) + ('cons (funcall error-callback (car result) (cdr result))) + (_ (error "Incorrect type found in `chat-action-func': %s" (type-of-result))))) + (funcall response-callback "Sample response from `llm-chat-response-async'"))) -(cl-defmethod llm-embedding-async ((provider llm-openai) string vector-callback error-callback) +(cl-defmethod llm-embedding-async ((provider llm-fake) string vector-callback error-callback) (when (llm-fake-output-to-buffer provider) (with-current-buffer (get-buffer-create (llm-fake-output-to-buffer provider)) (goto-char (point-max)) (insert "\nCall to llm-embedding with text: " string "\n"))) - (or (when-let (f (llm-fake-chat-action-func provider)) - (let ((result (funcall f))) - (pcase (type-of result) - ('vector (funcall vector-callback result)) - ('cons (funcall error-callback (car result) (cdr result))) - (_ (error "Incorrect type found in `chat-embedding-func': %s" (type-of-result)))))) - (funcall response-callback [0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]))) + (if (llm-fake-embedding-action-func provider) + (let* ((f (llm-fake-embedding-action-func provider)) + (result (funcall f))) + (pcase (type-of result) + ('vector (funcall vector-callback result)) + ('cons (funcall error-callback (car result) (cdr result))) + (_ (error "Incorrect type found in `chat-embedding-func': %s" (type-of-result))))) + (funcall vector-callback [0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]))) (provide 'llm-fake) diff --git a/llm-test.el b/llm-test.el new file mode 100644 index 0000000000..5470db0c8a --- /dev/null +++ b/llm-test.el @@ -0,0 +1,57 @@ +;;; llm-test.el --- Unit tests for the llm module -*- lexical-binding: t -*- + +;; Copyright (c) 2023 Andrew Hyatt <ahy...@gmail.com> + +;; Author: Andrew Hyatt <ahy...@gmail.com> +;; SPDX-License-Identifier: GPL-3.0-or-later +;; +;; This program 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. +;; +;; This program 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 tests just the code in the `llm' module, although it uses `llm-fake' as +;; well to do so. All individual providers are probably best tested in the +;; `llm-tester' module. + +;;; Code: + +(require 'llm) +(require 'llm-fake) +(require 'ert) + +(ert-deftest llm-test-embedding () + (should-error (llm-embedding nil "Test")) + (should-error (llm-embedding-async nil "Test")) + ;; TODO: Test signals that are not errors, which ert doesn't seem to catch. + (should-error (llm-embedding (make-llm-fake + :embedding-action-func + (lambda () (cons 'error "my message"))) + "Test")) + (should (equal + [0.1 0.2 0.3] + (llm-embedding (make-llm-fake :embedding-action-func (lambda () [0.1 0.2 0.3])) + "Test")))) + +(ert-deftest llm-test-chat () + (should-error (llm-chat-response nil "Test")) + (should-error (llm-chat-response-async nil "Test")) + (should-error (llm-chat-response + (make-llm-fake + :chat-action-func (lambda () (cons 'error "my message"))) + (make-llm-chat-prompt))) + (should (equal + "Response" + (llm-chat-response (make-llm-fake :chat-action-func (lambda () "Response")) + (make-llm-chat-prompt))))) + +;;; llm-test.el ends here diff --git a/llm.el b/llm.el index f83233eaaf..3c18ac8253 100644 --- a/llm.el +++ b/llm.el @@ -115,7 +115,7 @@ ERROR-CALLBACK receives the error response." "Return a vector embedding of STRING from PROVIDER." (llm--run-async-as-sync #'llm-embedding-async provider string)) -(cl-defmethod llm-chat-embedding ((_ (eql nil)) _) +(cl-defmethod llm-embedding ((_ (eql nil)) _) (error "LLM provider was nil. Please set the provider in the application you are using.")) (cl-defgeneric llm-embedding-async (provider string vector-callback error-callback)