Designing a unit-test framework for writing custom tests in CLIPS for CLIPS rules, using a multi-file setup - testing

I'd like to make a unit-test like framework that allows me to write custom tests for individual rules. I'd like each test to be in it's own file, i.e. test_R1.clp would be the test file for rule R1. Each test should be able to load it's own facts file. I've tried many variations of the following, including using a different defmodule for each file. Is what I'm trying to do even possible in CLIPS? If so, what else is needed to make this work?
I'd like to run my tests via:
$CLIPSDOS64.exe -f2 .\test_all.clp
With the current example, the error I get is
[EXPRNPSR3] Missing function declaration for setup-tests.
I've gotten a single test to work correctly using a unique defmodule for each file (i.e. UNITTEST for the testing framework and R1 for the test_R1 file). However, I would still get errors because of the automatic switching between focus statements when files are loaded, or when functions are defined in other files. I've looked at the basic and advanced CLIPS programming guides, but if I've missed something there, please let me know.
Other specific questions:
Since some tests may load facts that overwrite existing facts, how do I prevent getting errors from redefining existing facts? Do I need to do a (clear) in between running each test?
TestingFramework.clp:
;;; File: TestingFramework.clp
(defglobal ?*tests-counter* = 0)
(defglobal ?*all-tests-passed* = TRUE)
(defglobal ?*failed-tests-counter* = 0)
(deftemplate test_to_run
(slot testid)
(slot testname)
(slot testsetupfunc)
(slot testcheckfunc))
(deffunction test-check (?test-name ?test-condition)
(if (eval ?test-condition)
then (printout t "SUCCESS: Test " ?test-name crlf)
(printout test_results_file "SUCCESS: Test " ?test-name crlf)
(return TRUE)
else (printout t "FAILURE: Test " ?test-name crlf)
(printout test_results_file "FAILURE: Test " ?test-name crlf)
(return FALSE)))
(deffunction setup_tests ()
(open "test_summary_results.txt" test_results_file "w"))
(deffunction finish_tests ()
(close test_results_file))
(deffunction add_test (?test-name ?test-setup-func ?test-check-func)
(bind ?*tests-counter* (+ 1 ?*tests-counter*))
(assert (test_to_run (testid ?*tests-counter*)
(testname ?test-name)
(testsetupfunc ?test-setup-func)
(testcheckfunc ?test-check-func))))
(deffunction run_all_tests ()
(printout t "About to run " ?*tests-counter* " test(s):" crlf)
(do-for-all-facts ((?ttr_fact test_to_run)) TRUE
(funcall (fact-slot-value ?ttr_fact testsetupfunc))
(if (funcall (fact-slot-value ?ttr_fact testcheckfunc))
then (printout t " SUCCESS" crlf)
else (printout t " FAILURE" crlf)
(bind ?*failed-tests-counter* (+ 1 ?*failed-tests-counter*))
(bind ?*all-tests-passed* FALSE)))
(if ?*all-tests-passed*
then (printout t "All " ?*tests-counter* " tests passed successfully." crlf)
else (printout t ?*failed-tests-counter* "/" ?*tests-counter* " tests failed." crlf)))
tests\test_R1.clp:
;;; File: test_R1.clp
;;; Tests for Rule 1
(deffunction R1_TEST_1_SETUP ()
(load* "FluidSystem_facts_demo.clp")
(load* "FluidSystem_rules_demo.clp")
(reset))
(deffunction R1_TEST_1 ()
(send [JacketWaterInletTempReading] put-hasValue 35.0)
(send [JacketWaterInletTempReading] put-hasValueDefined DEFINED)
(send [JacketWaterOutletTempReading] put-hasValue 37.0)
(send [JacketWaterOutletTempReading] put-hasValueDefined DEFINED)
(run)
(return (member$ [DissimilarHighTempFlowRate] (send [CounterFlowHeatExchanger] get-hasIssue))))
test_all.clp:
;;; File: test_all.clp
;;; Run tests via:
;;; CLIPSDOS64.exe -f2 .\test_all.clp
(load* "TestingFramework.clp")
(setup-tests)
;;; Test R1
(load* "tests\\test_R1.clp")
(add_test (test_to_run "R1_TEST_1" R1_TEST_1_SETUP R1_TEST_1))
(clear) ;; unsure if this is needed
;;; ... more tests to follow
(run_all_tests)
(finish_tests)

