tests: standardize on embedded tests (migrate all from tests/ to lisp/ sources)
Some checks failed
Deploy (Gitea) / deploy (push) Failing after 2s
Some checks failed
Deploy (Gitea) / deploy (push) Failing after 2s
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,6 +9,5 @@ test_input.txt
|
||||
|
||||
# Generated artifacts (source of truth is .org)
|
||||
/skills/*.lisp
|
||||
/tests/*.lisp
|
||||
/tmp/*.lisp
|
||||
*.fasl
|
||||
|
||||
@@ -99,11 +99,8 @@
|
||||
(string= n "security-dispatcher")
|
||||
(string= n "system-model-router")
|
||||
(string= n "system-model-embedding")
|
||||
(string= n "system-model-explorer")
|
||||
(string= n "gateway-tui")
|
||||
(string= n "gateway-tui-model")
|
||||
(string= n "gateway-tui-view")
|
||||
(string= n "gateway-tui-main"))))
|
||||
(string= n "system-model-explorer")
|
||||
(string= n "gateway-tui"))))
|
||||
all-files))
|
||||
(adj (make-hash-table :test 'equal))
|
||||
(name-to-file (make-hash-table :test 'equal))
|
||||
@@ -284,3 +281,29 @@
|
||||
(load-skill-from-lisp file)
|
||||
(load-skill-from-org file)))
|
||||
(log-message "LOADER: Boot Complete."))))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
(defpackage :passepartout-boot-tests
|
||||
(:use :cl :fiveam :passepartout)
|
||||
(:export #:boot-suite))
|
||||
|
||||
(in-package :passepartout-boot-tests)
|
||||
|
||||
(def-suite boot-suite :description "Verification of the Skill Engine loader")
|
||||
(in-suite boot-suite)
|
||||
|
||||
(test test-topological-sort-basic
|
||||
(let ((tmp-dir "/tmp/passepartout-boot-test/"))
|
||||
(uiop:ensure-all-directories-exist (list tmp-dir))
|
||||
(with-open-file (out (merge-pathnames "org-skill-a.org" tmp-dir) :direction :output :if-exists :supersede)
|
||||
(format out "#+DEPENDS_ON: skill-b-id~%"))
|
||||
(with-open-file (out (merge-pathnames "org-skill-b.org" tmp-dir) :direction :output :if-exists :supersede)
|
||||
(format out ":PROPERTIES:~%:ID: skill-b-id~%:END:~%"))
|
||||
(unwind-protect
|
||||
(let ((sorted (passepartout::skill-topological-sort tmp-dir)))
|
||||
(let ((pos-a (position "org-skill-a" sorted :key #'pathname-name :test #'string-equal))
|
||||
(pos-b (position "org-skill-b" sorted :key #'pathname-name :test #'string-equal)))
|
||||
(is (< pos-b pos-a))))
|
||||
(uiop:delete-directory-tree (uiop:ensure-directory-pathname tmp-dir) :validate t))))
|
||||
|
||||
@@ -163,3 +163,24 @@
|
||||
(refresh scr)
|
||||
(sleep 0.03))
|
||||
(disconnect-daemon))))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
(defpackage :passepartout-tui-tests
|
||||
(:use :cl :passepartout)
|
||||
(:export #:tui-suite))
|
||||
|
||||
(in-package :passepartout-tui-tests)
|
||||
|
||||
(fiveam:def-suite tui-suite :description "Verification of the TUI parsing and styling logic")
|
||||
(fiveam:in-suite tui-suite)
|
||||
|
||||
(fiveam:test test-tui-connection-drop
|
||||
"Tier 2 Chaos: Verify that handle-return degrades gracefully when the daemon connection is lost."
|
||||
(let ((passepartout.gateway-tui::*incoming-msgs* nil)
|
||||
(passepartout.gateway-tui::*input-buffer* (make-array 5 :element-type 'character :initial-contents "hello" :fill-pointer 5 :adjustable t))
|
||||
(mock-stream (make-string-output-stream)))
|
||||
(close mock-stream)
|
||||
(passepartout.gateway-tui::handle-return mock-stream)
|
||||
(fiveam:is (member "ERROR: Connection to daemon lost." passepartout.gateway-tui::*incoming-msgs* :test #'string=))))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
(in-package :passepartout)
|
||||
|
||||
(defun lisp-structural-check (code)
|
||||
"Checks if parentheses are balanced and the code is readable."
|
||||
(handler-case
|
||||
@@ -146,3 +148,78 @@
|
||||
(defskill :passepartout-programming-lisp
|
||||
:priority 400
|
||||
:trigger (lambda (ctx) (declare (ignore ctx)) nil))
|
||||
|
||||
(defpackage :passepartout-utils-lisp-tests
|
||||
(:use :cl :fiveam :passepartout)
|
||||
(:export #:utils-lisp-suite))
|
||||
|
||||
(in-package :passepartout-utils-lisp-tests)
|
||||
|
||||
(def-suite utils-lisp-suite
|
||||
:description "Tests for the Lisp Validator structural, syntactic, and semantic gates")
|
||||
|
||||
(in-suite utils-lisp-suite)
|
||||
|
||||
(test structural-balanced
|
||||
(is (eq t (passepartout:lisp-structural-check "(+ 1 2)"))))
|
||||
|
||||
(test structural-unbalanced-open
|
||||
(multiple-value-bind (ok reason) (passepartout:lisp-structural-check "(+ 1 2")
|
||||
(is (null ok))
|
||||
(is (search "Reader Error" reason))))
|
||||
|
||||
(test structural-unbalanced-close
|
||||
(multiple-value-bind (ok reason) (passepartout:lisp-structural-check "+ 1 2)")
|
||||
(is (null ok))
|
||||
(is (search "Reader Error" reason))))
|
||||
|
||||
(test syntactic-valid
|
||||
(is (eq t (passepartout:lisp-syntactic-check "(+ 1 2)"))))
|
||||
|
||||
(test semantic-safe
|
||||
(is (eq t (passepartout:lisp-semantic-check "(+ 1 2)"))))
|
||||
|
||||
(test semantic-blocked-eval
|
||||
(multiple-value-bind (ok reason) (passepartout:lisp-semantic-check "(eval '(+ 1 2))")
|
||||
(is (null ok))
|
||||
(is (search "Unsafe" reason))))
|
||||
|
||||
(test unified-success
|
||||
(let ((result (passepartout:lisp-validate "(+ 1 2)" :strict t)))
|
||||
(is (eq (getf result :status) :success))))
|
||||
|
||||
(test unified-failure
|
||||
(let ((result (passepartout:lisp-validate "(+ 1 2" :strict nil)))
|
||||
(is (eq (getf result :status) :error))))
|
||||
|
||||
(test eval-basic
|
||||
(let ((result (passepartout:lisp-eval "(+ 1 2)")))
|
||||
(is (eq (getf result :status) :success))
|
||||
(is (string= (getf result :result) "3"))))
|
||||
|
||||
(test structural-extract
|
||||
(let* ((code "(defun hello () (print \"hi\")) (defun bye () (print \"bye\"))")
|
||||
(extracted (passepartout:lisp-extract code "hello")))
|
||||
(is (not (null extracted)))
|
||||
(let ((form (read-from-string extracted)))
|
||||
(is (eq (car form) 'DEFUN))
|
||||
(is (eq (second form) 'HELLO)))))
|
||||
|
||||
(test list-definitions
|
||||
(let ((code "(defun foo () t) (defmacro bar () nil) (defparameter *baz* 10)"))
|
||||
(let ((names (passepartout:lisp-list-definitions code)))
|
||||
(is (member 'FOO names))
|
||||
(is (member 'BAR names))
|
||||
(is (member '*BAZ* names)))))
|
||||
|
||||
(test structural-inject
|
||||
(let* ((code "(defun my-fun (x) (print x))")
|
||||
(injected (passepartout:lisp-inject code "my-fun" "(finish-output)")))
|
||||
(let ((form (read-from-string injected)))
|
||||
(is (equal (last form) '((FINISH-OUTPUT)))))))
|
||||
|
||||
(test structural-slurp
|
||||
(let* ((code "(defun work () (step-1))")
|
||||
(slurped (passepartout:lisp-slurp code "work" "(step-2)")))
|
||||
(let ((form (read-from-string slurped)))
|
||||
(is (equal (last form) '((STEP-2)))))))
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
(in-package :passepartout)
|
||||
|
||||
(defun org-filetags-extract (content)
|
||||
"Extracts the list of tags from a #+FILETAGS: line."
|
||||
(let ((lines (uiop:split-string content :separator '(#\Newline))))
|
||||
@@ -242,3 +244,41 @@ AST format: (:TYPE :HEADLINE :properties (:ID ... :TITLE ... :TAGS (...))
|
||||
(defskill :passepartout-programming-org
|
||||
:priority 100
|
||||
:trigger (lambda (ctx) (declare (ignore ctx)) nil))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ignore-errors (ql:quickload :fiveam :silent t)))
|
||||
|
||||
(defpackage :passepartout-utils-org-tests
|
||||
(:use :cl :fiveam :passepartout)
|
||||
(:export #:utils-org-suite))
|
||||
|
||||
(in-package :passepartout-utils-org-tests)
|
||||
|
||||
(def-suite utils-org-suite
|
||||
:description "Tests for Utils Org skill.")
|
||||
|
||||
(in-suite utils-org-suite)
|
||||
|
||||
(test id-generation
|
||||
(let ((id1 (org-id-generate))
|
||||
(id2 (org-id-generate)))
|
||||
(is (plusp (length id1)))
|
||||
(is (not (string= id1 id2)))))
|
||||
|
||||
(test id-format
|
||||
(let ((formatted (org-id-format "abc12345")))
|
||||
(is (search "id:" formatted))))
|
||||
|
||||
(test property-setter
|
||||
(let ((ast (list :type :HEADLINE
|
||||
:properties (list :ID "id:test123" :TITLE "Test")
|
||||
:contents nil)))
|
||||
(org-property-set ast "id:test123" :STATUS "ACTIVE")
|
||||
(is (string= (getf (getf ast :properties) :STATUS) "ACTIVE"))))
|
||||
|
||||
(test todo-setter
|
||||
(let ((ast (list :type :HEADLINE
|
||||
:properties (list :ID "id:todo001" :TITLE "Task")
|
||||
:contents nil)))
|
||||
(org-todo-set ast "id:todo001" "DONE")
|
||||
(is (string= (getf (getf ast :properties) :TODO) "DONE"))))
|
||||
|
||||
@@ -172,6 +172,34 @@
|
||||
(uiop:quit 0)
|
||||
(uiop:quit 1)))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
(defpackage :passepartout-diagnostics-tests
|
||||
(:use :cl :fiveam :passepartout)
|
||||
(:export #:diagnostics-suite))
|
||||
|
||||
(in-package :passepartout-diagnostics-tests)
|
||||
|
||||
(def-suite diagnostics-suite :description "Verification of the System Diagnostics logic")
|
||||
(in-suite diagnostics-suite)
|
||||
|
||||
(test test-diagnostics-dependency-fail
|
||||
"Verify that missing binaries are correctly identified as failures."
|
||||
(let ((passepartout::*diagnostics-binaries* '("non-existent-binary-123")))
|
||||
(is (null (diagnostics-dependencies-check)))))
|
||||
|
||||
(test test-diagnostics-env-fail
|
||||
"Verify that an invalid MEMEX_DIR triggers a critical failure."
|
||||
(let ((old-m (uiop:getenv "MEMEX_DIR"))
|
||||
(old-d (uiop:getenv "PASSEPARTOUT_DATA_DIR")))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setf (uiop:getenv "MEMEX_DIR") "/non/existent/path/999")
|
||||
(is (null (diagnostics-env-check))))
|
||||
(setf (uiop:getenv "MEMEX_DIR") (or old-m ""))
|
||||
(setf (uiop:getenv "PASSEPARTOUT_DATA_DIR") (or old-d "")))))
|
||||
|
||||
(defskill :passepartout-system-diagnostics
|
||||
:priority 100
|
||||
:trigger (lambda (ctx) (eq (getf (getf ctx :payload) :sensor) :heartbeat))
|
||||
|
||||
@@ -67,3 +67,43 @@
|
||||
(:chat . "Casual conversation, Q&A, creative writing. Prefer balanced quality, low latency.\nRecommend: Llama 3.3 70B (strong generalist) or Gemma 4 31B (thinking mode).")
|
||||
(:plan . "Strategic planning, architecture design, complex multi-step reasoning.\nRecommend: Owl Alpha (free, tool use, 1M ctx) or Hermes 3 405B (strongest free reasoning).")
|
||||
(:background . "Heartbeat summaries, delegation responses, tool output filtering. Must be small + fast.\nRecommend: Llama 3.2 3B (131K ctx, fast) or LFM 2.5 1.2B (edge-ready).")))
|
||||
|
||||
;; REPL-verified: 2026-05-04
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ignore-errors (ql:quickload :fiveam :silent t)))
|
||||
|
||||
(defpackage :passepartout-system-model-explorer-tests
|
||||
(:use :cl :passepartout)
|
||||
(:export #:model-explorer-suite))
|
||||
|
||||
(in-package :passepartout-system-model-explorer-tests)
|
||||
|
||||
(fiveam:def-suite model-explorer-suite :description "Tests for the model explorer skill")
|
||||
|
||||
(fiveam:in-suite model-explorer-suite)
|
||||
|
||||
(fiveam:test model-explorer-recommend-slots
|
||||
"model-explorer-recommend should return models for all standard slots"
|
||||
(dolist (slot '(:code :chat :plan :background))
|
||||
(let ((recs (passepartout::model-explorer-recommend slot)))
|
||||
(fiveam:is (listp recs))
|
||||
(fiveam:is (>= (length recs) 1)))))
|
||||
|
||||
(fiveam:test model-explorer-recommend-format
|
||||
"Each recommendation should have :id and :name"
|
||||
(dolist (rec (passepartout::model-explorer-recommend :chat))
|
||||
(fiveam:is (getf rec :id))
|
||||
(fiveam:is (getf rec :name))))
|
||||
|
||||
(fiveam:test model-explorer-recommend-unknown-slot
|
||||
"Unknown slot should return fallback"
|
||||
(let ((recs (passepartout::model-explorer-recommend :unknown)))
|
||||
(fiveam:is (listp recs))
|
||||
(fiveam:is (>= (length recs) 1))))
|
||||
|
||||
(fiveam:test model-explorer-fetch-openrouter-count
|
||||
"OpenRouter API should return at least 300 models"
|
||||
(let ((models (passepartout::model-explorer-fetch :openrouter)))
|
||||
(if models
|
||||
(fiveam:is (>= (length models) 300))
|
||||
(fiveam:skip "API unreachable"))))
|
||||
|
||||
@@ -116,3 +116,20 @@ If API-KEY is nil, reads from environment."
|
||||
(defskill :passepartout-system-model-provider
|
||||
:priority 50
|
||||
:trigger (lambda (ctx) (declare (ignore ctx)) nil))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
(defpackage :passepartout-llm-gateway-tests
|
||||
(:use :cl :passepartout)
|
||||
(:export #:llm-gateway-suite))
|
||||
|
||||
(in-package :passepartout-llm-gateway-tests)
|
||||
|
||||
(fiveam:def-suite llm-gateway-suite :description "Tests for the LLM provider backend")
|
||||
(fiveam:in-suite llm-gateway-suite)
|
||||
|
||||
(fiveam:test test-provider-rejects-bad-keyword
|
||||
"Verify that provider-openai-request returns :error for an unregistered provider."
|
||||
(let ((result (provider-openai-request "hello" "test" :provider :not-a-real-provider)))
|
||||
(fiveam:is (eq (getf result :status) :error))))
|
||||
|
||||
@@ -40,21 +40,7 @@ Components are loaded in sequence (~:serial t~): package first (defines the publ
|
||||
|
||||
** Test System
|
||||
|
||||
The test system loads on top of ~opencortex~ and adds FiveAM (the test framework). Each test file is tangled from a ~:tangle ../tests/...~ block in the parent org file.
|
||||
|
||||
Note: not every harness or skill file has a corresponding test file. Tests exist only for the parts of the system where deterministic verification is most critical — the pipeline stages, the loader, the memory Merkle tree, and the peripheral vision model.
|
||||
|
||||
#+begin_src lisp
|
||||
(defsystem :passepartout/tests
|
||||
:depends-on (:passepartout :fiveam)
|
||||
:components ((:file "tests/programming-org-tests")
|
||||
(:file "tests/programming-lisp-tests")
|
||||
(:file "tests/boot-sequence-tests")
|
||||
(:file "tests/model-explorer-tests")
|
||||
(:file "tests/diagnostics-tests")
|
||||
(:file "tests/tui-tests")
|
||||
(:file "tests/llm-gateway-tests")))
|
||||
#+end_src
|
||||
Tests are embedded directly in each module's source file — see the `* Test Suite` section at the end of each `.org` file. No separate test system is needed.
|
||||
|
||||
** TUI System
|
||||
|
||||
|
||||
@@ -411,7 +411,7 @@ files live after tangling. The org source files live in ~org/~.
|
||||
|
||||
* Test Suite
|
||||
Verifies that the topological sorter correctly orders skills by their ~#+DEPENDS_ON:~ declarations.
|
||||
#+begin_src lisp :tangle ../tests/boot-sequence-tests.lisp
|
||||
#+begin_src lisp
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ Event handlers + daemon I/O + main loop.
|
||||
#+end_src
|
||||
|
||||
* Test Suite
|
||||
#+begin_src lisp :tangle ../tests/tui-tests.lisp
|
||||
#+begin_src lisp
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ The skill has four layers:
|
||||
|
||||
* Implementation
|
||||
|
||||
** Package Context
|
||||
#+begin_src lisp
|
||||
(in-package :passepartout)
|
||||
#+end_src
|
||||
|
||||
** Structural Validation
|
||||
;; REPL-VERIFIED: 2026-05-03T13:00:00
|
||||
#+begin_src lisp
|
||||
@@ -215,7 +220,7 @@ The skill has four layers:
|
||||
|
||||
* Test Suite
|
||||
Tests for the Lisp Validator structural, syntactic, and semantic gates.
|
||||
#+begin_src lisp :tangle ../tests/programming-lisp-tests.lisp
|
||||
#+begin_src lisp
|
||||
(defpackage :passepartout-utils-lisp-tests
|
||||
(:use :cl :fiveam :passepartout)
|
||||
(:export #:utils-lisp-suite))
|
||||
|
||||
@@ -8,6 +8,11 @@ Structural manipulation tools for Org-mode files. This skill handles reading, wr
|
||||
|
||||
* Implementation
|
||||
|
||||
** Package Context
|
||||
#+begin_src lisp
|
||||
(in-package :passepartout)
|
||||
#+end_src
|
||||
|
||||
** Reading Files (with Privacy Filter)
|
||||
;; REPL-VERIFIED: 2026-05-03T13:00:00
|
||||
#+begin_src lisp
|
||||
@@ -331,7 +336,7 @@ AST format: (:TYPE :HEADLINE :properties (:ID ... :TITLE ... :TAGS (...))
|
||||
|
||||
* Test Suite
|
||||
Verification of the structural manipulation for Org-mode files and their AST representation.
|
||||
#+begin_src lisp :tangle ../tests/programming-org-tests.lisp
|
||||
#+begin_src lisp
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ignore-errors (ql:quickload :fiveam :silent t)))
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ The doctor checks all supported LLM providers and detects local Ollama instances
|
||||
|
||||
* Phase D: Verification (Testing)
|
||||
|
||||
#+begin_src lisp :tangle ../tests/diagnostics-tests.lisp
|
||||
#+begin_src lisp
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ Recommended models are curated per task slot — code generation needs different
|
||||
|
||||
* Tests
|
||||
|
||||
#+begin_src lisp :tangle ../tests/model-explorer-tests.lisp
|
||||
#+begin_src lisp
|
||||
;; REPL-verified: 2026-05-04
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ignore-errors (ql:quickload :fiveam :silent t)))
|
||||
|
||||
@@ -163,7 +163,7 @@ If API-KEY is nil, reads from environment."
|
||||
#+end_src
|
||||
|
||||
* Test Suite
|
||||
#+begin_src lisp :tangle ../tests/llm-gateway-tests.lisp
|
||||
#+begin_src lisp
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(ql:quickload :fiveam :silent t))
|
||||
|
||||
|
||||
@@ -16,16 +16,6 @@
|
||||
(:file "lisp/core-loop-act")
|
||||
(:file "lisp/core-loop")))
|
||||
|
||||
(defsystem :passepartout/tests
|
||||
:depends-on (:passepartout :fiveam)
|
||||
:components ((:file "tests/programming-org-tests")
|
||||
(:file "tests/programming-lisp-tests")
|
||||
(:file "tests/boot-sequence-tests")
|
||||
(:file "tests/model-explorer-tests")
|
||||
(:file "tests/diagnostics-tests")
|
||||
(:file "tests/tui-tests")
|
||||
(:file "tests/llm-gateway-tests")))
|
||||
|
||||
(defsystem :passepartout/tui
|
||||
:depends-on (:passepartout :croatoan :usocket :bordeaux-threads)
|
||||
:components ((:file "lisp/gateway-tui")))
|
||||
|
||||
Reference in New Issue
Block a user