aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/test-prog-c-compile-command.el85
-rw-r--r--tests/test-prog-c-mode-keybindings.el25
-rw-r--r--tests/test-prog-c-mode-settings.el52
3 files changed, 162 insertions, 0 deletions
diff --git a/tests/test-prog-c-compile-command.el b/tests/test-prog-c-compile-command.el
new file mode 100644
index 00000000..59b5f3b6
--- /dev/null
+++ b/tests/test-prog-c-compile-command.el
@@ -0,0 +1,85 @@
+;;; test-prog-c-compile-command.el --- Tests for C compile command setup -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Verifies single-file C compile commands use file paths rather than buffer
+;; names, and quote paths safely for compile.el's shell command.
+
+;;; Code:
+
+(require 'ert)
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'prog-c)
+
+(ert-deftest test-prog-c-single-file-command-normal-path ()
+ "A simple C file should keep the readable historical command shape."
+ (should (equal
+ (cj/c--single-file-compile-command "/tmp/project/main.c")
+ "gcc -Wall -Wextra -g -o /tmp/project/main /tmp/project/main.c")))
+
+(ert-deftest test-prog-c-single-file-command-quotes-spaces ()
+ "C source and output paths with spaces should be shell-escaped."
+ (should (equal
+ (cj/c--single-file-compile-command "/tmp/my project/hello world.c")
+ "gcc -Wall -Wextra -g -o /tmp/my\\ project/hello\\ world /tmp/my\\ project/hello\\ world.c")))
+
+(ert-deftest test-prog-c-single-file-command-quotes-metacharacters ()
+ "Shell metacharacters in C paths should be escaped."
+ (should (equal
+ (cj/c--single-file-compile-command "/tmp/project/weird;name.c")
+ "gcc -Wall -Wextra -g -o /tmp/project/weird\\;name /tmp/project/weird\\;name.c")))
+
+(ert-deftest test-prog-c-single-file-command-errors-without-file ()
+ "Non-file buffers should fail clearly instead of compiling buffer names."
+ (should-error (cj/c--single-file-compile-command nil)
+ :type 'user-error))
+
+(ert-deftest test-prog-c-compile-command-uses-buffer-file-name ()
+ "The fallback compile command should ignore a renamed buffer's display name."
+ (let ((source (expand-file-name "real source.c" temporary-file-directory)))
+ (with-temp-buffer
+ (setq buffer-file-name source)
+ (rename-buffer "renamed display buffer" t)
+ (cl-letf (((symbol-function 'locate-dominating-file)
+ (lambda (&rest _args) nil)))
+ (cj/c-compile-command))
+ (should (equal
+ compile-command
+ (format "gcc -Wall -Wextra -g -o %s %s"
+ (shell-quote-argument
+ (file-name-sans-extension source))
+ (shell-quote-argument source)))))))
+
+(ert-deftest test-prog-c-compile-command-makefile-uses-make ()
+ "Normal: a Makefile dominating the source dir produces a make compile command."
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'locate-dominating-file)
+ (lambda (_dir name)
+ (when (equal name "Makefile") "/tmp/projectroot/"))))
+ (cj/c-compile-command))
+ (should (equal compile-command
+ (format "cd %s && make -k "
+ (shell-quote-argument "/tmp/projectroot/"))))))
+
+(ert-deftest test-prog-c-compile-command-cmake-uses-cmake-build ()
+ "Normal: a CMakeLists.txt dominating the source dir produces a cmake build command."
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'locate-dominating-file)
+ (lambda (_dir name)
+ (when (equal name "CMakeLists.txt") "/tmp/cmakeroot/"))))
+ (cj/c-compile-command))
+ (should (equal compile-command
+ (format "cd %s && cmake --build build "
+ (shell-quote-argument "/tmp/cmakeroot/"))))))
+
+(ert-deftest test-prog-c-compile-command-makefile-path-with-spaces-is-quoted ()
+ "Boundary: a Makefile in a directory with spaces is shell-quoted in the cd target."
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'locate-dominating-file)
+ (lambda (_dir name)
+ (when (equal name "Makefile") "/tmp/my project/"))))
+ (cj/c-compile-command))
+ (should (equal compile-command
+ "cd /tmp/my\\ project/ && make -k "))))
+
+(provide 'test-prog-c-compile-command)
+;;; test-prog-c-compile-command.el ends here
diff --git a/tests/test-prog-c-mode-keybindings.el b/tests/test-prog-c-mode-keybindings.el
new file mode 100644
index 00000000..85b872b0
--- /dev/null
+++ b/tests/test-prog-c-mode-keybindings.el
@@ -0,0 +1,25 @@
+;;; test-prog-c-mode-keybindings.el --- Tests for cj/c-mode-keybindings -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Verifies the C mode hook installs the S-modifier overrides on the
+;; current buffer's local keymap.
+
+;;; Code:
+
+(require 'ert)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'prog-c)
+
+(ert-deftest test-prog-c-mode-keybindings-normal-installs-fkey-overrides ()
+ "Normal: cj/c-mode-keybindings binds S-F5 to cj/disabled and S-F6 to gdb."
+ (with-temp-buffer
+ (use-local-map (make-sparse-keymap))
+ (cj/c-mode-keybindings)
+ (should (eq (lookup-key (current-local-map) (kbd "S-<f5>"))
+ 'cj/disabled))
+ (should (eq (lookup-key (current-local-map) (kbd "S-<f6>"))
+ 'gdb))))
+
+(provide 'test-prog-c-mode-keybindings)
+;;; test-prog-c-mode-keybindings.el ends here
diff --git a/tests/test-prog-c-mode-settings.el b/tests/test-prog-c-mode-settings.el
new file mode 100644
index 00000000..eef2d910
--- /dev/null
+++ b/tests/test-prog-c-mode-settings.el
@@ -0,0 +1,52 @@
+;;; test-prog-c-mode-settings.el --- Tests for cj/c-mode-settings -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Verifies the C mode hook applies the documented buffer-local values and
+;; only calls `lsp-deferred' when both the function and clangd are available.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'prog-c)
+
+(ert-deftest test-prog-c-mode-settings-normal-applies-buffer-locals ()
+ "Normal: cj/c-mode-settings applies the documented buffer-local values."
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'auto-fill-mode) (lambda (&rest _) nil))
+ ((symbol-function 'electric-pair-mode) (lambda (&rest _) nil))
+ ((symbol-function 'lsp-deferred) (lambda (&rest _) nil))
+ ((symbol-function 'executable-find) (lambda (_) nil)))
+ (cj/c-mode-settings))
+ (should (eq indent-tabs-mode nil))
+ (should (= c-basic-offset 4))
+ (should (= tab-width 4))
+ (should (= fill-column 80))
+ (should comment-auto-fill-only-comments)))
+
+(ert-deftest test-prog-c-mode-settings-boundary-lsp-available-deferred ()
+ "Boundary: when lsp-deferred is fbound and clangd is on PATH, lsp-deferred is called."
+ (let ((lsp-calls 0))
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'auto-fill-mode) (lambda (&rest _) nil))
+ ((symbol-function 'electric-pair-mode) (lambda (&rest _) nil))
+ ((symbol-function 'lsp-deferred) (lambda () (cl-incf lsp-calls)))
+ ((symbol-function 'executable-find) (lambda (_) "/usr/bin/clangd")))
+ (cj/c-mode-settings)))
+ (should (= lsp-calls 1))))
+
+(ert-deftest test-prog-c-mode-settings-error-clangd-missing-skips-lsp ()
+ "Error: when clangd is not on PATH, lsp-deferred is NOT called."
+ (let ((lsp-calls 0))
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'auto-fill-mode) (lambda (&rest _) nil))
+ ((symbol-function 'electric-pair-mode) (lambda (&rest _) nil))
+ ((symbol-function 'lsp-deferred) (lambda () (cl-incf lsp-calls)))
+ ((symbol-function 'executable-find) (lambda (_) nil)))
+ (cj/c-mode-settings)))
+ (should (zerop lsp-calls))))
+
+(provide 'test-prog-c-mode-settings)
+;;; test-prog-c-mode-settings.el ends here