Permalink
Browse files

Adds bats tests and use-pgbouncer script (#91)

This is to support a new, in development, way of using pgbouncer on Heroku Postgres.
  • Loading branch information...
gregburek committed Oct 2, 2017
1 parent 62b3003 commit 1ed90f87c9ffa618e0391b021b8e8803a6a0a8e8
Showing with 287 additions and 0 deletions.
  1. +9 −0 .travis.yml
  2. +5 −0 bin/compile
  3. +36 −0 bin/use-pgbouncer
  4. +165 −0 test/helper.bash
  5. +3 −0 test/run_all.sh
  6. +69 −0 test/use-pgbouncer.bats
View
@@ -0,0 +1,9 @@
language: bash
sudo: required
dist: trusty
before_install:
- sudo add-apt-repository ppa:duggan/bats --yes
- sudo apt-get update -qq
- sudo apt-get install -qq bats
script:
- ./test/run_all.sh
View
@@ -67,4 +67,9 @@ mkdir -p $BUILD_DIR/bin
cp "$BUILDPACK_DIR/bin/start-pgbouncer-stunnel" $BUILD_DIR/bin/
chmod +x $BUILD_DIR/bin/start-pgbouncer-stunnel
echo "-----> Moving the use-pgbouncer script into app/bin"
mkdir -p $BUILD_DIR/bin
cp "$BUILDPACK_DIR/bin/use-pgbouncer" $BUILD_DIR/bin/
chmod +x $BUILD_DIR/bin/use-pgbouncer
echo "-----> pgbouncer/stunnel done"
View
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
main() {
at pgbouncer-enabled
POSTGRES_URLS=${PGBOUNCER_URLS:-DATABASE_URL}
for POSTGRES_URL in $POSTGRES_URLS
do
at "mutating-${POSTGRES_URL}"
eval POSTGRES_URL_VALUE=\$$POSTGRES_URL
pattern='^postgres(ql)?:\/\/([^:\/]+):([^@\/]*)@([^:\/?]+):([0-9]+)(\/[^?]*)?(\?[^#]*)?$'
[[ "$POSTGRES_URL_VALUE" =~ $pattern ]] || return 1;
db_user=${BASH_REMATCH[2]}
db_password=${BASH_REMATCH[3]}
db_host=${BASH_REMATCH[4]}
db_port=${BASH_REMATCH[5]}
db_path=${BASH_REMATCH[6]}
db_query=${BASH_REMATCH[7]}
at "adding-one-to-${db_port}"
client_port=$((db_port + 1))
export ${POSTGRES_URL}_PGBOUNCER=postgres://"$db_user":"$db_password"@"$db_host":"$client_port""$db_path""$db_query"
eval "$POSTGRES_URL=\$${POSTGRES_URL}_PGBOUNCER"
done
at starting-app
exec "$@"
}
at() {
echo "buildpack=pgbouncer at=$*"
}
[[ "$0" != "$BASH_SOURCE" ]] || main "$@"
View
@@ -0,0 +1,165 @@
: <<COMMENTBLOCK
Adapted from https://github.com/jasonkarns/bats-assert/blob/c33dd8de65502c4aa6ea5d46ac4631d829889a1f/all.bash
The MIT License (MIT)
Copyright (c) 2015 Jason Karns
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
COMMENTBLOCK
flunk() {
{ if [ "$#" -eq 0 ]; then cat -
else echo "$@"
fi
} | sed "s:${BATS_TMPDIR}:\${BATS_TMPDIR}:g" >&2
return 1
}
assert() {
if ! "$@"; then
flunk "failed: $@"
fi
}
refute() {
if "$@"; then
flunk "expected to fail: $@"
fi
}
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
}
refute_equal() {
if [ "$1" = "$2" ]; then
flunk "unexpectedly equal: $1"
fi
}
assert_not_equal() {
refute_equal "$@"
}
assert_contains() {
local haystack="$1"
local needle="$2"
echo "$haystack" | $(type -p ggrep grep | head -1) -F -- "$needle" >/dev/null || {
{ echo "expected: $haystack"
echo "to contain: $needle"
} | flunk
}
}
refute_contains() {
local haystack="$1"
local needle="$2"
! assert_contains "$haystack" "$needle" || {
{ echo "expected: $haystack"
echo "not to contain: $needle"
} | flunk
}
}
assert_starts_with() {
if [ "$1" = "${1#${2}}" ]; then
{ echo "expected: $1"
echo "to start with: $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
if [ $# -eq 0 ]; then expected="$(cat -)"
else expected="$1"
fi
assert_contains "$output" "$expected"
}
refute_output_contains() {
local expected
if [ $# -eq 0 ]; then expected="$(cat -)"
else expected="$1"
fi
refute_contains "$output" "$expected"
}
assert_line() {
if [ "$1" -ge 0 ] 2>/dev/null; then
assert_equal "$2" "${lines[$1]}"
else
local line
for line in "${lines[@]}"; do
if [ "$line" = "$1" ]; then return 0; fi
done
{ echo "expected line: $1"
echo "to be found in:"
( IFS=$'\n'; echo "${lines[*]}" )
} | flunk
fi
}
refute_line() {
if [ "$1" -ge 0 ] 2>/dev/null; then
refute_equal "$2" "${lines[$1]}"
else
local line
for line in "${lines[@]}"; do
if [ "$line" = "$1" ]; then
{ echo "expected to not find line: $line"
echo "in:"
( IFS=$'\n'; echo "${lines[*]}" )
} | flunk
return $? # in case flunk didn't exit the loop
fi
done
fi
}
View
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
env -i TERM=$TERM bash -c "bats ./test/*.bats"
View
@@ -0,0 +1,69 @@
#!/usr/bin/env bats
load helper
@test "returns exit code of 1 with nothing to parse" {
run bin/use-pgbouncer "printenv"
assert_failure
assert_line 'buildpack=pgbouncer at=pgbouncer-enabled'
assert_line 'buildpack=pgbouncer at=mutating-DATABASE_URL'
refute_line 'buildpack=pgbouncer at=adding-one-to-5432'
}
@test "mutates DATABASE_URL" {
export DATABASE_URL='postgres://user:pass@host:5432/name?query'
run bin/use-pgbouncer "printenv"
assert_success
assert_line 'buildpack=pgbouncer at=pgbouncer-enabled'
assert_line 'buildpack=pgbouncer at=mutating-DATABASE_URL'
assert_line 'buildpack=pgbouncer at=adding-one-to-5432'
assert_line 'buildpack=pgbouncer at=starting-app'
assert_line 'DATABASE_URL_PGBOUNCER=postgres://user:pass@host:5433/name?query'
assert_line 'DATABASE_URL=postgres://user:pass@host:5433/name?query'
}
@test "substitutes postgres for postgresql in scheme" {
export DATABASE_URL='postgresql://user:pass@host:5432/name?query'
run bin/use-pgbouncer "printenv"
assert_success
assert_line 'buildpack=pgbouncer at=pgbouncer-enabled'
assert_line 'buildpack=pgbouncer at=mutating-DATABASE_URL'
assert_line 'buildpack=pgbouncer at=adding-one-to-5432'
assert_line 'buildpack=pgbouncer at=starting-app'
assert_line 'DATABASE_URL_PGBOUNCER=postgres://user:pass@host:5433/name?query'
assert_line 'DATABASE_URL=postgres://user:pass@host:5433/name?query'
}
@test "does not mutate other config vars not listed in PGBOUNCER_URLS" {
export DATABASE_URL='postgresql://user:pass@host:5432/name?query'
export OTHER_URL='postgresql://user:pass@host2:5432/name?query'
run bin/use-pgbouncer "printenv"
assert_success
assert_line 'buildpack=pgbouncer at=pgbouncer-enabled'
assert_line 'buildpack=pgbouncer at=mutating-DATABASE_URL'
assert_line 'buildpack=pgbouncer at=adding-one-to-5432'
assert_line 'buildpack=pgbouncer at=starting-app'
assert_line 'DATABASE_URL_PGBOUNCER=postgres://user:pass@host:5433/name?query'
assert_line 'DATABASE_URL=postgres://user:pass@host:5433/name?query'
assert_line 'OTHER_URL=postgresql://user:pass@host2:5432/name?query'
}
@test "mutates all config vars listed in PGBOUNCER_URLS" {
export PGBOUNCER_URLS="DATABASE_URL OTHER_URL"
export DATABASE_URL='postgresql://user:pass@host:5432/name?query'
export OTHER_URL='postgresql://user:pass@host2:5432/name?query'
run bin/use-pgbouncer "printenv"
assert_success
assert_line 'buildpack=pgbouncer at=pgbouncer-enabled'
assert_line 'buildpack=pgbouncer at=mutating-DATABASE_URL'
assert_line 'buildpack=pgbouncer at=adding-one-to-5432'
assert_line 'buildpack=pgbouncer at=starting-app'
assert_line 'DATABASE_URL_PGBOUNCER=postgres://user:pass@host:5433/name?query'
assert_line 'DATABASE_URL=postgres://user:pass@host:5433/name?query'
assert_line 'OTHER_URL=postgres://user:pass@host2:5433/name?query'
}

0 comments on commit 1ed90f8

Please sign in to comment.