diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 203534cb..9182ee3a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,6 +71,15 @@ jobs: name: docker-gen.tar path: docker-gen.tar + unit-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Required Dependencies + run: make install-unit-test-deps + - name: Run Unit Tests + run: make unit-test + docker-specs-tests: needs: companion-build runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 08ef5882..d0e86463 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,6 @@ vhost.d/ go/ nginx.tmpl test/local_test_env.sh -test/tests/docker_api/expected-std-out.txt -test/tests/container_restart/docker_event_out.txt -test/tests/certs_standalone/letsencrypt_user_data +test/integration/docker_api/expected-std-out.txt +test/integration/container_restart/docker_event_out.txt +test/integration/certs_standalone/letsencrypt_user_data diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..80bb0a83 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +.DEFAULT_GOAL := help + +.PHONY: help +help: ## Show help +# Source: https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: install +install: install-unit-test-deps ## Install all dev dependencies + +.PHONY: install-unit-test-deps +install-unit-test-deps: + ./hack/make-rules/install-unit-test-deps.sh + +.PHONY: unit-test +unit-test: ## Run all tests + ./hack/make-rules/unit-test.sh + +.PHONY: verify +verify: ## Verify that dev dependencies are installed and correctly configured + ./hack/make-rules/verify.sh \ No newline at end of file diff --git a/hack/init.sh b/hack/init.sh new file mode 100644 index 00000000..1659339d --- /dev/null +++ b/hack/init.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2034 # Variables sourced in other scripts. + +PROJECT_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +THIRD_PARTY=$PROJECT_ROOT/third_party diff --git a/hack/make-rules/install-unit-test-deps.sh b/hack/make-rules/install-unit-test-deps.sh new file mode 100755 index 00000000..137e619c --- /dev/null +++ b/hack/make-rules/install-unit-test-deps.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +PROJECT_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) + +# shellcheck disable=SC1090 # Sourced files +source "$PROJECT_ROOT/hack/shunit2.sh" + +shunit2::install diff --git a/hack/make-rules/unit-test.sh b/hack/make-rules/unit-test.sh new file mode 100755 index 00000000..83c6fdf4 --- /dev/null +++ b/hack/make-rules/unit-test.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2034 # Variables sourced in other scripts. + +set -e +shopt -s globstar + +PROJECT_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) + +UNIT_TEST_DIR=$PROJECT_ROOT/test/unit + +source_all_files_recursively_from() { + local directory=$1 + for file in "$directory"/**/*.sh; do + # shellcheck disable=SC1090 # Sourced files + source "$file" + done +} + +# shellcheck disable=SC1090 # Sourced files +source "$PROJECT_ROOT/hack/shunit2.sh" + +suite() { + source_all_files_recursively_from "$UNIT_TEST_DIR" +} + +# shellcheck disable=SC1090 # Sourced files +. "$SHUNIT2_BIN" diff --git a/hack/make-rules/verify.sh b/hack/make-rules/verify.sh new file mode 100644 index 00000000..df7fc75c --- /dev/null +++ b/hack/make-rules/verify.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +PROJECT_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) + +# shellcheck disable=SC1090 # Sourced files +source "$PROJECT_ROOT/hack/shunit2.sh" + +shunit2::validate diff --git a/hack/shunit2.sh b/hack/shunit2.sh new file mode 100644 index 00000000..64cbf71d --- /dev/null +++ b/hack/shunit2.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2034 # Variables sourced in other scripts. + +PROJECT_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) + +# shellcheck disable=SC1090 # Sourced files +source "$PROJECT_ROOT/hack/init.sh" + +SHUNIT2_VERSION=v2.1.8 +SHUNIT2_REPO_URL=https://github.com/kward/shunit2 +SHUNIT2_DIR=$THIRD_PARTY/shunit2 +SHUNIT2_BIN=$SHUNIT2_DIR/shunit2 + +shunit2::validate() { + # Validate shUnit2 is installed + if [[ ! -d $SHUNIT2_DIR ]]; then + echo "shUnit2 is not installed." + return 1 + fi + + # Validate installed version + local expected_release=$SHUNIT2_VERSION + local current_release + + current_release=$(cd "$SHUNIT2_DIR" && git describe --tags) + if [[ "$current_release" != "$expected_release" ]]; then + echo "shUnit2 version $expected_release required, the current version" \ + "installed is $current_release." + return 1 + fi +} + +shunit2::install() { + if shunit2::validate; then + echo "shUnit2 ${SHUNIT2_VERSION} already installed." + return 1 + else + shunit2::cleanup + + git clone --branch "$SHUNIT2_VERSION" "$SHUNIT2_REPO_URL" "$SHUNIT2_DIR" + chmod +x "$SHUNIT2_BIN" + fi +} + +shunit2::cleanup() { + if [[ -d "$SHUNIT2_DIR" ]]; then + rm -rf "$SHUNIT2_DIR" + fi +} diff --git a/test/tests/acme_accounts/expected-std-out.txt b/test/integration/acme_accounts/expected-std-out.txt similarity index 100% rename from test/tests/acme_accounts/expected-std-out.txt rename to test/integration/acme_accounts/expected-std-out.txt diff --git a/test/tests/acme_accounts/run.sh b/test/integration/acme_accounts/run.sh similarity index 100% rename from test/tests/acme_accounts/run.sh rename to test/integration/acme_accounts/run.sh diff --git a/test/tests/certs_san/expected-std-out.txt b/test/integration/certs_san/expected-std-out.txt similarity index 100% rename from test/tests/certs_san/expected-std-out.txt rename to test/integration/certs_san/expected-std-out.txt diff --git a/test/tests/certs_san/run.sh b/test/integration/certs_san/run.sh similarity index 100% rename from test/tests/certs_san/run.sh rename to test/integration/certs_san/run.sh diff --git a/test/tests/certs_single/expected-std-out.txt b/test/integration/certs_single/expected-std-out.txt similarity index 100% rename from test/tests/certs_single/expected-std-out.txt rename to test/integration/certs_single/expected-std-out.txt diff --git a/test/tests/certs_single/run.sh b/test/integration/certs_single/run.sh similarity index 100% rename from test/tests/certs_single/run.sh rename to test/integration/certs_single/run.sh diff --git a/test/tests/certs_single_domain/expected-std-out.txt b/test/integration/certs_single_domain/expected-std-out.txt similarity index 100% rename from test/tests/certs_single_domain/expected-std-out.txt rename to test/integration/certs_single_domain/expected-std-out.txt diff --git a/test/tests/certs_single_domain/run.sh b/test/integration/certs_single_domain/run.sh similarity index 100% rename from test/tests/certs_single_domain/run.sh rename to test/integration/certs_single_domain/run.sh diff --git a/test/tests/certs_standalone/expected-std-out.txt b/test/integration/certs_standalone/expected-std-out.txt similarity index 100% rename from test/tests/certs_standalone/expected-std-out.txt rename to test/integration/certs_standalone/expected-std-out.txt diff --git a/test/tests/certs_standalone/run.sh b/test/integration/certs_standalone/run.sh similarity index 92% rename from test/tests/certs_standalone/run.sh rename to test/integration/certs_standalone/run.sh index 20e5855b..345621b5 100755 --- a/test/tests/certs_standalone/run.sh +++ b/test/integration/certs_standalone/run.sh @@ -36,7 +36,7 @@ function cleanup { trap cleanup EXIT # Create letsencrypt_user_data with a single domain cert -cat > "${GITHUB_WORKSPACE}/test/tests/certs_standalone/letsencrypt_user_data" < "${GITHUB_WORKSPACE}/test/integration/certs_standalone/letsencrypt_user_data" < "${GITHUB_WORKSPACE}/test/tests/certs_standalone/letsencrypt_user_data" < "${GITHUB_WORKSPACE}/test/integration/certs_standalone/letsencrypt_user_data" < "${GITHUB_WORKSPACE}/test/tests/container_restart/docker_event_out.txt" & + --format 'Container {{.Actor.Attributes.name}} restarted' > "${GITHUB_WORKSPACE}/test/integration/container_restart/docker_event_out.txt" & docker_events_pid=$! # Cleanup function with EXIT trap @@ -23,7 +23,7 @@ function cleanup { # Kill the Docker events listener kill $docker_events_pid && wait $docker_events_pid 2>/dev/null # Remove temporary files - rm -f "${GITHUB_WORKSPACE}/test/tests/container_restart/docker_event_out.txt" + rm -f "${GITHUB_WORKSPACE}/test/integration/container_restart/docker_event_out.txt" # Remove any remaining Nginx container(s) silently. for domain in "${domains[@]}"; do docker rm --force "$domain" &> /dev/null @@ -42,7 +42,7 @@ for domain in "${domains[@]}"; do # Check if container restarted timeout="$(date +%s)" timeout="$((timeout + 60))" - until grep "$domain" "${GITHUB_WORKSPACE}"/test/tests/container_restart/docker_event_out.txt; do + until grep "$domain" "${GITHUB_WORKSPACE}"/test/integration/container_restart/docker_event_out.txt; do if [[ "$(date +%s)" -gt "$timeout" ]]; then echo "Container $domain didn't restart in under one minute." break diff --git a/test/tests/default_cert/expected-std-out.txt b/test/integration/default_cert/expected-std-out.txt similarity index 100% rename from test/tests/default_cert/expected-std-out.txt rename to test/integration/default_cert/expected-std-out.txt diff --git a/test/tests/default_cert/run.sh b/test/integration/default_cert/run.sh similarity index 100% rename from test/tests/default_cert/run.sh rename to test/integration/default_cert/run.sh diff --git a/test/tests/docker_api/run.sh b/test/integration/docker_api/run.sh similarity index 98% rename from test/tests/docker_api/run.sh rename to test/integration/docker_api/run.sh index 84acf098..209e767d 100755 --- a/test/tests/docker_api/run.sh +++ b/test/integration/docker_api/run.sh @@ -78,7 +78,7 @@ case $SETUP in "$1" \ bash -c "$commands" 2>&1 - cat > "${GITHUB_WORKSPACE}/test/tests/docker_api/expected-std-out.txt" < "${GITHUB_WORKSPACE}/test/integration/docker_api/expected-std-out.txt" <&1 - cat > "${GITHUB_WORKSPACE}/test/tests/docker_api/expected-std-out.txt" < "${GITHUB_WORKSPACE}/test/integration/docker_api/expected-std-out.txt" < "$location_file" # Create le1.wtf configuration file, *.le3.wtf and test.* from inside the nginx container diff --git a/test/tests/ocsp_must_staple/expected-std-out.txt b/test/integration/ocsp_must_staple/expected-std-out.txt similarity index 100% rename from test/tests/ocsp_must_staple/expected-std-out.txt rename to test/integration/ocsp_must_staple/expected-std-out.txt diff --git a/test/tests/ocsp_must_staple/run.sh b/test/integration/ocsp_must_staple/run.sh similarity index 100% rename from test/tests/ocsp_must_staple/run.sh rename to test/integration/ocsp_must_staple/run.sh diff --git a/test/tests/permissions_custom/expected-std-out.txt b/test/integration/permissions_custom/expected-std-out.txt similarity index 100% rename from test/tests/permissions_custom/expected-std-out.txt rename to test/integration/permissions_custom/expected-std-out.txt diff --git a/test/tests/permissions_custom/run.sh b/test/integration/permissions_custom/run.sh similarity index 100% rename from test/tests/permissions_custom/run.sh rename to test/integration/permissions_custom/run.sh diff --git a/test/tests/permissions_default/expected-std-out.txt b/test/integration/permissions_default/expected-std-out.txt similarity index 100% rename from test/tests/permissions_default/expected-std-out.txt rename to test/integration/permissions_default/expected-std-out.txt diff --git a/test/tests/permissions_default/run.sh b/test/integration/permissions_default/run.sh similarity index 100% rename from test/tests/permissions_default/run.sh rename to test/integration/permissions_default/run.sh diff --git a/test/tests/private_keys/expected-std-out.txt b/test/integration/private_keys/expected-std-out.txt similarity index 100% rename from test/tests/private_keys/expected-std-out.txt rename to test/integration/private_keys/expected-std-out.txt diff --git a/test/tests/private_keys/run.sh b/test/integration/private_keys/run.sh similarity index 100% rename from test/tests/private_keys/run.sh rename to test/integration/private_keys/run.sh diff --git a/test/tests/symlinks/expected-std-out.txt b/test/integration/symlinks/expected-std-out.txt similarity index 100% rename from test/tests/symlinks/expected-std-out.txt rename to test/integration/symlinks/expected-std-out.txt diff --git a/test/tests/symlinks/run.sh b/test/integration/symlinks/run.sh similarity index 100% rename from test/tests/symlinks/run.sh rename to test/integration/symlinks/run.sh diff --git a/test/tests/test-functions.sh b/test/integration/test-functions.sh similarity index 100% rename from test/tests/test-functions.sh rename to test/integration/test-functions.sh diff --git a/test/tests/unit_tests/expected-std-out.txt b/test/integration/unit_tests/expected-std-out.txt similarity index 100% rename from test/tests/unit_tests/expected-std-out.txt rename to test/integration/unit_tests/expected-std-out.txt diff --git a/test/run.sh b/test/run.sh index 7c9abb8c..1ea0a031 100755 --- a/test/run.sh +++ b/test/run.sh @@ -208,8 +208,8 @@ if [[ -z $GITHUB_ACTIONS ]] && [[ -f "$dir/local_test_env.sh" ]]; then source "$dir/local_test_env.sh" fi -# shellcheck source=./tests/test-functions.sh -source "$dir/tests/test-functions.sh" +# shellcheck source=./integration/test-functions.sh +source "$dir/integration/test-functions.sh" ## End of additional code usage() { @@ -296,12 +296,12 @@ for conf in "${configs[@]}"; do for testName in ${globalTests[@]} ${imageTests[@]}; do [ "${testPaths[$testName]}" ] && continue - if [ -d "$confDir/tests/$testName" ]; then + if [ -d "$confDir/integration/$testName" ]; then # Test directory found relative to the conf file - testPaths[$testName]="$confDir/tests/$testName" - elif [ -d "$dir/tests/$testName" ]; then + testPaths[$testName]="$confDir/integration/$testName" + elif [ -d "$dir/integration/$testName" ]; then # Test directory found in the main tests/ directory - testPaths[$testName]="$dir/tests/$testName" + testPaths[$testName]="$dir/integration/$testName" fi done done diff --git a/test/unit/test-template.sh b/test/unit/test-template.sh new file mode 100644 index 00000000..084a6dba --- /dev/null +++ b/test/unit/test-template.sh @@ -0,0 +1,8 @@ +#! /bin/sh + +testEquality() +{ + assertEquals 1 1 +} + +suite_addTest testEquality