Files
passepartout/tests/llm-gateway-tests.lisp

75 lines
3.5 KiB
Common Lisp

(defpackage :org-agent-llm-gateway-tests
(:use :cl :fiveam :org-agent)
(:export #:llm-gateway-suite))
(in-package :org-agent-llm-gateway-tests)
(def-suite llm-gateway-suite :description "Tests for the Unified LLM Gateway.")
(in-suite llm-gateway-suite)
(defun mock-dex-post (expected-json)
"Returns a lambda that can be used to mock dex:post."
(lambda (url &key headers content connect-timeout read-timeout)
(declare (ignore url headers content connect-timeout read-timeout))
expected-json))
(test test-provider-anthropic
"Verify Anthropic request formatting and response parsing."
(let ((old-post (symbol-function 'dex:post))
(mock-response "{\"content\": [{\"text\": \"Anthropic thought\"}]}"))
(unwind-protect
(progn
(setf (symbol-function 'dex:post) (mock-dex-post mock-response))
(setf (uiop:getenv "ANTHROPIC_API_KEY") "test-key")
(let ((res (org-agent::execute-llm-request "prompt" "sys" :provider :anthropic)))
(is (eq (getf res :status) :success))
(is (equal "Anthropic thought" (getf res :content)))))
(setf (symbol-function 'dex:post) old-post))))
(test test-provider-gemini
"Verify Gemini request formatting and response parsing."
(let ((old-post (symbol-function 'dex:post))
(mock-response "{\"candidates\": [{\"parts\": [{\"text\": \"Gemini thought\"}]}]}"))
(unwind-protect
(progn
(setf (symbol-function 'dex:post) (mock-dex-post mock-response))
(setf (uiop:getenv "GEMINI_API_KEY") "test-key")
(let ((res (org-agent::execute-llm-request "prompt" "sys" :provider :gemini-api)))
(is (eq (getf res :status) :success))
(is (equal "Gemini thought" (getf res :content)))))
(setf (symbol-function 'dex:post) old-post))))
(test test-provider-openai-compat
"Verify OpenAI-compatible (Groq, OpenAI, OpenRouter) response parsing."
(let ((old-post (symbol-function 'dex:post))
(mock-response "{\"choices\": [{\"message\": {\"content\": \"OpenAI thought\"}}]}"))
(unwind-protect
(progn
(setf (symbol-function 'dex:post) (mock-dex-post mock-response))
(dolist (p '(:openai :groq :openrouter))
(setf (uiop:getenv (format nil "~a_API_KEY" (string-upcase (string p)))) "test-key")
(let ((res (org-agent::execute-llm-request "prompt" "sys" :provider p)))
(is (eq (getf res :status) :success))
(is (equal "OpenAI thought" (getf res :content))))))
(setf (symbol-function 'dex:post) old-post))))
(test test-provider-ollama
"Verify Ollama response parsing."
(let ((old-post (symbol-function 'dex:post))
(mock-response "{\"response\": \"Ollama thought\"}"))
(unwind-protect
(progn
(setf (symbol-function 'dex:post) (mock-dex-post mock-response))
(let ((res (org-agent::execute-llm-request "prompt" "sys" :provider :ollama)))
(is (eq (getf res :status) :success))
(is (equal "Ollama thought" (getf res :content)))))
(setf (symbol-function 'dex:post) old-post))))
(test test-error-handling-missing-key
"Ensure missing keys return a standardized error plist."
;; Clear environment
(dolist (p '(:anthropic :openai :groq :openrouter :gemini-api))
(setf (uiop:getenv (format nil "~a_API_KEY" (string-upcase (string p)))) ""))
(let ((res (org-agent::execute-llm-request "test" "sys" :provider :openai)))
(is (eq (getf res :status) :error))
(is (search "API Key missing" (getf res :message)))))