Skip to content

Commit 19d8b84

Browse files
committed
more isolation tests
1 parent 7d54219 commit 19d8b84

File tree

1 file changed

+166
-6
lines changed

1 file changed

+166
-6
lines changed

contrib/pg_tsdtm/t/001_distributed_transactions.pl

Lines changed: 166 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
###############################################################################
22
# Test of proper transaction isolation.
3-
# Based on Martin Kleppmann tests, https://github.com/ept/hermitage
3+
# Based on Martin Kleppmann's tests set, https://github.com/ept/hermitage
44
###############################################################################
55

66
use strict;
77
use warnings;
88
use PostgresNode;
99
use TestLib;
10-
use Test::More tests => 2;
10+
use Test::More tests => 7;
1111
use DBI;
1212
use DBD::Pg ':async';
1313

@@ -16,7 +16,7 @@ sub query_row
1616
my ($dbi, $sql, @keys) = @_;
1717
my $sth = $dbi->prepare($sql) || die;
1818
$sth->execute(@keys) || die;
19-
my $ret = $sth->fetchrow_array;
19+
my $ret = $sth->fetchrow_array || undef;
2020
print "query_row('$sql') -> $ret \n";
2121
return $ret;
2222
}
@@ -81,11 +81,13 @@ sub PostgresNode::psql_fails {
8181
$node2->psql('postgres', "create table t(id int primary key, v int)");
8282
$node2->psql('postgres', "insert into t values(2, 20)");
8383

84-
# we need two connections to each node (run two simultameous global tx)
84+
# we will run up to three simultaneous tx, so six connections
8585
my $conn1a = DBI->connect('DBI:Pg:' . $node1->connstr('postgres'));
8686
my $conn2a = DBI->connect('DBI:Pg:' . $node2->connstr('postgres'));
8787
my $conn1b = DBI->connect('DBI:Pg:' . $node1->connstr('postgres'));
8888
my $conn2b = DBI->connect('DBI:Pg:' . $node2->connstr('postgres'));
89+
my $conn1c = DBI->connect('DBI:Pg:' . $node1->connstr('postgres'));
90+
my $conn2c = DBI->connect('DBI:Pg:' . $node2->connstr('postgres'));
8991

9092
sub count_total
9193
{
@@ -135,6 +137,12 @@ sub commit_global
135137
query_exec($c2, "commit prepared '$gtid'");
136138
}
137139

140+
# deadlock check!
141+
142+
# simple for share/update (examples in pg isolation tests)
143+
144+
145+
138146
###############################################################################
139147
# Sanity check for dirty reads
140148
###############################################################################
@@ -152,7 +160,7 @@ sub commit_global
152160
is($intermediate_total, 30, "Check for absence of dirty reads");
153161

154162
###############################################################################
155-
# G0
163+
# G0: Write Cycles
156164
###############################################################################
157165

158166
my $fail = 0;
@@ -188,7 +196,159 @@ sub commit_global
188196

189197
$fail = 1 if $v1 != 12 or $v2 != 22;
190198

191-
is($fail, 0, "Global transactions prevents Write Cycles (G0)");
199+
is($fail, 0, "Write Cycles (G0)");
200+
201+
###############################################################################
202+
# G1b: Intermediate Reads
203+
###############################################################################
204+
205+
$fail = 0;
206+
$node1->psql('postgres', "update t set v = 10 where id = 1");
207+
$node2->psql('postgres', "update t set v = 20 where id = 2");
208+
209+
start_global("G1b-a", $conn1a, $conn2a);
210+
start_global("G1b-b", $conn1b, $conn2b);
211+
212+
query_exec($conn1a, "update t set v = 101 where id = 1");
213+
214+
$v1 = query_row($conn1b, "select v from t where id = 1");
215+
$fail = 1 if $v1 != 10;
216+
217+
query_exec($conn1a, "update t set v = 11 where id = 1");
218+
commit_global("G1b-a", $conn1a, $conn2a);
219+
220+
$v1 = query_row($conn1b, "select v from t where id = 1");
221+
$fail = 1 if $v1 == 101;
222+
223+
if ($v1 != 11) {
224+
print "WARNIG: behavior is stricter than in usual read commited\n"
225+
}
226+
227+
commit_global("G1b-b", $conn1b, $conn2b);
228+
229+
is($fail, 0, "Intermediate Reads (G1b)");
230+
231+
232+
###############################################################################
233+
# G1c: Circular Information Flow
234+
###############################################################################
235+
236+
$fail = 0;
237+
$node1->psql('postgres', "update t set v = 10 where id = 1");
238+
$node2->psql('postgres', "update t set v = 20 where id = 2");
239+
240+
start_global("G1c-a", $conn1a, $conn2a);
241+
start_global("G1c-b", $conn1b, $conn2b);
242+
243+
query_exec($conn1a, "update t set v = 11 where id = 1");
244+
query_exec($conn2b, "update t set v = 22 where id = 2");
245+
246+
$v2 = query_row($conn2a, "select v from t where id = 2");
247+
$v1 = query_row($conn1b, "select v from t where id = 1");
248+
249+
$fail = 1 if $v1 != 10 or $v2 != 20;
250+
251+
commit_global("G1c-a", $conn1a, $conn2a);
252+
commit_global("G1c-b", $conn1b, $conn2b);
253+
254+
is($fail, 0, "Circular Information Flow (G1c)");
255+
256+
257+
###############################################################################
258+
# OTV: Observed Transaction Vanishes
259+
###############################################################################
260+
261+
$fail = 0;
262+
$node1->psql('postgres', "update t set v = 10 where id = 1");
263+
$node2->psql('postgres', "update t set v = 20 where id = 2");
264+
265+
start_global("OTV-a", $conn1a, $conn2a);
266+
start_global("OTV-b", $conn1b, $conn2b);
267+
start_global("OTV-c", $conn1c, $conn2c);
268+
269+
query_exec($conn1a, "update t set v = 11 where id = 1");
270+
query_exec($conn2a, "update t set v = 19 where id = 2");
271+
272+
query_exec_async($conn1b, "update t set v = 12 where id = 1");
273+
$fail = 1 if $conn1b->pg_ready != 0; # blocks
274+
commit_global("OTV-a", $conn1a, $conn2a);
275+
$conn1b->pg_result; # wait for unblock
276+
277+
$v1 = query_row($conn1c, "select v from t where id = 1");
278+
$fail = 1 if $v1 != 11;
279+
280+
query_exec($conn2b, "update t set v = 18 where id = 2");
281+
282+
$v2 = query_row($conn2c, "select v from t where id = 2");
283+
$fail = 1 if $v2 != 19;
284+
285+
commit_global("OTV-b", $conn1b, $conn2b);
286+
287+
$v2 = query_row($conn2c, "select v from t where id = 2");
288+
$v1 = query_row($conn1c, "select v from t where id = 1");
289+
$fail = 1 if $v2 != 18 or $v1 != 12;
290+
291+
commit_global("OTV-c", $conn1c, $conn2c);
292+
293+
is($fail, 0, "Observed Transaction Vanishes (OTV)");
294+
295+
296+
###############################################################################
297+
# PMP: Predicate-Many-Preceders
298+
###############################################################################
299+
300+
$fail = 0;
301+
$node1->psql('postgres', "delete from t");
302+
$node2->psql('postgres', "delete from t");
303+
$node1->psql('postgres', "insert into t values(1, 10)");
304+
$node2->psql('postgres', "insert into t values(2, 20)");
305+
306+
start_global("PMP-a", $conn1a, $conn2a);
307+
start_global("PMP-b", $conn1b, $conn2b);
308+
309+
my $v3 = query_row($conn1a, "select v from t where v = 30"); # should run everywhere!
310+
311+
query_exec($conn1b, "update t set v = 18 where id = 3"); # try place on second node?
312+
commit_global("PMP-b", $conn1b, $conn2b);
313+
314+
$v3 = query_row($conn1a, "select v from t where v % 3 = 0");
315+
$fail = 1 if defined $v3;
316+
317+
commit_global("PMP-a", $conn1a, $conn2a);
318+
319+
is($fail, 0, "Predicate-Many-Preceders (PMP)");
320+
321+
322+
323+
###############################################################################
324+
# PMP: Predicate-Many-Preceders for write predicates
325+
###############################################################################
326+
327+
$fail = 0;
328+
$node1->psql('postgres', "delete from t");
329+
$node2->psql('postgres', "delete from t");
330+
$node1->psql('postgres', "insert into t values(1, 10)");
331+
$node2->psql('postgres', "insert into t values(2, 20)");
332+
333+
start_global("PMPwp-a", $conn1a, $conn2a);
334+
start_global("PMPwp-b", $conn1b, $conn2b);
335+
336+
query_exec($conn1a, "update t set v = v + 10");
337+
query_exec($conn2a, "update t set v = v + 10");
338+
339+
query_exec_async($conn1b, "delete from t where v = 20");
340+
query_exec_async($conn2b, "delete from t where v = 20");
341+
commit_global("PMPwp-a", $conn1a, $conn2a);
342+
$conn1b->pg_result;
343+
$conn2b->pg_result;
344+
345+
query_row($conn1a, "select v from t where v = 20");
346+
query_row($conn2a, "select v from t where v = 20");
347+
348+
commit_global("PMPwp-b", $conn1b, $conn2b);
349+
350+
is($fail, 0, "Predicate-Many-Preceders for write predicates (PMPwp)");
351+
192352

193353

194354

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy