commit
33cf95ef36
@ -0,0 +1,10 @@ |
||||
<chapter xmlns="http://docbook.org/ns/docbook" |
||||
xmlns:xlink="http://www.w3.org/1999/xlink" |
||||
xmlns:xi="http://www.w3.org/2001/XInclude" |
||||
xml:id="chap-hooks"> |
||||
<title>Hooks reference</title> |
||||
<para> |
||||
Nixpkgs has several hook packages that augment the stdenv phases. |
||||
</para> |
||||
<xi:include href="./postgresql-test-hook.section.xml" /> |
||||
</chapter> |
@ -0,0 +1,59 @@ |
||||
|
||||
# `postgresqlTestHook` {#sec-postgresqlTestHook} |
||||
|
||||
This hook starts a PostgreSQL server during the `checkPhase`. Example: |
||||
|
||||
```nix |
||||
{ stdenv, postgresql, postgresqlTestHook }: |
||||
stdenv.mkDerivation { |
||||
|
||||
# ... |
||||
|
||||
checkInputs = [ |
||||
postgresql |
||||
postgresqlTestHook |
||||
]; |
||||
} |
||||
``` |
||||
|
||||
If you use a custom `checkPhase`, remember to add the `runHook` calls: |
||||
```nix |
||||
checkPhase '' |
||||
runHook preCheck |
||||
|
||||
# ... your tests |
||||
|
||||
runHook postCheck |
||||
'' |
||||
``` |
||||
|
||||
## Variables {#sec-postgresqlTestHook-variables} |
||||
|
||||
The hook logic will read a number of variables and set them to a default value if unset or empty. |
||||
|
||||
Exported variables: |
||||
|
||||
- `PGDATA`: location of server files. |
||||
- `PGHOST`: location of UNIX domain socket directory; the default `host` in a connection string. |
||||
- `PGUSER`: user to create / log in with, default: `test_user`. |
||||
- `PGDATABASE`: database name, default: `test_db`. |
||||
|
||||
Bash-only variables: |
||||
|
||||
- `postgresqlTestUserOptions`: SQL options to use when creating the `$PGUSER` role, default: `LOGIN`. |
||||
- `postgresqlTestSetupSQL`: SQL commands to run as database administrator after startup, default: statements that create `$PGUSER` and `$PGDATABASE`. |
||||
- `postgresqlTestSetupCommands`: bash commands to run after database start, defaults to running `$postgresqlTestSetupSQL` as database administrator. |
||||
- `postgresqlEnableTCP`: set to `1` to enable TCP listening. Flaky; not recommended. |
||||
- `postgresqlStartCommands`: defaults to `pg_ctl start`. |
||||
|
||||
## TCP and the Nix sandbox {#sec-postgresqlTestHook-tcp} |
||||
|
||||
`postgresqlEnableTCP` relies on network sandboxing, which is not available on macOS and some custom Nix installations, resulting in flaky tests. |
||||
For this reason, it is disabled by default. |
||||
|
||||
The preferred solution is to make the test suite use a UNIX domain socket connection. This is the default behavior when no `host` connection parameter is provided. |
||||
Some test suites hardcode a value for `host` though, so a patch may be required. If you can upstream the patch, you can make `host` default to the `PGHOST` environment variable when set. Otherwise, you can patch it locally to omit the `host` connection string parameter altogether. |
||||
|
||||
::: {.note} |
||||
The error `libpq: failed (could not receive data from server: Connection refused` is generally an indication that the test suite is trying to connect through TCP. |
||||
::: |
@ -0,0 +1,9 @@ |
||||
{ callPackage, makeSetupHook }: |
||||
|
||||
(makeSetupHook { |
||||
name = "postgresql-test-hook"; |
||||
} ./postgresql-test-hook.sh).overrideAttrs (o: { |
||||
passthru.tests = { |
||||
simple = callPackage ./test.nix { }; |
||||
}; |
||||
}) |
@ -0,0 +1,79 @@ |
||||
preCheckHooks+=('postgresqlStart') |
||||
postCheckHooks+=('postgresqlStop') |
||||
|
||||
|
||||
postgresqlStart() { |
||||
|
||||
# Add default environment variable values |
||||
# |
||||
# Client variables: |
||||
# - https://www.postgresql.org/docs/current/libpq-envars.html |
||||
# |
||||
# Server variables: |
||||
# - only PGDATA: https://www.postgresql.org/docs/current/creating-cluster.html |
||||
|
||||
if [[ "${PGDATA:-}" == "" ]]; then |
||||
PGDATA="$NIX_BUILD_TOP/postgresql" |
||||
fi |
||||
export PGDATA |
||||
|
||||
if [[ "${PGHOST:-}" == "" ]]; then |
||||
mkdir -p "$NIX_BUILD_TOP/run/postgresql" |
||||
PGHOST="$NIX_BUILD_TOP/run/postgresql" |
||||
fi |
||||
export PGHOST |
||||
|
||||
if [[ "${PGUSER:-}" == "" ]]; then |
||||
PGUSER="test_user" |
||||
fi |
||||
export PGUSER |
||||
|
||||
if [[ "${PGDATABASE:-}" == "" ]]; then |
||||
PGDATABASE="test_db" |
||||
fi |
||||
export PGDATABASE |
||||
|
||||
if [[ "${postgresqlTestUserOptions:-}" == "" ]]; then |
||||
postgresqlTestUserOptions="LOGIN" |
||||
fi |
||||
|
||||
if [[ "${postgresqlTestSetupSQL:-}" == "" ]]; then |
||||
postgresqlTestSetupSQL="$(cat <<EOF |
||||
CREATE ROLE "$PGUSER" $postgresqlTestUserOptions; |
||||
CREATE DATABASE "$PGDATABASE" OWNER '$PGUSER'; |
||||
EOF |
||||
)" |
||||
fi |
||||
|
||||
if [[ "${postgresqlTestSetupCommands:-}" == "" ]]; then |
||||
postgresqlTestSetupCommands='echo "$postgresqlTestSetupSQL" | PGUSER=postgres psql postgres' |
||||
fi |
||||
|
||||
if ! type initdb >/dev/null; then |
||||
echo >&2 'initdb not found. Did you add postgresql to the checkInputs?' |
||||
false |
||||
fi |
||||
header 'initializing postgresql' |
||||
initdb -U postgres |
||||
|
||||
# Move the socket |
||||
echo "unix_socket_directories = '$NIX_BUILD_TOP/run/postgresql'" >>"$PGDATA/postgresql.conf" |
||||
|
||||
# TCP ports can be a problem in some sandboxes, |
||||
# so we disable tcp listening by default |
||||
if ! [[ "${postgresqlEnableTCP:-}" = 1 ]]; then |
||||
echo "listen_addresses = ''" >>"$PGDATA/postgresql.conf" |
||||
fi |
||||
|
||||
header 'starting postgresql' |
||||
eval "${postgresqlStartCommands:-pg_ctl start}" |
||||
|
||||
header 'setting up postgresql' |
||||
eval "$postgresqlTestSetupCommands" |
||||
|
||||
} |
||||
|
||||
postgresqlStop() { |
||||
header 'stopping postgresql' |
||||
pg_ctl stop |
||||
} |
@ -0,0 +1,27 @@ |
||||
{ postgresql, postgresqlTestHook, stdenv }: |
||||
|
||||
stdenv.mkDerivation { |
||||
name = "postgresql-test-hook-test"; |
||||
buildInputs = [ postgresqlTestHook ]; |
||||
checkInputs = [ postgresql ]; |
||||
dontUnpack = true; |
||||
doCheck = true; |
||||
passAsFile = ["sql"]; |
||||
sql = '' |
||||
CREATE TABLE hello ( |
||||
message text |
||||
); |
||||
INSERT INTO hello VALUES ('it '||'worked'); |
||||
SELECT * FROM hello; |
||||
''; |
||||
checkPhase = '' |
||||
runHook preCheck |
||||
psql <$sqlPath | grep 'it worked' |
||||
TEST_RAN=1 |
||||
runHook postCheck |
||||
''; |
||||
installPhase = '' |
||||
[[ $TEST_RAN == 1 ]] |
||||
touch $out |
||||
''; |
||||
} |
Loading…
Reference in new issue