shspec/test/test-spec

361 lines
8.2 KiB
Bash

#!/bin/bash
# Specification DSL test
#
# Copyright (C) 2014, 2017 Mike Gerwitz
#
# This file is part of shspec.
#
# shspec is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# TODO: This is incompletely tested because the tests must be written as the
# system itself is written! Therefore, it is not presently capable of
# running all necessary assertions on itself.
#
# Note: this test case will run pretty slowly because it forks a new process
# for each expectation.
##
##
# It is necessary to test syntax in a separate process so we do not
# interfere with the existing stack
#
# This will take an arbitrary script from stdin and execute it
test-run()
{
( cd ../src && ./run-spec <( cat ) )
}
describe shspec:begin-spec
it is a placeholder that exits successfully
expect shspec:begin-spec
to succeed
end
end
describe describe
it fails if not paired with an "'end'"
expect test-run <<< '
describe foo
# no end
'; to fail
end
it succeeds if paired with matching "'end'"
expect test-run <<< '
describe foo
end
'; to succeed
end
end
describe it
it fails within "'describe'" if not paired with an "'end'"
expect test-run <<< '
describe it test
it will fail
# no end
end
'; to fail
end
it succeeds within "'describe'" if paired with an "'end'"
expect test-run <<< '
describe it test
it will succeed
end
end
'; to succeed
end
end
describe expect
it fails when not within "'describe'"
expect test-run <<< '
describe will fail
# not within it
expect true; to succeed
end
'; to fail
end
it succeeds with "'to'" clause when when within "'describe'"
expect test-run <<< '
describe foo
it will succeed
expect true; to succeed
end
end
'; to succeed
end
it fails when missing "'to'" clause of expectation
expect test-run <<< '
describe foo
it will fail
# no "to" clause
expect true
end
end
'; to fail
end
it cannot be "'end'd" before "'to'" clause
expect test-run <<< '
describe foo
it will fail
expect true
# expectation is unfinished
end
end
end
'; to fail
end
# the "premise" is the command executed by the `expect' line
describe premise
it properly executes quoted command lines
expect test-run <<< '
chk() { test $# -eq 1; }
describe foo
it handles whitespace
expect chk "foo bar"
to succeed
end
end
'; to succeed
end
# if result data are stored in a variable, the shell will remove
# trailing whitespace, which is certainly _not_ what we want
it retains trailing newlines
expect test-run <<< '
chk() { test $( wc -l ) -eq 3; }
describe foo
it retains trailing whitespace
expect chk <<< "foomoo
"
to succeed
end
end
'; to succeed
end
# null bytes must be properly handled when comparing binary data
it handles binary comparison with null bytes
expect test-run <<< '
input=007a0000
chk() { test $( xxd -p ) == "$input"; }
describe foo
it handles null bytes
expect chk < <( xxd -r -p <<< "$input" )
to succeed
end
end
'; to succeed
end
end
# the expectation handler performs the assertion logic
describe handler
it is provided premise exit code as first argument
expect test-run <<< '
declare excode=123
shspec:expect:chk() { test "$1" -eq $excode; }
describe foo
it exposes exit code
expect exit $excode
to chk
end
end
'; to succeed
end
# the "remainder" clause is the portion of the sentence that follows the
# execution of the expectation handler
it is provided remainder clause after shift argument
expect test-run <<< '
declare remain="a b c"
shspec:expect:chk()
{
shift "$2"
test "$*" == "$remain"
}
describe foo
it should expose remainder clause
expect true
to chk $remain
end
end
'; to succeed
end
it receives premise output via stdin
expect test-run <<< '
declare str=foo
shspec:expect:chk() { test "$(cat)" == "$str"; }
describe foo
it pipes command output
expect echo "$str"
to chk
end
end
'; to succeed
end
# that is, if we use <<< to provide premise output from memory, a
# newline will be added; we don't want that!
it does not have newline added to premise output if missing
expect test-run <<< '
shspec:expect:chk() { test "$( wc -c )" -eq 0; }
describe foo
it should not add newline
expect true
to chk
end
end
'; to succeed
end
end
describe to
it fails when missing assertion string
expect test-run <<< '
describe foo
it will fail
# missing assertion sting
expect true; to
end
end
'; to fail
end
it can only follow an "'expect'" clause
expect test-run <<< '
describe foo
it will fail
# does not follow expect clause
to succeed
end
'; to fail
end
it will fail on unknwon expectation
expect test-run <<< '
describe foo
it will fail
expect true
to ___some-invalid-expectation___
end
end
'; to fail
end
it will fail when expectation fails
expect test-run <<< '
describe foo
it will fail
# true is not a failure
expect true; to fail
end
end
'; to fail
end
it will succeed when expectation succeeds
expect test-run <<< '
describe foo
it will succeed
expect false; to fail
end
end
'; to succeed
end
end
describe and
# technically, we want this to be permitted after any declaration, but
# we do not yet support any others
it must appear after a "'to'" declaration
expect test-run <<< '
describe foo
it should fail
expect true
# missing "to"
and to succeed
end
end
'; to fail
end
it adds additional expectations to preceding declaration
# impossible condition
expect test-run <<< '
describe foo
it should fail
expect true
to succeed
and to fail
end
end
'; to fail
# redundant to demonstrate that it does not always fail
expect test-run <<< '
describe foo
it should fail
expect true
to succeed
and to succeed
end
end
'; to succeed
end
end
describe shspec:proxy-to
it proxies remainder clause with variable shift length
expect test-run <<< '
expected="foo bar baz"
shspec:expect:chk() { shift "$2"; test "$*" == "$expected"; }
describe foo
it should succeed
expect shspec:proxy-to 0 2 chk $expected
to succeed
expect shspec:proxy-to 0 3 /dev/null chk $expected
to succeed
end
end
'; to succeed
end
end
end