Carp/core/Test.carp

133 lines
4.4 KiB
Plaintext
Raw Normal View History

2018-08-06 18:19:39 +03:00
(load "Color.carp")
2017-10-20 18:00:47 +03:00
(defmodule Test
(deftype State [passed Int, failed Int])
2018-06-14 11:49:28 +03:00
(hidden handler)
2017-11-25 21:19:15 +03:00
(defn handler [state expected actual descr what op]
2017-10-20 18:00:47 +03:00
(if (op expected actual)
(do
2018-08-06 18:19:39 +03:00
(IO.colorize "green" &(str* @"Test '" @descr @"' passed\n"))
(State.update-passed (State.copy state) &Int.inc))
2017-10-20 18:00:47 +03:00
(do
(IO.color "red")
(IO.println &(str* @"Test '" @descr @"' failed:"))
(IO.print &(str* @"\tExpected " @what @": '"))
2017-10-20 18:00:47 +03:00
(IO.print &(str expected))
(IO.println &(str* @"', actual value: '" (str actual) @"'"))
2017-10-20 18:00:47 +03:00
(IO.color "reset")
(State.update-failed (State.copy state) &Int.inc))))
2017-10-20 18:00:47 +03:00
2018-06-14 11:49:28 +03:00
(doc assert-op "Assert that op returns true when given x and y.")
2017-11-25 21:19:15 +03:00
(defn assert-op [state x y descr op]
(handler state x y descr "value" op))
2017-10-20 18:00:47 +03:00
2018-06-14 11:49:28 +03:00
(doc assert-equal "Assert that x and y are equal. Equality needs to be implemented for their type.")
2017-11-25 21:19:15 +03:00
(defn assert-equal [state x y descr]
(handler state x y descr "value" =))
2017-10-20 18:00:47 +03:00
2018-06-14 11:49:28 +03:00
(doc assert-not-equal "Assert that x and y are not equal. Equality needs to be implemented for their type.")
2017-11-25 21:19:15 +03:00
(defn assert-not-equal [state x y descr]
(handler state x y descr "not value" /=))
2017-10-20 18:00:47 +03:00
2018-06-14 11:49:28 +03:00
(doc assert-true "Assert that x is true.")
2017-10-20 18:00:47 +03:00
(defn assert-true [state x descr]
2017-11-25 21:19:15 +03:00
(assert-equal state true x descr))
2017-10-20 18:00:47 +03:00
2018-06-14 11:49:28 +03:00
(doc assert-false "Assert that x is false.")
2017-10-20 18:00:47 +03:00
(defn assert-false [state x descr]
2017-11-25 21:19:15 +03:00
(assert-equal state false x descr))
2017-10-20 18:00:47 +03:00
2018-06-14 11:49:28 +03:00
(doc reset "Reset test state.")
2017-10-20 18:00:47 +03:00
(defn reset [state]
(State.set-failed (State.set-passed state 0) 0))
2018-06-14 11:49:28 +03:00
(hidden run-child)
(defn run-child [x]
(let [pid (System.fork)
status 0]
(if (= pid 0)
2018-05-23 16:13:13 +03:00
(do
(x)
0)
(do
(ignore (System.wait (address status)))
(System.get-exit-status status)))))
2018-06-14 11:49:28 +03:00
(hidden handle-signal)
2018-05-23 16:13:13 +03:00
(defn handle-signal [x] (System.exit x))
2018-06-14 11:49:28 +03:00
(hidden run-child-signals)
2018-05-23 16:13:13 +03:00
(defn run-child-signals [x]
(let [pid (System.fork)
status 0]
(if (= pid 0)
(do
(System.signal System.signal-abort handle-signal)
(System.signal System.signal-fpe handle-signal)
(System.signal System.signal-ill handle-signal)
(System.signal System.signal-segv handle-signal)
(System.signal System.signal-term handle-signal)
(x)
0)
(do
(ignore (System.wait (address status)))
(System.get-exit-status status)))))
2018-06-14 11:49:28 +03:00
(doc assert-exit "Assert that function f exits with exit code exit-code.")
(defn assert-exit [state exit-code f descr]
(assert-equal state exit-code (run-child f) descr))
2018-06-14 11:49:28 +03:00
(doc assert-exit "Assert that function f aborts with OS signal signal.")
2018-05-23 16:13:13 +03:00
(defn assert-signal [state signal x descr]
(assert-equal state signal (run-child-signals x) descr))
2018-06-14 11:49:28 +03:00
(doc print-test-results "Print test results.")
2017-10-20 18:00:47 +03:00
(defn print-test-results [state]
(let [passed @(State.passed state)
failed @(State.failed state)]
2017-10-20 18:00:47 +03:00
(do
(IO.println "Results:")
(if (Int.> (Int.+ passed failed) 0)
(do
(IO.color "green")
2019-05-27 19:05:44 +03:00
(if (Int.> passed 0) (IO.print &(String.append "\t|" &(String.repeat passed "="))) ())
2017-10-20 18:00:47 +03:00
(if (Int.= failed 0) (IO.print "|") ())
(IO.color "red")
(if (Int.= passed 0) (IO.print "\t|") ())
2019-05-27 19:05:44 +03:00
(if (Int.> failed 0) (IO.print &(String.append &(String.repeat failed "=") "|")) ())
2017-10-20 18:00:47 +03:00
(IO.println ""))
())
(IO.color "green")
(IO.print "\tPassed: ")
(IO.print &(Int.str passed))
(IO.color "red")
(IO.print "\tFailed: ")
(IO.println &(Int.str failed))
2018-09-13 02:10:17 +03:00
(IO.color "reset")))))
2017-10-20 18:00:47 +03:00
2019-03-13 20:49:48 +03:00
(defndynamic with-test-internal [name forms]
(if (= (length forms) 1)
(list (list 'set! name (list 'ref (car forms))))
(cons (list 'set! name (list 'ref (car forms)))
2017-10-20 18:00:47 +03:00
(with-test-internal name (cdr forms)))))
(defmacro with-test [name :rest forms]
2018-11-07 18:11:38 +03:00
(list 'let (array name '&(Test.State.init 0 0))
(cons-last
(list 'Int.copy (list 'Test.State.failed name))
2018-09-13 02:10:17 +03:00
(cons-last
(list 'Test.print-test-results name)
(cons 'do (with-test-internal name forms))))
))
2017-10-20 18:00:47 +03:00
2018-11-07 18:11:38 +03:00
(defmacro deftest [name :rest forms]
(list 'defn 'main (array)
(list 'let (array name '&(Test.State.init 0 0))
2017-10-20 18:00:47 +03:00
(cons-last
2018-11-07 18:11:38 +03:00
(list 'Int.copy (list 'Test.State.failed name))
(cons-last
(list 'Test.print-test-results name)
(cons 'do (with-test-internal name forms)))))))