mirror of
https://github.com/kvz/bash3boilerplate.git
synced 2025-05-07 10:48:07 +00:00
Set up basic acceptance testing #4
This commit is contained in:
parent
68219d21d4
commit
63cd89a659
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
node_modules
|
||||||
|
4
.travis.yml
Normal file
4
.travis.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- "4.2.1"
|
||||||
|
script: npm run test
|
53
Makefile
53
Makefile
@ -1,19 +1,40 @@
|
|||||||
SHELL := /usr/bin/env bash
|
# Licensed under MIT.
|
||||||
|
# Copyright (2016) by Kevin van Zonneveld https://twitter.com/kvz
|
||||||
|
#
|
||||||
|
# https://www.npmjs.com/package/fakefile
|
||||||
|
#
|
||||||
|
# This Makefile offers convience shortcuts into any Node.js project that utilizes npm scripts.
|
||||||
|
# It functions as a wrapper around the actual listed in `package.json`
|
||||||
|
# So instead of typing:
|
||||||
|
#
|
||||||
|
# $ npm script build:assets
|
||||||
|
#
|
||||||
|
# you could also type:
|
||||||
|
#
|
||||||
|
# $ make build-assets
|
||||||
|
#
|
||||||
|
# Notice that colons (:) are replaced by dashes for Makefile compatibility.
|
||||||
|
#
|
||||||
|
# The benefits of this wrapper are:
|
||||||
|
#
|
||||||
|
# - You get to keep the the scripts package.json, which is more portable
|
||||||
|
# (Makefiles & Windows are harder to mix)
|
||||||
|
# - Offer a polite way into the project for developers coming from different
|
||||||
|
# languages (npm scripts is obviously very Node centric)
|
||||||
|
# - Profit from better autocomplete (make <TAB><TAB>) than npm currently offers.
|
||||||
|
# OSX users will have to install bash-completion
|
||||||
|
# (http://davidalger.com/development/bash-completion-on-os-x-with-brew/)
|
||||||
|
|
||||||
.PHONY: release-major
|
define npm_script_targets
|
||||||
release-major:
|
TARGETS := $(shell node -e 'for (var k in require("./package.json").scripts) {console.log(k.replace(/:/g, "-"));}')
|
||||||
npm version major -m "Release %s"
|
$$(TARGETS):
|
||||||
git push
|
npm run $(subst -,:,$(MAKECMDGOALS))
|
||||||
npm publish
|
|
||||||
|
|
||||||
.PHONY: release-minor
|
.PHONY: $$(TARGETS)
|
||||||
release-minor:
|
endef
|
||||||
npm version minor -m "Release %s"
|
|
||||||
git push
|
|
||||||
npm publish
|
|
||||||
|
|
||||||
.PHONY: release-patch
|
$(eval $(call npm_script_targets))
|
||||||
release-patch:
|
|
||||||
npm version patch -m "Release %s"
|
# These npm run scripts are available, without needing to be mentioned in `package.json`
|
||||||
git push
|
install:
|
||||||
npm publish
|
npm run install
|
||||||
|
10
package.json
10
package.json
@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "bash3boilerplate",
|
"name": "bash3boilerplate",
|
||||||
"description": "Copypastable templates to write better bash scripts",
|
"description": "Copypastable templates to write better bash scripts",
|
||||||
"version": "1.1.0"
|
"version": "1.1.0",
|
||||||
|
"scripts": {
|
||||||
|
"release:major": "env SEMANTIC=major npm run release",
|
||||||
|
"release:minor": "env SEMANTIC=minor npm run release",
|
||||||
|
"release:patch": "env SEMANTIC=patch npm run release",
|
||||||
|
"test": "test/acceptance.sh",
|
||||||
|
"save:fixtures": "cross-env SAVE_FIXTURES=true npm run test",
|
||||||
|
"release": "npm version ${SEMANTIC:-patch} -m \"Release %s\" && git push --tags && npm publish"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
165
test/acceptance.sh
Executable file
165
test/acceptance.sh
Executable file
@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
# set -o xtrace
|
||||||
|
|
||||||
|
# Set magic variables for current FILE & DIR
|
||||||
|
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||||
|
__base="$(basename ${__file} .sh)"
|
||||||
|
__root="$(cd "$(dirname "${__dir}")" && pwd)"
|
||||||
|
|
||||||
|
scenarios="${1:-$(ls ${__dir}/scenario/|egrep -v ^prepare$)}"
|
||||||
|
|
||||||
|
__sysTmpDir="${TMPDIR:-/tmp}"
|
||||||
|
__sysTmpDir="${__sysTmpDir%/}" # <-- remove trailing slash on macosx
|
||||||
|
__b3bpTmpDir="${__sysTmpDir}/b3bp"
|
||||||
|
mkdir -p "${__b3bpTmpDir}"
|
||||||
|
|
||||||
|
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
||||||
|
cmdSed=gsed
|
||||||
|
else
|
||||||
|
cmdSed=sed
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
||||||
|
cmdTimeout="gtimeout --kill-after=6m 5m"
|
||||||
|
else
|
||||||
|
cmdTimeout="timeout --kill-after=6m 5m"
|
||||||
|
fi
|
||||||
|
|
||||||
|
__node="$(which node)"
|
||||||
|
|
||||||
|
__os="linux"
|
||||||
|
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
||||||
|
__os="darwin"
|
||||||
|
fi
|
||||||
|
__arch="amd64"
|
||||||
|
|
||||||
|
|
||||||
|
if ! which "${cmdSed}" > /dev/null; then
|
||||||
|
echo "Please install ${cmdSed}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Running prepare before other scenarios is important on Travis,
|
||||||
|
# so that stdio can diverge - and we can enforce stricter
|
||||||
|
# stdio comparison on all other tests.
|
||||||
|
for scenario in $(echo ${scenarios}); do
|
||||||
|
echo "==> Scenario: ${scenario}"
|
||||||
|
pushd "${__dir}/scenario/${scenario}" > /dev/null
|
||||||
|
|
||||||
|
# Run scenario
|
||||||
|
(${cmdTimeout} bash ./run.sh \
|
||||||
|
> "${__b3bpTmpDir}/${scenario}.stdio" 2>&1; \
|
||||||
|
echo "${?}" > "${__b3bpTmpDir}/${scenario}.exitcode" \
|
||||||
|
) || true
|
||||||
|
|
||||||
|
# Clear out environmental specifics
|
||||||
|
for typ in $(echo stdio exitcode); do
|
||||||
|
curFile="${__b3bpTmpDir}/${scenario}.${typ}"
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-e "s@${__node}@{node}@g" "${curFile}" \
|
||||||
|
-e "s@${__root}@{root}@g" "${curFile}" \
|
||||||
|
-e "s@${__sysTmpDir}@{tmpdir}@g" "${curFile}" \
|
||||||
|
-e "s@${HOME:-/home/travis}@{home}@g" "${curFile}" \
|
||||||
|
-e "s@${USER:-travis}@{user}@g" "${curFile}" \
|
||||||
|
-e "s@travis@{user}@g" "${curFile}" \
|
||||||
|
-e "s@kvz@{user}@g" "${curFile}" \
|
||||||
|
-e "s@{root}/node_modules/\.bin/node@{node}@g" "${curFile}" \
|
||||||
|
-e "s@{home}/build/{user}/fre{node}@{node}@g" "${curFile}" \
|
||||||
|
-e "s@${HOSTNAME}@{hostname}@g" "${curFile}" \
|
||||||
|
-e "s@${__os}@{os}@g" "${curFile}" \
|
||||||
|
-e "s@${__arch}@{arch}@g" "${curFile}" \
|
||||||
|
-e "s@OSX@{os}@g" "${curFile}" \
|
||||||
|
-e "s@Linux@{os}@g" "${curFile}" \
|
||||||
|
|| false
|
||||||
|
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_IPS' |wc -l)" -gt 0 ]; then
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}@{ip}@g' \
|
||||||
|
"${curFile}"
|
||||||
|
|
||||||
|
# IPs vary in length. Ansible uses padding. {ip} does not vary in length
|
||||||
|
# so kill the padding after it for consistent output
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@\{ip\}\s+@{ip} @g' \
|
||||||
|
"${curFile}"
|
||||||
|
fi
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_UUIDS' |wc -l)" -gt 0 ]; then
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@[0-9a-f\-]{32,40}@{uuid}@g' \
|
||||||
|
"${curFile}"
|
||||||
|
fi
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_BIGINTS' |wc -l)" -gt 0 ]; then
|
||||||
|
# Such as: 3811298194
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@[0-9]{7,64}@{bigint}@g' \
|
||||||
|
"${curFile}"
|
||||||
|
fi
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_DATETIMES' |wc -l)" -gt 0 ]; then
|
||||||
|
# Such as: 2016-02-10 15:38:44.420094
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}@{datetime}@g' \
|
||||||
|
"${curFile}"
|
||||||
|
fi
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_LONGTIMES' |wc -l)" -gt 0 ]; then
|
||||||
|
# Such as: 2016-02-10 15:38:44.420094
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{6}@{longtime}@g' \
|
||||||
|
"${curFile}"
|
||||||
|
fi
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_DURATIONS' |wc -l)" -gt 0 ]; then
|
||||||
|
# Such as: 0:00:00.001991
|
||||||
|
"${cmdSed}" -i \
|
||||||
|
-r 's@[0-9]{1,2}:[0-9]{2}:[0-9]{2}.[0-9]{6}@{duration}@g' \
|
||||||
|
"${curFile}"
|
||||||
|
fi
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_REPLACE_REMOTE_EXEC' |wc -l)" -gt 0 ]; then
|
||||||
|
egrep -v 'remote-exec\): [ a-zA-Z]' "${curFile}" > "${__sysTmpDir}/b3bp-filtered.txt"
|
||||||
|
mv "${__sysTmpDir}/b3bp-filtered.txt" "${curFile}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Save these as new fixtures?
|
||||||
|
if [ "${SAVE_FIXTURES:-}" = "true" ]; then
|
||||||
|
for typ in $(echo stdio exitcode); do
|
||||||
|
curFile="${__b3bpTmpDir}/${scenario}.${typ}"
|
||||||
|
cp -f \
|
||||||
|
"${curFile}" \
|
||||||
|
"${__dir}/fixture/${scenario}.${typ}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compare
|
||||||
|
for typ in $(echo stdio exitcode); do
|
||||||
|
curFile="${__b3bpTmpDir}/${scenario}.${typ}"
|
||||||
|
|
||||||
|
echo -n " comparing ${typ}.. "
|
||||||
|
|
||||||
|
if [ "${typ}" = "stdio" ]; then
|
||||||
|
if [ "$(cat "${curFile}" |grep 'B3BP:STDIO_SKIP_COMPARE' |wc -l)" -gt 0 ]; then
|
||||||
|
echo "skip"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
diff \
|
||||||
|
--strip-trailing-cr \
|
||||||
|
"${__dir}/fixture/${scenario}.${typ}" \
|
||||||
|
"${curFile}" || ( \
|
||||||
|
echo -e "\n\n==> MISMATCH OF: ${typ}";
|
||||||
|
echo -e "\n\n==> EXPECTED STDIO: ";
|
||||||
|
cat "${__dir}/fixture/${scenario}.stdio";
|
||||||
|
echo -e "\n\n==> ACTUAL STDIO: ";
|
||||||
|
cat "${__b3bpTmpDir}/${scenario}.stdio";
|
||||||
|
exit 1; \
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "✓"
|
||||||
|
done
|
||||||
|
|
||||||
|
popd "${__dir}/scenario/${scenario}" > /dev/null
|
||||||
|
done
|
0
test/fixture/.empty
Normal file
0
test/fixture/.empty
Normal file
1
test/fixture/help.exitcode
Normal file
1
test/fixture/help.exitcode
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
10
test/fixture/help.stdio
Normal file
10
test/fixture/help.stdio
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
B3BP:STDIO_REPLACE_DATETIMES
|
||||||
|
|
||||||
|
Help using {root}/main.sh
|
||||||
|
|
||||||
|
-f [arg] Filename to process. Required.
|
||||||
|
-t [arg] Location of tempfile. Default="/tmp/bar"
|
||||||
|
-d Enables debug mode
|
||||||
|
-h This page
|
||||||
|
|
||||||
|
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
15
test/scenario/help/run.sh
Executable file
15
test/scenario/help/run.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -o pipefail
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
# set -o xtrace
|
||||||
|
|
||||||
|
# Set magic variables for current FILE & DIR
|
||||||
|
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||||
|
__base="$(basename ${__file} .sh)"
|
||||||
|
__root="$(cd "$(dirname $(dirname $(dirname "${__dir}")))" && pwd)"
|
||||||
|
|
||||||
|
echo "B3BP:STDIO_REPLACE_DATETIMES"
|
||||||
|
|
||||||
|
bash "${__root}/main.sh" -h
|
Loading…
x
Reference in New Issue
Block a user