                                                (Thread.
                                                  (fn []
                                                    (binding [*out* tmp-out]
-                                                     (sleep 500)
+                                                     (utils/sleep 500)
                                                      (println "Finished."))))
                                                (.start)))
                                            "Started.")}}}
         test-cmd-input ["async-foo"]
-        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
-    (is (= (expected-string ["Starting..." "\"Started.\""]) out-string))))
-
-(deftest async-cmd-sleep-finished-test
+        out-string (cli-tests/test-cli-stdout #(cli/start-cli cli-opts) test-cmd-input)]
+    (test/is (= (cli-tests/expected-string ["Starting..." "\"Started.\""]) out-string))))
+
+(test/deftest async-cmd-sleep-finished-test
   (let [cli-opts {:cmds {:async-foo {:fn (fn []
                                            (println "Starting...")
                                            (let [tmp-out *out*]

  ^{:author "Ruediger Gad",
    :doc "Tests for cli4clj"}
  cli4clj.test.cli
  (:use clojure.test)
  (:require
    (cli4clj
      [cli :refer :all]
      [cli-tests :refer :all])
    (clj-assorted-utils [util :refer :all]))
  (:import (java.io ByteArrayInputStream)
           (java.util ArrayList)))

(deftest simple-options-merging-test
  (let [user-options {:cmds {:foo {:fn 123}}}
        defaults {:cmds {:bar {:fn 456}}}
        mandatory-defaults {}
        expected {:cmds {:bar {:fn 456}
                         :foo {:fn 123}}}]
    (is (= expected (merge-options defaults user-options mandatory-defaults)))))

(deftest simple-options-override-test
  (let [user-options {:cmds {:foo {:fn 123}
                             :bar {:fn 789}}}
        defaults {:cmds {:bar {:fn 456}}}
        mandatory-defaults {}
        expected {:cmds {:bar {:fn 789}
                         :foo {:fn 123}}}]
    (is (= expected (merge-options defaults user-options mandatory-defaults)))))

(deftest simple-mandatory-options-override-test
  (let [user-options {:cmds {:foo {:fn 123}
                             :bar {:fn 789}}}
        defaults {}
        mandatory-defaults {:cmds {:bar {:fn 456}}}
        expected {:cmds {:bar {:fn 456}
                         :foo {:fn 123}}}]
    (is (= expected (merge-options defaults user-options mandatory-defaults)))))

(deftest user-options-override-non-nested-test
  (let [user-options {:prompt :xyz}
        defaults {:prompt :abc}
        mandatory-defaults {}
        expected {:prompt :xyz}]
    (is (= expected (merge-options defaults user-options mandatory-defaults)))))



(deftest cmd-vector-to-cmd-test-input-string-test
  (let [expected (str "foo" *cli4clj-line-sep* "bar" *cli4clj-line-sep*)
        cmd-vec ["foo" "bar"]]
    (is (= expected (cmd-vector-to-test-input-string cmd-vec)))))

(deftest simple-test-cli-interaction-stdout-test
  (let [out-string (test-cli-stdout #(start-cli {}) [])]
    (is (= "" out-string))))

(deftest simple-test-cli-interaction-stderr-test
  (let [err-string (test-cli-stderr #(start-cli {}) ["xyz"])]
    (is (.startsWith err-string "Invalid command: \"[xyz]\"."))))

(deftest add-cmd-cli-interaction-stdout-test
  (let [cli-opts {:cmds {:add {:fn #(+ %1 %2)}}}
        test-cmd-input ["add 1 2"]
        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
    (is (= "3" out-string))))

(deftest add-cmd-cli-interaction-stdout-multiline-test
  (let [cli-opts {:cmds {:add {:fn #(+ %1 %2)}}}
        test-cmd-input ["add 1 2" "add 3 4" "add 5 6"]
        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
    (is (= (expected-string ["3" "7" "11"]) out-string))))

(deftest div-cmd-cli-interaction-cmd-error-test
  (let [cli-opts {:cmds {:div {:fn #(/ %1 %2)}}}
        test-cmd-input ["div 1 0"]
        out-string (test-cli-stderr #(start-cli cli-opts) test-cmd-input)]
    (is (= "Divide by zero" out-string))))

(deftest help-cmd-cli-interaction-stdout-test
  (let [cli-opts {:cmds {:add {:fn #(+ %1 %2)
                               :fn-args "fn-args string"}}}
        test-cmd-input ["help"]
        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
    (is (= (str "add" *cli4clj-line-sep*
                "\t Arguments: fn-args string" *cli4clj-line-sep* *cli4clj-line-sep*
                "help [? h]" *cli4clj-line-sep*
                "\tShow help." *cli4clj-line-sep*
                "\tDisplay a help text that lists all available commands including further detailed information about these commands." *cli4clj-line-sep* *cli4clj-line-sep*
                "quit [q]" *cli4clj-line-sep*
                "\tQuit the CLI." *cli4clj-line-sep*
                "\tTerminate and close the command line interface.")
           out-string))))

(deftest allow-eval-cli-interaction-test
  (let [cli-opts {:allow-eval true}
        test-cmd-input ["(+ 1 2)"]
        out-string (test-cli-stdout #(start-cli cli-opts) test-cmd-input)]
    (is (= (expected-string ["3"]) out-string))))



(deftest expected-string-creation-single-line-test
  (let [in ["a"]
        out (expected-string in)]
    (is (= "a" out))))

(deftest expected-string-creation-multi-line-test
  (let [in ["a" "b" "c"]
        out (expected-string in)
        line-sep (System/getProperty "line.separator")]
    (is (= (str "a" line-sep "b" line-sep "c") out))))

(deftest expected-string-creation-custom-separator-test
  (let [in ["a" "b" "c"]
        out (expected-string in "foo")
        line-sep "foo"]
    (is (= (str "a" line-sep "b" line-sep "c") out))))



(deftest get-cmd-aliases-test
  (let [cmds {:a {}
              :b :a
              :c :a

                                               (Thread.
                                                 (fn []
                                                   (binding [*out* tmp-out]
                                                     (utils/sleep 500)
                                                     (println "Finished."))))
                                               (.start)))
                                           "Started.")}}}
        test-cmd-input ["async-foo" "_sleep 1000"]
        out-string (cli-tests/test-cli-stdout #(cli/start-cli cli-opts) test-cmd-input)]
    (test/is (= (cli-tests/expected-string ["Starting..." "\"Started.\"" "Finished."]) out-string))))



(test/deftest print-cmd-invalid-token-to-string-fallback-test
  (let [cli-opts {:cmds {:print {:fn #(println %)}}}
        test-cmd-input ["print /foo/bar"]
        out-string (cli-tests/test-cli-stdout #(cli/start-cli cli-opts) test-cmd-input)]
    (test/is (= (cli-tests/expected-string ["/foo/bar"]) out-string))))

(test/deftest print-cmd-invalid-token-exception-test
  (let [cli-opts {:cmds {:print {:fn #(println %)}}
                  :invalid-token-to-string false}
        test-cmd-input ["print /foo/bar"]
        out-string (cli-tests/test-cli-stderr #(cli/start-cli cli-opts) test-cmd-input)]
    (test/is (.startsWith out-string "java.lang.RuntimeException: Invalid token: /foo/bar"))))



(test/deftest enable-trace-test
  (let [cli-opts {}
        test-cmd-input ["_enable-trace true"]
        out-string (cli-tests/test-cli-stdout #(cli/start-cli cli-opts) test-cmd-input)]
    (test/is (= (cli-tests/expected-string ["print-exception-trace is set to: true"]) out-string))))

(test/deftest enable-trace-wrong-arg-test
  (let [cli-opts {}
        test-cmd-input ["_enable-trace 123"]
        out-string (cli-tests/test-cli-stdout #(cli/start-cli cli-opts) test-cmd-input)]
    (test/is (= (cli-tests/expected-string
             ["Error, you need to supply a boolean value: true or false"
              "print-exception-trace is set to: false"])
           out-string))))



(test/deftest simple-jline-input-stream-mock-test
  (let [in-string (str "a 1" cli/*cli4clj-line-sep* "b 2 3" cli/*cli4clj-line-sep* "q" cli/*cli4clj-line-sep*)
        out (binding [cli/*jline-input-stream* (ByteArrayInputStream. (.getBytes in-string))]
              (with-out-str
                (cli/start-cli {:cmds {:a {:fn (fn [arg] (inc arg))}
                                   :b {:fn (fn [summand1 summand2] (+ summand1 summand2))}}})))]
    (test/is (= (cli-tests/expected-string ["2" (str "5" cli/*cli4clj-line-sep*)]) out))))

