Merge lp:~salgado/storm/bug-374909 into lp:storm

Proposed by Sidnei da Silva
Status: Merged
Merged at revision: not available
Proposed branch: lp:~salgado/storm/bug-374909
Merge into: lp:storm
Diff against target: 108 lines
To merge this branch: bzr merge lp:~salgado/storm/bug-374909
Reviewer Review Type Date Requested Status
James Henstridge Approve
Jamu Kakar (community) Approve
Review via email: mp+9403@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jamu Kakar (jkakar) wrote :

Looks good to me, +1!

review: Approve
Revision history for this message
James Henstridge (jamesh) wrote :

Looks good.

review: Approve
Revision history for this message
James Henstridge (jamesh) wrote :

Actually, it needs a bit of work. I got a test failure when trying to merge your branch:

======================================================================
FAIL: Test that InterfaceErrors get caught on rollback().
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/james/src/storm/storm.trunk/tests/mocker.py", line 102, in test_method_wrapper
    result = test_method()
  File "/home/james/src/storm/storm.trunk/tests/databases/base.py", line 549, in test_rollback_swallows_InterfaceError
    self.fail('Exception should have been swallowed: %s' % repr(exc))
AssertionError: Exception should have been swallowed: InterfaceError('connection already closed',)

----------------------------------------------------------------------

That test is too specific to the PostgreSQL backend.

I'd suggest modifying the test to be closer to test_wb_catch_already_disconnected(), but replace the final assertRaises() call with the connection.rollback() call from your test.

That will test the behaviour you are after (handling the case of rollback on a connection where we missed the initial disconnection notification) rather than simply testing that this one particular exception is caught.

review: Needs Fixing
Revision history for this message
James Henstridge (jamesh) wrote :

The above failure is for the MySQL backend, btw.

Revision history for this message
Guilherme Salgado (salgado) wrote :

On Wed, 2009-07-29 at 08:57 +0000, James Henstridge wrote:
[...]
> That test is too specific to the PostgreSQL backend.
>
> I'd suggest modifying the test to be closer to test_wb_catch_already_disconnected(), but replace the final assertRaises() call with the connection.rollback() call from your test.

That sounds good, but such test would not fail if I reverted my changes,
so I thought of moving my original test to PostgresDisconnectionTest and
writing a new one as you suggest on DatabaseDisconnectionTest.

I've pushed these changes up. Please let me know what you think

--
Guilherme Salgado <email address hidden>

lp:~salgado/storm/bug-374909 updated
317. By Guilherme Salgado

Move original test to PostgresDisconnectionTest as it is postgres-specific and write a new generic one on DatabaseDisconnectionTest

Revision history for this message
James Henstridge (jamesh) wrote :

> That sounds good, but such test would not fail if I reverted my changes,
> so I thought of moving my original test to PostgresDisconnectionTest and
> writing a new one as you suggest on DatabaseDisconnectionTest.

It seems that that the test doesn't fail on MySQL due to MySQL issuing a DatabaseError subclass in this situation. So that indicates that this particular bug was only affecting the PostgreSQL backend.

That doesn't make the test useless though: it makes sure we don't reintroduce the bug, or have it occur in future backends.

> I've pushed these changes up. Please let me know what you think

They look good. I've merged them as r319.

review: Approve
Revision history for this message
Guilherme Salgado (salgado) wrote :

On Thu, 2009-07-30 at 06:23 +0000, James Henstridge wrote:
> Review: Approve
> > That sounds good, but such test would not fail if I reverted my changes,
> > so I thought of moving my original test to PostgresDisconnectionTest and
> > writing a new one as you suggest on DatabaseDisconnectionTest.
>
> It seems that that the test doesn't fail on MySQL due to MySQL issuing a DatabaseError subclass in this situation. So that indicates that this particular bug was only affecting the PostgreSQL backend.
>
> That doesn't make the test useless though: it makes sure we don't reintroduce the bug, or have it occur in future backends.
>

Absolutely; I was just arguing for a test that was specific for the
InterfaceError exception.

>
> > I've pushed these changes up. Please let me know what you think
>
> They look good. I've merged them as r319.

Thanks!

