Skip to content

Commit d4c9923

Browse files
committedOct 28, 2020
tests: add test suite and GitHub action to run it with coverage
- [x] add test subdirectory with a suite of tests for sbang - [x] add workflow for linux tests - [x] add workflow for macos tests - [x] add workflow for shellcheck - [x] add codecov to macos tests TODO: It seems like kcov doesn't work on linux tests for some reason. Will need to debug later.
1 parent da0b5af commit d4c9923

26 files changed

+396
-6
lines changed
 

‎.codecov.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
coverage:
2+
precision: 2
3+
round: nearest
4+
range: 60...90
5+
status:
6+
project:
7+
default:
8+
threshold: 0.2%
9+
10+
ignore:
11+
- test/.*
12+
13+
comment: off

‎.github/workflows/linux-test.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: linux
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
jobs:
11+
unit-tests:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
with:
16+
fetch-depth: 0
17+
- name: run unit tests
18+
run: |
19+
make -C test test

‎.github/workflows/macos-tests.yaml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: macos
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
jobs:
11+
unit-tests:
12+
runs-on: macos-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
with:
16+
fetch-depth: 0
17+
- name: Setup Homebrew packages
18+
run: |
19+
brew install kcov
20+
- name: Run unit tests
21+
env:
22+
COVERAGE: true
23+
run: make -C test test
24+
- uses: codecov/codecov-action@v1
25+
with:
26+
directory: ./coverage
27+
flags: unittests

‎.github/workflows/shellcheck.yaml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: shellcheck
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
jobs:
11+
shellcheck:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
with:
16+
fetch-depth: 0
17+
- name: install shellcheck
18+
run: |
19+
sudo apt-get update
20+
sudo apt-get install shellcheck
21+
- name: run unit tests
22+
run: make -C test shellcheck

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
coverage

