378 lines
12 KiB
EmacsLisp
378 lines
12 KiB
EmacsLisp
;;; srecode-utest-template.el --- SRecode Core Template tests. -*- lexical-binding:t -*-
|
|
|
|
;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
;;
|
|
;; Tests of SRecode template insertion routines and tricks.
|
|
;;
|
|
|
|
|
|
(require 'srecode/map)
|
|
(require 'srecode/insert)
|
|
(require 'srecode/dictionary)
|
|
|
|
|
|
;;; Code:
|
|
|
|
;;; MAP DUMP TESTING
|
|
(defun srecode-utest-map-reset ()
|
|
"Reset, then dump the map of SRecoder templates.
|
|
Probably should be called `describe-srecode-maps'."
|
|
(interactive)
|
|
(message "SRecode Template Path: %S" srecode-map-load-path)
|
|
;; Interactive call allows us to dump.
|
|
(call-interactively 'srecode-get-maps)
|
|
(switch-to-buffer "*SRECODE MAP*")
|
|
(message (buffer-string))
|
|
)
|
|
|
|
;;; OUTPUT TESTING
|
|
;;
|
|
(defclass srecode-utest-output ()
|
|
((point :initarg :point
|
|
:type string
|
|
:documentation
|
|
"Name of this test point.")
|
|
(name :initarg :name
|
|
:type string
|
|
:documentation
|
|
"Name of the template tested.")
|
|
(output :initarg :output
|
|
:type string
|
|
:documentation
|
|
"Expected output of the template.")
|
|
(dict-entries :initarg :dict-entries
|
|
:initform nil
|
|
:type list
|
|
:documentation
|
|
"Additional dictionary entries to specify.")
|
|
(pre-fill :initarg :pre-fill
|
|
:type (or null string)
|
|
:initform nil
|
|
:documentation
|
|
"Text to prefill a buffer with.
|
|
Place cursor on the ! and delete it.
|
|
If there is a second !, the put the mark there."))
|
|
"A single template test.")
|
|
|
|
(cl-defmethod srecode-utest-test ((o srecode-utest-output))
|
|
"Perform the insertion and test the output.
|
|
Assumes that the current buffer is the testing buffer.
|
|
Return NIL on success, or a diagnostic on failure."
|
|
(let ((fail nil))
|
|
(catch 'fail-early
|
|
(with-slots (name (output-1 output) dict-entries pre-fill) o
|
|
;; Prepare buffer: erase content and maybe insert pre-fill
|
|
;; content.
|
|
(erase-buffer)
|
|
(insert (or pre-fill ""))
|
|
(goto-char (point-min))
|
|
(let ((start nil))
|
|
(when (re-search-forward "!" nil t)
|
|
(goto-char (match-beginning 0))
|
|
(setq start (point))
|
|
(replace-match ""))
|
|
(when (re-search-forward "!" nil t)
|
|
(push-mark (match-beginning 0) t t)
|
|
(replace-match ""))
|
|
(when start (goto-char start)))
|
|
|
|
;; Find a template, perform an insertion and validate the output.
|
|
(let ((dict (srecode-create-dictionary))
|
|
(temp (or (srecode-template-get-table
|
|
(srecode-table) name "test" 'tests)
|
|
(progn
|
|
(srecode-map-update-map)
|
|
(srecode-template-get-table
|
|
(srecode-table) name "test" 'tests))
|
|
(progn
|
|
(setq fail (format "Test template \"%s\" for `%s' not loaded!"
|
|
name major-mode))
|
|
(throw 'fail-early t)
|
|
)))
|
|
(srecode-handle-region-when-non-active-flag t))
|
|
|
|
;; RESOLVE AND INSERT
|
|
(let ((entry dict-entries))
|
|
(while entry
|
|
(srecode-dictionary-set-value
|
|
dict (nth 0 entry) (nth 1 entry))
|
|
(setq entry (nthcdr 1 entry))))
|
|
|
|
(srecode-insert-fcn temp dict)
|
|
|
|
;; COMPARE THE OUTPUT
|
|
(let ((actual (buffer-substring-no-properties
|
|
(point-min) (point-max))))
|
|
(if (string= output-1 actual)
|
|
nil
|
|
|
|
(goto-char (point-max))
|
|
(insert "\n\n ------------- ^^ actual ^^ ------------\n\n
|
|
------------- vv expected vv ------------\n\n"
|
|
output-1)
|
|
(setq fail
|
|
(list (format "Entry %s failed:" (oref o point))
|
|
(buffer-string))
|
|
)))))
|
|
)
|
|
fail))
|
|
|
|
;;; ARG HANDLER
|
|
;;
|
|
(defun srecode-semantic-handle-:utest (dict)
|
|
"Add macros into the dictionary DICT for unit testing purposes."
|
|
(srecode-dictionary-set-value dict "UTESTVAR1" "ARG HANDLER ONE")
|
|
(srecode-dictionary-set-value dict "UTESTVAR2" "ARG HANDLER TWO")
|
|
)
|
|
|
|
(defun srecode-semantic-handle-:utestwitharg (dict)
|
|
"Add macros into the dictionary DICT based on other vars in DICT."
|
|
(let ((val1 (srecode-dictionary-lookup-name dict "UTWA"))
|
|
(nval1 nil))
|
|
;; If there is a value, mutate it
|
|
(if (and val1 (stringp val1))
|
|
(setq nval1 (upcase val1))
|
|
;; No value, make stuff up
|
|
(setq nval1 "NO VALUE"))
|
|
|
|
(srecode-dictionary-set-value dict "UTESTARGXFORM" nval1))
|
|
|
|
(let ((dicts (srecode-dictionary-lookup-name dict "UTLOOP")))
|
|
(dolist (D dicts)
|
|
;; For each dictionary, lookup NAME, and transform into
|
|
;; something in DICT instead.
|
|
(let ((sval (srecode-dictionary-lookup-name D "NAME")))
|
|
(srecode-dictionary-set-value dict (concat "FOO_" sval) sval)
|
|
)))
|
|
)
|
|
|
|
;;; TEST POINTS
|
|
;;
|
|
(defvar srecode-utest-output-entries
|
|
(list
|
|
(srecode-utest-output
|
|
:point "test1" :name "test"
|
|
:output (concat ";; " (user-full-name) "\n"
|
|
";; " (upcase (user-full-name))) )
|
|
(srecode-utest-output
|
|
:point "subs" :name "subs"
|
|
:output ";; Before Loop
|
|
;; After Loop" )
|
|
(srecode-utest-output
|
|
:point "firstlast" :name "firstlast"
|
|
:output "
|
|
;; << -- FIRST
|
|
;; I'm First
|
|
;; I'm Not Last
|
|
;; -- >>
|
|
|
|
;; << -- MIDDLE
|
|
;; I'm Not First
|
|
;; I'm Not Last
|
|
;; -- >>
|
|
|
|
;; << -- LAST
|
|
;; I'm Not First
|
|
;; I'm Last
|
|
;; -- >>
|
|
" )
|
|
(srecode-utest-output
|
|
:point "gapsomething" :name "gapsomething"
|
|
:output ";; First Line
|
|
### ALL ALONE ON A LINE ###
|
|
;;Second Line"
|
|
:pre-fill ";; First Line
|
|
!;;Second Line")
|
|
(srecode-utest-output
|
|
:point "wrapsomething" :name "wrapsomething"
|
|
:output ";; Put this line in front:
|
|
;; First Line
|
|
;; Put this line at the end:"
|
|
:pre-fill "!;; First Line
|
|
!")
|
|
(srecode-utest-output
|
|
:point "inlinetext" :name "inlinetext"
|
|
:output ";; A big long comment XX*In the middle*XX with cursor in middle"
|
|
:pre-fill ";; A big long comment XX!XX with cursor in middle")
|
|
|
|
(srecode-utest-output
|
|
:point "wrapinclude-basic" :name "wrapinclude-basic"
|
|
:output ";; An includable we could use.
|
|
;; \n;; Text after a point inserter."
|
|
)
|
|
(srecode-utest-output
|
|
:point "wrapinclude-basic2" :name "wrapinclude-basic"
|
|
:output ";; An includable MOOSE we could use.
|
|
;; \n;; Text after a point inserter."
|
|
:dict-entries '("COMMENT" "MOOSE")
|
|
)
|
|
(srecode-utest-output
|
|
:point "wrapinclude-around" :name "wrapinclude-around"
|
|
:output ";; An includable we could use.
|
|
;; [VAR]Intermediate Comments
|
|
;; Text after a point inserter."
|
|
)
|
|
(srecode-utest-output
|
|
:point "wrapinclude-around1" :name "wrapinclude-around"
|
|
:output ";; An includable PENGUIN we could use.
|
|
;; [VAR]Intermediate Comments
|
|
;; Text after a point inserter."
|
|
:dict-entries '("COMMENT" "PENGUIN")
|
|
)
|
|
(srecode-utest-output
|
|
:point "complex-subdict" :name "complex-subdict"
|
|
:output ";; I have a cow and a dog.")
|
|
(srecode-utest-output
|
|
:point "wrap-new-template" :name "wrap-new-template"
|
|
:output "template newtemplate
|
|
\"A nice doc string goes here.\"
|
|
----
|
|
Random text in the new template
|
|
----
|
|
bind \"a\""
|
|
:dict-entries '( "NAME" "newtemplate" "KEY" "a" )
|
|
)
|
|
(srecode-utest-output
|
|
:point "column-data" :name "column-data"
|
|
:output "Table of Values:
|
|
Left Justified | Right Justified
|
|
FIRST | FIRST
|
|
VERY VERY LONG STRIN | VERY VERY LONG STRIN
|
|
MIDDLE | MIDDLE
|
|
S | S
|
|
LAST | LAST")
|
|
(srecode-utest-output
|
|
:point "custom-arg-handler" :name "custom-arg-handler"
|
|
:output "OUTSIDE SECTION: ARG HANDLER ONE
|
|
INSIDE SECTION: ARG HANDLER ONE")
|
|
(srecode-utest-output
|
|
:point "custom-arg-w-arg none" :name "custom-arg-w-arg"
|
|
:output "Value of xformed UTWA: NO VALUE")
|
|
(srecode-utest-output
|
|
:point "custom-arg-w-arg upcase" :name "custom-arg-w-arg"
|
|
:dict-entries '( "UTWA" "uppercaseme" )
|
|
:output "Value of xformed UTWA: UPPERCASEME")
|
|
(srecode-utest-output
|
|
:point "custom-arg-w-subdict" :name "custom-arg-w-subdict"
|
|
:output "All items here: item1 item2 item3")
|
|
|
|
;; Test cases for new "section ... end" dictionary syntax
|
|
(srecode-utest-output
|
|
:point "nested-dictionary-syntax-flat"
|
|
:name "nested-dictionary-syntax-flat"
|
|
:output "sub item1")
|
|
(srecode-utest-output
|
|
:point "nested-dictionary-syntax-nesting"
|
|
:name "nested-dictionary-syntax-nesting"
|
|
:output "item11-item11-item21-item31 item21-item11-item21-item31 item31-item311-item321 ")
|
|
(srecode-utest-output
|
|
:point "nested-dictionary-syntax-mixed"
|
|
:name "nested-dictionary-syntax-mixed"
|
|
:output "item1 item2"))
|
|
"Test point entries for the template output tests.")
|
|
|
|
;;; Master Harness
|
|
;;
|
|
(defvar srecode-utest-testfile
|
|
(expand-file-name (concat (make-temp-name "srecode-utest-") ".srt") temporary-file-directory)
|
|
"File used to do testing.")
|
|
|
|
(ert-deftest srecode-utest-template-output ()
|
|
"Test various template insertion options."
|
|
(save-excursion
|
|
(let ((testbuff (find-file-noselect srecode-utest-testfile)))
|
|
|
|
(set-buffer testbuff)
|
|
|
|
(srecode-load-tables-for-mode major-mode)
|
|
(srecode-load-tables-for-mode major-mode 'tests)
|
|
|
|
(should (srecode-table major-mode))
|
|
|
|
;; Loop over the output testpoints.
|
|
(dolist (p srecode-utest-output-entries)
|
|
(should-not (srecode-utest-test p)))))
|
|
|
|
(when (file-exists-p srecode-utest-testfile)
|
|
(delete-file srecode-utest-testfile)))
|
|
|
|
;;; Project test
|
|
;;
|
|
;; Test that "project" specification works ok.
|
|
|
|
(ert-deftest srecode-utest-project ()
|
|
"Test that project filtering works."
|
|
(save-excursion
|
|
(let ((testbuff (find-file-noselect srecode-utest-testfile))
|
|
(temp nil))
|
|
|
|
(set-buffer testbuff)
|
|
(erase-buffer)
|
|
|
|
;; Load the basics, and test that we can't find the application templates.
|
|
(srecode-load-tables-for-mode major-mode)
|
|
|
|
(should (srecode-table major-mode))
|
|
|
|
(setq temp (srecode-template-get-table (srecode-table)
|
|
"test-project"
|
|
"test"
|
|
'tests
|
|
))
|
|
(when temp
|
|
(should-not "App Template Loaded when not specified."))
|
|
|
|
;; Load the application templates, and make sure we can find them.
|
|
(srecode-load-tables-for-mode major-mode 'tests)
|
|
|
|
(dolist (table (oref (srecode-table) tables))
|
|
(when (gethash "test" (oref table contexthash))
|
|
(oset table project default-directory)))
|
|
|
|
(setq temp (srecode-template-get-table (srecode-table)
|
|
"test-project"
|
|
"test"
|
|
'tests
|
|
))
|
|
|
|
(when (not temp)
|
|
(should-not "Failed to load app specific template when available."))
|
|
|
|
;; Temporarily change the home of this file. This will make the
|
|
;; project template go out of scope.
|
|
(let ((default-directory (expand-file-name "~/")))
|
|
|
|
(setq temp (srecode-template-get-table (srecode-table)
|
|
"test-project"
|
|
"test"
|
|
'tests
|
|
))
|
|
|
|
(when temp
|
|
(should-not "Project specific template available when in wrong directory."))
|
|
|
|
)))
|
|
(when (file-exists-p srecode-utest-testfile)
|
|
(delete-file srecode-utest-testfile)))
|
|
|
|
|
|
(provide 'cedet/srecode-utest-template)
|
|
;;; srecode-utest-template.el ends here
|