9 use MogileFS::Util qw(error_code);
12 my $sto = eval { temp_store(); };
14 plan skip_all => "Can't create temporary test database: $@";
18 my $dmid = $sto->create_domain("foo");
19 ok($dmid, "created a domain");
20 my $clsid = $sto->create_class($dmid, "classA");
21 ok($clsid, "created a class");
23 my $df = MogileFS::DevFID->new(100, 200);
24 ok($df, "made devfid");
25 ok($df->add_to_db, "added to db");
28 ok($fid, "got fid from df");
29 my @on = $fid->devids;
30 is(scalar @on, 1, "FID 200 on one device");
31 is($on[0], 100, "is correct number");
33 ok($sto->mass_insert_file_on(MogileFS::DevFID->new(1, 101),
34 MogileFS::DevFID->new(2, 101)), "did mass insert");
35 $fid = MogileFS::FID->new(101);
37 is(scalar @on, 2, "FID 101 on 2 devices");
41 my $fidid = $sto->register_tempfile(
46 devids => join(',', 1,2,3),
48 ok($fidid, "got a fidid");
51 $sto->register_tempfile(
56 devids => join(',', 1,2,3),
59 my $errc = error_code($@);
60 ok(!$fidid2, "didn't get fidid");
61 is($errc, "dup", "got a dup into tempfile")
62 or die "Got error: $@\n";
65 my $ignore_replace_match = {
66 base => { pattern => undef, dies => 1 },
67 MySQL => { pattern => qr/INSERT IGNORE/, dies => 0 },
68 SQLite => { pattern => qr/REPLACE/, dies => 0 },
69 Postgres => { pattern => undef, dies => 1 },
72 my $prx = eval { $sto->ignore_replace } || '';
73 my $sto_driver = ( split( /::/, ref($sto) ) )[2] || 'base';
74 my $match_spec = $ignore_replace_match->{ $sto_driver }
75 or die "Test not configured for '$sto_driver' storage driver";
79 ref( $match_spec->{pattern} ) eq 'Regexp'?
80 ( $prx =~ $match_spec->{pattern} ) :
83 "ignore_replace %s return value for storage type '%s'",
84 ref( $match_spec->{pattern} ) eq 'Regexp'?
85 'should' : 'should not',
88 ) or diag "Got value: $prx";
91 $match_spec->{dies}? $@ : !$@,
93 "ignore_replace %s die for storage type '%s'",
94 $match_spec->{dies}? 'should' : 'should not',
97 ) or diag "Got exception: $@";
101 # test retry_on_deadlock using good sql
103 $sto->retry_on_deadlock( sub { $sto->dbh->do("SELECT 1;"); } );
106 $rv eq '1' || $rv eq '0E0',
107 "retry_on_deadlock return value for '$sto_driver': $rv"
108 ) or diag "Got return value: $rv";
110 # test retry_on_deadlock using bad sql
112 $sto->retry_on_deadlock( sub { $sto->dbh->do("BADSQL;"); } );
116 "retry_on_deadlock got an exception on bad sql '$sto_driver'"
117 ) or diag "Got exception value: $@";
119 # test retry_on_deadlock using a custom exception
121 $sto->retry_on_deadlock( sub { die "preempt"; } );
125 "retry_on_deadlock got a non-sql exception for '$sto_driver'"
128 sub _do_induce_deadlock {
132 no warnings 'redefine';
134 local *{ "MogileFS\::Store\::$sto_driver\::was_deadlock_error" } = sub {
135 return $c++ < 2; # unlock on third try
137 $sto->retry_on_deadlock( @args );
141 # attempt to induce a deadlock and check iterations
143 $rv = _do_induce_deadlock( sub { return $_v++; } );
147 "no exception on retry_on_deadlock while inducing a deadlock"
152 'retry_on_deadlock returned good iteration count while inducing a deadlock'
155 # induce a deadlock using badsql... should return an exemption
156 $rv = _do_induce_deadlock( sub { $sto->dbh->do("BADSQL;"); } );
158 !$rv && $@ =~ /BADSQL/,
159 "retry_on_deadlock got expected exemption inducing a deadlock with bad sql"
160 ) or diag "Got value '$rv' with exemption: $@";
162 # induce a deadlock with good sql check sql return and iterations
164 $rv = _do_induce_deadlock(
166 return [ $sto->dbh->do("SELECT 1;"), $_v++ ];
170 ( !$@ && ref($rv) eq 'ARRAY' ) && (
171 ( $rv->[0] eq '1' || $rv->[0] eq '0E0' ) &&
174 "retry_on_deadlock got proper return value and iteration while inducing a deadlock"
177 use Digest::MD5 qw(md5);
179 $sto->set_checksum(6, 1, md5("FOO"));
180 my $hash = $sto->get_checksum(6);
181 ok($hash->{checksum} eq md5("FOO"), "checksum matches expected");
182 ok($hash->{fid} == 6, "checksum fid set correctly");
183 ok($hash->{hashtype} == 1, "hashtype set correctly");
185 $sto->set_checksum(6, 2, md5("MOO"));
186 $hash = $sto->get_checksum(6);
187 ok($hash->{checksum} eq md5("MOO"), "checksum matches expected");
188 ok($hash->{fid} == 6, "checksum fid set correctly");
189 ok($hash->{hashtype} == 2, "hashtype set correctly");
191 ok(1 == $sto->delete_checksum(6), "checksum deleted OK");
192 ok(0 == $sto->delete_checksum(6), "checksum delete MISS");
193 ok(!defined $sto->get_checksum(6), "undef on missing checksum");
195 # case-sensitivity tests for list_keys
199 key => 'Case_Sensitive_Clod',
204 $sto->replace_into_file(%arg);
207 # ensure existing (broken) case-insensitive list_keys works for MySQL/SQLite
208 # LIKE is always case-sensitive in Postgres, so its behavior for list_keys
210 $rows = $sto->get_keys_like($dmid, "case", undef, 1000);
211 if (ref($sto) eq "MogileFS::Store::Postgres") {
212 ok(scalar @$rows == 0, "Postgres list_keys is case-sensitive");
214 ok($rows->[0] eq 'Case_Sensitive_Clod', "list_keys matches insensitively");
217 # make list_keys case-sensitive
218 MogileFS::Config->set_server_setting("case_sensitive_list_keys", 1);
219 MogileFS::Config->cache_server_setting("case_sensitive_list_keys", 1);
221 $rows = $sto->get_keys_like($dmid, "case", undef, 1000);
222 ok(scalar @$rows == 0, "case-incorrect list_keys fails to match");
223 $rows = $sto->get_keys_like($dmid, "Case", undef, 1000);
224 ok($rows->[0] eq 'Case_Sensitive_Clod', "case-correct list_keys matches");
225 ok(scalar @$rows == 1, "only one row matched");
227 # make list_keys case-insensitive again
228 MogileFS::Config->set_server_setting("case_sensitive_list_keys", 0);
229 MogileFS::Config->cache_server_setting("case_sensitive_list_keys", 0);
231 $rows = $sto->get_keys_like($dmid, "case", undef, 1000);
232 if (ref($sto) eq "MogileFS::Store::Postgres") {
233 ok(scalar @$rows == 0, "Postgres list_keys is case-sensitive");
235 ok($rows->[0] eq 'Case_Sensitive_Clod', "list_keys matches insensitively (again)");