Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More multiline issues: arrays and chained expressions #37

Open
joaoe opened this issue May 3, 2018 · 3 comments
Open

More multiline issues: arrays and chained expressions #37

joaoe opened this issue May 3, 2018 · 3 comments

Comments

@joaoe
Copy link

joaoe commented May 3, 2018

This snippet should have 100% coverage

#!/usr/bin/env bash

function this_command_runs {
	true
}

function main {
	
	# awk script -> it just a long string passed to the awk.
	# Both the command and arguments should could as covered.

	awk -F, 'NR==1{
	print("Some long script")
}
NR > 1 {
	print("And script continues")
}' /dev/null


	# multiline array specification

	local some_array=( "Some" "values" "${and[@]}"
		"${many}" other $(echo 123)
	)

	local some_array=(
		"Some" "values" "${and[@]}"
		"${many}" other $(echo 123)
	)

	declare -A some_hashmap=(
		[A]="aaa"
		[B]="bbb"
		[C]="..."
	)

	##### multiline with && and ||

	true line 1 \
		line 2 \
		line 3

	true line 1 \
		"$(true && echo line 2)" \
		line 3

	true line 1 \
		"$(false || echo line 2)" \
		line 3

	##### multiline with redirect and boolean operator

	false line 1 \
		line 2 2> >(cat) || this_command_runs

	false line 1 \
		line 2 2> >(cat) || \
		this_command_runs

	true line 1 \
		line 2 2> >(cat) && this_command_runs

	true line 1 \
		line 2 2> >(cat) && \
		this_command_runs

	##### A for loop in multiple lines
	
	for ((k = 1;
	k <= 2;
	k++));
	do
		true
	done

	echo "This test case should have 100% line coverage"

	exit 0
}

main "$@"

Instead I'm getting 60%.

Using bashcov 1.8.2.

Thank you.

@infertux
Copy link
Owner

Thank you for this great snippet. However adding even more regexps to address all these examples feels wrong to me because there will always be weird edge cases that can't be handled by regexps. So I'm tagging this issue as a duplicate/reminder of #25

@pawamoy
Copy link

pawamoy commented May 10, 2019

Indeed, I managed to get a 65.91% coverage on this snippet with a Bash solution, using regular expressions and hacks, but without a lexer it will be impossible to get to 100%.

Something I find quite problematic is how the LINENO variable behaves.
With normal commands it's fine.
With commands in process substitutions ($(), ``, <(), >(), (), etc.), using backslashes \, pipes | and logical operators (&&, ||) (and without mentioning handling additional comments # in regexes, and weird eval cases), it's completely useless.
The line numbers I get are completely offset, sometimes overlapping with later lines, like empty lines, comments, or commands. It's indecipherable.

I wonder if we could get to 100%, even with a lexer, if the LINENO variable is not improved.
Bash says it itself:

LINENO Each time this parameter is referenced, the shell substitutes a decimal number representing the current sequential line number (starting with 1) within a script or function. When not in a script or function, the value substituted is not guaranteed to be meaningful.

(Emphasis mine)

Maybe a more reliable way would be to do heuristics to match the actual line using the value of LINENO and the command written in the trace log. LINENO gives you a close position in the file, the command helps you identifying the actual line.

I also wonder how Zsh handles this.

@pawamoy
Copy link

pawamoy commented May 10, 2019

More info on this stackoverflow post and in this gist I made in response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants