pax_global_header00006660000000000000000000000064136755106670014532gustar00rootroot0000000000000052 comment=f7d70036c7edf5405ad5e3336981fcf360a29426 shove-0.8.4/000077500000000000000000000000001367551066700126675ustar00rootroot00000000000000shove-0.8.4/.gitignore000066400000000000000000000000141367551066700146520ustar00rootroot00000000000000*.swp /tmp/ shove-0.8.4/.travis.yml000066400000000000000000000014231367551066700150000ustar00rootroot00000000000000language: sh script: make test os: - linux - osx notifications: slack: rooms: secure: 00NNL6SphnK5pCAjqRz9GzFICGb0IKfcZIEw94f6yGcS+uJXmacTnHGr084irxYuIiOSzk5Yrz7ai6HEUgYIubCmHNnVBuA4iuXQ/kbcH73fC8G4fZh+aphYXUvBRe3rOaUszAxXlmSJ0z6bQ9DqRZsixRYBLPVo55elI9W13RAfZ9ctvGlmyw8plo+jlww7xgBRoTB381YKGeGX1sEZkDBcHgOTGyIaHWsiAwUaVOWkRE5MgsIepZs0aTRsuZGwIzuZ5V5RCJx5ad1qSD8qR/kBCY6lDLr6f38X3/W9AGoQbyhG/rPjzL0xentYx3jRpsUrS8F+sxz2b0Lllv0zy5lT/E5KgemNDLa2C3s9EMXoWc0jA7QqTbDlbFYPnOueQXdn107IxX60WJiu2w3XEnrZJ5CMC1C+YLXV2gxmfTdmKtLirc+4dlXHI20Ydw/eji8vIA+HKu+7BZyqv6CDTrj2edXsQeCh2sWjADqqNvJ3K+JiwDtojNBjs0t/zoKHeI9ANFrtG10MyrsAeP++l79e/ma0x1DF/oRzHibpLaMtOSZ3624NfXEnw54MJ29bTLzNoPFZcy8Wo9f72z3oqv6tPjYLK1KHjPLZu9YvvsN8UX/oIA2Yc4an9BGFyhL5s+9PEu4IYqmEIjhxVjlZbasnBvyN8FUUbom4+PQRr+Q= shove-0.8.4/CHANGELOG.md000066400000000000000000000045661367551066700145130ustar00rootroot00000000000000## 0.8.4 (2020-06-27) Bug Fix: ([#12](https://github.com/progrhyme/shove/pull/12)) - (zsh) `t_success` and `t_error` did not work properly because zshoption `shwordsplit` was not set ## 0.8.3 (2020-05-22) Feature: - export `SHOVE_SHELL` variable to detect running shell inside test scripts ## 0.8.2 (2016-09-25) Improve: - Fix problem of `readlink` to work with relative or nested links #9 ## 0.8.1 (2016-09-19) Feature: - Add new grouping syntax `t::group "$msg" ({ ... })` which is compatible with the old one `T_SUB ((...))` #6 Deprecate: - To use the old grouping syntax `T_SUB "$msg" (( ... ))` is now deprecated ## 0.8.0 (2016-09-19) Feature: - New testing functions #5 - String: `t_present`, `t_blank` - File/directory: `t_exist`, `t_file`, `t_directory`, `t_symlink` - Algebraic: `t_eq`, `t_ne`, `t_gt`, `t_ge`, `t_lt`, `t_le` Bug Fix: - `t_is`, `t_isnt`: Add quote to arguments for separated strings #5 ## 0.7.4 (2016-09-18) Enhance: - Support symlink for `bin/shove` by fetching its path using readlink #4 Internal Change: - Move `lib/t.shrc` to `lib/shove/t.shrc` #4 Change for Dependency: - Support new format of `clam.spec` for [clenv](https://github.com/progrhyme/clenv) v0.3 #4 ## 0.7.3 (2016-08-28) Improve: - Check target file existence of `shove` command #3 BABAROT ## 0.7.2 (2016-05-4) Internal Change: - Add test task by [shpec](https://github.com/rylnd/shpec) - Remove unused variable to get running SHELL ## 0.7.1 (2016-04-26) Minor Improve: - Add indent to temporary test scripts according to grouping of tests. Minor Bug Fix: - Fix format option of `date` command to make temporary test scripts by minutes. ## 0.7.0 (2016-04-23) Feature: - Introduce special syntax `T_SUB (( ... ))` for grouping tests to reduce verbose writings and to make test codes more readable. ## 0.6.1 (2016-04-23) Feature: - Keep temporary test scripts for a while under working directory for troubleshooting. ## 0.6.0 (2016-04-22) Improve: - Add _ksh_ to test targets. - Don't use `local` keyword for variable declaration because it's not POSIX and not supported in _ksh_. ## 0.5.2 (2016-04-22) Change: - `shove` now exits 1 when test fails. Tiny Bug Fix: - "dash" was taken as "sh" at `t_init()`. (But no test uses the shell variable.) ## 0.5.1 (2016-04-22) Improve: - Quote argument string for compatibility. ## 0.5.0 (2016-04-21) Initial release. shove-0.8.4/LICENSE000066400000000000000000000020751367551066700137000ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2016-2020 IKEDA Kiyoshi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. shove-0.8.4/Makefile000066400000000000000000000013061367551066700143270ustar00rootroot00000000000000.PHONY: test shpec release BIN := bin/shove VERSION := $(shell $(BIN) -V) SHELLS := sh bash dash ksh zsh test: @set -e; \ for sh in $(SHELLS); do \ if which $$sh >/dev/null 2>&1; then \ $(BIN) -r t -v -s $$sh; \ else \ echo "$$sh is not found. skip."; \ fi; \ done shpec: @if ! which shpec >/dev/null 2>&1; then \ echo "shpec not found. quit."; \ exit 1; \ fi @set -e; \ for sh in $(SHELLS); do \ if which $$sh >/dev/null 2>&1; then \ echo "# shpec by $$sh"; \ $$sh `which shpec`; \ else \ echo "$$sh is not found. skip."; \ fi; \ done release: git commit -m $(VERSION) git tag -a v$(VERSION) -m $(VERSION) git push origin v$(VERSION) git push origin master shove-0.8.4/README.md000066400000000000000000000110301367551066700141410ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/progrhyme/shove.svg?branch=master)](https://travis-ci.org/progrhyme/shove) # shove A test tool for shell scripts with [TAP](https://testanything.org/) outputs. The name **"shove"** comes from _"shell"_ and _"[prove](http://perldoc.perl.org/prove.html)"_ of Perl. ### Table of Contents * [Screenshots](#screenshots) * [Supported Shells](#supported-shells) * [Install](#install) * [Usage](#usage) * [Options](#options) * [How to write test codes](#how-to-write-test-codes) * [Basics](#basics) * [Grouping](#grouping) * [Authors](#authors) * [License](#license) # Screenshots Pass:
shove-screenshot-pass_01
Fail:
shove-screenshot-fail_01
# Supported Shells - _sh, bash, dash, ksh, zsh_ _ash_ is not tested, but hopefully supposed to work with **shove**. No plan to support _(t)csh_ or _fish_ because they are not POSIX compatible. # Install Just clone this repository or get tarballs from [releases](https://github.com/progrhyme/shove/releases) page. ``` # example snippet to install `shove` mkdir ~/src git clone https://github.com/progrhyme/shove.git ~/src/shove alias shove="$HOME/src/shove/bin/shove" shove -V ``` You can make a symlink of `bin/shove` in your favorite path; i.e. `/usr/local/bin/` or `$HOME/bin/` or any path. Or you can make an alias command like the snippet above. NOTE: Do not change the directory structure because `bin/shove` assumes its libraries exists in `../lib/` directory. # Usage ```sh shove TARGETS [OPTIONS] shove t/foo.t shove t/foo.t t/bar.t -s /bin/bash -v shove -r t/ -v # help shove -h|--help # version shove -V|--version ``` ## Options * `-s|--shell SHELL` : SHELL to execute tests. Default is `$SHELL`. * `-v|--verbose` : verbose output. * `-r|--recursive DIRECTORY` : Search test script files with extension `.t` under the directory # How to write test codes Many test functions get hints from [Test::More](http://perldoc.perl.org/Test/More.html) of Perl. There are some example test codes in [example](example) directory. ## Basics ```sh t_diag "Test for your shell scripts" # Log message visible on the test t_pass # Always Pass t_fail # Always Fail t_ok $exp "exp is true" # [ $exp ] t_ng $exp "exp is false" # [ ! $exp ] t_present $str "str is present" # [ -n "$str" ] t_blank $str "str is blank" # [ -z "$str" ] t_exist $path "path exists" # [ -e "$path" ] t_file $path "path is file" # [ -f "$path" ] t_directory $path "path is directory" # [ -d "$path" ] t_symlink $path "path is symlink" # [ -L "$path" ] t_is $a $b "a is b" # [ "$a" = "$b" ] t_isnt $a $b "a isn't b" # [ "$a" != "$b" ] t_eq $x $y "x == y" # [ $x -eq $y ] t_ne $x $y "x != y" # [ $x -ne $y ] t_gt $x $y "x > y" # [ $x -gt $y ] t_ge $x $y "x >= y" # [ $x -ge $y ] t_lt $x $y "x < y" # [ $x -lt $y ] t_le $x $y "x <= y" # [ $x -le $y ] t_success $cmd "cmd succeeds" # $cmd; [ $? -eq 0 ] t_error $cmd "cmd fails" # $cmd; [ $? -ne 0 ] ``` ## Grouping This feature works like `subtest` of [Test::More](http://perldoc.perl.org/Test/More.html). New special syntax is introduced in v0.8.1: ```sh t_ok $ok t::group "level1 group" ({ t_diag "Comment for level1 tests" t_ok $lv1_ok t::group "level2 group" ({ t_diag "Comment for level2 tests" t_ok $lv2_ok t_is $lv2_a $lv2_b }) }) ``` These codes are the same as following codes: ```sh t_ok $ok ( t_substart "level1 group" t_diag "Comment for level1 tests" t_ok $lv1_ok ( t_substart "level2 group" t_diag "Comment for level2 tests" t_ok $lv2_ok t_is $lv2_a $lv2_b t_subclose ) t_subend "level2 group" t_subclose ) t_subend "level1 group" ``` Tests in group are run in subshell. So you can run them in different context from main tests context. If you want test groups A and B not affect to each other, you have to put them in different groups. **CAUTION:** - **The old grouping syntax `T_SUB (( ... ))` will be unsupported in the future release.** # Authors IKEDA Kiyoshi # License The MIT License (MIT) Copyright (c) 2016-2020 IKEDA Kiyoshi shove-0.8.4/bin/000077500000000000000000000000001367551066700134375ustar00rootroot00000000000000shove-0.8.4/bin/shove000077500000000000000000000037471367551066700145240ustar00rootroot00000000000000#!/usr/bin/env bash set -eu version="0.8.4" current_dir="$(pwd)" bin_path="$0" while [[ -L "$bin_path" ]]; do cd "$(dirname $bin_path)" bin_path="$(readlink ${bin_path##*/})" done bin_dir="$(cd "$(dirname ${bin_path})" && pwd)" lib_dir="$(cd "${bin_dir}/../lib" && pwd)" . "${lib_dir}/shove.bashrc" cd "$current_dir" [[ ${SHOVE_DEBUG:-} ]] && set -x mkdir -p $SHOVE_WORKDIR targets=() # ============================================================ # Parse Arguments for opt in "$@"; do case "${1:-}" in "-s" | "--shell" ) if [[ -z $2 || "$2" =~ ^-+ ]]; then help else SHOVE_SHELL=$2 shift 2 fi ;; "-r" | "--recurse" ) if [[ -z $2 || "$2" =~ ^-+ ]]; then help else targets+=($(find $2 -type f -name '*.t')) shift 2 fi ;; "-v" | "--verbose" ) SHOVE_VERBOSE=1 shift ;; "-h" | "--help" ) help ;; "-V" | "--version" ) echo $version exit 0 ;; * ) if [[ ${1:-} ]]; then targets+=($1) shift fi ;; esac done export SHOVE_SHELL=${SHOVE_SHELL:-$SHELL} SHOVE_SHELL_CMD=$SHOVE_SHELL if [ $SHOVE_DEBUG ]; then SHOVE_SHELL_CMD="$SHOVE_SHELL -x" fi # ============================================================ # Main Entry purge_tmp_files cat <&1 Run tests by $SHOVE_SHELL_CMD ------------------------- EOS t_cnt=0 for tgt in ${targets[@]}; do t_cnt=$((t_cnt + 1)) test_file $tgt done final_report exit $? : <<'__EOF__' =encoding utf8 =head1 NAME B - A test tool for shell scripts =head1 SYNOPSYS shove TARGETS [OPTIONS] shove t/foo.t shove t/bar.t t/bar.t -s /bin/sh -v shove -r t/ -v Help: shove -h|--help Show version: shove -V|--version =head1 DESCRIPTION This script runs target test scripts. =head1 AUTHORS IKEDA Kiyoshi Eprogrhyme@gmail.comE =head1 LICENSE The MIT License (MIT) Copyright (c) 2016-2020 IKEDA Kiyoshi =cut __EOF__ shove-0.8.4/example/000077500000000000000000000000001367551066700143225ustar00rootroot00000000000000shove-0.8.4/example/basic.t000066400000000000000000000003401367551066700155650ustar00rootroot00000000000000t_pass t_fail t_ok "foo" t_ok "-z 'foo'" t_ng "-f 'no-such-file'" t_ng "" t_is 1 1 t_is 1 2 t_is 1 a t_isnt 1 a t_isnt 1 2 t_isnt "a" "a" t_success true t_success "echo 'foo'" t_error false t_error "echo 'foo' | grep 'bar'" shove-0.8.4/example/group-ex.t000066400000000000000000000002341367551066700162540ustar00rootroot00000000000000t_ok ok t_ng ng T_SUB "child group" (( t_ok c1 t_ng c2 t_success foo "command 'foo' fails" T_SUB "grand child" (( t_ok gc1 t_ng gc2 )) )) shove-0.8.4/example/group.t000066400000000000000000000003621367551066700156440ustar00rootroot00000000000000t_ok ok t_ng ng ( t_substart "start child" t_ok c1 t_ng c2 t_success foo "command 'foo' fails" ( t_substart "grand child" t_ok gc1 t_ng gc2 t_subclose ) t_subend "grand child" t_subclose ) t_subend "end child" shove-0.8.4/lib/000077500000000000000000000000001367551066700134355ustar00rootroot00000000000000shove-0.8.4/lib/shove.bashrc000066400000000000000000000057661367551066700157630ustar00rootroot00000000000000SHOVE_SHELL= SHOVE_SHELL_CMD= SHOVE_WORKDIR=${SHOVE_WORK_DIR:-"${HOME}/.shove"} SHOVE_TMPFILE=${SHOVE_WORKDIR}/t_script.$(date +%Y%m%d%H%M).sh SHOVE_KEEPDAYS=${SHOVE_KEEPDAYS:-3} SHOVE_VERBOSE= SHOVE_DEBUG=${SHOVE_DEBUG:-} T_TOTAL=0 T_PASS=0 T_FAIL=0 LF=$(printf '\\\012_') LF=${LF%_} help() { pod2text $0 exit 1 } # indent _lv=0 _ws() { if [ $_lv -gt 0 ]; then printf '%*s' $((_lv * 2)) fi } _add() { echo "$(_ws)$1" >> $tmp } purge_tmp_files() { purge_targets=($(find $SHOVE_WORKDIR -type f -mtime +${SHOVE_KEEPDAYS})) if [[ -z "${purge_targets:-}" ]]; then return fi echo -n "# Purge ${#purge_targets[@]} files..." for pt in ${purge_targets[@]}; do rm -f $pt done echo "done." } test_file() { if [[ ! -f $1 ]]; then echo "$1: Is not a regular file" >&2 exit 1 fi _t=$1 tmp=$SHOVE_TMPFILE.${t_cnt} dat="${tmp}.dat" ## create tmp test script : > $tmp case "$SHOVE_SHELL" in *zsh ) _add ". ${lib_dir}/shove/t.zshrc";; * ) _add ". ${lib_dir}/shove/t.shrc";; esac _add "t_init" if [[ $SHOVE_VERBOSE ]]; then _add "__t_verbose=1" fi cat $_t | while read line; do if [[ "$line" =~ ^[[:space:]]*t::group[[:space:]]*.*\(\{$ ]]; then #echo "# '$line' matches group beginning." _item="$(echo $line | sed -e 's/^t::group //' | sed -e 's/ ({$//')" subtests+=("${_item}") _add '(' : $((_lv += 1)) _add "t_substart ${_item}" elif [[ "$line" =~ ^[[:space:]]*T_SUB[[:space:]]*.*\(\($ ]]; then #echo "# '$line' matches group beginning." _item="$(echo $line | sed -e 's/^T_SUB //' | sed -e 's/ (($//')" subtests+=("${_item}") _add '(' : $((_lv += 1)) _add "t_substart ${_item}" elif [[ "$line" =~ ^[[:space:]]*[\}\)]\)$ ]]; then #echo "# '$line' matches group ending." declare -i num=${#subtests[@]} last=$((num - 1)) _item="${subtests[$last]}" subtests=("${subtests[@]:0:$last}") echo "$(_ws)t_subclose" >> $tmp : $((_lv -= 1)) _add ')' _add "t_subend ${_item}" else _add "$line" fi done _add "echo 1..\$__t_total" _add "t_report $dat" # exec tmp test script echo "$_t ..." set +e $SHOVE_SHELL_CMD $tmp ret=$? set -e data=($(cat $dat)) T_TOTAL=$((T_TOTAL + ${data[0]})) T_PASS=$((T_PASS + ${data[1]})) T_FAIL=$((T_FAIL + ${data[2]})) if [[ $ret = 0 ]]; then echo ok rm -f $tmp else printf "\033[0;31mnot ok\033[0;39m\n" cat <&1 ---- # To reproduce this, run this: # $SHOVE_SHELL [-x] $tmp # Add '-x' to look into it. EOS fi rm -f $dat } final_report() { cat <&1 Test Summary Report ------------------- EOS if [[ $T_FAIL = 0 ]]; then printf "\033[0;32mAll tests successful.\033[0;39m\n" else printf "\033[0;31mSome tests failing.\033[0;39m\n" fi echo "Files=${t_cnt}, Tests=${T_TOTAL}, Successes=${T_PASS}, Failures=${T_FAIL}" if [[ $T_FAIL = 0 ]]; then echo "Result: PASS" return 0 else echo "Result: FAIL" return 1 fi } shove-0.8.4/lib/shove/000077500000000000000000000000001367551066700145615ustar00rootroot00000000000000shove-0.8.4/lib/shove/t.shrc000066400000000000000000000116461367551066700157150ustar00rootroot00000000000000# sh __t_idx=1 __t_total=0 __t_ok=0 __t_ng=0 __t_level=0 __t_verbose="" __t_tmpfile="./.__t_tmp.dat" _t_incr() { _var=$1 _cur_var=$(($_var)) eval ": $(($_var += 1))" unset _var _cur_var } _t_either() { _t_result=$1 _t_incr __t_idx _t_incr __t_total _t_incr $_t_result unset _t_result } _t_incr_level() { : $((__t_level += 1)) } _t_decr_level() { : $((__t_level -= 1)) } _t_put() { if [ $__t_level -gt 0 -a -z "$__t_verbose" ]; then return fi if [ $__t_level -gt 0 ]; then printf '%*s' $((__t_level * 2)) fi printf "$1\n" } t_init() { __t_idx=1 __t_total=0 __t_ok=0 __t_ng=0 } t_diag() { _t_put "# $1" } t_pass() { if [ "$__t_verbose" ]; then _t_put "ok $__t_idx - ${1:-pass}" fi _t_either __t_ok return 0 } t_fail() { _t_put "\033[0;31mnot ok $__t_idx - ${1:-fail}\033[0;39m" _t_either __t_ng return 1 } _t_pass_or_fail() { _sbj="$1" _diag="$2" if eval "$_sbj"; then t_pass "$2" else t_fail "$2" fi } _t_single() { _sbj="$1" _diag="${2:-}" _type=$3 if [ -z "$_diag" ]; then case "$_type" in "ok" ) _diag="ok $_sbj";; "ng" ) _diag="ng $_sbj";; "present" ) _diag="$_sbj is present";; "blank" ) _diag="$_sbj is blank";; "exist" ) _diag="$_sbj exists";; "file" ) _diag="$_sbj is file";; "directory" ) _diag="$_sbj is directory";; "symlink" ) _diag="$_sbj is symlink";; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac fi case "$_type" in "ok" ) _t_pass_or_fail "[ $_sbj ]" "$_diag" ;; "ng" ) _t_pass_or_fail "[ ! $_sbj ]" "$_diag" ;; "present" ) _t_pass_or_fail "[ -n '$_sbj' ]" "$_diag" ;; "blank" ) _t_pass_or_fail "[ -z '$_sbj' ]" "$_diag" ;; "exist" ) _t_pass_or_fail "[ -e '$_sbj' ]" "$_diag" ;; "file" ) _t_pass_or_fail "[ -f '$_sbj' ]" "$_diag" ;; "directory" ) _t_pass_or_fail "[ -d '$_sbj' ]" "$_diag" ;; "symlink" ) _t_pass_or_fail "[ -L '$_sbj' ]" "$_diag" ;; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac unset _sbj _diag _type } t_ok() { _t_single "$1" "${2:-}" ok } t_ng() { _t_single "$1" "${2:-}" ng } t_present() { _t_single "$1" "${2:-}" present } t_blank() { _t_single "$1" "${2:-}" blank } t_exist() { _t_single "$1" "${2:-}" exist } t_file() { _t_single "$1" "${2:-}" file } t_directory() { _t_single "$1" "${2:-}" directory } t_symlink() { _t_single "$1" "${2:-}" symlink } _t_pair() { _lhs="$1" _rhs="$2" _diag="${3:-}" _type=$4 if [ -z "$_diag" ]; then case "$_type" in "is" ) _diag="$_lhs is $_rhs";; "isnt" ) _diag="$_lhs isn't $_rhs";; "eq" ) _diag="$_lhs == $_rhs";; "ne" ) _diag="$_lhs != $_rhs";; "gt" ) _diag="$_lhs > $_rhs";; "ge" ) _diag="$_lhs >= $_rhs";; "lt" ) _diag="$_lhs < $_rhs";; "le" ) _diag="$_lhs <= $_rhs";; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac fi case "$_type" in "is" ) _t_pass_or_fail "[ '$_lhs' = '$_rhs' ]" "$_diag" ;; "isnt" ) _t_pass_or_fail "[ '$_lhs' != '$_rhs' ]" "$_diag" ;; "eq" ) _t_pass_or_fail "[ $_lhs -eq $_rhs ]" "$_diag" ;; "ne" ) _t_pass_or_fail "[ $_lhs -ne $_rhs ]" "$_diag" ;; "gt" ) _t_pass_or_fail "[ $_lhs -gt $_rhs ]" "$_diag" ;; "ge" ) _t_pass_or_fail "[ $_lhs -ge $_rhs ]" "$_diag" ;; "lt" ) _t_pass_or_fail "[ $_lhs -lt $_rhs ]" "$_diag" ;; "le" ) _t_pass_or_fail "[ $_lhs -le $_rhs ]" "$_diag" ;; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac unset _lhs _rhs _diag _type } t_is() { _t_pair "$1" "$2" "${3:-}" is } t_isnt() { _t_pair "$1" "$2" "${3:-}" isnt } t_eq() { _t_pair "$1" "$2" "${3:-}" eq } t_ne() { _t_pair "$1" "$2" "${3:-}" ne } t_gt() { _t_pair "$1" "$2" "${3:-}" gt } t_ge() { _t_pair "$1" "$2" "${3:-}" ge } t_lt() { _t_pair "$1" "$2" "${3:-}" lt } t_le() { _t_pair "$1" "$2" "${3:-}" le } _t_try() { _cmd="$1" _type=$2 _diag="$3" _fail="" $_cmd > $__t_tmpfile 2>&1 _ret=$? if [ "$_type" = "success" ]; then if [ $_ret -ne 0 ]; then _fail=1 fi elif [ $_ret -eq 0 ]; then _fail=1 fi if [ "$_fail" ]; then t_fail "$_diag" cat $__t_tmpfile | while read _t_line; do _t_put "\033[0;31m# ${_t_line}\033[0;39m" done else t_pass "$_diag" fi rm -f $__t_tmpfile unset _cmd _type _diag _fail _ret } t_success() { _cmd="$1" _diag="${2:-}" if [ -z "$_diag" ]; then _diag="$1 success" fi _t_try "$_cmd" "success" "$_diag" unset _cmd _diag } t_error() { _cmd="$1" _diag="${2:-}" if [ -z "$_diag" ]; then _diag="$1 error" fi _t_try "$_cmd" "error" "$_diag" unset _cmd _diag } t_substart() { t_init _t_incr_level t_diag "${1:-substart}" } t_subend() { t_is $? 0 "${1:-subend}" } t_subclose() { _t_put "1..$__t_total" t_report } t_report() { if [ "${1:-}" ]; then printf "$__t_total\t$__t_ok\t$__t_ng\n" > $1 fi return $__t_ng } shove-0.8.4/lib/shove/t.zshrc000066400000000000000000000121461367551066700161030ustar00rootroot00000000000000# zsh __t_idx=1 __t_total=0 __t_ok=0 __t_ng=0 __t_level=0 __t_verbose="" __t_tmpfile="./.__t_tmp.dat" _t_incr() { _var=$1 _cur_var=$(($_var)) eval ": $(($_var += 1))" unset _var _cur_var } _t_either() { _t_result=$1 _t_incr __t_idx _t_incr __t_total _t_incr $_t_result unset _t_result } _t_incr_level() { : $((__t_level += 1)) } _t_decr_level() { : $((__t_level -= 1)) } _t_put() { if [ $__t_level -gt 0 -a -z "$__t_verbose" ]; then return fi if [ $__t_level -gt 0 ]; then printf '%*s' $((__t_level * 2)) fi printf "$1\n" } t_init() { __t_idx=1 __t_total=0 __t_ok=0 __t_ng=0 } t_diag() { _t_put "# $1" } t_pass() { if [ "$__t_verbose" ]; then _t_put "ok $__t_idx - ${1:-pass}" fi _t_either __t_ok return 0 } t_fail() { _t_put "\033[0;31mnot ok $__t_idx - ${1:-fail}\033[0;39m" _t_either __t_ng return 1 } _t_pass_or_fail() { _sbj="$1" _diag="$2" if eval "$_sbj"; then t_pass "$2" else t_fail "$2" fi } _t_single() { _sbj="$1" _diag="${2:-}" _type=$3 if [ -z "$_diag" ]; then case "$_type" in "ok" ) _diag="ok $_sbj";; "ng" ) _diag="ng $_sbj";; "present" ) _diag="$_sbj is present";; "blank" ) _diag="$_sbj is blank";; "exist" ) _diag="$_sbj exists";; "file" ) _diag="$_sbj is file";; "directory" ) _diag="$_sbj is directory";; "symlink" ) _diag="$_sbj is symlink";; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac fi case "$_type" in "ok" ) _t_pass_or_fail "[ $_sbj ]" "$_diag" ;; "ng" ) _t_pass_or_fail "[ ! $_sbj ]" "$_diag" ;; "present" ) _t_pass_or_fail "[ -n '$_sbj' ]" "$_diag" ;; "blank" ) _t_pass_or_fail "[ -z '$_sbj' ]" "$_diag" ;; "exist" ) _t_pass_or_fail "[ -e '$_sbj' ]" "$_diag" ;; "file" ) _t_pass_or_fail "[ -f '$_sbj' ]" "$_diag" ;; "directory" ) _t_pass_or_fail "[ -d '$_sbj' ]" "$_diag" ;; "symlink" ) _t_pass_or_fail "[ -L '$_sbj' ]" "$_diag" ;; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac unset _sbj _diag _type } t_ok() { _t_single "$1" "${2:-}" ok } t_ng() { _t_single "$1" "${2:-}" ng } t_present() { _t_single "$1" "${2:-}" present } t_blank() { _t_single "$1" "${2:-}" blank } t_exist() { _t_single "$1" "${2:-}" exist } t_file() { _t_single "$1" "${2:-}" file } t_directory() { _t_single "$1" "${2:-}" directory } t_symlink() { _t_single "$1" "${2:-}" symlink } _t_pair() { _lhs="$1" _rhs="$2" _diag="${3:-}" _type=$4 if [ -z "$_diag" ]; then case "$_type" in "is" ) _diag="$_lhs is $_rhs";; "isnt" ) _diag="$_lhs isn't $_rhs";; "eq" ) _diag="$_lhs == $_rhs";; "ne" ) _diag="$_lhs != $_rhs";; "gt" ) _diag="$_lhs > $_rhs";; "ge" ) _diag="$_lhs >= $_rhs";; "lt" ) _diag="$_lhs < $_rhs";; "le" ) _diag="$_lhs <= $_rhs";; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac fi case "$_type" in "is" ) _t_pass_or_fail "[ '$_lhs' = '$_rhs' ]" "$_diag" ;; "isnt" ) _t_pass_or_fail "[ '$_lhs' != '$_rhs' ]" "$_diag" ;; "eq" ) _t_pass_or_fail "[ $_lhs -eq $_rhs ]" "$_diag" ;; "ne" ) _t_pass_or_fail "[ $_lhs -ne $_rhs ]" "$_diag" ;; "gt" ) _t_pass_or_fail "[ $_lhs -gt $_rhs ]" "$_diag" ;; "ge" ) _t_pass_or_fail "[ $_lhs -ge $_rhs ]" "$_diag" ;; "lt" ) _t_pass_or_fail "[ $_lhs -lt $_rhs ]" "$_diag" ;; "le" ) _t_pass_or_fail "[ $_lhs -le $_rhs ]" "$_diag" ;; * ) echo "Unknown type: ${_type}" >&2; exit 1;; esac unset _lhs _rhs _diag _type } t_is() { _t_pair "$1" "$2" "${3:-}" is } t_isnt() { _t_pair "$1" "$2" "${3:-}" isnt } t_eq() { _t_pair "$1" "$2" "${3:-}" eq } t_ne() { _t_pair "$1" "$2" "${3:-}" ne } t_gt() { _t_pair "$1" "$2" "${3:-}" gt } t_ge() { _t_pair "$1" "$2" "${3:-}" ge } t_lt() { _t_pair "$1" "$2" "${3:-}" lt } t_le() { _t_pair "$1" "$2" "${3:-}" le } _t_try() { local _cmd="$1" local _type=$2 local _diag="$3" local _fail="" local opt_shwordsplit=$(setopt | grep shwordsplit || true) if [[ -z "$opt_shwordsplit" ]]; then setopt shwordsplit fi $_cmd > $__t_tmpfile 2>&1 local _ret=$? if [[ -z "$opt_shwordsplit" ]]; then unsetopt shwordsplit fi if [ "$_type" = "success" ]; then if [ $_ret -ne 0 ]; then _fail=1 fi elif [ $_ret -eq 0 ]; then _fail=1 fi if [ "$_fail" ]; then t_fail "$_diag" cat $__t_tmpfile | while read _t_line; do _t_put "\033[0;31m# ${_t_line}\033[0;39m" done else t_pass "$_diag" fi rm -f $__t_tmpfile } t_success() { _cmd="$1" _diag="${2:-}" if [ -z "$_diag" ]; then _diag="$1 success" fi _t_try "$_cmd" "success" "$_diag" unset _cmd _diag } t_error() { _cmd="$1" _diag="${2:-}" if [ -z "$_diag" ]; then _diag="$1 error" fi _t_try "$_cmd" "error" "$_diag" unset _cmd _diag } t_substart() { t_init _t_incr_level t_diag "${1:-substart}" } t_subend() { t_is $? 0 "${1:-subend}" } t_subclose() { _t_put "1..$__t_total" t_report } t_report() { if [ "${1:-}" ]; then printf "$__t_total\t$__t_ok\t$__t_ng\n" > $1 fi return $__t_ng } shove-0.8.4/shpec/000077500000000000000000000000001367551066700137715ustar00rootroot00000000000000shove-0.8.4/shpec/basic_shpec.sh000066400000000000000000000034321367551066700165720ustar00rootroot00000000000000. lib/shove/t.shrc test_equal() { sbj="$1" it "$sbj = $2" _sbj=$(($sbj)) assert equal $_sbj $2 end unset sbj } should_pass() { it "$1" assert equal $__t_ok 1 assert equal $__t_ng 0 end } should_fail() { it "$1" assert equal $__t_ok 0 assert equal $__t_ng 1 end } describe "t_init" t_init test_equal __t_idx 1 for var in total ok ng level; do test_equal __t_${var} 0 done unset var end describe "t_pass" t_init t_pass test_equal __t_idx 2 test_equal __t_total 1 test_equal __t_ok 1 test_equal __t_ng 0 end describe "t_fail" t_init t_fail >/dev/null test_equal __t_idx 2 test_equal __t_total 1 test_equal __t_ok 0 test_equal __t_ng 1 end describe "t_ok" t_init t_ok "ok" should_pass "ok is ok" t_init t_ok "" >/dev/null 2>&1 should_fail " is not ok" end describe "t_ng" t_init t_ng "ng" >/dev/null 2>&1 should_fail "ng is not ng" t_init t_ng "" should_pass " is ng" end describe "t_is" t_init t_is 1 1 should_pass "1 is 1" t_init t_is "aaa" "aaa" should_pass "aaa is aaa" t_init t_is 1 0 >/dev/null 2>&1 should_fail "1 is not 0" t_init t_is "aaa" "aab" >/dev/null 2>&1 should_fail "aaa is not aab" end describe "t_isnt" t_init t_isnt 1 1 >/dev/null 2>&1 should_fail "1 is 1" t_init t_isnt "aaa" "aaa" >/dev/null 2>&1 should_fail "aaa is aaa" t_init t_isnt 1 0 should_pass "1 isn't 0" t_init t_isnt "aaa" "aab" should_pass "aaa isn't aab" end describe "t_success" t_init t_success true should_pass "true succeeds" t_init t_success false >/dev/null 2>&1 should_fail "false fails" end describe "t_error" t_init t_error true >/dev/null 2>&1 should_fail "true doesn't fail" t_init t_error false should_pass "false fails" end shove-0.8.4/t/000077500000000000000000000000001367551066700131325ustar00rootroot00000000000000shove-0.8.4/t/algebraic.t000066400000000000000000000001331367551066700152250ustar00rootroot00000000000000t_eq 1 1 t_ne 1 2 t_gt 2 1 t_ge 2 2 t_ge 3 2 t_lt 1 2 t_le 1 2 t_le 2 2 # vim:set ft=sh : shove-0.8.4/t/basic.t000066400000000000000000000005621367551066700144030ustar00rootroot00000000000000t_pass t_ok "foo" "'foo' is, ok." t_ok "-e ." ". exists" t_ng "" "blank, is ng." t_ng "-f ." ". is not file" t_present "foo bar" "'foo bar' is, ok." t_blank "" "blank, is blank." t_is 1 1 t_is a a t_is "a b" "a b" "a eq b" t_isnt 1 a "1 isnt a" t_isnt 1 2 t_isnt "a" "b" "'a' isn't 'b'" t_isnt "a b" "ab" t_success true "true/ succeeds" t_error false # vim:set ft=sh : shove-0.8.4/t/command.t000066400000000000000000000001251367551066700147330ustar00rootroot00000000000000t_success true t_success "echo ok" t_error false t_error "no-such-command arg1 arg2" shove-0.8.4/t/file.t000066400000000000000000000003511367551066700142350ustar00rootroot00000000000000t_exist . t_file $0 t_directory . T_SUB "Test symlink" (( tmpdir=tmp/file-test mkdir $tmpdir touch $tmpdir/testfile ln -s $tmpdir/testfile $tmpdir/testlink t_symlink $tmpdir/testlink rm -rf $tmpdir )) # vim:set ft=sh : shove-0.8.4/t/group-ex.t000066400000000000000000000003131367551066700150620ustar00rootroot00000000000000t_ok ok T_SUB "child group 1" (( t_ok c1 T_SUB "grand child 1" (( t_ok gc1 )) t::group "grand child 2" ({ t_ok gc2 }) )) t::group "child child 2" ({ t_ok c2 }) # vim:set ft=sh : shove-0.8.4/t/group.t000066400000000000000000000002571367551066700144570ustar00rootroot00000000000000t_ok ok ( t_substart "child group" t_ok c1 ( t_substart "grand child" t_ok gc1 t_subclose ) t_subend "grand child" t_subclose ) t_subend "child group" shove-0.8.4/tmp/000077500000000000000000000000001367551066700134675ustar00rootroot00000000000000shove-0.8.4/tmp/.keep000066400000000000000000000000001367551066700144020ustar00rootroot00000000000000