From 8bcbe41a668733fc13c3b77bbac0854d9052d9fd Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 31 Jul 2020 08:49:56 -0500 Subject: [PATCH] Fix password option This contains a number of fixes for the password option to postgresql_proc: * Use password auth if it's specified, so that the password is actually honored. * Move --pwfile into the options list so that it's passed through to `initdb`; otherwise it causes an error as `pg_ctl` doesn't expect a --pwfile option. * Don't use a shell to run initdb. * Use lists instead of tuples to avoid tuple copying on append. * Flush the password file so that it actually hits disk. * Add unit test to cover the password option. --- src/pytest_postgresql/executor.py | 26 +++++++++++++++----------- tests/test_executor.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/pytest_postgresql/executor.py b/src/pytest_postgresql/executor.py index 389e3df9..e4beec4c 100644 --- a/src/pytest_postgresql/executor.py +++ b/src/pytest_postgresql/executor.py @@ -135,21 +135,25 @@ def init_directory(self): return # remove old one if exists first. self.clean_directory() - init_directory = ( - self.executable, 'initdb', - '-o "--auth=trust --username=%s"' % self.user, - '-D %s' % self.datadir, - ) + init_directory = [self.executable, 'initdb', '--pgdata', self.datadir] + options = ['--username=%s' % self.user] if self.password: with tempfile.NamedTemporaryFile() as password_file: - init_directory += ( - '--pwfile "%s"' % password_file.name, - ) - password_file.write(self.password) - subprocess.check_output(' '.join(init_directory), shell=True) + options += ['--auth=password', + '--pwfile=%s' % password_file.name] + if hasattr(self.password, 'encode'): + password = self.password.encode('utf-8') + else: + password = self.password + password_file.write(password) + password_file.flush() + init_directory += ['-o', ' '.join(options)] + subprocess.check_output(init_directory) else: - subprocess.check_output(' '.join(init_directory), shell=True) + options += ['--auth=trust'] + init_directory += ['-o', ' '.join(options)] + subprocess.check_output(init_directory) self._directory_initialised = True diff --git a/tests/test_executor.py b/tests/test_executor.py index 59461b2d..1459003a 100644 --- a/tests/test_executor.py +++ b/tests/test_executor.py @@ -1,8 +1,10 @@ """Test various executor behaviours.""" +import psycopg2 import pytest from pkg_resources import parse_version from pytest_postgresql.executor import PostgreSQLExecutor, PostgreSQLUnsupported +from pytest_postgresql.factories import postgresql_proc from pytest_postgresql.factories import get_config from pytest_postgresql.port import get_port @@ -32,3 +34,29 @@ def test_unsupported_version(request): with pytest.raises(PostgreSQLUnsupported): executor.start() + + +postgres_with_password = postgresql_proc(password='hunter2') + + +def test_proc_with_password( + postgres_with_password): # pylint: disable=redefined-outer-name + """Check that password option to postgresql_proc factory is honored.""" + assert postgres_with_password.running() is True + + # no assertion necessary here; we just want to make sure it connects with + # the password + psycopg2.connect( + dbname=postgres_with_password.user, + user=postgres_with_password.user, + password=postgres_with_password.password, + host=postgres_with_password.host, + port=postgres_with_password.port) + + with pytest.raises(psycopg2.OperationalError): + psycopg2.connect( + dbname=postgres_with_password.user, + user=postgres_with_password.user, + password='bogus', + host=postgres_with_password.host, + port=postgres_with_password.port)