10000 CI: Dev/federated by jchampio · Pull Request #19 · jchampio/postgres · GitHub
[go: up one dir, main page]

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .cirrus.tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ env:
MTEST_ARGS: --print-errorlogs --no-rebuild -C build
PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests
TEMP_CONFIG: ${CIRRUS_WORKING_DIR}/src/tools/ci/pg_ci_base.conf
PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth
PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth python


# What files to preserve in case tests fail
Expand Down Expand Up @@ -188,7 +188,7 @@ task:
chown root:postgres /tmp/cores
sysctl kern.corefile='/tmp/cores/%N.%P.core'
setup_additional_packages_script: |
#pkg install -y ...
pkg install -y security/py-cryptography

# NB: Intentionally build without -Dllvm. The freebsd image size is already
# large enough to make VM startup slow, and even without llvm freebsd
Expand Down Expand Up @@ -239,7 +239,6 @@ task:

task:
depends_on: SanityCheck
trigger_type: manual

env:
# Below are experimentally derived to be a decent choice.
Expand Down Expand Up @@ -270,7 +269,7 @@ task:
# -Duuid is not set for the NetBSD, see the comment below, above
# configure_script, for more information.
setup_additional_packages_script: |
#pkgin -y install ...
pkgin -y install py312-cryptography
<<: *netbsd_task_template

- name: OpenBSD - Meson
Expand All @@ -282,7 +281,7 @@ task:
UUID: -Duuid=e2fs
TCL: -Dtcl_version=tcl86
setup_additional_packages_script: |
#pkg_add -I ...
pkg_add -I py3-cryptography
# Always core dump to ${CORE_DUMP_DIR}
set_core_dump_script: sysctl -w kern.nosuidcoredump=2
<<: *openbsd_task_template
Expand Down Expand Up @@ -445,8 +444,9 @@ task:
EOF

setup_additional_packages_script: |
#apt-get update
#DEBIAN_FRONTEND=noninteractive apt-get -y install ...
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get -y install \
python3-venv \

matrix:
# SPECIAL:
Expand Down Expand Up @@ -554,8 +554,11 @@ task:
# can easily provide some here by running one of the sets of tests that
# way. Newer versions of python insist on changing the LC_CTYPE away
# from C, prevent that with PYTHONCOERCECLOCALE.
# XXX 32-bit Python tests are currently disabled, as the system's 64-bit
# Python modules can't link against libpq.
test_world_32_script: |
su postgres <<-EOF
export PG_TEST_EXTRA="${PG_TEST_EXTRA//python}"
ulimit -c unlimited
PYTHONCOERCECLOCALE=0 LANG=C meson test $MTEST_ARGS -C build-32 --num-processes ${TEST_JOBS}
EOF
Expand Down
111 changes: 107 additions & 4 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -943,10 +943,10 @@ if not libcurlopt.disabled()
# libcurl and one of either epoll or kqueue.
oauth_flow_supported = (
libcurl.found()
and (cc.check_header('sys/event.h', required: false,
args: test_c_args, include_directories: postgres_inc)
or cc.check_header('sys/epoll.h', required: false,
args: test_c_args, include_directories: postgres_inc))
and (cc.has_header('sys/event.h', args: test_c_args,
include_directories: postgres_inc)
or cc.has_header('sys/epoll.h', args: test_c_args,
include_directories: postgres_inc))
)

if oauth_flow_supported
Expand Down Expand Up @@ -3615,6 +3615,9 @@ else
endif

testwrap = files('src/tools/testwrap')
make_venv = files('src/tools/make_venv')

checked_working_venv = false

foreach test_dir : tests
testwrap_base = [
Expand Down Expand Up @@ -3783,6 +3786,106 @@ foreach test_dir : tests
)
endforeach
install_suites += test_group
elif kind == 'pytest'
venv_name = test_dir['name'] + '_venv'
venv_path = meson.build_root() / venv_name

# The Python tests require a working venv module. This is part of the
# standard library, but some platforms disable it until a separate package
# is installed. Those same platforms don't provide an easy way to check
# whether the venv command will work until the first time you try it, so
# we decide whether or not to enable these tests on the fly.
if not checked_working_venv
cmd = run_command(python, '-m', 'venv', venv_path, check: false)

have_working_venv = (cmd.returncode() == 0)
if not have_working_venv
warning('A working Python venv module is required to run Python tests.')
endif

checked_working_venv = true
endif

if not have_working_venv
continue
endif

# Make sure the temporary installation is in PATH (necessary both for
# --temp-instance and for any pip modules compiling a C0AE gainst libpq, like
# psycopg2).
env = test_env
env.prepend('PATH', temp_install_bindir, test_dir['bd'])

foreach name, value : t.get('env', {})
env.set(name, value)
endforeach

reqs = files(t['requirements'])
test('install_' + venv_name,
python,
args: [ make_venv, '--requirements', reqs, venv_path ],
env: env,
priority: setup_tests_priority - 1, # must run after tmp_install
is_parallel: false,
suite: ['setup'],
timeout: 60, # 30s is too short for the cryptography package compile
)

test_group = test_dir['name']
test_output = test_result_dir / test_group / kind
test_kwargs = {
#'protocol': 'tap',
'suite': test_group,
'timeout': 1000,
'depends': test_deps,
'env': env,
} + t.get('test_kwargs', {})

if fs.is_dir(venv_path / 'Scripts')
# Windows virtualenv layout
pytest = venv_path / 'Scripts' / 'py.test'
else
pytest = venv_path / 'bin' / 'py.test'
endif

