[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Omaha.pm] Testing DNS servers
revision 1.2
date: 2007/01/16 16:28:42; author: jhannah; state: Exp; lines: +65 -17
I discovered a problem with my testing robot. The answers coming from the
servers were not necessarily authoritative. This was a fatal design flaw
because when the target server recurses to find the correct answer the
test robot must detect that behavior and report it as a failure.
I switched from parsing dig output to Net::DNS where I can explicitly
check the aa (authoritative answer) bit to make sure that the answer I'm
receiving isn't from cache.
Also, in this version if you're expecting multiple responses (e.g.: 3 MX
servers)
you can pass an array reference in and the test will check all values.
(There may be a sorting bug here that I haven't fixed.)
use strict;
use Test::More;
eval { require Sys::HostIP };
plan skip_all => "Sys::HostIP required" if $@;
eval { require Net::DNS::Resolver };
plan skip_all => "Net::DNS::Resolver required" if $@;
my $ip_address = Sys::HostIP->ip;
if ($ip_address =~ /^10\./) {
plan skip_all => "You can only run these tests from the Internet. Your IP: [$ip_address]";
} else {
plan tests => 102;
}
my @servers = (
'63.174.225.42', # omares-netservices's Internet IP
'63.251.92.193', # dns3.corporatedomains.com
);
my @expect = qw(
omnihotels.com A 63.241.199.252
www.omnihotels.com A 63.241.199.252
# You can also pass array references like this:
#'676restaurant.com', 'NS', [ 'ns.panomedia.net', 'ns1.panomedia.net' ],
);
run_tests(\@servers, \@expect);
exit;
# -------------
sub run_tests {
my ($servers, $expect) = @_;
# Set up our resolver objects...
my %resolvers;
foreach my $server (@$servers) {
my $res = Net::DNS::Resolver->new(
nameservers => [ $server ],
recurse => 0,
#debug => 1
);
$resolvers{$server} = $res;
}
for (my $j = 0; $j < @$expect; $j += 3) {
foreach my $server (@$servers) {
my ($q, $type, $a) = @$expect[$j .. $j + 2];
my $res = $resolvers{$server};
my $packet = $res->search($q, $type); # Net::DNS::Packet object
my @response;
if ($packet) {
### Hmm... This NS theory is unproven, so I'm commenting it out.
###if ($type eq "NS") {
### # These don't have to be authoritative. When we delgate NS for a server
### # apparently named does not set the aa (authoritative answer) flag.
###} else {
if ($packet->header->aa) {
# Good. It's authoritative.
} else {
# Ack! Non-authoritative answer??
push @response, "ERROR! Server returned non-authoritative answer!";
}
###}
foreach my $rr ($packet->answer) {
next unless $rr->type eq $type;
#print $rr->address, "\n";
if ($type eq "A") {
push @response, $rr->address;
} elsif ($type eq "NS") {
push @response, $rr->nsdname;
} elsif ($type eq "MX") {
push @response, $rr->exchange;
} elsif ($type eq "TXT") {
push @response, $rr->txtdata;
}
}
}
if (ref $a eq "ARRAY") {
# The test requested we check multiple values...
is_deeply([@response], $a, "\@$server $q $type -> $a");
} else {
is_deeply([@response], [$a], "\@$server $q $type -> $a");
}
}
}
}