New test files: - test-config.scm (15 tests): find-config directory walking, load-config with explicit/missing/auto-discovery paths, merge-configs override semantics, generate-template pretty-print output validity. - test-engine.scm (40 tests): filter-rules-by-config with enable/disable/combined, severity>=? helper, lint-file with --pass surface (no compile errors leak), severity filtering (info excluded at warning level), rule disabling via config. Fix mode tests: trailing-whitespace fix, comment-semicolons fix (single ; → ;;), no-tabs fix (8-space expansion), tab-stop alignment, blank-lines deletion, fix composition (tabs + trailing whitespace on same line), idempotency (second pass changes nothing), multi-pass convergence (3-way conflict: tabs + trailing + comment on same line converges in 2 passes). Compile-error formatting: no raw ~S/~A format specifiers in error messages, module name present in output. Integration: lint-files with %fix mode applies fixes and returns 0 unfixed count.
100 lines
3.5 KiB
Scheme
100 lines
3.5 KiB
Scheme
;;; Tests for (gulie config) — config loading, auto-discovery, template
|
|
|
|
(use-modules (srfi srfi-64)
|
|
(ice-9 textual-ports)
|
|
(gulie config))
|
|
|
|
(test-begin "config")
|
|
|
|
;;; find-config — walk up directories
|
|
|
|
(test-group "find-config"
|
|
;; Create a temp directory tree with a config in the grandparent
|
|
(let* ((tmp (tmpnam))
|
|
(child (string-append tmp "/a/b/c")))
|
|
(system* "mkdir" "-p" child)
|
|
(call-with-output-file (string-append tmp "/.gulie.sexp")
|
|
(lambda (p) (display "((line-length . 42))" p)))
|
|
|
|
(test-equal "finds config in ancestor"
|
|
(string-append tmp "/.gulie.sexp")
|
|
(find-config child))
|
|
|
|
(test-equal "finds config in same dir"
|
|
(string-append tmp "/.gulie.sexp")
|
|
(find-config tmp))
|
|
|
|
;; No config above /tmp
|
|
(let ((no-config (string-append tmp "/a/b")))
|
|
;; Config is in tmp, so searching from tmp/a/b should still find it
|
|
(test-assert "finds config from intermediate dir"
|
|
(string? (find-config no-config))))
|
|
|
|
;; Clean up
|
|
(system* "rm" "-rf" tmp)))
|
|
|
|
(test-group "find-config-returns-false"
|
|
;; A directory guaranteed to have no .gulie.sexp above it
|
|
(let ((tmp (tmpnam)))
|
|
(system* "mkdir" "-p" tmp)
|
|
(test-equal "returns #f when no config found"
|
|
#f
|
|
(find-config tmp))
|
|
(system* "rm" "-rf" tmp)))
|
|
|
|
;;; load-config — explicit path and auto-discovery
|
|
|
|
(test-group "load-config-explicit-path"
|
|
(let ((tmp (tmpnam)))
|
|
(call-with-output-file tmp
|
|
(lambda (p) (display "((line-length . 99) (indent . 4))" p)))
|
|
(let ((cfg (load-config tmp)))
|
|
(test-equal "reads line-length" 99 (assq-ref cfg 'line-length))
|
|
(test-equal "reads indent" 4 (assq-ref cfg 'indent)))
|
|
(delete-file tmp)))
|
|
|
|
(test-group "load-config-missing-path"
|
|
(test-equal "missing explicit path returns empty"
|
|
'()
|
|
(load-config "/nonexistent/path/.gulie.sexp")))
|
|
|
|
(test-group "load-config-auto-discovery"
|
|
;; When path is #f, load-config should auto-discover
|
|
;; We can't easily test this without controlling CWD, so just
|
|
;; verify it doesn't crash with #f
|
|
(test-assert "does not crash with #f path"
|
|
(list? (load-config #f))))
|
|
|
|
;;; merge-configs
|
|
|
|
(test-group "merge-configs"
|
|
(let ((base '((line-length . 80) (indent . 2) (enable)))
|
|
(override '((line-length . 120) (enable foo bar))))
|
|
(let ((merged (merge-configs base override)))
|
|
(test-equal "override scalar" 120 (assq-ref merged 'line-length))
|
|
(test-equal "base value preserved" 2 (assq-ref merged 'indent))
|
|
(test-equal "override list" '(foo bar) (assq-ref merged 'enable)))))
|
|
|
|
;;; generate-template
|
|
|
|
(test-group "generate-template"
|
|
(let* ((output (call-with-output-string generate-template))
|
|
(lines (string-split output #\newline)))
|
|
(test-assert "starts with comment"
|
|
(string-prefix? ";;;" (car lines)))
|
|
(test-assert "contains multiple lines (pretty-printed)"
|
|
(> (length lines) 5))
|
|
;; Should be valid sexp — skip comment lines, parse the rest
|
|
(let ((sexp-text (call-with-output-string
|
|
(lambda (p)
|
|
(for-each (lambda (line)
|
|
(unless (string-prefix? ";;;" line)
|
|
(display line p)
|
|
(newline p)))
|
|
lines)))))
|
|
(let ((data (call-with-input-string sexp-text read)))
|
|
(test-assert "output is valid alist" (list? data))
|
|
(test-assert "contains line-length" (assq 'line-length data))))))
|
|
|
|
(test-end "config")
|