Add Subtract function and tests
1 parent c44b017 commit 3fe5c20ee5fbf412ea06d903550ac56bece75598
@Andreas Jaggi Andreas Jaggi authored on 18 Oct 2015
Showing 3 changed files
View
26
IP.pm
$rfc3021
);
require Exporter;
 
@EXPORT_OK = qw(Compact Coalesce Zero Zeros Ones V4mask V4net Exclude netlimit);
@EXPORT_OK = qw(Compact Coalesce Zero Zeros Ones V4mask V4net Subtract Exclude netlimit);
@EXPORT_FAIL = qw($_netlimit);
 
@ISA = qw(Exporter NetAddr::IP::Lite);
 
Zeros
Ones
V4mask
V4net
Subtract
Exclude
netlimit
:aton DEPRECATED
:lower
*Compact = \&compact;
 
sub Coalesce {
return &coalesce;
}
 
sub Subtract {
my @add = ref $_[0] eq __PACKAGE__ ? ($_[0]) : @{$_[0]};
my @sub = @{$_[1]};
my @ret;
while (@add && @sub) {
if ($sub[0]->contains($add[0])) {
shift @add;
} elsif ($add[0]->contains($sub[0])) {
my ($low,$up) = Exclude(shift @add,shift @sub);
push @ret, @$low;
unshift @add, @$up;
} else {
if ($add[0]->bigint < $sub[0]->bigint) {
push @ret, shift @add;
} else {
shift @sub;
}
}
}
push @ret, @add;
return \@ret;
}
 