test_command = [
pytest,
# Avoid running these tests against an existing database.
'--temp-instance', test_output / 'data',

# FIXME pytest-tap's stream feature accidentally suppresses errors that
# are critical for debugging:
# https://github.com/python-tap/pytest-tap/issues/30
# Don't use the meson TAP protocol for now...
#'--tap-stream',
]

foreach pyt : t['tests']
# Similarly to TAP, strip ./ and .py to make the names prettier
pyt_p = pyt
if pyt_p.startswith('./')
pyt_p = pyt_p.split('./')[1]
endif
if pyt_p.endswith('.py')
pyt_p = fs.stem(pyt_p)
endif

testwrap_pytest = testwrap_base + [
'--testgroup', test_group,
'--testname', pyt_p,
'--skip-without-extra', 'python',
]

test(test_group / pyt_p,
python,
kwargs: test_kwargs,
args: testwrap_pytest + [
'--', test_command,
test_dir['sd'] / pyt,
],
)
endforeach
install_suites += test_group
else
error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
endif
Expand Down
2 changes: 2 additions & 0 deletions src/backend/libpq/auth-oauth.c
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ generate_error_response(struct oauth_ctx *ctx, char **output, int *outputlen)
initStringInfo(&buf);

/*
* TODO
* Escaping the string here is belt-and-suspenders defensive programming
* since escapable characters aren't valid in either the issuer URI or the
* scope list, but the HBA doesn't enforce that yet.
Expand Down Expand Up @@ -699,6 +700,7 @@ validate(Port *port, const char *auth)
/* Make sure the validator authenticated the user. */
if (ret->authn_id == NULL || ret->authn_id[0] == '\0')
{
/* TODO: test logdetail; reduce message duplication elsewhere */
ereport(LOG,
errmsg("OAuth bearer authentication failed for user \"%s\"",
port->user_name),
Expand Down
1 change: 1 addition & 0 deletions src/test/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ subdir('postmaster')
subdir('recovery')
subdir('subscription')
subdir('modules')
subdir('python')

if ssl.found()
subdir('ssl')
Expand Down
2 changes: 2 additions & 0 deletions src/test/python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
/venv/
38 changes: 38 additions & 0 deletions src/test/python/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# Copyright 2021 VMware, Inc.
# SPDX-License-Identifier: PostgreSQL
#

# Only Python 3 is supported, but if it's named something different on your
# system you can override it with the PYTHON3 variable.
PYTHON3 := python3

# All dependencies are placed into this directory. The default is .gitignored
# for you, but you can override it if you'd like.
VENV := ./venv

override VBIN := $(VENV)/bin
override PIP := $(VBIN)/pip
override PYTEST := $(VBIN)/py.test
override ISORT := $(VBIN)/isort
override BLACK := $(VBIN)/black

.PHONY: installcheck indent

installcheck: $(PYTEST)
$(PYTEST) -v -rs

indent: $(ISORT) $(BLACK)
$(ISORT) --profile black *.py client/*.py server/*.py
$(BLACK) *.py client/*.py server/*.py

$(PYTEST) $(ISORT) $(BLACK) &: requirements.txt | $(PIP)
$(PIP) install --force-reinstall -r $<

$(PIP):
$(PYTHON3) -m venv $(VENV)

# A convenience recipe to rebuild psycopg2 against the local libpq.
.PHONY: rebuild-psycopg2
rebuild-psycopg2: | $(PIP)
$(PIP) install --force-reinstall --no-binary :all: $(shell grep psycopg2 requirements.txt)
66 changes: 66 additions & 0 deletions src/test/python/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
A test suite for exercising both the libpq client and the server backend at the
protocol level, based on pytest and Construct.

WARNING! This suite takes superuser-level control of the cluster under test,
writing to the server config, creating and destroying databases, etc. It also
spins up various ephemeral TCP services. This is not safe for production servers
and therefore must be explicitly opted into by setting PG_TEST_EXTRA=python in
the environment.

The test suite currently assumes that the standard PG* environment variables
point to the database under test and are sufficient to log in a superuser on
that system. In other words, a bare `psql` needs to Just Work before the test
suite can do its thing. For a newly built dev cluster, typically all that I need
to do is a

export PGDATABASE=postgres

but you can adjust as needed for your setup. See also 'Advanced Usage' below.

## Requirements

A supported version (3.6+) of Python.

The first run of

make installcheck PG_TEST_EXTRA=python

will install a local virtual environment and all needed dependencies. During
development, if libpq changes incompatibly, you can issue

$ make rebuild-psycopg2

to force a rebuild of the client library.

## Hacking

The code style is enforced by a _very_ opinionated autoformatter. Running the

make indent

recipe will invoke it for you automatically. Don't fight the tool; part of the
zen is in knowing that if the formatter makes your code ugly, there's probably a
cleaner way to write your code.

## Advanced Usage

The Makefile is there for convenience, but you don't have to use it. Activate
the virtualenv to be able to use pytest directly:

$ export PG_TEST_EXTRA=python
$ source venv/bin/activate
$ py.test -k oauth
...
$ py.test ./server/test_server.py
...
$ deactivate # puts the PATH et al back the way it was before

To make quick smoke tests possible, slow tests have been marked explicitly. You
can skip them by saying e.g.

$ py.test -m 'not slow'

If you'd rather not test against an existing server, you can have the suite spin
up a temporary one using whatever pg_ctl it finds in PATH:

$ py.test --temp-instance=./tmp_check
Empty file.
Loading
0