‎README.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# sbang
2+
![linux](https://github.com/spack/sbang/workflows/linux/badge.svg)
3+
![macos](https://github.com/spack/sbang/workflows/macos/badge.svg)
4+
![shellcheck](https://github.com/spack/sbang/workflows/shellcheck/badge.svg)
5+
[![codecov](https://codecov.io/gh/spack/sbang/branch/main/graph/badge.svg?token=IKH7mB5qq7)](undefined)
26

37
`sbang` lets you run scripts with very long shebang (`#!`) lines.
48

‎sbang

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/sh
22
#
33
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
4-
# sbang Project Developers. See the top-level COPYRIGHT file for details.
4+
# sbang project developers. See the top-level COPYRIGHT file for details.
55
#
66
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
77

@@ -67,6 +67,11 @@ done < "$script"
6767
# this saves arguments for later and intentionally assigns as an array
6868
args="$@"
6969

70+
# error if we did not find any interpreter
71+
if [ -z "$shebang_line" ]; then
72+
die "error: sbang found no interpreter in $script"
73+
fi
74+
7075
# handle scripts with sbang parameters, e.g.:
7176
#
7277
# #!/<some-long-path>/perl -w
@@ -79,11 +84,6 @@ set -- "$@"
7984
interpreter="$1"
8085
arg1="$2"
8186

82-
# error if we did not find any interpreter
83-
if [ -z "$interpreter" ]; then
84-
die "error: sbang found no interpreter in $script"
85-
fi
86-
8787
# Determine if the interpreter is a particular program, accounting for the
8888
# '#!/usr/bin/env PROGRAM' convention. So:
8989
#

‎test/Makefile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
2+
# sbang project developers. See the top-level COPYRIGHT file for details.
3+
#
4+
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
5+
6+
# Run make to run the test suite with just sbang.
7+
# Run make COVERAGE=TRUE to run with kcov
8+
COVERAGE_DIR = ../coverage
9+
SBANG_SCRIPT = ../sbang
10+
SBANG = $(if $(COVERAGE),kcov $(COVERAGE_DIR) ,)$(SBANG_SCRIPT)
11+
12+
test:
13+
echo $(SBANG)
14+
SBANG="$(SBANG)" ./test-suite.sh
15+
16+
shellcheck:
17+
shellcheck $(SBANG_SCRIPT)

‎test/shebangs/bash.bash

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/bin/bash

‎test/shebangs/lua.lua

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
--!/path/to/lua

‎test/shebangs/no-interpreter

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This is a simple file.
2+
It has no shebang and no interpreter.

‎test/shebangs/node.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
//!/path/to/node

‎test/shebangs/perl-env.pl

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/env perl

‎test/shebangs/perl-w-env.pl

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/env perl -w

‎test/shebangs/perl-w.pl

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/perl -w

‎test/shebangs/perl.pl

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/perl

‎test/shebangs/php.php

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env sbang
2+
<?php #!/usr/bin/php ?>
3+
<?php echo "hello\n" ?>

‎test/shebangs/python-env.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/env python
3+
4+
from __future__ import print_function
5+
6+
print("python")

‎test/shebangs/python.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/python
3+
4+
from __future__ import print_function
5+
6+
print("python")

‎test/shebangs/ruby-env.rb

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/env ruby
3+
4+
puts "ruby"

‎test/shebangs/ruby.rb

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/ruby
3+
4+
puts "ruby"

‎test/shebangs/sbang

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/path/to/sbang

‎test/shebangs/sbang-env

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/usr/bin/env sbang

‎test/shebangs/sh.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sbang
2+
#!/bin/sh

‎test/test-framework.sh

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
2+
# sbang project developers. See the top-level COPYRIGHT file for details.
3+
#
4+
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
5+
6+
#
7+
# A testing framework for any POSIX-compatible shell.
8+
#
9+
10+
# ------------------------------------------------------------------------
11+
# Functions for color output.
12+
# ------------------------------------------------------------------------
13+
14+
# Colors for output
15+
red='\033[1;31m'
16+
cyan='\033[1;36m'
17+
green='\033[1;32m'
18+
reset='\033[0m'
19+
20+
echo_red() {
21+
printf "${red}$*${reset}\n"
22+
}
23+
24+
echo_green() {
25+
printf "${green}$*${reset}\n"
26+
}
27+
28+
echo_msg() {
29+
printf "${cyan}$*${reset}\n"
30+
}
31+
32+
# ------------------------------------------------------------------------
33+
# Generic functions for testing shell code.
34+
# ------------------------------------------------------------------------
35+
36+
# counts of test successes and failures.
37+
success=0
38+
errors=0
39+
40+
# Print out a header for a group of tests.
41+
title() {
42+
echo
43+
echo_msg "$@"
44+
echo_msg "---------------------------------"
45+
}
46+
47+
# echo FAIL in red text; increment failures
48+
fail() {
49+
echo_red FAIL
50+
errors=$((errors+1))
51+
}
52+
53+
#
54+
# Echo SUCCESS in green; increment successes
55+
#
56+
pass() {
57+
echo_green SUCCESS
58+
success=$((success+1))
59+
}
60+
61+
#
62+
# Run a command and suppress output unless it fails.
63+
# On failure, echo the exit code and output.
64+
#
65+
succeeds() {
66+
printf "'%s' succeeds ... " "$*"
67+
output=$("$@" 2>&1)
68+
err="$?"
69+
70+
if [ "$err" != 0 ]; then
71+
fail
72+
echo_red "Command failed with error $err."
73+
if [ -n "$output" ]; then
74+
echo_msg "Output:"
75+
echo "$output"
76+
else
77+
echo_msg "No output."
78+
fi
79+
else
80+
pass
81+
fi
82+
}
83+
84+
#
85+
# Run a command and suppress output unless it succeeds.
86+
# If the command succeeds, echo the output.
87+
#
88+
fails() {
89+
printf "'%s' fails ... " "$*"
90+
output=$("$@" 2>&1)
91+
err="$?"
92+
93+
if [ "$err" = 0 ]; then
94+
fail
95+
echo_red "Command failed with error $err."
96+
if [ -n "$output" ]; then
97+
echo_msg "Output:"
98+
echo "$output"
99+
else
100+
echo_msg "No output."
101+
fi
102+
else
103+
pass
104+
fi
105+
}
106+
107+
#
108+
# Ensure that a string is in the output of a command.
109+
# Suppresses output on success.
110+
# On failure, echo the exit code and output.
111+
#
112+
contains() {
113+
string="$1"
114+
shift
115+
116+
printf "'%s' output contains '$string' ... " "$*"
117+
output=$("$@" 2>&1)
118+
err="$?"
119+
120+
if [ "${output#*$string}" = "${output}" ]; then
121+
fail
122+
echo_red "Command exited with error $err."
123+
echo_red "'$string' was not in output."
124+
if [ -n "$output" ]; then
125+
echo_msg "Output:"
126+
echo "$output"
127+
else
128+
echo_msg "No output."
129+
fi
130+
else
131+
pass
132+
fi
133+
}
134+
135+
#
136+
# Ensure that a variable is set.
137+
#
138+
is_set() {
139+
printf "'%s' is set ... " "$1"
140+
if eval "[ -z \${${1:-}+x} ]"; then
141+
fail
142+
echo_msg "$1 was not set!"
143+
else
144+
pass
145+
fi
146+
}
147+
148+
#
149+
# Ensure that a variable is not set.
150+
# Fails and prints the value of the variable if it is set.
151+
#
152+
is_not_set() {
153+
printf "'%s' is not set ... " "$1"
154+
if eval "[ ! -z \${${1:-}+x} ]"; then
155+
fail
156+
echo_msg "$1 was set:"
157+
echo " $1"
158+
else
159+
pass
160+
fi
161+
}
162+
163+
#
164+
# Report the number of tests that succeeded and failed on exit.
165+
#
166+
teardown() {
167+
if [ "$?" != 0 ]; then
168+
trapped_error=true
169+
else
170+
trapped_error=false
171+
fi
172+
173+
if type cleanup &> /dev/null
174+
then
175+
cleanup
176+
fi
177+
178+
echo
179+
echo "$success tests succeeded."
180+
echo "$errors tests failed."
181+
182+
if [ "$trapped_error" = true ]; then
183+
echo "Exited due to an error."
184+
fi
185+
186+
if [ "$errors" = 0 ] && [ "$trapped_error" = false ]; then
187+
pass
188+
exit 0
189+
else
190+
fail
191+
exit 1
192+
fi
193+
}
194+
195+
trap teardown EXIT

‎test/test-suite.sh

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/sh
2+
#
3+
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
4+
# sbang project developers. See the top-level COPYRIGHT file for details.
5+
#
6+
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
7+
8+
set -u
9+
. ./test-framework.sh
10+
11+
# you must set SBANG when running the test suite
12+
if [ -z "${SBANG:-}" ]; then
13+
echo_red "error: must set SBANG to location of sbang script"
14+
exit 1
15+
fi
16+
17+
# enable debug mode for tests below to work
18+
export SBANG_DEBUG=1
19+
20+
title "Testing languages with shell-style comments"
21+
contains "/usr/bin/perl -x" $SBANG shebangs/perl.pl
22+
contains "/usr/bin/env perl -x" $SBANG shebangs/perl-env.pl
23+
contains "/usr/bin/perl -w -x" $SBANG shebangs/perl-w.pl
24+
contains "/usr/bin/env perl -w -x" $SBANG shebangs/perl-w-env.pl
25+
26+
contains "/usr/bin/ruby -x" $SBANG shebangs/ruby.rb
27+
contains "/usr/bin/env ruby -x" $SBANG shebangs/ruby-env.rb
28+
29+
contains "/usr/bin/python" $SBANG shebangs/python.py
30+
contains "/usr/bin/env python" $SBANG shebangs/python-env.py
31+
32+
contains "/bin/sh" $SBANG shebangs/sh.sh
33+
contains "/bin/bash" $SBANG shebangs/bash.bash
34+
35+
title "Testing languages without shell-style comments"
36+
contains "/path/to/lua" $SBANG shebangs/lua.lua
37+
contains "/path/to/node" $SBANG shebangs/node.js
38+
contains "/usr/bin/php" $SBANG shebangs/php.php
39+
40+
title "Testing sbang fails with invalid input"
41+
fails $SBANG
42+
fails $SBANG nonexistent-file
43+
fails $SBANG shebangs/no-interpreter
44+
45+
title "Testing sbang doesn't loop infinitely"
46+
fails $SBANG shebangs/sbang
47+
fails $SBANG shebangs/sbang-env

0 commit comments

Comments
 (0)
Please sign in to comment.