Merge lp:~allenap/storm/oneiric-admin-shutdown-bug-871596 into lp:storm

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: 447
Merged at revision: 421
Proposed branch: lp:~allenap/storm/oneiric-admin-shutdown-bug-871596
Merge into: lp:storm
Prerequisite: lp:~allenap/storm/go-setuptools
Diff against target: 407 lines (+212/-32)
9 files modified
MANIFEST.in (+1/-1)
NEWS (+12/-1)
README (+11/-4)
setup.py (+4/-0)
storm/databases/postgres.py (+46/-15)
test (+2/-3)
tests/__init__.py (+9/-0)
tests/databases/postgres.py (+120/-1)
tests/tracer.py (+7/-7)
To merge this branch: bzr merge lp:~allenap/storm/oneiric-admin-shutdown-bug-871596
Reviewer Review Type Date Requested Status
Gavin Panella Abstain
Raphaël Badin code Approve
Stuart Bishop Pending
Review via email: mp+79889@code.launchpad.net

This proposal supersedes a proposal from 2011-10-17.

Description of the change

This branch adds three tests for disconnection errors:

- When the connection is terminated with pg_terminate_backend.

- When the connection is terminated with pg_terminate_backend and the
  connection goes via pgbouncer.

- When the connection is terminated because pgbouncer is terminated.

It then updates is_disconnection_error to match those situations.

Additionally, under Oneiric, some disconnection tests were failing
anyway, so is_disconnection_error has been updated to catch those too.

This branch adds two optional test dependencies: python-fixtures and
python-pgbouncer. If these are not available the tests will not be
attempted.

To post a comment you must log in.
Revision history for this message
Stuart Bishop (stub) wrote : Posted in a previous version of this proposal

Thanks for working on this!

So the only time you ever saw the 57P01 error was with pgbouncer? That is interesting as in the past we often never saw the error codes at all (hence the string matching).

The code seems good. Just a few suggestions and points for discussion:

- Rather than check just for 57P01, I think we might as well check for the following list:

pg_connection_failure_codes = frozenset([
    '08006', # CONNECTION FAILURE
    '08001', # SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION
    '08004', # SQLSERVER REJECTED ESTABLISHMENT OF SQLCONNECTION
    '53300', # TOO MANY CONNECTIONS
    '57000', # OPERATOR INTERVENTION
    '57014', # QUERY CANCELED
    '57P01', # ADMIN SHUTDOWN
    '57P02', # CRASH SHUTDOWN
    '57P03', # CANNOT CONNECT NOW
    ])

- Should we document installing python-pgbouncer using the Python egg from pypi rather than checking out the Bazaar branch and using a symlink hack?

- Should python-fixtures be an optional dependency? Maybe if it gets used elsewhere.

- Do we want python-pgbouncer and fixtures as optional dependencies for running the PostgreSQL tests? I understand not needing the environment setup for testing every database backend, but there seems little point for allowing people to run a subset of the tests for a particular DB backend.

review: Approve
Revision history for this message
Gavin Panella (allenap) wrote : Posted in a previous version of this proposal

> Thanks for working on this!
>
> So the only time you ever saw the 57P01 error was with pgbouncer? That is
> interesting as in the past we often never saw the error codes at all (hence
> the string matching).

Yeah, I don't fully understand what was happening there.

>
> The code seems good. Just a few suggestions and points for discussion:
>
> - Rather than check just for 57P01, I think we might as well check for the
> following list:
>
> pg_connection_failure_codes = frozenset([
> '08006', # CONNECTION FAILURE
> '08001', # SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION
> '08004', # SQLSERVER REJECTED ESTABLISHMENT OF SQLCONNECTION
> '53300', # TOO MANY CONNECTIONS
> '57000', # OPERATOR INTERVENTION
> '57014', # QUERY CANCELED
> '57P01', # ADMIN SHUTDOWN
> '57P02', # CRASH SHUTDOWN
> '57P03', # CANNOT CONNECT NOW
> ])

Tip top, done.

>
> - Should we document installing python-pgbouncer using the Python egg from
> pypi rather than checking out the Bazaar branch and using a symlink hack?
>
> - Should python-fixtures be an optional dependency? Maybe if it gets used
> elsewhere.
>
> - Do we want python-pgbouncer and fixtures as optional dependencies for
> running the PostgreSQL tests? I understand not needing the environment setup
> for testing every database backend, but there seems little point for allowing
> people to run a subset of the tests for a particular DB backend.

I've switched everything to use setuptools, and have defined all the
test dependencies in setup.py. I've switched make check over to use
setuptools' testing support, and I've also made the ./test script use
the eggs that setuptools downloads. There's also an additional develop
Makefile target that downloads the test dependencies without running
the tests.

This means you can do make check from a fresh branch of Storm and run
*all* the tests without further intervention (other than doing the
one-off package installations and database set-up). This has already
shown me that there's another Django disconnection test failure that I
need to address.

Revision history for this message
Robert Collins (lifeless) wrote : Posted in a previous version of this proposal

van.pg can do postgresql cluster setup as a test fixture, if you want :)

Revision history for this message
Gavin Panella (allenap) wrote : Posted in a previous version of this proposal

> van.pg can do postgresql cluster setup as a test fixture, if you
> want :)

Indeed, I do want! I did some work on van.pg last week or the week
before, but it was a little more complicated than I had imagined... or
I was misunderstanding. I won't attempt it again in this branch, but I
feel like I might have a much better chance of success with the things
I've learnt doing this.

Revision history for this message
Stuart Bishop (stub) wrote : Posted in a previous version of this proposal

On Wed, Oct 19, 2011 at 3:42 PM, Gavin Panella
<email address hidden> wrote:
>> van.pg can do postgresql cluster setup as a test fixture, if you
>> want :)
>
> Indeed, I do want! I did some work on van.pg last week or the week
> before, but it was a little more complicated than I had imagined... or
> I was misunderstanding. I won't attempt it again in this branch, but I
> feel like I might have a much better chance of success with the things
> I've learnt doing this.

Yer, separate branch for that or this will never land :)

--
Stuart Bishop <email address hidden>
http://www.stuartbishop.net/

Revision history for this message
Gavin Panella (allenap) wrote : Posted in a previous version of this proposal

I'm going to split this branch into two, to help review.

443. By Gavin Panella

Include ez_setup.py in tarballs.

444. By Gavin Panella

Rely upon pgbouncer 0.0.6 or later, owing to unreliable shutdown problems in earlier versions.

445. By Gavin Panella

Deal with a weird ProgrammingError when connecting via pgbouncer.

446. By Gavin Panella

QUERY CANCELED is not a disconnection.

447. By Gavin Panella

Merged go-setuptools into oneiric-admin-shutdown-bug-871596, resolving conflicts.

Revision history for this message
Raphaël Badin (rvb) wrote :

I'm getting weird Segmentation fault errors when running the test suite but I know this is not unheard of when dealing with storm :/.

    test_terminated_backend (tests.databases.postgres.PostgresDisconnectionTestWithoutProxyUnixSockets) ... Segmentation fault

I suppose you have all the tests passing so it must be something with my setup.

Apart from that, this looks good. (I confess I'd like to know more about pgbouncer but right now http://pgfoundry.org/projects/pgbouncer says "PgFoundry Could Not Connect to Database:").

[0]

8 -include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test
9 +include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test ez_setup.py

This should probably go in the prereq branch but since you're going to land them together I guess that's ok ;)

[1]

317 +if has_fixtures:
318 + # Upgrade to full test case class with fixtures.
319 + from fixtures import TestWithFixtures
320 + class PostgresDisconnectionTestWithPGBouncer(
321 + PostgresDisconnectionTestWithPGBouncerBase,
322 + TestWithFixtures, TestHelper): pass

I don't think that's very readable but I have no better idea atm…

review: Approve (code)
Revision history for this message
Gavin Panella (allenap) wrote :

Stuart reviewed an earlier version of this branch. I have not made
huge changes since then so I'm going to assume that his +1 still
stands.