sub Exclude {
return ([],[]) if $_[0] == $_[1];
View
87
t/v4-subtract.t 0 → 100644
use Test::More;
use NetAddr::IP qw(Exclude Subtract);
 
my @r = (
['10.0.0.0/8','10.0.0.0/9'],
['10.0.0.0/8','10.0.0.0/8'],
['10.0.0.0/8','10.128.0.0/9'],
['10.0.0.0/8','10.128.0.0/10'],
['10.0.0.0/8','10.0.0.0/32'],
['192.168.0.0/24','192.168.0.255/32'],
['192.168.0.0/23','192.168.0.127/32'],
['1.2.3.4/32','1.2.3.4/32'],
['0.0.0.0/0','0.0.0.0/32'],
);
 
plan tests => 1 + 19 * scalar @r;
 
SKIP: {
my $res = Subtract([],[]);
is("@$res", "", "Subtract([],[]) returns an empty list");
 
foreach my $case (@r) {
my $whole = [NetAddr::IP->new($case->[0])];
my $part1 = [NetAddr::IP->new($case->[1])];
my ($low,$up) = Exclude($whole->[0],$part1->[0]);
my $part2 = [@{$low},@{$up}];
my $res = [];
 
$res = Subtract($whole,$part1);
is("@$res", "@$part2", "Subtract(@$whole,@$part1) returns @$part2");
 
$res = $whole->[0]->Subtract($part1);
is("@$res", "@$part2", "($whole->[0])->Subtract(@$part1) returns @$part2");
 
$res = Subtract($whole,$part2);
is("@$res", "@$part1", "Subtract(@$whole,@$part2) returns @$part1");
 
$res = $whole->[0]->Subtract($part2);
is("@$res", "@$part1", "($whole->[0])->Subtract(@$part2) returns @$part1");
 
$res = Subtract($part1,$part2);
is("@$res", "@$part1", "Subtract(@$part1,@$part2) returns @$part1");
 
$res = $part1->[0]->Subtract($part2);
is("@$res", "@$part1", "($part1->[0])->Subtract(@$part2) returns @$part1");
 
$res = Subtract($part2,$part1);
is("@$res", "@$part2", "Subtract(@$part2,@$part1) returns @$part2");
 
$res = Subtract(Subtract($whole,$part1),$part2);
is("@$res", "", "Subtract(Subtract(@$whole,@$part1),$part2) returns an empty list");
 
$res = Subtract($whole->[0]->Subtract($part1),$part2);
is("@$res", "", "Subtract(($whole->[0])->Subtract(@$part1),$part2) returns an empty list");
 
$res = Subtract(Subtract($whole,$part2),$part1);
is("@$res", "", "Subtract(Subtract(@$whole,@$part2),$part1) returns an empty list");
 
$res = Subtract($whole->[0]->Subtract($part2),$part1);
is("@$res", "", "Subtract(($whole->[0])->Subtract(@$part2),$part1) returns an empty list");
 
$res = Subtract($whole,$whole);
is("@$res", "", "Subtract(@$whole,@$whole) returns an empty list");
 
$res = $whole->[0]->Subtract($whole);
is("@$res", "", "($whole->[0])->Subtract(@$whole) returns an empty list");
 
$res = Subtract($part1,$part1);
is("@$res", "", "Subtract(@$part1,@$part1) returns an empty list");
 
$res = $part1->[0]->Subtract($part1);
is("@$res", "", "($part1->[0])->Subract(@$part1) returns an empty list");
 
$res = Subtract($part2,$part2);
is("@$res", "", "Subtract(@$part2,@$part2) returns an empty list");
 
$res = Subtract($part1,$whole);
is("@$res", "", "Subtract(@$part1,@$whole) returns an empty list");
 
$res = $part1->[0]->Subtract($whole);
is("@$res", "", "($part1->[0])->Subtract(@$whole) returns an empty list");
 
$res = Subtract($part2,$whole);
is("@$res", "", "Subtract(@$part2,@$whole) returns an empty list");
}
}
View
83
t/v6-subtract.t 0 → 100644
use Test::More;
use NetAddr::IP qw(:lower Exclude Subtract);
 
my @r = (
['2001:db8::/32','2001:db8::/33'],
['2001:db8::/64','2001:db8::/64'],
['2001:db8::/128','2001:db8::/128'],
['2001:db8::/32','2001:db8:8000::/33'],
['2001:db8::/32','2001:db8:8000::/34'],
);
 
plan tests => 1 + 19 * scalar @r;
 
SKIP: {
my $res = Subtract([],[]);
is("@$res", "", "Subtract([],[]) returns an empty list");
 
foreach my $case (@r) {
my $whole = [NetAddr::IP->new($case->[0])];
my $part1 = [NetAddr::IP->new($case->[1])];
my ($low,$up) = Exclude($whole->[0],$part1->[0]);
my $part2 = [@{$low},@{$up}];
my $res = [];
 
$res = Subtract($whole,$part1);
is("@$res", "@$part2", "Subtract(@$whole,@$part1) returns @$part2");
 
$res = $whole->[0]->Subtract($part1);
is("@$res", "@$part2", "($whole->[0])->Subtract(@$part1) returns @$part2");
 
$res = Subtract($whole,$part2);
is("@$res", "@$part1", "Subtract(@$whole,@$part2) returns @$part1");
 
$res = $whole->[0]->Subtract($part2);
is("@$res", "@$part1", "($whole->[0])->Subtract(@$part2) returns @$part1");
 
$res = Subtract($part1,$part2);
is("@$res", "@$part1", "Subtract(@$part1,@$part2) returns @$part1");
 
$res = $part1->[0]->Subtract($part2);
is("@$res", "@$part1", "($part1->[0])->Subtract(@$part2) returns @$part1");
 
$res = Subtract($part2,$part1);
is("@$res", "@$part2", "Subtract(@$part2,@$part1) returns @$part2");
 
$res = Subtract(Subtract($whole,$part1),$part2);
is("@$res", "", "Subtract(Subtract(@$whole,@$part1),$part2) returns an empty list");
 
$res = Subtract($whole->[0]->Subtract($part1),$part2);
is("@$res", "", "Subtract(($whole->[0])->Subtract(@$part1),$part2) returns an empty list");
 
$res = Subtract(Subtract($whole,$part2),$part1);
is("@$res", "", "Subtract(Subtract(@$whole,@$part2),$part1) returns an empty list");
 
$res = Subtract($whole->[0]->Subtract($part2),$part1);
is("@$res", "", "Subtract(($whole->[0])->Subtract(@$part2),$part1) returns an empty list");
 
$res = Subtract($whole,$whole);
is("@$res", "", "Subtract(@$whole,@$whole) returns an empty list");
 
$res = $whole->[0]->Subtract($whole);
is("@$res", "", "($whole->[0])->Subtract(@$whole) returns an empty list");
 
$res = Subtract($part1,$part1);
is("@$res", "", "Subtract(@$part1,@$part1) returns an empty list");
 
$res = $part1->[0]->Subtract($part1);
is("@$res", "", "($part1->[0])->Subract(@$part1) returns an empty list");
 
$res = Subtract($part2,$part2);
is("@$res", "", "Subtract(@$part2,@$part2) returns an empty list");
 
$res = Subtract($part1,$whole);
is("@$res", "", "Subtract(@$part1,@$whole) returns an empty list");
 
$res = $part1->[0]->Subtract($whole);
is("@$res", "", "($part1->[0])->Subtract(@$whole) returns an empty list");
 
$res = Subtract($part2,$whole);
is("@$res", "", "Subtract(@$part2,@$whole) returns an empty list");
}
}