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

POSIX sh support? #24

Open
ghost opened this issue Jan 14, 2017 · 11 comments
Open

POSIX sh support? #24

ghost opened this issue Jan 14, 2017 · 11 comments

Comments

@ghost
Copy link

ghost commented Jan 14, 2017

Hi, I'm looking for a tool to test a rather large sh script (it's around a 1000 lines atm). I have one main script for which I want to generate coverage (preferably also for the large command strings that are passed to xargs to get around read not supporting \0-separation in most implementations), but I also have a collection of test scripts also written in sh.

Does bashcov have support for pure sh scripts? Would you recommend I use bashcov for this?

@infertux
Copy link
Owner

Great question! Bashcov relies on the xtrace ability and the $LINENO special variable to get the current line number. I just tried that on a Debian machine (which uses Dash as the POSIX shell):

$ cat test.sh
#!/bin/sh -x

echo $LINENO

$ ./test.sh
+ echo

So -x (i.e. xtrace) is supported but not $LINENO. It seems it's disabled at compilation time.

Are you using a *BSD variant and does it support $LINENO by default?

@infertux
Copy link
Owner

@infertux
Copy link
Owner

As expected, it fails badly without $LINENO support: https://travis-ci.org/infertux/bashcov/jobs/191911884

It'd be interesting to compile Dash with $LINENO support or try with KornShell...

@tomeon
Copy link
Collaborator

tomeon commented Jan 14, 2017

@infertux -- dash 0.5.9.1 on Arch Linux comes with support for $LINENO, and I was able to get bashcov working with a few changes:

  • $PS4 needs to use $0 instead of $BASH_SOURCE
  • Hacked Bashcov::BashInfo.bash_xtracefd? to return false, since parsing $BASH_VERSINFO doesn't tell us anything of interest when using dash :)
  • Prepended -x to the command since dash does not recognize SHELLOPTS=xtrace: bashcov --bash-path /usr/bin/dash -- -x ./test.sh

Happy to take a crack at updating bashcov to support shells that recognize $LINENO . Maybe we could check during the initialization proces whether the program provided as --bash-path expands $LINENO to an integer?

@infertux
Copy link
Owner

That's great news. Thanks a lot @BaxterStockman.

$0 behaves slightly differently than $BASH_SOURCE so we'll need to make sure it doesn't introduce regressions.

I see sh is just a symlink to bash on Arch:

% ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Dec 10 18:55 /bin/sh -> bash

I wonder if Bash runs in "pseudo" POSIX-compliant mode when called that way. The man page says you can pass --posix to Bash.

I should have some time to work on this next week but please feel free to take a crack at it! That would be most welcomed :)

@tomeon
Copy link
Collaborator

tomeon commented Jan 19, 2017

So it looks like it will be difficult to support POSIX shells in all but the most basic scenario of generating coverage stats for a single script. As far as I have been able to determine, dash, ksh, and mksh provide no means of globally enabling execution tracing a la SHELLOPTS=xtrace -- the only way to turn on tracing is with set -x, which isn't inherited by scripts invoked from the "parent" script.

One possiblity is to provide "shim" scripts -- something like <bashcov root>/exe/{sh,dash,ksh,mksh} -- that simply exec the correct shell with the -x option, passing through the contents of ARGV. By prepending the exe dir to PATH, scripts with shebangs like #!/usr/bin/env sh will use the shim scripts and therefore have execution tracing enabled. Of course, this approach won't work for scripts that use shebangs like #!/bin/sh.

@infertux
Copy link
Owner

which isn't inherited by scripts invoked from the "parent" script

Same result for me. Bummer.

One possiblity is to provide "shim" scripts [...] Of course, this approach won't work for scripts that use shebangs like #!/bin/sh.

Great idea but yeah I'm afraid most sh scripts out there use #!/bin/sh and not #!/usr/bin/env sh. That being said, they should be able to switch to #!/usr/bin/env sh without breaking anything in theory if they really want to use Bashcov. It looks like it's the only reliable option we have anyway. Would this be helpful in your case @WillemMali?

PS: Thanks again for your help @BaxterStockman :)

@infertux
Copy link
Owner

Ping @WillemMali

@ghost
Copy link
Author

ghost commented Dec 28, 2017

Sorry for not responding, I guess I missed the email.

Yes, that would be helpful. I could then wrap bashcov to run on a copy of my script with the #! modified, if I were really stubborn about wanting to use #!/bin/sh :^)

bashcov() {
    $tmp="$(mktemp)"
    { echo "#!/usr/bin/env sh"; tail -n+2 "$0"; } | cat > "$tmp"
    shift
    status=0
    exec bashcov "$tmp" "$@" || status="$?"
    rm "$tmp"
    exit "$status"
}

... I'm not sure if I'm spending too much or too little of my time writing shell scripts.

@tomeon
Copy link
Collaborator

tomeon commented Jan 9, 2019

Holy moly, TIL that kcov is using some LD_PRELOAD trickery to override execve calls and inject the -x flag into the argument vector when the command name is /bin/bash, /bin/sh, /bin/ash or /bin/dash. That's... brilliant(/depraved). Not sure it's worth supporting something similar for Bashcov, but it's a neat idea.

@infertux
Copy link
Owner

Nice find! Though I feel like overriding LD_PRELOAD is more depraved than brilliant IMHO... unless you're doing it for debugging purposes.

Repository owner deleted a comment from jhoosy Jan 31, 2024
Repository owner deleted a comment from devarya Feb 16, 2024
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

2 participants