Merge branch 'python-build-test'

This commit is contained in:
Yamashita Yuu 2014-01-17 21:28:03 +09:00
commit cbe7d0241b
17 changed files with 945 additions and 13 deletions

View file

@ -1,4 +1,8 @@
install: git clone https://github.com/sstephenson/bats.git
script: bats/bin/bats --tap test
# skips unnecessary Python-specific setup
after_script:
- bats/bin/bats --tap plugins/python-build/test
language: c
notifications:
email:
on_success: never

View file

@ -913,28 +913,37 @@ use_homebrew_yaml() {
fi
}
has_broken_mac_readline() {
if [ "$(uname -s)" = "Darwin" ] && ! use_homebrew_readline; then
# MacOSX 10.4 has a broken readline.
configured_with_readline_dir() {
# Mac OS X 10.4 has broken readline.
# https://github.com/yyuu/pyenv/issues/23
local retval=1
local conftest="$BUILD_PATH/has_broken_mac_readline.h"
echo "#include <readline/rlconf.h>" > "$conftest"
"${CPP:-cpp}" $CPPFLAGS "$conftest" 1>/dev/null 2>&1 || retval=0
rm -f "$conftest"
return "$retval"
else
return 1
local arg flag
for arg in ${CONFIGURE_OPTS} ${PYTHON_CONFIGURE_OPTS} "${PYTHON_CONFIGURE_OPTS_ARRAY[@]}"; do
if [[ "$arg" == "CPPFLAGS="* ]]; then
for flag in ${CPPFLAGS} ${arg##CPPFLAGS=}; do
if [[ "$flag" == "-I"* ]] && [ -e "${flag##-I}/readline/rlconf.h" ]; then
return 0
fi
done
fi
done
return 1
}
has_broken_mac_readline() {
[ "$(uname -s)" = "Darwin" ] &&
! configured_with_readline_dir &&
! use_homebrew_readline
}
use_homebrew_readline() {
if ! configured_with_readline_dir; then
local libdir="$(brew --prefix readline 2>/dev/null || true)"
if [ -d "$libdir" ]; then
package_option python configure CPPFLAGS="-I$libdir/include" LDFLAGS="-L$libdir/lib"
else
return 1
fi
fi
}
has_broken_mac_openssl() {

View file

@ -0,0 +1,299 @@
#!/usr/bin/env bats
load test_helper
export PYTHON_BUILD_CACHE_PATH="$TMP/cache"
export MAKE=make
export MAKE_OPTS="-j 2"
setup() {
mkdir -p "$INSTALL_ROOT"
stub md5 false
stub curl false
}
executable() {
local file="$1"
mkdir -p "${file%/*}"
cat > "$file"
chmod +x "$file"
}
cached_tarball() {
mkdir -p "$PYTHON_BUILD_CACHE_PATH"
pushd "$PYTHON_BUILD_CACHE_PATH" >/dev/null
tarball "$@"
popd >/dev/null
}
tarball() {
local name="$1"
local path="$PWD/$name"
local configure="$path/configure"
shift 1
executable "$configure" <<OUT
#!$BASH
echo "$name: \$@" \${PYTHONOPT:+PYTHONOPT=\$PYTHONOPT} >> build.log
OUT
for file; do
mkdir -p "$(dirname "${path}/${file}")"
touch "${path}/${file}"
done
tar czf "${path}.tar.gz" -C "${path%/*}" "$name"
}
stub_make_install() {
stub "$MAKE" \
" : echo \"$MAKE \$@\" >> build.log" \
"install : cat build.log >> '$INSTALL_ROOT/build.log'"
}
assert_build_log() {
run cat "$INSTALL_ROOT/build.log"
assert_output
}
@test "yaml is installed for python" {
cached_tarball "yaml-0.1.4"
cached_tarball "Python-3.2.1"
stub brew false
stub_make_install
stub_make_install
install_fixture definitions/needs-yaml
assert_success
unstub make
assert_build_log <<OUT
yaml-0.1.4: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 2
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 2
OUT
}
@test "apply python patch before building" {
cached_tarball "yaml-0.1.4"
cached_tarball "Python-3.2.1"
stub brew false
stub_make_install
stub_make_install
stub patch ' : echo patch "$@" >> build.log'
install_fixture --patch definitions/needs-yaml
assert_success
unstub make
unstub patch
assert_build_log <<OUT
yaml-0.1.4: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 2
patch -p0 -i -
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 2
OUT
}
@test "yaml is linked from Homebrew" {
cached_tarball "Python-3.2.1"
brew_libdir="$TMP/homebrew-yaml"
mkdir -p "$brew_libdir"
stub brew "--prefix libyaml : echo '$brew_libdir'" false
stub_make_install
install_fixture definitions/needs-yaml
assert_success
unstub brew
unstub make
assert_build_log <<OUT
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib CPPFLAGS=-I$brew_libdir/include LDFLAGS=-L$brew_libdir/lib
make -j 2
OUT
}
@test "readline is linked from Homebrew" {
cached_tarball "Python-3.2.1"
readline_libdir="$TMP/homebrew-readline"
mkdir -p "$readline_libdir"
stub brew "--prefix readline : echo '$readline_libdir'"
stub_make_install
run_inline_definition <<DEF
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"
DEF
assert_success
unstub brew
unstub make
assert_build_log <<OUT
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib CPPFLAGS=-I$readline_libdir/include LDFLAGS=-L$readline_libdir/lib
make -j 2
OUT
}
@test "readline is not linked from Homebrew when explicitly defined" {
cached_tarball "Python-3.2.1"
readline_libdir="$TMP/custom"
mkdir -p "$readline_libdir/include/readline"
touch "$readline_libdir/include/readline/rlconf.h"
stub brew
stub_make_install
export PYTHON_CONFIGURE_OPTS="CPPFLAGS=-I$readline_libdir/include LDFLAGS=-L$readline_libdir/lib"
run_inline_definition <<DEF
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"
DEF
assert_success
unstub brew
unstub make
assert_build_log <<OUT
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib CPPFLAGS=-I$readline_libdir/include LDFLAGS=-L$readline_libdir/lib
make -j 2
OUT
}
@test "number of CPU cores defaults to 2" {
cached_tarball "Python-3.2.1"
stub uname '-s : echo Darwin'
stub sysctl false
stub_make_install
export -n MAKE_OPTS
run_inline_definition <<DEF
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"
DEF
assert_success
unstub uname
unstub make
assert_build_log <<OUT
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 2
OUT
}
@test "number of CPU cores is detected on Mac" {
cached_tarball "Python-3.2.1"
stub uname '-s : echo Darwin'
stub sysctl '-n hw.ncpu : echo 4'
stub_make_install
export -n MAKE_OPTS
run_inline_definition <<DEF
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"
DEF
assert_success
unstub uname
unstub sysctl
unstub make
assert_build_log <<OUT
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 4
OUT
}
@test "custom relative install destination" {
export PYTHON_BUILD_CACHE_PATH="$FIXTURE_ROOT"
cd "$TMP"
install_fixture definitions/without-checksum ./here
assert_success
assert [ -x ./here/bin/package ]
}
@test "make on FreeBSD defaults to gmake" {
cached_tarball "Python-3.2.1"
stub uname "-s : echo FreeBSD"
MAKE=gmake stub_make_install
MAKE= install_fixture definitions/vanilla-python
assert_success
unstub gmake
unstub uname
}
@test "can use PYTHON_CONFIGURE to apply a patch" {
cached_tarball "Python-3.2.1"
executable "${TMP}/custom-configure" <<CONF
#!$BASH
apply -p1 -i /my/patch.diff
exec ./configure "\$@"
CONF
stub apply 'echo apply "$@" >> build.log'
stub_make_install
export PYTHON_CONFIGURE="${TMP}/custom-configure"
run_inline_definition <<DEF
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"
DEF
assert_success
unstub make
unstub apply
assert_build_log <<OUT
apply -p1 -i /my/patch.diff
Python-3.2.1: --prefix=$INSTALL_ROOT --libdir=$INSTALL_ROOT/lib
make -j 2
OUT
}
@test "copy strategy forces overwrite" {
export PYTHON_BUILD_CACHE_PATH="$FIXTURE_ROOT"
mkdir -p "$INSTALL_ROOT/bin"
touch "$INSTALL_ROOT/bin/package"
chmod -w "$INSTALL_ROOT/bin/package"
install_fixture definitions/without-checksum
assert_success
run "$INSTALL_ROOT/bin/package" "world"
assert_success "hello world"
}
@test "non-writable TMPDIR aborts build" {
export TMPDIR="${TMP}/build"
mkdir -p "$TMPDIR"
chmod -w "$TMPDIR"
touch "${TMP}/build-definition"
run python-build "${TMP}/build-definition" "$INSTALL_ROOT"
assert_failure "python-build: TMPDIR=$TMPDIR is set to a non-accessible location"
}
@test "non-executable TMPDIR aborts build" {
export TMPDIR="${TMP}/build"
mkdir -p "$TMPDIR"
chmod -x "$TMPDIR"
touch "${TMP}/build-definition"
run python-build "${TMP}/build-definition" "$INSTALL_ROOT"
assert_failure "python-build: TMPDIR=$TMPDIR is set to a non-accessible location"
}

View file

@ -0,0 +1,90 @@
#!/usr/bin/env bats
load test_helper
export PYTHON_BUILD_SKIP_MIRROR=1
export PYTHON_BUILD_CACHE_PATH="$TMP/cache"
setup() {
mkdir "$PYTHON_BUILD_CACHE_PATH"
}
@test "packages are saved to download cache" {
stub md5 true
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/without-checksum
[ "$status" -eq 0 ]
[ -e "${PYTHON_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]
unstub curl
unstub md5
}
@test "cached package without checksum" {
stub md5 true
stub curl
cp "${FIXTURE_ROOT}/package-1.0.0.tar.gz" "$PYTHON_BUILD_CACHE_PATH"
install_fixture definitions/without-checksum
[ "$status" -eq 0 ]
[ -e "${PYTHON_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]
unstub curl
unstub md5
}
@test "cached package with valid checksum" {
stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
stub curl
cp "${FIXTURE_ROOT}/package-1.0.0.tar.gz" "$PYTHON_BUILD_CACHE_PATH"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
[ -e "${PYTHON_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]
unstub curl
unstub md5
}
@test "cached package with invalid checksum falls back to mirror and updates cache" {
export PYTHON_BUILD_SKIP_MIRROR=
local checksum="83e6d7725e20166024a1eb74cde80677"
stub md5 true "echo invalid" "echo $checksum"
stub curl "-*I* : true" \
"-C - -o * -*S* http://?*/$checksum : cp $FIXTURE_ROOT/package-1.0.0.tar.gz \$4"
touch "${PYTHON_BUILD_CACHE_PATH}/package-1.0.0.tar.gz"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
[ -e "${PYTHON_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" ]
diff -q "${PYTHON_BUILD_CACHE_PATH}/package-1.0.0.tar.gz" "${FIXTURE_ROOT}/package-1.0.0.tar.gz"
unstub curl
unstub md5
}
@test "nonexistent cache directory is ignored" {
stub md5 true
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
export PYTHON_BUILD_CACHE_PATH="${TMP}/nonexistent"
install_fixture definitions/without-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
[ ! -d "$PYTHON_BUILD_CACHE_PATH" ]
unstub curl
unstub md5
}

View file

@ -0,0 +1,70 @@
#!/usr/bin/env bats
load test_helper
export PYTHON_BUILD_SKIP_MIRROR=1
export PYTHON_BUILD_CACHE_PATH=
@test "package URL without checksum" {
stub md5 true
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/without-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package URL with valid checksum" {
stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package URL with invalid checksum" {
stub md5 true "echo 83e6d7725e20166024a1eb74cde80677"
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-invalid-checksum
[ "$status" -eq 1 ]
[ ! -f "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package URL with checksum but no MD5 support" {
stub md5 false
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package with invalid checksum" {
stub md5 true "echo invalid"
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-checksum
[ "$status" -eq 1 ]
[ ! -f "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}

View file

@ -0,0 +1,14 @@
#!/usr/bin/env bats
load test_helper
export PYTHON_BUILD_SKIP_MIRROR=1
export PYTHON_BUILD_CACHE_PATH=
@test "failed download displays error message" {
stub curl false
install_fixture definitions/without-checksum
assert_failure
assert_output_contains "> http://example.com/packages/package-1.0.0.tar.gz"
assert_output_contains "error: failed to download package-1.0.0.tar.gz"
}

View file

@ -0,0 +1,2 @@
install_package "yaml-0.1.4" "http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz" --if needs_yaml
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"

View file

@ -0,0 +1 @@
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz"

View file

@ -0,0 +1 @@
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#83e6d7725e20166024a1eb74cde80677" copy

View file

@ -0,0 +1 @@
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#invalid" copy

View file

@ -0,0 +1 @@
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz" copy

Binary file not shown.

View file

@ -0,0 +1,56 @@
#!/usr/bin/env bats
load test_helper
setup() {
export PYENV_ROOT="${TMP}/pyenv"
export HOOK_PATH="${TMP}/i has hooks"
mkdir -p "$HOOK_PATH"
}
@test "pyenv-install hooks" {
cat > "${HOOK_PATH}/install.bash" <<OUT
before_install 'echo before: \$PREFIX'
after_install 'echo after: \$STATUS'
OUT
stub pyenv-hooks "install : echo '$HOOK_PATH'/install.bash"
stub pyenv-rehash "echo rehashed"
definition="${TMP}/3.2.1"
cat > "$definition" <<<"echo python-build"
run pyenv-install "$definition"
assert_success
assert_output <<-OUT
before: ${PYENV_ROOT}/versions/3.2.1
python-build
after: 0
rehashed
OUT
}
@test "pyenv-uninstall hooks" {
cat > "${HOOK_PATH}/uninstall.bash" <<OUT
before_uninstall 'echo before: \$PREFIX'
after_uninstall 'echo after.'
rm() {
echo "rm \$@"
command rm "\$@"
}
OUT
stub pyenv-hooks "uninstall : echo '$HOOK_PATH'/uninstall.bash"
stub pyenv-rehash "echo rehashed"
mkdir -p "${PYENV_ROOT}/versions/3.2.1"
run pyenv-uninstall -f 3.2.1
assert_success
assert_output <<-OUT
before: ${PYENV_ROOT}/versions/3.2.1
rm -rf ${PYENV_ROOT}/versions/3.2.1
rehashed
after.
OUT
assert [ ! -d "${PYENV_ROOT}/versions/3.2.1" ]
}

View file

@ -0,0 +1,49 @@
#!/usr/bin/env bats
load test_helper
@test "installs python-build into PREFIX" {
cd "$TMP"
PREFIX="${PWD}/usr" run "${BATS_TEST_DIRNAME}/../install.sh"
assert_success ""
cd usr
assert [ -x bin/python-build ]
assert [ -x bin/pyenv-install ]
assert [ -x bin/pyenv-uninstall ]
assert [ -e share/python-build/2.7.2 ]
assert [ -e share/python-build/pypy-2.0 ]
}
@test "overwrites old installation" {
cd "$TMP"
mkdir -p bin share/python-build
touch bin/python-build
touch share/python-build/2.7.2
PREFIX="$PWD" run "${BATS_TEST_DIRNAME}/../install.sh"
assert_success ""
assert [ -x bin/python-build ]
run grep "install_package" share/python-build/2.7.2
assert_success
}
@test "unrelated files are untouched" {
cd "$TMP"
mkdir -p bin share/bananas
chmod g-w bin
touch bin/bananas
touch share/bananas/docs
PREFIX="$PWD" run "${BATS_TEST_DIRNAME}/../install.sh"
assert_success ""
assert [ -e bin/bananas ]
assert [ -e share/bananas/docs ]
run ls -ld bin
assert_equal "r-x" "${output:4:3}"
}

View file

@ -0,0 +1,103 @@
#!/usr/bin/env bats
load test_helper
export PYTHON_BUILD_SKIP_MIRROR=
export PYTHON_BUILD_CACHE_PATH=
export PYTHON_BUILD_MIRROR_URL=http://mirror.example.com
@test "package URL without checksum bypasses mirror" {
stub md5 true
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/without-checksum
echo "$output" >&2
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package URL with checksum but no MD5 support bypasses mirror" {
stub md5 false
stub curl "-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package URL with checksum hits mirror first" {
local checksum="83e6d7725e20166024a1eb74cde80677"
local mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum"
stub md5 true "echo $checksum"
stub curl "-*I* $mirror_url : true" \
"-C - -o * -*S* $mirror_url : cp $FIXTURE_ROOT/package-1.0.0.tar.gz \$4"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package is fetched from original URL if mirror download fails" {
local checksum="83e6d7725e20166024a1eb74cde80677"
local mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum"
stub md5 true "echo $checksum"
stub curl "-*I* $mirror_url : false" \
"-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "package is fetched from original URL if mirror download checksum is invalid" {
local checksum="83e6d7725e20166024a1eb74cde80677"
local mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum"
stub md5 true "echo invalid" "echo $checksum"
stub curl "-*I* $mirror_url : true" \
"-C - -o * -*S* $mirror_url : cp $FIXTURE_ROOT/package-1.0.0.tar.gz \$4" \
"-C - -o * -*S* http://example.com/* : cp $FIXTURE_ROOT/\${6##*/} \$4"
install_fixture definitions/with-checksum
echo "$output" >&2
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}
@test "default mirror URL" {
export PYTHON_BUILD_MIRROR_URL=
local checksum="83e6d7725e20166024a1eb74cde80677"
stub md5 true "echo $checksum"
stub curl "-*I* : true" \
"-C - -o * -*S* http://?*/$checksum : cp $FIXTURE_ROOT/package-1.0.0.tar.gz \$4" \
install_fixture definitions/with-checksum
[ "$status" -eq 0 ]
[ -x "${INSTALL_ROOT}/bin/package" ]
unstub curl
unstub md5
}

View file

@ -0,0 +1,109 @@
#!/usr/bin/env bash
set -e
status=0
program="${0##*/}"
PROGRAM="$(echo "$program" | tr a-z- A-Z_)"
[ -n "$TMPDIR" ] || TMPDIR="/tmp"
_STUB_PLAN="${PROGRAM}_STUB_PLAN"
_STUB_RUN="${PROGRAM}_STUB_RUN"
_STUB_INDEX="${PROGRAM}_STUB_INDEX"
_STUB_RESULT="${PROGRAM}_STUB_RESULT"
_STUB_END="${PROGRAM}_STUB_END"
_STUB_DEBUG="${PROGRAM}_STUB_DEBUG"
if [ -n "${!_STUB_DEBUG}" ]; then
echo "$program" "$@" >&${!_STUB_DEBUG}
fi
[ -e "${!_STUB_PLAN}" ] || exit 1
[ -n "${!_STUB_RUN}" ] || eval "${_STUB_RUN}"="${TMPDIR}/${program}-stub-run"
# Initialize or load the stub run information.
eval "${_STUB_INDEX}"=1
eval "${_STUB_RESULT}"=0
[ ! -e "${!_STUB_RUN}" ] || source "${!_STUB_RUN}"
# Loop over each line in the plan.
index=0
while IFS= read -r line; do
index=$(($index + 1))
if [ -z "${!_STUB_END}" ] && [ $index -eq "${!_STUB_INDEX}" ]; then
# We found the plan line we're interested in.
# Start off by assuming success.
result=0
# Split the line into an array of arguments to
# match and a command to run to produce output.
command=" $line"
if [ "$command" != "${command/ : }" ]; then
patterns="${command%% : *}"
command="${command#* : }"
fi
# Naively split patterns by whitespace for now.
# In the future, use a sed script to split while
# respecting quoting.
set -f
patterns=($patterns)
set +f
arguments=("$@")
# Match the expected argument patterns to actual
# arguments.
for (( i=0; i<${#patterns[@]}; i++ )); do
pattern="${patterns[$i]}"
argument="${arguments[$i]}"
case "$argument" in
$pattern ) ;;
* ) result=1 ;;
esac
done
# If the arguments matched, evaluate the command
# in a subshell. Otherwise, log the failure.
if [ $result -eq 0 ] ; then
set +e
( eval "$command" )
status="$?"
set -e
else
eval "${_STUB_RESULT}"=1
fi
fi
done < "${!_STUB_PLAN}"
if [ -n "${!_STUB_END}" ]; then
# Clean up the run file.
rm -f "${!_STUB_RUN}"
# If the number of lines in the plan is larger than
# the requested index, we failed.
if [ $index -ge "${!_STUB_INDEX}" ]; then
eval "${_STUB_RESULT}"=1
fi
# Return the result.
exit "${!_STUB_RESULT}"
else
# If the requested index is larger than the number
# of lines in the plan file, we failed.
if [ "${!_STUB_INDEX}" -gt $index ]; then
eval "${_STUB_RESULT}"=1
fi
# Write out the run information.
{ echo "${_STUB_INDEX}=$((${!_STUB_INDEX} + 1))"
echo "${_STUB_RESULT}=${!_STUB_RESULT}"
} > "${!_STUB_RUN}"
exit "$status"
fi

View file

@ -0,0 +1,123 @@
export TMP="$BATS_TEST_DIRNAME/tmp"
if [ "$FIXTURE_ROOT" != "$BATS_TEST_DIRNAME/fixtures" ]; then
export FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures"
export INSTALL_ROOT="$TMP/install"
PATH=/usr/bin:/usr/sbin:/bin/:/sbin
PATH="$BATS_TEST_DIRNAME/../bin:$PATH"
PATH="$TMP/bin:$PATH"
export PATH
fi
teardown() {
rm -fr "$TMP"/*
}
stub() {
local program="$1"
local prefix="$(echo "$program" | tr a-z- A-Z_)"
shift
export "${prefix}_STUB_PLAN"="${TMP}/${program}-stub-plan"
export "${prefix}_STUB_RUN"="${TMP}/${program}-stub-run"
export "${prefix}_STUB_END"=
mkdir -p "${TMP}/bin"
ln -sf "${BATS_TEST_DIRNAME}/stubs/stub" "${TMP}/bin/${program}"
touch "${TMP}/${program}-stub-plan"
for arg in "$@"; do printf "%s\n" "$arg" >> "${TMP}/${program}-stub-plan"; done
}
unstub() {
local program="$1"
local prefix="$(echo "$program" | tr a-z- A-Z_)"
local path="${TMP}/bin/${program}"
export "${prefix}_STUB_END"=1
local STATUS=0
"$path" || STATUS="$?"
rm -f "$path"
rm -f "${TMP}/${program}-stub-plan" "${TMP}/${program}-stub-run"
return "$STATUS"
}
run_inline_definition() {
local definition="${TMP}/build-definition"
cat > "$definition"
run python-build "$definition" "${1:-$INSTALL_ROOT}"
}
install_fixture() {
local args
while [ "${1#-}" != "$1" ]; do
args="$args $1"
shift 1
done
local name="$1"
local destination="$2"
[ -n "$destination" ] || destination="$INSTALL_ROOT"
run python-build $args "$FIXTURE_ROOT/$name" "$destination"
}
assert() {
if ! "$@"; then
flunk "failed: $@"
fi
}
flunk() {
{ if [ "$#" -eq 0 ]; then cat -
else echo "$@"
fi
} | sed "s:${TMP}:\${TMP}:g" >&2
return 1
}
assert_success() {
if [ "$status" -ne 0 ]; then
{ echo "command failed with exit status $status"
echo "output: $output"
} | flunk
elif [ "$#" -gt 0 ]; then
assert_output "$1"
fi
}
assert_failure() {
if [ "$status" -eq 0 ]; then
flunk "expected failed exit status"
elif [ "$#" -gt 0 ]; then
assert_output "$1"
fi
}
assert_equal() {
if [ "$1" != "$2" ]; then
{ echo "expected: $1"
echo "actual: $2"
} | flunk
fi
}
assert_output() {
local expected
if [ $# -eq 0 ]; then expected="$(cat -)"
else expected="$1"
fi
assert_equal "$expected" "$output"
}
assert_output_contains() {
local expected="$1"
echo "$output" | grep -F "$expected" >/dev/null || {
{ echo "expected output to contain $expected"
echo "actual: $output"
} | flunk
}
}