Merge lp:~cjwatson/storm/postgresfixture into lp:storm
- postgresfixture
- Merge into trunk
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 536 |
Proposed branch: | lp:~cjwatson/storm/postgresfixture |
Merge into: | lp:storm |
Diff against target: |
425 lines (+125/-60) 12 files modified
.bzrignore (+2/-0) MANIFEST.in (+2/-0) NEWS (+6/-0) README (+0/-1) dev/db-setup (+0/-45) setup.py (+1/-0) storm/tests/databases/base.py (+23/-8) storm/tests/databases/postgres.py (+33/-0) storm/tests/databases/proxy.py (+18/-3) storm/tests/mocker.py (+1/-1) test (+39/-0) tox.ini (+0/-2) |
To merge this branch: | bzr merge lp:~cjwatson/storm/postgresfixture |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Simon Poirier (community) | Approve | ||
Review via email: mp+373379@code.launchpad.net |
Commit message
Use postgresfixture to simplify developer setup.
Description of the change
Since postgresfixture provides a cluster listening on a Unix-domain socket, we use a TCP proxy for tests that require a TCP connection string.
This necessitated some minor improvements to test cleanup code to ensure that the temporary database can be dropped cleanly.
To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2019-09-17 09:45:08 +0000 | |||
3 | +++ .bzrignore 2019-09-29 14:08:50 +0000 | |||
4 | @@ -2,6 +2,8 @@ | |||
5 | 2 | build | 2 | build |
6 | 3 | storm.egg-info | 3 | storm.egg-info |
7 | 4 | build-stamp | 4 | build-stamp |
8 | 5 | db | ||
9 | 6 | .db.lock | ||
10 | 5 | dist | 7 | dist |
11 | 6 | debian/files | 8 | debian/files |
12 | 7 | debian/python-storm | 9 | debian/python-storm |
13 | 8 | 10 | ||
14 | === modified file 'MANIFEST.in' | |||
15 | --- MANIFEST.in 2019-08-11 17:51:37 +0000 | |||
16 | +++ MANIFEST.in 2019-09-29 14:08:50 +0000 | |||
17 | @@ -1,3 +1,5 @@ | |||
18 | 1 | recursive-include storm *.py *.c *.zcml *.txt | 1 | recursive-include storm *.py *.c *.zcml *.txt |
19 | 2 | 2 | ||
20 | 3 | include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test tox.ini | 3 | include MANIFEST.in LICENSE README TODO NEWS Makefile setup.cfg test tox.ini |
21 | 4 | |||
22 | 5 | prune db | ||
23 | 4 | 6 | ||
24 | === modified file 'NEWS' | |||
25 | --- NEWS 2019-09-27 19:22:54 +0000 | |||
26 | +++ NEWS 2019-09-29 14:08:50 +0000 | |||
27 | @@ -1,6 +1,12 @@ | |||
28 | 1 | 0.21.1 (XXXX-XX-XX) | 1 | 0.21.1 (XXXX-XX-XX) |
29 | 2 | =================== | 2 | =================== |
30 | 3 | 3 | ||
31 | 4 | Improvements | ||
32 | 5 | ------------ | ||
33 | 6 | |||
34 | 7 | - Use the postgresfixture package to set up a temporary cluster for | ||
35 | 8 | PostgreSQL tests, simplifying developer setup. | ||
36 | 9 | |||
37 | 4 | Bug fixes | 10 | Bug fixes |
38 | 5 | --------- | 11 | --------- |
39 | 6 | 12 | ||
40 | 7 | 13 | ||
41 | === modified file 'README' | |||
42 | --- README 2017-02-08 11:47:02 +0000 | |||
43 | +++ README 2019-09-29 14:08:50 +0000 | |||
44 | @@ -90,7 +90,6 @@ | |||
45 | 90 | 90 | ||
46 | 91 | $ dev/ubuntu-deps | 91 | $ dev/ubuntu-deps |
47 | 92 | $ make develop | 92 | $ make develop |
48 | 93 | $ dev/db-setup | ||
49 | 94 | $ make check | 93 | $ make check |
50 | 95 | 94 | ||
51 | 96 | LONG VERSION: | 95 | LONG VERSION: |
52 | 97 | 96 | ||
53 | === removed file 'dev/db-setup' | |||
54 | --- dev/db-setup 2016-03-10 12:04:01 +0000 | |||
55 | +++ dev/db-setup 1970-01-01 00:00:00 +0000 | |||
56 | @@ -1,45 +0,0 @@ | |||
57 | 1 | #!/bin/bash -eu | ||
58 | 2 | |||
59 | 3 | PGHBA=/etc/postgresql/*/main/pg_hba.conf | ||
60 | 4 | PGCONF=/etc/postgresql/*/main/postgresql.conf | ||
61 | 5 | PGINIT=/etc/init.d/postgresql* | ||
62 | 6 | |||
63 | 7 | is_number() { | ||
64 | 8 | test "$1" && printf '%f' "$1" >/dev/null; | ||
65 | 9 | } | ||
66 | 10 | |||
67 | 11 | # Restart service and examine output to attempt to adjust kernel tunables | ||
68 | 12 | restart_service() { | ||
69 | 13 | sudo $PGINIT stop | ||
70 | 14 | set +e | ||
71 | 15 | output=$(sudo $PGINIT start 2>&1) | ||
72 | 16 | rc=$? | ||
73 | 17 | set -e | ||
74 | 18 | if [ $rc -ne 0 ]; then | ||
75 | 19 | size=$(echo $output | grep -E 'size=[0-9]+' | sed -r 's/.*size=([0-9]+).*/\1/') | ||
76 | 20 | is_number $size | ||
77 | 21 | SYSCTLCONF=/etc/sysctl.d/90-storm.conf | ||
78 | 22 | sudo sh -c "echo kernel.shmmax = $size > $SYSCTLCONF" | ||
79 | 23 | sudo sysctl -p $SYSCTLCONF | ||
80 | 24 | sudo $PGINIT start | ||
81 | 25 | fi | ||
82 | 26 | } | ||
83 | 27 | |||
84 | 28 | echo " * Fixing localhost access to postgres, restarting service" | ||
85 | 29 | sudo sed -i.bak -r 's/(host.*127\.0\.0\.1.*)\s+\w+$/\1 trust/' $PGHBA | ||
86 | 30 | sudo sed -i.bak -r 's/(host.*::1\/128.*)\s+\w+$/\1 trust/' $PGHBA | ||
87 | 31 | sudo sed -i.bak -r 's/(host.*::1\/128.*)\s+\w+$/\1 trust/' $PGHBA | ||
88 | 32 | sudo sed -i.bak -r 's/#(max_prepared_transactions.*)= 0/\1 = 200/' $PGCONF | ||
89 | 33 | restart_service | ||
90 | 34 | |||
91 | 35 | echo " * Create postgres superuser ($USER - will fail if existing)" | ||
92 | 36 | # If this fails, we will get errors later, so don't fail. | ||
93 | 37 | sudo -u postgres createuser --superuser $USER || /bin/true | ||
94 | 38 | |||
95 | 39 | echo " * Create DB Test Fixtures (will fail if existing)" | ||
96 | 40 | createdb storm_test || /bin/true | ||
97 | 41 | |||
98 | 42 | echo " * Testing DB Access for user:$USER" | ||
99 | 43 | pg_dump storm_test > /dev/null | ||
100 | 44 | |||
101 | 45 | echo " * All Done." | ||
102 | 46 | 0 | ||
103 | === modified file 'setup.py' | |||
104 | --- setup.py 2019-09-28 13:03:31 +0000 | |||
105 | +++ setup.py 2019-09-29 14:08:50 +0000 | |||
106 | @@ -24,6 +24,7 @@ | |||
107 | 24 | "fixtures >= 0.3.5", | 24 | "fixtures >= 0.3.5", |
108 | 25 | # pgbouncer (the Python module) is not yet packaged in Ubuntu. | 25 | # pgbouncer (the Python module) is not yet packaged in Ubuntu. |
109 | 26 | "pgbouncer >= 0.0.7", | 26 | "pgbouncer >= 0.0.7", |
110 | 27 | "postgresfixture", | ||
111 | 27 | "psycopg2 >= 2.3.0", | 28 | "psycopg2 >= 2.3.0", |
112 | 28 | "testresources >= 0.2.4", | 29 | "testresources >= 0.2.4", |
113 | 29 | "testtools >= 0.9.8", | 30 | "testtools >= 0.9.8", |
114 | 30 | 31 | ||
115 | === modified file 'storm/tests/databases/base.py' | |||
116 | --- storm/tests/databases/base.py 2019-09-27 19:22:54 +0000 | |||
117 | +++ storm/tests/databases/base.py 2019-09-29 14:08:50 +0000 | |||
118 | @@ -700,6 +700,7 @@ | |||
119 | 700 | self.create_connection() | 700 | self.create_connection() |
120 | 701 | 701 | ||
121 | 702 | def tearDown(self): | 702 | def tearDown(self): |
122 | 703 | self.drop_connection() | ||
123 | 703 | self.drop_database() | 704 | self.drop_database() |
124 | 704 | self.proxy.close() | 705 | self.proxy.close() |
125 | 705 | super(DatabaseDisconnectionMixin, self).tearDown() | 706 | super(DatabaseDisconnectionMixin, self).tearDown() |
126 | @@ -708,18 +709,21 @@ | |||
127 | 708 | return bool(self.get_uri()) | 709 | return bool(self.get_uri()) |
128 | 709 | 710 | ||
129 | 710 | def get_uri(self): | 711 | def get_uri(self): |
135 | 711 | """Return URI instance with a defined host and port.""" | 712 | """Return URI instance with a defined host (and port, for TCP).""" |
136 | 712 | if not self.environment_variable or not self.default_port: | 713 | if not self.environment_variable: |
137 | 713 | raise RuntimeError("Define at least %s.environment_variable and " | 714 | raise RuntimeError( |
138 | 714 | "%s.default_port" % (type(self).__name__, | 715 | "Define at least %s.environment_variable" % |
139 | 715 | type(self).__name__)) | 716 | type(self).__name__) |
140 | 716 | uri_str = os.environ.get(self.host_environment_variable) | 717 | uri_str = os.environ.get(self.host_environment_variable) |
141 | 717 | if uri_str: | 718 | if uri_str: |
142 | 718 | uri = URI(uri_str) | 719 | uri = URI(uri_str) |
143 | 719 | if not uri.host: | 720 | if not uri.host: |
144 | 720 | raise RuntimeError("The URI in %s must include a host." % | 721 | raise RuntimeError("The URI in %s must include a host." % |
145 | 721 | self.host_environment_variable) | 722 | self.host_environment_variable) |
147 | 722 | if not uri.port: | 723 | if not uri.host.startswith("/") and not uri.port: |
148 | 724 | if not self.default_port: | ||
149 | 725 | raise RuntimeError( | ||
150 | 726 | "Define at least %s.default_port" % type(self).__name) | ||
151 | 723 | uri.port = self.default_port | 727 | uri.port = self.default_port |
152 | 724 | return uri | 728 | return uri |
153 | 725 | else: | 729 | else: |
154 | @@ -727,11 +731,19 @@ | |||
155 | 727 | if uri_str: | 731 | if uri_str: |
156 | 728 | uri = URI(uri_str) | 732 | uri = URI(uri_str) |
157 | 729 | if uri.host: | 733 | if uri.host: |
159 | 730 | if not uri.port: | 734 | if not uri.host.startswith("/") and not uri.port: |
160 | 735 | if not self.default_port: | ||
161 | 736 | raise RuntimeError( | ||
162 | 737 | "Define at least %s.default_port" % | ||
163 | 738 | type(self).__name) | ||
164 | 731 | uri.port = self.default_port | 739 | uri.port = self.default_port |
165 | 732 | return uri | 740 | return uri |
166 | 733 | return None | 741 | return None |
167 | 734 | 742 | ||
168 | 743 | def create_proxy(self, uri): | ||
169 | 744 | """Create a TCP proxy forwarding requests to `uri`.""" | ||
170 | 745 | return ProxyTCPServer((uri.host, uri.port)) | ||
171 | 746 | |||
172 | 735 | def create_database_and_proxy(self): | 747 | def create_database_and_proxy(self): |
173 | 736 | """Set up the TCP proxy and database object. | 748 | """Set up the TCP proxy and database object. |
174 | 737 | 749 | ||
175 | @@ -739,7 +751,7 @@ | |||
176 | 739 | database object should point at the TCP proxy. | 751 | database object should point at the TCP proxy. |
177 | 740 | """ | 752 | """ |
178 | 741 | uri = self.get_uri() | 753 | uri = self.get_uri() |
180 | 742 | self.proxy = ProxyTCPServer((uri.host, uri.port)) | 754 | self.proxy = self.create_proxy(uri) |
181 | 743 | uri.host, uri.port = self.proxy.server_address | 755 | uri.host, uri.port = self.proxy.server_address |
182 | 744 | self.proxy_uri = uri | 756 | self.proxy_uri = uri |
183 | 745 | self.database = create_database(uri) | 757 | self.database = create_database(uri) |
184 | @@ -747,6 +759,9 @@ | |||
185 | 747 | def create_connection(self): | 759 | def create_connection(self): |
186 | 748 | self.connection = self.database.connect() | 760 | self.connection = self.database.connect() |
187 | 749 | 761 | ||
188 | 762 | def drop_connection(self): | ||
189 | 763 | self.connection.close() | ||
190 | 764 | |||
191 | 750 | def drop_database(self): | 765 | def drop_database(self): |
192 | 751 | pass | 766 | pass |
193 | 752 | 767 | ||
194 | 753 | 768 | ||
195 | === modified file 'storm/tests/databases/postgres.py' | |||
196 | --- storm/tests/databases/postgres.py 2019-09-17 09:35:10 +0000 | |||
197 | +++ storm/tests/databases/postgres.py 2019-09-29 14:08:50 +0000 | |||
198 | @@ -25,6 +25,7 @@ | |||
199 | 25 | import json | 25 | import json |
200 | 26 | 26 | ||
201 | 27 | import six | 27 | import six |
202 | 28 | from six.moves.urllib.parse import urlunsplit | ||
203 | 28 | 29 | ||
204 | 29 | from storm.databases.postgres import ( | 30 | from storm.databases.postgres import ( |
205 | 30 | Postgres, compile, currval, Returning, Case, PostgresTimeoutTracer, | 31 | Postgres, compile, currval, Returning, Case, PostgresTimeoutTracer, |
206 | @@ -50,6 +51,7 @@ | |||
207 | 50 | from storm.tests.databases.base import ( | 51 | from storm.tests.databases.base import ( |
208 | 51 | DatabaseTest, DatabaseDisconnectionTest, UnsupportedDatabaseTest, | 52 | DatabaseTest, DatabaseDisconnectionTest, UnsupportedDatabaseTest, |
209 | 52 | TwoPhaseCommitTest, TwoPhaseCommitDisconnectionTest) | 53 | TwoPhaseCommitTest, TwoPhaseCommitDisconnectionTest) |
210 | 54 | from storm.tests.databases.proxy import ProxyTCPServer | ||
211 | 53 | from storm.tests.expr import column1, column2, column3, elem1, table1, TrackContext | 55 | from storm.tests.expr import column1, column2, column3, elem1, table1, TrackContext |
212 | 54 | from storm.tests.tracer import TimeoutTracerTestBase | 56 | from storm.tests.tracer import TimeoutTracerTestBase |
213 | 55 | from storm.tests.helper import TestHelper | 57 | from storm.tests.helper import TestHelper |
214 | @@ -62,6 +64,16 @@ | |||
215 | 62 | has_pgbouncer = True | 64 | has_pgbouncer = True |
216 | 63 | 65 | ||
217 | 64 | 66 | ||
218 | 67 | def create_proxy_and_uri(uri): | ||
219 | 68 | """Create a TCP proxy to a Unix-domain database identified by `uri`.""" | ||
220 | 69 | proxy = ProxyTCPServer(os.path.join(uri.host, ".s.PGSQL.5432")) | ||
221 | 70 | proxy_host, proxy_port = proxy.server_address | ||
222 | 71 | proxy_uri = URI(urlunsplit( | ||
223 | 72 | ("postgres", "%s:%s" % (proxy_host, proxy_port), "/storm_test", | ||
224 | 73 | "", ""))) | ||
225 | 74 | return proxy, proxy_uri | ||
226 | 75 | |||
227 | 76 | |||
228 | 65 | def terminate_other_backends(connection): | 77 | def terminate_other_backends(connection): |
229 | 66 | """Terminate all connections to the database except the one given.""" | 78 | """Terminate all connections to the database except the one given.""" |
230 | 67 | pid_column = "procpid" if connection._database._version < 90200 else "pid" | 79 | pid_column = "procpid" if connection._database._version < 90200 else "pid" |
231 | @@ -737,6 +749,13 @@ | |||
232 | 737 | host_environment_variable = "STORM_POSTGRES_HOST_URI" | 749 | host_environment_variable = "STORM_POSTGRES_HOST_URI" |
233 | 738 | default_port = 5432 | 750 | default_port = 5432 |
234 | 739 | 751 | ||
235 | 752 | def create_proxy(self, uri): | ||
236 | 753 | """See `DatabaseDisconnectionMixin.create_proxy`.""" | ||
237 | 754 | if uri.host.startswith("/"): | ||
238 | 755 | return create_proxy_and_uri(uri)[0] | ||
239 | 756 | else: | ||
240 | 757 | return super(PostgresDisconnectionTest, self).create_proxy(uri) | ||
241 | 758 | |||
242 | 740 | def test_rollback_swallows_InterfaceError(self): | 759 | def test_rollback_swallows_InterfaceError(self): |
243 | 741 | """Test that InterfaceErrors get caught on rollback(). | 760 | """Test that InterfaceErrors get caught on rollback(). |
244 | 742 | 761 | ||
245 | @@ -803,6 +822,13 @@ | |||
246 | 803 | 822 | ||
247 | 804 | database_uri = os.environ.get("STORM_POSTGRES_HOST_URI") | 823 | database_uri = os.environ.get("STORM_POSTGRES_HOST_URI") |
248 | 805 | 824 | ||
249 | 825 | def setUp(self): | ||
250 | 826 | super(PostgresDisconnectionTestWithoutProxyTCPSockets, self).setUp() | ||
251 | 827 | if self.database.get_uri().host.startswith("/"): | ||
252 | 828 | proxy, proxy_uri = create_proxy_and_uri(self.database.get_uri()) | ||
253 | 829 | self.addCleanup(proxy.close) | ||
254 | 830 | self.database = create_database(proxy_uri) | ||
255 | 831 | |||
256 | 806 | 832 | ||
257 | 807 | class PostgresDisconnectionTestWithPGBouncerBase(object): | 833 | class PostgresDisconnectionTestWithPGBouncerBase(object): |
258 | 808 | # Connecting via pgbouncer <http://pgfoundry.org/projects/pgbouncer> | 834 | # Connecting via pgbouncer <http://pgfoundry.org/projects/pgbouncer> |
259 | @@ -816,6 +842,9 @@ | |||
260 | 816 | def setUp(self): | 842 | def setUp(self): |
261 | 817 | super(PostgresDisconnectionTestWithPGBouncerBase, self).setUp() | 843 | super(PostgresDisconnectionTestWithPGBouncerBase, self).setUp() |
262 | 818 | database_uri = URI(os.environ["STORM_POSTGRES_HOST_URI"]) | 844 | database_uri = URI(os.environ["STORM_POSTGRES_HOST_URI"]) |
263 | 845 | if database_uri.host.startswith("/"): | ||
264 | 846 | proxy, database_uri = create_proxy_and_uri(database_uri) | ||
265 | 847 | self.addCleanup(proxy.close) | ||
266 | 819 | database_user = database_uri.username or os.environ['USER'] | 848 | database_user = database_uri.username or os.environ['USER'] |
267 | 820 | database_dsn = make_dsn(database_uri) | 849 | database_dsn = make_dsn(database_uri) |
268 | 821 | # Create a pgbouncer fixture. | 850 | # Create a pgbouncer fixture. |
269 | @@ -874,6 +903,10 @@ | |||
270 | 874 | self.tracer.get_remaining_time = lambda: self.remaining_time | 903 | self.tracer.get_remaining_time = lambda: self.remaining_time |
271 | 875 | self.remaining_time = 10.5 | 904 | self.remaining_time = 10.5 |
272 | 876 | 905 | ||
273 | 906 | def tearDown(self): | ||
274 | 907 | self.connection.close() | ||
275 | 908 | super(PostgresTimeoutTracerTest, self).tearDown() | ||
276 | 909 | |||
277 | 877 | def test_set_statement_timeout(self): | 910 | def test_set_statement_timeout(self): |
278 | 878 | result = self.connection.execute("SHOW statement_timeout") | 911 | result = self.connection.execute("SHOW statement_timeout") |
279 | 879 | self.assertEquals(result.get_one(), ("10500ms",)) | 912 | self.assertEquals(result.get_one(), ("10500ms",)) |
280 | 880 | 913 | ||
281 | === modified file 'storm/tests/databases/proxy.py' | |||
282 | --- storm/tests/databases/proxy.py 2019-06-07 17:14:33 +0000 | |||
283 | +++ storm/tests/databases/proxy.py 2019-09-29 14:08:50 +0000 | |||
284 | @@ -22,11 +22,13 @@ | |||
285 | 22 | 22 | ||
286 | 23 | from __future__ import print_function | 23 | from __future__ import print_function |
287 | 24 | 24 | ||
288 | 25 | import errno | ||
289 | 25 | import os | 26 | import os |
290 | 26 | import select | 27 | import select |
291 | 27 | import socket | 28 | import socket |
292 | 28 | import threading | 29 | import threading |
293 | 29 | 30 | ||
294 | 31 | import six | ||
295 | 30 | from six.moves import socketserver | 32 | from six.moves import socketserver |
296 | 31 | 33 | ||
297 | 32 | 34 | ||
298 | @@ -42,7 +44,10 @@ | |||
299 | 42 | self, request, client_address, server) | 44 | self, request, client_address, server) |
300 | 43 | 45 | ||
301 | 44 | def handle(self): | 46 | def handle(self): |
303 | 45 | dst = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 47 | if isinstance(self.server.proxy_dest, (bytes, six.text_type)): |
304 | 48 | dst = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||
305 | 49 | else: | ||
306 | 50 | dst = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
307 | 46 | dst.connect(self.server.proxy_dest) | 51 | dst.connect(self.server.proxy_dest) |
308 | 47 | 52 | ||
309 | 48 | readers = [self.request, dst] | 53 | readers = [self.request, dst] |
310 | @@ -56,13 +61,23 @@ | |||
311 | 56 | 61 | ||
312 | 57 | if self.request in rlist: | 62 | if self.request in rlist: |
313 | 58 | chunk = os.read(self.request.fileno(), 1024) | 63 | chunk = os.read(self.request.fileno(), 1024) |
315 | 59 | dst.send(chunk) | 64 | try: |
316 | 65 | dst.send(chunk) | ||
317 | 66 | except socket.error as e: | ||
318 | 67 | if e.errno == errno.EPIPE: | ||
319 | 68 | return | ||
320 | 69 | raise | ||
321 | 60 | if chunk == "": | 70 | if chunk == "": |
322 | 61 | readers.remove(self.request) | 71 | readers.remove(self.request) |
323 | 62 | dst.shutdown(socket.SHUT_WR) | 72 | dst.shutdown(socket.SHUT_WR) |
324 | 63 | 73 | ||
325 | 64 | if dst in rlist: | 74 | if dst in rlist: |
327 | 65 | chunk = os.read(dst.fileno(), 1024) | 75 | try: |
328 | 76 | chunk = os.read(dst.fileno(), 1024) | ||
329 | 77 | except OSError as e: | ||
330 | 78 | if e.errno == errno.ECONNRESET: | ||
331 | 79 | return | ||
332 | 80 | raise | ||
333 | 66 | self.request.send(chunk) | 81 | self.request.send(chunk) |
334 | 67 | if chunk == "": | 82 | if chunk == "": |
335 | 68 | readers.remove(dst) | 83 | readers.remove(dst) |
336 | 69 | 84 | ||
337 | === modified file 'storm/tests/mocker.py' | |||
338 | --- storm/tests/mocker.py 2019-09-17 09:35:10 +0000 | |||
339 | +++ storm/tests/mocker.py 2019-09-29 14:08:50 +0000 | |||
340 | @@ -149,7 +149,7 @@ | |||
341 | 149 | elif os.path.isdir(path): | 149 | elif os.path.isdir(path): |
342 | 150 | shutil.rmtree(path) | 150 | shutil.rmtree(path) |
343 | 151 | self.mocker.restore() | 151 | self.mocker.restore() |
345 | 152 | for func, args, kwargs in self.__cleanup_funcs: | 152 | for func, args, kwargs in reversed(self.__cleanup_funcs): |
346 | 153 | func(*args, **kwargs) | 153 | func(*args, **kwargs) |
347 | 154 | 154 | ||
348 | 155 | def addCleanup(self, func, *args, **kwargs): | 155 | def addCleanup(self, func, *args, **kwargs): |
349 | 156 | 156 | ||
350 | === modified file 'test' | |||
351 | --- test 2019-08-11 17:51:37 +0000 | |||
352 | +++ test 2019-09-29 14:08:50 +0000 | |||
353 | @@ -21,6 +21,7 @@ | |||
354 | 21 | # | 21 | # |
355 | 22 | import glob | 22 | import glob |
356 | 23 | import optparse | 23 | import optparse |
357 | 24 | import re | ||
358 | 24 | import unittest | 25 | import unittest |
359 | 25 | import sys | 26 | import sys |
360 | 26 | import os | 27 | import os |
361 | @@ -73,6 +74,43 @@ | |||
362 | 73 | return test_with_runner(runner) | 74 | return test_with_runner(runner) |
363 | 74 | 75 | ||
364 | 75 | 76 | ||
365 | 77 | def with_postgresfixture(runner_func): | ||
366 | 78 | """If possible, wrap a test runner with code to set up PostgreSQL.""" | ||
367 | 79 | try: | ||
368 | 80 | from postgresfixture import ClusterFixture | ||
369 | 81 | except ImportError: | ||
370 | 82 | return runner_func | ||
371 | 83 | |||
372 | 84 | from six.moves.urllib.parse import urlunsplit | ||
373 | 85 | from storm.uri import escape | ||
374 | 86 | |||
375 | 87 | def wrapper(): | ||
376 | 88 | cluster = ClusterFixture("db") | ||
377 | 89 | cluster.create() | ||
378 | 90 | # Allow use of prepared transactions, which some tests need. | ||
379 | 91 | pg_conf_path = os.path.join(cluster.datadir, "postgresql.conf") | ||
380 | 92 | with open(pg_conf_path) as pg_conf_old: | ||
381 | 93 | with open(pg_conf_path + ".new", "w") as pg_conf_new: | ||
382 | 94 | for line in pg_conf_old: | ||
383 | 95 | pg_conf_new.write(re.sub( | ||
384 | 96 | r"^#(max_prepared_transactions.*)= 0", r"\1= 200", | ||
385 | 97 | line)) | ||
386 | 98 | os.fchmod( | ||
387 | 99 | pg_conf_new.fileno(), | ||
388 | 100 | os.fstat(pg_conf_old.fileno()).st_mode) | ||
389 | 101 | os.rename(pg_conf_path + ".new", pg_conf_path) | ||
390 | 102 | |||
391 | 103 | with cluster: | ||
392 | 104 | cluster.createdb("storm_test") | ||
393 | 105 | uri = urlunsplit( | ||
394 | 106 | ("postgres", escape(cluster.datadir), "/storm_test", "", "")) | ||
395 | 107 | os.environ["STORM_POSTGRES_URI"] = uri | ||
396 | 108 | os.environ["STORM_POSTGRES_HOST_URI"] = uri | ||
397 | 109 | return runner_func() | ||
398 | 110 | |||
399 | 111 | return wrapper | ||
400 | 112 | |||
401 | 113 | |||
402 | 76 | if __name__ == "__main__": | 114 | if __name__ == "__main__": |
403 | 77 | runner = os.environ.get("STORM_TEST_RUNNER") | 115 | runner = os.environ.get("STORM_TEST_RUNNER") |
404 | 78 | if not runner: | 116 | if not runner: |
405 | @@ -80,6 +118,7 @@ | |||
406 | 80 | runner_func = globals().get("test_with_%s" % runner.replace(".", "_")) | 118 | runner_func = globals().get("test_with_%s" % runner.replace(".", "_")) |
407 | 81 | if not runner_func: | 119 | if not runner_func: |
408 | 82 | sys.exit("Test runner not found: %s" % runner) | 120 | sys.exit("Test runner not found: %s" % runner) |
409 | 121 | runner_func = with_postgresfixture(runner_func) | ||
410 | 83 | sys.exit(runner_func()) | 122 | sys.exit(runner_func()) |
411 | 84 | 123 | ||
412 | 85 | # vim:ts=4:sw=4:et | 124 | # vim:ts=4:sw=4:et |
413 | 86 | 125 | ||
414 | === modified file 'tox.ini' | |||
415 | --- tox.ini 2019-09-17 09:45:08 +0000 | |||
416 | +++ tox.ini 2019-09-29 14:08:50 +0000 | |||
417 | @@ -8,8 +8,6 @@ | |||
418 | 8 | .[test] | 8 | .[test] |
419 | 9 | passenv = STORM_TEST_RUNNER USER | 9 | passenv = STORM_TEST_RUNNER USER |
420 | 10 | setenv = | 10 | setenv = |
421 | 11 | STORM_POSTGRES_URI = postgres:storm_test | ||
422 | 12 | STORM_POSTGRES_HOST_URI = postgres://localhost:5432/storm_test | ||
423 | 13 | cextensions: STORM_CEXTENSIONS = 1 | 11 | cextensions: STORM_CEXTENSIONS = 1 |
424 | 14 | nocextensions: STORM_CEXTENSIONS = 0 | 12 | nocextensions: STORM_CEXTENSIONS = 0 |
425 | 15 | commands = | 13 | commands = |
+1 LGTM