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)