#!/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 . # # 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