;;; srecode/test.el --- SRecode Core Template tests. -*- lexical-binding:t -*- ;; Copyright (C) 2008-2021 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 . ;;; 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