Data-RecordStore
view release on metacpan or search on metacpan
t/recordstore.t view on Meta::CPAN
my $silos = $rs->silos;
is( @$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 1 + (31 - 12), '20 silos' );
$rs = Data::RecordStore->reopen_store( $dir );
ok( $rs, 'reopen store right stuff' );
is( @$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 1 + (31 - 12), 'still 20 silos' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( "$dir/NOODIR" );
ok( $rs, 'inited store' );
$dir = tempdir( CLEANUP => 1 );
failnice( sub { Data::RecordStore->open_store( BASE_PATH => $dir, MAX_FILE_SIZE => 300, MIN_FILE_SIZE => 3_000 ) },
'cannot be more than',
'min size cant be larger than max' );
$rs = Data::RecordStore->open_store( BASE_PATH => $dir, MAX_FILE_SIZE => 3_000_000_000, MIN_FILE_SIZE => 300 );
ok( $rs, 'reinit store right stuff' );
is( $rs->[Data::RecordStore->MIN_SILO_ID], 9, "min silo id for 300 min size" );
is( @$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 1 + (31 - 9), 'number of silos' );
$rs = Data::RecordStore->reopen_store( $dir );
ok( $rs, 'reinit store right stuff min' );
is( $rs->[Data::RecordStore->MIN_SILO_ID], 9, "still min silo id for 300 min size" );
is( @$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 1 + ( 31 - 9), 'still number of silos for 300-3B' );
my $size = 2 ** 12;
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
MAX_FILE_SIZE => $size,
);
$silos = $rs->silos;
is( @$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 13 - 12, '1 silo' );
ok( $rs, 'inited store' );
failnice( sub { Data::RecordStore->open_store( BASE_PATH => $dir, MAX_FILE_SIZE => 2**9 ) },
'cannot be more than',
'default min size cant be larger than max' );
my $min_size = 2 ** 10;
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
MIN_FILE_SIZE => $min_size,
);
is( $rs->[Data::RecordStore->MIN_SILO_ID], 10, 'min silo id is 10' );
is( $rs->[Data::RecordStore->MAX_SILO_ID], 31, 'max silo id is 31' );
$silos = $rs->silos;
is( $#$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 31 - 10, '21 silos' );
ok( $rs, 'inited store' );
if( ! $is_root ) {
$dir = tempdir( CLEANUP => 1 );
chmod 0444, $dir;
failnice( sub { Data::RecordStore->open_store(
BASE_PATH => "$dir/cant",
MAX_FILE_SIZE => 2 ** 12,
) },
'permission denied',
'made a directory that it could not' );
$dir = tempdir( CLEANUP => 1 );
my $lockfile = "$dir/LOCK";
open my $out, '>', $lockfile;
print $out '';
close $out;
chmod 0444, $lockfile;
failnice( sub {
Data::RecordStore->open_store( BASE_PATH => $dir ) },
"permission denied",
"was able to init store with unwritable lock file" );
$dir = tempdir( CLEANUP => 1 );
Data::RecordStore->open_store( $dir );
chmod 0000, "$dir/LOCK";
failnice( sub { Data::RecordStore->reopen_store( $dir ) },
'permission denied',
'was able to reopen store with unwritable lock file' );
$dir = tempdir( CLEANUP => 1 );
chmod 0444, "$dir";
failnice( sub { Data::RecordStore->open_store( $dir ) },
'permission denied',
'was not able to open store in unwritable directory' );
$dir = tempdir( CLEANUP => 1 );
open $out, ">", "$dir/VERSION";
print $out "666\n";
close $out;
failnice( sub { Data::RecordStore->open_store( $dir ) },
'Aborting open',
'opened with version file but no lockfile' );
}
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( BASE_PATH => $dir,
MAX_FILE_SIZE => 2 ** 12 );
ok( $rs, 'opened a record store' );
$silos = $rs->silos;
is( @$silos - $rs->[Data::RecordStore->MIN_SILO_ID], 13 - 12, 'opened with correct number of silos' );
unless( $is_root ) {
remove_tree "$dir/data_silos/12";
failnice( sub { Data::RecordStore->reopen_store( $dir ) },
'could not find silo',
'was able to open data store with missing silo' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( BASE_PATH => $dir,
MAX_FILE_SIZE => 2 ** 12 );
my $lockfile = "$dir/LOCK";
unlink $lockfile;
failnice( sub { Data::RecordStore->reopen_store( $dir ) },
'no lock file found',
'able to open store without lockfile' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( BASE_PATH => $dir,
MAX_FILE_SIZE => 2 ** 12 );
my $infofile = "$dir/config.yaml";
unlink $infofile;
failnice( sub { Data::RecordStore->reopen_store( $dir ) },
'could not find record store',
'able to open store without infofile' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( $dir );
my $lock_dir = "$dir/user_locks";
remove_tree( $lock_dir );
failnice( sub { Data::RecordStore->reopen_store( $dir ) },
'locks directory not found',
'able to open store without locks dir' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( BASE_PATH => $dir,
MAX_FILE_SIZE => 2 ** 12 );
my $trans_dir = "$dir/transactions";
remove_tree( $trans_dir );
failnice( sub { Data::RecordStore->reopen_store( $dir ) },
'transaction directory not found',
'able to open store without transactions dir' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store( BASE_PATH => $dir,
MAX_FILE_SIZE => 2 ** 12 );
my $trans_silo_dir = "$dir/transactions";
chmod 0444, $trans_silo_dir;
failnice( sub { $rs->use_transaction },
'permission denied',
'able to use transaction with unwritable stack silo dir' );
}
} #test_init
sub test_locks {
my $use_single = shift;
my $dir = tempdir( CLEANUP => 1 );
my $store = Data::RecordStore->open_store( BASE_PATH => $dir );
$store->lock( "FOO", "BAR", "BAZ", "BAZ" );
eval {
$store->lock( "SOMETHING" );
fail( "Data::RecordStore->lock called twice in a row" );
};
like( $@, qr/cannot be called twice in a row/, 'Data::RecordStore->lock called twice in a row error message' );
$store->unlock;
$store->lock( "SOMETHING" );
pass( "Store was able to lock after unlocking" );
$store->unlock;
$store->lock( "SOMETHING", "ZOMETHING" );
pass( "Store was able to lock same label after unlocking" );
$store->unlock;
unless( $is_root ) {
chmod 0444, "$dir/user_locks/SOMETHING";
eval {
$store->lock( "SOMETHING" );
fail( "Store was able to lock unwritable lock file" );
};
like( $@, qr/lock failed/, 'lock failed when unwritable' );
undef $@;
chmod 0744, "$dir/user_locks/SOMETHING";
chmod 0444, "$dir/user_locks/ZOMETHING";
eval {
$store->lock( "BUMTHING", "ZOMETHING" );
fail( "Store was able to lock unwritable lock file" );
};
like( $@, qr/lock failed/, 'lock failed when unwritable' );
undef $@;
chmod 0744, "$dir/user_locks/ZOMETHING";
$store->lock( "BUMTHING", "ZOMETHING" );
pass( 'store able to lock with permissions restored' );
$store->unlock;
$dir = tempdir( CLEANUP => 1 );
eval {
$store = Data::RecordStore->open_store( BASE_PATH => $dir );
pass( "Was able to open store" );
chmod 0444, "$dir/user_locks";
$store->lock( "FOO" );
fail( "Data::RecordStore->lock didnt die trying to lock to unwriteable directory" );
};
like( $@, qr/lock failed/, "unable to lock because of unwriteable lock directory" );
$dir = tempdir( CLEANUP => 1 );
eval {
$store = Data::RecordStore->open_store( BASE_PATH => $dir );
open my $out, '>', "$dir/user_locks/BAR";
print $out '';
close $out;
chmod 0444, "$dir/user_locks/BAR";
pass( "Was able to open store" );
$store->lock( "FOO", "BAR", "BAZ" );
fail( "Data::RecordStore->lock didnt die trying to lock unwriteable lock file" );
};
like( $@, qr/lock failed/, "unable to lock because of unwriteable lock file" );
}
} #test_locks
sub test_use {
my $dir = tempdir( CLEANUP => 1 );
my $rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
);
is( $rs->entry_count, 0, 'starts with no entry count' );
my $id = $rs->stow( "FOOOOF" );
is( $rs->entry_count, 1, 'added one thing' );
is( $rs->entry_count, $id, 'id of one thing is that of entry count' );
my $nid = $rs->next_id;
is( $rs->entry_count, 2, 'added nuther thing' );
$id = $rs->stow( "LOOOOL", $nid );
is( $rs->entry_count, 2, 'stowed that nuther thing' );
is( $rs->index_silo->entry_count, 2, 'index silo also entry count 2' );
is( $nid, 2, 'second id by next' );
is( $id, $nid, 'entry count after forced set of things' );
is( $rs->fetch( 1 ), "FOOOOF", 'got first entry' );
is( $rs->fetch( 2 ), "LOOOOL", 'got second entry' );
$rs->stow( "X"x10_000, 2 );
is( $rs->fetch( 2 ), "X"x10_000, 'got ten zousand xsx' );
$rs->delete_record( 2 );
is( $rs->fetch( 2 ), undef, ' ten zousand xsx deletd' );
$nid = $rs->next_id;
is( $rs->fetch( $nid ), undef, 'nothing when next id' );
$rs->delete_record( $nid );
is( $rs->fetch( $nid ), undef, 'nothing when nothing next id dleted' );
is( $rs->next_id, 1 + $nid, 'still produces an other id after nothign delete' );
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
);
my $d1 = $rs->stow( "ZIPPO" ); #A 1
$rs->stow( "BLINK" ); #B 2
$rs->stow( "ZAP" ); #C 3
my $d2 = $rs->stow( "XZOOR" ); #D 4
my $d3 = $rs->stow( "ZSMOON" ); #E 5
$rs->stow( "SOOZ" ); #F 6
is( $rs->record_count, 6, "6 records stowed before delete test" );
is( $rs->entry_count, 6, "6 entries before delete test" );
is( $rs->silos_entry_count, 6, "6 items in silos" );
is( $rs->active_entry_count, 6, "6 active items in silos" );
# A B C D E F
$rs->delete_record( $d1 );
# F B C D E
t/recordstore.t view on Meta::CPAN
eval {
local( *STDERR );
my $errout;
open( STDERR, ">>", \$errout );
$rs->use_transaction();
like( $errout, qr/already in transaction/i, "error message for trying to transaction twice" );
pass( "able to open transaction twice" );
};
is( $rs->transaction_silo->entry_count, 1, 'trans silo still with one count' );
is( $copy->transaction_silo->entry_count, 1, 'copy trans silo still with one count' );
is( $rs->fetch( $oid ), "OMETHING ELSE", 'trans has right val for something not in trans' );
$rs->stow( "THIS MEANS SOMETHING", $id );
is( $rs->fetch( $id ), "THIS MEANS SOMETHING", "correct value in transaction" );
is( $copy->fetch( $id ), "SOMETHING ZOMETHING", "correct value in non-transaction" );
my $newid = $rs->stow( "ONE MORE THING TO STOWWWWWWWW" );
is( $newid, 3, '3rd id' );
is( $rs->fetch( $newid ), "ONE MORE THING TO STOWWWWWWWW", "correct value assigned id" );
is( $copy->fetch( $newid ), undef, "copy cant see commit value" );
$rs->stow( "OH LETS CHANGE THIS UP", $newid );
is( $rs->fetch( $newid ), "OH LETS CHANGE THIS UP", "correct new value assigned id" );
is( $copy->fetch( $newid ), undef, "copy still cant see commit value" );
my $nid = $rs->stow( "FORGRABS" );
my $nextid = $copy->next_id;
is( $nextid, 1 + $nid, 'copy gets one id further than trans store' );
is( $rs->fetch( $nid ), "FORGRABS", "correct new value assigned id" );
is( $copy->fetch( $nid ), undef, "copy still cant see commit value" );
$rs->delete_record( $nid );
is( $rs->fetch( $nid ), undef, "correct deleted assigned id" );
is( $copy->fetch( $nid ), undef, "copy still cant see commit value" );
$copy->stow( "neet", $nextid );
is( $rs->fetch( $nextid ), 'neet', "trans sees copy stow" );
is( $copy->fetch( $nextid ), 'neet', "copy sees own stow" );
$rs->delete_record( $nextid );
is( $rs->fetch( $nextid ), undef, "trans cant see deleted item" );
is( $copy->fetch( $nextid ), 'neet', "copy still sees own stow" );
$rs->stow( "X" x 10_000 );
$rs->commit_transaction();
is( $copy->fetch( $id ), "THIS MEANS SOMETHING", "correct value in copy after commit" );
is( $rs->fetch( $id ), "THIS MEANS SOMETHING", "correct value in after commit" );
is( $rs->fetch( $nextid ), undef, "trans cant see deleted item after commit" );
is( $copy->fetch( $nextid ), undef, "copy sees deleted own stow after commit" );
is( $copy->fetch( $nextid + 1 ), "X" x 10_000, 'big thing saved' );
if( ! $is_root ) {
$dir = tempdir( CLEANUP => 1 );
my $stacks = "$dir/transactions/1";
make_path( $stacks );
chmod 0444, $stacks;
$rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
);
eval {
$rs->use_transaction;
fail( 'was able to use transaction with unwritable dir' );
};
like( $@, qr/permission denied/i, 'err msg for trans with unwrite dir' );
}
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
);
$copy = Data::RecordStore->open_store( $dir );
$rs->use_transaction;
$newid = $rs->stow( "WIBBLES AND FOOKZA" );
$id = $copy->stow( "SOMETHING TO NEARLY DELETE" );
$rs->delete_record( $id );
is( $rs->fetch( $id ), undef, "trans cant see deleted item before commit" );
is( $copy->fetch( $id ), "SOMETHING TO NEARLY DELETE", "copy sees thing after transaction delete no commit" );
$rs->stow( "BLAME ME", $id );
is( $rs->fetch( $id ), "BLAME ME", "trans sees updated before commit" );
is( $copy->fetch( $id ), "SOMETHING TO NEARLY DELETE", "copy sees thing after transaction delete no commit" );
$rs->delete_record( $id );
$rs->delete_record( $id );
is( $rs->fetch( $id ), undef, "trans cant see deleted item before commit" );
is( $copy->fetch( $id ), "SOMETHING TO NEARLY DELETE", "copy sees thing after transaction delete no commit" );
is( $rs->fetch( $newid ), "WIBBLES AND FOOKZA", "trans can see stowed item before rollback" );
is( $copy->fetch( $newid ), undef, "copy cant see stowed item before rollback" );
$rs->rollback_transaction;
is( $rs->fetch( $id ), "SOMETHING TO NEARLY DELETE", "rs sees thing after transaction delete rollback" );
is( $copy->fetch( $id ), "SOMETHING TO NEARLY DELETE", "copy sees thing after transaction delete no commit" );
is( $rs->fetch( $newid ), undef, "trans cant see stowed item after rollback" );
is( $copy->fetch( $newid ), undef, "copy cant see stowed item after rollback" );
# need to monkey patch to test rollback of partially commited thing
$dir = tempdir( CLEANUP => 1 );
$rs = Data::RecordStore->open_store(
BASE_PATH => $dir,
);
$copy = Data::RecordStore->open_store( $dir );
my $times = 100_000;
my $id1 = $copy->stow( "THIS IS THE FIRST ONE IN THE FIRST PLACE" );
my $id2 = $copy->stow( "DELETE ME OR TRY TO" );
( run in 0.690 second using v1.01-cache-2.11-cpan-140bd7fdf52 )