review: Abstain
Revision history for this message
Gavin Panella (allenap) wrote :

> I'm getting weird Segmentation fault errors when running the test suite but I
> know this is not unheard of when dealing with storm :/.
>
> test_terminated_backend
> (tests.databases.postgres.PostgresDisconnectionTestWithoutProxyUnixSockets)
> ... Segmentation fault
>
> I suppose you have all the tests passing so it must be something with my
> setup.

Grargh, there are two outstanding tests failing which I ought to
address:

  test_wb_disconnect
    in tests.django.backend.PostgresDjangoBackendDisconnectionTests

  test_configure_stores_configures_store_uris
    in tests.django.stores.DjangoStoreTests

> Apart from that, this looks good. (I confess I'd like to know more about
> pgbouncer but right now http://pgfoundry.org/projects/pgbouncer says
> "PgFoundry Could Not Connect to Database:").

man 1 pgbouncer is where I read about it.

> [0]
>
> 8 -include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test
> 9 +include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test
> ez_setup.py
>
> This should probably go in the prereq branch but since you're going to land
> them together I guess that's ok ;)

Doh, of course. Oops.

>
> [1]
>
> 317 +if has_fixtures:
> 318 + # Upgrade to full test case class with fixtures.
> 319 + from fixtures import TestWithFixtures
> 320 + class PostgresDisconnectionTestWithPGBouncer(
> 321 + PostgresDisconnectionTestWithPGBouncerBase,
> 322 + TestWithFixtures, TestHelper): pass
>
> I don't think that's very readable but I have no better idea atm…

No, me neither :-/

448. By Gavin Panella

Merged go-setuptools into oneiric-admin-shutdown-bug-871596, resolving conflicts.

449. By Gavin Panella

Merged go-setuptools into oneiric-admin-shutdown-bug-871596.

450. By Gavin Panella

Use has_fixtures from tests/__init__.py.

451. By Gavin Panella

Update NEWS.

452. By Gavin Panella

pgbouncer 0.0.7 is needed.

453. By Gavin Panella

Add eggs to path before importing tests.

454. By Gavin Panella

