| @ -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 | |||
| } | |||
| } | |||