@ -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 |
@ -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" | |||
} |
@ -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 | |||
} |
@ -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 | |||
} |
@ -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" | |||
} |
@ -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" |
@ -0,0 +1 @@ | |||
install_package "Python-3.2.1" "http://python.org/ftp/python/3.2.1/Python-3.2.1.tar.gz" |
@ -0,0 +1 @@ | |||
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#83e6d7725e20166024a1eb74cde80677" copy |
@ -0,0 +1 @@ | |||
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz#invalid" copy |
@ -0,0 +1 @@ | |||
install_package "package-1.0.0" "http://example.com/packages/package-1.0.0.tar.gz" copy |
@ -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" ] | |||
} |
@ -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}" | |||
} |
@ -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 | |||
} |
@ -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 |
@ -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 | |||
} | |||
} |