Depend on testtools >= 0.9.8; newer versions of python-fixtures needs it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'MANIFEST.in'
--- MANIFEST.in 2008-01-28 18:17:33 +0000
+++ MANIFEST.in 2011-10-28 14:51:59 +0000
@@ -1,4 +1,4 @@
1recursive-include storm *.py *.c *.zcml1recursive-include storm *.py *.c *.zcml
2recursive-include tests *.py *.txt2recursive-include tests *.py *.txt
33
4include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test4include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test ez_setup.py
55
=== modified file 'NEWS'
--- NEWS 2011-10-27 13:19:00 +0000
+++ NEWS 2011-10-28 14:51:59 +0000
@@ -14,10 +14,21 @@
1414
15 You will need the python-fixtures package in order to use this feature.15 You will need the python-fixtures package in order to use this feature.
1616
17- Setuptools <http://pypi.python.org/pypi/setuptools> is now required
18 to run setup.py. This makes it much easier to install the majority
19 of the dependencies required to run the test suite in its entirety.
20
21- Disconnection errors arising from PostgreSQL are now more reliably
22 detected, especially with regard to recent libpq updates in Ubuntu.
23 There are also disconnection tests that simulate sudden termination
24 of pgbouncer <http://pgfoundry.org/projects/pgbouncer/>.
25
17Bug fixes26Bug fixes
18---------27---------
1928
20- When a SQLObjectResultSet object was sliced with slice.start and slice.end both zero (sqlobject[0:0]), the full, unsliced resultset was returned (bug #872086).29- When a SQLObjectResultSet object was sliced with slice.start and
30 slice.end both zero (sqlobject[0:0]), the full, unsliced resultset
31 was returned (bug #872086).
2132
220.19 (2011-10-03)330.19 (2011-10-03)
23=================34=================
2435
=== modified file 'README'
--- README 2011-10-28 14:51:59 +0000
+++ README 2011-10-28 14:51:59 +0000
@@ -100,7 +100,8 @@
100100
101 $ sudo apt-get install \101 $ sudo apt-get install \
102 python-mysqldb mysql-server \102 python-mysqldb mysql-server \
103 postgresql build-essential103 postgresql pgbouncer \
104 build-essential
104105
105These will take a few minutes to download (its a bit under 200MB all106These will take a few minutes to download (its a bit under 200MB all
106together). Once the download is complete, a screen called107together). Once the download is complete, a screen called
@@ -115,9 +116,15 @@
115apt-get:116apt-get:
116117
117 $ apt-get install \118 $ apt-get install \
118 python-django python-psycopg2 python-testresources \119 python-django python-fixtures python-psycopg2 \
119 python-transaction python-twisted python-zope.component \120 python-testresources python-transaction python-twisted \
120 python-zope.security121 python-zope.component python-zope.security
122
123Two modules - pgbouncer and timeline - are not yet packaged in
124Ubuntu. These can be installed from PyPI:
125
126 http://pypi.python.org/pypi/pgbouncer
127 http://pypi.python.org/pypi/timeline
121128
122Alternatively, dependencies can be downloaded as eggs into the current129Alternatively, dependencies can be downloaded as eggs into the current
123directory with:130directory with:
124131
=== modified file 'setup.py'
--- setup.py 2011-10-28 14:51:59 +0000
+++ setup.py 2011-10-28 14:51:59 +0000
@@ -54,8 +54,12 @@
54 tests_require=[54 tests_require=[
55 # Versions based on Lucid, where packaged.55 # Versions based on Lucid, where packaged.
56 "django >= 1.1.1",56 "django >= 1.1.1",
57 "fixtures >= 0.3.5",
58 # pgbouncer (the Python module) is not yet packaged in Ubuntu.
59 "pgbouncer >= 0.0.7",
57 "psycopg2 >= 2.0.13",60 "psycopg2 >= 2.0.13",
58 "testresources >= 0.2.4",61 "testresources >= 0.2.4",
62 "testtools >= 0.9.8",
59 # timeline is not yet packaged in Ubuntu.63 # timeline is not yet packaged in Ubuntu.
60 "timeline >= 0.0.2",64 "timeline >= 0.0.2",
61 "transaction >= 1.0.0",65 "transaction >= 1.0.0",
6266
=== modified file 'storm/databases/postgres.py'
--- storm/databases/postgres.py 2011-09-22 09:16:49 +0000
+++ storm/databases/postgres.py 2011-10-28 14:51:59 +0000
@@ -47,7 +47,7 @@
47from storm.database import Database, Connection, Result47from storm.database import Database, Connection, Result
48from storm.exceptions import (48from storm.exceptions import (
49 install_exceptions, DatabaseError, DatabaseModuleError, InterfaceError,49 install_exceptions, DatabaseError, DatabaseModuleError, InterfaceError,
50 OperationalError, ProgrammingError, TimeoutError)50 OperationalError, ProgrammingError, TimeoutError, Error)
51from storm.tracer import TimeoutTracer51from storm.tracer import TimeoutTracer
5252
5353
@@ -217,6 +217,18 @@
217 return And(*equals)217 return And(*equals)
218218
219219
220pg_connection_failure_codes = frozenset([
221 '08006', # CONNECTION FAILURE
222 '08001', # SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION
223 '08004', # SQLSERVER REJECTED ESTABLISHMENT OF SQLCONNECTION
224 '53300', # TOO MANY CONNECTIONS
225 '57000', # OPERATOR INTERVENTION
226 '57P01', # ADMIN SHUTDOWN
227 '57P02', # CRASH SHUTDOWN
228 '57P03', # CANNOT CONNECT NOW
229 ])
230
231
220class PostgresConnection(Connection):232class PostgresConnection(Connection):
221233
222 result_factory = PostgresResult234 result_factory = PostgresResult
@@ -277,22 +289,41 @@
277 yield param289 yield param
278290
279 def is_disconnection_error(self, exc, extra_disconnection_errors=()):291 def is_disconnection_error(self, exc, extra_disconnection_errors=()):
280 if not isinstance(exc, (InterfaceError, OperationalError,292 # Attempt to use pgcode to determine the nature of the error. This is
281 ProgrammingError, extra_disconnection_errors)):293 # more reliable than string matching because it is not affected by
282 return False294 # locale settings. Fall through if pgcode is not available.
283295 if isinstance(exc, Error):
284 # XXX: 2007-09-17 jamesh296 pgcode = getattr(exc, "pgcode", None)
285 # The last message is for the benefit of old versions of297 if pgcode in pg_connection_failure_codes:
286 # psycopg2 (prior to 2.0.7) which have a bug related to298 return True
287 # stripping the error severity from the message.299
288 msg = str(exc)300 disconnection_errors = (
289 return ("server closed the connection unexpectedly" in msg or301 InterfaceError, OperationalError, ProgrammingError,
302 extra_disconnection_errors)
303
304 if isinstance(exc, disconnection_errors):
305 # When the connection is closed by a termination of pgbouncer, a
306 # ProgrammingError is raised. If the raw connection is closed we
307 # assume it's actually a disconnection.
308 if isinstance(exc, ProgrammingError):
309 if self._raw_connection.closed:
310 return True
311 msg = str(exc)
312 return (
313 "connection already closed" in msg or
314 "connection not open" in msg or
290 "could not connect to server" in msg or315 "could not connect to server" in msg or
316 "could not receive data from server" in msg or
317 "losed the connection unexpectedly" in msg or
291 "no connection to the server" in msg or318 "no connection to the server" in msg or
292 "connection not open" in msg or319 "terminating connection due to administrator" in msg)
293 "connection already closed" in msg or320 elif isinstance(exc, DatabaseError):
294 "losed the connection unexpectedly" in msg or321 msg = str(exc)
295 "could not receive data from server" in msg)322 return (
323 "EOF detected" in msg or
324 "server closed the connection unexpectedly" in msg)
325 else:
326 return False
296327
297328
298class Postgres(Database):329class Postgres(Database):
299330
=== modified file 'test'
--- test 2011-10-28 14:51:59 +0000
+++ test 2011-10-28 14:51:59 +0000
@@ -26,8 +26,6 @@
26import sys26import sys
27import os27import os
2828
29import tests
30
3129
32def add_eggs_to_path():30def add_eggs_to_path():
33 here = os.path.dirname(__file__)31 here = os.path.dirname(__file__)
@@ -50,7 +48,8 @@
50 # top directory, so we add them to sys.path here for convenience.48 # top directory, so we add them to sys.path here for convenience.
51 add_eggs_to_path()49 add_eggs_to_path()
5250
53 suite = tests.find_tests(args)51 from tests import find_tests
52 suite = find_tests(args)
54 result = runner.run(suite)53 result = runner.run(suite)
55 return not result.wasSuccessful()54 return not result.wasSuccessful()
5655
5756
=== modified file 'tests/__init__.py'
--- tests/__init__.py 2011-10-28 14:51:59 +0000
+++ tests/__init__.py 2011-10-28 14:51:59 +0000
@@ -21,12 +21,21 @@
2121
22__all__ = [22__all__ = [
23 'find_tests',23 'find_tests',
24 'has_fixtures',
24 ]25 ]
2526
26import doctest27import doctest
27import os28import os
28import unittest29import unittest
2930
31try:
32 import fixtures
33 fixtures # Silence lint.
34except ImportError:
35 has_fixtures = False
36else:
37 has_fixtures = True
38
3039
31def find_tests(testpaths=()):40def find_tests(testpaths=()):
32 """Find all test paths, or test paths contained in the provided sequence.41 """Find all test paths, or test paths contained in the provided sequence.
3342
=== modified file 'tests/databases/postgres.py'
--- tests/databases/postgres.py 2011-02-25 10:26:26 +0000
+++ tests/databases/postgres.py 2011-10-28 14:51:59 +0000
@@ -22,26 +22,53 @@
22import os22import os
2323
24from storm.databases.postgres import (24from storm.databases.postgres import (
25 Postgres, compile, currval, Returning, PostgresTimeoutTracer)25 Postgres, compile, currval, Returning, PostgresTimeoutTracer, make_dsn)
26from storm.database import create_database26from storm.database import create_database
27from storm.exceptions import InterfaceError, ProgrammingError27from storm.exceptions import InterfaceError, ProgrammingError
28from storm.variables import DateTimeVariable, RawStrVariable28from storm.variables import DateTimeVariable, RawStrVariable
29from storm.variables import ListVariable, IntVariable, Variable29from storm.variables import ListVariable, IntVariable, Variable
30from storm.properties import Int30from storm.properties import Int
31from storm.exceptions import DisconnectionError
31from storm.expr import (Union, Select, Insert, Alias, SQLRaw, State,32from storm.expr import (Union, Select, Insert, Alias, SQLRaw, State,
32 Sequence, Like, Column, COLUMN)33 Sequence, Like, Column, COLUMN)
33from storm.tracer import install_tracer, TimeoutError34from storm.tracer import install_tracer, TimeoutError
35from storm.uri import URI
3436
35# We need the info to register the 'type' compiler. In normal37# We need the info to register the 'type' compiler. In normal
36# circumstances this is naturally imported.38# circumstances this is naturally imported.
37import storm.info39import storm.info
40storm # Silence lint.
3841
42from tests import has_fixtures
39from tests.databases.base import (43from tests.databases.base import (
40 DatabaseTest, DatabaseDisconnectionTest, UnsupportedDatabaseTest)44 DatabaseTest, DatabaseDisconnectionTest, UnsupportedDatabaseTest)
41from tests.expr import column1, column2, column3, elem1, table1, TrackContext45from tests.expr import column1, column2, column3, elem1, table1, TrackContext
42from tests.tracer import TimeoutTracerTestBase46from tests.tracer import TimeoutTracerTestBase
43from tests.helper import TestHelper47from tests.helper import TestHelper
4448
49try:
50 import pgbouncer
51except ImportError:
52 has_pgbouncer = False
53else:
54 has_pgbouncer = True
55
56
57def terminate_other_backends(connection):
58 """Terminate all connections to the database except the one given."""
59 connection.execute(
60 "SELECT pg_terminate_backend(procpid)"
61 " FROM pg_stat_activity"
62 " WHERE datname = current_database()"
63 " AND procpid != pg_backend_pid()")
64
65
66def terminate_all_backends(database):
67 """Terminate all connections to the given database."""
68 connection = database.connect()
69 terminate_other_backends(connection)
70 connection.close()
71
4572
46class PostgresTest(DatabaseTest, TestHelper):73class PostgresTest(DatabaseTest, TestHelper):
4774
@@ -542,6 +569,98 @@
542 self.fail('Exception should have been swallowed: %s' % repr(exc))569 self.fail('Exception should have been swallowed: %s' % repr(exc))
543570
544571
572class PostgresDisconnectionTestWithoutProxyBase(object):
573 # DatabaseDisconnectionTest uses a socket proxy to simulate broken
574 # connections. This class tests some other causes of disconnection.
575
576 database_uri = None
577
578 def is_supported(self):
579 return bool(self.database_uri)
580
581 def setUp(self):
582 super(PostgresDisconnectionTestWithoutProxyBase, self).setUp()
583 self.database = create_database(self.database_uri)
584
585 def test_terminated_backend(self):
586 # The error raised when trying to use a connection that has been
587 # terminated at the server is considered a disconnection error.
588 connection = self.database.connect()
589 terminate_all_backends(self.database)
590 self.assertRaises(
591 DisconnectionError, connection.execute,
592 "SELECT current_database()")
593
594
595class PostgresDisconnectionTestWithoutProxyUnixSockets(
596 PostgresDisconnectionTestWithoutProxyBase, TestHelper):
597 """Disconnection tests using Unix sockets."""
598
599 database_uri = os.environ.get("STORM_POSTGRES_URI")
600
601
602class PostgresDisconnectionTestWithoutProxyTCPSockets(
603 PostgresDisconnectionTestWithoutProxyBase, TestHelper):
604 """Disconnection tests using TCP sockets."""
605
606 database_uri = os.environ.get("STORM_POSTGRES_HOST_URI")
607
608
609class PostgresDisconnectionTestWithPGBouncerBase(object):
610 # Connecting via pgbouncer <http://pgfoundry.org/projects/pgbouncer>
611 # introduces new possible causes of disconnections.
612
613 def is_supported(self):
614 return (
615 has_fixtures and has_pgbouncer and
616 bool(os.environ.get("STORM_POSTGRES_HOST_URI")))
617
618 def setUp(self):
619 super(PostgresDisconnectionTestWithPGBouncerBase, self).setUp()
620 database_uri = URI(os.environ["STORM_POSTGRES_HOST_URI"])
621 database_user = database_uri.username or os.environ['USER']
622 database_dsn = make_dsn(database_uri)
623 # Create a pgbouncer fixture.
624 self.pgbouncer = pgbouncer.fixture.PGBouncerFixture()
625 self.pgbouncer.databases[database_uri.database] = database_dsn
626 self.pgbouncer.users[database_user] = "trusted"
627 self.pgbouncer.admin_users = [database_user]
628 self.useFixture(self.pgbouncer)
629 # Create a Database that uses pgbouncer.
630 pgbouncer_uri = database_uri.copy()
631 pgbouncer_uri.host = self.pgbouncer.host
632 pgbouncer_uri.port = self.pgbouncer.port
633 self.database = create_database(pgbouncer_uri)
634
635 def test_terminated_backend(self):
636 # The error raised when trying to use a connection through pgbouncer
637 # that has been terminated at the server is considered a disconnection
638 # error.
639 connection = self.database.connect()
640 terminate_all_backends(self.database)
641 self.assertRaises(
642 DisconnectionError, connection.execute,
643 "SELECT current_database()")
644
645 def test_pgbouncer_stopped(self):
646 # The error raised from a connection that is no longer connected
647 # because pgbouncer has been immediately shutdown (via SIGTERM; see
648 # man 1 pgbouncer) is considered a disconnection error.
649 connection = self.database.connect()
650 self.pgbouncer.stop()
651 self.assertRaises(
652 DisconnectionError, connection.execute,
653 "SELECT current_database()")
654
655
656if has_fixtures:
657 # Upgrade to full test case class with fixtures.
658 from fixtures import TestWithFixtures
659 class PostgresDisconnectionTestWithPGBouncer(
660 PostgresDisconnectionTestWithPGBouncerBase,
661 TestWithFixtures, TestHelper): pass
662
663
545class PostgresTimeoutTracerTest(TimeoutTracerTestBase):664class PostgresTimeoutTracerTest(TimeoutTracerTestBase):
546665
547 tracer_class = PostgresTimeoutTracer666 tracer_class = PostgresTimeoutTracer
548667
=== modified file 'tests/tracer.py'
--- tests/tracer.py 2011-10-27 13:22:32 +0000
+++ tests/tracer.py 2011-10-28 14:51:59 +0000
@@ -2,14 +2,14 @@
2import sys2import sys
3from unittest import TestCase3from unittest import TestCase
44
5try:5from tests import has_fixtures
6 # Optional dependency, if missing Fixture tests are skipped.6
7# Optional dependency. If missing, Fixture tests are skipped.
8if has_fixtures:
9 import fixtures.testcase
10 TestWithFixtures = fixtures.testcase.TestWithFixtures
11else:
7 TestWithFixtures = object12 TestWithFixtures = object
8 from fixtures.testcase import TestWithFixtures
9except ImportError:
10 has_fixtures = False
11else:
12 has_fixtures = True
1313
14try:14try:
15 # Optional dependency, if missing TimelineTracer tests are skipped.15 # Optional dependency, if missing TimelineTracer tests are skipped.

Subscribers

People subscribed via source and target branches

to status/vote changes: