From 3df8f4bd03cc2d087c1abfb340e9d2949e2f91ad Mon Sep 17 00:00:00 2001 From: merakor Date: Tue, 5 Jan 2021 11:40:43 +0000 Subject: shellspec: add unit tests FossilOrigin-Name: cc6f029081294c10be43ba51dedecb1997cc653215b587a566c0a527705162ab --- .gitignore | 6 ++ .shellspec | 3 + CHANGELOG.md | 1 + spec/01_lib_spec.sh | 201 ++++++++++++++++++++++++++++++++++++++++++++++++ spec/02_src_spec.sh | 93 ++++++++++++++++++++++ spec/03_contrib_spec.sh | 67 ++++++++++++++++ tests/etc/cpt-hook | 1 + tests/hook-file | 3 + 8 files changed, 375 insertions(+) create mode 100644 .shellspec create mode 100644 spec/01_lib_spec.sh create mode 100644 spec/02_src_spec.sh create mode 100644 spec/03_contrib_spec.sh create mode 120000 tests/etc/cpt-hook create mode 100644 tests/hook-file diff --git a/.gitignore b/.gitignore index efe4341..e9c6fcb 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,9 @@ cpt-lib ### Texinfo ### *.info + +### Shellspec files ### +/.shellspec-local +/.shellspec-quick.log +/report/ +/coverage/ diff --git a/.shellspec b/.shellspec new file mode 100644 index 0000000..77d79cf --- /dev/null +++ b/.shellspec @@ -0,0 +1,3 @@ +--kcov-options "--include-pattern=cpt-lib" +--kcov-options "--include-pattern=/src/cpt,/contrib/cpt-" +--kcov-options "--exclude-pattern=.in" diff --git a/CHANGELOG.md b/CHANGELOG.md index 9445f59..b5212bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ UNRELEASED ### Added - Added basic installation instructions to an `INSTALL` file. +- Added code coverage and unit tests using `shellspec`. ### Changed - All `src` scripts now exit with success after being called with `--help`. diff --git a/spec/01_lib_spec.sh b/spec/01_lib_spec.sh new file mode 100644 index 0000000..6deef06 --- /dev/null +++ b/spec/01_lib_spec.sh @@ -0,0 +1,201 @@ +# shellcheck disable=2091 + +Describe 'CPT Library' + export CPT_COLOR=0 + Include ./src/cpt-lib + Describe '--help' + It 'prints usage information when called as a standalone script' + When run script src/cpt-lib --help + The word 1 of output should eq "usage:" + End + End + Describe 'version()' + VERSION=$(grep VERSION ./config.rc | sed 's/.* //g') + It 'prints version information' + When run script src/cpt-lib version + The stderr should eq "-> Carbs Packaging Tools $VERSION" + End + End + Describe 'text functions' + Describe 'out()' + It 'outputs a message with every argument triggering a newline' + When call out Line1 Line2 + The output should eq "$(printf 'Line1\nLine2\n')" + End + End + + Describe 'log()' + Parameters + "#1" "-> hello " hello + "#2" "-> hello world" hello world + "#3" "hello test world" test world hello + End + It "prints a message prettily ($1)" + When call log "$3" "$4" "$5" + The stderr should eq "$2" + End + End + + Describe 'die()' + It "exits the script by printing the given message" + When run script src/cpt-lib die "Exiting" + The stderr should eq "!> Exiting " + The status should be failure + End + End + + Describe 'warn()' + Parameters + "#1" "WARNING notice " "notice" + "#2" "WARNING package not found" "package" "not found" + "#3" "!!! package not found" "package" "not found" "!!!" + End + It "displays a warning message ($1)" + When call warn "$3" "$4" "$5" + The stderr should eq "$2" + End + End + + Describe 'contains()' + Parameters + "#1" "foo bar" baz failure + "#2" "foo bar baz" baz success + End + It "checks whether the given string list contains a word ($1)" + When call contains "$2" "$3" + The status should be "$4" + End + End + + Describe 'pop()' + It "removes the first item from the following items" + When call pop baz from foo bar baz + The output should eq " foo bar " + End + End + + Describe 'regesc()' + Parameters + "#1" '^[\\test$' '\^\[\\\\test\$' + "#2" '\.*$' '\\\.\*\$' + End + It "escapes POSIX BRE sequences ($1)" + When call regesc "$2" + The output should eq "$3" + End + End + + Describe 'sepchar()' + It 'seperates the output of given string' + When call sepchar test + The output should eq "$(printf 't\ne\ns\nt\n')" + End + End + End + + + Describe 'helper functions' + Describe '_seq()' + It 'counts to the given number' + When call _seq 3 + The output should eq " 1 2 3 " + End + End + + Describe '_stat()' + It 'outputs the owner of the given file' + When call _stat README + The output should eq "$(id -un)" + End + End + + Describe '_readlinkf()' + mklink() { :> testfile; ln -s testfile testfile2 ;} + rmlink() { rm -f testfile testfile2 ;} + RPWD=$(cd -P .||:; printf %s "$PWD") + Before mklink + After rmlink + Parameters + "#1" . "$RPWD" + "#2" "$PWD/testfile2" "$RPWD/testfile" + End + It "outputs the real location of the given file ($1)" + When call _readlinkf "$2" + The output should eq "$3" + End + End + + Describe 'sh256()' + It 'outputs an sha256 digest of the given file' + # This should cover our bases for a long time. + When call sh256 .editorconfig + The output should eq "da42265df733ca05a08d77405c35aa3dd5b8b7fefcc2da915f508067a49351da .editorconfig" + End + End + End + + Describe 'system functions' + Describe 'as_root()' + as_root_env() { user=$1 as_root env ;} + Parameters + root + "$(id -un)" + End + It "runs the given command as user: '$1'" + When call as_root_env "$1" + The output should not eq "" + The stderr should not eq "" + The status should be success + End + End + End + + Describe 'package functions' + Describe 'run_hook()' + CPT_HOOK=$PWD/tests/hook-file + CPT_ROOT=$PWD/tests + It "runs the given hook file" + When call run_hook 1 test-package destination + The stderr should eq "-> test-package Running 1 hook" + The output should eq "$CPT_HOOK 1 test-package destination" + End + It "doesn't log 'running hook' if no package is given" + When call run_hook 2 '' destination + The stderr should eq "" + The output should eq "$CPT_HOOK 2 null destination" + End + It "uses the /etc/cpt-hook file of the root when called with a fourth arg" + When call run_hook 3 cpt destdir root + The stderr should eq "-> cpt Running 3 hook" + The output should eq "$CPT_ROOT/etc/cpt-hook 3 cpt destdir" + The variable CPT_HOOK should eq "$PWD/tests/hook-file" + End + It "returns with success even when the file doesn't exist" + CPT_HOOK=$PWD/some-non-existent-file + When call run_hook 4 thiswillnotrun + The variable CPT_HOOK should not be exist + The stderr should eq "" + The status should be success + End + It "restores the \$CPT_HOOK variable when called with root" + CPT_ROOT=$PWD/nonexistentdir + When call run_hook 5 cpt dest root + The variable CPT_ROOT should not be exist + The stderr should eq "" + The status should be success + The variable CPT_HOOK should eq "$PWD/tests/hook-file" + End + End + Describe 'create_cache()' + After pkg_clean + It 'creates cache directories' + When call create_cache + The variable mak_dir should be a directory + End + It "doesn't create build directories if an argument is passed" + When call create_cache nobuild + The variable mak_dir should be undefined + End + End + End +End diff --git a/spec/02_src_spec.sh b/spec/02_src_spec.sh new file mode 100644 index 0000000..626c7b3 --- /dev/null +++ b/spec/02_src_spec.sh @@ -0,0 +1,93 @@ +Describe 'Main toolchain' + export PATH=$PWD/src:$PATH + + Describe 'cpt' + + Describe '--version' + VERSION=$(grep VERSION config.rc | sed 's/.* //g') + It 'outputs cpt version' + When run script src/cpt --version + The stderr should eq "-> Carbs Packaging Tools $VERSION" + End + End + + Describe '--help' + It 'outputs usage information' + When run script src/cpt --help + The line 1 of stderr should eq "-> Carbs Packaging Tool " + End + End + + Describe 'prefix completion' + Describe 'single key expansion' + Parameters + a alternatives + b build + c checksum + d download + i install + l list + r remove + s search + u update + End + It "completes '$1' single key prefix to '$2'" + When run script src/cpt "$1" --help + The status should eq 0 + The word 1 of line 1 should eq "usage:" + The word 2 of line 1 should eq "cpt-$2" + End + End + Describe 'shortcut expansion' + Parameters + bi "build install" + cbi "checksum build install" + End + It "expands the '$1' shortcut to '$2'" + When run script src/cpt "$1" --help + The status should be success + The word 2 of line 1 should eq "cpt-${2%% *}" + End + End + End + + + It 'fails when a given subcommand is not valid' + When run script src/cpt somerandomcommand + The stderr should eq "!> 'cpt somerandomcommand' is not a valid command " + The status should be failure + End + End + + Describe 'cpt-list' + no_db_dir() { + # Return 0 if database directory is empty (or doesn't exist) + # shellcheck disable=2012 + count=$(ls -1 "$CPT_ROOT/var/db/cpt/installed" 2>/dev/null | wc -l) + [ "$count" -eq 0 ] + } + Skip if "there are no installed packages" no_db_dir + It 'lists all packages when called without arguments' + When run script src/cpt-list + The lines of output should eq "$(ls -1 "$CPT_ROOT/var/db/cpt/installed" 2>/dev/null | wc -l)" + End + for firstpkg in "$CPT_ROOT/var/db/cpt/installed/"*; do firstpkg=${firstpkg##*/}; break; done + It 'only lists the packages given in the arguments' + When run script src/cpt-list "$firstpkg" + The word 1 of stdout should eq "$firstpkg" + End + It 'fails when the package supplied in the arguments does not exist' + When run script src/cpt-list somerandompackage + The stderr should eq "-> somerandompackage not installed" + The status should be failure + End + Parameters + "$firstpkg" success + somerandompackage failure + End + It "can print a $2 message with 'cpt-list --check PKG TRUE FALSE'" + When run script src/cpt-list --check "$1" success failure + The output should eq "$2" + End + End +End diff --git a/spec/03_contrib_spec.sh b/spec/03_contrib_spec.sh new file mode 100644 index 0000000..c817b2f --- /dev/null +++ b/spec/03_contrib_spec.sh @@ -0,0 +1,67 @@ +Describe 'contrib scripts' + no_db_dir() { + # Return 0 if database directory is empty (or doesn't exist) + # shellcheck disable=2012 + count=$(ls -1 "$CPT_ROOT/var/db/cpt/installed" 2>/dev/null | wc -l) + [ "$count" -eq 0 ] + } + Skip if "there are no installed packages" no_db_dir + + for firstpkg in "$CPT_ROOT/var/db/cpt/installed/"*; do + firstpkg=${firstpkg##*/}; break + done + + Describe 'cpt-cat' + It 'outputs the file contents in the given package directory' + When run script ./contrib/cpt-cat "$firstpkg" + The stdout should not eq "" + The line 1 of stderr should eq "$(printf '\033[1mbuild:\033[m\n')" + End + It "uses the current directory for the package name if none is supplied (${PWD##*/})" + When run script ./contrib/cpt-cat + The stdout should not eq "" + The line 1 of stderr should eq "$(printf '\033[1mbuild:\033[m\n')" + End + It "exits with error if the package isn't installed" + When run script ./contrib/cpt-cat somerandompackage + The stderr should eq "-> somerandompackage not installed" + The status should be failure + End + It "prints usage information when called with --help" + When run script ./contrib/cpt-cat --help + The word 1 of stdout should eq "usage:" + The status should be success + End + Parameters + build + checksums + manifest + version + End + It "outputs the given file contents in the given package directory ($1)" + When run script ./contrib/cpt-cat "$firstpkg" "$1" + The stdout should eq "$(cat "$CPT_ROOT/var/db/cpt/installed/$firstpkg/$1")" + The stderr should eq "$(printf '\033[1m%s:\033[m\n' "$1")" + End + It "outputs the given file contents for the name of the current directory (${PWD##*/} - $1)" + When run script ./contrib/cpt-cat "" "$1" + The stdout should eq "$(cat "$CPT_ROOT/var/db/cpt/installed/${PWD##*/}/$1")" + The stderr should eq "$(printf '\033[1m%s:\033[m\n' "$1")" + End + End + Describe 'cpt-depends' + It "outputs the dependencies of the given package" + When run script ./contrib/cpt-depends "$firstpkg" + The status should be success + End + It "uses the current directory for the package name if none is supplied (${PWD##*/})" + When run script ./contrib/cpt-depends + The stdout should eq "$(cat "$CPT_ROOT/var/db/cpt/installed/${PWD##*/}/depends" 2>/dev/null ||:)" + The status should be success + End + It "prints usage information when called with --help" + When run script ./contrib/cpt-depends --help + The word 1 of stdout should eq usage: + End + End +End diff --git a/tests/etc/cpt-hook b/tests/etc/cpt-hook new file mode 120000 index 0000000..e95622a --- /dev/null +++ b/tests/etc/cpt-hook @@ -0,0 +1 @@ +../hook-file \ No newline at end of file diff --git a/tests/hook-file b/tests/hook-file new file mode 100644 index 0000000..4b8a2ce --- /dev/null +++ b/tests/hook-file @@ -0,0 +1,3 @@ +# -*- mode: sh -*- +# This a test hook file that only returns back the $TYPE, $PKG, and $DEST +out "$CPT_HOOK $TYPE $PKG $DEST" -- cgit v1.2.3