diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6946830 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +test-runner.sh +test/assert.sh +test/stub.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0cd9f49 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: c +env: + - TMUX_VERSION="1.6" + - TMUX_VERSION="1.7" + - TMUX_VERSION="1.8" + - TMUX_VERSION="1.9a" +before_install: + - sudo apt-get update + - sudo apt-get install -y bc build-essential libevent-dev libncurses5-dev + - wget http://downloads.sourceforge.net/tmux/tmux-${TMUX_VERSION}.tar.gz + - tar -zxf tmux-${TMUX_VERSION}.tar.gz + - cd tmux-${TMUX_VERSION} + - ./configure && make && sudo make install + - cd .. +script: make test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8a83c37 --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +test: bootstrap + ./test-runner.sh + +bootstrap: test-runner.sh test/assert.sh test/stub.sh +clean: remove_test-runner.sh remove_test/assert.sh remove_test/stub.sh +update: update_test-runner.sh update_test/assert.sh update_test/stub.sh + +test-runner.sh: + echo "fetching test-runner.sh..." && \ + curl -s -L -o test-runner.sh \ + https://github.com/jimeh/test-runner.sh/raw/v0.2.0/test-runner.sh && \ + chmod +x test-runner.sh + +remove_test-runner.sh: + ( \ + test -f "test-runner.sh" && rm "test-runner.sh" && \ + echo "removed test-runner.sh"\ + ) || exit 0 + +update_test-runner.sh: remove_test-runner.sh test-runner.sh + +test/assert.sh: + echo "fetching test/assert.sh..." && \ + curl -s -L -o test/assert.sh \ + https://raw.github.com/lehmannro/assert.sh/v1.0.2/assert.sh + +remove_test/assert.sh: + test -f "test/assert.sh" && \ + rm "test/assert.sh" && \ + echo "removed test/assert.sh" + +update_test/assert.sh: remove_test/assert.sh test/assert.sh + +test/stub.sh: + echo "fetching test/stub.sh..." && \ + curl -s -L -o test/stub.sh \ + https://raw.github.com/jimeh/stub.sh/v1.0.1/stub.sh + +remove_test/stub.sh: + test -f "test/stub.sh" && \ + rm "test/stub.sh" && \ + echo "removed test/stub.sh" + +update_test/stub.sh: remove_test/stub.sh test/stub.sh + +.SILENT: +.PHONY: test bootstrap clean \ + remove_test-runner.sh update_test-runner.sh \ + remove_test/assert.sh update_test/assert.sh \ + remove_test/stub.sh update_test/stub.sh diff --git a/test/lib/env.test.sh b/test/lib/env.test.sh new file mode 100755 index 0000000..0caf1c0 --- /dev/null +++ b/test/lib/env.test.sh @@ -0,0 +1,33 @@ +#! /usr/bin/env bash +source "../test-helper.sh" + +# +# env.sh tests. +# + +# Setup. +realTMUXIFIER="$TMUXIFIER" +TMUXIFER="/path/to/tmuxifier" + +# When TMUXIFIER_LAYOUT_PATH is not set. +source "${root}/lib/env.sh" +assert 'echo $TMUXIFIER_LAYOUT_PATH' "${TMUXIFIER}/layouts" + +# When TMUXIFIER_LAYOUT_PATH is set and has a trailing slash. +TMUXIFIER_LAYOUT_PATH="/path/to/layouts/" +source "${root}/lib/env.sh" +assert 'echo $TMUXIFIER_LAYOUT_PATH' "/path/to/layouts" +unset TMUXIFIER_LAYOUT_PATH + +# When TMUXIFIER_LAYOUT_PATH is set and does not have a trailing slash. +TMUXIFIER_LAYOUT_PATH="/path/to/layouts" +source "${root}/lib/env.sh" +assert 'echo $TMUXIFIER_LAYOUT_PATH' "/path/to/layouts" +unset TMUXIFIER_LAYOUT_PATH + +# Tear down. +TMUXIFER="$realTMUXIFIER" +unset realTMUXIFIER + +# End of tests. +assert_end "env.sh" diff --git a/test/lib/layout-helpers/__expand_path.test.sh b/test/lib/layout-helpers/__expand_path.test.sh new file mode 100755 index 0000000..f94069f --- /dev/null +++ b/test/lib/layout-helpers/__expand_path.test.sh @@ -0,0 +1,27 @@ +#! /usr/bin/env bash +source "../../test-helper.sh" +source "${root}/lib/layout-helpers.sh" + +# +# __expand_path() tests. +# + +# Setup. +realHOME="$HOME" +HOME="/home/test-user" + +# When given a path containing "~", it expands "~" to "$HOME". +assert '__expand_path "~/Foo/Bar"' "${HOME}/Foo/Bar" + +# When given a path without "~", it returns path as is. +assert '__expand_path "/path/to/file"' "/path/to/file" + +# When given a path containing spaces, it returns path correctly. +assert '__expand_path "~/Path To/File"' "${HOME}/Path To/File" + +# Tear down. +HOME="$realHOME" +unset realHOME + +# End of tests. +assert_end "__expand_path()" diff --git a/test/lib/layout-helpers/__get_first_window_index.test.sh b/test/lib/layout-helpers/__get_first_window_index.test.sh new file mode 100755 index 0000000..c08dfd4 --- /dev/null +++ b/test/lib/layout-helpers/__get_first_window_index.test.sh @@ -0,0 +1,30 @@ +#! /usr/bin/env bash +source "../../test-helper.sh" +source "${root}/lib/layout-helpers.sh" + +# +# __get_first_window_index() tests. +# + +# When first window has a index of 0. +create-test-session +assert "__get_first_window_index" "0" +kill-test-session + +# When first window has a index of 1. +create-test-session +test-socket-tmux new-window -t "$session:1" +test-socket-tmux kill-window -t "$session:0" +assert "__get_first_window_index" "1" +kill-test-session + +# When first window has a index of 2. +create-test-session +test-socket-tmux new-window -t "$session:2" +test-socket-tmux kill-window -t "$session:0" +assert "__get_first_window_index" "2" +kill-test-session + + +# End of tests. +assert_end "__get_first_window_index()" diff --git a/test/lib/layout-helpers/__go_to_session.test.sh b/test/lib/layout-helpers/__go_to_session.test.sh new file mode 100755 index 0000000..84e4a89 --- /dev/null +++ b/test/lib/layout-helpers/__go_to_session.test.sh @@ -0,0 +1,32 @@ +#! /usr/bin/env bash +source "../../test-helper.sh" +source "${root}/lib/layout-helpers.sh" + +# +# __go_to_session() tests. +# + +# Setup. +session="tmuxifier-test-session" + +# When TMUX is not set, attach to $session. +stub tmuxifier-tmux +__go_to_session +assert_raises \ + "stub_called_with tmuxifier-tmux -u attach-session -t \"${session}:\"" 0 +restore tmuxifier-tmux + +# When TMUX is set, switch to $session. +TMUX="/tmp/tmux-501/default,1203,0" +stub tmuxifier-tmux +__go_to_session +assert_raises \ + "stub_called_with tmuxifier-tmux -u switch-client -t \"${session}:\"" 0 +restore tmuxifier-tmux +unset TMUX + +# Tear down. +unset session + +# End of tests. +assert_end "__go_to_session()" diff --git a/test/lib/layout-helpers/__go_to_window_or_session_path.test.sh b/test/lib/layout-helpers/__go_to_window_or_session_path.test.sh new file mode 100755 index 0000000..4d6542f --- /dev/null +++ b/test/lib/layout-helpers/__go_to_window_or_session_path.test.sh @@ -0,0 +1,49 @@ +#! /usr/bin/env bash +source "../../test-helper.sh" +source "${root}/lib/layout-helpers.sh" + +# +# __go_to_window_or_session_path() tests. +# + +# When neither $window_root or $session_root are set, does nothing. +stub run_cmd +__go_to_window_or_session_path +assert "stub_called_times run_cmd" "0" +restore run_cmd + + +# When only $window_root is set, runs cd to $window_root path. +stub run_cmd +window_root="/tmp" +__go_to_window_or_session_path +assert 'stub_called_with_times run_cmd cd \"/tmp\"' "1" +assert 'stub_called_with_times run_cmd clear' "1" +unset window_root +restore run_cmd + + +# When only $session_root is set, runs cd to $session_root path. +stub run_cmd +session_root="/usr" +__go_to_window_or_session_path +assert 'stub_called_with_times run_cmd cd \"/usr\"' "1" +assert 'stub_called_with_times run_cmd clear' "1" +unset session_root +restore run_cmd + + +# When $window_root and $session_root are set, runs cd to $window_root path. +stub run_cmd +window_root="/tmp" +session_root="/usr" +__go_to_window_or_session_path +assert 'stub_called_with_times run_cmd cd \"/tmp\"' "1" +assert 'stub_called_with_times run_cmd clear' "1" +unset window_root +unset session_root +restore run_cmd + + +# End of tests. +assert_end "__go_to_window_or_session_path()" diff --git a/test/lib/layout-helpers/new_window.test.sh b/test/lib/layout-helpers/new_window.test.sh new file mode 100755 index 0000000..5b162b7 --- /dev/null +++ b/test/lib/layout-helpers/new_window.test.sh @@ -0,0 +1,47 @@ +#! /usr/bin/env bash +source "../../test-helper.sh" +source "${root}/lib/layout-helpers.sh" + +# +# new_window() tests. +# + +# When called without arguments, creates new window. +create-test-session +stub __go_to_window_or_session_path +assert "test-socket-window-count" "1" +new_window +assert "test-socket-window-count" "2" +assert "stub_called_times __go_to_window_or_session_path" "1" +restore __go_to_window_or_session_path +kill-test-session + +# When called with name argument, creates new window with specified name. +create-test-session +stub __go_to_window_or_session_path +assert "test-socket-window-count yippieezzz" "0" +new_window "yippieezzz" +assert "test-socket-window-count" "2" +assert "test-socket-window-count yippieezzz" "1" +restore __go_to_window_or_session_path +kill-test-session + +# When called with name and command argument, creates new window with +# specified name and executes given command. +rm "/tmp/tmuxifier-new_window-test" &> /dev/null +create-test-session +stub __go_to_window_or_session_path +new_window "foobardoo" "touch /tmp/tmuxifier-new_window-test; bash" +assert "test-socket-window-count" "2" +assert "test-socket-window-count foobardoo" "1" +assert_raises 'test -f "/tmp/tmuxifier-new_window-test"' 0 +restore __go_to_window_or_session_path +kill-test-session +rm "/tmp/tmuxifier-new_window-test" &> /dev/null + + +# Tear down. +kill-test-server + +# End of tests. +assert_end "new_window()" diff --git a/test/lib/layout-helpers/tmux.test.sh b/test/lib/layout-helpers/tmux.test.sh new file mode 100755 index 0000000..2803b22 --- /dev/null +++ b/test/lib/layout-helpers/tmux.test.sh @@ -0,0 +1,20 @@ +#! /usr/bin/env bash +source "../../test-helper.sh" +source "${root}/lib/layout-helpers.sh" + +# +# tmux() tests. +# + +# Passes all arguments to tmuxifier-tmux. +stub tmuxifier-tmux +tmux -V +tmux --help +tmux new -s dude +assert_raises "stub_called_with tmuxifier-tmux -V" 0 +assert_raises "stub_called_with tmuxifier-tmux --help" 0 +assert_raises "stub_called_with tmuxifier-tmux new -s dude" 0 +restore tmuxifier-tmux + +# End of tests. +assert_end "tmux()" diff --git a/test/lib/runtime.test.sh b/test/lib/runtime.test.sh new file mode 100755 index 0000000..06d5a68 --- /dev/null +++ b/test/lib/runtime.test.sh @@ -0,0 +1,23 @@ +#! /usr/bin/env bash +source "../test-helper.sh" + +# +# runtime.sh tests. +# + +source "${root}/lib/runtime.sh" + +# We assume env.sh has been sourced if $TMUXIFIER_LAYOUT_PATH has been set. +assert 'echo $TMUXIFIER_LAYOUT_PATH' "${TMUXIFIER}/layouts" + +# We ensure $session_root is set to $HOME by default. +assert 'echo $session_root' "$HOME" + +# We assume layout-helpers.sh has been sourced if a few of them are available. +for helper in new_window split_v split_h select_window select_pane; do + assert "type $helper | head -1" "$helper is a function" +done + + +# End of tests. +assert_end "runtime.sh" diff --git a/test/lib/util.test.sh b/test/lib/util.test.sh new file mode 100755 index 0000000..df6cc08 --- /dev/null +++ b/test/lib/util.test.sh @@ -0,0 +1,58 @@ +#! /usr/bin/env bash +source "../test-helper.sh" +source "${root}/lib/util.sh" + +# +# calling-help() tests. +# + +# Returns 0 when "--help" is part of passed arguments. +assert_raises 'calling-help --help' 0 +assert_raises 'calling-help foo --help' 0 +assert_raises 'calling-help --help bar' 0 +assert_raises 'calling-help foo --help bar' 0 + +# Returns 0 when "-h" is part of passed arguments. +assert_raises 'calling-help -h' 0 +assert_raises 'calling-help foo -h' 0 +assert_raises 'calling-help -h bar' 0 +assert_raises 'calling-help foo -h bar' 0 + +# Returns 1 when neither "--help" or "-h" is not part of passed arguments. +assert_raises 'calling-help' 1 +assert_raises 'calling-help foo' 1 +assert_raises 'calling-help foo bar' 1 + +# Returns 1 when "--help" is part of passed arguments, but not free-standing. +assert_raises 'calling-help --help-me' 1 +assert_raises 'calling-help foo--help' 1 + +# Returns 1 when "-h" is part of passed arguments, but not free-standing. +assert_raises 'calling-help -hj' 1 +assert_raises 'calling-help welcome-home' 1 + +# End of tests. +assert_end "calling-help()" + + +# +# calling-complete() tests. +# + +# Returns 0 when "--complete" is part of passed arguments. +assert_raises 'calling-complete --complete' 0 +assert_raises 'calling-complete foo --complete' 0 +assert_raises 'calling-complete --complete bar' 0 +assert_raises 'calling-complete foo --complete bar' 0 + +# Returns 1 when "--complete" is not part of passed arguments. +assert_raises 'calling-complete' 1 +assert_raises 'calling-complete foo' 1 +assert_raises 'calling-complete foo bar' 1 + +# Returns 1 when "--complete" is part of passed arguments, but not free-standing. +assert_raises 'calling-complete --complete-me' 1 +assert_raises 'calling-complete foo--complete' 1 + +# End of tests. +assert_end "calling-complete()" diff --git a/test/libexec/tmuxifier-tmux.test.sh b/test/libexec/tmuxifier-tmux.test.sh new file mode 100755 index 0000000..9716360 --- /dev/null +++ b/test/libexec/tmuxifier-tmux.test.sh @@ -0,0 +1,22 @@ +#! /usr/bin/env bash +source "../test-helper.sh" +source "${root}/lib/util.sh" + +# +# tmuxifier-tmux tests. +# + +# Setup. +libexec="${root}/libexec" +test-socket-tmux new-session -d -s foobar +test-socket-tmux new-session -d -s dude + +# Passes all arguments to Tmux. +assert "${libexec}/tmuxifier-tmux list-sessions -F \"- #{session_name}\"" \ + "- dude\n- foobar" + +# Tear down. +kill-test-server + +# End of tests. +assert_end "tmuxifier-tmux" diff --git a/test/test-helper.sh b/test/test-helper.sh new file mode 100644 index 0000000..ed081be --- /dev/null +++ b/test/test-helper.sh @@ -0,0 +1,87 @@ +[ -n "$TEST_DEBUG" ] && set -x + +resolve_link() { + $(type -p greadlink readlink | head -1) $1 +} + +abs_dirname() { + local cwd="$(pwd)" + local path="$1" + + while [ -n "$path" ]; do + cd "${path%/*}" + local name="${path##*/}" + path="$(resolve_link "$name" || true)" + done + + pwd + cd "$cwd" +} + +# Find and store path to Tmux binary. +TMUX_BIN="$(command -v tmux)" + +# Set testroot variable. +testroot="$(abs_dirname "$BASH_SOURCE")" + +# Set root variable. +root="$(abs_dirname "$testroot/../..")" + +# Set TMUXIFIER environment variable. +TMUXIFIER="$root" + +# Setup PATH environment variable. +PATH="$root/bin:$root/libexec:$PATH" + +# Unset TMUX environment variable, tests assume they're not running within +# Tmux. +unset TMUX + +# Unset various Tmuxifier environment variables to prevent a local install of +# Tmuxifier interfering with tests. +unset TMUXIFIER_LAYOUT_PATH +unset TMUXIFIER_TMUX_OPTS +unset TMUXIFIER_NO_COMPLETE + +# Include assert.sh and stub.sh libraries. +source "${testroot}/assert.sh" +source "${testroot}/stub.sh" + + +# +# Test Helpers +# + +test-socket-tmux() { + export TMUXIFIER_TMUX_OPTS="-L tmuxifier-tests" + "$TMUX_BIN" $TMUXIFIER_TMUX_OPTS $@ +} + +create-test-session() { + session="$1" + if [ -z "$session" ]; then session="test"; fi + + test-socket-tmux new-session -d -s "$session" +} + +kill-test-session() { + local target="$1" + if [ -z "$target" ]; then target="$session"; fi + + test-socket-tmux kill-session -t "$target" +} + +kill-test-server() { + test-socket-tmux kill-server + unset TMUXIFIER_TMUX_OPTS + unset session +} + +test-socket-window-count() { + local list="$(test-socket-tmux list-windows)" + if [ -n "$1" ]; then + echo "$list" | grep $1 | wc -l | awk '{print $1}' + else + echo "$list" | wc -l | awk '{print $1}' + fi +}