The CLIPS regression tests use a framework that might serve your needs. You can download it (clips_feature_tests_640.zip) from one of the 6.4 download directories (sourceforge.net/projects/clipsrules/files/CLIPS/6.40_Beta_3/ for the current beta release). To run the tests, launch CLIPS in the same directory and execute a (batch "testall.tst") command. Using the CLIPS terminal application, you can also run them from the shell with "clips -f testall.tst". When execution completes you can look at the *.rsl files in the Results directory for the results. If difference occurs you can use a diff program to compare the contents of the .out file in the Actual directory with the contents of the Expected directory.
The framework uses the batch command to automatically load and run the test cases. The dribble-on command is used to capture the output of each test case and place it in its own file in the Actual directory. The framework allows you to run all of the test cases (using the testall.tst batch file) or you can run any of the individual test cases by running the .tst batch file associated with the test.

Related

not able tochange voices festival i arch linux

whenever i tries to change voice in festival in arch linux it give me this error
#<CLOSURE n (let ((me voice_cmu_us_awb_cg)) (require "/usr/share/festival/voices/us/cmu_us_awb_cg/festvox/cmu_us_awb_cg") (if (eq me voice_cmu_us_awb_cg) (error (string-append "autoload: \"""/usr/share/festival/voices/us/cmu_us_awb_cg/festvox/cmu_us_awb_cg" ".scm\" does not define " (quote voice_cmu_us_awb_cg)))) (apply voice_cmu_us_awb_cg n))>
can any one help me in this

Can I doc-test ELisp functions?

