summaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
authorAlexander Sulfrian <alex@spline.inf.fu-berlin.de>2016-06-21 02:42:25 +0200
committerAlexander Sulfrian <alex@spline.inf.fu-berlin.de>2016-06-21 02:42:25 +0200
commit339312c92a71a0943ae34aab27b1026bb3479d0d (patch)
treecea49efa50ec436b517a25dc1d1ff90f575e2f18 /t
parentd9ba41806745b830fd229b4cbcd8b5386203af27 (diff)
downloadsrs-339312c92a71a0943ae34aab27b1026bb3479d0d.tar.gz
srs-339312c92a71a0943ae34aab27b1026bb3479d0d.tar.bz2
srs-339312c92a71a0943ae34aab27b1026bb3479d0d.zip
Make subclasses of Net::Server
Spline::Socketmap is now a subclasses of Net::Server and Spline::Socketmap::Srs is a subclass of Spline::Socketmap. This way the Srs stuff is completly independent of the postfix-socketmap protocol handling. The config is located in the instances and configurable with Net::Server command line options or config file.
Diffstat (limited to 't')
-rw-r--r--t/netstring.t44
-rw-r--r--t/socketmap.t132
-rw-r--r--t/srs.t184
3 files changed, 281 insertions, 79 deletions
diff --git a/t/netstring.t b/t/netstring.t
new file mode 100644
index 0000000..de0b61e
--- /dev/null
+++ b/t/netstring.t
@@ -0,0 +1,44 @@
+use strict;
+use warnings;
+
+use Test::More tests => 11;
+use Test::Exception;
+
+BEGIN {
+ use_ok 'Spline::Socketmap', qw(
+ netstring_read
+ netstring_write
+ ) or BAIL_OUT;
+}
+
+sub output($) {
+ my $data = shift;
+
+ my $output;
+ open(my $fh, '>', \$output);
+ netstring_write($fh, $data);
+ return $output;
+}
+
+sub input($) {
+ my $data = shift;
+
+ open(my $fh, '<', \$data);
+ return netstring_read($fh);
+}
+
+# Netstring output
+is(output('test'), '4:test,', 'Netstring output');
+is(output(''), '0:,', 'Empty netstring output');
+is(output('. '), '2:. ,', 'Preserve spaces');
+
+# Netstring input
+is(input('4:test,'), 'test', 'Basic netstring input');
+is(input('0:,'), '', 'Empty netstring input');
+throws_ok { input('4:test') } qr/, missing/, 'Missing final ,';
+throws_ok { input('5:test') } qr/4 of 5 bytes/, 'Data too short';
+throws_ok { input('4test') } qr/Invalid length/, 'Format error';
+throws_ok { input('') } qr/Cannot read .* length/, 'Empty input';
+throws_ok { netstring_read('') } qr/Filehandle required/, 'No filehandle';
+
+# vim: set et ts=4:
diff --git a/t/socketmap.t b/t/socketmap.t
new file mode 100644
index 0000000..a788663
--- /dev/null
+++ b/t/socketmap.t
@@ -0,0 +1,132 @@
+use strict;
+use warnings;
+
+use Test::More tests => 19;
+use Test::Exception;
+
+BEGIN {
+ use_ok 'Spline::Socketmap', qw(
+ lookup
+ handle_request
+ socketmap_protocol
+ process_request
+ ) or BAIL_OUT;
+}
+
+# Default handler
+throws_ok { lookup(undef, 'map', 'key') } qr/Not implemented/, 'No handler';
+
+my $socketmap = new Spline::Socketmap();
+
+# Parsing socketmap input
+my @args;
+{
+ no warnings 'redefine';
+ local *Spline::Socketmap::lookup = sub { shift; @args = @_; return };
+ is($socketmap->handle_request('map key with whitespace'), undef,
+ 'Protocol parsed');
+ is_deeply(\@args, ['map', 'key with whitespace'], 'Parsing with whitespace');
+}
+
+{
+ no warnings 'redefine';
+ local *Spline::Socketmap::lookup = sub { return 'OK test' };
+ is(handle_request($socketmap, 'map key'), 'OK test', 'Result passed');
+}
+
+# Socketmap protocol handling
+{
+ no warnings 'redefine';
+ local *Spline::Socketmap::lookup = sub { };
+ is($socketmap->socketmap_protocol('map key'), undef, 'Pass undef return value');
+}
+
+{
+ no warnings 'redefine';
+ local *Spline::Socketmap::lookup = sub { shift; shift; return shift };
+ is($socketmap->socketmap_protocol('map key'), 'key', 'Pass return value');
+}
+
+{
+ no warnings 'redefine';
+ local *Spline::Socketmap::lookup = sub { sleep 2 };
+ $socketmap->{server}->{timeout} = 1;
+
+ is($socketmap->socketmap_protocol('map key'), 'TEMP Timeout',
+ 'Temporary error on timeout');
+}
+
+{
+ no warnings 'redefine';
+ local *Spline::Socketmap::lookup = sub { die 'Other error' };
+ like($socketmap->socketmap_protocol('map key'), qr/TEMP Other error/,
+ 'Temporary error on die');
+}
+
+# process_request (Net::Server)
+my ($input, $output, $log);
+my $dummy = {};
+{
+ package Dummy;
+ use base 'Spline::Socketmap';
+ sub recv { return $input }
+ sub send { shift; $output = shift }
+ sub log { shift; shift; $log = shift }
+ bless $dummy, 'Dummy';
+}
+
+{
+ no warnings 'redefine';
+ local *Dummy::socketmap_protocol = sub { shift; return &{shift()} };
+
+ $input = 'OK test';
+ process_request($dummy);
+ is($output, 'OK test', 'Send output if defined (ok)');
+
+ $input = 'NOTFOUND ';
+ process_request($dummy);
+ is($output, 'NOTFOUND ', 'Send output if defined (notfound)');
+}
+
+{
+ no warnings 'redefine';
+ local *Dummy::socketmap_protocol = sub { };
+
+ process_request($dummy);
+ like($output, qr/TEMP .* error/, 'Temporary error if result is undef');
+}
+
+{
+ no warnings 'redefine';
+ local *Dummy::recv = sub { sleep 10 };
+ $dummy->{server}->{timeout} = 1;
+
+ lives_ok { process_request($dummy) } 'Temporary error with hanging input';
+ like($output, qr/TEMP Timeout/, 'Timeout on hanging input');
+}
+
+# recv
+{
+ my $recv_data;
+ open(my $fh, '<', \$recv_data);
+ local *STDIN = $fh;
+
+ $log = undef;
+ $recv_data = '7:OK test,';
+ is(Spline::Socketmap::recv($dummy), 'OK test', 'Receive works');
+ is($log, 'OK test', 'Log data after receiving');
+}
+
+# send
+{
+ my $send_data;
+ open(my $fh, '>', \$send_data);
+ local *STDOUT = $fh;
+
+ $log = undef;
+ lives_ok { Spline::Socketmap::send($dummy, 'OK test') } 'Sending works';
+ is($send_data, '7:OK test,', 'Send data in netstring format');
+ is($log, 'OK test', 'Log data before sending');
+}
+
+# vim: set et ts=4:
diff --git a/t/srs.t b/t/srs.t
index a1c8104..b6482b4 100644
--- a/t/srs.t
+++ b/t/srs.t
@@ -1,30 +1,16 @@
use strict;
use warnings;
-use Test::More tests => 39;
+use Test::More tests => 35;
use Test::Exception;
use Test::MockModule;
BEGIN {
use_ok 'Spline::Srs', qw(
- config_set
- config_get
check_exclude
- srs_forward
- srs_reverse
) or BAIL_OUT;
}
-# Test config
-my $old_value = config_get('hash_length');
-isnt($old_value, undef, 'Config value exists');
-config_set('hash_length', $old_value+1);
-isnt(config_get('hash_length'), $old_value, 'Config changed');
-
-is(config_get('invalid'), undef, 'Invalid config value is undef');
-config_set('invalid', 'test');
-is(config_get('invalid'), undef, 'Cannot set invalid config values');
-
# Testing ignores
is(check_exclude('test@example.com',['example.com']), 1, 'Ignore matching domain');
is(check_exclude('test@example.de', ['example.com']), 0, 'Do not ignore non-matching domain');
@@ -32,80 +18,120 @@ is(check_exclude('test@test.example.com', ['example.com']), 0, 'Do not ignore su
is(check_exclude('test@test.example.com', ['.example.com']), 1, 'Ignore sub-domain if requested');
# Try without config
-throws_ok { srs_forward('something@example.com') } qr/configure.*secret/, 'Secret required';
-config_set('secret', 'abc');
-throws_ok { srs_forward('something@example.com') } qr/configure.*secret/, 'Long secret required';
-config_set('secret', '12345678901234567890');
-throws_ok { srs_forward('something@example.com') } qr/configure.*alias/, 'Alias required';
-config_set('alias', 'something');
-lives_ok { srs_forward('something@example.com') } 'Config complete';
+my %config = ();
+throws_ok { new Spline::Srs(\%config) } qr/configure.*secret/, 'Secret required';
+$config{secret} = 'abc';
+throws_ok { new Spline::Srs(\%config) } qr/configure.*secret/, 'Long secret required';
+$config{secret} = '12345678901234567890';
+throws_ok { new Spline::Srs(\%config) } qr/configure.*alias/, 'Alias required';
+$config{alias} = 'something';
+lives_ok { new Spline::Srs(\%config) } 'Config complete';
# Testing ignores with config
-config_set('alias', 'domain.invalid');
-is(srs_forward('test@domain.invalid'), 'test@domain.invalid', 'Exclude alias domain by default');
-isnt(srs_forward('test@example.com'), 'test@example.com', 'Not excluding something other');
+$config{alias} = 'domain.invalid';
+{
+ my $srs = new Spline::Srs(\%config);
+ is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
+ 'Exclude alias domain by default');
+ isnt($srs->forward('test@example.com'), 'test@example.com',
+ 'Not excluding something other');
+}
-config_set('excludes', ['example.com']);
-is(srs_forward('test@domain.invalid'), 'test@domain.invalid', 'Exclude alias domain by default');
-is(srs_forward('test@example.com'), 'test@example.com', 'Exclude is working');
-isnt(srs_forward('test@test.example.com'), 'test@test.example.com', 'Excluded domain should not match subdomain');
+$config{excludes} = ['example.com'];
+{
+ my $srs = new Spline::Srs(\%config);
+ is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
+ 'Exclude alias domain by default');
+ is($srs->forward('test@example.com'), 'test@example.com',
+ 'Exclude is working');
+ isnt($srs->forward('test@test.example.com'), 'test@test.example.com',
+ 'Excluded domain should not match subdomain');
+}
-config_set('excludes', ['.example.com']);
-is(srs_forward('test@domain.invalid'), 'test@domain.invalid', 'Exclude alias domain by default');
-is(srs_forward('test@test.example.com'), 'test@test.example.com', 'Exclude subdomains');
-isnt(srs_forward('test@example.com'), 'test@example.com', 'Excluded subdomain should not match domain');
+$config{excludes} = ['.example.com'];
+{
+ my $srs = new Spline::Srs(\%config);
+ is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
+ 'Exclude alias domain by default');
+ is($srs->forward('test@test.example.com'), 'test@test.example.com',
+ 'Exclude subdomains');
+ isnt($srs->forward('test@example.com'), 'test@example.com',
+ 'Excluded subdomain should not match domain');
+}
-config_set('excludes', ['example.com', '.example.com']);
-is(srs_forward('test@domain.invalid'), 'test@domain.invalid', 'Exclude alias domain by default');
-is(srs_forward('test@test.example.com'), 'test@test.example.com', 'Multiple excludes');
-is(srs_forward('test@example.com'), 'test@example.com', 'Multiple excludes');
+$config{excludes} = ['example.com', '.example.com'];
+{
+ my $srs = new Spline::Srs(\%config);
+ is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
+ 'Exclude alias domain by default');
+ is($srs->forward('test@test.example.com'), 'test@test.example.com',
+ 'Multiple excludes');
+ is($srs->forward('test@example.com'), 'test@example.com',
+ 'Multiple excludes');
+}
# SRS Forward
-config_set('secret', '12345678901234567890');
-config_set('alias', 'domain.invalid');
-config_set('excludes', undef);
-my $result = srs_forward('alex@example.com');
-isnt($result, undef, 'Not undef');
-isnt($result, 'alex@example.com', 'Not rewritten');
-like($result, qr/^SRS0[+=-]/, 'SRS0 Prefix');
-like($result, qr/\@domain\.invalid$/, 'Rewrite to alias-Domain');
-
-# Check SRS forward an backwards
-my $address = 'alex@example.com';
-my $srs_address = srs_forward($address);
-isnt($srs_address, undef, 'Forward works');
-isnt($srs_address, $address, 'Forward works');
-is(srs_reverse($srs_address), $address, 'Reverse maps back to original');
-
-# Some checks requires a fixed time for deterministic output
+$config{secret} = '12345678901234567890';
+$config{alias} = 'domain.invalid';
+$config{excludes} = undef;
+$config{hash_length} = 6;
my ($old_srs_address, $broken);
{
- no warnings 'redefine';
- my $timestamp_create = \&Mail::SRS::timestamp_create;
- local *Mail::SRS::timestamp_create = sub {
- my $self = shift;
- $timestamp_create->($self, 1);
- };
-
- $old_srs_address = srs_forward($address);
- isnt($old_srs_address, $srs_address, 'Time should have changed');
- is($old_srs_address, 'SRS0=R0OuN1=AA=example.com=alex@domain.invalid', 'exakt match with fixed time');
-
- # Hash with broken chars
- $broken = srs_forward('nk@example.com');
- is($broken, 'SRS0=s/6g+P=AA=example.com=nk@domain.invalid', 'srs address is as expected');
+ my $srs = new Spline::Srs(\%config);
+ my $result = $srs->forward('alex@example.com');
+ isnt($result, undef, 'Not undef');
+ isnt($result, 'alex@example.com', 'Not rewritten');
+ like($result, qr/^SRS0[+=-]/, 'SRS0 Prefix');
+ like($result, qr/\@domain\.invalid$/, 'Rewrite to alias-Domain');
+
+ # Check SRS forward an backwards
+ my $address = 'alex@example.com';
+ my $srs_address = $srs->forward($address);
+ isnt($srs_address, undef, 'Forward works');
+ isnt($srs_address, $address, 'Forward works');
+ is($srs->reverse($srs_address), $address, 'Reverse maps back to original');
+
+ # Some checks requires a fixed time for deterministic output
+ {
+ no warnings 'redefine';
+ my $timestamp_create = \&Mail::SRS::timestamp_create;
+ local *Mail::SRS::timestamp_create = sub {
+ my $self = shift;
+ $timestamp_create->($self, 1);
+ };
+
+ $old_srs_address = $srs->forward($address);
+ isnt($old_srs_address, $srs_address, 'Time should have changed');
+ is($old_srs_address, 'SRS0=R0OuN1=AA=example.com=alex@domain.invalid',
+ 'exakt match with fixed time');
+
+ # Hash with broken chars
+ $broken = $srs->forward('nk@example.com');
+ is($broken, 'SRS0=s/6g+P=AA=example.com=nk@domain.invalid',
+ 'srs address is as expected');
+ }
+
+ # Timestamp should timeout (but old timestamps can be ignored)
+ throws_ok { $srs->reverse($old_srs_address) } qr/Invalid timestamp/,
+ 'Timestamp should be to old';
}
-# Timestamp should timeout (but old timestamps can be ignored)
-throws_ok { srs_reverse($old_srs_address) } qr/Invalid timestamp/, 'Timestamp should be to old';
-config_set('ignore_time', 1);
-lives_ok { srs_reverse($old_srs_address) } 'Ignore old timestamp';
-
-# libsrs_alt uses different base64 chars and should also work
-lives_ok { srs_reverse($broken) } 'Reverse with special chars';
-$broken = 'SRS0=s.6g_P=AA=example.com=nk@domain.invalid';
-throws_ok { srs_reverse($broken) } qr/Invalid hash/, 'Reverse with legacy chars';
-config_set('srsalt_fallback', 1);
-is(srs_reverse($broken), 'nk@example.com', 'Reverse with legacy chars');
+$config{'ignore_time'} = 1;
+{
+ my $srs = new Spline::Srs(\%config);
+ lives_ok { $srs->reverse($old_srs_address) } 'Ignore old timestamp';
+
+ # libsrs_alt uses different base64 chars and should also work
+ lives_ok { $srs->reverse($broken) } 'Reverse with special chars';
+ $broken = 'SRS0=s.6g_P=AA=example.com=nk@domain.invalid';
+ throws_ok { $srs->reverse($broken) } qr/Invalid hash/,
+ 'Reverse with legacy chars';
+}
+
+$config{'srsalt_fallback'} = 1;
+{
+ my $srs = new Spline::Srs(\%config);
+ is($srs->reverse($broken), 'nk@example.com', 'Reverse with legacy chars');
+}
# vim: set et ts=4: