Skip to content

Commit 5d0b05c

Browse files
committed
fix: implement custom data provider arg parser
This removes the need to use "eval" and hence fixes potential gotchas.
1 parent b7caa1b commit 5d0b05c

1 file changed

Lines changed: 49 additions & 7 deletions

File tree

src/runner.sh

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,50 @@ function runner::functions_for_script() {
8080
shopt -u extdebug
8181
}
8282

83+
function runner::parse_data_provider_args() {
84+
local input="$1"
85+
local current_arg=""
86+
local in_quotes=false
87+
local quote_char=""
88+
local escaped=false
89+
local i
90+
local -a args=()
91+
# Parse args from the input string into an array, respecting quotes and escapes
92+
for ((i=0; i<${#input}; i++)); do
93+
local char="${input:$i:1}"
94+
if [ "$escaped" = true ]; then
95+
current_arg+="$char"
96+
escaped=false
97+
elif [ "$char" = "\\" ]; then
98+
escaped=true
99+
elif [ "$in_quotes" = false ]; then
100+
case "$char" in
101+
"'" | '"')
102+
in_quotes=true
103+
quote_char="$char"
104+
;;
105+
" " | $'\t')
106+
args+=("$current_arg")
107+
current_arg=""
108+
;;
109+
*)
110+
current_arg+="$char"
111+
;;
112+
esac
113+
elif [ "$char" = "$quote_char" ]; then
114+
in_quotes=false
115+
quote_char=""
116+
else
117+
current_arg+="$char"
118+
fi
119+
done
120+
args+=("$current_arg")
121+
# Print one arg per line to stdout
122+
for a in "${args[@]}"; do
123+
printf '%s\n' "$a"
124+
done
125+
}
126+
83127
function runner::call_test_functions() {
84128
local script="$1"
85129
local filter="$2"
@@ -116,13 +160,11 @@ function runner::call_test_functions() {
116160

117161
# Execute the test function for each line of data
118162
for data in "${provider_data[@]}"; do
119-
# Use eval with set -- to properly parse quoted arguments
120-
eval "set -- $data"
121-
if [ "$#" -gt 1 ]; then
122-
runner::run_test "$script" "$fn_name" "$@"
123-
else
124-
runner::run_test "$script" "$fn_name" "$data"
125-
fi
163+
local parsed_data=()
164+
while IFS= read -r line; do
165+
parsed_data+=("$line")
166+
done <<< "$(runner::parse_data_provider_args "$data")"
167+
runner::run_test "$script" "$fn_name" "${parsed_data[@]}"
126168
done
127169
unset fn_name
128170
done

0 commit comments

Comments
 (0)