--
Guilherme Salgado <email address hidden>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storm/database.py'
2--- storm/database.py 2009-07-29 05:21:32 +0000
3+++ storm/database.py 2009-07-29 16:20:10 +0000
4@@ -243,7 +243,7 @@
5 if self._state == STATE_CONNECTED:
6 try:
7 self._raw_connection.rollback()
8- except DatabaseError, exc:
9+ except Error, exc:
10 if self.is_disconnection_error(exc):
11 self._raw_connection = None
12 self._state = STATE_RECONNECT
13
14=== modified file 'tests/databases/base.py'
15--- tests/databases/base.py 2009-07-29 05:21:32 +0000
16+++ tests/databases/base.py 2009-07-29 16:20:10 +0000
17@@ -26,14 +26,15 @@
18 import os
19
20 from storm.uri import URI
21-from storm.expr import Select, Column, Undef, SQLToken, SQLRaw, Count, Alias
22+from storm.expr import Select, Column, SQLToken, SQLRaw, Count, Alias
23 from storm.variables import (Variable, PickleVariable, RawStrVariable,
24 DecimalVariable, DateTimeVariable, DateVariable,
25 TimeVariable, TimeDeltaVariable)
26 from storm.database import *
27 from storm.event import EventSystem
28 from storm.exceptions import (
29- DatabaseError, DatabaseModuleError, DisconnectionError, OperationalError)
30+ DatabaseError, DatabaseModuleError, DisconnectionError, Error,
31+ OperationalError)
32
33 from tests.databases.proxy import ProxyTCPServer
34 from tests.helper import MakePath
35@@ -532,6 +533,39 @@
36 self.proxy.restart()
37 self.assertRaises(DisconnectionError, self.connection.commit)
38
39+ def test_wb_catch_already_disconnected_on_rollback(self):
40+ """Connection.rollback() swallows disconnection errors.
41+
42+ If the connection is being used outside of Storm's control,
43+ then it is possible that Storm won't see the disconnection.
44+ It should be able to recover from this situation though.
45+ """
46+ result = self.connection.execute("SELECT 1")
47+ self.assertTrue(result.get_one())
48+ self.proxy.restart()
49+ # Perform an action that should result in a disconnection.
50+ try:
51+ cursor = self.connection._raw_connection.cursor()
52+ cursor.execute("SELECT 1")
53+ cursor.fetchone()
54+ except Error, exc:
55+ self.assertTrue(self.connection.is_disconnection_error(exc))
56+ else:
57+ self.fail("Disconnection was not caught.")
58+
59+ # Make sure our raw connection's rollback() raises a disconnection
60+ # error when called.
61+ try:
62+ self.connection._raw_connection.rollback()
63+ except Error, exc:
64+ self.assertTrue(self.connection.is_disconnection_error(exc))
65+ else:
66+ self.fail("Disconnection was not raised.")
67+
68+ # Our rollback() will catch and swallow that disconnection error,
69+ # though.
70+ self.connection.rollback()
71+
72 def test_wb_catch_already_disconnected(self):
73 """Storm detects connections that have already been disconnected.
74
75
76=== modified file 'tests/databases/postgres.py'
77--- tests/databases/postgres.py 2008-10-02 15:47:18 +0000
78+++ tests/databases/postgres.py 2009-07-29 16:20:10 +0000
79@@ -24,7 +24,7 @@
80 from storm.databases.postgres import (
81 Postgres, compile, currval, Returning, PostgresTimeoutTracer)
82 from storm.database import create_database
83-from storm.exceptions import ProgrammingError
84+from storm.exceptions import InterfaceError, ProgrammingError
85 from storm.variables import DateTimeVariable, RawStrVariable
86 from storm.variables import ListVariable, IntVariable, Variable
87 from storm.properties import Int
88@@ -526,6 +526,21 @@
89 host_environment_variable = "STORM_POSTGRES_HOST_URI"
90 default_port = 5432
91
92+ def test_rollback_swallows_InterfaceError(self):
93+ """Test that InterfaceErrors get caught on rollback().
94+
95+ InterfaceErrors are a form of a disconnection error, so rollback()
96+ must swallow them and reconnect.
97+ """
98+ class FakeConnection:
99+ def rollback(self):
100+ raise InterfaceError('connection already closed')
101+ self.connection._raw_connection = FakeConnection()
102+ try:
103+ self.connection.rollback()
104+ except Exception, exc:
105+ self.fail('Exception should have been swallowed: %s' % repr(exc))
106+
107
108 class PostgresTimeoutTracerTest(TimeoutTracerTestBase):
109

Subscribers

People subscribed via source and target branches

to status/vote changes: