diff options
author | Russ Allbery <rra@stanford.edu> | 2007-09-14 23:18:48 +0000 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2007-09-14 23:18:48 +0000 |
commit | f95a894b439402ec7982851e37ca1761143668db (patch) | |
tree | f53e8c9a70de8bdbd729def0eacbf3475d4a262e /tests/server | |
parent | b342f26f16ae3dbbc6ad1ac1ed3bc318defeac40 (diff) |
Add a test suite for the backend driver program.
Diffstat (limited to 'tests/server')
-rw-r--r-- | tests/server/backend-t.in | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/tests/server/backend-t.in b/tests/server/backend-t.in new file mode 100644 index 0000000..c509fff --- /dev/null +++ b/tests/server/backend-t.in @@ -0,0 +1,274 @@ +#!/usr/bin/perl -w +# $Id$ +# +# t/backend.t -- Tests for the wallet-backend dispatch code. + +use strict; +use IO::String; +use Test::More tests => 710; + +# Create a dummy class for Wallet::Server that prints what method was called +# with its arguments and returns data for testing. +package Wallet::Server; + +use vars qw($error $okay); +$error = 0; +$okay = 0; + +sub error { + if ($okay) { + $okay = 0; + return undef; + } else { + $error++; + return "error count $error\n"; + } +} + +sub new { shift; print "new @_\n"; return bless ({}, 'Wallet::Server') } +sub create { shift; print "create @_\n"; ($_[0] eq 'error') ? undef : 1 } +sub destroy { shift; print "destroy @_\n"; ($_[0] eq 'error') ? undef : 1 } +sub store { shift; print "store @_\n"; ($_[0] eq 'error') ? undef : 1 } + +sub acl_add + { shift; print "acl_add @_\n"; ($_[0] eq 'error') ? undef : 1 } +sub acl_create + { shift; print "acl_create @_\n"; ($_[0] eq 'error') ? undef : 1 } +sub acl_destroy + { shift; print "acl_destroy @_\n"; ($_[0] eq 'error') ? undef : 1 } +sub acl_remove + { shift; print "acl_remove @_\n"; ($_[0] eq 'error') ? undef : 1 } +sub acl_rename + { shift; print "acl_rename @_\n"; ($_[0] eq 'error') ? undef : 1 } + +sub acl { + shift; + print "acl @_\n"; + if ($_[0] eq 'error') { + return undef; + } elsif ($_[1] eq 'empty') { + $okay = 1; + return undef; + } else { + return 'acl'; + } +} + +sub expires { + shift; + print "expires @_\n"; + if ($_[0] eq 'error') { + return undef; + } elsif ($_[1] eq 'empty') { + $okay = 1; + return undef; + } else { + return 'expires'; + } +} + +sub get { + shift; + print "get @_\n"; + return if $_[0] eq 'error'; + return 'get'; +} + +sub owner { + shift; + print "owner @_\n"; + if ($_[0] eq 'error') { + return undef; + } elsif ($_[1] eq 'empty') { + $okay = 1; + return undef; + } else { + return 'owner'; + } +} + +sub show { + shift; + print "show @_\n"; + return if $_[0] eq 'error'; + return 'show'; +} + +# Back to the main package and the actual test suite. Lie about whether the +# Wallet::Server package has already been loaded. +package main; +$INC{'Wallet/Server.pm'} = 'FAKE'; +eval { do '@abs_top_srcdir@/server/wallet-backend' }; + +# Run the wallet backend. This fun hack takes advantage of the fact that the +# wallet backend is written in Perl so that we can substitute our own +# Wallet::Server class. +sub run_backend { + my (@args) = @_; + my $result; + my $output = IO::String->new (\$result); + $output->autoflush (1); + select $output; + eval { command (@args) }; + my $error = $@; + select STDOUT; + return ($result, $error); +} + +# Now for the actual tests. First, check for lack of trace information. +my ($out, $err) = run_backend; +is ($err, "REMOTE_USER not set\n", 'REMOTE_USER required'); +$ENV{REMOTE_USER} = 'admin'; +($out, $err) = run_backend; +is ($err, "neither REMOTE_HOST nor REMOTE_ADDR set\n", + 'REMOTE_HOST or _ADDR required'); +$ENV{REMOTE_ADDR} = '1.2.3.4'; +my $new = 'new admin 1.2.3.4'; + +# Check unknown commands. +($out, $err) = run_backend ('foo'); +is ($err, "unknown command foo\n", 'Unknown command'); +is ($out, "$new\n", ' and nothing ran'); +($out, $err) = run_backend ('acl', 'foo'); +is ($err, "unknown command acl foo\n", 'Unknown ACL command'); +is ($out, "$new\n", ' and nothing ran'); + +# Check too few, too many, and bad arguments for every command. +my %commands = (create => [2, 2], + destroy => [2, 2], + expires => [2, 3], + get => [2, 2], + getacl => [3, 3], + owner => [2, 3], + setacl => [4, 4], + show => [2, 2], + store => [3, 3]); +my %acl_commands = (add => [3, 3], + create => [1, 1], + destroy => [1, 1], + remove => [3, 3], + rename => [2, 2]); +for my $command (sort keys %commands) { + my ($min, $max) = @{ $commands{$command} }; + ($out, $err) = run_backend ($command, ('foo') x ($min - 1)); + is ($err, "insufficient arguments\n", "Too few arguments for $command"); + is ($out, "$new\n", ' and nothing ran'); + ($out, $err) = run_backend ($command, ('foo') x ($max + 1)); + is ($err, "too many arguments\n", "Too many arguments for $command"); + is ($out, "$new\n", ' and nothing ran'); + my @base = ('foobar') x $max; + for my $arg (0 .. ($max - 1)) { + my @args = @base; + $args[$arg] = 'foo;bar'; + ($out, $err) = run_backend ($command, @args); + if ($command eq 'store' and $arg == 2) { + is ($err, '', 'Store allows any characters'); + is ($out, "$new\nstore foobar foobar foo;bar\n", + ' and calls the right method'); + } else { + is ($err, "invalid characters in argument: foo;bar\n", + "Invalid arguments for $command $arg"); + is ($out, "$new\n", ' and nothing ran'); + } + } +} +for my $command (sort keys %acl_commands) { + my ($min, $max) = @{ $acl_commands{$command} }; + ($out, $err) = run_backend ('acl', $command, ('foo') x ($min - 1)); + is ($err, "insufficient arguments\n", + "Too few arguments for acl $command"); + is ($out, "$new\n", ' and nothing ran'); + ($out, $err) = run_backend ('acl', $command, ('foo') x ($max + 1)); + is ($err, "too many arguments\n", "Too many arguments for acl $command"); + is ($out, "$new\n", ' and nothing ran'); + my @base = ('foobar') x $max; + for my $arg (0 .. ($max - 1)) { + my @args = @base; + $args[$arg] = 'foo;bar'; + ($out, $err) = run_backend ('acl', $command, @args); + is ($err, "invalid characters in argument: foo;bar\n", + "Invalid arguments for acl $command $arg"); + is ($out, "$new\n", ' and nothing ran'); + } +} + +# Now, test that we ran the right functions and passed the correct arguments. +my $error = 1; +for my $command (qw/create destroy setacl store/) { + my $method = ($command eq 'setacl') ? 'acl' : $command; + my @extra = ('foo') x ($commands{$command}[0] - 2); + my $extra = @extra ? join (' ', '', @extra) : ''; + ($out, $err) = run_backend ($command, 'type', 'name', @extra); + is ($err, '', "Command $command ran with no errors"); + is ($out, "$new\n$method type name$extra\n", + ' and ran the right method'); + ($out, $err) = run_backend ($command, 'error', 'name', @extra); + is ($err, "error count $error\n", "Command $command ran with errors"); + is ($out, "$new\n$method error name$extra\n", + ' and ran the right method'); + $error++; +} +for my $command (qw/expires get getacl owner show/) { + my $method = ($command eq 'getacl') ? 'acl' : $command; + my @extra = ('foo') x ($commands{$command}[0] - 2); + my $extra = @extra ? join (' ', '', @extra) : ''; + my $newline = ($command eq 'get' or $command eq 'show') ? '' : "\n"; + ($out, $err) = run_backend ($command, 'type', 'name', @extra); + is ($err, '', "Command $command ran with no errors"); + is ($out, "$new\n$method type name$extra\n$method$newline", + ' and ran the right method with output'); + if ($command ne 'get' and $command ne 'getacl' and $command ne 'show') { + ($out, $err) = run_backend ($command, 'type', 'name', @extra, 'foo'); + is ($err, '', "Command $command ran with no errors (setting)"); + is ($out, "$new\n$method type name$extra foo\n", + ' and ran the right method'); + } + if ($command ne 'get' and $command ne 'show') { + ($out, $err) = run_backend ($command, 'type', 'empty', @extra); + is ($err, '', "Command $command ran with no errors (empty)"); + my $desc; + if ($command eq 'expires') { $desc = 'expiration' } + elsif ($command eq 'getacl') { $desc = 'ACL' } + elsif ($command eq 'owner') { $desc = 'owner' } + is ($out, "$new\n$method type empty$extra\nNo $desc set\n", + ' and ran the right method with output'); + $error++; + } + ($out, $err) = run_backend ($command, 'error', 'name', @extra); + is ($err, "error count $error\n", "Command $command ran with errors"); + is ($out, "$new\n$method error name$extra\n", + ' and ran the right method'); + $error++; +} +for my $command (sort keys %acl_commands) { + my @extra = ('foo') x ($acl_commands{$command}[0] - 1); + my $extra = @extra ? join (' ', '', @extra) : ''; + ($out, $err) = run_backend ('acl', $command, 'name', @extra); + is ($err, '', "Command acl $command ran with no errors"); + is ($out, "$new\nacl_$command name$extra\n", ' and ran the right method'); + ($out, $err) = run_backend ('acl', $command, 'error', @extra); + is ($err, "error count $error\n", "Command acl $command ran with errors"); + is ($out, "$new\nacl_$command error$extra\n", + ' and ran the right method'); + $error++; +} + +# Almost done. All that remains is to test the robustness of the bad +# character checks against every possible character. +my $ok = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_/.-'; +($out, $err) = run_backend ('show', 'type', $ok); +is ($err, '', 'Allowed all valid characters'); +is ($out, "$new\nshow type $ok\nshow", ' and returned the right output'); +for my $n (0 .. 255) { + my $c = chr ($n); + my $name = $ok . $c; + ($out, $err) = run_backend ('show', 'type', $name); + if (index ($ok, $c) == -1) { + is ($err, "invalid characters in argument: $name\n", + "Rejected invalid character $n"); + is ($out, "$new\n", ' and did nothing'); + } else { + is ($err, '', "Accepted valid character $n"); + is ($out, "$new\nshow type $name\nshow", ' and ran the method'); + } +} |