Skip to content

Commit

Permalink
add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nwmcsween committed Jun 30, 2021
1 parent 364c026 commit 5e5b6de
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 96 deletions.
11 changes: 11 additions & 0 deletions .shellspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--require spec_helper
## Default kcov (coverage) options
# --kcov-options "--include-path=. --path-strip-level=1"
# --kcov-options "--include-pattern=.sh"
# --kcov-options "--exclude-pattern=/.shellspec,/spec/,/coverage/,/report/"

## Example: Include script "myprog" with no extension
# --kcov-options "--include-pattern=.sh,myprog"

## Example: Only specified files/directories
# --kcov-options "--include-pattern=myprog,/lib/"
3 changes: 2 additions & 1 deletion backlog.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Todo
----
* Quote function
* Create tests, hopefully with a 'framework' that doesn't suck
* create str_icat - string idempotent concatenation, e.g. PATH=$PATH:foo will have foo once even if previously set.
9 changes: 2 additions & 7 deletions cmd.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
if [ -z "$CMD_SH" ]; then
CMD_SH=1
#!/bin/sh

cmd_exists() {
cmd=$1

type "$cmd" >/dev/null 2>&1;
type "$1" > /dev/null 2>&1
}

fi
36 changes: 19 additions & 17 deletions compiler.sh
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
if [ -z "$COMPILER_SH" ]; then
COMPILER_SH=1
#!/bin/sh

cc() {
cc=$1 file=$2; args=$3
cc_is_pp() {
pp=$1; file=$2; cc=${3:-${CC:-cc}}

$cc $args -o /dev/null "$file" > /dev/null 2>&1;
}
! type "$cc" > /dev/null 2>&1 && printf "%s\n" "\$1 with value $cc not found" >&2 && return 2
[ ! -f "$file" ] && printf "%s\n" "\$2 with value $file doesn't exist" >&2 && return 3

cc_is_pp() {
cc=$1; file=$2; pp_sym=$3
printf "typedef int x;\n#if !%s\n#error yes\n#endif\n" "$pp" > "$file"
$cc -c -o /dev/null "$file" > /dev/null 2>&1 || return 1

printf "typedef int x;\n#if \"%s\"\n#error\n#endif" "$pp_sym" > "$file"
$cc "$file" "-c"
return 0
}

cc_is_lflag() {
cc=$1; file=$2; lflag=$3
cc_is_ldflag() {
flag=$1; file=$2; cc=${3:-${CC:-cc}}

! type "$cc" > /dev/null 2>&1 && printf "%s\n" "\$1 with value $cc not found" >&2 && exit 1
[ ! -f "$file" ] && printf "%s\n" "\$2 with value $file doesn't exist" >&2 && exit 1

printf "typedef int x;\n" > "$file"
$cc "$file" "-nostdlib -shared $lflag"
$cc "$file" -c -o /dev/null "-nostdlib -shared $flag" > /dev/null 2>&1
}

cc_is_flag() {
cc=$1; file=$2; flag=$3
flag=$1; file=$2; cc=${3:-${CC:-cc}}

! type "$cc" > /dev/null 2>&1 && printf "%s\n" "\$1 with value $cc not found" >&2 && exit 1
[ ! -f "$file" ] && printf "%s\n" "\$2 with value $file doesn't exist" >&2 && exit 1

printf "typedef int x;\n" > "$file"
$cc "$file" "-c $flag"
$cc "$file" -c -o /dev/null "$flag" > /dev/null 2>&1
}

fi
56 changes: 40 additions & 16 deletions file.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,48 @@
if [ -z "$FILE_SH" ]; then
FILE_SH=1
#!/bin/sh

file_tmp() {
src=$1; dir=$2; ext=$3
fl_tmp() {
suffix=; quiet=0
file=; dir="/tmp"; tries=100

set -C
i=0
usage=$(cat <<'EOF'
Usage: $0 [OPTION]... [DIR]
Create a temporaray file in [DIR:-/tmp]
-q, supress stderr output
-s SUFFUX, append suffix SUFFIX
EOF
)

while [ "$i" -le 50 ]; do i=$((i + 1))
if eval "$src=\"\${dir}/tmp-\$\$-\$PPID-\$i.\$ext\" 2>|\
/dev/null > \"\${dir}/tmp-\$\$-\$PPID-\$i.\$ext\""; then
i=0
break
fi
while [ $# -gt 0 ]; do
case "$1" in
-s) [ "$2" ] && suffix=$2 && shift || echo "$usage";;
-q) quiet=1;;
-h) printf "%s\n" "$usage" && exit 0;;
--) shift && break;;
*) break;;
esac
shift
done