I like the Python feature of doc-tests for testing functions independently. Does Emacs Lisp have something similar, or could I emulate it in some way?
For example, this function gets timestamps from an Org-mode clock segment:
(defun org-get-timestamps (line)
"Parses a clock segment line and returns the first and last timestamps in a list."
(let* ((org-clock-regexp (concat "CLOCK: " org-ts-regexp3 "--" org-ts-regexp3))
(t1 (if (string-match org-clock-regexp line)
(match-string 1 line)
(user-error "The argument must have a valid CLOCK range")))
(t2 (match-string 9 line)))
(cons t1 (cons t2 '()))))
I would like a doc-test such as:
(org-get-timestamps "CLOCK: [2019-09-26 Thu 00:29]--[2019-09-26 Thu 01:11] => 0:42")
("2019-09-26 Thu 00:29" "2019-09-26 Thu 01:11")
A test of the user-error would also be nice.
I also would like to ensure that any refactoring passes the doc-test, so it's also a regression test.
Does that exist?
An important feature of Python doctest is how its input looks like a Python interactive REPL session, as described in the doctest documentation:
The doctest module searches for pieces of text that look like
interactive Python sessions, and then executes those sessions to
verify that they work exactly as shown.
I'm not aware of any elisp facilities exactly like this, but I think you can achieve what you want using the Emacs Lisp Regression Testing (ERT) framework, which supports both interactive and batch test execution.
To test the org-get-timestamps function you can define a test like this:
(require 'ert)
(ert-deftest org-timestamp-test ()
(should (equal
(org-get-timestamps "CLOCK: [2019-09-26 Thu 00:29]--[2019-09-26 Thu 01:11] => 0:42")
'("2019-09-26 Thu 00:29" "2019-09-26 Thu 01:11"))))
To run the test interactively, you can type M-x ert, press enter, and then either press enter again to select all tests using the default t argument or type the name of the test to run and press enter, and the test results will be shown in the *ert* buffer:
Selector: org-timestamp-test
Passed: 1
Failed: 0
Skipped: 0
Total: 1/1
Started at: 2019-09-27 08:44:57-0400
Finished.
Finished at: 2019-09-27 08:44:57-0400
.
The dot character at the very end above represents the test that was run. If multiple tests were executed, there would be multiple dots.
To run the test in batch mode, save it to file org-timestamp-test.el and assuming the org-get-timestamps function resides in file org-timestamps.el, run it like this from your shell command line:
emacs -batch -l ert -l org-timestamps.el -l org-timestamp-test.el -f ert-run-tests-batch-and-exit
The test results are then presented on the shell output:
Running 1 tests (2019-09-27 06:03:09-0700) passed 1/1
org-timestamp-test
Ran 1 tests, 1 results as expected (2019-09-27 06:03:09-0700)

Is there an (idiomatic) way of testing the result of an IO function in Clojure?

I have a function that saves some text to a file:
(defn save-keypair
"saves keypair to ~/.ssb-clj/secret"
[pair file-path]
(let [public-key-string (->> (:public pair) (.array) (byte-array) (b64/encode) (bs/to-string))
secret-key-string (->> (:secret pair) (.array) (byte-array) (b64/encode) (bs/to-string))]
(spit file-path (str "Public Key: " public-key-string))
(spit file-path (str "\nPrivate Key: " secret-key-string) :append true)))
It works fine (currently checking via just opening the file and looking at it myself). However, I'd like to write an actual test to check that everything is working correctly. Is there an idiomatic way of doing this in Clojure?
Look into using with-redefs, as part of your unit tests. In your case, you probably want to merge the writing of the public and private keys into a single form which we can exploit for the test:
;; compute public-key-string and private-key-string as before
(let [contents (format "Public Key: %s\nPrivate Key: %s"
public-key-string secret-key-string)]
(spit file-path contents)
A test could be something like:
(deftest saving-keypair
(testing "Successful save"
(let [file-mock (atom nil)]
;; During this test we redefine `spit` to save into the atom defined above
(with-redefs [spit (fn [path data] (reset! file-mock {:path path :data data}))]
;; Perform IO action
(save-keypair "~/.ssb-clj/secret" {:public "XXXX" :private "YYYYY"})
;; Test if the expected data was saved in the file-mock
(is (= {:path "~/.ssb-clj/secret" :data "Public key: XXXYYYZZZ\nXXXYYYZZ"}
#file-mock))
Use Java interop with File
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/File.html
In particular, see File.createTempFile() and either file.delete() or file.deleteOnExit(). So you create a temp file, use that in your unit test, reading the file that you just wrote and verifying contents. Then either delete the file explicitly (ideally inside of try/finally) with auto-delete as a backup.
Depending on how you set up the expected results in your tests, you may find the following useful:
clojure.string/trim
tupelo.string/collapse-whitespace
tupelo.string/nonblank=
These helper functions are especially useful for text file output, where the presence of a trailing newline char can be OS dependent. They are also helpful to ignore differences due to the "newline" being CR, CR/LF, or LF.

Is there an Awk- or Lisp-like programming language that can process a stream of s-expressions?

I have been creating some PCB footprints in KiCad recently, which are stored in s-expression files with data that looks like this:
(fp_text user %R (at 0 5.08) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -27.04996 -3.986) (end -27.24996 -3.786) (layer F.Fab) (width 0.1))
(pad "" np_thru_hole circle (at 35.56 0) (size 3.175 3.175) (drill 3.175) (layers *.Cu *.Mask)
(clearance 1.5875))
(pad 96 smd rect (at 1.25 3.08473) (size 0.29972 1.45034) (layers F.Cu F.Paste F.Mask)
(clearance 0.09906))
I would like to be able to write shell one-liners to efficiently edit multiple parameters. I would normally use Awk for something like this, but the recursive nature of s-expressions makes it ill-suited for the task. I would like to know if there is a programming language with an interpreter designed to handle piped data and can process s-expressions natively. Perhaps a data-driven dialect of Lisp would do this, but I'm not sure where to look.
In summary, I would like to be able to make quick edits to an s-expression file in a similar manner to the way Awk lets me process columns of data line-by-line; only in the case of s-expressions the processing would be performed level-by-level.
Example: find all of the pad expressions of type smd with (size 0.29972 1.45034), and renumber each one based its position.
Simple script
Here is an example in Common Lisp, assuming your input is in file "/tmp/ex.cad" (it could also be obtained by reading the output stream of a process).
The main processing loop consists in opening the file in order to obtain an input stream in (which is automatically closed at the end of with-open-file), loop over all forms in the file, process them and possibly output them to standard output. You could complexify the process as much as you want, but the following is good enough:
(with-open-file (in #"/tmp/ex.cad")
(let ((*read-eval* nil))
(ignore-errors
(loop (process-form (read in))))))
Suppose you want to increase the width of fp_line entries, ignore fp_text and otherwise print the form unmodified, you could define process-form as follows:
(defun process-form (form)
(destructuring-bind (header . args) form
(print
(case header
(fp_line (let ((width (assoc 'width args)))
(when width (incf (second width) 3)))
form)
(fp_text (return-from process-form))
(t form)))))
Running the previous loop would then output:
(FP_LINE (START -27.04996 -3.986) (END -27.24996 -3.786) (LAYER F.FAB) (WIDTH 3.1))
(PAD "" NP_THRU_HOLE CIRCLE (AT 35.56 0) (SIZE 3.175 3.175) (DRILL 3.175) (LAYERS *.CU *.MASK) (CLEARANCE 1.5875))
(PAD 96 SMD RECT (AT 1.25 3.08473) (SIZE 0.29972 1.45034) (LAYERS F.CU F.PASTE F.MASK) (CLEARANCE 0.09906))
More safety
From there, you can build more elaborate pipelines, with the help of pattern matching or macros if you want. You have to take into account some safety measures, like binding *read-eval* to nil, using with-standard-io-syntax
and binding *print-circte* to T as suggested by tfb, disallowing fully qualified symbols (by having #\: signal an error), etc. Ultimately, like Shell scripts one-liners, the amount of precautions you add is based on how much you trust your inputs:
;; Load libraries
(ql:quickload '(:alexandria :optima))
;; Import symbols in current package
(use-package :optima)
(use-package :alexandria)
;; Transform source into a stream
(defgeneric ensure-stream (source)
(:method ((source pathname)) (open source))
(:method ((source string)) (make-string-input-stream source))
(:method ((source stream)) source))
;; make reader stop on illegal characters
(defun abort-reader (&rest values)
(error "Aborting reader: ~s" values))
Dedicated package for KiCad symbols (exporting is optional):
(defpackage :kicad
(:use)
(:export #:fp_text
#:fp_line
#:pad
#:size))
Loop over forms:
(defmacro do-forms ((form source &optional result) &body body)
"Loop over forms from source, eventually return result"
(with-gensyms (in form%)
`(with-open-stream (,in (ensure-stream ,source))
(with-standard-io-syntax
(let ((*read-eval* nil)
(*print-circle* t)
(*package* (find-package :kicad))
(*readtable* (copy-readtable)))
(set-macro-character #\: #'abort-reader nil)
(loop
:for ,form% := (read ,in nil ,in)
:until (eq ,form% ,in)
:do (let ((,form ,form%)) ,#body)
:finally (return ,result)))))))
Example:
;; Print lines at which there is a size parameter, and its value
(let ((line 0))
(labels ((size (alist) (second (assoc 'kicad:size alist)))
(emit (size) (when size (print `(:line ,line :size ,size))))
(process (options) (emit (size options))))
(do-forms (form #P"/tmp/ex.cad")
(match form
((list* 'kicad:fp_text _ _ options) (process options))
((list* 'kicad:fp_line options) (process options))
((list* 'kicad:pad _ _ _ options) (process options)))
(incf line))))
Output
(:LINE 2 :SIZE 3.175)
(:LINE 3 :SIZE 0.29972)
Just write a simple Lisp or Scheme script which loops on reading and processes recursively your s-expr as required. On Linux I would recommend using Guile (a good Scheme interpreter) or perhaps Clisp (a simple Common Lisp implementation) or even SBCL (a very powerful Common Lisp).
(You might consider DSSSL, but in your case it is overkill)
Notice that your sample input is not an S-expression, because (layer F.Fab) is not one (since after the dot you should have another s-expression, not an atom like Fab). I guess it is a typo and should be (layer "F.Fab"); or maybe your KiCad software don't process S-expressions, but some other input language (which should be specified, probably in EBNF notation) inspired by S-expressions.
Notice also that KiCad is a free software and has a community with forums and a mailing list. Perhaps you should ask your actual problem there?
PS. We don't know what transformation you have in mind, but Scheme and Common Lisp are really fit for such tasks. In most cases they are extremely simple to code (probably a few lines only).

How do I do basic authentication in Emacs Lisp?

I'm trying to authenticate to an API using basic authentication. It seems like the code below should work, but it's breaking when I run it in the scratch buffer after running it with C-x C-e (says: debugger entered--Lisp error: (wrong-type-argument characterp)).
My code is below. If anyone knows what I need to change to make this work, please let me know! There are basically no complete Emacs Lisp basic authentication examples I could find online, so this would be a huge help.
(setq ztoken "areallyfaketokenrandomtokenwithfakechars")
(setq zsite "https://fake.zendesk.com/api/v2/users/1100000011/related.json")
(let ((url-request-method "GET")
(url-request-extra-headers '(("Content Type" . "application/json")
("Authorization" . ,(concat "Basic "
(base64-encode-string
(concat "joe#fake.com/token" ":" ztoken)))))))
(condition-case nil
(url-retrieve-synchronously
(format zsite))))
As lawlist mentions, your code uses a single-quote instead of a back-tick. Below is an alternative approach, that does not use the back-tick/comma. For more information on backquotes: https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html#Backquote
(let* ((url-request-method "GET")
(base64 (concat "Basic "
(base64-encode-string
(concat "joe#fake.com/token" ":" ztoken))))
(url-request-extra-headers (list (cons "Content Type" "application/json")
(cons "Authorization" base64))))
(condition-case nil
(url-retrieve-synchronously
(format zsite))))