1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
(ns puppetlabs.puppetserver.shell-utils-test
(:require [clojure.test :refer :all]
[puppetlabs.puppetserver.shell-utils :as sh-utils]
[puppetlabs.kitchensink.core :as ks]
[puppetlabs.trapperkeeper.testutils.logging :as logging]
[clojure.string :as str]
[clojure.set :as set])
(:import (java.io ByteArrayInputStream)
(com.puppetlabs.puppetserver ShellUtils ShellUtils$ExecutionOptions)))
(def test-resources
(ks/absolute-path
"./dev-resources/puppetlabs/puppetserver/shell_utils_test"))
(defn script-path
[script-name]
(str test-resources "/" script-name))
(defn parse-env-output
[env-output]
(set (str/split-lines env-output)))
(deftest returns-the-exit-code
(testing "true should return 0"
(is (zero? (:exit-code (sh-utils/execute-command (script-path "true"))))))
(testing "false should return 1"
(is (= 1 (:exit-code (sh-utils/execute-command (script-path "false")))))))
(deftest returns-stdout-correctly
(testing "echo should add content to stdout"
(is (= "foo\n" (:stdout (sh-utils/execute-command
(script-path "echo")
{:args ["foo"]}))))))
(deftest returns-stderr-correctly
(testing "echo can add content to stderr as well"
(logging/with-test-logging
(is (= "bar\n" (:stderr (sh-utils/execute-command
(script-path "warn")
{:args ["bar"]})))))))
(deftest combines-stderr-and-stdout-correctly
(logging/with-test-logging
(let [options (ShellUtils$ExecutionOptions.)
_ (.setCombineStdoutStderr options true)
results (ShellUtils/executeCommand (str (script-path "echo_and_warn")
" baz")
options)]
(testing "combined info echoed to stdout and stderr captured as output"
(let [output (.getOutput results)]
;; Allow stdout and stderr messages to come in either order since
;; the order in which they are read from the different stream
;; consuming threads is not reliable.
(is (or (= "to out: baz\nto err: baz\n" output)
(= "to err: baz\nto out: baz\n" output))
(format "Output produced, '%s', did not match expected output"
output))))
(testing "only info echoed to stderr captured as error"
(is (= "to err: baz\n" (.getError results))))
(testing "only stderr info (and not stdout info) is logged"
(is (logged?
"Executed an external process which logged to STDERR: to err: baz\n"
:warn))))))
(deftest pass-args-correctly
(testing "passes the expected number of args to cmd"
(is (= 5 (:exit-code (sh-utils/execute-command
(script-path "num-args")
{:args ["a" "b" "c" "d" "e"]}))))))
(deftest inherits-env-correctly
(testing "inherits environment variables if not specified"
(let [env-output (:stdout (sh-utils/execute-command
(script-path "list_env_var_names")))
env (parse-env-output env-output)]
(is (< 3 (count env))
(str "Expected at least 3 environment variables, got:\n" env-output))
(is (contains? env "PATH"))
(is (contains? env "PWD"))
(is (contains? env "HOME")))))
(deftest sets-env-correctly
(testing "sets environment variables correctly"
(is (= "foo\n" (:stdout (sh-utils/execute-command
(script-path "echo_foo_env_var")
{:env {"FOO" "foo"}}))))
(let [env-output (:stdout (sh-utils/execute-command
(script-path "list_env_var_names")
{:env {"FOO" "foo\nbar"}}))
env (parse-env-output env-output)
;; it seems that the JVM always includes a PWD env var, no
;; matter what, and in certain terminals it may also include a few
;; other vars, so we are writing the test to be tolerant of that.
expected-keys #{"FOO" "PWD" "_" "SHLVL"}
extra-keys (set/difference env expected-keys)]
(is (empty? extra-keys)
(str "Found unexpected environment variables:" extra-keys)))))
(deftest pass-stdin-correctly
(testing "passes stdin stream to command"
(is (= "foo" (:stdout (sh-utils/execute-command
(script-path "cat")
{:in (ByteArrayInputStream.
(.getBytes "foo" "UTF-8"))}))))))
(deftest sets-cwd-correctly
(testing "sets current working directory correctly"
(let [tmpdir (System/getProperty "java.io.tmpdir")]
(is (= (str tmpdir "\n") (:stdout (sh-utils/execute-command
(script-path "echo_cwd")
{:cwd tmpdir})))))))
(deftest throws-exception-for-non-absolute-path
(testing "Commands must be given using absolute paths"
(is (thrown? IllegalArgumentException
(sh-utils/execute-command "echo")))))
(deftest throws-exception-for-non-existent-file
(testing "The given command must exist"
(is (thrown-with-msg? IllegalArgumentException
#"command '/usr/bin/footest' does not exist"
(sh-utils/execute-command "/usr/bin/footest")))))
(deftest throws-reasonable-error-for-arguments-in-command
(testing "A meaningful error is raised if arguments are added to the command"
(is (thrown-with-msg? IllegalArgumentException
#"appears to use command-line arguments, but this is not allowed"
(sh-utils/execute-command
(str (script-path "echo") " foo"))))))
(deftest can-read-more-than-the-pipe-buffer
(testing "Doesn't deadlock when reading more than the pipe can hold"
(is (= 128000 (count (:stdout (sh-utils/execute-command
(script-path "gen-output")
{:args ["128000"]})))))))
|