(in-package #:lispsearch/test)

;;;; Tier-2 enrichment: safe .asd parsing (offline), and real version/artifact
;;;; enrichment of a handful of systems (network). (was test/m3-enrich.lisp)

(define-test parse-asd :parent offline
  (let ((m (ls:parse-asd "(defsystem \"x\" :description \"hi there\" :author \"Me\"
                            :license \"MIT\" :depends-on (:a \"b\" (:version \"c\" \"1.0\")))")))
    (is string= "hi there" (getf m :description))
    (is string= "Me" (getf m :author))
    (is string= "MIT" (getf m :license))
    (is equal '("a" "b" "c") (getf m :depends-on) "depends-on normalized"))
  (is string= "BSD" (getf (ls:parse-asd "(defsystem :y :licence \"BSD\")") :license)
      "handles :licence spelling")
  ;; SAFETY: #. must never execute; yields an empty/NIL field, not an error.
  (let ((m (ls:parse-asd "(defsystem \"evil\" :description #.(error \"boom\"))")))
    (true (and (listp m) (null (getf m :description)))
          "never evaluates #. (read-eval off)"))
  (false (ls:parse-asd "}{ not lisp") "returns empty plist on garbage"))

(define-test system-versions :parent network
  (multiple-value-bind (tags latest) (ls:system-versions "cl-ppcre")
    (true (and (listp tags) (member "latest" tags :test #'string=)) "returns tags")
    (true (and latest (not (string= latest "latest"))) "latest is a dated tag")))

(define-test enrichment :parent network
  (with-fresh-db (db)
    (dolist (n '("cl-html5-parser" "plump" "cl-ppcre" "drakma")) (ls:upsert-name db n n))
    (is = 4 (ls:enrich-rows db (ls:pending-rows db)) "enriched all 4 systems")
    (is = 4 (getf (ls:stats db) :enriched) "enriched count in stats = 4")
    (let ((ppcre (ls:get-system db "cl-ppcre"))
          (drak (ls:get-system db "drakma")))
      (true (search "regular expression"
                    (string-downcase (or (getf ppcre :description) "")))
            "cl-ppcre description populated")
      (is string= "BSD" (getf ppcre :license) "cl-ppcre license populated")
      (true (plusp (length (or (getf ppcre :latest) ""))) "cl-ppcre latest is a version")
      (true (search "cl+ssl" (or (getf drak :deps) "")) "drakma deps include cl+ssl")
      (is = 1 (getf drak :enriched) "drakma marked enriched"))
    ;; acceptance: 'html parser' returns the parsers, excludes non-parsers
    (let ((names (mapcar #'first (ls:search-fts db "html parser"))))
      (true (member "cl-html5-parser" names :test #'string=))
      (true (member "plump" names :test #'string=))
      (false (member "cl-ppcre" names :test #'string=) "excludes cl-ppcre")
      (false (member "drakma" names :test #'string=) "excludes drakma"))
    (true (member "cl-ppcre" (mapcar #'first (ls:search-fts db "regular expression"))
                  :test #'string=)
          "'regular expression' -> cl-ppcre")
    (true (member "drakma" (mapcar #'first (ls:search-fts db "http client"))
                  :test #'string=)
          "'http client' -> drakma")
    ;; re-enrich is idempotent (no new rows)
    (ls:enrich-rows db (list (first (sqlite:execute-to-list db
                       "SELECT id,registry_name,system_name FROM system WHERE system_name='plump'"))))
    (is = 4 (getf (ls:stats db) :total) "re-enrich keeps 4 rows")))
