| 1 | #!/usr/bin/perl -w |
|---|
| 2 | |
|---|
| 3 | BEGIN { chdir 't' if -d 't' } |
|---|
| 4 | use lib '../lib'; |
|---|
| 5 | use blib; |
|---|
| 6 | |
|---|
| 7 | use Test::More tests => 223; |
|---|
| 8 | use Test::DatabaseRow; |
|---|
| 9 | use Test::Exception; |
|---|
| 10 | use Test::Warn; |
|---|
| 11 | |
|---|
| 12 | use File::Path; |
|---|
| 13 | |
|---|
| 14 | package Lancelot::DB; |
|---|
| 15 | use subs 'time'; |
|---|
| 16 | package main; |
|---|
| 17 | my $the_time = 1000000000; |
|---|
| 18 | *Lancelot::DB::time = sub { |
|---|
| 19 | return $the_time; |
|---|
| 20 | }; |
|---|
| 21 | |
|---|
| 22 | use_ok(Lancelot::DB); |
|---|
| 23 | |
|---|
| 24 | # This must not conflict with a real list name. |
|---|
| 25 | my ($listname_local, $listname_domain) = ('pl-testlist', 'example.com'); |
|---|
| 26 | my $listname = "$listname_local\@$listname_domain"; |
|---|
| 27 | |
|---|
| 28 | can_ok('Lancelot::DB', 'new'); |
|---|
| 29 | rmtree("$ENV{HOME}/.pl/$listname", 1); |
|---|
| 30 | my $db = new Lancelot::DB $listname, { "create" => 0 }; |
|---|
| 31 | ok( !defined $db, "new() returned undef for non-existing list" ); |
|---|
| 32 | |
|---|
| 33 | $db = new Lancelot::DB $listname, { user => "root" }; |
|---|
| 34 | ok( !defined $db, "new() still undef if user is root"); |
|---|
| 35 | dies_ok { $db = new Lancelot::DB $listname, { user => 'NONEXISTENTUSER' } } |
|---|
| 36 | "new() with non-existent user"; |
|---|
| 37 | |
|---|
| 38 | foreach my $create (qw/1 0/) { |
|---|
| 39 | $db = new Lancelot::DB $listname, { "create" => $create }; |
|---|
| 40 | ok( defined $db, "new() returned something with create=$create" ); |
|---|
| 41 | |
|---|
| 42 | if ($create) { |
|---|
| 43 | # double-create test |
|---|
| 44 | my $db2; |
|---|
| 45 | dies_ok { $db2 = new Lancelot::DB $listname, { create => 1 } } |
|---|
| 46 | "creating existing database"; |
|---|
| 47 | } |
|---|
| 48 | |
|---|
| 49 | ok( $db->isa('Lancelot::DB'), "and it's the right class" ); |
|---|
| 50 | ok( $db->get_parameter('dbversion') > 0, "and it has a schema version" ); |
|---|
| 51 | |
|---|
| 52 | is( $db->get_config('list.address'), $listname, |
|---|
| 53 | "and the proper list address"); |
|---|
| 54 | |
|---|
| 55 | ok( $db->set_parameter('pl-test', 'xyzzy'), |
|---|
| 56 | "set_parameter() seems to work" ); |
|---|
| 57 | my $test = $db->get_parameter('pl-test'); |
|---|
| 58 | is( $test, 'xyzzy', "and get_parameter() gets the same back" ); |
|---|
| 59 | |
|---|
| 60 | ok( $db->set_config('ll.test', 'xyzzy'), "set_config() seems to work"); |
|---|
| 61 | $test = $db->get_config('ll.test'); |
|---|
| 62 | is( $test, 'xyzzy', "and get_config() gets the same back" ); |
|---|
| 63 | } |
|---|
| 64 | undef $db; |
|---|
| 65 | |
|---|
| 66 | my $home = $ENV{HOME}; delete $ENV{HOME}; |
|---|
| 67 | ok( $db = Lancelot::DB->new($listname, { create => 0 }), "HOME from passwd"); |
|---|
| 68 | undef $db; |
|---|
| 69 | $ENV{HOME} = $home; |
|---|
| 70 | |
|---|
| 71 | # ourisp hack |
|---|
| 72 | |
|---|
| 73 | my $ourispdir = "$ENV{HOME}/domains/$listname_domain"; |
|---|
| 74 | -d $ourispdir || mkpath $ourispdir; |
|---|
| 75 | rmtree "$ourispdir/$listname_local"; |
|---|
| 76 | ok( $db = Lancelot::DB->new($listname, { create => 1, ourisp => 1 }), |
|---|
| 77 | "ourisp hack"); |
|---|
| 78 | ok( -f "$ourispdir/$listname_local/list.db", "ourisp hack list.db check"); |
|---|
| 79 | undef $db; |
|---|
| 80 | |
|---|
| 81 | $ENV{HOME} = "$ourispdir/$listname_local"; |
|---|
| 82 | ok( $db = Lancelot::DB->new($listname, { create => 0 }), |
|---|
| 83 | "ourisp hack - use only"); |
|---|
| 84 | undef $db; |
|---|
| 85 | unlink "$ourispdir/$listname_local/list.db"; |
|---|
| 86 | $db = new Lancelot::DB $listname, { create => 0 }, |
|---|
| 87 | ok( !defined $db, "ourisp hack - use only (no list.db file)"); |
|---|
| 88 | undef $db; |
|---|
| 89 | rmtree "$ourispdir/$listname_local"; |
|---|
| 90 | |
|---|
| 91 | $ENV{HOME} = $home; |
|---|
| 92 | $db = new Lancelot::DB $listname, { create => 1, ourisp => 1 }; |
|---|
| 93 | undef $db; |
|---|
| 94 | ok( $db = Lancelot::DB->new($listname, { create => 0 }), |
|---|
| 95 | "open ourisp-style list w/o \$HOME"); |
|---|
| 96 | undef $db; |
|---|
| 97 | rmtree "$ourispdir/$listname_local"; |
|---|
| 98 | |
|---|
| 99 | # various nit-picks |
|---|
| 100 | |
|---|
| 101 | $ENV{HOME} = $home; |
|---|
| 102 | rmtree "$ENV{HOME}/.pl/$listname"; |
|---|
| 103 | $db = new Lancelot::DB $listname, { create => 1 }; |
|---|
| 104 | undef $db; |
|---|
| 105 | |
|---|
| 106 | open F, "> $ENV{HOME}/.pl/$listname/list.db"; |
|---|
| 107 | print F "Hallo\n"; |
|---|
| 108 | close F; |
|---|
| 109 | $db = new Lancelot::DB $listname, { create => 0 }; |
|---|
| 110 | ok( !defined $db, "list.db too short"); |
|---|
| 111 | |
|---|
| 112 | open F, "> $ENV{HOME}/.pl/$listname/list.db"; |
|---|
| 113 | print F "** This file contains an SQLite 2.1 database"; # Yeah right. |
|---|
| 114 | close F; |
|---|
| 115 | $db = new Lancelot::DB $listname, { create => 0 }; |
|---|
| 116 | ok( !defined $db, "list.db is SQLite2 file"); |
|---|
| 117 | rmtree "$ENV{HOME}/.pl/$listname"; |
|---|
| 118 | |
|---|
| 119 | $db = new Lancelot::DB $listname, { create => 1 }; |
|---|
| 120 | $db->{dbh}->do("update config set value='sqlite:foobar' where key='list.addressdb'"); |
|---|
| 121 | undef $db; |
|---|
| 122 | dies_ok { |
|---|
| 123 | $db = new Lancelot::DB $listname, { create => 0 }; |
|---|
| 124 | $db->get_addresses(); |
|---|
| 125 | } "invalid sqlite:foobar subscriber data source type"; |
|---|
| 126 | rmtree "$ENV{HOME}/.pl/$listname"; |
|---|
| 127 | |
|---|
| 128 | $db = new Lancelot::DB $listname, { create => 1 }; |
|---|
| 129 | $db->{dbh}->do("update config set value='foo:bar' where key='list.addressdb'"); |
|---|
| 130 | undef $db; |
|---|
| 131 | dies_ok { |
|---|
| 132 | $db = new Lancelot::DB $listname, { create => 0 }; |
|---|
| 133 | $db->get_addresses(); |
|---|
| 134 | } "invalid foo:bar subscriber data source type"; |
|---|
| 135 | rmtree "$ENV{HOME}/.pl/$listname"; |
|---|
| 136 | |
|---|
| 137 | $db = new Lancelot::DB $listname, { create => 1 }; |
|---|
| 138 | $db->{dbh}->do("update parameter set value=9999 where key='dbversion'"); |
|---|
| 139 | undef $db; |
|---|
| 140 | dies_ok { $db = new Lancelot::DB $listname, { create => 0 } } |
|---|
| 141 | "schema version too new"; |
|---|
| 142 | |
|---|
| 143 | # get_listdir |
|---|
| 144 | |
|---|
| 145 | $ENV{HOME} = $home; |
|---|
| 146 | rmtree "$ENV{HOME}/.pl/$listname"; |
|---|
| 147 | $db = new Lancelot::DB $listname, { create => 1 }; |
|---|
| 148 | my $dir = $db->get_listdir(); |
|---|
| 149 | is( $dir, "$ENV{HOME}/.pl/$listname", "get_listdir() seems to work" ); |
|---|
| 150 | |
|---|
| 151 | # Parameter |
|---|
| 152 | |
|---|
| 153 | can_ok($db, 'set_parameter'); |
|---|
| 154 | can_ok($db, 'increment_parameter'); |
|---|
| 155 | can_ok($db, 'get_parameter'); |
|---|
| 156 | $db->set_parameter('pl-inctest', '0'); |
|---|
| 157 | is( $db->increment_parameter('pl-inctest'), 0, "increment_parameter() result" ); |
|---|
| 158 | is( $db->get_parameter('pl-inctest'), 1, "increment_parameter() db entry" ); |
|---|
| 159 | |
|---|
| 160 | local $Test::DatabaseRow::dbh = $db->{dbh}; |
|---|
| 161 | |
|---|
| 162 | can_ok($db, 'set_configs'); |
|---|
| 163 | ok( $db->set_configs("ll.c1 = abc"), "set_configs() single" ); |
|---|
| 164 | row_ok(table => 'config', |
|---|
| 165 | where => [ key => 'll.c1', value => 'abc' ], |
|---|
| 166 | label => "set_configs() single db check"); |
|---|
| 167 | ok( $db->set_configs('ll.c1 = "abc "'), "set_configs() single quoted" ); |
|---|
| 168 | row_ok(table => 'config', |
|---|
| 169 | where => [ key => 'll.c1', value => 'abc ' ], |
|---|
| 170 | label => "set_configs() single quoted db check"); |
|---|
| 171 | ok( $db->set_configs("ll.c1 = abc", "ll.c2 = def"), "set_configs() double" ); |
|---|
| 172 | row_ok(table => 'config', |
|---|
| 173 | where => [ key => 'll.c1', value => 'abc' ], |
|---|
| 174 | label => "set_configs() double db check"); |
|---|
| 175 | can_ok($db, 'get_config'); |
|---|
| 176 | ok( $db->get_config('ll.c1') eq 'abc' && $db->get_config('ll.c2') eq 'def' |
|---|
| 177 | && $db->get_config('list.address') eq $listname, "set_configs() db entry"); |
|---|
| 178 | |
|---|
| 179 | can_ok($db, 'delete_configs'); |
|---|
| 180 | ok( $db->delete_configs("ll.c1", "ll.c2") == 2, 'delete_configs()'); |
|---|
| 181 | ok( !defined $db->get_config('ll.c1') && !defined $db->get_config('ll.c2') |
|---|
| 182 | && $db->get_config('list.address') eq $listname, |
|---|
| 183 | "delete_configs() db entry"); |
|---|
| 184 | warning_like { |
|---|
| 185 | ok( $db->delete_configs("%&/*+") == 0, 'delete_configs() invalid key'); |
|---|
| 186 | } qr|invalid config name: %&/\*\+|, "invalid config name warning"; |
|---|
| 187 | warning_like { |
|---|
| 188 | ok( $db->set_configs("xyzzy") == 0, 'invalid config' ); |
|---|
| 189 | } qr|invalid config "xyzzy"|, "invalid config warning"; |
|---|
| 190 | |
|---|
| 191 | $db->set_configs('ll.c1 = abc', 'll.c2 = def'); |
|---|
| 192 | can_ok($db, 'config_names'); |
|---|
| 193 | my @names = sort $db->config_names(); |
|---|
| 194 | my @stdnames = <DATA>; chomp @stdnames; |
|---|
| 195 | is_deeply (\@names, \@stdnames, 'config_names()'); |
|---|
| 196 | |
|---|
| 197 | can_ok($db, 'set_configs_from_file'); |
|---|
| 198 | ok( $db->set_configs_from_file('nonexistent.cfg', 0) == 0, |
|---|
| 199 | "set_configs_from_file: nonexistent file"); |
|---|
| 200 | dies_ok { $db->set_configs_from_file('nonexistent.cfg', 1) } |
|---|
| 201 | "set_configs_from_file: nonexistent file (must_exist)"; |
|---|
| 202 | ok( $db->set_configs_from_file('test.cfg', 0) == 2, |
|---|
| 203 | "set_configs_from_file: test.cfg"); |
|---|
| 204 | |
|---|
| 205 | can_ok($db, 'init_address_db'); |
|---|
| 206 | ok( $db->init_address_db(), 'init_address_db()' ); |
|---|
| 207 | row_ok(sql => 'select * from user', results => 0, |
|---|
| 208 | label => "new list has no users"); |
|---|
| 209 | row_ok(sql => 'select * from address', results => 0, |
|---|
| 210 | label => "new list has no addresses"); |
|---|
| 211 | row_ok(sql => 'select * from subscription', results => 0, |
|---|
| 212 | label => "new list has no subscriptions"); |
|---|
| 213 | can_ok($db, 'add_address'); |
|---|
| 214 | ok( $db->add_address('hugo@example.com', {}), 'simple add_address()' ); |
|---|
| 215 | row_ok(table => 'user', |
|---|
| 216 | where => [ id => 1, name => 'hugo@example.com', password => '' ], |
|---|
| 217 | label => 'user row added'); |
|---|
| 218 | row_ok(table => 'address', |
|---|
| 219 | where => [ user_id => 1, |
|---|
| 220 | local => 'hugo', domain => 'example.com' ], |
|---|
| 221 | label => 'address row added'); |
|---|
| 222 | row_ok(table => 'subscription', |
|---|
| 223 | where => [ list_id => 1, address_id => 1, |
|---|
| 224 | status => 'SUBSCRIBED', |
|---|
| 225 | moderator => 0, nomail => 0, digest => 0, moderated => 0, |
|---|
| 226 | admin => 0 ], |
|---|
| 227 | label => "one subscriber added"); |
|---|
| 228 | can_ok($db, 'get_subscription_id'); |
|---|
| 229 | is( $db->get_subscription_id('hugo@example.com'), 1, |
|---|
| 230 | 'get_subscription_id(), existing sub'); |
|---|
| 231 | is( $db->get_subscription_id((Email::Address->parse('hugo@example.com'))[0]), 1, |
|---|
| 232 | 'get_subscription_id(), existing sub, Email::Address'); |
|---|
| 233 | is( $db->get_subscription_id('nonexistent@example.com'), undef, |
|---|
| 234 | 'get_subscription_id(), non-existing sub'); |
|---|
| 235 | ok( $db->add_address('John Doe <jdoe@example.com>', {}), |
|---|
| 236 | 'add_address() w/name'); |
|---|
| 237 | row_ok(table => 'user', |
|---|
| 238 | where => [ id => 2, name => 'John Doe', password => '' ], |
|---|
| 239 | label => 'user w/name added'); |
|---|
| 240 | row_ok(table => 'address', |
|---|
| 241 | where => [ user_id => 2, |
|---|
| 242 | local => 'jdoe', domain => 'example.com' ], |
|---|
| 243 | label => 'address row w/name added'); |
|---|
| 244 | row_ok(table => 'subscription', |
|---|
| 245 | where => [ id => '2', list_id => 1, address_id => 2, |
|---|
| 246 | status => 'SUBSCRIBED', |
|---|
| 247 | moderator => 0, nomail => 0, digest => 0, moderated => 0, |
|---|
| 248 | admin => 0 ], |
|---|
| 249 | label => "second subscription (w/name) added" ); |
|---|
| 250 | { my $addr = (Email::Address->parse('Bob <bob@example.com>'))[0]; |
|---|
| 251 | ok( $db->add_address($addr, {}), |
|---|
| 252 | 'add_address() from pre-parsed Email::Address'); |
|---|
| 253 | } |
|---|
| 254 | row_ok(table => 'user', |
|---|
| 255 | where => [ id => 3, name => 'Bob', password => '' ], |
|---|
| 256 | label => 'user w/name from pre-parsed Email::Address added'); |
|---|
| 257 | row_ok(table => 'address', |
|---|
| 258 | where => [ user_id => 3, |
|---|
| 259 | local => 'bob', domain => 'example.com' ], |
|---|
| 260 | label => 'address row w/name from pre-parsed Email::Address added'); |
|---|
| 261 | row_ok(table => 'subscription', |
|---|
| 262 | where => [ id => '3', list_id => 1, address_id => 3, |
|---|
| 263 | status => 'SUBSCRIBED', |
|---|
| 264 | moderator => 0, nomail => 0, digest => 0, moderated => 0, |
|---|
| 265 | admin => 0 ], |
|---|
| 266 | label => "third subscription added (from Email::Address)" ); |
|---|
| 267 | |
|---|
| 268 | can_ok($db, 'set_address_options'); |
|---|
| 269 | ok( $db->set_address_options('jdoe@example.com', { name => 'Jonathan Doe' }), |
|---|
| 270 | "name change using set_address_options"); |
|---|
| 271 | row_ok( sql => q{select u.name as name |
|---|
| 272 | from user u left join address a on a.user_id=u.id |
|---|
| 273 | where a.local='jdoe' and a.domain='example.com'}, |
|---|
| 274 | tests => [ name => 'Jonathan Doe' ], |
|---|
| 275 | label => "name changed" ); |
|---|
| 276 | |
|---|
| 277 | ok( $db->set_address_options('jdoe@example.com', { status => 'DELETE' }), |
|---|
| 278 | "deleting second subscriber"); |
|---|
| 279 | row_ok( sql => q{select * from subscription where list_id=1 and address_id=2}, |
|---|
| 280 | results => 0, label => "second subscriber deleted again" ); |
|---|
| 281 | ok( $db->set_address_options('bob@example.com', { status => 'DELETE' }), |
|---|
| 282 | "deleting third subscriber"); |
|---|
| 283 | row_ok( sql => q{select * from subscription where list_id=1 and address_id=3}, |
|---|
| 284 | results => 0, label => "third subscriber deleted again" ); |
|---|
| 285 | |
|---|
| 286 | # See if we can set individual subscription options. One iteration of |
|---|
| 287 | # the loop is good for three tests. |
|---|
| 288 | |
|---|
| 289 | my ($local, $domain) = ('jane.doe', 'example.net'); |
|---|
| 290 | my $address = "$local\@$domain"; |
|---|
| 291 | my $fulladdress = "Jane Doe <$address>"; |
|---|
| 292 | my @options = qw/admin moderator digest nomail moderated/; |
|---|
| 293 | foreach my $i (0 .. $#options) { |
|---|
| 294 | my $opt = $options[$i]; |
|---|
| 295 | ok( $db->add_address($fulladdress, { $opt => 1 }), |
|---|
| 296 | "adding record with option $opt set" ); |
|---|
| 297 | my @check_opts = @options; |
|---|
| 298 | splice(@check_opts, $i, 1); |
|---|
| 299 | row_ok(sql => sprintf(q{select %s |
|---|
| 300 | from subscription s |
|---|
| 301 | left join address a on s.address_id=a.id |
|---|
| 302 | where s.list_id=1 |
|---|
| 303 | and a.local='%s' and a.domain='%s'}, |
|---|
| 304 | join(",", map { "s.$_ as $_" } @options), |
|---|
| 305 | $local, $domain), |
|---|
| 306 | tests => [ $opt => 1, map { $_ => 0 } @check_opts ], |
|---|
| 307 | label => "check if option $opt is set" ); |
|---|
| 308 | ok( $db->set_address_options($address, { status => 'DELETE' }), |
|---|
| 309 | "delete record with option $opt set"); |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | # Now see if we can do the same using set_address_options |
|---|
| 313 | |
|---|
| 314 | ok(!defined $db->set_address_options('NONEXISTENT@example.com', { digest=>1 }), |
|---|
| 315 | "set_address_options w/nonexistent address"); |
|---|
| 316 | |
|---|
| 317 | $db->add_address($fulladdress, {}); |
|---|
| 318 | foreach my $i (0 .. $#options) { |
|---|
| 319 | my $opt = $options[$i]; |
|---|
| 320 | ok( $db->set_address_options($address, { $opt => 1 }), |
|---|
| 321 | "setting option $opt" ); |
|---|
| 322 | my @check_opts = @options; |
|---|
| 323 | splice(@check_opts, $i, 1); |
|---|
| 324 | my $ao = $db->get_address_options($address); |
|---|
| 325 | row_ok(sql => sprintf(q{select %s |
|---|
| 326 | from subscription s |
|---|
| 327 | left join address a on s.address_id=a.id |
|---|
| 328 | where s.list_id=1 |
|---|
| 329 | and a.local='%s' and a.domain='%s'}, |
|---|
| 330 | join(",", map { "s.$_ as $_" } @options), |
|---|
| 331 | $local, $domain), |
|---|
| 332 | tests => [ $opt => 1, map { $_ => 0 } @check_opts ], |
|---|
| 333 | label => "check if option $opt is set"); |
|---|
| 334 | ok( $db->set_address_options($address, { $opt => 0 }), |
|---|
| 335 | "unsetting option $opt" ); |
|---|
| 336 | row_ok(sql => sprintf(q{select %s |
|---|
| 337 | from subscription s |
|---|
| 338 | left join address a on s.address_id=a.id |
|---|
| 339 | where s.list_id=1 |
|---|
| 340 | and a.local='%s' and a.domain='%s'}, |
|---|
| 341 | join(",", map { "s.$_ as $_" } @options), |
|---|
| 342 | $local, $domain), |
|---|
| 343 | tests => [ $opt => 0, map { $_ => 0 } @check_opts ], |
|---|
| 344 | label => "check if option $opt is unset" ); |
|---|
| 345 | } |
|---|
| 346 | |
|---|
| 347 | ok ( $db->set_address_options($fulladdress, { auth => 'abc:def:ghi' }), |
|---|
| 348 | "auth test" ); |
|---|
| 349 | row_ok(sql => sprintf(q{select am.method as method, |
|---|
| 350 | am.par1 as par1, am.par2 as par2 |
|---|
| 351 | from authmethod am |
|---|
| 352 | left join subscription s on am.subscription_id=s.id |
|---|
| 353 | left join address a on s.address_id=a.id |
|---|
| 354 | where s.list_id=1 |
|---|
| 355 | and a.local='%s' and a.domain='%s'}, $local, $domain), |
|---|
| 356 | tests => [ method => 'abc', par1 => 'def', par2 => 'ghi' ], |
|---|
| 357 | label => 'auth test db check'); |
|---|
| 358 | ok ( $db->set_address_options($fulladdress, |
|---|
| 359 | { auth => 'abc:123:456,xyz:987:654' }), |
|---|
| 360 | "auth test (double)"); |
|---|
| 361 | row_ok(sql => sprintf(q{select am.method as method, |
|---|
| 362 | am.par1 as par1, am.par2 as par2 |
|---|
| 363 | from authmethod am |
|---|
| 364 | left join subscription s on am.subscription_id=s.id |
|---|
| 365 | left join address a on s.address_id=a.id |
|---|
| 366 | where s.list_id=1 |
|---|
| 367 | and a.local='%s' and a.domain='%s'}, $local, $domain), |
|---|
| 368 | results => 2, label => 'auth test (double) row count/del check'); |
|---|
| 369 | row_ok(sql => sprintf(q{select am.par1 as par1, am.par2 as par2 |
|---|
| 370 | from authmethod am |
|---|
| 371 | left join subscription s on am.subscription_id=s.id |
|---|
| 372 | left join address a on s.address_id=a.id |
|---|
| 373 | where am.method='abc' and s.list_id=1 |
|---|
| 374 | and a.local='%s' and a.domain='%s'}, $local, $domain), |
|---|
| 375 | tests => [ par1 => '123', par2 => '456' ], |
|---|
| 376 | label => 'auth test (double) db check (1)'); |
|---|
| 377 | row_ok(sql => sprintf(q{select am.par1 as par1, am.par2 as par2 |
|---|
| 378 | from authmethod am |
|---|
| 379 | left join subscription s on am.subscription_id=s.id |
|---|
| 380 | left join address a on s.address_id=a.id |
|---|
| 381 | where am.method='xyz' and s.list_id=1 |
|---|
| 382 | and a.local='%s' and a.domain='%s'}, $local, $domain), |
|---|
| 383 | tests => [ par1 => '987', par2 => '654' ], |
|---|
| 384 | label => 'auth test (double) db check (2)'); |
|---|
| 385 | |
|---|
| 386 | ok ( $db->set_address_options($fulladdress, { auth => '' }), "auth del test"); |
|---|
| 387 | row_ok(sql => sprintf(q{select am.method as method, |
|---|
| 388 | am.par1 as par1, am.par2 as par2 |
|---|
| 389 | from authmethod am |
|---|
| 390 | left join subscription s on am.subscription_id=s.id |
|---|
| 391 | left join address a on s.address_id=a.id |
|---|
| 392 | where s.list_id=1 |
|---|
| 393 | and a.local='%s' and a.domain='%s'}, $local, $domain), |
|---|
| 394 | results => 0, |
|---|
| 395 | label => 'auth del test row count/del check'); |
|---|
| 396 | |
|---|
| 397 | # Check the result of get_address_options |
|---|
| 398 | |
|---|
| 399 | my $ref = { |
|---|
| 400 | status => 'SUBSCRIBED', name => 'Jane Doe', auth => '', id => '2', |
|---|
| 401 | }; |
|---|
| 402 | $ref->{$_} = 0 foreach (@options); |
|---|
| 403 | |
|---|
| 404 | can_ok($db, 'get_address_options'); |
|---|
| 405 | my $aa = (Email::Address->parse($address))[0]; |
|---|
| 406 | foreach my $a ($fulladdress, ucfirst($aa), $aa) { |
|---|
| 407 | foreach my $i (0 .. $#options) { |
|---|
| 408 | $db->set_address_options($a, { $options[$i] => 1 }); |
|---|
| 409 | my $opts; |
|---|
| 410 | $ref->{$options[$i]} = 1; |
|---|
| 411 | ok( $opts = $db->get_address_options($a), "getting address options" ); |
|---|
| 412 | is_deeply($opts, $ref, "option $options[$i] set"); |
|---|
| 413 | $db->set_address_options($a, { $options[$i] => 0 }); |
|---|
| 414 | $ref->{$options[$i]} = 0; |
|---|
| 415 | } |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | $db->set_address_options($address, { auth => 'abc:123:456,xyz:987:654' }); |
|---|
| 419 | my $opts = $db->get_address_options($address); |
|---|
| 420 | is($opts->{auth}, 'abc:123:456,xyz:987:654', "get_address_options auth check"); |
|---|
| 421 | |
|---|
| 422 | $db->set_address_options($address, { status => 'DELETE' }); |
|---|
| 423 | |
|---|
| 424 | |
|---|
| 425 | # Check the result of get_addresses |
|---|
| 426 | |
|---|
| 427 | my @crew = ( |
|---|
| 428 | [ 'emil', 'example.com', 'Emil Schmidt', { digest => 1 }, 0 ], |
|---|
| 429 | [ 'hans', 'example.net', 'Hans Huber', { nomail => 1 }, 0 ], |
|---|
| 430 | [ 'trude', 'example.com', 'Trude Schulz', {}, 1 ], |
|---|
| 431 | [ 'liese', 'example.net', 'Liese Huber', { nomail => 1 }, 1 ], |
|---|
| 432 | [ 'susi', 'example.com', 'Susi Sorglos', {}, 0 ], |
|---|
| 433 | [ 'fritz', 'example.net', 'Fritz Friedlich', { moderator => 1 }, 0 ], |
|---|
| 434 | ); |
|---|
| 435 | |
|---|
| 436 | foreach my $cref (@crew) { |
|---|
| 437 | my ($local, $domain, $name, $optref, $bouncing) = @$cref; |
|---|
| 438 | $db->add_address("$name <$local\@$domain>", $optref); |
|---|
| 439 | $db->set_address_options("$local\@$domain", { status => 'BOUNCING' }) |
|---|
| 440 | if $bouncing; |
|---|
| 441 | } |
|---|
| 442 | |
|---|
| 443 | can_ok($db, 'get_addresses'); |
|---|
| 444 | my @result = $db->get_addresses; |
|---|
| 445 | is(@result, 7, "get_addresses with no argument"); |
|---|
| 446 | is_deeply(\@result, [ 'emil@example.com', |
|---|
| 447 | 'hugo@example.com', |
|---|
| 448 | 'susi@example.com', |
|---|
| 449 | 'trude@example.com', |
|---|
| 450 | 'fritz@example.net', |
|---|
| 451 | 'hans@example.net', |
|---|
| 452 | 'liese@example.net' ], "get_addresses result check"); |
|---|
| 453 | @result = $db->get_addresses('*@example.net'); |
|---|
| 454 | is(@result, 3, "get_addresses with address pattern"); |
|---|
| 455 | @result = $db->get_addresses('*', { digest => 1 }); |
|---|
| 456 | is(@result, 1, "get_addresses for digest subscribers"); |
|---|
| 457 | @result = $db->get_addresses('*', { digest => 0 }); |
|---|
| 458 | is(@result, 6, "get_addresses for regular subscribers"); |
|---|
| 459 | @result = $db->get_addresses('*', { nomail => 1 }); |
|---|
| 460 | is(@result, 2, "get_addresses for nomail subscribers"); |
|---|
| 461 | @result = $db->get_addresses('*', { nomail => 0 }); |
|---|
| 462 | is(@result, 5, "get_addresses for no-nomail subscribers"); |
|---|
| 463 | @result = $db->get_addresses('*', { recipient => 1 }); |
|---|
| 464 | is(@result, 4, "get addresses for recipient subscribers"); |
|---|
| 465 | @result = $db->get_addresses('*', { bouncing => 1 }); |
|---|
| 466 | is(@result, 2, "get addresses for bouncing subscribers"); |
|---|
| 467 | @result = $db->get_addresses('*', { bouncing => 1, nomail => 1 }); |
|---|
| 468 | is(@result, 1, "get addresses for bouncing nomail subscribers (AND test)"); |
|---|
| 469 | @result = $db->get_addresses('*', { moderator => 1 }); |
|---|
| 470 | is(@result, 1, "get addresses for moderators"); |
|---|
| 471 | |
|---|
| 472 | @result = $db->get_addresses('*', { order => 'address' }); |
|---|
| 473 | is_deeply(\@result, [ 'emil@example.com', |
|---|
| 474 | 'fritz@example.net', |
|---|
| 475 | 'hans@example.net', |
|---|
| 476 | 'hugo@example.com', |
|---|
| 477 | 'liese@example.net', |
|---|
| 478 | 'susi@example.com', |
|---|
| 479 | 'trude@example.com' ], |
|---|
| 480 | "get_addresses sort check (address)"); |
|---|
| 481 | |
|---|
| 482 | @result = $db->get_addresses('*', { order => 'domain' }); |
|---|
| 483 | is_deeply(\@result, [ 'emil@example.com', |
|---|
| 484 | 'hugo@example.com', |
|---|
| 485 | 'susi@example.com', |
|---|
| 486 | 'trude@example.com', |
|---|
| 487 | 'fritz@example.net', |
|---|
| 488 | 'hans@example.net', |
|---|
| 489 | 'liese@example.net' ], |
|---|
| 490 | "get_addresses sort check (domain)"); |
|---|
| 491 | |
|---|
| 492 | # confirmation database |
|---|
| 493 | |
|---|
| 494 | { |
|---|
| 495 | can_ok($db, 'set_confirm'); |
|---|
| 496 | can_ok($db, 'check_confirm'); |
|---|
| 497 | can_ok($db, 'clear_confirm'); |
|---|
| 498 | ok ($db->set_confirm('foo@example.com', 'ABCD1234', $the_time+5, 'Data'), |
|---|
| 499 | "set_confirm test"); |
|---|
| 500 | ok (! defined $db->check_confirm('foo@example.com', 'XYZQ6789'), |
|---|
| 501 | "check_confirm with bad cookie"); |
|---|
| 502 | ok (! defined $db->check_confirm('bar@example.com', 'ABCD1234'), |
|---|
| 503 | "check_confirm with non-existing address"); |
|---|
| 504 | { my $data = $db->check_confirm('foo@example.com', 'ABCD1234'); |
|---|
| 505 | is ($data, 'Data', "check_confirm with correct parameters"); |
|---|
| 506 | } |
|---|
| 507 | $the_time += 10; |
|---|
| 508 | ok (! defined $db->check_confirm('foo@example.com', 'ABCD1234'), |
|---|
| 509 | "confirm time limit exceeded"); |
|---|
| 510 | $db->clear_confirm('foo@example.com', 'XYZQ6789'); |
|---|
| 511 | row_ok(sql => q{select * |
|---|
| 512 | from confirmation c |
|---|
| 513 | left join subscription s on c.subscription_id=s.id |
|---|
| 514 | left join address a on s.address_id=a.id |
|---|
| 515 | where a.local='foo' and a.domain='example.com' |
|---|
| 516 | and c.cookie='ABCD1234'}, |
|---|
| 517 | results => 1, label => 'clear_confirm with wrong cookie'); |
|---|
| 518 | $db->clear_confirm('bar@example.com', 'ABCD1234'); |
|---|
| 519 | row_ok(sql => q{select * |
|---|
| 520 | from confirmation c |
|---|
| 521 | left join subscription s on c.subscription_id=s.id |
|---|
| 522 | left join address a on s.address_id=a.id |
|---|
| 523 | where a.local='foo' and a.domain='example.com' |
|---|
| 524 | and c.cookie='ABCD1234'}, |
|---|
| 525 | results => 1, label => 'clear_confirm with wrong address'); |
|---|
| 526 | $db->clear_confirm('foo@example.com', 'ABCD1234'); |
|---|
| 527 | row_ok(sql => q{select * |
|---|
| 528 | from confirmation c |
|---|
| 529 | left join subscription s on c.subscription_id=s.id |
|---|
| 530 | left join address a on s.address_id=a.id |
|---|
| 531 | where a.local='foo' and a.domain='example.com' |
|---|
| 532 | and c.cookie='ABCD1234'}, |
|---|
| 533 | results => 0, label => 'clear_confirm with correct parameters'); |
|---|
| 534 | } |
|---|
| 535 | |
|---|
| 536 | # bounce database |
|---|
| 537 | |
|---|
| 538 | can_ok($db, 'log_bounce'); |
|---|
| 539 | can_ok($db, 'get_bounces'); |
|---|
| 540 | can_ok($db, 'get_bounce_addresses'); |
|---|
| 541 | can_ok($db, 'clear_bounces'); |
|---|
| 542 | row_ok(sql => "select * from bounce", results => 0, |
|---|
| 543 | label => "bounce database must be empty"); |
|---|
| 544 | $db->log_bounce('susi@example.com', 1234, 10); |
|---|
| 545 | row_ok(sql => "select * from bounce", results => 1, |
|---|
| 546 | label => "log_bounce 1"); |
|---|
| 547 | $db->log_bounce('hugo@example.com', 1234, 10); |
|---|
| 548 | row_ok(sql => "select * from bounce", results => 2, |
|---|
| 549 | label => "log_bounce 2"); |
|---|
| 550 | { my $ref = $db->get_bounces('susi@example.com', 0); |
|---|
| 551 | is(@$ref, 1, "number of bounces returned by get_bounces()"); |
|---|
| 552 | my $aref = $$ref[0]; |
|---|
| 553 | is($$aref[1], 10, "bounce score returned by get_bounces()"); |
|---|
| 554 | is($$aref[2], 1234, "bounce message returned by get_bounces()"); |
|---|
| 555 | $db->log_bounce('susi@example.com', 1235, 10); |
|---|
| 556 | row_ok(sql => "select * from bounce", results => 3, |
|---|
| 557 | label => "log_bounce 3"); |
|---|
| 558 | $ref = $db->get_bounces('susi@example.com', 0); |
|---|
| 559 | is(@$ref, 2, "number of bounces returned by get_bounces()"); |
|---|
| 560 | $aref = $$ref[0]; |
|---|
| 561 | is($$aref[1], 10, "bounce score returned by get_bounces()"); |
|---|
| 562 | is($$aref[2], 1235, "bounce message returned by get_bounces()"); |
|---|
| 563 | $aref = $$ref[1]; |
|---|
| 564 | is($$aref[1], 10, "bounce score returned by get_bounces()"); |
|---|
| 565 | is($$aref[2], 1234, "bounce message returned by get_bounces()"); |
|---|
| 566 | my @addr = $db->get_bounce_addresses(); |
|---|
| 567 | is(scalar(@addr), 2, "result count of get_bounce_addresses()"); |
|---|
| 568 | ok($addr[0] eq 'hugo@example.com' && $addr[1] eq 'susi@example.com', |
|---|
| 569 | "result of get_bounce_addresses()"); |
|---|
| 570 | @addr = $db->get_bounce_addresses('*'); |
|---|
| 571 | is(scalar(@addr), 2, "result count of get_bounce_addresses('*')"); |
|---|
| 572 | ok($addr[0] eq 'hugo@example.com' && $addr[1] eq 'susi@example.com', |
|---|
| 573 | "result of get_bounce_addresses('*')"); |
|---|
| 574 | @addr = $db->get_bounce_addresses('susi@*'); |
|---|
| 575 | is(scalar(@addr), 1, "result count of get_bounce_addresses('foo\@*')"); |
|---|
| 576 | ok($addr[0] eq 'susi@example.com', "result of get_bounce_adresses('foo\@*')"); |
|---|
| 577 | $db->clear_bounces('susi@example.com'); |
|---|
| 578 | row_ok(sql => "select * from bounce", results => 1, |
|---|
| 579 | label => "row count after clear_bounces('foo')"); |
|---|
| 580 | } |
|---|
| 581 | |
|---|
| 582 | # bounce warnings |
|---|
| 583 | |
|---|
| 584 | can_ok($db, 'log_bounce_warning'); |
|---|
| 585 | can_ok($db, 'last_bounce_warning'); |
|---|
| 586 | can_ok($db, 'clear_bounce_warnings'); |
|---|
| 587 | $the_time = 1000000000; |
|---|
| 588 | row_ok(sql => 'select * from bouncewarning', |
|---|
| 589 | results => 0, label => 'check bouncewarning table is empty'); |
|---|
| 590 | $db->log_bounce_warning('susi@example.com'); |
|---|
| 591 | row_ok(sql => 'select * from bouncewarning', |
|---|
| 592 | results => 1, label => 'check database after log_bounce_warning() 1'); |
|---|
| 593 | $the_time += 10; |
|---|
| 594 | $db->log_bounce_warning('susi@example.com'); |
|---|
| 595 | row_ok(sql => 'select * from bouncewarning', |
|---|
| 596 | results => 2, label => 'check database after log_bounce_warning() 2'); |
|---|
| 597 | $db->log_bounce_warning('hugo@example.com'); |
|---|
| 598 | row_ok(sql => 'select * from bouncewarning', |
|---|
| 599 | results => 3, label => 'check database after log_bounce_warning() 3'); |
|---|
| 600 | { my ($count, $last) = $db->last_bounce_warning('susi@example.com'); |
|---|
| 601 | ok($count == 2 && $last == $the_time, "check last_bounce_warning() result"); |
|---|
| 602 | $db->clear_bounce_warnings('susi@example.com'); |
|---|
| 603 | row_ok(sql => 'select * from bouncewarning', |
|---|
| 604 | results => 1, label => 'check database after clear_bounce_warning()'); |
|---|
| 605 | } |
|---|
| 606 | |
|---|
| 607 | |
|---|
| 608 | __END__ |
|---|
| 609 | archive.directory |
|---|
| 610 | bounce.bucketcount |
|---|
| 611 | bounce.bucketsize |
|---|
| 612 | bounce.score.hard |
|---|
| 613 | bounce.score.soft |
|---|
| 614 | bounce.threshold |
|---|
| 615 | bounce.unknownaction |
|---|
| 616 | digests.enable |
|---|
| 617 | digests.maxperiod |
|---|
| 618 | digests.maxsize |
|---|
| 619 | lancelot.templatedirs |
|---|
| 620 | list.address |
|---|
| 621 | list.addressdb |
|---|
| 622 | list.language |
|---|
| 623 | ll.c1 |
|---|
| 624 | ll.c2 |
|---|
| 625 | mail.delimiter |
|---|
| 626 | mail.forcereplyto |
|---|
| 627 | mail.listheaders |
|---|
| 628 | mail.policy.explicitaddress |
|---|
| 629 | mail.policy.subscribersonly |
|---|
| 630 | mail.replyto |
|---|
| 631 | mail.subjecttag |
|---|
| 632 | mail.workflow.bounce |
|---|
| 633 | mail.workflow.config |
|---|
| 634 | mail.workflow.help |
|---|
| 635 | mail.workflow.owner |
|---|
| 636 | mail.workflow.submit |
|---|
| 637 | mail.workflow.subscribe |
|---|
| 638 | mail.workflow.unsubscribe |
|---|
| 639 | mod.aquorum |
|---|
| 640 | mod.enable |
|---|
| 641 | mod.rquorum |
|---|
| 642 | smtp.debug |
|---|
| 643 | smtp.maxrecipients |
|---|
| 644 | smtp.port |
|---|
| 645 | smtp.server |
|---|
| 646 | smtp.timeout |
|---|
| 647 | subscribe.confirm |
|---|
| 648 | subscribe.confirmdefault |
|---|
| 649 | subscribe.digestchange |
|---|
| 650 | subscribe.digestdefault |
|---|
| 651 | subscribe.moderateddefault |
|---|
| 652 | subscribe.nomailchange |
|---|
| 653 | subscribe.nomaildefault |
|---|
| 654 | subscribe.type |
|---|
| 655 | subscribe.welcome |
|---|
| 656 | unsubscribe.confirm |
|---|
| 657 | unsubscribe.confirmdefault |
|---|
| 658 | unsubscribe.goodbye |
|---|