1# Test script for Bourne-shell extensions. Set TARGET_SHELL
2# to the shell to be tested (bash, zsh, etc) before sourcing it.
3if [[ -z "$TARGET_SHELL" ]]; then
4  echo "TARGET_SHELL variable not set"
5  exit 1
6fi
7
8set -e
9
10cd "$(dirname "$0")"
11TEST_DIR=$PWD
12export XDG_CONFIG_HOME=${TEST_DIR}/config
13export XDG_DATA_HOME=${TEST_DIR}/data
14PATH=$(dirname "$TEST_DIR"):$PATH
15export PATH
16
17# Reset the direnv loading if any
18export DIRENV_CONFIG=$PWD
19unset DIRENV_BASH
20unset DIRENV_DIR
21unset DIRENV_MTIME
22unset DIRENV_WATCHES
23unset DIRENV_DIFF
24
25mkdir -p "${XDG_CONFIG_HOME}/direnv"
26touch "${XDG_CONFIG_HOME}/direnv/direnvrc"
27
28has() {
29  type -P "$1" &>/dev/null
30}
31
32direnv_eval() {
33  eval "$(direnv export "$TARGET_SHELL")"
34}
35
36test_start() {
37  cd "$TEST_DIR/scenarios/$1"
38  direnv allow
39  if [[ "$DIRENV_DEBUG" == "1" ]]; then
40    echo
41  fi
42  echo "## Testing $1 ##"
43  if [[ "$DIRENV_DEBUG" == "1" ]]; then
44    echo
45  fi
46}
47
48test_stop() {
49  cd /
50  direnv_eval
51}
52
53test_eq() {
54  if [[ "$1" != "$2" ]]; then
55    echo "FAILED: '$1' == '$2'"
56    exit 1
57  fi
58}
59
60test_neq() {
61  if [[ "$1" == "$2" ]]; then
62    echo "FAILED: '$1' != '$2'"
63    exit 1
64  fi
65}
66
67### RUN ###
68
69direnv allow || true
70direnv_eval
71
72test_start base
73  echo "Setting up"
74  direnv_eval
75  test_eq "$HELLO" "world"
76
77  WATCHES=$DIRENV_WATCHES
78
79  echo "Reloading (should be no-op)"
80  direnv_eval
81  test_eq "$WATCHES" "$DIRENV_WATCHES"
82
83  sleep 1
84
85  echo "Updating envrc and reloading (should reload)"
86  touch .envrc
87  direnv_eval
88  test_neq "$WATCHES" "$DIRENV_WATCHES"
89
90  echo "Leaving dir (should clear env set by dir's envrc)"
91  cd ..
92  direnv_eval
93  echo "${HELLO}"
94  test -z "${HELLO}"
95
96  unset WATCHES
97test_stop
98
99test_start inherit
100  cp ../base/.envrc ../inherited/.envrc
101  direnv_eval
102  echo "HELLO should be world:" "$HELLO"
103
104  sleep 1
105  echo "export HELLO=goodbye" > ../inherited/.envrc
106  direnv_eval
107  test_eq "$HELLO" "goodbye"
108test_stop
109
110if has ruby; then
111  test_start "ruby-layout"
112    direnv_eval
113    test_neq "$GEM_HOME" ""
114  test_stop
115fi
116
117# Make sure directories with spaces are fine
118test_start "space dir"
119  direnv_eval
120  test_eq "$SPACE_DIR" "true"
121test_stop
122
123test_start "child-env"
124  direnv_eval
125  test_eq "$PARENT_PRE" "1"
126  test_eq "$CHILD" "1"
127  test_eq "$PARENT_POST" "1"
128  test -z "$REMOVE_ME"
129test_stop
130
131test_start "special-vars"
132  export DIRENV_BASH=$(command -v bash)
133  export DIRENV_CONFIG=foobar
134  direnv_eval || true
135  test -n "$DIRENV_BASH"
136  test_eq "$DIRENV_CONFIG" "foobar"
137  unset DIRENV_BASH
138  unset DIRENV_CONFIG
139test_stop
140
141test_start "dump"
142  direnv_eval
143  test_eq "$LS_COLORS" "*.ogg=38;5;45:*.wav=38;5;45"
144  test_eq "$THREE_BACKSLASHES" '\\\'
145  test_eq "$LESSOPEN" "||/usr/bin/lesspipe.sh %s"
146test_stop
147
148test_start "empty-var"
149  direnv_eval
150  test_neq "${FOO-unset}" "unset"
151  test_eq "${FOO}" ""
152test_stop
153
154test_start "empty-var-unset"
155  export FOO=""
156  direnv_eval
157  test_eq "${FOO-unset}" "unset"
158  unset FOO
159test_stop
160
161test_start "in-envrc"
162  direnv_eval
163  set +e
164  ./test-in-envrc
165  es=$?
166  set -e
167  test_eq "$es" "1"
168test_stop
169
170test_start "missing-file-source-env"
171  direnv_eval
172test_stop
173
174test_start "symlink-changed"
175  # when using a symlink, reload if the symlink changes, or if the
176  # target file changes.
177  ln -fs ./state-A ./symlink
178  direnv_eval
179  test_eq "${STATE}" "A"
180  sleep 1
181
182  ln -fs ./state-B ./symlink
183  direnv_eval
184  test_eq "${STATE}" "B"
185test_stop
186
187test_start "utf-8"
188  direnv_eval
189  test_eq "${UTFSTUFF}" "♀♂"
190test_stop
191
192test_start "failure"
193  # Test that DIRENV_DIFF and DIRENV_WATCHES are set even after a failure.
194  #
195  # This is needed so that direnv doesn't go into a loop when the loading
196  # fails.
197  test_eq "${DIRENV_DIFF:-}" ""
198  test_eq "${DIRENV_WATCHES:-}" ""
199
200  direnv_eval
201
202  test_neq "${DIRENV_DIFF:-}" ""
203  test_neq "${DIRENV_WATCHES:-}" ""
204test_stop
205
206test_start "watch-dir"
207    echo "No watches by default"
208    test_eq "${DIRENV_WATCHES}" "${WATCHES}"
209
210    direnv_eval
211
212    if ! direnv show_dump "${DIRENV_WATCHES}" | grep -q "testfile"; then
213        echo "FAILED: testfile not added to DIRENV_WATCHES"
214        exit 1
215    fi
216
217    echo "After eval, watches have changed"
218    test_neq "${DIRENV_WATCHES}" "${WATCHES}"
219test_stop
220
221# Context: foo/bar is a symlink to ../baz. foo/ contains and .envrc file
222# BUG: foo/bar is resolved in the .envrc execution context and so can't find
223#      the .envrc file.
224#
225# Apparently, the CHDIR syscall does that so I don't know how to work around
226# the issue.
227#
228# test_start "symlink-bug"
229#   cd foo/bar
230#   direnv_eval
231# test_stop
232
233# Pending: test that the mtime is looked on the original file
234# test_start "utils"
235#   LINK_TIME=`direnv file-mtime link-to-somefile`
236#   touch somefile
237#   NEW_LINK_TIME=`direnv file-mtime link-to-somefile`
238#   test "$LINK_TIME" = "$NEW_LINK_TIME"
239# test_stop
240