X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2F33_transactions.t;h=3107cc03d258d4f07d5ceda2f745f2ed6436620b;hb=67e9b86f22e8dacf29904f0163be3b23fae91074;hp=1edd0825b7d270e9f84add6edaa5b04d7a675d81;hpb=c57b19c6ae9b7bd8b23581479afa8664d69023b2;p=dbsrgits%2FDBM-Deep.git diff --git a/t/33_transactions.t b/t/33_transactions.t index 1edd082..3107cc0 100644 --- a/t/33_transactions.t +++ b/t/33_transactions.t @@ -1,141 +1,125 @@ use strict; -use Test::More tests => 99; +use warnings FATAL => 'all'; + +use Test::More; use Test::Deep; use Test::Exception; -use t::common qw( new_fh ); +use t::common qw( new_dbm ); use_ok( 'DBM::Deep' ); -my ($fh, $filename) = new_fh(); -my $db1 = DBM::Deep->new( - file => $filename, - locking => 1, - autoflush => 1, - num_txns => 16, -); - -my $db2 = DBM::Deep->new( - file => $filename, +my $dbm_factory = new_dbm( locking => 1, autoflush => 1, num_txns => 16, ); +while ( my $dbm_maker = $dbm_factory->() ) { + my $db1 = $dbm_maker->(); + next unless $db1->supports( 'transactions' ); -$db1->{x} = 'y'; -is( $db1->{x}, 'y', "Before transaction, DB1's X is Y" ); -is( $db2->{x}, 'y', "Before transaction, DB2's X is Y" ); + my $db2 = $dbm_maker->(); -cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); -cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); + $db1->{x} = 'y'; + is( $db1->{x}, 'y', "Before transaction, DB1's X is Y" ); + is( $db2->{x}, 'y', "Before transaction, DB2's X is Y" ); -throws_ok { - $db1->rollback; -} qr/Cannot rollback without an active transaction/, "Attempting to rollback without a transaction throws an error"; + cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); -throws_ok { - $db1->commit; -} qr/Cannot commit without an active transaction/, "Attempting to commit without a transaction throws an error"; + throws_ok { + $db1->rollback; + } qr/Cannot rollback without an active transaction/, "Attempting to rollback without a transaction throws an error"; -$db1->begin_work; + throws_ok { + $db1->commit; + } qr/Cannot commit without an active transaction/, "Attempting to commit without a transaction throws an error"; -throws_ok { $db1->begin_work; -} qr/Cannot begin_work within an active transaction/, "Attempting to begin_work within a transaction throws an error"; - -lives_ok { - $db1->rollback; -} "Rolling back an empty transaction is ok."; -cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); -cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); + throws_ok { + $db1->begin_work; + } qr/Cannot begin_work within an active transaction/, "Attempting to begin_work within a transaction throws an error"; -$db1->begin_work; - -lives_ok { - $db1->commit; -} "Committing an empty transaction is ok."; - -cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); -cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); - -$db1->begin_work; + lives_ok { + $db1->rollback; + } "Rolling back an empty transaction is ok."; cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); - is( $db1->{x}, 'y', "DB1 transaction started, no actions - DB1's X is Y" ); - is( $db2->{x}, 'y', "DB1 transaction started, no actions - DB2's X is Y" ); + $db1->begin_work; - $db2->{x} = 'a'; - is( $db1->{x}, 'y', "Within DB1 transaction, DB1's X is still Y" ); - is( $db2->{x}, 'a', "Within DB1 transaction, DB2's X is now A" ); + lives_ok { + $db1->commit; + } "Committing an empty transaction is ok."; - $db1->{x} = 'z'; - is( $db1->{x}, 'z', "Within DB1 transaction, DB1's X is Z" ); - is( $db2->{x}, 'a', "Within DB1 transaction, DB2's X is still A" ); + cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); - $db1->{z} = 'a'; - is( $db1->{z}, 'a', "Within DB1 transaction, DB1's Z is A" ); - ok( !exists $db2->{z}, "Since z was added after the transaction began, DB2 doesn't see it." ); + $db1->begin_work; - $db2->{other_x} = 'foo'; - is( $db2->{other_x}, 'foo', "DB2 set other_x within DB1's transaction, so DB2 can see it" ); - ok( !exists $db1->{other_x}, "Since other_x was added after the transaction began, DB1 doesn't see it." ); + cmp_bag( [ keys %$db1 ], [qw( x )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x )], "DB2 keys correct" ); - # Reset to an expected value - $db2->{x} = 'y'; - is( $db1->{x}, 'z', "Within DB1 transaction, DB1's X is istill Z" ); - is( $db2->{x}, 'y', "Within DB1 transaction, DB2's X is now Y" ); + is( $db1->{x}, 'y', "DB1 transaction started, no actions - DB1's X is Y" ); + is( $db2->{x}, 'y', "DB1 transaction started, no actions - DB2's X is Y" ); - cmp_bag( [ keys %$db1 ], [qw( x z )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x other_x )], "DB2 keys correct" ); + $db2->{x} = 'a'; + is( $db1->{x}, 'y', "Within DB1 transaction, DB1's X is still Y" ); + is( $db2->{x}, 'a', "Within DB1 transaction, DB2's X is now A" ); -$db1->rollback; + $db1->{x} = 'z'; + is( $db1->{x}, 'z', "Within DB1 transaction, DB1's X is Z" ); + is( $db2->{x}, 'a', "Within DB1 transaction, DB2's X is still A" ); -is( $db1->{x}, 'y', "After rollback, DB1's X is Y" ); -is( $db2->{x}, 'y', "After rollback, DB2's X is Y" ); + $db1->{z} = 'a'; + is( $db1->{z}, 'a', "Within DB1 transaction, DB1's Z is A" ); + ok( !exists $db2->{z}, "Since z was added after the transaction began, DB2 doesn't see it." ); -is( $db1->{other_x}, 'foo', "After DB1 transaction is over, DB1 can see other_x" ); -is( $db2->{other_x}, 'foo', "After DB1 transaction is over, DB2 can still see other_x" ); + $db2->{other_x} = 'foo'; + is( $db2->{other_x}, 'foo', "DB2 set other_x within DB1's transaction, so DB2 can see it" ); + ok( !exists $db1->{other_x}, "Since other_x was added after the transaction began, DB1 doesn't see it." ); -$db1->begin_work; + # Reset to an expected value + $db2->{x} = 'y'; + is( $db1->{x}, 'z', "Within DB1 transaction, DB1's X is istill Z" ); + is( $db2->{x}, 'y', "Within DB1 transaction, DB2's X is now Y" ); - cmp_bag( [ keys %$db1 ], [qw( x other_x )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x other_x )], "DB2 keys correct" ); + cmp_bag( [ keys %$db1 ], [qw( x z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x other_x )], "DB2 keys correct" ); - is( $db1->{x}, 'y', "DB1 transaction started, no actions - DB1's X is Y" ); - is( $db2->{x}, 'y', "DB1 transaction started, no actions - DB2's X is Y" ); + $db1->rollback; - $db1->{x} = 'z'; - is( $db1->{x}, 'z', "Within DB1 transaction, DB1's X is Z" ); - is( $db2->{x}, 'y', "Within DB1 transaction, DB2's X is still Y" ); + is( $db1->{x}, 'y', "After rollback, DB1's X is Y" ); + is( $db2->{x}, 'y', "After rollback, DB2's X is Y" ); - $db2->{other_x} = 'bar'; - is( $db2->{other_x}, 'bar', "DB2 set other_x within DB1's transaction, so DB2 can see it" ); - is( $db1->{other_x}, 'foo', "Since other_x was modified after the transaction began, DB1 doesn't see the change." ); + is( $db1->{other_x}, 'foo', "After DB1 transaction is over, DB1 can see other_x" ); + is( $db2->{other_x}, 'foo', "After DB1 transaction is over, DB2 can still see other_x" ); - $db1->{z} = 'a'; - is( $db1->{z}, 'a', "Within DB1 transaction, DB1's Z is A" ); - ok( !exists $db2->{z}, "Since z was added after the transaction began, DB2 doesn't see it." ); + $db1->begin_work; - cmp_bag( [ keys %$db1 ], [qw( x other_x z )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x other_x )], "DB2 keys correct" ); + cmp_bag( [ keys %$db1 ], [qw( x other_x )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x other_x )], "DB2 keys correct" ); -$db1->commit; + is( $db1->{x}, 'y', "DB1 transaction started, no actions - DB1's X is Y" ); + is( $db2->{x}, 'y', "DB1 transaction started, no actions - DB2's X is Y" ); -is( $db1->{x}, 'z', "After commit, DB1's X is Z" ); -is( $db2->{x}, 'z', "After commit, DB2's X is Z" ); + $db1->{x} = 'z'; + is( $db1->{x}, 'z', "Within DB1 transaction, DB1's X is Z" ); + is( $db2->{x}, 'y', "Within DB1 transaction, DB2's X is still Y" ); -is( $db1->{z}, 'a', "After commit, DB1's Z is A" ); -is( $db2->{z}, 'a', "After commit, DB2's Z is A" ); + $db2->{other_x} = 'bar'; + is( $db2->{other_x}, 'bar', "DB2 set other_x within DB1's transaction, so DB2 can see it" ); + is( $db1->{other_x}, 'foo', "Since other_x was modified after the transaction began, DB1 doesn't see the change." ); -is( $db1->{other_x}, 'bar', "After commit, DB1's other_x is bar" ); -is( $db2->{other_x}, 'bar', "After commit, DB2's other_x is bar" ); + $db1->{z} = 'a'; + is( $db1->{z}, 'a', "Within DB1 transaction, DB1's Z is A" ); + ok( !exists $db2->{z}, "Since z was added after the transaction began, DB2 doesn't see it." ); -$db1->begin_work; + cmp_bag( [ keys %$db1 ], [qw( x other_x z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x other_x )], "DB2 keys correct" ); - cmp_bag( [ keys %$db1 ], [qw( x z other_x )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x z other_x )], "DB2 keys correct" ); + $db1->commit; is( $db1->{x}, 'z', "After commit, DB1's X is Z" ); is( $db2->{x}, 'z', "After commit, DB2's X is Z" ); @@ -143,93 +127,108 @@ $db1->begin_work; is( $db1->{z}, 'a', "After commit, DB1's Z is A" ); is( $db2->{z}, 'a', "After commit, DB2's Z is A" ); - is( $db1->{other_x}, 'bar', "After begin_work, DB1's other_x is still bar" ); - is( $db2->{other_x}, 'bar', "After begin_work, DB2's other_x is still bar" ); + is( $db1->{other_x}, 'bar', "After commit, DB1's other_x is bar" ); + is( $db2->{other_x}, 'bar', "After commit, DB2's other_x is bar" ); - delete $db2->{other_x}; - ok( !exists $db2->{other_x}, "DB2 deleted other_x in DB1's transaction, so it can't see it anymore" ); - is( $db1->{other_x}, 'bar', "Since other_x was deleted after the transaction began, DB1 still sees it." ); + $db1->begin_work; - cmp_bag( [ keys %$db1 ], [qw( x z other_x )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); + cmp_bag( [ keys %$db1 ], [qw( x z other_x )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x z other_x )], "DB2 keys correct" ); - delete $db1->{x}; - ok( !exists $db1->{x}, "DB1 deleted X in a transaction, so it can't see it anymore" ); - is( $db2->{x}, 'z', "But, DB2 can still see it" ); + is( $db1->{x}, 'z', "After commit, DB1's X is Z" ); + is( $db2->{x}, 'z', "After commit, DB2's X is Z" ); - cmp_bag( [ keys %$db1 ], [qw( other_x z )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); + is( $db1->{z}, 'a', "After commit, DB1's Z is A" ); + is( $db2->{z}, 'a', "After commit, DB2's Z is A" ); -$db1->rollback; + is( $db1->{other_x}, 'bar', "After begin_work, DB1's other_x is still bar" ); + is( $db2->{other_x}, 'bar', "After begin_work, DB2's other_x is still bar" ); -ok( !exists $db2->{other_x}, "It's still deleted for DB2" ); -ok( !exists $db1->{other_x}, "And now DB1 sees the deletion" ); + delete $db2->{other_x}; + ok( !exists $db2->{other_x}, "DB2 deleted other_x in DB1's transaction, so it can't see it anymore" ); + is( $db1->{other_x}, 'bar', "Since other_x was deleted after the transaction began, DB1 still sees it." ); -is( $db1->{x}, 'z', "The transaction was rolled back, so DB1 can see X now" ); -is( $db2->{x}, 'z', "DB2 can still see it" ); + cmp_bag( [ keys %$db1 ], [qw( x z other_x )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); -cmp_bag( [ keys %$db1 ], [qw( x z )], "DB1 keys correct" ); -cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); + delete $db1->{x}; + ok( !exists $db1->{x}, "DB1 deleted X in a transaction, so it can't see it anymore" ); + is( $db2->{x}, 'z', "But, DB2 can still see it" ); -$db1->begin_work; + cmp_bag( [ keys %$db1 ], [qw( other_x z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); - delete $db1->{x}; - ok( !exists $db1->{x}, "DB1 deleted X in a transaction, so it can't see it anymore" ); + $db1->rollback; - is( $db2->{x}, 'z', "But, DB2 can still see it" ); + ok( !exists $db2->{other_x}, "It's still deleted for DB2" ); + ok( !exists $db1->{other_x}, "And now DB1 sees the deletion" ); - cmp_bag( [ keys %$db1 ], [qw( z )], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); + is( $db1->{x}, 'z', "The transaction was rolled back, so DB1 can see X now" ); + is( $db2->{x}, 'z', "DB2 can still see it" ); -$db1->commit; + cmp_bag( [ keys %$db1 ], [qw( x z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); -ok( !exists $db1->{x}, "The transaction was committed, so DB1 still deleted X" ); -ok( !exists $db2->{x}, "DB2 can now see the deletion of X" ); + $db1->begin_work; -$db1->{foo} = 'bar'; -is( $db1->{foo}, 'bar', "Set foo to bar in DB1" ); -is( $db2->{foo}, 'bar', "Set foo to bar in DB2" ); + delete $db1->{x}; + ok( !exists $db1->{x}, "DB1 deleted X in a transaction, so it can't see it anymore" ); -cmp_bag( [ keys %$db1 ], [qw( foo z )], "DB1 keys correct" ); -cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); + is( $db2->{x}, 'z', "But, DB2 can still see it" ); -$db1->begin_work; + cmp_bag( [ keys %$db1 ], [qw( z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( x z )], "DB2 keys correct" ); - %$db1 = (); # clear() - ok( !exists $db1->{foo}, "Cleared foo" ); - is( $db2->{foo}, 'bar', "But in DB2, we can still see it" ); + $db1->commit; - cmp_bag( [ keys %$db1 ], [qw()], "DB1 keys correct" ); - cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); + ok( !exists $db1->{x}, "The transaction was committed, so DB1 still deleted X" ); + ok( !exists $db2->{x}, "DB2 can now see the deletion of X" ); -$db1->rollback; + $db1->{foo} = 'bar'; + is( $db1->{foo}, 'bar', "Set foo to bar in DB1" ); + is( $db2->{foo}, 'bar', "Set foo to bar in DB2" ); -is( $db1->{foo}, 'bar', "Rollback means 'foo' is still there" ); -is( $db2->{foo}, 'bar', "Rollback means 'foo' is still there" ); + cmp_bag( [ keys %$db1 ], [qw( foo z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); -cmp_bag( [ keys %$db1 ], [qw( foo z )], "DB1 keys correct" ); -cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); + $db1->begin_work; -SKIP: { - skip "Optimize tests skipped on Win32", 5 - if $^O eq 'MSWin32' || $^O eq 'cygwin'; + %$db1 = (); # clear() + ok( !exists $db1->{foo}, "Cleared foo" ); + is( $db2->{foo}, 'bar', "But in DB2, we can still see it" ); - $db1->optimize; + cmp_bag( [ keys %$db1 ], [qw()], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); - is( $db1->{foo}, 'bar', 'After optimize, everything is ok' ); - is( $db2->{foo}, 'bar', 'After optimize, everything is ok' ); + $db1->rollback; - is( $db1->{z}, 'a', 'After optimize, everything is ok' ); - is( $db2->{z}, 'a', 'After optimize, everything is ok' ); + is( $db1->{foo}, 'bar', "Rollback means 'foo' is still there" ); + is( $db2->{foo}, 'bar', "Rollback means 'foo' is still there" ); cmp_bag( [ keys %$db1 ], [qw( foo z )], "DB1 keys correct" ); cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); - $db1->begin_work; + SKIP: { + skip "Optimize tests skipped on Win32", 7 + if $^O eq 'MSWin32' || $^O eq 'cygwin'; - cmp_ok( $db1->_engine->trans_id, '==', 1, "Transaction ID has been reset after optimize" ); + $db1->optimize; - $db1->rollback; + is( $db1->{foo}, 'bar', 'After optimize, everything is ok' ); + is( $db2->{foo}, 'bar', 'After optimize, everything is ok' ); + + is( $db1->{z}, 'a', 'After optimize, everything is ok' ); + is( $db2->{z}, 'a', 'After optimize, everything is ok' ); + + cmp_bag( [ keys %$db1 ], [qw( foo z )], "DB1 keys correct" ); + cmp_bag( [ keys %$db2 ], [qw( foo z )], "DB2 keys correct" ); + + $db1->begin_work; + + cmp_ok( $db1->_engine->trans_id, '==', 1, "Transaction ID has been reset after optimize" ); + + $db1->rollback; + } } -__END__ +done_testing;