[ "$1" ] && dir="$1"

if [ "$suffix" ]; then
printf "%s" "$suffix" | grep -q '^\.' || suffix=".$suffix"
fi

if [ ! -d "$dir" ]; then
[ "$quiet" -ne 1 ] && printf "%s\n" "\$1 with value $dir isn't a valid directory" 1>&2
return 2
fi

set -C
i=0
while [ $((i = i + 1)) -le "$tries" ]; do
file="${dir}/tmp-$$-$PPID-$i${suffix}"
[ ! -f "$file" ] && touch "$file" > /dev/null 1>&2 && break
done
set +C
trap 'rm "$src"' EXIT INT QUIT TERM HUP
[ "$i" -gt "$tries" ] && return 1

test "$i" -eq 0 && return 0 || return 1
printf "%s\n" "$file"
return 0
}

fi
10 changes: 0 additions & 10 deletions io.sh

This file was deleted.

27 changes: 12 additions & 15 deletions path.sh
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
if [ -z "$PATH_SH" ]; then
PATH_SH=1
#!/bin/sh

path_resolve() {
dst="$1"; src="$2"

eval "$dst=\"\$(ls -l \$src | awk '{ printf \$NF }')\"" && return 0

return 1
path_absolute() {
printf "%s" "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}

path_real() {
src="$1"
path_relative() {
dst="$(cd $(dirname $1); pwd -P)"; src="$(cd $(dirname $1); pwd -P)"
up=

cd $(dirname \"$src\")
printf "%s" "$(pwd)/$(basename \"$src\")"
cd -
}
while [ "${dst#$src/}" = "$dst" ]; do
src=$(dirname "$src")
up="../$up"
done

fi
printf "%s" "$up${dst#$src}/"
}
50 changes: 42 additions & 8 deletions process.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,45 @@
if [ "$PROC_SH" ]; then
PROC_SH=1
#!/bin/sh

proc_abort() {
args="$*"
pr_dosh() {
file=; retries=3; quiet=0
n=0

printf "%s\n" "$args"
exit 1
}
usage=$(cat <<'EOF'
Usage: $0 [OPTION]... [FILES]
Run shell scripts in [FILES]
-q, supress stderr output
-r RETRIES, number of retries per file to run (default $retries)
EOF
)

while [ $# -gt 0 ]; do
case "$1" in
-r)
if [ -n "$2" ]; then
retries="$2"
shift
else
echo "$usage"
fi
;;
-q) quiet=1;;
-h) printf "%s\n" "$usage" && exit 0;;
--) shift && break;;
*) break;;
esac
shift
done

fi
for file in "$@"; do
printf "Running %s\n" "$file"
[ ! -f "$file" ] && [ "$quiet" -ne 0 ] && printf "Argument %s isn't a file\n" "$file" 2>&1
while ! ( trap - INT QUIT TSTP; . $file ) && [ $((n = n + 1)) -le "$retries" ]; do
if [ "$quiet" -eq 0 ]; then
printf "Failed to run %s: %s/%s times\n" "$file" "$n" "$retries" 2>&1
fi
done
[ "$n" -gt "$retries" ] && printf "Failed to %s\n" "$file" && return 2
done

return 0
}
5 changes: 1 addition & 4 deletions regex.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
if [ -z "$REGEX_SH" ]; then
REGEX_SH=1
#!/bin/sh

rx_match() {
needle="$1"; haystack="$2"

eval "case \"\$haystack\" in $needle) return 0;; *) return 1;; esac";
}

fi
16 changes: 16 additions & 0 deletions spec/cmd_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
% FIXTURES: "$SHELLSPEC_HELPERDIR/fixtures"

Describe 'cmd.sh'
Before SHELLSPEC_LOAD_PATH="$FIXTURES"
Include ./cmd.sh
Describe 'cmd_exists'
It 'succeeds on a valid command'
When call cmd_exists "["
The status should be success
End
It 'fails on an invalid command'
# When call cmd_exists "/dev/null"
# The status should be failure
End
End
End
35 changes: 35 additions & 0 deletions spec/compiler_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
% FIXTURES: "$SHELLSPEC_HELPERDIR/fixtures"

Describe 'compiler.sh'
before() {
. $SHELLSPEC_PROJECT_ROOT/file.sh
export SHELLSPEC_LOAD_PATH="$FIXTURES"
tmp=$(fl_tmp -s .c)
}
after() {
rm -rf $tmp
}
BeforeAll 'before'
AfterAll 'after'
Include ./compiler.sh
Describe 'cc_is_pp'
It 'succeeds when given a valid preprocessor symbol'
When run cc_is_pp '__GNUC__' "$tmp"
The status should be success
End
It 'fails when given an invalid preprocessor symbol'
When run cc_is_pp 'FOOBAR' "$tmp"
The status should be failure
End
End
Describe 'cc_is_flag'
It 'succeeds when given a valid flag'
When run cc_is_flag '-Wall' "$tmp"
The status should be success
End
It 'fails when given an invalid flag'
When run cc_is_flag '-null' "$tmp"
The status should be failure
End
End
End
32 changes: 32 additions & 0 deletions spec/file_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
% FIXTURES: "$SHELLSPEC_HELPERDIR/fixtures"

Describe 'file.sh'
Before SHELLSPEC_LOAD_PATH="$FIXTURES"
Include ./file.sh
Describe 'fl_tmp'
It 'supresses stderr with -q switch'
When run fl_tmp -q /dev/null
The status should be failure
End
It 'adds a suffix with -s switch'
When run fl_tmp -s '.c'
The stdout should end with ".c"
The status should be success
End
It 'outputs help info with -h switch'
When run fl_tmp -h
The stdout should start with "Usage"
The status should be success
End
It 'fails if given an invalid directory'
When run fl_tmp /dev/null
The stderr should equal "\$1 with value /dev/null isn't a valid directory"
The status should be failure
End
It 'creates a temparary file and succeeds with no args'
When run fl_tmp
The stdout should start with "/tmp/"
The status should be success
End
End
End
2 changes: 2 additions & 0 deletions spec/fixtures/failure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exit 1
2 changes: 2 additions & 0 deletions spec/fixtures/success.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
echo hello world
13 changes: 13 additions & 0 deletions spec/process_spec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
% FIXTURES: "$SHELLSPEC_HELPERDIR/fixtures"

Describe 'process.sh'
Before SHELLSPEC_LOAD_PATH="$FIXTURES"
Include ./process.sh
Describe 'pr_dosh'
It 'retries 6 times given arg'
When call pr_dosh -r 6 "$FIXTURES/failure.sh"
The stdout should match pattern "*failure.sh"
The status should equal 2
End
End
End
24 changes: 24 additions & 0 deletions spec/spec_helper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# shellcheck shell=sh

# Defining variables and functions here will affect all specfiles.
# Change shell options inside a function may cause different behavior,
# so it is better to set them here.
# set -eu

# This callback function will be invoked only once before loading specfiles.
spec_helper_precheck() {
# Available functions: info, warn, error, abort, setenv, unsetenv
# Available variables: VERSION, SHELL_TYPE, SHELL_VERSION
: minimum_version "0.28.1"
}

# This callback function will be invoked after a specfile has been loaded.
spec_helper_loaded() {
:
}

# This callback function will be invoked after core modules has been loaded.
spec_helper_configure() {
# Available functions: import, before_each, after_each, before_all, after_all
: import 'support/custom_matcher'
}
Loading

0 comments on commit 5e5b6de

Please sign in to comment.