Skip to content

Commit

Permalink
Set up automated bash tests with bats (#1721)
Browse files Browse the repository at this point in the history
Resolves #1714.
Related #1710.
Stacked onto #1720.

This PR sets up bash tests with
[bats](https://bats-core.readthedocs.io/en/stable/), and adds a first
test suite for [the `strip-marker-sections`
script](#1720).

## Notes
- Similar to how we do it with other test files, I put the `.bats` test
file next to the script under test. The directive in `.dockerignore`
[removes it from the bundle / `.deb`
file](https://github.com/tiny-pilot/tinypilot/assets/83721279/7f52ca3e-17d9-486a-83a5-ea1c6132eb36).
- The `build_bash` dev script is called “build” for consistency with
`build_python` and `build_javascript`, even though we technically don’t
build something. I’ve created
#1716 for us to
potentially reconsider this overall.
- In `build_bash`, it somehow felt reasonable to me to search all places
that are likely to contain `.bats` files, even though we currently only
have them in `/opt/tinypilot-privileged/scripts/`. I don’t feel strongly
about this, though.
- For running the tests, there theoretically would be [an official bats
Docker
image](https://bats-core.readthedocs.io/en/stable/installation.html#running-bats-in-docker),
however that doesn’t play nicely with our bash files: the docker image
doesn’t have a symlink at `/bin/bash`, so it fails to execute any of our
bash scripts that have a `#!/bin/bash` shebang (which is effectively all
of them). We instead would either have to change all our shebangs to the
(most portable) `#!/usr/bin/env bash` shebang, or we just install bats
manually like done here (in the Circle conf).
<a data-ca-tag
href="https://codeapprove.com/pr/tiny-pilot/tinypilot/1721"><img
src="https://codeapprove.com/external/github-tag-allbg.png" alt="Review
on CodeApprove" /></a>

---------

Co-authored-by: Jan Heuermann <[email protected]>
  • Loading branch information
jotaen4tinypilot and jotaen authored Jan 17, 2024
1 parent 8dadc66 commit a141353
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ jobs:
- run:
name: Run build script
command: ./dev-scripts/build-javascript
build_bash:
docker:
- image: cimg/base:2024.01
steps:
- checkout
- run:
name: Install dependencies
command: |
git clone --depth 1 --branch v1.10.0 https://github.com/bats-core/bats-core.git
cd bats-core
sudo ./install.sh /usr/local
- run:
name: Run build script
command: ./dev-scripts/build-bash
e2e:
docker:
# To run tests against the dev server, Playwright needs a CircleCI image
Expand Down Expand Up @@ -263,6 +277,7 @@ workflows:
- decode_edid
- build_python
- build_javascript
- build_bash
- build_debian_package
- e2e
- lint_debian_package:
Expand Down
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# Test files.
**/*_test.py
**/*.test.js
**/*.bats

/debian-pkg/Dockerfile
/debian-pkg/releases/
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The steps below show you how to quickly set up a development environment for Tin
- Python 3.9 or higher
- Node.js 18.16.1 or higher
- [shellcheck](https://github.com/koalaman/shellcheck#installing)
- [bats](https://bats-core.readthedocs.io/en/stable/installation.html)
- Docker 20.10.x or higher

### Install packages
Expand Down
193 changes: 193 additions & 0 deletions debian-pkg/opt/tinypilot-privileged/scripts/strip-marker-sections.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#!/bin/bash

{
# Silence shellcheck for global bats variables.
# https://github.com/tiny-pilot/tinypilot/issues/1718
# shellcheck disable=SC2154
echo "${output}" "${status}" "${lines}" >/dev/null
}

# Wrapper for invoking the script under test as command.
strip-marker-sections() {
bash "${BATS_TEST_DIRNAME}/strip-marker-sections" "$@"
}

prints-help() { #@test
run strip-marker-sections --help
expected_output="$(cat << EOF
Usage: strip-marker-sections [--help] TARGET_FILE
Strips TinyPilot marker sections from a file.
TARGET_FILE Path to file with marker sections.
--help Display this help and exit.
EOF
)"

[[ "${status}" == 0 ]]
[[ "${output}" == "${expected_output}" ]]
}

rejects-missing-input-arg() { #@test
run strip-marker-sections

[[ "${status}" == 1 ]]
[[ "${output}" == 'Input parameter missing: TARGET_FILE' ]]
}

rejects-illegal-flag() { #@test
run strip-marker-sections --foo

[[ "${status}" == 1 ]]
[[ "${output}" == 'Illegal option: --foo' ]]
}

rejects-non-existing-file() { #@test
run strip-marker-sections foo-file.txt

[[ "${status}" == 1 ]]
[[ "${output}" == 'Not a file: foo-file.txt' ]]
}

rejects-non-file() { #@test
tmp_dir="$(mktemp --directory)"
run strip-marker-sections "${tmp_dir}"

[[ "${status}" == 1 ]]
[[ "${output}" == "Not a file: ${tmp_dir}" ]]
}

noop-if-file-has-no-markers() { #@test
target_file="$(mktemp)"
cat << EOF > "${target_file}"
line 1
line 2
line 3
EOF
run strip-marker-sections "${target_file}"
actual_contents="$(<"${target_file}")"
expected_contents="$(cat << EOF
line 1
line 2
line 3
EOF
)"

[[ "${status}" == 0 ]]
[[ "${output}" == "" ]]
[[ "${actual_contents}" == "${expected_contents}" ]]
}

preserves-whitespace() { #@test
target_file="$(mktemp)"
cat << EOF > "${target_file}"
x y
1
EOF
run strip-marker-sections "${target_file}"
actual_contents="$(<"${target_file}")"
expected_contents="$(cat << EOF
x y
1
EOF
)"

[[ "${status}" == 0 ]]
[[ "${output}" == "" ]]
[[ "${actual_contents}" == "${expected_contents}" ]]
}

strips-marker-section() { #@test
target_file="$(mktemp)"
cat << EOF > "${target_file}"
some line
some other line
# --- AUTOGENERATED BY TINYPILOT - START ---
to be stripped
# --- AUTOGENERATED BY TINYPILOT - END ---
final line
EOF
run strip-marker-sections "${target_file}"
actual_contents="$(<"${target_file}")"
expected_contents="$(cat << EOF
some line
some other line
final line
EOF
)"

[[ "${status}" == 0 ]]
[[ "${output}" == "" ]]
[[ "${actual_contents}" == "${expected_contents}" ]]
}

strips-multiple-marker-sections() { #@test
target_file="$(mktemp)"
cat << EOF > "${target_file}"
some line
some other line
# --- AUTOGENERATED BY TINYPILOT - START ---
to be stripped
# --- AUTOGENERATED BY TINYPILOT - END ---
intermediate line
# --- AUTOGENERATED BY TINYPILOT - START ---
to be stripped too
# --- AUTOGENERATED BY TINYPILOT - END ---
final line
EOF
run strip-marker-sections "${target_file}"
actual_contents="$(<"${target_file}")"
expected_contents="$(cat << EOF
some line
some other line
intermediate line
final line
EOF
)"

[[ "${status}" == 0 ]]
[[ "${output}" == "" ]]
[[ "${actual_contents}" == "${expected_contents}" ]]
}

fails-for-unmatched-start-marker() { #@test
target_file="$(mktemp)"
cat << EOF > "${target_file}"
some line
# --- AUTOGENERATED BY TINYPILOT - START ---
to be stripped
EOF
run strip-marker-sections "${target_file}"
actual_contents="$(<"${target_file}")"
expected_contents="$(cat << EOF
some line
# --- AUTOGENERATED BY TINYPILOT - START ---
to be stripped
EOF
)"

[[ "${status}" == 1 ]]
[[ "${output}" == "Unmatched start marker" ]]
[[ "${actual_contents}" == "${expected_contents}" ]]
}

fails-for-unmatched-end-marker() { #@test
target_file="$(mktemp)"
cat << EOF > "${target_file}"
some line
# --- AUTOGENERATED BY TINYPILOT - END ---
final line
EOF
run strip-marker-sections "${target_file}"
actual_contents="$(<"${target_file}")"
expected_contents="$(cat << EOF
some line
# --- AUTOGENERATED BY TINYPILOT - END ---
final line
EOF
)"

[[ "${status}" == 1 ]]
[[ "${output}" == 'Unmatched end marker' ]]
[[ "${actual_contents}" == "${expected_contents}" ]]
}
17 changes: 17 additions & 0 deletions dev-scripts/build-bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# Exit on first failure.
set -e

# Echo commands before executing them, by default to stderr.
set -x

# Exit on unset variable.
set -u

# Run bats tests.
bats \
--recursive \
scripts/ \
debian-pkg/ \
dev-scripts/

0 comments on commit a141353

Please sign in to comment.