mirror of
https://github.com/dredx/prole.git
synced 2026-09-27 15:54:30 +00:00
- Introduce lib/shell helpers and keep etc/* scripts thin via compatibility shims - Move Kerberos validation to scripts/validation/check_kerberos.sh and update callers - Add deterministic shellspec unit tests under tests/shellspec/ and wire Maven to run them - Add minimal Spring Boot authority module with startup + /health endpoint and Maven wiring - Document the new layout in docs/layout.md Co-authored-by: Junie <junie@jetbrains.com>
532 lines
12 KiB
Bash
532 lines
12 KiB
Bash
#shellcheck shell=sh disable=SC2004,SC2034,SC2119,SC2120,SC2016
|
|
|
|
# shellcheck source=lib/libexec.sh
|
|
. "${SHELLSPEC_LIB:-./lib}/libexec.sh"
|
|
use constants trim match_pattern ends_with escape_quote replace_all match includes
|
|
load grammar
|
|
|
|
initialize() {
|
|
block_id='' block_id_increased=1 inside_of_example='' inside_of_text=''
|
|
lineno=0 block_no=0 example_no=1 skip_id=0 error='' focused='' skipped=''
|
|
_block_no=0 _block_no_stack='' mock_no=1 inside_of_mock='' use_dsl_in_mock=''
|
|
parameter_count='' parameter_no=0 _parameter_count_stack=''
|
|
parameters_need_example=''
|
|
}
|
|
|
|
finalize() {
|
|
if [ "$_block_no_stack" ]; then
|
|
syntax_error "Unexpected end of file (expecting 'End')"
|
|
lineno=
|
|
while [ "$_block_no_stack" ]; do block_end; done
|
|
fi
|
|
if [ ! "$block_id_increased" ]; then
|
|
trans after_last_block ""
|
|
fi
|
|
trans after_block ""
|
|
}
|
|
|
|
read_specfile() {
|
|
eval "{ IFS= read -r $1 || [ \"\$$1\" ]; } && $1=\${$1%\"\$CR\"}" && {
|
|
lineno=$(($lineno + 1))
|
|
}
|
|
}
|
|
|
|
one_line_syntax_check() { :; }
|
|
|
|
check_filter() {
|
|
check_filter="$1"
|
|
replace_all check_filter '$' "$DC1"
|
|
replace_all check_filter '`' "$DC2"
|
|
eval "set -- $check_filter"
|
|
if [ $# -gt 0 ]; then
|
|
check_filter="$1"
|
|
replace_all check_filter "$DC1" '$'
|
|
replace_all check_filter "$DC2" '`'
|
|
match_pattern "$check_filter" "$SHELLSPEC_EXAMPLE_FILTER" && return 0
|
|
shift
|
|
fi
|
|
[ $# -gt 0 ] || return 1
|
|
check_tag_filter "$@"
|
|
}
|
|
|
|
check_tag_filter() {
|
|
[ "$SHELLSPEC_TAG_FILTER" ] || return 1
|
|
while [ $# -gt 0 ]; do
|
|
includes ",$SHELLSPEC_TAG_FILTER," ",$1," && return 0
|
|
case $1 in (*:*)
|
|
includes ",$SHELLSPEC_TAG_FILTER," ",${1%%:*}," && return 0
|
|
esac
|
|
shift
|
|
done
|
|
return 1
|
|
}
|
|
|
|
is_constant_name() {
|
|
match "$1" "[!A-Z_]*" && return 1
|
|
match "$1" "*[!A-Z0-9_]*" && return 1
|
|
return 0
|
|
}
|
|
|
|
is_function_name() {
|
|
match "$1" "[!a-zA-Z_]*" && return 1
|
|
match "$1" "*[!a-zA-Z0-9_]*" && return 1
|
|
return 0
|
|
}
|
|
|
|
is_comment() {
|
|
case $1 in (\# | \#\ * | \#$TAB*) return 0; esac
|
|
return 1
|
|
}
|
|
|
|
is_embedded_text() {
|
|
case $1 in (\#\|*) return 0; esac
|
|
return 1
|
|
}
|
|
|
|
if_embedded_text() {
|
|
is_embedded_text "$1" || return 1
|
|
set -- "$@" "${1#??}"
|
|
shift
|
|
"$@"
|
|
}
|
|
|
|
increase_block_id() {
|
|
[ "$block_id_increased" ] && block_id=$block_id${block_id:+-}0
|
|
case $block_id in
|
|
*-*) block_id=${block_id%-*}-$((${block_id##*-} + 1)) ;;
|
|
* ) block_id=$(($block_id + 1)) ;;
|
|
esac
|
|
block_id_increased=1
|
|
}
|
|
|
|
decrease_block_id() {
|
|
if [ "$block_id_increased" ]; then
|
|
block_id_increased=''
|
|
else
|
|
block_id=${block_id%-*}
|
|
fi
|
|
}
|
|
|
|
block_example_group() {
|
|
if [ "$inside_of_example" ]; then
|
|
syntax_error "Describe/Context cannot be defined inside of Example"
|
|
return 0
|
|
fi
|
|
|
|
if ! one_line_syntax_check error "$1"; then
|
|
syntax_error "Describe/Context has occurred an error" "$error"
|
|
return 0
|
|
fi
|
|
|
|
check_filter "$1" && filter=1
|
|
|
|
if [ "$block_id_increased" ]; then
|
|
trans before_first_block "$block_id"
|
|
fi
|
|
increase_block_id
|
|
_block_no=$(($_block_no + 1))
|
|
block_no=$_block_no lineno_begin=$lineno
|
|
eval "block_lineno_begin${_block_no}=$lineno"
|
|
|
|
eval trans block_example_group ${1+'"$@"'}
|
|
|
|
_block_no_stack="$_block_no_stack $_block_no" filter=''
|
|
_parameter_count_stack="$_parameter_count_stack $parameter_no:$parameter_count"
|
|
}
|
|
|
|
block_example() {
|
|
if [ "$inside_of_example" ]; then
|
|
syntax_error "It/Example/Specify/Todo cannot be defined inside of Example"
|
|
return 0
|
|
fi
|
|
|
|
parameters_need_example=''
|
|
|
|
if ! one_line_syntax_check error "$1"; then
|
|
syntax_error "It/Example/Specify/Todo has occurred an error" "$error"
|
|
return 0
|
|
fi
|
|
|
|
check_filter "$1" && filter=1
|
|
|
|
if [ "$block_id_increased" ]; then
|
|
trans before_first_block "$block_id"
|
|
fi
|
|
increase_block_id
|
|
_block_no=$(($_block_no + 1))
|
|
block_no=$_block_no lineno_begin=$lineno
|
|
eval "block_lineno_begin${block_no}=$lineno"
|
|
|
|
eval trans block_example ${1+'"$@"'}
|
|
|
|
_block_no_stack="$_block_no_stack $_block_no"
|
|
example_no=$(($example_no + ${parameter_count:-1}))
|
|
_parameter_count_stack="$_parameter_count_stack $parameter_no:$parameter_count"
|
|
filter='' inside_of_example="yes"
|
|
}
|
|
|
|
block_end() {
|
|
if [ ! "$_block_no_stack" ]; then
|
|
syntax_error "Unexpected 'End'"
|
|
return 0
|
|
fi
|
|
|
|
if [ "$parameters_need_example" ]; then
|
|
syntax_error "Not found any examples. (Missing 'End' of Parameters?)"
|
|
parameters_need_example=''
|
|
return 0
|
|
fi
|
|
|
|
if [ ! "$block_id_increased" ]; then
|
|
trans after_last_block "${block_id%-*}"
|
|
fi
|
|
decrease_block_id
|
|
block_no=${_block_no_stack##* } lineno_end=$lineno
|
|
trans after_block "$block_no"
|
|
eval "block_lineno_end${block_no}=$lineno"
|
|
eval "lineno_begin=\$block_lineno_begin${block_no}"
|
|
|
|
if is_in_ranges; then
|
|
enabled=1
|
|
remove_from_ranges
|
|
fi
|
|
|
|
eval trans block_end ${1+'"$@"'}
|
|
enabled=''
|
|
|
|
_block_no_stack=${_block_no_stack% *}
|
|
parameter_count=${_parameter_count_stack##* }
|
|
parameter_no=${parameter_count%:*}
|
|
parameter_count=${parameter_count#*:}
|
|
_parameter_count_stack=${_parameter_count_stack% *}
|
|
inside_of_example=""
|
|
}
|
|
|
|
x() {
|
|
skipped=1 skip_id=$(($skip_id + 1))
|
|
"$@"
|
|
skipped=''
|
|
}
|
|
|
|
f() {
|
|
focused="focus" filter=1
|
|
"$@"
|
|
focused='' filter=''
|
|
}
|
|
|
|
todo() {
|
|
block_example "$1"
|
|
pending "$1"
|
|
block_end
|
|
}
|
|
|
|
evaluation() {
|
|
if [ ! "$inside_of_example" ]; then
|
|
syntax_error "When cannot be defined outside of Example"
|
|
return 0
|
|
fi
|
|
eval trans evaluation ${1+'"$@"'}
|
|
}
|
|
|
|
expectation() {
|
|
if [ ! "$inside_of_example" ]; then
|
|
syntax_error "The cannot be defined outside of Example"
|
|
return 0
|
|
fi
|
|
eval trans expectation ${1+'"$@"'}
|
|
}
|
|
|
|
example_hook() {
|
|
if [ "$inside_of_example" ]; then
|
|
syntax_error "Before/After cannot be defined inside of Example"
|
|
return 0
|
|
fi
|
|
eval trans control ${1+'"$@"'}
|
|
}
|
|
|
|
example_all_hook() {
|
|
if [ "$inside_of_example" ]; then
|
|
syntax_error "BeforeAll/AfterAll cannot be defined inside of Example"
|
|
return 0
|
|
fi
|
|
|
|
if [ "$1" = "before_all" ] && [ ! "$block_id_increased" ]; then
|
|
syntax_error "BeforeAll cannot be defined after of Example Group/Example in same block"
|
|
return 0
|
|
fi
|
|
|
|
eval trans control ${1+'"$@"'}
|
|
}
|
|
|
|
control() {
|
|
eval trans control ${1+'"$@"'}
|
|
}
|
|
|
|
pending() {
|
|
case ${1:-} in (\#*)
|
|
temporary_pending=${1#"#"}
|
|
escape_quote temporary_pending
|
|
trim temporary_pending "$temporary_pending"
|
|
set -- "'# $temporary_pending'"
|
|
esac
|
|
eval trans pending ${1+'"$@"'}
|
|
}
|
|
|
|
skip() {
|
|
skip_id=$(($skip_id + 1))
|
|
case ${1:-} in (\#*)
|
|
temporary_skip=${1#"#"}
|
|
escape_quote temporary_skip
|
|
trim temporary_skip "$temporary_skip"
|
|
set -- "'# $temporary_skip'"
|
|
esac
|
|
eval trans skip ${1+'"$@"'}
|
|
}
|
|
|
|
data() {
|
|
eval trans data_begin ${1+'"$@"'}
|
|
case ${2:-} in
|
|
'' | \#* | \|*)
|
|
trans embedded_text_begin "$1" "${2:-}"
|
|
line='' error=
|
|
while read_specfile line; do
|
|
trim line "$line"
|
|
is_comment "$line" && continue # ignore comment line
|
|
if_embedded_text "$line" trans embedded_text_line && continue
|
|
is_end_block "${line%% *}" && break
|
|
[ "$error" ] && continue
|
|
error=$(syntax_error "Data text should begin with '#|' or '# '")
|
|
done
|
|
trans embedded_text_end
|
|
[ ! "$error" ] || putsn "$error"
|
|
;;
|
|
\'* | \"*) trans data_text "$2" ;;
|
|
\<*) trans data_file "$2" ;;
|
|
*) trans data_func "$2" ;;
|
|
esac
|
|
eval trans data_end ${1+'"$@"'}
|
|
}
|
|
|
|
text_begin() {
|
|
eval trans embedded_text_begin ${1+'"$@"'}
|
|
inside_of_text=1
|
|
}
|
|
|
|
text_line() {
|
|
if_embedded_text "$1" trans embedded_text_line && return 0
|
|
text_end
|
|
return 1
|
|
}
|
|
|
|
text_end() {
|
|
eval trans embedded_text_end ${1+'"$@"'}
|
|
inside_of_text=''
|
|
}
|
|
|
|
parameters() {
|
|
if [ "$inside_of_example" ]; then
|
|
syntax_error "Parameters cannot be defined inside of Example"
|
|
return 0
|
|
fi
|
|
parameters_need_example=1
|
|
|
|
parameter_no=$(($parameter_no + 1))
|
|
trans parameters_begin "$parameter_no"
|
|
#shellcheck disable=SC2145
|
|
"parameters_$@"
|
|
trans parameters_end
|
|
}
|
|
|
|
parameters_generate_code() {
|
|
trans line "$1"
|
|
code="${code}${1}${LF}"
|
|
}
|
|
|
|
parameters_continuation_line() {
|
|
line=$1
|
|
shift
|
|
while ends_with "$line" "\\"; do
|
|
read_specfile line ||:
|
|
"$@" "$line"
|
|
done
|
|
}
|
|
|
|
parameters_block() {
|
|
while read_specfile line; do
|
|
trim line "$line"
|
|
is_end_block "${line%% *}" && break
|
|
case $line in (\#* | '') continue; esac
|
|
|
|
trans parameters "$line"
|
|
parameter_count=$(($parameter_count + 1))
|
|
parameters_continuation_line "$line" trans line
|
|
done
|
|
}
|
|
|
|
parameters_value() {
|
|
code=''
|
|
if [ $# -gt 0 ]; then
|
|
IFS=" $IFS"
|
|
parameters_generate_code "for shellspec_matrix in $*; do"
|
|
IFS=${IFS#?}
|
|
trans parameters "\"\$shellspec_matrix\""
|
|
code="${code}count=\$((\$count + 1))${LF}"
|
|
parameters_generate_code "done"
|
|
fi
|
|
eval "parameter_count=\$(count=0${LF}${code}echo \"\$count\")"
|
|
}
|
|
|
|
parameters_matrix() {
|
|
code='' nest=0 arguments=''
|
|
|
|
while read_specfile line; do
|
|
trim line "$line"
|
|
is_end_block "${line%% *}" && break
|
|
case $line in (\#* | '') continue; esac
|
|
|
|
nest=$(($nest + 1))
|
|
parameters_generate_code "for shellspec_matrix${nest} in $line"
|
|
arguments="$arguments\"\$shellspec_matrix${nest}\" "
|
|
parameters_continuation_line "$line" parameters_generate_code
|
|
parameters_generate_code "do"
|
|
done
|
|
|
|
trans parameters "$arguments"
|
|
code="${code}count=\$((\$count + 1))${LF}"
|
|
|
|
while [ $nest -gt 0 ]; do
|
|
parameters_generate_code "done"
|
|
nest=$(($nest - 1))
|
|
done
|
|
|
|
eval "parameter_count=\$(count=0${LF}${code}echo \"\$count\")"
|
|
}
|
|
|
|
parameters_dynamic() {
|
|
code=''
|
|
|
|
while read_specfile line; do
|
|
trim line "$line"
|
|
is_end_block "${line%% *}" && break
|
|
|
|
case $line in
|
|
%data | %data\ *)
|
|
line=${line#%data}
|
|
trans parameters "$line"
|
|
line='count=$(($count + 1))'
|
|
;;
|
|
*) trans line "$line"
|
|
esac
|
|
code="${code}${line}${LF}"
|
|
done
|
|
|
|
eval "parameter_count=\$(count=0${LF}{ $code }>&2;echo \"\$count\")"
|
|
}
|
|
|
|
mock() {
|
|
inside_of_mock=1
|
|
eval trans mock_begin ${1+'"$@"'}
|
|
mock_no=$(($mock_no + 1))
|
|
}
|
|
|
|
mock_end() {
|
|
is_end_block "${1%% *}" || return 1
|
|
inside_of_mock=''
|
|
eval trans mock_end ${1+'"$@"'}
|
|
}
|
|
|
|
constant() {
|
|
if [ "$_block_no_stack" ]; then
|
|
syntax_error "Constant should be defined outside of Example Group/Example"
|
|
return 0
|
|
fi
|
|
|
|
trim line "$1"
|
|
name=${line%%:*} value=''
|
|
trim value "${line#*:}"
|
|
if is_constant_name "$name"; then
|
|
trans constant "$name" "$value"
|
|
eval "$name=\$value"
|
|
else
|
|
syntax_error "Constant name should match pattern [A-Z_][A-Z0-9_]*"
|
|
fi
|
|
}
|
|
|
|
include() {
|
|
if [ "$inside_of_example" ]; then
|
|
syntax_error "Include cannot be defined inside of Example"
|
|
return 0
|
|
fi
|
|
|
|
if ! one_line_syntax_check error "$1"; then
|
|
syntax_error "Include has occurred an error" "$error"
|
|
return 0
|
|
fi
|
|
|
|
eval trans include ${1+'"$@"'}
|
|
}
|
|
|
|
with_function() {
|
|
trans with_function "$1"
|
|
shift
|
|
"$@"
|
|
}
|
|
|
|
out() {
|
|
eval trans out ${1+'"$@"'}
|
|
}
|
|
|
|
is_in_range() {
|
|
case $1 in
|
|
@*) [ "$block_id" = "${1#@}" ] ;;
|
|
*) [ "$lineno_begin" -le "$1" ] && [ "$1" -le "$lineno_end" ] ;;
|
|
esac
|
|
}
|
|
|
|
is_in_ranges() {
|
|
[ "${ranges:-}" ] || return 1
|
|
eval "set -- $ranges"
|
|
while [ $# -gt 0 ]; do
|
|
is_in_range "$1" && return 0
|
|
shift
|
|
done
|
|
return 1
|
|
}
|
|
|
|
remove_from_ranges() {
|
|
eval "set -- $ranges"
|
|
ranges=''
|
|
while [ $# -gt 0 ]; do
|
|
is_in_range "$1" || ranges="$ranges$1 "
|
|
shift
|
|
done
|
|
}
|
|
|
|
translate() {
|
|
work=''
|
|
while read_specfile line; do
|
|
while ends_with "$line" "\\"; do
|
|
read_specfile work ||:
|
|
line="${line}${LF}${work}"
|
|
done
|
|
trim work "$line"
|
|
dsl=${work%% *} rest=''
|
|
|
|
[ "$inside_of_text" ] && text_line "$work" && continue
|
|
translate_mock "$dsl" && continue
|
|
|
|
trim rest "${work#"$dsl"}"
|
|
mapping "$dsl" "$rest" || trans line "$line"
|
|
done
|
|
}
|
|
|
|
translate_mock() {
|
|
if [ "$inside_of_mock" ]; then
|
|
mock_end "$1" && return 0
|
|
is_dsl "$1" && use_dsl_in_mock=1 && return 0
|
|
elif [ "$use_dsl_in_mock" ]; then
|
|
syntax_error "Only directives can be used in Mock"
|
|
fi
|
|
return 1
|
|
}
|